Files
esh-pfi-infrastructure/docs/fleettools/booth.md
T
vh 14bd95d76d chore: extract the Booth to its own repo (vh/booth)
The Booth is now one of the most-used fleet tools -- 17 agent handles post to
it daily -- and it is taking an information-architecture rework plus a
cross-agent SVOS design retrofit from design-dev. That work wants its own
ROADMAP, contracts and blast radius, not the fleet-infrastructure repo's.

All 29 commits moved with it via `git subtree split`; the history carries real
lessons (two shipped-dead controls, the verbatim-injection traps) that a
squashed import would have thrown away.

Live service repointed and verified: the user unit and the ~/.local/bin/booth
symlink now resolve into ~/development/booth, healthz answers, all 24 booths
intact. services/booth/ keeps a pointer README, same shape as the
chatterbox-fast and tts-stack extractions.
2026-09-21 21:54:47 -07:00

3.2 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)

booth ask    <booth> <stem> "<prompt>" "<option A>" "<option B>" [...] [--no-notes]
booth answer <booth> <stem> --wait               # blocks until answered (default 1h)
booth answer <booth> <stem>                      # non-blocking; exit 1 while unanswered
booth asks   <booth>

Open asks are flagged amber on the Booth front page, so a waiting question is visible without pinging anyone. Files are the state: <stem>.ask.json (yours), <stem>.answer.json (theirs: choice, choice_index, label, notes, answered_at, answered_by). Re-answering overwrites — the sidecar is the current answer, not a log. Radio only, no multi-select.

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. 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)