fix(devx): generate the debt re-measure tsconfig outside the repository - #8260
Merged
Conversation
`--re-measure` wrote `tsconfig.debt-remeasure.json` into each ledgered package's own directory -- a tracked directory, matched by no .gitignore rule -- and left it there for the duration of that package's tsc run. Measured across the ledger that is a ~250s window in which any `git add -A` in the same worktree stages a live generated file; it already reached one real commit. The `finally` that removes it was never the gap, the address was. The project now goes to a fresh os.tmpdir() directory, which means every path it emits has to be absolute -- including the typeRoots tsc would otherwise derive from the config's own location. Without them packages/cli measures 1 instead of 188, so TS2688 now counts as a broken measurement rather than as one tidy error. Refs #8218
…t-remeasure-temp-tsconfig
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
hotlong
marked this pull request as ready for review
August 13, 2026 01:09
hotlong
enabled auto-merge
August 13, 2026 01:10
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.
Fixes #8218
check-type-check-coverage.mjs --re-measurewrotetsconfig.debt-remeasure.jsoninto each ledgered package's own directory — a tracked directory matched by no.gitignorerule — and left it there for the whole of that package'stscrun. Thefinallythat removes it was never the gap. The address was.What was measured, before choosing a shape
The card offered three shapes: gitignore it, harden the cleanup, or move it out of the tree. The measurements picked the third, and one of them nearly picked something else.
The window is normal-path, not crash-path. With the pre-fix code, a
git status --porcelainsampler running alongside a full--re-measuresaw?? packages/plugins/plugin-approvals/tsconfig.debt-remeasure.jsonat sample 22 of a 233s run. No crash involved — anygit add -Ain the same worktree during those minutes stages a live generated file. SIGKILLing the run mid-measurement then left the file behind permanently, which is the half afinallycannot cover.The file is genuinely not ignored.
git check-ignore -von the path exits 1 (no match) for bothpackages/cli/andpackages/plugins/plugin-approvals/.Moving it out is possible, but not for free — and the cost is silent. The old docblock argued the config had to be a sibling in the package directory, because
include/outDir/rootDirresolve relative to the file that declares them. That argument is half right: paths declared UP theextendschain keep resolving against the file that declared them, so the package's ownincludeneeds no help. What does need help is everything this generated file declares itself, plus one thing it does not declare at all —typeRoots, which tsc derives from the directory of the root config file. Measured onpackages/cli, same tree, same sources:os.tmpdir(),typeRootsreconstructedos.tmpdir(),typeRootsleft to tscThat 1 is a single
error TS2688: Cannot find type definition file for 'node'— and the counter was happy to record it as debt. A 187-error "improvement", handed to the ledger by a broken measurement, which--lowerwould then have written down. So TS2688 joinsTSC_SETUP_ERROR: the next way this breaks is loud rather than free.The change
measureTestDebtnow builds the project through a pureremeasureProject()and writes it into a freshmkdtempSync(os.tmpdir())directory it owns and removes. Every path it emits is absolute and rooted at the package:extends,exclude,include,rootDir, and a reconstructedtypeRoots(the ancestor walk tsc would have done from the package, stopped at the repo root so the number cannot depend on what is installed above the checkout). Two implicit paths are made explicit, because from a temp directory an implicit path does not fail — it quietly means something else:include(tsc substitutes**/*against the temp dir) — now always written, unless theextendschain already selects files;typeRoots— now written, unless the chain names its own.Six self-test cases pin those shapes, and every case additionally asserts the blanket property the design rests on: no path in the generated object may be relative.
Why no
.gitignorelineNo code path in the repo writes that name any more, so the rule would be dead the day it lands — and an ignore rule is precisely what would turn a resurrected stray into an invisible one. This script's own tsconfig scan is supposed to see strays in a package directory; that is the hazard its docblock already named.
The sibling survey
The card asked whether this is the only gate writing scratch into a tracked directory. It is — and the instrument was validated before the empty result was trusted.
check:*gates run with a tight-loopgit status --porcelainsampler alongside it. 0 dirtied the tree. Positive control: the same harness pointed at the pre-fix gate saw the stray file, so the empty result is a real answer and not a blind instrument.git statusround-trip): a write-API census over 83 script files shortlisted 34 with a create-and-delete signature; the 7 that do not usemkdtempSyncwere read directly. All write tomktemp -d,os.tmpdir(), a gitignorednode_modules/.*holder (check-driver-conformance.mjs— an existing precedent for keeping throwaway state where git cannot see it), gitignored build output, or an intentional tracked baseline behind--update.Verification
pnpm check:type-check-debt(the full--re-measure) on the merged tree: OK — 33 ledger entries re-measured in 243.3s, 1969 raw tsc errors total, none above its recorded number. surplus: none. Identical total to the pre-change baseline (1969, 249.1s), and since chore(devx): lower nine type-check DEBT ledger entries to their measurement (#7888) #8225 left every entry sitting exactly at its measurement, "green + surplus: none" is a per-entry oracle: no entry rose (green) and none fell (no surplus). All 33 measure the same as before.git status --porcelainsampled during the run, not only after. 74 samples across a 233s--re-measure: empty at every one, andfindfortsconfig.debt-*.jsonempty at every one. Tree clean afterwards.pnpm check:type-check-coverage(structural + self-test): OK, 25 re-measure cases now hold.pnpm check:type-source-resolution: OK.pnpm check:nul-bytes: OK, plus a direct control-byte scan of the changed file.eslint: clean.node scripts/pm/dispatch-gates.mjs scripts/check-type-check-coverage.mjs): the derivation added nothing beyond the three families named in the dispatch prompt.No
.changeset/entry: a CI-internal script releases nothing, which is this repo's own textbookskip-changesetcase (lint.yml's changeset-family note). No DEBT / TEST_DEBT ledger number is touched. The stale prose near lines 500 and ~1410 is out of scope: #8189 remains open and is not addressed here.Generated by Claude Code