docs: CHANGELOG + README for the gate entry point (no version bump)

README's Enforcement block now names controller_gates.py as THE entry point rather than
listing five of the seven gates individually. CHANGELOG records the allowlist entry, the
runner, the hook, the seam test and their red-proofs, and states the no-bump explicitly so
the omission reads as a decision.
This commit is contained in:
2026-08-02 15:28:40 +02:00
parent 8cb3d7af91
commit 7c32c74140
2 changed files with 50 additions and 5 deletions
+39
View File
@@ -1,5 +1,44 @@
## Changelog
### Gate enforcement — one entry point + pre-push hook (2026-08-02) — NO VERSION BUMP
**Deliberately no version bump, and no build or deploy.** Nothing compiled changed: this touches
`controller/scripts/` and `.githooks/` only, so no behaviour on any box moves. Stated explicitly so
the omission reads as a decision rather than a miss.
**`controller/scripts/docker_run_volume_path_gate.py` — one allowlist entry, in its own commit
(`c432f70`).** The gate was RED, flagging `internal/appexport/estimate.go:179`. The finding is
benign: `realVolumeSize` mounts a **named Docker volume** read-only into a throwaway alpine to `du`
it from a container view — no host path is involved, the daemon resolves the volume name daemon-side,
and it is structurally identical to the already-allowlisted `internal/backup/backup.go` entry. The
gate was right to demand review; that diff **is** the review, on its own, because burying an
allowlist widening inside a feature commit is how an allowlist stops meaning anything.
`realVolumeSize` was not touched — the code is correct; the allowlist was incomplete.
**`controller/scripts/controller_gates.py` (new) — THE entry point.** A census of all thirteen gate
scripts across the four felhom repos found that every check a `CLAUDE.md` names was passing and two
of the four nobody is told to run were failing. This repo had seven gates and `CLAUDE.md` named
two; four more were reachable only through a line in `REUSE.md`, and the docker-`-v` gate through one
line in `REUSE.md` and nothing else — while RED. The runner invokes all seven plus `reuse_refs_check`
on the repo root, streams each gate's own output, and exits worst-wins non-zero. `--fast` selects the
gates that touch no network and no container runtime; today that is all eight.
**The shared checker is never copied here.** `reuse_refs_check.py` lives in `felhom.eu/scripts/` and
is invoked across the workspace at `<repo-root>/../felhom.eu/scripts/`. A copy would recreate exactly
the drift it exists to detect. If the sibling clone is absent the gate **FAILS** and prints the path
tried — fail-closed. On this repo it now resolves 133 cited paths: 126 exact, 6 by suffix, and
`wgsync/reconciler.go` cross-repo into the hub.
**`.githooks/pre-push` (new)** — runs `controller_gates.py --fast` and refuses the push. Per-clone
(`git config core.hooksPath .githooks`; a manual run WARNS when the clone is unarmed) and
`--no-verify`-able on purpose; both limits are written into the hook. CI is the unbypassable half and
is owed — `felhom.eu` `OPEN-ITEMS.md` R-168.
**`controller/scripts/test_controller_gates.py` (new, 4 tests)** — a SEAM test asserting each member
gate's own distinctive stdout, never the runner's summary line, which an inert runner prints while
calling nothing. Red-proofed: replacing `run_gate`'s body with `return 0` still prints "all controller
gates OK" and exits 0, and turns the seam test red.
### v0.188.0 — D5: an app restore works from the drive alone (2026-07-30) — MinAgent 0.113.0 (unchanged)
**Tier-1/Tier-2 no longer depend on the whole-guest tier.** Until now the recovery unit on the
+11 -5
View File
@@ -162,11 +162,17 @@ backups, monitoring and notifications. All Proxmox/disk operations are delegated
logo-less app shows a placeholder on every list surface instead of a hidden icon; infra rows still
override with the server glyph. The felhom brand mark is never an app placeholder (brand = platform
identity only).
**Enforcement:** `scripts/template_id_gate.py` (JS element-ID integrity) + `scripts/emoji_gate.py`
(no emoji) + `scripts/native_confirm_gate.py` (zero native confirm/prompt) +
`scripts/app_row_dedup_gate.py` (row markup single-sourced) + `scripts/mojibake_gate.py`
(no double-encoded UTF-8 in templates/Go sources) — run after any template change; the Go
`TestNoEmojiInTemplates` mirrors the emoji gate.
**Enforcement — one entry point (2026-08-02):** run `python3 scripts/controller_gates.py` from
`controller/` after any template change. It is THE runner and invokes every gate:
`template_id_gate.py` (JS element-ID integrity), `emoji_gate.py` (no emoji),
`native_confirm_gate.py` (zero native confirm/prompt), `app_row_dedup_gate.py` (row markup
single-sourced), `mojibake_gate.py` (no double-encoded UTF-8 in templates/Go sources),
`docker_run_volume_path_gate.py` (every `docker … -v` mount reviewed), and `reuse_refs_check.py`
on the repo root. It exits non-zero if any gate does, and a missing gate script is a FAILURE, not
a skip. `--fast` (what `.githooks/pre-push` runs) selects the gates that touch no network and no
container runtime — today all of them. The Go `TestNoEmojiInTemplates` mirrors the emoji gate.
Why a runner: of this project's gates, only the ones named by a `CLAUDE.md` entry point ever got
run — the 2026-08-02 census found the two unnamed ones red, one for nineteen days.
- **Europe/Budapest timezone** — All scheduled jobs, timestamps, and UI labels use Hungarian timezone.
### Module Map