Skip to content

Commit fff8946

Browse files
committed
chore(gates): scope stale approvals to introduced entries and keep readers in sync
Address review findings on the eager-closure merge-base ratchet. - docs/agents/testing.md: drop the new bullet. The file was 386 bytes over the 10,000-byte focused-doc budget, and the gate module's header already owns the invariant, so the prose was duplication the ownership rule forbids. - The closure walker's relative resolver no longer tries a .tsx suffix. The repo defines a production source as .ts (tracked-sources.ts pathspecs and isProductionSourceFile), so the committed-tree reader never loads .tsx content; resolving one produced an edge that reader could not read, crashing the ratchet instead of failing it. - The APPROVED_OVER_CEILING staleness check now looks only at entries still first-introduced. Once the merge-base carries an entry, the no-growth rule governs it and nothing reads its row again, so the row is stale for the same reason a shrunk entry's row is.
1 parent 8f139c7 commit fff8946

4 files changed

Lines changed: 16 additions & 9 deletions

File tree

docs/agents/testing.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,6 @@ or remove flakes.
181181
- Test files over 1,000 lines may be no longer than at the merge-base with `origin/main`, and no
182182
new test file may cross that line. Split the family before adding tests; shrinking needs no
183183
gate edit.
184-
- Package entry surfaces and the designated hub modules may not evaluate more repo modules on
185-
import than at the merge-base with `origin/main` (`scripts/__tests__/eager-closure-budgets.ts`);
186-
a first-introduced entry fits a per-category ceiling, and a platform façade stays at exactly
187-
one module. Shrinking needs no gate edit; growth means moving an import behind `await import`.
188184
- Keep isolation enabled and the pool on forks — both alternatives were measured and did not help.
189185
The useful optimization is importing the module under test, not a platform barrel.
190186
- Local Vitest runs use a four-worker cap. Override it when a run needs a different host share:

scripts/__tests__/eager-closure-budgets.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,18 @@ test.for(introduced)(
406406
);
407407

408408
test('no APPROVED_OVER_CEILING row is stale', () => {
409+
// Only a first-introduced entry consults a ceiling. Once the merge-base carries the entry, the
410+
// no-growth rule governs it and nothing reads the row again, so a carried entry's row is stale
411+
// for the same reason a shrunk one is: it can no longer change any verdict.
412+
const introducedById = new Map(introduced.map((entry) => [entry.entryFile, entry]));
409413
const stale = Object.keys(APPROVED_OVER_CEILING).filter((id) => {
410-
const entry = entries.find((candidate) => candidate.entryFile === id);
414+
const entry = introducedById.get(id);
411415
return !entry || eagerClosureGraphOf(absolute(id)).size <= NEW_ENTRY_CEILINGS[entry.category];
412416
});
413417
expect(
414418
stale,
415-
'These approvals name an entry that no longer exists or now fits its ceiling: remove the rows.',
419+
'These approvals name an entry that no longer exists, that the merge-base now carries, or ' +
420+
'that now fits its ceiling: remove the rows.',
416421
).toEqual([]);
417422
});
418423

scripts/__tests__/eager-closure-budgets.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
// - An entry absent at the merge-base: a per-category CEILING (`NEW_ENTRY_CEILINGS`). At or
2121
// under it, nothing to write. Over it, one `APPROVED_OVER_CEILING` row naming the issue, the
2222
// reason, and an owner; the row records no number, and the merge-base carries the entry from
23-
// the next PR on. A row for an entry at or under its ceiling, or one that no longer exists,
24-
// is stale and fails.
23+
// the next PR on. A row is stale once nothing can read it -- the entry is gone, the merge-base
24+
// now carries it, or its closure fits the ceiling -- and a stale row fails.
2525
//
2626
// Independent of size, a façade entry's closure must never reach a concrete platform
2727
// implementation (`PLATFORM_IMPLEMENTATION_PATTERNS`) before discovery or binding selects an

src/__tests__/eager-import-closure.fixtures.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,16 @@ const workingTreeReader: SourceTreeReader = {
125125
readFile: (file) => fs.readFileSync(file, 'utf8'),
126126
};
127127

128+
/**
129+
* `.ts` only, matching what the repo counts as a production source: `tracked-sources.ts` scans
130+
* `.ts` pathspecs and `isProductionSourceFile` accepts `.ts`, so a `.tsx` file under a walked root
131+
* is invisible to every layering scan. Resolving one here would only produce an edge the committed
132+
* tree reader cannot read, which crashes the ratchet instead of failing it.
133+
*/
128134
function resolveRelative(from: string, specifier: string, tree: SourceTreeReader): string | null {
129135
const candidate = path.resolve(path.dirname(from), specifier);
130136
if (tree.isFile(candidate)) return candidate;
131-
for (const suffix of ['.ts', '.tsx', '/index.ts']) {
137+
for (const suffix of ['.ts', '/index.ts']) {
132138
if (tree.exists(`${candidate}${suffix}`)) return `${candidate}${suffix}`;
133139
}
134140
return null;

0 commit comments

Comments
 (0)