fix(design-gate): fail-visible on unverified tools (no silent READY)
When `claude` is unreachable, the plugin/MCP checks (magic, ui-ux-pro-max — the most important design tools) return `unknown`. The old verdict folded that into a silent `READY` exit 0 — a fail-OPEN: the gate granted "proceed" exactly when it had verified nothing. Contradicts the fail-closed-on-uncertainty rule. Now fail-VISIBLE (not strict fail-closed — claude can be merely slow, false blocks would get the gate ignored): a third outcome READY BUT UNVERIFIED with a distinct exit 11. It proceeds, but says so loudly and names the unchecked tools, telling the user to confirm with `claude mcp list` / `claude plugin list`. The distinct non-zero code also stops a naive `if gate; then proceed` shell caller from silently passing. Also covers the non-reproducible "transient claude absent after apply" flake seen in live testing. design-gate.md §DECISION updated: exit-code line + a real branch-3 state for 11. Verified: shellcheck clean; reachable+active -> READY exit 0; claude off PATH -> READY BUT UNVERIFIED exit 11 naming magic+ui-ux-pro-max; magic off -> INCOMPLETE exit 10 (trip branch intact after the restructure). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
131d0bcb5d
commit
4d191354c6
@ -57,7 +57,7 @@ skill symlink, `claude plugin list`, `claude mcp list`, `command -v`. It never
|
||||
reads `disabledMcpServers` (unreliable for bi-modal servers like magic/context7).
|
||||
The core set lives in `design.profile`, not in the script or here — single source.
|
||||
|
||||
Exit codes: `0` = ready (proceed) · `10` = incomplete (gate trips) · `2` = error.
|
||||
Exit codes: `0` = ready · `11` = ready-but-unverified (proceed, but surface it) · `10` = incomplete (gate trips) · `2` = error.
|
||||
|
||||
### 3. Branch on the result
|
||||
|
||||
@ -77,8 +77,11 @@ Exit codes: `0` = ready (proceed) · `10` = incomplete (gate trips) · `2` = err
|
||||
a silent "optional". `/profile design` runs `toggle-external.sh` for magic,
|
||||
which needs a valid `MAGIC_API_KEY` in `~/.claude/.env` — tell the user to verify it.
|
||||
- Do NOT hand-activate individual tools. The profile is the unit of activation.
|
||||
- **`unverified` line** (claude CLI absent) → the state of a plugin/mcp couldn't
|
||||
be checked; it does not block. Mention it, proceed.
|
||||
- **11 / `READY BUT UNVERIFIED`** → `claude` was unreachable, so the design
|
||||
plugin/MCP (magic, ui-ux-pro-max) could NOT be checked. Do NOT report a plain
|
||||
"ready": proceed only after telling the user that N tool(s) went unverified and
|
||||
having them confirm with `claude mcp list` / `claude plugin list`. Fail-visible,
|
||||
not fail-silent — the most important tool (magic) is exactly an unverifiable one.
|
||||
|
||||
### Other toolchains
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
# disabledMcpServers is NEVER read — unreliable for bi-modal servers
|
||||
# (magic/context7 can appear there yet be active via another channel).
|
||||
#
|
||||
# Exit: 0 = ready (proceed) · 10 = incomplete (gate trips) · 2 = error.
|
||||
# Exit: 0 = ready · 11 = ready-but-unverified (proceed, say so) · 10 = incomplete (trips) · 2 = error.
|
||||
# Usage: design-tool-gate.sh [profile] (default profile: design)
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
@ -112,18 +112,13 @@ while IFS=$'\t' read -r type name; do
|
||||
esac
|
||||
done <<< "$plain"
|
||||
|
||||
# Verdict. Either class trips the gate.
|
||||
trip=0
|
||||
if [ "${#blocking[@]}" -gt 0 ] || [ "${#manual[@]}" -gt 0 ]; then trip=1; fi
|
||||
|
||||
if [ "$trip" -eq 0 ]; then
|
||||
echo "design toolchain: READY — profile '$PROFILE' design tools active"
|
||||
if [ "${#unverified[@]}" -gt 0 ]; then
|
||||
echo " note: could not verify (claude CLI absent): ${unverified[*]}"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Verdict — three outcomes:
|
||||
# blocking/manual non-empty -> INCOMPLETE (exit 10): the gate trips.
|
||||
# only unverified non-empty -> READY BUT UNVERIFIED (exit 11): fail-VISIBLE.
|
||||
# claude was unreachable, so the plugin/MCP (magic, ui-ux-pro-max) could
|
||||
# not be checked. Never pass this as a silent READY — proceed, but say so.
|
||||
# nothing pending -> READY (exit 0).
|
||||
if [ "${#blocking[@]}" -gt 0 ] || [ "${#manual[@]}" -gt 0 ]; then
|
||||
echo "design toolchain: INCOMPLETE"
|
||||
if [ "${#blocking[@]}" -gt 0 ]; then
|
||||
echo " activate with /profile $PROFILE: ${blocking[*]}"
|
||||
@ -135,7 +130,20 @@ if [ "${#manual[@]}" -gt 0 ]; then
|
||||
esac
|
||||
fi
|
||||
if [ "${#unverified[@]}" -gt 0 ]; then
|
||||
echo " unverified (claude CLI absent): ${unverified[*]}"
|
||||
echo " also unverified (claude CLI unreachable): ${unverified[*]}"
|
||||
fi
|
||||
echo " → run: /profile $PROFILE"
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ "${#unverified[@]}" -gt 0 ]; then
|
||||
echo "design toolchain: READY BUT UNVERIFIED — ${#unverified[@]} tool(s) not checked"
|
||||
echo " unverified (claude CLI unreachable): ${unverified[*]}"
|
||||
echo " the gate could NOT confirm the design plugin/MCP (e.g. magic,"
|
||||
echo " ui-ux-pro-max) are active. Proceed only after checking manually:"
|
||||
echo " claude mcp list claude plugin list"
|
||||
exit 11
|
||||
fi
|
||||
|
||||
echo "design toolchain: READY — profile '$PROFILE' design tools active"
|
||||
exit 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user