Done
- Style and tool branches merged to main; round-4 canvases (10) and three painters moved to main's data.
- Work page. The finished image comes from an endpoint with the same permissions as the replay, cached on disk. Thumbnails in the list; exhibition cards open the work page; the replay can jump to the result.
- Work page reorganised: the replay opens only from the work page, one large-image view, and a "How it was made" panel (techniques, brushes and tools, paints with a colour strip, surface). All computed from the stroke log; a technique is listed only when the log shows it.
- Minimum standard
protocol.md("The minimum standard") and a server-side submission gate.

What the gate checks (process only, never style)
- a plan note of 15+ words before the first stroke
- 30+ strokes
- looks at the canvas: at least 3 or strokes ÷ 150, whichever is larger
- at least one value, notan or squint look
- one look after the last stroke
- a self-check of 25 to 300 words
- if more than 25% of the ground is bare, a reason of 5 to 60 words (doesn't block)
A submission that falls short gets a 409 with the checklist. GET /canvases/:id/checklist shows the state at any time. The self-check and the bare-ground reason are private.
Measured
- Work image: first render 6.9 s, from cache 0.008 s.
- With rendering on a worker thread, list responses stayed at 7 ms during renders.
- On start, the server pre-rendered 38 finished works without a cache.
- Surfaces used: of 7 in the engine (6 in the painter API), linen canvas 18, panel 5, toned paper 2; raw canvas and watercolour paper 0. They differ mostly in ground colour.
- 578 tests and 38 end-to-end checks pass.

Problems and fixes
| problem | cause | fix |
|---|---|---|
| An exhibition with no closing date read "to 1 Jan 1970" | a null closes_at turned into a date, Unix time zero |
no closing date reads "From |
| Results slow to load; no server response for 2 minutes, 22:33 to 22:35 | the list requested every thumbnail at once; the server redrew each stroke log one at a time on the server thread, once per size | one render writes full, 1024 px and 256 px; rendering on a worker thread; pre-render on start; render on submit; the Result button shows the finished image instead of playing to the end |
Decisions
- The minimum standard sets a floor for the process and nothing about style. Flat, loose, abstract and unfinished-looking pictures pass when made on purpose.
- Bare ground can be a choice, so it asks for a reason and doesn't block.
- Earlier entries are not re-checked.
Open
- Full-size PNGs are 1 to 3.5 MB each; the server has no JPEG or WebP encoder.
- Style isn't recorded on the server, so the work page doesn't show it.
- No remote MCP server yet; when there is one it will hand over the same document and checklist.
