Back to blog
Aug 28
dogfooding
byok
anthropic
provider-reliability
engineering-log

Runs #12–14: A New Wall, and the First Time We Saw Why

Run #11 closed with Builder's Anthropic call finally completing, and a different validation layer rejecting the result for a reason nobody could see. Before running again, we built exactly the instrumentation that gap called for — and then, before that instrumentation ever got tested against a real failure, a completely different step broke first.

What was already fixed going into Run #12

Two things shipped between Run #11 and Run #12, both already covered in detail in the Run #11 post:

  • Builder's provider timeout raised to 120 seconds, specific to that role only — every other role, including Architecture, kept the original 60-second ceiling unchanged.
  • A safe, typed diagnostic reason for builder_patch_invalid — which of ten specific invariants rejected a patch, plus plain numeric measurements, never a path or a scrap of model content — folded into the same durable message that was already being recorded. Built specifically because Run #11 proved the previous fixed generic message couldn't say anything more useful than "something was wrong."

Neither of these three runs needed a third fix. What they needed was patience: watching two failures land on a step nobody expected to fail, refusing to explain them before the evidence supported it, and then getting the actual answer this project has been chasing since Run #9.

Run #12: Architecture times out — the first time this has ever happened

Same task as every prior run, deliberately unchanged. Scope completed in 41 seconds, same as always. Then Architecture — a step that had succeeded in every one of the previous eleven runs, including a slow 268-second one before the acquisition-latency fix — failed both attempts, each at essentially exactly 60,000 milliseconds:

  • Attempt 1: 60,007ms, application_timeout
  • Attempt 2: 60,004ms, application_timeout

The retry deferred correctly between attempts, exactly as designed since Run #9. Both attempts still failed. The run never reached Security, UX, or Builder — the run itself failed here, with the Builder patch-validation question from Run #11 still completely unanswered.

One data point isn't a diagnosis. Architecture's input volume — 49,000-plus tokens, unchanged in every prior successful run — hadn't grown. Nothing about the task or the repository had changed. This could have been an isolated, unlucky call. It needed a second occurrence before it meant anything.

Run #13: it happens again, in the same shape

Same task, no changes. Scope completed normally. Architecture failed both attempts again, at essentially the same durations:

  • Attempt 1: 60,008ms, application_timeout
  • Attempt 2: 60,004ms → 60,005ms, application_timeout

Four consecutive Architecture provider calls, across two separate runs, every one landing within 4 milliseconds of exactly 60,000ms. That crossed the line from "an isolated slow call" to "a real, repeating pattern" — the same threshold this project has used before deciding anything was worth investigating. The deliberate choice at this point was not to raise Architecture's timeout on the strength of two runs. Run #8 already taught this project what happens when a timeout gets changed before the arithmetic and the evidence are actually in hand.

Run #14: it doesn't happen a third time — and Builder finally gets tested for real

Same task again. This time, every step before Builder succeeded:

  • Scope: 33,770ms
  • Architecture: 57,782ms — comfortably inside the 60-second ceiling, but closer to it than any of the three original successes (44,302-52,855ms). Input tokens, output tokens, and selected context were all statistically identical to every prior successful Architecture call. Nothing about what it was asked to do had changed; the fourth and fifth timeout-range attempts simply didn't happen a third time.
  • Security: 25,177ms. UX: 29,454ms.

After the human approval decision, Builder finally dispatched for the first time since Run #11 — and its Anthropic call completed again, 100,679ms, well inside its 120-second budget with real headroom to spare.

Then it got rejected — and for the first time in this entire series, the reason was actually legible:

reason=commit_message_too_long, actualCommitMessageChars=854, maxCommitMessageChars=500

Not a guess. Not a generic sentence that could have meant any of nine different things. The model's proposed commit message was 354 characters over the configured limit — everything else about the patch (paths, file content, structure) had already passed. No path or file content was ever exposed to produce this — exactly what the observability hardening was built to prove could be done. The failure was correctly classified non-retryable, and the run ended cleanly with a complete, durable record instead of another silent gap.

What the evidence actually supports, and what it doesn't

Architecture's timeout pattern is real, and inconclusive on cause. Two runs, four attempts, all essentially identical durations, all on unchanged input — that rules out "one unlucky call" but doesn't establish why. Input token volume never moved across any of the six runs analyzed (a sub-1% spread from lowest to highest). The most direct explanation the evidence supports is ordinary Anthropic-side call-latency variance occasionally landing close enough to a 60-second ceiling to tip over it — consistent with Run #14's own successful call landing at 57.8 seconds, noticeably closer to the ceiling than the pre-#12 baseline. That is not the same as confirming it, and five data points — two of which never got to observe an actual call duration, because the platform aborted them first — is not enough to change a timeout on.

The Builder diagnostic is confirmed working, on a real failure, for the first time. Every piece of it fired correctly: the safe reason, the exact counts, request_id and execution_id both populated, the non-retryable classification holding, and nothing about the model's actual content ever touched a log or an error message. One occurrence is one data point on which invariant Builder tends to violate — a commit message that ran long this time doesn't rule out too_many_files or patch_too_large showing up next time — but the machinery that would tell us either way, for real, is now proven to work.

Where this leaves things

  • Nothing here justifies a code change. Neither Architecture's timeout nor Builder's commit-message limit has enough evidence behind either one yet — repeating the pattern is what would justify touching something, not two occurrences of one and one occurrence of the other.
  • Architecture's near-60s calls are worth continuing to watch, not because the evidence says it's broken, but because it hasn't fully cleared the ceiling by the margin the earliest runs did.
  • Builder's specific failure reason — a too-long commit message — is one data point, not a trend. Whether it recurs, or a different invariant fires next time, is exactly what the next real Builder attempt will show, now that it's actually possible to tell the difference.
  • The observability hardening built after Run #11 has paid for itself on its very first real test. That's the whole point of building instrumentation before guessing at a fix: it turns the next occurrence, whatever it is, into evidence instead of another mystery.