diff --git a/.changeset/2494-review-claude-gemini-empty-guard.md b/.changeset/2494-review-claude-gemini-empty-guard.md new file mode 100644 index 000000000..04e8a975f --- /dev/null +++ b/.changeset/2494-review-claude-gemini-empty-guard.md @@ -0,0 +1,5 @@ +--- +type: Fixed +pr: 2592 +--- +**The Gemini and Claude reviewer legs now fail loudly instead of silently dropping out of the cross-AI review** — both blocks capture stderr to a `.err` sidecar instead of discarding it to `/dev/null`, and write a diagnostic stub with the captured error when the lane produces no output. Previously they were the only two of the ten prompt-fed reviewer legs with neither guard, so any failure that wrote no stdout (CLI missing, unauthenticated, rate-limited, crashed) left a zero-byte review file that `write_reviews` rendered as a reviewer that had run cleanly with nothing to report — quietly degrading an N-reviewer consensus to N-1 while `present_results` reported success. The guard matches the shape the Codex and Cursor legs already use. (#2494) diff --git a/gsd-core/workflows/review.md b/gsd-core/workflows/review.md index 82310d263..e1e67e223 100644 --- a/gsd-core/workflows/review.md +++ b/gsd-core/workflows/review.md @@ -277,19 +277,39 @@ For each selected CLI, invoke in sequence (not parallel — avoid rate limits): **Gemini:** ```bash +# #2494: capture stderr to a .err sidecar (not /dev/null) and stub an empty +# result, mirroring the Codex and Cursor blocks. Without the guard a failed +# lane — CLI missing, unauthenticated, rate-limited, crashed, or any exit that +# writes no stdout — leaves a zero-byte file that write_reviews renders as a +# reviewer that ran cleanly with nothing to report, silently dropping a lane +# from the cross-AI consensus while present_results reports success. +# Scope limit: the guard only runs if this block completes. A host Bash-tool +# timeout that kills the whole block skips it, the same hard bound the +# OpenCode block documents below — per the timeout guidance above, treat an +# empty result on a slow lane as a dropped lane rather than a crash. if [ -n "$GEMINI_MODEL" ] && [ "$GEMINI_MODEL" != "null" ]; then - cat {run_dir}/gsd-review-prompt.md | gemini -m "$GEMINI_MODEL" -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md + cat {run_dir}/gsd-review-prompt.md | gemini -m "$GEMINI_MODEL" -p - 2>{run_dir}/gsd-review-gemini.err > {run_dir}/gsd-review-gemini.md else - cat {run_dir}/gsd-review-prompt.md | gemini -p - 2>/dev/null > {run_dir}/gsd-review-gemini.md + cat {run_dir}/gsd-review-prompt.md | gemini -p - 2>{run_dir}/gsd-review-gemini.err > {run_dir}/gsd-review-gemini.md +fi +if [ ! -s {run_dir}/gsd-review-gemini.md ]; then + echo "Gemini review failed or returned empty output. stderr:" > {run_dir}/gsd-review-gemini.md + cat {run_dir}/gsd-review-gemini.err >> {run_dir}/gsd-review-gemini.md fi ``` **Claude (separate session):** ```bash +# #2494: same guard as the Gemini block above — stderr to a .err sidecar +# instead of /dev/null, and a diagnostic stub when the lane produces nothing. if [ -n "$CLAUDE_MODEL" ] && [ "$CLAUDE_MODEL" != "null" ]; then - cat {run_dir}/gsd-review-prompt.md | claude --model "$CLAUDE_MODEL" $CLAUDE_EFFORT_ARGS -p - 2>/dev/null > {run_dir}/gsd-review-claude.md + cat {run_dir}/gsd-review-prompt.md | claude --model "$CLAUDE_MODEL" $CLAUDE_EFFORT_ARGS -p - 2>{run_dir}/gsd-review-claude.err > {run_dir}/gsd-review-claude.md else - cat {run_dir}/gsd-review-prompt.md | claude $CLAUDE_EFFORT_ARGS -p - 2>/dev/null > {run_dir}/gsd-review-claude.md + cat {run_dir}/gsd-review-prompt.md | claude $CLAUDE_EFFORT_ARGS -p - 2>{run_dir}/gsd-review-claude.err > {run_dir}/gsd-review-claude.md +fi +if [ ! -s {run_dir}/gsd-review-claude.md ]; then + echo "Claude review failed or returned empty output. stderr:" > {run_dir}/gsd-review-claude.md + cat {run_dir}/gsd-review-claude.err >> {run_dir}/gsd-review-claude.md fi ``` diff --git a/tests/fix-2494-review-claude-gemini-empty-guard.test.cjs b/tests/fix-2494-review-claude-gemini-empty-guard.test.cjs new file mode 100644 index 000000000..8d5ec8d04 --- /dev/null +++ b/tests/fix-2494-review-claude-gemini-empty-guard.test.cjs @@ -0,0 +1,204 @@ +// allow-test-rule: source-text-is-the-product (see #2494) +// The Gemini and Claude reviewer dispatch blocks in gsd-core/workflows/review.md +// ARE the runtime contract — the workflow's text is what the reviewing agent +// executes. This suite extracts those two shell blocks verbatim from the +// workflow and runs them under a real bash against a failing CLI stub, so the +// shipped guard is what gets exercised rather than a reimplementation of it. +// The assertions on the produced review file are assertions on that guard's +// documented output contract (the stub line the consensus step must be able to +// tell apart from a clean empty review), not incidental string matching. + +/** + * Regression tests for #2494 — the claude and gemini reviewer legs discarded + * stderr with no empty-output guard. + * + * Before the fix both blocks were `... 2>/dev/null > {run_dir}/gsd-review-.md` + * with nothing after: a non-zero exit that wrote no stdout (CLI missing, + * unauthenticated, rate-limited, timeout-killed, crashed) left a ZERO-BYTE + * review file with the only diagnostic evidence — stderr — already discarded. + * The write_reviews step then substituted that empty file into a + * `## Review` section indistinguishable from "ran cleanly, nothing + * to report", silently degrading the advertised N-reviewer consensus to N-1. + * + * These tests fail against pre-fix review.md: the produced file is zero-byte, + * so both the non-empty and the diagnosable-message assertions trip. + */ + +'use strict'; + +const { describe, test, before, after } = require('node:test'); +const assert = require('node:assert/strict'); +const { spawnSync } = require('node:child_process'); +const fs = require('node:fs'); +const path = require('node:path'); +const { createTempDir, cleanup } = require('./helpers.cjs'); + +const ROOT = path.join(__dirname, '..'); +const REVIEW_PATH = path.join(ROOT, 'gsd-core', 'workflows', 'review.md'); + +// Normalize CRLF: on a Windows git-autocrlf checkout every line carries a +// trailing \r, which would leave the extracted block's shebang/redirect tokens +// mangled and defeat the fence regexes below. +const WORKFLOW = fs.readFileSync(REVIEW_PATH, 'utf-8').replace(/\r\n/g, '\n'); + +// This suite executes the extracted blocks with a real bash and a POSIX CLI +// stub on PATH. Gate to non-Windows, mirroring the opencode reconstruction +// suite's win32 skip — the guard logic is platform-independent and is asserted +// in full on every macOS/Linux CI leg. +const skipReason = process.platform === 'win32' + ? 'extracted block is POSIX shell; guard logic is platform-independent and asserted on macOS/Linux' + : false; + +/** + * Extract a reviewer dispatch block verbatim from the workflow. If review.md + * changes the block's shape these throw and the test fails loudly — intended + * coupling, the same contract the opencode suite pins for its jq programs. + */ +function extractBlock(headingRe, label) { + const re = new RegExp(`${headingRe}\\n\`\`\`bash\\n([\\s\\S]*?)\\n\`\`\``); + const m = WORKFLOW.match(re); + assert.ok(m, `review.md must define the ${label} reviewer dispatch as a bash block (#2494)`); + return m[1]; +} + +const GEMINI_BLOCK = extractBlock('\\*\\*Gemini:\\*\\*', 'Gemini'); +const CLAUDE_BLOCK = extractBlock('\\*\\*Claude \\(separate session\\):\\*\\*', 'Claude'); + +const STUB_STDERR = 'gsd-2494-stub: command not found / not authenticated'; + +let sandbox; + +before(() => { + sandbox = createTempDir('gsd-2494-'); +}); + +after(() => { + cleanup(sandbox); +}); + +/** + * Run one extracted block with `{run_dir}` pointed at a fresh run directory and + * `stubBody` installed on PATH under the reviewer's binary name. + * + * Single exec site for the whole suite so the Windows guard lives in one place: + * Git Bash (msys2) ignores Node's chmod exec bit for PATH-executed + * extension-less scripts (DEFECT.WINDOWS-TEST-PORTABILITY), and every suite + * below is skipped on win32 — this early return keeps the exec unreachable + * there rather than relying on the skip alone. + */ +function runBlockWithStub({ binName, block, stubBody, env = {} }) { + if (process.platform === 'win32') return null; + + const caseDir = fs.mkdtempSync(path.join(sandbox, 'run-')); + const runDir = path.join(caseDir, 'run'); + const binDir = path.join(caseDir, 'bin'); + fs.mkdirSync(runDir); + fs.mkdirSync(binDir); + + const stub = path.join(binDir, binName); + fs.writeFileSync(stub, stubBody); + fs.chmodSync(stub, 0o755); + + fs.writeFileSync(path.join(runDir, 'gsd-review-prompt.md'), '# review prompt\n'); + + const script = block.split('{run_dir}').join(runDir); + const result = spawnSync('bash', ['-c', script], { + encoding: 'utf8', + timeout: 30000, + killSignal: 'SIGKILL', + env: { ...process.env, PATH: `${binDir}${path.delimiter}${process.env.PATH}`, ...env }, + }); + + const reviewPath = path.join(runDir, `gsd-review-${binName}.md`); + return { + result, + reviewPath, + errPath: path.join(runDir, `gsd-review-${binName}.err`), + review: fs.existsSync(reviewPath) ? fs.readFileSync(reviewPath, 'utf-8') : null, + }; +} + +/** + * The issue's own repro harness: a CLI that writes STUB_STDERR to stderr, + * nothing to stdout, and exits non-zero. + */ +function runLeg({ binName, block, env = {} }) { + return runBlockWithStub({ + binName, + block, + stubBody: `#!/bin/sh\necho "${STUB_STDERR}" >&2\nexit 127\n`, + env, + }); +} + +/** + * The guard's contract: the review file exists, is NOT empty, names the leg as + * failed-or-empty, and carries the captured stderr. The last assertion is what + * separates this fix from a bare `[ ! -s ]` stub — the evidence has to survive. + */ +function assertDiagnosable({ review, reviewPath, errPath }, legLabel) { + assert.ok(review !== null, `${legLabel}: review file must exist after a failed lane (#2494)`); + assert.notStrictEqual(review.trim(), '', `${legLabel}: review file must not be empty after a failed lane (#2494)`); + assert.match( + review, + new RegExp(`${legLabel} review failed or returned empty output`, 'i'), + `${legLabel}: review file must carry a diagnosable failure line, distinguishable at consensus synthesis from "ran cleanly, nothing to report" (#2494)`, + ); + assert.ok( + review.includes(STUB_STDERR), + `${legLabel}: captured stderr must be appended to the review file, not discarded to /dev/null (#2494)`, + ); + assert.ok(fs.existsSync(errPath), `${legLabel}: stderr must be captured to a .err sidecar (#2494)`); + assert.ok(reviewPath.endsWith('.md'), `${legLabel}: review output path unchanged`); +} + +describe('#2494 — gemini reviewer leg fails loudly', { skip: skipReason }, () => { + test('a failing gemini CLI produces a diagnosable stub, not an empty file (model configured)', () => { + const out = runLeg({ binName: 'gemini', block: GEMINI_BLOCK, env: { GEMINI_MODEL: 'gemini-test-model' } }); + assertDiagnosable(out, 'Gemini'); + }); + + test('a failing gemini CLI produces a diagnosable stub, not an empty file (no model configured)', () => { + const out = runLeg({ binName: 'gemini', block: GEMINI_BLOCK, env: { GEMINI_MODEL: '' } }); + assertDiagnosable(out, 'Gemini'); + }); +}); + +describe('#2494 — claude reviewer leg fails loudly', { skip: skipReason }, () => { + test('a failing claude CLI produces a diagnosable stub, not an empty file (model configured)', () => { + const out = runLeg({ + binName: 'claude', + block: CLAUDE_BLOCK, + env: { CLAUDE_MODEL: 'claude-test-model', CLAUDE_EFFORT_ARGS: '' }, + }); + assertDiagnosable(out, 'Claude'); + }); + + test('a failing claude CLI produces a diagnosable stub, not an empty file (no model configured)', () => { + const out = runLeg({ + binName: 'claude', + block: CLAUDE_BLOCK, + env: { CLAUDE_MODEL: '', CLAUDE_EFFORT_ARGS: '' }, + }); + assertDiagnosable(out, 'Claude'); + }); +}); + +describe('#2494 — the guard does not swallow a successful review', { skip: skipReason }, () => { + test('gemini stdout is preserved verbatim when the CLI succeeds', () => { + const out = runBlockWithStub({ + binName: 'gemini', + block: GEMINI_BLOCK, + stubBody: '#!/bin/sh\necho "## Real Review"\necho "Looks good."\nexit 0\n', + env: { GEMINI_MODEL: '' }, + }); + + const { review } = out; + assert.ok(review !== null, 'a successful review must produce a review file (#2494)'); + assert.ok(review.includes('Looks good.'), 'a successful review must pass through untouched (#2494)'); + assert.ok( + !/failed or returned empty output/i.test(review), + 'the stub must not fire on a non-empty review (#2494)', + ); + }); +}); diff --git a/tests/fixtures/golden-install-parity/antigravity.json b/tests/fixtures/golden-install-parity/antigravity.json index cc79ca3a1..c72c3317a 100644 --- a/tests/fixtures/golden-install-parity/antigravity.json +++ b/tests/fixtures/golden-install-parity/antigravity.json @@ -299,7 +299,7 @@ "gsd-core/workflows/remove-phase.md": "23b9eb0858a2535e", "gsd-core/workflows/remove-workspace.md": "1058d1d3160eb120", "gsd-core/workflows/resume-project.md": "98e2cf8908e73a52", - "gsd-core/workflows/review.md": "cb4ed7b2b77bba35", + "gsd-core/workflows/review.md": "73ea346aebf61b77", "gsd-core/workflows/scan.md": "46c5a73f6f682023", "gsd-core/workflows/secure-phase.md": "9564c529052d1d36", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/augment.json b/tests/fixtures/golden-install-parity/augment.json index 12558d2ba..b258b4271 100644 --- a/tests/fixtures/golden-install-parity/augment.json +++ b/tests/fixtures/golden-install-parity/augment.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/claude-local.json b/tests/fixtures/golden-install-parity/claude-local.json index b8f84a72a..706030e91 100644 --- a/tests/fixtures/golden-install-parity/claude-local.json +++ b/tests/fixtures/golden-install-parity/claude-local.json @@ -369,7 +369,7 @@ "gsd-core/workflows/remove-phase.md": "8effc8742d58a11a", "gsd-core/workflows/remove-workspace.md": "64b73daff58b9aec", "gsd-core/workflows/resume-project.md": "af9761bcec0f6fe9", - "gsd-core/workflows/review.md": "9eb81c7c61cfe50e", + "gsd-core/workflows/review.md": "7838e12644bf808a", "gsd-core/workflows/scan.md": "686e787d3704db90", "gsd-core/workflows/secure-phase.md": "a7272ff8163a61ac", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/claude.json b/tests/fixtures/golden-install-parity/claude.json index e32ceb066..9ac94b580 100644 --- a/tests/fixtures/golden-install-parity/claude.json +++ b/tests/fixtures/golden-install-parity/claude.json @@ -298,7 +298,7 @@ "gsd-core/workflows/remove-phase.md": "ada8a0546c686483", "gsd-core/workflows/remove-workspace.md": "015cde237c75be39", "gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96", - "gsd-core/workflows/review.md": "bba666ebc5e13130", + "gsd-core/workflows/review.md": "fa72c8f343102dba", "gsd-core/workflows/scan.md": "a71e3009998cfc57", "gsd-core/workflows/secure-phase.md": "ba807b4862d7f3c9", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/cline.json b/tests/fixtures/golden-install-parity/cline.json index 197e69e19..a3809388b 100644 --- a/tests/fixtures/golden-install-parity/cline.json +++ b/tests/fixtures/golden-install-parity/cline.json @@ -302,7 +302,7 @@ "gsd-core/workflows/remove-phase.md": "e336350f8113a328", "gsd-core/workflows/remove-workspace.md": "79d3669cc9eb0b10", "gsd-core/workflows/resume-project.md": "e23981178fa37b3d", - "gsd-core/workflows/review.md": "b1c5ebc05398ca45", + "gsd-core/workflows/review.md": "2a95ced731e6d14c", "gsd-core/workflows/scan.md": "f0bd2f64f5530598", "gsd-core/workflows/secure-phase.md": "1a2e389991fc6263", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/codebuddy.json b/tests/fixtures/golden-install-parity/codebuddy.json index 9741bc146..58251a23b 100644 --- a/tests/fixtures/golden-install-parity/codebuddy.json +++ b/tests/fixtures/golden-install-parity/codebuddy.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/codex.json b/tests/fixtures/golden-install-parity/codex.json index 820551db9..3b510e23a 100644 --- a/tests/fixtures/golden-install-parity/codex.json +++ b/tests/fixtures/golden-install-parity/codex.json @@ -405,7 +405,7 @@ "gsd-core/workflows/remove-phase.md": "9ee0fddd11a0d9d4", "gsd-core/workflows/remove-workspace.md": "d0160c5d05bcb2bb", "gsd-core/workflows/resume-project.md": "9965f87eb278f7f8", - "gsd-core/workflows/review.md": "6c74f7151f41df8b", + "gsd-core/workflows/review.md": "9987e9fd8f7e5adb", "gsd-core/workflows/scan.md": "dcd6aac25ef39251", "gsd-core/workflows/secure-phase.md": "3ba89719288dd3f3", "gsd-core/workflows/session-report.md": "dd8fa011c9394075", diff --git a/tests/fixtures/golden-install-parity/copilot.json b/tests/fixtures/golden-install-parity/copilot.json index c2fbfbac6..6c925db52 100644 --- a/tests/fixtures/golden-install-parity/copilot.json +++ b/tests/fixtures/golden-install-parity/copilot.json @@ -300,7 +300,7 @@ "gsd-core/workflows/remove-phase.md": "e262654e319d1bc4", "gsd-core/workflows/remove-workspace.md": "e7e5b5b1e0cc9d81", "gsd-core/workflows/resume-project.md": "40db7f350f5866d8", - "gsd-core/workflows/review.md": "31d6ec81b8c8dddc", + "gsd-core/workflows/review.md": "6aad3c5254932206", "gsd-core/workflows/scan.md": "76aad4e70281c364", "gsd-core/workflows/secure-phase.md": "d60aa4053154e52f", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/cursor.json b/tests/fixtures/golden-install-parity/cursor.json index c44054a7f..97da6ef48 100644 --- a/tests/fixtures/golden-install-parity/cursor.json +++ b/tests/fixtures/golden-install-parity/cursor.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "ada8a0546c686483", "gsd-core/workflows/remove-workspace.md": "0572a83d71650937", "gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96", - "gsd-core/workflows/review.md": "28a82741e3e8616d", + "gsd-core/workflows/review.md": "f5972bbe92dc5f0c", "gsd-core/workflows/scan.md": "a71e3009998cfc57", "gsd-core/workflows/secure-phase.md": "b008216148d2afac", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/hermes.json b/tests/fixtures/golden-install-parity/hermes.json index 42451b23f..264299f88 100644 --- a/tests/fixtures/golden-install-parity/hermes.json +++ b/tests/fixtures/golden-install-parity/hermes.json @@ -299,7 +299,7 @@ "gsd-core/workflows/remove-phase.md": "fce799aae3ab2715", "gsd-core/workflows/remove-workspace.md": "42029a7559f1d8fb", "gsd-core/workflows/resume-project.md": "a0443839f1f83c2d", - "gsd-core/workflows/review.md": "9a7fd3c1c2bd617d", + "gsd-core/workflows/review.md": "b7aa706def0b93d6", "gsd-core/workflows/scan.md": "5c2370d6a8118b6c", "gsd-core/workflows/secure-phase.md": "c087131f1dd12901", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/kilo.json b/tests/fixtures/golden-install-parity/kilo.json index 4c6d21cb5..e32fee630 100644 --- a/tests/fixtures/golden-install-parity/kilo.json +++ b/tests/fixtures/golden-install-parity/kilo.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "ada8a0546c686483", "gsd-core/workflows/remove-workspace.md": "f5dc82bb63e2efa4", "gsd-core/workflows/resume-project.md": "7f8dc986f0f35d96", - "gsd-core/workflows/review.md": "9299d96d44252a8a", + "gsd-core/workflows/review.md": "c5c59f2bb70396ab", "gsd-core/workflows/scan.md": "c039d3e40d26b606", "gsd-core/workflows/secure-phase.md": "5a8fbf603d218100", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/kimi-code.json b/tests/fixtures/golden-install-parity/kimi-code.json index 57e89a25d..446f5e560 100644 --- a/tests/fixtures/golden-install-parity/kimi-code.json +++ b/tests/fixtures/golden-install-parity/kimi-code.json @@ -327,7 +327,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/kimi.json b/tests/fixtures/golden-install-parity/kimi.json index 1f304bc93..bcd39c42b 100644 --- a/tests/fixtures/golden-install-parity/kimi.json +++ b/tests/fixtures/golden-install-parity/kimi.json @@ -363,7 +363,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/opencode.json b/tests/fixtures/golden-install-parity/opencode.json index ef6597e46..8680b26fb 100644 --- a/tests/fixtures/golden-install-parity/opencode.json +++ b/tests/fixtures/golden-install-parity/opencode.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "dea4661e8f89596f", "gsd-core/workflows/remove-workspace.md": "21a8581add5f31ae", "gsd-core/workflows/resume-project.md": "ad9f06a10bab8cc0", - "gsd-core/workflows/review.md": "a2c5d053c8ef6e27", + "gsd-core/workflows/review.md": "486bc0f9ab4c24f4", "gsd-core/workflows/scan.md": "cbfb79df855e5e61", "gsd-core/workflows/secure-phase.md": "ef09f40dfd4d2424", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/pi.json b/tests/fixtures/golden-install-parity/pi.json index b7e1377bd..617ec1dab 100644 --- a/tests/fixtures/golden-install-parity/pi.json +++ b/tests/fixtures/golden-install-parity/pi.json @@ -266,7 +266,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/qwen.json b/tests/fixtures/golden-install-parity/qwen.json index b0546f9b6..53bb936da 100644 --- a/tests/fixtures/golden-install-parity/qwen.json +++ b/tests/fixtures/golden-install-parity/qwen.json @@ -299,7 +299,7 @@ "gsd-core/workflows/remove-phase.md": "e8ae4fbbfac700f0", "gsd-core/workflows/remove-workspace.md": "ae520235f4d1f4a5", "gsd-core/workflows/resume-project.md": "7f20769f302e5427", - "gsd-core/workflows/review.md": "5b59389282a276fc", + "gsd-core/workflows/review.md": "3db704f47d7a5bde", "gsd-core/workflows/scan.md": "b7efd0d381a3b8a5", "gsd-core/workflows/secure-phase.md": "f7bfa7175102af31", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/trae.json b/tests/fixtures/golden-install-parity/trae.json index 07a757748..604f8bfa3 100644 --- a/tests/fixtures/golden-install-parity/trae.json +++ b/tests/fixtures/golden-install-parity/trae.json @@ -299,7 +299,7 @@ "gsd-core/workflows/remove-phase.md": "a46c2fe853bf4e86", "gsd-core/workflows/remove-workspace.md": "8ddc5f04f7c48d6c", "gsd-core/workflows/resume-project.md": "f242e4c8aba18ea2", - "gsd-core/workflows/review.md": "2e10545b307c867c", + "gsd-core/workflows/review.md": "b02dae5c743b1797", "gsd-core/workflows/scan.md": "3b14bcb51d3a4de8", "gsd-core/workflows/secure-phase.md": "267393d5b02b5334", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/windsurf.json b/tests/fixtures/golden-install-parity/windsurf.json index 5b487d32e..714d36815 100644 --- a/tests/fixtures/golden-install-parity/windsurf.json +++ b/tests/fixtures/golden-install-parity/windsurf.json @@ -299,7 +299,7 @@ "gsd-core/workflows/remove-phase.md": "e7a6af429b36e77b", "gsd-core/workflows/remove-workspace.md": "30ca05fe4a3efc25", "gsd-core/workflows/resume-project.md": "82cfe1b8cb17c085", - "gsd-core/workflows/review.md": "ac0c02f11e2ae1dc", + "gsd-core/workflows/review.md": "f3fdf577dbc08f5f", "gsd-core/workflows/scan.md": "4a910da5e34f2685", "gsd-core/workflows/secure-phase.md": "d5d811bc468ce7f2", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/fixtures/golden-install-parity/zcode.json b/tests/fixtures/golden-install-parity/zcode.json index b1433f2db..b2202efc1 100644 --- a/tests/fixtures/golden-install-parity/zcode.json +++ b/tests/fixtures/golden-install-parity/zcode.json @@ -370,7 +370,7 @@ "gsd-core/workflows/remove-phase.md": "df9a45f0b1880999", "gsd-core/workflows/remove-workspace.md": "f67860c795fb4bfe", "gsd-core/workflows/resume-project.md": "f28da1200e4545f4", - "gsd-core/workflows/review.md": "d4f26b05b3eff7f6", + "gsd-core/workflows/review.md": "ed04746925ea035f", "gsd-core/workflows/scan.md": "e1c12d542e61720d", "gsd-core/workflows/secure-phase.md": "fda2361739e511ee", "gsd-core/workflows/session-report.md": "2e5b1205324ddefa", diff --git a/tests/workflow-size-baseline.json b/tests/workflow-size-baseline.json index f72cfe917..ff7efc135 100644 --- a/tests/workflow-size-baseline.json +++ b/tests/workflow-size-baseline.json @@ -64,7 +64,7 @@ "remove-phase.md": 8513, "remove-workspace.md": 7916, "resume-project.md": 17270, - "review.md": 51210, + "review.md": 52646, "scan.md": 8314, "secure-phase.md": 14627, "session-report.md": 4044,