Summary
TEMPLATE_MANIFEST declares source: 'Rai-charter.md' (packages/squad-cli/src/cli/core/templates.ts:139-140), but the file on disk is rai-charter.md (lowercase) in all four template locations. It is the only one of 59 manifest sources that does not resolve case-sensitively.
Found while fixing the README casing in #1949; deliberately left out of that docs PR because the fix spans runtime code, tests, and a prompt template.
Why this hasn't been caught
existsSync gives a false pass on macOS, because the filesystem is case-insensitive. A check that reads directory entries and compares exact basenames tells the truth:
total 59 case-sensitively missing 1
MISSING: Rai-charter.md
On disk, all four locations agree:
.squad-templates charter.md fact-checker-charter.md rai-charter.md scribe-charter.md
templates charter.md fact-checker-charter.md personal-charter.md rai-charter.md scribe-charter.md
packages/squad-cli/templates charter.md fact-checker-charter.md rai-charter.md scribe-charter.md
packages/squad-sdk/templates charter.md fact-checker-charter.md rai-charter.md scribe-charter.md
This is exactly the failure mode the codebase already warns about in its own comment at packages/squad-sdk/src/config/init.ts:1141-1151 — mixed-case lookups missing on case-sensitive filesystems (Linux CI), referencing the regression #1299 was fixing.
Blast radius
The wrong casing is load-bearing in several places, which is why this needs its own PR:
packages/squad-cli/src/cli/core/templates.ts:139-140 — manifest source and destination
packages/squad-cli/src/cli/core/upgrade.ts:1027 — { dirName: 'Rai', templateFile: 'Rai-charter.md' }
test/template-routing.test.ts:61 — currently pins the incorrect mapping, so it will need updating in the same change
packages/squad-cli/templates/squad.agent.md.template:912 — runtime prompt instructs reading .squad/templates/Rai-charter.md
.squad/skills/coordinator-init-mode/SKILL.md:76 — prose reference
Note the destination directory agents/Rai/charter.md is intentionally capitalized (dirName: 'Rai') and should stay that way — only the source filename is wrong.
Suggested durable fix
Add a guard asserting every manifest source exists case-sensitively (read readdirSync entries, compare exact basenames — do not use existsSync, which is what let this through). That single test would have caught this and prevents recurrence across all 59 entries.
I considered adding that guard in #1949 but it would have failed on this pre-existing entry and required an allowlist, so it belongs here with the fix.
Acceptance criteria
Summary
TEMPLATE_MANIFESTdeclaressource: 'Rai-charter.md'(packages/squad-cli/src/cli/core/templates.ts:139-140), but the file on disk israi-charter.md(lowercase) in all four template locations. It is the only one of 59 manifest sources that does not resolve case-sensitively.Found while fixing the README casing in #1949; deliberately left out of that docs PR because the fix spans runtime code, tests, and a prompt template.
Why this hasn't been caught
existsSyncgives a false pass on macOS, because the filesystem is case-insensitive. A check that reads directory entries and compares exact basenames tells the truth:On disk, all four locations agree:
This is exactly the failure mode the codebase already warns about in its own comment at
packages/squad-sdk/src/config/init.ts:1141-1151— mixed-case lookups missing on case-sensitive filesystems (Linux CI), referencing the regression #1299 was fixing.Blast radius
The wrong casing is load-bearing in several places, which is why this needs its own PR:
packages/squad-cli/src/cli/core/templates.ts:139-140— manifestsourceanddestinationpackages/squad-cli/src/cli/core/upgrade.ts:1027—{ dirName: 'Rai', templateFile: 'Rai-charter.md' }test/template-routing.test.ts:61— currently pins the incorrect mapping, so it will need updating in the same changepackages/squad-cli/templates/squad.agent.md.template:912— runtime prompt instructs reading.squad/templates/Rai-charter.md.squad/skills/coordinator-init-mode/SKILL.md:76— prose referenceNote the destination directory
agents/Rai/charter.mdis intentionally capitalized (dirName: 'Rai') and should stay that way — only the source filename is wrong.Suggested durable fix
Add a guard asserting every manifest source exists case-sensitively (read
readdirSyncentries, compare exact basenames — do not useexistsSync, which is what let this through). That single test would have caught this and prevents recurrence across all 59 entries.I considered adding that guard in #1949 but it would have failed on this pre-existing entry and required an allowlist, so it belongs here with the fix.
Acceptance criteria
rai-charter.mdupgrade.ts:1027templateFilecorrectedtest/template-routing.test.tsupdated to pin the correct mappingTEMPLATE_MANIFESTsource resolves case-sensitively (not viaexistsSync)