inspector/clients
Repository files (latest commit first)
Filename Latest commit message Latest commit date
cliffhall 1e6bf6425a chore: widen verify:dep-lockstep to declared cross-install copies (#2226)
`clients/cli` resolved `@types/node` 24.13.1 against the root's 24.13.3.
Neither client declares it — #2196 consolidated it to the root — so the cli
copy arrived transitively via `@types/express` and was constrained by no
range of ours. `verify:dep-lockstep` reported OK and was right to: it
compares only packages that reach one `tsc` **program** from two installs,
and no one program sees both copies.

Fixes the instance and the class, which the issue notes are not exclusive.

**The class.** The guard grows a second tier alongside the program-derived
one, asking the weaker but broader question `AGENTS.md`'s "one version per
install-crossing dependency" rule actually states: does a package this repo
declares anywhere resolve to two versions across our installs at all? The
candidate set is every name in any install's `dependencies`/`devDependencies`
that more than one install holds a **top-level** copy of — 17 packages today.
Nested copies are excluded: one exists because some dependency asked for a
different version, so it is that dependency's range, not ours.

Neither tier subsumes the other. The program tier sees a copy no manifest
names (the `@modelcontextprotocol/sdk` case, arriving through another
package's `.d.ts`). The declared tier sees a transitive copy no program
loads (this issue), two *clients* disagreeing with no root copy involved
(`@types/react`, web against tui), and the peer shadows `AGENTS.md` calls out
as ungated — `eslint`, `typescript`, `vitest`.

Deny-by-default, with its own empty `TOLERATED_DECLARED_SKEW` and the same
within-a-major rule, now stated once in a shared `toleratesSkew` so the two
tiers cannot drift.

**The instance, and three others the new tier surfaced.** All four were
patch-level:

- `@types/node` — cli 24.13.1 vs root 24.13.3. Transitive, so it takes an
  `overrides` entry in `clients/cli` (the repo's sanctioned lever for a
  transitive pin), at the root's own `^24.12.4` rather than a frozen number.
- `@types/react` — web 19.2.18 vs tui 19.2.17.
- `react` — web 19.2.8 vs root/tui 19.2.7.
- `@vitejs/plugin-react` — web 6.0.5 vs root 6.0.2.

The last three are `npm update` in the stale install: it moves the lockfile
within the declared range without widening a range, which matters for the
root `react ^19.0.0` that `ink`'s externalized-bundle exemption depends on.
No declaration or range changed.

Tests: 4 end-to-end cases (the fixture gains manifest deps and a client-side
`solo` install, so the skew is real and no program holds both copies) and 13
helper cases.

Closes #2226

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J86a6vMcA9csPtdsg7ZcCZ
Signed-off-by: cliffhall <cliff@futurescale.com>
2026-09-05 14:10:36 -04:00
..
cli chore: widen verify:dep-lockstep to declared cross-install copies (#2226) 2026-09-05 14:10:36 -04:00
launcher Merge remote-tracking branch 'origin/v2/main' into v2/chore/2196-consolidate-toolchain-devdeps 2026-08-31 23:17:20 -04:00
tui chore: widen verify:dep-lockstep to declared cross-install copies (#2226) 2026-09-05 14:10:36 -04:00
web chore: widen verify:dep-lockstep to declared cross-install copies (#2226) 2026-09-05 14:10:36 -04:00