mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 22:45:02 +01:00
fix(review-army): pass the state-machines output to check as a written file, not a heredoc placeholder (W3-5)
The generated-bash lint (env-host-fence-conformance INV-3) rejects free text in a heredoc body: <its complete output> reached the shell. The agent now writes the specialist's full output to .gstack/tmp/state-machines.md and the fence runs gstack-state-matrix check on that file. Two stack-detection comments and the parenthetical are trimmed to stay inside the review/ship parity ratios; gstack-review shrinks by 33 on the five pinned hosts and their pins are lowered to match. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
b789898982
commit
dc739be05a
5 files changed
+18
-25
No files matched your search
@@ -8,7 +8,6 @@
|
|||||||
_SM=$(~/.claude/skills/gstack/bin/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
|
_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
|
source <(~/.claude/skills/gstack/bin/gstack-diff-scope <base> 2>/dev/null) || true
|
||||||
set | grep '^SCOPE_'
|
set | grep '^SCOPE_'
|
||||||
# Detect stack
|
|
||||||
STACK=""
|
STACK=""
|
||||||
[ -f Gemfile ] && STACK="${STACK}ruby "
|
[ -f Gemfile ] && STACK="${STACK}ruby "
|
||||||
[ -f package.json ] && STACK="${STACK}node "
|
[ -f package.json ] && STACK="${STACK}node "
|
||||||
@@ -19,7 +18,7 @@ echo "STACK: ${STACK:-unknown}"
|
|||||||
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
||||||
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
||||||
echo "DIFF_LINES: $DIFF_LINES"
|
echo "DIFF_LINES: $DIFF_LINES"
|
||||||
# Detect test framework for specialist test stub generation
|
# Detect test framework
|
||||||
TEST_FW=""
|
TEST_FW=""
|
||||||
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
||||||
[ -f vitest.config.ts ] && TEST_FW="vitest"
|
[ -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`
|
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
|
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.
|
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
|
```bash
|
||||||
~/.claude/skills/gstack/bin/gstack-state-matrix check - <<'EOF'
|
~/.claude/skills/gstack/bin/gstack-state-matrix check .gstack/tmp/state-machines.md
|
||||||
<its complete output>
|
|
||||||
EOF
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adaptive gating
|
### Adaptive gating
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ function generateSpecialistSelection(ctx: TemplateContext): string {
|
|||||||
_SM=$(${ctx.paths.binDir}/gstack-state-matrix detect --base <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
|
_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
|
source <(${ctx.paths.binDir}/gstack-diff-scope <base> 2>/dev/null) || true
|
||||||
set | grep '^SCOPE_'
|
set | grep '^SCOPE_'
|
||||||
# Detect stack
|
|
||||||
STACK=""
|
STACK=""
|
||||||
[ -f Gemfile ] && STACK="\${STACK}ruby "
|
[ -f Gemfile ] && STACK="\${STACK}ruby "
|
||||||
[ -f package.json ] && STACK="\${STACK}node "
|
[ -f package.json ] && STACK="\${STACK}node "
|
||||||
@@ -38,7 +37,7 @@ echo "STACK: \${STACK:-unknown}"
|
|||||||
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
||||||
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
||||||
echo "DIFF_LINES: $DIFF_LINES"
|
echo "DIFF_LINES: $DIFF_LINES"
|
||||||
# Detect test framework for specialist test stub generation
|
# Detect test framework
|
||||||
TEST_FW=""
|
TEST_FW=""
|
||||||
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
||||||
[ -f vitest.config.ts ] && TEST_FW="vitest"
|
[ -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\`
|
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
|
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.
|
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
|
\`\`\`bash
|
||||||
${ctx.paths.binDir}/gstack-state-matrix check - <<'EOF'
|
${ctx.paths.binDir}/gstack-state-matrix check .gstack/tmp/state-machines.md
|
||||||
<its complete output>
|
|
||||||
EOF
|
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
### Adaptive gating
|
### Adaptive gating
|
||||||
|
|||||||
@@ -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 <base>) || _SM=SCOPE_STATE_MACHINE=unknown; source <(echo "$_SM")
|
_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
|
source <(~/.claude/skills/gstack/bin/gstack-diff-scope <base> 2>/dev/null) || true
|
||||||
set | grep '^SCOPE_'
|
set | grep '^SCOPE_'
|
||||||
# Detect stack
|
|
||||||
STACK=""
|
STACK=""
|
||||||
[ -f Gemfile ] && STACK="${STACK}ruby "
|
[ -f Gemfile ] && STACK="${STACK}ruby "
|
||||||
[ -f package.json ] && STACK="${STACK}node "
|
[ -f package.json ] && STACK="${STACK}node "
|
||||||
@@ -281,7 +280,7 @@ echo "STACK: ${STACK:-unknown}"
|
|||||||
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
DIFF_BASE=$(git merge-base origin/<base> HEAD)
|
||||||
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
DIFF_LINES=$(git diff "$DIFF_BASE" --numstat | awk '{n+=$1+$2} END {print n+0}')
|
||||||
echo "DIFF_LINES: $DIFF_LINES"
|
echo "DIFF_LINES: $DIFF_LINES"
|
||||||
# Detect test framework for specialist test stub generation
|
# Detect test framework
|
||||||
TEST_FW=""
|
TEST_FW=""
|
||||||
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
{ [ -f jest.config.ts ] || [ -f jest.config.js ]; } && TEST_FW="jest"
|
||||||
[ -f vitest.config.ts ] && TEST_FW="vitest"
|
[ -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`
|
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
|
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.
|
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
|
```bash
|
||||||
~/.claude/skills/gstack/bin/gstack-state-matrix check - <<'EOF'
|
~/.claude/skills/gstack/bin/gstack-state-matrix check .gstack/tmp/state-machines.md
|
||||||
<its complete output>
|
|
||||||
EOF
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adaptive gating
|
### Adaptive gating
|
||||||
|
|||||||
+5
-5
@@ -37,7 +37,7 @@
|
|||||||
"cursor/gstack-plan-design-review": 138935,
|
"cursor/gstack-plan-design-review": 138935,
|
||||||
"cursor/gstack-plan-devex-review": 134558,
|
"cursor/gstack-plan-devex-review": 134558,
|
||||||
"cursor/gstack-plan-eng-review": 151523,
|
"cursor/gstack-plan-eng-review": 151523,
|
||||||
"cursor/gstack-review": 141043,
|
"cursor/gstack-review": 141010,
|
||||||
"factory/gstack-autoplan": 131397,
|
"factory/gstack-autoplan": 131397,
|
||||||
"factory/gstack-codex": 100523,
|
"factory/gstack-codex": 100523,
|
||||||
"factory/gstack-design-consultation": 108523,
|
"factory/gstack-design-consultation": 108523,
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
"factory/gstack-plan-design-review": 141716,
|
"factory/gstack-plan-design-review": 141716,
|
||||||
"factory/gstack-plan-devex-review": 137927,
|
"factory/gstack-plan-devex-review": 137927,
|
||||||
"factory/gstack-plan-eng-review": 154637,
|
"factory/gstack-plan-eng-review": 154637,
|
||||||
"factory/gstack-review": 144825,
|
"factory/gstack-review": 144792,
|
||||||
"gbrain/gstack-autoplan": 129650,
|
"gbrain/gstack-autoplan": 129650,
|
||||||
"gbrain/gstack-design-review": 132733,
|
"gbrain/gstack-design-review": 132733,
|
||||||
"gbrain/gstack-land-and-deploy": 116039,
|
"gbrain/gstack-land-and-deploy": 116039,
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
"kiro/gstack-plan-design-review": 138775,
|
"kiro/gstack-plan-design-review": 138775,
|
||||||
"kiro/gstack-plan-devex-review": 134398,
|
"kiro/gstack-plan-devex-review": 134398,
|
||||||
"kiro/gstack-plan-eng-review": 151373,
|
"kiro/gstack-plan-eng-review": 151373,
|
||||||
"kiro/gstack-review": 140849,
|
"kiro/gstack-review": 140816,
|
||||||
"openclaw/gstack-autoplan": 129355,
|
"openclaw/gstack-autoplan": 129355,
|
||||||
"openclaw/gstack-design-review": 131538,
|
"openclaw/gstack-design-review": 131538,
|
||||||
"openclaw/gstack-land-and-deploy": 115627,
|
"openclaw/gstack-land-and-deploy": 115627,
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
"opencode/gstack-plan-design-review": 140705,
|
"opencode/gstack-plan-design-review": 140705,
|
||||||
"opencode/gstack-plan-devex-review": 136779,
|
"opencode/gstack-plan-devex-review": 136779,
|
||||||
"opencode/gstack-plan-eng-review": 153275,
|
"opencode/gstack-plan-eng-review": 153275,
|
||||||
"opencode/gstack-review": 143291,
|
"opencode/gstack-review": 143258,
|
||||||
"slate/gstack-autoplan": 128994,
|
"slate/gstack-autoplan": 128994,
|
||||||
"slate/gstack-design-consultation": 106996,
|
"slate/gstack-design-consultation": 106996,
|
||||||
"slate/gstack-design-review": 142272,
|
"slate/gstack-design-review": 142272,
|
||||||
@@ -90,6 +90,6 @@
|
|||||||
"slate/gstack-plan-design-review": 138855,
|
"slate/gstack-plan-design-review": 138855,
|
||||||
"slate/gstack-plan-devex-review": 134478,
|
"slate/gstack-plan-devex-review": 134478,
|
||||||
"slate/gstack-plan-eng-review": 151448,
|
"slate/gstack-plan-eng-review": 151448,
|
||||||
"slate/gstack-review": 140946
|
"slate/gstack-review": 140913
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,8 +387,10 @@ for (const skillName of ['review', 'ship']) {
|
|||||||
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).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_'"));
|
expect(block.indexOf('SCOPE_STATE_MACHINE=unknown')).toBeLessThan(block.indexOf("set | grep '^SCOPE_'"));
|
||||||
const selection = between(army, '### Select specialists', '### Adaptive gating').replace(/\s+/g, ' ');
|
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('9. **State Machines** — if SCOPE_STATE_MACHINE is true or unknown: read');
|
||||||
expect(selection).toContain("gstack-state-matrix check - <<'EOF' <its complete output> EOF");
|
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');
|
expect(selection).not.toContain('pipe output');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user