Merge branch 'next' into feat/2163-statusline-git-segment

This commit is contained in:
Tom Boucher
2026-07-13 16:29:31 -04:00
committed by GitHub
22 changed files with 256 additions and 22 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 2184
---
**The Antigravity reviewer in `/gsd-review` no longer reviews blind** — `agy -p` never granted the agent the repo under review, so it frequently anchored on its own scratch directory and returned plan-text-only verdicts counted at full consensus weight. The reviewer is now granted the repo (capability-probed `--add-dir`) and anchored to the absolute repo root; a review that still runs without repo access is stamped `[reviewed-without-repo-access]` and down-weighted in the Consensus Summary. The cursor-agent prompt gains the same absolute-root anchor. (#2176)

View File

@@ -366,7 +366,12 @@ fi
# prompt as an ARGUMENT, not stdin. A full review prompt can exceed the OS argument limit, so
# reference the prompt file by path rather than inlining it. Capture stderr so a failure is
# diagnosable instead of a silent empty result.
CURSOR_PROMPT_ARG="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carry out the review request it contains. Output only the resulting markdown review. Do not edit any files."
# #2176: same absolute-root anchor as the Antigravity block — cursor-agent runs
# in the repo cwd, but repo-relative references in the assembled prompt still
# need an explicit root to resolve against. rev-parse (not bare pwd) so the
# anchor is correct even when /gsd:review is invoked from a repo subdirectory.
_CURSOR_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
CURSOR_PROMPT_ARG="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carry out the review request it contains. The repository under review is at $_CURSOR_ROOT — resolve every relative file path in the review request against that absolute root. Output only the resulting markdown review. Do not edit any files."
cursor-agent -p --mode ask --trust --output-format text "$CURSOR_PROMPT_ARG" 2>/tmp/gsd-review-cursor-{phase}.err > /tmp/gsd-review-cursor-{phase}.md
if [ ! -s /tmp/gsd-review-cursor-{phase}.md ]; then
echo "Cursor review failed or returned empty output. stderr:" > /tmp/gsd-review-cursor-{phase}.md
@@ -458,7 +463,19 @@ if [ -n "$AGY_MODEL" ] && [ "$AGY_MODEL" != "null" ]; then
else
set --
fi
_AGY_PROMPT="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carry out the review request it contains. Output only the resulting markdown review. Do not edit any files."
# #2176: grant the reviewer the repo under review. Without --add-dir, agy's
# permission context never receives the cwd repo — the agent anchors on its own
# ~/.gemini/antigravity-cli/scratch dir and reviews the plan text in isolation
# (the exact failure the Review Instructions forbid). Capability-probed like the
# Codex bypass flag so an older agy without --add-dir still runs; the prompt
# anchor below keeps absolute-path reads possible on that fallback.
if agy --help 2>/dev/null | grep -q -- '--add-dir'; then
set -- "$@" --add-dir "$_AGY_WS"
fi
# #2176: anchor the prompt to the absolute repo root so repo-relative references
# in the assembled review prompt resolve even on the no---add-dir fallback, and
# require an explicit self-report if the reviewer still cannot read the repo.
_AGY_PROMPT="Read the file at /tmp/gsd-review-prompt-{phase}.md in full and carry out the review request it contains. The repository under review is at $_AGY_WS — resolve every relative file path in the review request against that absolute root and verify claims against those files. If you cannot read files under $_AGY_WS, begin your output with the exact line REVIEWED-WITHOUT-REPO-ACCESS before the review. Output only the resulting markdown review. Do not edit any files."
# Capability-probe an external wall-clock killer (GNU coreutils `timeout` or the
# macOS Homebrew `gtimeout`). Stock macOS ships NEITHER — a bare `timeout …` would
# fail with rc 127 ("command not found") and silently lose the reviewer, so fall
@@ -525,6 +542,26 @@ if [ ! -s /tmp/gsd-review-antigravity-{phase}.md ]; then
echo "If no agy run started, that is the pre-session-stall case: check whether a new ~/.gemini/antigravity-cli/brain/<conv-id>/ dir appeared within ~30s of launch."
} > /tmp/gsd-review-antigravity-{phase}.md
fi
# #2176: blind-review marker. Two tells that the reviewer ran without repo
# access: the prompt's mandated REVIEWED-WITHOUT-REPO-ACCESS self-report in the
# first lines of output, or the agent DECLARING the scratch dir as its
# workspace. Both patterns are anchored — the self-report to the head of the
# file, the scratch tell to a workspace-declaration phrasing — so a grounded
# review that merely QUOTES these strings (e.g. reviewing this very file) is
# never mis-stamped. Stamp a machine-readable marker so the Consensus Summary
# down-weights the review instead of counting an ungrounded verdict at full
# weight. (Temp file + mv, no in-place sed — BSD/GNU safe.)
if [ -s /tmp/gsd-review-antigravity-{phase}.md ] && \
{ head -5 /tmp/gsd-review-antigravity-{phase}.md | grep -q 'REVIEWED-WITHOUT-REPO-ACCESS' || \
grep -qiE '(workspace|working) (directory|dir).{0,40}antigravity-cli/scratch' /tmp/gsd-review-antigravity-{phase}.md; }; then
{
echo "> [reviewed-without-repo-access] This reviewer ran without visibility into the repo under review — down-weight its verdict in the Consensus Summary."
echo ""
cat /tmp/gsd-review-antigravity-{phase}.md
} > /tmp/gsd-review-antigravity-{phase}.md.tmp && \
mv /tmp/gsd-review-antigravity-{phase}.md.tmp /tmp/gsd-review-antigravity-{phase}.md
fi
```
**Ollama (local, OpenAI-compatible):**
@@ -837,7 +874,7 @@ trimmed_reviewers: # only present if at least one reviewer was trimmed
## Consensus Summary
{synthesize common concerns across all reviewers. CodeRabbit is a diff-only reviewer (it never received the source-grounding prompt), so do not weight its verdict as a grounded plan review — fold in its diff findings, but base plan-level consensus on the prompt-fed reviewers.}
{synthesize common concerns across all reviewers. CodeRabbit is a diff-only reviewer (it never received the source-grounding prompt), so do not weight its verdict as a grounded plan review — fold in its diff findings, but base plan-level consensus on the prompt-fed reviewers. A reviewer output carrying the `[reviewed-without-repo-access]` marker (or beginning with `REVIEWED-WITHOUT-REPO-ACCESS`) ran without repo access (#2176) — treat it the same way: note its concerns, but do not count its verdict at full consensus weight.}
### Agreed Strengths
{strengths mentioned by 2+ reviewers}

View File

@@ -0,0 +1,192 @@
// allow-test-rule: source-text-is-the-product (see #2073)
// gsd-core/workflows/review.md is a workflow document whose bash blocks ARE
// what /gsd-review loads and executes at runtime. Asserting the invocation
// shape asserts the deployed contract — this is behavioral coverage of the
// workflow, not a source-grep over application code.
/**
* Antigravity reviewer repo-grounding tests (#2176)
*
* The agy block invoked the CLI without granting it the repo under review:
* no --add-dir on either invocation arm, and no absolute repo-root anchor in
* _AGY_PROMPT. The agent frequently anchored on its own
* ~/.gemini/antigravity-cli/scratch dir, reviewed the plan text in isolation
* (the exact failure the block's Review Instructions forbid), and its
* ungrounded verdict flowed into the Consensus Summary at full weight,
* undetected.
*
* These tests pin the fix: capability-probed --add-dir (mirrors the Codex
* bypass-flag probe), absolute-root prompt anchor (agy AND the cursor-agent
* block, which shared the anchor gap), a mandated self-report line, a stamped
* blind-review marker, and consensus down-weighting of marked reviews.
* Each assertion fails against the pre-fix block.
*/
const { test, describe } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const ROOT = path.join(__dirname, '..');
const REVIEW_PATH = path.join(ROOT, 'gsd-core', 'workflows', 'review.md');
function reviewContent() {
return fs.readFileSync(REVIEW_PATH, 'utf-8');
}
function agyBashBlock() {
const fences = reviewContent().match(/```bash[\s\S]*?```/g) || [];
const agy = fences.find((f) => /\bagy\b/.test(f) && /gsd-review-antigravity/.test(f));
assert.ok(agy, 'review.md should contain the agy invocation bash block');
return agy;
}
function cursorBashBlock() {
const fences = reviewContent().match(/```bash[\s\S]*?```/g) || [];
const cursor = fences.find((f) => /cursor-agent -p/.test(f));
assert.ok(cursor, 'review.md should contain the cursor-agent invocation bash block');
return cursor;
}
describe('Antigravity reviewer repo grounding in /gsd-review (#2176)', () => {
test('probes agy for --add-dir support (capability-probe idiom, mirrors the Codex block)', () => {
const block = agyBashBlock();
assert.ok(
/agy --help 2>\/dev\/null \| grep -q -- '--add-dir'/.test(block),
'agy block must capability-probe --add-dir via `agy --help | grep -q` so older CLIs still run',
);
});
test('passes --add-dir with the repo root when supported', () => {
const block = agyBashBlock();
assert.ok(
/set -- "\$@" --add-dir "\$_AGY_WS"/.test(block),
'the probed arm must append --add-dir "$_AGY_WS" so both invocation arms (which expand "$@") receive it',
);
});
test('_AGY_PROMPT is anchored to the absolute repo root', () => {
const block = agyBashBlock();
const promptLine = block.split('\n').find((l) => l.startsWith('_AGY_PROMPT='));
assert.ok(promptLine, 'agy block must define _AGY_PROMPT');
assert.ok(
/\$_AGY_WS/.test(promptLine),
'_AGY_PROMPT must embed the absolute repo root ($_AGY_WS) so repo-relative references resolve on the no---add-dir fallback',
);
});
test('_AGY_PROMPT mandates a REVIEWED-WITHOUT-REPO-ACCESS self-report', () => {
const block = agyBashBlock();
const promptLine = block.split('\n').find((l) => l.startsWith('_AGY_PROMPT='));
assert.ok(
/REVIEWED-WITHOUT-REPO-ACCESS/.test(promptLine),
'_AGY_PROMPT must require the exact self-report line when the reviewer cannot read the repo',
);
});
test('stamps a blind-review marker on self-reported or scratch-anchored output', () => {
const block = agyBashBlock();
assert.ok(
/head -5 [^|]*\| grep -q 'REVIEWED-WITHOUT-REPO-ACCESS'/.test(block),
'the self-report tell must be anchored to the head of the output, not a whole-body substring',
);
assert.ok(
/grep -qiE '\(workspace\|working\) \(directory\|dir\)\.\{0,40\}antigravity-cli\/scratch'/.test(block),
'the scratch tell must be anchored to a workspace-declaration phrasing whose bridge (.{0,40}) can span the dotted ~/.gemini/ path prefix',
);
assert.ok(
/\[reviewed-without-repo-access\]/.test(block),
'detected blind reviews must be stamped with the [reviewed-without-repo-access] marker',
);
});
test('marker stamping avoids sed -i (BSD/GNU divergence) — uses temp file + mv', () => {
const block = agyBashBlock();
assert.ok(!/sed -i/.test(block), 'agy block must not use sed -i (BSD vs GNU incompatibility)');
assert.ok(
/\.tmp && \\?\s*\n?\s*mv /.test(block),
'marker stamping should rewrite via temp file + mv',
);
});
test('Consensus Summary down-weights marked blind reviews', () => {
const content = reviewContent();
const consensusIdx = content.indexOf('## Consensus Summary');
assert.ok(consensusIdx >= 0, 'review.md should contain the Consensus Summary section');
const consensus = content.slice(consensusIdx, consensusIdx + 2000);
assert.ok(
/\[reviewed-without-repo-access\]/.test(consensus),
'consensus instructions must reference the blind-review marker',
);
assert.ok(
/REVIEWED-WITHOUT-REPO-ACCESS/.test(consensus),
'consensus instructions must also honor the raw self-report line',
);
assert.ok(
/not count its verdict at full consensus weight/.test(consensus),
'marked reviews must be down-weighted, not counted at full weight',
);
});
test('blind-review detection behaves correctly on synthetic transcripts', () => {
// Behavioral, not string-on-string: extract the actual detection compound
// from the fence, point it at a temp file, and run it through bash for
// ungrounded and grounded transcript shapes.
const os = require('os');
const { execFileSync } = require('node:child_process');
const { toPosixPath } = require('../gsd-core/bin/lib/shell-command-projection.cjs');
const block = agyBashBlock();
const m = block.match(/\{ head -5[\s\S]*?\}; then/);
assert.ok(m, 'detection compound not found in the agy block');
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'agy-detect-'));
const out = path.join(tmp, 'review-out.md');
const detect = m[0]
.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));
const runDetect = (content) => {
fs.writeFileSync(out, content);
try {
execFileSync('bash', ['-c', detect], { stdio: 'ignore' });
return true; // exit 0 → blind review detected
} catch {
return false;
}
};
try {
// Ungrounded tells — must be stamped
assert.equal(runDetect('REVIEWED-WITHOUT-REPO-ACCESS\n\n## Review\nPlan-only review.\n'), true,
'self-report line in the head must be detected');
assert.equal(runDetect('## Review\nMy working directory is ~/.gemini/antigravity-cli/scratch.\nPlan-only review.\n'), true,
'full dotted scratch path in a workspace declaration must be detected (#2184 re-review Major)');
assert.equal(runDetect('Workspace directory: /home/me/.gemini/antigravity-cli/scratch\n'), true,
'colon-style workspace declaration must be detected');
// Grounded shapes — must NOT be stamped
assert.equal(runDetect('## Review\nVerified hooks/gsd-statusline.js against the plan. Solid.\n'), false,
'ordinary grounded review must not be stamped');
assert.equal(runDetect('## Review\nThe workflow mentions antigravity-cli/scratch as the agy scratch dir; the guard there is correct.\n'), false,
'grounded review merely quoting the scratch path must not be stamped');
assert.equal(
runDetect('## Review\n\nGrounded findings below.\n\n### Details\nLine 20 of the workflow mentions REVIEWED-WITHOUT-REPO-ACCESS as the self-report marker; fine.\n'),
false,
'self-report string quoted beyond the first 5 lines must not be stamped');
} finally {
require('./helpers.cjs').cleanup(tmp);
}
});
test('cursor-agent prompt carries the same absolute-root anchor (identical gap, #2176 AC5)', () => {
const block = cursorBashBlock();
assert.ok(
/_CURSOR_ROOT="\$\(git rev-parse --show-toplevel 2>\/dev\/null \|\| pwd\)"/.test(block),
'cursor anchor must resolve the repo TOP-LEVEL (rev-parse, not bare pwd) so subdirectory invocations anchor correctly',
);
const promptLine = block.split('\n').find((l) => l.startsWith('CURSOR_PROMPT_ARG='));
assert.ok(promptLine, 'cursor block must define CURSOR_PROMPT_ARG');
assert.ok(
/repository under review is at \$_CURSOR_ROOT/.test(promptLine),
'CURSOR_PROMPT_ARG must anchor repo-relative references to the absolute repo root',
);
});
});

View File

@@ -285,7 +285,7 @@
"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": "43c052bba1cbd4ac",
"gsd-core/workflows/review.md": "c4622380e61615c8",
"gsd-core/workflows/scan.md": "a7fecd67e5cd655f",
"gsd-core/workflows/secure-phase.md": "52ddc46233e8fa66",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "ad7c0f372ed986ae",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -355,7 +355,7 @@
"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": "eec3a15bebb7fcf0",
"gsd-core/workflows/review.md": "15b8defb2d791092",
"gsd-core/workflows/scan.md": "75c670d08cee8680",
"gsd-core/workflows/secure-phase.md": "8030d2b2a5bfdf07",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -284,7 +284,7 @@
"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": "b0baf1dafebe3821",
"gsd-core/workflows/review.md": "f1dbb3769d461ec2",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "d6ac1f4db6a5da75",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -288,7 +288,7 @@
"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": "6c689f4ff8146d28",
"gsd-core/workflows/review.md": "8c996dc10e923685",
"gsd-core/workflows/scan.md": "dfd92717caea0ce7",
"gsd-core/workflows/secure-phase.md": "00de56d6d993bb2c",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "ad7c0f372ed986ae",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -391,7 +391,7 @@
"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": "5faef3f4feb45c99",
"gsd-core/workflows/review.md": "a980007626185b70",
"gsd-core/workflows/scan.md": "1a3caa5d724d39e9",
"gsd-core/workflows/secure-phase.md": "ab387a4bca381c18",
"gsd-core/workflows/session-report.md": "dd8fa011c9394075",

View File

@@ -286,7 +286,7 @@
"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": "4b649f31865a1785",
"gsd-core/workflows/review.md": "1f44a33c50b1cd36",
"gsd-core/workflows/scan.md": "dcc2f76d0850e2fb",
"gsd-core/workflows/secure-phase.md": "9bec6635ee1cbaed",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "3ba8bb85c8ede5b8",
"gsd-core/workflows/review.md": "ad115fadce422eae",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "3063b0b6f7b56d46",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -285,7 +285,7 @@
"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": "761dd1ae5be40613",
"gsd-core/workflows/review.md": "d8c53e495b067afe",
"gsd-core/workflows/scan.md": "b28f65d88c522767",
"gsd-core/workflows/secure-phase.md": "a503dc469fd7a252",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "f8109b9ec1f56962",
"gsd-core/workflows/review.md": "3d62fa3096f46ecb",
"gsd-core/workflows/scan.md": "47371c2073d6c0be",
"gsd-core/workflows/secure-phase.md": "4977cf9e0462745b",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -349,7 +349,7 @@
"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": "ad7c0f372ed986ae",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "2d28a6683ff587de",
"gsd-core/workflows/review.md": "98e441bde98a9d92",
"gsd-core/workflows/scan.md": "ad8ebcad4626d4a8",
"gsd-core/workflows/secure-phase.md": "71e6e689e80288ec",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -252,7 +252,7 @@
"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": "ad7c0f372ed986ae",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -285,7 +285,7 @@
"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": "bcbc20cb8df021cc",
"gsd-core/workflows/review.md": "7e1d8901d796338f",
"gsd-core/workflows/scan.md": "949692db4834dd27",
"gsd-core/workflows/secure-phase.md": "ef7b5ad194b687bf",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -285,7 +285,7 @@
"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": "835cf8c9594f17c1",
"gsd-core/workflows/review.md": "5fd9c6a9d7777eee",
"gsd-core/workflows/scan.md": "63631467651d9ca8",
"gsd-core/workflows/secure-phase.md": "4a647aec1e4d2dfe",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -285,7 +285,7 @@
"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": "3e72508a5dccd45a",
"gsd-core/workflows/review.md": "a63e0b5bb3b73730",
"gsd-core/workflows/scan.md": "12c11b2edc165df9",
"gsd-core/workflows/secure-phase.md": "185a15d389951e6e",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -356,7 +356,7 @@
"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": "ad7c0f372ed986ae",
"gsd-core/workflows/review.md": "3ce57633978035ad",
"gsd-core/workflows/scan.md": "003883d71c37da7d",
"gsd-core/workflows/secure-phase.md": "22ab3bb5da494ea7",
"gsd-core/workflows/session-report.md": "2e5b1205324ddefa",

View File

@@ -64,7 +64,7 @@
"remove-phase.md": 8513,
"remove-workspace.md": 7551,
"resume-project.md": 17270,
"review.md": 47168,
"review.md": 50362,
"scan.md": 7732,
"secure-phase.md": 13622,
"session-report.md": 4044,