W-105: Dependency catalogs and updates¶
Type: chore · Size: M · Epic: E-setup · Target: pnpm-workspace.yaml, root and workspace package.json files · Breaking: no Depends: W-104 Refs: AGENTS.md (Rules: no new dependencies without approval, koota pinned exact), pnpm-workspace.yaml, workflow (chore gates)
Goal¶
Move every dependency that more than one workspace uses into named catalogs: in pnpm-workspace.yaml, grouped by purpose: koota (exact pin, replaces the default catalog:), react (react, react-dom, @types/react, @types/react-dom, lucide-react), testing (vitest, jsdom, @testing-library/jest-dom, @testing-library/react), build (typescript, tsdown, vite, @vitejs/plugin-react, @tailwindcss/vite, tailwindcss, turbo, @turbo/gen, @types/node), and lint (oxlint, oxfmt). Manifests reference them with catalog:<name>, including the koota and react peer dependencies, so each version is set in one place. Dependencies used by one workspace only (@base-ui/react, shadcn, zod, bumpp, @changesets/cli, and so on) stay inline. @vitest/coverage-v8 is not installed and is not added (new dependency, needs user approval). The only version change during the catalog move is aligning @types/node (^26.6.5 in packages/*, ^24 in apps/* and packages/ui) to one entry. Then update every dependency to the latest version compatible with the rest of the workspace, one catalog group per step. The user approves the version list before any update step runs. If a major bump may change a package's public API, stop and ask.
Steps¶
Check used by every step below: pnpm install then pnpm turbo run build typecheck lint test. pnpm-lock.yaml changes only through pnpm install, never by hand. Manifests (13 files): package.json, apps/{web,demo-anno,demo-ck3,demo-dnd,demo-totalwar}/package.json, packages/{ecs,ecs-devtools,ecs-prefab,ecs-relations,ecs-schedule,ecs-serialize,ui}/package.json.
- S1: create the named catalogs and migrate all manifests, with identical versions except
@types/node. Inpnpm-workspace.yaml, replace the defaultcatalog:withcatalogs:holdingkoota(koota: 0.6.6),react,testing,build,lintas listed in the Goal, using each dependency's current range (react/react-dom^19.3.1,typescript7.0.2(exact, set by W-104; keep the exact pin because rolldown-plugin-dts detects tsgo only for7.0.x),vitest^5.0.5,tsdown^0.23.1, and so on); set@types/nodeto^26.6.5(flagged: the one version change, see Q1). In every manifest above, replace the range withcatalog:<group>:kootabecomescatalog:kootain dependencies, devDependencies and peerDependencies;reactinpackages/ecs-devtoolspeerDependencies becomescatalog:react;@turbo/geninpackages/uijoinsbuild; keepworkspace:*and single-use dependencies inline. Check:pnpm installleaves nocatalog:default reference,pnpm why kootashows0.6.6everywhere, and the shared check passes; files: pnpm-workspace.yaml, package.json, apps//package.json, packages//package.json, pnpm-lock.yaml (viapnpm install) - S2 (approval gate): produce the list of proposed version changes. Run
pnpm outdated -rand, per catalog group, record current, wanted and latest versions, marking each as patch, minor or major. Add one Log line per group with the table in the chat reply. Flag these for an explicit stop-and-ask: anytypescriptmajor or any change to the exact7.0.2pin (W-104 moved to 7.0.2 with user approval; a 7.1 bump can break tsgo detection in rolldown-plugin-dts, which checks for7.0; changes emitted.d.tsand type checking for every package), anyvite,@vitejs/plugin-react,tsdown(0.x, minor bumps may be breaking) orvitestmajor,react/@types/reactmajors,tailwindcssand@tailwindcss/vitemajors (sharedpackages/uistyles), and anykootachange.kootais excluded from the update steps: it stays at the exact0.6.6that matchesreference/kootaand thekootaskill, unless the user approves a bump and a separate item. No file changes in this step except the Log; do not start S3 until the user approves the list in writing; files: docs/work/W-105-dependency-catalogs-updates.md (Log only) - S3: update the
testingcatalog (vitest,jsdom,@testing-library/jest-dom,@testing-library/react) to the approved versions by editing the entries inpnpm-workspace.yaml, thenpnpm installand the shared check. Do not edit tests to make them pass: if a bump breaks a test, stop and report; files: pnpm-workspace.yaml, pnpm-lock.yaml (viapnpm install) - S4: update the
reactcatalog (react,react-dom,@types/react,@types/react-dom,lucide-react) to the approved versions, thenpnpm installand the shared check. Areactpeer range change inpackages/ecs-devtoolscounts as a public change: stop and ask if the range narrows; files: pnpm-workspace.yaml, pnpm-lock.yaml (viapnpm install) - S4a: bump
cnto0.5.1(keep the existing^range style,^0.5.1) inpackages/ui/package.json, thenpnpm installand the shared check; files: packages/ui/package.json, pnpm-lock.yaml (viapnpm install) - S5: update the
buildcatalog (typescript,tsdown,vite,@vitejs/plugin-react,@tailwindcss/vite,tailwindcss,turbo,@turbo/gen,@types/node) to the approved versions, then thelintcatalog (oxlint,oxfmt), as two separate commits, each followed bypnpm installand the shared check. After thelintbump runpnpm run formatand report any formatting churn instead of committing it silently; files: pnpm-workspace.yaml, pnpm-lock.yaml (viapnpm install) - S6 (acceptance): final check from a clean state:
pnpm install --frozen-lockfilethenpnpm turbo run build typecheck lint test. Confirmpnpm outdated -rlists nothing beyond the versions the user excluded, no manifest holds a range for a catalog-managed dependency (grepfor"vitest": "^and similar), andkootais still0.6.6; files: none
Log¶
- 2026-11-02 created from user request under E-setup (Triage)
- 2026-11-02 sized M, epic E-setup; Depends W-104 because both items edit the same package.json files and the build should be green before versions move (Triage)
- 2026-11-02 placed in Later, not prioritized (Triage)
- 2026-11-02 steps written (Planner); Goal refined: named catalogs
koota,react,testing,build,lint,lucide-reactinreact, single-use dependencies stay inline,@vitest/coverage-v8not added; waiting for plan approval - 2026-11-02 moved Later -> Next, plan awaiting user approval (Triage)
- 2026-11-02 open questions for user:
@types/nodemajor (^26vs^24); drop defaultcatalog:;kootaexcluded from updates (stays0.6.6) - 2026-11-02 S1 and S2 updated for W-104's switch to
typescript7.0.2 (Planner) - 2026-11-02 Depends W-104 is done, so it is unblocked; state ready, stays in Next. Start still needs plan approval (chore, M) and the S2 version-list approval (Triage)
- 2026-11-02 plan S1-S6 approved by user
- 2026-11-02 answer:
@types/nodeuses^26.6.5(applies in S1, replacing^24inapps/*andpackages/ui) - 2026-11-02 answer: drop the default
catalog:in favour of namedcatalogs: - 2026-11-02 answer:
kootais excluded from update steps and stays exactly0.6.6 - 2026-11-02 WIP check: 0 of 2 slots used (Now was empty); moved Next -> Now, state active (Triage)
- 2026-11-02 S1 passed review, checkbox ticked
- 2026-11-02 S2
koota: koota 0.6.6 / wanted 0.6.6 / latest 0.6.6 (not listed bypnpm outdated -r); excluded from updates, no change - 2026-11-02 S2
react: react 19.3.1 / 19.3.1 / 19.3.1 (up to date); react-dom 19.3.1 / 19.3.1 / 19.3.1 (up to date); @types/react 19.3.0 / 19.3.0 / 19.3.0 (up to date); @types/react-dom 19.3.0 / 19.3.0 / 19.3.0 (up to date); lucide-react 1.64.0 / 1.64.0 / 1.66.0 (minor, range^1.64.0already allows it) - 2026-11-02 S2
testing: vitest 5.0.5, jsdom 30.1.3, @testing-library/jest-dom 7.0.1, @testing-library/react 16.3.3 are all up to date (current = wanted = latest); nothing to propose - 2026-11-02 S2
build: typescript 7.0.2, tsdown 0.23.4, vite 8.3.5, @vitejs/plugin-react 6.1.2, @tailwindcss/vite 4.3.3, tailwindcss 4.3.3, turbo 2.11.10, @turbo/gen 2.11.10, @types/node 26.6.6 are all up to date (current = wanted = latest); nothing to propose - 2026-11-02 S2
lint: oxlint 1.90.0, oxfmt 0.75.0 are up to date (current = wanted = latest); nothing to propose - 2026-11-02 S2 outside the catalogs:
cn0.5.0 -> 0.5.1 (patch, single-use inpackages/ui, inline); no stop-and-ask item has a newer version, S2 stays unchecked awaiting user approval of the list - 2026-11-02 S2 approved in writing by user:
lucide-react-> 1.66.0 (reactcatalog) andcn-> 0.5.1 (inline inpackages/ui/package.json); no other updates; S2 ticked - 2026-11-02 S3 and S5 are no-ops:
pnpm outdated -rlists nothing for thetesting,buildandlintgroups; no versions changed, ticked - 2026-11-02 new step S4a added after S4 for the inline
cnbump (Implementer); S4 and S4a stay unticked until the Reviewer gate - 2026-11-02 user widened the Implementer hook allowlist in
.github/agents/Implementer.agent.mdfor W-105 (explicit user decision) so the chore can editpnpm-workspace.yaml, root,apps/*andpackages/uipackage.json; resolves the Reviewer's blocking finding - 2026-11-02 S4 (
lucide-react^1.66.0) and S4a (cn^0.5.1) implemented; shared check passed (47/47 tasks),pnpm outdated -rempty; reviewed, ticked - 2026-11-02 S6 acceptance passed:
pnpm install --frozen-lockfileup to date;pnpm turbo run build typecheck lint test --force47/47 tasks successful (run outside the sandbox);pnpm outdated -rempty; no catalog-managed dependency holds a literal range in the 13 manifests (all usecatalog:<group>,kootaiscatalog:koota);pnpm why koota -rshows onlykoota@0.6.6; ticked - 2026-11-02 review: Reviewer APPROVED; all steps ticked (Triage)
- 2026-11-02 done: moved Now -> Done (Triage)