Skip to content

check:type-check-debt writes tsconfig.debt-remeasure.json into tracked package dirs and it is not gitignored — a concurrent git add -A commits it #8218

Description

@os-zhuang

Demonstrated, not hypothetical: it happened to me while working #8119, and the stray file reached a commit. Filed unassigned.

The window

scripts/check-type-check-coverage.mjs --re-measure measures each ledgered package's TEST_DEBT by writing a scratch tsconfig into that package's own directory:

const REMEASURE_CONFIG = 'tsconfig.debt-remeasure.json';
const configPath = join(ROOT, dir, REMEASURE_CONFIG);

writeFileSync(configPath, `${JSON.stringify(project, null, 2)}\n`);
try {
  return tscErrorCount(posix.join(dir, REMEASURE_CONFIG));
} finally {
  rmSync(configPath, { force: true });
}

The cleanup is correct and the finally is right. The gap is that the path is inside a tracked directory and matches no .gitignore rule, so for the duration of one package's tsc run the repo has an untracked, non-ignored file sitting in packages/<name>/.

The function's own docblock already anticipates the stray-file hazard — "a stray tsconfig.*.json left behind would be picked up by this very script's own tsconfig scan on the next run" — but only from the script's perspective. From git's perspective it is an ordinary new file.

What it costs

The full re-measure is slow (221s in my run, 33 entries, sequential by design), so the aggregate window is minutes. Anything doing git add -A in that worktree during it commits the scratch file. That is not an exotic move here: it is what the standard commit flow does, and this repo runs many agents in parallel.

In my case the sequence was ordinary — start the gate, write an unrelated one-line doc fix while it ran, git add -A && git commit:

 2 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 packages/cli/tsconfig.debt-remeasure.json

71 lines of generated tsconfig in a docs-only commit. It never reached main (that commit was blocked from pushing for an unrelated reason and I caught it when re-applying), but nothing in the toolchain would have stopped it — and the follow-on is worse than the file itself: the gate's finally then deleted it, so git status showed a deleted tracked file, which reads exactly like a real deletion to clean up. Restoring it with git checkout -- (the natural response) re-materialises the junk and makes it look intentional.

Suggested fix

One .gitignore line — tsconfig.debt-remeasure.json, or tsconfig.*.remeasure.json if a pattern is preferred. No behaviour change to the gate, and it makes the accident structurally impossible rather than relying on nobody committing during a several-minute window.

Worth a scan for sibling generators writing scratch files into tracked dirs under names no ignore rule covers; I only checked this one.

Not the same as


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions