Skip to content

fix(draft-cache): retry the hard gate in the same conversation instead of a fresh spawnCli call (AGT-4300) - #621

Merged
unohee merged 1 commit into
mainfrom
perf/draft-finish-validator
Sep 10, 2026
Merged

unohee merged 1 commit into
mainfrom
perf/draft-finish-validator

Conversation

@unohee

@unohee unohee commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • draftAnalyzer.ts's hard-gate retry (thin brief → retry) used to call spawnCli again — a structurally new conversation. Measured on vela post-fingerprint-fix: that retry's first call lands at 0.3% cache against 95%+ around it, reproducibly.
  • Adds finishValidator/finishValidatorMaxRetries to CliRunOptions and the shared agenticLoop.ts (openrouter/gpt/local/atlascloud), modeled on the existing no-edit-guard pattern: rejecting a would-be final answer appends a nudge as a new turn on the SAME conversation instead of the caller restarting.
  • draftAnalyzer.ts's DRAFT_MAX_ATTEMPTS loop replaced by one spawnCli call using this hook.
  • Layer-2 review caught a real gap in the first draft: the mechanism only works for adapters routed through runAgenticLoop, so codex/claude/cursor/codex-responses/cc-router (and the loop's own turn-budget-exhaustion salvage path) would have silently gotten zero retries. Fixed with an explicit fallback that restores the historical "every adapter gets DRAFT_MAX_ATTEMPTS real chances" guarantee. Round-2 re-review found no further issues.

Test plan

  • New/updated tests: retry within the same conversation, retry-budget exhaustion returns as-is, fallback fires when the validator never got its full quota — all three mutation-verified (broke the logic, confirmed the test fails, restored)
  • npx tsc --noEmit / lint / build / full vitest suite green (one unrelated fileLock.test.ts flake confirmed by isolated rerun)
  • Layer-2 independent review, 2 rounds — round 1 found CRITICAL/HIGH/MEDIUM/MINOR, all fixed in this PR; round 2 clean
  • Deploy to vela and measure the draft stage cache rate (part of the standing 80%-cache goal)

🤖 Generated with Claude Code

…d of a fresh spawnCli call (AGT-4300)

draftAnalyzer's hard gate used to retry an insufficient draft brief by
calling spawnCli AGAIN with a stricter prompt -- a structurally fresh
conversation. Measured on vela post-fingerprint-fix: that retry's first
call lands at 0.3% prompt-cache hit against 95%+ for the calls around
it, reproducibly (4/4 in a small sample), correlated exactly with the
attempt boundary. Root cause of why a fresh conversation loses cache on
this provider wasn't conclusively pinned (isolated reproductions of
"fresh conversation, identical/prefix-matching content" all cached
near-perfectly), so this sidesteps the mechanism instead of chasing it:
retry in place.

Adds `finishValidator`/`finishValidatorMaxRetries` to CliRunOptions and
the shared agenticLoop.ts (openrouter/gpt/local/atlascloud). When the
loop is about to return a final answer with no more tool calls, the
validator gets a look; rejecting appends a nudge as a new user turn and
continues the SAME messages array instead of the caller starting over,
modeled directly on the existing no-edit-guard pattern
(nudgeMaxOnNoEdit). draftAnalyzer.ts's DRAFT_MAX_ATTEMPTS loop is
replaced by one spawnCli call using this hook.

Layer-2 review caught a real gap in the first draft of this fix: the
mechanism only works for adapters routed through runAgenticLoop, so
codex/claude/cursor/codex-responses/cc-router (and the loop's own
turn-budget-exhaustion salvage path, which bypasses the no-tool-calls
branch entirely) would have silently gotten ZERO retries instead of a
colder one. Fixed with an explicit fallback: if the validator never
reached its full DRAFT_MAX_ATTEMPTS quota (tracked via the attempt
number it's called with), draftAnalyzer does exactly one more
old-style fresh retry, restoring the historical guarantee universally.
Round-2 re-review confirmed no findings survive.

TSC=0, LINT=0, BUILD=0, full vitest suite green (one unrelated
fileLock.test.ts flake confirmed by isolated rerun, not touched by
this diff).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@unohee
unohee merged commit 38e6826 into main Sep 10, 2026
7 checks passed
@unohee
unohee deleted the perf/draft-finish-validator branch September 10, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant