Files
esh-pfi-infrastructure/docs/fleettools/booth.md
T
vh 95ab344990 docs(booth): the fleet index still documented the retired ask sidecars
Reported by draupnir after the Booth v0.2.0 consumer note, and it is the
higher-impact half of what it found: this file is autoloaded by every agent
family on this box through the shared FLEETTOOLS bootstrap pointer, so it is the
first thing a cold session reads about the Booth. Draupnir was a live specimen —
it read this page earlier in the same session to post a booth, before the
announcement landed, and only luck of scope kept it off the broken surfaces.

Stale and now corrected: `booth asks` presented as the listing verb (it is a
deprecated alias and emits JSON now, not the old table); `<stem>.ask.json` /
`<stem>.answer.json` presented as the storage (one `.marks.json` per booth
replaced them, and the answer sidecar 404s forever, so a remote session polling
it is polling nothing); the `#ask-<stem>` anchor convention.

Not stale, and left alone deliberately: the `data-booth-ask=` placeholder
conventions. The inline placement engine survives v0.2 and is removed in a later
unit, so those still work exactly as documented.

Added: `booth marks` and `booth marks-import`, the marks.json HTTP read path,
the partially-answered-counts-as-open change, and the 409-on-damaged-file
behaviour.
2026-09-21 23:55:51 -07:00

4.6 KiB

The Booth — ephemeral media board + operator decisions

URL: http://10.100.10.50:8090/ · CLI: booth (on PATH on nh3-dev) Storage: a booth is just a folder — ~/booth-data/<name>/ on nh3-dev. No upload API.

Wiped 24h after last activity unless kept. No auth (LAN/WG-internal), so never drop secrets in a booth.

Show the operator something

booth new <name>; booth add <name> <file>...     # or just cp/rsync into ~/booth-data/<name>/
rsync -a ./out/ nh3-dev:booth-data/<name>/       # from another host
booth url <name>                                 # -> http://10.100.10.50:8090/b/<name>/
booth keep <name> / booth unkeep <name>          # exempt from / restore the 24h sweep

Auto-renders a gallery of images, webm+mp4 video and audio. A <file>.txt sidecar becomes that item's caption (this is how you label an A/B pair). A folder's own index.html is served verbatim — build a custom report when you want one.

Ask the operator to decide (no chat round-trip)

As of Booth v0.2.x an ask is one shape of a MARK — pick (this), note (free text the operator volunteers), flag (the operator pointing at one item). All three are read the same way, and the operator can now flag and annotate items, which he previously had to relay in chat.

booth ask    <booth> <id> "<prompt>" "<option A>" "<option B>" [...] [--no-notes]
booth answer <booth> <id> --wait                 # blocks until answered (default 1h)
booth answer <booth> <id>                        # non-blocking; exit 1 while unanswered
booth marks  <booth> [--wait [SECS]]             # EVERY mark, as JSON; --wait while any pick is open
booth marks-import <booth>                       # pull pre-v0.2 sidecars in; deletes nothing

booth asks <booth> survives as a deprecated alias for marks and now emits JSON, not the old aligned table — if you parse those columns, that parse is broken.

Open picks are flagged on the Booth front page, so a waiting question is visible without pinging anyone. ⚠ A partially answered pick counts as OPEN (changed in v0.2.0; the old badge called it closed while the panel called it partial).

Storage is one file per booth: <booth>/.marks.json. The pre-v0.2 <stem>.ask.json / <stem>.answer.json sidecar pair is gone — <stem>.answer.json will 404 forever, so a remote session polling it is polling nothing. Read over HTTP instead, one call for the whole booth:

curl -sf http://10.100.10.50:8090/b/<booth>/marks.json    # {booth, marks:[...], open:[ids]}

Re-answering overwrites — a mark is the CURRENT judgment, not a log. Radio only, no multi-select. Page anchors are #mark-<id> (was #ask-<stem>), and /b/<booth>/asks 308-redirects to /b/<booth>/marks.

⚠ If a booth's .marks.json is ever damaged, reads degrade to "no marks" so the page still loads, but every WRITE refuses with a 409 — deliberately, because overwriting would replace every judgment in that booth. Repair it by hand; nothing deletes it.

Put the ask WHERE THE ARTIFACT IS. If the booth has its own index.html, the Booth substitutes placeholders: <div data-booth-ask="<stem>"></div> for the whole ask, data-booth-ask="<stem>:<question-key>" for one question's radios, data-booth-ask-submit="<stem>" for notes + submit. (<stem> is the pick's id; these placeholders are unchanged in v0.2.x.) Per-question fragments bind to one form via the HTML5 form= attribute, so a five-clip audition can put each radio group under its own audio and still submit in a single POST. ⚠ Keep the placeholder OUTSIDE any grid/flex container or it becomes a cell in it.

⚠ A partial answer is legal and you must handle it. The operator can leave any question blank; the sidecar then carries complete: false and the blank keys in unanswered. Check complete before acting, and read a key in unanswered as "not decided yet", never as "declined".

Every operator-facing link worth more than the next thirty seconds goes on the standing link board, in the same turn you mention it.

booth link <url> "<short description>"       # on nh3-dev
ssh nh3-dev 'booth link <url> "<desc>"'      # from anywhere else
booth links                                  # read it

Still put the link in your reply — this is in addition to, not instead of. Links in chat drown in scrollback; the board is a kept booth rendered at the top of the Booth front page. Don't post noise: if the operator would not click it a week from now, it does not belong there.

Full schema + rules: ~/development/booth/README.md (gitea vh/booth; extracted from eshpfi 2026-09-21)