docs(hooks): document the post-#7422 PreToolUse fail-closed exit contract - #7749
docs(hooks): document the post-#7422 PreToolUse fail-closed exit contract#77497487 wants to merge 2 commits into
Conversation
… exit contract kirodotdev#7422 made a preToolUse script hook that exits with anything other than 0 or 2 block the tool (undelivered verdict resolves to deny), but the user-facing hooks reference and the ScriptHook docstring still described the old warn-only rule. - docs/reference/kiro-cli/hooks.md is an upstream mirror we do not author (docs/reference/README.md), so the mirrored text stays intact and the divergence is called out in clearly-marked Kiro Crew notes, following the existing precedent in steering.md and mcp/oauth-token-storage.md. The note also says plainly that there is no per-hook opt-out, so nobody writes a warn-style exit-1 hook expecting the old contract. - The ScriptHook docstring now states the fail-closed PreToolUse rule and that it diverges from Kiro CLI's own semantics. - The two kirodotdev#7422 tests now build their hook results with spec=ScriptHookResult, so a renamed production field fails the test instead of matching a truthy child mock. Fixes kirodotdev#7744 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Triaged the shard-3 red: it is upstream main drift, not this diff.
Already tracked upstream as #7756/#7757, with the fix in flight in #7762 (converts that line to the composed-context read). I am deliberately not bumping Will update this branch from main once #7762 lands and main is green again. |
The shard-3 failure (test_no_new_gate_side_log_line_reads_the_baseline_redactor) was upstream drift from kirodotdev#7424, fixed on main by kirodotdev#7761. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The census fix landed on main via #7761 (74ffc28, 2026-09-02; #7762 was closed as its duplicate). Merged upstream main into this branch (f194ebf) to pick it up — locally |
Design Review (Fable 5, fork) — ✅ PASSDesign-level review of Design-Verdict: PASS Docs corrected to match verified shipped behavior ( [DESIGN-REVIEWED] f194ebf |
Opus 4.8 Review (fork) — ✅ no blocking findingsReviewed |
First Principles Review (Fable 5, fork) — 🟡 CONCERNSPremise-level review of All claims verified against the base tree. The docs did contradict shipped behavior ( First-Principles-Verdict: CONCERNS Every doc item corrects a verified falsehood; the riding-along test fix pins 2 of 4 bare hook-result mocks in the same file and leaves the other 2 fragile. What this change shipsIntent: make the hook docs a user reads before writing a
WatchItem 4's root cause — a bare [FIRST-PRINCIPLES-REVIEWED] f194ebf |
GPT 5.6 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
bolichen97
left a comment
There was a problem hiding this comment.
The docs now match shipped behavior: chat_runner's elif r.exit_code not in (0, 2) branch appends BLOCKED:<hook>:<detail> for HOOK_EVENT_PRE_TOOL_USE and warns for every other event, which is exactly what the new divergence note and the ScriptHook docstring state, including the no-per-hook-opt-out point. Correctly annotates the upstream mirror with a marked Kiro Crew note instead of rewriting mirrored text that is still accurate about upstream kiro-cli, and the spec=ScriptHookResult tightening turns a renamed field into a test failure rather than a truthy child mock.
|
Closing as superseded. The conflict is #8402 (505e7c8, merged 2026-09-04 17:57Z, nine minutes after the approval here), which fixed #7744 across the same three files: it rewrites the mirrored |
Pull request was closed
Problem / Motivation
#7422 (
5fbce9db) changed the PreToolUse script-hook exit-code contract: any exit that is neither 0 nor 2 now blocks the tool, where it previously only warned. The PR updateddocs/system-specs/modules/learn-cron-dashboard.md, but the user-facing reference (docs/reference/kiro-cli/hooks.md, "Exit 2 blocks / Other: warning") and theScriptHookdocstring insrc/kiro_crew/hooks.pystill describe the old rule — they now state the opposite of shipped behavior, and they are exactly what a user reads before writing ahooks.jsonhook.Why it matters
A user who writes a
preToolUsehook that exits 1 to mean "issues found, but proceed" (or whose hook can fail transiently) gets every matched tool call denied, with the docs telling them that cannot happen. There is no per-hook opt-out (ScriptHookcarries onlyenabled), so the docs are the only place to learn this before hitting it.What changed (motivation → approach → change)
Verified the shipped behavior first:
chat_runner.py's inner_fire()blocks on any non-0/2preToolUseexit withBLOCKED:<hook>:<detail>(detail =error→stderr→exited with code <n>), and warns only on non-gating events.docs/reference/kiro-cli/hooks.md— this tree is an upstream mirror we do not author (docs/reference/README.md: "Fix an error upstream first; a local edit silently diverges from the source it claims to mirror"), and the mirrored lines are still correct about upstream kiro-cli — it is Kiro Crew's own re-implementation that diverged. So instead of rewriting the mirrored text in place, the divergence is called out in clearly-marked Kiro Crew blockquote notes under "Hook output" and "PreToolUse", following the existing precedent insteering.md("Viewing and editing in Kiro Crew") andmcp/oauth-token-storage.md. The note also says plainly there is no per-hook opt-out. Happy to inline-edit the mirrored lines instead if that is preferred.src/kiro_crew/hooks.py— theScriptHookdocstring now states the fail-closed PreToolUse rule and that it diverges from Kiro CLI's own semantics (it previously claimed "Aligned with Kiro CLI hook semantics").fire_tool_hooksbeing informational on the subagent/task-runner paths — so the doc note deliberately links no tracking issue.Tests
The two tests added by #7422 built their hook results with bare
MagicMocks, so a renamed production field (e.g.error) would still match a truthy child mock and pass. They now usespec=ScriptHookResult(picking up the issue's "minor test note while here"); an attribute read outside the real field set now raises.test/test_dashboard_approval.pypasses 74/74;black --checkandflake8clean on the touched files.Manual verification
N/A — docs + docstring text and a mock-tightening; unit coverage sufficient (the behavior being documented is pinned by the existing #7422 tests).
Fixes #7744
🤖 Generated with Claude Code