Skip to content

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. In pnpm-workspace.yaml, replace the default catalog: with catalogs: holding koota (koota: 0.6.6), react, testing, build, lint as listed in the Goal, using each dependency's current range (react/react-dom ^19.3.1, typescript 7.0.2 (exact, set by W-104; keep the exact pin because rolldown-plugin-dts detects tsgo only for 7.0.x), vitest ^5.0.5, tsdown ^0.23.1, and so on); set @types/node to ^26.6.5 (flagged: the one version change, see Q1). In every manifest above, replace the range with catalog:<group>: koota becomes catalog:koota in dependencies, devDependencies and peerDependencies; react in packages/ecs-devtools peerDependencies becomes catalog:react; @turbo/gen in packages/ui joins build; keep workspace:* and single-use dependencies inline. Check: pnpm install leaves no catalog: default reference, pnpm why koota shows 0.6.6 everywhere, and the shared check passes; files: pnpm-workspace.yaml, package.json, apps//package.json, packages//package.json, pnpm-lock.yaml (via pnpm install)
  • S2 (approval gate): produce the list of proposed version changes. Run pnpm outdated -r and, 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: any typescript major or any change to the exact 7.0.2 pin (W-104 moved to 7.0.2 with user approval; a 7.1 bump can break tsgo detection in rolldown-plugin-dts, which checks for 7.0; changes emitted .d.ts and type checking for every package), any vite, @vitejs/plugin-react, tsdown (0.x, minor bumps may be breaking) or vitest major, react/@types/react majors, tailwindcss and @tailwindcss/vite majors (shared packages/ui styles), and any koota change. koota is excluded from the update steps: it stays at the exact 0.6.6 that matches reference/koota and the koota skill, 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 testing catalog (vitest, jsdom, @testing-library/jest-dom, @testing-library/react) to the approved versions by editing the entries in pnpm-workspace.yaml, then pnpm install and 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 (via pnpm install)
  • S4: update the react catalog (react, react-dom, @types/react, @types/react-dom, lucide-react) to the approved versions, then pnpm install and the shared check. A react peer range change in packages/ecs-devtools counts as a public change: stop and ask if the range narrows; files: pnpm-workspace.yaml, pnpm-lock.yaml (via pnpm install)
  • S4a: bump cn to 0.5.1 (keep the existing ^ range style, ^0.5.1) in packages/ui/package.json, then pnpm install and the shared check; files: packages/ui/package.json, pnpm-lock.yaml (via pnpm install)
  • S5: update the build catalog (typescript, tsdown, vite, @vitejs/plugin-react, @tailwindcss/vite, tailwindcss, turbo, @turbo/gen, @types/node) to the approved versions, then the lint catalog (oxlint, oxfmt), as two separate commits, each followed by pnpm install and the shared check. After the lint bump run pnpm run format and report any formatting churn instead of committing it silently; files: pnpm-workspace.yaml, pnpm-lock.yaml (via pnpm install)
  • S6 (acceptance): final check from a clean state: pnpm install --frozen-lockfile then pnpm turbo run build typecheck lint test. Confirm pnpm outdated -r lists nothing beyond the versions the user excluded, no manifest holds a range for a catalog-managed dependency (grep for "vitest": "^ and similar), and koota is still 0.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-react in react, single-use dependencies stay inline, @vitest/coverage-v8 not added; waiting for plan approval
  • 2026-11-02 moved Later -> Next, plan awaiting user approval (Triage)
  • 2026-11-02 open questions for user: @types/node major (^26 vs ^24); drop default catalog:; koota excluded from updates (stays 0.6.6)
  • 2026-11-02 S1 and S2 updated for W-104's switch to typescript 7.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/node uses ^26.6.5 (applies in S1, replacing ^24 in apps/* and packages/ui)
  • 2026-11-02 answer: drop the default catalog: in favour of named catalogs:
  • 2026-11-02 answer: koota is excluded from update steps and stays exactly 0.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 by pnpm 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.0 already 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: cn 0.5.0 -> 0.5.1 (patch, single-use in packages/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 (react catalog) and cn -> 0.5.1 (inline in packages/ui/package.json); no other updates; S2 ticked
  • 2026-11-02 S3 and S5 are no-ops: pnpm outdated -r lists nothing for the testing, build and lint groups; no versions changed, ticked
  • 2026-11-02 new step S4a added after S4 for the inline cn bump (Implementer); S4 and S4a stay unticked until the Reviewer gate
  • 2026-11-02 user widened the Implementer hook allowlist in .github/agents/Implementer.agent.md for W-105 (explicit user decision) so the chore can edit pnpm-workspace.yaml, root, apps/* and packages/ui package.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 -r empty; reviewed, ticked
  • 2026-11-02 S6 acceptance passed: pnpm install --frozen-lockfile up to date; pnpm turbo run build typecheck lint test --force 47/47 tasks successful (run outside the sandbox); pnpm outdated -r empty; no catalog-managed dependency holds a literal range in the 13 manifests (all use catalog:<group>, koota is catalog:koota); pnpm why koota -r shows only koota@0.6.6; ticked
  • 2026-11-02 review: Reviewer APPROVED; all steps ticked (Triage)
  • 2026-11-02 done: moved Now -> Done (Triage)