diff --git a/review/sections/review-army.md b/review/sections/review-army.md
index 975d649e3..36d1b340c 100644
--- a/review/sections/review-army.md
+++ b/review/sections/review-army.md
@@ -5,10 +5,10 @@
### Detect stack and scope
```bash
-source <(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base || echo SCOPE_STATE_MACHINE=unknown)
+_SM=$(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base ) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(~/.claude/skills/gstack/bin/gstack-diff-scope 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 "
diff --git a/scripts/resolvers/review-army.ts b/scripts/resolvers/review-army.ts
index 980915181..1a4c4935c 100644
--- a/scripts/resolvers/review-army.ts
+++ b/scripts/resolvers/review-army.ts
@@ -24,10 +24,10 @@ function generateSpecialistSelection(ctx: TemplateContext): string {
### Detect stack and scope
\`\`\`bash
-source <(${ctx.paths.binDir}/gstack-state-matrix detect --base || echo SCOPE_STATE_MACHINE=unknown)
+_SM=$(${ctx.paths.binDir}/gstack-state-matrix detect --base ) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(${ctx.paths.binDir}/gstack-diff-scope 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 "
diff --git a/ship/sections/review-army.md b/ship/sections/review-army.md
index 38e0963e7..87a857032 100644
--- a/ship/sections/review-army.md
+++ b/ship/sections/review-army.md
@@ -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 || echo SCOPE_STATE_MACHINE=unknown)
+_SM=$(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base ) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
source <(~/.claude/skills/gstack/bin/gstack-diff-scope 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 "
diff --git a/test/fixtures/skill-md-size-allowlist.json b/test/fixtures/skill-md-size-allowlist.json
index ebd02e815..82dbfe751 100644
--- a/test/fixtures/skill-md-size-allowlist.json
+++ b/test/fixtures/skill-md-size-allowlist.json
@@ -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
}
}
diff --git a/test/review-workflow-clarity.test.ts b/test/review-workflow-clarity.test.ts
index 80f97f5f2..1f78c25a9 100644
--- a/test/review-workflow-clarity.test.ts
+++ b/test/review-workflow-clarity.test.ts
@@ -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 || echo SCOPE_STATE_MACHINE=unknown)\n`);
+ expect(block).toContain(`_SM=$(${HOST_PATHS.claude.binDir}/gstack-state-matrix detect --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);