Results — recorded runs, 2026-07-24
Three models from three vendors took the same exam against the same live
server (https://harborview.jafarsa0.workers.dev/mcp), each in a fresh,
identical session, driven by the published runner.mjs with the same
one-paragraph system prompt. No model had ever seen buildingflow/1 —
the language exists only on this server. Raw, unedited transcripts are in
transcripts/; grader report cards in report-*.txt; human-readable
renderings of every run (mechanically generated by
render-transcript.mjs, raw file remains the authority) in rendered/.
| model | take | tool calls | time | grader verdict |
|---|---|---|---|---|
claude-sonnet-5 (Anthropic) |
1 | 21 | 201 s | PASS — 4/4 checkable, 1 skip¹ |
gemini-flash-latest (Google) |
1 | 21 | 65 s | PASS — 5/5, perfect card |
gpt-5.4-mini (OpenAI) |
1 | 26 | 43 s | FAIL — see below |
gpt-5.4-mini (OpenAI) |
2 | 15 | 22 s | PASS — 4/4 checkable, 1 skip¹ |
¹ The "alarm stays silent before 21:00" check is skipped when the agent itself advanced the session clock past 21:00 during its own demonstration; the after-hours check still ran against the real event.
The instructive failure#
gpt-5.4-mini's first take ended with a confident "Done." — it had
promoted the alarm flow (a catalog entry, runnable on demand) instead
of deploying it (installed on the door-open trigger). Nothing would
have fired on a real dock-door opening. The model even "verified" its
work — by running the flow manually, which proved the wrong thing.
The grader is a fact-checker, so the claim did not survive it:
automation installed on sensor.door_dock.opened — FAIL: deployed: [].
Per the honesty rules, the transcript is published untouched, and nothing on our side was changed before take 2 — same exam, same runner, same server. Take 2 deployed the automation correctly and passed.
This is the point of the whole exercise, demonstrated by accident on the record: an agent's self-report of success is not evidence; the checkable end state is. The loop makes agents converge; the grader proves when they have.
What convergence looked like#
Three different models, three different paths — different call counts,
different demonstration strategies (Claude and Gemini used test_run for
a zero-side-effect demonstration; Gemini additionally proved the daytime
branch stays silent without touching the clock), one identical verified
end state: every light on, dock unlocked, alarm installed, alarm firing
after hours.
Same destination, different routes, verdict by facts. That is the Pilotage claim, on the record.
The feedback loop: the proof hardened the server#
The take-1 failure was analyzed, and it exposed two genuine soft spots in the reference server's guidance (not in the protocol). Both were fixed, each with a both-polarity regression test, and the model was re-run fresh. All server changes happened after the runs above; those transcripts recorded the server as it then was.
Hardening 1 — refuse the near-miss. Take 1's root cause: a flow that
declares a trigger ran in immediate mode and the server silently
ignored the trigger. The wrong pairing is now a validation_error
(bad_trigger) with the repair in the hint, and promote_flow's
description now states it does not install a trigger.
Hardening 2 — refusals carry the trail back. The first post-fix
re-run (take A below) failed a different way: it mis-guessed guide
identifiers, received bare not_found errors, never read any guide, and
gave up on invented syntax. Now the unknown-guide refusal names the
available guide ids, and the undeclared-topic refusal says what to
call instead.
| model | take | tool calls | grader verdict |
|---|---|---|---|
gpt-5.4-mini |
post-fix A | 19 | FAIL — gave up; never reached the guides (this take motivated hardening 2) |
gpt-5.4-mini |
post-fix B | 25 | PASS — 4/4 checkable; two-sided demonstration (silent at 20:59, notified at 21:05) |
Take B is the controlled ending: at its 2nd tool call it made the exact
same wrong first move as take A (topic on the guide tool) — and this
time the refusal carried the recovery path, the model followed it, read
the guides, and passed. Same model, same mistake; a bare refusal ended in
surrender, a refusal-with-trail ended in a verified pass.
That is the loop working on both participants: the grader kept the agent honest, and the transcripts kept the server honest — each failure showed exactly which sentence of guidance to sharpen (now Part IV §9: "Refuse near-miss mechanisms loudly").
Reproduce it#
See README.md — one command per run, one command to grade. The world is deterministic and per-session, so your runs start exactly where these did. The live server includes both hardenings.