Skip to content

feat!: runtime upstream inheritance, remove personal squads, host feature matrix (pre-preview follow-up) - #2274

Closed
tamirdresher wants to merge 6 commits into
devfrom
tamirdresher-microsoft-squad2-upstream-runtime-and-personal-rem
Closed

tamirdresher wants to merge 6 commits into
devfrom
tamirdresher-microsoft-squad2-upstream-runtime-and-personal-rem

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

What

Squad 2.0 pre-preview follow-up for the true blockers surfaced by the host-feature-matrix audit (#2255 stack reviews, Data's findings F1–F9). Three product changes and one evidence change: (1) upstream inheritance is now real at runtime on all 7 hosts (F1); (2) personal squads are removed rather than patched (F9, Brady: "personal squads can die a fiery death"); (3) state-bridge fixes F6/F7/F8 plus doc corrections for F2/F3/F5; (4) Data's Squad-feature × host matrix (test-fixtures/spec/suite-v0.2/host-feature-matrix.json, rendered reference page, integrity + bridge tests) ships with its cells updated to the post-fix state.

Why

  • F1 (CRITICAL): squad upstream add/sync wrote .squad/upstream.json, resolveUpstreams() existed in the SDK, but nothing called it and no coordinator prompt mentioned it. Docs promised "the coordinator reads upstreams at session start"; no host did. Brady: "upstream inheritance is critical".
  • F9: squad init silently set teamRoot to the global squad root whenever %APPDATA%\squad\personal-squad existed, so squad cast wrote the project's members into the personal squad and the project team.md stayed empty. Decision: remove the feature (insider-first 2.0.0-preview.1), never touch existing personal data.
  • F6/F8: squad_state_health returned the storage class name, not the backend the digest promises; squad_state_list without dir failed on orphan/two-layer. F7: Claude Code runs Agent spawns in the background but the matrix under-declared it. F2/F3/F5: docs over-promised GitLab, blurred what "ADO support" means, and under-documented headless Claude.

Related: #2251 #2252 #2253 #2254 (cascade now on dev), #2255.

How

F1 — Upstream inheritance at runtime (0723af44, 5d274f8f)

  • SDK upstream/resolver.ts: every ResolvedUpstream carries provenance (upstream:<name>@<ref>), origin, ref, depth, via, status (ok|stale|missing|unavailable|invalid|cycle|depth-exceeded), diagnostic, squadDir, lastSynced. Resolution recurses into each upstream's own upstream.json depth-first in declared order (default depth 3), de-duplicates diamonds (repo→org, repo→team→org inherits org once), detects cycles, and never fetches — git upstreams are read only from the clone squad upstream sync materialized (unavailable + sync hint otherwise; stale after 30 days, still read). buildEffectiveUpstreamContext applies precedence (local .squad/ wins, then order; losers kept with overriddenBy). formatUpstreamReport renders the tool output and is bounded (UPSTREAM_REPORT_MAX_CHARS = 48k; summary intact, detail truncated with an explicit marker). Also fixes the documented squad upstream add ../org/.squad form (a source that is the .squad dir).
  • Bridge: new runtime tool squad_state_upstreams (detail: true returns inherited bodies) registered in ToolRegistry and aliased in squad state-mcp, so every host gets it.
  • CLI: squad doctor gains an "upstream inheritance" check (pass/warn/fail with diagnostics); squad status prints the inherited-context display; squad upstream add messages no longer claim "read live".
  • Coordinator contract: canonical ### Upstream Inheritance section in .squad-templates/squad.agent.md (synced to .github/agents/squad.agent.md and all template mirrors) + digest item 16a in coordinator.ts; CANONICAL_COORDINATOR_HEADINGS updated (sync test green). Rules: call once after the handshake, never fetch, local wins then returned order, cite provenance, fail soft.
  • Docs: features/upstream-inheritance.md rewritten to what ships — note the precedence correction: earlier entries win (old docs said later-wins).

F9 — Personal squads removed (480ecf8a)

  • Deleted: squad personal|consult|extract (CLI), agents/personal.ts + sharing/consult.ts (SDK), resolvePersonalSquadDir/ensurePersonalSquadDir/ensureSquadPathTriple/isConsultMode, ResolvedSquadPaths.personalDir, SquadDirConfig.consult|extractionDisabled, InitOptions.extractionDisabled, the @bradygaster/squad-sdk/agents/personal subpath, init teamRoot auto-link, Ghost Protocol spawn block, personal-squad skill (+3 mirrors), ghost-protocol.md/personal-charter.md, coordinator "Personal Squad (Ambient Discovery)" / "Consult Mode Detection" / consult routing row, docs pages + nav, 7 dead test files.
  • Kept: squad init|upgrade --global (manages the global squad only; no longer bootstraps personal-squad/), squad export/import, Human Team Members, squad cast (minus personal/Ghost Protocol columns).
  • Added: read-only legacyPersonalSquadPath() / detectLegacyPersonalSquad() (computes the path without mkdir); cli/core/personal-squad-notice.ts used by squad upgrade, squad doctor and the dead subcommands (which exit 1).
  • Changeset .changeset/squad-2-0-upstream-runtime-and-personal-removal.md (major × 3), whatsnew v2.0.0 rows, upgrading guide "Personal squads removed".

F6/F7/F8 — state bridge (3792e629)

  • F6: squad_state_health → State backend: local|orphan|two-layer + storage class + team squad dir (ToolRegistry accepts a trailing { backendName }; state-mcp passes context.backend.name).
  • F8: StateBackendStorageAdapter.toRelative() maps the squad root to the empty key instead of ., so root listing works on git-backed backends.
  • F7: Claude Code declares background-runs in capability-matrix.json, CAPABILITY_TOKENS_BY_HOST, the architecture doc; R3-12 test flipped.

F2/F3/F5 — docs only

  • F5: headless Claude (claude -p) needs --mcp-config .mcp.json; Squad deliberately does not project enableAllProjectMcpServers: true.
  • F3: ADO support = detection + squad triage|watch via az; interactive Issues mode is GitHub-only for now.
  • F2: GitLab Issues pages marked "planned, not shipped".

Matrix (1cff52e5, e2985918 cherry-picked from Data; cells updated in 3792e629)

F1 cells → supported with validated-test evidence on all 7 hosts; consult-personal-squad → n/a (removed); Claude background-agents → supported; F6/F8 notes. Renderer now escapes | in feature names (markdownlint was red on Data's branch); cspell words for live-run names.

Reviewer redlines (Q/Bubu) → tests

Redline Satisfied by
Never delete/overwrite/relocate personal data test/personal-squad-removal.test.ts › "init → cast → upgrade → client install/rollback leaves a legacy personal squad byte-identical…" (sha256 fingerprint of the legacy tree before/after each step; teamRoot never set; roster lands in the project)
Byte-exact rollback / idempotency / interruption same test: second runUpgrade identical; installClients→uninstallClients removes the projection and leaves the legacy tree identical
Coexistence / multi-project personal-squad-removal.test.ts › "two projects initialised side by side … are independent"
Explicit, reversible migration notice; user choice on shared teamRoot personal-squad-removal.test.ts › "squad doctor warns about the legacy directory and about a teamRoot…" (path named, "untouched", export/import recipe, "remove the key … or keep it"); "squad personal|consult|extract print the removal notice…"; detection "never creates the legacy directory"
Upstreams: locally synced only, no startup network test/upstream-runtime.test.ts › "reports missing local paths, unsynced git clones, stale clones and invalid entries…" (asserts no clone dir created) and both bridge tests assert _upstream_repos is never created
Deterministic order / precedence / provenance, project overrides "orders upstreams by declaration, then depth-first…", "local .squad/ wins skill-name conflicts, then the earliest upstream…", "is deterministic across repeated resolutions (restart)"
Cycles / depth / duplicates / missing / corrupt / stale "stops at the depth limit…", "detects cycles back to the root and between upstreams…", "a diamond … inherits org once", soft-failure test above
Bounded prompt size "formatUpstreamReport bounds the detail output and keeps the summary intact…"
Restart / monorepo / multiple-upstream / upgrade-rollback "is deterministic across repeated resolutions", "state-mcp launched from a monorepo subfolder resolves the root upstream.json", "squad upgrade leaves upstream.json and the synced clone untouched…", plus test/squad-20-host-feature-matrix.test.ts › "squad_state_upstreams over the bridge serves inherited skills and decisions with provenance and never fetches"

⚠️ Quick Check

  • If SDK/CLI source files changed: completed the applicable Changeset step below (.changeset/squad-2-0-upstream-runtime-and-personal-removal.md, major × 3)

PR Readiness Checklist

The PR readiness bot will validate these automatically after push.

Branch & Commit

Build & Test

  • SKIP_BUILD_BUMP=1 npm run build — passed
  • npm run lint — passed (SDK + CLI tsc --noEmit)
  • npm run lint:eslint — 0 errors (2224 pre-existing warnings repo-wide)
  • npm run lint:docs — passed (markdownlint 0 issues, cspell 0 issues; was red on the matrix branch before the renderer/cspell fix)
  • Targeted suites: npx vitest run test/clients.test.ts test/clients-real-cli.test.ts test/squad-20-host-feature-matrix.test.ts test/cli-command-wiring.test.ts test/ux-gates.test.ts test/speed-gates.test.ts test/template-sync.test.ts test/squad-20-all-scenarios.e2e.test.ts test/squad-20-real-clients-stdio.e2e.test.ts test/backend.test.ts test/specification-suite.test.ts test/docs-build.test.ts test/squad-20-pack-smoke.test.ts test/upstream-runtime.test.ts test/upstream.test.ts test/upstream-e2e.test.ts test/personal-squad-removal.test.ts test/tools.test.ts test/compat-v041.test.ts --testTimeout=120000 --hookTimeout=120000 — 779 passed / 5 expected-fail / 0 failed. The 5 it.fails are the remaining known digest gaps (team-root, ADO, GitLab, model-selection, marketplace) that this PR does not claim to close. The raised timeout was needed because the Windows host running this was saturated (single git ops took 10–60 s); the gate tests themselves pass.
  • npm test (full): 11482 passed / 358 failed / 263 skipped / 47 todo across 2418 files — honestly not all green on this host. Every failure was triaged and is environmental, not caused by this branch: gh-aw suites require gh aw v0.91.5 (v0.89.22 installed) or workflows path resolution; state-backend*, storage-provider, notes-promote, create-if-absent, upgrade-state-backend = git hook timeouts + Windows 8.3 short-path realpath ("Symlink traversal blocked: café"); charter-spec, coordinator-scope-control, gh-aw-command-parse = CRLF working copy; repl-ux*, journey-power-user = no TTY; speed-gates = load; acceptance doctor scenarios pass when run serially and the acceptance init scenario trips the git-worktree guard (I'm in a worktree); team-root-resolution expects no ~/.squad on the machine. The two failures that were branch-caused were fixed in-branch (test/cli/cast.test.ts mocked the deleted agents/personal subpath; compat-v041 tool count 18→19). Requesting CI as the authoritative full run.
  • For migration PRs (>20 files): include test output summary in PR description — above

Changeset

  • Changeset added (.changeset/squad-2-0-upstream-runtime-and-personal-removal.md)
  • Or direct CHANGELOG.md entry — N/A
  • Or skip-changelog label applied — N/A

Docs

  • README section updated (--global wording; personal-squad references removed in README + CLI README)
  • Docs feature page (features/upstream-inheritance.md rewritten; scenarios/upgrading.md "Personal squads removed"; whatsnew.md v2.0.0; reference/host-feature-matrix.md; scenarios/using-squad-across-clients.md, features/enterprise-platforms.md, features/gitlab-issues.md, tour-gitlab-issues.md, get-started/installation.md, guide.md, reference/{cli,config,sdk,api-reference}.md, concepts/squad-2-0-architecture.md)

Exports

  • package.json subpath exports updated — removed ./agents/personal; ./upstream already existed and now exports UpstreamStatus, ResolveUpstreamsOptions, InheritedSkill, InheritedDocument, EffectiveUpstreamContext, DEFAULT_UPSTREAM_MAX_DEPTH, DEFAULT_UPSTREAM_STALE_DAYS, UPSTREAM_REPORT_MAX_CHARS, upstreamProvenance, buildEffectiveUpstreamContext, formatUpstreamReport; root barrel exports legacyPersonalSquadPath, detectLegacyPersonalSquad, LegacyPersonalSquadInfo

Breaking Changes

Personal squads are removed (Squad 2.0). squad personal, squad consult, squad extract, ambient ~/.config/squad/personal-squad (%APPDATA%\squad\personal-squad) agent discovery, Ghost Protocol spawn rules, consult-mode routing and the SQUAD_NO_PERSONAL / SQUAD_PERSONAL_DIR switches no longer exist. squad init never sets config.json teamRoot to the global squad root and never writes outside the project .squad/. SDK removals are listed under "How → F9" above (resolvePersonalSquadDir, ensurePersonalSquadDir, ensureSquadPathTriple, isConsultMode, ResolvedSquadPaths.personalDir, SquadDirConfig.consult|extractionDisabled, InitOptions.extractionDisabled, @bradygaster/squad-sdk/agents/personal, sharing/consult).

Nothing is deleted, moved or rewritten. squad upgrade and squad doctor print this once when 1.x leftovers are detected (and squad personal|consult|extract print it and exit 1):

⚠ Personal squads were removed in Squad 2.0.
  Your personal squad at <path>/squad/personal-squad is untouched: Squad 2.0 never reads, writes or deletes it.
  To keep agents from it, copy them into this project explicitly:
    squad export --output personal-squad.json   (run inside <path>/squad/personal-squad)
    squad import personal-squad.json           (run inside this project)
  Delete the old directory yourself when you no longer need it.
  This project's .squad/config.json has teamRoot = <global squad root>, which a 1.x "squad init" set automatically.
  Squad 2.0 does not change it: remove the key to make this project self-contained, or keep it if the shared team root is intentional.
  Details: docs → Upgrading → "Personal squads removed".

Upstream precedence clarified: the local .squad/ wins, then earlier entries in upstream.json win conflicts (the 1.x docs said later-wins; the code never implemented either). Git upstreams are read only from the clone made by squad upstream sync — run it after upgrading. ToolRegistry gains a 7th optional { backendName } parameter (additive). squad_state_health output format changed from a single line to State backend: … / State backend storage: … / Team squad dir: ….

Waivers

Requesting a waiver for the "npm test passes (all tests green)" item on the contributor's host: reason — the 358 failures are environmental on a saturated Windows worktree (gh-aw version pin, git timeouts, 8.3 short paths, CRLF, no TTY, worktree guard) and are enumerated above; CI is requested as the authoritative run. To be approved by the current Lead or Quality role owner in PR comments before merge.


Working as B'Elanna (Durable Systems Engineer). Decision context: Brady — "insider first (2.0.0-preview.1); upstream inheritance is critical; personal squads can die a fiery death." Scope cut approved by the Squad 2.0 research session; Q/Bubu redlines addressed as tabulated above.

Copilot AI balanced review requested due to automatic review settings October 22, 2026 13:10
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

🏗️ Architectural Review

Authoritative evidence: base-controlled pull_request_target reporter.

⚠️ Architectural review: 4 warning(s).

Severity Category Finding Files
🟡 warning bootstrap-area 4 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/command-help.ts, packages/squad-cli/src/cli/core/init.ts, packages/squad-cli/src/cli/core/personal-squad-notice.ts, packages/squad-cli/src/cli/core/upgrade.ts
🟡 warning export-surface Package entry point(s) modified with 171 new/changed export(s). New public API surface requires careful review for backward compatibility. packages/squad-sdk/src/index.ts
🟡 warning sweeping-refactor This PR touches 104 files (84 modified/added, 20 deleted). Large PRs are harder to review — consider splitting if possible. —
🟡 warning file-deletion 5 source file(s) deleted from packages/. Verify no public API or imports are broken. packages/squad-cli/src/cli/commands/consult.ts, packages/squad-cli/src/cli/commands/extract.ts, packages/squad-cli/src/cli/commands/personal.ts, packages/squad-sdk/src/agents/personal.ts, packages/squad-sdk/src/sharing/consult.ts

Automated architectural review — informational only.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

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

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 3 item(s) to address before review

Status Check Details
❌ Single commit 6 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 0 active Copilot thread(s) resolved (5 outdated skipped)
❌ CI passing 1 check(s) still running

Files Changed (104 files, +9619 −6571)

File +/−
.changeset/squad-2-0-upstream-runtime-and-personal-removal.md +12 −0
.github/agents/squad.agent.md +8 −23
.squad-templates/README.md +1 −1
.squad-templates/skills/personal-squad/SKILL.md +0 −66
.squad-templates/spawn-reference.md +0 −12
.squad-templates/squad.agent.md +8 −23
README.md +2 −2
cspell.json +2 −0
docs/src/content/docs/concepts/portability.md +2 −2
docs/src/content/docs/concepts/squad-2-0-architecture.md +1 −1
docs/src/content/docs/features/consult-mode.md +0 −260
docs/src/content/docs/features/enterprise-platforms.md +2 −0
docs/src/content/docs/features/gitlab-issues.md +1 −1
docs/src/content/docs/features/upstream-inheritance.md +86 −29
docs/src/content/docs/get-started/installation.md +8 −5
docs/src/content/docs/guide.md +1 −1
docs/src/content/docs/guide/personal-squad.md +0 −350
docs/src/content/docs/reference/api-reference.md +1 −1
docs/src/content/docs/reference/cli.md +2 −2
docs/src/content/docs/reference/config.md +1 −1
docs/src/content/docs/reference/host-feature-matrix.md +1055 −0
docs/src/content/docs/reference/sdk.md +3 −3
docs/src/content/docs/scenarios/upgrading.md +21 −0
docs/src/content/docs/scenarios/using-squad-across-clients.md +2 −2
docs/src/content/docs/tour-gitlab-issues.md +1 −1
docs/src/content/docs/whatsnew.md +5 −0
docs/src/navigation.ts +1 −2
packages/squad-cli/README.md +2 −2
packages/squad-cli/src/cli-entry.ts +32 −30
packages/squad-cli/src/cli/commands/cast.ts +16 −74
packages/squad-cli/src/cli/commands/consult.ts +0 −103
packages/squad-cli/src/cli/commands/doctor.ts +56 −0
packages/squad-cli/src/cli/commands/extract.ts +0 −332
packages/squad-cli/src/cli/commands/import-legacy-personal.ts +172 −0
packages/squad-cli/src/cli/commands/personal.ts +0 −248
packages/squad-cli/src/cli/commands/state-mcp.ts +11 −3
packages/squad-cli/src/cli/commands/upstream.ts +312 −250
packages/squad-cli/src/cli/core/command-help.ts +10 −31
packages/squad-cli/src/cli/core/init.ts +6 −41
packages/squad-cli/src/cli/core/personal-squad-notice.ts +57 −0
packages/squad-cli/src/cli/core/upgrade.ts +8 −0
packages/squad-cli/templates/README.md +1 −1
packages/squad-cli/templates/skills/personal-squad/SKILL.md +0 −66
packages/squad-cli/templates/spawn-reference.md +0 −12
packages/squad-cli/templates/squad.agent.md.template +8 −23
packages/squad-sdk/package.json +0 −4
packages/squad-sdk/src/agents/index.ts +0 −8
packages/squad-sdk/src/agents/personal.ts +0 −97
packages/squad-sdk/src/client/adapters/capabilities.ts +1 −1
packages/squad-sdk/src/client/adapters/coordinator.ts +2 −0
... +54 more files

Total: +9619 −6571


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 22, 2026 •

Copy link
Copy Markdown
Contributor

🔴 Impact Analysis — PR #2274

Risk tier: 🔴 CRITICAL

📊 Summary

Metric Count
Files changed 104
Files added 10
Files modified 74
Files deleted 20
Modules touched 8
Critical files 6

🎯 Risk Factors

  • 104 files changed (>50 → CRITICAL)
  • 8 modules touched (5-8 → HIGH)
  • 20 files deleted (>10 → CRITICAL)
  • Critical files touched: packages/squad-sdk/package.json, packages/squad-sdk/src/agents/index.ts, packages/squad-sdk/src/index.ts, packages/squad-sdk/src/sharing/index.ts, packages/squad-sdk/src/tools/index.ts, packages/squad-sdk/src/upstream/index.ts

📦 Modules Affected

ci-workflows (1 file)
  • .github/agents/squad.agent.md
docs (19 files)
  • docs/src/content/docs/concepts/portability.md
  • docs/src/content/docs/concepts/squad-2-0-architecture.md
  • docs/src/content/docs/features/consult-mode.md
  • docs/src/content/docs/features/enterprise-platforms.md
  • docs/src/content/docs/features/gitlab-issues.md
  • docs/src/content/docs/features/upstream-inheritance.md
  • docs/src/content/docs/get-started/installation.md
  • docs/src/content/docs/guide.md
  • docs/src/content/docs/guide/personal-squad.md
  • docs/src/content/docs/reference/api-reference.md
  • docs/src/content/docs/reference/cli.md
  • docs/src/content/docs/reference/config.md
  • docs/src/content/docs/reference/host-feature-matrix.md
  • docs/src/content/docs/reference/sdk.md
  • docs/src/content/docs/scenarios/upgrading.md
  • docs/src/content/docs/scenarios/using-squad-across-clients.md
  • docs/src/content/docs/tour-gitlab-issues.md
  • docs/src/content/docs/whatsnew.md
  • docs/src/navigation.ts
root (11 files)
  • .changeset/squad-2-0-upstream-runtime-and-personal-removal.md
  • README.md
  • cspell.json
  • templates/README.md
  • templates/ghost-protocol.md
  • templates/personal-charter.md
  • templates/skills/personal-squad/SKILL.md
  • templates/spawn-reference.md
  • templates/squad.agent.md.template
  • test-fixtures/spec/suite-v0.2/capability-matrix.json
  • test-fixtures/spec/suite-v0.2/host-feature-matrix.json
scripts (1 file)
  • scripts/render-host-feature-matrix.mjs
squad-cli (18 files)
  • packages/squad-cli/README.md
  • packages/squad-cli/src/cli-entry.ts
  • packages/squad-cli/src/cli/commands/cast.ts
  • packages/squad-cli/src/cli/commands/consult.ts
  • packages/squad-cli/src/cli/commands/doctor.ts
  • packages/squad-cli/src/cli/commands/extract.ts
  • packages/squad-cli/src/cli/commands/import-legacy-personal.ts
  • packages/squad-cli/src/cli/commands/personal.ts
  • packages/squad-cli/src/cli/commands/state-mcp.ts
  • packages/squad-cli/src/cli/commands/upstream.ts
  • packages/squad-cli/src/cli/core/command-help.ts
  • packages/squad-cli/src/cli/core/init.ts
  • packages/squad-cli/src/cli/core/personal-squad-notice.ts
  • packages/squad-cli/src/cli/core/upgrade.ts
  • packages/squad-cli/templates/README.md
  • packages/squad-cli/templates/skills/personal-squad/SKILL.md
  • packages/squad-cli/templates/spawn-reference.md
  • packages/squad-cli/templates/squad.agent.md.template
squad-sdk (20 files)
  • packages/squad-sdk/package.json
  • packages/squad-sdk/src/agents/index.ts
  • packages/squad-sdk/src/agents/personal.ts
  • packages/squad-sdk/src/client/adapters/capabilities.ts
  • packages/squad-sdk/src/client/adapters/coordinator.ts
  • packages/squad-sdk/src/config/init.ts
  • packages/squad-sdk/src/index.ts
  • packages/squad-sdk/src/multi-squad.ts
  • packages/squad-sdk/src/resolution.ts
  • packages/squad-sdk/src/sharing/consult.ts
  • packages/squad-sdk/src/sharing/index.ts
  • packages/squad-sdk/src/state-backend.ts
  • packages/squad-sdk/src/tools/index.ts
  • packages/squad-sdk/src/upstream/index.ts
  • packages/squad-sdk/src/upstream/resolver.ts
  • packages/squad-sdk/src/upstream/types.ts
  • packages/squad-sdk/templates/README.md
  • packages/squad-sdk/templates/skills/personal-squad/SKILL.md
  • packages/squad-sdk/templates/spawn-reference.md
  • packages/squad-sdk/templates/squad.agent.md.template
templates (4 files)
  • .squad-templates/README.md
  • .squad-templates/skills/personal-squad/SKILL.md
  • .squad-templates/spawn-reference.md
  • .squad-templates/squad.agent.md
tests (30 files)
  • test/acceptance/acceptance.test.ts
  • test/acceptance/features/consult-command.feature
  • test/acceptance/features/extract-command.feature
  • test/cli-global.test.ts
  • test/cli-packaging-smoke.test.ts
  • test/cli/cast.test.ts
  • test/cli/command-help.test.ts
  • test/cli/consult.test.ts
  • test/cli/extract.test.ts
  • test/cli/upstream-source-hardening.test.ts
  • test/clients.test.ts
  • test/compat-v041.test.ts
  • test/cross-package-exports.test.ts
  • test/docs-build.test.ts
  • test/external-state.test.ts
  • test/multi-squad.test.ts
  • test/personal-squad-init.test.ts
  • test/personal-squad-removal.test.ts
  • test/personal-squad.test.ts
  • test/resolution.test.ts
  • test/sdk-feature-parity.test.ts
  • test/sdk/consult.test.ts
  • test/squad-20-all-scenarios.e2e.test.ts
  • test/squad-20-host-feature-matrix.test.ts
  • test/squad-20-pack-smoke.test.ts
  • test/standalone-release-workflow.test.ts
  • test/template-extra-classification.test.ts
  • test/tools.test.ts
  • test/upstream-runtime.test.ts
  • test/upstream.test.ts

⚠️ Critical Files

  • packages/squad-sdk/package.json
  • packages/squad-sdk/src/agents/index.ts
  • packages/squad-sdk/src/index.ts
  • packages/squad-sdk/src/sharing/index.ts
  • packages/squad-sdk/src/tools/index.ts
  • packages/squad-sdk/src/upstream/index.ts

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

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

Destructive test cleanup, an unusable migration recipe and inconsistent upstream precedence and configuration roots remain unresolved.

5 open issues
What changed in this PR

This Squad 2.0 follow-up connects upstream inheritance to the multi-host runtime, removes personal-squad functionality, and aligns capability reporting and documentation with supported behavior.

Changes:

  • Adds runtime upstream resolution, provenance, precedence rules, coordinator instructions and diagnostic reporting.
  • Removes personal-squad commands, APIs and templates; adds legacy detection, migration notices and preservation tests.
  • Corrects state-backend reporting, root listing and Claude background capabilities; adds host-matrix rendering and documentation updates.
File Description
test/​upstream.test.ts Updates upstream diagnostic expectations.
test/​tools.test.ts Expects the upstream runtime tool.
test/​template-extra-classification.test.ts Removes deleted personal-template exceptions.
test/​standalone-release-workflow.test.ts Removes the deleted personal-squad guide.
test/​squad-20-pack-smoke.test.ts Removes the retired personal-squad switch.
test/​squad-20-all-scenarios.e2e.test.ts Updates Claude background-capability assertions.
test/​sdk-feature-parity.test.ts Removes consult-mode API tests.
test/​resolution.test.ts Tests read-only legacy detection.
test/​personal-squad-removal.test.ts Adds preservation, isolation and notice coverage.
test/​multi-squad.test.ts Clarifies global-squad terminology in a comment.
test/​docs-build.test.ts Removes deleted documentation expectations.
test/​cross-package-exports.test.ts Updates removed APIs and detector exports.
test/​compat-v041.test.ts Updates built-in tool counts.
test/​clients.test.ts Tests upstream instructions and documented digest gaps.
test/​cli/​extract.test.ts Deletes obsolete extract-command tests.
test/​cli/​consult.test.ts Deletes obsolete consult-command tests.
test/​cli/​command-help.test.ts Removes retired commands from help expectations.
test/​cli/​cast.test.ts Removes the personal-agent mock.
test/​cli-packaging-smoke.test.ts Removes retired command expectations.
test/​cli-global.test.ts Changes routing fixtures to global squads.
test/​acceptance/​features/​extract-command.feature Deletes extract acceptance scenarios.
test/​acceptance/​features/​consult-command.feature Deletes consult acceptance scenarios.
test/​acceptance/​acceptance.test.ts Unregisters deleted acceptance features.
test-fixtures/​spec/​suite-v0.2/​capability-matrix.json Declares Claude background runs.
templates/​squad.agent.md.template Adds inheritance instructions; removes personal routing.
templates/​spawn-reference.md Removes Ghost Protocol spawn instructions.
templates/​skills/​personal-squad/​SKILL.md Deletes the personal-squad skill mirror.
templates/​README.md Updates the spawn-reference description.
templates/​personal-charter.md Deletes the personal-agent charter template.
templates/​ghost-protocol.md Deletes personal-agent behavior rules.
scripts/​render-host-feature-matrix.mjs Adds matrix rendering, summaries and freshness checks.
README.md Clarifies global init and upgrade terminology.
packages/​squad-sdk/​templates/​squad.agent.md.template Mirrors updated coordinator instructions.
packages/​squad-sdk/​templates/​spawn-reference.md Removes packaged Ghost Protocol instructions.
packages/​squad-sdk/​templates/​skills/​personal-squad/​SKILL.md Deletes the SDK personal-squad skill.
packages/​squad-sdk/​templates/​README.md Updates the packaged spawn-reference description.
packages/​squad-sdk/​src/​upstream/​types.ts Defines provenance, statuses and effective context.
packages/​squad-sdk/​src/​upstream/​index.ts Exports expanded upstream APIs.
packages/​squad-sdk/​src/​tools/​index.ts Adds upstream tooling and backend identification.
packages/​squad-sdk/​src/​state-backend.ts Maps root listing to the empty state key.
packages/​squad-sdk/​src/​sharing/​index.ts Removes consult-module exports.
packages/​squad-sdk/​src/​resolution.ts Replaces personal helpers with legacy detection.
packages/​squad-sdk/​src/​multi-squad.ts Clarifies global-squad terminology in a comment.
packages/​squad-sdk/​src/​index.ts Updates public exports for personal-squad removal.
packages/​squad-sdk/​src/​config/​init.ts Removes consult extraction configuration.
packages/​squad-sdk/​src/​client/​adapters/​coordinator.ts Adds the upstream inheritance digest contract.
packages/​squad-sdk/​src/​client/​adapters/​capabilities.ts Declares Claude background-run support.
packages/​squad-sdk/​src/​agents/​personal.ts Deletes ambient personal-agent discovery.
packages/​squad-sdk/​src/​agents/​index.ts Removes personal-agent exports.
packages/​squad-sdk/​package.json Removes the personal-agent subpath export.
packages/​squad-cli/​templates/​squad.agent.md.template Mirrors updated coordinator instructions.
packages/​squad-cli/​templates/​spawn-reference.md Removes packaged Ghost Protocol instructions.
packages/​squad-cli/​templates/​skills/​personal-squad/​SKILL.md Deletes the CLI personal-squad skill.
packages/​squad-cli/​templates/​README.md Updates the packaged spawn-reference description.
packages/​squad-cli/​src/​cli/​core/​upgrade.ts Prints legacy personal-squad notices.
packages/​squad-cli/​src/​cli/​core/​personal-squad-notice.ts Adds removal and migration messages.
packages/​squad-cli/​src/​cli/​core/​init.ts Removes personal-directory creation and automatic linking.
packages/​squad-cli/​src/​cli/​core/​command-help.ts Removes retired commands and updates terminology.
packages/​squad-cli/​src/​cli/​commands/​upstream.ts Clarifies local-snapshot startup behavior.
packages/​squad-cli/​src/​cli/​commands/​state-mcp.ts Exposes upstream tooling and passes backend identity.
packages/​squad-cli/​src/​cli/​commands/​personal.ts Deletes personal-squad management commands.
packages/​squad-cli/​src/​cli/​commands/​extract.ts Deletes consult-learning extraction.
packages/​squad-cli/​src/​cli/​commands/​doctor.ts Adds upstream and legacy-personal diagnostics.
packages/​squad-cli/​src/​cli/​commands/​consult.ts Deletes consult-mode setup.
packages/​squad-cli/​src/​cli/​commands/​cast.ts Removes personal-agent merging and display columns.
packages/​squad-cli/​src/​cli-entry.ts Adds removal handling and upstream status output.
packages/​squad-cli/​README.md Clarifies global-squad behavior.
docs/​src/​navigation.ts Removes retired pages and links the host matrix.
docs/​src/​content/​docs/​whatsnew.md Documents runtime additions and breaking changes.
docs/​src/​content/​docs/​tour-gitlab-issues.md Marks the walkthrough as planned functionality.
docs/​src/​content/​docs/​scenarios/​using-squad-across-clients.md Clarifies headless Claude setup and legacy linking.
docs/​src/​content/​docs/​scenarios/​upgrading.md Adds personal-squad removal and migration guidance.
docs/​src/​content/​docs/​reference/​sdk.md Updates resolution terminology and helper descriptions.
docs/​src/​content/​docs/​reference/​config.md Uses global-squad terminology.
docs/​src/​content/​docs/​reference/​cli.md Clarifies global initialization and resolution.
docs/​src/​content/​docs/​reference/​api-reference.md Updates the global-path API description.
docs/​src/​content/​docs/​guide/​personal-squad.md Deletes the retired personal-squad guide.
docs/​src/​content/​docs/​guide.md Clarifies global initialization behavior.
docs/​src/​content/​docs/​get-started/​installation.md Replaces personal-squad setup guidance.
docs/​src/​content/​docs/​features/​upstream-inheritance.md Documents runtime resolution, precedence and APIs.
docs/​src/​content/​docs/​features/​gitlab-issues.md Marks GitLab integration as not shipped.
docs/​src/​content/​docs/​features/​enterprise-platforms.md Defines the scope of Azure DevOps support.
docs/​src/​content/​docs/​features/​consult-mode.md Deletes retired consult-mode documentation.
docs/​src/​content/​docs/​concepts/​squad-2-0-architecture.md Updates Claude capability documentation.
cspell.json Adds names used in documentation.
.squad-templates/​squad.agent.md Adds canonical inheritance instructions; removes personal routing.
.squad-templates/​spawn-reference.md Removes canonical Ghost Protocol instructions.
.squad-templates/​skills/​personal-squad/​SKILL.md Deletes the canonical personal-squad skill.
.squad-templates/​README.md Updates the canonical spawn-reference description.
.github/​agents/​squad.agent.md Synchronizes the active coordinator contract.
.changeset/​squad-2-0-upstream-runtime-and-personal-removal.md Records major releases and migration changes.

Review effort: Balanced

Comment thread test/cli-global.test.ts Resolved
Comment thread packages/squad-sdk/src/tools/index.ts Resolved
Comment thread packages/squad-sdk/src/tools/index.ts Resolved
tamirdresher pushed a commit that referenced this pull request Oct 22, 2026
… untrusted marking, working legacy import, project-local upstream root

Copilot review threads + Worf FUP-1..12 on #2274:

Upstream inheritance
- FUP-2: all snapshot reads go through a ContainedReader rooted at the
  upstream (clone dir / declared source / export dir): per-component lstat
  refuses symlinks and junctions, realpath must stay inside the root; any
  refusal marks the upstream `invalid` and serves nothing from it.
- FUP-9: per-file cap UPSTREAM_MAX_FILE_BYTES (1 MiB); larger files invalidate
  the upstream with a diagnostic.
- FUP-3: report header states inherited content is UNTRUSTED third-party data,
  every body in detail mode is fenced with BEGIN/END UNTRUSTED markers; the
  canonical `### Upstream Inheritance` section and digest 16a say the same.
- FUP-11: relative local/export sources resolve against the declaring squad's
  project root, never process.cwd().
- Copilot P2 (root policy): upstream declarations are project-local
  (`squad upstream add` writes them beside config.json, `squad externalize`
  keeps them local). ToolRegistry gains `upstreamDir`; state-mcp passes
  context.paths.projectDir while state tools keep operating on the team
  root; `squad doctor` reads the local .squad/ too.
- Copilot P2 / FUP-8: local-wins scans all five skill roots (.squad,
  .copilot, .github, .claude, .agents).
- FUP-7: doctor reports an unsynced/stale git upstream as a warning with the
  sync hint; only missing/invalid/cycle/depth fail.
- FUP-4: concepts/portability.md now says earlier entries win.

Personal squad removal
- FUP-1 / Copilot P2: the advertised `squad export` recipe could not read a
  1.x layout (no .squad/, no team.md; flag is --out). New read-only
  `squad import --legacy-personal [<dir>] [--dry-run]` registers each 1.x
  agent through the normal cast flow (charter/history kept verbatim,
  existing names skipped, source never written). Notice, doctor, upgrading
  guide, whatsnew, changeset and matrix text updated to it.
- FUP-5: notice also printed by `squad init` and by the already-up-to-date
  upgrade path.
- FUP-6: detection honours a still-set SQUAD_PERSONAL_DIR.
- FUP-12: external-state tests no longer assert the dead `consult` field;
  "fiery death" phrasing removed from the public matrix page.

Tests (all mutation-proven against the pre-fix code): junction/symlink
escape, file-symlink escape, oversized file, untrusted fences around an
injection payload, relative source from another cwd, linked-project
upstream root over the bridge, five skill roots, real-1.x-layout legacy
import round trip (dry-run, import, re-run skips, source sha256-identical),
SQUAD_PERSONAL_DIR detection, notice on init/up-to-date upgrade, doctor
severity; digest regex asserts the untrusted sentence on all 7 hosts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
Copilot and others added 5 commits October 22, 2026 16:59
…enCode runs and bridge tests

Adds test-fixtures/spec/suite-v0.2/host-feature-matrix.json (source of truth),
scripts/render-host-feature-matrix.mjs, the rendered reference page, and
test/squad-20-host-feature-matrix.test.ts (schema/evidence integrity, rendered
page in sync, runtime flags vs capability tokens, deterministic bridge
scenarios: monorepo subfolder, remote-mode satellite, orphan/two-layer
squad_decide). Live validation: Claude Code 2.1.296 + OpenCode across 15
scenarios; Kiro/Antigravity/Cursor/Codex blocked (quota/auth) and kept
static-only. Cherry-picked from tamirdresher-microsoft-squad2-host-feature-matrix.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
`squad upstream add/sync` wrote `.squad/upstream.json` but `resolveUpstreams()`
had no caller and no coordinator prompt mentioned it, so no host ever inherited
anything. This makes inheritance real at session start:

- SDK resolver: provenance (`upstream:<name>@<ref>`) on every upstream, status
  (`ok|stale|missing|unavailable|invalid|cycle|depth-exceeded`) with actionable
  diagnostics, transitive resolution (declared order, depth-first, default depth
  3) with cycle detection and diamond de-duplication, deterministic precedence
  (local `.squad/` wins, then order) via `buildEffectiveUpstreamContext`, and a
  `formatUpstreamReport` renderer. Never fetches: git upstreams are read from
  the clone `squad upstream sync` materialized. Accepts a source that already
  is a `.squad/` dir (the documented `squad upstream add ../org/.squad` form).
- New `squad_state_upstreams` runtime tool, exposed over `squad state-mcp` so
  all 7 hosts see inherited skills/decisions/routing/wisdom/casting policy with
  provenance (`detail: true` returns the bodies).
- `squad doctor` gains an "upstream inheritance" check; `squad status` prints
  the inherited-context display.
- Coordinator contract: canonical `### Upstream Inheritance` section plus digest
  item 16a in coordinator.ts (CANONICAL_COORDINATOR_HEADINGS updated), mirrored
  to all template copies.
- Tests: test/upstream-runtime.test.ts (precedence, provenance, depth, cycles,
  diamond, soft failures, no fetch, ToolRegistry + stdio bridge, doctor check);
  F1 digest `it.fails` flipped to a positive assertion; bridge scenario added to
  the host-feature-matrix suite.
- Docs: features/upstream-inheritance.md now describes exactly what ships
  (earlier entries win, no implicit fetch, statuses, SDK API).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
BREAKING CHANGE: `squad personal`, `squad consult`, `squad extract`, ambient
`~/.config/squad/personal-squad` agent discovery, Ghost Protocol spawn rules,
consult-mode routing and the `SQUAD_NO_PERSONAL` / `SQUAD_PERSONAL_DIR`
switches are removed. `squad init` no longer points `config.json` `teamRoot`
at the global squad root (the F9 bug that made every project a satellite of
the personal squad) and never writes outside the project `.squad/`.

SDK removals: resolvePersonalSquadDir, ensurePersonalSquadDir,
ensureSquadPathTriple, isConsultMode, ResolvedSquadPaths.personalDir,
SquadDirConfig.consult/extractionDisabled, InitOptions.extractionDisabled,
the `agents/personal` subpath and the `sharing/consult` module.
Added read-only `legacyPersonalSquadPath()` / `detectLegacyPersonalSquad()`.

Safety contract (Q/Bubu redlines):
- Nothing is deleted, moved or rewritten. `squad upgrade` and `squad doctor`
  print a one-time notice naming the untouched legacy directory and/or the
  leftover `teamRoot`, with the reversible path (`squad export` there,
  `squad import` here; user decides about shared `teamRoot`). The dead
  subcommands print the same notice and exit non-zero.
- test/personal-squad-removal.test.ts: with a legacy personal squad present,
  init -> cast -> upgrade -> upgrade (idempotent) -> client install/rollback
  leaves the legacy tree byte-identical (sha256 fingerprint) and populates
  the project roster; two side-by-side projects stay independent; detection
  never mkdirs; doctor/notice text is asserted.

`squad init --global` / `squad upgrade --global` keep managing the *global*
squad but no longer bootstrap `personal-squad/`. Docs/nav, canonical
coordinator (+ all template mirrors), help text, acceptance features, the
matrix row and dead tests are updated; changeset added under `major`.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
… Claude background-runs; matrix + docs (F5–F8, F2/F3)

- F6: `squad_state_health` now reports `State backend: local|orphan|two-layer`
  plus the storage class and team squad dir (ToolRegistry takes a trailing
  `{ backendName }` option; state-mcp passes `context.backend.name`).
- F8: `StateBackendStorageAdapter.toRelative()` maps the squad root to the
  empty key instead of `.`, so `squad_state_list` without `dir` lists the
  root on orphan/two-layer instead of failing key validation.
- F7: Claude Code declares `background-runs` in capability-matrix.json,
  CAPABILITY_TOKENS_BY_HOST and the architecture doc (live run showed
  background Agent spawns).
- Upstream tool output is bounded (UPSTREAM_REPORT_MAX_CHARS, summary kept,
  detail truncated with an explicit marker) per reviewer redline.
- Host feature matrix: F1 cells -> supported with validated-test evidence
  for all 7 hosts; F6/F8 notes; Claude background-agents -> supported;
  consult-personal-squad -> n/a (removed); renderer escapes `|` in feature
  names; cspell words for the live-run names; F6 `it.fails` flipped and F8
  asserted in the bridge test.
- Docs: headless Claude needs `--mcp-config .mcp.json` (F5; no
  enableAllProjectMcpServers projection); ADO = detection + triage/watch via
  `az`, interactive Issues mode GitHub-only (F3); GitLab marked planned, not
  shipped (F2).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
… untrusted marking, working legacy import, project-local upstream root; CI/test fixes

Copilot review threads + Worf FUP-1..12 on #2274, plus the CI fix.

Upstream inheritance
- FUP-2: all snapshot reads go through a ContainedReader rooted at the
  upstream (clone dir / declared source / export dir): per-component lstat
  refuses symlinks and junctions, realpath must stay inside the root; any
  refusal marks the upstream `invalid` and serves nothing from it.
- FUP-9: per-file cap UPSTREAM_MAX_FILE_BYTES (1 MiB); larger files invalidate
  the upstream with a diagnostic.
- FUP-3: report header states inherited content is UNTRUSTED third-party data,
  every body in detail mode is fenced with BEGIN/END UNTRUSTED markers; the
  canonical `### Upstream Inheritance` section and digest 16a say the same.
- FUP-11: relative local/export sources resolve against the declaring squad's
  project root, never process.cwd().
- Copilot P2 (root policy): upstream declarations are project-local
  (`squad upstream add` writes them beside config.json, `squad externalize`
  keeps them local). ToolRegistry gains `upstreamDir`; state-mcp passes
  context.paths.projectDir while state tools keep operating on the team
  root; `squad doctor` reads the local .squad/ too.
- Copilot P2 / FUP-8: local-wins scans all five skill roots (.squad,
  .copilot, .github, .claude, .agents).
- FUP-7: doctor reports an unsynced/stale git upstream as a warning with the
  sync hint; only missing/invalid/cycle/depth fail.
- FUP-4: concepts/portability.md now says earlier entries win.
- FUP-10: render-host-feature-matrix.mjs --check compares CRLF-insensitively.

Personal squad removal
- FUP-1 / Copilot P2: the advertised `squad export` recipe could not read a
  1.x layout (no .squad/, no team.md; flag is --out). New read-only
  `squad import --legacy-personal [<dir>] [--dry-run]` registers each 1.x
  agent through the normal cast flow (charter/history kept verbatim,
  existing names skipped, source never written). Notice, doctor, upgrading
  guide, whatsnew, changeset and matrix text updated to it.
- FUP-5: notice also printed by `squad init` and by the already-up-to-date
  upgrade path.
- FUP-6: detection honours a still-set SQUAD_PERSONAL_DIR.
- FUP-12: external-state tests no longer assert the dead `consult` field;
  "fiery death" phrasing removed from the public matrix page.

Tests
- CI: the satellite fixture wrote teamRoot '..\base' (Windows separator),
  which fails to lstat on Linux; use '../base'.
- Copilot P1: test/cli-global.test.ts stubs the platform config home under
  TMP instead of creating/deleting the developer's real global .squad.
- test/cli/cast.test.ts drops the mock of the removed agents/personal subpath.
- test/upstream-runtime.test.ts: restart determinism, monorepo subfolder
  bridge, upgrade leaves upstream state intact, junction/symlink escape,
  file-symlink escape, oversized file, untrusted fences around an injection
  payload, relative source from another cwd, linked-project upstream root
  over the bridge, five skill roots, doctor severity.
- test/personal-squad-removal.test.ts: real-1.x-layout legacy import round
  trip (dry-run, import, re-run skips, source sha256-identical),
  SQUAD_PERSONAL_DIR detection, notice on init/up-to-date upgrade.
- test/clients.test.ts: digest regex asserts the untrusted sentence on all
  7 hosts.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
@tamirdresher
tamirdresher force-pushed the tamirdresher-microsoft-squad2-upstream-runtime-and-personal-rem branch from 61a94ed to 73a4de5 Compare October 22, 2026 14:00
…, traversal budgets, git source allow-list, untrusted-wording, expected-fail labels

Upstream inheritance (Layer B scope)
- TOCTOU: ContainedReader opens first (O_NOFOLLOW where available), fstat()s
  the descriptor and requires dev/ino/size to match the pre-open lstat chain,
  re-checks the directory chain realpath after open, reads via the fd only.
  Injectable `beforeOpen` seam (resolveUpstreams options) for deterministic
  race tests.
- Traversal budgets enforced from lstat sizes BEFORE any read: 1 MiB/file,
  8 MiB and 2000 files per upstream, 500 entries per directory, depth 8
  (DEFAULT_UPSTREAM_READ_LIMITS, overridable via readLimits). Exceeding ⇒
  upstream `invalid` with diagnostic.
- Git source hardening in `squad upstream add|sync`: allow-list https://,
  ssh://, git@host:path; refuse leading-dash, remote helpers (ext::, fd::),
  file://, http://, whitespace; `--` before every positional in clone/pull;
  subprocess env GIT_CONFIG_PARAMETERS disables protocol.ext/file and
  re-enables only https/ssh; GIT_TERMINAL_PROMPT=0. `unsafeGitSourceReason`
  and `gitSyncEnv` exported for tests.
- Wording: report header, canonical section, digest 16a, changeset and docs
  now say inherited bodies are data-only, cannot change tools/permissions/
  approvals/MCP/host settings, and the UNTRUSTED fences are a mitigation,
  not a sandbox or authorization boundary.
- Matrix: the five expected-fail digest gaps are labelled `failing` with an
  explanatory note on every degraded cell, listed under a new
  `expectedFailures` block rendered as "Expected failures (it.fails)".

Personal squad removal (Layer C scope)
- `squad import --legacy-personal` reads the legacy tree with lstat/open/
  fstat (no symlinks or junctions, 1 MiB cap), refuses unsafe slugs, and
  copies no machine-specific path into the project.

Tests: test/cli/upstream-source-hardening.test.ts (20: allow-list, env,
add refuses 4 dangerous sources before write/spawn, `--` placement, sync
skips hand-edited ext::/dash entries, pull uses `--`); upstream-runtime
+6 (hook-driven dir→junction swap, leaf replaced between stat/open, every
inherited type + nested + dangling link, no-open proof for oversized file,
byte/file/entry/depth budgets, tool output fence + non-sandbox wording);
personal-squad-removal +1 (junctioned legacy agent refused, no absolute
path copied, dry-run keeps project sha256-identical); clients.test
asserts the canonical section carries the untrusted/non-sandbox rule.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
@tamirdresher

Copy link
Copy Markdown
Collaborator Author

Superseded by Stack #2281, merged to dev as #2277 (894e3c4) → #2278 (e3de47a) → #2279 (f154968) → #2282 (f22847a). All content from this PR landed through the split layers after per-layer review.

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.

2 participants