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

16 KiB
Raw Blame History

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.