From 176db3fa12c93ca564e94e847b35b78d2a509f16 Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 16:55:43 +0000 Subject: [PATCH] fix(merge fc292e22f): tentative REVIEW_EXCLUDE_KEY_VERSION, classify targeted.json, render main's new outside-voice test from a clean checkout - lib/ship-policy.ts: REVIEW_EXCLUDE_KEY_VERSION 1.93.0.0 -> 1.94.0.0, the next-minor tentative form stamp_paths moves (docs/ship-policy.md, #3512); 1.93.0.0 is a released heading that never names the key. - test/gstack-clean-producers.test.ts (new from main): KEPT gains targeted.json, the wave's --review-targeted input. - test/review-dispatch.test.ts: main's wrong-tree test rendered the outside voice from ROOT; a CI build that dirties ROOT pushes that diff past the wave's REVIEW_DIFF_MAX_BYTES ceiling, so render refused and verify saw no brief (exit 3). It now runs in cleanCheckout like the wave's other outside-voice tests. --- lib/ship-policy.ts | 2 +- test/gstack-clean-producers.test.ts | 1 + test/review-dispatch.test.ts | 13 +++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/ship-policy.ts b/lib/ship-policy.ts index 2eca8d55c..d7dbefd83 100644 --- a/lib/ship-policy.ts +++ b/lib/ship-policy.ts @@ -236,7 +236,7 @@ export const BUMP_NEVER_KEY_VERSION = '1.91.353.0'; export const BASE_RED_KEY_VERSION = '1.91.374.0'; /** `train.gates` and `train.land` are values of the older train key, so compatErrors checks them by value, as for bump: never. */ export const TRAIN_GATES_KEY_VERSION = '1.92.0.0'; -export const REVIEW_EXCLUDE_KEY_VERSION = '1.93.0.0'; +export const REVIEW_EXCLUDE_KEY_VERSION = '1.94.0.0'; export const POLICY_KEY_INTRODUCED: Record = { bump: '1.91.73.0', queue_mode: '1.91.73.0', release_tool: '1.91.73.0', release_outputs: '1.91.73.0', stamp_paths: '1.91.73.0', changelog: '1.91.73.0', mirror: '1.91.73.0', history: '1.91.73.0', preregistration_shas: '1.91.73.0', stamp_sensitive_gates: '1.91.73.0', diff --git a/test/gstack-clean-producers.test.ts b/test/gstack-clean-producers.test.ts index 58781cd0b..14c9cdc1c 100644 --- a/test/gstack-clean-producers.test.ts +++ b/test/gstack-clean-producers.test.ts @@ -40,6 +40,7 @@ const KEPT: Record = { 'base-red.json': '/ship base-red record', 'review-*': '/ship review loop records', 'fix-check-*': '/ship fix-check inputs', + 'targeted.json': '/ship targeted review record, read by gstack-ship-receipt write --review-targeted (ship/DRIVER.md.tmpl)', 'tasks-*': 'gstack-tasks rows files (bin/gstack-tasks)', 'autoplan': 'autoplan phase artifacts (autoplan/SKILL.md.tmpl)', 'eval-bisect': '/investigate eval bisect cache', diff --git a/test/review-dispatch.test.ts b/test/review-dispatch.test.ts index 67a6ac34a..e2e9662da 100644 --- a/test/review-dispatch.test.ts +++ b/test/review-dispatch.test.ts @@ -843,16 +843,17 @@ describe('gstack-review-dispatch sent, collect, judge and verify: nothing change // later review voids it, or an output with no recorded file passes on its review field (fix-checks at 721539c, 56ed6e3 and 50dc73c: VERIFY: clean); why_new=the GST-482 count exemption trusted collect's // fields; seam=verify; no_claim=that a deleted output event is caught (#3719) test('an output event edited to look refused, or a refused one edited to look accepted, is dirty; a real wrong-tree reply is NOT_REVIEWED, then voided by a review', () => { - const head = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: ROOT, encoding: 'utf8', timeout: 30_000 }).stdout.trim(); + const wt = cleanCheckout(); + const head = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: wt, encoding: 'utf8', timeout: 30_000 }).stdout.trim(); const findings = '1. **CRITICAL**: auth.ts:3 leaks a token\nBlocks: yes\n\nRecommendation: request changes\n'; const voice = (reply: string) => { const out = tmp(); const ledger = path.join(out, 'review-ledger.jsonl'); const merged = path.join(out, 'merged.jsonl'); - const brief = field(run(['render', '--role', 'outside-voice', '--out', out, '--diff-base', head]).stdout, 'file'); - const send = () => run(['sent', '--ledger', ledger, '--role', 'outside-voice', '--sent', brief]); + const brief = field(run(['render', '--role', 'outside-voice', '--out', out, '--diff-base', head], wt).stdout, 'file'); + const send = () => run(['sent', '--ledger', ledger, '--role', 'outside-voice', '--sent', brief], wt); let n = 0; - const take = (text: string) => { const f = path.join(out, `ov${++n}.out`); fs.writeFileSync(f, text); return run(['collect', '--ledger', ledger, '--role', 'outside-voice', '--output', f, '--merged', merged]); }; + const take = (text: string) => { const f = path.join(out, `ov${++n}.out`); fs.writeFileSync(f, text); return run(['collect', '--ledger', ledger, '--role', 'outside-voice', '--output', f, '--merged', merged], wt); }; send(); const c = take(reply); const forge = (edit: Record) => { @@ -861,8 +862,8 @@ describe('gstack-review-dispatch sent, collect, judge and verify: nothing change }; const verify = () => { fs.writeFileSync(path.join(out, 'judged.jsonl'), ''); - expect(run(['judge', '--ledger', ledger, '--merged', merged, '--judged', path.join(out, 'judged.jsonl')]).status).toBe(0); - return run(['verify', '--ledger', ledger]); + expect(run(['judge', '--ledger', ledger, '--merged', merged, '--judged', path.join(out, 'judged.jsonl')], wt).status).toBe(0); + return run(['verify', '--ledger', ledger], wt); }; return { c, send, take, forge, verify }; };