You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #1896 and #1965 / PR #2029, from a question raised reviewing that PR: since the clients are not published separately and all ship inside one flat package, do the dependencies need to be split across five manifests at all?
The finding
Almost every client dependency is already a verbatim duplicate of a root one — same package, same range:
root ^19.0.0, clients ^19.2.4 — the one real divergence
These are exactly the packages core/ imports at runtime, which AGENTS.md already requires to be root-only. The rule simply was never applied beyond the SDK packages that #1970 cleaned up.
Why this is the structural fix, not a cleanup
A package can only be installed into an install root that declares it. Deleting the redundant client-side declarations does not merely align the two copies — it makes the second copy impossible to create. That is the failure class #1896 was opened for (two structurally-distinct copies of one type in a single tsc program; zod 4.3.6 vs 4.4.3 exhausted the 4GB tsc heap in clients/web) and that #1965 / #2029 built a guard to detect.
After consolidation the guard in #2029 should find almost nothing. That is the correct end state for it: it stops being the thing holding the line and becomes the thing that keeps us honest if a declaration creeps back.
The recorded rationale does not argue against it
specification/v2_cli_tui_launcher.md:25 rejects npm workspaces, on three grounds: core/ is consumed by bundling rather than symlinked linking, the published package is one flat fat package, and hoisting fights the dual-instance pins. None of those is a reason to declare zod in four manifests — this issue is not proposing workspaces.
That line's third clause is in fact backwards today: the dedupe + alias pins in vitest.shared.mts exist because duplicate installs happen. Consolidating should let some of them retire — worth checking as part of the work, but not assumed here.
Scope
Move to root — runtime dependencies (step 1): ajv, atomically, chokidar, commander, open, pino, undici, zod, @napi-rs/keyring, hono, @hono/node-server. Delete the client-side declarations; they resolve from the root install by walk-up.
Move to root — shared toolchain devDependencies (step 2, separate PR): eslint, prettier, typescript, typescript-eslint, globals, @eslint/js are declared in all five manifests; vitest, @vitest/coverage-v8, @types/node in four. Verified that npm run from a client directory has the repo root's node_modules/.bin on PATH, so each client's scripts still resolve their binaries from a root-only install. This also strengthens the exact-pin rule on prettier (#1790) — one pin instead of five that can drift independently.
Leave where they are — both must NOT become root dependencies:
ink-form, ink-scroll-view — deliberately inlined into the TUI bundle (TUI Error when pressing Enter to call a tool #1952). A root dependency would make consumers install unused copies; clients/tui/__tests__/tsupConfig.test.ts enforces this.
Web's UI stack (@mantine/*, @dnd-kit/*, @emotion/react, react-dom, react-icons, react-markdown, react-syntax-highlighter, remark-gfm, papaparse) — bundled into dist, so shipping them to consumers is pointless.
Constraints
react must stay ^19.0.0 at the root. Narrowing it reopens TUI Error when pressing Enter to call a tool #1952 for the ink renderer itself, which breaks TUI startup, not just its forms. The clients' ^19.2.4 is the declaration that goes away, not the root's open range.
Regenerate the lockfiles, and gate with npm run ci and npm run pack:verify — this changes what the published tarball resolves against, which ci alone does not cover.
Confirm the postinstall cascade (scripts/install-clients.mjs) still behaves when a client manifest declares few or no dependencies.
Done when
The duplicated runtime deps are declared once, at the root.
npm run ci and npm run pack:verify both pass.
AGENTS.md's dependency-placement section and the root README's matching section describe the consolidated layout, with the .github/copilot-instructions.md mirror updated in the same PR.
Follow-up to #1896 and #1965 / PR #2029, from a question raised reviewing that PR: since the clients are not published separately and all ship inside one flat package, do the dependencies need to be split across five manifests at all?
The finding
Almost every client
dependencyis already a verbatim duplicate of a root one — same package, same range:ajv,atomically,chokidar,commander,open,pino,undici,zod,@napi-rs/keyring,hono,@hono/node-serverreact^19.0.0, clients^19.2.4— the one real divergenceThese are exactly the packages
core/imports at runtime, which AGENTS.md already requires to be root-only. The rule simply was never applied beyond the SDK packages that #1970 cleaned up.Why this is the structural fix, not a cleanup
A package can only be installed into an install root that declares it. Deleting the redundant client-side declarations does not merely align the two copies — it makes the second copy impossible to create. That is the failure class #1896 was opened for (two structurally-distinct copies of one type in a single
tscprogram; zod4.3.6vs4.4.3exhausted the 4GB tsc heap inclients/web) and that #1965 / #2029 built a guard to detect.After consolidation the guard in #2029 should find almost nothing. That is the correct end state for it: it stops being the thing holding the line and becomes the thing that keeps us honest if a declaration creeps back.
The recorded rationale does not argue against it
specification/v2_cli_tui_launcher.md:25rejects npm workspaces, on three grounds:core/is consumed by bundling rather than symlinked linking, the published package is one flat fat package, and hoisting fights the dual-instance pins. None of those is a reason to declarezodin four manifests — this issue is not proposing workspaces.That line's third clause is in fact backwards today: the
dedupe+ alias pins invitest.shared.mtsexist because duplicate installs happen. Consolidating should let some of them retire — worth checking as part of the work, but not assumed here.Scope
Move to root — runtime
dependencies(step 1):ajv,atomically,chokidar,commander,open,pino,undici,zod,@napi-rs/keyring,hono,@hono/node-server. Delete the client-side declarations; they resolve from the root install by walk-up.Move to root — shared toolchain
devDependencies(step 2, separate PR):eslint,prettier,typescript,typescript-eslint,globals,@eslint/jsare declared in all five manifests;vitest,@vitest/coverage-v8,@types/nodein four. Verified thatnpm runfrom a client directory has the repo root'snode_modules/.binonPATH, so each client's scripts still resolve their binaries from a root-only install. This also strengthens the exact-pin rule onprettier(#1790) — one pin instead of five that can drift independently.Leave where they are — both must NOT become root
dependencies:ink-form,ink-scroll-view— deliberately inlined into the TUI bundle (TUI Error when pressing Enter to call a tool #1952). A root dependency would make consumers install unused copies;clients/tui/__tests__/tsupConfig.test.tsenforces this.@mantine/*,@dnd-kit/*,@emotion/react,react-dom,react-icons,react-markdown,react-syntax-highlighter,remark-gfm,papaparse) — bundled intodist, so shipping them to consumers is pointless.Constraints
reactmust stay^19.0.0at the root. Narrowing it reopens TUI Error when pressing Enter to call a tool #1952 for theinkrenderer itself, which breaks TUI startup, not just its forms. The clients'^19.2.4is the declaration that goes away, not the root's open range.npm run ciandnpm run pack:verify— this changes what the published tarball resolves against, whichcialone does not cover.npm run verify:dep-lockstepafterward and record the new candidate set in the PR.TOLERATED_SKEWis empty as of chore(scripts): derive dep-lockstep candidates from what enters each tsc program #2029 and should stay empty.scripts/install-clients.mjs) still behaves when a client manifest declares few or no dependencies.Done when
npm run ciandnpm run pack:verifyboth pass..github/copilot-instructions.mdmirror updated in the same PR.