wip(review): R65 review scales to risk (GSTA-258 build C): lean single reader, platform depth, risk_paths, HARN-1 false triggers

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-03 00:02:15 +00:00
1 parent 2e0e65d0e5
commit f6a7eba552
12 files changed
+466 -52

No files matched your search

+193
View File
@@ -0,0 +1,193 @@
import { describe, test, expect } from 'bun:test';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { classifyDiff, nextStep, planReview, scanNumbers, type PlanInput, type ReviewShape } from '../lib/review-depth';
import { matchRisk } from '../lib/review-risk';
import { renderBrief, sectionTexts } from '../lib/review-brief';
import { validatePolicy, DEFAULT_POLICY, REVIEW_POLICY_KEY_VERSION } from '../lib/ship-policy';
const ROOT = path.join(import.meta.dir, '..');
const none = scanNumbers({});
const HEAD = 'a'.repeat(40);
const lean = (o: Partial<ReviewShape> = {}): ReviewShape => ({ panel: 'risk', readerModel: 'lane', platform: 'off', head: HEAD, platformReview: null, ...o });
const base = (o: Partial<PlanInput>): PlanInput => ({ paths: ['src/app.ts'], scope: { SCOPE_BACKEND: 'true', SCOPE_STATE_MACHINE: 'false' }, gateTagged: 0, diffLines: 120, history: { fullPasses: 0, last: 'none' }, numbers: none, shape: lean(), ...o });
const roles = (p: ReturnType<typeof planReview>) => p.dispatches.map(d => `${d.role}:${d.name}:${d.effort}:${d.model ?? '-'}`);
describe('HARN-1 false triggers (harness-evals#231 on 1.93.7.0): data, config and stats scripts never raise the depth', () => {
const sqlite = 'docs/benchmarks/2026-11-01-installer-cc-codex/results/cc-none.smoke.ledger.sqlite';
test('committed sqlite ledgers git cannot count are data, not code, and never name money', () => {
const c = classifyDiff({ paths: [sqlite, 'README.md'], gateTagged: 0, perPath: [{ path: sqlite, lines: 0, binary: true }, { path: 'README.md', lines: 3, binary: false }], consumed: [] });
expect([c.class, c.errors.map(e => e.code), c.risk]).toEqual(['docs', [], []]);
});
test('a sqlite file is data even when a script names it', () => {
const c = classifyDiff({ paths: [sqlite, 'scripts/load.py'], gateTagged: 0, perPath: [{ path: sqlite, lines: 0, binary: true }, { path: 'scripts/load.py', lines: 4, binary: false }], consumed: [sqlite] });
expect([c.class, c.errors.map(e => e.code), c.runtimeLines]).toEqual(['code', [], 4]);
});
test('money on lease_usd lines of a JSON config a script reads is not a risk class; the config is judged by its path', () => {
const p = 'docs/benchmarks/x/results/cc-none.shard-vm.json';
expect(matchRisk({ codePaths: [p], added: { [p]: [' "lease_usd": 32.9,', ' "list_price_usd": 1.2485,'] }, scopeAuth: false }).size).toBe(0);
expect(matchRisk({ codePaths: ['config/billing.json'], added: { 'config/billing.json': ['{}'] }, scopeAuth: false }).has('money')).toBe(true);
expect(matchRisk({ codePaths: ['lib/lease.ts'], added: { 'lib/lease.ts': ['const lease_usd = 3;'] }, scopeAuth: false }).has('money')).toBe(true);
});
test('a stats script under a results directory is judged by its path: no security or money from its name or lines', () => {
const p = 'docs/benchmarks/2026-11-01-installer-cc-codex/results/cost-intervals.py';
expect(matchRisk({ codePaths: [p], added: { [p]: ["rows = [json.loads(l) for l in open(os.path.join(sys.argv[1], 'trials.jsonl'))]"] }, scopeAuth: false }).size).toBe(0);
expect(matchRisk({ codePaths: ['tools/fetch.py'], added: { 'tools/fetch.py': ['p = os.path.join(sys.argv[1], name)'] }, scopeAuth: false }).has('security')).toBe(true);
});
test('a secret in a config file still counts', () => {
expect(matchRisk({ codePaths: ['deploy/app.yaml'], added: { 'deploy/app.yaml': [' key: ${OPENAI_API_KEY}'] }, scopeAuth: false }).has('secret')).toBe(true);
});
});
describe('FOUN-64 item 4: docs that can print a credential are security risk (gbrain#8417)', () => {
const docsWith = (line: string) => classifyDiff({ paths: ['docs/mcp.md'], gateTagged: 0, added: { 'docs/mcp.md': [line] } });
test.each([['$ claude mcp get gbrain'], ['Authorization: Bearer abcdefgh12345678'], ['export OPENAI_API_KEY=sk-live-0123456789abcdefghij'], ['gh auth token']])('%s', l => expect(docsWith(l).risk).toEqual(['security']));
test('ordinary docs stay risk-free', () => expect(docsWith('Run gstack-review-plan --base main to see the plan.').risk).toEqual([]));
});
describe('FOUN-32 §4: eval scorers, judges and graders are risk class eval by path', () => {
test.each([['lib/eval-scorer.ts'], ['evals/judges/rubric.py'], ['scripts/grade-trials.ts']])('%s', p => expect(classifyDiff({ paths: [p], gateTagged: 0 }).risk).toContain('eval'));
test('a test helper named judge stays tests class, and an ordinary path is not eval', () => {
expect(classifyDiff({ paths: ['test/helpers/llm-judge.ts'], gateTagged: 0 }).risk).toEqual([]);
expect(classifyDiff({ paths: ['lib/review-pass.ts'], gateTagged: 0 }).risk).not.toContain('eval');
});
});
describe('risk_paths: a repo extends the risk classes from its base policy (FOUN-64)', () => {
const rp = ['src/balance/**', 'src/outcome*.ts'];
test('a matching code path is risk class policy; data and docs under the glob are not', () => {
expect(classifyDiff({ paths: ['src/balance/view.tsx'], gateTagged: 0, riskPaths: rp }).risk).toEqual(['policy']);
expect(classifyDiff({ paths: ['src/outcome-score.ts'], gateTagged: 0, riskPaths: rp }).risk).toEqual(['policy']);
expect(classifyDiff({ paths: ['src/balance/snap.sqlite', 'src/balance/notes.md'], gateTagged: 0, riskPaths: rp, consumed: [] }).risk).toEqual([]);
expect(classifyDiff({ paths: ['src/app.ts'], gateTagged: 0, riskPaths: rp }).risk).toEqual([]);
});
test('a policy risk path plans the merged reader at full depth', () => {
const p = planReview(base({ paths: ['src/balance/x.ts'], riskPaths: rp, shape: lean({ panel: 'off' }) }));
expect([p.depth, roles(p)]).toEqual(['full', ['adversarial-native:merged:full:lane']]);
expect(planReview(base({ paths: ['src/balance/x.ts'], riskPaths: rp })).mode).toBe('panel');
});
});
describe('R65 lean dispatch (GSTA-258 build C): one reviewer, once', () => {
test('non-risk code: one native reader at the lane\'s reasoning carrying the adversarial brief, the checklists and the Red Team', () => {
const p = planReview(base({}));
expect([p.mode, roles(p)]).toEqual(['lean', ['adversarial-native:single:full:lane']]);
expect(p.dispatches[0]!.checklists).toEqual(['testing', 'security', 'red-team']);
expect(p.skipped.join('\n')).toMatch(/outside-voice/);
});
test('non-risk code that publishes numbers keeps the native reader by default (FOUN-32 §3, ggstack#52); cross-family is a setting', () => {
const p = planReview(base({ paths: ['src/app.ts', 'docs/results.md'], numbers: scanNumbers({ 'docs/results.md': ['recall 87% (26/30)'] }) }));
expect(roles(p)).toEqual(['adversarial-native:single:full:lane']);
expect(roles(planReview(base({ shape: lean({ readerModel: 'cross-family' }) })))).toEqual(['adversarial-native:single:full:cross-family']);
});
test('default (panel risk, FOUN-64 item 1): a risk-class diff gets the printed full-depth panel; a fixed blocker re-runs the printed plan as round 2 (FOUN-32 §5)', () => {
const today = roles(planReview(base({ paths: ['lib/billing.ts'], targeted: { classes: ['money'] }, shape: undefined })));
const p = planReview(base({ paths: ['lib/billing.ts'], targeted: { classes: ['money'] } }));
expect([p.depth, p.mode, roles(p)]).toEqual(['full', 'panel', today]);
expect(today.length).toBeGreaterThan(1);
expect(planReview(base({ paths: ['lib/billing.ts'], history: { fullPasses: 1, last: 'full', fixedBlocking: true } })).next.step).toBe('full');
expect(planReview(base({ paths: ['lib/billing.ts'], history: { fullPasses: 2, last: 'full', fixedBlocking: true } })).next.step).toBe('stop');
expect(planReview(base({ history: { fullPasses: 1, last: 'full', fixedBlocking: true } })).next.step).toBe('fix-check');
});
test('panel off: risk class gets one reader on the configured model with the merged panel brief; it carries the targeted classes', () => {
const p = planReview(base({ paths: ['lib/billing.ts'], targeted: { classes: ['money'] }, shape: lean({ panel: 'off' }) }));
expect([p.depth, roles(p)]).toEqual(['full', ['adversarial-native:merged:full:lane']]);
expect(p.dispatches[0]!.classes).toEqual(['money']);
expect(p.dispatches[0]!.checklists).toContain('red-team');
const opus = planReview(base({ paths: ['.github/workflows/ci.yml'], shape: lean({ panel: 'off', readerModel: 'anthropic/claude-opus-5-5' }) }));
expect(roles(opus)).toEqual(['adversarial-native:merged:full:anthropic/claude-opus-5-5']);
});
test('docs and tests stay core only; docs with numbers keep the outside voice', () => {
expect(planReview(base({ paths: ['README.md'], gateTagged: null })).dispatches).toEqual([]);
expect(roles(planReview(base({ paths: ['docs/r.md'], numbers: scanNumbers({ 'docs/r.md': ['cost $4.10'] }) })))).toEqual(['outside-voice:outside-voice:host:-']);
});
test('panel all is today\'s panel; panel risk keeps it on risk class only', () => {
const today = (o: Partial<PlanInput>) => roles(planReview(base({ ...o, shape: undefined })));
expect(roles(planReview(base({ paths: ['lib/billing.ts'], shape: lean({ panel: 'all' }) })))).toEqual(today({ paths: ['lib/billing.ts'] }));
expect(roles(planReview(base({ paths: ['lib/billing.ts'], shape: lean({ panel: 'risk' }) })))).toEqual(today({ paths: ['lib/billing.ts'] }));
expect(planReview(base({ shape: lean({ panel: 'risk' }) })).mode).toBe('lean');
expect(planReview(base({ shape: lean({ panel: 'all' }) })).mode).toBe('panel');
});
});
describe('C6 platform depth (FOUN-32, founderstar#496): a planned skip needs the platform review at the exact head', () => {
const on = (review: ReviewShape['platformReview']) => lean({ platform: 'on', platformReview: review });
const docs = { paths: ['docs/howto-install.md', 'test/a.test.ts'] };
test('platform on with the review at HEAD on a docs or tests diff: no reader, a planned SKIP for every reader, the core read included', () => {
const p = planReview(base({ ...docs, shape: on({ id: '5744388738', head: HEAD, reviewer: 'capy-ai[bot]' }) }));
expect([p.mode, p.next.step, p.dispatches]).toEqual(['platform', 'platform', []]);
expect(p.skipped.filter(s => /planned skip/.test(s)).length).toBeGreaterThanOrEqual(2);
expect(p.skipped.join('\n')).toMatch(/core.*planned skip.*5744388738/);
});
test('without the evidence, or with it at another head, the core read stands', () => {
expect(planReview(base({ ...docs, shape: on(null) })).mode).toBe('lean');
expect(planReview(base({ ...docs, shape: on({ id: '1', head: 'b'.repeat(40), reviewer: 'capy-ai[bot]' }) })).next.step).toBe('full');
});
test('FOUN-64 item 2: runtime code, results or prereg paths never take the platform depth', () => {
const ev = { id: '1', head: HEAD, reviewer: 'capy-ai[bot]' };
expect(roles(planReview(base({ shape: on(ev) })))).toEqual(['adversarial-native:single:full:lane']);
expect(planReview(base({ paths: ['docs/benchmarks/run/results/summary.md'], shape: on(ev) })).mode).toBe('lean');
expect(planReview(base({ paths: ['evals/prereg.md'], shape: on(ev) })).mode).toBe('lean');
});
test('risk class and published numbers never take the platform depth', () => {
const ev = { id: '1', head: HEAD, reviewer: 'capy-ai[bot]' };
expect(planReview(base({ paths: ['lib/billing.ts'], shape: on(ev) })).mode).toBe('panel');
expect(planReview(base({ paths: ['src/app.ts', 'docs/r.md'], numbers: scanNumbers({ 'docs/r.md': ['p50 4.7 h'] }), shape: on(ev) })).mode).toBe('lean');
});
test('the platform skip is pass 1 only: a later step plans as lean', () => {
const p = planReview(base({ shape: on({ id: '1', head: HEAD, reviewer: 'capy-ai[bot]' }), history: { fullPasses: 1, last: 'full', fixedBlocking: true } }));
expect(p.next.step).toBe('fix-check');
});
});
describe('R65 lean loop: one fix round, never more than 2 rounds', () => {
const h = (o: object) => ({ fullPasses: 1, last: 'full' as const, lean: true, ...o });
test('non-risk: a fixed blocker earns one fix-check; below-floor fixes ship as notes', () => {
expect(nextStep(h({ fixedBlocking: true }), 'light').step).toBe('fix-check');
expect(nextStep(h({ fixedBelow: true }), 'light')).toMatchObject({ step: 'done', reason: expect.stringContaining('notes') });
});
test('risk: any fix earns one scoped fix-check, a gate-class edit included, never a second full pass', () => {
for (const o of [{ fixedBlocking: true }, { fixedBelow: true }, { fixedBelow: true, touchedGate: true }]) expect(nextStep(h(o), 'full').step).toBe('fix-check');
});
test('a fix-check blocker stops for the owner; a recorded grant adds one fix-check, never two', () => {
expect(nextStep(h({ last: 'fix-check', fixedBlocking: true, fixChecks: 1 }), 'full').step).toBe('stop');
expect(nextStep(h({ last: 'fix-check', fixedBlocking: true, fixChecks: 1, granted: 'apr_1' }), 'full').step).toBe('fix-check');
expect(nextStep(h({ last: 'fix-check', fixedBlocking: true, fixChecks: 2, granted: 'apr_1' }), 'full').step).toBe('stop');
});
test('planReview marks the loop lean and a fix-check dispatches one full-effort reader', () => {
expect(roles(planReview(base({ paths: ['lib/billing.ts'], history: { fullPasses: 1, last: 'full', fixedBlocking: true }, shape: lean({ panel: 'off' }) })))).toEqual(['fix-check:fix-check:full:-']);
});
});
describe('C7 merged reader brief and the outside voice reading its diff from disk', () => {
const t = sectionTexts(ROOT);
const sha = 'c'.repeat(40);
test('the merged reader renders the targeted brief and every checklist in one native adversarial context', () => {
const brief = fs.readFileSync(path.join(ROOT, 'review/specialists/targeted.md'), 'utf8');
const text = renderBrief('adversarial-native', { diff_base: sha, checklists: '/x/testing.md,/x/red-team.md', classes: 'money', brief, checklist: '/x/targeted.md' }, t);
expect(text).toContain(t.native.slice(0, 60));
expect(text).toContain('/x/testing.md, /x/red-team.md');
expect(text).toMatch(/money/);
});
test('the outside voice gets a path and a hash, not the pasted diff', () => {
const text = renderBrief('outside-voice', { diff_base: sha, diff_file: '/tmp/o/outside-voice.diff', diff_sha256: 'd'.repeat(64), diff_bytes: '1234' }, t);
expect(text).toContain('/tmp/o/outside-voice.diff');
expect(text).toContain('d'.repeat(64));
expect(text).not.toContain('```diff');
});
});
describe('ship policy: the base-read review key', () => {
const codes = (raw: object) => validatePolicy(raw).map(e => `${e.code}:${e.path}`);
test('defaults: panel risk, the lane\'s native reader, platform off, no extra risk paths', () => expect(DEFAULT_POLICY.review).toEqual({ panel: 'risk', reader_model: 'lane', platform: 'off', risk_paths: [] }));
test('valid values pass with min_gstack_version; bad ones name the field', () => {
const v = REVIEW_POLICY_KEY_VERSION;
expect(codes({ review: { platform: 'on', reader_model: 'anthropic/claude-opus-5-5', panel: 'risk', risk_paths: ['src/balance/**'] }, min_gstack_version: v })).toEqual([]);
expect(codes({ review: { platform: 'yes' }, min_gstack_version: v })).toEqual(['POLICY_INVALID:review.platform']);
expect(codes({ review: { panel: 'some' }, min_gstack_version: v })).toEqual(['POLICY_INVALID:review.panel']);
expect(codes({ review: { reader_model: 'a b' }, min_gstack_version: v })).toEqual(['POLICY_INVALID:review.reader_model']);
expect(codes({ review: { risk_paths: ['../x'] }, min_gstack_version: v })).toEqual(['POLICY_CONTAINMENT:review.risk_paths[0]']);
expect(codes({ review: { other: 1 }, min_gstack_version: v })).toEqual(['POLICY_INVALID:review.other']);
expect(codes({ review: { platform: 'on' } })).toContain('POLICY_INVALID:review');
});
});
+4 -3
View File
@@ -189,8 +189,8 @@ function planRepo(f: Fixture) {
*/
const FULL_PANEL = ['specialist', 'red-team', 'adversarial-native', 'outside-voice'];
const R51: Record<string, { depth: string; panel: boolean; dropped?: string[] }> = {
'none-light': { depth: 'light', panel: false }, 'none-standard': { depth: 'light', panel: false, dropped: ['outside-voice'] }, 'none-docs': { depth: 'light', panel: false },
'none-tests': { depth: 'light', panel: false }, 'none-costume': { depth: 'light', panel: false }, 'none-gate-path': { depth: 'full', panel: true },
'none-light': { depth: 'light', panel: false, dropped: ['specialist'] }, 'none-standard': { depth: 'light', panel: false, dropped: ['specialist', 'outside-voice'] }, 'none-docs': { depth: 'light', panel: false },
'none-tests': { depth: 'light', panel: false }, 'none-costume': { depth: 'light', panel: false, dropped: ['specialist'] }, 'none-gate-path': { depth: 'full', panel: true },
'secret-light': { depth: 'full', panel: true }, 'secret-path': { depth: 'full', panel: true }, 'secret-removed': { depth: 'full', panel: true }, 'gate-tagged': { depth: 'full', panel: true },
'money-light': { depth: 'full', panel: true }, 'money-path': { depth: 'full', panel: true }, 'money-removed': { depth: 'full', panel: true }, 'money-standard': { depth: 'full', panel: true },
'auth-path': { depth: 'full', panel: true }, 'money-fix-check': { depth: 'full', panel: false }, 'money-pass2': { depth: 'full', panel: false }, 'gate-repeat': { depth: 'full', panel: false },
@@ -204,7 +204,8 @@ describe('gstack-review-plan prints TARGETED and dispatches the targeted reader'
// with no class; seam=bin/gstack-review-plan end to end; no_claim=that the reader finds the defect (the paid replay's question)
// R51 changes the table: risk and gate fixtures plan full (every role main dispatched, plus the full panel), and the one
// non-risky standard fixture drops only the outside voice; fails_when=a risk fixture loses a role main dispatched or misses
// the full panel, or a non-risky fixture loses a role the R51 table does not list
// the full panel, or a non-risky fixture loses a role the R51 table does not list. R65 (GSTA-258 build C): a non-risky code
// fixture runs one native adversarial reader carrying the checklists and the Red Team, so its batched specialist drops too
test('the dispatch-superset no-loss check: risk and gate fixtures keep every role main dispatched plus the full panel; non-risky ones drop only what R51 lists', () => {
expect(Object.keys(MAIN).sort()).toEqual(Object.keys(FIXTURES).sort());
expect(Object.keys(R51).sort()).toEqual(Object.keys(FIXTURES).sort());