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

  1. added this to the v2.6.0 milestone on Sep 2, 2026
  2. added
    v2Issues and PRs for v2
    choreMaintenance: deps, build tooling, CI, cleanup — no user-facing behavior change
    on Sep 2, 2026
  3. cliffhall commented on Sep 2, 2026

    @cliffhall
    MemberAuthor

    Triage: Priority Low (total 4)

    • Severity 2 — minor friction with an easy workaround. @types/node ships no runtime code, the skew is two patch releases, and npm run local:gate passes today — verify:typecheck-coverage gives all 1082 tracked source files a tsc pass. This is a latent risk, not a current defect.
    • Urgency 2 — wanted eventually. Nothing waits on it, and the drift is already written down in AGENTS.md, so it is not going to surprise anyone who reads the rules before touching a manifest.
    • Bonuses: none. Not a bug, not security-related, no engagement, unassigned, not a sub-issue, and no milestone bonus (see the note on chore: pin browserslist past GHSA-c83g-rgw3-j3cx in clients/tui (dev-only high advisory) #2225 — it is a constant for create-flow issues).

    May legitimately sit. The reason to keep it on the board rather than close it is the second bullet under Done when: the value here is deciding whether verify:dep-lockstep should widen to see this class at all, and that decision is worth recording either way — including as an explicit "no, an overrides pin is the whole mechanism."

    Board: #28, Status Todo, milestone v2.6.0.

  4. self-assigned this
    on Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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