Skip to content

Fix legacy casting upgrades, portable MCP config, and CRLF preservation - #2190

Merged
bradygaster merged 5 commits into
devfrom
tamirdresher-microsoft-legacy-casting-upgrade-migration
Oct 13, 2026
Merged

bradygaster merged 5 commits into
devfrom
tamirdresher-microsoft-legacy-casting-upgrade-migration

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

Summary

Fixes #2174 and #2182.

Automatically migrates supported legacy casting state before upgrade-managed files are changed. Preserves agent identities and historical dates, archives original casting files unchanged, and rejects inconsistent or unsupported input before upgrade writes.

Also prevents machine-specific executable paths in shared MCP configuration and preserves existing line endings during upgrades, including coordinator capability refreshes and backups.

Validation

Tested official checksum-verified Windows releases 0.13.0 and 0.13.1 using actual released initialization and casting writers.

Six genuine released-state cases reproduce the 1.0.1 failure and successfully upgrade with this fix. Six additional anonymized legacy-format cases pass separately.

Verified identity/date/archive preservation, mutation-free dry runs, repeat upgrades, CRLF preservation, newline-only no-op behavior, portable MCP configuration, preserved custom metadata, and invalid-input rejection before upgrade changes.

Build/type checking and ESLint passed. Fifteen targeted test suites passed: 313 tests, one existing skip, and one TODO.

Dependency caveat: Microsoft CFS did not provide locked @types/node 26.6.4. Local validation temporarily used 26.6.3; tracked manifests and the lockfile remain unchanged.

Tamir Dresher and others added 2 commits October 8, 2026 17:24
Preserve historical identities and dates with non-overwriting original archives, strict preflight validation, and recoverable managed-pair publication. Add dry-run, idempotency, interruption, and upgrade-before-writes regressions.

Closes #2174

Closes #2182

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cd73060d-2a21-4bce-b8d6-c7507887dbe7
Use supported PATH executables for standalone project MCP entries, retaining machine-local absolute launch resolution and npm pins. Preserve destination newlines across managed copies, workflow stubs, coordinator capabilities, and shared MCP updates, including byte-preserving backups and newline-only no-op behavior.

Closes #2174

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cd73060d-2a21-4bce-b8d6-c7507887dbe7
Copilot AI balanced review requested due to automatic review settings October 9, 2026 04:09
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

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

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 2 item(s) to address before review

Status Check Details
❌ Single commit 5 commits — consider squashing before review
✅ 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 All 1 Copilot thread(s) resolved
✅ CI passing All checks passing

Files Changed (28 files, +1732 −65)

File +/−
.changeset/legacy-assignment-provenance.md +10 −0
.changeset/legacy-casting-upgrade.md +6 −0
.changeset/portable-mcp-preserve-newlines.md +6 −0
docs/src/content/docs/features/standalone-install.md +16 −4
docs/src/content/docs/scenarios/upgrading.md +104 −7
packages/squad-cli/src/cli/core/init.ts +3 −3
packages/squad-cli/src/cli/core/managed-file.ts +41 −0
packages/squad-cli/src/cli/core/mcp-root.ts +18 −14
packages/squad-cli/src/cli/core/mcp-spec.ts +17 −5
packages/squad-cli/src/cli/core/upgrade.ts +27 −16
packages/squad-sdk/src/casting/durable-registry.ts +364 −14
packages/squad-sdk/src/casting/index.ts +1 −0
packages/squad-sdk/src/config/team-capabilities.ts +2 −1
test/casting-legacy-migration.test.ts +489 −0
test/cli/legacy-casting-upgrade.test.ts +208 −0
test/cli/upgrade-portability.test.ts +181 −0
test/fixtures/casting-assigned-at/history.json +13 −0
test/fixtures/casting-assigned-at/registry.json +11 −0
test/fixtures/casting-entries/history.json +10 −0
test/fixtures/casting-entries/identities.json +16 −0
test/fixtures/casting-entries/registry.json +18 −0
test/fixtures/casting-incomplete-universe/history.json +13 −0
test/fixtures/casting-incomplete-universe/registry.json +17 −0
test/fixtures/casting-legacy/history.json +23 −0
test/fixtures/casting-legacy/registry.json +20 −0
test/mcp-root-write.test.ts +34 −0
test/mcp-spec-init.test.ts +49 −1
test/team-capabilities-lifecycle.test.ts +15 −0

Total: +1732 −65


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

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

🟠 Impact Analysis — PR #2190

Risk tier: 🟠 HIGH

📊 Summary

Metric Count
Files changed 28
Files added 16
Files modified 12
Files deleted 0
Modules touched 5
Critical files 1

🎯 Risk Factors

  • 28 files changed (21-50 → HIGH)
  • 5 modules touched (5-8 → HIGH)
  • Critical files touched: packages/squad-sdk/src/casting/index.ts

📦 Modules Affected

docs (2 files)
  • docs/src/content/docs/features/standalone-install.md
  • docs/src/content/docs/scenarios/upgrading.md
root (3 files)
  • .changeset/legacy-assignment-provenance.md
  • .changeset/legacy-casting-upgrade.md
  • .changeset/portable-mcp-preserve-newlines.md
squad-cli (5 files)
  • packages/squad-cli/src/cli/core/init.ts
  • packages/squad-cli/src/cli/core/managed-file.ts
  • packages/squad-cli/src/cli/core/mcp-root.ts
  • packages/squad-cli/src/cli/core/mcp-spec.ts
  • packages/squad-cli/src/cli/core/upgrade.ts
squad-sdk (3 files)
  • packages/squad-sdk/src/casting/durable-registry.ts
  • packages/squad-sdk/src/casting/index.ts
  • packages/squad-sdk/src/config/team-capabilities.ts
tests (15 files)
  • test/casting-legacy-migration.test.ts
  • test/cli/legacy-casting-upgrade.test.ts
  • test/cli/upgrade-portability.test.ts
  • test/fixtures/casting-assigned-at/history.json
  • test/fixtures/casting-assigned-at/registry.json
  • test/fixtures/casting-entries/history.json
  • test/fixtures/casting-entries/identities.json
  • test/fixtures/casting-entries/registry.json
  • test/fixtures/casting-incomplete-universe/history.json
  • test/fixtures/casting-incomplete-universe/registry.json
  • test/fixtures/casting-legacy/history.json
  • test/fixtures/casting-legacy/registry.json
  • test/mcp-root-write.test.ts
  • test/mcp-spec-init.test.ts
  • test/team-capabilities-lifecycle.test.ts

⚠️ Critical Files

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

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

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

Authoritative evidence: base-controlled pull_request_target reporter.

⚠️ Architectural review: 2 warning(s).

Severity Category Finding Files
🟡 warning bootstrap-area 5 file(s) in the bootstrap area (packages/squad-cli/src/cli/core/) were modified. These files must maintain zero external dependencies. Review carefully. packages/squad-cli/src/cli/core/init.ts, packages/squad-cli/src/cli/core/managed-file.ts, packages/squad-cli/src/cli/core/mcp-root.ts, packages/squad-cli/src/cli/core/mcp-spec.ts, packages/squad-cli/src/cli/core/upgrade.ts
🟡 warning sweeping-refactor This PR touches 28 files (28 modified/added, 0 deleted). Large PRs are harder to review — consider splitting if possible. —

Automated architectural review — informational only.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The managed-file binary heuristic can corrupt valid UTF-8 binary assets when adapting line endings.

1 open finding
What changed in this PR

Fixes legacy casting upgrades while improving MCP portability and preserving line endings across managed files.

Changes:

  • Migrates and archives supported legacy casting state before upgrades.
  • Writes portable project MCP commands while retaining custom metadata.
  • Preserves destination newline styles during upgrades.
File Description
test/​team-capabilities-lifecycle.test.ts Tests CRLF capability refreshes.
test/​mcp-spec-init.test.ts Tests portable MCP commands.
test/​mcp-root-write.test.ts Tests MCP metadata and CRLF preservation.
test/​fixtures/​casting-legacy/​registry.json Adds legacy registry fixture.
test/​fixtures/​casting-legacy/​history.json Adds legacy history fixture.
test/​cli/​upgrade-portability.test.ts Tests portable upgrades and managed files.
test/​cli/​legacy-casting-upgrade.test.ts Tests upgrade migration preflight.
test/​casting-legacy-migration.test.ts Tests migration validation and durability.
packages/​squad-sdk/​src/​config/​team-capabilities.ts Preserves coordinator line endings.
packages/​squad-sdk/​src/​casting/​index.ts Exports casting preflight API.
packages/​squad-sdk/​src/​casting/​durable-registry.ts Implements legacy casting migration.
packages/​squad-cli/​src/​cli/​core/​upgrade.ts Integrates migration and managed writes.
packages/​squad-cli/​src/​cli/​core/​mcp-spec.ts Projects portable MCP commands.
packages/​squad-cli/​src/​cli/​core/​mcp-root.ts Preserves MCP custom fields and newlines.
packages/​squad-cli/​src/​cli/​core/​managed-file.ts Adds newline-aware file helpers.
packages/​squad-cli/​src/​cli/​core/​init.ts Uses portable MCP specifications.
docs/​src/​content/​docs/​scenarios/​upgrading.md Documents migration and newline behavior.
docs/​src/​content/​docs/​features/​standalone-install.md Documents PATH-based MCP launching.
.changeset/​portable-mcp-preserve-newlines.md Records portability and newline fixes.
.changeset/​legacy-casting-upgrade.md Records casting migration behavior.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Require explicit known-text extensions before preserving destination newlines. Cover valid UTF-8 binary payloads without NUL bytes over existing CRLF files, unknown extensions, and known-text update/no-op behavior.

Closes #2174

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cd73060d-2a21-4bce-b8d6-c7507887dbe7
@bradygaster

Copy link
Copy Markdown
Collaborator

Cross-repository upgrade testing: three remaining legacy compatibility gaps

Publishing the findings here so they are visible on GitHub; the earlier inline comments were only local pending-review drafts and were not submitted.

Tested PR commit 0a9121218db7e96f34db238ebd6e4d384673b131 on October 9 using isolated, unchanged copies of three existing squads. The PR still has that head commit. Build used exact-lock dependencies with no overrides, macOS arm64, Node 24.16.0. None of the three native squads successfully upgraded. All rejected before persistent file changes.

1. Octosquad: entries[] / assignments[] legacy format is not recognized

  • Consumer: bradygaster/Octosquad at 47c688015d6148e7af0963a6490be0172c11e05e; installed coordinator 0.9.6-insider.2.
  • Native registry has 14 entries with persistent_name, universe, created_at, legacy_named, and status. History uses assignments[]. The installed coordinator explicitly documents this initialization format.
  • upgrade --dry-run, upgrade, and a repeat upgrade all exit 1: Cannot read a consistent casting registry/history pair: registry revision is invalid. The same failure reproduces using only the two original casting files.
  • Relevant code: legacy discriminator, line 1539. Only an agents root enters legacy conversion; entries falls through to modern revision validation.

Requested fix: Explicitly recognize and convert this historical pair format with validated identity mapping. Do not assume display names are canonical IDs or rebuild historical assignments from today's roster. Preserve original dates/membership and archive bytes. Add a real-shaped fixture covering dry-run, successful migration, and repeat upgrade.

2. PlanningSquad: historical assigned_at timestamps are not supported

  • Consumer: bradygaster/PlanningSquad at 873d8667de81c2228cea2260cf7f20419e2a5e5b; installed coordinator 0.11.0.
  • Genuine snapshot and usage records use assigned_at; the snapshot contains agents: string[] and universe.
  • Dry-run, upgrade, and repeat upgrade all exit 1: Cannot migrate legacy casting: snapshot descriptive-2026-08-08T01:16:24.000Z created_at is not a timestamp.
  • Relevant code: snapshot timestamp, line 1474 and usage timestamp, lines 1484-1492.

Requested fix: Accept the historical assigned_at field for both snapshot and usage conversion, preserve its original date, and reject conflicts when multiple recognized timestamp fields disagree. Retain snapshot/usage consistency checks. Add this variant to end-to-end migration, archive-fidelity, and repeat-upgrade coverage.

3. BradyBlogSquad: missing universe information needs an explicit compatibility policy

  • Consumer: bradygaster/BradyBlogSquad at 37d633f1e33c07d3143885f5501eb3963d81d8d8; installed coordinator 0.10.0.
  • All 13 native legacy agent records omit universe.
  • Dry-run, upgrade, and repeat upgrade all exit 1: Cannot read a consistent casting registry/history pair: registry contains invalid agent records.
  • Relevant code: post-conversion validation, line 1424. The converter does not handle this omission before validateRegistryShape requires a nonempty universe.
  • Source inspection additionally found a native snapshot with universe: null and no matching usage records. That later failure was not separately executed, so merely filling the agent field is not a demonstrated complete fix.

Requested fix: Define and test safe handling for descriptive legacy casts with incomplete universe/history evidence. Any normalization must be grounded in authoritative input; do not invent a universe or historical usage just to pass validation. If automatic migration cannot be justified, document the unsupported variant and provide actionable recovery guidance. Keep a fixture with the native omissions rather than repairing it before the test.

What passed, and what these results do not prove

  • All native and assigned derived-case rejections left fixture path/content snapshots unchanged. Original repository checkouts remained clean and byte-identical; no live squads were upgraded.
  • Exact-lock restore and SKIP_BUILD_BUMP=1 npm run build passed. Six focused regression suites passed 112 tests, with 2 Windows-only tests skipped.
  • A supported synthetic legacy fixture successfully migrated, preserved original archive bytes, and preserved casting state on repeat upgrade.
  • Octosquad's derived CRLF case and BradyBlogSquad's derived custom-MCP case hit the same casting preflight blockers. Therefore successful real-repository migration, archive fidelity, idempotence, MCP generation, and CRLF update behavior were not reached on these squads. CRLF simulation on macOS is not native Windows validation.
  • These are remaining compatibility gaps, not proven regressions from a successful baseline. Baseline source was inspected for Octosquad/PlanningSquad, but no baseline CLI comparison was executed.

Reproduction approach: check out the pinned consumer commit into a disposable directory, retain its native casting pair unchanged, and run the CLI built from the pinned PR commit with upgrade --dry-run, then upgrade, from that directory. Set SQUAD_HOME_DIR_OVERRIDE to a disposable home, unset SQUAD_TEAM_ROOT and SQUAD_STANDALONE_HOME, and invoke the built packages/squad-cli/dist/cli-entry.js directly rather than an installed release. Exact commands, logs, snapshots, and runners are retained in the local test-session artifacts; those local artifacts are not attached to GitHub.

Independent state-storage revision: map entries/assignments through unambiguous authoritative folder/charter identities, retain historical membership and dates, accept assigned_at with conflict detection, and provide actionable recovery refusals for incomplete universe evidence. Add anonymized native-shaped regressions and recovery documentation.

Closes #2174

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cd73060d-2a21-4bce-b8d6-c7507887dbe7
@tamirdresher

Copy link
Copy Markdown
Collaborator Author

@bradygaster Thanks for the pinned repros and access. I’ve pushed the independently revised converter in 75bfec3.

Octosquad now passes dry-run, upgrade, and repeat upgrade on an unchanged disposable copy of the pinned snapshot. The entries/assignments format uses validated folder/charter identity evidence rather than slugifying display names; historical membership comes from each recorded assignment, not today’s roster. Original dates and byte-exact archives are preserved.

PlanningSquad’s unchanged pinned input also passes all three runs. Snapshot and usage conversion now accepts assigned_at and rejects disagreements among recognized timestamp fields. Exact archives and historical dates are preserved.

BradyBlogSquad remains explicitly unsupported for automatic migration: the pinned input lacks sufficient universe and usage evidence. Dry-run, upgrade, and repeat stop before file changes with actionable recovery guidance. We do not fill in a universe or fabricate historical usage. The docs describe recovering original assignment/coordinator evidence from backups or version control and keeping the installed version if that evidence is unavailable. This is a verified safe refusal, not a successful migration.

These checks ran on Windows, including Octosquad/PlanningSquad CRLF and custom-MCP derived cases that actually reached migration. BradyBlogSquad’s custom-MCP case also remains unchanged on refusal. All private consumer input stays in private artifacts; committed fixtures are anonymized.

Build/type checks passed. Fifteen focused suites passed 357 tests (one existing skip and one TODO); ESLint passed with zero errors and 2248 warnings. The seven-release 0.10.0–1.0.1 rerun passed all 20 genuine producer cases and 21 separate supplemental cases. Existing dependency-restore/runtime caveats still apply; this does not claim macOS execution or an exact CI restore.

No merge, rebase, or squash was performed. The shared temporary workaround was not changed.

@bradygaster
bradygaster merged commit bfdd5ce into dev Oct 13, 2026
17 checks passed
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.

Updating to Squad 1.0.1 error

3 participants