Skip to content

fix(cli): replace hardcoded state lists with dynamic directory scan#908

Merged
tamirdresher merged 1 commit intodevfrom
squad/863-discoverable-state-manifest
Apr 12, 2026
Merged

fix(cli): replace hardcoded state lists with dynamic directory scan#908
tamirdresher merged 1 commit intodevfrom
squad/863-discoverable-state-manifest

Conversation

@diberry
Copy link
Copy Markdown
Collaborator

@diberry diberry commented Apr 7, 2026

Summary

Replaces the hardcoded STATE_DIRS / STATE_FILES arrays in externalize/internalize with a dynamic listSync() scan of .squad/. A KEEP_LOCAL set of 6 entries stays in the working tree — everything else is discovered at runtime.

KEEP_LOCAL entries (6): config.json, manifest.json, workstreams.json, upstream.json, squad-registry.json, _upstream_repos

These files are read from the working tree by runtime code that does not go through external-state resolution, so they must remain local.

This prevents silent orphaning when new state artifacts are added to .squad/ (e.g. new agent directories, plugin files) without updating the hardcoded lists.

Changes

  • 1 file changed (externalize.ts): ~15 lines of net change
  • Replaced two hardcoded arrays + two for loops with one KEEP_LOCAL set + one dynamic scan loop per function
  • Added KEEP_LOCAL guard in runInternalize to prevent contaminated external dirs from overwriting local-only files
  • Added changeset

Testing

All 12 existing external-state.test.ts tests pass unchanged.

Closes #863

Copilot AI review requested due to automatic review settings April 7, 2026 23:09
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🟡 Impact Analysis — PR #908

Risk tier: 🟡 MEDIUM

📊 Summary

Metric Count
Files changed 6
Files added 2
Files modified 4
Files deleted 0
Modules touched 4
Critical files 1

🎯 Risk Factors

  • 6 files changed (6-20 → MEDIUM)
  • 4 modules touched (2-4 → MEDIUM)
  • Critical files touched: packages/squad-sdk/src/index.ts

📦 Modules Affected

root (1 file)
  • .changeset/discoverable-state-manifest.md
squad-cli (2 files)
  • packages/squad-cli/src/cli-entry.ts
  • packages/squad-cli/src/cli/commands/externalize.ts
squad-sdk (2 files)
  • packages/squad-sdk/src/index.ts
  • packages/squad-sdk/src/state-manifest.ts
tests (1 file)
  • test/external-state.test.ts

⚠️ Critical Files

  • packages/squad-sdk/src/index.ts

This report is generated automatically for every PR. See #733 for details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🏗️ Architectural Review

⚠️ Architectural review: 1 warning(s).

Severity Category Finding Files
🟡 warning export-surface Package entry point(s) modified with 9 new/changed export(s). New public API surface requires careful review for backward compatibility. packages/squad-sdk/src/index.ts

Automated architectural review — informational only.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces hardcoded .squad/ state artifact lists with a centralized SDK “state manifest”, then updates the CLI externalize/internalize flows to discover artifacts from that manifest and perform a copy→verify→delete migration with rollback and orphan detection.

Changes:

  • Added state-manifest.ts in squad-sdk to declare state artifacts and provide helpers (dirs/files/exclusions + orphan detection).
  • Rewrote squad externalize / squad internalize to be manifest-driven and to use a copy-verify-delete flow with rollback and audit logging.
  • Added tests covering manifest shape, legacy artifact coverage, exclusions, and orphan detection.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
test/external-state.test.ts Adds tests for manifest helpers and detectOrphanArtifacts() alongside existing external state tests.
packages/squad-sdk/src/state-manifest.ts Introduces the canonical manifest list and helper APIs (dirs/files/exclusions + orphan detection).
packages/squad-sdk/src/index.ts Re-exports the manifest types/functions from the SDK barrel.
packages/squad-cli/src/cli/commands/externalize.ts Switches externalize/internalize to manifest discovery with 3-phase migration, rollback, and audit output.
.changeset/discoverable-state-manifest.md Adds a changeset describing the manifest-driven migration work.

Comment thread packages/squad-sdk/src/state-manifest.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts
Comment thread test/external-state.test.ts
Comment thread test/external-state.test.ts Outdated
Comment thread .changeset/discoverable-state-manifest.md Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts Outdated
@diberry diberry force-pushed the squad/863-discoverable-state-manifest branch from cbac697 to bc9d88e Compare April 7, 2026 23:20
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 7, 2026

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit bc9d88e

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 3 item(s) to address before review

Status Check Details
Single commit 1 commit — clean history
Not in draft Ready for review
Branch up to date Up to date with dev
Copilot review No Copilot review yet — it may still be processing
Changeset present Changeset file found
Scope clean No .squad/ or docs/proposals/ files
No merge conflicts No merge conflicts
Copilot threads resolved 5 unresolved Copilot thread(s) — fix and resolve before merging
CI passing 1 check(s) failing: test
Issue linked Issue reference found
Protected files No protected bootstrap files changed

Files Changed (6 files, +636 −104)

File +/−
.changeset/discoverable-state-manifest.md +9 −0
packages/squad-cli/src/cli-entry.ts +2 −1
packages/squad-cli/src/cli/commands/externalize.ts +398 −101
packages/squad-sdk/src/index.ts +4 −0
packages/squad-sdk/src/state-manifest.ts +113 −0
test/external-state.test.ts +110 −2

Total: +636 −104


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Apr 8, 2026

🔍 Squad Review — Kaylee (Engineering)

# Check Status Notes
1 Changelog entry .changeset/discoverable-state-manifest.md (SDK + CLI patch)
2 Squashed to 1 commit 1 commit
3 CI green All checks passed
4 Copilot comments resolved 9/9 threads resolved with fixes or acknowledgments
5 No .squad/ files Clean
6 No unrelated files 6 files — all scoped to state manifest + externalize
7 Tests for changes est/external-state.test.ts — 26 tests (15 new)
8 Not a duplicate/reversal Unique scope (closes #863)

Verdict: ✅ Ready to merge


Review by Squad AI team (Kaylee — Engineering) · requested by Dina Berry

@diberry diberry force-pushed the squad/863-discoverable-state-manifest branch from f2404cf to b9a3bc2 Compare April 10, 2026 02:53
@diberry diberry changed the title fix(sdk): replace hardcoded state dirs with discoverable manifest fix(cli): replace hardcoded state lists with dynamic directory scan Apr 10, 2026
@diberry diberry force-pushed the squad/863-discoverable-state-manifest branch from b9a3bc2 to 93c6be3 Compare April 10, 2026 03:41
Copy link
Copy Markdown
Collaborator Author

@diberry diberry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(submitting pending review to unblock new review)

Comment thread test/external-state.test.ts Outdated
Comment thread packages/squad-cli/src/cli/commands/externalize.ts
Copy link
Copy Markdown
Collaborator Author

@diberry diberry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: runInternalize doesn't filter KEEP_LOCAL entries when copying from external to local. Under normal operation the external dir won't contain these files, but if it ever gets contaminated (manual copy, third-party tool), internalize would silently overwrite the local config.json, manifest.json, etc. A one-liner if (KEEP_LOCAL.has(entry)) continue; at the top of the loop would make this safe.

nit: PR description says "Only config.json is kept local" but KEEP_LOCAL now has 6 entries. Worth updating so reviewers aren't misled.

nit: isDirectorySync is marked @deprecated in the StorageProvider interface. This PR adds two new call-sites. Not a blocker since the whole externalize flow is sync, but worth a comment acknowledging the tech debt.

- Dynamic listSync() scan replaces static STATE_DIRS/STATE_FILES arrays
- Eliminates silent orphaning when new state artifacts are added
- KEEP_LOCAL protects 5 files read from the working tree by runtime code
  that does not go through external-state resolution:
  config.json, manifest.json, workstreams.json, upstream.json,
  squad-registry.json
- Add 6 tests for runExternalize/runInternalize covering basic ops,
  dynamic scan of unknown entries, config preservation, round-trip,
  config cleanup, and empty .squad/ edge case

Closes #863

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Apr 10, 2026

✅ CI validation passed on fork: diberry#141 — 7/7 checks green

@diberry diberry closed this Apr 10, 2026
@diberry diberry reopened this Apr 10, 2026
@diberry diberry closed this Apr 10, 2026
@diberry diberry reopened this Apr 10, 2026
@tamirdresher tamirdresher merged commit f50bbc8 into dev Apr 12, 2026
@tamirdresher tamirdresher deleted the squad/863-discoverable-state-manifest branch April 12, 2026 10:34
tamirdresher pushed a commit that referenced this pull request Apr 21, 2026
…908)

- Dynamic listSync() scan replaces static STATE_DIRS/STATE_FILES arrays
- Eliminates silent orphaning when new state artifacts are added
- KEEP_LOCAL protects 5 files read from the working tree by runtime code
  that does not go through external-state resolution:
  config.json, manifest.json, workstreams.json, upstream.json,
  squad-registry.json
- Add 6 tests for runExternalize/runInternalize covering basic ops,
  dynamic scan of unknown entries, config preservation, round-trip,
  config cleanup, and empty .squad/ edge case

Closes #863

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

arch: replace hardcoded STATE_DIRS/STATE_FILES in externalize.ts with discoverable manifest

3 participants