W-104: Fix package build and dev scripts¶
Type: chore · Size: M · Epic: E-setup · Target: packages/*, turbo.json and root package.json · Breaking: no · Dependency change: typescript 6 -> 7.0.2 (user approved); root engines.node >=20.19.0 -> >=26.0.0 (user approved)
Depends: –
Refs: AGENTS.md (Commands), turbo.json, package-rules
Goal¶
From a clean pnpm install, pnpm turbo run build typecheck lint test passes for the whole repo, and pnpm dev starts every package's tsdown --watch without errors. The six packages/*/tsdown.config.ts keep dts: { generator: "tsgo" } (user decision); the build is fixed by upgrading typescript from ~6.0.2 to exactly 7.0.2 (stable, ships the Go compiler tsgo) in the whole workspace. This is a dependency change; the user approved it ("go to ts7 if suitable") and research found TS 7 suitable with the conditions below. The root engines.node is also bumped from >=20.19.0 to >=26.0.0 (user decision: tsdown 0.23.4 / rolldown-plugin-dts 0.28.8 require ^22.18.0 || ^24.11.0 || >=26.0.0, and the user wants v26), in S7. S1 only confirms the TS version exists and the installed Node is >=26 (otherwise the bump would make pnpm install warn or fail with engine-strict). The root package.json is not covered by the Implementer file guards, so the main agent or user makes that edit. Aligning @types/node is out of scope (W-105).
Verified findings (from pnpm build at the root and the .turbo/turbo-build.log files):
- Package build (confirmed, root cause; fix = TypeScript 7.0.2). All six
packages/*/tsdown.config.tssetdts: { generator: "tsgo" }. tsdown 0.23.4 / rolldown-plugin-dts 0.28.8 then needstypescript@7.0or@typescript/native-preview, but the workspace hastypescript@6.0.3(~6.0.2) and neither is installed, sotsdownthrows "TypeScript Go is not installed" (seepackages/ecs-schedule/.turbo/turbo-build.log). Decision (user): keep thetsgogenerator; go to TypeScript 7 if suitable. Thetsdown.config.tsfiles stay unchanged. All package tsconfigs already havedeclarationandemitDeclarationOnly. - Chosen:
typescriptexactly7.0.2(npmlatest, stable, ships the Go compiler). tsdown 0.23.4 peer istypescript ^5||^6||^7; rolldown-plugin-dts 0.28.8 peer is^5||^6||~7.0.0. The plugin's tsgo detection checksversion.slice(0,3) === "7.0", so pin exactly7.0.2(not~or^): a future 7.1 would break tsgo detection. With TS 7 installed the plugin'stscgenerator throws, which is fine whiletsgostays. - TS 7 compatibility (research): no repo code imports the
typescriptJS API (TS 7 does not export it). No removed or deprecated tsconfig options found (nobaseUrl, node10 resolution and so on). Options in use:paths,moduleResolution: bundler,module: preserve,verbatimModuleSyntax,erasableSyntaxOnly,allowImportingTsExtensions,tsBuildInfoFile,declaration+emitDeclarationOnly. Unverified:tsc -bandtsBuildInfoFilebehaviour on TS 7, and whether the apps'tsc -bfailure (finding 2) changes; S3 and S5 verify. - Scope: change
"typescript": "~6.0.2"to"7.0.2"in the rootpackage.jsonand in 12 more:packages/{ecs,ecs-devtools,ecs-prefab,ecs-relations,ecs-schedule,ecs-serialize,ui}andapps/{demo-anno,demo-ck3,demo-dnd,demo-totalwar,web};pnpm installupdatespnpm-lock.yaml.apps/web,packages/uiand the rootpackage.jsonare not covered by the Implementer, DemoImplementer or Scaffolder file guards: the user or main agent makes those edits (S5). - Environment: the
node_modulesstore is out of sync with the lockfile (the lockfile hastypescript@6.0.3only; a staletypescript-eslintleftover is innode_modulesbut not in the lockfile).pnpm installresolves it. - Fallback (not planned):
@typescript/native-previewpinned to an exact dev snapshot as a devDependency of the six packages, withtypescriptstaying at 6.0.x. Use only if S1 fails or TS 7 breaks something S3 cannot fix with a small change; it needs a new user approval. - Rejected fallback:
dts: true(the defaulttscgenerator). It contradicts the user decision and throws on TS 7. - W-105 later moves
typescriptinto itsbuildcatalog; see its S1 (updated to7.0.2). - App build (silent
tsc -bfailure; cause not yet determined).apps/demo-dndandapps/webfail attsc -band their logs contain only "Command failed", with no diagnostics. Comparison with the passingapps/demo-anno:tsconfig.json,tsconfig.app.json,tsconfig.node.json,package.json,vite.config.ts,src/App.tsx(except the title),src/main.tsx,src/ecs/world.tsandsrc/test/setup.tsare identical, so the difference is not config or source.demo-dndhasnode_modules/.tmp/*.tsbuildinfofrom an earlier success (typescript 6.0.3, no errors) andwebhas none, sowebhas never completedtsc -b(that tsbuildinfo came from TS 6.0.3; TS 7 may not read it).webadditionally importsButtonfrom@workspace/ui(packages/ui/srcis type-checked through thepathsalias), whichdemo-dndanddemo-annodo not.demo-anno,demo-ck3,demo-totalwarpassed from the turbo cache, so they may fail the same way on a cache miss. The real error needs a run oftsc -b(S5). - Missing
lintscript (confirmed).packages/ecs/package.jsonhas nolintscript; the other five packages have"lint": "oxlint", and the root.oxlintrc.jsonapplies. - Turbo config (verified sound, no change).
build(^build, outputsdist/**,inputswith$TURBO_DEFAULT$),lint,typecheck,testanddev(cache: false,persistent: true) fit the packages' scripts (tsdown,tsdown --watch,oxlint,tsc --noEmit). Packages typecheck cleanly today on TypeScript 6.0.3 (tsc --noEmitwithemitDeclarationOnly); on TS 7 this is unverified until S3.devruns after the tsgo fix becausetsdown --watchuses the same config. - Side findings, not fixed here (see open questions). App
typecheckistsc --noEmitagainst atsconfig.jsonwith"files": [], so it checks nothing.@types/nodeis^26.6.5inpackages/*and^24inapps/*andpackages/ui(no failure observed; alignment stays in W-105). tsdown needs Node^22.18 || ^24.11 || >=26while the rootenginessays>=20.19.0: resolved here by bumping to>=26.0.0(S7). Node-version pin check (grep of the repo outsidereference/): the only pin is rootpackage.jsonengines.node. There is no.nvmrc,.node-version,.tool-versions,mise.toml,voltaentry or.github/workflows/in the repo root (.npmrcis empty, so noengine-strict);packageManagerispnpm@11.25.0(not a Node pin); README, AGENTS anddocs/do not mention a Node version; no workspacepackage.jsonhas its ownengines. Matches underreference/belong to read-only sources and are ignored.
Steps¶
- S1 (gate, no file changes): confirm TS 7 is usable and Node is new enough for the engines bump. Run
pnpm view typescript@7.0.2 version peerDependencies(must print7.0.2), andnode -v(must bev26.0.0or higher; this also satisfies tsdown'spnpm view tsdown@0.23.4 engines,^22.18 || ^24.11 || >=26). Record both results in the Log. The user already approved TS 7 and the engines bump (see Log), so no further approval is needed; if the TS version is missing ornode -vis below 26, stop and ask (do not runpnpm installor editengines; the S7 bump would makepnpm installwarn or fail with engine-strict). Fallback for TS: finding 1. Files: docs/work/W-104-fix-package-build-dev.md (Log only) - S2: set
"typescript": "7.0.2"(exact, no~or^) in thedevDependenciesof the sixpackages/ecs,packages/ecs-devtools,packages/ecs-prefab,packages/ecs-relations,packages/ecs-scheduleandpackages/ecs-serialize, then runpnpm install(never hand-editpnpm-lock.yaml). Leave everytsdown.config.tsunchanged. Verify:pnpm --filter @workspace/ecs-schedule buildexits 0 and writesdist/index.mjsanddist/index.d.mts, andpnpm --filter @workspace/ecs-schedule typecheckpasses. If tsdown still reports "TypeScript Go is not installed" orpnpm installfails, record it in the Log and stop (no switch todts: trueor@typescript/native-previewwithout asking). tsdown'sexports: truemay rewritepackage.jsonexports(for example addtypes): reviewgit diff -- 'packages/*/package.json'and keep the change only if it is limited todevDependenciesandexportsand the./dist/index.mjsentry is intact; files:packages/{ecs,ecs-devtools,ecs-prefab,ecs-relations,ecs-schedule,ecs-serialize}/package.json,pnpm-lock.yaml - S3: verify the six packages on TS 7:
pnpm turbo run build typecheck --filter="./packages/*"exits 0 (this runstsc --noEmiton TS 7 for every package), each package hasdist/index.mjsanddist/index.d.mts,git diff --stat -- 'packages/*/tsdown.config.ts'is empty. If TS 7 rejects something, fix it with the smallest change in the named file only (no tsconfig option removals across packages, no test edits); if the fix needs more than that, stop and ask. Apply theexportsdiff review from S2; files: only the file named by the error (none if clean) - S4: add
"lint": "oxlint"to thescriptsofpackages/ecs/package.json, placed aftertypecheckas in the other packages. Verify:pnpm --filter @workspace/ecs lintreports 0 errors (packages/ecs/src/index.tsandtests/are linted); files:packages/ecs/package.json - S5: align the rest of the workspace on one TypeScript version, then diagnose the apps'
tsc -bon TS 7. (1) Set"typescript": "7.0.2"inpackages/ui, the rootpackage.json,apps/demo-anno,apps/demo-ck3,apps/demo-dnd,apps/demo-totalwarandapps/web, thenpnpm install;pnpm why typescriptshows only7.0.2.apps/web,packages/uiand the rootpackage.jsonare outside the Implementer, DemoImplementer and Scaffolder file guards: the user or main agent makes those three edits. (2) Diagnosis, no further file changes: runpnpm --filter demo-dnd exec tsc -b --verbose,pnpm --filter web exec tsc -b --verbose, thenpnpm --filter demo-anno exec tsc -b --forceto see whether the passing demos fail on a real run. Record in the Log, per command: the exit code, the full error text, which project (tsconfig.app.jsonortsconfig.node.json) fails, and the cause category: (a) a type error in app orpackages/uisource, (b) a stale or corruptnode_modules/.tmp/*.tsbuildinfo, © a config or TypeScript 7 option problem shared by all apps, or (d) something else. If no error text appears even with--verbose, also runpnpm --filter demo-dnd exec tsc -b --listFilesOnlyand record what it shows. If (1) and (2) are better as two commits, split into S5 (bump) and S5a (diagnosis); files:package.json,packages/ui/package.json,apps/{demo-anno,demo-ck3,demo-dnd,demo-totalwar,web}/package.json,pnpm-lock.yaml - S6: fix what the S5 diagnosis found, one small change that leaves the repo green. The fix is determined by the S5 result (if S5 found nothing failing, tick this step with a Log line and no change): (a) correct the type error in the file named by S5 (for a
packages/uierror, in that file only; if the fix needs a component or dependency change, stop and ask); (b) for a stale.tsbuildinfo, delete onlyapps/<app>/node_modules/.tmp/*.tsbuildinfowith a non-recursiverm(the hook blocksrm -r) and rerun; this changes no tracked file, so record it in the Log and add no commit; © fix the shared TS 7 option in the affectedtsconfig.*.jsonof everyapps/*that has it (apps/webis not covered by the Implementer, DemoImplementer or Scaffolder file guards, so the user or main agent makes that edit); (d) write a new Log line with the cause and add stepsS6a..before continuing. Verify:pnpm turbo run build --filter=demo-dnd --filter=webexits 0 andpnpm --filter demo-anno exec tsc -b --forceexits 0. If the S6 fix touches a dependency, this is a gate: stop for user approval; files: determined by the S5 result - S7: bump the root Node engine. In the root
package.jsonchange"engines": { "node": ">=20.19.0" }to">=26.0.0"; this is the only Node pin in the repo (see finding 5; nothing else to keep consistent, and@types/nodestays out of scope, W-105). The rootpackage.jsonis outside the Implementer file guards: the user or main agent makes this edit. Do this only after the S1 gate passed (installed Node >=26). Verify:pnpm installfinishes without an engines warning or error and leavespnpm-lock.yamlunchanged by this step;node -vis still >=26; files:package.json - S8 (acceptance): run
pnpm install, thenpnpm turbo run build typecheck lint test --forceover the whole repo (no--filter) so turbo cache hits cannot hide failures; all tasks pass. Then the dev smoke check: startpnpm --filter @workspace/ecs-schedule dev, confirm the log shows a successful first build and a watching state with noERROR, then stop it (Ctrl+C). Confirmgit statusshows only the expected files: the 13package.jsonfiles (root plus 12 workspaces: 7 packages and 5 apps; the root one carries both thetypescriptandengineschanges),pnpm-lock.yaml, and any S3 or S6 fix (no straydist/, sincedistis git-ignored;tsdown.config.tsuntouched). Changeset check: all six packages areprivateat0.0.0and the change is toolchain-only (chore), so perpackage-rulesno changeset is added. If S2 or S3 changed publishedexportsmetadata in apackage.json, add.changeset/w-104-fix-package-build-dev.mdwith apatchentry for the affected packages. Do not edit.changeset/config.json(the guard hooks allow only.changeset/w-*files for the Implementer); no change to it is needed
Log¶
- 2026-11-02 created from user request under E-setup (Triage)
- 2026-11-02 sized M, epic E-setup (Triage)
- 2026-11-02 placed in Later, not prioritized; the user has not yet named the observed build/dev failures (Triage)
- 2026-11-02 Goal replaced with verified findings; steps S1..S6 written (Planner). tsgo failure confirmed in
packages/ecs-schedule/.turbo/turbo-build.log; apptsc -bcause still unknown, diagnosed in S4. No dependency change planned;@typescript/native-previewis only an alternative and needs user approval - 2026-11-02 moved Later -> Next, plan awaiting user approval (Triage)
- 2026-11-02 open questions for user: app
tsc -bcause unknown;typecheckof apps checks nothing - 2026-11-02 plan revised: keep tsgo, add @typescript/native-preview (or TS 7), dependency gate added (Planner)
- 2026-11-02 open questions for user: confirm tsgo source and version (
@typescript/native-previewrecommended, S1); W-105'sbuildcatalog should include it (W-105 not edited here); apptsc -bcause unknown;typecheckof apps checks nothing;@types/node^26vs^24 - 2026-11-02 plan revised: upgrade typescript to 7.0.2, keep tsgo; user approved TS 7 if suitable, research found it suitable (Planner)
- 2026-11-02 user approved the
typescriptmajor (6 -> 7.0.2) in this session; W-105's stop-and-ask for atypescriptmajor is therefore satisfied for 7.0.2 (W-105 S1 and S2 updated); S1 only confirms the version exists and Node satisfies tsdown's engines - 2026-11-02 open questions for user: (1) engines mismatch: tsdown needs Node
^22.18 || ^24.11 || >=26, rootenginessays>=20.19.0; fix in a separate item? (2) apps'typecheckistsc --noEmiton"files": []and checks nothing; (3)@types/node^26inpackages/*vs^24inapps/*andpackages/ui(W-105 aligns it); (4)tsc -bfailure cause unknown and may change on TS 7 (S5); (5) size: 7 steps exceeds M (4-6); keep as M or split S5..S6 into a follow-up item (Triage decides) - 2026-11-02 plan approved by user (Triage to set active)
- 2026-11-02 user asked to bump root engines.node to >=26; step added (Planner)
- 2026-11-02 plan approved, set active (Triage)
- 2026-11-02 S1: pass. node v26.5.0, pnpm 11.25.0; typescript@7.0.2 exists (version 7.0.2, no peerDependencies, engines node >=16.20.0); tsdown@0.23.4 engines
^22.18.0 || ^24.11.0 || >=26.0.0(satisfied by node v26.5.0), peer typescript^5.0.0 || ^6.0.0 || ^7.0.0 - 2026-11-02 S2: pass.
typescriptset to7.0.2in the sixpackages/ecs*package.json files;pnpm installupdatedpnpm-lock.yaml(installed typescript 7.0.2).pnpm --filter @workspace/ecs-schedule buildexit 0 ("Emit types with typescript@7.0.2",dist/index.mjsanddist/index.d.mtswritten; WARN that TS 7 API is experimental);typecheckexit 0.git diff -- 'packages/*/package.json'shows only thetypescriptdevDependency line;exportsunchanged;tsdown.config.tsuntouched - 2026-11-02 S3: pass.
pnpm turbo run build typecheck --filter="./packages/*"exit 0 (13/13 tasks; typecheck re-run with--force: 7/7, exit 0,tsc --noEmiton TS 7.0.2). All six packages havedist/index.mjsanddist/index.d.mts;git diff --stat -- 'packages/*/tsdown.config.ts'empty;package.jsondiff limited to thetypescriptdevDependency,exportsunchanged. No TS 7 incompatibility found, no fix needed - 2026-11-02 S4: pass. Added
"lint": "oxlint"aftertypecheckinpackages/ecs/package.json.pnpm --filter @workspace/ecs lintexit 0 (oxlint prints no diagnostics;src/index.tsandtests/index.test.tspresent) - 2026-11-02 S5: partial, not ticked. Done:
typescriptset to7.0.2inapps/demo-{anno,ck3,dnd,totalwar}/package.json;pnpm installexit 0 (needed unsandboxed store access). BLOCKED by.github/hooks/guard.mjs(outside agent scope): rootpackage.json,packages/ui/package.json,apps/web/package.jsonstill~6.0.2;pnpm why typescripttherefore shows 6.0.3 (zard-ecs,@workspace/ui,web) and 7.0.2 (everything else). The user or main agent must make those three edits and rerunpnpm installand thewebdiagnosis (thewebrun below used TS 6.0.3) - 2026-11-02 S5 diagnosis (no file changes):
pnpm --filter demo-dnd exec tsc -b --verboseexit 0 on TS 7.0.2 (tsbuildinfo "generated with version 6.0.3 differs with 7.0.2", rebuilt both projects, no errors);pnpm --filter web exec tsc -b --verboseexit 0 but on TS 6.0.3 (no tsbuildinfo existed, built both projects, no errors; not valid for TS 7 until web is bumped);pnpm --filter demo-anno exec tsc -b --forceexit 0, no output. No error text, failing project or category (a)-(d) reproduced: the earlier silent failure did not reproduce;--listFilesOnlynot needed.pnpm --filter demo-dnd buildexit 0 (vite built). Likely earlier cause: category (b), stale tsbuildinfo, unconfirmed - 2026-11-02 S5: pass. User edited root
package.json,apps/web/package.json(7.0.2) andpackages/ui/package.json(~7.0.2, tilde not exact: reported, not edited).pnpm installexit 0 ("Already up to date");pnpm why typescript -rshows onlytypescript@7.0.2("Found 1 version of typescript"; theuitilde range resolves to 7.0.2).pnpm --filter web exec tsc -b --verboseexit 0 on TS 7.0.2 (both projects rebuilt, tsbuildinfo 6.0.3 -> 7.0.2, no errors);pnpm --filter web buildexit 0 (tsc -b && vite build, 55 modules, built in 176ms) - 2026-11-02 S6: nothing failing in S5, no change
- 2026-11-02 S7: pass (verify only; user made the edit). Root
engines.nodeis>=26.0.0;pnpm installexit 0 with no engines warning or error;pnpm-lock.yamlbyte-identical before and after the install;node -vv26.5.0 - 2026-11-02 S8: pass.
pnpm installexit 0.pnpm turbo run build typecheck lint test --forceexit 0 (47/47 tasks, 0 cached; first sandboxed run failed only with EROFS on/tmpmkdtemp in the tsgo dts step, passed unsandboxed).timeout 30 pnpm --filter @workspace/ecs-schedule dev: "Build start", "Emit types with typescript@7.0.2", dist/index.mjs and dist/index.d.mts written, "Rebuilt in 44ms", no ERROR (only the TS 7 experimental WARN); killed by timeout (exit 124).git status: only expected files (13 package.json incl.packages/uinow exact7.0.2,pnpm-lock.yaml, docs, plus unrelated.gitignoreandzensical.toml);tsdown.config.tsuntouched; noexportschange, so no changeset (.changeset/has only config.json and README.md) - 2026-11-02 open question for user (resolved,
packages/ui/package.jsonis now exact7.0.2):packages/ui/package.jsonhastypescript~7.0.2(tilde) while the item and rolldown-plugin-dts detection require an exact7.0.2; change to7.0.2? - 2026-11-02 count corrected in S8 step text and S8 Log line: 13
package.jsonfiles (root plus 12 workspaces: 7 packages, 5 apps) (Triage) - 2026-11-02 final Reviewer pass APPROVED; state active -> review (Triage)
- 2026-11-02 no
[manual]requirements, so no accept gate; review -> done, moved Now -> Done on board, archive trimmed (W-005 to archive) (Triage)