docs+gate: felhom.eu/CLAUDE.md becomes core + path-scoped rules; instructions gate registered (R-229)
gates / gates (push) Successful in 8s
gates / gates (push) Successful in 8s
227 -> 115 effective lines, split into .claude/rules/{hub,website,manifests,docs}.md, and
repo_gates.py gains gate 6. Trim first, register second: a registered-but-failing gate refuses
every push through the pre-push hook, which is why this repo -- the one that OWNS the gate --
was the only one not running it.
Register discipline and the R-110 installer fence deliberately stayed in the core; both have
triggers no fixed glob covers, and scoping them would have rebuilt the failure class they exist
to prevent.
Scoping proven from the InstructionsLoaded hook log in two fresh sessions, not from frontmatter.
This commit is contained in:
@@ -1,3 +1,38 @@
|
||||
## repo_gates.py — `instructions` registered, and the repo that owns the gate now runs it (2026-08-06, R-229)
|
||||
|
||||
`instructions_gate.py` **lives in this repo's `scripts/`** and was registered in `controller_gates.py`
|
||||
and `agent_gates.py` on the day it was written — but not in `repo_gates.py`. The reason was
|
||||
mechanical: `felhom.eu/CLAUDE.md` was 227 effective lines against a 200 ceiling, and a
|
||||
registered-but-failing gate refuses **every** push through `.githooks/pre-push`. So the one repo that
|
||||
owns the check was the one place it did not run — the exact failure the R-29 gate census was created
|
||||
to find.
|
||||
|
||||
Fixed in the required order: **trim first, register second.**
|
||||
|
||||
- `CLAUDE.md` **227 → 115 effective lines**, restructured into a core plus
|
||||
`.claude/rules/{hub,website,manifests,docs}.md`, all `paths:`-scoped, all ≤60 effective lines.
|
||||
- `repo_gates.py` gains gate 6, `--fast` safe. Six gates, all OK.
|
||||
|
||||
**Two placements deviate from the spec's sketch, both to avoid rebuilding a failure class:**
|
||||
- **Register discipline (`OPEN-ITEMS.md` first, `STATUS.md` is a view) stayed in the core**, not in
|
||||
`docs.md`. It applies to every session that ships or decides something; behind a
|
||||
`documentation/**` glob it would be invisible in exactly the code-shipping sessions where findings
|
||||
get lost — which is how R-153/154/155 and R-156/157 were minted and lost.
|
||||
- **The R-110 installer fence stayed in the core.** Its trigger is editing
|
||||
`scripts/felhom-host-install.sh`, which none of the four fixed globs covers; behind `website/**` it
|
||||
would never load for the one artifact that runs as root on a virgin box. Compressed to its
|
||||
actionable clauses rather than relocated.
|
||||
|
||||
**Scoping proven from the hook log, not the frontmatter** (`InstructionsLoaded`,
|
||||
`~/.claude/instructions-loaded.jsonl`), in two fresh sessions so the negative control is clean:
|
||||
reading `website/index.html` produced `website.md path_glob_match` and **no** `hub.md` line; reading
|
||||
`hub/internal/api/handler.go` produced `hub.md path_glob_match` and **no** `website.md` line.
|
||||
|
||||
**Trap worth keeping:** creating `.claude/rules/` mid-session does **not** arm it. The in-session
|
||||
reads that followed produced no hook line at all — a directory whose instructions were already seeded
|
||||
is not re-scanned. Same class as the settings-watcher caveat. A new rule file is only live in a
|
||||
session started after it exists, which is why the proof above needed `claude -p`.
|
||||
|
||||
## instructions_gate.py 1.0.0 — instruction files cannot silently regrow (2026-08-06, R-229)
|
||||
|
||||
New shared gate, registered in `controller_gates.py` and `agent_gates.py`, never copied into a
|
||||
|
||||
@@ -13,6 +13,14 @@ Gates, in order (all must pass; **non-zero exit on any failure**):
|
||||
3. hub-confirm no native confirm()/prompt() in hub templates
|
||||
4. manifest-bearer no bearer-shaped literal anywhere in manifests/
|
||||
5. reuse-refs every path cited by this repo's REUSE.md still resolves
|
||||
6. instructions CLAUDE.md length/versions/TEMPORARY, rule-file scoping, workspace-copy identity
|
||||
|
||||
WHY 6 IS HERE AND WAS NOT (2026-08-06, R-229 deferred leg). instructions_gate.py LIVES in this
|
||||
repo's scripts/ and was registered in the controller and agent runners on the day it was written —
|
||||
but not in this one, because this repo's own CLAUDE.md was still 27 lines over the ceiling and a
|
||||
registered-but-failing gate refuses every push through .githooks/pre-push. The file was trimmed
|
||||
(227 -> 115 effective lines, core + .claude/rules/) and the gate registered in the same session.
|
||||
A check that does not run in the place it applies is the exact failure the R-29 gate census found.
|
||||
|
||||
WHY THIS FILE EXISTS (2026-08-02, closing R-29 leg (a) and half of leg (b)).
|
||||
|
||||
@@ -49,6 +57,7 @@ GATES = [
|
||||
("hub-confirm", os.path.join(SCRIPTS, "hub_confirm_gate.py"), [], True),
|
||||
("manifest-bearer", os.path.join(SCRIPTS, "manifest_bearer_gate.py"), [], True),
|
||||
("reuse-refs", os.path.join(SCRIPTS, "reuse_refs_check.py"), [ROOT], True),
|
||||
("instructions", os.path.join(SCRIPTS, "instructions_gate.py"), [ROOT], True),
|
||||
]
|
||||
|
||||
VERDICT = {0: "OK", 1: "FAILED", 2: "INCONCLUSIVE"}
|
||||
|
||||
Reference in New Issue
Block a user