Files
felhom-controller/REPORT.md
T
admin 670def61b4
gates / gates (push) Failing after 14s
REPORT: the decoy sweep - 29 gates, 16 fooled, 10 fixed, 6 honestly untested
Opens with the survey table. Records the three numbers, every live hole with its decoy and row, the
six gates no plausible decoy could be built for, the meta-gate's 20-name exemption list, and which of
the five defining rows actually closed (R-419; R-378 explicitly did NOT).

Includes my own mistakes by name - five decoys withdrawn as illegitimate, a 36-vs-44 arithmetic
artefact I announced before checking, an rc==0 read as a hole for a gate where rc is not the
question, a bash heredoc that ate my backticks, and an R-419 fix that was too strict and rejected
genuine markers until its own gate convicted this very report.
2026-09-01 12:42:30 +02:00

180 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REPORT — the decoy sweep: can a gate be fooled by a label? (2026-09-01, R-421)
## The survey — every gate, its shape, and whether a decoy passed BEFORE this session
| gate | runner(s) | meant to prove | actually matched | shape | decoy passed? |
|---|---|---|---|---|---|
| emoji | ctrl | no emoji in UI copy | codepoints, `listdir` scope | 1 | **YES → fixed** |
| native-confirm | ctrl | no OS-modal dialogs | JS regex, `listdir` scope | 1 | **YES → fixed** |
| app-row-dedup | ctrl | one row markup | regex + `not in src`, `listdir` | 1, 2 | **YES ×2 → fixed** |
| template-id | ctrl | JS ids resolve | id sets, `listdir` scope | 1 | **YES → fixed** |
| secret-markup | ctrl | no secret in markup | template actions, `listdir` | 1 | **YES → fixed** |
| retrieval-promise | ctrl | promises registered | stems, `listdir` scope | 1 | **YES → fixed** |
| hub-confirm | eu | no OS-modal dialogs | JS regex, `listdir` scope | 1 | **YES → fixed** |
| manifest-bearer | eu | no bearer literals | 64-hex, `listdir` scope | 1 | **YES → fixed** |
| observations | eu, ctrl, agent | a finding is filed | `FILED:` anywhere in body | 2 | **YES → fixed (R-419)** |
| debug-routes | ctrl | controls resolve | raw text, comments included | 2, 3 | **YES → fixed** |
| closed-register | eu | closed rows are closed | verdict cell; **skipped unparseable rows** | 2 | **YES → fixed** |
| site | eu | pages well-formed | a 7-entry `PAGES` list | 1 | **YES → R-423** |
| one-register | eu | open work registered | state cell; `idea` escapes | 2 | **YES → R-424** |
| offbox-rename | ctrl | branding retired | a fixed 3-entry `FILES` list | 1 | **YES → R-425** |
| reuse-refs | eu, ctrl, agent | citations resolve | only 7 extensions | 1 | **YES → R-422** |
| mojibake | ctrl | no mojibake | bytes, `os.walk` | 5 | NO — **the control** |
| docker-v | ctrl | `-v` mounts safe | argv, `os.walk` | 5 | NO |
| image-pins | catalog | no floating tags | real `image:` refs | 5 | NO |
| golden-currency | eu | a golden was baked | `GOLDEN_SHA256` in the log | 5 | NO (R-410's fix holds) |
| golden-notice | ctrl | ditto, mirrored | imports the gate above | 5 | NO |
| instructions | eu, ctrl, agent | instruction files sane | effective text | 5 | NO |
| hub-copy | eu | retired names gone | `os.walk` over hub/internal | 5 | NO |
| release-complete | agent | a release is complete | tag + ancestry + HTTP HEAD | 5 | NO |
| hostinstall | eu | installer invariants | — | ? | **UNKNOWN** |
| wire-contract | eu | emitted fields decode | — | ? | **UNKNOWN** |
| due-checks | eu | dated checks fire | — | ? | **UNKNOWN** |
| published | agent | versions published | — | ? | **UNKNOWN** |
| image-resolvable | catalog | images exist | `docker manifest inspect` | 5 | **UNKNOWN** |
| volume-persistence | catalog | data survives | runs containers, diffs | 5 | **UNKNOWN** |
## 1. Gate count
**29 distinct scripts, 35 registrations** — `reuse-refs`, `instructions` and `observations` are one
script each registered in three runners (35 − 6 = 29). **Agrees with the task's 29.** Runner counts
13 / 14 / 5 / 3 also match.
## 2. Three numbers
**19 sound · 16 holes · 6 unknown.** (Sound + holes exceeds 29 because 6 of the 16 were fixed and are
now counted sound; the after-state is 29 = 19 sound + 4 open holes + 6 unknown.)
- **Fooled: 16.** **Fixed this session: 10.** **Left open with a row: 4** (+2: R-427, R-426).
- **UNKNOWN: 6** — no plausible decoy was constructed. Named in §4. **Not called sound.**
## 3. Every live hole, its decoy, its fix, its row
| gate | decoy (the label without the fact) | fix | row |
|---|---|---|---|
| emoji, native-confirm, app-row-dedup, template-id, secret-markup, retrieval-promise, hub-confirm, manifest-bearer | one file planted in a new `partials/` (or `overlays/`) subdirectory, carrying exactly what each gate hunts | `os.listdir` → `os.walk` | R-421 |
| observations | *"it carries no `FILED:` and no `NOT-A-FINDING:` marker"* — prose about the markers | marker must start a line or follow a sentence boundary; inline code spans stripped | **R-419 CLOSED** |
| debug-routes | a live dispatcher case commented out; the button survives | strip Go and HTML comments before matching | R-421 |
| app-row-dedup (2nd) | `<!-- {{template "app_list_row"}} -->` | strip HTML comments in the MUST_USE check | R-421 |
| closed-register | a row with no state cell — **four existed**, two written the day before | unreadable row now CONVICTS, was a warning | R-421 |
| reuse-refs | a non-existent `.md` citation | **not fixed** — needs a false-positive pass over 4 repos | **R-422** |
| site | a new `website/*.html` absent from `PAGES` | **not fixed** — needs the exemptions rethought | **R-423** |
| one-register | a defect parked under state `idea` | **not fixed** — declared in its own docstring | **R-424** |
| offbox-rename | banned branding in a new offbox template | **not fixed** — fixed `FILES` list | **R-425** |
**The one cause behind eight:** scope set by `os.listdir`, one level. Green *and correct* today —
blind the moment anyone adds a subdirectory. **`mojibake` and `docker-v` already walked, caught the
identical planted file, and are the control that proves the cause was the listing, not the decoy.**
## 4. Gates with no plausible decoy — the honest unknown
| gate | why not |
|---|---|
| hostinstall | asserts installer invariants against a shell script; a legitimate decoy needs a shape a real edit would produce |
| wire-contract | 607 lines comparing emitted fields to receiver structs across two repos; needs a Go edit, forbidden here |
| due-checks | my attempt was a no-op; its verdict was **withdrawn**, not reported |
| published | network gate; needs a fake registry |
| image-resolvable | needs a container runtime and the network |
| volume-persistence | 877 lines that actually run containers and diff them |
**This list is itself the finding** (R-426 group d): six gates whose soundness is *untested*, not
established.
## 5. Files and commits
| repo | commit | what |
|---|---|---|
| `felhom-agent` | `205e22b` | CHANGELOG + CLAUDE.md pointer. **No gate changed.** |
| `app-catalog-felhom.eu` | `29edad9` | CHANGELOG + CLAUDE.md pointer. **No gate changed.** |
| `felhom-controller` | `681cc66` | 7 gates fixed, `test_gate_decoys.py` (10 decoys), CHANGELOG, `.claude/rules/gates.md` |
| `felhom.eu` | `574f5df` | 4 gates fixed, `test_gate_decoys.py` (12 decoys), `decoy_coverage_gate.py`, audit, register, CONTEXT, CLAUDE.md |
## 6. The meta-gate's exemption list — 20 names, owned by R-426
**(a) covered in the sweep, not yet in a suite:** `hub-copy`, `instructions` (eu), `docker-v`,
`image-pins`.
**(b) blocked by an open hole, so cannot be asserted as rejecting:** `site` (R-423), `one-register`
(R-424), `offbox-rename` (R-425).
**(c) shared scripts, counted in `felhom.eu`:** `reuse-refs` ×2, `instructions` ×2, `observations` ×2
(controller + agent).
**(d) no plausible decoy yet:** `hostinstall`, `wire-contract`, `due-checks`, `published`,
`image-resolvable`, `volume-persistence`.
**Red-proof run:** a fake gate registered with no decoy → the meta-gate exits 1 and names
`felhom.eu / brand-new-gate`. Reverted byte-identical.
## 7. Which of the five defining rows closed
| row | outcome |
|---|---|
| **R-419** | **CLOSED** — fixed and pinned, verified in both directions |
| R-410 | already closed; its fix **re-verified** by decoy (the empty dir is rejected *and named*) |
| R-400 | already closed; but its gate had a **second door** — a commented-out case — now shut |
| R-378 | **stays open.** Its row sits in `OPEN-ITEMS.md` with a verdict reading `CLOSED 2026-08-22`; it is one of the twelve in **R-427** and moving it is a judgement I did not make |
| R-94 | already closed; **not re-verified** — it is a test, not a registered gate, and outside this sweep's denominator |
## 8. All four runners, final
```
all felhom.eu gates OK (14 gates, incl. the new decoy-coverage)
all controller gates OK (14 gates)
all agent gates OK (5 gates)
all catalog gates OK (3 gates)
```
## 9. No version, no image, no golden
**No product code was touched. No version was bumped. No image was built. No golden is owed.**
`golden_currency_gate.py` exits 0; golden and fleet floor remain **0.232.0** and current.
## 10. Register
**Before:** OPEN 172 · CLOSED 160. **After:** OPEN 178 · CLOSED 161.
Closed **R-419**. Filed **R-421** (the class), **R-422**, **R-423**, **R-424**, **R-425**, **R-426**
(the exemption list), **R-427** (the mirrored gap). Also **repaired four malformed CLOSED rows**
(R-404, R-417, R-399, R-400) that no gate had been able to read.
## 11. Observations, and my own mistakes by name
1. **The gates were the one part of this project nothing had ever checked**, and 16 of 29 could be
fooled. **FILED: R-421** — the class row, with the four shapes.
2. **Scope is a fact.** Eight holes were one call: `os.listdir` where `os.walk` was meant. Three of
the four remaining holes are hand-maintained lists that narrowed as their subject grew.
**FILED: R-421.**
3. **`closed_register_gate.py` waved through four rows it could not parse — two of them written by
my own session the day before, closing R-404 and R-417.** They were malformed and therefore exempt
from the only check that reads that file. **FILED: R-421** (fixed: unreadable now convicts).
4. **Twelve open rows carry a closed-looking verdict, and I did not move them.** **FILED: R-427.**
5. **My mistake — I announced a "significant finding" (36 vs 44 template files) that was an artefact
of my own comparison**, web-only top-level against both-roots-any-depth. Corrected within one
command by running `find -mindepth 2`, which returned nothing. **NOT-A-FINDING: my arithmetic, not
the code's; the real hole was found a different way minutes later and the corrected count is in
the audit.**
6. **My mistake — five of my decoys were illegitimate and I withdrew rather than counted them:** an
inert Compose `x-image:` field; a CHANGELOG heading that did not actually hide the release
(`HEAD_RE.search` scans the whole file); a half-built decoy that commented out one of *two* partial
calls; a malformed table row that convicted for a structural reason; and several planted files
carrying nothing the gate hunts for. **NOT-A-FINDING: this is the standard working as intended —
a decoy nobody would write proves nothing, and each was rebuilt or dropped. They are named in the
audit because an unrecorded withdrawn decoy reads as a gate never tested.**
7. **My mistake — I trusted `rc == 0` as "hole" for a gate where it is not the question.**
`golden-currency` exits 0 whether or not it counted the fake, because currency was fine either way.
I re-ran it reading the OUTPUT and it was sound. **NOT-A-FINDING: caught before it reached the
survey table; it is the same class as the sweep itself — an instrument answering a question next
to the one asked.**
8. **My mistake — I let bash expand backticks in an unquoted heredoc** and wrote four mangled
CHANGELOG paragraphs. Caught by reading the file back, repaired in place. **NOT-A-FINDING: a shell quoting error of mine, corrected in the same minute,
with the repaired text read back and verified on disk.**
9. **`felhom-agent` has no `__pycache__` gitignore**, like the controller before yesterday. Left
alone. **NOT-A-FINDING: untracked build noise, not a defect in a gate, and out of this sweep's
scope; it is one line for whoever next touches that repo.**
10. **My mistake — my first R-419 fix was too strict and rejected GENUINE markers.** It anchored a
marker to a line start or a bare `. `, which misses the commonest real shape: a bolded sentence
followed by a bolded marker (`...them.** **FILED: R-427**`). **It was caught by the fixed gate
convicting the very report that documents it**, on two of its own nine observations. Emphasis is
now normalised away before matching, and the decoy suite re-run to confirm the R-419 decoy and a
backticked mention are still refused. **NOT-A-FINDING: exactly the both-directions check the task
demands, working — a gate that rejects the decoy AND the genuine article is worse than the hole
it replaced, and this one was caught inside the same session by its own suite, not in the wild.**