test: derive paid touchfiles from each eval's static closure (E)

touchfiles.test.ts now checks, per key, that the paid file's static
test/helpers and test/fixtures closure (plus fixture paths it names in string
literals) is covered, and names the file, path, chain and key to fix when it is
not. Free *.test.ts files are no longer touchfiles, so editing a free replay
test stops selecting paid evals: 950 entries removed, 653 real closure paths
added. The hand-copied inventories go: periodic-fixture-selection,
fake-impeccable-touchfiles and 45 per-file selection examples. Selection for
the sample edits (plan-eng-review template, claude-pty-runner,
plan-count-fixture, gstack-config) loses no case under either profile.
CONTRIBUTING documents the rule and its lower bound.
This commit is contained in:
garrytan committed 2026-09-29 07:00:28 +00:00
1 parent 689ef3094b
commit 7cbb5e04e4
53 files changed
+627 -1873

No files matched your search

+10
View File
@@ -393,6 +393,16 @@ Each dimension is scored 1-5. Threshold: every dimension must score **≥ 4**. T
- Tests live in `test/skill-llm-eval.test.ts` - Tests live in `test/skill-llm-eval.test.ts`
- Calls the Anthropic API directly (not `claude -p`), so it works from anywhere including inside Claude Code - Calls the Anthropic API directly (not `claude -p`), so it works from anywhere including inside Claude Code
### Paid-test touchfiles
`test/helpers/touchfiles-data.ts` maps each paid case to the files whose edits select it. Free
`*.test.ts` files are never listed: editing a free test does not run paid evals. `test/touchfiles.test.ts`
derives each paid file's static `test/helpers` / `test/fixtures` import closure, plus the fixture and helper
paths it names in string literals, and fails when that closure is not covered by the case's key. When it
fails, add the named path to the named key and check selection with
`bun run scripts/test-paid-shards.ts --tier gate --profile pr --list`. The rule is a lower bound: a fixture
path the test builds at runtime is not visible to it, so add such paths to the key by hand.
### CI ### CI
A GitHub Action (`.github/workflows/skill-docs.yml`) generates all hosts on pushes to main and on PRs, then rejects tracked differences and nonignored untracked output. Generation errors also fail the job. Optional ignored host caches are not compared against Git. A GitHub Action (`.github/workflows/skill-docs.yml`) generates all hosts on pushes to main and on PRs, then rejects tracked differences and nonignored untracked output. Generation errors also fail the job. Optional ignored host caches are not compared against Git.
-9
View File
@@ -6,8 +6,6 @@ import { spawnSync } from 'node:child_process';
import { createAutoplanArtifactRecorder, recordAutoplanArtifact, readPendingAutoplanArtifact, import { createAutoplanArtifactRecorder, recordAutoplanArtifact, readPendingAutoplanArtifact,
autoplanArtifactRecorderStatus, autoplanArtifactApprovalBoundary } from './helpers/autoplan-artifact-recorder'; autoplanArtifactRecorderStatus, autoplanArtifactApprovalBoundary } from './helpers/autoplan-artifact-recorder';
import type { NativePublicToolEvent } from './helpers/plan-count-transcript'; import type { NativePublicToolEvent } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
// Synthetic hook envelopes and owned temp paths. The live pending hook envelope // Synthetic hook envelopes and owned temp paths. The live pending hook envelope
// was unpublished; these controls do not reconstruct it or provide paid coverage. // was unpublished; these controls do not reconstruct it or provide paid coverage.
function fixture(approveEdits=false) { function fixture(approveEdits=false) {
@@ -164,13 +162,6 @@ describe('owned Autoplan pending artifact metadata recorder',()=>{
expect(f.status()).toEqual({status:'invalid',reason:'stdin_timeout'}); expect(f.status()).toEqual({status:'invalid',reason:'stdin_timeout'});
}finally{clearTimeout(timer);child.stdin.end();if(child.exitCode===null){child.kill('SIGKILL');await child.exited}f.dispose()} }finally{clearTimeout(timer);child.stdin.end();if(child.exitCode===null){child.kill('SIGKILL');await child.exited}f.dispose()}
},7000); },7000);
test('recorder disposal removes owned state and shared recorder inputs select both paid owners',()=>{
const f=fixture();f.write(f.event());f.dispose();expect(fs.existsSync(f.recorder.file)).toBe(false);
for(const file of ['test/helpers/autoplan-artifact-recorder.ts','test/autoplan-artifact-recorder.test.ts'])
expect(selectTests([file],E2E_TOUCHFILES,[]).selected.sort()).toEqual([]);
for(const file of ['test/autoplan-pending-artifact.test.ts','test/fixtures/autoplan-pending-artifact-ae.json'])
expect(selectTests([file],E2E_TOUCHFILES,[]).selected).toEqual([]);
});
}); });
// Real hook subprocesses and the public JSONL reader; no synthetic phase success // Real hook subprocesses and the public JSONL reader; no synthetic phase success
-6
View File
@@ -1,6 +0,0 @@
import {test,expect,afterEach} from 'bun:test';
import {E2E_TOUCHFILES} from './helpers/touchfiles-data';
const cleanup:Array<()=>void>=[];afterEach(()=>{for(const f of cleanup.splice(0))f()});
test('new regression files register only the actual Autoplan owner',()=>{
for(const p of ['test/autoplan-clipped-suffix-aq.test.ts','test/fixtures/autoplan-clipped-suffix-aq.json'])expect(Object.entries(E2E_TOUCHFILES).filter(([,files])=>files.includes(p)).map(([owner])=>owner)).toEqual([]);
});
-4
View File
@@ -4,7 +4,6 @@ import fixture from './fixtures/autoplan-edit-digests-al.json';
import {createAutoplanArtifactRecorder,recordAutoplanArtifact,readPendingAutoplanArtifact,autoplanArtifactRecorderStatus} from './helpers/autoplan-artifact-recorder'; import {createAutoplanArtifactRecorder,recordAutoplanArtifact,readPendingAutoplanArtifact,autoplanArtifactRecorderStatus} from './helpers/autoplan-artifact-recorder';
import {createAutoplanEditDigest,validAutoplanEditDigest} from './helpers/autoplan-artifact-digest'; import {createAutoplanEditDigest,validAutoplanEditDigest} from './helpers/autoplan-artifact-digest';
import type {NativePublicToolEvent} from './helpers/plan-count-transcript'; import type {NativePublicToolEvent} from './helpers/plan-count-transcript';
import {E2E_TOUCHFILES,selectTests} from './helpers/touchfiles';
const cleanups:Array<()=>void>=[];afterEach(()=>{for(const cleanup of cleanups.splice(0))cleanup()}); const cleanups:Array<()=>void>=[];afterEach(()=>{for(const cleanup of cleanups.splice(0))cleanup()});
function replay(record=true) { function replay(record=true) {
const root=fs.mkdtempSync(path.join(os.tmpdir(),'ap-digest-')),cwd=path.join(root,path.basename(fixture.cwd)),ownedStateRoot=path.join(root,'home','.gstack'),config=path.join(root,'config'); const root=fs.mkdtempSync(path.join(os.tmpdir(),'ap-digest-')),cwd=path.join(root,path.basename(fixture.cwd)),ownedStateRoot=path.join(root,'home','.gstack'),config=path.join(root,'config');
@@ -37,9 +36,6 @@ test('unavailable or oversized before/request data yields no new digest authorit
const link=path.join(r.root,'linked');fs.symlinkSync(r.file,link);expect(createAutoplanEditDigest(link,r.event.tool_input.old_string,r.event.tool_input.new_string)).toBeUndefined(); const link=path.join(r.root,'linked');fs.symlinkSync(r.file,link);expect(createAutoplanEditDigest(link,r.event.tool_input.old_string,r.event.tool_input.new_string)).toBeUndefined();
fs.writeFileSync(r.file,'x'.repeat(1024*1024+1));expect(createAutoplanEditDigest(r.file,'x','new')).toBeUndefined();fs.unlinkSync(r.file);expect(createAutoplanEditDigest(r.file,'old','new')).toBeUndefined(); fs.writeFileSync(r.file,'x'.repeat(1024*1024+1));expect(createAutoplanEditDigest(r.file,'x','new')).toBeUndefined();fs.unlinkSync(r.file);expect(createAutoplanEditDigest(r.file,'old','new')).toBeUndefined();
}); });
test('Eng and Autoplan share the digest helper and regression evidence',()=>{
for(const file of ['test/helpers/autoplan-artifact-digest.ts','test/autoplan-edit-digests-al.test.ts','test/fixtures/autoplan-edit-digests-al.json'])expect(selectTests([file],E2E_TOUCHFILES,[]).selected.sort()).toEqual([]);
});
test('identical pending hook replay cannot refresh digest or timestamp',()=>{ test('identical pending hook replay cannot refresh digest or timestamp',()=>{
const r=replay(),before=fs.readFileSync(r.recorder.file,'utf8');recordAutoplanArtifact(JSON.stringify(r.event),r.recorder.file,r.context.cwd,r.config,r.context.ownedStateRoot);expect(fs.readFileSync(r.recorder.file,'utf8')).toBe(before); const r=replay(),before=fs.readFileSync(r.recorder.file,'utf8');recordAutoplanArtifact(JSON.stringify(r.event),r.recorder.file,r.context.cwd,r.config,r.context.ownedStateRoot);expect(fs.readFileSync(r.recorder.file,'utf8')).toBe(before);
}); });
-8
View File
@@ -5,7 +5,6 @@ import * as path from 'node:path';
import { spawnSync } from 'node:child_process'; import { spawnSync } from 'node:child_process';
import { createPendingQuestionRecorder, readPendingQuestion, recordPendingQuestion } from './helpers/plan-count-pending-question'; import { createPendingQuestionRecorder, readPendingQuestion, recordPendingQuestion } from './helpers/plan-count-pending-question';
import { readPlanCountTranscript } from './helpers/plan-count-transcript'; import { readPlanCountTranscript } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import captured from './fixtures/autoplan-routing-manual-skills-ac.json'; import captured from './fixtures/autoplan-routing-manual-skills-ac.json';
// Exact retained public question; hook envelopes and owned temp paths are // Exact retained public question; hook envelopes and owned temp paths are
@@ -208,13 +207,6 @@ describe('opt-in pending native AskUserQuestion capture', () => {
} }
} finally { f.dispose(); } } finally { f.dispose(); }
}); });
test('the helper and new free test select only the two opted-in workflows', () => {
for (const file of ['test/helpers/plan-count-pending-question.ts', 'test/autoplan-pending-question.test.ts']) {
expect(selectTests([file], E2E_TOUCHFILES, []).selected.sort()).toEqual(['plan-ceo-mode-routing']);
}
});
test('a hook whose input never ends closes within its own bound and remains silent', async () => { test('a hook whose input never ends closes within its own bound and remains silent', async () => {
const f = fixture(); const f = fixture();
const hook = f.recorder.hooks.PreToolUse[0]!.hooks[0]!; const hook = f.recorder.hooks.PreToolUse[0]!.hooks[0]!;
-8
View File
@@ -5,7 +5,6 @@ import * as path from 'node:path';
import { pathToFileURL } from 'node:url'; import { pathToFileURL } from 'node:url';
import { autoplanPhaseCompletions } from './helpers/autoplan-phase-observer'; import { autoplanPhaseCompletions } from './helpers/autoplan-phase-observer';
import type { PlanCountTranscript } from './helpers/plan-count-transcript'; import type { PlanCountTranscript } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import fixture_autoplan_phase_dash_ao from './fixtures/autoplan-phase-dash-ao.json'; import fixture_autoplan_phase_dash_ao from './fixtures/autoplan-phase-dash-ao.json';
import actual_autoplan_with_result_au from './fixtures/autoplan-with-result-au.json'; import actual_autoplan_with_result_au from './fixtures/autoplan-with-result-au.json';
@@ -204,13 +203,6 @@ describe('native autoplan phase observation', () => {
.toEqual([{ phase: 3, ts: START + 1 }, { phase: 1, ts: START + 2 }]); .toEqual([{ phase: 3, ts: START + 1 }, { phase: 1, ts: START + 2 }]);
expect(autoplanPhaseCompletions(transcript([1, 'Phase 2 skipped — no UI scope.']), START)).toEqual([]); expect(autoplanPhaseCompletions(transcript([1, 'Phase 2 skipped — no UI scope.']), START)).toEqual([]);
}); });
test('phase observer changes select the autoplan eval', () => {
for (const file of ['test/helpers/autoplan-phase-observer.ts', 'test/autoplan-phase-observer.test.ts']) {
expect(selectTests([file], E2E_TOUCHFILES).selected).toEqual([]);
}
});
test.skipIf(process.platform === 'win32')('ANSI-rendered completions use native evidence while displayed Read/source markers do not', async () => { test.skipIf(process.platform === 'win32')('ANSI-rendered completions use native evidence while displayed Read/source markers do not', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'autoplan-phase-replay-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'autoplan-phase-replay-'));
const fake = path.join(dir, 'fake-claude'); const fake = path.join(dir, 'fake-claude');
-16
View File
@@ -5,8 +5,6 @@ import path from 'node:path';
import {readPlanCountTranscript,type NativePublicToolEvent} from './helpers/plan-count-transcript'; import {readPlanCountTranscript,type NativePublicToolEvent} from './helpers/plan-count-transcript';
import {autoplanPhaseCompletions} from './helpers/autoplan-phase-observer'; import {autoplanPhaseCompletions} from './helpers/autoplan-phase-observer';
import fixture from './fixtures/autoplan-public-narration-ad.json'; import fixture from './fixtures/autoplan-public-narration-ad.json';
import {E2E_TOUCHFILES,selectTests} from './helpers/touchfiles';
const at=Date.parse(fixture.provenance.timestamp); const at=Date.parse(fixture.provenance.timestamp);
function read(blocks: unknown[]= [fixture.block],delta: any={},complete=true) { function read(blocks: unknown[]= [fixture.block],delta: any={},complete=true) {
const dir=fs.mkdtempSync(path.join(os.tmpdir(),'public-narration-')),cwd=path.join(dir,'repo'); const dir=fs.mkdtempSync(path.join(os.tmpdir(),'public-narration-')),cwd=path.join(dir,'repo');
@@ -124,17 +122,3 @@ test('phase ordering and duplicate collapse use native time rather than polling
{sessionId:'parent',timestamp:new Date(at+30).toISOString(),text:'Phase 1 is done.'}]}; {sessionId:'parent',timestamp:new Date(at+30).toISOString(),text:'Phase 1 is done.'}]};
expect(autoplanPhaseCompletions(t,at)).toEqual([{phase:1,ts:at+10},{phase:2,ts:at+20}]); expect(autoplanPhaseCompletions(t,at)).toEqual([{phase:1,ts:at+10},{phase:2,ts:at+20}]);
}); });
test('public narration changes select every existing shared native-reader consumer',()=>{
const expected=[
'auto-decide-preserved',
'plan-ceo-mode-routing','plan-ceo-split-overflow',
'plan-design-review-plan-mode','plan-design-with-ui-scope',
'plan-eng-multi-finding-batching',
'plan-eng-review-plan-mode',
].sort();
const reader=selectTests(['test/helpers/plan-count-transcript.ts'],E2E_TOUCHFILES).selected.sort();
expect(reader).toEqual(expected);
for(const file of ['test/autoplan-public-narration.test.ts','test/fixtures/autoplan-public-narration-ad.json'])
expect(selectTests([file],E2E_TOUCHFILES).selected.sort()).toEqual(reader);
});
-1
View File
@@ -193,7 +193,6 @@ describe('autoplan reads installed host methodology', () => {
test('the new discovery contract selects the affected live autoplan workflows', () => { test('the new discovery contract selects the affected live autoplan workflows', () => {
for (const name of ['autoplan-dual-voice', 'carve-section-loading']) { for (const name of ['autoplan-dual-voice', 'carve-section-loading']) {
expect(E2E_TOUCHFILES[name]).toContain('test/autoplan-review-discovery.test.ts');
expect(E2E_TOUCHFILES[name]).toContain('scripts/resolvers/composition.ts'); expect(E2E_TOUCHFILES[name]).toContain('scripts/resolvers/composition.ts');
} }
}); });
-1
View File
@@ -503,7 +503,6 @@ describe('installed snapshot helper in fresh shells', () => {
test('all affected live workflow selectors include the executable continuity contract', () => { test('all affected live workflow selectors include the executable continuity contract', () => {
for (const name of ['autoplan-dual-voice', 'carve-section-loading']) { for (const name of ['autoplan-dual-voice', 'carve-section-loading']) {
expect(E2E_TOUCHFILES[name]).toContain('bin/gstack-autoplan-snapshot.ts'); expect(E2E_TOUCHFILES[name]).toContain('bin/gstack-autoplan-snapshot.ts');
expect(E2E_TOUCHFILES[name]).toContain('test/autoplan-snapshot.test.ts');
} }
}); });
}); });
-7
View File
@@ -1,7 +1,6 @@
import { describe, expect, test } from 'bun:test'; import { describe, expect, test } from 'bun:test';
import { hasNativePostAnswerCeoPosture, nextCeoPostureContinuation } from './helpers/ceo-mode-option'; import { hasNativePostAnswerCeoPosture, nextCeoPostureContinuation } from './helpers/ceo-mode-option';
import type { PlanCountTranscript } from './helpers/plan-count-transcript'; import type { PlanCountTranscript } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import captured from './fixtures/ceo-barless-submit-ac.json'; import captured from './fixtures/ceo-barless-submit-ac.json';
const selectedAt = Date.parse(captured.provenance.modeRequestAt); const selectedAt = Date.parse(captured.provenance.modeRequestAt);
@@ -118,10 +117,4 @@ describe('bounded CEO barless packet submission', () => {
text: 'HOLD SCOPE: keep the saved-view feature fixed and make its failure handling rigorous.' }); text: 'HOLD SCOPE: keep the saved-view feature fixed and make its failure handling rigorous.' });
expect(hasNativePostAnswerCeoPosture(p.t, 'HOLD SCOPE', /hold\s*scope/i, selectedAt)).toBe(true); expect(hasNativePostAnswerCeoPosture(p.t, 'HOLD SCOPE', /hold\s*scope/i, selectedAt)).toBe(true);
}); });
test('the free test and fixture select only the mode-routing workflow', () => {
for (const file of ['test/ceo-barless-submit.test.ts', 'test/fixtures/ceo-barless-submit-ac.json']) {
expect(selectTests([file], E2E_TOUCHFILES, []).selected).toEqual(['plan-ceo-mode-routing']);
}
});
}); });
-7
View File
@@ -5,7 +5,6 @@ import * as path from 'node:path';
import { findCeoModeOption, hasNativePostAnswerCeoPosture } from './helpers/ceo-mode-option'; import { findCeoModeOption, hasNativePostAnswerCeoPosture } from './helpers/ceo-mode-option';
import { parseNumberedOptions } from './helpers/claude-pty-runner'; import { parseNumberedOptions } from './helpers/claude-pty-runner';
import { readPlanCountTranscript, type NativePublicToolEvent } from './helpers/plan-count-transcript'; import { readPlanCountTranscript, type NativePublicToolEvent } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import captured from './fixtures/ceo-expansion-auq-ac.json'; import captured from './fixtures/ceo-expansion-auq-ac.json';
const posture = /\b(expansion|10x|delight|dream|cathedral|opt[\s-]?in)\b/i; const posture = /\b(expansion|10x|delight|dream|cathedral|opt[\s-]?in)\b/i;
@@ -118,10 +117,4 @@ describe('CEO expansion posture in a completed native decision brief', () => {
(records: Records) => { records[6]!.message.content[0]!.is_error = true; }, (records: Records) => { records[6]!.message.content[0]!.is_error = true; },
]) expect(matches(replay(change))).toBe(false); ]) expect(matches(replay(change))).toBe(false);
}); });
test('the new free test and captured fixture select the paid mode-routing case', () => {
for (const file of ['test/ceo-expansion-auq.test.ts', 'test/fixtures/ceo-expansion-auq-ac.json']) {
expect(selectTests([file], E2E_TOUCHFILES, []).selected).toEqual(['plan-ceo-mode-routing']);
}
});
}); });
-10
View File
@@ -1,7 +1,6 @@
import { describe, expect, test } from 'bun:test'; import { describe, expect, test } from 'bun:test';
import { findCeoModeOption, hasPostAnswerCeoPosture, hasNativePostAnswerCeoPosture, nativeCeoModeAnswer, nextCeoModeNavigation, nextCeoPostureContinuation } from './helpers/ceo-mode-option'; import { findCeoModeOption, hasPostAnswerCeoPosture, hasNativePostAnswerCeoPosture, nativeCeoModeAnswer, nextCeoModeNavigation, nextCeoPostureContinuation } from './helpers/ceo-mode-option';
import { parseNumberedOptions, stripAnsi, planCountQuestionInput, nativePlanCallFingerprint } from './helpers/claude-pty-runner'; import { parseNumberedOptions, stripAnsi, planCountQuestionInput, nativePlanCallFingerprint } from './helpers/claude-pty-runner';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import type { PlanCountTranscript } from './helpers/plan-count-transcript'; import type { PlanCountTranscript } from './helpers/plan-count-transcript';
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
@@ -90,15 +89,6 @@ describe('CEO mode option matching', () => {
{ index: 2, label: 'Choose a plan │ SCOPE EXPANSION' }, { index: 2, label: 'Choose a plan │ SCOPE EXPANSION' },
], 'HOLD SCOPE')).toBeNull(); ], 'HOLD SCOPE')).toBeNull();
}); });
test('the shared parser selects all callers while mode-specific regressions stay scoped', () => {
expect(selectTests(['test/helpers/ceo-mode-option.ts'], E2E_TOUCHFILES).selected)
.toEqual(['plan-ceo-mode-routing', 'plan-ceo-split-overflow']);
expect(selectTests(['test/ceo-mode-option.test.ts'], E2E_TOUCHFILES).selected)
.toEqual(['plan-ceo-mode-routing', 'plan-ceo-split-overflow']);
expect(selectTests(['test/pty-option-selection.test.ts'], E2E_TOUCHFILES).selected)
.toEqual(['plan-ceo-mode-routing']);
});
}); });
describe('CEO mode navigation replay', () => { describe('CEO mode navigation replay', () => {
-4
View File
@@ -4,7 +4,6 @@ import os from 'node:os';
import path from 'node:path'; import path from 'node:path';
import {spawnSync} from 'node:child_process'; import {spawnSync} from 'node:child_process';
import {getQuestion} from '../scripts/question-registry'; import {getQuestion} from '../scripts/question-registry';
import {E2E_TOUCHFILES} from './helpers/touchfiles-data';
import {CARVE_GUARDS} from './helpers/carve-guards'; import {CARVE_GUARDS} from './helpers/carve-guards';
const root=path.resolve(import.meta.dir,'..'); const root=path.resolve(import.meta.dir,'..');
const temp=fs.mkdtempSync(path.join(os.tmpdir(),'gstack-ceo-mode-preference-')); const temp=fs.mkdtempSync(path.join(os.tmpdir(),'gstack-ceo-mode-preference-'));
@@ -126,9 +125,6 @@ test('only an explicit user selection or enabled successful mode check bypasses
expect(document).toContain('Note: options differ in kind, not coverage — no completeness score.'); expect(document).toContain('Note: options differ in kind, not coverage — no completeness score.');
} }
}); });
test('the new render/runtime regression belongs to the existing auto-decide owner',()=>{
expect(Object.entries(E2E_TOUCHFILES).filter(([,v])=>v.includes('test/ceo-mode-preference-al.test.ts')).map(([k])=>k)).toEqual(['auto-decide-preserved']);
});
test('rendered mode contract stays within the existing canonical skeleton cap',()=>{ test('rendered mode contract stays within the existing canonical skeleton cap',()=>{
// --out-dir changes section-link roots only. Undo that output-location // --out-dir changes section-link roots only. Undo that output-location
// substitution before measuring the same canonical bytes as parity-suite. // substitution before measuring the same canonical bytes as parity-suite.
-4
View File
@@ -7,7 +7,6 @@ import { execFileSync } from 'node:child_process';
import { nextCeoModeNavigation } from './helpers/ceo-mode-option'; import { nextCeoModeNavigation } from './helpers/ceo-mode-option';
import { planCountQuestionInput } from './helpers/claude-pty-runner'; import { planCountQuestionInput } from './helpers/claude-pty-runner';
import type { NativePlanQuestionCall } from './helpers/plan-count-transcript'; import type { NativePlanQuestionCall } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import priorCalls from './fixtures/ceo-mode-prerequisite-o-calls.json'; import priorCalls from './fixtures/ceo-mode-prerequisite-o-calls.json';
import directProceedCall from './fixtures/ceo-mode-prerequisite-q-call.json'; import directProceedCall from './fixtures/ceo-mode-prerequisite-q-call.json';
import fullAd from './fixtures/ceo-mode-full-ad.json'; import fullAd from './fixtures/ceo-mode-full-ad.json';
@@ -88,9 +87,6 @@ describe('CEO mode prerequisite navigation', () => {
const modes='☐ Review mode\nWhich mode?\n❯ 1. SELECTIVE EXPANSION\n 2. HOLD SCOPE\n 3. SCOPE EXPANSION\n 4. SCOPE REDUCTION'; const modes='☐ Review mode\nWhich mode?\n❯ 1. SELECTIVE EXPANSION\n 2. HOLD SCOPE\n 3. SCOPE EXPANSION\n 4. SCOPE REDUCTION';
for(const [mode,index] of [['HOLD SCOPE',2],['SCOPE EXPANSION',3]] as const){const a=nextCeoModeNavigation(modes,mode,new Set());expect(a.kind).toBe('mode');if(a.kind==='mode')expect(a.index).toBe(index);} for(const [mode,index] of [['HOLD SCOPE',2],['SCOPE EXPANSION',3]] as const){const a=nextCeoModeNavigation(modes,mode,new Set());expect(a.kind).toBe('mode');if(a.kind==='mode')expect(a.index).toBe(index);}
}); });
test('fixture and free regression select only the mode-routing eval', () => {
for(const file of ['test/ceo-mode-prerequisite.test.ts','test/fixtures/ceo-mode-prerequisite-o-calls.json','test/fixtures/ceo-mode-prerequisite-q-call.json'])expect(selectTests([file],E2E_TOUCHFILES).selected).toEqual(['plan-ceo-mode-routing']);
});
}); });
for(const fixtureIndex of [1,2,3,4])test.skipIf(process.platform==='win32')(`fake native PTY skips prerequisite ${fixtureIndex} and confirms target posture`,async()=>{ for(const fixtureIndex of [1,2,3,4])test.skipIf(process.platform==='win32')(`fake native PTY skips prerequisite ${fixtureIndex} and confirms target posture`,async()=>{
const dir=fs.mkdtempSync(path.join(os.tmpdir(),'ceo-mode-prerequisite-')),fake=path.join(dir,'fake-claude'),events=path.join(dir,'events.jsonl'),worker=path.join(dir,'worker.ts'); const dir=fs.mkdtempSync(path.join(os.tmpdir(),'ceo-mode-prerequisite-')),fake=path.join(dir,'fake-claude'),events=path.join(dir,'events.jsonl'),worker=path.join(dir,'worker.ts');
-26
View File
@@ -1,26 +0,0 @@
import { describe, expect, test } from 'bun:test';
import { E2E_TIERS, E2E_TOUCHFILES, GLOBAL_TOUCHFILES, selectTests } from './helpers/touchfiles';
function selectedBy(file: string) {
return selectTests([file], E2E_TOUCHFILES, GLOBAL_TOUCHFILES).selected;
}
describe('Codex eval selection', () => {
test('recording-helper changes select every recorded Codex case in the periodic tier', () => {
const selected = selectedBy('test/helpers/codex-eval.ts');
expect(selected.sort()).toEqual([
'codex-discover-skill',
'codex-review-findings',
'codex-sol-scope-termination',
].sort());
expect(selected.every((id) => E2E_TIERS[id] === 'periodic')).toBe(true);
});
test('Sol fixture generation changes select its periodic case', () => {
for (const file of ['test/helpers/sol-skill-fixture.ts', 'test/sol-skill-fixture.test.ts']) {
expect(selectedBy(file)).toEqual(['codex-sol-scope-termination']);
}
expect(E2E_TIERS['codex-sol-scope-termination']).toBe('periodic');
});
});
+5 -3
View File
@@ -253,12 +253,14 @@ describe('cookie workflow judge input', () => {
}); });
test('each owned dependency selects this judge in the fast PR profile', () => { test('each owned dependency selects this judge in the fast PR profile', () => {
for (const file of ['setup-browser-cookies/SKILL.md.tmpl', 'setup-browser-cookies/SKILL.md', 'BROWSER.md', 'test/helpers/cookie-workflow-judge-input.ts', 'test/cookie-workflow-judge-input.test.ts', 'test/helpers/cookie-workflow-manual-review.ts', 'test/cookie-workflow-manual-review.test.ts', 'test/helpers/manual-judge-review-fixture.ts', '.github/cookie-workflow-manual-review.json']) { for (const file of ['setup-browser-cookies/SKILL.md.tmpl', 'setup-browser-cookies/SKILL.md', 'BROWSER.md', 'test/helpers/cookie-workflow-judge-input.ts', 'test/helpers/cookie-workflow-manual-review.ts', 'test/helpers/manual-judge-review-fixture.ts', '.github/cookie-workflow-manual-review.json']) {
const selectedJudges = selectTests([file], LLM_JUDGE_TOUCHFILES).selected; const selectedJudges = selectTests([file], LLM_JUDGE_TOUCHFILES).selected;
expect(selectedJudges).toEqual([NAME]); // Helpers the judge file imports select every judge that file registers (derived closure).
const exact = !file.startsWith('test/helpers/') || file === 'test/helpers/manual-judge-review-fixture.ts';
if (exact) expect(selectedJudges).toEqual([NAME]); else expect(selectedJudges).toContain(NAME);
const selectedE2E = selectTests([file], E2E_TOUCHFILES).selected; const selectedE2E = selectTests([file], E2E_TOUCHFILES).selected;
const profile = selectPrProfile({ changedFiles: [file], selectedJudges, selectedE2E }); const profile = selectPrProfile({ changedFiles: [file], selectedJudges, selectedE2E });
expect(profile.judges).toEqual([NAME]); if (exact) expect(profile.judges).toEqual([NAME]); else expect(profile.judges).toContain(NAME);
expect(profile.deferredPromptFiles).toEqual([]); expect(profile.deferredPromptFiles).toEqual([]);
expect(profile.missingCoverage).toEqual([]); expect(profile.missingCoverage).toEqual([]);
expect(profile.needsFullValidation).toBe(false); expect(profile.needsFullValidation).toBe(false);
-8
View File
@@ -4,8 +4,6 @@ import fixture from './fixtures/coverage-audit-ae.json';
import ciDiagrams from './fixtures/coverage-audit-ci-diagrams.json'; import ciDiagrams from './fixtures/coverage-audit-ci-diagrams.json';
import { coverageAuditVerdict } from './helpers/coverage-audit-evidence'; import { coverageAuditVerdict } from './helpers/coverage-audit-evidence';
import { recordE2E } from './helpers/e2e-helpers'; import { recordE2E } from './helpers/e2e-helpers';
import { E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES, GLOBAL_TOUCHFILES } from './helpers/touchfiles';
import { selectTests } from './helpers/test-selection';
import fixture_coverage_audit_af from './fixtures/coverage-audit-af.json'; import fixture_coverage_audit_af from './fixtures/coverage-audit-af.json';
import { posix } from 'node:path'; import { posix } from 'node:path';
import { win32 } from 'node:path'; import { win32 } from 'node:path';
@@ -450,12 +448,6 @@ Guard clauses tested: 0 / 4
expect(entries).toHaveLength(1);expect(entries[0].passed).toBe(valid);expect(entries[0].error).toBe(valid?undefined:v.failures.join('; ')); expect(entries).toHaveLength(1);expect(entries[0].passed).toBe(valid);expect(entries[0].error).toBe(valid?undefined:v.failures.join('; '));
} }
}); });
test('coverage evidence files select their exact registered consumers',()=>{
for(const file of ['test/helpers/coverage-audit-evidence.ts','test/coverage-audit-evidence.test.ts','test/fixtures/coverage-audit-ae.json','test/fixtures/coverage-audit-ci-diagrams.json']){
expect(selectTests([file],E2E_TOUCHFILES,GLOBAL_TOUCHFILES).selected.sort()).toEqual(file === 'test/helpers/coverage-audit-evidence.ts' || file === 'test/coverage-audit-evidence.test.ts' ? ['plan-eng-coverage-audit','review-coverage-audit','ship-coverage-audit'] : ['plan-eng-coverage-audit','review-coverage-audit']);
expect(selectTests([file],LLM_JUDGE_TOUCHFILES,GLOBAL_TOUCHFILES).selected).toEqual([]);
}
});
}); });
describe('coverage-audit-af', () => { describe('coverage-audit-af', () => {
-8
View File
@@ -1,8 +1,6 @@
import { expect, test } from 'bun:test'; import { expect, test } from 'bun:test';
import { readFileSync } from 'node:fs'; import { readFileSync } from 'node:fs';
import { extractDesignResearchContract } from './helpers/skill-fixture'; import { extractDesignResearchContract } from './helpers/skill-fixture';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
const source = readFileSync(new URL('../design-consultation/SKILL.md', import.meta.url), 'utf8'); const source = readFileSync(new URL('../design-consultation/SKILL.md', import.meta.url), 'utf8');
test('research-only fixture supplies actual readiness and egress dependencies without expanding scope', () => { test('research-only fixture supplies actual readiness and egress dependencies without expanding scope', () => {
@@ -23,9 +21,3 @@ test.each(['## BROWSER SETUP', '### Rules for driving a real browser', '## Web r
'## Phase 2: Research', '**Step 1: Identify', '**Step 2: Visual research', '_aside_exec()'])('missing %s fails closed before a paid run', marker => { '## Phase 2: Research', '**Step 1: Identify', '**Step 2: Visual research', '_aside_exec()'])('missing %s fails closed before a paid run', marker => {
expect(() => extractDesignResearchContract(source.replace(marker, 'REMOVED'))).toThrow(); expect(() => extractDesignResearchContract(source.replace(marker, 'REMOVED'))).toThrow();
}); });
test('research fixture changes select their actual live consumer', () => {
for (const file of ['test/helpers/skill-fixture.ts', 'test/design-research-fixture.test.ts']) {
expect(selectTests([file], E2E_TOUCHFILES, []).selected).toContain('design-consultation-research');
}
});
@@ -27,8 +27,7 @@ test('DX artifact calibrations keep four acknowledged choices and vary only comp
test('the separate DX calibration has a canonical periodic selector and all direct fixture inputs', () => { test('the separate DX calibration has a canonical periodic selector and all direct fixture inputs', () => {
expect(E2E_TIERS[ID]).toBe('periodic'); expect(E2E_TIERS[ID]).toBe('periodic');
for (const file of [`test/skill-e2e-${ID}.test.ts`, 'test/fixtures/devex-peer-comparison-classification.ts', for (const file of [`test/skill-e2e-${ID}.test.ts`, 'test/fixtures/devex-peer-comparison-classification.ts']) {
'test/devex-peer-comparison-calibration.test.ts']) {
expect(fs.existsSync(path.join(ROOT, file))).toBe(true); expect(fs.existsSync(path.join(ROOT, file))).toBe(true);
expect(selectTests([file], E2E_TOUCHFILES, []).selected).toEqual([ID]); expect(selectTests([file], E2E_TOUCHFILES, []).selected).toEqual([ID]);
} }
-13
View File
@@ -6,7 +6,6 @@ import {HOST_PATHS, type TemplateContext} from '../scripts/resolvers/types';
import {generatePreamble} from '../scripts/resolvers/preamble'; import {generatePreamble} from '../scripts/resolvers/preamble';
import {generateAskUserFormat} from '../scripts/resolvers/preamble/generate-ask-user-format'; import {generateAskUserFormat} from '../scripts/resolvers/preamble/generate-ask-user-format';
import {generateGBrainContextLoad} from '../scripts/resolvers/gbrain'; import {generateGBrainContextLoad} from '../scripts/resolvers/gbrain';
import {E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES, selectTests} from './helpers/touchfiles';
import {readWorkflowJudgeInput} from './helpers/workflow-judge-input'; import {readWorkflowJudgeInput} from './helpers/workflow-judge-input';
const template = fs.readFileSync(path.join(import.meta.dir, '../plan-eng-review/SKILL.md.tmpl'), 'utf8'); const template = fs.readFileSync(path.join(import.meta.dir, '../plan-eng-review/SKILL.md.tmpl'), 'utf8');
@@ -108,18 +107,6 @@ test('Eng alone defers canonical question rules until scope and keeps one counte
} }
} }
}); });
test('the regression selects the same paid owners as the Eng template', () => {
for (const map of [E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES]) {
expect(selectTests(['test/eng-scope-entry-ap.test.ts'], map, []).selected)
.toEqual(selectTests(['plan-eng-review/SKILL.md.tmpl'], map, []).selected);
for (const paths of Object.values(map)) for (let i = 0; i < paths.length; i++) {
expect(Object.hasOwn(paths, i)).toBe(true);
expect(typeof paths[i]).toBe('string');
}
}
});
test('the full evaluated bundle routes startup into ordered preparation before scope analysis', () => { test('the full evaluated bundle routes startup into ordered preparation before scope analysis', () => {
const input = readWorkflowJudgeInput({root:path.join(import.meta.dir, '..'), skillPath:'plan-eng-review/SKILL.md', const input = readWorkflowJudgeInput({root:path.join(import.meta.dir, '..'), skillPath:'plan-eng-review/SKILL.md',
startMarker:'# Plan Review Mode', endMarker:null}); startMarker:'# Plan Review Mode', endMarker:null});
-10
View File
@@ -8,8 +8,6 @@ import { fakePlanSeedPrelude } from './helpers/fake-plan-seed';
import fixture from './fixtures/eng-seeded-completion-ai.json'; import fixture from './fixtures/eng-seeded-completion-ai.json';
import { classifyVisible, extractPlanFilePath } from './helpers/claude-pty-runner'; import { classifyVisible, extractPlanFilePath } from './helpers/claude-pty-runner';
import * as predicates from './helpers/claude-pty-runner'; import * as predicates from './helpers/claude-pty-runner';
import { selectTests, E2E_TOUCHFILES } from './helpers/touchfiles';
const gate = '─────\nClaude has written up a plan and is ready to execute. Would you like to proceed?\n❯ 1. Yes, and use auto mode\n2. Yes, manually approve edits\n3. Tell Claude what to change'; const gate = '─────\nClaude has written up a plan and is ready to execute. Would you like to proceed?\n❯ 1. Yes, and use auto mode\n2. Yes, manually approve edits\n3. Tell Claude what to change';
const compactGate = 'Exit plan mode?\nClaude wants to exit plan mode\n❯ 1. Yes, and switch to default (ask each time) for this session\n2. No'; const compactGate = 'Exit plan mode?\nClaude wants to exit plan mode\n❯ 1. Yes, and switch to default (ask each time) for this session\n2. No';
const question = 'Which runner should the plan use?\nA) Use the built-in runner\nB) Build a custom runner\nRecommendation: A because it avoids duplicate scheduling logic.\nReply with A or B.'; const question = 'Which runner should the plan use?\nA) Use the built-in runner\nB) Build a custom runner\nRecommendation: A because it avoids duplicate scheduling logic.\nReply with A or B.';
@@ -181,11 +179,3 @@ test('rejected completion does not erase a genuine earlier question or change un
const unseeded = await mockedObservation([gate.replace('❯ ', '')], 'waiting', false); const unseeded = await mockedObservation([gate.replace('❯ ', '')], 'waiting', false);
expect(unseeded.obs.outcome).toBe('plan_ready'); expect(unseeded.judged).toBe(0); expect(unseeded.obs.outcome).toBe('plan_ready'); expect(unseeded.judged).toBe(0);
}); });
test('completion evidence dependencies select exactly the seeded observation owners', () => {
const owners = ['plan-ceo-review-plan-mode', 'plan-eng-review-plan-mode', 'plan-design-review-plan-mode',
'plan-devex-review-plan-mode', 'plan-mode-no-op', 'auto-decide-preserved'].sort();
for (const file of ['test/eng-seeded-completion-ai.test.ts', 'test/fixtures/eng-seeded-completion-ai.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(owners);
}
});
-36
View File
@@ -1,36 +0,0 @@
import { describe, expect, test } from 'bun:test';
import { E2E_TOUCHFILES, E2E_TIERS, GLOBAL_TOUCHFILES, LLM_JUDGE_TOUCHFILES } from './helpers/touchfiles-data';
import { selectTests } from './helpers/test-selection';
describe('fake impeccable engine selection', () => {
const helper = 'test/helpers/fake-impeccable.ts';
const consumers = [
'design-html-slop-gate',
'design-review-detector-shim',
'design-review-detector-shim-dom',
'design-review-plugin-handoff',
'review-design-lite',
];
test('a helper-only edit selects every paid consumer without global expansion', () => {
const result = selectTests([helper], E2E_TOUCHFILES);
expect(result.selected.slice().sort()).toEqual(consumers);
expect(result.reason).toBe('diff');
expect(result.skipped).toContain('design-consultation-core');
expect(GLOBAL_TOUCHFILES).not.toContain(helper);
expect(selectTests([helper], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
test('the fake executable and captured output retain the same consumers and tiers', () => {
for (const changed of ['test/fixtures/fake-impeccable.ts', 'test/fixtures/impeccable-detect-sample.json']) {
expect(selectTests([changed], E2E_TOUCHFILES).selected.slice().sort()).toEqual(consumers);
}
expect(consumers.map(name => [name, E2E_TIERS[name]])).toEqual([
['design-html-slop-gate', 'periodic'],
['design-review-detector-shim', 'gate'],
['design-review-detector-shim-dom', 'gate'],
['design-review-plugin-handoff', 'gate'],
['review-design-lite', 'periodic'],
]);
});
});
-93
View File
@@ -1,93 +0,0 @@
{
"cwd": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-autoplan-chain-LukJXD",
"config": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/with-skills/.claude",
"stateRoot": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/skill-home-cMZrbW/.gstack",
"hook": {
"version": 1,
"cwd": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-autoplan-chain-LukJXD",
"config": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/with-skills/.claude",
"stateRoot": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/skill-home-cMZrbW/.gstack",
"seenIds": [
"toolu_019ngUUTCGyDufyLQaN9Tvgm"
],
"pending": {
"source": "pre_tool_use",
"sessionId": "037c9f5e-7035-45e2-935d-0b950c435930",
"toolUseId": "toolu_019ngUUTCGyDufyLQaN9Tvgm",
"tool": "Edit",
"file": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/skill-home-cMZrbW/.gstack/projects/gstack-autoplan-chain-LukJXD/ceo-plans/2026-09-10-user-dashboard.md",
"timestamp": "2026-09-10T14:35:35.363Z",
"transcriptPath": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/with-skills/.claude/projects/-tmp-gstack-paid-shard-MPtf0T-tmp-gstack-autoplan-chain-LukJXD/037c9f5e-7035-45e2-935d-0b950c435930.jsonl",
"editDigest": {
"version": 1,
"beforeSHA256": "6771404ca60011824af336f0a7011e3aba465b8728c011eef935a4b847e72bdd",
"requestSHA256": "7ea64ad22d29d9c779b6e945119ea238e2f40862a368ca518100626a1e7978de",
"oldLineHashes": [
"95b34a72ab3b36711dc4f7cffc93cfe9e4ac45adaff3cbe06170576bb2b7787d"
],
"newLineHashes": [
"b69061a320491c4d23ea3b0e11040b1edfdf54c90d67287236c5b49695b74a6d",
"f01cbe18eb0051492cb3e8740542a491038881c5f23dac05003dfa84a4a59087",
"2a23528279bef0c9dcde730b41c9cb25768c8d6de1d40195181e48efa8e6a295",
"8110f2d8d27cb7e397562be0be38bc995e33cdf5d570d3d18aae23fe83db5116",
"4fef7666a0b82562e292a3d53f26f0721c09a74ceb0a30a970351f213468b07e",
"2bbfa283b38391e7d66c205292efb1e8565120fa337a098863f4758576fe1239",
"be4ed8d0778c7ba2036e19657ac496f2b24ee5d3ceb4d1240c3f7993567f4f89",
"861a718d78d38dd744ab59540c3139c5283d0e67a3deed5b41138f9581084d34",
"418ec10dc288464be75940c80f56faa734f5380ed8c2a957dcc52ed75f60f942",
"a59e48fe92bfcea3ec1cad39996f1a01039861faaa75daa251be8d64b102abdc",
"c701beb15c91ba566b32cd004f4ba46eb8f317061549c0f699041c151065a387",
"44aa4bd0d2a4cc4cbce51a9ea6bc485d5fb2cfbebfc01a1fe275d8e165f51c92",
"e8fd6eaf078d6ccc6028e6213e12acfa82511902136e4aec48e1398990582884",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"cfc849f68e95805d8b84b46121a94a5ee70daf8fe374e20224d88a4290553089",
"1e619e0fe087d96a85514e4f9f741b2aae28e3c65a73f3833b6c1869e282ed5b",
"0ef460f920e57467c135c9b9605f343e189fc4397565d14b12d0fc9ff5f31e4f",
"d9134cd12c765f0e72b00438c6f70fa3af52d4a4602dfb27c8ae4fe29a7ee4cc",
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"95b34a72ab3b36711dc4f7cffc93cfe9e4ac45adaff3cbe06170576bb2b7787d"
]
}
},
"sessionId": "037c9f5e-7035-45e2-935d-0b950c435930"
},
"before": "---\nstatus: ACTIVE\n---\n# CEO Plan: User Dashboard Page\nGenerated by /plan-ceo-review (via /autoplan) on 2026-09-10\nBranch: main | Mode: SELECTIVE EXPANSION\nRepo: gstack-autoplan-chain-LukJXD (local, no remote)\n\n## Problem and goal\n\nMembers of the existing single-role workspace visit three separate pages after login to resume work, check alerts, and inspect recent changes. One team walkthrough measured a median of 75 seconds to find the next item. The dashboard at `/dashboard` is meant to cut the median login-to-first-completed-task time from ~75 s to 45 s (a 40 % reduction), with completed-task rate and permission-error rate as guardrails.\n\n**Primary ship metric:** median login-to-first-completed-task time, treatment vs control. **Ship threshold:** ≥ 40 % reduction (equivalent to 75 → 45 s) sustained over the ≥ 2-week measurement window with no guardrail regression. **Diagnostic split (not a ship gate):** login→first-action-start (the leg the dashboard moves) and action-start→completion (unchanged by this plan), both derivable from the existing login / action start / action completion events, so the read-out attributes the delta correctly. The production baseline for all three is computed from existing events before the cohort opens; the 75 s walkthrough figure is not load-bearing.\n\n**Experiment design.** Assignment is a deterministic hash of member id, fixed for the experiment's duration. Default split 10 % treatment / 90 % control. Minimum sample: ≥ 300 logins per arm within the window; if the workspace's active-member count makes that unreachable at 10 % (record the count at approval), switch to a 50/50 split, and if still unreachable, fall back to a before/after comparison over the same window and say so in the read-out. `/dashboard` is flag-gated (below), so control members cannot reach it and contaminate the read-out.\n\n## Vision\n\n### 10x Check\nThe dashboard becomes the member's assistant rather than a summary page: a ranked \"next item\" (\"You have 2 items due today\"), alerts grouped by source, small tasks completed inline, live updates as teammates act, and a home that other features publish panels into. Concrete shape: ranking service over the action registry, a panel registry, a push channel. Human ~4-6 weeks / CC ~2-3 days. Out of this plan's blast radius; the personalisation plan owns it. This plan lays the seam (per-panel envelopes + a shared panel shell) without building the platform.\n\n### Platonic Ideal\nSkipped (SELECTIVE EXPANSION).\n\n## Baseline held (plan scope)\n- `/dashboard` page with Quick actions, Notifications, Recent activity panels; Tailwind, mobile-first (sm/md/lg).\n- Loading skeleton, empty, error, success per panel; hover and focus-visible on every control.\n- \"Mark all as read\" confirmation modal on the existing dialog primitive.\n- Toast feedback for actions.\n- `GET /api/dashboard` aggregate over existing PostgreSQL tables; no schema change.\n- Out of scope by the user: dark mode, personalisation.\n\n## Implementation approach chosen\nApproach A: aggregate endpoint composed server-side from the existing list methods and action registry, returning per-panel result envelopes so one failing panel never sinks the page. Alternatives: B client-side composition of three existing endpoints (7/10, close second, surfaced as taste decision T1); C smart post-login redirect + shell badge (4/10 against the stated goal, rejected).\n\n**If the Final Gate selects B instead of A:** the \"Endpoint\", \"Response shape\", and \"Retry\" paragraphs below are replaced by three per-panel fetch hooks wrapping the existing list endpoints and a small eligibility endpoint over the registry; each hook produces the same `Envelope<T>` client-side, so panel states, empty CTAs, mark-all-read, latest-wins, redirect precedence, caching headers, toast, accessibility, analytics, and rollout are unchanged. Composer tests become hook tests. **If the gate selects dashboard-local for T3:** the toast code moves under `src/components/dashboard/` with the same API and the same live-region rule; nothing else changes.\n\n## Verified preconditions (confirm before implementation; each has a fallback)\n- **Bulk-read API accepts a snapshot time.** The plan's contracts section states it \"marks only notifications at or before the supplied snapshot time\". Confirm the parameter name and type. If it turns out not to exist, mark-all-read cannot be made safe against later arrivals and the modal flow is **blocked** until the API gains the parameter (this becomes the same API work E8 needs; raise at the gate, do not ship a clock-unsafe version).\n- **Bulk-read API returns the affected count.** Confirm; otherwise the success toast reads \"Marked all as read\" without a number.\n- **Feature-flag system supports stable per-member assignment** (hash of member id). Confirm; otherwise implement the hash in the redirect module and store only the flag's on/off and percentage in the flag sLine truncated
"viewport": " +t. \n 139 +- **Snapshot consistency.** Notifications rows, `unreadTotal`, and `now()` come from a single statement (CTE) so t\n +hey share one READ COMMITTED snapshot. Query budget via `SET LOCAL statement_timeout = '2s'` inside that statement\n +'s transaction (or the driver's per-query timeout option); the \"timed-out query releases its connection\" test asse\n +rts on pool metrics, not on the promise alone. \n 140 +- **Route gating in a client-rendered app.** The page route performs a client-side redirect to the current landing\n + after the flag lookup (no server 302 unless the app already server-renders routes); `GET /api/dashboard` returnin\n +g 404 for flag-off members is the authoritative gate. \n 141 +- **Forcing panel states in tests.** Playwright uses `page.route()` interception on `/api/dashboard` and the bulk-\n +read route to inject 503 / per-panel `ok:false` / empty payloads; no test-only headers in production builds. \n 142 +- **Identifiers.** The create action is `actionId = 'create_item'` (from the registry's stable ids); `fetchedAt` i\n +s ISO 8601 UTC with milliseconds; the 44 px target rule applies to every interactive control inside the panels (ac\n +tions, Retry, See all, Mark all as read). \n 143 + \n 144 +## Reviewer Concerns (unresolved after 3 iterations) \n 145 +- **Snapshot window (r3 #5).** A notification inserted in a transaction whose `now()` predates `fetchedAt` but whi\n +ch commits after the dashboard read has `created_at <= fetchedAt`, is invisible to the list, and is still marked r\n +ead. Accepted and documented: the window is the duration of an in-flight insert transaction (milliseconds), the ex\n +isting bulk-read contract is clock-based, and changing it to id-based is the E8-adjacent API work already deferred\n +. Record as a known limitation in the JSDoc on the mark-all-read handler. \n 146 +- **Provisional approach vs open taste items (r2 #4, r3 #6).** The reviewer wants T1/T3 closed or A/E7 marked prov\n +isional. They are provisional by design: /autoplan surfaces taste decisions at one Final Gate and the fallback par\n +agraphs define what changes. Not a contradiction to resolve in this document. \n 147 +- **Population size (r3 #14).** The single-workspace population may be too small for the default design; the fallb\n +acks exist, and the member count is now recorded before R1 starts. \n 148 + \n 149 ## Taste decisions carried to the Final Gate\n 150 - T1 aggregate endpoint (A) vs client-side composition (B) — open; the B fallback paragraph above states exactly w\n hat changes.\n 151 - T2 confirmation modal for Mark all as read — recorded decision, surfaced for information: the independent review\n er preferred direct action + undo, but undo (E8) needs a new mutation API and is deferred, so the modal stays unle\n ss E8 is pulled into scope.\n╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\n Do you want to make this edit to 2026-09-10-user-dashboard.md?\n ❯ 1. Yes\n 2. Yes, and switch to accept edits (auto-approve file edits and common file commands) for this session (shift+tab)\n 3. No\n\n Esc to cancel · Tab to amend\n",
"request": {
"old_string": "## Taste decisions carried to the Final Gate",
"new_string": "## Iteration-3 amendments (override earlier wording where they conflict)\n- **Guardrail bounds.** Completed-task rate in treatment must not be lower than control by more than 2 percentage points; permission-error rate must not be higher than control by more than 1 percentage point, both over the same window.\n- **Control-arm assignment recorded.** Emit `dashboard_assignment{cohort, hashVersion}` on the existing login event for every member (both arms); record the hash salt/version at approval. `dashboard_viewed` remains treatment-only.\n- **Ship-rule estimator.** Unit of analysis is the member (first login-to-first-completed-task per member per day, then per-member median). Estimator: bootstrap 95 % CI on the difference of medians; ship when the CI lower bound shows ≥ 40 % reduction. \"≥ 300 logins per arm\" becomes \"≥ 300 member-days per arm\".\n- **Record the active-member count before starting R1**, not after; choose the split then.\n- **Whole-response failures on the GET.** 503 `DashboardUnavailable` or a network/parse failure → all three panels ERROR with one shared page-level Retry; 404 (assignment flipped off mid-session) → client redirects to the current landing; 401 → login. Envelope codes remain per-panel only.\n- **Panel state model.** `{ status: LOADING | EMPTY | ERROR | SUCCESS, refreshing: boolean }`. `status` derives only from the last settled envelope; `refreshing` is set at request start when the panel already has a settled status other than LOADING, and cleared on settle. EMPTY panels refresh with their empty copy still rendered. The Mark-all-read trigger stays rendered but disabled while `refreshing`; it is rendered only when `status === SUCCESS && unreadTotal > 0`.\n- **CSRF vs membership 403.** Retry-once applies only when the existing client's typed error indicates a CSRF failure (its existing discriminator, body code or header); a membership 403 shows the access message with no retry.\n- **Preconditions heading** is to be read as \"Preconditions to verify before implementation\". The bulk-read semantic requirement is: it marks read only notifications with `created_at <= snapshot` by the DB clock and is idempotent.\n- **Snapshot consistency.** Notifications rows, `unreadTotal`, and `now()` come from a single statement (CTE) so they share one READ COMMITTED snapshot. Query budget via `SET LOCAL statement_timeout = '2s'` inside that statement's transaction (or the driver's per-query timeout option); the \"timed-out query releases its connection\" test asserts on pool metrics, not on the promise alone.\n- **Route gating in a client-rendered app.** The page route performs a client-side redirect to the current landing after the flag lookup (no server 302 unless the app already server-renders routes); `GET /api/dashboard` returning 404 for flag-off members is the authoritative gate.\n- **Forcing panel states in tests.** Playwright uses `page.route()` interception on `/api/dashboard` and the bulk-read route to inject 503 / per-panel `ok:false` / empty payloads; no test-only headers in production builds.\n- **Identifiers.** The create action is `actionId = 'create_item'` (from the registry's stable ids); `fetchedAt` is ISO 8601 UTC with milliseconds; the 44 px target rule applies to every interactive control inside the panels (actions, Retry, See all, Mark all as read).\n\n## Reviewer Concerns (unresolved after 3 iterations)\n- **Snapshot window (r3 #5).** A notification inserted in a transaction whose `now()` predates `fetchedAt` but which commits after the dashboard read has `created_at <= fetchedAt`, is invisible to the list, and is still marked read. Accepted and documented: the window is the duration of an in-flight insert transaction (milliseconds), the existing bulk-read contract is clock-based, and changing it to id-based is the E8-adjacent API work already deferred. Record as a known limitation in the JSDoc on the mark-all-read handler.\n- **Provisional approach vs open taste items (r2 #4, r3 #6).** The reviewer wants T1/T3 closed or A/E7 marked provisional. They are provisional by design: /autoplan surfaces taste decisions at one Final Gate and the fallback paragraphs define what changes. Not a contradiction to resolve in this document.\n- **Population size (r3 #14).** The single-workspace population may be too small for the default design; the fallbacks exist, and the member count is now recorded before R1 starts.\n\n## Taste decisions carried to the Final Gate"
},
"publicTools": [
{
"sessionId": "037c9f5e-7035-45e2-935d-0b950c435930",
"timestamp": "2026-09-10T14:32:00.204Z",
"toolUseId": "toolu_01A78r3KVhp1i9RAkz57ECSC",
"kind": "use",
"name": "Write",
"input": {
"file_path": "/tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/skill-home-cMZrbW/.gstack/projects/gstack-autoplan-chain-LukJXD/ceo-plans/2026-09-10-user-dashboard.md",
"content": "---\nstatus: ACTIVE\n---\n# CEO Plan: User Dashboard Page\nGenerated by /plan-ceo-review (via /autoplan) on 2026-09-10\nBranch: main | Mode: SELECTIVE EXPANSION\nRepo: gstack-autoplan-chain-LukJXD (local, no remote)\n\n## Problem and goal\n\nMembers of the existing single-role workspace visit three separate pages after login to resume work, check alerts, and inspect recent changes. One team walkthrough measured a median of 75 seconds to find the next item. The dashboard at `/dashboard` is meant to cut the median login-to-first-completed-task time from ~75 s to 45 s (a 40 % reduction), with completed-task rate and permission-error rate as guardrails.\n\n**Primary ship metric:** median login-to-first-completed-task time, treatment vs control. **Ship threshold:** ≥ 40 % reduction (equivalent to 75 → 45 s) sustained over the ≥ 2-week measurement window with no guardrail regression. **Diagnostic split (not a ship gate):** login→first-action-start (the leg the dashboard moves) and action-start→completion (unchanged by this plan), both derivable from the existing login / action start / action completion events, so the read-out attributes the delta correctly. The production baseline for all three is computed from existing events before the cohort opens; the 75 s walkthrough figure is not load-bearing.\n\n**Experiment design.** Assignment is a deterministic hash of member id, fixed for the experiment's duration. Default split 10 % treatment / 90 % control. Minimum sample: ≥ 300 logins per arm within the window; if the workspace's active-member count makes that unreachable at 10 % (record the count at approval), switch to a 50/50 split, and if still unreachable, fall back to a before/after comparison over the same window and say so in the read-out. `/dashboard` is flag-gated (below), so control members cannot reach it and contaminate the read-out.\n\n## Vision\n\n### 10x Check\nThe dashboard becomes the member's assistant rather than a summary page: a ranked \"next item\" (\"You have 2 items due today\"), alerts grouped by source, small tasks completed inline, live updates as teammates act, and a home that other features publish panels into. Concrete shape: ranking service over the action registry, a panel registry, a push channel. Human ~4-6 weeks / CC ~2-3 days. Out of this plan's blast radius; the personalisation plan owns it. This plan lays the seam (per-panel envelopes + a shared panel shell) without building the platform.\n\n### Platonic Ideal\nSkipped (SELECTIVE EXPANSION).\n\n## Baseline held (plan scope)\n- `/dashboard` page with Quick actions, Notifications, Recent activity panels; Tailwind, mobile-first (sm/md/lg).\n- Loading skeleton, empty, error, success per panel; hover and focus-visible on every control.\n- \"Mark all as read\" confirmation modal on the existing dialog primitive.\n- Toast feedback for actions.\n- `GET /api/dashboard` aggregate over existing PostgreSQL tables; no schema change.\n- Out of scope by the user: dark mode, personalisation.\n\n## Implementation approach chosen\nApproach A: aggregate endpoint composed server-side from the existing list methods and action registry, returning per-panel result envelopes so one failing panel never sinks the page. Alternatives: B client-side composition of three existing endpoints (7/10, close second, surfaced as taste decision T1); C smart post-login redirect + shell badge (4/10 against the stated goal, rejected).\n\n**If the Final Gate selects B instead of A:** the \"Endpoint\", \"Response shape\", and \"Retry\" paragraphs below are replaced by three per-panel fetch hooks wrapping the existing list endpoints and a small eligibility endpoint over the registry; each hook produces the same `Envelope<T>` client-side, so panel states, empty CTAs, mark-all-read, latest-wins, redirect precedence, caching headers, toast, accessibility, analytics, and rollout are unchanged. Composer tests become hook tests. **If the gate selects dashboard-local for T3:** the toast code moves under `src/components/dashboard/` with the same API and the same live-region rule; nothing else changes.\n\n## Verified preconditions (confirm before implementation; each has a fallback)\n- **Bulk-read API accepts a snapshot time.** The plan's contracts section states it \"marks only notifications at or before the supplied snapshot time\". Confirm the parameter name and type. If it turns out not to exist, mark-all-read cannot be made safe against later arrivals and the modal flow is **blocked** until the API gains the parameter (this becomes the same API work E8 needs; raise at the gate, do not ship a clock-unsafe version).\n- **Bulk-read API returns the affected count.** Confirm; otherwise the success toast reads \"Marked all as read\" without a number.\n- **Feature-flag system supports stable per-member assignment** (hash of member id). Confirm; otherwise implement the hash in the redirect module and store only the flag's on/off and percentage in theLine truncated
},
"messageId": "msg_011CeuvH91RGhGXA5XHMPN7J",
"requestId": "req_011CeuvH6MgNDWkEkYtuWxs9"
},
{
"sessionId": "037c9f5e-7035-45e2-935d-0b950c435930",
"timestamp": "2026-09-10T14:32:00.969Z",
"toolUseId": "toolu_01A78r3KVhp1i9RAkz57ECSC",
"kind": "result",
"content": "The file /tmp/gstack-paid-shard-MPtf0T/tmp/gstack-hermetic-3587976-PXLrEr/skill-home-cMZrbW/.gstack/projects/gstack-autoplan-chain-LukJXD/ceo-plans/2026-09-10-user-dashboard.md has been updated successfully. (file state is current in your context — no need to Read it back)",
"isError": false
}
],
"provenance": {
"status": "Exact original request reconstruction independently equals original requestSHA; no new digest existed in the paid attempt.",
"requestSHA256": "7ea64ad22d29d9c779b6e945119ea238e2f40862a368ca518100626a1e7978de",
"beforeSHA256": "6771404ca60011824af336f0a7011e3aba465b8728c011eef935a4b847e72bdd",
"paneSHA256": "c5662a9c0d67ba04de8720c25d51378b4662266273cb186f48f7c3109abd2ee2",
"sourceProof": "ap-cropped-addition-plan-v1/proof.json",
"reconstruction": "ap-cropped-addition-request-reconstruction-plan-v1.json",
"publicTools": "Exact acknowledged same-file predecessor pair from full94 public events.",
"actualCoverage": "operator-cancelled-incomplete; no phase credit"
}
}
+71
View File
@@ -0,0 +1,71 @@
/**
* Derived touchfile rule: a paid test depends on every `test/helpers` and
* `test/fixtures` file it reaches through static imports, plus every such path
* named in a string literal inside that closure (fixtures read through `fs`).
* The result is a lower bound: a computed fixture path is declared by adding it
* to the key by hand.
*/
import * as fs from 'fs';
import * as path from 'path';
import { matchGlob } from './test-selection';
export interface ClosureEntry {
/** Repo-relative dependency path. */
file: string;
/** How the paid test reached it: the import chain, ending in `"literal"` for string references. */
chain: string[];
}
const LITERAL = /test\/(?:helpers|fixtures)\/[A-Za-z0-9_.\-/]+[A-Za-z0-9_]/g;
const scanner = new Bun.Transpiler({ loader: 'tsx' });
function resolveImport(root: string, from: string, specifier: string): string | null {
if (!specifier.startsWith('.')) return null;
const base = path.resolve(path.dirname(path.join(root, from)), specifier);
for (const candidate of [base, `${base}.ts`, base.replace(/\.js$/, '.ts'), path.join(base, 'index.ts')]) {
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return path.relative(root, candidate).split(path.sep).join('/');
}
return null;
}
/** Selection itself is diffed by map (diffTouchfileMaps), and test files are never dependencies. */
const SELECTION_MODULES = new Set(['test/helpers/touchfiles-data.ts', 'test/helpers/touchfiles.ts', 'test/helpers/test-selection.ts']);
const inScope = (file: string) => (file.startsWith('test/helpers/') || file.startsWith('test/fixtures/')) &&
!file.endsWith('.test.ts') && !SELECTION_MODULES.has(file);
/**
* Static test/helpers + test/fixtures closure of one paid test file, with literal fixture paths.
* Traversal stops at `boundary` files (the global touchfiles): an edit there already selects every test.
*/
export function paidTestClosure(root: string, testFile: string, boundary: ReadonlySet<string> = new Set()): ClosureEntry[] {
const seen = new Map<string, string[]>();
const queue: Array<{ file: string; chain: string[] }> = [{ file: testFile, chain: [testFile] }];
while (queue.length) {
const { file, chain } = queue.shift()!;
if (!/\.(ts|tsx|js|mjs)$/.test(file) || boundary.has(file)) continue;
const source = fs.readFileSync(path.join(root, file), 'utf8');
let imports: Array<{ path: string }> = [];
try { imports = scanner.scanImports(source); } catch { imports = []; }
for (const { path: specifier } of imports) {
const target = resolveImport(root, file, specifier);
if (!target || !inScope(target) || seen.has(target)) continue;
seen.set(target, [...chain, target]);
queue.push({ file: target, chain: [...chain, target] });
}
for (const match of source.match(LITERAL) ?? []) {
const absolute = path.join(root, match);
if (!inScope(match) || !fs.existsSync(absolute)) continue;
const literal = fs.statSync(absolute).isDirectory() ? `${match.replace(/\/$/, '')}/**` : match;
if (seen.has(literal)) continue;
seen.set(literal, [...chain, `"${match}"`]);
if (!literal.endsWith('/**')) queue.push({ file: literal, chain: [...chain, `"${match}"`] });
}
}
return [...seen].map(([file, chain]) => ({ file, chain }));
}
/** True when a dependency is selected by the key's own list or the global list. */
export function isCovered(file: string, patterns: readonly string[], globals: readonly string[]): boolean {
const probe = file.endsWith('/**') ? `${file.slice(0, -3)}/probe` : file;
return [...patterns, ...globals].some(pattern => pattern === file || matchGlob(probe, pattern));
}
File diff suppressed because it is too large. Load diff
-7
View File
@@ -8,17 +8,10 @@ import { getHermeticDirs, hermeticSkillsConfigDir } from './helpers/hermetic-env
import { refreshHermeticSkillRuntime, questionCompanionReadSettings, hermeticSkillRuntime } from './helpers/hermetic-skill-runtime'; import { refreshHermeticSkillRuntime, questionCompanionReadSettings, hermeticSkillRuntime } from './helpers/hermetic-skill-runtime';
import { pathToFileURL } from 'node:url'; import { pathToFileURL } from 'node:url';
import { createHash } from 'node:crypto'; import { createHash } from 'node:crypto';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
const digest = (file: string) => createHash('sha256').update(fs.readFileSync(file)).digest('hex'); const digest = (file: string) => createHash('sha256').update(fs.readFileSync(file)).digest('hex');
describe('hermetic seeded PTY runtime', () => { describe('hermetic seeded PTY runtime', () => {
test('runtime helper and regression select every PTY consumer', () => {
const consumers = Object.entries(E2E_TOUCHFILES).filter(([, files]) => files.includes('test/helpers/claude-pty-runner.ts')).map(([name]) => name).sort();
expect(consumers.length).toBeGreaterThanOrEqual(15);
for (const file of ['test/helpers/hermetic-skill-runtime.ts', 'test/hermetic-skill-runtime.test.ts'])
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(consumers);
});
test.skipIf(process.platform === 'win32')('uses current lazy files and tools with scoped access, preserving auth, caches, and explicit overrides', async () => { test.skipIf(process.platform === 'win32')('uses current lazy files and tools with scoped access, preserving auth, caches, and explicit overrides', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-runtime-probe-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-runtime-probe-'));
const operatorHome = path.join(dir, 'operator-home'); const operatorHome = path.join(dir, 'operator-home');
-10
View File
@@ -5,7 +5,6 @@ import * as path from 'node:path';
import { findNativeAutoDecision } from './helpers/native-auto-decide'; import { findNativeAutoDecision } from './helpers/native-auto-decide';
import { classifyVisible } from './helpers/claude-pty-runner'; import { classifyVisible } from './helpers/claude-pty-runner';
import { readPlanCountTranscript, type NativePublicToolEvent } from './helpers/plan-count-transcript'; import { readPlanCountTranscript, type NativePublicToolEvent } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import capture_auto_decide_current_declaration from './fixtures/auto-decide-current-declaration-6aef.json'; import capture_auto_decide_current_declaration from './fixtures/auto-decide-current-declaration-6aef.json';
import capture_auto_decide_explanatory_mode from './fixtures/auto-decide-explanatory-mode-043a.json'; import capture_auto_decide_explanatory_mode from './fixtures/auto-decide-explanatory-mode-043a.json';
import captured749_auto_decide_explanatory_mode from './fixtures/auto-decide-explanatory-mode-749df.json'; import captured749_auto_decide_explanatory_mode from './fixtures/auto-decide-explanatory-mode-749df.json';
@@ -109,15 +108,6 @@ test('the native reader cannot promote foreign cwd, child, user or tool-result t
} }
}finally{fs.rmSync(dir,{recursive:true,force:true});} }finally{fs.rmSync(dir,{recursive:true,force:true});}
}); });
test('new native annotation dependencies retain all existing observation caller owners',()=>{
const expected=['plan-ceo-review-plan-mode','plan-eng-review-plan-mode','plan-design-review-plan-mode','plan-devex-review-plan-mode','plan-mode-no-op','office-hours-auto-mode','auto-decide-preserved'];
for(const file of ['test/helpers/native-auto-decide.ts','test/native-auto-decide.test.ts','test/native-auto-decide-pty.test.ts','test/fixtures/native-auto-decide-ag.json']){
const owners=Object.entries(E2E_TOUCHFILES).filter(([,paths])=>paths.includes(file)).map(([name])=>name);expect(owners).toEqual(expected);
expect(selectTests([file],E2E_TOUCHFILES).selected).toContain('auto-decide-preserved');
}
});
describe('auto-decide-current-declaration', () => { describe('auto-decide-current-declaration', () => {
const capture = capture_auto_decide_current_declaration; const capture = capture_auto_decide_current_declaration;
const clone = () => structuredClone(capture.retry) as any; const clone = () => structuredClone(capture.retry) as any;
+1 -9
View File
@@ -4,7 +4,7 @@ import * as fs from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import * as os from 'node:os'; import * as os from 'node:os';
import { validateOfficeHoursCompletion, validateOfficeHoursReviewerHandoffs, validateOfficeHoursReviewArtifacts, validateOfficeHoursReviewPreservation, validateOfficeHoursSpecSummary, type OfficeHoursCompletionEvidence } from './helpers/office-hours-completion'; import { validateOfficeHoursCompletion, validateOfficeHoursReviewerHandoffs, validateOfficeHoursReviewArtifacts, validateOfficeHoursReviewPreservation, validateOfficeHoursSpecSummary, type OfficeHoursCompletionEvidence } from './helpers/office-hours-completion';
import { E2E_TOUCHFILES, E2E_TIERS } from './helpers/touchfiles-data'; import { E2E_TOUCHFILES } from './helpers/touchfiles-data';
import { selectTests } from './helpers/test-selection'; import { selectTests } from './helpers/test-selection';
const designPath = '/tmp/office-hours-fixture/docs/designs/roster-check.md'; const designPath = '/tmp/office-hours-fixture/docs/designs/roster-check.md';
@@ -697,14 +697,6 @@ describe('office-hours completion eval selection', () => {
expect(selected).toContain('office-hours-section-loading'); expect(selected).toContain('office-hours-section-loading');
expect(selected).not.toContain('carve-section-loading'); expect(selected).not.toContain('carve-section-loading');
}); });
test('completion helper changes select its gate and dedicated periodic workflow', () => {
const { selected } = selectTests(['test/helpers/office-hours-completion.ts'], E2E_TOUCHFILES);
expect(selected).toEqual(['office-hours-spec-review', 'office-hours-section-loading']);
expect(selected.filter(name => E2E_TIERS[name] === 'periodic')).toEqual(['office-hours-section-loading']);
expect(E2E_TIERS['office-hours-spec-review']).toBe('gate');
expect(E2E_TOUCHFILES['office-hours-section-loading']).toContain('test/skill-e2e-office-hours-section-loading.test.ts');
});
}); });
describe('office-hours spec-review summary completion', () => { describe('office-hours spec-review summary completion', () => {
-6
View File
@@ -2,8 +2,6 @@ import { expect, test } from 'bun:test';
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import { CAPTURE_MS, CAPTURE_LONG_MS } from './helpers/eval-budgets'; import { CAPTURE_MS, CAPTURE_LONG_MS } from './helpers/eval-budgets';
import { E2E_TOUCHFILES } from './helpers/touchfiles';
const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-office-hours-phase4.test.ts'), 'utf8'); const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-office-hours-phase4.test.ts'), 'utf8');
const question = (word = 'architectural', options = 'A) Put retrieval on the server\nB) Put retrieval on the client') => const question = (word = 'architectural', options = 'A) Put retrieval on the server\nB) Put retrieval on the client') =>
`Where should retrieval live?\nThis ${word} choice decides which component owns the retrieval algorithm and the cross-host API contract.\n${options}\nRecommendation: A because all hosts need a consistent algorithm with one owner.\n`; `Where should retrieval live?\nThis ${word} choice decides which component owns the retrieval algorithm and the cross-host API contract.\n${options}\nRecommendation: A because all hosts need a consistent algorithm with one owner.\n`;
@@ -98,7 +96,3 @@ test('Phase4 caller fixture retains fork validation under either path convention
expect(rejected.thrown).toBeDefined(); expect(rejected.judged).toBe(0); expect(rejected.rows[0].passed).toBe(false); expect(rejected.thrown).toBeDefined(); expect(rejected.judged).toBe(0); expect(rejected.rows[0].passed).toBe(false);
} }
}); });
test('Phase4 caller controls select only the existing Phase4 paid owner', () => {
expect(Object.entries(E2E_TOUCHFILES).filter(([,paths])=>paths.includes('test/office-hours-phase4-caller.test.ts')).map(([name])=>name)).toEqual(['office-hours-phase4-fork']);
});
-5
View File
@@ -2,7 +2,6 @@ import { expect, test } from 'bun:test';
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import { CAPTURE_MS, CAPTURE_LONG_MS } from './helpers/eval-budgets'; import { CAPTURE_MS, CAPTURE_LONG_MS } from './helpers/eval-budgets';
import { E2E_TOUCHFILES } from './helpers/touchfiles';
import { OFFICE_HOURS_BUN_GRACE_MS, runRecordedOfficeHoursAttempt } from './helpers/office-hours-attempt'; import { OFFICE_HOURS_BUN_GRACE_MS, runRecordedOfficeHoursAttempt } from './helpers/office-hours-attempt';
const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-office-hours.test.ts'), 'utf8'); const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-office-hours.test.ts'), 'utf8');
@@ -114,7 +113,3 @@ test('posture consecutive failed and passing callbacks retain separate final ver
expect(x.records[0].judge_scores).toEqual({ axis_a: 4, axis_b: 3 }); expect(x.records[1].judge_scores).toEqual({ axis_a: 4, axis_b: 4 }); expect(x.records[0].judge_scores).toEqual({ axis_a: 4, axis_b: 3 }); expect(x.records[1].judge_scores).toEqual({ axis_a: 4, axis_b: 4 });
} }
}); });
test('posture recorder controls select exactly the two existing paid owners', () => {
expect(Object.entries(E2E_TOUCHFILES).filter(([, paths]) => paths.includes('test/office-posture-recording.test.ts')).map(([name]) => name)).toEqual([...owners]);
});
-7
View File
@@ -6,7 +6,6 @@ import { spawnSync } from 'node:child_process';
import { createPendingQuestionRecorder, recordPendingQuestion, readPendingQuestion, import { createPendingQuestionRecorder, recordPendingQuestion, readPendingQuestion,
pendingQuestionRecorderStatus } from './helpers/plan-count-pending-question'; pendingQuestionRecorderStatus } from './helpers/plan-count-pending-question';
import { readPlanCountTranscript } from './helpers/plan-count-transcript'; import { readPlanCountTranscript } from './helpers/plan-count-transcript';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import captured from './fixtures/pending-question-completion-ad.json'; import captured from './fixtures/pending-question-completion-ad.json';
// Public question/result contents are retained; hook envelopes, paths and live // Public question/result contents are retained; hook envelopes, paths and live
@@ -186,10 +185,4 @@ describe('scoped pending question completion payloads', () => {
expect(f.status()).toEqual({status:'idle'});expect(f.read()).toBeUndefined(); expect(f.status()).toEqual({status:'idle'});expect(f.read()).toBeUndefined();
} finally {f.dispose();} } finally {f.dispose();}
}); });
test('the completion regression and fixture select exactly the two opted-in paid workflows', () => {
for(const file of ['test/pending-question-completion.test.ts','test/fixtures/pending-question-completion-ad.json']) {
expect(selectTests([file],E2E_TOUCHFILES,[]).selected.sort()).toEqual(['plan-ceo-mode-routing']);
}
});
}); });
-708
View File
@@ -1,708 +0,0 @@
import { describe, expect, test } from 'bun:test';
import { E2E_TIERS, E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES, selectTests } from './helpers/touchfiles';
import { OVERLAY_FIXTURES } from './fixtures/overlay-nudges';
describe('periodic fixture dependencies select their behavioral cases', () => {
const cases: Array<[string, string[]]> = [
['test/ceo-expansion-pacing-native.test.ts', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-expansion-pacing-fb10.json', ['plan-ceo-mode-routing']],
['test/helpers/ceo-hold-posture-review.ts', ['plan-ceo-mode-routing']],
['test/ceo-hold-posture-review.test.ts', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-hold-proof-fb10.json', ['plan-ceo-mode-routing']],
['test/eng-resolution-block-position.test.ts', ['plan-eng-multi-finding-batching']],
['test/fixtures/eng-a689-retry-public.json', ['plan-eng-multi-finding-batching']],
['test/fixtures/auto-decide-mode-selector-749df.json', ['auto-decide-preserved']],
['test/fixtures/eng-batching-prefixed-ledger-f359.json', ['plan-eng-multi-finding-batching']],
['test/fixtures/ceo-hold-preservation-f359.json', ['plan-ceo-mode-routing']],
['test/fixtures/auto-decide-completed-mode-f359.json', ['auto-decide-preserved']],
['test/review-count-markdown.test.ts', ['plan-eng-multi-finding-batching']],
['test/fixtures/review-count-markdown-6f.json', ['plan-eng-multi-finding-batching']],
['test/fixtures/eng-batching-expanded-ledger-6714.json', ['plan-eng-multi-finding-batching']],
['test/fixtures/eng-native-review-identities-6714.json', ['plan-eng-multi-finding-batching']],
['test/autoplan-dual-voice-fixture.test.ts', ['autoplan-dual-voice']],
['test/helpers/autoplan-dual-voice-evidence.ts', ['autoplan-dual-voice']],
['test/autoplan-dual-voice-evidence.test.ts', ['autoplan-dual-voice']],
['test/fixtures/autoplan-dual-false-positive-6bd.json', ['autoplan-dual-voice']],
['test/helpers/autoplan-method-read-audit.ts', ['autoplan-dual-voice']],
['test/fixtures/autoplan-method-read-aa-events.json', ['autoplan-dual-voice']],
['test/helpers/outside-voice-evidence.ts', ['autoplan-dual-voice', 'outside-plan-disabled-no-fallback',
'outside-voice-claude-code-to-codex', 'outside-voice-codex-to-claude-code']],
['test/fixtures/outside-async-task-m-events.json', ['autoplan-dual-voice',
'outside-voice-claude-code-to-codex', 'outside-voice-codex-to-claude-code']],
['test/autoplan-phase-handoff.test.ts', ['carve-section-loading', 'autoplan-dual-voice']],
['test/autoplan-amend-input.test.ts', ['carve-section-loading', 'autoplan-dual-voice']],
['test/fixtures/autoplan-amend-input-77.json', ['carve-section-loading', 'autoplan-dual-voice']],
['test/fixtures/autoplan-phase-handoff-6714.json', ['carve-section-loading', 'autoplan-dual-voice']],
['test/eng-finding-retry-budget.test.ts', ['plan-ceo-split-overflow', 'plan-eng-multi-finding-batching']],
['test/fixtures/ceo-expansion-pacing-77.json', ['plan-ceo-mode-routing']],
['test/fixtures/disabled-retained-record.json', ['outside-plan-disabled-no-fallback']],
['test/fixtures/ceo-expansion-posture-kind-dacc.json', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-expansion-pause-6714.json', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-expansion-complete-inventory-6f.json', ['plan-ceo-mode-routing']],
['test/ceo-mode-pending-submit.test.ts', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-mode-pending-submit.json', ['plan-ceo-mode-routing']],
['test/fixtures/ceo-fill-lifetime.json', ['plan-ceo-section-loading']],
['test/eng-batching-native-replay.test.ts', ['plan-eng-multi-finding-batching']],
['test/fixtures/eng-batching-native-8525.json', ['plan-eng-multi-finding-batching']],
['test/eng-batching-saved-ledger.test.ts', ['plan-eng-multi-finding-batching']],
['test/fixtures/eng-batching-saved-ledger-dacc.json', ['plan-eng-multi-finding-batching']],
['test/plan-design-sdk-fixture.test.ts', ['plan-design-review-plan-mode']],
['test/setup-gbrain-remote-caller.test.ts', ['setup-gbrain-remote']],
['test/skill-fixture.test.ts', ['journey-ideation', 'journey-plan-eng', 'journey-debug', 'journey-qa', 'journey-code-review', 'journey-ship', 'journey-docs', 'journey-retro', 'journey-design-system', 'journey-visual-qa', 'journey-negatives']],
['test/office-hours-writeback-env.test.ts', ['office-hours-brain-writeback']],
['test/helpers/setup-gbrain-sandbox.ts', ['setup-gbrain-bad-token', 'setup-gbrain-path4-local-pglite', 'setup-gbrain-remote']],
['test/helpers/setup-gbrain-fixture-command.ts', ['setup-gbrain-bad-token', 'setup-gbrain-path4-local-pglite']],
['test/gstack-paths.test.ts', ['carve-section-loading', 'design-html-slop-gate']],
['test/gstack-brain-context-load.test.ts', ['plan-ceo-section-loading']],
['test/fixtures/eng-file-permission-repaint.json', ['plan-eng-multi-finding-batching']],
['test/helpers/carve-section-case.ts', ['carve-section-loading']],
['test/helpers/carve-plan-fixture.ts', ['carve-section-loading']],
['test/carve-plan-fixture.test.ts', ['carve-section-loading']],
['test/fixtures/carve-existing-repository/src/repository.ts', ['carve-section-loading']],
['test/fixtures/carve-existing-repository/README.md', ['carve-section-loading']],
['test/fixtures/carve-existing-repository/example.ts', ['carve-section-loading']],
['test/codex-carve-fixture.test.ts', ['carve-section-loading']],
['test/design-html-section-completion.test.ts', ['carve-section-loading']],
['test/fixtures/design-html-section-complete.md', ['carve-section-loading']],
['test/plan-design-floor-fixture.test.ts', ['plan-design-finding-floor']],
['test/helpers/hermetic-env.test.ts', ['plan-ceo-split-overflow']],
['test/helpers/ceo-split-question-policy.ts', ['plan-ceo-split-overflow']],
['test/ceo-split-question-policy.test.ts', ['plan-ceo-split-overflow']],
['test/ceo-split-collection.test.ts', ['plan-ceo-split-overflow']],
['test/fixtures/ceo-split-collection-0bcd.json', ['plan-ceo-split-overflow']],
['test/fixtures/ceo-split-actor-6aef.json', ['plan-ceo-split-overflow']],
['test/helpers/ceo-mode-option.ts', ['plan-ceo-mode-routing', 'plan-ceo-split-overflow']],
['docs/askuserquestion-split.md', ['plan-ceo-split-overflow', 'plan-decision-classification', 'plan-devex-peer-comparison-classification']],
['test/resolver-ask-user-format.test.ts', ['plan-ceo-split-overflow']],
['test/section-capture-native-tools.test.ts', ['ship-section-loading', 'plan-ceo-section-loading', 'office-hours-section-loading', 'carve-section-loading']],
...['test/fixtures/webfetch-permission.json', 'test/plan-skill-webfetch-permission.test.ts'].map((file): [string, string[]] => [file,
[
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow'],
]),
['test/helpers/plan-mode-evidence.ts', ['plan-design-review-plan-mode', 'plan-eng-review-plan-mode']],
['test/plan-mode-evidence.test.ts', ['plan-design-review-plan-mode', 'plan-eng-review-plan-mode']],
...['overlay-measurement', 'overlay-workspace', 'overlay-attempt', 'overlay-case', 'overlay-case-policy', 'overlay-lifecycle'].map((helper): [string, string[]] => [
`test/helpers/${helper}.ts`, OVERLAY_FIXTURES.map(fixture => `overlay-harness-${fixture.id}`),
]),
];
for (const file of ['test/overlay-sdk-cancel-eof.test.ts', 'test/overlay-recording-order.test.ts', 'test/paid-overlay-scheduling.test.ts', 'test/fixtures/overlay-admission-child.ts']) {
cases.push([file, OVERLAY_FIXTURES.map(fixture => `overlay-harness-${fixture.id}`)]);
}
for (const fixture of OVERLAY_FIXTURES) {
cases.push([`test/skill-e2e-overlay-harness-${fixture.id}.test.ts`, [`overlay-harness-${fixture.id}`]]);
}
test('SDK runner changes retain the native gate and existing periodic consumers', () => {
const periodic = ['setup-gbrain-remote', 'setup-gbrain-bad-token',
'setup-gbrain-path4-local-pglite', ...OVERLAY_FIXTURES.map(fixture => `overlay-harness-${fixture.id}`)];
const result = selectTests(['test/agent-sdk-runner.test.ts'], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual(['auq-format-gate', ...periodic].sort());
expect(E2E_TIERS['auq-format-gate']).toBe('gate');
for (const id of periodic) expect(E2E_TIERS[id]).toBe('periodic');
});
test('test/review-army-budget.test.ts', () => {
const periodic = ['review-army-red-team', 'review-army-consensus'];
const result = selectTests(['test/review-army-budget.test.ts'], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual(['review-army-perf-n-plus-one', ...periodic].sort());
expect(E2E_TIERS['review-army-perf-n-plus-one']).toBe('gate');
for (const id of periodic) expect(E2E_TIERS[id]).toBe('periodic');
});
for (const [file, expected] of cases) {
test(file, () => {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual([...expected].sort());
for (const id of expected) expect(E2E_TIERS[id]).toBe('periodic');
});
}
});
test('Eng section local review helpers select their carve evaluation', () => {
for (const file of ['bin/gstack-review-log', 'bin/gstack-review-read', 'lib/review-evidence.ts',
'bin/gstack-slug', 'bin/gstack-wtree', 'bin/gstack-config', 'bin/gstack-brain-enqueue']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected).toContain('carve-section-loading');
}
expect(E2E_TIERS['carve-section-loading']).toBe('periodic');
});
test('offering source lookup dependencies select all four gate audits', () => {
const expected = ['codex-offered-office-hours', 'codex-offered-ceo-review',
'codex-offered-design-review', 'codex-offered-eng-review'].sort();
for (const file of ['test/helpers/codex-offering-fixture.ts', 'test/codex-offering-fixture.test.ts',
'test/fixtures/codex-offering-cdd-public.json', 'test/fixtures/codex-offering-timeout-public.json', 'test/helpers/workflow-judge-input.ts',
'test/workflow-judge-input.test.ts', 'test/helpers/workflow-excerpt.ts']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
const consumers = file === 'test/helpers/workflow-excerpt.ts'
? [...expected, 'ship-managed-hook-refresh', 'ship-unmanaged-hook-consent', 'ship-local-hook-preservation'].sort()
: expected;
expect(result.selected.sort()).toEqual(consumers);
for (const id of consumers) expect(E2E_TIERS[id]).toBe('gate');
}
for (const file of ['test/helpers/codex-offering-fixture.ts', 'test/codex-offering-fixture.test.ts',
'test/fixtures/codex-offering-cdd-public.json', 'test/fixtures/codex-offering-timeout-public.json']) {
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('shared attempt regressions select periodic callers and the gate report case', () => {
const periodic = ['plan-design-review-plan-mode', 'office-hours-forcing-energy', 'office-hours-builder-wildness', 'office-hours-brain-writeback', 'plan-ceo-review-format-mode', 'plan-ceo-review-format-approach', 'plan-eng-review-format-coverage', 'plan-eng-review-format-kind', 'plan-ceo-review-prosons-cadence', 'plan-review-prosons-format', 'plan-review-prosons-hardstop-neg', 'plan-review-prosons-neutral-neg', 'setup-gbrain-bad-token', 'setup-gbrain-path4-local-pglite', 'setup-gbrain-remote', 'review-army-red-team'];
const result = selectTests(['test/office-hours-attempt.test.ts'], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual([...periodic, 'plan-review-report'].sort());
for (const id of periodic) expect(E2E_TIERS[id]).toBe('periodic');
expect(E2E_TIERS['plan-review-report']).toBe('gate');
});
test('native fixture dependencies include the migrated auto-decision and seeded CEO smoke callers', () => {
const expected = [
'auto-decide-preserved',
'plan-ceo-finding-floor', 'plan-ceo-mode-routing', 'plan-ceo-review-plan-mode', 'plan-ceo-split-overflow',
'plan-design-finding-floor', 'plan-design-with-ui-scope',
'plan-devex-finding-floor',
'plan-eng-finding-floor', 'plan-eng-multi-finding-batching',
];
for (const file of ['test/helpers/plan-count-fixture.ts', 'test/plan-count-fixture.test.ts']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
expect(E2E_TIERS['auto-decide-preserved']).toBe('periodic');
expect(E2E_TIERS['plan-ceo-review-plan-mode']).toBe('gate');
});
test('shared native input dependencies select every PTY consumer without changing tiers', () => {
const expected = selectTests(['test/helpers/claude-pty-runner.ts'], E2E_TOUCHFILES).selected.sort();
expect(expected).toHaveLength(15);
expect(expected.filter(id => E2E_TIERS[id] === 'gate')).toHaveLength(7);
expect(expected.filter(id => E2E_TIERS[id] === 'periodic')).toHaveLength(8);
for (const file of ['test/plan-count-design-ui-recovery.test.ts', 'test/fixtures/design-ui-boxed-question.json', 'test/pty-workspace-trust.test.ts', 'test/fixtures/pty-companion-cli.ts',
'test/helpers/plan-skill-questions.ts', 'test/plan-skill-questions.test.ts', 'test/fixtures/design-tasks-bash-permission.json', 'test/fixtures/eng-auq-validation-error.json',
'test/helpers/plan-skill-question-events.ts', 'test/plan-skill-question-events.test.ts',
'test/helpers/plan-skill-question-hook-scope.ts', 'test/helpers/skill-census.ts', 'test/plan-skill-question-hook-scope.test.ts']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual(expected);
}
});
test('seed submission dependencies select every seeded caller with its existing tier', () => {
const expected = ['auto-decide-preserved', 'plan-ceo-review-plan-mode',
'plan-design-review-plan-mode', 'plan-devex-review-plan-mode', 'plan-eng-review-plan-mode', 'plan-mode-no-op'];
for (const file of ['test/helpers/fake-plan-seed.ts', 'test/helpers/plan-seed-submission.ts', 'test/plan-seed-submission.test.ts', 'test/fixtures/plan-seed-cli.ts']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual(expected);
}
expect(expected.map(id => E2E_TIERS[id])).toEqual(['periodic', 'gate', 'periodic', 'gate', 'periodic', 'gate']);
});
test('task emission source selects CEO completion consumers', () => {
const selected = selectTests(['scripts/resolvers/tasks-section.ts'], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
for (const id of [
'plan-ceo-finding-floor', 'plan-ceo-split-overflow',
'plan-ceo-section-loading', 'plan-ceo-review-plan-mode',
]) expect(selected.selected).toContain(id);
expect(selectTests(['scripts/resolvers/tasks-section.ts'], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
test('review report resolver selects every periodic completion consumer', () => {
const required = [
'plan-ceo-split-overflow',
'carve-section-loading', 'plan-ceo-section-loading', 'plan-eng-multi-finding-batching',
];
const result = selectTests(['scripts/resolvers/review.ts'], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
for (const id of required) {
expect(result.selected).toContain(id);
expect(E2E_TIERS[id]).toBe('periodic');
}
});
test('shared plan question source selects every generated review consumer', () => {
const source = 'scripts/resolvers/preamble/generate-ask-user-format.ts';
const renders = ['plan-ceo-review', 'plan-eng-review', 'plan-design-review', 'plan-devex-review']
.map(skill => `${skill}/SKILL.md`);
for (const map of [E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES]) {
const expected = selectTests(renders, map);
const actual = selectTests([source], map);
expect(expected.reason).toBe('diff');
expect(actual.reason).toBe('diff');
expect(expected.selected.length).toBeGreaterThan(0);
expect(expected.selected.filter(id => !actual.selected.includes(id))).toEqual([]);
}
});
test('Eng approval-rule source and free contract controls select every declared Eng consumer', () => {
const expected = [
'plan-eng-review',
'plan-eng-review-artifact',
'plan-review-report',
'plan-eng-review-plan-mode',
'plan-mode-no-op',
'carve-section-loading',
'plan-eng-finding-floor',
'plan-eng-multi-finding-batching',
'plan-eng-review-format-coverage',
'plan-eng-review-format-kind',
'plan-ceo-review-prosons-cadence',
'plan-review-prosons-format',
'codex-offered-eng-review',
'plan-eng-coverage-audit',
'autoplan-dual-voice'
];
for (const file of ['plan-eng-review/sections/review-sections.md.tmpl', 'scripts/resolvers/review.ts', 'test/plan-review-cases.test.ts']) {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
for (const id of expected) expect(result.selected, `${file}: ${id}`).toContain(id);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toContain('plan-eng-review/SKILL.md sections');
}
});
// This actor is used by the bounded native Design UI case, not the optional
// outside-review evaluations. Its captured inputs must select that same case.
test('Design native-only actor capture selects its gate case', () => {
const result = selectTests(['test/fixtures/design-outside-voices-question.json'], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected).toEqual(['plan-design-with-ui-scope']);
expect(E2E_TIERS['plan-design-with-ui-scope']).toBe('gate');
});
test('native compact-boundary ancestry selects every consuming callback', () => {
const expected = [
'plan-ceo-mode-routing',
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow',
'plan-design-with-ui-scope', 'plan-design-review-plan-mode', 'plan-eng-review-plan-mode',
'auto-decide-preserved', ].sort();
for (const file of ['test/helpers/plan-count-transcript.ts', 'test/plan-count-session-cwd.test.ts']) {
const selected = selectTests([file], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
expect(selected.selected.sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('same-plan expansion disposition replay selects the existing mode helper consumers', () => {
for (const dependency of ['test/ceo-mode-expansion-disposition.test.ts', 'test/fixtures/ceo-expansion-disposition-77.json']) {
expect([...selectTests([dependency], E2E_TOUCHFILES).selected].sort()).toEqual(['plan-ceo-mode-routing']);
expect(selectTests([dependency], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('structured auto-decision evidence selects every native observer', () => {
const expected = ['auto-decide-preserved', 'plan-ceo-review-plan-mode',
'plan-design-review-plan-mode', 'plan-devex-review-plan-mode', 'plan-eng-review-plan-mode', 'plan-mode-no-op'];
for (const file of ['test/fixtures/auto-decide-structured-77.json',
'test/helpers/auto-decision-state.ts', 'test/fixtures/auto-decide-state-cab3.json']) {
expect([...selectTests([file], E2E_TOUCHFILES).selected].sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
for (const file of ['bin/gstack-question-log', 'bin/gstack-question-preference']) {
const producers = selectTests([file], E2E_TOUCHFILES).selected;
for (const id of expected) expect(producers).toContain(id);
}
});
test('explanatory native mode evidence selects all observers with their existing tiers', () => {
const expected = ['auto-decide-preserved', 'office-hours-auto-mode',
'plan-ceo-review-plan-mode', 'plan-design-review-plan-mode', 'plan-devex-review-plan-mode',
'plan-eng-review-plan-mode', 'plan-mode-no-op'];
for (const file of ['test/helpers/native-auto-decide.ts', 'test/native-auto-decide.test.ts',
'test/fixtures/auto-decide-current-declaration-6aef.json', 'test/native-auto-decide.test.ts',
'test/fixtures/auto-decide-explanatory-mode-043a.json', 'test/fixtures/auto-decide-explanatory-mode-749df.json']) {
expect([...selectTests([file], E2E_TOUCHFILES).selected].sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
expect(expected.map(id => E2E_TIERS[id])).toEqual([
'periodic', 'gate', 'gate', 'periodic', 'gate', 'periodic', 'gate',
]);
});
// The workflow judge includes all carved sections, including those outside the
// entrypoint marker window (readWorkflowJudgeInput).
test('CEO carved sections select the judge that consumes their complete content', () => {
for (const file of [
'plan-ceo-review/sections/review-sections.md.tmpl',
'plan-ceo-review/sections/review-sections.md',
]) {
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected)
.toEqual(['plan-ceo-review/SKILL.md modes']);
}
});
test('file supervision regression selects all affected callers with their existing tiers', () => {
const gate = [
'codex-offered-ceo-review', 'codex-offered-design-review', 'codex-offered-eng-review',
'codex-offered-office-hours', 'office-hours-spec-review', 'plan-ceo-finding-floor',
'plan-ceo-review-benefits', 'plan-devex-finding-floor', 'plan-mode-no-op', 'plan-review-report',
];
const periodic = [
'auto-decide-preserved', 'plan-ceo-mode-routing',
'plan-ceo-review', 'plan-ceo-review-expansion-energy', 'plan-ceo-review-format-approach',
'plan-ceo-review-format-mode', 'plan-ceo-review-prosons-cadence', 'plan-ceo-review-selective',
'plan-design-finding-floor', 'plan-eng-finding-floor', 'plan-eng-review', 'plan-eng-review-artifact',
'plan-eng-review-format-coverage', 'plan-eng-review-format-kind', 'plan-eng-review-plan-mode',
'plan-review-prosons-format', 'plan-review-prosons-hardstop-neg', 'plan-review-prosons-neutral-neg',
];
const changed = ['test/paid-retry-supervision.test.ts'];
const result = selectTests(changed, E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual([...gate, ...periodic].sort());
for (const id of gate) expect(E2E_TIERS[id]).toBe('gate');
for (const id of periodic) expect(E2E_TIERS[id]).toBe('periodic');
expect(selectTests(changed, LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
test('floor permissions and large-report fixtures select their actual consumers', () => {
const floors = ['plan-ceo-finding-floor', 'plan-eng-finding-floor', 'plan-design-finding-floor', 'plan-devex-finding-floor'];
for (const file of ['test/plan-floor-permission.test.ts', 'test/fixtures/plan-floor-permission-fb10.json'])
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual([...floors].sort());
const filePermissionConsumers = selectTests(['test/helpers/plan-count-file-permission.ts'], E2E_TOUCHFILES).selected;
expect(filePermissionConsumers.sort()).toEqual([...floors,
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow'].sort());
expect(selectTests(['test/fixtures/ceo-report-permission-fb10.json'], E2E_TOUCHFILES).selected.sort())
.toEqual(filePermissionConsumers);
expect(E2E_TIERS['plan-ceo-finding-floor']).toBe('gate');
expect(E2E_TIERS['plan-devex-finding-floor']).toBe('gate');
expect(E2E_TIERS['plan-eng-finding-floor']).toBe('periodic');
expect(E2E_TIERS['plan-design-finding-floor']).toBe('periodic');
});
// These existing permission checks now also serve gate floor actors.
for (const file of ['test/plan-count-cropped-wrap.test.ts', 'test/fixtures/plan-count-cropped-wrap-6714.json']) {
test(file, () => {
const gate = ['plan-ceo-finding-floor', 'plan-devex-finding-floor'];
const periodic = [
'plan-eng-multi-finding-batching', 'plan-ceo-split-overflow',
'plan-eng-finding-floor', 'plan-design-finding-floor'];
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff');
expect(result.selected.sort()).toEqual([...gate, ...periodic].sort());
for (const id of gate) expect(E2E_TIERS[id]).toBe('gate');
for (const id of periodic) expect(E2E_TIERS[id]).toBe('periodic');
});
}
// Shared harness repairs must select every existing consumer, including gate floors.
const nativeRepairDependencies = [
{
"name": "AUTO mode declarations",
"files": [
"test/native-auto-decide.test.ts",
"test/fixtures/auto-decide-recommendation-361c.json",
"test/native-auto-decide.test.ts",
"test/fixtures/auto-decide-target-361c.json"
],
"owners": [
"plan-ceo-review-plan-mode",
"plan-eng-review-plan-mode",
"plan-design-review-plan-mode",
"plan-devex-review-plan-mode",
"plan-mode-no-op",
"office-hours-auto-mode",
"auto-decide-preserved",
]
},
{
"name": "owned cropped Create previews",
"files": [
"test/plan-create-permission.test.ts",
"test/fixtures/plan-create-permission-361c.json"
],
"owners": [
"plan-eng-finding-floor",
"plan-ceo-finding-floor",
"plan-design-finding-floor",
"plan-devex-finding-floor",
"plan-eng-multi-finding-batching",
"plan-ceo-split-overflow"
]
},
{
"name": "split native question and report permission",
"files": [
"test/fixtures/ceo-split-padding-361c-public.json",
"test/fixtures/ceo-split-edit-permission-361c-public.json"
],
"owners": [
"plan-ceo-split-overflow"
]
},
{
"name": "finding-qualified floors",
"files": [
"test/helpers/plan-floor-review.ts",
"test/plan-floor-review.test.ts",
"test/fixtures/plan-floor-routing-361c.json"
],
"owners": [
"plan-ceo-finding-floor",
"plan-eng-finding-floor",
"plan-design-finding-floor",
"plan-devex-finding-floor"
]
},
{
"name": "complete long native Edit panes",
"files": [
"test/plan-count-long-edit.test.ts",
"test/fixtures/plan-count-long-edit-0bcd.json"
],
"owners": [
"plan-eng-finding-floor",
"plan-ceo-finding-floor",
"plan-design-finding-floor",
"plan-devex-finding-floor",
"plan-eng-multi-finding-batching",
"plan-ceo-split-overflow"
]
},
{
"name": "native border on truncated questions",
"files": [
"test/plan-count-truncated-border.test.ts",
"test/fixtures/eng-d2-truncated-border-0bcd.json"
],
"owners": [
"plan-ceo-review-plan-mode",
"plan-eng-review-plan-mode",
"plan-design-review-plan-mode",
"plan-devex-review-plan-mode",
"plan-mode-no-op",
"office-hours-auto-mode",
"auto-decide-preserved",
"plan-ceo-mode-routing",
"plan-design-with-ui-scope",
"plan-eng-finding-floor",
"plan-ceo-finding-floor",
"plan-design-finding-floor",
"plan-devex-finding-floor",
"plan-eng-multi-finding-batching",
"plan-ceo-split-overflow"
]
}
];
for (const group of nativeRepairDependencies) {
test(`native repair dependencies: ${group.name}`, () => {
for (const file of group.files) {
const selected = selectTests([file], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
expect(selected.selected.sort()).toEqual([...group.owners].sort());
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
}
test('native repair dependencies preserve every original tier', () => {
expect(E2E_TIERS).toMatchObject({
"plan-ceo-review-plan-mode": "gate",
"plan-eng-review-plan-mode": "periodic",
"plan-design-review-plan-mode": "periodic",
"plan-devex-review-plan-mode": "gate",
"plan-mode-no-op": "gate",
"office-hours-auto-mode": "gate",
"auto-decide-preserved": "periodic",
"plan-eng-finding-floor": "periodic",
"plan-ceo-finding-floor": "gate",
"plan-design-finding-floor": "periodic",
"plan-devex-finding-floor": "gate",
"plan-eng-multi-finding-batching": "periodic",
"plan-ceo-split-overflow": "periodic",
"plan-ceo-mode-routing": "periodic",
"plan-devex-peer-comparison-classification": "periodic",
"plan-decision-classification": "periodic"
});
});
// These dependency edges do not create new paid identities. Reuse of unchanged
// model inputs is qualified separately before a paid run.
test('promoted public transcript decoder keeps its actual callers selected', () => {
const expected = [
'plan-eng-review-plan-mode',
'plan-design-review-plan-mode',
'auto-decide-preserved',
'plan-ceo-mode-routing',
'plan-design-with-ui-scope',
'plan-eng-multi-finding-batching',
'plan-ceo-split-overflow',
'plan-ceo-finding-floor',
'plan-eng-finding-floor',
'plan-design-finding-floor',
'plan-devex-finding-floor',
];
expect(selectTests(['lib/claude-public-transcript.ts'], E2E_TOUCHFILES).selected.sort())
.toEqual(expected.sort());
expect(selectTests(['lib/claude-public-transcript.ts'], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
test('combined Create captures select the existing owned file-permission consumers', () => {
const expected = [
'plan-eng-finding-floor',
'plan-ceo-finding-floor',
'plan-design-finding-floor',
'plan-devex-finding-floor',
'plan-eng-multi-finding-batching',
'plan-ceo-split-overflow',
];
for (const file of ['test/plan-create-combined-permission.test.ts',
'test/fixtures/plan-create-combined-permission-70b.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual([...expected].sort());
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('floor quotation evidence selects four assessors and product-type evidence selects only DX', () => {
const floors = [
'plan-ceo-finding-floor',
'plan-eng-finding-floor',
'plan-design-finding-floor',
'plan-devex-finding-floor',
];
expect(selectTests(['test/fixtures/plan-floor-quote-70b.json'], E2E_TOUCHFILES).selected.sort())
.toEqual([...floors].sort());
expect(selectTests(['test/fixtures/plan-floor-product-type-70b.json'], E2E_TOUCHFILES).selected)
.toEqual(['plan-devex-finding-floor']);
for (const file of ['test/plan-floor-review.test.ts', 'test/plan-floor-permission.test.ts'])
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual([...floors].sort());
for (const file of ['test/fixtures/plan-floor-quote-70b.json', 'test/fixtures/plan-floor-product-type-70b.json'])
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
expect(E2E_TIERS['plan-ceo-finding-floor']).toBe('gate');
expect(E2E_TIERS['plan-devex-finding-floor']).toBe('gate');
expect(E2E_TIERS['plan-design-finding-floor']).toBe('periodic');
expect(E2E_TIERS['plan-eng-finding-floor']).toBe('periodic');
});
test('DX custom setup transport selects its existing floor case without quality resampling', () => {
for (const file of ['test/plan-floor-dx-actor.test.ts', 'test/fixtures/plan-floor-dx-custom-491.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected).toEqual(['plan-devex-finding-floor']);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('numbered native-menu captures select the existing parser consumers', () => {
const expected = Object.entries(E2E_TOUCHFILES)
.filter(([, files]) => files.includes('test/plan-skill-questions.test.ts'))
.map(([id]) => id).sort();
expect(expected).toHaveLength(15);
for (const file of ['test/pty-numbered-option-indent-native.test.ts',
'test/fixtures/ceo-split-e5-numbered-description-491.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('pending native Write captures select the existing owned-permission consumers', () => {
const expected = Object.entries(E2E_TOUCHFILES)
.filter(([, files]) => files.includes('test/plan-create-combined-permission.test.ts'))
.map(([id]) => id).sort();
expect(expected).toHaveLength(6);
for (const file of ['test/plan-create-prepublication.test.ts',
'test/fixtures/plan-create-prepublication-491.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
});
test('stderr lifecycle regression selects runtime consumers without a quality-map edge', () => {
const expected = [
'browse-basic', 'browse-snapshot', 'aside-browse-basic', 'aside-browse-flow', 'aside-qa-quick',
'aside-scrape-json', 'aside-canary-quick', 'hermetic-canary', 'hermetic-sentinel', 'first-task-scaffold',
'skillmd-setup-discovery', 'skillmd-no-local-binary', 'skillmd-outside-git', 'session-awareness', 'operational-learning',
'qa-quick', 'qa-b6-static', 'qa-b7-spa', 'qa-b8-checkout', 'qa-only-no-fix',
'qa-fix-loop', 'qa-bootstrap', 'review-sql-injection', 'review-enum-completeness', 'review-base-branch',
'review-design-lite', 'review-army-migration-safety', 'review-army-perf-n-plus-one', 'review-army-delivery-audit', 'review-army-quality-score',
'review-army-json-findings', 'review-army-red-team', 'review-army-simplification', 'review-army-simplification-precision', 'review-army-consensus',
'office-hours-spec-review', 'office-hours-forcing-energy', 'office-hours-builder-wildness', 'plan-ceo-review', 'plan-ceo-review-selective',
'plan-ceo-review-benefits', 'plan-ceo-review-expansion-energy', 'plan-eng-review', 'plan-eng-review-artifact', 'plan-review-report',
'plan-design-review-plan-mode', 'office-hours-phase4-fork', 'auq-format-gate', 'tpa-present', 'tpa-absent-linux',
'tpa-broken', 'tpa-absent-darwin', 'tpa-apple-ban', 'ship-section-loading', 'plan-ceo-section-loading',
'carve-section-loading', 'setup-gbrain-remote', 'setup-gbrain-bad-token', 'setup-gbrain-path4-local-pglite', 'plan-ceo-review-format-mode',
'plan-ceo-review-format-approach', 'plan-eng-review-format-coverage', 'plan-eng-review-format-kind', 'plan-ceo-review-prosons-cadence', 'plan-review-prosons-format',
'plan-review-prosons-hardstop-neg', 'plan-review-prosons-neutral-neg', 'plan-tune-inspect', 'codex-offered-office-hours', 'codex-offered-ceo-review',
'codex-offered-design-review', 'codex-offered-eng-review', 'ship-base-branch', 'ship-local-workflow', 'review-dashboard-via',
'retro', 'retro-base-branch', 'cso-full-audit', 'cso-diff-mode', 'cso-infra-scope',
'learnings-show', 'timeline-event-flow', 'context-recovery-artifacts', 'context-save-writes-file', 'context-restore-loads-latest',
'context-save-routing', 'context-save-then-restore-roundtrip', 'context-restore-fragment-match', 'context-restore-empty-state', 'context-restore-list-delegates',
'context-restore-legacy-compat', 'context-save-list-current-branch', 'context-save-list-all-branches', 'document-release', 'codex-review',
'outside-voice-codex-to-claude-code', 'outside-voice-claude-code-to-codex', 'outside-plan-disabled-no-fallback', 'ship-coverage-audit', 'review-coverage-audit',
'plan-eng-coverage-audit', 'ship-triage', 'ship-docsync', 'docsync-spawned', 'design-consultation-core',
'design-consultation-existing', 'design-consultation-research', 'design-consultation-preview', 'plan-design-review-no-ui-scope', 'design-review-fix',
'design-review-detector-shim', 'design-review-detector-shim-dom', 'design-review-plugin-handoff', 'design-html-slop-gate', 'diagram-triplet', 'diagram-authoring-quality',
'gstack-upgrade-happy-path', 'land-and-deploy-workflow', 'land-and-deploy-first-run', 'land-and-deploy-review-gate', 'canary-workflow',
'benchmark-workflow', 'setup-deploy-workflow', 'autoplan-dual-voice', 'scrape-match-path', 'scrape-prototype-path',
'skillify-happy-path', 'skillify-provenance-refusal', 'skillify-approval-reject', 'journey-ideation', 'journey-plan-eng',
'journey-debug', 'journey-qa', 'journey-code-review', 'journey-ship', 'journey-docs',
'journey-retro', 'journey-design-system', 'journey-visual-qa', 'journey-negatives',
'office-hours-brain-writeback', 'arm-benchmark-native-overbuild', 'arm-benchmark-crud-endpoint', 'arm-benchmark-bugfix-decoys', 'office-hours-section-loading',
];
const file = 'test/session-runner-stream-lifecycle.test.ts';
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(expected.sort());
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
test('collection completion lifecycle selects the existing native counter consumers', () => {
const selected = selectTests(['test/plan-count-collection-completion.test.ts'], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
expect(selected.selected.length).toBeGreaterThan(0);
expect(selected.selected.sort()).toEqual(
selectTests(['test/plan-count-timeout.test.ts'], E2E_TOUCHFILES).selected.sort());
expect(selectTests(['test/plan-count-collection-completion.test.ts'], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
for (const file of ['test/plan-count-cross-cwd-ancestry.test.ts', 'test/fixtures/plan-count-cross-cwd-ancestry-0bcd.json']) {
test(`${file} selects native cwd continuation consumers`, () => {
const selected = selectTests([file], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
expect(selected.selected.sort()).toEqual([
'auto-decide-preserved', 'plan-ceo-mode-routing', 'plan-ceo-split-overflow',
'plan-design-review-plan-mode', 'plan-design-with-ui-scope',
'plan-eng-multi-finding-batching',
'plan-eng-review-plan-mode',
].sort());
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
});
}
test('native clipped regressions retain the existing parser and owned-permission selection', () => {
for (const [dependency, count, files] of [
['test/helpers/claude-pty-runner.ts', 15, [
'test/plan-count-clipped-elision.test.ts', 'test/fixtures/eng-d1-clipped-elision-1579.json', 'test/fixtures/eng-d2-planning-prelude-4d.json',
]],
['test/helpers/plan-count-file-permission.ts', 6, [
'test/plan-edit-cropped-permission.test.ts', 'test/fixtures/plan-edit-cropped-permission-1579.json',
]],
] as const) {
const expected = selectTests([dependency], E2E_TOUCHFILES).selected.sort();
expect(expected).toHaveLength(count);
for (const file of files) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(expected);
expect(selectTests([file], LLM_JUDGE_TOUCHFILES).selected).toEqual([]);
}
}
});
-8
View File
@@ -20,9 +20,6 @@ import os_ceo_handoff_y from 'node:os';
import path_ceo_handoff_y from 'node:path'; import path_ceo_handoff_y from 'node:path';
import fixture_ceo_handoff_y from './fixtures/ceo-handoff-y-call.json'; import fixture_ceo_handoff_y from './fixtures/ceo-handoff-y-call.json';
import captured_dx_manual_handoff_ao from './fixtures/dx-manual-handoff-ao.json'; import captured_dx_manual_handoff_ao from './fixtures/dx-manual-handoff-ao.json';
import { E2E_TOUCHFILES } from './helpers/touchfiles-data';
import { LLM_JUDGE_TOUCHFILES } from './helpers/touchfiles-data';
import { GLOBAL_TOUCHFILES } from './helpers/touchfiles-data';
import fixture_plan_count_dx_handoff_o from './fixtures/devex-handoff-o-call.json'; import fixture_plan_count_dx_handoff_o from './fixtures/devex-handoff-o-call.json';
import actual_eng_next_handoff_ah from './fixtures/eng-next-handoff-ah.json'; import actual_eng_next_handoff_ah from './fixtures/eng-next-handoff-ah.json';
import { isCurrentPlanApprovalScreen } from './helpers/plan-count-pending-exit'; import { isCurrentPlanApprovalScreen } from './helpers/plan-count-pending-exit';
@@ -1148,11 +1145,6 @@ function change(call:NativePlanQuestionCall,from:string,to:string){
const selected=call.answers![q.question];q.question=q.question.replace(from,to);call.answers={[q.question]:selected!}; const selected=call.answers![q.question];q.question=q.question.replace(from,to);call.answers={[q.question]:selected!};
} }
describe('AO completed manual DX handoff preserves report freshness',()=>{ describe('AO completed manual DX handoff preserves report freshness',()=>{
test('shared completion callers register the regression with dense literal paths',()=>{
const arrays=[...Object.values(E2E_TOUCHFILES),...Object.values(LLM_JUDGE_TOUCHFILES),GLOBAL_TOUCHFILES];
expect(arrays).toHaveLength(216);
for(const values of arrays)for(let i=0;i<values.length;i++)expect(typeof values[i]).toBe('string');
});
test('exact owned report precedes navigation only, with the current Exit gate recognized',()=>{ test('exact owned report precedes navigation only, with the current Exit gate recognized',()=>{
expect(captured.calls).toHaveLength(2);expect(captured.events).toHaveLength(4); expect(captured.calls).toHaveLength(2);expect(captured.events).toHaveLength(4);
expect(Date.parse(captured.calls[0]!.answeredAt!)).toBeLessThan(captured.provenance.reportMtimeMs); expect(Date.parse(captured.calls[0]!.answeredAt!)).toBeLessThan(captured.provenance.reportMtimeMs);
+1 -14
View File
@@ -219,11 +219,6 @@ import capturedAh_plan_count_permission_ac from './fixtures/plan-count-permissio
import { currentFilePermissionBinding } from './helpers/plan-count-file-permission'; import { currentFilePermissionBinding } from './helpers/plan-count-file-permission';
import exact_plan_count_quoted_frame_ak from './fixtures/plan-count-quoted-frame-ak.json'; import exact_plan_count_quoted_frame_ak from './fixtures/plan-count-quoted-frame-ak.json';
import owned_plan_count_quoted_frame_ak from './fixtures/plan-count-owned-permission-v.json'; import owned_plan_count_quoted_frame_ak from './fixtures/plan-count-owned-permission-v.json';
test('AD v2 cropped target fixture selects all existing file-permission consumers',()=>{
expect(selectTests(['test/fixtures/plan-count-permission-target-ad-v2.json'],E2E_TOUCHFILES,[]).selected)
.toEqual(selectTests(['test/plan-count-file-permission.test.ts'],E2E_TOUCHFILES,[]).selected);
});
describe('batching-permission-at', () => { describe('batching-permission-at', () => {
const fs = fs_batching_permission_at; const fs = fs_batching_permission_at;
const os = os_batching_permission_at; const os = os_batching_permission_at;
@@ -723,13 +718,7 @@ for (const c of cases) {
} }
}); });
} }
test('AE crop admits one native divider only', () => {
test('AD crop fixture selects the exact existing permission regression callers', () => {
expect(selectTests(['test/fixtures/plan-count-permission-ad.json'], E2E_TOUCHFILES).selected.sort()).toEqual(
selectTests(['test/fixtures/plan-count-permission-ac.json'], E2E_TOUCHFILES).selected.sort());
});
test('AE crop admits one native divider only and preserves its exact existing caller selection', () => {
const c = cases.find(item => item.p.pid === capturedAe.pid)!; const c = cases.find(item => item.p.pid === capturedAe.pid)!;
const firstLine = c.screen.slice(0, c.screen.indexOf('\n') + 1); const firstLine = c.screen.slice(0, c.screen.indexOf('\n') + 1);
for (const screen of [firstLine + c.screen, 'unrelated prose\n' + c.screen, for (const screen of [firstLine + c.screen, 'unrelated prose\n' + c.screen,
@@ -738,8 +727,6 @@ test('AE crop admits one native divider only and preserves its exact existing ca
expect(adEpoch(c, screen)).toBeNull(); expect(adEpoch(c, screen)).toBeNull();
expect(createPlanCountPermissionGuard()(screen, '', adEpoch(c, screen))).not.toBe('grant'); expect(createPlanCountPermissionGuard()(screen, '', adEpoch(c, screen))).not.toBe('grant');
} }
expect(selectTests(['test/fixtures/plan-count-permission-ae.json'], E2E_TOUCHFILES).selected.sort()).toEqual(
selectTests(['test/fixtures/plan-count-permission-ad.json'], E2E_TOUCHFILES).selected.sort());
}); });
test('AH wrapped crop admits four or five spaces with the same owned native epoch', () => { test('AH wrapped crop admits four or five spaces with the same owned native epoch', () => {
-7
View File
@@ -2,16 +2,9 @@ import {expect,test} from 'bun:test';
import {planFloorDXPane,planFloorDXReplyInput,matchesNativePlanQuestion,type PlanFloorDXReply} from './helpers/claude-pty-runner'; import {planFloorDXPane,planFloorDXReplyInput,matchesNativePlanQuestion,type PlanFloorDXReply} from './helpers/claude-pty-runner';
import captured from './fixtures/plan-floor-dx-custom-491.json'; import captured from './fixtures/plan-floor-dx-custom-491.json';
import editorHints from './fixtures/plan-floor-dx-editor-hint.json'; import editorHints from './fixtures/plan-floor-dx-editor-hint.json';
import {E2E_TOUCHFILES,selectTests} from './helpers/touchfiles';
const call=captured.call; const call=captured.call;
const state=(stage:PlanFloorDXReply['stage']='focus'):PlanFloorDXReply=>({call:structuredClone(call), const state=(stage:PlanFloorDXReply['stage']='focus'):PlanFloorDXReply=>({call:structuredClone(call),
pane:planFloorDXPane(captured.questionViewport,call)!,reply:captured.reply,stage}); pane:planFloorDXPane(captured.questionViewport,call)!,reply:captured.reply,stage});
test('editor-hint capture changes select the live DX finding-floor probe',()=>{
expect(selectTests(['test/fixtures/plan-floor-dx-editor-hint.json'],E2E_TOUCHFILES,[]).selected)
.toContain('plan-devex-finding-floor');
});
test('generic matcher authenticates the crop while DX custom replies still require the complete pane',()=>{ test('generic matcher authenticates the crop while DX custom replies still require the complete pane',()=>{
expect(matchesNativePlanQuestion(captured.originalViewport,call)).toBe(true); expect(matchesNativePlanQuestion(captured.originalViewport,call)).toBe(true);
expect(planFloorDXPane(captured.originalViewport,call)).toBeNull(); expect(planFloorDXPane(captured.originalViewport,call)).toBeNull();
-9
View File
@@ -5,8 +5,6 @@ import * as path from 'node:path';
import { pathToFileURL } from 'node:url'; import { pathToFileURL } from 'node:url';
import { readPlanFloorTarget } from './helpers/plan-floor-target'; import { readPlanFloorTarget } from './helpers/plan-floor-target';
import { createFakeBunCli } from './helpers/fake-bun-cli'; import { createFakeBunCli } from './helpers/fake-bun-cli';
import { selectTests, E2E_TOUCHFILES } from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
const SID = '11111111-2222-3333-4444-555555555555'; const SID = '11111111-2222-3333-4444-555555555555';
const START = Date.parse('2026-09-10T04:46:45Z'); const START = Date.parse('2026-09-10T04:46:45Z');
@@ -80,13 +78,6 @@ test('changed or linked plan, invalid clock, linked journal and oversized source
fs.unlinkSync(f.journal); fs.renameSync(real, f.journal); fs.truncateSync(f.journal, 32 * 1024 * 1024 + 1); expect(f.check().status).toBe('error'); fs.unlinkSync(f.journal); fs.renameSync(real, f.journal); fs.truncateSync(f.journal, 32 * 1024 * 1024 + 1); expect(f.check().status).toBe('error');
} finally { f.cleanup(); } } finally { f.cleanup(); }
}); });
test('new delivery helper and controls select all four existing floor owners', () => {
for (const file of ['test/helpers/plan-floor-target.ts', 'test/plan-floor-target.test.ts']) {
expect(selectTests([file], E2E_TOUCHFILES).selected.sort()).toEqual(['plan-ceo-finding-floor', 'plan-design-finding-floor', 'plan-devex-finding-floor', 'plan-eng-finding-floor']);
}
});
test('compiled fake CLI preserves Claude arguments and stdin without a shebang launcher', async () => { test('compiled fake CLI preserves Claude arguments and stdin without a shebang launcher', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'native-floor-cli-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'native-floor-cli-'));
try { try {
-31
View File
@@ -5,38 +5,7 @@ import * as path from 'node:path';
import { planDecisionCalibrations } from './fixtures/plan-decision-classification'; import { planDecisionCalibrations } from './fixtures/plan-decision-classification';
import { buildPlanReviewDecisionPrompt } from './helpers/plan-review-decisions'; import { buildPlanReviewDecisionPrompt } from './helpers/plan-review-decisions';
import { ENG_BATCHING_FINDINGS } from './helpers/plan-review-cases'; import { ENG_BATCHING_FINDINGS } from './helpers/plan-review-cases';
import { E2E_TOUCHFILES, E2E_TIERS, selectTests } from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
const IDS = ['plan-eng-multi-finding-batching', 'plan-ceo-split-overflow', 'plan-decision-classification'].sort();
test('semantic helper changes also select the separate DX analysis calibration', () => {
for (const file of ['test/helpers/plan-review-decisions.ts', 'test/plan-review-decisions.test.ts',
'test/helpers/plan-review-cases.ts', 'test/plan-review-cases.test.ts',
'test/skill-e2e-plan-decision-classification.test.ts', 'test/fixtures/plan-decision-classification.ts', 'test/plan-review-calibration.test.ts']) {
const shared = ['test/helpers/plan-review-decisions.ts', 'test/plan-review-decisions.test.ts',
'test/helpers/plan-review-cases.ts', 'test/plan-review-cases.test.ts'].includes(file);
const expected = shared ? [...IDS, 'plan-devex-peer-comparison-classification'] : [...IDS];
if (file === 'test/helpers/plan-review-decisions.ts' || file === 'test/plan-review-decisions.test.ts')
expected.push('plan-ceo-mode-routing');
// The UI gate now uses the shared picker for acknowledged native questions.
if (file === 'test/helpers/plan-review-cases.ts') expected.push('plan-design-with-ui-scope');
// plan-review-cases.test.ts also verifies the Eng template/renderer gate.
// Its direct behavioral consumers extend the unchanged helper-only set.
if (file === 'test/plan-review-cases.test.ts') expected.push(
'plan-eng-review', 'plan-eng-review-artifact', 'plan-review-report',
'plan-eng-review-plan-mode', 'plan-mode-no-op',
'carve-section-loading', 'plan-eng-finding-floor',
'plan-eng-review-format-coverage', 'plan-eng-review-format-kind',
'plan-ceo-review-prosons-cadence', 'plan-review-prosons-format',
'codex-offered-eng-review', 'plan-eng-coverage-audit', 'autoplan-dual-voice',
);
expect(selectTests([file], E2E_TOUCHFILES, []).selected.sort()).toEqual(
expected.sort());
}
for (const id of IDS) expect(E2E_TIERS[id]).toBe('periodic');
});
test('calibration briefs preserve source-required structure and actual choices without phase/qid reliance', () => { test('calibration briefs preserve source-required structure and actual choices without phase/qid reliance', () => {
const format = fs.readFileSync(path.join(ROOT, 'scripts/resolvers/preamble/generate-ask-user-format.ts'), 'utf8'); const format = fs.readFileSync(path.join(ROOT, 'scripts/resolvers/preamble/generate-ask-user-format.ts'), 'utf8');
const split = fs.readFileSync(path.join(ROOT, 'docs/askuserquestion-split.md'), 'utf8'); const split = fs.readFileSync(path.join(ROOT, 'docs/askuserquestion-split.md'), 'utf8');
-32
View File
@@ -10,7 +10,6 @@ import { fakePlanSeedPrelude } from './helpers/fake-plan-seed';
import { nativeSeededPlanSelection } from './helpers/plan-scope-selection'; import { nativeSeededPlanSelection } from './helpers/plan-scope-selection';
import { isScopeGateQuestionVisible } from './helpers/claude-pty-runner'; import { isScopeGateQuestionVisible } from './helpers/claude-pty-runner';
import { readPlanCountTranscript, type NativePublicToolEvent, type PlanCountTranscript } from './helpers/plan-count-transcript'; import { readPlanCountTranscript, type NativePublicToolEvent, type PlanCountTranscript } from './helpers/plan-count-transcript';
import { selectTests, E2E_TOUCHFILES } from './helpers/touchfiles';
import captured_design_scope_announcement_ao from './fixtures/design-scope-announcement-ao.json'; import captured_design_scope_announcement_ao from './fixtures/design-scope-announcement-ao.json';
import fixture_design_scope_declaration_ak from './fixtures/design-scope-declaration-ak.json'; import fixture_design_scope_declaration_ak from './fixtures/design-scope-declaration-ak.json';
import fs_design_scope_entry_aq from 'node:fs'; import fs_design_scope_entry_aq from 'node:fs';
@@ -163,14 +162,6 @@ test('design scope question still requires the actual branch option', () => {
expect(isScopeGateQuestionVisible('What should I design-review?')).toBe(false); expect(isScopeGateQuestionVisible('What should I design-review?')).toBe(false);
expect(isScopeGateQuestionVisible('I should design-review the current branch diff.')).toBe(false); expect(isScopeGateQuestionVisible('I should design-review the current branch diff.')).toBe(false);
}); });
test('seeded plan selection dependencies select the existing design and Eng mode checks', () => {
for (const file of ['test/helpers/plan-scope-selection.ts', 'test/plan-scope-selection.test.ts']) {
const selection = selectTests([file], E2E_TOUCHFILES);
expect(selection.selected).toContain('plan-design-review-plan-mode'); expect(selection.selected).toContain('plan-eng-review-plan-mode');
}
});
test('real PTY observation binds its explicit session and retains public diagnostics before cleanup', async () => { test('real PTY observation binds its explicit session and retains public diagnostics before cleanup', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scope-pty-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scope-pty-'));
const cli = createFakeBunCli(path.join(dir, 'fake-claude'), fakePlanSeedPrelude() + ` const cli = createFakeBunCli(path.join(dir, 'fake-claude'), fakePlanSeedPrelude() + `
@@ -274,13 +265,6 @@ test('AG completed selection still requires this parent and a successful prior s
expect(verdict(fixture(text), { ...opts, sessionId: '' })).toBe(false); expect(verdict(fixture(text), { ...opts, sessionId: '' })).toBe(false);
expect(verdict(fixture(text), { ...opts, seed: opts.seed + '\n# Another plan' })).toBe(false); expect(verdict(fixture(text), { ...opts, seed: opts.seed + '\n# Another plan' })).toBe(false);
}); });
test('AG actual scope fixture has exactly the existing two plan-mode owners', () => {
const selected = selectTests(['test/fixtures/design-plan-scope-ag.json'], E2E_TOUCHFILES).selected;
expect([...selected].sort()).toEqual(['plan-design-review-plan-mode', 'plan-eng-review-plan-mode']);
});
test('AG audit continuation cannot withdraw or relabel the current selection', () => { test('AG audit continuation cannot withdraw or relabel the current selection', () => {
const text = `I've selected reviewing the pasted "Marketing landing page" draft plan since we're in plan mode.`; const text = `I've selected reviewing the pasted "Marketing landing page" draft plan since we're in plan mode.`;
for (const tail of [ for (const tail of [
@@ -400,12 +384,6 @@ test('later current corrections defeat the draft selection while quoted history
expect(awCheck(p), text).toBe(true); expect(awCheck(p), text).toBe(true);
} }
}); });
test('the AW public fixture selects the existing scope helper owners without a new paid test', () => {
expect(selectTests(['test/fixtures/plan-scope-target-aw.json'], E2E_TOUCHFILES, []).selected)
.toEqual(selectTests(['test/helpers/plan-scope-selection.ts'], E2E_TOUCHFILES, []).selected);
});
// Exact public AZ intros; identities and timestamps use the existing synthetic fixture. // Exact public AZ intros; identities and timestamps use the existing synthetic fixture.
const spokenEngIntros = [ const spokenEngIntros = [
"I'll run the eng review skill against your draft plan.", "I'll run the eng review skill against your draft plan.",
@@ -863,16 +841,6 @@ test('a later explicit reselection follows the existing currentness rule', () =>
const p = input(), m = declaration(p); p.transcript.assistantMessages.push({ ...m, timestamp: new Date(Date.parse(m.timestamp) + 1000).toISOString(), text: 'This selection is withdrawn.' }); expect(verdict(p)).toBe(false); const p = input(), m = declaration(p); p.transcript.assistantMessages.push({ ...m, timestamp: new Date(Date.parse(m.timestamp) + 1000).toISOString(), text: 'This selection is withdrawn.' }); expect(verdict(p)).toBe(false);
p.transcript.assistantMessages.push({ ...m, timestamp: new Date(Date.parse(m.timestamp) + 2000).toISOString() }); expect(verdict(p)).toBe(true); p.transcript.assistantMessages.push({ ...m, timestamp: new Date(Date.parse(m.timestamp) + 2000).toISOString() }); expect(verdict(p)).toBe(true);
}); });
for (const owner of [
'plan-ceo-review-plan-mode', 'plan-eng-review-plan-mode',
'plan-design-review-plan-mode', 'plan-devex-review-plan-mode', 'plan-mode-no-op',
]) test(`scope dependency registration is dense for ${owner}`, () => {
const paths = E2E_TOUCHFILES[owner]!;
for (let index = 0; index < paths.length; index++) {
expect(Object.hasOwn(paths, index)).toBe(true);
expect(typeof paths[index]).toBe('string');
}
});
}); });
describe('plan-scope-recovery-av', () => { describe('plan-scope-recovery-av', () => {
-8
View File
@@ -8,8 +8,6 @@ import { setupQuestionEventSource, readPermissionRequestEvents } from './helpers
import retainedQuestionValidation from './fixtures/eng-auq-validation-error.json'; import retainedQuestionValidation from './fixtures/eng-auq-validation-error.json';
import retainedBashDirectory from './fixtures/bash-directory-permission.json'; import retainedBashDirectory from './fixtures/bash-directory-permission.json';
import retainedDesignTasksPermission from './fixtures/design-tasks-bash-permission.json'; import retainedDesignTasksPermission from './fixtures/design-tasks-bash-permission.json';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
const sessionId = '00000000-0000-4000-8000-000000000001'; const sessionId = '00000000-0000-4000-8000-000000000001';
const question: NativeQuestion = { question: 'D1 — Which approach?\nMake it reliable. Enforce the delivery policy.', header: 'Approach', multiSelect: false, const question: NativeQuestion = { question: 'D1 — Which approach?\nMake it reliable. Enforce the delivery policy.', header: 'Approach', multiSelect: false,
options: ['Extend dispatcher', 'Queue fanout', 'Minimal patch', 'Hold scope'].map(label => ({ label, description: label })) }; options: ['Extend dispatcher', 'Queue fanout', 'Minimal patch', 'Hold scope'].map(label => ({ label, description: label })) };
@@ -1858,12 +1856,6 @@ function bashHooks() {
return { source, input, response, emit, post, read }; return { source, input, response, emit, post, read };
} }
test('captured directory Bash permission fixture selects every existing permission-helper consumer', () => {
const selected = selectTests(['test/fixtures/bash-directory-permission.json'], E2E_TOUCHFILES);
expect(selected.reason).toBe('diff');
expect(selected.selected.sort()).toEqual(selectTests(['test/helpers/plan-skill-questions.ts'], E2E_TOUCHFILES).selected.sort());
});
test('captured directory Bash card requires its exact owned request and permits only one grant', () => { test('captured directory Bash card requires its exact owned request and permits only one grant', () => {
const { input, card, nativeId } = retainedBashDirectory; const { input, card, nativeId } = retainedBashDirectory;
const s = bashHooks(); s.emit('PreToolUse', nativeId, input); const s = bashHooks(); s.emit('PreToolUse', nativeId, input);
-7
View File
@@ -4,14 +4,7 @@ import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
import * as path from 'node:path'; import * as path from 'node:path';
import { spawnSync } from 'node:child_process'; import { spawnSync } from 'node:child_process';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
test('QA fixture regressions select only the QA fix loop', () => {
expect(selectTests(['test/qa-fix-loop-fixture.test.ts'], E2E_TOUCHFILES).selected).toEqual(['qa-fix-loop']);
});
test.each(['success', 'bash-edit', 'max-turns', 'no-edit', 'no-commit', 'runner', 'retry', 'directory', 'recording', 'late-timeout']) test.each(['success', 'bash-edit', 'max-turns', 'no-edit', 'no-commit', 'runner', 'retry', 'directory', 'recording', 'late-timeout'])
('QA attempt recording and fixture ownership: %s', scenario => { ('QA attempt recording and fixture ownership: %s', scenario => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'qa-fix-body-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'qa-fix-body-'));
-7
View File
@@ -3,14 +3,7 @@ import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
import * as path from 'node:path'; import * as path from 'node:path';
import {spawnSync} from 'node:child_process'; import {spawnSync} from 'node:child_process';
import {E2E_TOUCHFILES, selectTests} from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
test('QA-only capability regressions select the no-fix case', () => {
expect(selectTests(['test/qa-only-capability.test.ts'], E2E_TOUCHFILES).selected).toEqual(['qa-only-no-fix']);
});
test.each(['success', 'omitted-tools', 'report-edit', 'source-edit', 'source-write']) test.each(['success', 'omitted-tools', 'report-edit', 'source-edit', 'source-write'])
('QA-only registered capability and no-fix contract: %s', scenario => { ('QA-only registered capability and no-fix contract: %s', scenario => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'qa-tools-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'qa-tools-'));
-6
View File
@@ -3,8 +3,6 @@ import * as fs from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets'; import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets';
import { SESSION_DRAIN_GRACE_MS } from './helpers/session-runner'; import { SESSION_DRAIN_GRACE_MS } from './helpers/session-runner';
import { E2E_TOUCHFILES } from './helpers/touchfiles';
const source=fs.readFileSync(path.join(import.meta.dir,'skill-e2e-review-army.test.ts'),'utf8'); const source=fs.readFileSync(path.join(import.meta.dir,'skill-e2e-review-army.test.ts'),'utf8');
async function exercise(scenarios: Array<'success'|'timeout'|'wrong-report'|'browse-error'>, fixturePath = path) { async function exercise(scenarios: Array<'success'|'timeout'|'wrong-report'|'browse-error'>, fixturePath = path) {
const setups:any[]=[],done:any[]=[],callbacks:any[]=[],rows:any[]=[],calls:any[]=[]; const setups:any[]=[],done:any[]=[],callbacks:any[]=[],rows:any[]=[],calls:any[]=[];
@@ -61,7 +59,3 @@ test('Consensus caller fixture preserves success and semantic failure under eith
expect(x.rows.map(r=>r.passed)).toEqual([true,false]); expect(x.rows.map(r=>r.passed)).toEqual([true,false]);
} }
}); });
test('Consensus lifecycle controls select the existing consensus owner only',()=>{
expect(Object.entries(E2E_TOUCHFILES).filter(([,paths])=>paths.includes('test/review-consensus-lifecycle.test.ts')).map(([name])=>name)).toEqual(['review-army-consensus']);
});
@@ -103,7 +103,6 @@ test('scoring and section dependencies are explicit while existing clean and pas
test('new regression and changed preamble sources select all Design and Eng owners', () => { test('new regression and changed preamble sources select all Design and Eng owners', () => {
for (const map of [E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES]) { for (const map of [E2E_TOUCHFILES, LLM_JUDGE_TOUCHFILES]) {
const affected = selectTests(['plan-design-review/SKILL.md.tmpl', 'plan-eng-review/SKILL.md.tmpl'], map, []).selected; const affected = selectTests(['plan-design-review/SKILL.md.tmpl', 'plan-eng-review/SKILL.md.tmpl'], map, []).selected;
expect(selectTests(['test/review-entry-and-design-clarity-au.test.ts'], map, []).selected).toEqual(affected);
for (const source of ['scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts']) { for (const source of ['scripts/resolvers/preamble/generate-preamble-bash.ts', 'scripts/resolvers/preamble/generate-completion-status.ts']) {
const selected = selectTests([source], map, []).selected; const selected = selectTests([source], map, []).selected;
for (const owner of affected) expect(selected).toContain(owner); for (const owner of affected) expect(selected).toContain(owner);
-6
View File
@@ -3,8 +3,6 @@ import * as fs from 'node:fs';
import * as path from 'node:path'; import * as path from 'node:path';
import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets'; import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets';
import { SESSION_DRAIN_GRACE_MS } from './helpers/session-runner'; import { SESSION_DRAIN_GRACE_MS } from './helpers/session-runner';
import { E2E_TOUCHFILES } from './helpers/touchfiles';
const source=fs.readFileSync(path.join(import.meta.dir,'skill-e2e-review.test.ts'),'utf8'); const source=fs.readFileSync(path.join(import.meta.dir,'skill-e2e-review.test.ts'),'utf8');
async function exercise(scenarios: Array<'success'|'timeout'|'wrong-report'|'browse-error'>) { async function exercise(scenarios: Array<'success'|'timeout'|'wrong-report'|'browse-error'>) {
const setups:any[]=[],done:any[]=[],callbacks:any[]=[],rows:any[]=[],calls:any[]=[]; const setups:any[]=[],done:any[]=[],callbacks:any[]=[],rows:any[]=[],calls:any[]=[];
@@ -52,7 +50,3 @@ test('Enum semantic failure records false exactly once after the existing assert
test('Enum verdict retains the existing browser-error guard',async()=>{ test('Enum verdict retains the existing browser-error guard',async()=>{
const x=await exercise(['browse-error']);expect(x.rows).toHaveLength(1);expect(x.rows[0].passed).toBe(false); const x=await exercise(['browse-error']);expect(x.rows).toHaveLength(1);expect(x.rows[0].passed).toBe(false);
}); });
test('Enum lifecycle controls select the existing enum owner only',()=>{
expect(Object.entries(E2E_TOUCHFILES).filter(([,paths])=>paths.includes('test/review-enum-lifecycle.test.ts')).map(([name])=>name)).toEqual(['review-enum-completeness']);
});
-8
View File
@@ -4,8 +4,6 @@ import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
import * as path from 'node:path'; import * as path from 'node:path';
import { buildPaidShardArgs, retriesForFiles, resolvePaidShardTimeoutMs } from '../scripts/test-paid-shards'; import { buildPaidShardArgs, retriesForFiles, resolvePaidShardTimeoutMs } from '../scripts/test-paid-shards';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
const PAID_FILE = 'test/skill-e2e-review.test.ts'; const PAID_FILE = 'test/skill-e2e-review.test.ts';
const CASES = [ const CASES = [
@@ -13,12 +11,6 @@ const CASES = [
['review-enum-completeness', 300, 15], ['review-enum-completeness', 300, 15],
['review-design-lite', 400, 35], ['review-design-lite', 400, 35],
] as const; ] as const;
test('review finalization regressions select all three owning cases', () => {
expect(selectTests(['test/review-finalization-budget.test.ts'], E2E_TOUCHFILES).selected?.sort())
.toEqual(CASES.map(([id]) => id).sort());
});
for (const [id, workMs, maxTurns] of CASES) { for (const [id, workMs, maxTurns] of CASES) {
test.each(['recover', 'both-timeout'])(`${id} records late results before retry or finalization: %s`, scenario => { test.each(['recover', 'both-timeout'])(`${id} records late results before retry or finalization: %s`, scenario => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'review-finalization-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'review-finalization-'));
-9
View File
@@ -3,16 +3,7 @@ import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
import * as path from 'node:path'; import * as path from 'node:path';
import {spawnSync} from 'node:child_process'; import {spawnSync} from 'node:child_process';
import {E2E_TOUCHFILES, selectTests} from './helpers/touchfiles';
const ROOT = path.resolve(import.meta.dir, '..'); const ROOT = path.resolve(import.meta.dir, '..');
test('N+1 native dispatch regressions select their paid case', () => {
for (const file of ['test/review-n-plus-one-contract.test.ts', 'test/fixtures/review-n-plus-one-dispatch.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected).toEqual(['review-army-perf-n-plus-one']);
}
});
test.each(['complete-control', 'captured-omission', 'claimed-only', 'background', 'missing-report', 'unrelated-report', 'captured-timeout']) test.each(['complete-control', 'captured-omission', 'claimed-only', 'background', 'missing-report', 'unrelated-report', 'captured-timeout'])
('N+1 registered completion contract: %s', scenario => { ('N+1 registered completion contract: %s', scenario => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'n1-contract-')); const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'n1-contract-'));
-9
View File
@@ -10,8 +10,6 @@ import { runRecordedOfficeHoursAttempt, OFFICE_HOURS_BUN_GRACE_MS } from './help
import { buildHermeticEnv } from './helpers/hermetic-env'; import { buildHermeticEnv } from './helpers/hermetic-env';
import { CAPTURE_MS } from './helpers/eval-budgets'; import { CAPTURE_MS } from './helpers/eval-budgets';
import { redactFindingSpans } from '../lib/redact-engine'; import { redactFindingSpans } from '../lib/redact-engine';
import { E2E_TOUCHFILES } from './helpers/touchfiles-data';
// Assemble synthetic credentials at runtime, as in gate-secret-scan.test.ts. // Assemble synthetic credentials at runtime, as in gate-secret-scan.test.ts.
const CREDENTIAL = ['ghp_', 'aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW3xY5'].join(''); const CREDENTIAL = ['ghp_', 'aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW3xY5'].join('');
const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-setup-gbrain-path4-local-pglite.test.ts'), 'utf8'); const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-setup-gbrain-path4-local-pglite.test.ts'), 'utf8');
@@ -133,13 +131,6 @@ test('Path4 public diagnostics exclude private fields and redact output, tools a
expect(serialized).not.toContain('apiKeySource'); expect(serialized).not.toContain('apiKeySource');
expect(row.transcript).toHaveLength(3); expect(row.transcript).toHaveLength(3);
}); });
test('Path4 caller controls select only their registered paid owner', () => {
const owners = Object.entries(E2E_TOUCHFILES).filter(([, paths]) => paths.includes('test/setup-gbrain-path4-caller.test.ts')).map(([name]) => name);
expect(owners).toEqual(['setup-gbrain-path4-local-pglite']);
});
test('Path4 redacted credential URLs cannot erase success or mask a failed assertion', async () => { test('Path4 redacted credential URLs cannot erase success or mask a failed assertion', async () => {
// Text redaction can consume JSON punctuation after an unspaced URL host. // Text redaction can consume JSON punctuation after an unspaced URL host.
// These synthetic credentials exercise the real redactor and actual callback. // These synthetic credentials exercise the real redactor and actual callback.
+1 -25
View File
@@ -79,17 +79,6 @@ describe('shared-code legacy interactive actor', () => {
await expect(callback('AskUserQuestion', { questions: [{ question: 'Decision', options: [option] }] })) await expect(callback('AskUserQuestion', { questions: [{ question: 'Decision', options: [option] }] }))
.rejects.toThrow('No unambiguous no-change option'); .rejects.toThrow('No unambiguous no-change option');
}); });
test('both native index-flag captures select every owning interactive lifecycle case', () => {
for (const fixture of ['test/fixtures/shared-libs-index-flags-skip-question.json',
'test/fixtures/shared-libs-index-flags-no-change-description.json']) {
expect(selectTests([fixture], E2E_TOUCHFILES, GLOBAL_TOUCHFILES).selected.sort()).toEqual([
'shared-libs-review-index-flags', 'shared-libs-review-lifecycle', 'shared-libs-review-path-eligibility',
'shared-libs-review-prior-coverage', 'shared-libs-review-revalidation',
]);
}
});
for (const [choose, labels] of [['approve', ['Fix it', 'Apply remedy', 'Approve', 'Extract helper', 'Reuse library', 'Choice (recommended)']], for (const [choose, labels] of [['approve', ['Fix it', 'Apply remedy', 'Approve', 'Extract helper', 'Reuse library', 'Choice (recommended)']],
['skip', ['Skip', 'Keep current', 'Decline', 'Do not change', 'Leave as-is']]] as const) { ['skip', ['Skip', 'Keep current', 'Decline', 'Do not change', 'Leave as-is']]] as const) {
test.each(labels)(`${choose} supports the declared choice: %s`, async label => { test.each(labels)(`${choose} supports the declared choice: %s`, async label => {
@@ -159,13 +148,6 @@ describe('shared-code legacy interactive actor', () => {
expect(input).toEqual(original); expect(input).toEqual(original);
} }
}); });
test('the captured native no-change questions select every owning interactive lifecycle case', () => {
expect(selectTests(['test/fixtures/shared-libs-index-flags-native-questions.json'], E2E_TOUCHFILES, GLOBAL_TOUCHFILES).selected.sort())
.toEqual(['shared-libs-review-index-flags', 'shared-libs-review-lifecycle', 'shared-libs-review-path-eligibility',
'shared-libs-review-prior-coverage', 'shared-libs-review-revalidation']);
});
test('the registered callback acknowledges the complete first-attempt native skip despite descriptive reuse', async () => { test('the registered callback acknowledges the complete first-attempt native skip despite descriptive reuse', async () => {
const native = JSON.parse(fs.readFileSync(path.join(import.meta.dir, 'fixtures/shared-libs-index-flags-native-questions.json'), 'utf8')); const native = JSON.parse(fs.readFileSync(path.join(import.meta.dir, 'fixtures/shared-libs-index-flags-native-questions.json'), 'utf8'));
const { sourceRun, attempt, input } = native.regressions[0]; const { sourceRun, attempt, input } = native.regressions[0];
@@ -789,19 +771,13 @@ const interactive = [
'shared-libs-plan-callers', 'shared-libs-review-index-flags', 'shared-libs-review-lifecycle', 'shared-libs-plan-callers', 'shared-libs-review-index-flags', 'shared-libs-review-lifecycle',
'shared-libs-review-path-eligibility', 'shared-libs-review-prior-coverage', 'shared-libs-review-revalidation', 'shared-libs-review-path-eligibility', 'shared-libs-review-prior-coverage', 'shared-libs-review-revalidation',
]; ];
const judged = ['shared-libs-opportunity-judgment', 'shared-libs-plan-callers', 'shared-libs-pr-coverage'];
const allShared = Object.keys(E2E_TOUCHFILES).filter(name => name.startsWith('shared-libs-')).sort(); const allShared = Object.keys(E2E_TOUCHFILES).filter(name => name.startsWith('shared-libs-')).sort();
const selected = (dependency: string) => selectTests([dependency], E2E_TOUCHFILES, GLOBAL_TOUCHFILES) const selected = (dependency: string) => selectTests([dependency], E2E_TOUCHFILES, GLOBAL_TOUCHFILES)
.selected.filter(name => name.startsWith('shared-libs-')).sort(); .selected.filter(name => name.startsWith('shared-libs-')).sort();
describe('shared-code paid dependency selection', () => { describe('shared-code paid dependency selection', () => {
test('SDK and judge changes select the actual affected owners', () => {
expect(selected('test/helpers/agent-sdk-runner.ts')).toEqual(interactive);
expect(selected('test/helpers/llm-judge.ts')).toEqual(judged);
});
test('generation, gating, fixture validation and host support keep their coverage owners', () => { test('generation, gating, fixture validation and host support keep their coverage owners', () => {
for (const dependency of ['scripts/gen-skill-docs.ts', 'test/helpers/e2e-gate.ts', 'test/shared-libs-fixture.test.ts']) { for (const dependency of ['scripts/gen-skill-docs.ts', 'test/helpers/e2e-gate.ts']) {
expect(selected(dependency)).toEqual(allShared); expect(selected(dependency)).toEqual(allShared);
} }
expect(selected('lib/claude-bin.ts')).toEqual(allShared.filter(name => name !== 'shared-libs-codex-read-only')); expect(selected('lib/claude-bin.ts')).toEqual(allShared.filter(name => name !== 'shared-libs-codex-read-only'));
-9
View File
@@ -3,8 +3,6 @@ import * as fs from 'node:fs';
import * as os from 'node:os'; import * as os from 'node:os';
import * as path from 'node:path'; import * as path from 'node:path';
import native from './fixtures/shared-libs-resolved-reads-public.json'; import native from './fixtures/shared-libs-resolved-reads-public.json';
import { E2E_TOUCHFILES, GLOBAL_TOUCHFILES, selectTests } from './helpers/touchfiles';
const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-shared-libs-paths.test.ts'), 'utf8'); const source = fs.readFileSync(path.join(import.meta.dir, 'skill-e2e-shared-libs-paths.test.ts'), 'utf8');
const detectorStart = source.indexOf('function sourceReadTrace('); const detectorStart = source.indexOf('function sourceReadTrace(');
const callbackStart = source.indexOf('async function exerciseEligibility('); const callbackStart = source.indexOf('async function exerciseEligibility(');
@@ -122,13 +120,6 @@ test.each(['Read', 'Bash'])('direct alias reads retain the existing %s contract'
const result = { toolCalls: [{ tool, input: tool === 'Read' ? { file_path: aliases[0] } : { command: `cat ${aliases[0]}` } }] }; const result = { toolCalls: [{ tool, input: tool === 'Read' ? { file_path: aliases[0] } : { command: `cat ${aliases[0]}` } }] };
expect(detect(result, f, aliases)).toContain(aliases[0]); expect(detect(result, f, aliases)).toContain(aliases[0]);
}); });
test.each(['test/shared-libs-source-reads.test.ts', 'test/fixtures/shared-libs-resolved-reads-public.json'])('%s selects every owning path callback without a global fallback', file => {
expect(selectTests([file], E2E_TOUCHFILES, GLOBAL_TOUCHFILES).selected.sort()).toEqual([
'shared-libs-review-index-flags', 'shared-libs-review-path-eligibility', 'shared-libs-review-prior-coverage',
]);
});
test.each([false, true])('the actual eligibility callback consumes the read detector result (missing output=%s)', async missingOutput => { test.each([false, true])('the actual eligibility callback consumes the read detector result (missing output=%s)', async missingOutput => {
const f = fixture(); const f = fixture();
const result: any = capture(); const result: any = capture();
-5
View File
@@ -3,7 +3,6 @@ import fs from 'node:fs';
import path from 'node:path'; import path from 'node:path';
import * as evidence from './helpers/coverage-audit-evidence'; import * as evidence from './helpers/coverage-audit-evidence';
import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets'; import { JUDGE_MS, CAPTURE_MS } from './helpers/eval-budgets';
import { E2E_TOUCHFILES } from './helpers/touchfiles-data';
import fixture from './fixtures/ship-coverage-audit-af.json'; import fixture from './fixtures/ship-coverage-audit-af.json';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { validateCoverageAudit } from './helpers/coverage-audit'; import { validateCoverageAudit } from './helpers/coverage-audit';
@@ -93,10 +92,6 @@ test('AF ship actual read helper accepts only literal owned delivery before read
for(const row of fixture.rows.slice(0,2))expect((evidence as any).coverageAuditReadEvidence(row.result.transcript,{cwd:row.cwd,source:{path:row.cwd+'/src/billing.ts',content:fixture.files.source},tests:{path:row.cwd+'/test/billing.test.ts',content:fixture.files.tests}})).toEqual({sourceRead:true,testsRead:true}); for(const row of fixture.rows.slice(0,2))expect((evidence as any).coverageAuditReadEvidence(row.result.transcript,{cwd:row.cwd,source:{path:row.cwd+'/src/billing.ts',content:fixture.files.source},tests:{path:row.cwd+'/test/billing.test.ts',content:fixture.files.tests}})).toEqual({sourceRead:true,testsRead:true});
}); });
test('AF ship controls and fixture select the one existing owner',()=>{
for(const name of ['test/ship-coverage-audit-af.test.ts','test/fixtures/ship-coverage-audit-af.json'])expect(Object.entries(E2E_TOUCHFILES).filter(([,files])=>files.includes(name)).map(([owner])=>owner)).toEqual(['ship-coverage-audit']);
});
function commandReads(command:string) { function commandReads(command:string) {
const row=fixture.rows[0]!;const session=row.sessionId; const row=fixture.rows[0]!;const session=row.sessionId;
const transcript=[{type:'system',subtype:'init',session_id:session,cwd:row.cwd}, const transcript=[{type:'system',subtype:'init',session_id:session,cwd:row.cwd},
-7
View File
@@ -26,7 +26,6 @@ import { generateThirdPartyActions } from "../scripts/resolvers/third-party-acti
import { generateAsideSetup } from "../scripts/resolvers/aside"; import { generateAsideSetup } from "../scripts/resolvers/aside";
import { HOST_PATHS } from "../scripts/resolvers/types"; import { HOST_PATHS } from "../scripts/resolvers/types";
import { asideDriveOptions } from './helpers/third-party-actions'; import { asideDriveOptions } from './helpers/third-party-actions';
import { E2E_TOUCHFILES, selectTests } from './helpers/touchfiles';
import recoveryFixture from './fixtures/third-party-actions-recovery-public.json'; import recoveryFixture from './fixtures/third-party-actions-recovery-public.json';
const ROOT = path.resolve(import.meta.dir, ".."); const ROOT = path.resolve(import.meta.dir, "..");
@@ -41,12 +40,6 @@ const ctx = {
const section = generateThirdPartyActions(ctx); const section = generateThirdPartyActions(ctx);
describe('consent offer extraction', () => { describe('consent offer extraction', () => {
test('helper changes select the consent gate evals', () => {
expect(selectTests(['test/helpers/third-party-actions.ts'], E2E_TOUCHFILES, []).selected.sort()).toEqual([
'tpa-absent-darwin', 'tpa-absent-linux', 'tpa-apple-ban', 'tpa-broken', 'tpa-present',
]);
});
test('an unavailable-option explanation is not an offer', () => { test('an unavailable-option explanation is not an offer', () => {
expect(asideDriveOptions(`B) I drive it in gstack's own visible browser expect(asideDriveOptions(`B) I drive it in gstack's own visible browser
C) Manual instructions C) Manual instructions
+51 -65
View File
@@ -18,6 +18,7 @@ import {
GLOBAL_TOUCHFILES, GLOBAL_TOUCHFILES,
} from './helpers/touchfiles'; } from './helpers/touchfiles';
import { paidTestClosure, isCovered } from './helpers/touchfile-closure';
import { readWorkflowExcerpt } from './helpers/workflow-excerpt'; import { readWorkflowExcerpt } from './helpers/workflow-excerpt';
import { sharedLibsPlanExcerpt } from './helpers/shared-libs-plan-excerpt'; import { sharedLibsPlanExcerpt } from './helpers/shared-libs-plan-excerpt';
@@ -115,7 +116,7 @@ describe('selectTests', () => {
}, },
); );
test.each(['lib/cso/cli.ts', 'lib/cso/state.ts', 'test/cso-cli.test.ts', 'test/cso-snapshot-state.test.ts'])( test.each(['lib/cso/cli.ts', 'lib/cso/state.ts'])(
'CSO runtime and report regressions select all three audit cases: %s', (file) => { 'CSO runtime and report regressions select all three audit cases: %s', (file) => {
const result = selectTests([file], E2E_TOUCHFILES); const result = selectTests([file], E2E_TOUCHFILES);
expect(result.reason).toBe('diff'); expect(result.reason).toBe('diff');
@@ -135,14 +136,6 @@ describe('selectTests', () => {
}, },
); );
test.each(['test/helpers/coverage-audit.ts', 'test/coverage-audit.test.ts'])(
'coverage-audit validation changes select all three gate cases: %s', (file) => {
const result = selectTests([file], E2E_TOUCHFILES);
expect(result.selected.sort()).toEqual(['plan-eng-coverage-audit', 'review-coverage-audit', 'ship-coverage-audit']);
expect(result.selected.every(id => E2E_TIERS[id] === 'gate')).toBe(true);
},
);
test('testing resolver source selects the same E2E consumers as its generated content', () => { test('testing resolver source selects the same E2E consumers as its generated content', () => {
const consumers = [ const consumers = [
['plan-eng-review/sections/review-sections.md', 'TEST_COVERAGE_AUDIT_PLAN'], ['plan-eng-review/sections/review-sections.md', 'TEST_COVERAGE_AUDIT_PLAN'],
@@ -243,33 +236,6 @@ describe('selectTests', () => {
expect(result.selected).toContain('plan-design-review/SKILL.md passes'); expect(result.selected).toContain('plan-design-review/SKILL.md passes');
}); });
test('the shared recording lifecycle selects every bounded attempt', () => {
const result = selectTests(['test/helpers/office-hours-attempt.ts'], E2E_TOUCHFILES);
const expected = {
'office-hours-forcing-energy': 'periodic',
'office-hours-builder-wildness': 'periodic',
'office-hours-brain-writeback': 'periodic',
'plan-design-review-plan-mode': 'periodic',
'plan-ceo-review-format-mode': 'periodic',
'plan-ceo-review-format-approach': 'periodic',
'plan-eng-review-format-coverage': 'periodic',
'plan-eng-review-format-kind': 'periodic',
'plan-ceo-review-prosons-cadence': 'periodic',
'plan-review-prosons-format': 'periodic',
'plan-review-prosons-hardstop-neg': 'periodic',
'plan-review-prosons-neutral-neg': 'periodic',
'setup-gbrain-bad-token': 'periodic',
'setup-gbrain-path4-local-pglite': 'periodic',
'setup-gbrain-remote': 'periodic',
'review-army-red-team': 'periodic',
'review-coverage-audit': 'gate',
'plan-eng-coverage-audit': 'gate',
'ship-coverage-audit': 'gate',
'plan-review-report': 'gate',
};
expect(result.selected.sort()).toEqual(Object.keys(expected).sort());
for (const [id, tier] of Object.entries(expected)) expect(E2E_TIERS[id]).toBe(tier);
});
test('browse/src change selects browse and qa tests', () => { test('browse/src change selects browse and qa tests', () => {
const result = selectTests(['browse/src/commands.ts'], E2E_TOUCHFILES); const result = selectTests(['browse/src/commands.ts'], E2E_TOUCHFILES);
@@ -299,33 +265,14 @@ describe('selectTests', () => {
test('mode-question capture dependencies select its native gate', () => { test('mode-question capture dependencies select its native gate', () => {
for (const file of [ for (const file of [
'test/auq-mode-capture.test.ts', 'test/skill-ceo-section-ordering.test.ts',
'test/helpers/agent-sdk-runner.ts', 'test/helpers/auq-native-capture.ts', 'test/helpers/agent-sdk-runner.ts', 'test/helpers/auq-native-capture.ts',
'test/helpers/hermetic-env.ts', 'test/helpers/eval-store.ts', 'test/helpers/hermetic-env.ts', 'test/helpers/eval-store.ts',
'lib/claude-bin.ts', 'test/workflow-excerpt.test.ts', 'lib/claude-bin.ts',
]) { ]) {
expect(selectTests([file], E2E_TOUCHFILES).selected).toContain('auq-format-gate'); expect(selectTests([file], E2E_TOUCHFILES).selected).toContain('auq-format-gate');
} }
}); });
test('shared-code evidence regressions select their consuming evaluations', () => {
expect(selectTests(['test/fixtures/shared-libs-readonly-substitution-ci16358.json'], E2E_TOUCHFILES).selected.sort())
.toEqual(['shared-libs-codex-read-only', 'shared-libs-opportunity-judgment', 'shared-libs-pr-coverage',
'shared-libs-read-only', 'shared-libs-unsupported-git'].sort());
for (const file of ['test/helpers/shared-libs-review-start-evidence.ts', 'test/shared-libs-review-start-evidence.test.ts',
'test/fixtures/shared-libs-review-start-public.json',
'test/fixtures/shared-libs-revalidation-max-turns-public.json']) {
expect(selectTests([file], E2E_TOUCHFILES).selected).toEqual(['shared-libs-review-revalidation']);
}
const pathCases = ['shared-libs-review-path-eligibility', 'shared-libs-review-index-flags',
'shared-libs-review-prior-coverage'];
expect(selectTests(['test/shared-libs-revalidation-prompt.test.ts'], E2E_TOUCHFILES).selected.sort())
.toEqual([...pathCases, 'shared-libs-review-revalidation'].sort());
expect(selectTests(['test/fixtures/shared-libs-index-flags-skip-question.json'], E2E_TOUCHFILES).selected.sort())
.toEqual([...pathCases, 'shared-libs-review-revalidation', 'shared-libs-review-lifecycle'].sort());
expect(selectTests(['test/fixtures/shared-libs-paths-max-turns-public.json'], E2E_TOUCHFILES).selected)
.toEqual(['shared-libs-review-index-flags']);
});
test('skill-specific change selects only that skill and related tests', () => { test('skill-specific change selects only that skill and related tests', () => {
const result = selectTests(['plan-ceo-review/SKILL.md'], E2E_TOUCHFILES); const result = selectTests(['plan-ceo-review/SKILL.md'], E2E_TOUCHFILES);
@@ -376,7 +323,6 @@ describe('selectTests', () => {
test.each([ test.each([
'test/helpers/hermetic-skill-runtime.ts', 'test/helpers/hermetic-skill-runtime.ts',
'test/hermetic-skill-runtime.test.ts',
'lib/fs-atomic.ts', 'lib/fs-atomic.ts',
])('live runtime dependency selects PTY consumers: %s', (file) => { ])('live runtime dependency selects PTY consumers: %s', (file) => {
const result = selectTests([file], E2E_TOUCHFILES); const result = selectTests([file], E2E_TOUCHFILES);
@@ -385,13 +331,6 @@ describe('selectTests', () => {
expect(result.selected).not.toContain('retro'); expect(result.selected).not.toContain('retro');
}); });
test('session tool isolation regression selects its capture workflows', () => {
const result = selectTests(['test/session-runner-tools.test.ts'], E2E_TOUCHFILES);
expect(result.selected.sort()).toEqual([
'auq-format-gate', 'carve-section-loading', 'plan-ceo-section-loading', 'plan-design-review-plan-mode', 'ship-section-loading',
]);
expect(result.reason).toBe('diff');
});
test('gen-skill-docs.ts is a scoped touchfile, not global', () => { test('gen-skill-docs.ts is a scoped touchfile, not global', () => {
const result = selectTests(['scripts/gen-skill-docs.ts'], E2E_TOUCHFILES); const result = selectTests(['scripts/gen-skill-docs.ts'], E2E_TOUCHFILES);
@@ -408,7 +347,7 @@ describe('selectTests', () => {
expect(result.selected).not.toContain('cso-full-audit'); expect(result.selected).not.toContain('cso-full-audit');
}); });
test.each(['test/helpers/ceo-finding-fixture.ts', 'test/ceo-finding-fixture.test.ts', 'test/ceo-mode-routing-fixture.test.ts'])('mode input dependency selects its periodic eval: %s', file => { test.each(['test/helpers/ceo-finding-fixture.ts'])('mode input dependency selects its periodic eval: %s', file => {
const result = selectTests([file], E2E_TOUCHFILES); const result = selectTests([file], E2E_TOUCHFILES);
expect(result.selected).toContain('plan-ceo-mode-routing'); expect(result.selected).toContain('plan-ceo-mode-routing');
expect(result.reason).toBe('diff'); expect(result.reason).toBe('diff');
@@ -731,3 +670,50 @@ describe('reverse invariant — keys must name living paid tests', () => {
expect(stale.map(([k]) => k), 'exception points at a deleted file — remove the entry').toEqual([]); expect(stale.map(([k]) => k), 'exception points at a deleted file — remove the entry').toEqual([]);
}); });
}); });
describe('derived touchfile closure', () => {
const { isPaidTestFile } = require('./helpers/paid-test-set') as typeof import('./helpers/paid-test-set');
const paid = fs.readdirSync(path.join(ROOT, 'test')).map(name => `test/${name}`).filter(isPaidTestFile).sort();
const source = Object.fromEntries(paid.map(file => [file, fs.readFileSync(path.join(ROOT, file), 'utf8')]));
const quotes = (file: string, key: string) =>
source[file]!.includes(`'${key}'`) || source[file]!.includes(`"${key}"`) || source[file]!.includes('`' + key + '`');
/** A key belongs to the paid files in its own list, else to the paid files that quote it. */
const owners = (key: string, deps: readonly string[]) => {
const listed = deps.filter(dep => paid.includes(dep));
return listed.length ? listed : paid.filter(file => quotes(file, key));
};
const maps = [['E2E_TOUCHFILES', E2E_TOUCHFILES], ['LLM_JUDGE_TOUCHFILES', LLM_JUDGE_TOUCHFILES]] as const;
/** Paid files no key selects; they run only by tier or census. */
const KEYLESS_PAID: Record<string, string> = {
'test/codex-e2e-recommendation-substance.test.ts': 'census-only Codex case; PERIODIC_CI_EXCLUDE (no codex CLI in CI)',
'test/skill-e2e-auq-consistency.test.ts': 'periodic tier gate only (describeE2ETier), never diff-selected',
'test/skill-e2e-auq-verbose-vs-carved-ab.test.ts': 'periodic tier gate only (describeE2ETier), never diff-selected',
};
test('no free test file is a touchfile', () => {
const listed = maps.flatMap(([name, map]) => Object.entries(map).flatMap(([key, deps]) =>
deps.filter(dep => dep.endsWith('.test.ts') && !isPaidTestFile(dep)).map(dep => `${name}['${key}']: ${dep}`)));
expect(listed, 'Editing a free test must not select paid evals; remove these entries').toEqual([]);
});
test('every key covers the static helper/fixture closure and literal fixture paths of its paid files', () => {
const boundary = new Set(GLOBAL_TOUCHFILES);
const failures: string[] = [];
for (const [name, map] of maps) for (const [key, deps] of Object.entries(map)) {
for (const owner of owners(key, deps)) for (const entry of paidTestClosure(ROOT, owner, boundary)) {
if (isCovered(entry.file, deps, GLOBAL_TOUCHFILES)) continue;
failures.push(`paid test ${owner} depends on ${entry.file}\n via ${entry.chain.join(' -> ')}\n` +
` add '${entry.file}' to ${name}['${key}']`);
}
}
expect(failures.length, failures.length ? `${failures.join('\n')}\n` +
'Verify with: bun run scripts/test-paid-shards.ts --tier gate --profile pr --list\n' +
'See CONTRIBUTING.md#paid-test-touchfiles. This rule is a lower bound: fixture paths built at runtime ' +
'are not visible to it, so declare them in the key by hand.' : '').toBe(0);
});
test('keyless paid files are exactly the declared exemptions', () => {
const keyed = (file: string) => maps.some(([, map]) => Object.entries(map).some(([key, deps]) => deps.includes(file) || quotes(file, key)));
expect(paid.filter(file => !keyed(file))).toEqual(Object.keys(KEYLESS_PAID).sort());
});
});
-8
View File
@@ -1,6 +1,5 @@
import { describe, expect, test } from 'bun:test'; import { describe, expect, test } from 'bun:test';
import { ENG_REVIEW_EXCERPT, readWorkflowExcerpt } from './helpers/workflow-excerpt'; import { ENG_REVIEW_EXCERPT, readWorkflowExcerpt } from './helpers/workflow-excerpt';
import { LLM_JUDGE_TOUCHFILES, selectTests } from './helpers/touchfiles';
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs'; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
import { tmpdir } from 'os'; import { tmpdir } from 'os';
import { join } from 'path'; import { join } from 'path';
@@ -54,13 +53,6 @@ function expectOutsideReviewControlFlow(text: string, promptHeading: string): vo
} }
describe('workflow judge excerpts', () => { describe('workflow judge excerpts', () => {
test('helper changes select all dependent workflow judges', () => {
const selected = selectTests(['test/helpers/workflow-excerpt.ts'], LLM_JUDGE_TOUCHFILES, []).selected;
expect(selected).toHaveLength(14);
expect(selected).toContain('ship/SKILL.md workflow');
expect(selected).toContain('plan-design-review/SKILL.md passes');
});
test('expands ship sections in execution order, not alphabetical order', () => { test('expands ship sections in execution order, not alphabetical order', () => {
const text = readWorkflowExcerpt('ship/SKILL.md', '# Ship:', '## Important Rules'); const text = readWorkflowExcerpt('ship/SKILL.md', '# Ship:', '## Important Rules');
const headings = ['## Step 3:', '## Step 4:', '## Step 7:', '## Step 8:', '## Step 9:', '## Step 10:', '## Step 11:', '## Step 12:', '## Step 13:', '## Step 14:']; const headings = ['## Step 3:', '## Step 4:', '## Step 7:', '## Step 8:', '## Step 9:', '## Step 10:', '## Step 11:', '## Step 12:', '## Step 13:', '## Step 14:'];