docs+gate: instruction files cannot silently regrow (R-229)
gates / gates (push) Successful in 7s

New shared scripts/instructions_gate.py, registered in controller_gates.py and
agent_gates.py, never copied into a sibling repo (the reuse_refs_check.py
precedent). 20 fixture tests, all asserting the effect: exit code AND that the
message names the file and the reason.

It is a consistency gate, not a budget gate, and the failure message says so. A
/context reading measured the instruction files at 15k tokens against 869k free in
a 1M window -- space is not the constraint, and a future reader must not re-derive
the wrong reason. The 200-line ceiling is adherence guidance; a file nobody can
hold in their head is where contradictions hide, and five were found here.

Checks run against effective text (HTML comments stripped, because they are
stripped before injection): the line ceiling; every .claude/rules/*.md declares
paths: or an explicit unconditional: true; no component version literal; no
TEMPORARY block carrying a past date; and the workspace-root CLAUDE.md is
byte-identical to its versioned copy -- the live file sits outside any git repo,
so that copy is its only version-controlled record.

Two traps recorded so they are not reintroduced: a bare \d+\.\d+\.\d+ matches the
first three octets of every IPv4 (the gate excludes dotted quads, or it fails on
192.168.0.180 in the agent's own file); and unconditional: true is NOT a Claude
Code feature but this project's own marker.

Workspace-root CLAUDE.md 208 -> 182 lines (142 effective), copy kept identical.
The nine-instance invariant table moved into the felhom-testing skill, which
triggers when writing or reviewing a test; all three directive bullets stayed in
the core. felhom.eu/CLAUDE.md got surgical corrections only and is knowingly still
over the ceiling at 227 effective lines -- closing it needs the restructure R-229
defers, said plainly rather than quietly absorbed.

CONTEXT.md gains standing ruling S-35. OPEN-ITEMS.md gains R-229.

Docs only -- no Go, no version bump, nothing built or deployed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJc8sAGRWmavP3rMtdpkr2
This commit is contained in:
2026-08-06 09:38:52 +02:00
parent d30c2a51ed
commit c21bcf84f7
10 changed files with 1125 additions and 333 deletions
+34
View File
@@ -17,6 +17,40 @@
## Standing rulings
**S-35 — INSTRUCTION FILES ARE A SHORT CORE PLUS PATH-SCOPED RULES (2026-08-06, R-229).**
Decided while rightsizing the four `CLAUDE.md` files. The mechanisms were verified before being
relied on, and two of the three the task assumed turned out to need correcting:
1. **Shape.** A `CLAUDE.md` is a short always-loaded core: what the repo is, a "doing X → read Y"
retrieval map, the gotchas that cost an incident, one command per surface, the fences, the
end-of-session checklist. Everything path-bound goes to `.claude/rules/<topic>.md` with a
`paths:` glob list, which Claude Code loads **only when a matching file is read** (confirmed
against the installed 2.1.222 build). Procedures go to the skill that already covers them.
2. **Earned rationale goes in block-level HTML comments.** They are stripped before injection and
never reach the model — **verified empirically**, not assumed: a control (two plain markers →
both reported) against a treatment (one marker inside `<!-- -->` → not reported, twice). So the
incident histories stay in the repo for human readers at zero cost. **This makes the raw line
count the wrong measure** — the gate counts *effective* lines, and so should any future budget.
3. **What may NOT move into a lazily-loaded file:** irreversible fences and agent directives. Rules
are not re-injected after `/compact`; the project-root `CLAUDE.md` is. That is why the
destructive-target fences, the secrets rule and the clean-tree gate stay in the root file.
4. **Amnesty criterion.** A prohibition with no recorded production violation and a recoverable worst
case may be deleted. Anything paid for in a real incident stays — and **a fence keeps its
permitted target and its reason**, never reduced to a bare prohibition. Exactly one item met the
bar (three generic code-quality bullets).
5. **No component version literal in any `CLAUDE.md`.** Versions change several times a day; ask the
hub or the box. **A historical citation is not fleet state** — "fixed in hub v0.97.0" cannot go
stale the way "this box runs agent 0.93.0" can, so citations moved into the HTML comment beside
the rule they justify rather than earning a carve-out in the gate.
6. **Subagent rule, narrowed (operator, 2026-08-06):** read-only research, inventory and verification
are permitted with a bounded digest; **no subagent may edit, commit, build, deploy or touch live
hardware.** None was used for R-229.
Enforced by `scripts/instructions_gate.py`, registered in `controller_gates.py` and
`agent_gates.py`. **`felhom.eu/CLAUDE.md` is knowingly still over the ceiling (227 effective lines)**
and is therefore not yet gated — closing it needs the restructure R-229 defers.
**S-34 — UNLOCKING AND RESTORING ARE SEPARATE. The recovery screen shipped (2026-08-05, controller
v0.200.0, R-193 CLOSED). Read with S-32 and S-33; together they close the whole customer journey up to
the listing.**