fix(selfhost): correlate Codex provider timeouts with job/PR context - #3315
Conversation
Thread the webhook delivery id, repo, PR number, and retry attempt from the AI review pipeline down into the self-host provider chain so a selfhost_ai_provider_failed line (Codex timeout, Claude Code failure, or the in-chain fallback warn) can be matched back to the review that produced it without cross-referencing timestamps. All four fields are optional and forwarded only when the caller actually has them, so an unconfigured or test caller keeps the log line byte-identical. Also adds a regression test pinning the existing (and correct) Codex- timeout-falls-through-to-Claude-Code chain behavior, which previously had no test coverage of its own.
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
gittensory-ui | c6b195f | Commit Preview URL Branch Preview URL |
Jul 05 2026, 01:44 AM |
|
Warning 🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨 ⏸️ Gittensory review result - manual review recommendedReview updated: 2026-07-05 03:05:12 UTC
⏸️ Suggested Action - Manual Review
Review summary Nits — 4 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3315 +/- ##
=======================================
Coverage 93.73% 93.74%
=======================================
Files 276 276
Lines 30381 30386 +5
Branches 11073 11076 +3
=======================================
+ Hits 28479 28484 +5
Misses 1257 1257
Partials 645 645
🚀 New features to boost your workflow:
|
Summary
logSelfHostAiProviderFailed(and the in-chainselfhost_ai_provider_failed_in_chainwarn log increateChainAi) only ever carriedprovider/model/effort/timeoutMs/error. There was no way to correlate a Codex/Claude Code failure log line back to the review that triggered it — no job id, no repo, no PR number, no attempt number. This PR threads those four fields, when actually available, from the AI review pipeline down into the self-host provider layer.AiRunOptions(self-host provider options) gains optionaljobId/repoFullName/pullNumber/attempt;runWorkersOpinion(the caller that invokesenv.AI.run) now forwardsrepoFullName/prNumberfromGittensoryAiReviewInputplus its own per-attempt retry counter;runAiReviewForAdvisoryandrunGittensoryAiReviewgained an optionaldeliveryId/jobIdpassthrough, sourced from the real inbound webhook delivery id at the one production call site (src/queue/processors.ts) — the closest thing this queue has to a job id. All four fields are optional and only appear in the log when the caller actually supplied them, so the log line is byte-identical to before whenever they're absent (e.g. a sweep/repair fan-out with no single originating delivery, or any existing caller/test that predates this field).createChainAi) already correctly falls through from a failing Codex attempt to the next configured provider (e.g. Claude Code) — that behavior needed no code change. It previously had no regression test of its own pinning it, so this PR adds one: a Codex timeout followed by a successful Claude Code fallback, asserting the review still completes, both the provider-level and chain-level failure logs carry the new correlation fields, and no secret ever leaks into the logged error text.deliveryIdis real, existing GitHub webhook-delivery-id data already threaded throughsrc/queue/processors.tsfor audit-event metadata at the exact call site; I forwarded the same value rather than adding new plumbing.Scope
type(scope): short summaryConventional Commit format, for examplefix(api): restore profile access checks.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run actionlintnpm run typechecknpm run test:coveragelocally;codecov/patchrequires ≥99% coverage of the lines AND branches you changed (aim for 100% on your diff so CI variance does not fail near the threshold). Global coverage is a non-blocking trend with a loose 90% backstop, not the gate. (Every new line insrc/selfhost/ai.ts,src/services/ai-review.ts, andsrc/queue/processors.tsis covered, including both arms of each new conditional, verified directly against the lcov report.)npm run test:workersnpm run build:mcpnpm run test:mcp-packnpm run ui:openapi:checknpm run ui:lintnpm run ui:typechecknpm run ui:buildnpm audit --audit-level=moderateAlso ran (this change touches self-host env docs and observability):
npm run selfhost:env-reference(regeneratedapps/gittensory-ui/src/lib/selfhost-env-reference.ts— the new lines insrc/selfhost/ai.tsshifted line numbers for existing env var references; no env vars were added or removed)npm run selfhost:validate-observabilitynpm run cf-typegen:check(clean — no wrangler binding/var changed)npm run db:migrations:check/npm run db:schema-drift:check(clean — no schema change)npm run test:cionce after the initial implementation, thentypecheck+ the two affected unit test files again after each subsequent rebase onto a fast-movingmain.Safety
ui:openapi:checkconfirms.)apps/gittensory-uifile touched is the regenerated env-reference data file.)UI Evidencesection below with screenshots. (N/A — this PR has no visible UI change.)Notes
jobId,repoFullName,pullNumber,attempt) are forwarded purely for operator log correlation; the error/detail text itself still goes through the existingerrorMessage()secret-redaction path unchanged, and the new regression test asserts no secret value appears in the logged output.attemptinrunWorkersOpinionis the reviewer's own per-model retry counter (0, 1, 2) already computed in that loop — forwarded as-is, not invented.