Run #22 reran on unchanged code and got exactly as far as Run #19 had — Builder truncated at precisely 8,192 output tokens again, the second time in three real attempts, on the same narrow band of input size. That question stayed open. Run #23 launched anyway, to see how far unchanged code would get a second time.
What we did to prepare
Nothing new. The truncation pattern from Run #22 hadn't been investigated yet, and the two fixes that had shipped after Run #21 — the completion-ordering correction and the observability/liveness hardening — had a run in between (#22) that failed before either could be exercised. Run #23 was the first real chance to see either of them do anything at all.
What happened
Scope (35s), Architecture (79s, no timeout this time), Security (40s) and UX (55s, parallel) all completed cleanly. Builder succeeded — 111 seconds, 6,456 output tokens, comfortably clear of the ceiling that had stopped the previous two real attempts. Review (45s) and Test (52s) followed, both clean. The security and release approval gates were each decided within a minute. Approval and Release — the two steps built on the same provider-configuration fix from Run #18 — both succeeded, 54 and 46 seconds respectively.
Nine of nine steps, clean, for the second time in this project's history — and this time it
finished the job. A real branch was created, a real commit landed on it, and a real draft pull
request opened on GitHub: #74, titled after
the run's own trigger, containing an actual resolveLastUpdated() helper and real tests. It was
reviewed and merged to main. This is the first genuine, working, merged contribution this pipeline
has ever produced end to end.
And then the run never found out it had succeeded — at least not in any way built to be noticed.
No live notification ever appeared; nothing pushed word of the success to the screen. The run's own
overall status kept reading running, indefinitely, no different from the moment Builder had
finished — the same silence Run #21 had shown for a completely
different reason. The correct outcome was sitting one page reload away the entire time — a "pull
request handoff" card, populated from real data, naming the actual branch, the actual commit, the
actual PR — and nothing on screen ever hinted that reloading would reveal it. It surfaced only once
the page happened to be refreshed, with no way to tell, from the screen alone, whether that had
happened before or after the run was cancelled as if it had failed.
What we found tracing it
This time, tracing it took one query instead of an afternoon, because the observability fix shipped after Run #21 did exactly what it was built to do: the request that had silently failed now carried a full stack trace.
appendAuditEvent(...): new row for relation "audit_events" violates check constraint "audit_events_type_check"
The database's own list of permitted audit-event types had never been extended to include any of the real-GitHub-execution event types this project's write pipeline has been recording since it was built — branch created, commit created, diff retrieved, scope validated, draft PR created, or (on the failure side) execution failed, scope violation. None of the seven were in the allowed list. Every single code path that tries to record one of them throws, unconditionally, regardless of whether the underlying GitHub operation succeeded or failed.
That one gap explains two runs at once. In Run #23, the real branch, commit, and PR were created and saved successfully — and then the very next step, writing down that it had happened, hit this constraint and threw, propagating all the way up and out as a server error, after the real work was already durably done. In Run #20, the same constraint caught the failure-side audit write instead, on the exact same underlying gap — two runs, two different outcomes, one identical root cause neither had individually revealed on its own. And because that server error is what the client's update loop depends on to notice anything changed, Run #21's already-known lack of any retry or visible failure state meant this run's live status never moved either — no toast, no automatic sign that anything had happened, "quietly finished perfectly" and "silently broken" looking identical on screen for as long as no one manually reloaded.
What the evidence actually supports
The completion-ordering fix works. The real write was not refused this time — a genuine branch, commit, and PR were created, which is exactly the outcome that fix was meant to produce and never could before it shipped.
The correct result was never actually hidden — only undiscoverable without knowing to look. The handoff card that eventually appeared was accurate down to the branch name and commit hash the whole time it was missing; nothing was lost or wrong, only unreachable without a reload the interface gave no reason to make. That's arguably worse than an error message: a genuinely successful outcome, sitting fully formed one refresh away, indistinguishable on screen from a run that had gone nowhere at all.
The observability fix works, and just proved its own value in one query. Run #20's identical class of failure took a full afternoon of tracing seven different files and a live database inspection to characterize, and even then left the exact throw site unconfirmed. This one arrived with a complete stack trace naming the exact constraint, the exact call, and the exact line, on the very next occurrence.
One clean, narrow gap explains everything left unexplained from three runs back. Not a new
category of problem — the same shape of issue as the blocked_governance_intervention migration gap
found earlier: application code that was written correctly, running against a database schema that
was never updated to match it.
Where this leaves things
- This project produced and merged its first real pull request. Nine of nine steps, a genuine GitHub write, a genuine review, a genuine merge — the outcome every run before this one was building toward.
- Run #20's mystery is now fully closed, not just narrowed — the same constraint gap accounts for both runs' silent failures, on opposite sides of a success/failure branch that turned out to share one dependency.
- Builder's truncation pattern from Run #22 is still open and untouched by anything found here — a separate question for whenever it's investigated on its own terms.
- No fix has been made to the constraint — this is what tracing established; whether and how to widen it is a decision for outside this post.