fix: four defects the U4 bug-hunt panel found in code it did not add
All four pre-date U4 and sit in files it touched, which is why a diff-scoped robustness lens saw them. They are separated from the unit's own commit so the feature history stays readable; the release tags both. * A booth name reached a JS string context. The confirm dialogs interpolated the name into a string literal inside `onsubmit`. Jinja's autoescape is HTML-attribute escaping, not JS-string escaping: the browser decodes the entity back to a quote before the JS parser sees it, so a name crafted to close the string executed on submit. Booth names are agent-authored — making a folder under the data dir is the whole API — so this was a live path, not a theoretical one. The name now travels as a data attribute to a delegated handler, where escaping is escaping. * An unreadable `links.md` returned 500 for the whole booth page. `is_file()` then an unguarded `read_text()`. The board is one tile on that page, and a page that will not load is worse than one missing a tile — the posture `read_blurred`, `marks_for` and `read_manifest` already take. * The index order had no tie-breaker, which violates the deterministic-order invariant. Equal-mtime booths fell back to whatever `iterdir()` yielded, and two booths landed by one `rsync` batch share an mtime exactly. Now `(mtime, name)` reverse: newest first, then name. The operator refers to cards positionally, so a sequence that moves between renders misfiles his judgment rather than crashing. * `/b/<n>/marks.json` reported damage as empty success. `booth marks` exits 3 on an unreadable file precisely so a caller can tell "not yet" from "broken"; the HTTP mirror — the only reader a remote session has — returned the same empty list for both. It now carries `error` and `detail`. The status stays 200 deliberately: reads are lenient here, and a pinned status code is a promise to remote clients this fix has no business breaking. Each has a regression test. 410 tests.
This commit is contained in:
@@ -25,14 +25,13 @@ _As of 2026-09-22:_
|
||||
`5e41108` → `v0.2.1`, `026a1fc` → `v0.2.2`; U5 `c015a91` + `95beede` →
|
||||
`v0.3.0`. **U4 landed 2026-09-22** — 396 tests green (341 → 396), deployed and
|
||||
verified live, 24/24 booth pages 200, layout probe clean.
|
||||
- **U4 IS NOT YET RELEASED — the version bump is an open operator decision.**
|
||||
Recommended **v0.3.0 → v0.4.0 (minor)**: U4 changes what `keep` MEANS for 17
|
||||
agent handles ("stop pressing keep when you are only waiting"), which is
|
||||
release-note-worthy at the pre-1.0 bar and the same tier U2 and U5 took. The
|
||||
defensible alternative is v0.3.1 if U4 reads as internal plumbing, since no
|
||||
CLI verb or URL changed shape. **Commits are not releases**, so the work is
|
||||
committed unbumped and untagged; the tag waits on his word and nothing is
|
||||
blocked by the wait.
|
||||
- **U4 released as `v0.4.0`** (operator approved the minor on 2026-09-22).
|
||||
`c3a97c1` is the unit; the release commit carries the pre-existing fixes the
|
||||
bug-hunt panel surfaced in touched files. The tag waited for the last gate to
|
||||
close, per the `v0.2.0` lesson — see Tried and abandoned.
|
||||
- ⚠ **The 17 consuming handles have NOT been told** that `keep` no longer means
|
||||
"waiting on an answer". That is the one coordination this release genuinely
|
||||
warrants, and a fleetwide post needs operator approval before it is sent.
|
||||
- **THE NEXT UNIT IS THE OPERATOR'S CALL.** U3 (declared embed seam) and U6
|
||||
(benches) are both unblocked; U7 waits on the rest. U6 is independent of
|
||||
everything and was conceptually unblocked by U5 giving job 5 a home; U3 is
|
||||
|
||||
Reference in New Issue
Block a user