fix(review-army): keep the state-machine detector's output only on exit 0 (W3-5 confirm round)

A failing gstack-state-matrix detect prints SCOPE_STATE_MACHINE=false before
exiting non-zero. The scope block now captures its output and sources it only
when the detector succeeds; otherwise it discards the output, sets
SCOPE_STATE_MACHINE=unknown (dispatching the State Machines specialist) and
leaves the detector's stderr visible. Free tests cover false-output/non-zero,
empty-output/non-zero and a late failure after printing true. The stack
comment is shortened so gstack-review stays 4 chars under its pin; the five
host pins are lowered to match.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-17 20:25:57 +00:00
1 parent c777750457
commit f16dce25f0
5 files changed
+18 -12

No files matched your search

+2 -2
View File
@@ -5,10 +5,10 @@
### Detect stack and scope
```bash
source <(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base <base> || echo SCOPE_STATE_MACHINE=unknown)
_SM=$(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(~/.claude/skills/gstack/bin/gstack-diff-scope <base> 2>/dev/null) || true
set | grep '^SCOPE_'
# Detect stack for specialist context
# Detect stack
STACK=""
[ -f Gemfile ] && STACK="${STACK}ruby "
[ -f package.json ] && STACK="${STACK}node "
+2 -2
View File
@@ -24,10 +24,10 @@ function generateSpecialistSelection(ctx: TemplateContext): string {
### Detect stack and scope
\`\`\`bash
source <(${ctx.paths.binDir}/gstack-state-matrix detect --base <base> || echo SCOPE_STATE_MACHINE=unknown)
_SM=$(${ctx.paths.binDir}/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(${ctx.paths.binDir}/gstack-diff-scope <base> 2>/dev/null) || true
set | grep '^SCOPE_'
# Detect stack for specialist context
# Detect stack
STACK=""
[ -f Gemfile ] && STACK="\${STACK}ruby "
[ -f package.json ] && STACK="\${STACK}node "
+2 -2
View File
@@ -267,10 +267,10 @@ distinct defects stay separate and neither pass substitutes for the other.
### Detect stack and scope
```bash
source <(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base <base> || echo SCOPE_STATE_MACHINE=unknown)
_SM=$(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(~/.claude/skills/gstack/bin/gstack-diff-scope <base> 2>/dev/null) || true
set | grep '^SCOPE_'
# Detect stack for specialist context
# Detect stack
STACK=""
[ -f Gemfile ] && STACK="${STACK}ruby "
[ -f package.json ] && STACK="${STACK}node "
+5 -5
View File
@@ -37,7 +37,7 @@
"cursor/gstack-plan-design-review": 138935,
"cursor/gstack-plan-devex-review": 134558,
"cursor/gstack-plan-eng-review": 151523,
"cursor/gstack-review": 141047,
"cursor/gstack-review": 141043,
"factory/gstack-autoplan": 131397,
"factory/gstack-codex": 100523,
"factory/gstack-design-consultation": 108523,
@@ -47,7 +47,7 @@
"factory/gstack-plan-design-review": 141716,
"factory/gstack-plan-devex-review": 137927,
"factory/gstack-plan-eng-review": 154637,
"factory/gstack-review": 144829,
"factory/gstack-review": 144825,
"gbrain/gstack-autoplan": 129650,
"gbrain/gstack-design-review": 132733,
"gbrain/gstack-land-and-deploy": 116039,
@@ -67,7 +67,7 @@
"kiro/gstack-plan-design-review": 138775,
"kiro/gstack-plan-devex-review": 134398,
"kiro/gstack-plan-eng-review": 151373,
"kiro/gstack-review": 140853,
"kiro/gstack-review": 140849,
"openclaw/gstack-autoplan": 129355,
"openclaw/gstack-design-review": 131538,
"openclaw/gstack-land-and-deploy": 115627,
@@ -82,7 +82,7 @@
"opencode/gstack-plan-design-review": 140705,
"opencode/gstack-plan-devex-review": 136779,
"opencode/gstack-plan-eng-review": 153275,
"opencode/gstack-review": 143295,
"opencode/gstack-review": 143291,
"slate/gstack-autoplan": 128994,
"slate/gstack-design-consultation": 106996,
"slate/gstack-design-review": 142272,
@@ -90,6 +90,6 @@
"slate/gstack-plan-design-review": 138855,
"slate/gstack-plan-devex-review": 134478,
"slate/gstack-plan-eng-review": 151448,
"slate/gstack-review": 140950
"slate/gstack-review": 140946
}
}
+7 -1
View File
@@ -384,7 +384,7 @@ for (const skillName of ['review', 'ship']) {
test(`${skillName} clarity: the state-machine signal checks the detector's exit status and fails toward dispatch`, () => {
const block = between(army, '### Detect stack and scope', '### Read specialist hit rates');
expect(block).toContain(`source <(${HOST_PATHS.claude.binDir}/gstack-state-matrix detect --base <base> || echo SCOPE_STATE_MACHINE=unknown)\n`);
expect(block).toContain(`_SM=$(${HOST_PATHS.claude.binDir}/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")\n`);
expect(block.indexOf('SCOPE_STATE_MACHINE=unknown')).toBeLessThan(block.indexOf("set | grep '^SCOPE_'"));
const selection = between(army, '### Select specialists', '### Adaptive gating').replace(/\s+/g, ' ');
expect(selection).toContain('9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown (printed by the scope block)');
@@ -407,6 +407,12 @@ for (const skillName of ['review', 'ship']) {
expect(failed.stdout).not.toMatch(/^SCOPE_STATE_MACHINE=false$/m);
expect(failed.stderr).toContain('detector crashed');
expect(run('exit 127').stdout).toMatch(/^SCOPE_STATE_MACHINE=unknown$/m);
const silent = run("echo 'detector found no git' >&2; exit 3");
expect(silent.stdout).toMatch(/^SCOPE_STATE_MACHINE=unknown$/m);
expect(silent.stderr).toContain('detector found no git');
const lateFail = run("echo SCOPE_STATE_MACHINE=true; echo SCOPE_LEAK=1; exit 1");
expect(lateFail.stdout).toMatch(/^SCOPE_STATE_MACHINE=unknown$/m);
expect(lateFail.stdout).not.toContain('SCOPE_LEAK');
const detected = run("echo SCOPE_STATE_MACHINE=true; echo '# state-machine: src/takes.ts:4 proposal,accept'");
expect(detected.stdout).toMatch(/^SCOPE_STATE_MACHINE=true$/m);
expect(detected.stdout).toMatch(/^SCOPE_FRONTEND=false$/m);