# 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)`.
