Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions docs/trajectories/typescript-bun-migration/RESUME.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
**Next concrete action**: Maintain the bash-retirement inventory guard and treat
any newly tracked non-Lean shell-family file outside the allowlist as drift. Do
not revive the old Cluster G/H/I or budget-cluster port queues.
**Last updated**: 2026-05-27T17:48Z
**Last updated**: 2026-05-28T12:35Z

## Why this trajectory exists

Expand Down Expand Up @@ -52,11 +52,12 @@ bun run hygiene:check-bash-retirement-inventory
The expected retained surface is the explicit repo-wide allowlist: setup and
bootstrap scripts, host-service wrappers, NixOS installer scripts,
dev-cluster wrappers, launchd-bootstrap, and the Kiro loop wrapper. Any new
non-Lean shell-family file (`.sh`, `.bash`, `.zsh`, `.ksh`, or `.command`)
outside the allowlist is bash-retirement drift. Executable dotted-name files
with shell-family shebangs are also entrypoints and are classified as drift;
non-executable dotted documentation fixtures with shell-looking first lines stay
outside the retained-shell inventory.
non-Lean shell-family file (`.sh`, `.bash`, `.zsh`, `.ksh`, or `.command`,
including uppercase extension variants) outside the allowlist is
bash-retirement drift. Executable dotted-name files with shell-family shebangs
are also entrypoints and are classified as drift; non-executable dotted
documentation fixtures with shell-looking first lines stay outside the
retained-shell inventory.
Comment thread
AceHack marked this conversation as resolved.

### Bucket A — Should stay Shell (21 files)

Expand Down
10 changes: 10 additions & 0 deletions tools/hygiene/check-bash-retirement-inventory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,15 @@ describe("buildInventoryReport", () => {
mkdirSync(join(repo, "scripts"), { recursive: true });
mkdirSync(join(repo, "tools", "lean4"), { recursive: true });
writeFileSync(join(repo, "scripts", "a.sh"), "#!/usr/bin/env bash\n");
writeFileSync(join(repo, "scripts", "a-uppercase.SH"), "echo uppercase extension drift\n");
writeFileSync(join(repo, "scripts", "b.bash"), "#!/usr/bin/env bash\n");
writeFileSync(join(repo, "scripts", "b-uppercase.BASH"), "echo uppercase extension drift\n");
writeFileSync(join(repo, "scripts", "c.zsh"), "#!/usr/bin/env zsh\n");
writeFileSync(join(repo, "scripts", "c-uppercase.ZSH"), "echo uppercase extension drift\n");
writeFileSync(join(repo, "scripts", "d.ksh"), "#!/usr/bin/env ksh\n");
writeFileSync(join(repo, "scripts", "d-uppercase.KSH"), "echo uppercase extension drift\n");
writeFileSync(join(repo, "scripts", "e.command"), "#!/usr/bin/env bash\n");
writeFileSync(join(repo, "scripts", "e-uppercase.COMMAND"), "echo uppercase extension drift\n");
writeFileSync(join(repo, "scripts", "extensionless-bash"), "#!/usr/bin/env bash\n");
writeFileSync(join(repo, "scripts", "extensionless-bash-env-s"), "#!/usr/bin/env -S bash -eu\n");
writeFileSync(join(repo, "scripts", "extensionless-dash"), "#!/bin/dash\n");
Expand All @@ -214,11 +219,16 @@ describe("buildInventoryReport", () => {

expect(trackedNonLeanShellFilesFromGit(repo)).toEqual([
"scripts/a.sh",
"scripts/a-uppercase.SH",
"scripts/b.bash",
"scripts/b-uppercase.BASH",
"scripts/c.zsh",
"scripts/c-uppercase.ZSH",
"scripts/d.ksh",
"scripts/d-uppercase.KSH",
"scripts/dotted-shell-entry.env",
"scripts/e.command",
"scripts/e-uppercase.COMMAND",
"scripts/extensionless-bash",
"scripts/extensionless-bash-env-s",
"scripts/extensionless-dash",
Expand Down
3 changes: 2 additions & 1 deletion tools/hygiene/check-bash-retirement-inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ function parseTrackedGitFile(entry: string): TrackedGitFile | undefined {
}

function isTrackedShellFamilyFile(repoRoot: string, file: string, executable: boolean): boolean {
if (SHELL_FILE_EXTENSIONS.some((extension) => file.endsWith(extension))) return true;
const lowerFile = file.toLowerCase();
if (SHELL_FILE_EXTENSIONS.some((extension) => lowerFile.endsWith(extension))) return true;
if (basename(file).includes(".") && !executable) return false;

const firstLine = readFirstLine(join(repoRoot, file));
Expand Down
Loading