7db42c5fec
gates / gates (push) Successful in 12s
215 lines -> 110 (92 effective; block-level HTML comments are stripped before injection and never reach the model, verified empirically on Claude Code 2.1.222 with a control and a treatment run). Four new .claude/rules/*.md, each with a paths: glob list so it loads only when a matching file is read: gates, ui-hungarian, backup-paths, agent-coupling. The ## Layout tree was deleted as derivable; REUSE.md already owns the per-package seams its annotations stood in for. The host/access table was deleted in favour of a pointer to documentation/operations/nodes.md -- it carried three defects at once: demo-felhom given as the LAN fallback address as if it were the route, a pinned "agent 0.93.0" against the project's own no-versions-in-docs rule, and the claim that no drill VM was provisioned on demo-hp. Measured live: qm list shows VM 300 drill-r50. felhom-agent/CLAUDE.md was right; this file was wrong. Kept verbatim: the seven session-critical invariants, the F9 live-validation fence, the end-of-session checklist. controller_gates.py registers the shared instructions gate (felhom.eu/scripts/, never copied here; an absent sibling clone FAILS). Docs only -- no Go, no version bump, no image, no deploy. Ledger: felhom.eu/documentation/audits/LEDGER-instruction-trim-2026-08-06.md Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJc8sAGRWmavP3rMtdpkr2
54 lines
3.0 KiB
Markdown
54 lines
3.0 KiB
Markdown
---
|
|
paths: ["controller/**/*.go", "controller/**/*.html", "controller/**/*.css", "controller/scripts/**"]
|
|
---
|
|
|
|
# Gates and logging — felhom-controller
|
|
|
|
## The ONE entry point
|
|
|
|
**Run `python3 controller/scripts/controller_gates.py` (from `controller/`) after ANY change in this
|
|
repo.** It runs all seven local gates — `template_id_gate`, `emoji_gate`, `native_confirm_gate`,
|
|
`offbox_rename_gate`, `app_row_dedup_gate`, `mojibake_gate`, `docker_run_volume_path_gate` — plus
|
|
`reuse_refs_check` and `instructions_gate` on the repo root, streaming each gate's own output and
|
|
exiting non-zero if any fails.
|
|
|
|
- `--fast` selects the gates that touch no network and no container runtime; today that is all of them.
|
|
- **A missing gate script is a FAILURE, never a skip.**
|
|
- **The shared `reuse_refs_check.py` and `instructions_gate.py` live in `felhom.eu/scripts/` and are
|
|
never copied here** — a copy would recreate the drift they detect; an absent sibling clone FAILS.
|
|
- **The pre-push hook** (`.githooks/pre-push`) runs it with `--fast` and refuses a failing push. It is
|
|
per-clone — switch it on once with `git config core.hooksPath .githooks`, and a manual run WARNS
|
|
when this clone is unarmed. `git push --no-verify` bypasses it deliberately; **say so in the session
|
|
report when you use it.** Both facts are why CI is still owed (`OPEN-ITEMS.md` R-168).
|
|
|
|
<!--
|
|
WHY A RUNNER AND NOT SEVEN INVOCATIONS (2026-08-02, R-29) — rationale, not a directive.
|
|
A census of all thirteen gates across the four repos found that every check a CLAUDE.md named was
|
|
passing, and two of the four nobody is told to run were failing. This repo's CLAUDE.md used to name
|
|
two of the seven; the other five were reachable only through a line in REUSE.md, and
|
|
docker_run_volume_path_gate.py was RED. The single-entry-point shape is the only one that
|
|
demonstrably gets run. app-catalog-felhom.eu/scripts/catalog_gates.py is the canonical version of
|
|
the runner (R-161); repo_gates.py copies it. site_gates.py is a *gate*, not a runner — do not model
|
|
new work on it.
|
|
-->
|
|
|
|
## Logging
|
|
|
|
New leveled lines use `internal/logx` — DEBUG always reaches the debug ring; stdout respects
|
|
`logging.level`. English, keys-never-values, durations on outcomes. Full rules:
|
|
`felhom.eu/documentation/runbooks/logging-conventions.md`.
|
|
|
|
## Health checks issue no block I/O
|
|
|
|
A probe that touches a wedged device enters uninterruptible sleep, survives `SIGKILL`, and cannot be
|
|
recovered until the device returns or the host reboots — so `systemctl restart` hangs too. A timeout
|
|
protects the caller's control flow and nothing else: the blocked thread remains. Liveness is decided
|
|
from `/proc` and kernel state, never by reading or writing the filesystem.
|
|
|
|
<!--
|
|
Measured, R-117 spike §6.3 (felhom.eu/documentation/audits/SPIKE-r117-bind-liveness-2026-07-30.md):
|
|
a probe stayed in D state 3m50s after kill -9; a buffered write with no fsync blocked too (O_CREAT
|
|
needs journal access); and statfs/getdents returned HEALTHY on a namespace that EIOs every byte —
|
|
fast, and wrong.
|
|
-->
|