test: GST-986 fix-check failing-first: test skip after the read, re-raised blocker, verify early-return cleanup, carry wording

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-11-02 14:02:41 +00:00
1 parent 7f207c05bf
commit 83b89ebd8a
2 files changed
+52 -2

No files matched your search

+13
View File
@@ -285,4 +285,17 @@ describe('GST-986 item 5: fix-check passes and their findings count from the led
const s = loop(summary(repo, '--run', run));
expect(s).toMatchObject({ passes: 1, blocking_found: 3, deferred: 1, fixed: 0, fix_checks: 1, rounds: 2, unrecorded: 2 });
});
// Value: protects=a blocker the last fix-check raises again is not fixed: only a fix-check after its last occurrence follows it
// (round 2 outside voice on this PR: the re-raised blocker read blocking_found=1 fixed=1 with nothing unrecorded);
// fails_when=an earlier occurrence's follow-up marks it fixed; seam=gstack-review-scope summary --run
test('a blocker the last fix-check raises again stays unrecorded', () => {
const repo = branchWith([review(0, 1, [{ fingerprint: 'lib/a.ts:10:logic', raised_by: 'red-team' }])]);
const run = path.join(repo.root, 'run');
const step = (dir: string, readers: Array<[string, string]>) => { pass(path.join(run, dir), readers); Bun.sleepSync(5); };
step('p1', [['red-team', '[CRITICAL] lib/a.ts:10 the cap is never enforced']]);
step('fc1', [['fix-check', '[CRITICAL] lib/a.ts:10 the cap is still never enforced']]);
const s = loop(summary(repo, '--run', run));
expect(s).toMatchObject({ passes: 1, blocking_found: 1, fixed: 0, fix_checks: 1, unrecorded: 1 });
});
});
+39 -2
View File
@@ -37,10 +37,10 @@ const commit = (repo: FixtureRepo, file: string, text: string, msg: string) => {
};
/** One targeted read through the real dispatch steps; `reply` is the reader's raw output after its REVIEWED_TREE line. */
function targetedRead(repo: FixtureRepo, base: string, dir: string, reply: string | null, sent = true): string {
function targetedRead(repo: FixtureRepo, base: string, dir: string, reply: string | null, sent = true, classes = 'money'): string {
const out = path.join(repo.root, dir);
const ledger = path.join(out, 'review-ledger.jsonl');
const render = runBin(repo, 'gstack-review-dispatch', ['render', '--role', 'targeted', '--classes', 'money', '--diff-base', base, '--out', out]);
const render = runBin(repo, 'gstack-review-dispatch', ['render', '--role', 'targeted', '--classes', classes, '--diff-base', base, '--out', out]);
expect(render.status, render.err).toBe(0);
const file = /file=(\S+)/.exec(render.out)![1]!;
if (sent) expect(runBin(repo, 'gstack-review-dispatch', ['sent', '--ledger', ledger, '--role', 'targeted', '--sent', file]).status).toBe(0);
@@ -107,6 +107,18 @@ describe('verify records the targeted reader\'s outcome and the commit it read (
expect(recordLine(v.out)).toBe('');
expect(fs.existsSync(record)).toBe(false);
});
// Value: protects=a verify that stops early (an empty ledger: no brief records) still removes the stale record (round 2 Red
// Team and adversarial on this PR); fails_when=the early return leaves it; seam=gstack-review-dispatch verify --targeted-out
test('verify on a ledger with no brief records removes a stale --targeted-out file too', () => {
const { repo } = moneyBranch();
const ledger = path.join(repo.root, 'empty-ledger.jsonl');
fs.writeFileSync(ledger, '');
const record = path.join(repo.root, 'targeted.json');
fs.writeFileSync(record, '{"stale":true}\n');
expect(verify(repo, ledger, record).status).toBe(EXIT.refused);
expect(fs.existsSync(record)).toBe(false);
});
});
describe('write binds a targeted record only to the product patch the reader read (item 2)', () => {
@@ -158,6 +170,30 @@ describe('write binds a targeted record only to the product patch the reader rea
expect(stale.status).toBe(EXIT.fail);
expect(stale.err).toContain(`the targeted reader read ${head.slice(0, 12)}`);
});
// Value: protects=a test edit after the read that skips a case is gate-class work the reader never saw, so the record does not
// bind though the product patch (which leaves tests out) is unchanged (round 2 outside voice and adversarial on this PR);
// a record whose read commit is not an ancestor of the head is refused; fails_when=write binds either;
// seam=gstack-ship-receipt write --review-targeted
test('a test skipped after the read is refused though the product patch is unchanged; a rewritten read is refused', () => {
const { repo, base } = moneyBranch();
const cases = (cap: string) => `import { test, expect } from "bun:test";\ntest.skip("unit", () => { expect(1).toBe(1); });\n${cap}("cap", () => { expect(5).toBe(5); });\n`;
commit(repo, 'test/charge.test.ts', cases('test'), 'cap test, unit case skipped');
const head = repo.git('rev-parse', 'HEAD');
const record = path.join(repo.root, 'targeted.json');
expect(verify(repo, targetedRead(repo, base, 'h1', 'NO FINDINGS', true, 'money,gate'), record).status).toBe(0);
expect(write(repo, ['--review-targeted', `@${record}`]).status).toBe(EXIT.ok);
commit(repo, 'test/charge.test.ts', cases('test.skip'), 'skip the cap test');
const skipped = write(repo, ['--review-targeted', `@${record}`]);
expect(skipped.status).toBe(EXIT.fail);
expect(skipped.err).toContain(`the targeted reader read ${head.slice(0, 12)}`);
repo.git('reset', '-q', '--hard', base);
commit(repo, 'src/charge.ts', 'export const spend_cap_usd = 75;\n', 'rewritten money change');
const rewritten = write(repo, ['--review-targeted', `@${record}`]);
expect(rewritten.status).toBe(EXIT.fail);
expect(rewritten.err).toContain(`the targeted reader read ${head.slice(0, 12)}`);
});
});
describe('write and carry refuse a receipt the queue\'s targeted verdict refuses (item 4, #3854)', () => {
@@ -204,6 +240,7 @@ describe('write and carry refuse a receipt the queue\'s targeted verdict refuses
const uncovered = carry(versioned);
expect(uncovered.status).toBe(EXIT.refused);
expect(uncovered.err).toMatch(/requires the targeted reader on money, but the receipt records no targeted pass.*\(RECEIPT_CARRY_REFUSED/);
expect(uncovered.err).toContain('the queue refuses it once #3859 lands');
expect(extractReceipt(fs.readFileSync(uncovered.body, 'utf8')).receipt!.head).toBe(head);
const ok = carry(covered);
expect(ok.status, ok.err).toBe(EXIT.ok);