Skip to content

fix(cli): remove dangling ./shell/sdk-bridge export - #2285

Merged
tamirdresher merged 2 commits into
devfrom
fix-dangling-sdk-bridge-export
Oct 23, 2026
Merged

tamirdresher merged 2 commits into
devfrom
fix-dangling-sdk-bridge-export

Conversation

@tamirdresher

Copy link
Copy Markdown
Collaborator

What

Remove the ./shell/sdk-bridge subpath export from @bradygaster/squad-cli and add a test that every exports target of both packages exists in the built dist/.

Why

The entry points at dist/cli/shell/sdk-bridge.{js,d.ts}, which has never existed (git log -S sdk-bridge: added alongside the squad aspire / remote-control work with no source module; git grep finds no consumers in packages/, test/ or docs/). Importing the subpath fails with ERR_MODULE_NOT_FOUND, and the tarball advertises a module it does not ship — flagged by reviewers as a preview-publication blocker.

How

  • Delete the export entry (no code change otherwise).
  • test/package-exports-targets.test.ts: for each package, every string target under exports (any condition) must exist under the package dir once dist/ is built; skipped when not built. Verified red on the pre-fix manifest (./shell/sdk-bridge -> ./dist/cli/shell/sdk-bridge.d.ts).

⚠️ Quick Check

  • Changeset: .changeset/fix-dangling-sdk-bridge-export.md (@bradygaster/squad-cli patch)

PR Readiness Checklist

  • Branch from dev, up to date, diff is the single intended change
  • Not draft; single commit
  • npm run build ✓ · new test ✓ (red pre-fix) · lint unaffected (manifest + test only)
  • Docs N/A · Exports: entry removed (nothing imported it)

Breaking Changes

None — the removed subpath never resolved.

Waivers

None.

…exports target exists in dist

The entry pointed at dist/cli/shell/sdk-bridge.js, which has never existed in the package
(no source module, no consumers; introduced with the squad aspire/remote-control work).
Importing it failed with ERR_MODULE_NOT_FOUND. The new test fails on the pre-fix manifest.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
Copilot AI balanced review requested due to automatic review settings October 23, 2026 00:38
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

🛫 PR Readiness Check

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

PR Scope: 🔧 Infrastructure

⚠️ 2 item(s) to address before review

Status Check Details
❌ Single commit 2 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 No Copilot review threads
✅ CI passing All checks passing

Files Changed (3 files, +46 −4)

File +/−
.changeset/fix-dangling-sdk-bridge-export.md +5 −0
packages/squad-cli/package.json +0 −4
test/package-exports-targets.test.ts +41 −0

Total: +46 −4


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

@github-actions

Copy link
Copy Markdown
Contributor

🟡 Impact Analysis — PR #2285

Risk tier: 🟡 MEDIUM

📊 Summary

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

🎯 Risk Factors

  • 3 files changed (≤5 → LOW)
  • 3 modules touched (2-4 → MEDIUM)
  • Critical files touched: packages/squad-cli/package.json

📦 Modules Affected

root (1 file)
  • .changeset/fix-dangling-sdk-bridge-export.md
squad-cli (1 file)
  • packages/squad-cli/package.json
tests (1 file)
  • test/package-exports-targets.test.ts

⚠️ Critical Files

  • packages/squad-cli/package.json

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.

🟢 Approval recommended

The change removes a nonfunctional export, adds focused regression coverage, and has no unresolved findings.

No open issues 🎉

What changed in this PR

Removes an unusable CLI subpath export so the package no longer advertises a module it does not ship.

Changes:

  • Removes ./shell/sdk-bridge from the CLI export map.
  • Adds regression checks for explicit export targets in both packages, skipped when build output is absent.
  • Adds a patch changeset for the CLI package.
File Description
test/​package-exports-targets.test.ts Checks that explicit export targets exist after building.
packages/​squad-cli/​package.json Removes the dangling ./shell/sdk-bridge export.
.changeset/​fix-dangling-sdk-bridge-export.md Records the CLI patch and regression coverage.

Review effort: Balanced

@tamirdresher
tamirdresher merged commit 559e0f9 into dev Oct 23, 2026
17 checks passed
tamirdresher pushed a commit that referenced this pull request Oct 23, 2026
…ev by #2285) [3/3]

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b822a455-fa94-49a2-9127-eee479ab954e
tamirdresher added a commit that referenced this pull request Oct 23, 2026
…d; project-only resolution; F6/F7/F8 (#2279)

* feat!: remove personal squads, consult mode and the global squad; project-only resolution; state-bridge fixes [3/3]

BREAKING: Personal squads, consult mode and the global squad (`--global`) were removed;
existing `personal-squad/` and global `.squad/` directories under the user profile are
no longer read or written and may be deleted manually.

Squad 2.0 keeps exactly one place for a team: the project `.squad/`. This removes every
trace of the 1.x profile-level features from the product and the docs, with one line of
history in the changeset.

Removed
- CLI: `squad personal|consult|extract`, `--global` on init/upgrade, the user-profile
  fallback in `squad status`/`squad cost`/the shell, `--legacy-personal` import, the
  `SQUAD_NO_PERSONAL`/`SQUAD_PERSONAL_DIR` switches, init `teamRoot` auto-link, the
  `multi-squad` registry.
- SDK: `agents/personal`, `sharing/consult`, `resolvePersonalSquadDir`,
  `ensurePersonalSquadDir`, `ensureSquadPathTriple`, `isConsultMode`,
  `ResolvedSquadPaths.personalDir`, `SquadDirConfig.consult`/`extractionDisabled`,
  `InitOptions.extractionDisabled`/`isGlobal`, `multi-squad.ts` and its types.
  `resolveGlobalSquadPath()` stays only as the base of externalized project state.
- Coordinator: Personal Squad / Consult Mode / Ghost Protocol sections and routing rows
  in the canonical agent and all host digests; personal-squad skill, ghost-protocol and
  personal-charter templates; docs pages, nav, README rows, whatsnew/upgrading mentions,
  the retired matrix row. Dead tests for the removed surface.

Behaviour
- Squad resolves `.squad/` only from the current directory and its parents. Outside a
  project `squad status`, `squad doctor`, `squad cast` and `squad cost` fail with
  "No squad in this directory … run squad init" instead of resolving a profile dir.
- Nothing ever reads, writes, moves or deletes the 1.x directories.

State-bridge fixes (Data F6/F7/F8)
- `squad_state_health` reports `State backend: local|orphan|two-layer`, storage class and
  team squad dir (`ToolRegistry` accepts `backendName`); `squad_state_list` without `dir`
  lists the root on git-backed backends; Claude Code declares `background-runs` in
  `capability-matrix.json` and `CAPABILITY_TOKENS_BY_HOST`; matrix cells/notes updated.

Tests
- test/retired-symbols.test.ts: CI gate grepping every tracked file and the built dist
  for the retired names/phrases, with an explicit allowlist (the changeset BREAKING line,
  CHANGELOGs, pre-2.0 whatsnew history, a contributor credit, the two tombstone tests).
- test/profile-squad-tombstone.test.ts: a seeded 1.x profile tree (personal-squad/ +
  global .squad/) stays sha256-identical and is never touched by any fs/storage call
  through init -> cast -> upgrade x2 -> client install/rollback; roster lands in the
  project; teamRoot never set; two side-by-side projects independent; no fallback.
- test/cli-outside-project.test.ts: built CLI in an empty repo with a seeded profile
  squad: status/doctor/cast/cost exit non-zero with the remediation message, never
  mention or touch the profile squad; status inside a project still works.

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

* fix!: never resolve a squad from the user profile; reject --global; prune retired exports; guard tests from the real profile [3/3]

Worf Layer C review (LC-1..6) and the test-profile incident:

- LC-2 (data integrity): both squad-dir walkers (resolveSquad, resolveSquadPaths/
  findSquadDir) stop at the home directory and never accept ~/.squad or SQUAD_HOME as a
  project squad, so `squad cast` from a directory without a repo marker can no longer
  write into the profile. Tests: tombstone unit test (fake HOME/USERPROFILE/SQUAD_HOME,
  no .git, zero fs hits) and a built-CLI test (cast/status/doctor/cost fail with the
  remediation message, fake profile sha256-identical) — verified red pre-fix
  (`Added agent Probe` under fake-home/.squad).
- LC-3: `--global` on any command fails with `Unknown option: --global` (exit 1) instead
  of silently running the project form; test for init/upgrade.
- LC-1: `./commands/extract` and `./commands/personal` exports removed from the CLI
  package.json; the retired-symbol gate now scans both manifests' `exports` (retired
  names + every target must exist in dist; the pre-existing dangling
  `./shell/sdk-bridge` is listed as known) and the `npm pack --dry-run` file lists.
- Incident: new vitest setupFile `test/setup/profile-guard.ts` redirects SQUAD_HOME,
  APPDATA, LOCALAPPDATA and XDG_CONFIG_HOME into a per-worker temp dir before any test
  loads, so no test can read or write the real profile (HOME/USERPROFILE untouched so
  git/gh keep working; the walker fix covers ~/.squad).
- LC-4: squad-home docs no longer speak of "personal agents". LC-5: the single BREAKING
  sentence is repeated verbatim once in whatsnew v2.0.0 and the upgrading guide (gate
  enforces exactly once, nothing else). LC-6: `health` help line shortened.

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

* fix(upgrade): strip stale profile teamRoot, stamp-insensitive customization check [3/3]

Data's upgrade matrix (#2282) findings UM-F1 and UM-F2:

- UM-F1: projects initialized by 0.13-1.1 while a profile squad existed carry
  `teamRoot: "<platform-config>/squad"`. `isRetiredProfileTeamRoot()` (SDK) recognises
  the platform config dir, `~/.squad`, `SQUAD_HOME` and the home dir; `resolveSquadPaths`
  never follows such a teamRoot (local mode), and `squad upgrade` removes the key with one
  neutral line ("Removed stale teamRoot pointing to <path>; project state is now local";
  --dry-run only announces). A genuine dual-root teamRoot (another repo) is preserved.
- UM-F2: `stripAgentStamps()` normalizes every stamp form the upgrader writes
  (`<!-- version: X -->`, `- **Version:** X`, `Squad vX`, `@bradygaster/squad-cli@X`,
  legacy `<!-- squad-cli vX -->`) before comparing squad.agent.md with the template, and an
  existing `.local-backup` holding the same bytes is not rewritten.
- Docs: upgrading guide notes both and adds "Downgrading and old CLIs" guidance.
- Tests: test/upgrade-profile-teamroot.test.ts (6) — both findings verified red against
  the pre-fix SDK/CLI (remote mode; "local customizations" warning on pass 1).

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

* fix: resolver-only doctor admission, XDG on macOS, token-only stamp normalization, tolerant teamRoot preflight [3/3]

Copilot review threads on #2279:

- doctor: the resolver is the single admission check (a bare ./.squad existence check let
  `squad doctor` run from the home directory against ~/.squad); test now also runs every
  outside-project command directly from the seeded home dir (red pre-fix for doctor).
- upgrade: the stale-teamRoot preflight tolerates null/array/scalar config.json like
  readSquadConfig (test); stripAgentStamps normalizes only the version token on the
  `- **Version:**` line so an edited instruction is still a customization (test).
- resolveGlobalSquadPath honours XDG_CONFIG_HOME on macOS as well, so the test profile
  guard (and the outside-project test, which no longer overrides HOME) isolates macOS too.
- retired-symbols gate: validates the changeset fragment only while it exists (changeset
  version consumes it); post-release it requires the sentence in the CLI CHANGELOG; the
  whatsnew/upgrading exactly-once checks stay durable.
- cast: outside-project message aligned with status/doctor ("No squad in this directory
  (searched from ...). Run "squad init" here, or use --team-root ...").

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

* fix: canonical profile boundary (8.3 names), SQUAD_HOME guard shape, acceptance/portability expectations for 2.0 [3/3]

CI on 21ecca7 (ubuntu) — all branch-caused, all from the last two commits:

- Profile boundary compared `os.homedir()` with the walk's current path textually; on
  Windows `os.tmpdir()` yields the 8.3 form (`C:\Users\SOMEUS~1\...`) so the boundary was
  missed and `squad status` from a temp dir resolved `~/.squad` (acceptance saw
  `Path: C:\Users\TAMIRD~1\.squad`). Boundary comparisons now use `realpathSync.native`
  on the longest existing prefix (`canonicalDir`); callers still get paths in their own
  spelling (resolve-cache tests unchanged).
- test/setup/profile-guard.ts: SQUAD_HOME is redirected to `<guard>/home/.squad` so the
  path keeps its real shape (comms-teams tests assert the `.squad` segment).
- acceptance features: outside a project `squad status`/`squad doctor` now fail with
  "No squad in this directory … squad init" (exit 1) — the 2.0 contract, replacing the
  old fallback expectations.
- cli/upgrade-portability: the fixture asserted the UM-F2 bug (a stamp/CRLF-only delta
  produced a .local-backup); it now applies a genuine local edit, which is still backed up.

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

* fix!: canonical outside-project error, platform-config boundary, fail-closed canonicalization, fs guard, one-pass 0.9.x upgrade [3/3]

Q/Bubu/Worf conditions on Layer C:

- LC-9: one message for every project-scoped command, from `NO_SQUAD_MESSAGE` /
  `fatalNoSquad()`: `No squad in this directory. Run "squad init" first.` (status, doctor,
  cast, cost, upgrade, nap, export, notes, upstream, economy, config, loop, watch, migrate,
  copilot). economy/config used private walkers that reached ~/.squad — replaced by the
  SDK resolver. Test runs 11 commands from an empty repo, asserts the identical line,
  exit 1, and that nothing (no .squad mkdir) is created.
- LC-11: the platform config dir (%APPDATA%\squad, ~/.config/squad, ~/Library/…/squad)
  is part of the profile boundary: a `.squad` at or under it is never admitted (any
  spelling), and the boundary is established by canonicalizing only the PARENT so the
  retired directory itself is never stat'ed.
- LC-12: canonicalization is fail-closed — `canonicalDir` returns null when the existing
  prefix cannot be realpath'ed and callers refuse (resolver returns null, teamRoot treated
  as retired) instead of comparing lexically; an unknown home dir also refuses. A link
  named `.squad` whose target is profile-owned is refused too.
- Fail-closed test guard: `test/setup/profile-fs-guard.cjs` wraps fs/fs.promises (sync,
  callback, promise) and THROWS on any access under the real profile roots; loaded by the
  vitest setup file from the original environment and inherited by child processes via
  NODE_OPTIONS=--require + SQUAD_TEST_FORBIDDEN_ROOTS. test/profile-fs-guard.test.ts proves
  a deliberate access throws in-process and in a child with faked HOME/APPDATA.
- Projects under the profile keep working: test/profile-boundary.test.ts covers
  <home>/src/proj, long/8.3 paths (skips loudly when 8.3 is disabled), case/separator
  variants, a junction to the profile root, SQUAD_HOME/APPDATA/HOME/USERPROFILE variants.
- F4 (Data, upgrade matrix): the casting pair is ensured BEFORE squad.agent.md is rendered,
  so a 0.9.x project (empty casting/) gets the capabilities block on the first upgrade and
  the second upgrade is a byte-identical no-op.
- Eradication boundary: the teamRoot cleanup prints `Removed obsolete "teamRoot" setting
  from .squad/config.json.` (no path).
- Single historical record: the BREAKING sentence lives only in whatsnew v2.0.0; the
  upgrading guide links to that section; the retired-symbol gate enforces both.

LC-9 equality, LC-11, LC-12 and F4 tests verified red against the pre-fix code.

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

* test: keep the profile-boundary test clear of retired terms (gate) [3/3]

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

* test(gate): drop the sdk-bridge dangling-export exemption (fixed on dev by #2285) [3/3]

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

---------

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