Skip to content

chore: clients/cli drifts to @types/node 24.13.1 via @types/express, and verify:dep-lockstep cannot see it #2226

Description

@cliffhall

clients/cli resolves @types/node 24.13.1 while the repo root declares and installs
24.13.3:

clients/cli/node_modules/@types/node  = 24.13.1
clients/web/node_modules/@types/node  = 24.13.3
node_modules/@types/node              = 24.13.3   (the root declaration, ^24.12.4)

Neither client declares @types/node#2196 consolidated it to the root. The cli copy is
hoisted transitively via @types/express, so it is constrained by nothing of ours: no range
we own governs it, and nothing pulls it forward when the root moves.

Why the guard does not catch it

verify:dep-lockstep reports OK, and it is right to. It compares only packages that a single
tsc program loads from two installs, and no one program sees both copies — so the
difference is outside its candidate set entirely. AGENTS.md says this in as many words:

A transitive copy is constrained by nothing of ours at all, and cli's @types/node
(24.13.1 against the root's 24.13.3) has already diverged on exactly that.
verify:dep-lockstep does not catch either […] the cli @types/node difference goes
unreported because no one program sees both copies.

So this is a known, documented drift rather than a new discovery. Filing it because the
documentation currently states the problem without anything tracking the fix, and because two
patch versions of @types/node is the harmless end of a failure mode whose expensive end is a
type error that reproduces on one machine and not another.

Impact today

Low. It is a types-only package (no runtime code ships), the skew is two patch releases, and
npm run local:gate passes — verify:typecheck-coverage gives all 1082 tracked source files a
tsc pass. Nothing is broken right now; the concern is that nothing would tell us when it stops
being two patches.

Options

  1. Declare @types/node in clients/cli — simplest, but re-creates the second declaration
    chore: consolidate shared toolchain devDependencies into the root package.json #2196 removed, and AGENTS.md is explicit that re-adding a root-declared package to a client
    manifest re-creates the duplicate the rule exists to make impossible (chore(deps): zod 4.4 blows the tsc heap in clients/web — held at ~4.3.6 #1896). Probably wrong.
  2. A root overrides entry for @types/node — one declaration, still one place to bump,
    and it reaches the transitive copy. Consistent with the repo's "pin a transitive with
    overrides" rule.
  3. Widen verify:dep-lockstep so it compares installed copies of root-declared packages
    directly rather than only those a shared tsc program loads. Catches the whole class instead
    of this instance — but it is a real change to what the guard means, and would likely surface
    the peer shadows in web and tui too (which currently agree with the root, so it would start
    green).

(3) is the one that stops the next instance; (2) fixes this one now. They are not exclusive.

Done when

  • clients/cli and the root resolve the same @types/node
  • Something fails when they next diverge — either the widened guard, or a stated decision
    that an overrides pin is the whole mechanism and the guard is deliberately left as-is
  • npm run local:gate passes

Found while smoke-testing the v2.5.0 payload — see the note on
#2215 (comment)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    choreMaintenance: deps, build tooling, CI, cleanup — no user-facing behavior changev2Issues and PRs for v2

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions