fix(#2358): scope review.md and ship.md temp files to a per-run mktemp directory (#2433)

* fix(#2358): scope review workflow temp files to a per-run mktemp dir

/gsd-review wrote every prompt/section/output temp file to a hardcoded
/tmp path keyed only on the phase number, so two GSD projects sharing
a small phase number collide on the exact same path and a crashed
run's leftover file becomes bait a later, unrelated run can silently
read. ship.md's external peer-review stderr capture was strictly
worse — one shared, unqualified path across every project/phase/run.

Thread a single mktemp -d "${TMPDIR:-/tmp}/gsd-review.XXXXXX" run
directory through every review.md temp path (67 sites) via a new
{run_dir}/$RUN_DIR placeholder, mirroring the existing {phase}
substitution mechanism, and clean it up at the end of the run. Route
ship.md's stderr capture through a per-run mktemp file the same way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#2358): regenerate fixtures + lint gate-prep

* fix(#2358): repair failing tests after gate verification

* fix(#2358): thread RUN_DIR scoping into reviewer-instances.md (#1517)

review.md's own invoke_reviewers step lazily loads
gsd-core/references/reviewer-instances.md for the review.reviewer_instances
codepath, but that doc was missed when review.md and ship.md were moved to
the run-scoped {run_dir} temp directory. It still read the combined prompt
from the old /tmp/gsd-review-prompt-{phase}.md (which build_prompt no longer
writes, breaking reviewer-instances functionality outright) and wrote each
instance's output to the old unscoped /tmp/gsd-review-${INSTANCE_NAME}-{phase}.md,
leaving the exact cross-project temp-file collision bug open for that code
path. Both paths now thread through {run_dir}, matching every other reviewer
block in review.md.

Extends the existing #2358 regression test with assertions pinning
reviewer-instances.md's prompt read and output write to {run_dir}, and adds
the Fixed changeset fragment. Regenerated the golden-install-parity content
hashes for reviewer-instances.md via `npm run gen:golden` (paths unchanged;
only the modified file's hash moved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#2358): backfill changeset pr (#2433)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-19 13:12:03 -04:00
committed by GitHub
parent cd6665d73b
commit 40ce95f882
28 changed files with 380 additions and 151 deletions

View File

@@ -144,7 +144,7 @@ describe('Antigravity reviewer repo grounding in /gsd-review (#2176)', () => {
.replace(/\}; then$/, '}')
// Convert the native path to POSIX form so it survives bash on Windows
// runners (Git Bash accepts D:/... but eats backslashes).
.replaceAll('/tmp/gsd-review-antigravity-{phase}.md', toPosixPath(out));
.replaceAll('{run_dir}/gsd-review-antigravity.md', toPosixPath(out));
const runDetect = (content) => {
fs.writeFileSync(out, content);
try {

View File

@@ -52,7 +52,7 @@ describe('Antigravity (agy) reviewer invocation in /gsd-review (#2073)', () => {
test('#2073 mode 1 — uses a file-reference prompt (mirrors the Cursor block)', () => {
const block = agyBashBlock();
assert.ok(
/Read the file at \/tmp\/gsd-review-prompt-/.test(block),
/Read the file at \{run_dir\}\/gsd-review-prompt\.md/.test(block),
'agy should reference the prompt by file path, not inline it',
);
});

View File

@@ -79,7 +79,7 @@ describe('Cursor CLI reviewer in /gsd-review (#1960)', () => {
test('invocation passes prompt as a file-path argument (not via stdin pipe)', () => {
const c = fs.readFileSync(reviewPath, 'utf-8');
assert.ok(
c.includes('Read the file at /tmp/gsd-review-prompt-'),
c.includes('Read the file at {run_dir}/gsd-review-prompt.md'),
'review.md cursor-agent invocation should pass prompt by referencing the file path as an argument'
);
});

View File

@@ -0,0 +1,201 @@
'use strict';
/**
* #2358 — review.md (and ship.md's external peer-review step) wrote every
* temp file to a hardcoded, phase-number-only path under /tmp
* (`/tmp/gsd-review-prompt-{phase}.md`, `/tmp/gsd-review-<reviewer>-{phase}.*`,
* `/tmp/gsd-review-stderr.log`). Two GSD projects with a phase sharing the
* same small integer number collide on the exact same path; a crashed prior
* run's leftover file is bait a later, unrelated run can silently read (the
* reporter forensically confirmed agy read a 3-week-old stale prompt from a
* DIFFERENT project). Neither file used the portable ${TMPDIR:-/tmp} seam,
* and review.md had no cleanup.
*
* The fix threads a single `mktemp -d "${TMPDIR:-/tmp}/gsd-review-XXXXXX"`
* run directory (RUN_DIR / {run_dir}) through every review.md temp path, and
* ship.md's stderr capture through a per-run `mktemp` file — eliminating the
* shared-path collision by construction rather than by convention.
*
* review.md and ship.md ARE the product the runtime loads (an AI agent reads
* and executes these workflow instructions verbatim), so this is a
* static-content regression against the deployed text, mirroring
* fix-2194-review-timeout-guidance.test.cjs.
*/
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { cleanup } = require('./helpers.cjs');
const REVIEW_MD = path.join(__dirname, '..', 'gsd-core', 'workflows', 'review.md');
const SHIP_MD = path.join(__dirname, '..', 'gsd-core', 'workflows', 'ship.md');
const REVIEWER_INSTANCES_MD = path.join(__dirname, '..', 'gsd-core', 'references', 'reviewer-instances.md');
describe('#2358 review.md temp paths are run-scoped, not phase-only', () => {
const content = fs.readFileSync(REVIEW_MD, 'utf-8');
test('no bare, unscoped /tmp/gsd-review-* path remains', () => {
assert.ok(
!content.includes('/tmp/gsd-review'),
'review.md must not contain any hardcoded /tmp/gsd-review* literal — ' +
'every review temp path must be rooted under the run-scoped mktemp directory'
);
});
test('creates exactly one run-scoped directory via the portable ${TMPDIR:-/tmp} seam', () => {
const mktempAssignments = content.match(/RUN_DIR=\$\(mktemp -d "\$\{TMPDIR:-\/tmp\}\/gsd-review-XXXXXX"\)/g) || [];
assert.equal(
mktempAssignments.length, 1,
'review.md must create the run directory with exactly one `mktemp -d "${TMPDIR:-/tmp}/gsd-review-XXXXXX"` — ' +
'a hardcoded /tmp (no ${TMPDIR:-/tmp} seam) breaks on Windows, and re-mktemp-ing per block would break the ' +
'write/read pairing between build_prompt and the local-reviewer budget-trimming reads'
);
});
test('every downstream temp path is threaded through {run_dir} / $RUN_DIR, not re-derived from {phase}', () => {
assert.ok(
/\{run_dir\}\/gsd-review-/.test(content),
'reviewer blocks must reference {run_dir}/gsd-review-... (the run-scoped placeholder)'
);
assert.ok(
/\$\{RUN_DIR\}\/gsd-review-/.test(content),
'the build_prompt section-file writes must reference ${RUN_DIR}/gsd-review-... (the run-scoped shell var)'
);
// The old isolation key must be gone entirely from path construction.
assert.ok(
!/\/tmp\/gsd-review[^\r\n]*\{phase\}/.test(content),
'no temp path may still be keyed on a bare {phase} placeholder'
);
assert.ok(
!/\$\{PHASE\}-(?:instructions|roadmap|plan|project|context|research|requirements)\.md/.test(content),
'no temp path may still be keyed on the ${PHASE} shell var'
);
});
test('the Antigravity reviewer prompt-instruction string references the run-scoped path', () => {
const agyPromptMatch = content.match(/_AGY_PROMPT="Read the file at ([^ ]+)/);
assert.ok(agyPromptMatch, '_AGY_PROMPT must contain a "Read the file at <path>" instruction');
assert.equal(
agyPromptMatch[1], '{run_dir}/gsd-review-prompt.md',
'the Antigravity reviewer must be told to read the run-scoped prompt path, not a bare {phase}-only /tmp path — ' +
'this is the exact instruction text the reporter forensically traced back to a stale cross-project read'
);
});
test('the Cursor reviewer prompt-instruction string references the run-scoped path', () => {
const cursorPromptMatch = content.match(/CURSOR_PROMPT_ARG="Read the file at ([^ ]+)/);
assert.ok(cursorPromptMatch, 'CURSOR_PROMPT_ARG must contain a "Read the file at <path>" instruction');
assert.equal(
cursorPromptMatch[1], '{run_dir}/gsd-review-prompt.md',
'the Cursor reviewer must be told to read the run-scoped prompt path, not a bare {phase}-only /tmp path'
);
});
test('the run directory is cleaned up at the end of the review', () => {
const presentResultsStart = content.indexOf('<step name="present_results">');
assert.notEqual(presentResultsStart, -1, 'review.md must contain the present_results step');
const section = content.slice(presentResultsStart, presentResultsStart + 1500);
assert.ok(
/rm -rf "\{run_dir\}"/.test(section),
'present_results must remove the run-scoped temp directory once REVIEWS.md is written'
);
});
});
describe('#2358 ship.md external-review stderr capture is run-scoped', () => {
const content = fs.readFileSync(SHIP_MD, 'utf-8');
test('no bare, unqualified /tmp/gsd-review-stderr.log path remains', () => {
assert.ok(
!content.includes('/tmp/gsd-review-stderr.log'),
'ship.md must not write/read a shared, unqualified stderr log path — every ship run, phase, and project ' +
'shares this exact path with zero disambiguator, which is strictly worse than review.md\'s phase-only keying'
);
});
test('stderr is captured to a per-run file via the portable ${TMPDIR:-/tmp} seam', () => {
assert.ok(
/REVIEW_STDERR_FILE=\$\(mktemp "\$\{TMPDIR:-\/tmp\}\/gsd-review-stderr-XXXXXX"\)/.test(content),
'ship.md must create the stderr capture file via `mktemp "${TMPDIR:-/tmp}/gsd-review-stderr-XXXXXX"`'
);
assert.ok(
/2>"\$\{REVIEW_STDERR_FILE\}"/.test(content),
'the external review command invocation must redirect stderr to the per-run $REVIEW_STDERR_FILE, not a literal path'
);
assert.ok(
/cat "\$\{REVIEW_STDERR_FILE\}"/.test(content),
'the failure-handling block must read back the same per-run $REVIEW_STDERR_FILE'
);
});
});
describe('#2358 reviewer-instances.md (#1517, lazily loaded from invoke_reviewers) is run-scoped too', () => {
// review.md's own invoke_reviewers step lazily loads this companion doc for the
// review.reviewer_instances codepath — it was missed in the initial pass and still
// pointed at the old, unscoped /tmp/gsd-review-*-{phase} paths, which both broke
// reviewer-instances functionality (the prompt file build_prompt now writes lives
// at {run_dir}/gsd-review-prompt.md, never the old path) and left the exact
// cross-project collision bug open for that code path.
const content = fs.readFileSync(REVIEWER_INSTANCES_MD, 'utf-8');
test('no bare, unscoped /tmp/gsd-review-* path remains', () => {
assert.ok(
!content.includes('/tmp/gsd-review'),
'reviewer-instances.md must not contain any hardcoded /tmp/gsd-review* literal — ' +
'every review temp path must be rooted under the run-scoped {run_dir} directory'
);
});
test('no temp path is still keyed on a bare {phase} placeholder', () => {
assert.ok(
!/gsd-review[^\r\n]*\{phase\}/.test(content),
'no temp path may still be keyed on a bare {phase} placeholder'
);
});
test('the instance prompt read and output write are threaded through {run_dir}', () => {
assert.ok(
/\{run_dir\}\/gsd-review-prompt\.md/.test(content),
'reviewer-instances.md must read the prompt from {run_dir}/gsd-review-prompt.md, ' +
'the same run-scoped path build_prompt writes in review.md'
);
assert.ok(
/\{run_dir\}\/gsd-review-\$\{INSTANCE_NAME\}\.md/.test(content),
'reviewer-instances.md must write each instance\'s output to ' +
'{run_dir}/gsd-review-${INSTANCE_NAME}.md, not a {phase}-keyed /tmp path'
);
});
});
describe('#2358 design principle: run-scoped temp dirs never collide across projects/phases', () => {
// review.md and ship.md are markdown instructions an AI agent executes, not
// node-executable code, so this does not shell out to the literal snippet —
// it validates the underlying guarantee the fix relies on (mktemp-style
// randomized-suffix isolation) using Node's built-in equivalent, which is
// cross-platform (Windows included) unlike shelling out to `mktemp`/bash.
test('two runs — even for the same phase number, same or different project — get distinct run dirs', () => {
const prefix = path.join(os.tmpdir(), 'gsd-review-');
const runDirA = fs.mkdtempSync(prefix);
const runDirB = fs.mkdtempSync(prefix);
try {
assert.notEqual(
runDirA, runDirB,
'two review runs sharing the same phase number must never resolve to the same run-scoped directory'
);
const phase = '10'; // same phase number in both "projects" — the historical collision case
const staleProjectAPath = path.join(runDirA, `gsd-review-prompt.md`);
const laterProjectBPath = path.join(runDirB, `gsd-review-prompt.md`);
assert.notEqual(
staleProjectAPath, laterProjectBPath,
`phase ${phase} in two different runs must not resolve to the same prompt path`
);
} finally {
// helpers.cleanup (not raw fs.rmSync) carries the Windows-EBUSY retry budget.
cleanup(runDirA);
cleanup(runDirB);
}
});
});

View File

@@ -129,7 +129,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -295,14 +295,14 @@
"gsd-core/workflows/remove-phase.md": "23b9eb0858a2535e",
"gsd-core/workflows/remove-workspace.md": "d0bd7e0601138798",
"gsd-core/workflows/resume-project.md": "98e2cf8908e73a52",
"gsd-core/workflows/review.md": "c4622380e61615c8",
"gsd-core/workflows/review.md": "6f6575621367b9ff",
"gsd-core/workflows/scan.md": "a7fecd67e5cd655f",
"gsd-core/workflows/secure-phase.md": "52ddc46233e8fa66",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "6d25100a9de15b31",
"gsd-core/workflows/settings-integrations.md": "4d3001ad2b5dad8f",
"gsd-core/workflows/settings.md": "8258f7bd3700d608",
"gsd-core/workflows/ship.md": "82a63ca54f4b322f",
"gsd-core/workflows/ship.md": "782e5998a4257acf",
"gsd-core/workflows/sketch-wrap-up.md": "0f842a609851a401",
"gsd-core/workflows/sketch.md": "314b7d323c6b57eb",
"gsd-core/workflows/smart-entry.md": "3ce5b6228238fdb6",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "df9a45f0b1880999",
"gsd-core/workflows/remove-workspace.md": "a7ca66db6b7c132c",
"gsd-core/workflows/resume-project.md": "f28da1200e4545f4",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/review.md": "f1fbefbd64bd890e",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "414db4dbea97ba44",
"gsd-core/workflows/settings-integrations.md": "70515c5838fb9826",
"gsd-core/workflows/settings.md": "d96ddf01fb85e61e",
"gsd-core/workflows/ship.md": "b377dab2bc92a6e5",
"gsd-core/workflows/ship.md": "f486f2731ca8b72a",
"gsd-core/workflows/sketch-wrap-up.md": "5f5ebb6a80d610c6",
"gsd-core/workflows/sketch.md": "8319cedf3f93fc35",
"gsd-core/workflows/smart-entry.md": "449238eb94abe187",

View File

@@ -199,7 +199,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -365,14 +365,14 @@
"gsd-core/workflows/remove-phase.md": "8effc8742d58a11a",
"gsd-core/workflows/remove-workspace.md": "10882656198d9075",
"gsd-core/workflows/resume-project.md": "af9761bcec0f6fe9",
"gsd-core/workflows/review.md": "15b8defb2d791092",
"gsd-core/workflows/review.md": "8c05b76fe9d00c30",
"gsd-core/workflows/scan.md": "75c670d08cee8680",
"gsd-core/workflows/secure-phase.md": "8030d2b2a5bfdf07",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "94d61da368e9f85b",
"gsd-core/workflows/settings-integrations.md": "dfe3672c4fabf139",
"gsd-core/workflows/settings.md": "acdd79110699a608",
"gsd-core/workflows/ship.md": "2e50ecfb12d48282",
"gsd-core/workflows/ship.md": "3a0262c1197cf2f8",
"gsd-core/workflows/sketch-wrap-up.md": "d52a5462bafda830",
"gsd-core/workflows/sketch.md": "dbe6acc4d976060c",
"gsd-core/workflows/smart-entry.md": "1850447c045f36d8",

View File

@@ -128,7 +128,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -294,14 +294,14 @@
"gsd-core/workflows/remove-phase.md": "ada8a0546c686483",
"gsd-core/workflows/remove-workspace.md": "f3ab3a88a7e9e1ed",
"gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96",
"gsd-core/workflows/review.md": "f1dbb3769d461ec2",
"gsd-core/workflows/review.md": "013126685d8a9d50",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "d6ac1f4db6a5da75",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "339def28c34b0797",
"gsd-core/workflows/settings-integrations.md": "53649313d20694ae",
"gsd-core/workflows/settings.md": "7e7458cdb2b68ec5",
"gsd-core/workflows/ship.md": "63e65d06a6038e8e",
"gsd-core/workflows/ship.md": "cc8428f393c44f67",
"gsd-core/workflows/sketch-wrap-up.md": "121ed4b8127abf04",
"gsd-core/workflows/sketch.md": "737c0492686fea2d",
"gsd-core/workflows/smart-entry.md": "ad20cf74ae2e8291",

View File

@@ -132,7 +132,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -298,14 +298,14 @@
"gsd-core/workflows/remove-phase.md": "e336350f8113a328",
"gsd-core/workflows/remove-workspace.md": "e685dfbd736dfd90",
"gsd-core/workflows/resume-project.md": "e23981178fa37b3d",
"gsd-core/workflows/review.md": "8c996dc10e923685",
"gsd-core/workflows/review.md": "075ea1aa6a2b8339",
"gsd-core/workflows/scan.md": "dfd92717caea0ce7",
"gsd-core/workflows/secure-phase.md": "00de56d6d993bb2c",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "69f3a19bf2c61160",
"gsd-core/workflows/settings-integrations.md": "76eee76d6eb57657",
"gsd-core/workflows/settings.md": "3701faed09d55247",
"gsd-core/workflows/ship.md": "baf53afdff3601d4",
"gsd-core/workflows/ship.md": "416cfe6c07694753",
"gsd-core/workflows/sketch-wrap-up.md": "1f44789553180d84",
"gsd-core/workflows/sketch.md": "2226779b6003a71c",
"gsd-core/workflows/smart-entry.md": "9a64f43927641ca4",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "df9a45f0b1880999",
"gsd-core/workflows/remove-workspace.md": "a7ca66db6b7c132c",
"gsd-core/workflows/resume-project.md": "f28da1200e4545f4",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/review.md": "f1fbefbd64bd890e",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "414db4dbea97ba44",
"gsd-core/workflows/settings-integrations.md": "70515c5838fb9826",
"gsd-core/workflows/settings.md": "d96ddf01fb85e61e",
"gsd-core/workflows/ship.md": "b377dab2bc92a6e5",
"gsd-core/workflows/ship.md": "f486f2731ca8b72a",
"gsd-core/workflows/sketch-wrap-up.md": "2aba89ecd8f41a0d",
"gsd-core/workflows/sketch.md": "5eedd93f9a5b49d5",
"gsd-core/workflows/smart-entry.md": "449238eb94abe187",

View File

@@ -235,7 +235,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "335a974ea98d5d83",
"gsd-core/references/reviewer-instances.md": "1a677abcfba49da4",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -401,14 +401,14 @@
"gsd-core/workflows/remove-phase.md": "9ee0fddd11a0d9d4",
"gsd-core/workflows/remove-workspace.md": "19d7465aaa50cb62",
"gsd-core/workflows/resume-project.md": "9965f87eb278f7f8",
"gsd-core/workflows/review.md": "a980007626185b70",
"gsd-core/workflows/review.md": "e4e61845190da702",
"gsd-core/workflows/scan.md": "1a3caa5d724d39e9",
"gsd-core/workflows/secure-phase.md": "ab387a4bca381c18",
"gsd-core/workflows/session-report.md": "dd8fa011c9394075",
"gsd-core/workflows/settings-advanced.md": "2431433811616f76",
"gsd-core/workflows/settings-integrations.md": "77730321d3d6d317",
"gsd-core/workflows/settings.md": "054c8c31b3905ced",
"gsd-core/workflows/ship.md": "b5ac8caee76f3727",
"gsd-core/workflows/ship.md": "779e345e22f3f974",
"gsd-core/workflows/sketch-wrap-up.md": "07724a390fbb43f6",
"gsd-core/workflows/sketch.md": "576f300dfdde1b7d",
"gsd-core/workflows/smart-entry.md": "6f686195ae531b03",

View File

@@ -130,7 +130,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -296,14 +296,14 @@
"gsd-core/workflows/remove-phase.md": "e262654e319d1bc4",
"gsd-core/workflows/remove-workspace.md": "ceddfeef5f2d6754",
"gsd-core/workflows/resume-project.md": "40db7f350f5866d8",
"gsd-core/workflows/review.md": "1f44a33c50b1cd36",
"gsd-core/workflows/review.md": "a9f422db38ab8bb9",
"gsd-core/workflows/scan.md": "dcc2f76d0850e2fb",
"gsd-core/workflows/secure-phase.md": "9bec6635ee1cbaed",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "230a658de9c017a6",
"gsd-core/workflows/settings-integrations.md": "a1d146d6bfd14db5",
"gsd-core/workflows/settings.md": "f611f14f2f447f1e",
"gsd-core/workflows/ship.md": "dc4ac0166a559f98",
"gsd-core/workflows/ship.md": "3d0022d2d3ed8f78",
"gsd-core/workflows/sketch-wrap-up.md": "f2590cb6ddbfad94",
"gsd-core/workflows/sketch.md": "e2063966439af8c1",
"gsd-core/workflows/smart-entry.md": "6c707b959a41900b",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "ada8a0546c686483",
"gsd-core/workflows/remove-workspace.md": "433affcd1a200826",
"gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96",
"gsd-core/workflows/review.md": "ad115fadce422eae",
"gsd-core/workflows/review.md": "ea18faf9ff633667",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "3063b0b6f7b56d46",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "bf8ea69c8f7ae019",
"gsd-core/workflows/settings-integrations.md": "166ca51b1f33c2a3",
"gsd-core/workflows/settings.md": "0623c673eaf04799",
"gsd-core/workflows/ship.md": "8a2504f02df7529d",
"gsd-core/workflows/ship.md": "36603e9c574e8374",
"gsd-core/workflows/sketch-wrap-up.md": "5be73b7bdf96b539",
"gsd-core/workflows/sketch.md": "373bc0d83368a411",
"gsd-core/workflows/smart-entry.md": "c8fc316358cdcd7b",

View File

@@ -129,7 +129,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -295,14 +295,14 @@
"gsd-core/workflows/remove-phase.md": "fce799aae3ab2715",
"gsd-core/workflows/remove-workspace.md": "8facde381657dd71",
"gsd-core/workflows/resume-project.md": "a0443839f1f83c2d",
"gsd-core/workflows/review.md": "d8c53e495b067afe",
"gsd-core/workflows/review.md": "cde982eb704261ef",
"gsd-core/workflows/scan.md": "ebc3faaf1170dd12",
"gsd-core/workflows/secure-phase.md": "5284cfc143ad0e2c",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "49be159144d7f426",
"gsd-core/workflows/settings-integrations.md": "1dce76db0aca08a5",
"gsd-core/workflows/settings.md": "9ced580679ed0255",
"gsd-core/workflows/ship.md": "9ec9f316622ccfd9",
"gsd-core/workflows/ship.md": "36029cf37057f466",
"gsd-core/workflows/sketch-wrap-up.md": "f1ece50ac65ea281",
"gsd-core/workflows/sketch.md": "d5887983e62b574a",
"gsd-core/workflows/smart-entry.md": "47f5c5e8608e5f7a",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "ada8a0546c686483",
"gsd-core/workflows/remove-workspace.md": "fc83f362a2d0a1b7",
"gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96",
"gsd-core/workflows/review.md": "3d62fa3096f46ecb",
"gsd-core/workflows/review.md": "6033fab6d070c993",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "4977cf9e0462745b",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "edd858cd6cfddaf1",
"gsd-core/workflows/settings-integrations.md": "3ea8095d5fad891b",
"gsd-core/workflows/settings.md": "1925ecc2225c2216",
"gsd-core/workflows/ship.md": "8c68f5a43d9fd578",
"gsd-core/workflows/ship.md": "e8ea6299b57fef04",
"gsd-core/workflows/sketch-wrap-up.md": "888c0548e63197b3",
"gsd-core/workflows/sketch.md": "34a0c10fa56af7ea",
"gsd-core/workflows/smart-entry.md": "7ffe4fdb93935400",

View File

@@ -193,7 +193,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -359,14 +359,14 @@
"gsd-core/workflows/remove-phase.md": "df9a45f0b1880999",
"gsd-core/workflows/remove-workspace.md": "a7ca66db6b7c132c",
"gsd-core/workflows/resume-project.md": "f28da1200e4545f4",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/review.md": "f1fbefbd64bd890e",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "414db4dbea97ba44",
"gsd-core/workflows/settings-integrations.md": "70515c5838fb9826",
"gsd-core/workflows/settings.md": "d96ddf01fb85e61e",
"gsd-core/workflows/ship.md": "b377dab2bc92a6e5",
"gsd-core/workflows/ship.md": "f486f2731ca8b72a",
"gsd-core/workflows/sketch-wrap-up.md": "b767a1d3db129a8a",
"gsd-core/workflows/sketch.md": "88cfdf4edcf222ab",
"gsd-core/workflows/smart-entry.md": "449238eb94abe187",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "a602b41bfa081fdf",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "dea4661e8f89596f",
"gsd-core/workflows/remove-workspace.md": "446847e71aa52504",
"gsd-core/workflows/resume-project.md": "ad9f06a10bab8cc0",
"gsd-core/workflows/review.md": "98e441bde98a9d92",
"gsd-core/workflows/review.md": "fbe68c9f86385274",
"gsd-core/workflows/scan.md": "ad8ebcad4626d4a8",
"gsd-core/workflows/secure-phase.md": "71e6e689e80288ec",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "252b0d3edc315339",
"gsd-core/workflows/settings-integrations.md": "d1711a95f44fdbde",
"gsd-core/workflows/settings.md": "2e42ee34c791378a",
"gsd-core/workflows/ship.md": "3a80ea841f0a81b9",
"gsd-core/workflows/ship.md": "1875ec8f59fcf0b4",
"gsd-core/workflows/sketch-wrap-up.md": "681800323681c5c6",
"gsd-core/workflows/sketch.md": "fcb7af914159ef7b",
"gsd-core/workflows/smart-entry.md": "2a253fe437496eea",

View File

@@ -96,7 +96,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -262,14 +262,14 @@
"gsd-core/workflows/remove-phase.md": "df9a45f0b1880999",
"gsd-core/workflows/remove-workspace.md": "a7ca66db6b7c132c",
"gsd-core/workflows/resume-project.md": "f28da1200e4545f4",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/review.md": "f1fbefbd64bd890e",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "414db4dbea97ba44",
"gsd-core/workflows/settings-integrations.md": "70515c5838fb9826",
"gsd-core/workflows/settings.md": "d96ddf01fb85e61e",
"gsd-core/workflows/ship.md": "b377dab2bc92a6e5",
"gsd-core/workflows/ship.md": "f486f2731ca8b72a",
"gsd-core/workflows/sketch-wrap-up.md": "838c701bd072ae73",
"gsd-core/workflows/sketch.md": "c7725562b3efd311",
"gsd-core/workflows/smart-entry.md": "449238eb94abe187",

View File

@@ -129,7 +129,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -295,14 +295,14 @@
"gsd-core/workflows/remove-phase.md": "e8ae4fbbfac700f0",
"gsd-core/workflows/remove-workspace.md": "4ac64de862dc650e",
"gsd-core/workflows/resume-project.md": "7f20769f302e5427",
"gsd-core/workflows/review.md": "7e1d8901d796338f",
"gsd-core/workflows/review.md": "b3548b43dcf1fb4e",
"gsd-core/workflows/scan.md": "949692db4834dd27",
"gsd-core/workflows/secure-phase.md": "ef7b5ad194b687bf",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "5e05212fb5cba531",
"gsd-core/workflows/settings-integrations.md": "29c5de27fbbb18e9",
"gsd-core/workflows/settings.md": "26b9b7979d3a5747",
"gsd-core/workflows/ship.md": "cee31be37b2b6c6a",
"gsd-core/workflows/ship.md": "a07a8ab18935985a",
"gsd-core/workflows/sketch-wrap-up.md": "89e0eab2af946b04",
"gsd-core/workflows/sketch.md": "483387542d6fc3af",
"gsd-core/workflows/smart-entry.md": "d309710bcabd4675",

View File

@@ -129,7 +129,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -295,14 +295,14 @@
"gsd-core/workflows/remove-phase.md": "a46c2fe853bf4e86",
"gsd-core/workflows/remove-workspace.md": "ae0e1c6d4438d663",
"gsd-core/workflows/resume-project.md": "f242e4c8aba18ea2",
"gsd-core/workflows/review.md": "5fd9c6a9d7777eee",
"gsd-core/workflows/review.md": "35d023ff48e3827f",
"gsd-core/workflows/scan.md": "63631467651d9ca8",
"gsd-core/workflows/secure-phase.md": "4a647aec1e4d2dfe",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "39e66386f6c48025",
"gsd-core/workflows/settings-integrations.md": "f8f756709ec02363",
"gsd-core/workflows/settings.md": "44b10c59215633b8",
"gsd-core/workflows/ship.md": "da81bf2515257822",
"gsd-core/workflows/ship.md": "1d471a767b11e961",
"gsd-core/workflows/sketch-wrap-up.md": "dbec602d104cb951",
"gsd-core/workflows/sketch.md": "44ff275150b6d045",
"gsd-core/workflows/smart-entry.md": "d8018578571f08d5",

View File

@@ -129,7 +129,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "1412472f858b8f41",
"gsd-core/references/reviewer-instances.md": "a857fc444baec27a",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -295,14 +295,14 @@
"gsd-core/workflows/remove-phase.md": "e7a6af429b36e77b",
"gsd-core/workflows/remove-workspace.md": "b5e60fbb33b3e33a",
"gsd-core/workflows/resume-project.md": "82cfe1b8cb17c085",
"gsd-core/workflows/review.md": "a63e0b5bb3b73730",
"gsd-core/workflows/review.md": "805bea46bed56bd8",
"gsd-core/workflows/scan.md": "12c11b2edc165df9",
"gsd-core/workflows/secure-phase.md": "185a15d389951e6e",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "2f86ec7b998f9485",
"gsd-core/workflows/settings-integrations.md": "b082fc518b484c07",
"gsd-core/workflows/settings.md": "002eb0ce3c10c741",
"gsd-core/workflows/ship.md": "bce39010f9518cf3",
"gsd-core/workflows/ship.md": "4ff6590f1e04f124",
"gsd-core/workflows/sketch-wrap-up.md": "10063f56c2c7f141",
"gsd-core/workflows/sketch.md": "25c1f8f7acfb1da9",
"gsd-core/workflows/smart-entry.md": "bd81482cb6a7ac53",

View File

@@ -200,7 +200,7 @@
"gsd-core/references/research-documentation-lookup.md": "c070007d1d72ab71",
"gsd-core/references/research-philosophy.md": "62930e66cc979c1a",
"gsd-core/references/research-verification-protocol.md": "9c38c9d9a687e679",
"gsd-core/references/reviewer-instances.md": "385501e4f9bbb31d",
"gsd-core/references/reviewer-instances.md": "ae64e44f2f132bc2",
"gsd-core/references/revision-loop.md": "e55ff32dd98c63df",
"gsd-core/references/scout-codebase.md": "ba266ecc18fbf172",
"gsd-core/references/security-asvs-levels.md": "4774fac3b94b6ca8",
@@ -366,14 +366,14 @@
"gsd-core/workflows/remove-phase.md": "df9a45f0b1880999",
"gsd-core/workflows/remove-workspace.md": "a7ca66db6b7c132c",
"gsd-core/workflows/resume-project.md": "f28da1200e4545f4",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/review.md": "f1fbefbd64bd890e",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",
"gsd-core/workflows/settings-advanced.md": "414db4dbea97ba44",
"gsd-core/workflows/settings-integrations.md": "70515c5838fb9826",
"gsd-core/workflows/settings.md": "d96ddf01fb85e61e",
"gsd-core/workflows/ship.md": "b377dab2bc92a6e5",
"gsd-core/workflows/ship.md": "f486f2731ca8b72a",
"gsd-core/workflows/sketch-wrap-up.md": "86db87b16548117e",
"gsd-core/workflows/sketch.md": "e96f1866d3e60cab",
"gsd-core/workflows/smart-entry.md": "449238eb94abe187",

View File

@@ -216,7 +216,7 @@ describe('bug #687 → #2073: agy print mode bounded by --print-timeout PAIRED w
const c = read();
assert.doesNotMatch(c, /agy[^\n]*-p "\$\(cat/,
'review.md must not feed agy the prompt inline via "$(cat …)" — a large review prompt overflows the exec arg list (rc 126)');
assert.match(c, /Read the file at \/tmp\/gsd-review-prompt-/,
assert.match(c, /Read the file at \{run_dir\}\/gsd-review-prompt\.md/,
'review.md should pass agy a file-reference prompt (mirrors the Cursor block)');
});
@@ -228,7 +228,7 @@ describe('bug #687 → #2073: agy print mode bounded by --print-timeout PAIRED w
test('discards partial output on non-zero exit so the fallback fires (#687)', () => {
const c = read();
assert.match(c, /_AGY_RC.*-ne 0/, 'review.md must check the agy exit code');
assert.match(c, /: > \/tmp\/gsd-review-antigravity-/,
assert.match(c, /: > \{run_dir\}\/gsd-review-antigravity\.md/,
'review.md must truncate the output file when agy timed out / failed');
});
@@ -323,7 +323,7 @@ describe('enh-773: automated codex exec invocations include --ephemeral and --da
);
}
assert.ok(
/\[ ! -s \/tmp\/gsd-review-codex-\{phase\}\.md \]/.test(workflow),
/\[ ! -s \{run_dir\}\/gsd-review-codex\.md \]/.test(workflow),
'review.md must guard against an empty codex review output and surface the failure'
);
});
@@ -369,8 +369,8 @@ describe('#1698 regression: codex review is captured via --output-last-message,
test('every codex exec invocation captures the review via -o <FILE>', () => {
for (const line of codexExecLines) {
assert.ok(
/\s-o\s+\/tmp\/gsd-review-codex-\{phase\}\.md\b/.test(line),
`codex exec invocation must capture the review via -o /tmp/gsd-review-codex-{phase}.md:\n ${line.trim()}`
/\s-o\s+\{run_dir\}\/gsd-review-codex\.md\b/.test(line),
`codex exec invocation must capture the review via -o {run_dir}/gsd-review-codex.md:\n ${line.trim()}`
);
}
});
@@ -378,7 +378,7 @@ describe('#1698 regression: codex review is captured via --output-last-message,
test('no codex exec invocation redirects stdout into the review file', () => {
for (const line of codexExecLines) {
assert.ok(
!/>\s*\/tmp\/gsd-review-codex-\{phase\}\.md\b/.test(line),
!/>\s*\{run_dir\}\/gsd-review-codex\.md\b/.test(line),
`codex exec must not redirect stdout into the review file (teardown noise pollutes it); use -o + >/dev/null:\n ${line.trim()}`
);
assert.ok(
@@ -428,7 +428,7 @@ function openCodeBlock() {
describe('bug #1936: OpenCode reviewer must not silently yield an empty review', () => {
test('captures opencode stderr to a sidecar, never /dev/null', () => {
const block = openCodeBlock();
assert.match(block, /opencode run [^\n]*2>\/tmp\/gsd-review-opencode-\{phase\}\.err/,
assert.match(block, /opencode run [^\n]*2>\{run_dir\}\/gsd-review-opencode\.err/,
'the opencode invocation must send stderr to a .err sidecar so failures are diagnosable');
assert.doesNotMatch(block, /opencode run [^\n]*2>\/dev\/null/,
'the opencode invocation must not discard stderr to /dev/null (#1936)');
@@ -450,7 +450,7 @@ describe('bug #1936: OpenCode reviewer must not silently yield an empty review',
assert.match(block, /OPENCODE_REVIEW=\$\(jq/, 'must capture the extraction into a variable');
assert.match(block, /\[ -n "\$OPENCODE_REVIEW" \]/,
'must branch on the content of $OPENCODE_REVIEW, not on the size of the .md file');
assert.doesNotMatch(block, /\[ ! -s \/tmp\/gsd-review-opencode-\{phase\}\.md \]/,
assert.doesNotMatch(block, /\[ ! -s \{run_dir\}\/gsd-review-opencode\.md \]/,
'must not gate the stub on `[ ! -s ...opencode...md ]` (a lone newline defeats it)');
});
@@ -459,14 +459,14 @@ describe('bug #1936: OpenCode reviewer must not silently yield an empty review',
assert.match(block, /#1936/, 'the empty-output stub must reference the issue');
assert.match(block, /step_finish[\s\S]*\.part\.reason[\s\S]*\.part\.tokens\.output/,
'the stub must surface the stop reason and output-token count from the final step_finish');
assert.match(block, /cat \/tmp\/gsd-review-opencode-\{phase\}\.err/,
assert.match(block, /cat \{run_dir\}\/gsd-review-opencode\.err/,
'the stub must append the captured stderr');
});
test('does not regress the Codex reviewer block (still captures stderr to .err)', () => {
// #1936 changes only the OpenCode block; the Codex block's existing
// stderr-to-sidecar contract must remain intact.
assert.match(read(), /codex exec [^\n]*2>\/tmp\/gsd-review-codex-\{phase\}\.err/,
assert.match(read(), /codex exec [^\n]*2>\{run_dir\}\/gsd-review-codex\.err/,
'the Codex reviewer block must be left unchanged');
});
});

View File

@@ -64,14 +64,14 @@
"remove-phase.md": 8513,
"remove-workspace.md": 7551,
"resume-project.md": 17270,
"review.md": 50362,
"review.md": 50497,
"scan.md": 7732,
"secure-phase.md": 13622,
"session-report.md": 4044,
"settings-advanced.md": 40019,
"settings-integrations.md": 15892,
"settings.md": 33467,
"ship.md": 25222,
"ship.md": 25555,
"sketch-wrap-up.md": 14267,
"sketch.md": 20004,
"smart-entry.md": 11124,