Skip to content

feat(selfhost): add AI provider fallback chains - #3058

Merged
JSONbored merged 2 commits into
mainfrom
codex/provider-fallback-chain
Jul 4, 2026
Merged

feat(selfhost): add AI provider fallback chains#3058
JSONbored merged 2 commits into
mainfrom
codex/provider-fallback-chain

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • make AI_PROVIDER comma lists resolve to one primary reviewer plus a fallback by default
  • keep true two-reviewer mode available behind AI_DUAL_REVIEW=1
  • default Codex and Claude Code effort to medium for subscription-token conservation
  • add fallback-attempt metrics, dashboard coverage, cache fingerprinting, generated env docs, and user-facing docs

Why

  • lets self-hosted ORB run Codex first and fall back to Claude Code when Codex quota/auth fails without spending both providers on every PR
  • keeps reviewer-chain changes from reusing stale AI review cache entries
  • gives operators visibility into how often fallback is actually used

Validation

  • npx vitest run test/unit/selfhost-ai.test.ts test/unit/ai-review.test.ts test/unit/ai-review-advisory.test.ts test/unit/ai-review-cache-input.test.ts test/unit/selfhost-grafana-dashboard.test.ts test/unit/selfhost-env-reference-script.test.ts test/unit/selfhost-config-examples.test.ts
  • npm run typecheck
  • npm run selfhost:validate-observability
  • npm run selfhost:env-reference:check
  • git diff --check
  • npm run test:coverage

Notes

  • Default fallback config is now AI_PROVIDER=codex,claude-code.
  • Use AI_DUAL_REVIEW=1 only when you intentionally want both providers to spend tokens on the same PR.
  • Existing AI usage counters remain available for token-per-review analysis; this adds a fallback counter so fallback spend is visible separately.

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui 215ab47 Commit Preview URL

Branch Preview URL
Jul 04 2026, 06:36 PM

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 4, 2026
@loopover-orb

loopover-orb Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-04 18:38:40 UTC

17 files · 1 AI reviewer · no blockers · readiness 93/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review

Review summary
The change correctly shifts comma-separated self-host providers from dual-review-by-default to a single reviewer with one fallback, updates cache fingerprinting so fallback changes invalidate stale AI reviews, and adds a fallback-attempt metric through the existing review path. The core wiring is coherent for the documented two-provider `codex,claude-code` case, but the implementation only preserves one fallback even though the PR and docs describe fallback chains. I do not see a reachable break in the provided diff, but the chain semantics should be tightened or documented as single-fallback before merge.

Nits — 6 non-blocking
  • src/selfhost/ai.ts:970: nit: `AI_PROVIDER=a,b,c` is described as a fallback chain, but `resolveAiReviewerPlan` keeps only the first distinct fallback via `names.find(...)`, so either support the full chain or change the wording to "one fallback" everywhere.
  • src/services/ai-review.ts:697: nit: `gittensory_ai_review_model_fallback_total` increments before the fallback model actually runs, so the metric is really fallback-selected rather than fallback-attempted if future code adds a preflight/skip path here.
  • grafana/dashboards/gittensory.json:1287: nit: the new fallback PromQL target lacks `or vector(0)`, unlike several zero-safe dashboard counters covered elsewhere, so the panel may disappear when the counter has never been emitted.
  • src/selfhost/ai.ts:975: nit: `enabledEnvFlag` accepts true-ish values but there is no explicit test that `AI_DUAL_REVIEW=0/false/off` stays in fallback mode; add that branch because this env flag controls token-spend semantics.
  • src/selfhost/ai.ts:970: Either change the plan shape to carry `fallbacks: string[]` and teach `runWorkersOpinion` to walk them, or rename the user-facing docs/comments from fallback chain to primary-plus-one-fallback.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ⚠️ Missing No linked issue or no-issue rationale found.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 60 registered-repo PR(s), 50 merged, 442 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 60 PR(s), 442 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: not available
  • Official Gittensor activity: 60 PR(s), 442 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Explain no-issue PR.
  • No action.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 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.

  • Re-run Gittensory review

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.71%. Comparing base (fa38886) to head (215ab47).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3058      +/-   ##
==========================================
- Coverage   94.71%   94.71%   -0.01%     
==========================================
  Files         269      269              
  Lines       29544    29558      +14     
  Branches    10773    10781       +8     
==========================================
+ Hits        27984    27997      +13     
  Misses        916      916              
- Partials      644      645       +1     
Files with missing lines Coverage Δ
src/review/ai-review-cache-input.ts 100.00% <100.00%> (ø)
src/selfhost/ai-config.ts 100.00% <100.00%> (ø)
src/selfhost/ai.ts 97.99% <100.00%> (-0.22%) ⬇️
src/selfhost/metrics.ts 100.00% <ø> (ø)
src/services/ai-review.ts 95.67% <100.00%> (+0.03%) ⬆️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

JSONbored added 2 commits July 4, 2026 11:32
ui:lint failed with 5 prettier/prettier errors in the two self-hosting
docs routes touched by the fallback-chain change; re-wrap the affected
paragraphs to match the repo's line-width formatting, no wording change.
@JSONbored
JSONbored force-pushed the codex/provider-fallback-chain branch from 06c52f8 to 215ab47 Compare July 4, 2026 18:34
@JSONbored JSONbored self-assigned this Jul 4, 2026
@JSONbored
JSONbored merged commit d5282e3 into main Jul 4, 2026
13 checks passed
@JSONbored
JSONbored deleted the codex/provider-fallback-chain branch July 4, 2026 18:42
JSONbored added a commit that referenced this pull request Jul 4, 2026
apps/gittensory-ui/src/lib/selfhost-env-reference.ts drifted again
after #3058 (AI provider fallback chains) shifted line numbers in
src/selfhost/ai.ts without regenerating the reference, breaking
npm run selfhost:env-reference:check on a clean main checkout. Pure
regeneration via npm run selfhost:env-reference, no manual edits.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Development

Successfully merging this pull request may close these issues.

1 participant