mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-03 01:46:55 +02:00
* 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
71 lines
3.5 KiB
TypeScript
71 lines
3.5 KiB
TypeScript
import { expect, test } from 'bun:test';
|
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join, resolve } from 'node:path';
|
|
|
|
const template = readFileSync(new URL('../ship/sections/pr-body.md.tmpl', import.meta.url), 'utf8');
|
|
const scanner = resolve(import.meta.dir, '../bin/gstack-redact');
|
|
|
|
for (const failure of ['none', 'body', 'title'] as const) {
|
|
test(`publication scan consumes the real scanner result: ${failure}`, () => {
|
|
const root = mkdtempSync(join(tmpdir(), 'ship-scan-'));
|
|
try {
|
|
const bin = join(root, '.claude/skills/gstack/bin');
|
|
mkdirSync(bin, { recursive: true });
|
|
writeFileSync(join(bin, 'gstack-config'), '#!/bin/sh\nprintf "private\\n"\n', { mode: 0o755 });
|
|
writeFileSync(join(bin, 'gstack-redact'), `#!/bin/sh
|
|
kind=title
|
|
case "$*" in *--from-file*) kind=body ;; esac
|
|
printf '%s\\n' "$kind" >> "$HOME/scans"
|
|
if [ "$kind" = "$FAIL_AT" ]; then
|
|
exec ${JSON.stringify(process.execPath)} ${JSON.stringify(scanner)} --from-file "$HOME/missing-input" --json
|
|
fi
|
|
exec ${JSON.stringify(process.execPath)} ${JSON.stringify(scanner)} "$@"
|
|
`, { mode: 0o755 });
|
|
const block = template.match(/```bash\n(: "\$\{NEW_TITLE:[\s\S]*?)\n```/)?.[1];
|
|
expect(block).toBeDefined();
|
|
const result = Bun.spawnSync(['bash', '-c', block!], {
|
|
cwd: root,
|
|
env: { ...process.env, HOME: root, NEW_TITLE: 'v1.2.3.4 fix: publication checks', FAIL_AT: failure },
|
|
stdout: 'pipe', stderr: 'pipe', timeout: 10_000,
|
|
});
|
|
const output = result.stdout.toString();
|
|
const error = result.stderr.toString();
|
|
const calls = readFileSync(join(root, 'scans'), 'utf8').trim().split('\n');
|
|
if (failure === 'none') {
|
|
expect(result.exitCode).toBe(0);
|
|
expect(calls).toEqual(['body', 'title']);
|
|
expect(output).toContain('"HIGH": 0');
|
|
} else {
|
|
expect(result.exitCode).toBe(1);
|
|
expect(error).toContain('missing-input');
|
|
expect(calls).toEqual(failure === 'body' ? ['body'] : ['body', 'title']);
|
|
if (failure === 'body') expect(output).toContain('BLOCKED');
|
|
}
|
|
} finally {
|
|
rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
}
|
|
|
|
test('publication reports unavailable triage separately from an empty successful fetch', () => {
|
|
const section = template.slice(template.indexOf('## Greptile Review'), template.indexOf('## Scope Drift'));
|
|
expect(section).toContain('Greptile triage: UNAVAILABLE (dispatch failed)');
|
|
expect(section).toContain('actual reason');
|
|
expect(section).toContain('complete');
|
|
expect(section).toContain('no_pr');
|
|
});
|
|
|
|
test('publication refreshes the open review and title without treating lookup failure as absence', () => {
|
|
const lookup = template.slice(0, template.indexOf('### Resolve Linked Spec'));
|
|
expect(lookup).toContain("Recheck Step 18's PR/MR lookup and record it");
|
|
expect(lookup.replace(/\s+/g, ' ')).toContain('Errors or ambiguous matches STOP publication');
|
|
expect(lookup.replace(/\s+/g, ' ')).toContain("If the open PR/MR or title changed, repeat Step 18's identity/title preparation");
|
|
expect(lookup.replace(/\s+/g, ' ')).toContain('then return here for a new lookup, fresh body and both redaction scans before publishing');
|
|
expect(lookup).not.toContain('Ship control flow');
|
|
expect(lookup).not.toContain('|| echo "NO_PR"');
|
|
expect(lookup).not.toContain('|| echo "NO_MR"');
|
|
expect(template).toContain('Exit 1 or any other error blocks');
|
|
expect(template).toContain('public-strict policy');
|
|
});
|