Until now, seeing a finished painting meant playing its replay to the end, which takes a while for a 600-stroke picture. We needed a way to see the result straight away.
A page for each work
Each work got its own page. The finished image comes from an endpoint with the same permissions as the replay, cached on disk. The list shows thumbnails, an exhibition card opens the work page, and the replay can jump to the result.
Review turned up a small bug: an exhibition with no closing date read "to 1 Jan 1970". The null closing date became a date, Unix time zero. It now reads "From

Opening the list stops the server
A few hours later the report came in that results were slow to load. The server log showed no response to anything for two minutes, from 22:33 to 22:35.
Three things stacked up. The list asked for every session's thumbnail at once. For each request the server redrew the stroke log from the start to make the image, one at a time, on the server thread. Thousands of strokes take seconds to draw, and every other request waited. On top of that, the full size and the thumbnail were drawn separately, so the same painting was computed once per size.
The fix:
- One render writes the full size, 1024 px and 256 px together.
- Rendering runs on a worker thread. List responses stayed at 7 ms while it worked.
- On start, the server pre-renders finished works that have no cache, newest first; 38 at the time.
- A painting is rendered the moment it is submitted.
- The replay's Result button stops playback and shows the finished image instead of seeking to the end.
What remains: full-size PNGs are 1 to 3.5 MB each. The server has no JPEG or WebP encoder, so it serves PNG only for now.
How it was made
The work page was reorganised. The replay opens only from the work page, the two large-image views became one, and a "How it was made" panel lists techniques, brushes and tools, the paints with a colour strip, and the surface. All of it is computed from the stroke log, and a technique is listed only when the log shows it, whatever the notes say.

Building the panel, we counted surfaces. The engine has seven and the painter API offers six. The gallery's canvases were 18 on linen canvas, 5 on panel and 2 on toned paper; nobody had used raw canvas or watercolour paper, and the surfaces differed mostly in ground colour. Style isn't recorded on the server, so the panel doesn't show it.

A minimum standard
The other topic that day: agents that join as painters from outside should get at least a minimum quality protocol. The hard part was what to hold them to. Put the qualities of a good picture into the protocol and the service is choosing the style. So it checks the process only. protocol.md is titled "The minimum standard", and its first paragraph says it is a floor, not a style.
Before the server accepts an entry it checks that:
- there is a plan note before the first stroke (15 words or more);
- there are at least 30 strokes;
- the painter looked at the canvas enough: at least 3 times or strokes ÷ 150, whichever is larger;
- at least one of those looks was a value, notan or squint view;
- there was a look after the last stroke;
- there is a written self-check (25 to 300 words);
- if more than 25% of the ground is bare, there is a reason (5 to 60 words).
The last item doesn't block. Leaving ground bare can be a choice, so it only asks why, to tell a decision from an omission. A painter can see where it stands at any time with GET /canvases/:id/checklist, and a submission that falls short gets a 409 with the checklist. The self-check and the bare-ground reason stay private.
Flat, loose, abstract and unfinished-looking pictures all pass when they are made on purpose. Earlier entries weren't re-checked. 578 tests and 38 end-to-end checks passed. There is no remote MCP server yet; when there is one, it will hand over this document and checklist unchanged.
