chore(types): close the .vue type-check gap - adopt vue-tsc in verify - #52
Merged
Conversation
This was referenced Jul 29, 2026
`pnpm run check:vue` (`vue-tsc --noEmit`) now runs inside `verify`, between `vp check` and `vp test`. It is the only thing in this repo that type-checks `<script setup lang="ts">` bodies - 22 `.vue` files that until now were checked by nothing at all. The gap was real and is reproduced here rather than asserted: a planted `TS2322` in `src/ui/FInfo.vue` left `vp check` printing "Found no warnings, lint errors, or type errors in 301 files", while `vue-tsc` reported `src/ui/FInfo.vue(3,7): error TS2322` and `pnpm run verify` exited 2 with the test suite never running. That plant-and-check is the proof the guard is not vacuous; if a future change makes `check:vue` pass on a planted error, it has been neutered. Against the real tree: 22 files, 0 errors, ~2.5s. No latent breakage was hiding behind the gap, so this is a regression guard, not a bug hunt. It runs on the existing `typescript` 6.0.3 - `vue-tsc`'s peer range is `>=5.0.0`, so no TypeScript 7 work was involved. Two CLAUDE.md claims this falsified, both now corrected in place: - **"Bare `vue-tsc --noEmit` crashes, it needs its own tsconfig excluding `vite.config.ts`."** No longer true, so no extra tsconfig is added here. That was measured 2026-07-22, one day before the `vue() as Plugin` cast landed in 388f285. Confirmed causally by deleting the cast and re-running: without it, `vp check` fails `TS2321` and `tsc` AND `vue-tsc` both die on the same `Debug Failure` assertion; with it, all three pass. So the `TS2321` and the `Debug Failure` crash are one pathology with one fix, not two problems. - **"`verify` is ~9.5s."** Measured 63s. That was already wrong by ~6x before this commit - the suite grew to 143 files through the Vulcanus and cliff work - so it is corrected rather than merely adjusted for the ~2.5s this adds. **Why it was rejected on 2026-07-22 and why that expired.** The only stated blocker was supply-chain freshness: 3.3.8 was under an hour old and installing it made pnpm silently write a `minimumReleaseAgeExclude` bypass. It was 7.3 days old here, so the gate passed on its own and `pnpm-workspace.yaml` is untouched by this commit - checked, not assumed. The old fallback advice to "pick 3.3.7 instead" is now obsolete and has been removed. Also documented while in the area, because it misleads in a dangerous direction: `pnpm config get minimumReleaseAge` reports `undefined`, which reads like "no policy". The 24-hour guard comes from pnpm 11's own defaults table (`"minimum-release-age": 24 * 60`), read out of pnpm 11.17.0's shipped code. And TypeScript 7 is now written up as a "don't" rather than a vague deferral: 7.0 ships no programmatic API at all (planned for 7.1), the official migration is a dual-install alias, and `vue-tsc` hard-crashes on a bare `typescript@7` with `ERR_PACKAGE_PATH_NOT_EXPORTED`. `vue-tsc` is ranged `^3.3.8` to match every sibling devDependency. Gate: `pnpm run verify` exit 0 - 314 files formatted, 301 files clean, `check:vue` clean, app 1249 passed / 3 skipped, worker 12, container 3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GjMSePtN9aTgr8EtZp66k1
`verify` gained a fourth phase, so three places that spell the list out went stale the moment it did. CLAUDE.md was updated in the parent commit; these were not: - `README.md` listed the gate as `vp check` + `vp test` + `preview:test` in two places (the script list and the deploy section) and had no `check:vue` entry at all, so the one command that type-checks `.vue` bodies was undiscoverable from the README. - `.github/workflows/verify.yml`'s comment said "its three phases". The count is the whole point of that comment - it explains why the workflow calls `pnpm run verify` verbatim instead of re-listing phases as steps. Comment-only in the YAML: no step is added and no phase is mirrored into CI, which is deliberate - `verify` stays the single definition and CI picks up the new phase with no workflow change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F3a2HLJ4beKARi7SPmaM54
wormeyman
force-pushed
the
chore/vue-tsc-type-check
branch
from
July 30, 2026 05:44
66a3645 to
9934a45
Compare
wormeyman
added a commit
that referenced
this pull request
Jul 30, 2026
Verified locally and in CI, and the archive itself was opened by two readers other than the one the test uses. ## The ZIP output is byte-identical across the swap Generated the real artifact both ways (jszip on `main`, client-zip on this branch) for the `Default` preset and compared with **Info-ZIP `unzip`** and **Python `zipfile`** - neither of which is jszip, the reader the spec uses: ``` unzip -t: "No errors detected in compressed data" for BOTH archives ``` | entry | before | after | bytes identical | | --- | --- | --- | --- | | `map-gen-settings.json` | 2936 B | 2936 B | **yes** | | `map-settings.json` | 3806 B | 3806 B | **yes** | | `Default.txt` | 798 B | 798 B | **yes** | Entry **names, order and bodies all identical**; both archives `Stored` at 0%, confirming jszip was not compressing either, so the pako 1.x payload was pure waste. Archive total 7888 -> 7936 B (+48, central-directory layout). Also checked the contents against the exporters directly - with no zip library in the loop - and `Default.txt` is verbatim equal to the `builtin-presets.json` fixture. ## No `eval`, no Node builtins, no new warnings `pnpm vp build` exit 0 and **zero warnings**. Scanning the emitted bundle: | marker | count in `dist` | | --- | --- | | `eval(` / `new Function(` | **0** | | `jszip` / `JSZip` | **0** | | `setImmediate`, `readable-stream`, `_tr_stored_block` | **0** | | `require(`, `node:fs`, `node:path`, `process.nextTick`, `Buffer.from` | **0** | | `incorrect header check` (pako) | **1** - the codec's pako 3.0.1 correctly remains | `public/_headers` and `vite.config.ts` are untouched: CSP is still `script-src 'self' https://static.cloudflareinsights.com` with no `unsafe-eval`, and **no `build.rollupOptions.onLog` suppression was added**. Upstream, `client-zip@2.5.0` is 6.4 kB of single-file ESM, MIT, **zero runtime dependencies**, and its tarball contains no `eval`, `new Function`, `require(` or `node:*` import. ## Bundle size re-measured, not taken from the description Built both branches here: **302.07 kB -> 211.44 kB raw (-90.64 kB, -30.0%)**, gzip -26.7%. Matches the claim. ## Gate - Local `pnpm run verify` exit **0** in 60s on the rebased tree: format 316, lint+type 301, `check:vue` clean, app **1251 passed / 3 skipped** (+2 as described), worker 12. - CI `verify`: **pass** on head `39a5890`, rebased onto `605a4cc` so it ran against a `main` containing both #51 and #52 - including #52's new `check:vue` phase. - `jszip` is in `devDependencies` and `client-zip` in `dependencies`; `pnpm install --frozen-lockfile` clean. ## One thing the PR missed `test/actionBar.spec.ts:72` still carries a jszip-specific comment - "buildZip -> JSZip.generateAsync resolves across macrotasks/setImmediate, which flushPromises (microtasks only) does not drain". The 100ms real-timer wait it justifies still works, so nothing fails, but the comment now explains the code by naming a dependency the app no longer bundles. Left as-is rather than widened into this PR; worth a one-line follow-up.
wormeyman
added a commit
that referenced
this pull request
Jul 30, 2026
…RULE, not the fields (#57) Verified locally and in CI, and the anti-vacuity control was tested by breaking it. ## The `+3` control is genuinely load-bearing - proven, not assumed This repo has a documented history of confirmations that turned out vacuous, so I sabotaged the substitution rather than trusting the assertion. Replacing the game-field lookup with one that never matches - i.e. simulating every lookup silently falling through to our own field: | test | with substitution dead | | --- | --- | | "substituting the game's own elevation and cliffiness does not move a single cell" | **still passes** | | "and the substitution really is live - a `+3` elevation bias does move cells" | **FAILS**: `AssertionError: expected 0 to be greater than 5` | So the headline assertion *would* have passed vacuously, and the `+3` control is exactly what catches it. Restored and re-confirmed 9/9 green. `expect(game.size).toBeGreaterThan(500)` is a second, independent guard against an empty placement set making the equality trivial. ## Provenance `test/fixtureProvenance.spec.ts` passes (4/4). Both new fixtures carry entries with `factorioVersion: "2.1.12"` and concrete `evidence` naming the capture script and recording that `refs:sync --check` reported in-sync at capture time - so neither lands as `unknown`, and the spec's `unknown` cap is not touched. ## Gate - Local `pnpm run verify` exit **0** in 60s on the exact tree that lands (`5399b6f`): format 316, lint+type 301, `check:vue` clean, app **1255 passed / 3 skipped**, worker 12. - CI `verify`: **pass** (4m41s). The branch was updated **twice** so the run tests the real target - it now contains #51, #52, #55 and #59, not the older `main` the first run saw. - No `src/` change, so nothing shipped to users; the new spec needs no Factorio at runtime because the fixtures are committed, which is why CI can run it. ## Two notes, neither blocking - The description reads as though `test/vulcanusOreCliffSeparation.spec.ts` is new. It is not - it already existed on `main` at 222 lines and this extends it to 597 (3 -> 7 `it` blocks at the top level, 9 tests total), which is why the file count stays 143 and the suite moves +4 rather than +9. - Re-deriving the binary reading and the statistics was explicitly out of scope for this pass, so the `0x1016229b4` / `0x101625038` disassembly claims and the Poisson figures are **recorded as the author's measurements, not independently reproduced here**. What was checked is that the code is gated, the fixtures have provenance, and the assertions can fail.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
pnpm run check:vue(vue-tsc --noEmit) now runs insideverify, betweenvp checkandvp test. It is the only thing in this repo that type-checks<script setup lang="ts">bodies - 22.vuefiles that until now were checked by nothing at all.The gap is reproduced, not asserted
Planted a
TS2322insrc/ui/FInfo.vueand ran both tools on the same tree:vp checkpass: Found no warnings, lint errors, or type errors in 301 filesvue-tscsrc/ui/FInfo.vue(3,7): error TS2322: Type 'string' is not assignable to type 'number'pnpm run verifyThat plant-and-check is the proof the guard is not vacuous. If a future change makes
check:vuepass on a planted error, it has been neutered - the note in CLAUDE.md says so explicitly.Against the real tree: 22 files, 0 errors, ~2.5s. No latent breakage was hiding behind the gap, so this is a regression guard rather than a bug hunt. It runs on the existing
typescript6.0.3 (vue-tsc's peer range is>=5.0.0), so no TypeScript 7 work was involved.Two CLAUDE.md claims this falsified
1. "Bare
vue-tsc --noEmitcrashes; it needs its own tsconfig excludingvite.config.ts."No longer true, so no extra tsconfig is added here. That was measured 2026-07-22 - one day before the
vue() as Plugincast landed in 388f285. Confirmed causally rather than guessed, by deleting the cast and re-running:vp checkTS2321: Excessive stack depthtsc --noEmitDebug Failure. False expression...vue-tsc --noEmitDebug Failure. False expression...So the
TS2321and theDebug Failurecrash are one pathology with one fix, not two problems. That is now recorded, because a reappearance of either should send you to the same place.2. "
verifyis ~9.5s." Measured 63s. Already wrong by ~6x before this commit - the suite grew to 143 files through the Vulcanus and cliff work - so it is corrected outright rather than nudged for the 2.5s this adds.Why it was rejected in July and why that expired
The only stated blocker was supply-chain freshness:
vue-tsc@3.3.8was under an hour old on 2026-07-22, and installing it made pnpm silently write aminimumReleaseAgeExcludebypass intopnpm-workspace.yaml.It was 7.3 days old here. The gate passed on its own and
pnpm-workspace.yamlis untouched by this commit - checked, not assumed. The old fallback advice to "pick 3.3.7 instead" is obsolete and removed. Ranged^3.3.8to match every sibling devDependency.Also documented while in the area
pnpm config get minimumReleaseAgereportsundefined, which reads like "no policy". It isn't - the 24-hour guard comes from pnpm 11's own defaults table ("minimum-release-age": 24 * 60, // 1 day), read out of pnpm 11.17.0's shipped code. Worth knowing before someone concludes the guard is off.typescript→npm:@typescript/typescript6); andvue-tschard-crashes on a baretypescript@7withERR_PACKAGE_PATH_NOT_EXPORTED: './lib/tsc'(Failed with typescript@7.0.2 vuejs/language-tools#6124). Meanwhile the type-check already runs TS7 semantics via tsgolint, so there is nothing to gain.pnpm outdated's6.0.3 -> 7.0.2row is a trap.Gate
pnpm run verifyexit 0 - 314 files formatted, 301 files clean,check:vueclean, app 1249 passed / 3 skipped, worker 12, container 3.Found by the dependency audit of 2026-07-29.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GjMSePtN9aTgr8EtZp66k1