Files
felhom.eu/REPORT.md
T
admin f2edf7e545
gates / gates (push) Successful in 15s
REPORT: record CI run 384/252 by id
2026-08-22 12:14:32 +02:00

300 lines
16 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 — one register, and a rule that keeps it readable (2026-08-22)
**Records and process only. No controller, agent or hub code. No release, no bake, no machine
contacted.** Previous report preserved at
`documentation/audits/REPORT-mis-called-defect-and-sweep-2026-08-22.md`.
---
## 1. Baselines — confirmed
Controller **0.218.0**, agent **0.130.0**, golden **0.218.0 vouched**, floor **0.218.0** — all read
back from the hub, not assumed. Register ceiling was **R-375** (grepped, not trusted). All four repos
clean, `HEAD == origin/main`.
**The prompt's measurements, re-measured.** `ROADMAP.md` 249 lines / 239,306 B and `CONTEXT.md`
2,580 lines matched **exactly**. `OPEN-ITEMS.md` read 691 lines / **672,376 B / 286 entries, 134
closed** against the prompt's 642,731 / 272 / 104 — the difference is **this project's own last
session**, which added 17 rows, plus a wider closed-vocabulary on my side (I count `RESOLVED` and
`FIXED` as terminal). Longest single entry **16,108 B (R-193)**, not 15,965 — same entry, since grown.
---
## 2. The 59-versus-72 reconciliation — **both were right when taken, and neither should size anything**
| method | value | stable? |
|---|---|---|
| ids **mentioned** in ROADMAP minus ids mentioned in the register | **72** at commit `5a7502b`, **61** today | **no** |
| ROADMAP **rows** minus register **rows** | **90**, unchanged across all five commits checked | **yes** |
| …of those 90, marked shipped/closed/killed/ruled | **59** | — |
| …of those 90, **not** so marked | **31** | — |
**Why 72 became 61 without anything moving:** my own **R-369** row, written last session, *names* 11
of those identifiers in its prose. A "mentioned" count therefore falls when someone merely writes
about the problem. **That measure is unusable for sizing a migration.**
**And 59 is real** — it is the *history* half of the row-based population. So the prompt's figure and
mine were measuring the two halves of the same 90. **The count that matters is 31**, and the gate
later found the true figure is **32** (§4).
---
## 3. The population, and the rule used to sort it
**The rule, stated so it need not be re-invented:**
> **Does the item assert something about the shipped product that a reader could go and check, and
> find false?** If yes it is a **finding** and belongs in the register. If it proposes something that
> does not exist yet — a feature, a spike, a curation task — there is nothing to be wrong about, and
> it stays in the roadmap as an intention.
Two refinements the population forced: **an owed operator decision moves too** (it is work owed, not
an idea), and **an item already satisfied moves as CLOSED**, so nobody redoes it.
| group | count | disposition |
|---|---|---|
| **open work — findings and owed items** | **17** | **moved to the register**, keeping identifier, evidence and original filing date |
| **ideas and proposals that were never findings** | **15** | **stay in `ROADMAP.md`** — see below |
| **already closed** | **59** | stay as history in the roadmap |
**Where the 15 ideas live, since "not the register" is not an answer:** they stay in **`ROADMAP.md`**,
which is exactly what that file says it is — *"the prioritized decision log of planned/open work…
Items are intentions"*. The gate exempts them **by their own state word**, so they are not
second-class; they are correctly filed. They are R-6, R-8, R-9, R-12, R-14, R-19, R-34, R-45, R-46,
R-56, R-58, R-62, R-65, R-69, R-72.
---
## 4. The migration — 17 items, and the oldest
Each moved **verbatim**, nothing added or reinterpreted; the roadmap keeps its copy marked
`MOVED -> OPEN-ITEMS.md` and is not deleted, because that file's job is history.
| id | originally filed | note |
|---|---|---|
| **R-10** | **2026-07-15** | **the oldest — 38 days** (T-6E-1, dir-fsync asymmetry) |
| R-25, R-40, R-49 | 2026-07-19 | |
| R-30, R-31, R-32, R-35 | 2026-07-21 | three of them marked **[P2-HIGH]** |
| R-78 | 2026-07-25 | an **owed operator decision**, not a defect |
| R-76, R-79 | 2026-07-26 | |
| R-96 | 2026-07-27 | **moved as CLOSED** — both rules are committed at `workspace-CLAUDE.md:48-70` under a heading naming R-96 |
| R-102, R-104, R-105, **R-107** | 2026-07-28 | R-107 **moved as CLOSED** — shipped as R-354 on 2026-08-22 |
| **R-103** | 2026-07-28 | **found by the gate, not by me** — see §5 |
**Staleness named, not edited away**, as instructed:
- **R-104** — *partly stale.* The self-heal it calls unreachable **was built**: `resticStep`
escalates to `unlock --remove-all` and retries once (`offbox.go:763-768`), and `unlockStale` runs
before every off-site run and restore (`:1274`). Its premise is also doubtful — the probe is
`restic cat config`, a read that takes no lock. **What remains true:** `ClassifyOffsiteFailure`
(`:179-193`) still has no lock case.
- **R-105** — *partly fixed by its own update.* The `drives` third was traced and populated
2026-07-28; the other two thirds were not re-verified and are carried as written.
**No halt.** I checked the three READY findings for urgency before migrating them quietly. R-104 is
the one that reads urgent — *"the tier stays dead until a human runs `restic unlock --remove-all`"* —
and **it is not**, for the reasons above. Nothing in the 31 is both open and urgent.
---
## 5. The gate — and it convicted me before it convicted anything else
`scripts/one_register_gate.py`, wired into `scripts/repo_gates.py` as **`one-register`** (11 gates now,
all OK). It fails when a `ROADMAP.md` row is **neither an idea nor done** and has **no counterpart row
in `OPEN-ITEMS.md`**. The predicate is the roadmap's **own state column**, so it reads data that
already exists rather than asking anyone to maintain a new marker.
**The control — plant → convict → remove → pass:**
| step | result |
|---|---|
| baseline | **PASS** |
| plant an open roadmap-only row | **CONVICTED by name**, rc=1, quoted back |
| remove the plant | **PASS**, file byte-identical (md5) |
| plant an `idea` row | **not convicted** — the exemption is real, not a blanket pass |
**The control caught my control first.** The first plant did *not* convict, and the counts did not
move at all. Cause: **`ROADMAP.md` has no trailing newline**, so `>>` appended the row onto the last
line and it never started at column 0. A flaw in my test, not the gate. Third session running in which
the instrument caught the operator before the corpus.
**And the gate then caught three rows my hand-sort missed** — the reason is worth recording because it
is this project's most repeated shape: **my sorting regex matched the whole row, where a finding's
body routinely contains the word "shipped"; the gate matches the state cell only.**
- **R-103** (`READY — 2026-07-28`) — a genuine finding, mis-read by me as done. **Migrated.**
- **R-23** (`BANKED in full`) and **R-13** (`first slice PROVEN-LIVE`) — this project's own done-words,
which the gate did not know. Vocabulary extended; both are correctly exempt.
**And on the split it caught a genuine disagreement between the two files:** **R-203** and **R-163**
are recorded closed in the register and still open in the roadmap — R-203 even carries two
contradictory roadmap rows. The register is right in both cases; the roadmap copies are marked
`SUPERSEDED 2026-08-22` with the register's verdict.
### What the gate cannot see — named, not implied
1. **A finding filed with the state `idea` escapes.** The state column is a human judgement.
2. **A finding written in prose with no `R-` identifier escapes entirely** — this gate matches ids.
That is the previous session's sweep territory and the template rule *"an enumerated gap becomes a
row"*.
3. **A finding that never reaches the roadmap escapes.** Nothing here reads audits or spikes.
4. It checks a counterpart **exists**, never that the two agree. A stale register row passes.
---
## 6. Housekeeping — sizes before and after
| file | before | after | |
|---|---|---|---|
| `backlog/OPEN-ITEMS.md` | 691 lines / **672,376 B** | 594 lines / **327,109 B** | **−51%**, and it now holds open work only |
| `backlog/CLOSED-ITEMS.md` | — | 156 lines / 61,580 B | **new sibling**, 128 compressed closed entries |
| `backlog/ROADMAP.md` | 249 lines / **239,306 B** | 160 lines / **78,110 B** | **−67%** |
| `backlog/ROADMAP-HISTORY.md` | — | 116 lines / 28,683 B | **new sibling**, 105 finished items |
| `CONTEXT.md` | 2,580 lines / 217,260 B | 2,607 lines / 219,104 B | **deliberately not compressed** — §7 |
**A sibling, not the bottom of the file** — appending keeps the byte count and the scroll, which is
the thing being fixed. Closed work compressed to **17%** of its bytes in both files.
**Nothing was deleted.** Every compressed entry ends `full text: git show fddfe00ce268:<path>`.
**Load-bearing reasoning was not compressed away.** Rather than judge 134 entries by hand, the
compressor **keeps any sentence stating a rule, a fence or a deliberate refusal, verbatim**, under
**Reasoning kept** — 25 entries carry one. Spot-checked: R-320's kept sentence itself records that its
rule is now standing rule 5 in `workspace-CLAUDE.md`, and R-110's rule is in `felhom.eu/CLAUDE.md`
("The installer publishes by TAG, not by push (R-110)") — **both already homed outside the register,
verified by grep with a negative control.**
### The compressor moved six rows it should not have — caught and reversed
**`PARTLY CLOSED` and `OPEN — NOT FIXED` both matched a closed-vocabulary applied to the whole status
field.** R-123, R-190, R-214, R-264, R-295 and **R-352** were moved out of the register. Caught by a
follow-up check in the same session and **restored verbatim from commit `fddfe00ce268`** — not from
the compressed form, because an open row keeps its detail. **The same bug, in the same session, as the
one the gate had.** Filed as **R-378** so the next person to write a status predicate reaches for the
leading verdict rather than the whole field.
---
## 7. Why `CONTEXT.md` was not compressed — a disagreement with the task, stated
**86% of that file — 187,913 of 217,260 bytes — is one `## Standing rulings` section**, carrying 39
`S-` ids and 153 bullets under a single heading. **Standing rulings are live reasoning, not finished
work.**
**This prompt's own §3.4 says the decision log is *"dated, never edited afterwards"*** and is *"the
only place that answers 'has this been proposed before, and why did we say no?'"*. Compressing it
destroys exactly that, and there is no per-ruling delimiter, so a mechanical split risks cutting a
live ruling from its reason — **the failure this whole arc is correcting.** 13 mentions of
`SUPERSEDED` sit inside that blob and cannot be separated from live text safely today.
**So the problem is navigational, not volumetric, and the fix is structural:** give each ruling a
sub-heading with its `S-` id and date, and it becomes linkable and findable **without a word being
edited**. Filed as **R-377 (LOW)** rather than done, because it is a careful pass of its own.
The file grew by 1,844 bytes — the new decision-log entry in §8.
---
## 8. Where the hot/bulk decision was recorded — **nowhere. That is the finding.**
Established by reading, not by citation: it exists as **one unmarked bullet** at
`architecture/01-topology-and-trust.md:150-152`. **No dated entry in the decision log, no `R-` row, no
record of when it was taken.** The only mention in `CONTEXT.md` before today was the entry I wrote
*yesterday about failing to read it*.
Meanwhile its **consequence** — 40 of 53 templates declare no path — is marked **[FACT]** at
`07-backup-architecture.md:296-299`. **A reader met a marked observation beside an unmarked choice**,
and reasonably asked whether it should be so. Four times.
**Marker usage, measured** (the prompt said "three times"; the real figure is 45):
| | before | after |
|---|---|---|
| documents carrying the legend | **1 of 8** (`07`: 10 `[DESIGN]`, 35 `[FACT]`) | **8 of 8** |
**Done:**
1. **The legend is carried into all seven** other architecture documents — same wording, no third
marker invented — each stating explicitly that **an unmarked statement means *not yet classified*,
never *observed***.
2. **The hot/bulk split is marked `[DESIGN]`**, with a pointer that is honest about what it can point
at: the decision has **no original date on record**, and the new log entry exists *to give it a
home, not to claim it was decided then*.
3. **A decision-log entry** in `CONTEXT.md` — what was chosen, what follows from it, and **what was
rejected** (moving all-hot data to the data drive), so the same proposal does not return.
**Deliberately not done, and filed:** the existing statements in those seven documents were **not**
swept into one marker or the other. A wrong mark is worse than none. **R-376 (MEDIUM)** records the
remainder and the rule: mark what a session touches.
---
## 9. The template's closing step, as written
It had none — `compress` → 0 hits, `CLOSED-ITEMS` → 0, `size before` → 0, with a negative control.
Added as **§N.7**, abridged here:
> **N.7 Housekeeping — before the report, not after (2026-08-22 ruling)**
>
> 1. **Compress what this session closed.** A closed row keeps its title, the version it shipped in,
> its evidence paths, and any sentence stating a rule. Everything else goes, and it moves to
> `backlog/CLOSED-ITEMS.md`. **Nothing is deleted:** the compressed entry names the commit whose
> `git show` returns the full original text. **Open rows are not touched — their detail is doing a
> job.**
> 2. **Rehome live reasoning before compressing it away.** … **Where it is a decision, mark the
> resulting shape `[DESIGN]` in the architecture document and point it at the log entry.**
> **Losing a reason is how a deliberate design becomes a bug in someone's eyes** — that cost four
> mis-filed defect reports in August 2026 (R-370, R-376).
> 3. **State the register's size in the report, before and after.** A number every session is what
> makes growth visible; prose about tidiness is not a mechanism.
---
## 10. Part 4.2 — the storage default
**Confirmed correctly filed.** **R-368**, rank **LOW**, open, and it states the corrected position:
the default **does** apply at deploy time (`deploy.html:612` pre-selects `.IsDefault`), the residual
is that it lives in the **template, not the server**, so the API has no default and there is nothing
server-side to test.
**No row anywhere still asserts the default never applies.** The one occurrence of *"the deploy route
never reads it"* in the register is inside R-368's own quotation of the claim it corrects; the SPEC
carries `[CORRECTED 2026-08-22]` blocks; `grep` across the register, `CLOSED-ITEMS.md` and the SPEC
returns nothing else.
---
## 11. Rows and ceiling
**Opened:** R-376 (MEDIUM), R-377 (LOW), R-378 (CLOSED same session).
**Migrated in, keeping their original identifiers and dates:** R-10, R-25, R-30, R-31, R-32, R-35,
R-40, R-49, R-76, R-78, R-79, R-96 (closed), R-102, R-103, R-104, R-105, R-107 (closed).
**Restored after a compressor error:** R-123, R-190, R-214, R-264, R-295, R-352.
**Ceiling R-375 → R-378.**
**CI:** `felhom.eu` **id=384 / run_number=252**, head `ef6ac6fe` — **success**. Commit `ef6ac6f`,
pushed to `main`, all **11** gates OK, tree clean. No other repo touched.
---
## 12. What was dropped, and observations
**Dropped: nothing from Parts 1–4.** Part 4 (droppable first) and Part 3 both completed.
**One thing deliberately not done and argued rather than obeyed:** compressing `CONTEXT.md` — §7,
filed as R-377.
**Observations — noticed, not acted on:**
- **`ROADMAP.md` has no trailing newline.** It broke my own gate control and would break any future
`>>` append. One byte; not fixed here because it belongs to whoever next edits that file
deliberately.
- **R-203 has two contradictory rows in the roadmap** — one open, one shipped. Only the open one was
marked superseded; the duplicate remains as history.
- **The migrated rows are large.** Seventeen verbatim roadmap rows are now in the register, which is
why it fell 51% rather than further. They are open work and keep their detail, by the rule.
- **`OPEN-ITEMS.md` is still 327 KB.** The remaining bulk is open rows with long evidence sections —
that is detail doing a job, and the next reduction comes from closing work, not from editing it.
- **The one-register gate compares existence, not content.** R-203/R-163 were caught only because the
register had *no* row for them after the split; a stale-but-present row would pass. Named in the
gate's own docstring as residual hole 4.