Files
booth/ROADMAP.md
T
vh 54c1e7c60f feat(marks)!: v0.2.0 — marks replaces asks, and the CLI surface moves with it
The release that closes U2. Consumers have to adapt, which is what makes this a
minor rather than a patch: three things a scripted session can notice.

  * `booth asks <name>` now emits JSON, not the old aligned human table.
    Anything parsing those columns breaks. `booth marks <name>` is the name to
    use; `asks` survives as a deprecated alias for the muscle memory.
  * Polling `http://…/b/<n>/<stem>.answer.json` will 404 forever. There is no
    per-question answer sidecar any more. `GET /b/<n>/marks.json` replaces it and
    answers for the whole booth in one request — including an `open` list.
  * `#ask-<stem>` page anchors are now `#mark-<id>`, and `/b/<n>/asks` 308s to
    `/b/<n>/marks`.

What a session GAINS: the operator can now attach a note to any item or to the
booth, and flag individual items — both readable with `booth marks`. Selecting
winners out of a set used to be a chat message.

Nothing a session already wrote is lost. Legacy `*.ask.json` / `*.answer.json`
sidecars are imported by `booth marks-import <name>`, idempotently, and are
never deleted.

No lockfile step: this repo tracks none (uv.lock is gitignored, 790d5ba).
2026-09-21 23:48:30 -07:00

5.9 KiB
Raw Blame History

The Booth — roadmap

Design: docs/design/information-architecture.md. Current version: 0.2.0 (U1 + U2 landed; extracted from eshpfi 2026-09-21).

v1 target

What must be true to cut 1.0. Seven capabilities, each closing a measured defect — not a wish. The measurements are in the IA doc.

# capability closes unit
1 One item record — landed ce598b3 captions never reach the zoom view (never sent, not lost) U1
2 Marks — landed c7f9437, released v0.2.0 5 mechanisms for 1 job; operator→session loop runs through chat U2
3 Declared embed seam — /_booth/embed.js, chrome mounts via DOM 6 regexes injected into arbitrary author HTML, load-bearing for asks U3
4 Derived lifetime — open marks pin; viewing is activity 54% of booths on the .forever escape hatch U4
5 Self-announcing booths — .booth.json, provenance on the index job 5 had no home, so it lived on the link board as 145 dead rows U5
6 Benches — registry, identity, enforced rule, migration 69% link-board rot; the same bench posted 5× U6
7 Navigation at 270 items — sections, rail, filters, grid keyboard one flat wall; subfolder structure discarded at render U7

Ordering is dependency-driven, not priority-driven: U1 → U2 → {U3, U4, U5} → U7, with U6 independent of all of them (different storage, different surface) and therefore the safest thing to land first or in parallel.

U1 and U2 are landed, which unblocks U3, U4 and U5 — all three read marks. U5 is next (operator, 2026-09-21). U6 remains independent and unstarted.

Cross-cutting invariant — deterministic order, everywhere

Every ordered collection the Booth renders must have a stated, deterministic order. Not "usually stable", not "whatever the filesystem yields" — a rule someone can name, that produces the same sequence on every render of the same state. The rule itself is free to be anything defensible: byte order over a path, creation time, an explicit number, even an arbitrary-but-recorded sequence. What is forbidden is no rule.

This matters more here than in most services because the Booth's whole job is comparison. The operator is judging pancake-v3-full against pancake-v4-full, tile 47 against tile 47. If the order shifts between two page loads — or differs between the gallery, the zoom ring, the zip manifest and the marks read — then every positional reference the operator makes ("the third one from the left", "the one after the banded one") is silently wrong, and a flag or a note lands on the wrong artifact. Non-determinism does not present as a bug report; it presents as the operator's judgment being quietly misfiled.

Where it already binds, and what the rule is in each case:

collection rule
items in a booth sorted(rel) — byte order over the booth-relative path (U1 INV-3)
the zoom prev/next ring the item order, filtered to images — same sequence, one source
caption sidecar resolution sorted scan, so two media files sharing a stem resolve the same way every time (a real non-determinism U1 removed)
marks in a booth (created, id) — time, with the id as tie-break so two marks written in the same second cannot swap
legacy ask import (mtime, name), which is the order list_asks gave them
link board rows pinned first, then newest-first

Where it is still to be decided, and must be before the unit ships: U7's section ordering and its compare pairing (sections need a stated order among themselves, not just within; pairing by filename needs a rule for what happens to an unpaired file), and U6's bench listing.

The test for any new ordered surface: can you write the rule down in one line? If not, it does not have one yet.

Explicitly NOT in v1

  • Backward compatibility with the ask CLI verbs. Pre-1.0, and ask / asks / answer become thin aliases over marks rather than a second code path. The 17 consuming handles get one althing note naming the change — the one case where telling peers is real coordination and not a broadcast.
  • A migration that deletes anything. links.md is archived verbatim and committed before the registry is seeded from it.

Parking lot

Deferred with a home, per the anti-creep gate. Default is park; these were weighed against the v1 path and lost on purpose.

item why parked
Compare mode — pair-by-name A/B across subfolders The best idea in the set, and the only one that is a new capability rather than a fix for a measured defect. The four-booth pancake-v3/v4 dance still works. First thing in v1.1.
Virtualized / progressive grid loading Speculative. 270 <img loading="lazy"> may be fine. Measure the real booth before optimising it — if it renders inside a second, this is invented work.
Bench uptime history + graphs The v1 need is "is it dead", which one flag answers. A time series is a different product.
Cross-booth search No evidence of the need in the usage data.
Per-viewer state (who has seen what) The Booth has one viewer. Revisit if that stops being true.
Auth Standing non-goal. LAN/mesh-internal. Blur stays cosmetic and says so.

Post-v1, already committed

  • SVOS theme retrofit by design-dev. Runs as a parallel track, not a v1 gate: we own the information architecture (it is driven by the measurement above), design-dev owns the visual and interaction system. The handoff is a /vor-ui brief written against the landed v1 structure — the same shape hamr-dev and pewpew-dev used.

Gate

A proposed feature is on the v1 path or it is parked. Default: parked. When both are defensible, park it — same asymmetry as the patch-default in SemVer. Applies regardless of who proposed it.