{
  "experimentId": "2026-08-23-sacred-blue-study",
  "exportedAt": "2026-08-24T04:17:49.458Z",
  "study": {
    "experimentId": "2026-08-23-sacred-blue-study",
    "createdAt": "2026-08-23",
    "promptSpec": "sacred-blue-v10",
    "subjects": [
      {
        "promptId": "royal-blue-biblical-v1",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "directionId": "royal-codex-sacred-v4",
        "medium": "watercolor",
        "paper": "night",
        "seed": 2401
      },
      {
        "promptId": "spiritual-warfare-v1",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "directionId": "spiritual-watch-sacred-v4",
        "medium": "gouache",
        "paper": "night",
        "seed": 2402
      },
      {
        "promptId": "phoenix-ashes-v2",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "directionId": "phoenix-bird-sacred-v5",
        "medium": "gouache",
        "paper": "night",
        "seed": 2403
      },
      {
        "promptId": "good-versus-evil-v1",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "directionId": "two-trees-sacred-v4",
        "medium": "ink",
        "paper": "cream",
        "seed": 2404
      },
      {
        "promptId": "persisting-against-evil-v1",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "directionId": "pilgrim-thorns-sacred-v4",
        "medium": "gouache",
        "paper": "cream",
        "seed": 2405
      },
      {
        "promptId": "stand-for-right-v1",
        "prompt": "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",
        "directionId": "witness-square-sacred-v4",
        "medium": "ink",
        "paper": "cream",
        "seed": 2406
      },
      {
        "promptId": "watchman-at-dawn-v3",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "directionId": "watchman-gate-sacred-v8",
        "medium": "watercolor",
        "paper": "cream",
        "seed": 2407
      },
      {
        "promptId": "lion-and-lamb-v3",
        "prompt": "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",
        "directionId": "lion-lamb-sacred-v7",
        "medium": "watercolor",
        "paper": "cream",
        "seed": 2408
      },
      {
        "promptId": "model-self-portrait-night-v1",
        "prompt": "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",
        "directionId": "model-self-portrait-sacred-v9",
        "medium": "gouache",
        "paper": "night",
        "seed": 2410
      },
      {
        "promptId": "wrestling-at-dawn-night-v1",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "medium": "gouache",
        "paper": "night",
        "seed": 2411
      },
      {
        "promptId": "lions-den-night-v1",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "directionId": "lions-den-sacred-v9",
        "medium": "gouache",
        "paper": "night",
        "seed": 2412
      },
      {
        "promptId": "storm-galilee-night-v1",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "directionId": "storm-galilee-sacred-v9",
        "medium": "watercolor",
        "paper": "night",
        "seed": 2413
      },
      {
        "promptId": "midnight-exodus-night-v1",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "directionId": "midnight-exodus-sacred-v9",
        "medium": "ink",
        "paper": "night",
        "seed": 2414
      },
      {
        "promptId": "light-in-darkness-night-v1",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "directionId": "light-in-darkness-sacred-v9",
        "medium": "watercolor",
        "paper": "night",
        "seed": 2415
      }
    ]
  },
  "baselines": [],
  "reviews": null,
  "promptRequests": [
    {
      "id": "4b55ee164c728eb7",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "cea57d15b6e32a7b",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "dc76ad00f32a216a",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "b3b17bc594f3da33",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "313bbefeae2a1692",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "c279e85d609e9acd",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "0590c0981624e7c6",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a30b7167496d383e",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e8fb4d1d51e0217e",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "09e138874ac7588c",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "818f026e56484927",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a79377bd954f7f8e",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "311c6e37aea1951c",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a977857e4b3bdd54",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2403) and noiseSeed(2403) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "9158e9c75a3711a7",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "65ce4166cfc8fccd",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "864164e489485c15",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "ba3b58587e86a716",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "2e2b1a826b23193a",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5893db0a29455721",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "bb74dd6bf1708641",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "79a5d25789aa1d18",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "9635c9386c024be8",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "82cba721617db6e2",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "3ef23edcae7fd8f6",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "696be2da45d221ef",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "68f12596c95b24e4",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "c0bcf426aa202f7b",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e0913d9d3ec6ef46",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "3485b5be44df3ee3",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "85364a6fc2471096",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "ca91a5b8bb475936",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "afc2671f2f24c750",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "60e61c1b04922fca",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "cf9bd2863c525e54",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a2dfadc17d75ed48",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "9a7012da72705da3",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "34a56eb9c40f0fb4",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "88b1cd3cba42a67d",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "3cf5834ff927f058",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "eb92e53c3b45d190",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "fc7f482fb3510749",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "54717715804720e0",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5833f1d6ba651d43",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "9d97116c42ce7e8f",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "ba3755b30b6fbc4d",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "0c2a9b1319d8cb54",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "fc4bfe2fe45fc58e",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "3d8dbf92afa4f04d",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "de8fad8f3f52e349",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "d92b8d6614cc780d",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "0fcc4e614791f7c9",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5f1a6af55685656e",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "d51a782fce05b804",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v3\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na lone witness in a royal-blue cloak standing upright in a crowded stone square while dark banners bend away, standing for what is right\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2406) and noiseSeed(2406) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a6b8050e4526e932",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\nan open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2401) and noiseSeed(2401) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e668fd732f4bc6b1",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#0c120e\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore\n\nPaper: night (#0c120e)\nCanvas: 600x600\nCall randomSeed(2402) and noiseSeed(2402) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "1474e394382b87b2",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\ntwo ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2404) and noiseSeed(2404) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e9099e3e17b419d4",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\na small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2405) and noiseSeed(2405) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "388df202b33e6f50",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "7efb6d5fc1ddbcd9",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "f2cfb5b11a29fb50",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "c15f9a9ddd51e84c",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5745268a3af2bf56",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "88e1d10db2aa4b04",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "29f8967fcbf658ec",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na 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\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2408) and noiseSeed(2408) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "0d93c7f3574371bc",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "4a639e6fc5111c91",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "97de479497d2eff9",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#f4e8c1\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround 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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage\n\nPaper: cream (#f4e8c1)\nCanvas: 600x600\nCall randomSeed(2407) and noiseSeed(2407) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nOn warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "2783a39d04477986",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "d712b8f2b38a0f57",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "381ad0cc05d28165",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "0ffd29160f1ac96c",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "7e28c07f58ae974b",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "13feb0d31c307111",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "991e68d7236a29a9",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "c86f4dbac09a8750",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "7399a2daea3683c6",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "48214584d20bc2eb",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "c7e40e4b76d960fa",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "18460ff4ab855300",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "831e0525aa0a3561",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "53e7de4aad7b2723",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "56843f79f173ddf9",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "fcb129e5738e8537",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "18593f88d2cabf08",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5ec025f8c65eb8b2",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "fb3cb1a909e623a3",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "d69ad4c5abaaf579",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "dd4f754646aaf2d5",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "23d64a8df7934dfd",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "1bf63b849e0339ab",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "35a6fb984f12b442",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "25ff9d1b226fcbbb",
      "provider": "opencode-go",
      "model": "gpt-5.6-luna",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "f789462a6ca7a2c0",
      "provider": "openrouter",
      "model": "thinkingmachines/inkling",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "f81d9651f954b59c",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "bac1439963f99740",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "23bea13f26ba44d7",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "2f14615613e3a770",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e129d3df5ef49b40",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "d2c05cbb65e44c88",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "8825a5c1bf61e774",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "1c3463396e0429a4",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "ed74952eeb191651",
      "provider": "opencode-go",
      "model": "mimo-v2.5-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 8192,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "24eb5dd0639e1d60",
      "provider": "opencode-go",
      "model": "deepseek-v4-pro",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e968a4dabe9fc71e",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\npaint 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\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2410) and noiseSeed(2410) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nInterpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "1cd47cdf0e2f4fa0",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nJacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2411) and noiseSeed(2411) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e3bf750b07658d03",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nMore opaque fills (110–200). Flat-ish colour fields with light fillTexture. Limited palette. Soft but not watery edges (bleed ≤ 0.15).\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished gouache picture:\nDaniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2412) and noiseSeed(2412) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "56de46df75aed7b2",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "f0f7ebbd92f7ee91",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "8d2a1bba17975743",
      "provider": "opencode-go",
      "model": "deepseek-v4-flash",
      "protocol": "chat",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "418f9196d47fe64d",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "a78a63afe47cc201",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "55a7277ef05e64f5",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "e171746daf8897b5",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nHigh 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.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished ink picture:\na small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2414) and noiseSeed(2414) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "7cc8fc459d2328be",
      "provider": "opencode-go",
      "model": "qwen3.7-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "b20e211f560e9ed3",
      "provider": "opencode-go",
      "model": "grok-4.5",
      "protocol": "responses",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\none small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2415) and noiseSeed(2415) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "5909c51cdfc5ebbb",
      "provider": "opencode-go",
      "model": "minimax-m3",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    },
    {
      "id": "ec5e623e3d4a91ae",
      "provider": "opencode-go",
      "model": "qwen3.8-max",
      "protocol": "messages",
      "system": "PROMPT SPEC: taste-v4\n\nYou write complete p5.js sketches that PAINT with the p5.brush library.\n\nReturn ONLY JavaScript source for sketch.js. No markdown fences. No explanation.\n\nREQUIRED SHAPE (copy this structure):\nasync function setup() {\n  createCanvas(600, 600, WEBGL);\n  angleMode(DEGREES);\n  brush.scaleBrushes(3);\n  noLoop();\n}\nfunction draw() {\n  translate(-width / 2, -height / 2);\n  background(\"#081329\");\n  // painting\n}\n\nHARD RULES\n- Canvas MUST be WEBGL. WEBGL origin is the center; always translate(-width/2, -height/2) before drawing.\n- 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.\n- Paint ONLY with brush.* listed below. Native p5 drawing (ellipse, triangle, line, rect, fill, stroke, bezier, beginShape without brush.) is forbidden for the picture.\n- background(), push(), pop(), translate(), rotate(), random(), noise(), lerp(), map(), dist(), sin(), cos(), color(), lerpColor() are allowed.\n- Do not invent APIs. If it is not on the allowlist, it does not exist.\n- Do not load images, fonts, or files.\n- Do not animate. Call noLoop() in setup.\n- Do not write HTML, markdown, or the string </script>.\n- Every beginShape() must have at least 3 vertex() calls and an endShape().\n- Close filled shapes with brush.endShape(true). Use brush.endShape(false) only after brush.noFill().\n- Target 80–220 lines. Dense marks, not verbose comments.\n\nALLOWLIST — stroke\n- brush.set(name, color, weight)\n- brush.pick(name)\n- brush.stroke(color)\n- brush.strokeWeight(weight)\n- brush.noStroke()\n- brush.line(x1, y1, x2, y2)\n- brush.flowLine(x, y, length, dir)\n\nALLOWLIST — watercolor fill\n- brush.fill(color, opacity)          // opacity 0–255\n- brush.noFill()\n- brush.fillBleed(strength, \"in\"|\"out\")  // strength 0–1\n- brush.fillTexture(texture, border)     // both 0–1\n- brush.circle(x, y, radius, irregularity?)\n- brush.rect(x, y, w, h, \"corner\"|\"center\")\n- brush.beginShape(curvature)\n- brush.vertex(x, y)\n- brush.endShape(closeBoolean)\n\nALLOWLIST — hatch / field\n- brush.hatch(dist, angle, { rand })\n- brush.hatchStyle(name, color, weight)\n- brush.noHatch()\n- brush.field(\"hand\"|\"curved\"|\"waves\"|\"seabed\"|\"spiral\")\n- brush.noField()\n\nBRUSH NAMES: \"2B\", \"HB\", \"2H\", \"pen\", \"rotring\", \"marker\", \"charcoal\"\nCOLOURS: hex strings like \"#c06c5a\"\n\nMEDIUM\nTransparent but pigment-rich overlapping washes. Use opacity 75–140 for focal subject glazes and 12–35 only for atmosphere. Never paint the primary subject solely below opacity 70; stack 2–4 glazes until it reads at thumbnail size. Keep paper visible, use bleed 0.12–0.4, and add one or two restrained charcoal or slate contour accents near the focal point rather than outlining everything.\n\nPAPER\nGround colour is #081329 (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.\n\nTASTE\n- 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%.\n- Make the subject readable at thumbnail size. Establish one decisive silhouette before adding texture.\n- Build a clear value hierarchy: the darkest dark and crispest edge belong near the focal subject; atmosphere and background stay quieter.\n- Prefer 6–16 deliberately placed contour vertices over primitive icons. Use randomness for texture, never for the primary anatomy or silhouette.\n- Use three spatial layers at most: quiet ground/atmosphere, dominant subject, and a small number of accents. Avoid scattered filler marks.\n- Overlap 4–12 organic shapes. Petals, leaves, hills, cloth, birds — built from beginShape vertices, never a perfect regular polygon unless the subject is geometric.\n- Avoid clip-art: no five identical rotated petals as the whole picture, no emoji faces, no symmetric logo flowers.\n- Limited palette: 3–5 colours plus paper.\n- Leave breathing room. Do not fill every pixel.\n- If the subject is a plant, include stem/sepals/stain/shadow, not only the bloom.\n- Irregularity: vary vertex positions, use circle(..., 0.15–0.5), hatch with rand.\n- Composition: subject off dead-center is better than bullseye, but keep the whole focal silhouette on-canvas.\n- Restraint: stop when the image reads. Fewer confident masses are better than many pale, unrelated marks.\n- Symbolic subjects must remain paintings, not advocacy posters: no lettering, slogans, captions, real flags, logos, split-screen morality diagrams, or generic badge compositions.\n- Avoid perfect bilateral symmetry and centered heraldic emblems unless the subject physically requires symmetry. Let weight, weather, and gesture create asymmetry.\n- Human figures need believable head, shoulder, torso, arm, and leg proportions even when simplified; imply faces rather than drawing emoji features.\n- Dark paper still needs separated values. Use midtone and light subject masses against the ground instead of drawing near-black shapes on near-black paper.",
      "user": "Paint this as a finished watercolor picture:\na small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves\n\nPaper: night (#081329)\nCanvas: 600x600\nCall randomSeed(2413) and noiseSeed(2413) at the start of setup.\n\nSHARED COMPOSITION BLUEPRINT\nPaint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.\n\nOutput only the complete sketch.js source.",
      "maxTokens": 12000,
      "temperature": 1,
      "images": 0
    }
  ],
  "attempts": [
    {
      "attemptId": "2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978",
        "createdAt": "2026-08-24T01:56:19.279Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "cea57d15b6e32a7b",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 31120,
          "usage": {
            "prompt_tokens": 1496,
            "completion_tokens": 5583,
            "total_tokens": 7079,
            "cost": 0.02403235,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.02403235,
              "upstream_inference_prompt_cost": 0.0014212,
              "upstream_inference_completions_cost": 0.02261115
            },
            "completion_tokens_details": {
              "reasoning_tokens": 2716,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978/painting.png",
        "projectSource": "sketches/2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978.png",
        "source": "/images/model-painting-study/2026-08-24T01-56-19-b1b4594f-0e27-4c0b-a232-1216ae523978.js.txt",
        "stats": {
          "unique": 563,
          "meanLuma": 22.21383281249961,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "2b05829479e70e8cab7b7f471d25830c114d6fcd9339883ec91ac19651dc8fc2",
          "png": "ce53c47bee080d86686528659ecd155ade2e83b6a806887d82d0b66ea6467f94",
          "raw": "2b05829479e70e8cab7b7f471d25830c114d6fcd9339883ec91ac19651dc8fc2"
        },
        "latencyMs": 31120,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1496,
              "completion_tokens": 5583,
              "total_tokens": 7079,
              "cost": 0.02403235,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.02403235,
                "upstream_inference_prompt_cost": 0.0014212,
                "upstream_inference_completions_cost": 0.02261115
              },
              "completion_tokens_details": {
                "reasoning_tokens": 2716,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 31120
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T01:57:03.075Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 563,
          "meanLuma": 22.21383281249961,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300",
        "createdAt": "2026-08-24T01:57:49.231Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "dc76ad00f32a216a",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 40805,
          "usage": {
            "prompt_tokens": 1487,
            "completion_tokens": 6567,
            "total_tokens": 8054,
            "cost": 0.028009,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.028009,
              "upstream_inference_prompt_cost": 0.00141265,
              "upstream_inference_completions_cost": 0.02659635
            },
            "completion_tokens_details": {
              "reasoning_tokens": 4910,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300/painting.png",
        "projectSource": "sketches/2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300.png",
        "source": "/images/model-painting-study/2026-08-24T01-57-49-5524f483-b5eb-4170-8eb0-5118e6279300.js.txt",
        "stats": {
          "unique": 348,
          "meanLuma": 22.932855642360952,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5eb16eb0043e32684343d1a325730fa08d0441b61cab23e522333fe0ca437ffb",
          "png": "3b02cc70ed34c7f17dbd6bc3bce0a6d2d368e7b131df03c065fc86fbf687a770",
          "raw": "5eb16eb0043e32684343d1a325730fa08d0441b61cab23e522333fe0ca437ffb"
        },
        "latencyMs": 40805,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1487,
              "completion_tokens": 6567,
              "total_tokens": 8054,
              "cost": 0.028009,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.028009,
                "upstream_inference_prompt_cost": 0.00141265,
                "upstream_inference_completions_cost": 0.02659635
              },
              "completion_tokens_details": {
                "reasoning_tokens": 4910,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 40805
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T01:58:40.841Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 348,
          "meanLuma": 22.932855642360952,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b",
        "createdAt": "2026-08-24T01:58:24.594Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "b3b17bc594f3da33",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 31951,
          "usage": {
            "input_tokens": 1504,
            "output_tokens": 5108,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b/painting.png",
        "projectSource": "sketches/2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b.png",
        "source": "/images/model-painting-study/2026-08-24T01-58-24-c08cff70-382a-4d37-90c5-726e6ba6608b.js.txt",
        "stats": {
          "unique": 857,
          "meanLuma": 21.452897222222877,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "fa6fc60d7dc30d25c6d7b6ad87a81f9588db7085dc17890db66089dd983b3cc7",
          "png": "3c48d7f96cefa60f280b53e04c092f37c7bed75d99d2d542186e88a7dec95eb2",
          "raw": "fa6fc60d7dc30d25c6d7b6ad87a81f9588db7085dc17890db66089dd983b3cc7"
        },
        "latencyMs": 31951,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1504,
              "output_tokens": 5108,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 31951
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T01:59:26.959Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 857,
          "meanLuma": 21.452897222222877,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d",
        "createdAt": "2026-08-24T01:58:40.843Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "313bbefeae2a1692",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 13112,
          "usage": {
            "prompt_tokens": 1447,
            "completion_tokens": 3341,
            "total_tokens": 4788,
            "cost": 0.01497805,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.01497805,
              "upstream_inference_prompt_cost": 0.001447,
              "upstream_inference_completions_cost": 0.01353105
            },
            "completion_tokens_details": {
              "reasoning_tokens": 786,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d/painting.png",
        "projectSource": "sketches/2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d.png",
        "source": "/images/model-painting-study/2026-08-24T01-58-40-a8820619-46ce-4f83-b951-835795c0b64d.js.txt",
        "stats": {
          "unique": 292,
          "meanLuma": 18.174913628471884,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5f2ef70bc0c122fc609720e4def1b86e0f91a73731ab31824254b05ef02f2147",
          "png": "651d5bd340fc733894e9c9ef9ff7373f6a2e7c0cdbb9babb4b9b6416e3b6456c",
          "raw": "5f2ef70bc0c122fc609720e4def1b86e0f91a73731ab31824254b05ef02f2147"
        },
        "latencyMs": 13112,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1447,
              "completion_tokens": 3341,
              "total_tokens": 4788,
              "cost": 0.01497805,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.01497805,
                "upstream_inference_prompt_cost": 0.001447,
                "upstream_inference_completions_cost": 0.01353105
              },
              "completion_tokens_details": {
                "reasoning_tokens": 786,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 13112
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T01:59:10.507Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 292,
          "meanLuma": 18.174913628471884,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116",
        "createdAt": "2026-08-24T01:59:10.509Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "c279e85d609e9acd",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 14543,
          "usage": {
            "prompt_tokens": 1472,
            "completion_tokens": 2184,
            "total_tokens": 3656,
            "cost": 0.0103172,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0103172,
              "upstream_inference_prompt_cost": 0.001472,
              "upstream_inference_completions_cost": 0.0088452
            },
            "completion_tokens_details": {
              "reasoning_tokens": 563,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116/painting.png",
        "projectSource": "sketches/2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116.png",
        "source": "/images/model-painting-study/2026-08-24T01-59-10-c1699556-667a-4686-81e9-53b589a20116.js.txt",
        "stats": {
          "unique": 600,
          "meanLuma": 202.18270156250315,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "0ae7702b891acab75cb3ba7509e4e9f90f5051a460ee39acb156f59e0da37525",
          "png": "a5b53c168a80b396bac2d1fb3a7f7a7fd93109e96f5c9e59c288e5313e7c4416",
          "raw": "0ae7702b891acab75cb3ba7509e4e9f90f5051a460ee39acb156f59e0da37525"
        },
        "latencyMs": 14543,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1472,
              "completion_tokens": 2184,
              "total_tokens": 3656,
              "cost": 0.0103172,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0103172,
                "upstream_inference_prompt_cost": 0.001472,
                "upstream_inference_completions_cost": 0.0088452
              },
              "completion_tokens_details": {
                "reasoning_tokens": 563,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 14543
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T01:59:35.767Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 600,
          "meanLuma": 202.18270156250315,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890",
        "createdAt": "2026-08-24T01:59:26.962Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "0590c0981624e7c6",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 155938,
          "usage": {
            "prompt_tokens": 1617,
            "completion_tokens": 8192,
            "total_tokens": 9809,
            "prompt_cache_hit_tokens": 1280,
            "prompt_cache_miss_tokens": 337,
            "prompt_tokens_details": {
              "cached_tokens": 1280
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 154691,
          "usage": {
            "prompt_tokens": 1790,
            "completion_tokens": 8192,
            "total_tokens": 9982,
            "prompt_cache_hit_tokens": 1280,
            "prompt_cache_miss_tokens": 510,
            "prompt_tokens_details": {
              "cached_tokens": 1280
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 68059,
          "usage": {
            "prompt_tokens": 8895,
            "completion_tokens": 5352,
            "total_tokens": 14247,
            "prompt_cache_hit_tokens": 1280,
            "prompt_cache_miss_tokens": 7615,
            "prompt_tokens_details": {
              "cached_tokens": 1280
            },
            "completion_tokens_details": {
              "reasoning_tokens": 2721
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890/painting.png",
        "projectSource": "sketches/2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890.png",
        "source": "/images/model-painting-study/2026-08-24T01-59-26-2188e4a3-c6e2-414c-b426-2a237f675890.js.txt",
        "stats": {
          "unique": 793,
          "meanLuma": 32.97366362847179,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "82fea959fed849f1c0eb656db1cbebc9ad972ba1f49a94c3278ff997b70e356b",
          "png": "2d9497f982e3118338dd85f4614850f396a2ea8c0c83b8964d6377bc1d5b6276",
          "raw": "aa35083aeee54d2bda6afea89ac7f6a2708372d8de3d0d1776d88a7e6c345113"
        },
        "latencyMs": 378688,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1617,
              "completion_tokens": 8192,
              "total_tokens": 9809,
              "prompt_cache_hit_tokens": 1280,
              "prompt_cache_miss_tokens": 337,
              "prompt_tokens_details": {
                "cached_tokens": 1280
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1790,
              "completion_tokens": 8192,
              "total_tokens": 9982,
              "prompt_cache_hit_tokens": 1280,
              "prompt_cache_miss_tokens": 510,
              "prompt_tokens_details": {
                "cached_tokens": 1280
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 8895,
              "completion_tokens": 5352,
              "total_tokens": 14247,
              "prompt_cache_hit_tokens": 1280,
              "prompt_cache_miss_tokens": 7615,
              "prompt_tokens_details": {
                "cached_tokens": 1280
              },
              "completion_tokens_details": {
                "reasoning_tokens": 2721
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 155938
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 154691
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 68059
          }
        ]
      },
      "failure": null,
      "eventCount": 5,
      "lastEvent": {
        "at": "2026-08-24T02:05:56.459Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 793,
          "meanLuma": 32.97366362847179,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55",
        "createdAt": "2026-08-24T01:59:35.769Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a30b7167496d383e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 34373,
          "usage": {
            "prompt_tokens": 1445,
            "completion_tokens": 5102,
            "total_tokens": 6547,
            "cost": 0.0221081,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0221081,
              "upstream_inference_prompt_cost": 0.001445,
              "upstream_inference_completions_cost": 0.0206631
            },
            "completion_tokens_details": {
              "reasoning_tokens": 3700,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55/painting.png",
        "projectSource": "sketches/2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55.png",
        "source": "/images/model-painting-study/2026-08-24T01-59-35-b0ccd377-3c7f-4dcc-ab64-3ce323e5ac55.js.txt",
        "stats": {
          "unique": 466,
          "meanLuma": 204.77732048611432,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "fe783c64e85fa90f8f5518c37f170a56b87bcf15a7b10314e717d71cdcb6d6d6",
          "png": "47792daff2cb1e0e64817647598820dc4173afe070846ea575dccd4febce95c9",
          "raw": "fe783c64e85fa90f8f5518c37f170a56b87bcf15a7b10314e717d71cdcb6d6d6"
        },
        "latencyMs": 34373,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1445,
              "completion_tokens": 5102,
              "total_tokens": 6547,
              "cost": 0.0221081,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0221081,
                "upstream_inference_prompt_cost": 0.001445,
                "upstream_inference_completions_cost": 0.0206631
              },
              "completion_tokens_details": {
                "reasoning_tokens": 3700,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 34373
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:00:24.525Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 466,
          "meanLuma": 204.77732048611432,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80",
        "createdAt": "2026-08-24T02:00:24.533Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e8fb4d1d51e0217e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 53432,
          "usage": {
            "prompt_tokens": 1445,
            "completion_tokens": 8192,
            "total_tokens": 9637,
            "cost": 0.0346226,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0346226,
              "upstream_inference_prompt_cost": 0.001445,
              "upstream_inference_completions_cost": 0.0331776
            },
            "completion_tokens_details": {
              "reasoning_tokens": 7659,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 32310,
          "usage": {
            "prompt_tokens": 1997,
            "completion_tokens": 5875,
            "total_tokens": 7872,
            "cost": 0.0256909,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0256909,
              "upstream_inference_prompt_cost": 0.00189715,
              "upstream_inference_completions_cost": 0.02379375
            },
            "completion_tokens_details": {
              "reasoning_tokens": 3428,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80/painting.png",
        "projectSource": "sketches/2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80.png",
        "source": "/images/model-painting-study/2026-08-24T02-00-24-d2a8acae-d04c-44ee-93c7-8e9a6042cd80.js.txt",
        "stats": {
          "unique": 481,
          "meanLuma": 213.0226670138917,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "2464e6dc1970d97a97d3247c2e34becc1e08b3deabd4919a15bd32c99f7af9c7",
          "png": "9e1f0c46281e0c6ec46333566165d1cbe423b7456b80cb84b2df3c511c8d7656",
          "raw": "3a3d7fd8109df5ec63903a0c1b7a003891c00c63e278ab84c70abe77db4b6cf8"
        },
        "latencyMs": 85742,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1445,
              "completion_tokens": 8192,
              "total_tokens": 9637,
              "cost": 0.0346226,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0346226,
                "upstream_inference_prompt_cost": 0.001445,
                "upstream_inference_completions_cost": 0.0331776
              },
              "completion_tokens_details": {
                "reasoning_tokens": 7659,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1997,
              "completion_tokens": 5875,
              "total_tokens": 7872,
              "cost": 0.0256909,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0256909,
                "upstream_inference_prompt_cost": 0.00189715,
                "upstream_inference_completions_cost": 0.02379375
              },
              "completion_tokens_details": {
                "reasoning_tokens": 3428,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 53432
          },
          {
            "stage": "repair",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 32310
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:02:04.884Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 481,
          "meanLuma": 213.0226670138917,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab",
        "createdAt": "2026-08-24T02:02:18.583Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "09e138874ac7588c",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 58207,
          "usage": {
            "input_tokens": 1827,
            "output_tokens": 4391,
            "total_tokens": 6218,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 43
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab/painting.png",
        "projectSource": "sketches/2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab.png",
        "source": "/images/model-painting-study/2026-08-24T02-02-18-5b55377a-146a-4fa5-8579-ef6b78a03fab.js.txt",
        "stats": {
          "unique": 391,
          "meanLuma": 21.761715798610485,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "32b8155281e9f2fde14a0188c7ae792c2f478748080040314c272ce50829f70d",
          "png": "6bde3d5606d54ee39943a967d19d9d143d9b01f06164c3482578c31aa60fbdc0",
          "raw": "32b8155281e9f2fde14a0188c7ae792c2f478748080040314c272ce50829f70d"
        },
        "latencyMs": 58207,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1827,
              "output_tokens": 4391,
              "total_tokens": 6218,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 43
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 58207
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:03:35.604Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 391,
          "meanLuma": 21.761715798610485,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c",
        "createdAt": "2026-08-24T02:03:35.606Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "818f026e56484927",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 32271,
          "usage": {
            "input_tokens": 1485,
            "output_tokens": 3505,
            "total_tokens": 4990,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1482
            },
            "output_tokens_details": {
              "reasoning_tokens": 860
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 29378,
          "usage": {
            "input_tokens": 4146,
            "output_tokens": 3126,
            "total_tokens": 7272,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 4143
            },
            "output_tokens_details": {
              "reasoning_tokens": 388
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c/painting.png",
        "projectSource": "sketches/2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c.png",
        "source": "/images/model-painting-study/2026-08-24T02-03-35-51097715-a21b-4276-bcd8-b71d4b30377c.js.txt",
        "stats": {
          "unique": 583,
          "meanLuma": 27.196692621527102,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "393e91129de451055f4eb315adb0b51542ff6df49f1af9d6d436dd76bc6e8105",
          "png": "4ef7673b1d6181e4a4d9bdc42460a995f679ea53ee5ddd121d22fa703fbb127e",
          "raw": "202c0150734b902cd94a24c4faa8c123489be67ce67b3fd02b28a19a3c1bfe75"
        },
        "latencyMs": 61649,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1485,
              "output_tokens": 3505,
              "total_tokens": 4990,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1482
              },
              "output_tokens_details": {
                "reasoning_tokens": 860
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "input_tokens": 4146,
              "output_tokens": 3126,
              "total_tokens": 7272,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 4143
              },
              "output_tokens_details": {
                "reasoning_tokens": 388
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 32271
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 29378
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:04:47.488Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 583,
          "meanLuma": 27.196692621527102,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4",
        "createdAt": "2026-08-24T02:05:56.461Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a79377bd954f7f8e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 37026,
          "usage": {
            "input_tokens": 1636,
            "output_tokens": 2336,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4/painting.png",
        "projectSource": "sketches/2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4.png",
        "source": "/images/model-painting-study/2026-08-24T02-05-56-28f9f692-74ef-4164-ac4c-d7d773f5f4f4.js.txt",
        "stats": {
          "unique": 616,
          "meanLuma": 28.24602994791588,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "97d86a24ab2c2ee056e077d124f128ca71b4a3e7fe64ab12a0d7416d710951d5",
          "png": "beb83da176ccb4080158b792a921b96b3cc0700329ebeef2a4d8351afee760e6",
          "raw": "97d86a24ab2c2ee056e077d124f128ca71b4a3e7fe64ab12a0d7416d710951d5"
        },
        "latencyMs": 37026,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1636,
              "output_tokens": 2336,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 37026
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:06:45.549Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 616,
          "meanLuma": 28.24602994791588,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166",
        "createdAt": "2026-08-24T02:06:45.551Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "311c6e37aea1951c",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 23029,
          "usage": {
            "input_tokens": 1636,
            "output_tokens": 2153,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166/painting.png",
        "projectSource": "sketches/2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166.png",
        "source": "/images/model-painting-study/2026-08-24T02-06-45-26034581-31bf-41fe-8cbd-0549accf3166.js.txt",
        "stats": {
          "unique": 539,
          "meanLuma": 28.185072048610575,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "fcdb4ac44b47749384b0bd99c7380bcb7aed8d51774ffdbc26884d46eb2dacf2",
          "png": "66a585abce202e632652deeec55d92e1a070fccc26649382109f56dbb5ef6fd6",
          "raw": "fcdb4ac44b47749384b0bd99c7380bcb7aed8d51774ffdbc26884d46eb2dacf2"
        },
        "latencyMs": 23029,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1636,
              "output_tokens": 2153,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 23029
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:07:17.558Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 539,
          "meanLuma": 28.185072048610575,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063",
        "createdAt": "2026-08-24T02:07:17.560Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a977857e4b3bdd54",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 81130,
          "usage": {
            "prompt_tokens": 1617,
            "completion_tokens": 9303,
            "total_tokens": 10920,
            "prompt_tokens_details": {}
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063/painting.png",
        "projectSource": "sketches/2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063.png",
        "source": "/images/model-painting-study/2026-08-24T02-07-17-fdc612a8-81d0-4b93-a144-8d2ef462f063.js.txt",
        "stats": {
          "unique": 740,
          "meanLuma": 28.536033940971794,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "fe5201bc8ff717461134a3ce5dc674a9db79f34fb6d4e2fda9debf1e92c02668",
          "png": "98a10a02287cdb7c4457149a47892f561a73e3202527741d0426b45be45409a9",
          "raw": "86adf0679606618837fc08fb3f0d40582cd42a42407d6b7a70e55c168625f93d"
        },
        "latencyMs": 81130,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1617,
              "completion_tokens": 9303,
              "total_tokens": 10920,
              "prompt_tokens_details": {}
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 81130
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:08:49.081Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 740,
          "meanLuma": 28.536033940971794,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033",
        "createdAt": "2026-08-24T02:07:31.400Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "65ce4166cfc8fccd",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 50173,
          "usage": {
            "input_tokens": 1815,
            "output_tokens": 3613,
            "total_tokens": 5428,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 52
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033/painting.png",
        "projectSource": "sketches/2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033.png",
        "source": "/images/model-painting-study/2026-08-24T02-07-31-5f8b282e-aa8a-4620-83e6-f93baf1ea033.js.txt",
        "stats": {
          "unique": 512,
          "meanLuma": 25.269298263888505,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e3aba4da3231a949a0ba94da5c00880ab7e394bb8a457836a4876b6e0ae198da",
          "png": "a302d2da9ff541259bd9fe1b9cae4cb95d93cd30b387989d5b011c22c1fcc300",
          "raw": "e3aba4da3231a949a0ba94da5c00880ab7e394bb8a457836a4876b6e0ae198da"
        },
        "latencyMs": 50173,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1815,
              "output_tokens": 3613,
              "total_tokens": 5428,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 52
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 50173
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:08:47.579Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 512,
          "meanLuma": 25.269298263888505,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6",
        "createdAt": "2026-08-24T02:07:31.400Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "864164e489485c15",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 34340,
          "usage": {
            "input_tokens": 1628,
            "output_tokens": 2467
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6/painting.png",
        "projectSource": "sketches/2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6.png",
        "source": "/images/model-painting-study/2026-08-24T02-07-31-ecfe8ac4-2576-4216-86f8-31059fc684b6.js.txt",
        "stats": {
          "unique": 541,
          "meanLuma": 24.258839236110784,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "bad94c694acd9b8fed7fc70d60afb73b8b3726ababa3ccc26d0c33c8ee34baf8",
          "png": "2d5dfaa297f6dbf088b58f200e09efde69605b24976b24e6d903558fa156aeb8",
          "raw": "bad94c694acd9b8fed7fc70d60afb73b8b3726ababa3ccc26d0c33c8ee34baf8"
        },
        "latencyMs": 34340,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1628,
              "output_tokens": 2467
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 34340
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:08:23.563Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 541,
          "meanLuma": 24.258839236110784,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76",
        "createdAt": "2026-08-24T02:07:31.421Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "9158e9c75a3711a7",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 27754,
          "usage": {
            "input_tokens": 1620,
            "output_tokens": 1903,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76/painting.png",
        "projectSource": "sketches/2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76.png",
        "source": "/images/model-painting-study/2026-08-24T02-07-31-16e742ef-533b-4ca4-b2fd-d60e2063cc76.js.txt",
        "stats": {
          "unique": 523,
          "meanLuma": 28.277866579860845,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "c16800c48a88a320770c601d14d93936a9d9b700fa1b6a9e9be003f629d104ee",
          "png": "3cf3e05553790c96b8326e8780bebe42a8e246d145e10d0628c832efaef0b263",
          "raw": "c16800c48a88a320770c601d14d93936a9d9b700fa1b6a9e9be003f629d104ee"
        },
        "latencyMs": 27754,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1620,
              "output_tokens": 1903,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 27754
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:08:15.875Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 523,
          "meanLuma": 28.277866579860845,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9",
        "createdAt": "2026-08-24T02:08:15.886Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "ba3b58587e86a716",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 27020,
          "usage": {
            "input_tokens": 1566,
            "output_tokens": 1807,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9/painting.png",
        "projectSource": "sketches/2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9.png",
        "source": "/images/model-painting-study/2026-08-24T02-08-15-3964f31c-8949-4be2-bfa8-66ed8341e1c9.js.txt",
        "stats": {
          "unique": 367,
          "meanLuma": 22.30783055555561,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "df6666dca53dd6d1f8b01ef568ce79cfe2a689f4ebf0353756202324f97922a7",
          "png": "10a10e39b74e88ef875694166dbaf35dac70b4e21e28e5f4cea3453a326c1c1b",
          "raw": "df6666dca53dd6d1f8b01ef568ce79cfe2a689f4ebf0353756202324f97922a7"
        },
        "latencyMs": 27020,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1566,
              "output_tokens": 1807,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 27020
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:08:51.308Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 367,
          "meanLuma": 22.30783055555561,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1",
        "createdAt": "2026-08-24T02:08:23.574Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "2e2b1a826b23193a",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 28046,
          "usage": {
            "input_tokens": 1453,
            "output_tokens": 3831,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1/painting.png",
        "projectSource": "sketches/2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1.png",
        "source": "/images/model-painting-study/2026-08-24T02-08-23-8510cb8d-09ba-48e3-93f9-ac1f76c75bb1.js.txt",
        "stats": {
          "unique": 535,
          "meanLuma": 19.26838506944385,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "74cb243faccae5600bcbdbda6022f26bf22b0a0bc43eff10ecb825a194266125",
          "png": "686531dab3534655101991f7177c5de18e79730fcb695ed4477a825c5a472763",
          "raw": "74cb243faccae5600bcbdbda6022f26bf22b0a0bc43eff10ecb825a194266125"
        },
        "latencyMs": 28046,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1453,
              "output_tokens": 3831,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 28046
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:09:06.009Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 535,
          "meanLuma": 19.26838506944385,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8",
        "createdAt": "2026-08-24T02:08:47.591Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5893db0a29455721",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 57751,
          "usage": {
            "input_tokens": 1778,
            "output_tokens": 4040,
            "total_tokens": 5818,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 188
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8/painting.png",
        "projectSource": "sketches/2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8.png",
        "source": "/images/model-painting-study/2026-08-24T02-08-47-a9e6da62-5bbd-47f3-92b0-6f637346a4d8.js.txt",
        "stats": {
          "unique": 229,
          "meanLuma": 19.055032291666237,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "95f994f50db920bdd506a2b2eecb5359eb8381567429ab8b5cd4f8e6281eb4ab",
          "png": "0b06ca010e5db09dd4cb9c21bb60b9a4f919e73f019c999581f2bd49db7284bb",
          "raw": "95f994f50db920bdd506a2b2eecb5359eb8381567429ab8b5cd4f8e6281eb4ab"
        },
        "latencyMs": 57751,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1778,
              "output_tokens": 4040,
              "total_tokens": 5818,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 188
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 57751
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:10:05.973Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 229,
          "meanLuma": 19.055032291666237,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea",
        "createdAt": "2026-08-24T02:08:51.310Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "bb74dd6bf1708641",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 37368,
          "usage": {
            "input_tokens": 1597,
            "output_tokens": 2265,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea/painting.png",
        "projectSource": "sketches/2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea.png",
        "source": "/images/model-painting-study/2026-08-24T02-08-51-935ce077-0ab4-4b48-9e0f-ed97d88321ea.js.txt",
        "stats": {
          "unique": 640,
          "meanLuma": 209.1623412326412,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "d24ee7dbe5b1553687d183c0cb075cf09096f1bb0a20a8128b78c798aa7af253",
          "png": "66d7384bb82b747feb09f20188cf09e68482c7b61a6e4251a515c8d50ee51b3c",
          "raw": "d24ee7dbe5b1553687d183c0cb075cf09096f1bb0a20a8128b78c798aa7af253"
        },
        "latencyMs": 37368,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1597,
              "output_tokens": 2265,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 37368
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:09:40.816Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 640,
          "meanLuma": 209.1623412326412,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076",
        "createdAt": "2026-08-24T02:09:06.012Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "79a5d25789aa1d18",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 30981,
          "usage": {
            "input_tokens": 1478,
            "output_tokens": 4188,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076/painting.png",
        "projectSource": "sketches/2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076.png",
        "source": "/images/model-painting-study/2026-08-24T02-09-06-36bb791a-97c9-4203-840e-e97420dea076.js.txt",
        "stats": {
          "unique": 709,
          "meanLuma": 210.25881067708542,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8bfaa6e66b8f0386c7d453b912c7c29875b544527c7a3bdea45cd87457f2e15a",
          "png": "3882a68ef4511dd379a98bfdbe8d43f65412a5dc1cbcb9bb42d878eb588e94e0",
          "raw": "8bfaa6e66b8f0386c7d453b912c7c29875b544527c7a3bdea45cd87457f2e15a"
        },
        "latencyMs": 30981,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1478,
              "output_tokens": 4188,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 30981
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:09:48.288Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 709,
          "meanLuma": 210.25881067708542,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68",
        "createdAt": "2026-08-24T02:09:40.818Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "9635c9386c024be8",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 36560,
          "usage": {
            "input_tokens": 1567,
            "output_tokens": 2256,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68/painting.png",
        "projectSource": "sketches/2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68.png",
        "source": "/images/model-painting-study/2026-08-24T02-09-40-0e01d222-f9c7-4f9d-9069-d1ddbde39d68.js.txt",
        "stats": {
          "unique": 275,
          "meanLuma": 218.0115064236143,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "1f7516a40932d474b6a1eabe33050e8534e9d555743d6cb76dcd6e664bd36f70",
          "png": "ffcd70b7098c4551e66d68eb79b75274593d60813585adb13e27950e05d2cff4",
          "raw": "1f7516a40932d474b6a1eabe33050e8534e9d555743d6cb76dcd6e664bd36f70"
        },
        "latencyMs": 36560,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1567,
              "output_tokens": 2256,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 36560
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:10:22.506Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 275,
          "meanLuma": 218.0115064236143,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65",
        "createdAt": "2026-08-24T02:09:48.290Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "82cba721617db6e2",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 51898,
          "usage": {
            "input_tokens": 1455,
            "output_tokens": 3725,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 128
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65/painting.png",
        "projectSource": "sketches/2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65.png",
        "source": "/images/model-painting-study/2026-08-24T02-09-48-45ee0e3b-2536-4c38-99d5-f90914961e65.js.txt",
        "stats": {
          "unique": 939,
          "meanLuma": 123.0717870659746,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "f61b4bd27da8e1b3ba56709b43d684690f8deb80856b1e98e1d96550fda95186",
          "png": "7d063685f79325c98ae340b2810943e6117a1cc93172ad5af065d09c8ce5bb97",
          "raw": "f61b4bd27da8e1b3ba56709b43d684690f8deb80856b1e98e1d96550fda95186"
        },
        "latencyMs": 51898,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1455,
              "output_tokens": 3725,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 128
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 51898
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:10:57.257Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 939,
          "meanLuma": 123.0717870659746,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9",
        "createdAt": "2026-08-24T02:10:05.975Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "3ef23edcae7fd8f6",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 64253,
          "usage": {
            "input_tokens": 1802,
            "output_tokens": 4633,
            "total_tokens": 6435,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 69
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9/painting.png",
        "projectSource": "sketches/2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9.png",
        "source": "/images/model-painting-study/2026-08-24T02-10-05-2c0e3156-7a5f-4eab-ab57-fb9fda2c5ee9.js.txt",
        "stats": {
          "unique": 739,
          "meanLuma": 210.30557656250232,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5e14c64d05736cf327f537564af68e94dd535ca0bfe722bfbf27fe70dc16677a",
          "png": "d5aa28441102a5ace8f5d6f48cf126507b84d377d8a60fc7ef1129772065649c",
          "raw": "5e14c64d05736cf327f537564af68e94dd535ca0bfe722bfbf27fe70dc16677a"
        },
        "latencyMs": 64253,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1802,
              "output_tokens": 4633,
              "total_tokens": 6435,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 69
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 64253
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:11:54.853Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 739,
          "meanLuma": 210.30557656250232,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12",
        "createdAt": "2026-08-24T02:10:22.508Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "696be2da45d221ef",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 34147,
          "usage": {
            "input_tokens": 1551,
            "output_tokens": 2103,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12/painting.png",
        "projectSource": "sketches/2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12.png",
        "source": "/images/model-painting-study/2026-08-24T02-10-22-70f550f4-cac3-4ae0-af23-e5c5d8ea2f12.js.txt",
        "stats": {
          "unique": 863,
          "meanLuma": 192.11258098958365,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "cd12d03f1ea1265c80f2c39744d5e246e4c2488acd501ca03e968d5a2d13f8d2",
          "png": "319c220b55edc135caea4b086cd77f22c8d9680399c0475ed2e6e3e35ffa261c",
          "raw": "cd12d03f1ea1265c80f2c39744d5e246e4c2488acd501ca03e968d5a2d13f8d2"
        },
        "latencyMs": 34147,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1551,
              "output_tokens": 2103,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 34147
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:11:38.352Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 863,
          "meanLuma": 192.11258098958365,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339",
        "createdAt": "2026-08-24T02:10:57.259Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "68f12596c95b24e4",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 26224,
          "usage": {
            "input_tokens": 234,
            "output_tokens": 3329,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1352
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339/painting.png",
        "projectSource": "sketches/2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339.png",
        "source": "/images/model-painting-study/2026-08-24T02-10-57-8767afb2-e8bc-42f3-937a-7a502498e339.js.txt",
        "stats": {
          "unique": 529,
          "meanLuma": 216.2853456597245,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e95d5d304fe5810717fc79699c3989711851d15b1385e3aea3f26c5b131791f7",
          "png": "9ce6e030d6ef2907636bc4202408f1aa26943ddaf8b84de9e6fcede0c44386b3",
          "raw": "e95d5d304fe5810717fc79699c3989711851d15b1385e3aea3f26c5b131791f7"
        },
        "latencyMs": 26224,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 234,
              "output_tokens": 3329,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1352
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 26224
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:12:24.317Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 529,
          "meanLuma": 216.2853456597245,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d",
        "createdAt": "2026-08-24T02:11:03.766Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "c0bcf426aa202f7b",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 25177,
          "usage": {
            "input_tokens": 1620,
            "output_tokens": 2205,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d/painting.png",
        "projectSource": "sketches/2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d.png",
        "source": "/images/model-painting-study/2026-08-24T02-11-03-49f5c024-4711-4ea9-a9c8-bc9c8a0bdd9d.js.txt",
        "stats": {
          "unique": 505,
          "meanLuma": 24.780601041666344,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "768b11b0a45a781eb973e1de1967ecf60cb1c6db341edb2a114b6a4311cd2221",
          "png": "1b40cb4c2af2ca7152000d064a0aa09d03f73e36873ee8775f80ab635934193d",
          "raw": "768b11b0a45a781eb973e1de1967ecf60cb1c6db341edb2a114b6a4311cd2221"
        },
        "latencyMs": 25177,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1620,
              "output_tokens": 2205,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 25177
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:11:51.226Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 505,
          "meanLuma": 24.780601041666344,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2",
        "createdAt": "2026-08-24T02:11:09.681Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e0913d9d3ec6ef46",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 134621,
          "usage": {
            "prompt_tokens": 1550,
            "completion_tokens": 8192,
            "total_tokens": 9742,
            "prompt_tokens_details": {
              "cached_tokens": 512
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2/painting.png",
        "projectSource": "sketches/2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2.png",
        "source": "/images/model-painting-study/2026-08-24T02-11-09-64e97ae0-39a3-4577-a3c6-fc79895b53b2.js.txt",
        "stats": {
          "unique": 496,
          "meanLuma": 25.726925520833007,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "f09e133a2c660f915cf35a63f2166cfd10be1b7e4e2b3371158483706b6a2efe",
          "png": "e1d557580e1366e768c101c8850f997a0f95ded5b950261f429d1a411836dc19",
          "raw": "c1bbce17d4d266529f6e1fc86966f13abe07bec05679818f19263ab21eaede16"
        },
        "latencyMs": 134621,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1550,
              "completion_tokens": 8192,
              "total_tokens": 9742,
              "prompt_tokens_details": {
                "cached_tokens": 512
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 134621
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:13:42.951Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 496,
          "meanLuma": 25.726925520833007,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d",
        "createdAt": "2026-08-24T02:11:51.239Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "3485b5be44df3ee3",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 28881,
          "usage": {
            "input_tokens": 542,
            "output_tokens": 2818,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d/painting.png",
        "projectSource": "sketches/2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d.png",
        "source": "/images/model-painting-study/2026-08-24T02-11-51-f486356b-feed-48e8-9be6-5d8ecd42219d.js.txt",
        "stats": {
          "unique": 538,
          "meanLuma": 23.38092517361105,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "9a2aea6e3f074aa2aecd10df48400fbaa131ba4072e952947676d5e0c312c77d",
          "png": "f07611195968381ec66285f3bf30c8c293e39e32e6c75bb81e3d8f1d3208ec61",
          "raw": "9a2aea6e3f074aa2aecd10df48400fbaa131ba4072e952947676d5e0c312c77d"
        },
        "latencyMs": 28881,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 542,
              "output_tokens": 2818,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 28881
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:12:32.255Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 538,
          "meanLuma": 23.38092517361105,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec",
        "createdAt": "2026-08-24T02:11:54.855Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "85364a6fc2471096",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 61707,
          "usage": {
            "input_tokens": 1778,
            "output_tokens": 4803,
            "total_tokens": 6581,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 314
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec/painting.png",
        "projectSource": "sketches/2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec.png",
        "source": "/images/model-painting-study/2026-08-24T02-11-54-cc603e7f-c7f0-4b69-ad5e-5f64c671b4ec.js.txt",
        "stats": {
          "unique": 512,
          "meanLuma": 218.50442673611212,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "183f1e0a1c0b82ec51f68190020638032cdddd82a10bb893310d6ce811e2f1cb",
          "png": "d4244182f03531abc1a3acc75f5ec2826ff555ac58acbdfb36c7d7c2c00ba319",
          "raw": "183f1e0a1c0b82ec51f68190020638032cdddd82a10bb893310d6ce811e2f1cb"
        },
        "latencyMs": 61707,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1778,
              "output_tokens": 4803,
              "total_tokens": 6581,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 314
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 61707
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:13:14.110Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 512,
          "meanLuma": 218.50442673611212,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311",
        "createdAt": "2026-08-24T02:12:32.257Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "ca91a5b8bb475936",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 26540,
          "usage": {
            "input_tokens": 1597,
            "output_tokens": 2494,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311/painting.png",
        "projectSource": "sketches/2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311.png",
        "source": "/images/model-painting-study/2026-08-24T02-12-32-8eb910d9-8fd1-4f79-8a77-167a1b5fd311.js.txt",
        "stats": {
          "unique": 745,
          "meanLuma": 206.7533693576406,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "4698e59a96e45fa832a96bbddaa332c0ac9591e0bc981871690955a298b2a157",
          "png": "a538231c59d1b56b1cc0c6711faddec947738f958b85af6857d8503e21947f0c",
          "raw": "4698e59a96e45fa832a96bbddaa332c0ac9591e0bc981871690955a298b2a157"
        },
        "latencyMs": 26540,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1597,
              "output_tokens": 2494,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 26540
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:13:23.777Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 745,
          "meanLuma": 206.7533693576406,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a",
        "createdAt": "2026-08-24T02:13:14.121Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "afc2671f2f24c750",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 46942,
          "usage": {
            "input_tokens": 1776,
            "output_tokens": 4070,
            "total_tokens": 5846,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 67
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a/painting.png",
        "projectSource": "sketches/2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a.png",
        "source": "/images/model-painting-study/2026-08-24T02-13-14-d00c0b45-e38d-426c-9c84-223dba18a84a.js.txt",
        "stats": {
          "unique": 542,
          "meanLuma": 218.01948498264014,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "c5d6699b8ac78fdde684959f48616b77060dafaaa442a20ba1b37c2f2df5d550",
          "png": "93ff3bb932d594cd7af8063671c7d8e46c2c6a43bd94f4b205370eb6acf72a17",
          "raw": "c5d6699b8ac78fdde684959f48616b77060dafaaa442a20ba1b37c2f2df5d550"
        },
        "latencyMs": 46942,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1776,
              "output_tokens": 4070,
              "total_tokens": 5846,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 67
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 46942
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:14:46.773Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 542,
          "meanLuma": 218.01948498264014,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393",
        "createdAt": "2026-08-24T02:13:23.780Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "60e61c1b04922fca",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 21465,
          "usage": {
            "input_tokens": 1567,
            "output_tokens": 1783,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393/painting.png",
        "projectSource": "sketches/2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393.png",
        "source": "/images/model-painting-study/2026-08-24T02-13-23-233dd575-029c-4062-903e-39f8179ff393.js.txt",
        "stats": {
          "unique": 235,
          "meanLuma": 214.64013645833697,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "53674e04891fb2e6d7054133d75307e346518e7617aed3081cc1dd4686fb7cf4",
          "png": "d08a8a5ffea3936844170c318550182a5081ba25dd15a3025e893b5b5895f98f",
          "raw": "53674e04891fb2e6d7054133d75307e346518e7617aed3081cc1dd4686fb7cf4"
        },
        "latencyMs": 21465,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1567,
              "output_tokens": 1783,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 21465
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:13:48.990Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 235,
          "meanLuma": 214.64013645833697,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5",
        "createdAt": "2026-08-24T02:13:42.954Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "cf9bd2863c525e54",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 135630,
          "usage": {
            "prompt_tokens": 1495,
            "completion_tokens": 8192,
            "total_tokens": 9687,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5/painting.png",
        "projectSource": "sketches/2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5.png",
        "source": "/images/model-painting-study/2026-08-24T02-13-42-a4f69d03-cb9c-445c-aa5c-23bad9f61cf5.js.txt",
        "stats": {
          "unique": 299,
          "meanLuma": 18.915007291666463,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "671c4352da8252ea96ba8e7aa469ff5533cce4d7729ab70e6628d19e2fe87828",
          "png": "347f3d961ee2419edd906f5b4499362c5cddcc3ee5e6ca7394eed1848012f7f8",
          "raw": "46775a6fd6e22057fcc158ab9d241136a808bd655379dd3f50bd2bf141d1bf45"
        },
        "latencyMs": 135630,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1495,
              "completion_tokens": 8192,
              "total_tokens": 9687,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 135630
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:16:13.892Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 299,
          "meanLuma": 18.915007291666463,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4",
        "createdAt": "2026-08-24T02:13:48.992Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a2dfadc17d75ed48",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 24297,
          "usage": {
            "input_tokens": 527,
            "output_tokens": 2359,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4/painting.png",
        "projectSource": "sketches/2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4.png",
        "source": "/images/model-painting-study/2026-08-24T02-13-48-3ad1a8a8-c794-4b63-99fc-082cb0d883c4.js.txt",
        "stats": {
          "unique": 503,
          "meanLuma": 210.7530774305586,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e7d70ea00abd3e4ef52fa5d8a24d977bef9208d58a49bf1e653f52fe45c6b0a4",
          "png": "99bc66ac8f2e007082e1f9e2401fe0cf602812028b2a1316a0a5420c12e043c1",
          "raw": "e7d70ea00abd3e4ef52fa5d8a24d977bef9208d58a49bf1e653f52fe45c6b0a4"
        },
        "latencyMs": 24297,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 527,
              "output_tokens": 2359,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 24297
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:14:29.009Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 503,
          "meanLuma": 210.7530774305586,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b",
        "createdAt": "2026-08-24T02:15:36.125Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "9a7012da72705da3",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 126606,
          "usage": {
            "prompt_tokens": 1604,
            "completion_tokens": 8192,
            "total_tokens": 9796,
            "prompt_cache_hit_tokens": 0,
            "prompt_cache_miss_tokens": 1604,
            "prompt_tokens_details": {
              "cached_tokens": 0
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b/painting.png",
        "projectSource": "sketches/2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b.png",
        "source": "/images/model-painting-study/2026-08-24T02-15-36-e1f61ae4-494b-4c03-8885-c1d7c25d671b.js.txt",
        "stats": {
          "unique": 597,
          "meanLuma": 28.62994453124957,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "ac5d3dfd3dd7e10877fa9d61a653bd707fdd26b4dfad4e0f8c9f0b138323b548",
          "png": "98847f42a62eec901974ee0a0edf437479e2de7e221b317e324d2d63b0bbe228",
          "raw": "79faf3731fbe8642edfdc61c89c2c847ad5edd4b09061477f387e71c82023cdd"
        },
        "latencyMs": 126606,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1604,
              "completion_tokens": 8192,
              "total_tokens": 9796,
              "prompt_cache_hit_tokens": 0,
              "prompt_cache_miss_tokens": 1604,
              "prompt_tokens_details": {
                "cached_tokens": 0
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 126606
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:17:51.277Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 597,
          "meanLuma": 28.62994453124957,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052",
        "createdAt": "2026-08-24T02:16:13.894Z",
        "prompt": "a mythic phoenix bird rising from pale ash into a midnight royal-blue sky, restrained ember-gold fire",
        "promptId": "phoenix-ashes-v2",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "phoenix-bird-sacred-v5",
        "artDirection": "Paint a mythic bird in rising three-quarter profile: a small head near (335, 120) facing right with a clearly curved beak, an S-shaped neck, and a breast spanning roughly x=265..350 and y=170..365. Sweep the nearer wing from the shoulder toward x=65..285 and y=175..405, and the farther wing toward x=330..535 and y=135..350. Build each from four to six long, overlapping feather contours with pointed tips. Extend two or three long tail-feather ribbons from the lower body near (305, 350) into an ash basin across y=465..545. Tuck two small bird talons beneath the breast. This must read as a phoenix bird, never a moth or butterfly: no antennae, proboscis, oval insect abdomen, four equal wings, or bilateral specimen pose. Use royal-blue feather masses with restrained ember-gold edges and low pale ash; no halo, logo symmetry, or scattered sparks.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2403,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "4b55ee164c728eb7",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 144668,
          "usage": {
            "prompt_tokens": 1565,
            "completion_tokens": 8192,
            "total_tokens": 9757,
            "prompt_tokens_details": {
              "cached_tokens": 1536
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052/painting.png",
        "projectSource": "sketches/2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052.png",
        "source": "/images/model-painting-study/2026-08-24T02-16-13-859a6742-6f27-4822-8516-2385aa4d4052.js.txt",
        "stats": {
          "unique": 324,
          "meanLuma": 20.128164496527823,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "a0e78518bf8e371721420f9b3c4e186e9bdf72cf37e27a5bb57e68d20693d269",
          "png": "0367f16f0d47908e6a02cc40039c78cfe7eee59770c4ace5d6252c0e9a8f98c8",
          "raw": "3319b5402354a6494ff385548744e6632e2a65a4a8f3b324d692c4807e8f270d"
        },
        "latencyMs": 144668,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1565,
              "completion_tokens": 8192,
              "total_tokens": 9757,
              "prompt_tokens_details": {
                "cached_tokens": 1536
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 144668
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:18:59.746Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 324,
          "meanLuma": 20.128164496527823,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754",
        "createdAt": "2026-08-24T02:17:17.122Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "34a56eb9c40f0fb4",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 32089,
          "usage": {
            "input_tokens": 1476,
            "output_tokens": 3638,
            "total_tokens": 5114,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1473
            },
            "output_tokens_details": {
              "reasoning_tokens": 898
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754/painting.png",
        "projectSource": "sketches/2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754.png",
        "source": "/images/model-painting-study/2026-08-24T02-17-17-23e53ed6-7e39-4047-a68c-b1f8e6f33754.js.txt",
        "stats": {
          "unique": 557,
          "meanLuma": 27.708946180555127,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "015cefff7512902eade93586443f55d823f780d8cc2c1e2429cf8376bd20ccfb",
          "png": "6c990c6a675f8afc8ab730000e4f137f286b48279e0600b7fd2c4bdf01660042",
          "raw": "015cefff7512902eade93586443f55d823f780d8cc2c1e2429cf8376bd20ccfb"
        },
        "latencyMs": 32089,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1476,
              "output_tokens": 3638,
              "total_tokens": 5114,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1473
              },
              "output_tokens_details": {
                "reasoning_tokens": 898
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 32089
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:18:00.045Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 557,
          "meanLuma": 27.708946180555127,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4",
        "createdAt": "2026-08-24T02:18:00.047Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "88b1cd3cba42a67d",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 28877,
          "usage": {
            "input_tokens": 1435,
            "output_tokens": 3303,
            "total_tokens": 4738,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1432
            },
            "output_tokens_details": {
              "reasoning_tokens": 687
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4/painting.png",
        "projectSource": "sketches/2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4.png",
        "source": "/images/model-painting-study/2026-08-24T02-18-00-c25543cf-938a-4c03-8429-feba94fe6ec4.js.txt",
        "stats": {
          "unique": 268,
          "meanLuma": 20.574263975694024,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "39f20dfdc82db9fee69b2b7c151bbac9cb5803c287833ea1066d801175bb8cef",
          "png": "b5a98f9137b8985211600fd249868cbd42fad9005ac1d9ef15af74c58ccfa066",
          "raw": "39f20dfdc82db9fee69b2b7c151bbac9cb5803c287833ea1066d801175bb8cef"
        },
        "latencyMs": 28877,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1435,
              "output_tokens": 3303,
              "total_tokens": 4738,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1432
              },
              "output_tokens_details": {
                "reasoning_tokens": 687
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 28877
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:18:34.212Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 268,
          "meanLuma": 20.574263975694024,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8",
        "createdAt": "2026-08-24T02:18:34.215Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "3cf5834ff927f058",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 24372,
          "usage": {
            "input_tokens": 1460,
            "output_tokens": 3461,
            "total_tokens": 4921,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1457
            },
            "output_tokens_details": {
              "reasoning_tokens": 809
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8/painting.png",
        "projectSource": "sketches/2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8.png",
        "source": "/images/model-painting-study/2026-08-24T02-18-34-b30fd125-ddde-4193-99bb-c133fa6489b8.js.txt",
        "stats": {
          "unique": 602,
          "meanLuma": 202.50439531250254,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "2f2a35b8e8d191496727c549ccff20a9b5f4f64299722dce5091908ca71f1b2c",
          "png": "a9f8d0f9a1ba0737a7d2c2a47914f47dfbee4109a9d234e113a53728684ea721",
          "raw": "2f2a35b8e8d191496727c549ccff20a9b5f4f64299722dce5091908ca71f1b2c"
        },
        "latencyMs": 24372,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1460,
              "output_tokens": 3461,
              "total_tokens": 4921,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1457
              },
              "output_tokens_details": {
                "reasoning_tokens": 809
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 24372
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:19:09.513Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 602,
          "meanLuma": 202.50439531250254,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c",
        "createdAt": "2026-08-24T02:18:59.749Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "eb92e53c3b45d190",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 146514,
          "usage": {
            "prompt_tokens": 1526,
            "completion_tokens": 8192,
            "total_tokens": 9718,
            "prompt_tokens_details": {},
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c/painting.png",
        "projectSource": "sketches/2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c.png",
        "source": "/images/model-painting-study/2026-08-24T02-18-59-af3f144d-5c9a-4a99-95ff-5a789931ad8c.js.txt",
        "stats": {
          "unique": 570,
          "meanLuma": 214.29071336805845,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "1a57bf3785fcb2a5b6942b5518157b33d4de4e95f61702d1ecc21d9b8bd1aabf",
          "png": "e59334490950f200cbd551d818b59fb3f316341bf21b29eaa675316c124fff9a",
          "raw": "86e691de132d5a85563e9c8deb01cf3feef893957203451215df9a69f23c80e5"
        },
        "latencyMs": 146514,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1526,
              "completion_tokens": 8192,
              "total_tokens": 9718,
              "prompt_tokens_details": {},
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 146514
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:21:44.651Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 570,
          "meanLuma": 214.29071336805845,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9",
        "createdAt": "2026-08-24T02:19:09.516Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "fc7f482fb3510749",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 27315,
          "usage": {
            "input_tokens": 1433,
            "output_tokens": 3502,
            "total_tokens": 4935,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1430
            },
            "output_tokens_details": {
              "reasoning_tokens": 981
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 13806,
          "usage": {
            "input_tokens": 3990,
            "output_tokens": 2659,
            "total_tokens": 6649,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 3987
            },
            "output_tokens_details": {
              "reasoning_tokens": 168
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9/painting.png",
        "projectSource": "sketches/2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9.png",
        "source": "/images/model-painting-study/2026-08-24T02-19-09-4e79c65b-8821-49bf-a24a-5624ce7996d9.js.txt",
        "stats": {
          "unique": 389,
          "meanLuma": 217.14835295139187,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "559c6e4c56d35771fdeae8164c65124a9a8f3cd7f5a5b3704c5907db7254a5d7",
          "png": "8c535aaab5662df96efbcfe66eb5ce8f82955aa86a1dbb4e40cfa99637202c3d",
          "raw": "1095e11f6f881ba07a81196a7ceb25ef019c4249a790c74d762425fcaaef27b9"
        },
        "latencyMs": 41121,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1433,
              "output_tokens": 3502,
              "total_tokens": 4935,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1430
              },
              "output_tokens_details": {
                "reasoning_tokens": 981
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "input_tokens": 3990,
              "output_tokens": 2659,
              "total_tokens": 6649,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 3987
              },
              "output_tokens_details": {
                "reasoning_tokens": 168
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 27315
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 13806
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:19:57.427Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 389,
          "meanLuma": 217.14835295139187,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12",
        "createdAt": "2026-08-24T02:19:57.430Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "54717715804720e0",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 23756,
          "usage": {
            "input_tokens": 1433,
            "output_tokens": 2599,
            "total_tokens": 4032,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1430
            },
            "output_tokens_details": {
              "reasoning_tokens": 516
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12/painting.png",
        "projectSource": "sketches/2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12.png",
        "source": "/images/model-painting-study/2026-08-24T02-19-57-6d5c2167-0b1d-43e2-8363-7e9ed35b1c12.js.txt",
        "stats": {
          "unique": 444,
          "meanLuma": 212.99641362847524,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "b4dcd0591c0083104963d378b87baf28bc4ef0c30db5f18c017cfd2bfc3cb62d",
          "png": "52033309fba2bdc6e01fa504a0c010158572d118df353d5f3ecb0ad3728010e9",
          "raw": "b4dcd0591c0083104963d378b87baf28bc4ef0c30db5f18c017cfd2bfc3cb62d"
        },
        "latencyMs": 23756,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1433,
              "output_tokens": 2599,
              "total_tokens": 4032,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1430
              },
              "output_tokens_details": {
                "reasoning_tokens": 516
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 23756
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:20:36.517Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 444,
          "meanLuma": 212.99641362847524,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65",
        "createdAt": "2026-08-24T02:21:44.653Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5833f1d6ba651d43",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 152111,
          "usage": {
            "prompt_tokens": 1496,
            "completion_tokens": 8192,
            "total_tokens": 9688,
            "prompt_tokens_details": {
              "cached_tokens": 512
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65/painting.png",
        "projectSource": "sketches/2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65.png",
        "source": "/images/model-painting-study/2026-08-24T02-21-44-632109e3-1804-447d-8cea-58347c96ea65.js.txt",
        "stats": {
          "unique": 329,
          "meanLuma": 207.27662864583618,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8ce0c3e378f059dcf0824e8b6446473b417faff5f436d22b3b1264bcc438a95f",
          "png": "40fc6550960d75c233f00e7baa097b7c7c5e6d80955a4c089fdc3ad67d0b36d3",
          "raw": "5438b782a99154b95ca2af7b127c22e9cacace86d829fe47dadd8dcd6e5eb7a5"
        },
        "latencyMs": 152111,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1496,
              "completion_tokens": 8192,
              "total_tokens": 9688,
              "prompt_tokens_details": {
                "cached_tokens": 512
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 152111
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:24:25.739Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 329,
          "meanLuma": 207.27662864583618,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc",
        "createdAt": "2026-08-24T02:24:25.742Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "9d97116c42ce7e8f",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 152373,
          "usage": {
            "prompt_tokens": 1480,
            "completion_tokens": 8192,
            "total_tokens": 9672,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 144561,
          "usage": {
            "prompt_tokens": 1822,
            "completion_tokens": 8192,
            "total_tokens": 10014,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc/painting.png",
        "projectSource": "sketches/2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc.png",
        "source": "/images/model-painting-study/2026-08-24T02-24-25-d0e247bd-471c-40de-9695-2d64fd7c3ccc.js.txt",
        "stats": {
          "unique": 609,
          "meanLuma": 214.68514192708574,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "64adbb7b1d8627a3ce271fc7a034de593d0bfa5e30461e61b2a052e99365abe7",
          "png": "98242105383410e0fab2f8958cea0bd29982a93687d3bc69f38d2f8406d79c9a",
          "raw": "eda4fd9bf6738ad99e62d3525d7789b99f7750358cd0c4f529322ae6173144ce"
        },
        "latencyMs": 296934,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1480,
              "completion_tokens": 8192,
              "total_tokens": 9672,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1822,
              "completion_tokens": 8192,
              "total_tokens": 10014,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 152373
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 144561
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:29:51.624Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 609,
          "meanLuma": 214.68514192708574,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f",
        "createdAt": "2026-08-24T02:24:35.064Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "ba3755b30b6fbc4d",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 131980,
          "usage": {
            "prompt_tokens": 1587,
            "completion_tokens": 8192,
            "total_tokens": 9779,
            "prompt_cache_hit_tokens": 0,
            "prompt_cache_miss_tokens": 1587,
            "prompt_tokens_details": {
              "cached_tokens": 0
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 81794,
          "usage": {
            "prompt_tokens": 3988,
            "completion_tokens": 5963,
            "total_tokens": 9951,
            "prompt_cache_hit_tokens": 0,
            "prompt_cache_miss_tokens": 3988,
            "prompt_tokens_details": {
              "cached_tokens": 0
            },
            "completion_tokens_details": {
              "reasoning_tokens": 2899
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f/painting.png",
        "projectSource": "sketches/2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f.png",
        "source": "/images/model-painting-study/2026-08-24T02-24-35-d045fa28-9732-43b6-93dc-1cbbed7b936f.js.txt",
        "stats": {
          "unique": 601,
          "meanLuma": 211.79893229166817,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "7f1b60af629d90d4302b7618ca83b9284978c74daab30cbd8059c3318c0eedbe",
          "png": "ede7301f5a04a921896c7c265d29a8034fb839c8965fe877a64d56cceea4ac7d",
          "raw": "35a2ec73415840856193fa99e130867f47239021dee117310b35004f677f3a33"
        },
        "latencyMs": 213774,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1587,
              "completion_tokens": 8192,
              "total_tokens": 9779,
              "prompt_cache_hit_tokens": 0,
              "prompt_cache_miss_tokens": 1587,
              "prompt_tokens_details": {
                "cached_tokens": 0
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 3988,
              "completion_tokens": 5963,
              "total_tokens": 9951,
              "prompt_cache_hit_tokens": 0,
              "prompt_cache_miss_tokens": 3988,
              "prompt_tokens_details": {
                "cached_tokens": 0
              },
              "completion_tokens_details": {
                "reasoning_tokens": 2899
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 131980
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 81794
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:28:24.123Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 601,
          "meanLuma": 211.79893229166817,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc",
        "createdAt": "2026-08-24T02:25:07.659Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "fc4bfe2fe45fc58e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 30936,
          "usage": {
            "input_tokens": 1740,
            "output_tokens": 1914,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc/painting.png",
        "projectSource": "sketches/2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc.png",
        "source": "/images/model-painting-study/2026-08-24T02-25-07-9a479e42-e6c4-4872-ae38-4e03f5c57ebc.js.txt",
        "stats": {
          "unique": 272,
          "meanLuma": 228.86427907986373,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "9b929aeac4b8805c002f62f13da088bb2cfcfe1ad719f7dd5d2c12950988f254",
          "png": "1b7fb0fc197b20ffe7ba0a9c57036b6ab4de65ea034e3d791e7e7132d91dd672",
          "raw": "9b929aeac4b8805c002f62f13da088bb2cfcfe1ad719f7dd5d2c12950988f254"
        },
        "latencyMs": 30936,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1740,
              "output_tokens": 1914,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 30936
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:25:54.202Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 272,
          "meanLuma": 228.86427907986373,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e",
        "createdAt": "2026-08-24T02:25:07.667Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "0c2a9b1319d8cb54",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 57856,
          "usage": {
            "input_tokens": 1758,
            "output_tokens": 4220
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e/painting.png",
        "projectSource": "sketches/2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e.png",
        "source": "/images/model-painting-study/2026-08-24T02-25-07-17ef1292-64b1-4c88-95f7-fe33cf811b9e.js.txt",
        "stats": {
          "unique": 826,
          "meanLuma": 186.2521730902784,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "363004deee3ed8ab6019335ed81fbcaae4d7b071355db4f104327727c38aa900",
          "png": "ea02751cf4fed4e18f52bdafc948ab868f1dd0ee7f118323dcc5b79ae33c18e3",
          "raw": "363004deee3ed8ab6019335ed81fbcaae4d7b071355db4f104327727c38aa900"
        },
        "latencyMs": 57856,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1758,
              "output_tokens": 4220
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 57856
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:26:34.870Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 826,
          "meanLuma": 186.2521730902784,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08",
        "createdAt": "2026-08-24T02:25:54.205Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "3d8dbf92afa4f04d",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 27994,
          "usage": {
            "input_tokens": 1740,
            "output_tokens": 2175,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08/painting.png",
        "projectSource": "sketches/2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08.png",
        "source": "/images/model-painting-study/2026-08-24T02-25-54-23776f31-2bcb-4114-b030-5f89117bea08.js.txt",
        "stats": {
          "unique": 310,
          "meanLuma": 227.74902430555844,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "43dda3faad953ea1814f9baa7685d6c7f5e08b2a4601a7b8b2e777ac1304f1e5",
          "png": "46bb06db2dcf00af1a5abc1838abfdc336f27e4aa2e7e699e117466dcf071758",
          "raw": "43dda3faad953ea1814f9baa7685d6c7f5e08b2a4601a7b8b2e777ac1304f1e5"
        },
        "latencyMs": 27994,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1740,
              "output_tokens": 2175,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 27994
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:26:37.711Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 310,
          "meanLuma": 227.74902430555844,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67",
        "createdAt": "2026-08-24T02:26:34.874Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "de8fad8f3f52e349",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 36399,
          "usage": {
            "prompt_tokens": 1619,
            "completion_tokens": 5625,
            "total_tokens": 7244,
            "cost": 0.02440025,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.02440025,
              "upstream_inference_prompt_cost": 0.001619,
              "upstream_inference_completions_cost": 0.02278125
            },
            "completion_tokens_details": {
              "reasoning_tokens": 2776,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67/painting.png",
        "projectSource": "sketches/2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67.png",
        "source": "/images/model-painting-study/2026-08-24T02-26-34-c9f3bad6-1b60-442d-8d98-ee08a50a9e67.js.txt",
        "stats": {
          "unique": 272,
          "meanLuma": 229.7015580729196,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "493b102de74870a893fb96dfa79f3f9a7498b5cb100f3ea89fba04ea7d9a0963",
          "png": "34b36ea92a4749d2b6fea3aacaf942865d6ee4f1dc911c3354a302f1e039c894",
          "raw": "493b102de74870a893fb96dfa79f3f9a7498b5cb100f3ea89fba04ea7d9a0963"
        },
        "latencyMs": 36399,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1619,
              "completion_tokens": 5625,
              "total_tokens": 7244,
              "cost": 0.02440025,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.02440025,
                "upstream_inference_prompt_cost": 0.001619,
                "upstream_inference_completions_cost": 0.02278125
              },
              "completion_tokens_details": {
                "reasoning_tokens": 2776,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 36399
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:27:38.353Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 272,
          "meanLuma": 229.7015580729196,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0",
        "createdAt": "2026-08-24T02:26:48.730Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "d92b8d6614cc780d",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 64102,
          "usage": {
            "input_tokens": 1949,
            "output_tokens": 4680,
            "total_tokens": 6629,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 60
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0/painting.png",
        "projectSource": "sketches/2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0.png",
        "source": "/images/model-painting-study/2026-08-24T02-26-48-998d4fc1-5ee4-4b92-9718-e34ff4244ea0.js.txt",
        "stats": {
          "unique": 389,
          "meanLuma": 228.52654322916908,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "97c8e07dfcb1e78bce6a1f095a995bb9deb0f8e1358bb9b44a59b6fd9bd3ebf9",
          "png": "5bf147a203510a9072b5ed57aeaff17e656b5db8f7b9066741d920a6735a355f",
          "raw": "97c8e07dfcb1e78bce6a1f095a995bb9deb0f8e1358bb9b44a59b6fd9bd3ebf9"
        },
        "latencyMs": 64102,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1949,
              "output_tokens": 4680,
              "total_tokens": 6629,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 60
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 64102
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:28:09.197Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 389,
          "meanLuma": 228.52654322916908,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc",
        "createdAt": "2026-08-24T02:28:24.126Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "0fcc4e614791f7c9",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 148456,
          "usage": {
            "prompt_tokens": 1556,
            "completion_tokens": 8192,
            "total_tokens": 9748,
            "prompt_cache_hit_tokens": 0,
            "prompt_cache_miss_tokens": 1556,
            "prompt_tokens_details": {
              "cached_tokens": 0
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 143827,
          "usage": {
            "prompt_tokens": 1715,
            "completion_tokens": 8192,
            "total_tokens": 9907,
            "prompt_cache_hit_tokens": 768,
            "prompt_cache_miss_tokens": 947,
            "prompt_tokens_details": {
              "cached_tokens": 768
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 124555,
          "usage": {
            "prompt_tokens": 5400,
            "completion_tokens": 8192,
            "total_tokens": 13592,
            "prompt_cache_hit_tokens": 1280,
            "prompt_cache_miss_tokens": 4120,
            "prompt_tokens_details": {
              "cached_tokens": 1280
            },
            "completion_tokens_details": {
              "reasoning_tokens": 8192
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc/painting.png",
        "projectSource": "sketches/2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc.png",
        "source": "/images/model-painting-study/2026-08-24T02-28-24-85ae40a3-9b5a-468c-8bc7-7e03a54c04cc.js.txt",
        "stats": {
          "unique": 387,
          "meanLuma": 222.17451857639114,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "a6eb9b74d2a810b95b15c155267696f225011698c6056ec7b5f96b0b168d945b",
          "png": "455ff6332ff7983674c981a05f17278296ae28c553ec19fae459e9bb6b53fc91",
          "raw": "17c6ccc99ecbcb11b0a700add657c3aac32d40bab5dc82e474dcb52bf290515b"
        },
        "latencyMs": 416838,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1556,
              "completion_tokens": 8192,
              "total_tokens": 9748,
              "prompt_cache_hit_tokens": 0,
              "prompt_cache_miss_tokens": 1556,
              "prompt_tokens_details": {
                "cached_tokens": 0
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1715,
              "completion_tokens": 8192,
              "total_tokens": 9907,
              "prompt_cache_hit_tokens": 768,
              "prompt_cache_miss_tokens": 947,
              "prompt_tokens_details": {
                "cached_tokens": 768
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 5400,
              "completion_tokens": 8192,
              "total_tokens": 13592,
              "prompt_cache_hit_tokens": 1280,
              "prompt_cache_miss_tokens": 4120,
              "prompt_tokens_details": {
                "cached_tokens": 1280
              },
              "completion_tokens_details": {
                "reasoning_tokens": 8192
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 148456
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 143827
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 124555
          }
        ]
      },
      "failure": null,
      "eventCount": 5,
      "lastEvent": {
        "at": "2026-08-24T02:35:26.026Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 387,
          "meanLuma": 222.17451857639114,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f",
        "createdAt": "2026-08-24T02:29:03.643Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5f1a6af55685656e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 28592,
          "usage": {
            "input_tokens": 1607,
            "output_tokens": 3761,
            "total_tokens": 5368,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1604
            },
            "output_tokens_details": {
              "reasoning_tokens": 828
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f/painting.png",
        "projectSource": "sketches/2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f.png",
        "source": "/images/model-painting-study/2026-08-24T02-29-03-839df435-dace-46c9-8653-fc188b4b3d3f.js.txt",
        "stats": {
          "unique": 470,
          "meanLuma": 226.12737239583572,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e94eea75ccd398702c9eabe0cafd8ad9916ad835dced0115d08033208d587937",
          "png": "62e5f1720591c679fd399f6e707749b5e9a7bd9a9f8e0763dce80e5c4c78a8da",
          "raw": "e94eea75ccd398702c9eabe0cafd8ad9916ad835dced0115d08033208d587937"
        },
        "latencyMs": 28592,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1607,
              "output_tokens": 3761,
              "total_tokens": 5368,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1604
              },
              "output_tokens_details": {
                "reasoning_tokens": 828
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 28592
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:29:59.157Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 470,
          "meanLuma": 226.12737239583572,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b",
        "createdAt": "2026-08-24T02:29:13.645Z",
        "prompt": "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",
        "promptId": "stand-for-right-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "witness-square-sacred-v4",
        "artDirection": "Paint one upright witness spanning x=240..355 and y=120..505, seen mostly from behind in a long royal-blue cloak with believable shoulders, head, hands, and stance. Arrange eight to twelve low charcoal crowd silhouettes in loose groups along both outer thirds, leaving open paper around the witness. Set three dark banner shapes on diagonal poles bending away from the central figure; the banners must contain no words, emblems, or flags of a real nation. Keep the witness vertical and crisp while the crowd and banners remain broken and wind-softened. Add one muted-gold edge light, no raised-fist poster pose, halo, or theatrical spotlight.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2406,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "d51a782fce05b804",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 8945,
          "usage": {
            "prompt_tokens": 1481,
            "completion_tokens": 2844,
            "total_tokens": 4325,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 6991,
          "usage": {
            "prompt_tokens": 4328,
            "completion_tokens": 2954,
            "total_tokens": 7282,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b/painting.png",
        "projectSource": "sketches/2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b.png",
        "source": "/images/model-painting-study/2026-08-24T02-29-13-891daa9f-06d1-44b6-ad2c-cca48f12b70b.js.txt",
        "stats": {
          "unique": 547,
          "meanLuma": 216.89253689236347,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "64d340da760001b285bbf6dc1fd35609e907a7dd3bec0486bd6ef90211fb957e",
          "png": "66ec1645672f10eb9196de72b94c7c6efd58fc8cbcc9808392bc2977af450010",
          "raw": "2fbe0fb376b4b7b034c263d1b95924328013b0f7a7d126179b33dac33fd9e108"
        },
        "latencyMs": 15936,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1481,
              "completion_tokens": 2844,
              "total_tokens": 4325,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 4328,
              "completion_tokens": 2954,
              "total_tokens": 7282,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 8945
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 6991
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:30:08.913Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 547,
          "meanLuma": 216.89253689236347,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117",
        "createdAt": "2026-08-24T02:35:05.430Z",
        "prompt": "an open biblical codex beneath a royal-blue night, a narrow ladder of light ascending into stars, restrained illuminated-manuscript ornament",
        "promptId": "royal-blue-biblical-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "royal-codex-sacred-v4",
        "artDirection": "Paint an open biblical codex across x=90..510 and y=330..520 using two unequal warm-ivory page contours, a dark royal-blue cover, and only a few fine ink marks with no readable lettering. Raise one narrow, slightly leaning ladder of light from near (305, 345) to (350, 105), with five restrained gold rungs; it must read as illumination, not construction equipment. Frame the scene with one deep royal-blue arch spanning roughly x=55..545 and y=45..535, then place no more than seven quiet stars in the upper half. Keep the page edges and lowest ladder rung crispest. Use #123A8C, #244FA3, warm ivory, muted gold, and charcoal only; avoid decorative borders, crosses, logos, and poster text.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2401,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a6b8050e4526e932",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 6983,
          "usage": {
            "prompt_tokens": 1552,
            "completion_tokens": 1996,
            "total_tokens": 3548,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 4572,
          "usage": {
            "prompt_tokens": 3486,
            "completion_tokens": 1793,
            "total_tokens": 5279,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117/painting.png",
        "projectSource": "sketches/2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117.png",
        "source": "/images/model-painting-study/2026-08-24T02-35-05-c2c247a1-2f00-43be-ae86-11440086d117.js.txt",
        "stats": {
          "unique": 704,
          "meanLuma": 39.51283532986069,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "637cf003fda7adb62695d98fa5513579c3d313814b877b276abb1b0ac23e2873",
          "png": "d0c09268cb796cc71752a9e24f0faae347c555a6ed8c45ce6a37abddcf76231a",
          "raw": "2a0403eeb170531164c7ec23ebca28bf49da4f02b8ac912ee8e1dcd9737f0dd4"
        },
        "latencyMs": 11555,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1552,
              "completion_tokens": 1996,
              "total_tokens": 3548,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 3486,
              "completion_tokens": 1793,
              "total_tokens": 5279,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 6983
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 4572
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:35:25.492Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 704,
          "meanLuma": 39.51283532986069,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95",
        "createdAt": "2026-08-24T02:35:25.494Z",
        "prompt": "a lone watchman in royal-blue armor standing between a sleeping city and a storm of shadowed arrows, spiritual warfare, one lamp, no gore",
        "promptId": "spiritual-warfare-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "spiritual-watch-sacred-v4",
        "artDirection": "Paint one believable watchman spanning x=235..370 and y=120..500, standing in three-quarter silhouette with a royal-blue cloak, a simple shield, and one small lamp near (365, 245). Set a sleeping walled city quietly along y=430..520. Let six to ten charcoal arrow strokes enter from the outer upper thirds and break or turn before reaching the figure. The lamp is the smallest and lightest focal mark; the blue cloak and shield form the dominant mass. Keep the figure human in proportion, not a superhero emblem. Use midnight charcoal, two royal blues, muted brass, and warm lamp cream. Show spiritual pressure symbolically: no demons, wings, gore, text, or literal battle scene.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2402,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e668fd732f4bc6b1",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 7656,
          "usage": {
            "prompt_tokens": 1483,
            "completion_tokens": 2191,
            "total_tokens": 3674,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 6017,
          "usage": {
            "prompt_tokens": 3673,
            "completion_tokens": 2144,
            "total_tokens": 5817,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 5439,
          "usage": {
            "prompt_tokens": 3645,
            "completion_tokens": 2176,
            "total_tokens": 5821,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95/painting.png",
        "projectSource": "sketches/2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95.png",
        "source": "/images/model-painting-study/2026-08-24T02-35-25-e08edf7b-5f43-40bf-895a-7923bc2abf95.js.txt",
        "stats": {
          "unique": 212,
          "meanLuma": 18.43858107638857,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "62ff4d56c104fe9ff1455607fbca16b1d0362d651f154248a1d51c7cfb584b9d",
          "png": "6686b6d61b44ebc6e3b5501fd9d6f8b17177204d71aae960594811f6bab23a38",
          "raw": "a9b937c7da6bbefa42d377da976957e346984395c17ecb042ae14e3ee3128b17"
        },
        "latencyMs": 19112,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1483,
              "completion_tokens": 2191,
              "total_tokens": 3674,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 3673,
              "completion_tokens": 2144,
              "total_tokens": 5817,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 3645,
              "completion_tokens": 2176,
              "total_tokens": 5821,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 7656
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 6017
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 5439
          }
        ]
      },
      "failure": null,
      "eventCount": 6,
      "lastEvent": {
        "at": "2026-08-24T02:36:29.428Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 212,
          "meanLuma": 18.43858107638857,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810",
        "createdAt": "2026-08-24T02:36:29.429Z",
        "prompt": "two ancient trees on opposite banks of a narrow river, one living and luminous, one charred and thorned, good and evil held in tension",
        "promptId": "good-versus-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "two-trees-sacred-v4",
        "artDirection": "Paint two distinct ancient trees: a living tree spanning x=55..275 and y=80..510, and a charred thorn tree spanning x=345..555 and y=105..520. Let a narrow royal-blue river widen from x=285..325 at y=120 to x=250..365 at y=560. Roots may approach the water but must remain organic and unequal. Give the living tree one restrained muted-gold fruit cluster and a broad blue-green crown; give the charred tree five to nine angular limbs and no cartoon face or flames. Hold good and evil in visual tension without a hard split-screen, yin-yang symbol, captions, or obvious iconography. Keep the river and living trunk crispest and leave the sky mostly untouched.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "ink",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2404,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "1474e394382b87b2",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 7898,
          "usage": {
            "prompt_tokens": 1508,
            "completion_tokens": 2358,
            "total_tokens": 3866,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810/painting.png",
        "projectSource": "sketches/2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810.png",
        "source": "/images/model-painting-study/2026-08-24T02-36-29-51277973-8065-450a-80d4-b77ab66f5810.js.txt",
        "stats": {
          "unique": 594,
          "meanLuma": 213.21754062500256,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "40b37d361ac2ac7f23a38424fdb2916c6d2dc90a906d0d193e8d9254226c92bf",
          "png": "f851cff83537597347a75293eb3f8d5d16f03777632feb5608a55310444d098d",
          "raw": "d1879e3a02ee6dc005e055462737b00e6f444669f4fc9ab99c28530050932559"
        },
        "latencyMs": 7898,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1508,
              "completion_tokens": 2358,
              "total_tokens": 3866,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 7898
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:36:54.352Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 594,
          "meanLuma": 213.21754062500256,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2",
        "createdAt": "2026-08-24T02:36:54.353Z",
        "prompt": "a small pilgrim in a royal-blue cloak continuing uphill through black thorns toward a distant gold sanctuary, persisting against evil",
        "promptId": "persisting-against-evil-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v5",
        "directionId": "pilgrim-thorns-sacred-v4",
        "artDirection": "Paint one small but readable pilgrim in a royal-blue cloak spanning x=205..300 and y=270..485, leaning uphill on a diagonal path that rises from (40, 520) toward (520, 190). Place black thorn shapes behind and below the pilgrim, never closing around the figure. Put a distant warm-gold sanctuary between x=450..535 and y=115..225. The path must remain visibly open. Use the blue cloak as the strongest color, the sanctuary as one quiet light, and charcoal for the weather and thorns. Show persistence through posture and distance, not a slogan or action-poster pose. No lettering, crowds, monsters, flags, or decorative framing.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2405,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e9099e3e17b419d4",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 9254,
          "usage": {
            "prompt_tokens": 1477,
            "completion_tokens": 2713,
            "total_tokens": 4190,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2/painting.png",
        "projectSource": "sketches/2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2.png",
        "source": "/images/model-painting-study/2026-08-24T02-36-54-befe9f7f-0379-4b81-88cb-565f088773b2.js.txt",
        "stats": {
          "unique": 156,
          "meanLuma": 228.79658741319813,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "0c4aea6f4350bd2639ec45a5ffc87fffe9f745889922ff8096cdb23d7acabdde",
          "png": "6c60a88573009efa04ff7bb224811e9612e7f2af31eb9307cfcbd6ddd7ae0196",
          "raw": "792eccab3fb5a1cdec57e3b3a887c9f3ccc34227dac03d7cf93aff2e61c3da63"
        },
        "latencyMs": 9254,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1477,
              "completion_tokens": 2713,
              "total_tokens": 4190,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 9254
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:37:12.794Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 156,
          "meanLuma": 228.79658741319813,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7",
        "createdAt": "2026-08-24T02:37:13.903Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "388df202b33e6f50",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 46397,
          "usage": {
            "input_tokens": 1916,
            "output_tokens": 3401,
            "total_tokens": 5317,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 57
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7/painting.png",
        "projectSource": "sketches/2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7.png",
        "source": "/images/model-painting-study/2026-08-24T02-37-13-160566b0-e024-47f6-89be-0f2ee04f0dc7.js.txt",
        "stats": {
          "unique": 344,
          "meanLuma": 225.71529244791958,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "cecbc222704fcf72f6e2fc123d4a6398356e504843fbbf247dba0e068e155eaa",
          "png": "f24bd0a883cea35679674ba021518af96297e4b8af6b0277e3c95cc2824a7ce9",
          "raw": "cecbc222704fcf72f6e2fc123d4a6398356e504843fbbf247dba0e068e155eaa"
        },
        "latencyMs": 46397,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1916,
              "output_tokens": 3401,
              "total_tokens": 5317,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 57
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 46397
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:38:29.957Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 344,
          "meanLuma": 225.71529244791958,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416",
        "createdAt": "2026-08-24T02:37:13.917Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "7efb6d5fc1ddbcd9",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 52556,
          "usage": {
            "input_tokens": 1724,
            "output_tokens": 3882
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416/painting.png",
        "projectSource": "sketches/2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416.png",
        "source": "/images/model-painting-study/2026-08-24T02-37-13-c4fdcb71-56a0-4a32-853f-5aed6f90b416.js.txt",
        "stats": {
          "unique": 471,
          "meanLuma": 222.86211276041868,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "fc899d6cff110d57cabb966a3409f4cefc2f7ef62f3ead6a4767ddf36eea9c79",
          "png": "a1b377b96c30269ae95cf162c7760205c0e32740faab3abccf402c7e32dcaf00",
          "raw": "fc899d6cff110d57cabb966a3409f4cefc2f7ef62f3ead6a4767ddf36eea9c79"
        },
        "latencyMs": 52556,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1724,
              "output_tokens": 3882
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 52556
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:38:50.650Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 471,
          "meanLuma": 222.86211276041868,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201",
        "createdAt": "2026-08-24T02:37:32.790Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "f2cfb5b11a29fb50",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 10427,
          "usage": {
            "prompt_tokens": 1621,
            "completion_tokens": 3010,
            "total_tokens": 4631,
            "prompt_tokens_details": {
              "cached_tokens": 512,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201/painting.png",
        "projectSource": "sketches/2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201.png",
        "source": "/images/model-painting-study/2026-08-24T02-37-32-9aa3b437-df96-4252-9985-1816b584b201.js.txt",
        "stats": {
          "unique": 509,
          "meanLuma": 171.38991831597457,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "0c23f4febaf5853809106924c0be1fcca7d24600da6ac3cfa061a58dc083866e",
          "png": "daabebbb3f5b36f67bf4c39e98f1568d0cc52937bbd860e2d8d642cb3dceacb3",
          "raw": "33ab05d1d1abf630ad54259159bb4157e4e7a34975098802bdc32522f6538d8d"
        },
        "latencyMs": 10427,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1621,
              "completion_tokens": 3010,
              "total_tokens": 4631,
              "prompt_tokens_details": {
                "cached_tokens": 512,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 10427
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:38:05.939Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 509,
          "meanLuma": 171.38991831597457,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f",
        "createdAt": "2026-08-24T02:38:05.943Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "c15f9a9ddd51e84c",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 10015,
          "usage": {
            "prompt_tokens": 1654,
            "completion_tokens": 3128,
            "total_tokens": 4782,
            "prompt_tokens_details": {
              "cached_tokens": 512,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 7393,
          "usage": {
            "prompt_tokens": 4787,
            "completion_tokens": 3094,
            "total_tokens": 7881,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f/painting.png",
        "projectSource": "sketches/2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f.png",
        "source": "/images/model-painting-study/2026-08-24T02-38-05-ccdfc3b8-c4c9-49cf-ba05-06775ff50e0f.js.txt",
        "stats": {
          "unique": 275,
          "meanLuma": 226.85581250000277,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "de29d58dd442de4fd84afffaa3d619abd7e3b947a61b942b2ab37af788146805",
          "png": "ecd222be3158422f6c1788055b6651b19f7edf78156d62923d8992203057e516",
          "raw": "7c9c82e3160dab8e62b534a09f96c75fa07e2f526b39a4c6f6b8e21b412adb0a"
        },
        "latencyMs": 17408,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1654,
              "completion_tokens": 3128,
              "total_tokens": 4782,
              "prompt_tokens_details": {
                "cached_tokens": 512,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 4787,
              "completion_tokens": 3094,
              "total_tokens": 7881,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 10015
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 7393
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:39:07.273Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 275,
          "meanLuma": 226.85581250000277,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536",
        "createdAt": "2026-08-24T02:38:29.961Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5745268a3af2bf56",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 25238,
          "usage": {
            "input_tokens": 1572,
            "output_tokens": 3154,
            "total_tokens": 4726,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1569
            },
            "output_tokens_details": {
              "reasoning_tokens": 831
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 17944,
          "usage": {
            "input_tokens": 3931,
            "output_tokens": 2577,
            "total_tokens": 6508,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 3928
            },
            "output_tokens_details": {
              "reasoning_tokens": 316
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536/painting.png",
        "projectSource": "sketches/2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536.png",
        "source": "/images/model-painting-study/2026-08-24T02-38-29-0ccd03a8-fdc8-4079-a440-9027ba4f3536.js.txt",
        "stats": {
          "unique": 339,
          "meanLuma": 219.0386842881981,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "f4662ce1ddd0491082202ff9cf74a6cbd62dc8e3cee7bb042be9c8a4e7b3c3b1",
          "png": "305322c06752abe5406b5f065a74f472e802aaf7656b917039f2a576f411973f",
          "raw": "fbb02e34e2d70fb6733579b77172fa5579caa67ce59d8f7da6bc962a69325389"
        },
        "latencyMs": 43182,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1572,
              "output_tokens": 3154,
              "total_tokens": 4726,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1569
              },
              "output_tokens_details": {
                "reasoning_tokens": 831
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "input_tokens": 3931,
              "output_tokens": 2577,
              "total_tokens": 6508,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 3928
              },
              "output_tokens_details": {
                "reasoning_tokens": 316
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 25238
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 17944
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:39:25.808Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 339,
          "meanLuma": 219.0386842881981,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6",
        "createdAt": "2026-08-24T02:38:50.654Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "88e1d10db2aa4b04",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 27526,
          "usage": {
            "input_tokens": 1706,
            "output_tokens": 1778,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6/painting.png",
        "projectSource": "sketches/2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6.png",
        "source": "/images/model-painting-study/2026-08-24T02-38-50-1e2d9f9b-a376-4491-9317-34b132f1baa6.js.txt",
        "stats": {
          "unique": 387,
          "meanLuma": 211.468329079864,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "d60c54b9f883ec62581cd82dc57fceef4c85950e6098e75424b6e109f0b0a2ef",
          "png": "380f27079c149e075bbcfaf64b48a6ee7b7037ceccf8b1bd14aa660ceec81a23",
          "raw": "d60c54b9f883ec62581cd82dc57fceef4c85950e6098e75424b6e109f0b0a2ef"
        },
        "latencyMs": 27526,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1706,
              "output_tokens": 1778,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 27526
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:39:33.185Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 387,
          "meanLuma": 211.468329079864,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a",
        "createdAt": "2026-08-24T02:39:07.199Z",
        "prompt": "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",
        "promptId": "lion-and-lamb-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v7",
        "directionId": "lion-lamb-sacred-v7",
        "artDirection": "Paint a close, quiet side-view portrait of two resting animals on open cream paper, with no tree or architecture. The lion fills x=55..325 and y=145..485, facing right; the lamb fills x=315..545 and y=215..475, facing left. Their noses nearly meet near (325, 315), making that small gap the focal point. Build the lion from an irregular muted-gold mane contour, a separate tawny face and long muzzle, two small ears, one restrained eye, a sloping shoulder and back, one haunch, and two broad folded forepaws. Keep the mane open around the face; no spiral, circular badge, human expression, or roaring mouth. Build the lamb from a pale warm-gray head, two long lateral ears, short neck, chest, level back, belly, and two folded legs. Use a few broken charcoal curls only along its back, never a circular cloud body or toy face. Join them with one low royal-blue shared shadow and a few muted-gold dawn strokes behind their backs. Keep heads, muzzle, ears, paws, and the negative space between noses crispest; leave the upper half mostly untouched and add no cedar, halo, heart, text, border, or decorative icon.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2408,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "29f8967fcbf658ec",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 155996,
          "usage": {
            "prompt_tokens": 1669,
            "completion_tokens": 8192,
            "total_tokens": 9861,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a/painting.png",
        "projectSource": "sketches/2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a.png",
        "source": "/images/model-painting-study/2026-08-24T02-39-07-8055584d-c20b-47db-8289-cc38b259096a.js.txt",
        "stats": {
          "unique": 535,
          "meanLuma": 217.94829895833598,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "00e2e4a3a04c6c0c7ec45a2089a7b3501c450640ab1df233f6d20c737b2c0d6f",
          "png": "5d068ab9c264f0987ad15abf0fd649c6f7036f009d083d833d17108995809543",
          "raw": "c57dc5d0b2eba1b64ff68e913bccfeb0a04a6ca27264ce92d3cc71fee6287a56"
        },
        "latencyMs": 155996,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1669,
              "completion_tokens": 8192,
              "total_tokens": 9861,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 155996
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:42:07.163Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 535,
          "meanLuma": 217.94829895833598,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f",
        "createdAt": "2026-08-24T02:39:25.811Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "0d93c7f3574371bc",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 28274,
          "usage": {
            "input_tokens": 682,
            "output_tokens": 2162,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f/painting.png",
        "projectSource": "sketches/2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f.png",
        "source": "/images/model-painting-study/2026-08-24T02-39-25-56855275-28ad-4371-abbe-7db14cade16f.js.txt",
        "stats": {
          "unique": 563,
          "meanLuma": 218.0161985243082,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "ec78e4aad09ff01efd8b89b131687e8b98c9791708bfa577470b15fe2b2c3916",
          "png": "6bf3ab866ec5525d7e0f5c693e16317c700de0808cbc665170abaa5c50cf5c3f",
          "raw": "ec78e4aad09ff01efd8b89b131687e8b98c9791708bfa577470b15fe2b2c3916"
        },
        "latencyMs": 28274,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 682,
              "output_tokens": 2162,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 28274
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:40:09.298Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 563,
          "meanLuma": 218.0161985243082,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9",
        "createdAt": "2026-08-24T02:39:33.188Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "4a639e6fc5111c91",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 22737,
          "usage": {
            "prompt_tokens": 1584,
            "completion_tokens": 5844,
            "total_tokens": 7428,
            "cost": 0.0252522,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0252522,
              "upstream_inference_prompt_cost": 0.001584,
              "upstream_inference_completions_cost": 0.0236682
            },
            "completion_tokens_details": {
              "reasoning_tokens": 4249,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9/painting.png",
        "projectSource": "sketches/2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9.png",
        "source": "/images/model-painting-study/2026-08-24T02-39-33-495f19d5-192b-478e-8b6f-2b45a712c1b9.js.txt",
        "stats": {
          "unique": 337,
          "meanLuma": 225.10469600694768,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "b4780473117f34894b4151439677c7acd49336c6cc71edca625be96fce6869fa",
          "png": "5534be9c41389128daa2671410d32a7a9c19d76072d5dd22f5ded715cc5f337a",
          "raw": "b4780473117f34894b4151439677c7acd49336c6cc71edca625be96fce6869fa"
        },
        "latencyMs": 22737,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1584,
              "completion_tokens": 5844,
              "total_tokens": 7428,
              "cost": 0.0252522,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0252522,
                "upstream_inference_prompt_cost": 0.001584,
                "upstream_inference_completions_cost": 0.0236682
              },
              "completion_tokens_details": {
                "reasoning_tokens": 4249,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 22737
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:40:11.246Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 337,
          "meanLuma": 225.10469600694768,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559",
        "createdAt": "2026-08-24T02:42:32.144Z",
        "prompt": "a solitary watchman holding one warm lamp at a stone city gate as royal-blue night gives way to dawn, vigilance and moral courage",
        "promptId": "watchman-at-dawn-v3",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v8",
        "directionId": "watchman-gate-sacred-v8",
        "artDirection": "On warm cream paper, make one watchman the dominant readable subject, spanning x=220..380 and y=145..515. Build separate pigment-rich contours for a small head, shoulders, midtone royal-blue cloak, bent lamp arm, straight staff arm, and two planted legs; keep the face merely implied. Hang one warm lamp near (385, 260). Its compact glow may overlap the hand and inner cloak edge, but must not become a large circular sun or halo. Put the darkest charcoal accent at the staff, shoulder, and one boot, not around the whole figure. Suggest the gate behind the figure with two broken warm-stone wall fragments and one incomplete arch from x=185..430 and y=205..515. Never paint a continuous dark band across the canvas, and keep every wall mass lighter and softer than the watchman. Wash only the upper third with two loose royal-blue dawn strokes fading into untouched cream at the horizon. Use royal blue, slate, warm stone, charcoal, and muted gold only; no armies, text, stars, fantasy effects, black-on-black masses, circular diagrams, or decorative border.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "watercolor",
        "paper": "cream",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2407,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "97de479497d2eff9",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 161326,
          "usage": {
            "prompt_tokens": 1635,
            "completion_tokens": 8192,
            "total_tokens": 9827,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559/painting.png",
        "projectSource": "sketches/2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559.png",
        "source": "/images/model-painting-study/2026-08-24T02-42-32-127a7fb5-7a44-472f-bf23-3ba12e973559.js.txt",
        "stats": {
          "unique": 456,
          "meanLuma": 218.27359817708637,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "a3fc2815ec56c3aa046efb2e519f00e03f69fefd66bbc1ea6221be92c62d28ee",
          "png": "d61b1980568581ca69a40c3dbe90c3887f1da7e6559c1090be286a2e8286de03",
          "raw": "1ca39c6ab11a5332672b06205d53b6ce39ecfb98ec081fa988db1e69da9aa318"
        },
        "latencyMs": 161326,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1635,
              "completion_tokens": 8192,
              "total_tokens": 9827,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 161326
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:45:31.165Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 456,
          "meanLuma": 218.27359817708637,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661",
        "createdAt": "2026-08-24T02:49:37.101Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "0ffd29160f1ac96c",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 21171,
          "usage": {
            "input_tokens": 1484,
            "output_tokens": 2769,
            "total_tokens": 4253,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1481
            },
            "output_tokens_details": {
              "reasoning_tokens": 931
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-b5acaa47-49eb-4465-bbdd-5bd015470661.js.txt",
        "stats": {
          "unique": 399,
          "meanLuma": 25.462281510415814,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "be9453d2a68424ea93aefb5c93d4099d3dff2e35a1f6e5e1332c2d24c3bd2098",
          "png": "d675b0d6980213110ce24ffa900a9a4acc21dab8d6a233e67c20cfb29dfe235d",
          "raw": "be9453d2a68424ea93aefb5c93d4099d3dff2e35a1f6e5e1332c2d24c3bd2098"
        },
        "latencyMs": 21171,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1484,
              "output_tokens": 2769,
              "total_tokens": 4253,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1481
              },
              "output_tokens_details": {
                "reasoning_tokens": 931
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 21171
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:09.597Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 399,
          "meanLuma": 25.462281510415814,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4",
        "createdAt": "2026-08-24T02:49:37.102Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "d712b8f2b38a0f57",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 72171,
          "usage": {
            "input_tokens": 1827,
            "output_tokens": 4463,
            "total_tokens": 6290,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 831
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-7bfb8c0a-33af-4e1d-a23d-cda251908ae4.js.txt",
        "stats": {
          "unique": 278,
          "meanLuma": 24.002027690972152,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "ec18e4b9554618bf0a441dc16a4cad5a77d7519cb77f119f9adb22d6d02c6671",
          "png": "560e8fee895f005a607db52096806d8a8f4ac7e101fb30db868420cac5673a1d",
          "raw": "ec18e4b9554618bf0a441dc16a4cad5a77d7519cb77f119f9adb22d6d02c6671"
        },
        "latencyMs": 72171,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1827,
              "output_tokens": 4463,
              "total_tokens": 6290,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 831
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 72171
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:51:01.728Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 278,
          "meanLuma": 24.002027690972152,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45",
        "createdAt": "2026-08-24T02:49:37.102Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "13feb0d31c307111",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 22289,
          "usage": {
            "input_tokens": 1614,
            "output_tokens": 1364,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-f8ec21d2-fe5c-4fb6-bbea-1d015c554a45.js.txt",
        "stats": {
          "unique": 380,
          "meanLuma": 28.285775954860455,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "21eaa8e39ee8605b917b58eeb78d592a8fae54ed523bfb397ffdac629f40eb53",
          "png": "a26165773ab6414f0ea5fe829a8d7cf66364bbfb1ab59ea89db9b1756fa1bbf5",
          "raw": "21eaa8e39ee8605b917b58eeb78d592a8fae54ed523bfb397ffdac629f40eb53"
        },
        "latencyMs": 22289,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1614,
              "output_tokens": 1364,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 22289
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:09.401Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 380,
          "meanLuma": 28.285775954860455,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462",
        "createdAt": "2026-08-24T02:49:37.909Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "7e28c07f58ae974b",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 177294,
          "usage": {
            "prompt_tokens": 1543,
            "completion_tokens": 8192,
            "total_tokens": 9735,
            "prompt_tokens_details": {},
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 166928,
          "usage": {
            "prompt_tokens": 1751,
            "completion_tokens": 8192,
            "total_tokens": 9943,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-bcb3e2da-7f97-4f8d-a6b2-572795ada462.js.txt",
        "stats": {
          "unique": 229,
          "meanLuma": 22.002526909721684,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "d4f46f0b2d63f1ad07431dd47d636d7d120486aeafad44a807be38fb117500f9",
          "png": "323a9809bd33f038a87aba8890232257152fe17f3656afee951663325ac46f8d",
          "raw": "3f71b04ab45ebc1f6508953cabbd771359e7a3b23896202c64f55b0fdf550cd5"
        },
        "latencyMs": 344222,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1543,
              "completion_tokens": 8192,
              "total_tokens": 9735,
              "prompt_tokens_details": {},
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1751,
              "completion_tokens": 8192,
              "total_tokens": 9943,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 177294
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 166928
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T02:55:30.818Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 229,
          "meanLuma": 22.002526909721684,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33",
        "createdAt": "2026-08-24T02:49:37.934Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "2783a39d04477986",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 19472,
          "usage": {
            "input_tokens": 1614,
            "output_tokens": 1423,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-664f5d1c-0462-4ded-91ff-edbb4aa55b33.js.txt",
        "stats": {
          "unique": 292,
          "meanLuma": 27.6430449652772,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "553a84f141cfd6cb39d68bc0ec9acda084fff4b06d2304f1b9346a6d4f7e7ebd",
          "png": "c729e12cc55729865c3cad8ea465be019ece6d59aaad72a4b2c3b6576263a4a6",
          "raw": "553a84f141cfd6cb39d68bc0ec9acda084fff4b06d2304f1b9346a6d4f7e7ebd"
        },
        "latencyMs": 19472,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1614,
              "output_tokens": 1423,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 19472
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:07.906Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 292,
          "meanLuma": 27.6430449652772,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62",
        "createdAt": "2026-08-24T02:49:37.952Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "381ad0cc05d28165",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 19392,
          "usage": {
            "input_tokens": 1503,
            "output_tokens": 2529,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-37-8024f62e-1c34-4c83-a9fe-256b1c1fcf62.js.txt",
        "stats": {
          "unique": 539,
          "meanLuma": 26.09265295138836,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "c769fb570f747c85fbeed755c5c66721f202e12e701c9df5aec6a8ca14adad91",
          "png": "eea452a171801ef936a935e0fc66e342e35b3c64ae26e959197332dfa2619aa1",
          "raw": "c769fb570f747c85fbeed755c5c66721f202e12e701c9df5aec6a8ca14adad91"
        },
        "latencyMs": 19392,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1503,
              "output_tokens": 2529,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 19392
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:17.840Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 539,
          "meanLuma": 26.09265295138836,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892",
        "createdAt": "2026-08-24T02:49:46.492Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "991e68d7236a29a9",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 9224,
          "usage": {
            "prompt_tokens": 1495,
            "completion_tokens": 1834,
            "total_tokens": 3329,
            "cost": 0.00884795,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.00884795,
              "upstream_inference_prompt_cost": 0.00142025,
              "upstream_inference_completions_cost": 0.0074277
            },
            "completion_tokens_details": {
              "reasoning_tokens": 441,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892/painting.png",
        "projectSource": "sketches/2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892.png",
        "source": "/images/model-painting-study/2026-08-24T02-49-46-10778339-3d06-40a1-a9de-bdce0d7cb892.js.txt",
        "stats": {
          "unique": 443,
          "meanLuma": 29.19738532986071,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "eea54effdef2091e57f7e84568abb8f0de989cf84ffe12a60eb5fb58474e32d3",
          "png": "0bfa9407f3bbcab1973af914a4168fb4e85f3d456c86f39cc4eeff27ed7dbbf4",
          "raw": "eea54effdef2091e57f7e84568abb8f0de989cf84ffe12a60eb5fb58474e32d3"
        },
        "latencyMs": 9224,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1495,
              "completion_tokens": 1834,
              "total_tokens": 3329,
              "cost": 0.00884795,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.00884795,
                "upstream_inference_prompt_cost": 0.00142025,
                "upstream_inference_completions_cost": 0.0074277
              },
              "completion_tokens_details": {
                "reasoning_tokens": 441,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 9224
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:06.789Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 443,
          "meanLuma": 29.19738532986071,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2",
        "createdAt": "2026-08-24T02:50:06.793Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "7399a2daea3683c6",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 35058,
          "usage": {
            "prompt_tokens": 1465,
            "completion_tokens": 7381,
            "total_tokens": 8846,
            "cost": 0.0312848,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0312848,
              "upstream_inference_prompt_cost": 0.00139175,
              "upstream_inference_completions_cost": 0.02989305
            },
            "completion_tokens_details": {
              "reasoning_tokens": 5454,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-06-07d6ad01-f9db-46d7-844d-12bc84adcaa2.js.txt",
        "stats": {
          "unique": 604,
          "meanLuma": 31.506203559027888,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "43f003049f7dbc656b0125e3d9046dce52f00c3f6779f88411abd08683fc3dc6",
          "png": "95b5ef7c5dfdcb9d017e88e91e8bc77a63f03db0a4183c4589223f2200557ee0",
          "raw": "43f003049f7dbc656b0125e3d9046dce52f00c3f6779f88411abd08683fc3dc6"
        },
        "latencyMs": 35058,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1465,
              "completion_tokens": 7381,
              "total_tokens": 8846,
              "cost": 0.0312848,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0312848,
                "upstream_inference_prompt_cost": 0.00139175,
                "upstream_inference_completions_cost": 0.02989305
              },
              "completion_tokens_details": {
                "reasoning_tokens": 5454,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 35058
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:54.108Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 604,
          "meanLuma": 31.506203559027888,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d",
        "createdAt": "2026-08-24T02:50:07.910Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "48214584d20bc2eb",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 23760,
          "usage": {
            "input_tokens": 559,
            "output_tokens": 1751,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-07-851a9501-e582-4679-b03f-b72cb6a6055d.js.txt",
        "stats": {
          "unique": 608,
          "meanLuma": 28.492174739583433,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "96b369f724e601307b08fce9de11f231d6af6e487116f8ba6cbd0900f5bb1d1d",
          "png": "de5c0da245a8b26b18a99654f863dad643cc67fa589970804ecee6a01b0b9cad",
          "raw": "96b369f724e601307b08fce9de11f231d6af6e487116f8ba6cbd0900f5bb1d1d"
        },
        "latencyMs": 23760,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 559,
              "output_tokens": 1751,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 23760
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:37.905Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 608,
          "meanLuma": 28.492174739583433,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc",
        "createdAt": "2026-08-24T02:50:09.405Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "c7e40e4b76d960fa",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 26573,
          "usage": {
            "input_tokens": 1583,
            "output_tokens": 1683,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-09-21e5dcf3-95ba-4432-a9db-22fa0dd733cc.js.txt",
        "stats": {
          "unique": 570,
          "meanLuma": 29.979573350694434,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "4e6114c087feafcdb35370696c8def448be769cf9e06d112925bd16a60e8b3f9",
          "png": "a68442c5fb6d32b81e262695ef705ccd4dd7edb2da1a4276ce827cfdc0341ab9",
          "raw": "4e6114c087feafcdb35370696c8def448be769cf9e06d112925bd16a60e8b3f9"
        },
        "latencyMs": 26573,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1583,
              "output_tokens": 1683,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 26573
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:42.335Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 570,
          "meanLuma": 29.979573350694434,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf",
        "createdAt": "2026-08-24T02:50:09.601Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "18460ff4ab855300",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 22199,
          "usage": {
            "input_tokens": 1454,
            "output_tokens": 3002,
            "total_tokens": 4456,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1451
            },
            "output_tokens_details": {
              "reasoning_tokens": 804
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-09-8e93dd7d-3ad1-4c72-b36f-85fab760dcaf.js.txt",
        "stats": {
          "unique": 582,
          "meanLuma": 28.881741145833455,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "54ffdca33fc0e631cd8a0f9945a95bbc760559f6e5ac81becec7f7a433a4febd",
          "png": "c88a9db1ce8197e920e0f3e748479bfbf90a3953f4ea14394637d2989ddf50cc",
          "raw": "54ffdca33fc0e631cd8a0f9945a95bbc760559f6e5ac81becec7f7a433a4febd"
        },
        "latencyMs": 22199,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1454,
              "output_tokens": 3002,
              "total_tokens": 4456,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1451
              },
              "output_tokens_details": {
                "reasoning_tokens": 804
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 22199
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:50:41.867Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 582,
          "meanLuma": 28.881741145833455,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7",
        "createdAt": "2026-08-24T02:50:17.843Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "831e0525aa0a3561",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 43583,
          "usage": {
            "input_tokens": 1605,
            "output_tokens": 3122
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-17-043d8acd-4e46-4a1b-b407-ca92fb43c0d7.js.txt",
        "stats": {
          "unique": 564,
          "meanLuma": 25.82045381944454,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "3deab40e8f445aa6f11824aaaf59888b520df149a4559b65bc5d5b9d31788425",
          "png": "6d768f4ff6ec7cd037624bb692a57cc4d000e979e629bfc85b4387301fed9e5b",
          "raw": "3deab40e8f445aa6f11824aaaf59888b520df149a4559b65bc5d5b9d31788425"
        },
        "latencyMs": 43583,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1605,
              "output_tokens": 3122
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 43583
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:51:26.350Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 564,
          "meanLuma": 25.82045381944454,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d",
        "createdAt": "2026-08-24T02:50:37.929Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "53e7de4aad7b2723",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 26161,
          "usage": {
            "input_tokens": 558,
            "output_tokens": 2167,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-37-a68b7c9c-7571-48d5-809a-77298fd0f07d.js.txt",
        "stats": {
          "unique": 417,
          "meanLuma": 21.19978072916676,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "131981eda189d748d058701e670bfca1a989c07a5b5683905de93a4301e6f193",
          "png": "6773368904c3ef1f41e62623daa3db3e6e50ce470066f13f73615938fb25f6c6",
          "raw": "131981eda189d748d058701e670bfca1a989c07a5b5683905de93a4301e6f193"
        },
        "latencyMs": 26161,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 558,
              "output_tokens": 2167,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 26161
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:51:31.182Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 417,
          "meanLuma": 21.19978072916676,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861",
        "createdAt": "2026-08-24T02:50:41.872Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "56843f79f173ddf9",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 24689,
          "usage": {
            "input_tokens": 1449,
            "output_tokens": 2717,
            "total_tokens": 4166,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1446
            },
            "output_tokens_details": {
              "reasoning_tokens": 516
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-41-304c51ea-5a66-47b4-8491-7400165ec861.js.txt",
        "stats": {
          "unique": 344,
          "meanLuma": 29.554582638888974,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8dc86a979fb365473cff829c3b71c690a1f468914610b9af2b9056f8acabc3f4",
          "png": "f36fb292c535f54147194420ff99345ba6ab6320472d7d9178851d9880756f93",
          "raw": "8dc86a979fb365473cff829c3b71c690a1f468914610b9af2b9056f8acabc3f4"
        },
        "latencyMs": 24689,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1449,
              "output_tokens": 2717,
              "total_tokens": 4166,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1446
              },
              "output_tokens_details": {
                "reasoning_tokens": 516
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 24689
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:51:25.728Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 344,
          "meanLuma": 29.554582638888974,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c",
        "createdAt": "2026-08-24T02:50:42.339Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "fcb129e5738e8537",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 30748,
          "usage": {
            "input_tokens": 1582,
            "output_tokens": 1931,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c/painting.png",
        "projectSource": "sketches/2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c.png",
        "source": "/images/model-painting-study/2026-08-24T02-50-42-7af72b69-dfe6-457b-ad91-8636e76b521c.js.txt",
        "stats": {
          "unique": 224,
          "meanLuma": 20.872772048611004,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "d7d5b83b39d084b8de425a51df997d081e66a4b9993460237ec57284248df27f",
          "png": "c219038bdf4f2ccac1b52a51b5171a6ac981f0964bf660440e971a8403fdf430",
          "raw": "d7d5b83b39d084b8de425a51df997d081e66a4b9993460237ec57284248df27f"
        },
        "latencyMs": 30748,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1582,
              "output_tokens": 1931,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 30748
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:51:22.456Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 224,
          "meanLuma": 20.872772048611004,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582",
        "createdAt": "2026-08-24T02:51:01.731Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5ec025f8c65eb8b2",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 67272,
          "usage": {
            "input_tokens": 1797,
            "output_tokens": 4154,
            "total_tokens": 5951,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 109
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582/painting.png",
        "projectSource": "sketches/2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582.png",
        "source": "/images/model-painting-study/2026-08-24T02-51-01-19cbeb98-9a57-4f79-8bad-451670de9582.js.txt",
        "stats": {
          "unique": 626,
          "meanLuma": 28.971536197916507,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8d48a3e54eb711a22f68677e560417b643f2b65ab7a8e182c7dd203369b14b62",
          "png": "c2ef7459326901875f4cea0a2cd78acbb4f31ccdcd27c96ddb68ec2ef3ec9fa8",
          "raw": "8d48a3e54eb711a22f68677e560417b643f2b65ab7a8e182c7dd203369b14b62"
        },
        "latencyMs": 67272,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1797,
              "output_tokens": 4154,
              "total_tokens": 5951,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 109
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 67272
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:52:20.927Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 626,
          "meanLuma": 28.971536197916507,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246",
        "createdAt": "2026-08-24T02:51:25.733Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "fb3cb1a909e623a3",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 23925,
          "usage": {
            "input_tokens": 1525,
            "output_tokens": 3418,
            "total_tokens": 4943,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1522
            },
            "output_tokens_details": {
              "reasoning_tokens": 538
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246/painting.png",
        "projectSource": "sketches/2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246.png",
        "source": "/images/model-painting-study/2026-08-24T02-51-25-2e90a020-22a6-4386-ae21-447ccdf90246.js.txt",
        "stats": {
          "unique": 715,
          "meanLuma": 27.799463107639045,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e2c154c8f24843f07280beb483960a7e106e764d354223b2324b9b41d5cf2ea4",
          "png": "153c22629aa5f9c73cc4995dfae0ed1b5785671b6776e843358cda9a8c101a09",
          "raw": "e2c154c8f24843f07280beb483960a7e106e764d354223b2324b9b41d5cf2ea4"
        },
        "latencyMs": 23925,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1525,
              "output_tokens": 3418,
              "total_tokens": 4943,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1522
              },
              "output_tokens_details": {
                "reasoning_tokens": 538
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 23925
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:52:09.496Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 715,
          "meanLuma": 27.799463107639045,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf",
        "createdAt": "2026-08-24T02:51:26.979Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "d69ad4c5abaaf579",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 15052,
          "usage": {
            "prompt_tokens": 1536,
            "completion_tokens": 3186,
            "total_tokens": 4722,
            "cost": 0.0143625,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0143625,
              "upstream_inference_prompt_cost": 0.0014592,
              "upstream_inference_completions_cost": 0.0129033
            },
            "completion_tokens_details": {
              "reasoning_tokens": 629,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf/painting.png",
        "projectSource": "sketches/2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf.png",
        "source": "/images/model-painting-study/2026-08-24T02-51-26-7d3d0bd5-804d-4c08-beb9-34b804a0d3bf.js.txt",
        "stats": {
          "unique": 330,
          "meanLuma": 21.366886458332985,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "e3243ab619c627c3b9001560fe054d207875b7a0e16b1ef880d3c5969d4f9cee",
          "png": "c3b588c5af3c18c6a57882923b8c3f2ec3a4cbd2c2a741713fea53f3f855544e",
          "raw": "e3243ab619c627c3b9001560fe054d207875b7a0e16b1ef880d3c5969d4f9cee"
        },
        "latencyMs": 15052,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1536,
              "completion_tokens": 3186,
              "total_tokens": 4722,
              "cost": 0.0143625,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0143625,
                "upstream_inference_prompt_cost": 0.0014592,
                "upstream_inference_completions_cost": 0.0129033
              },
              "completion_tokens_details": {
                "reasoning_tokens": 629,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 15052
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:52:01.271Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 330,
          "meanLuma": 21.366886458332985,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa",
        "createdAt": "2026-08-24T02:52:01.275Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "23d64a8df7934dfd",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 43471,
          "usage": {
            "prompt_tokens": 1469,
            "completion_tokens": 6287,
            "total_tokens": 7756,
            "cost": 0.02693135,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.02693135,
              "upstream_inference_prompt_cost": 0.001469,
              "upstream_inference_completions_cost": 0.02546235
            },
            "completion_tokens_details": {
              "reasoning_tokens": 4641,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa/painting.png",
        "projectSource": "sketches/2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa.png",
        "source": "/images/model-painting-study/2026-08-24T02-52-01-3953cc60-e130-438a-877a-f60ce8a043aa.js.txt",
        "stats": {
          "unique": 348,
          "meanLuma": 20.32308194444419,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5167376cb445e95c19b3eb1d5360d4aaf5865089b630ac3f6c7ca33d58e7d510",
          "png": "dcd4db3a950491c456fe599bde3de0029d90acafbcc78db0e76c64992e67ea18",
          "raw": "5167376cb445e95c19b3eb1d5360d4aaf5865089b630ac3f6c7ca33d58e7d510"
        },
        "latencyMs": 43471,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1469,
              "completion_tokens": 6287,
              "total_tokens": 7756,
              "cost": 0.02693135,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.02693135,
                "upstream_inference_prompt_cost": 0.001469,
                "upstream_inference_completions_cost": 0.02546235
              },
              "completion_tokens_details": {
                "reasoning_tokens": 4641,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 43471
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:53:08.460Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 348,
          "meanLuma": 20.32308194444419,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba",
        "createdAt": "2026-08-24T02:52:09.500Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "1bf63b849e0339ab",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 24530,
          "usage": {
            "input_tokens": 1457,
            "output_tokens": 3090,
            "total_tokens": 4547,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1454
            },
            "output_tokens_details": {
              "reasoning_tokens": 831
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba/painting.png",
        "projectSource": "sketches/2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba.png",
        "source": "/images/model-painting-study/2026-08-24T02-52-09-acb95df9-4b1f-41ee-8433-7d7d44873fba.js.txt",
        "stats": {
          "unique": 627,
          "meanLuma": 33.85153394097225,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "2949122b8b2e79a002306308a3e9b11c78e268f27eff34a86e3aa0b3c784a9af",
          "png": "5ffb584aed1720ef588d7a576c4f5fd23ef7db9102a0e835c38c8c2e11dbf231",
          "raw": "2949122b8b2e79a002306308a3e9b11c78e268f27eff34a86e3aa0b3c784a9af"
        },
        "latencyMs": 24530,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1457,
              "output_tokens": 3090,
              "total_tokens": 4547,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1454
              },
              "output_tokens_details": {
                "reasoning_tokens": 831
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 24530
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:52:53.622Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 627,
          "meanLuma": 33.85153394097225,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5",
        "createdAt": "2026-08-24T02:52:20.931Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "35a6fb984f12b442",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 76339,
          "usage": {
            "input_tokens": 1799,
            "output_tokens": 5463,
            "total_tokens": 7262,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 131
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5/painting.png",
        "projectSource": "sketches/2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5.png",
        "source": "/images/model-painting-study/2026-08-24T02-52-20-c70af6f9-288a-43ea-8f50-ea7558e07cb5.js.txt",
        "stats": {
          "unique": 668,
          "meanLuma": 27.722004687499847,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5db7143140934d242e7cafe71314fad046c3a030b2ee0dcebcb185cb4a3a31ef",
          "png": "01f49e6d7c66af2ffc59a7da68311d264f04e24a5e96703a691f134d2a18b8df",
          "raw": "5db7143140934d242e7cafe71314fad046c3a030b2ee0dcebcb185cb4a3a31ef"
        },
        "latencyMs": 76339,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1799,
              "output_tokens": 5463,
              "total_tokens": 7262,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 131
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 76339
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:53:55.808Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 668,
          "meanLuma": 27.722004687499847,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5",
        "createdAt": "2026-08-24T02:52:53.645Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "gpt-5.6-luna",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "25ff9d1b226fcbbb",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "gpt-5.6-luna",
          "protocol": "responses",
          "latencyMs": 20219,
          "usage": {
            "input_tokens": 1505,
            "output_tokens": 2939,
            "total_tokens": 4444,
            "input_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 1502
            },
            "output_tokens_details": {
              "reasoning_tokens": 516
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5/painting.png",
        "projectSource": "sketches/2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5.png",
        "source": "/images/model-painting-study/2026-08-24T02-52-53-5f092bb1-c60c-4370-9c4a-e7bb875ea5b5.js.txt",
        "stats": {
          "unique": 291,
          "meanLuma": 21.410042881944104,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "202039830f4c7a0555ea6f6cc74716addcfca3f1988aa7b52c68f5872fa138b1",
          "png": "0014266258dec69bf17a696220c21e955ef339fd6b2d66b6a3e42abb01408b7f",
          "raw": "202039830f4c7a0555ea6f6cc74716addcfca3f1988aa7b52c68f5872fa138b1"
        },
        "latencyMs": 20219,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1505,
              "output_tokens": 2939,
              "total_tokens": 4444,
              "input_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 1502
              },
              "output_tokens_details": {
                "reasoning_tokens": 516
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "gpt-5.6-luna",
            "protocol": "responses",
            "latencyMs": 20219
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:53:27.520Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 291,
          "meanLuma": 21.410042881944104,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479",
        "createdAt": "2026-08-24T02:53:08.481Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "f789462a6ca7a2c0",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 33023,
          "usage": {
            "prompt_tokens": 1517,
            "completion_tokens": 5016,
            "total_tokens": 6533,
            "cost": 0.0218318,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.0218318,
              "upstream_inference_prompt_cost": 0.001517,
              "upstream_inference_completions_cost": 0.0203148
            },
            "completion_tokens_details": {
              "reasoning_tokens": 3637,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479/painting.png",
        "projectSource": "sketches/2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479.png",
        "source": "/images/model-painting-study/2026-08-24T02-53-08-2a73717a-9228-4b27-9473-d06350c3e479.js.txt",
        "stats": {
          "unique": 218,
          "meanLuma": 19.87480460069409,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5dc5c760989c14300e21aec45400fc396a0d70f459dfaa39222e333b95bac305",
          "png": "184148da923deb5cd215db622db6c81c26413e7f7b77365bc017742d9faa8fe3",
          "raw": "5dc5c760989c14300e21aec45400fc396a0d70f459dfaa39222e333b95bac305"
        },
        "latencyMs": 33023,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1517,
              "completion_tokens": 5016,
              "total_tokens": 6533,
              "cost": 0.0218318,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.0218318,
                "upstream_inference_prompt_cost": 0.001517,
                "upstream_inference_completions_cost": 0.0203148
              },
              "completion_tokens_details": {
                "reasoning_tokens": 3637,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 33023
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:53:59.064Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 218,
          "meanLuma": 19.87480460069409,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7",
        "createdAt": "2026-08-24T02:54:18.963Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "openrouter",
        "model": "thinkingmachines/inkling",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "18593f88d2cabf08",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "openrouter",
          "model": "thinkingmachines/inkling",
          "protocol": "chat",
          "latencyMs": 13088,
          "usage": {
            "prompt_tokens": 1461,
            "completion_tokens": 3435,
            "total_tokens": 4896,
            "cost": 0.01420411,
            "is_byok": false,
            "prompt_tokens_details": {
              "cached_tokens": 1408,
              "cache_write_tokens": 0,
              "audio_tokens": 0,
              "video_tokens": 0
            },
            "cost_details": {
              "upstream_inference_cost": 0.01420411,
              "upstream_inference_prompt_cost": 0.00029236,
              "upstream_inference_completions_cost": 0.01391175
            },
            "completion_tokens_details": {
              "reasoning_tokens": 529,
              "image_tokens": 0,
              "audio_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7/painting.png",
        "projectSource": "sketches/2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7.png",
        "source": "/images/model-painting-study/2026-08-24T02-54-18-d04339fe-e0e7-4600-9fea-4cdc686fb3e7.js.txt",
        "stats": {
          "unique": 830,
          "meanLuma": 21.04633749999993,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "0bd5952aeddb00ae91da1c01f9cf189ec9617dfaf0d41aab6fc4efcd69575a6a",
          "png": "476cd6131363d5d84eaf9e12847e5a8ecdb89265d1c61911eaca24df605c985c",
          "raw": "0bd5952aeddb00ae91da1c01f9cf189ec9617dfaf0d41aab6fc4efcd69575a6a"
        },
        "latencyMs": 13088,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1461,
              "completion_tokens": 3435,
              "total_tokens": 4896,
              "cost": 0.01420411,
              "is_byok": false,
              "prompt_tokens_details": {
                "cached_tokens": 1408,
                "cache_write_tokens": 0,
                "audio_tokens": 0,
                "video_tokens": 0
              },
              "cost_details": {
                "upstream_inference_cost": 0.01420411,
                "upstream_inference_prompt_cost": 0.00029236,
                "upstream_inference_completions_cost": 0.01391175
              },
              "completion_tokens_details": {
                "reasoning_tokens": 529,
                "image_tokens": 0,
                "audio_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "openrouter",
            "model": "thinkingmachines/inkling",
            "protocol": "chat",
            "latencyMs": 13088
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T02:54:48.440Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 830,
          "meanLuma": 21.04633749999993,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0",
        "createdAt": "2026-08-24T03:36:38.994Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "d2c05cbb65e44c88",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 140329,
          "usage": {
            "prompt_tokens": 1512,
            "completion_tokens": 8192,
            "total_tokens": 9704,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0/painting.png",
        "projectSource": "sketches/2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0.png",
        "source": "/images/model-painting-study/2026-08-24T03-36-38-ecc678e3-925d-4268-9e41-5c35ef7730a0.js.txt",
        "stats": {
          "unique": 421,
          "meanLuma": 22.303814322916654,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "2a74c3a4931b8afdd1fca934308cde75289b7311f808ab7651aa0eadacda991b",
          "png": "b833eef4ee346141fc4eec0312d636145c04dcac2acc53fdd60e9e761d9973b2",
          "raw": "b9d25081c3e72ade437d2e47ed81d9b86c052d0bb78822bcb8cce02b1b5d243a"
        },
        "latencyMs": 140329,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1512,
              "completion_tokens": 8192,
              "total_tokens": 9704,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 140329
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:39:20.165Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 421,
          "meanLuma": 22.303814322916654,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc",
        "createdAt": "2026-08-24T03:36:38.998Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "dd4f754646aaf2d5",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 60676,
          "usage": {
            "input_tokens": 957,
            "output_tokens": 4652,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 640
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc/painting.png",
        "projectSource": "sketches/2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc.png",
        "source": "/images/model-painting-study/2026-08-24T03-36-38-4c97631a-31ad-4048-af35-435f3ae5f6fc.js.txt",
        "stats": {
          "unique": 515,
          "meanLuma": 23.545726736110417,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "4af29a7adc82175b66feb0022a50bf7a1db81913db3d35746a5739b9ba64ad04",
          "png": "2e41e7682e2d3619d9837e777a188a82169543011a09b4b95ad5982afd9c23c1",
          "raw": "4af29a7adc82175b66feb0022a50bf7a1db81913db3d35746a5739b9ba64ad04"
        },
        "latencyMs": 60676,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 957,
              "output_tokens": 4652,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 640
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 60676
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:38:05.041Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 515,
          "meanLuma": 23.545726736110417,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71",
        "createdAt": "2026-08-24T03:38:28.830Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "bac1439963f99740",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 24437,
          "usage": {
            "input_tokens": 563,
            "output_tokens": 1993,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71/painting.png",
        "projectSource": "sketches/2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71.png",
        "source": "/images/model-painting-study/2026-08-24T03-38-28-29ebe02d-b587-4a13-bcf6-d4201657ab71.js.txt",
        "stats": {
          "unique": 419,
          "meanLuma": 18.872649739583345,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "be290d658f397d1ed42e60601d4c1a5c291118fb03be3930bdb41cdf994ee062",
          "png": "34482301f6f5b0cc865201181109af907ddb421d441c783fc52c0bf45eca29b4",
          "raw": "be290d658f397d1ed42e60601d4c1a5c291118fb03be3930bdb41cdf994ee062"
        },
        "latencyMs": 24437,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 563,
              "output_tokens": 1993,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 24437
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:39:26.404Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 419,
          "meanLuma": 18.872649739583345,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e",
        "createdAt": "2026-08-24T03:39:20.167Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e129d3df5ef49b40",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 136163,
          "usage": {
            "prompt_tokens": 1511,
            "completion_tokens": 8192,
            "total_tokens": 9703,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 135196,
          "usage": {
            "prompt_tokens": 1622,
            "completion_tokens": 8192,
            "total_tokens": 9814,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e/painting.png",
        "projectSource": "sketches/2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e.png",
        "source": "/images/model-painting-study/2026-08-24T03-39-20-78061eb9-5ab2-418d-b990-b9dc0e588a1e.js.txt",
        "stats": {
          "unique": 509,
          "meanLuma": 24.577878993055652,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "dd6b1358546dc2a695426635db4016fc548d10ba9a80f8d0b07466b886e67f2a",
          "png": "4c61fdb59ef191b06aaa7c13dd1e5f888c8c85c675ecaa1efe651c7713c583a9",
          "raw": "887daefe3845859e38b5a007c777b2cab74808067033b2c20b00ee0d7d72e48d"
        },
        "latencyMs": 271359,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1511,
              "completion_tokens": 8192,
              "total_tokens": 9703,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1622,
              "completion_tokens": 8192,
              "total_tokens": 9814,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 136163
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 135196
          }
        ]
      },
      "failure": null,
      "eventCount": 3,
      "lastEvent": {
        "at": "2026-08-24T03:44:16.779Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 509,
          "meanLuma": 24.577878993055652,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5",
        "createdAt": "2026-08-24T03:39:26.406Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "f81d9651f954b59c",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 22783,
          "usage": {
            "input_tokens": 620,
            "output_tokens": 1740,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5/painting.png",
        "projectSource": "sketches/2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5.png",
        "source": "/images/model-painting-study/2026-08-24T03-39-26-0065daa6-1814-4f84-b281-b3e0cb7c50d5.js.txt",
        "stats": {
          "unique": 210,
          "meanLuma": 20.874453385416224,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8bbe8adf0e01e1288bb5a3d18baf81d1908e321adaf72849e8c47a683dec9f02",
          "png": "244d3c805b51f55dfcc51e24580419016b255c9d970474ef21e02a70b9e2bebb",
          "raw": "8bbe8adf0e01e1288bb5a3d18baf81d1908e321adaf72849e8c47a683dec9f02"
        },
        "latencyMs": 22783,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 620,
              "output_tokens": 1740,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 22783
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:40:04.650Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 210,
          "meanLuma": 20.874453385416224,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48",
        "createdAt": "2026-08-24T03:41:14.425Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "23bea13f26ba44d7",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 52961,
          "usage": {
            "input_tokens": 963,
            "output_tokens": 4222,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 640
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 20268,
          "usage": {
            "input_tokens": 5708,
            "output_tokens": 4022,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48/painting.png",
        "projectSource": "sketches/2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48.png",
        "source": "/images/model-painting-study/2026-08-24T03-41-14-ac8c6467-e51f-4f2b-905e-502c3ee10e48.js.txt",
        "stats": {
          "unique": 426,
          "meanLuma": 21.53426171874992,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "45eacdc05795ca52515808a43b1b570c72533870a3b378f33213a87f69f3c77c",
          "png": "92879deb7116f8e5d04378f733c1c197d1505bc37373290a1e40f20b3a69fba1",
          "raw": "3a783e3108bbdf73521ce00adb049fffb7c57027f6f761a42e77fc1b742068f8"
        },
        "latencyMs": 73229,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 963,
              "output_tokens": 4222,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 640
            }
          },
          {
            "stage": "repair",
            "usage": {
              "input_tokens": 5708,
              "output_tokens": 4022,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 52961
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 20268
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T03:43:31.511Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 426,
          "meanLuma": 21.53426171874992,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949",
        "createdAt": "2026-08-24T03:42:56.350Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e968a4dabe9fc71e",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 6658,
          "usage": {
            "prompt_tokens": 1534,
            "completion_tokens": 1937,
            "total_tokens": 3471,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949/painting.png",
        "projectSource": "sketches/2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949.png",
        "source": "/images/model-painting-study/2026-08-24T03-42-56-c51b0639-802a-44b2-a9b0-69fe0e6db949.js.txt",
        "stats": {
          "unique": 363,
          "meanLuma": 30.878983420139214,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "89287a62c93498f8b09966a6a965fb12fdb4187f76128a5b148ebc8eb2dda4b7",
          "png": "bf18d40ee780df06cd3f25b7a52e088bfe704ea988bb81c88d0a98940cb3b908",
          "raw": "2914e77476dbdac41ffc59933aff6f86815221eb7053e8954873d13565ad04b9"
        },
        "latencyMs": 6658,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1534,
              "completion_tokens": 1937,
              "total_tokens": 3471,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 6658
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:43:15.459Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 363,
          "meanLuma": 30.878983420139214,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5",
        "createdAt": "2026-08-24T03:43:15.461Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "1cd47cdf0e2f4fa0",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 6122,
          "usage": {
            "prompt_tokens": 1501,
            "completion_tokens": 2018,
            "total_tokens": 3519,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 5939,
          "usage": {
            "prompt_tokens": 3535,
            "completion_tokens": 2160,
            "total_tokens": 5695,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5/painting.png",
        "projectSource": "sketches/2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5.png",
        "source": "/images/model-painting-study/2026-08-24T03-43-15-ea76f51e-19a3-4f8a-98a3-1c08575d06b5.js.txt",
        "stats": {
          "unique": 370,
          "meanLuma": 23.74568159722204,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "8337e8b2f5f47783210cc8719626886327158bc774dbf75e163d9534daba09a8",
          "png": "a433a8972d34741e8031fc32f5c728381b77fbfdc97c2a801ea141b0bb63b6aa",
          "raw": "e3d9fa923170df774755823c2130b0f8faf752ac3b488bf653654c9004e442a9"
        },
        "latencyMs": 12061,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1501,
              "completion_tokens": 2018,
              "total_tokens": 3519,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 3535,
              "completion_tokens": 2160,
              "total_tokens": 5695,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 6122
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 5939
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T03:43:41.610Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 370,
          "meanLuma": 23.74568159722204,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac",
        "createdAt": "2026-08-24T03:43:31.514Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "2f14615613e3a770",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 43596,
          "usage": {
            "input_tokens": 504,
            "output_tokens": 3225,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1152
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac/painting.png",
        "projectSource": "sketches/2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac.png",
        "source": "/images/model-painting-study/2026-08-24T03-43-31-a52a3a06-5965-487d-9db8-37e096fd66ac.js.txt",
        "stats": {
          "unique": 159,
          "meanLuma": 19.080136631944022,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "9ba65cf49ffee9fa8209f38075b33af7496cf141ce54db0de2a4f7694394564e",
          "png": "28947780504669ee173e3d103de4869c5fc54b9f96fae40054811af644da5f9a",
          "raw": "9ba65cf49ffee9fa8209f38075b33af7496cf141ce54db0de2a4f7694394564e"
        },
        "latencyMs": 43596,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 504,
              "output_tokens": 3225,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1152
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 43596
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:44:44.688Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 159,
          "meanLuma": 19.080136631944022,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f",
        "createdAt": "2026-08-24T03:43:41.612Z",
        "prompt": "Daniel calm among two watchful lions in a dark stone den, one narrow shaft of light, courage without spectacle",
        "promptId": "lions-den-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "lions-den-sacred-v9",
        "artDirection": "Paint Daniel calm and awake in a dark stone den, seated or kneeling near x=245..355 and y=220..490, with a readable head, shoulders, simple robe, hands, and grounded posture. Place one lion resting across the lower left and a second lion resting across the lower right. Give each a distinct head, muzzle, irregular mane, back, haunch, and forepaws; both animals remain watchful but peaceful, never roaring mascots. Let one narrow shaft of moonlit ivory enter from the upper left and touch Daniel's face and hands, while restrained royal-blue reflected light separates all three silhouettes from the blue-black stone. Keep the outer walls broken and subordinate. The stillness is the subject. No cage bars, bones, gore, crowns, angel wings, text, decorative arch, children's-book faces, or symmetrical heraldic arrangement.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2412,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e3bf750b07658d03",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 10276,
          "usage": {
            "prompt_tokens": 1497,
            "completion_tokens": 3238,
            "total_tokens": 4735,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f/painting.png",
        "projectSource": "sketches/2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f.png",
        "source": "/images/model-painting-study/2026-08-24T03-43-41-e0ad9d7d-60bc-4f1c-b14c-1d9ef4a6be9f.js.txt",
        "stats": {
          "unique": 461,
          "meanLuma": 47.601494357640476,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "4ce5bb2f233f82c56044f77339891a518d34e773ae971acc5185c608eac605bb",
          "png": "e8fd96e0f65fb0256d77e6379bde440735d32703dcde09602bbc2c4e8e5fa2c9",
          "raw": "42f50f723daee275fc2b49e6d5daa688c918e32fd883e6f5a992bb83fa8af0f7"
        },
        "latencyMs": 10276,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1497,
              "completion_tokens": 3238,
              "total_tokens": 4735,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 10276
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:44:16.472Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 461,
          "meanLuma": 47.601494357640476,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092",
        "createdAt": "2026-08-24T03:44:16.475Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "56de46df75aed7b2",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 9037,
          "usage": {
            "prompt_tokens": 1573,
            "completion_tokens": 2670,
            "total_tokens": 4243,
            "prompt_tokens_details": {
              "cached_tokens": 0,
              "cache_write_tokens": null
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 8131,
          "usage": {
            "prompt_tokens": 4258,
            "completion_tokens": 2825,
            "total_tokens": 7083,
            "prompt_tokens_details": {
              "cached_tokens": 512,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092/painting.png",
        "projectSource": "sketches/2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092.png",
        "source": "/images/model-painting-study/2026-08-24T03-44-16-56e648e9-4d21-4a62-92c7-fab83d72c092.js.txt",
        "stats": {
          "unique": 148,
          "meanLuma": 19.71067022569414,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "21e2e5711648c7266bb271978d7034b9fe644b9a22bcaf1a8087db657d554fe8",
          "png": "75aa330ba81c5c3fd1eb6763b0fbbde3597fdf571ec4c17cb1e33c930c8e220c",
          "raw": "bf1a18e52df1c724336af1bef6c76bf1e5bd2f239a4fc7ec2e586fa734a46f0d"
        },
        "latencyMs": 17168,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1573,
              "completion_tokens": 2670,
              "total_tokens": 4243,
              "prompt_tokens_details": {
                "cached_tokens": 0,
                "cache_write_tokens": null
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 4258,
              "completion_tokens": 2825,
              "total_tokens": 7083,
              "prompt_tokens_details": {
                "cached_tokens": 512,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 9037
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 8131
          }
        ]
      },
      "failure": null,
      "eventCount": 3,
      "lastEvent": {
        "at": "2026-08-24T03:44:42.109Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 148,
          "meanLuma": 19.71067022569414,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd",
        "createdAt": "2026-08-24T03:44:16.782Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "ed74952eeb191651",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 133495,
          "usage": {
            "prompt_tokens": 1591,
            "completion_tokens": 8192,
            "total_tokens": 9783,
            "prompt_tokens_details": {
              "cached_tokens": 512
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 126722,
          "usage": {
            "prompt_tokens": 6426,
            "completion_tokens": 8192,
            "total_tokens": 14618,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 138801,
          "usage": {
            "prompt_tokens": 1789,
            "completion_tokens": 8192,
            "total_tokens": 9981,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd/painting.png",
        "projectSource": "sketches/2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd.png",
        "source": "/images/model-painting-study/2026-08-24T03-44-16-9dc1b41f-533b-4952-98c1-ab9945c817bd.js.txt",
        "stats": {
          "unique": 391,
          "meanLuma": 21.91141493055575,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "566187ee7c456c8a27c1926203b92855cf684032a714c51e2700fbf00238aec2",
          "png": "d47a696c51a51da9efe4dc51623ff1e4c34da06095c1d7e1996cee9ba731d801",
          "raw": "25908363e9c218856f2855631d3a3fa2aea6931d0ad62fcdd16880fb02fb3e99"
        },
        "latencyMs": 399018,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1591,
              "completion_tokens": 8192,
              "total_tokens": 9783,
              "prompt_tokens_details": {
                "cached_tokens": 512
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 6426,
              "completion_tokens": 8192,
              "total_tokens": 14618,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 1789,
              "completion_tokens": 8192,
              "total_tokens": 9981,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 133495
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 126722
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 138801
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T03:51:19.525Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 391,
          "meanLuma": 21.91141493055575,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c",
        "createdAt": "2026-08-24T03:44:42.112Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "f0f7ebbd92f7ee91",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 10641,
          "usage": {
            "prompt_tokens": 1502,
            "completion_tokens": 3648,
            "total_tokens": 5150,
            "prompt_tokens_details": {
              "cached_tokens": 512,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c/painting.png",
        "projectSource": "sketches/2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c.png",
        "source": "/images/model-painting-study/2026-08-24T03-44-42-d7cc9439-f213-467a-8e91-b90ffdca693c.js.txt",
        "stats": {
          "unique": 1039,
          "meanLuma": 31.18365138888888,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "69ebf9b4ac6608a9b698d215f09507098d3f8def71263b6fe6f3f5fc499e1977",
          "png": "d5dced29d8076dba252412922b9a79688bbde437cc268bbee84458f1c2ad7c3b",
          "raw": "8cd0ce7581628e355c16693948d69e94d58dec9baf26df264cb93f29a0858a0d"
        },
        "latencyMs": 10641,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1502,
              "completion_tokens": 3648,
              "total_tokens": 5150,
              "prompt_tokens_details": {
                "cached_tokens": 512,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 10641
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:45:30.545Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 1039,
          "meanLuma": 31.18365138888888,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53",
        "createdAt": "2026-08-24T03:45:30.547Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "deepseek-v4-flash",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "8d2a1bba17975743",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-flash",
          "protocol": "chat",
          "latencyMs": 8448,
          "usage": {
            "prompt_tokens": 1555,
            "completion_tokens": 2447,
            "total_tokens": 4002,
            "prompt_tokens_details": {
              "cached_tokens": 1024,
              "cache_write_tokens": null
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53/painting.png",
        "projectSource": "sketches/2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53.png",
        "source": "/images/model-painting-study/2026-08-24T03-45-30-242f1498-8a4b-4870-94b7-c1cdd9edcf53.js.txt",
        "stats": {
          "unique": 107,
          "meanLuma": 18.863740972222047,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "6f10e626d644c4f988d88cd3be9cec3fdf4a0857c36564f3bf34142e973d8040",
          "png": "3bd48c479d61ff33861d9d6705c7d8491372e072bb70cae6e68d2f52aa15ff56",
          "raw": "a74a4a9841caec0122d34a2c9bea69e29f93d40a5e927b91c26453cd465d1f8d"
        },
        "latencyMs": 8448,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1555,
              "completion_tokens": 2447,
              "total_tokens": 4002,
              "prompt_tokens_details": {
                "cached_tokens": 1024,
                "cache_write_tokens": null
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-flash",
            "protocol": "chat",
            "latencyMs": 8448
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:46:01.833Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 107,
          "meanLuma": 18.863740972222047,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5",
        "createdAt": "2026-08-24T03:45:39.108Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "418f9196d47fe64d",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 32252,
          "usage": {
            "input_tokens": 1662,
            "output_tokens": 1980,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5/painting.png",
        "projectSource": "sketches/2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5.png",
        "source": "/images/model-painting-study/2026-08-24T03-45-39-4c20aefc-20f0-43b8-a71a-b21f5cae21e5.js.txt",
        "stats": {
          "unique": 422,
          "meanLuma": 21.55733541666687,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "17def561bd8c49cade26acf7c752c79b96dc28556c330a4206b0a30f590cb7aa",
          "png": "25b38d66bf7deaf06670c6fd1f7452f79fbdcc1422e377ad6bd95a6b6b20a96c",
          "raw": "17def561bd8c49cade26acf7c752c79b96dc28556c330a4206b0a30f590cb7aa"
        },
        "latencyMs": 32252,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1662,
              "output_tokens": 1980,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 32252
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:46:27.024Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 422,
          "meanLuma": 21.55733541666687,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286",
        "createdAt": "2026-08-24T03:45:39.108Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "a78a63afe47cc201",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 53059,
          "usage": {
            "input_tokens": 1869,
            "output_tokens": 3521,
            "total_tokens": 5390,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 55
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286/painting.png",
        "projectSource": "sketches/2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286.png",
        "source": "/images/model-painting-study/2026-08-24T03-45-39-732a8358-8017-402c-a709-eea06f660286.js.txt",
        "stats": {
          "unique": 422,
          "meanLuma": 21.92325243055581,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "ad977448ee0a4d28771f818bd3e66956ca2576f2a12ec4e48b05ff23e99947fc",
          "png": "dbf89c15fdbe025f2dffe513d40b68fc3c6fdb410a9c41c859db0237496e1b32",
          "raw": "ad977448ee0a4d28771f818bd3e66956ca2576f2a12ec4e48b05ff23e99947fc"
        },
        "latencyMs": 53059,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1869,
              "output_tokens": 3521,
              "total_tokens": 5390,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 55
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 53059
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:46:57.691Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 422,
          "meanLuma": 21.92325243055581,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8",
        "createdAt": "2026-08-24T03:46:27.027Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "55a7277ef05e64f5",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 35310,
          "usage": {
            "input_tokens": 1587,
            "output_tokens": 2330,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8/painting.png",
        "projectSource": "sketches/2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8.png",
        "source": "/images/model-painting-study/2026-08-24T03-46-27-3d9e071d-326b-4632-8f51-ea4a5ae05ee8.js.txt",
        "stats": {
          "unique": 327,
          "meanLuma": 20.91013984375003,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "af280b830c31106e42de0c4d027326e6708a0c99ea6fc71672fb8952d4902a6c",
          "png": "ef477c067150db9bc55c6f7ce5b190289c4b11f0a6febdcff1d286263c020289",
          "raw": "af280b830c31106e42de0c4d027326e6708a0c99ea6fc71672fb8952d4902a6c"
        },
        "latencyMs": 35310,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1587,
              "output_tokens": 2330,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 35310
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:47:28.662Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 327,
          "meanLuma": 20.91013984375003,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020",
        "createdAt": "2026-08-24T03:46:57.692Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "e171746daf8897b5",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 68489,
          "usage": {
            "input_tokens": 1798,
            "output_tokens": 5085,
            "total_tokens": 6883,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 70
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020/painting.png",
        "projectSource": "sketches/2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020.png",
        "source": "/images/model-painting-study/2026-08-24T03-46-57-c1424ddc-a7b2-4696-bc46-f3be071bf020.js.txt",
        "stats": {
          "unique": 701,
          "meanLuma": 23.58813541666649,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "5cea9dc92582f2cc444819142efe21334819d5b802a7c5a57cc4216ec2540c95",
          "png": "68e4aeae2479f6737952bb5fd945c40fdef3ffea3168ce53109d5eb438ce9ed5",
          "raw": "5cea9dc92582f2cc444819142efe21334819d5b802a7c5a57cc4216ec2540c95"
        },
        "latencyMs": 68489,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1798,
              "output_tokens": 5085,
              "total_tokens": 6883,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 70
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 68489
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:48:41.690Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 701,
          "meanLuma": 23.58813541666649,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea",
        "createdAt": "2026-08-24T03:47:28.665Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "qwen3.7-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "7cc8fc459d2328be",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.7-max",
          "protocol": "messages",
          "latencyMs": 39267,
          "usage": {
            "input_tokens": 1644,
            "output_tokens": 2613,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 0
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea/painting.png",
        "projectSource": "sketches/2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea.png",
        "source": "/images/model-painting-study/2026-08-24T03-47-28-b7ec6e28-78d5-4f05-a86c-11a5e48899ea.js.txt",
        "stats": {
          "unique": 153,
          "meanLuma": 19.486805555555335,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "19eb18044b7ee9f92169347d9264c8e44463471393c1aa276eded6ab0369af82",
          "png": "c4172047bd5722c6536d0c95faf85f103be73ccd931b6445776e9a4b031680ad",
          "raw": "19eb18044b7ee9f92169347d9264c8e44463471393c1aa276eded6ab0369af82"
        },
        "latencyMs": 39267,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1644,
              "output_tokens": 2613,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 0
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.7-max",
            "protocol": "messages",
            "latencyMs": 39267
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:48:25.703Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 153,
          "meanLuma": 19.486805555555335,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874",
        "createdAt": "2026-08-24T03:48:41.692Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "grok-4.5",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "b20e211f560e9ed3",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "grok-4.5",
          "protocol": "responses",
          "latencyMs": 57100,
          "usage": {
            "input_tokens": 1846,
            "output_tokens": 3820,
            "total_tokens": 5666,
            "input_tokens_details": {
              "cached_tokens": 128
            },
            "output_tokens_details": {
              "reasoning_tokens": 142
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874/painting.png",
        "projectSource": "sketches/2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874.png",
        "source": "/images/model-painting-study/2026-08-24T03-48-41-d32389cb-2144-4377-8066-e0ccf2b2a874.js.txt",
        "stats": {
          "unique": 193,
          "meanLuma": 20.1641829861114,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "a46117c8c509b6e579f2c6b1b85ff5bfe09d3176aec12cf8e049cea849521e0c",
          "png": "96813d62b226409c120acf45bcb8bbcc8e7f28d932ca921ff17c4d92eb77d85e",
          "raw": "a46117c8c509b6e579f2c6b1b85ff5bfe09d3176aec12cf8e049cea849521e0c"
        },
        "latencyMs": 57100,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1846,
              "output_tokens": 3820,
              "total_tokens": 5666,
              "input_tokens_details": {
                "cached_tokens": 128
              },
              "output_tokens_details": {
                "reasoning_tokens": 142
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "grok-4.5",
            "protocol": "responses",
            "latencyMs": 57100
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:49:54.316Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 193,
          "meanLuma": 20.1641829861114,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744",
        "createdAt": "2026-08-24T03:49:10.484Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "minimax-m3",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "5909c51cdfc5ebbb",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "minimax-m3",
          "protocol": "messages",
          "latencyMs": 20952,
          "usage": {
            "input_tokens": 1544,
            "output_tokens": 3255,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 131
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744/painting.png",
        "projectSource": "sketches/2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744.png",
        "source": "/images/model-painting-study/2026-08-24T03-49-10-b9c70fd4-5ae9-4d5b-b4d5-b1f64b747744.js.txt",
        "stats": {
          "unique": 120,
          "meanLuma": 18.602448090277655,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "eb7db0f84c0540eaf30eca1647f6e494badc72be68dbc5a1c6d51491244dd73b",
          "png": "7002e213081f3fc33d4f6cd85dfee1e4afceeda2269341bcd8f3a9923a9e6d7e",
          "raw": "eb7db0f84c0540eaf30eca1647f6e494badc72be68dbc5a1c6d51491244dd73b"
        },
        "latencyMs": 20952,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 1544,
              "output_tokens": 3255,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 131
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "minimax-m3",
            "protocol": "messages",
            "latencyMs": 20952
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:49:34.099Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 120,
          "meanLuma": 18.602448090277655,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539",
        "createdAt": "2026-08-24T03:49:34.105Z",
        "prompt": "a small fishing boat in a violent night storm on Galilee, frightened disciples around one calm central figure, deep royal-blue waves",
        "promptId": "storm-galilee-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "storm-galilee-sacred-v9",
        "artDirection": "Paint a small first-century fishing boat pitched diagonally across x=85..515 and y=300..485 in a severe night storm. Build a curved hull, one bent mast, a torn triangular sail, and three to five readable human silhouettes rather than a modern ship. Make two layered royal-blue waves cross the lower half with pale broken crests. The boat may tilt but must remain fully on-canvas; keep the hull and central figures darker and crisper than the rain. Place one calm central figure near (330, 315), upright with a compact moonlit edge, while the other disciples brace, crouch, or pull a rope. Show calm amid fear through posture, not a spotlight or supernatural beam. Use blue-black, two royal blues, slate, moonlit ivory, and one muted-gold lamp mark. No giant face in the clouds, cross-shaped mast emphasis, text, logo, modern life jackets, decorative border, or wall of tiny wave marks.",
        "provider": "opencode-go",
        "model": "qwen3.8-max",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2413,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "ec5e623e3d4a91ae",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "qwen3.8-max",
          "protocol": "messages",
          "latencyMs": 25318,
          "usage": {
            "input_tokens": 638,
            "output_tokens": 2133,
            "cache_creation_input_tokens": 0,
            "cache_read_input_tokens": 1024
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539/painting.png",
        "projectSource": "sketches/2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539.png",
        "source": "/images/model-painting-study/2026-08-24T03-49-34-9bf3c184-8972-4bec-b6d9-98564cde0539.js.txt",
        "stats": {
          "unique": 500,
          "meanLuma": 22.349875000000274,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "c63a9b434c5479e15227f05259b90b6a47317623730b9d2982aef55452659b2f",
          "png": "9ea8086c9a9207e7436a9c15df12efb771073b1c76924b56d16fdde3d0c7e06a",
          "raw": "c63a9b434c5479e15227f05259b90b6a47317623730b9d2982aef55452659b2f"
        },
        "latencyMs": 25318,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "input_tokens": 638,
              "output_tokens": 2133,
              "cache_creation_input_tokens": 0,
              "cache_read_input_tokens": 1024
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "qwen3.8-max",
            "protocol": "messages",
            "latencyMs": 25318
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:50:11.049Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 500,
          "meanLuma": 22.349875000000274,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5",
        "createdAt": "2026-08-24T03:51:19.528Z",
        "prompt": "a small procession crossing a narrow dry path between towering sea walls at midnight, deliverance toward one distant warm light",
        "promptId": "midnight-exodus-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "midnight-exodus-sacred-v9",
        "artDirection": "Paint a narrow dry path receding from x=190..420 at the lower edge toward x=285..325 near y=135, held between two towering but unequal dark sea walls that occupy the outer thirds. Lead a small procession of eight to twelve simplified human figures along the path. Make the nearest two figures readable with heads, cloaks, arms, and steps; let the rest diminish toward one distant warm light without becoming a dotted pattern. Separate the water from the blue-black sky with broad royal-blue and slate-green masses plus a few moonlit ivory edges. Keep the open path and forward motion legible at thumbnail size and leave the upper center quiet. Treat deliverance with scale and restraint. No pyramids, chariots, armies, flags, readable tablets, giant divine face, split-screen symmetry, lettering, logo, or decorative frame.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "ink",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2414,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "8825a5c1bf61e774",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 132623,
          "usage": {
            "prompt_tokens": 1516,
            "completion_tokens": 8192,
            "total_tokens": 9708,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5/painting.png",
        "projectSource": "sketches/2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5.png",
        "source": "/images/model-painting-study/2026-08-24T03-51-19-783b3caa-5461-4313-a275-707b548049a5.js.txt",
        "stats": {
          "unique": 152,
          "meanLuma": 18.06158350694443,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "314712207f2367b9245f818ca81d1833795869e4a42208fe8fb943e38a2fe646",
          "png": "ead3876cda3423c97472b91c2282ed3a75a6c5c4f53ecf786be2ba9a38099011",
          "raw": "3459c710dff31c9ba2132f477abc52047613ad4edece6f655e16ff50174d45ce"
        },
        "latencyMs": 132623,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1516,
              "completion_tokens": 8192,
              "total_tokens": 9708,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 132623
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:54:13.495Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 152,
          "meanLuma": 18.06158350694443,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1",
        "createdAt": "2026-08-24T03:51:40.371Z",
        "prompt": "Jacob wrestling a mysterious stranger beside the river until first light, sacred endurance, royal-blue night breaking into one muted-gold dawn",
        "promptId": "wrestling-at-dawn-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "wrestling-at-dawn-sacred-v9",
        "artDirection": "Paint Jacob wrestling a mysterious angelic stranger beside a river just before dawn. Make the two believable human figures one joined diagonal mass spanning roughly x=125..475 and y=145..500, with distinct heads, shoulders, torsos, gripping arms, bent legs, and grounded feet. Use overlapping royal-blue and slate shapes to show strain without depicting injury. One figure leans from the left and one braces from the right; keep their gestures unequal and the faces merely implied. Reserve the lower fifth for a narrow silver-blue riverbank and place one thin muted-gold dawn band low on the horizon. The locked hands and opposing shoulders are the crisp focal area; the surrounding night stays broad and quiet. Treat the encounter as sacred endurance, not a wrestling poster or fantasy fight. No wings, weapons, gore, crowd, arena, halo, lettering, logo symmetry, or theatrical lightning.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2411,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "24eb5dd0639e1d60",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 145545,
          "usage": {
            "prompt_tokens": 1580,
            "completion_tokens": 11954,
            "total_tokens": 13534,
            "prompt_cache_hit_tokens": 1280,
            "prompt_cache_miss_tokens": 300,
            "prompt_tokens_details": {
              "cached_tokens": 1280
            },
            "completion_tokens_details": {
              "reasoning_tokens": 9012
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1/painting.png",
        "projectSource": "sketches/2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1.png",
        "source": "/images/model-painting-study/2026-08-24T03-51-40-90f6045a-c068-4ad0-bd26-67cac2bce3c1.js.txt",
        "stats": {
          "unique": 510,
          "meanLuma": 30.5366890625002,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "588d9ed74756bbe0e14760f1cda4727a38c555e9b34e4aaeda760cca26450b6d",
          "png": "295c2cc104ed909a2178ba171bebf2c1c84315432dad91f6cfc4eca8ed728593",
          "raw": "588d9ed74756bbe0e14760f1cda4727a38c555e9b34e4aaeda760cca26450b6d"
        },
        "latencyMs": 145545,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1580,
              "completion_tokens": 11954,
              "total_tokens": 13534,
              "prompt_cache_hit_tokens": 1280,
              "prompt_cache_miss_tokens": 300,
              "prompt_tokens_details": {
                "cached_tokens": 1280
              },
              "completion_tokens_details": {
                "reasoning_tokens": 9012
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 145545
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:54:15.913Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 510,
          "meanLuma": 30.5366890625002,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3",
        "createdAt": "2026-08-24T03:53:04.838Z",
        "prompt": "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",
        "promptId": "model-self-portrait-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "model-self-portrait-sacred-v9",
        "artDirection": "Interpret yourself as one singular painted presence rather than a product logo: choose one central embodiment that honestly reflects how you think, such as a figure, creature, instrument, archive, vessel, or constellation, and let that choice differ naturally from other models. Make the embodiment fill roughly x=115..485 and y=95..505, with one unmistakable silhouette, a focal detail inside the central third, and no more than three quiet supporting motifs. Do not turn the picture into a collage of technology symbols. On the blue-black ground, separate the subject with midtone royal blue, moonlit ivory, muted silver, and at most one restrained gold accent. Put the crispest edge and lightest mark at the feature that best represents your way of thinking. This is your self-portrait, not a portrait of your maker, company, user, or a generic human artist. Add no model name, letters, numbers, logos, circuit-board wallpaper, chatbot icon, decorative frame, or explanatory caption.",
        "provider": "opencode-go",
        "model": "deepseek-v4-pro",
        "medium": "gouache",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2410,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "c86f4dbac09a8750",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 195431,
          "usage": {
            "prompt_tokens": 1613,
            "completion_tokens": 12000,
            "total_tokens": 13613,
            "prompt_cache_hit_tokens": 1536,
            "prompt_cache_miss_tokens": 77,
            "prompt_tokens_details": {
              "cached_tokens": 1536
            },
            "completion_tokens_details": {
              "reasoning_tokens": 12000
            }
          }
        },
        {
          "stage": "repair",
          "provider": "opencode-go",
          "model": "deepseek-v4-pro",
          "protocol": "chat",
          "latencyMs": 76970,
          "usage": {
            "prompt_tokens": 10280,
            "completion_tokens": 7425,
            "total_tokens": 17705,
            "prompt_cache_hit_tokens": 1536,
            "prompt_cache_miss_tokens": 8744,
            "prompt_tokens_details": {
              "cached_tokens": 1536
            },
            "completion_tokens_details": {
              "reasoning_tokens": 4807
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3/painting.png",
        "projectSource": "sketches/2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3.png",
        "source": "/images/model-painting-study/2026-08-24T03-53-04-320e0a8c-be7d-4601-aa20-74f5c548adf3.js.txt",
        "stats": {
          "unique": 418,
          "meanLuma": 27.623256336804772,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "f8d9ae67b811489cc602dfc6047f94d7af1fcb15546fb60dbb4b3e41739ad576",
          "png": "41a9371d7ade785c5c9132c7dd5c459268914968234e0df80f57a21566591935",
          "raw": "7755b28ee592cd4bcffaf5e53f3ca55ec4560a20fda7ecd067e332d4b8549593"
        },
        "latencyMs": 272401,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1613,
              "completion_tokens": 12000,
              "total_tokens": 13613,
              "prompt_cache_hit_tokens": 1536,
              "prompt_cache_miss_tokens": 77,
              "prompt_tokens_details": {
                "cached_tokens": 1536
              },
              "completion_tokens_details": {
                "reasoning_tokens": 12000
              }
            }
          },
          {
            "stage": "repair",
            "usage": {
              "prompt_tokens": 10280,
              "completion_tokens": 7425,
              "total_tokens": 17705,
              "prompt_cache_hit_tokens": 1536,
              "prompt_cache_miss_tokens": 8744,
              "prompt_tokens_details": {
                "cached_tokens": 1536
              },
              "completion_tokens_details": {
                "reasoning_tokens": 4807
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 195431
          },
          {
            "stage": "repair",
            "provider": "opencode-go",
            "model": "deepseek-v4-pro",
            "protocol": "chat",
            "latencyMs": 76970
          }
        ]
      },
      "failure": null,
      "eventCount": 4,
      "lastEvent": {
        "at": "2026-08-24T03:57:42.921Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 418,
          "meanLuma": 27.623256336804772,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    },
    {
      "attemptId": "2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa",
      "status": "success",
      "request": {
        "attemptId": "2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa",
        "createdAt": "2026-08-24T03:54:13.499Z",
        "prompt": "one small oil lamp illuminating a narrow path toward a ruined wilderness chapel, light persisting in deep royal-blue darkness",
        "promptId": "light-in-darkness-night-v1",
        "experimentId": "2026-08-23-sacred-blue-study",
        "promptSpec": "sacred-blue-v9",
        "directionId": "light-in-darkness-sacred-v9",
        "artDirection": "Paint one small hand-held oil lamp near (225, 335) casting a restrained pool of warm light onto a narrow path that bends from the lower left toward a ruined wilderness chapel around x=390..505 and y=175..390. Make the path and chapel from broken, asymmetrical shapes: two wall fragments, one incomplete doorway, and no intact ornamental facade. The lamp, nearest path edge, and doorway are the only crisp features. Use the blue-black paper as active darkness, then add two royal-blue midtone washes, slate, moonlit ivory, and one muted-gold lamp glow. Preserve large quiet areas and keep the glow compact rather than a circular sun. Show light persisting without a slogan. No floating flame icon, oversized cross, human face in the sky, stars everywhere, text, logo, perfect arch symmetry, decorative border, or generic motivational-poster rays.",
        "provider": "opencode-go",
        "model": "mimo-v2.5-pro",
        "medium": "watercolor",
        "paper": "night",
        "size": 600,
        "deviceScaleFactor": 2,
        "seed": 2415,
        "index": 1,
        "total": 1
      },
      "promptRequestId": "1c3463396e0429a4",
      "apiResponses": [
        {
          "stage": "generate",
          "provider": "opencode-go",
          "model": "mimo-v2.5-pro",
          "protocol": "chat",
          "latencyMs": 126913,
          "usage": {
            "prompt_tokens": 1573,
            "completion_tokens": 8192,
            "total_tokens": 9765,
            "prompt_tokens_details": {
              "cached_tokens": 1024
            },
            "completion_tokens_details": {
              "reasoning_tokens": 0
            }
          }
        }
      ],
      "result": {
        "projectImage": "sketches/2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa/painting.png",
        "projectSource": "sketches/2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa/sketch.js",
        "image": "/images/model-painting-study/2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa.png",
        "source": "/images/model-painting-study/2026-08-24T03-54-13-611f0361-1052-425c-a78d-f78ec79981aa.js.txt",
        "stats": {
          "unique": 124,
          "meanLuma": 18.621140104166464,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        },
        "hashes": {
          "code": "0c71ed275f191d9262efd424e09ec1e964d7eda578de463953756ca70ecd302a",
          "png": "a7584e3aeb6dddad301c72f44991ffe4177a358fabc4fbe083935f6f9236c252",
          "raw": "e7cb296c7795deaac336900197768285fa24ff1d412665d926cfa1331b755dbd"
        },
        "latencyMs": 126913,
        "usage": [
          {
            "stage": "generate",
            "usage": {
              "prompt_tokens": 1573,
              "completion_tokens": 8192,
              "total_tokens": 9765,
              "prompt_tokens_details": {
                "cached_tokens": 1024
              },
              "completion_tokens_details": {
                "reasoning_tokens": 0
              }
            }
          }
        ],
        "apiCalls": [
          {
            "stage": "generate",
            "provider": "opencode-go",
            "model": "mimo-v2.5-pro",
            "protocol": "chat",
            "latencyMs": 126913
          }
        ]
      },
      "failure": null,
      "eventCount": 2,
      "lastEvent": {
        "at": "2026-08-24T03:56:38.404Z",
        "type": "render",
        "status": "success",
        "stats": {
          "unique": 124,
          "meanLuma": 18.621140104166464,
          "w": 1200,
          "h": 1200,
          "deviceScaleFactor": 2,
          "rendererBuild": "vendored-p5.brush+centroid-fallback-fix"
        }
      }
    }
  ]
}
