Claude Code First, specification version 0.1.0. The plain-language guide
Version 0.1.0. Grade R1/S2.
F100 A hook that refuses hand edits of planning files covers only the calls it matches, and widening it cost prompts
| Field | Value |
|---|---|
| Status | active |
| Topic | Planning, recording, and what the person decides |
| Grade | R1/S2 |
| Cases | roadkeep (the tool; the hook is carried by polyweave, freewilly, winwright and Shio) |
| Contrary | none |
| Harness facts | H4, H5, H6 |
Claim
roadkeep's refusal of hand edits to the governed planning files first matched only Edit and Write, left shell writes open until it also matched Bash, and the Bash match then asked about every commit that staged a governed file until git staging and reads were exempted.
Mechanism
A PreToolUse hook sees the tool name and its input. Edit and Write carry a path, so a governed path can be denied with the command to call instead. Bash carries a command string, which names a path without saying what the command does with it, so the hook can only ask the user. Asking on every command that names a governed path also asks on git add and git log, which never write the file. The premise that an agent will hand-edit when not refused is stated in the tool's rationale, not measured.
Observations
- roadkeep. The refusal shipped on the first day, to "deny the agent's hand-edit of a governed file, naming the command instead" [roadkeep@cf99c0a9].
Four days later its rationale for RK128 recorded a check run against Shio's copy of the hook, in which a shell payload that "writes the same path returns nothing at all" [roadkeep@6d710ffd:docs/IMPROVEMENTS.md#L525]; the ledger states the gap as "The guard denies Edit and Write and answers silence to a shell command writing the same file" [roadkeep@91754240:docs/CHANGELOG.md#L989], and the fix answers a matching Bash command with ask [roadkeep@e1d8056b]. The same day RK175 recorded the half that ask leaves open: "An approved shell write leaves a valid line and no record of who wrote it" [roadkeep@91754240:docs/CHANGELOG.md#L993] [roadkeep@3112274d]. On 2026-09-21 RK1689 recorded the cost of the wider match, "The guard asks about every commit that stages a governed file, though git add and git commit never write it" [roadkeep@91754240:docs/CHANGELOG.md#L1136], and the fix was to "stop asking about git staging or reading a governed file (RK1689)" [roadkeep@054faeed].
- Shio. The same hook did not load at all in Claude Code on the web, because that
environment "never installs marketplace plugins" [shio@c215718bb], until a committed launcher was added in that commit. This is a further gap in the same tool's coverage, seen from the adopting project.
- polyweave, freewilly, winwright. Each runs the same guard on
PreToolUse
[polyweave@6d1c136:.claude/settings.json#L13-L52] [freewilly@c1c2eaf:.claude/settings.json#L85-L95] [winwright@861b82e:.claude/settings.json#L1-L38]. freewilly adds a test that fails if "no roadkeep guard is wired on" [freewilly@c1c2eaf:tests/FreeWilly.Preflight.Tests/PackagingTests.cs#L326] a hook stage. These are copies of the tool and add no observation of its coverage.
Independence
One origin. Every observation is of roadkeep's guard, a shared tool (rule 3), and the Shio observation is the same tool seen from an adopter. The three recorded gaps are of different kinds (a shell write passing silently, an approved shell write leaving no record, a prompt on every staging commit), so they are not counted as one failure recurring.
Counter-evidence
No project in the corpus records an agent actually hand-editing a governed file. The premise that it will is prose: the RK22 rationale argues that an agent will bypass the format because an edit is cheaper than learning a CLI [roadkeep@91754240:src/roadkeep/guarding.py#L4-L6], and the RK128 check was run by the tool's author, not observed in a session. How often the guard denied or asked, and what the agent did next, is recorded nowhere in the sources read. By design a shell write the user approves still passes the hook; the turn-end check of RK175 names it but does not refuse it.
Grade
R1: a single tool origin. S2: the gaps and their fixes are recorded as dated ledger entries and commits. It is not S3, since no source counts how often a gap was used, and not S4, since no check that encodes the coverage was seen to fail in the sources read (the freewilly test only asserts that the guard is wired, and the pin records no failure of it).