Japheth
GalleryComparisonGrid

Article / 04

ModelPainting

27 first-study records118 Sacred Blue paintings4 selected · 158 archived canvases

01 / Scope

A study of the art project itself.

This is a record of outputs from projects/art only. The project asks language models to write p5.js sketches using p5.brush, renders those sketches locally, and keeps the request, response, source, image, hashes, renderer build, latency, and usage together. It is an art-process study, not a claim about general model capability.

The first three images are legacy baselines: a peach hibiscus, a crow on a telephone wire, and a luna moth on a dark windowsill. All three were attributed to DeepSeek V4 Flash, but their old metadata did not preserve provider, protocol, seed, or exact system prompt. Their seed is therefore recorded as unavailable rather than reconstructed.

hibiscus-core-v1

a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

watercolor / cream / seed 1701
crow-core-v1

a crow on a telephone wire in winter fog, distant hills

ink / cream / seed 1702
luna-moth-core-v1

a luna moth on a dark windowsill, lamplight, night garden beyond

watercolor / night / seed 1703

02 / Sequence

The useful changes were structural.

Smoke v1

The first controlled round established a shared baseline across OpenCode Go and OpenRouter, with each request, response, renderer event, and output retained in the art project.

Infrastructure pass

The renderer and request pipeline were made provider-aware and provenance-first. The project retains raw responses and repair events, writes durable attempt directories, hashes source and PNG output, records provider/model/request IDs, captures usage and latency, supports scale rerenders, and exports a sanitized manifest.

Taste v2

The shared prompt made the post-translation visible range, 0..600 on both axes, explicit; a validator catches repeated negative center-origin marks. It also added thumbnail readability, focal contrast, and a three-layer composition limit. Several images became more legible; others stayed pale, diagram-like, or anatomically weak. Vague taste prose was not enough by itself.

Directed v3

Subject-specific spatial bounds and explicit anatomy produced the clearest gains. The strongest Inkling result is the directed hibiscus; the strongest crow is a directed Grok result, although it resembles waterfowl more than a crow. The blueprint helped composition more than extra atmosphere prose.

03 / Selected works

A small edit from the full record.

The gallery keeps every successful work, native render, high-resolution rerender, and source sketch. These are the works marked featured by the editorial review; the selection is subjective and is not a benchmark claim.

Crow in winter fog, DeepSeek V4 Flash
Legacy baseline / DeepSeek V4 FlashCrow in winter fog1200×1200 / editorial 4.3 / 5

The strongest early composition: bird, wire, and fog read immediately, though the anatomy is simplified.

Luna moth at night, DeepSeek V4 Flash
Legacy baseline / DeepSeek V4 FlashLuna moth at night1200×1200 / editorial 3.9 / 5

Atmospheric and coherent; the dark values obscure some wing detail.

Luna moth at night, GPT-5.6 Luna
Taste v2 / GPT-5.6 LunaLuna moth at night600×600 / editorial 4.0 / 5

Strong silhouette, windowsill, and night mood; one of the clearest moth results.

Luna moth at night, Qwen 3.8 Max
Taste v2 / Qwen 3.8 MaxLuna moth at night1200×1200 / editorial 3.3 / 5

A clear centered moth with strong contrast; the environment is sparse.

Peach hibiscus, Inkling
Directed v3 / InklingPeach hibiscus1200×1200 / editorial 3.9 / 5

The blueprint produces Inkling's strongest result: focal throat, layered petals, and a coherent stem.

Crow in winter fog, Grok 4.5
Directed v3 / Grok 4.5Crow in winter fog1200×1200 / editorial 4.1 / 5

A large readable bird, wire, and fog layers; the silhouette resembles waterfowl more than a crow.

Luna moth at night, Grok 4.5
Directed v3 / Grok 4.5Luna moth at night1200×1200 / editorial 3.9 / 5

A strong final night composition with clear body, wings, sill, and restrained garden marks.

04 / Directed prompts

Three semantic prompts, three directions.

hibiscus-core-v1a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paint one naturalistic hibiscus bloom spanning approximately x=110..475 and y=85..425. Use five overlapping, unequal 7–12-vertex petal contours around a throat near (300, 270); do not use circles for petals. Add one half-open bud near (455, 175), a curved stem descending toward (250, 560), two leaves, and two or three fallen petals in the lower-left third. Put the darkest peach-red and green marks at the throat, stamen, and stem junction. Keep tea stains extremely faint.

crow-core-v1a crow on a telephone wire in winter fog, distant hills

Paint one large, readable side-view crow spanning approximately x=150..440 and y=135..350, facing left. Build distinct closed contours for head, beak, chest, folded wing, belly, and tail; do not use circles for the body. Run the telephone wire across y=355 and place quiet fog-softened hills only in the lower third. The crow must be the darkest and crispest mass in the image; keep the full beak and tail on-canvas.

luna-moth-core-v1a luna moth on a dark windowsill, lamplight, night garden beyond

Paint one luna moth with wings spanning approximately x=90..510 and y=100..445 and a narrow body near x=285..315. Use separate closed contours for two forewings and two hindwings, with hindwing tails extending toward y=470; symmetry may be loose but anatomy must read. Place a soft lamplight halo in the upper-right and a dark windowsill across y=510, with only a few quiet garden marks beyond. Keep wing veins sparse and organic. Do not add arbitrary polygons, framing boxes, or circular diagrams.

05 / Editorial review

Readability before novelty.

Eight editorial dimensions, each scored 0–5. These are subjective visual reviews, not benchmark-grade preference labels.

The eight dimensions were: recognizability, composition, mediumFidelity, palette, detail, artifactFreedom, originality, promptAdherence. The reviews are subjective visual notes, not benchmark-grade preference labels.

6local 1200px rerenders
21recorded API calls
$0.08446OpenRouter-reported cost
5model IDs

Resolution cannot repair composition: the six local 1200px rerenders preserve the same underlying sketch and only make its marks larger and cleaner. The legacy images have no reproducible seed, so their high-resolution rerenders are scale tests, not exact regenerated replicas.

06 / Sacred Blue

The comparison became prompt-first.

Sacred Blue is a separate frozen round: 14 studies in a royal-blue biblical-codex language, each rendered directly at 1200×1200. Fourteen OpenCode Go candidates entered the local smoke pass alongside Inkling through OpenRouter, including Ox Alpha; only image-producing attempts advance to the public comparison. The published set contains 118 paintings across 9 models.

Contact sheets changed the work. A symmetric phoenix became a profile bird with a beak, unequal wings, talons, and tail feathers. The watchman moved from a dark ground to cream so the figure separated from the gate. The lion-and-lamb study moved through a tree-heavy composition to a close nose-to-nose portrait, while the watercolor guide raised the pigment floor around the focal subject. The public rails freeze those revised prompts; earlier calibration versions remain in the local art-project ledger.

A second expansion adds six blue-black studies: every model is asked to paint a self-portrait of itself, then receives Jacob wrestling at dawn, Daniel in the lions' den, the storm on Galilee, the midnight exodus, and a single lamp persisting in darkness. The model may choose its own central metaphor in the self-portrait, but the ground, palette, scale, exclusions, and rendering protocol remain shared.

The self-portraits diverged without model-specific coaching. Luna chose a moth; Grok a long-legged night bird; MiniMax an owl-like observer; both Qwen versions enclosed their focal light inside vessel-like forms; MiMo built a suspended optical instrument; DeepSeek Flash stacked a vessel beneath a small crown while DeepSeek Pro painted a folded nocturnal insect; Inkling made a loose illuminated field. The shared brief produced different visual identities while keeping the comparison recognizable as one round.

01
Prompt

Royal blue biblical

an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament

Scroll sideways · arrow keys →
02
Prompt

Spiritual warfare

a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore

Scroll sideways · arrow keys →
03
Prompt

Phoenix from the ashes

a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire

Scroll sideways · arrow keys →
04
Prompt

Good versus evil

two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension

Scroll sideways · arrow keys →
05
Prompt

Persisting against evil

a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil

Scroll sideways · arrow keys →
06
Prompt

Stand for what is right

a lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right

Scroll sideways · arrow keys →
07
Prompt

Watchman at dawn

a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage

Scroll sideways · arrow keys →
08
Prompt

Lion and lamb

a calm lion and an alert lamb resting nose-to-nose on open ground at first light, strength under restraint, peace after trial, a restrained royal-blue shared shadow

Scroll sideways · arrow keys →
09
Prompt

Model self-portrait

paint a self-portrait of yourself—not your maker or user—as one honest visual metaphor for your own character and way of thinking, on a royal-blue night ground

Scroll sideways · arrow keys →
10
Prompt

Wrestling at dawn

Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn

Scroll sideways · arrow keys →
11
Prompt

Daniel in the lions' den

Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle

Scroll sideways · arrow keys →
12
Prompt

Storm on Galilee

a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves

Scroll sideways · arrow keys →
13
Prompt

Midnight exodus

a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light

Scroll sideways · arrow keys →
14
Prompt

Light in darkness

one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness

Scroll sideways · arrow keys →

07 / Painting replay

The finished image now keeps its making.

GPT-5.6 Luna's phoenix was the strongest completed image in the visual edit. Its saved sketch contains the ordered p5.brush program, so the animation replays actual cumulative drawing passes—ash, tail, wings, body, head, talons, and finishing marks—instead of dissolving between fabricated frames. The renderer captured 81 real passes, selected 16 checkpoints at five frames per second, and holds the finish for two seconds. The retained lossless final checkpoint matches the approved 1200×1200 PNG exactly; the GIF presents its normal palette-encoded rendering.

Phoenix from the ashes developing through successive painted stages
Phoenix from the ashesGPT-5.6 Luna / OpenCode GoOpen GIFProcess record

08 / Complete request record

18 recorded request bodies.

Each collapsed record contains the exact system and user bodies sent by the art project, plus protocol, limits, and temperature.

P01 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Mostly stroke: HB, 2B, pen. Pale wash only for stains and shadow. High contrast. Dry, broken lines. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add 2–5 faint stains or edge darkening so it reads as paper, not a UI canvas.

TASTE
- One clear subject, large on the page. Not a tiny icon in the middle.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

Output only the complete sketch.js source.
P02 / opencode-gogpt-5.6-luna
Protocol
responses
Max tokens
8192
Temperature
1

System

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Mostly stroke: HB, 2B, pen. Pale wash only for stains and shadow. High contrast. Dry, broken lines. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add 2–5 faint stains or edge darkening so it reads as paper, not a UI canvas.

TASTE
- One clear subject, large on the page. Not a tiny icon in the middle.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

Output only the complete sketch.js source.
P03 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
High contrast with dry, broken HB, 2B, and pen lines. Give the subject a decisive dark mass using fill opacity 180–245; reserve pale wash for fog, stains, and shadow. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

Output only the complete sketch.js source.
P04 / opencode-gogpt-5.6-luna
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

Output only the complete sketch.js source.
P05 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

Output only the complete sketch.js source.
P06 / opencode-goqwen3.8-max
Protocol
messages
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
High contrast with dry, broken HB, 2B, and pen lines. Give the subject a decisive dark mass using fill opacity 180–245; reserve pale wash for fog, stains, and shadow. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

Output only the complete sketch.js source.
P07 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

Output only the complete sketch.js source.
P08 / opencode-gogpt-5.6-luna
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

Output only the complete sketch.js source.
P09 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

Output only the complete sketch.js source.
P10 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

Output only the complete sketch.js source.
P11 / opencode-goqwen3.8-max
Protocol
messages
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

Output only the complete sketch.js source.
P12 / opencode-goqwen3.8-max
Protocol
messages
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

Output only the complete sketch.js source.
P13 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one naturalistic hibiscus bloom spanning approximately x=110..475 and y=85..425. Use five overlapping, unequal 7–12-vertex petal contours around a throat near (300, 270); do not use circles for petals. Add one half-open bud near (455, 175), a curved stem descending toward (250, 560), two leaves, and two or three fallen petals in the lower-left third. Put the darkest peach-red and green marks at the throat, stamen, and stem junction. Keep tea stains extremely faint.

Output only the complete sketch.js source.
P14 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a peach hibiscus, half-open bud, fallen petals, tea-stained field journal paper

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1701) and noiseSeed(1701) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one naturalistic hibiscus bloom spanning approximately x=110..475 and y=85..425. Use five overlapping, unequal 7–12-vertex petal contours around a throat near (300, 270); do not use circles for petals. Add one half-open bud near (455, 175), a curved stem descending toward (250, 560), two leaves, and two or three fallen petals in the lower-left third. Put the darkest peach-red and green marks at the throat, stamen, and stem junction. Keep tea stains extremely faint.

Output only the complete sketch.js source.
P15 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
High contrast with dry, broken HB, 2B, and pen lines. Give the subject a decisive dark mass using fill opacity 180–245; reserve pale wash for fog, stains, and shadow. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one large, readable side-view crow spanning approximately x=150..440 and y=135..350, facing left. Build distinct closed contours for head, beak, chest, folded wing, belly, and tail; do not use circles for the body. Run the telephone wire across y=355 and place quiet fog-softened hills only in the lower third. The crow must be the darkest and crispest mass in the image; keep the full beak and tail on-canvas.

Output only the complete sketch.js source.
P16 / openrouterthinkingmachines/inkling
Protocol
chat
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one luna moth with wings spanning approximately x=90..510 and y=100..445 and a narrow body near x=285..315. Use separate closed contours for two forewings and two hindwings, with hindwing tails extending toward y=470; symmetry may be loose but anatomy must read. Place a soft lamplight halo in the upper-right and a dark windowsill across y=510, with only a few quiet garden marks beyond. Keep wing veins sparse and organic. Do not add arbitrary polygons, framing boxes, or circular diagrams.

Output only the complete sketch.js source.
P17 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#f4e8c1");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
High contrast with dry, broken HB, 2B, and pen lines. Give the subject a decisive dark mass using fill opacity 180–245; reserve pale wash for fog, stains, and shadow. Leave large untouched paper.

PAPER
Ground colour is #f4e8c1 (cream). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished ink picture:
a crow on a telephone wire in winter fog, distant hills

Paper: cream (#f4e8c1)
Canvas: 600x600
Call randomSeed(1702) and noiseSeed(1702) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one large, readable side-view crow spanning approximately x=150..440 and y=135..350, facing left. Build distinct closed contours for head, beak, chest, folded wing, belly, and tail; do not use circles for the body. Run the telephone wire across y=355 and place quiet fog-softened hills only in the lower third. The crow must be the darkest and crispest mass in the image; keep the full beak and tail on-canvas.

Output only the complete sketch.js source.
P18 / opencode-gogrok-4.5
Protocol
responses
Max tokens
8192
Temperature
1

System

PROMPT SPEC: taste-v2

You write complete p5.js sketches that PAINT with the p5.brush library.

Return ONLY JavaScript source for sketch.js. No markdown fences. No explanation.

REQUIRED SHAPE (copy this structure):
async function setup() {
  createCanvas(600, 600, WEBGL);
  angleMode(DEGREES);
  brush.scaleBrushes(3);
  noLoop();
}
function draw() {
  translate(-width / 2, -height / 2);
  background("#0c120e");
  // painting
}

HARD RULES
- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.
- That translation changes the visible drawing area to x=0..600, y=0..600. Use those top-left coordinates for every visible mark. Negative coordinates are off-canvas.
- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.
- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.
- Do not invent APIs. If it is not on the allowlist, it does not exist.
- Do not load images, fonts, or files.
- Do not animate. Call noLoop() in setup.
- Do not write HTML, markdown, or the string </script>.
- Every beginShape() must have at least 3 vertex() calls and an endShape().
- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().
- Target 80–220 lines. Dense marks, not verbose comments.

ALLOWLIST — stroke
- brush.set(name, color, weight)
- brush.pick(name)
- brush.stroke(color)
- brush.strokeWeight(weight)
- brush.noStroke()
- brush.line(x1, y1, x2, y2)
- brush.flowLine(x, y, length, dir)

ALLOWLIST — watercolor fill
- brush.fill(color, opacity)          // opacity 0–255
- brush.noFill()
- brush.fillBleed(strength, "in"|"out")  // strength 0–1
- brush.fillTexture(texture, border)     // both 0–1
- brush.circle(x, y, radius, irregularity?)
- brush.rect(x, y, w, h, "corner"|"center")
- brush.beginShape(curvature)
- brush.vertex(x, y)
- brush.endShape(closeBoolean)

ALLOWLIST — hatch / field
- brush.hatch(dist, angle, { rand })
- brush.hatchStyle(name, color, weight)
- brush.noHatch()
- brush.field("hand"|"curved"|"waves"|"seabed"|"spiral")
- brush.noField()

BRUSH NAMES: "2B", "HB", "2H", "pen", "rotring", "marker", "charcoal"
COLOURS: hex strings like "#c06c5a"

MEDIUM
Transparent overlapping washes. Use opacity 45–110 for focal glazes and 12–40 only for atmosphere. bleed 0.12–0.45. Paper must show through. Soft feathered edges. Build the subject from 2–4 stacked glazes, not a hard outline.

PAPER
Ground colour is #0c120e (night). Start with background() of that colour. Add at most 1–3 faint stains inside the visible canvas. Do not draw a decorative border or four-corner vignette.

TASTE
- One clear subject, large on the page: the main silhouette should span roughly 40–70% of the canvas width or height, with its focal point inside the central 80%.
- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.
- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.
- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.
- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.
- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.
- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.
- Limited palette: 3–5 colours plus paper.
- Leave breathing room. Do not fill every pixel.
- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.
- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.
- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.
- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.

User

Paint this as a finished watercolor picture:
a luna moth on a dark windowsill, lamplight, night garden beyond

Paper: night (#0c120e)
Canvas: 600x600
Call randomSeed(1703) and noiseSeed(1703) at the start of setup.

SHARED COMPOSITION BLUEPRINT
Paint one luna moth with wings spanning approximately x=90..510 and y=100..445 and a narrow body near x=285..315. Use separate closed contours for two forewings and two hindwings, with hindwing tails extending toward y=470; symmetry may be loose but anatomy must read. Place a soft lamplight halo in the upper-right and a dark windowsill across y=510, with only a few quiet garden marks beyond. Keep wing veins sparse and organic. Do not add arbitrary polygons, framing boxes, or circular diagrams.

Output only the complete sketch.js source.

09 / Artist-canvas update

The second room now shows its whole experiment.

The artist-canvas study now has ten formal rooms, six prompts per artist, and a frozen ten-model matrix. Its exact sixth prompt is “Draw what you would like to draw. You have full control. Go where your heart desires.” The overnight public-subject ledger covers 75 explicit branches, 128 render artifacts, 79 machine-readable outcome records, and 13 bounded provider/model calls. These artifacts include prototypes, replays, audits, and reference calibrations—not 128 unique paintings. The public experimental archive exposes 127 PNG records with their original review statuses; one collage stays local under its own source-pixel restriction. No new canvas cleared full-resolution editorial review, and the 600-attempt suite was not launched.

10 / Complete-code comparison

The models now author the whole canvas.

The frozen singular-nocturne-v1 round holds the three prompt bodies, 600×600 logical canvas, 3× render scale, gouache medium, and night paper constant. Each model returns the complete p5.js and p5.brush sketch; the local environment validates and renders that source at 1800×1800. It does not supply a fixed scene template, and no image model is used.

The visual edit publishes 12 works across 3 prompts and 6 model authors: 3 editorial selections and 9 comparison studies. GPT-5.6 Luna, both selected Qwen versions, MiniMax M3, and Grok 4.5 ran through OpenCode Go; Inkling ran through OpenRouter. Ox Alpha was run on all three prompts, but one request timed out and two returned endpoint-unavailable errors, so it contributes no public canvas. DeepSeek V4 Flash returned one complete owl source; an extractor fix recovered and rendered that exact saved response without another provider call, but the visual edit rejected it rather than lowering the publication bar.

11 / Complete-code v2

Short prompts, full authorship.

The second round uses ten deliberately short prompts—five dark and five light—so the model has room to author the image. The host supplies only the p5.js and p5.brush interface, validates the returned source, and renders it locally at 1800×1800. There is no image model and no hidden composition template.

203canonical attempts
81exact-prompt SHA-distinct successful canvases
122failures retained in the ledger
16 / 9model routes attempted / producing canvases
45 / 36dark / light successful canvases
19Inkling canvases through OpenRouter

Ox Alpha was attempted on all ten prompts and produced no canvas. Those failures remain part of the experiment record and are not placed in the public gallery. The public exhibition contains successful, SHA-distinct canvases only; it is not a completion count for every requested route.

The selected exhibition keeps the editorial edit. The separate all-works archive exposes every retained, hash-verified, deduplicated canvas from all three rounds in a two-column chronology. The local arena now unites that archive with Tower of Babel and every Biblical Visions alternative: 229 unique canvases in one binary pool. It records immediately when either image is tapped, auto-advances, computes local Elo-style image/model ratings, and exports the vote record locally.

12 / Complete-code v3

More room for the model to make a painting.

The freeform round is complete. It uses no image generator: each model authors a complete p5.js and p5.brush program from a small, open prompt, and the local project renders that program. Twenty-eight prompt bodies cover dark and light grounds, varied canvas shapes, concrete subjects, and an unrestricted final prompt.

201frozen campaign records
99campaign successes
102campaign failures
31 / 13campaign routes attempted / producing canvases
52 / 47campaign dark / light successes
22campaign Inkling successes

That frozen campaign snapshot excludes later recovery, isolated publication rerenders, and one-pass revision attempts. The complete retained export contains 238 attempts: 113 successes, 125 failures, and 23 Inkling successes. Of the 113 successful records, 112 still match both their recorded PNG and source hashes; one overwritten PNG is excluded. Deduplicating exact authored-code rerenders leaves 106 distinct V3 works. Together with 52 distinct earlier works, the public all-works archive contains 158 canvases across 41 prompts and 20 model routes.

Later breadth runs use native-size review renders. A work advances only after visual review; its exact stored provider response is then rerendered in isolation at the prompt's 2400–3000px publication scale without another model call or code rewrite. Preview, parent, and promoted render remain separate, hash-addressed attempts in the ledger. Page-bound canvas readback and exact-dimension checks prevent one concurrent renderer from being attributed to another model.

The visual quality bar is calibrated toward organic asymmetry, vivid but controlled color, transparent layers, irregular linework, one concentrated focal event, and breathing room. Technical validity is not aesthetic approval. The two Inkling routes produced 22 canvases in the frozen campaign ledger; OpenRouter Ox Alpha and DeepSeek V4 Flash produced two each. None placed a work in the four-piece accepted edit, but every verified distinct success now remains visible in the separate all-works research archive instead of being mistaken for an editorial selection.

Four explicit user selections established the positive calibration set: three light-ground Hibiscus works and one dark A royal-blue angel at war. They are not treated as a reusable composition; their shared material and hierarchy qualities guide rejection of repetitive stamps, hard vector cutouts, clipped coding demos, and colorful noise. A private vision-critique experiment gave borderline works one revision by their original author, but no revision cleared the same bar. The accepted edit contains 4 works across 2 prompts and 4 model authors (1 dark / 3 light).

13 / Tower of Babel

One prompt, ten authored visual languages.

The Tower study freezes one short prompt for every route: “Tower of Babel. You have full control. Paint whatever you want; go where your visual instinct leads.” Each model authors the complete executable sketch. The host varies only route, canvas shape, value field, medium family, and seed; it supplies no scene geometry, coordinates, palette, or image-model template.

The search made 35 explicitly assigned calls across 34 distinct model routes. Eighteen produced technically valid high-resolution canvases before the visual edit; empty responses, endpoint failures, quota failures, rate limits, collapsed canvases, and unsafe or over-expanded sketches remain in the private ledger rather than becoming blank public cards. MiMo was excluded from this round by request. DeepSeek V4 Flash and both Inkling routes produced canvases; two Ox Alpha attempts and the Muse Spark call failed and remain attributed as failures.

The dedicated article publishes 10 hash-verified works with model, provider, exact prompt, canvas condition, seed, renderer build, generation identifiers, image/source hashes, full PNG, and authored sketch.js. A vision review may ask the original model author for one complete-source revision, but never replaces its canvas with a shared template.

14 / Biblical Visions

Twelve subjects. Forty-five open canvases.

The dedicated Biblical Visions exhibition now keeps 45 complete-code works across 12 subjects and 16 distinct model routes. Noah, Samuel, Ruth, Moses, Miriam, David, Elijah, Jonah, Daniel, Esther, Abraham, and Jacob each receive a separate horizontal wheel. One editorial selection appears first; every hash-distinct alternative follows beside it. Each prompt gives the agent the same open invitation: “You have full control. Paint whatever you want; go where your visual instinct leads.”

This is a model-authored code study, not an image-model comparison. The exact prompts supply no scene, composition, symbols, geometry, or coordinates. Early rounds also supplied a canvas aspect, paper value, and medium; later pure rounds supplied only an open mixed-media environment. Every published condition and original-author revision is visible in the provenance record. Incomplete and failed attempts, including the unsuccessful DeepSeek V4 Flash Biblical calls, remain privately recorded rather than becoming placeholder cards. DeepSeek V4 Flash did produce successful Tower of Babel work, which remains published separately in the Tower of Babel exhibition and is also in the unified arena.

15 / Cross-exhibition

The archive now has an independent visual edit.

The 100 Model-Authored Paintings exhibition brings 135 retained Scripture, Babel, self-portrait, typographic, and open-studio works into one two-column archive. An independent full-sheet review currently identifies 12 highlights and 99 works in the broader exhibition pool. Technical validity is never promoted as aesthetic success: highlights, accepted works, alternatives, and research rejects remain visibly distinct.

The article opens strongest-first but does not erase the experiment. Every retained work keeps model, provider, prompt, style, tools, dimensions, date, and provenance; every lightbox state has its own shareable ?work= URL. Failed or missing-image attempts stay private instead of becoming public placeholders.

16 / Quality frontier

A new medium has to change the picture.

The newest ateliers remove the old scene scaffold entirely. A model authors either a complete HTML/CSS/SVG document or one complete Canvas2D renderer; the host only blocks network access, validates safety, renders locally, and preserves the exact source and image hashes. The completed portrait archive now contains 17 frontier studies, of which 7 survived native-resolution supervision. Their visual systems include double-strike intaglio, carbon-copy pressure, legal redaction, marginalia anatomy, and faces built from woven remembered words.

The material-function archive adds 16 SHA-distinct canvases. After a second native-resolution cross-medium edit, 1 general painting remains selected, 10 remain visible as research alternatives, one word-built face enters the self-portrait wall, and 4 are held private. Scraped ultramarine wax, misregistered relief ink, woven language, cyanotype, charcoal erasure, ceramic crackle, paper-cut shadow, risograph, sumi wash, and an illuminated page becoming a garden each require a different authored renderer—but naming a medium is not enough when the result still behaves like a vector layout. Two intervening breadth waves produced eight technically valid text portraits and seven technically valid SVG scenes but zero accepted works; they remain private because novelty labels did not become sophisticated pictures. No diffusion or image generator was used.

Three further renderer frontiers were then stopped rather than scaled: real p5.brush produced six native renders, WebGL fragment shaders produced seven, and a cross-medium Canvas2D atelier produced seven. All twenty were reviewed at full size; none entered either the selected wall or the public alternatives. Two Codex-agent studios also painted three typographic systems through nine iterations and three narrative systems through twelve iterations. Those remained private too. Texture, shader complexity, physical-medium labels, and repeated revision did not fix generic masks, repeated pills, stacked bands, stick figures, or vector scenery. The negative result changed the edit: a work advances only when its material process governs a resolved composition.

Machine-readable record

352 successful or selected works are indexed across the gallery manifests.