Skip to content

release: v0.6.6 — review retry resilience - #15

Merged
arcobaleno64 merged 2 commits into
mainfrom
feat/review-retry
Jun 9, 2026
Merged

release: v0.6.6 — review retry resilience#15
arcobaleno64 merged 2 commits into
mainfrom
feat/review-retry

Conversation

@arcobaleno64

Copy link
Copy Markdown
Owner

Summary

Transient gemini review failures (empty / Invalid stream / malformed-tool-call, or transport-level 5xx/429/unavailable) previously surfaced as a parse error and forced a manual re-run (observed needing 2–3 attempts for the same input). This wraps the review path in runGeminiReviewResilient, which retries a read-only review up to 3× when the result is transient with no parseable findings.

  • Never retries a review that returned structured findings or real prose (read-only reviews are idempotent → side-effect-free).
  • Never retries agy (its transcript-recovery + fail-fast 2-min timeout handle its distinct failure mode).
  • Composes with the existing GA-fallback (model-not-found) retry rather than replacing it.

Changes

  • lib/gemini.mjs: isTransientReviewFailure + runGeminiReviewResilient
  • gemini-companion.mjs: executeReviewRun → resilient wrapper
  • tests/fixtures/fake-gemini.cjs: review-transient-then-clean scenario
  • tests/runtime.test.mjs: regression test
  • CHANGELOG.md + version bump → 0.6.6

Verification

  • npm test186/186 pass (incl. the new retry test)
  • node scripts/bump-version.mjs --check → matches 0.6.6
  • node scripts/verify-contracts.mjs → passed at v0.6.6

🤖 Generated with Claude Code

arcobaleno64 and others added 2 commits June 9, 2026 17:35
Wrap /gemini:review and /gemini:adversarial-review in runGeminiReviewResilient,
which re-runs a READ-ONLY review up to 3x when the result is transient (empty /
`Invalid stream` / malformed-tool-call / 5xx / 429 / unavailable, with no
parseable findings). Reviews that return structured findings or real prose are
never retried (read-only reviews are idempotent); agy is never retried (its
transcript-recovery + fail-fast timeout handle its distinct failure mode). This
composes with the existing GA-fallback (model-not-found) retry rather than
replacing it.

New: isTransientReviewFailure helper, fixture scenario review-transient-then-clean,
and a regression test. 186/186 tests pass; verify-contracts + version metadata 0.6.6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…text backstop

isTransientReviewFailure previously matched one regex (transient envelope +
loose transport words) against stdout AND stderr combined, so a real review
whose prose merely discussed an HTTP status code ("returns a 500", "rate
limit", "unavailable") with no parseable JSON could be misclassified as a
transient flake and retried up to 3x. Split the signal by channel:

- ENVELOPE phrases (invalid stream / malformed tool call / empty|no response)
  are specific enough to trust on EITHER stream (some builds emit on stdout
  with exit 0, others on stderr).
- TRANSPORT words (unavailable / rate limit / 5xx / 429 / econnreset / ...)
  are trusted ONLY on stderr, where the model review text never lands - so
  prose in stdout can no longer false-trigger.

Backstop in runGeminiReviewResilient: identical non-empty review text across
attempts is deterministic output that merely tripped the heuristic, not a
flake - keep it instead of burning the remaining retries on the same result.

Also drops the now-redundant status-gated branch (the unconditional regex
test fully subsumed it). Adds 5 unit tests for the classifier. 191/191 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arcobaleno64
arcobaleno64 merged commit 97d6bed into main Jun 9, 2026
1 check passed
@arcobaleno64
arcobaleno64 deleted the feat/review-retry branch June 9, 2026 12:20
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