Repository navigation
Description
Summary
squad upgrade overwrites repo-committed policy content under .squad/templates/ without creating a .local-backup. In the dogfood repo, .squad/templates/model-selection-reference.md contained active modelPolicy.allowedModels rules and a test asserting them; upgrade replaced it with the stock template and caused that test to fail.
This contradicts the upgrade help text that says .squad/ team state is left untouched. The same upgraded repo immediately reports 53 files to overwrite on squad upgrade --dry-run, so the upgrade is not idempotent. On Windows, adding one .gitignore line also rewrote the entire file from LF to CRLF.
Related but not duplicate: #2047 covers stale template snapshots; this report covers destructive overwrite, missing backup, idempotence, and line-ending churn.
Environment
- Squad CLI
2.0.0-preview.1, installed from the exact published release tarball - Windows 11
- Node.js 22
- CFS-only npm host (
https://packagefeedproxy.microsoft.io/npm/)
Repro
git status --short
squad --help
squad upgrade
git diff -- .squad/templates/model-selection-reference.md .gitignore
Get-ChildItem -Recurse -Filter *.local-backup
squad upgrade --dry-runObserved
Help states:
Never touches: .squad/ or .ai-team/
Upgrade reports:
✓ refreshed .squad/templates/
But the customized, committed model-selection-reference.md was replaced and no corresponding .local-backup was created. A repository test then failed because the expected text was gone:
Expected 'modelPolicy\.allowedModels' to match '# Model Selection Reference …'
Immediately after the successful upgrade, dry-run still reported:
Would overwrite 53 squad-owned file(s)
squad.agent.md is unmodified — would refresh with latest template
The listed targets included 21 templates, 19 skills, 11 workflows, and three legacy .squad/casting-*.json paths. Separately, .gitignore changed from 0 CR bytes to 22 CR bytes for a single added line, producing a whole-file diff.
Expected
- Customized committed files under
.squad/templates/are preserved or backed up before replacement. - Help accurately distinguishes mutable team state from Squad-owned template snapshots.
- A second upgrade/dry-run at the same version is a no-op.
- Existing line endings are preserved when appending
.squad/backend/to.gitignore.
Impact / Severity
HIGH. Upgrade can silently destroy repository policy text and break tests, while the advertised preservation contract says the opposite. Non-idempotent output and line-ending churn make it difficult to audit the actual changes.
Proposed fix
- Apply content-hash/customization detection and
.local-backupbehavior to every overwritten.squad/templates/**file. - Correct the help text to document exactly which
.squad/paths are managed. - Compare generated bytes before reporting/writing overwrites and add a second-upgrade no-op regression test.
- Preserve the existing newline style for edited files.
- Stop listing obsolete root-level casting paths after migration.
Activity
fix(cli): 2.0.0-preview.2 upgrade/health fixes from dogfooding
fix(cli): 2.0.0-preview.2 upgrade/health fixes from dogfooding (#2303)