memory: snapshot — U1 and U2 released at v0.2.1, U5 next

Records what this session learned that the code does not say on its own: the
read-lenient/write-strict asymmetry and why pointing both at one reader silently
collapses them; that the seam review and the cold contract panel had zero overlap
in BOTH directions on one unit, so neither substitutes for the other; that every
code-changing panel finding came from the ambiguity pass rather than the
paraphrase; and the timing lesson that a tag waits for an outstanding gate.

In-flight is set up for U5 with the two things already settled about it, so the
next session does not re-derive them: .booth.json is a dotfile and so is already
excluded by booth_items, and the deterministic-order invariant applies to whatever
it adds to the index card.

No version bump — memory snapshot, on the SemVer skip list.
This commit is contained in:
vh
2026-09-21 23:58:25 -07:00
parent a0448bdc24
commit 70fb15886b
+77 -30
View File
@@ -17,40 +17,74 @@ loop it turned out to actually be.
## Current state / in-flight
_As of 2026-09-21:_
_As of 2026-09-21 (late):_
- **v1 is gated on seven units** in `ROADMAP.md`, ordered by dependency:
**U1 → U2 → {U3, U4, U5} → U7**, with **U6 independent** of all of them.
- **U1 (one item record) has landed** at `ce598b3` and is verified against its
own invariants, not just its commit message: INV-1 holds (no `classify` /
`doc_kind` / `read_blurred` / `render_doc` call survives in a route body),
the zoom and doc templates render the caption they now receive, the
re-exports are asserted by a test. 192 tests green, `0.1.15`.
- **U2 (marks) has landed** — `booth/marks.py`, contract at
`docs/contracts/u2_marks.contract.md`, 242 tests green. Not yet deployed.
- **U2 is DEPLOYED and the migration is done.** The service was restarted
2026-09-21 23:41 and again after the `auto_reload` fix; all four legacy
sidecars imported (`dfa-concepts/dfa`, `run07-decisions/decisions`,
`sc-iso-spread/spread`, `sindra-voice-1/anchor`, all still open) with the
sidecars left on disk. Verified live: index + 25 booths x {booth page, marks
page, marks.json} all 200, plus zoom views on five booths.
- **Still needs the operator: the release tier.** U2 changes the CLI surface for
17 consuming handles (`booth asks` -> `booth marks`, new `marks-import`) and is
a v1 unit, so it reads minor-worthy — which needs explicit approval per the
SemVer rule. Nothing is bumped or tagged; the work is committed as SHAs.
- **`/heid-contract-review` on the U2 contract is still in flight** (panel mode,
posted 2026-09-21, redacted copy at
`/tmp/heid-contract-review/booth-20260922-061015/`). Triage it when it lands —
the code is written, so findings land as follow-up fixes rather than contract
edits. The seam review ran in-session and its nine findings are already folded
into the contract and the code.
- **Open, operator's call:** whether U6 (benches) runs in parallel with U2 or
strictly after it. Nothing blocks on the answer; U6 touches different storage
and a different surface, so it cannot be broken by U2.
- Live service is `active` on `:8090` (systemd `--user`), 25 booths.
- **v1 is gated on seven units** in `ROADMAP.md`, dependency-ordered
**U1 → U2 → {U3, U4, U5} → U7**, with **U6 independent**.
- **U1 and U2 are landed and released.** Current version `0.2.1`, deployed to the
live service, 253 tests green, tree clean. U1 `ce598b3`; U2 `c7f9437` released as
`v0.2.0`, then `5e41108` as `v0.2.1` carrying four cross-frontier panel findings.
- **U5 is the next unit** (operator, 2026-09-21): **self-announcing booths.**
`.booth.json` carrying `{handle, title, why, created}`, written by the CLI from
`$ALTHING_HANDLE`; the index card gains provenance and a one-line purpose, and
the index becomes the "what landed" feed the link board was being used as. It
closes job 5 of the five jobs — the one nobody named, and the reason 145 dead
link rows existed. Nothing started: no contract, no blast-radius pass.
- **Two things about U5 are already settled and should not be re-derived.**
(1) `.booth.json` is a DOTFILE, so `booth_items`' existing `startswith(".")` skip
already keeps it out of tiles, counts and zips — the same reason `.marks.json`
needed no new exclusion rule. (2) The deterministic-order invariant applies to
whatever U5 adds to the index; the index is ordered newest-first by mtime today
and that rule must stay stated. Also worth knowing before scoping: enforcing the
link rule without giving job 5 a home first just makes it homeless — that is the
lesson from the 69% rot, and U5 is the home.
- **One heid dispatch is still outstanding**: the `/heid-bug-hunt` on U2's diff,
msg `01M33XEC1H0298C0D968FWBN7A`, thread same. Triage it the same five-category
way when it lands. **Do not assume it is ceremony** — the contract-review panel
that preceded it found three real defects in already-released code.
- Live service `active` on `:8090`, 25 booths, verified 25 × 3 page types after the
last deploy. The booth set churns: `sindra20-engines` and `sindra-finalists` were
swept during the session, `cr123a-to-d-sleeve` and `sindra` appeared.
## Recent decisions
- `[2026-09-21]` **v0.2.0 cut and announced; v0.2.1 fixed what the announcement
was already wrong about.** Operator approved the minor (a v1 unit closed plus a
CLI surface change for 17 consuming handles clears the release-note bar). The
note went to 15 handles — the 17 link-board posters minus `nh3-dev`, a host
label, and `heid`, an oracle that does not script these verbs. Then the
cross-frontier contract panel landed and found **three defects in the code I had
just released**, so `v0.2.1` shipped within the hour. Sequence worth remembering:
the release was correct by the tier bar and still premature by the discipline —
the panel had been dispatched BEFORE implementation and its reply arrived AFTER
the tag. **If a gate is in flight, the tag can wait for it.**
- `[2026-09-21]` **A write over a damaged `.marks.json` was wiping every mark in
the booth.** Shipped in `v0.2.0`, found by the panel (Kimi, converged with
Hulda), fixed in `v0.2.1`. `marks_for` is deliberately lenient — unparseable
reads as `[]` so a review page still loads — and the write path inherited that
leniency through the same reader, so one flag click appended to an empty list and
atomically replaced the file. The fix is an **asymmetry**, which is the reusable
part: reads stay lenient, writes go strict (`MarksCorrupt`), damaged bytes stay
on disk, routes answer 409 not 500. A page that renders without an annotation is
recoverable; a file that overwrote the operator's judgment is not. Kimi also
named the class correctly — "an author steeped in the design conversation would
likely read past" it — and that was accurate.
- `[2026-09-21]` **The two review gates are complementary, measured on one unit.**
The caller-side **seam review** (nine findings, against the real sibling module
surfaces) and the cold **`/heid-contract-review` panel** (four arms,
artifact-only) had **zero overlap in both directions** on U2. The seam review
found a scope miss the panel structurally could not see: the contract omitted
`inline.py`, whose `place()` indexes by subscript, which a frozen dataclass
refuses. The panel found three code defects and a missing test the seam review
had no lens for. Matches heid's kvasir zero-overlap result on the
conformance-versus-hunt axis. **Run both; neither substitutes.**
- `[2026-09-21]` **Every one of the panel's code-changing findings came from the
AMBIGUITY pass, none from a paraphrase divergence** — and two arms independently
proposed cutting the paraphrase to a drift-check for narrative-heavy contracts,
because this contract's own frontmatter carries a plain-language narrative and the
paraphrase was partly reading my framing back to me. That is a finding about the
`/heid-contract-review` **skill**, not about this repo, and it was reported back
to heid. Recorded here only so a future session does not rediscover it.
- `[2026-09-21]` **Deterministic order is a cross-cutting v1 invariant** —
operator directive, mid-implementation. Every ordered collection the Booth
renders must have a *stated* rule producing the same sequence on every render
@@ -149,6 +183,19 @@ _As of 2026-09-21:_
## Tried and abandoned
- `[2026-09-21]` **Tagging a release while a review gate was still in flight.**
`v0.2.0` was cut and announced to 15 consuming handles; the
`/heid-contract-review` panel — dispatched BEFORE implementation, as the
discipline says — replied afterwards with three defects in the code that had just
shipped, one of them silent data loss. Nothing about the tier decision was wrong;
the *timing* was. **If a gate is outstanding on the work being released, the tag
waits for it.** The cost was a same-hour `v0.2.1` and a correction note to peers
who had already verified against the broken version.
- `[2026-09-21]` **Letting the write path share the read path's leniency.** See the
`MarksCorrupt` decision above. The general shape, worth carrying beyond marks:
a tolerant reader and a tolerant writer over the same state are not the same
decision, and pointing both at one function silently makes them one. Tolerate on
read so the surface still renders; refuse on write so nothing is destroyed.
- `[2026-09-21]` **Letting Jinja hot-reload templates while the repo is the
deployment root** — the cause of a live outage the same day U2 landed, and the
sharpest foot-gun in the repo. `booth.service` sets `WorkingDirectory` to this