Files
gstack/test/test-pr-profile.test.ts
T
garrytan fc9049a8b5 test(W7h): retire the paid SKILL.md-summary cases in skill-e2e-plan
W7h retirement (t14 F6-F8): office-hours-spec-review, plan-ceo-review-benefits
and codex-offered-{office-hours,ceo-review,design-review,eng-review}. Each
asked a model to read a generated SKILL.md, write a summary, and grepped the
summary for facts the generated file states directly.

Registration cleanup in the same commit: E2E_TOUCHFILES, E2E_TIERS (all six
gate) and E2E_KINDS (rule) in test/helpers/touchfiles-data.ts; six
scripts/paid-test-durations.json case-shard entries; no
test/helpers/periodic-exclude-data.ts entries existed. The fast PR profile
(scripts/test-pr-profile.ts) drops plan-ceo-review-benefits and
office-hours-spec-review from PR_PROFILE_CASE_IDS and PR_PROFILE_FILES. Tests
that named the retired ids as live examples move to existing ones:
paid-free-boundary and paid-pr-profile (a CEO template change now plans
auq-format-gate plus the CEO judge; the case-shard fixture uses
plan-review-report), test-pr-profile, touchfiles (CEO selection count
21 -> 19), the touchfile-moved-code w5 golden (retired ids removed), the
behavior-lane case-shard census (78 -> 72) in cookie-validation-phases, and
the skill-e2e-plan timeout list and full-gate PR floor (78,425 -> 72,755 s)
in paid-retry-supervision. e2e-tier-alignment, eval-kinds,
eval-detach-timeout-floor and paid-shards stay green.

Coverage consequence: per the Eng Retirements item, plan-ceo-review-benefits
was the only gate-tier CEO E2E in the fast PR profile, so CEO invariants are
treated as periodic-only under the W7c gate (every CEO conversion in this
branch keeps one free check per invariant); the gate judge
'plan-ceo-review/SKILL.md modes' still runs for CEO prompt changes. An
office-hours prompt change now has no fast PR E2E and is reported as
deferred to broad coverage rather than run.

Retirement cards:
- office-hours-spec-review: detects the Spec Review Loop's stated dimensions,
  dispatch tool, iteration cap and metrics. Replacement: gen-skill-docs.test.ts
  'SPEC_REVIEW_LOOP resolver' (round-3 cap, prepare/check/finalize commands,
  verdict and round-file wiring) and test/office-hours-review.test.ts (verdict
  parsing). Control: changing the round limit in
  scripts/resolvers/spec-review.ts turns gen-skill-docs red.
- plan-ceo-review-benefits: detects the CEO /office-hours prerequisite and
  mid-session offer. Replacement: gen-skill-docs.test.ts 'plan-ceo-review
  offers /office-hours when no design doc exists and detects a lost user
  mid-session' (previous commit). Control: 4/4 red mutations there.
- codex-offered-* (x4): detects the `command -v codex` probe, a fallback and
  optionality. Replacement: gen-skill-docs.test.ts 'Codex outside voice is
  offered behind an executed availability probe' (probe + not_installed
  fallback for all four skills) and skill-validation.test.ts 'plan reviews run
  the Codex outside voice default-on'. Control: 4/4 red there.
- non_test_callers: none; history: c118e24 v1.64.1.0 (#2572).
- validation: the registration tests named above.

Controls log: .context/mutation-skill-e2e-plan-retirements.md.
2026-10-03 01:47:21 +00:00

174 lines
9.3 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import {
PR_PROFILE_CASE_IDS, PR_PROFILE_MAPS, packageChangeOnlyVersion, selectPrProfile, validatePrProfileInventory,
type PrProfileMaps,
} from '../scripts/test-pr-profile';
const maps: PrProfileMaps = {
e2eTouchfiles: {
'ceo-smoke': ['plan-ceo-review/**'],
'ceo-full': ['plan-ceo-review/**'],
'ceo-periodic': ['plan-ceo-review/**'],
'autoplan-full': ['autoplan/**'],
'browse-smoke': ['browse/**'],
},
tiers: {
'ceo-smoke': 'gate', 'ceo-full': 'gate', 'ceo-periodic': 'periodic',
'autoplan-full': 'periodic', 'browse-smoke': 'gate',
},
judgeTouchfiles: {
'plan-ceo-review/SKILL.md modes': ['plan-ceo-review/**'],
'browse quality': ['browse/**'],
},
globalTouchfiles: ['test/helpers/shared-runner.ts'],
};
const profile = ['ceo-smoke', 'browse-smoke'];
const select = (options: Partial<Parameters<typeof selectPrProfile>[0]> = {}) => selectPrProfile({
maps, profile, selectedE2E: ['ceo-smoke', 'ceo-full', 'ceo-periodic'],
selectedJudges: ['plan-ceo-review/SKILL.md modes'],
changedFiles: ['plan-ceo-review/SKILL.md.tmpl'], ...options,
});
describe('fast PR coverage policy', () => {
test('canonical short probes exist in the unchanged broad gate census', () => {
expect(() => validatePrProfileInventory()).not.toThrow();
expect(PR_PROFILE_CASE_IDS).toContain('plan-review-report');
expect(PR_PROFILE_CASE_IDS).toContain('auq-format-gate');
for (const tier of Object.values(PR_PROFILE_MAPS.tiers)) expect(['gate', 'periodic', 'marathon']).toContain(tier);
});
test('keeps relevant short probes and the failing CEO quality obligation; reports broad work', () => {
const result = select();
expect(result.mode).toBe('pr');
expect(result.e2e).toEqual(['ceo-smoke']);
expect(result.judges).toEqual(['plan-ceo-review/SKILL.md modes']);
expect(result.deferred.map(({ id, tier }) => ({ id, tier }))).toEqual([
{ id: 'ceo-full', tier: 'gate' }, { id: 'ceo-periodic', tier: 'periodic' },
]);
expect(result.needsFullValidation).toBe(false);
});
test('does not add unrelated short probes or drop selected quality judges', () => {
const result = select({ selectedJudges: ['browse quality', 'plan-ceo-review/SKILL.md modes'] });
expect(result.e2e).not.toContain('browse-smoke');
expect(result.judges).toEqual(['browse quality', 'plan-ceo-review/SKILL.md modes']);
});
test('unknown source dependencies restore the full gate and judges, but never launch periodic work', () => {
const result = select({ changedFiles: ['lib/new-runtime.ts'] });
expect(result.mode).toBe('full-fallback');
expect(result.unknownFiles).toEqual(['lib/new-runtime.ts']);
expect(result.e2e).toEqual(['browse-smoke', 'ceo-full', 'ceo-smoke']);
expect(result.judges).toEqual(['browse quality', 'plan-ceo-review/SKILL.md modes']);
expect(result.deferred.map(x => x.id)).toEqual(['autoplan-full', 'ceo-periodic']);
expect(result.reasons[0]).toContain('Unknown dependencies');
});
test('unknown runner helpers and paid test files also trigger broad fallback', () => {
for (const file of ['test/helpers/new-runner.ts', 'test/fixtures/new-prompt.ts', 'test/skill-e2e-new.test.ts', 'bun.lock']) {
expect(select({ changedFiles: [file] }).mode).toBe('full-fallback');
}
});
test('docs, free tests and touchfile-map edits do not accidentally spend on the full gate', () => {
for (const file of ['README.md', 'docs/testing.md', 'VERSION', 'AGENTS.md', 'CLAUDE.md', 'agents-digest/gstack-AGENTS.md', 'test/new-parser.test.ts', 'test/helpers/touchfiles-data.ts']) {
expect(select({ changedFiles: [file], selectedE2E: [], selectedJudges: [] }).mode).toBe('pr');
}
});
test('only verified package version metadata is safe to ignore', () => {
const old = JSON.stringify({ version: '1', scripts: { test: 'bun test' }, dependencies: { bun: '1' } });
expect(packageChangeOnlyVersion(old, old.replace('"version":"1"', '"version":"2"'))).toBe(true);
expect(packageChangeOnlyVersion(old, old.replace('bun test', 'bun skip'))).toBe(false);
expect(packageChangeOnlyVersion(old, old.replace('"bun":"1"', '"bun":"2"'))).toBe(false);
expect(packageChangeOnlyVersion(old, '{}')).toBe(false);
expect(packageChangeOnlyVersion(old, 'broken')).toBe(false);
});
test('a periodic-only prompt reports deferred coverage instead of a quick-check claim', () => {
const result = select({ changedFiles: ['autoplan/SKILL.md.tmpl'], selectedE2E: ['autoplan-full'], selectedJudges: [] });
expect(result.e2e).toEqual([]);
expect(result.deferred.map(x => x.id)).toEqual(['autoplan-full']);
expect(result.missingCoverage).toEqual([]);
expect(result.deferredPromptFiles).toEqual(['autoplan/SKILL.md.tmpl']);
expect(result.needsFullValidation).toBe(false);
});
test('an unrelated retained check does not satisfy a changed prompt', () => {
const result = select({ changedFiles: ['autoplan/sections/phase-close.md'], selectedE2E: ['browse-smoke'], selectedJudges: ['browse quality'] });
expect(result.needsFullValidation).toBe(false);
expect(result.missingCoverage).toEqual([]);
expect(result.deferredPromptFiles).toEqual(['autoplan/sections/phase-close.md']);
});
test('verified template identity covers its generated artifact while reporting the original path', () => {
const generatedMaps = { ...maps,
e2eTouchfiles: { ...maps.e2eTouchfiles, 'generated-broad': ['generated/SKILL.md.tmpl'] },
tiers: { ...maps.tiers, 'generated-broad': 'periodic' as const },
};
const result = select({ maps: generatedMaps, selectedE2E: ['generated-broad'], selectedJudges: [],
changedFiles: ['generated/SKILL.md'], sourceAliases: { 'generated/SKILL.md': 'generated/SKILL.md.tmpl' } });
expect(result.unknownFiles).toEqual([]);
expect(result.deferredPromptFiles).toEqual(['generated/SKILL.md']);
expect(result.needsFullValidation).toBe(false);
expect(select({ maps: generatedMaps, selectedE2E: ['generated-broad'], selectedJudges: [],
changedFiles: ['generated/SKILL.md'] }).needsFullValidation).toBe(true);
});
test('an unknown new skill is visibly unvalidated even after broad fallback', () => {
const result = select({ changedFiles: ['new-skill/SKILL.md.tmpl'] });
expect(result.mode).toBe('full-fallback');
expect(result.needsFullValidation).toBe(true);
});
test('a selected judge alone can cover a changed prompt with broad behavioral work deferred', () => {
const result = select({ selectedE2E: ['ceo-periodic'], selectedJudges: ['plan-ceo-review/SKILL.md modes'] });
expect(result.e2e).toEqual([]);
expect(result.needsFullValidation).toBe(false);
expect(result.deferred).toHaveLength(1);
});
test('a missing selected prompt dependency is detected even when there are no selected cases', () => {
const result = select({ selectedE2E: [], selectedJudges: [] });
expect(result.needsFullValidation).toBe(true);
const globalPrompt = select({ maps: { ...maps, globalTouchfiles: ['plan-ceo-review/**'] }, selectedE2E: [], selectedJudges: [] });
expect(globalPrompt.needsFullValidation).toBe(true);
});
test('null selections expand inventories while an empty selection remains empty', () => {
expect(select({ selectedE2E: null, selectedJudges: null }).e2e).toEqual(['browse-smoke', 'ceo-smoke']);
const empty = select({ selectedE2E: [], selectedJudges: [], changedFiles: ['README.md'] });
expect(empty.e2e).toEqual([]);
expect(empty.judges).toEqual([]);
expect(empty.needsFullValidation).toBe(false);
});
test('normalizes Windows paths and deduplicates selection and changes', () => {
const result = select({ changedFiles: ['plan-ceo-review\\SKILL.md.tmpl', 'plan-ceo-review/SKILL.md.tmpl'], selectedE2E: ['ceo-smoke', 'ceo-smoke'] });
expect(result.e2e).toEqual(['ceo-smoke']);
expect(result.unknownFiles).toEqual([]);
expect(result.needsFullValidation).toBe(false);
});
test('marathon cases are deferred to their non-blocking lane, even on full fallback', () => {
const marathon: PrProfileMaps = { ...maps, tiers: { ...maps.tiers, 'ceo-full': 'marathon' } };
for (const changedFiles of [['plan-ceo-review/SKILL.md.tmpl'], ['lib/new-runtime.ts']]) {
const result = select({ maps: marathon, changedFiles });
expect(result.e2e).not.toContain('ceo-full');
expect(result.deferred.find(({ id }) => id === 'ceo-full')).toEqual({ id: 'ceo-full', tier: 'marathon',
reason: 'Full end-to-end marathon coverage; non-blocking lane, not executed by the PR gate' });
}
expect(() => select({ maps: marathon, profile: ['ceo-full'] })).toThrow('broad gate census');
});
test('rejects stale profile IDs, incorrect tiers, missing cadence, and unknown selections', () => {
expect(() => select({ profile: ['missing'] })).toThrow('broad gate census');
expect(() => select({ profile: ['ceo-periodic'] })).toThrow('broad gate census');
expect(() => select({ profile: ['ceo-smoke', 'ceo-smoke'] })).toThrow('Duplicate');
expect(() => select({ maps: { ...maps, tiers: { 'ceo-smoke': 'gate' } } })).toThrow('broad gate census');
expect(() => select({ maps: { ...maps, tiers: { ...maps.tiers, 'ceo-full': undefined! } } })).toThrow('no broad');
expect(() => select({ selectedE2E: ['missing'] })).toThrow('Unregistered');
expect(() => select({ selectedJudges: ['missing judge'] })).toThrow('Unregistered');
});
});