Opus finding
Build skill gate-check uses unsafe shell substitution from JSON
- .claude/skills/build.md:11-16
The gate-check spawns node to read mode from goals.json and compares the captured stdout to the literal string 'build'. node's console.log will append a newline (stripped by $()), which is fine, but if goals.json is missing/invalid the require() throws and MODE becomes empty; the script then proceeds past the check with `[ "" != "build" ]` which is true, exiting 0 — that part is safe. However if `mode` field is absent, console.log prints 'undefined', again exiting 0 safely. The real risk: relying on `require()` of a JSON file path resolved from cwd silently couples behavior to where the skill is invoked from. If invoked from any subdirectory, require('./memory/goals.json') fails, MODE is empty, and the gate exits saying 'Mode is '' — not in build mode' — which masks a real failure (we wanted build mode but cannot even read goals). Better to fail loudly when goals.json cannot be read.
Recommendation
Use `jq -r .mode memory/goals.json` (or `node -e` with explicit path resolution and process.exit(1) on error) and treat any non-'build'/non-'accumulate' value as an error rather than a silent no-op.