# Hook safety net forge-cli intercepts `store-cli write` and `store-cli update-status` bash calls and validates them before they reach the store. This prevents malformed payloads and illegal status transitions from corrupting the project's engineering knowledge base. > **See also (0.11.0):** three additional hooks ported from the Claude Code plugin now ship with forge-cli — `triage-error` (suggests `/forge:report-bug` after a forge-related Bash failure), `forge-permissions` (pattern-match auto-allow for forge-owned tool invocations), and `check-update` (banner injection + auto-dismiss on upgrade). All three are wired via `hook-dispatcher.ts` and active by default. They are operationally independent of the store-cli intercept described below. ## Default-on enforcement When enforcement is active (default), the hook dispatcher: 1. **Schema validation** — every `store-cli write ''` invocation is validated against the entity schema. If the payload is invalid, the model receives a structured error via `{ block: true, reason: }` and is expected to self-correct on the next attempt. 2. **Transition guard** — every `store-cli update-status status ` invocation is checked against the legal transition table for the entity. Illegal transitions (e.g. `draft → committed`, skipping required intermediate states) are blocked with an explanatory message naming both `from` and `to` states and the legal next states. Both checks are enforced by default. The hooks fire synchronously before the tool executes, so the model sees the error as the tool result and retries with a corrected payload. ## `--force` scope When `--force` is present in the `store-cli` argv: - **Transition guard** is bypassed — `--force` is an explicit operator override for status transitions. - **Schema validation still runs** — a malformed payload is always invalid regardless of intent. ## `FORGE_HOOK_AUDIT=1` — audit-only mode Set `FORGE_HOOK_AUDIT=1` to observe hook decisions without taking action. In audit mode: - Every decision (would-block, would-allow, lookup-failed) is logged to `.forge/logs/hooks.log`. - Nothing is blocked — all calls proceed regardless of validation outcome. - Useful for calibrating the false-positive rate before enabling enforcement in a new project. Log format (one entry per line): ``` [store-cli-intercept] subcmd=write entity=task payload={"taskId":"..."} [store-cli-intercept] decision=would-block reason=missing required field: taskId [store-cli-intercept] decision=would-allow [store-cli-intercept] decision=lookup-failed entity=task entityId=FORGE-S18-T03 ``` ## Interpreting block messages When the model emits a malformed `store-cli` call and the hook blocks it, the tool result will contain: ``` block: true reason: ``` The model should read the `reason` field and self-correct the payload or transition before retrying. Common block reasons: | Reason pattern | Cause | Fix | |---------------------------------------------------------|----------------------------------------------------|----------------------------------------------| | `missing required field: ` | Schema validation — required field absent | Add the missing field to the payload | | ` is not a legal transition...` | Transition guard — illegal status jump | Use the listed legal next states | | `store-cli validate exited with code 1` | Schema validation — malformed JSON or unknown entity | Fix the JSON payload |