diff --git a/review/sections/review-army.md b/review/sections/review-army.md
index 36d1b340c..0e1b20417 100644
--- a/review/sections/review-army.md
+++ b/review/sections/review-army.md
@@ -8,7 +8,6 @@
_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
STACK=""
[ -f Gemfile ] && STACK="${STACK}ruby "
[ -f package.json ] && STACK="${STACK}node "
@@ -19,7 +18,7 @@ echo "STACK: ${STACK:-unknown}"
DIFF_BASE=$(git merge-base origin/ HEAD)
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
echo "DIFF_LINES: $DIFF_LINES"
-# Detect test framework for specialist test stub generation
+# Detect test framework
TEST_FW=""
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
[ -f vitest.config.ts ] && TEST_FW="vitest"
@@ -52,11 +51,9 @@ Based on the scope signals above, select which specialists to dispatch.
6. **API Contract** — if SCOPE_API=true. Read `~/.claude/skills/gstack/review/specialists/api-contract.md`
7. **Design** — if SCOPE_FRONTEND=true. Use the existing design review checklist at `~/.claude/skills/gstack/review/design-checklist.md` and run the mechanical pass at the top of that checklist (the user-installed design detector, when present) before the LLM items
8. **Simplification** — if DIFF_LINES > 100. Read `~/.claude/skills/gstack/review/specialists/simplification.md`. Advisory-only lens: hunts unrequested structure (hand-rolled stdlib, one-implementation abstractions, dependencies duplicating platform features), never coverage.
-9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown (printed by the scope block): read `~/.claude/skills/gstack/review/specialists/state-machines.md`, then check its output:
+9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown: read `~/.claude/skills/gstack/review/specialists/state-machines.md`, then write its full output to `.gstack/tmp/state-machines.md` and check it:
```bash
-~/.claude/skills/gstack/bin/gstack-state-matrix check - <<'EOF'
-
-EOF
+~/.claude/skills/gstack/bin/gstack-state-matrix check .gstack/tmp/state-machines.md
```
### Adaptive gating
diff --git a/scripts/resolvers/review-army.ts b/scripts/resolvers/review-army.ts
index 1a4c4935c..a12fcb134 100644
--- a/scripts/resolvers/review-army.ts
+++ b/scripts/resolvers/review-army.ts
@@ -27,7 +27,6 @@ function generateSpecialistSelection(ctx: TemplateContext): string {
_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
STACK=""
[ -f Gemfile ] && STACK="\${STACK}ruby "
[ -f package.json ] && STACK="\${STACK}node "
@@ -38,7 +37,7 @@ echo "STACK: \${STACK:-unknown}"
DIFF_BASE=$(git merge-base origin/ HEAD)
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
echo "DIFF_LINES: $DIFF_LINES"
-# Detect test framework for specialist test stub generation
+# Detect test framework
TEST_FW=""
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
[ -f vitest.config.ts ] && TEST_FW="vitest"
@@ -71,11 +70,9 @@ Based on the scope signals above, select which specialists to dispatch.
6. **API Contract** — if SCOPE_API=true. Read \`${ctx.paths.skillRoot}/review/specialists/api-contract.md\`
7. **Design** — if SCOPE_FRONTEND=true. Use the existing design review checklist at \`${ctx.paths.skillRoot}/review/design-checklist.md\` and run the mechanical pass at the top of that checklist (the user-installed design detector, when present) before the LLM items
8. **Simplification** — if DIFF_LINES > 100. Read \`${ctx.paths.skillRoot}/review/specialists/simplification.md\`. Advisory-only lens: hunts unrequested structure (hand-rolled stdlib, one-implementation abstractions, dependencies duplicating platform features), never coverage.
-9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown (printed by the scope block): read \`${ctx.paths.skillRoot}/review/specialists/state-machines.md\`, then check its output:
+9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown: read \`${ctx.paths.skillRoot}/review/specialists/state-machines.md\`, then write its full output to \`.gstack/tmp/state-machines.md\` and check it:
\`\`\`bash
-${ctx.paths.binDir}/gstack-state-matrix check - <<'EOF'
-
-EOF
+${ctx.paths.binDir}/gstack-state-matrix check .gstack/tmp/state-machines.md
\`\`\`
### Adaptive gating
diff --git a/ship/sections/review-army.md b/ship/sections/review-army.md
index 87a857032..0efb11a24 100644
--- a/ship/sections/review-army.md
+++ b/ship/sections/review-army.md
@@ -270,7 +270,6 @@ distinct defects stay separate and neither pass substitutes for the other.
_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
STACK=""
[ -f Gemfile ] && STACK="${STACK}ruby "
[ -f package.json ] && STACK="${STACK}node "
@@ -281,7 +280,7 @@ echo "STACK: ${STACK:-unknown}"
DIFF_BASE=$(git merge-base origin/ HEAD)
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
echo "DIFF_LINES: $DIFF_LINES"
-# Detect test framework for specialist test stub generation
+# Detect test framework
TEST_FW=""
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
[ -f vitest.config.ts ] && TEST_FW="vitest"
@@ -314,11 +313,9 @@ Based on the scope signals above, select which specialists to dispatch.
6. **API Contract** — if SCOPE_API=true. Read `~/.claude/skills/gstack/review/specialists/api-contract.md`
7. **Design** — if SCOPE_FRONTEND=true. Use the existing design review checklist at `~/.claude/skills/gstack/review/design-checklist.md` and run the mechanical pass at the top of that checklist (the user-installed design detector, when present) before the LLM items
8. **Simplification** — if DIFF_LINES > 100. Read `~/.claude/skills/gstack/review/specialists/simplification.md`. Advisory-only lens: hunts unrequested structure (hand-rolled stdlib, one-implementation abstractions, dependencies duplicating platform features), never coverage.
-9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown (printed by the scope block): read `~/.claude/skills/gstack/review/specialists/state-machines.md`, then check its output:
+9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown: read `~/.claude/skills/gstack/review/specialists/state-machines.md`, then write its full output to `.gstack/tmp/state-machines.md` and check it:
```bash
-~/.claude/skills/gstack/bin/gstack-state-matrix check - <<'EOF'
-
-EOF
+~/.claude/skills/gstack/bin/gstack-state-matrix check .gstack/tmp/state-machines.md
```
### Adaptive gating
diff --git a/test/fixtures/skill-md-size-allowlist.json b/test/fixtures/skill-md-size-allowlist.json
index 82dbfe751..9f5980083 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": 141043,
+ "cursor/gstack-review": 141010,
"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": 144825,
+ "factory/gstack-review": 144792,
"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": 140849,
+ "kiro/gstack-review": 140816,
"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": 143291,
+ "opencode/gstack-review": 143258,
"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": 140946
+ "slate/gstack-review": 140913
}
}
diff --git a/test/review-workflow-clarity.test.ts b/test/review-workflow-clarity.test.ts
index 1f78c25a9..127575c14 100644
--- a/test/review-workflow-clarity.test.ts
+++ b/test/review-workflow-clarity.test.ts
@@ -387,8 +387,10 @@ for (const skillName of ['review', 'ship']) {
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)');
- expect(selection).toContain("gstack-state-matrix check - <<'EOF' EOF");
+ expect(selection).toContain('9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown: read');
+ expect(selection).toContain('then write its full output to `.gstack/tmp/state-machines.md` and check it:');
+ expect(selection).toContain('gstack-state-matrix check .gstack/tmp/state-machines.md ');
+ expect(selection).not.toContain('<<');
expect(selection).not.toContain('pipe output');
});