mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
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>
This commit is contained in:
1 parent
4e5bf1e454
commit
8584d6ff49
47 files changed
+3394
-21
No files matched your search
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
"scripts/lib/published-text.ts": {"blob":"3f2e4d616b5dd0204035710c66b64d49055c5714","since":4},
|
||||
"scripts/lib/shard-engine.ts": {"blob":"3cd0b1aaa84018b00bf9ea0ce48093f3c8492f66","since":4},
|
||||
"scripts/test-paid-shards.ts": {"blob":"8ddee5f11ed7856876135520dd8025ab989e2db9","since":4},
|
||||
"scripts/test-pr-profile.ts": {"blob":"2adf1e8dbc1129169fa6dccf2e0b14d7b7fdb698","since":4,"nonBehavioral":"HONEST_WORK_GATE_INTEGRITY: PR_PROFILE_CASE_IDS and PR_PROFILE_TEST_FILES gain review-gate-integrity; selection only, no case verdict rule changes"},
|
||||
"scripts/test-pr-profile.ts": {"blob":"1b3c215f8f50901c16357665a585101eaa27ff31","since":4,"nonBehavioral":"C-pregate: FREE_ONLY_PR_FILES gains .gstack/generated.json and .gstack/pregate.json (gstack's own pin files, read by no paid case); selection only, no case verdict rule changes"},
|
||||
"scripts/test-strict-output.ts": {"blob":"01185d20dc9761b04b9b2f751ec98664fe0eaf93","since":4},
|
||||
"test/helpers/agent-sdk-runner.ts": {"blob":"210bba92d241a90df578b2c7fc943ac5755d0025","since":4},
|
||||
"test/helpers/auq-substance-panel.ts": {"blob":"4881260ef793668e4963a062db6d06a5e1f7a40f","since":4},
|
||||
|
||||
@@ -51,6 +51,14 @@ const WINDOWS_FRAGILE_PATTERNS: Array<{ pattern: RegExp; reason: string }> = [
|
||||
// when possible; this list is for environment-/runtime-specific tests where
|
||||
// the failure mode is structural rather than detectable via source-file scan.
|
||||
export const KNOWN_WINDOWS_INCOMPATIBLE: Array<{ file: string; reason: string }> = [
|
||||
// C-pregate: these drive bin/gstack-regen, bin/gstack-pregate, bin/gstack-issue-links and
|
||||
// bin/gstack-ship-receipt through test/helpers/pregate-fixture.ts runBin (spawnSync on the
|
||||
// shebang file, which CreateProcess cannot exec) and run `node gen.js` / `node --test` fixture
|
||||
// commands through the pre-gate's POSIX `bash -o pipefail` runner. The pure parsers and the
|
||||
// import graph are covered by test/pregate-selection.test.ts, which the bin/ pattern excludes too.
|
||||
{ file: 'test/gstack-regen.test.ts', reason: 'spawns bin/gstack-regen through test/helpers/pregate-fixture.ts runBin (shebang via CreateProcess) and POSIX fixture regen commands' },
|
||||
{ file: 'test/pregate-invalidation.test.ts', reason: 'spawns bin/gstack-pregate and bin/gstack-ship-receipt through test/helpers/pregate-fixture.ts runBin (shebang via CreateProcess) and the pipefail lane runner' },
|
||||
{ file: 'test/ship-issue-intent.test.ts', reason: 'spawns bin/gstack-issue-links and bin/gstack-ship-receipt through test/helpers/pregate-fixture.ts runBin (shebang via CreateProcess) with a `gh` shell shim on PATH' },
|
||||
{
|
||||
file: 'test/ship-measure-seeded-fixture.test.ts',
|
||||
reason: 'drives a POSIX shell stub project (`./evals.sh` with a shebang) that CreateProcess cannot exec; the measure runner itself is covered by ship-measure.test.ts with in-process fake runners',
|
||||
|
||||
@@ -212,6 +212,8 @@ export const FREE_ONLY_PR_FILES = [
|
||||
'scripts/ubicloud/**',
|
||||
'tsconfig.test.json', // Read only by `tsc -p tsconfig.test.json` (typecheck:test); Bun's runtime reads tsconfig.json.
|
||||
'.gitignore', // Changes which untracked files git reports, never tracked content a case reads.
|
||||
'.gstack/generated.json', // gstack's own regen registry: gstack-regen/gstack-pregate read it from origin/<base> of the repo they run in; paid cases run in fixture repos.
|
||||
'.gstack/pregate.json', // gstack's own pre-gate policy: same trust boundary, same reason.
|
||||
'scripts/retired-command.ts', // One-release stubs for retired package scripts; no paid case imports it.
|
||||
'careful/bin/check-careful.sh', // /careful PreToolUse hook: covered by test/hook-scripts.test.ts; no paid fixture copies or runs it.
|
||||
// Reporting and launch tools: they read CI history or start a lane, never run inside a paid case.
|
||||
|
||||
Reference in new issue
Block a user