Files
nxdns/specs/milestone-22.md
T

4.6 KiB

Milestone 22: TypeScript 7

Goal: move the web toolchain from TypeScript 6.0.3 to TypeScript 7.0.x (the native compiler, GA 2026-07-08). One devDependency bump; every web gate and the release pipeline stay green.

Design written 2026-08-12 against HEAD 91a0aa9. TypeScript 7.0.2 is typescript@latest on npm at spec time; the milestone pins whatever 7.0.x is current when the session runs.

Implementation contract (read first)

  • Read AGENTS.md, then this spec whole, before session work starts.
  • web/src/lib/contractSamples.gen.ts is generated; it is type-checked by tsc -b but never hand-edited. If TS7 rejects it, the fix goes in the generator (AGENTS.md regeneration procedure), not the file.
  • No license work: typescript is a devDependency, absent from both the runtime closure and the bundled set in licenses/dependency-identity.txt. The Zig drift guard (src/licenses_drift_test.zig) must still pass — it recomputes from web/package-lock.json and dev-only changes are invisible to it.

Rulings (binding)

1. The bump is one line plus the lockfile

web/package.json:45 "typescript": "6.0.3" becomes the current 7.0.x, exact pin (repo convention: no ranges, milestone-14 ruling 12 pins by exact version everywhere). npm install updates web/package-lock.json. Nothing else in dependencies or devDependencies moves in this milestone.

2. The tsconfigs are already TS7-clean; verify, do not churn

Checked against TS7's removed options (recorded here so the session does not re-derive it): tsconfig.app.json and tsconfig.node.json use moduleResolution: "bundler", module: "esnext", targets es2022/es2023, paths without baseUrl, verbatimModuleSyntax, isolatedModules, noEmit. None of TS7's removals (target: es5, downlevelIteration, moduleResolution: node10/classic, module: amd/umd/system/none, baseUrl-as-alias) are present. tsconfig.json is a two-entry project reference; TS7 supports tsc -b and project references. The session changes a tsconfig only if tsc -b errors demand it, and records any such change in ## Recorded (implementation).

3. Known TS7 edge: skipLibCheck no longer hides parse-level .d.ts errors

Both tsconfigs set skipLibCheck: true. Under TS7 that still skips type checking of .d.ts files but not parse-level errors in them. If a dependency .d.ts fails to parse, the fix is a dependency patch bump or an upstream issue reference recorded in the spec — never a copied-and-edited local .d.ts.

4. Nothing else in the toolchain consumes the TS compiler

Verified at spec time: oxlint (own parser), vite/vitest (esbuild transpile, no type checking), prettier, and @vitejs/plugin-react run no tsc and load no typescript API. The only consumer is the typecheck script (web/package.json:12, tsc -b), run in CI at .gitea/workflows/gates.yml:113-114. TS7 has no stable programmatic API until 7.1; nothing in this repo needs one.

Sessions

One session.

Session S1: the bump

Owns: web/package.json, web/package-lock.json, and — only if ruling 2 forces it — web/tsconfig.app.json, web/tsconfig.node.json, web/tsconfig.json.

  • S1.1 bump per ruling 1; npm install.
  • S1.2 run, in order: npm run format:check, npm run lint, npm run typecheck, npm test, npm run build, npm run assert-bundled (all from web/).
  • S1.3 zig build test (the licenses drift guard and the contract-samples guard run inside it).

Acceptance (S1):

  • web/node_modules/.bin/tsc --version reports 7.0.x.
  • npm run typecheck exits 0 with no tsconfig change, or the change is recorded with the TS7 error text that forced it.
  • All six web gate commands exit 0.
  • zig build test exits 0.
  • git diff touches only the files S1 owns.

Module layout

New files: none. Deleted surface: none.

Acceptance (milestone complete)

  • All S1 boxes.
  • licenses/dependency-identity.txt is byte-identical to HEAD.

Anti-requirements

  • No other dependency bumps ride along — not oxlint, not vite, not vitest, not @types/*.
  • No tsconfig flag additions or "modernization" beyond what a TS7 error forces.
  • No typescript-eslint, ts-jest, or any tool needing the TS programmatic API (unavailable until 7.1, and unwanted regardless — oxlint is the linter).
  • No tsgo binary references anywhere: the binary is tsc, scripts stay as they are.
  • No edits to web/src/** — a source change to satisfy the new compiler is a finding to record and fix, not silently absorb, unless tsc -b fails without it; then it is recorded in ## Recorded (implementation).