Files
gstack/scripts/gen-ship-goldens.ts
Garry Tanandcapy-ai[bot] 8584d6ff49 v1.91.77.0 feat(ship): two-stage gstack-pregate, gstack-regen generated-file registry, intent-based issue links (multi-agent wave C-pregate) (#3121)
* v1.91.77.0 feat(ship): two-stage gstack-pregate, gstack-regen registry, intent-based issue links (multi-agent wave C-pregate)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(pregate): keep the bin-driving pregate tests off the Windows subset; pin files are free-only for eval selection

The three C-pregate tests that spawn bin/gstack-regen, bin/gstack-pregate,
bin/gstack-issue-links and bin/gstack-ship-receipt do so through
test/helpers/pregate-fixture.ts runBin, so the Windows curation's source
scan of the test file never saw a bin/ spawn and shipped them to
windows-latest, where CreateProcess cannot exec a shebang (14 failures in
windows-free-shard 2 and 5). Each is now a KNOWN_WINDOWS_INCOMPATIBLE entry
with the precise reason. .gstack/generated.json and .gstack/pregate.json
join FREE_ONLY_PR_FILES: no paid case reads gstack's own pin files (the
tools read origin/<base> of the repo they run in, and paid cases run in
fixture repos), so touching them no longer restores every gate case.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test(harness-version): record the FREE_ONLY_PR_FILES pin-file entries as non-behavioral

scripts/test-pr-profile.ts is a pinned shared-harness file; the two
.gstack pin-file entries change selection only, never a case verdict.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-11 01:57:16 +00:00

45 lines
2.0 KiB
TypeScript

/**
* gen-ship-goldens — refresh the byte-pinned /ship renders under
* test/fixtures/golden/ (test/host-config.test.ts compares a fresh render to
* them). The claude golden is the tracked ship/SKILL.md; the codex, factory
* and agy goldens come from a `--out-dir` render of each host. Registered in
* .gstack/generated.json so `gstack-regen check` reports a stale golden
* before any remote gate and `gstack-regen write` refreshes it.
*/
import { spawnSync } from 'node:child_process';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
const ROOT = path.resolve(import.meta.dir, '..');
const GOLDEN_DIR = path.join(ROOT, 'test', 'fixtures', 'golden');
const HOSTS: Array<{ host: string; dir: string }> = [
{ host: 'codex', dir: '.agents' },
{ host: 'factory', dir: '.factory' },
{ host: 'agy', dir: '.agy' },
];
export function generateShipGoldens(): string[] {
const written: string[] = [];
const out = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-ship-goldens-'));
try {
const copy = (from: string, to: string) => {
const bytes = fs.readFileSync(from);
const dest = path.join(GOLDEN_DIR, to);
if (!fs.existsSync(dest) || !fs.readFileSync(dest).equals(bytes)) { fs.writeFileSync(dest, bytes); written.push(path.relative(ROOT, dest)); }
};
copy(path.join(ROOT, 'ship', 'SKILL.md'), 'claude-ship-SKILL.md');
for (const { host, dir } of HOSTS) {
const r = spawnSync('bun', ['run', path.join(ROOT, 'scripts', 'gen-skill-docs.ts'), '--host', host, '--out-dir', out], { cwd: ROOT, encoding: 'utf8', timeout: 180_000 });
if (r.status !== 0) throw new Error(`gen-skill-docs --host ${host} --out-dir failed (exit ${r.status}):\n${r.stderr}`);
copy(path.join(out, dir, 'skills', 'gstack-ship', 'SKILL.md'), `${host}-ship-SKILL.md`);
}
} finally { fs.rmSync(out, { recursive: true, force: true }); }
return written;
}
if (import.meta.main) {
const written = generateShipGoldens();
console.log(written.length ? `GENERATED: ${written.join(' ')}` : 'ship goldens: fresh');
}