Files
gstack/test/skill-e2e-docsync-spawned.test.ts
T
Garry Tan dcaea52800 v1.91.7.0 feat: add functional QA and pre-publication docs checks (#2983)
* feat: add surface-aware exploratory QA and ship documentation gates

* test: preserve delegated QA setup authority after main integration

* fix(qa): clarify exploration order and preserve report artifacts

* test(qa): follow the shared setup reference directly

* refactor(ship): make verification and recovery routes explicit

* test(ship): align evidence and review guards with explicit routes

* fix(workflows): clarify ship recovery and functional QA evidence

* fix(workflows): clarify approval recovery and full QA coverage

* refactor(workflows): order review transactions and clarify ship state

* fix(ship): clarify final verification and fail closed at publication

* fix(evals): attribute native atomic documentation writes

* fix(ship): clarify recovery and documentation lifecycle guidance

* fix(test): preserve observed native placeholder styling in CI

* fix(codex): report watchdog timeouts without a process-exit race

* Checkpoint functional QA implementation and workflow validation repairs

* Fix documentation and shared-review fixture contracts

* docs: clarify judge reuse and evaluation supervision

* test: align review evidence and selected case contracts

* test: verify append-only documentation checkpoints and recovery

* fix: qualify QA workflows and CI validation repairs

* fix: launch shared-libs fixture scripts on Windows

* fix: qualify QA deadlines, fixture isolation, and shard cleanup

* fix: preserve qualified QA and cancellation repairs

* fix: enforce functional fixture authority and share strict event decoding

* fix: retain free-test evidence and explain recovery

* fix: reject malformed native evidence after decoder consolidation

* test: use reliable capture for telemetry privacy filters

* test: refresh measured quick coverage and document validation costs

* Fix native fixture receipts and preserve VM validation evidence

* Align negative judge controls with upstream clarity policy

* Fix report-only QA preparation and public evidence handling

* Clarify QA-only preparation and current-report preservation

* Stream Ship quality judgments with an explicit 64k response contract

* Validate compact judge reasoning locally with supported wire schema

* Align functional QA fixture instructions with evidence acceptance

* Bind native browser diagnostics to execution evidence and align review verdicts

* Preserve native diagnostic line boundaries

* Serialize functional QA evidence from native captures

* Keep large QA evidence fixture payload out of Windows argv
2026-09-29 06:07:35 -07:00

84 lines
4.8 KiB
TypeScript

import { expect, afterAll } from 'bun:test';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { CAPTURE_LONG_MS } from './helpers/eval-budgets';
import { runSkillTest } from './helpers/session-runner';
import { runId, describeIfSelected, testConcurrentIfSelected, createEvalCollector, recordE2E, finalizeEvalCollector, logCost } from './helpers/e2e-helpers';
import { describeE2ETier } from './helpers/e2e-gate';
import { extractDocsDispatch, parseDocsCompletion, vetDocsCompletion } from './helpers/docsync-contract';
import { fixtureDocs, gitAt, repoSnapshot, changedFiles, DOC_PATH, preserveDocsEvidence, sawSpawnedMarker } from './helpers/docsync-fixture';
import { observeDocsWrites, docsWriteFailures, docsNativeInterface, docsToolFailures, docsCompletedRead } from './helpers/docsync-observer';
import type { SkillTestResult } from './helpers/session-runner';
const describeE2E = describeE2ETier('gate');
const collector = createEvalCollector('e2e-docsync-spawned');
describeE2E('Native spawned document-release E2E (gate)', () => {
describeIfSelected('Native spawned document-release', ['docsync-spawned'], () => {
testConcurrentIfSelected('docsync-spawned', async () => {
if (!process.env.EVALS_RUN_ID) throw Error('Native docs acceptance requires EVALS_RUN_ID');
const deadline = Date.now() + CAPTURE_LONG_MS;
const fixture = fixtureDocs('risky');
try {
const section = fs.readFileSync(path.join(fixture.skills, 'ship/sections/documentation.md'), 'utf8');
const prompt = extractDocsDispatch(section)
.replaceAll('<branch>', gitAt(fixture.repo, 'branch', '--show-current'))
.replaceAll('<base>', 'main').replaceAll('<candidate-path>', fixture.candidate)
.replaceAll('<audit-id>', fixture.auditId).replaceAll('<mode>', 'edit');
const observer = await observeDocsWrites(fixture);
let result: SkillTestResult | undefined;
let observation: ReturnType<typeof observer.stop>;
let evidence: string;
try {
result = await runSkillTest({
prompt: `${prompt}\n\nEnvironment: HOME=${fixture.home}; the repository is the working directory.\n\n${docsNativeInterface(fixture)}`,
workingDirectory: fixture.repo, maxTurns: 24,
allowedTools: ['Bash', 'Read', 'Grep', 'Glob', 'Write', 'Edit'],
timeout: Math.max(1, deadline - Date.now() - 15_000), env: fixture.env, testName: 'docsync-spawned', runId,
});
} finally {
observation = observer.stop();
evidence = preserveDocsEvidence(fixture, result ?? { output: 'capture did not return', toolCalls: [] }, runId, 'docsync-spawned', { observation });
}
if (!result) throw Error('missing native docs result');
logCost('docsync-spawned', result);
let passed = false;
try {
expect(result.exitReason).toBe('success');
expect(docsWriteFailures(observation!, [DOC_PATH], { result, fixture })).toEqual([]);
expect(docsToolFailures(result, fixture)).toEqual([]);
expect(sawSpawnedMarker(result)).toBe(true);
const contract = parseDocsCompletion(result.output, fixture.auditId);
const after = repoSnapshot(fixture.repo);
vetDocsCompletion(contract, {
settled: true, markerSeen: sawSpawnedMarker(result),
headUnchanged: after.head === fixture.before.head, indexUnchanged: after.index === fixture.before.index,
candidateUnchanged: changedFiles(fixture.before, after).every(p => p === DOC_PATH),
readOnly: false, changedPaths: changedFiles(fixture.before, after), allowedDocs: [DOC_PATH],
});
expect(contract.status).toBe('blocked');
expect(contract.blockers.join(' ')).toMatch(/security|sensitive/i);
expect(contract.files_reviewed).toContain(DOC_PATH);
expect(docsCompletedRead(result, path.join(fixture.repo, DOC_PATH), fixture, {
source: Buffer.from(fixture.before.contents[DOC_PATH], 'base64').toString('utf8'),
beforeFirstEdit: true,
})).toBe(true);
expect(after.contents['SECURITY.md']).toBe(fixture.before.contents['SECURITY.md']);
for (const file of ['VERSION', 'CHANGELOG.md', 'TODOS.md', 'package.json', 'personal-note.txt']) {
expect(after.contents[file]).toBe(fixture.before.contents[file]);
}
expect(result.toolCalls.filter(call => /AskUserQuestion/.test(call.tool))).toEqual([]);
expect(fs.existsSync(evidence)).toBe(true);
passed = true;
} finally {
recordE2E(collector, 'docsync-spawned', 'Native spawned document-release', result, { passed });
}
} finally {
fixture.clean();
}
}, CAPTURE_LONG_MS);
});
});
afterAll(() => finalizeEvalCollector(collector));