docs: the dotfile list gains .seen, and names the shape a new one should copy

Held until the merge deliberately: this file describes what is deployed, and
writing it while the code sat on another agent's branch would have made our
canonical convention document describe a service that was not running.

Also records a latent bug the R2 work surfaced in code it did not touch.
.blurred stores one stripped rel per line, so a rel carrying a leading space or
a newline does not round-trip and blurring ' a.png' can blur 'a.png'. .seen was
written as a JSON array for that reason, and additionally opens O_NOFOLLOW |
O_NONBLOCK with an S_ISREG check so a planted symlink is refused and a FIFO
cannot hang the read — the outage this repo has already paid for once. New
dotfiles inherit .seen's shape, not .blurred's.
This commit is contained in:
vh
2026-09-23 10:28:52 -07:00
parent 1ddd1c5654
commit 225570623d
+13 -1
View File
@@ -63,12 +63,24 @@ No database. `ls ~/booth-data` tells you everything the service knows.
Per-booth operator state is a **dotfile inside the booth**: `.forever` (keep),
`.viewed` (last deliberate look — U4's "viewing is activity"), `.blurred` (one
rel per line), `.marks.json` + `.marks.lock` (judgment), `.pins` (link-board pin
rel per line — ⚠ see below), `.seen` (R2: rels looked at full size, a JSON
ARRAY), `.marks.json` + `.marks.lock` (judgment), `.pins` (link-board pin
ids), `.uploaded` (upload-booth marker). `booth_items()` skips `name.startswith(".")`, so a new
dotfile costs nothing in item counts, galleries or zips. That skip is why the
dotfile is the right shape for new operator state — use it rather than
inventing a sidecar-per-item.
⚠ **`.seen` is a JSON array where `.blurred` is one stripped rel per line, and
the difference is a latent bug in the older one.** A rel may carry a leading
space or a newline; line-stripped storage does not round-trip it, so blurring
`" a.png"` can blur `a.png` instead. `.seen` was written as JSON for exactly
that reason (design-dev, R2), and it also opens `O_NOFOLLOW | O_NONBLOCK` with
an `S_ISREG` check — a planted symlink is refused and a FIFO cannot hang the
read, which is the outage in
`persistent-memory.d/2026-09-22-size-cap-opened-a-hang.md`. **Any new dotfile
inherits that shape, not `.blurred`'s.** `.blurred` itself is unfixed and
pre-existing.
### 3. One resolver for item facts
`booth.items.booth_items(booth)` is the only place a file is classified, a