You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PRD: Versioned File Layout Manifest — Single Source of Truth for Directory Structure
Status: Approved (Flight) Requested by: Dina Berry Last Updated: 2026-03-28
Executive Summary
Squad's CLI has five independent code paths that hardcode file locations with no centralized source of truth. This inconsistency has already caused two confirmed bugs (skills discovery #77, squad.agent.md silent deletion #730) and will continue degrading reliability. We propose a versioned JSON manifest that defines every directory Squad manages, its canonical location per version, read priority order, write target, and deprecated paths. All five code paths will reference this manifest instead of hardcoding paths independently.
Problem Statement
Root Cause: Five Independent Code Paths Without Single Source of Truth
Squad manages 33+ template files and dozens of directories, but has no centralized registry for file layout across versions. Instead, five separate code paths each make independent assumptions about where files live:
init.ts — Creates directories at init time; hardcodes paths like .squad/, .copilot/agents/, .github/workflows/
migrations.ts — Moves files between locations on upgrade; implements custom logic for each version transition
upgrade.ts — Syncs template files to target directories; references TEMPLATE_MANIFEST but lacks runtime read-order logic
squad.agent.md — Tells agents where to read/write skills, decisions, and history; contains hardcoded paths that drift from runtime behavior
skill-source.ts, resolver.ts — Runtime reads from hardcoded paths using either/or logic (checks one location, stops on first match)
Evidence: Two Independent Bugs with Same Root Cause
Operations on critical files must NEVER silently skip. Every code path that writes, copies, or modifies a critical file must have an explicit else clause:
// ❌ Current pattern — silent degradationif(storage.existsSync(source)){storage.copySync(source,dest);}// ✅ Required pattern — fail-loudif(storage.existsSync(source)){storage.copySync(source,dest);}else{warn(`Template source missing for critical file: ${dest}`);warnings.push({file: dest,reason: 'template-source-missing'});}
For critical tier files, missing source should be an error. For important and scaffolding tiers, a warning suffices.
Empty = Missing
Existence checks must also verify non-empty for critical files. An empty squad.agent.md is functionally identical to a missing one — Copilot can't discover the agent — yet must not be silently skipped.
This runs as the final step in init(), upgrade(), and migrate() — after all file operations complete.
Recovery Cascade
When post-operation validation fails for a critical file, attempt recovery before erroring:
Try restore from template — re-copy from template source
Try restore from git — git show HEAD:<path> to recover from last commit
Error with clear message — if both fail, surface a specific, actionable error
asyncfunctionrecoverCriticalFile(entry: LayoutEntry,projectRoot: string): Promise<boolean>{constdest=path.join(projectRoot,entry.canonical);// Attempt 1: Restore from templateconsttemplatePath=resolveTemplatePath(entry.templateSource);if(templatePath&&storage.existsSync(templatePath)){storage.copySync(templatePath,dest);warn(`Recovered ${entry.canonical} from template`);returntrue;}// Attempt 2: Restore from gittry{constcontent=execSync(`git show HEAD:${entry.canonical}`,{cwd: projectRoot});if(content.toString().trim().length>0){storage.writeSync(dest,content.toString());warn(`Recovered ${entry.canonical} from git history`);returntrue;}}catch{/* file not in git history */}// Attempt 3: Error with actionable messagethrownewError(`Critical file missing and unrecoverable: ${entry.canonical}. Reinstall Squad or manually restore this file.`);}
Doctor Severity = Actual Impact
squad doctor severity must match actual user impact:
Condition
Correct Severity
Rationale
File missing, product broken
fail
User can't use Squad
File empty, product broken
fail
Functionally identical to missing
File exists but malformed
warn
May partially work
File missing, product works
warn
Degraded but functional
File missing, convenience only
info
No impact on core functionality
Bug fix: Empty squad.agent.md must report fail, not warn.
Implementation Strategy: Strangler Fig Pattern
We will not freeze the product. Instead, we will wrap the old system incrementally:
Step 1: Manifest Describes Current Reality
Write manifest JSON that documents the current layout
No behavior changes; manifest is purely descriptive
Ship and gather feedback
Risks: none — read-only
Step 2: Path Resolver Reads from Manifest
New resolvePathFromManifest() function references the manifest
Old paths still work; resolver logs warnings on drift
New code (future features) uses manifest resolver from day 1
Risks: low — old paths unchanged
Step 3: New Code Uses Manifest
When touching existing files for unrelated work, swap hardcoded paths to manifest lookups
.ai-team/ repos (v0.7): Manifest includes .ai-team/ in readOrder; users can upgrade without moving files manually
.squad/ repos (v0.8): Manifest includes .squad/ in readOrder and deprecated; automatic migration on upgrade moves files to .copilot/, old paths still readable during transition
.copilot/ repos (v0.9+): Canonical layout; no changes
No breaking changes: All upgrades are forward-compatible; deprecated paths remain readable for 1–2 versions
Upgrade Communication Plan
Release notes: "Squad now unifies directory structure across versions. Your layout will auto-migrate on squad upgrade."
Migration log:squad upgrade output includes: "Migrated skills from .squad/skills/ to .copilot/skills/" for transparency
Doctor report:squad doctor reports any deprecated paths still in use, with clear migration guidance
Rollback story: If migration fails, recover with squad doctor --repair or revert to previous version
Out of Scope
User-owned files (overwriteOnUpgrade: false): team.md, routing.md, decisions/, agent histories, identity files. These are user content — the framework doesn't overwrite or validate them.
Runtime agent behavior: This proposal covers CLI file operations only (init, upgrade, migrate, doctor). Agent runtime logic (how agents read/write at runtime) is a separate concern.
Non-file invariants: Config validation, schema enforcement, and other non-filesystem concerns are outside this proposal's scope.
Open Questions & Decisions Needed
Manifest versioning: Should we store multiple manifest versions in git history, or just the latest? (Recommendation: latest only; migrations derive from code history)
Manifest distribution: Should users commit the manifest to their repos, or is it CLI-only? (Recommendation: Users don't need to commit; it's shipped with CLI)
Manifest auto-update on CLI upgrade: Should squad upgrade fetch latest manifest from CLI release? (Recommendation: Yes, like TEMPLATE_MANIFEST)
Concurrent access: How do we handle two Squad sessions (e.g., git worktrees) reading/writing manifest simultaneously? (Recommendation: Use git locks; out of scope for Phase 1)
Implementation Notes for Teams
For Flight (Lead)
Validate that manifest schema covers all 5 code paths
PRD: Versioned File Layout Manifest — Single Source of Truth for Directory Structure
Status: Approved (Flight)
Requested by: Dina Berry
Last Updated: 2026-03-28
Executive Summary
Squad's CLI has five independent code paths that hardcode file locations with no centralized source of truth. This inconsistency has already caused two confirmed bugs (skills discovery #77, squad.agent.md silent deletion #730) and will continue degrading reliability. We propose a versioned JSON manifest that defines every directory Squad manages, its canonical location per version, read priority order, write target, and deprecated paths. All five code paths will reference this manifest instead of hardcoding paths independently.
Problem Statement
Root Cause: Five Independent Code Paths Without Single Source of Truth
Squad manages 33+ template files and dozens of directories, but has no centralized registry for file layout across versions. Instead, five separate code paths each make independent assumptions about where files live:
init.ts— Creates directories at init time; hardcodes paths like.squad/,.copilot/agents/,.github/workflows/migrations.ts— Moves files between locations on upgrade; implements custom logic for each version transitionupgrade.ts— Syncs template files to target directories; referencesTEMPLATE_MANIFESTbut lacks runtime read-order logicsquad.agent.md— Tells agents where to read/write skills, decisions, and history; contains hardcoded paths that drift from runtime behaviorskill-source.ts,resolver.ts— Runtime reads from hardcoded paths using either/or logic (checks one location, stops on first match)Evidence: Two Independent Bugs with Same Root Cause
Bug 1: Skills Discovery (#77)
.squad/skills/to.copilot/skills/, but runtime still only checks one locationskill-source.tsandresolver.tsuse either/or pattern (returns first match only), while migration didn't update both paths consistentlyBug 2: squad.agent.md Silent Deletion (#730)
squad upgrade, the file.github/agents/squad.agent.mdsilently disappears, breaking Copilot's ability to discover Squad as an agentupgrade.ts:496-504— Template source existence check with no else clause; silent skip if missinginit.ts:257-261— SDK init stamps version but silently skips if file wasn't createddoctor.ts:~392— Detects empty file but reportswarninstead offailSystemic Pattern: Silent Degradation
These bugs share a common pattern:
The
TEMPLATE_MANIFESTdefines 33 template files, ~23 markedoverwriteOnUpgrade: true. Any of these could silently disappear through the same pattern.Customer Impact
Proposed Solution: Versioned File Layout Manifest
Core Concept
A single versioned JSON manifest that defines:
.squad/skills/, v0.9+:.copilot/skills/)All five code paths will reference this manifest instead of hardcoding paths independently.
Benefits
squad doctorvalidates layout — catch drift before it becomes bugsManifest Schema
Version Inventory
Based on historical analysis, Squad's directory structure has evolved through these versions:
.ai-team/era.squad/.copilot/.squad/deprecated but supported for readingSchema Definition
{ "schemaVersion": "1.0.0", "comment": "Defines all directories Squad manages, indexed by purpose", "layout": { // Each entry: directory purpose → location info + migration path "skills": { "purpose": "Reusable patterns and process knowledge", "canonical": ".copilot/skills/", "readOrder": [".copilot/skills/", ".squad/skills/", ".ai-team/skills/"], "writeTarget": ".copilot/skills/", "deprecated": [".squad/skills/", ".ai-team/skills/"], "since": "0.9.0", "tier": "important", "validate": "dir-exists && non-empty" }, "decisions": { "purpose": "Recorded team decisions and ADRs", "canonical": ".copilot/decisions/", "readOrder": [".copilot/decisions/", ".squad/decisions/", ".ai-team/decisions/"], "writeTarget": ".copilot/decisions/", "deprecated": [".squad/decisions/", ".ai-team/decisions/"], "since": "0.9.0", "tier": "important", "validate": "dir-exists" }, "agents": { "purpose": "Agent configurations and team roster", "canonical": ".copilot/agents/", "readOrder": [".copilot/agents/", ".squad/agents/", ".ai-team/agents/"], "writeTarget": ".copilot/agents/", "deprecated": [".squad/agents/", ".ai-team/agents/"], "since": "0.9.0", "tier": "critical", "validate": "dir-exists" }, "config": { "purpose": "Squad configuration and team metadata", "canonical": ".squad/", "readOrder": [".squad/"], "writeTarget": ".squad/", "deprecated": [], "since": "0.8.0", "tier": "critical", "validate": "dir-exists" }, "agent-md": { "purpose": "GitHub Copilot agent discovery file (critical for Copilot integration)", "canonical": ".github/agents/squad.agent.md", "readOrder": [".github/agents/squad.agent.md"], "writeTarget": ".github/agents/squad.agent.md", "deprecated": [], "since": "0.8.0", "tier": "critical", "validate": "file-exists && non-empty && contains-markers", "markers": ["Squad", "agent", "system"] }, "ci-config": { "purpose": "Squad CI workflow configuration", "canonical": ".github/workflows/squad-ci.yml", "readOrder": [".github/workflows/squad-ci.yml"], "writeTarget": ".github/workflows/squad-ci.yml", "deprecated": [], "since": "0.8.0", "tier": "important", "validate": "file-exists && non-empty" } }, "migrations": { "0.7-to-0.8": [ { "from": ".ai-team/skills", "to": ".squad/skills", "action": "move" }, { "from": ".ai-team/decisions", "to": ".squad/decisions", "action": "move" } ], "0.8-to-0.9": [ { "from": ".squad/skills", "to": ".copilot/skills", "action": "move" }, { "from": ".squad/decisions", "to": ".copilot/decisions", "action": "move" }, { "from": ".squad/agents", "to": ".copilot/agents", "action": "move" } ] } }Tier Definitions
failin doctorsquad.agent.md,squad-ci.yml,.copilot/agents/warnin doctorcasting-registry.json, skill templates, decisionsinfoin doctorcharter.mdtemplate,history.mdtemplateArchitecture Principles
Fail-Loud Policy
Operations on critical files must NEVER silently skip. Every code path that writes, copies, or modifies a critical file must have an explicit else clause:
For
criticaltier files, missing source should be an error. Forimportantandscaffoldingtiers, a warning suffices.Empty = Missing
Existence checks must also verify non-empty for critical files. An empty
squad.agent.mdis functionally identical to a missing one — Copilot can't discover the agent — yet must not be silently skipped.Post-Operation Validation
After any operation that modifies the repo structure (
init,upgrade,migrate,doctor), validate all critical files:This runs as the final step in
init(),upgrade(), andmigrate()— after all file operations complete.Recovery Cascade
When post-operation validation fails for a critical file, attempt recovery before erroring:
git show HEAD:<path>to recover from last commitDoctor Severity = Actual Impact
squad doctorseverity must match actual user impact:failfailwarnwarninfoBug fix: Empty
squad.agent.mdmust reportfail, notwarn.Implementation Strategy: Strangler Fig Pattern
We will not freeze the product. Instead, we will wrap the old system incrementally:
Step 1: Manifest Describes Current Reality
Step 2: Path Resolver Reads from Manifest
resolvePathFromManifest()function references the manifestStep 3: New Code Uses Manifest
Step 4: Migrate Remaining Paths
Implementation Phases
Phase 1: Foundation — Manifest Schema + Path Resolver + Doctor Integration
Objective: Establish the foundation for the Squad manifest-driven architecture.
Deliverables:
lib/manifest.jsonwith 6+ directory entriesresolvePathFromManifest(name: string): string[]implemented inlib/path-resolver.tsdoctor.tsrefactored to useCriticalFileRegistryfrom manifest; critical files reportfailon missing/emptyinit(),upgrade(), anddoctorFiles Modified:
lib/manifest.json(new)lib/path-resolver.ts(new)packages/squad-cli/src/cli/commands/doctor.ts(update severity logic)packages/squad-cli/src/cli/core/init.ts(add validation step)packages/squad-cli/src/cli/core/upgrade.ts(add validation step)test/(add 20+ tests)Risks & Mitigations:
Definition of Done:
Phase 2: Code Migration — Audit Skill + Runtime Integration + CI Gate
Objective: Migrate the five code paths to use the manifest; add CI gates preventing regression.
Deliverables:
skill-source.tsrefactored to resolve paths from manifest (reads all directories in readOrder, merges results)resolver.tsrefactored to use manifest (returns all matches, not just first)upgrade.tsmigration logic refactored to derive migrations from manifest diffsmigrations.tsupdated to use manifest resolver for backward-compatible path lookupssquad.agent.mdupdated with manifest-derived paths (calls to resolve functions).copilot/wins on conflicts)critical-file-check— validates all critical files exist and are non-empty after initFiles Modified:
packages/squad-cli/src/runtime/skill-source.ts(migrate to manifest)packages/squad-cli/src/runtime/resolver.ts(migrate to manifest)packages/squad-cli/src/cli/core/upgrade.ts(migration derivation)packages/squad-cli/src/cli/core/migrations.ts(use manifest resolver)templates/squad.agent.md.template(reference manifest).github/workflows/squad-ci.yml(add critical-file-check job)test/(add 40+ tests)Related Work:
Test Matrix: 11 Core Scenarios
.ai-team/layout) → reads from deprecated paths.squad/layout) → reads from deprecated paths, writes to canonical.copilot/layout) → reads and writes to canonical.squad/and.copilot/present → reads both,.copilot/wins on conflicts.squad/present → reads.squad/.copilot/present → reads.copilot/fail, notwarnRisks & Mitigations:
.squad/users → Mitigation: readOrder includes deprecated paths.copilot/wins deterministicallyDefinition of Done:
.squad/or.ai-team/reposPhase 3: Automation — Migration Generator + Doctor Repair
Objective: Automate future layout changes and enable self-service CLI troubleshooting.
Deliverables:
generateMigrationFromManifest(fromVersion, toVersion)returns migration stepssquad doctor --repaircommand: auto-fixes common issues (missing critical files, deprecated path usage, empty files)squad test-migration --from-version X --to-version Ysimulates upgrade without modifying repoFiles Modified:
lib/migration-generator.ts(new)lib/manifest-backfill.ts(new)packages/squad-cli/src/cli/commands/doctor.ts(add --repair flag)packages/squad-cli/src/cli/commands/test.ts(new subcommand: test-migration).github/workflows/squad-ci.yml(add manifest version sanity check)test/(add 20+ tests)Risks & Mitigations:
Definition of Done:
squad doctor --repairWhat's Complete vs What's Remaining
Done (from related work)
docs/proposals/critical-file-resilience.mdwith 5 architecture principlesRemaining
Immediate Actions
Success Criteria
validateCriticalFiles()runs after every init/upgrade/migratesquad doctoraccurately reports all broken states asfailCriticalFileRegistrytiercheck-critical-filesjob in squad-ci.yml green.squad/and.copilot/presentsquad doctor --repairRelated Work & References
Backward Compatibility & Customer Impact
Guarantee to Existing Users
.ai-team/repos (v0.7): Manifest includes.ai-team/inreadOrder; users can upgrade without moving files manually.squad/repos (v0.8): Manifest includes.squad/inreadOrderanddeprecated; automatic migration on upgrade moves files to.copilot/, old paths still readable during transition.copilot/repos (v0.9+): Canonical layout; no changesUpgrade Communication Plan
squad upgrade."squad upgradeoutput includes: "Migrated skills from.squad/skills/to.copilot/skills/" for transparencysquad doctorreports any deprecated paths still in use, with clear migration guidancesquad doctor --repairor revert to previous versionOut of Scope
overwriteOnUpgrade: false):team.md,routing.md,decisions/, agent histories, identity files. These are user content — the framework doesn't overwrite or validate them.Open Questions & Decisions Needed
squad upgradefetch latest manifest from CLI release? (Recommendation: Yes, like TEMPLATE_MANIFEST)Implementation Notes for Teams
For Flight (Lead)
For EECOM (Core Dev)
For FIDO (Quality Owner)
For Procedures (Prompt Engineer)
For PAO (DevRel)
.squad/repo to.copilot/?"