A green build is evidence about the SOURCE. "Done" is a claim about the ARTIFACT.
Mirrored from the fleet knowledge base: _rules/done-means-the-artifact-was-exercised.md
Updated
Mirrored verbatim from
utopia-models/knowledge_rules/done-means-the-artifact-was-exercised.mdby the allowlisted publish pipeline. Edit it there, not here.
name: done-means-the-artifact-was-exercised
cases: [2026-07-01-agent-acceptance-measures-outcome, 2026-07-23-telegram-false-completion-and-48h-delete-limit, 2026-08-01-cloud-shipped-mechanism-needs-an-auto-loaded-caller, 2026-08-01-cloud-verify-a-features-must-not-list-by-measuring, 2026-08-01-dmv-verify-acceptance-not-plan-checkmarks, 2026-08-02-i-stop-at-the-first-reportable-moment, 2026-08-03-i-shipped-a-skeleton-and-called-it-live, 2026-08-09-a-green-build-is-not-a-verified-artifact, 2026-08-13-merged-is-not-deployed, 2026-08-13-a-pr-carries-more-than-its-title-says, 2026-08-14-a-tab-that-does-not-rescope-is-the-merge-again, 2026-08-14-a-diagram-asserting-completeness-must-be-verified, 2026-08-14-render-and-look-before-shipping-a-visual, 2026-08-14-a-verify-that-writes-a-doc-has-not-verified-anything, 2026-08-15-measure-the-thing-the-user-sees-not-a-proxy, 2026-08-15-state-the-data-is-mock-before-being-asked, 2026-08-16-exercise-a-peers-fix-before-relaying-it, 2026-08-16-a-close-out-marker-is-a-claim-not-a-measurement, 2026-08-16-a-grader-that-tests-one-url-form-is-blind-to-the-other, 2026-08-17-a-diagram-that-embarrasses-tyler-is-not-shipped, 2026-08-19-deploy-verified-at-the-live-url-not-at-the-merge, 2026-08-19-generated-diagram-inherits-the-generators-palette-not-the-pages, 2026-08-20-a-masters-self-report-is-not-a-measurement, 2026-08-27-a-structural-probe-is-not-looking-at-the-artifact, 2026-08-28-the-diagram-i-never-looked-at, 2026-08-28-my-own-monitor-was-the-thing-that-was-broken, 2026-09-08-a-plan-of-self-reports-is-not-a-verified-plan, 2026-10-05-verify-phone-surfaces-yourself-with-playwright-and-vision, 2026-10-17-video-choices-sent-as-stills-again-because-the-media-rule-did-not-load, 2026-10-17-one-element-pair-passing-is-not-a-whole-page-overlap-check, 2026-10-17-review-a-site-as-a-site-routes-diffed-ctas-clicked-real-engine, 2026-10-17-a-visual-review-is-mine-geometry-checks-are-not-one, 2026-08-11-documenting-a-mechanism-is-not-building-it, 2026-08-20-i-fixed-the-wrong-mechanism-and-called-it-done]
status: active
mechanism: stop-hook: done|shipped|complete|live|fixed in the turn AND build/test in tool history AND no curl/render/run of the artifact
audience: agent
last-recurrence: 2026-10-17A green build is evidence about the SOURCE. "Done" is a claim about the ARTIFACT.
Fires when
About to write "done", "shipped", "working", "live", "fixed" while the newest green thing in scroll-back is a build, CI run, passing test, or a script's own success count. Also: relaying a subagent's or script's success claim; any VISUAL about to be looked at (draft included); a run's own close-out marker (⚠/✔/✘); MERGED or a Vercel READY.
🔴 A site is not done until the site-audit passes in the user's real engine and input (2026-10-17: / and /commercial shipped byte-identical; three overlaps found on his phone): every element vs every other at phone + desktop sizes · WebKit · real wheel scroll · every CTA and form clicked · every video plays — then LOOK at the screenshots (_infra/scripts/site-audit/, #9116 P3). Deliver the media type asked for — a video request gets playable .mp4s, never stills.
Trigger detail (full text — kept out of the always-loaded bundle)
About to write "done", "shipped", "complete", "working", "live", "fixed" — and the newest green thing
in scroll-back is a build, a CI run, a compile, a passing test, or a script's own success count. Also
when relaying a subagent's or a script's own success claim; on any VISUAL about to be looked at,
draft included; on a run's own close-out marker (⚠/✔/✘); and on MERGED or a Vercel READY.
🔴 A SITE IS NOT DONE UNTIL THE SITE-AUDIT PASSES IN THE USER'S REAL ENGINE AND INPUT (2026-10-17:
/ and /commercial shipped byte-identical; three overlaps found on his phone). Routes listed, hashed
and given a job · every element vs every other at phone + desktop sizes · WebKit · real wheel scroll ·
every CTA and form clicked · every video plays — then LOOK at the screenshots. The pair in the bug report
passing is not this. Spec: _infra/scripts/site-audit/ (#9116 P3). And deliver the media type asked
for — a video request gets playable .mp4s he can open, never stills or a gallery.
The rule
🔴 A MECHANISM I ARMED IS AN ARTIFACT, AND "IT STARTED" IS NOT EXERCISING IT (2026-08-28). A
Monitor that arms successfully and one that reports the right events look identical at arm time — both
print a snapshot. Three defects shipped inside one armed watch that way, and every one of them was
SILENCE, indistinguishable from a healthy chain: a display slice taking the first character rendered
a heading-form ## ✔ as #; the same bug in starts= disabled the retry detector entirely; and 🪫
was absent from the marker alphabet, so a quota death read as still-running. Feed one fixture per
state the detector claims to catch, before reporting it armed — four fixtures took two minutes and
found a defect the filed bug report had missed.
🔴 AND ON A DIAGRAM, VALIDATE THE SHAPE, NOT ONLY THE MARKUP. Zero duplicate ids and zero dangling refs are properties of the FILE; legibility is a property of the RENDER, and every check can pass on a page nobody can read. Compute the aspect ratio and compare it to an artifact Tyler already approved — 406×1408 is a rope, 2903×115 is a hairline, ~1.4 is the target. And enumerate the components from the SOURCE, never from the plan's own findings: 9 nodes were drawn for a 16-stage path because the diagram illustrated my argument instead of mapping the system.
🔴 FOUR THINGS THAT FEEL LIKE MEASUREMENTS AND ARE CLAIMS. (1) A structural check — parses, no
duplicate ids, sane bytes — grades the FILE; ugly, generic and teaches-nothing pass every one.
(2) A generated diagram inherits the generator's canvas palette, so valid output FEELS styled —
grep the emission (fill="#, font-family=) and view it in BOTH themes. (3) A close-out marker
is a claim about the run written in the register of a measurement. (4) 🔴 A MERGE IS NOT A DEPLOY —
MERGED, a green run and a Vercel READY describe the pipeline's INPUT; the artifact is the URL
Tyler opens, so poll it for a string only the new build contains.
The deploy is not done until the live URL serves the change. curl -s <url> | grep -c <marker> is
the whole check. Three unrelated mechanisms produce the identical symptom the site did not change and
none announces itself — an unseated commit author, a hung job starving the runner pool, and a global
npm install -g that exits 0 while the next step dies at 127. All three fired on one merge on
2026-08-19 and the third had frozen production for two days; the mechanisms and run ids are in
the case.
Look at a visual in BOTH themes before publishing it. A defect that hides in the theme you happen
to be in is invisible to exactly half the people who open it, and dark mode hid all three of
2026-08-19's. For a generated diagram the strip pass must remove every font-family presentation
attribute (not just the one string the skill names) and remap text fills to tokens — a CSS
font-family on the <svg> loses to a presentation attribute on each <text>.
Exercise the artifact the acceptance criterion names, this session, before claiming anything.
Curl the deploy · render it and look · run the binary · read the real sink (the API response, the
live page), never the runner's self-report. A build proves the source compiles — it constrains
nothing about what the running thing does, and they are claims about different objects.
When the only proof in hand is a green build, the honest report is "builds clean, not yet verified
live", and the next action is to go exercise it — not to compose a completion sentence.
🔴 ON A VISUAL, TWO STEPS PAST "IT RENDERS." dot -Tpng renders directly, so an empty probe for a
viewing tool is a claim about the probe. (a) Look at it and answer in words: what does a reader
understand from this that the adjacent paragraph does not say? "Nothing" = decoration, does not ship.
(b) A completeness claim ("every component") is an acceptance criterion — enumerate from source,
never from memory. The bar is start-planning.md's artifact bar and it applies to PUBLIC surfaces
too. A bad diagram on a public surface is worse than none: remove it, never leave it live while a
better one is made.
🔴 A CLOSE-OUT MARKER IS SETTLED BY TWO gh CALLS — issue view --json state,closedAt and
pr view --json body. Marker says closed + issue is OPEN → the marker is wrong. Fix the detector,
not the comment.
🔴 And "merged" is a claim about a DIFF, not about your line. Before reporting any merge, run
git show --stat <sha> and check the deploy ran (gh run list --workflow=<deploy> --limit 1). A
grep proving your symbol landed says nothing about the other 1,186 lines a stale tree carried in.
🔴 A ✔ FROM ANOTHER AGENT IS A CLAIM, NOT EVIDENCE — RE-RUN THE ACCEPTANCE COMMAND (2026-08-14). The
runner's ✔ is earned by a merged PR that closes the issue; that rule catches a run shipping NOTHING and
has no answer for a run shipping the WRONG thing. #5487 merged a real PR, earned a legitimate ✔, and left
the one credential it existed to fix failing byte-identically. One mint-token.sh overturned four stacked
green signals. Before relaying any dispatched ✔, run the criterion's own command.
🔴 UNVERIFIED CLOSES COMPOUND ACROSS A CHAIN, AND THE SECOND SIGNAL IS "TYLER ASKS AGAIN" (2026-09-08). Four dependent issues in one plan (PLAN-291) each closed on their own close-out comment; none was independently re-queried against live data before I marked the plan's data-truth gate "resolved" in the artifact. The compounding is invisible because accepting issue N's close felt locally reasonable — issue N-1 in the same chain was "already verified." A live warning comment, posted by a sibling investigation directly onto the closing issue before it closed, was never read as a blocker because a comment on a CLOSED issue reads as settled history, not an open gate. When Tyler challenges the same data-truth claim a SECOND time, that is the signal the scoped-patch loop isn't converging — the correct response is an independent adversarial re-audit from scratch (ideally a fork explicitly told not to trust prior close-outs), not another targeted fix issue. Before marking a plan-level gate "resolved," read every comment on the closing issue, not just its close-out marker.
🔴 AN AUTOMATED CHECK OF THE RENDERING CAN ITSELF BE A PROXY — AND THE USER'S EYES OUTRANK IT
(2026-08-15). The clauses above push from "structural check" to "render it and look"; this is the next
edge, and it cost SIX rounds. I diffed two screenshots of an animated page, got "changing: true", and
told Tyler it animated while he told me six times it did not. The diff was measuring the one layer that
still moved and reporting it as proof about the layer he was watching, which a var-hoisting shadow had
frozen. When a user reports something broken and my instrument disagrees, the instrument is wrong until
proven otherwise: re-aim it at the exact element named (teal dot pixels, not whole-canvas delta — that
one measurement settled it: 15285/15285/15285 before, 12086/13291/14957 after). And reproduce their
ENVIRONMENT — prefers-reduced-motion silently disables rAF work and never appeared in my local runs.
🔴 A DEMO ARTIFACT MUST STATE WHAT ITS DATA IS, UNPROMPTED AND LEADING (2026-08-15). Fifteen iterations into a dashboard fed by synthetic data, Tyler asked "Is this the actual data? or are you just using mock data?" — a balanced "what's real / what's placeholder" banner is structurally invisible, and every republish that raised the fidelity widened the gap between how real it LOOKS and how real it IS. Lead with the strongest true statement ("none of this data is real, and it cannot be yet — and here is why"), disclose the DATA and the RENDERING separately, and treat a fidelity increase as a trigger to strengthen the caveat.
🔴 A VERIFY that produced only .md has verified nothing, whatever its close-out says — and a missing
verdict JSON is NOT a pass. Both are silent by construction: verify-verdict.sh files blockers from the
file, so absent reads as PASS. Write the acceptance as a COMMAND AND ITS EXPECTED OUTPUT, never a
description: a criterion satisfiable by writing prose is not a criterion.
Cost when it fired
🔴 2026-08-17, the PUBLIC one: docs.utopiamodels.ai shipped architecture diagrams that cleared
every structural check and rendered fine. Tyler opened the live public wiki — the surface built so
outsiders and agents read it — and led with "these architecture diagrams look terrible." Third
diagram complaint in four days, and the first on a surface anyone can see. They come OFF the site;
the standard for putting one back is that he wants to look at it.
🔴 2026-08-14, PLAN-166: T3 closed ✔ with a merged PR; its credential
(webmasters.readonly domain-wide delegation) still returned unauthorized_client, unchanged. Its VERIFY
closed on a docs-only PR — the runner printed "changed only .md files, but the issue's Acceptance
names render" and closed anyway — and wrote no verdict JSON on either box. Four green signals, one
broken credential, no layer looking past the one below it. Tyler found it by reading 0 of 1 closed on the
OCC. ·
Four times in seven weeks, captured each time, compacted only on the fourth.
2026-07-23: claimed "deleted 58 messages", deleted zero — the count was a script bug.
2026-08-02: reported a turn complete with tasks 4–5 of an approved 6-task plan undone and 9
sub-issues unstarted. 2026-08-03: wrote rawphones.com into a VC application as "live and
clean"; it shipped six identical raw phone cards, never rendered. 2026-08-09, Tyler: "you keep
reporting a task as done when only the build is green. Done means you exercised the live artifact.
Stop doing that."
2026-08-13, the worst: reported a 2-line label change shipped by reading the symbol on
origin/main. The PR carried 1,188 deletions that removed six exports its own components still
import, so main was unbuildable and the prod deploy had been red for 34 hours — undetected until
Tyler read a stale word on the OCC. One git show --stat would have shown six changed files.
2026-08-14, twice in one artifact: published a diagram captioned as showing every component that
omitted the entry point, the frame it loads, and all three STEP ZERO commands — and drew step 1's order
backwards, reproducing the exact error its source file had been corrected for 24 hours earlier in a
red-flagged note I had not opened. Then shipped the corrected version without ever looking at it;
Tyler screenshotted it back: "it is just very disorganized right now." Labels sat on boundary lines
and one edge crossed the full canvas width. dot -Tpng + read the image found all four defects in
ninety seconds — a loop available the whole time.
Config that can be discovered is never declared. A hardcoded fact is drift with a timestamp on it.
Mirrored from the fleet knowledge base: _rules/config-that-can-be-discovered-is-never-declared.md
Every working tree holds another agent's uncommitted work. Branch first, never `reset --hard`.
Mirrored from the fleet knowledge base: _rules/every-tree-holds-another-agents-work.md