Documentation Sponsor guides

Credit usage

This doc explains how Steward computes the cost of every evaluation in credits, the daily aggregation that drives the cap from Tiers + credits, and where the running totals surface in the dashboard.

What a credit costs you in dollars

One credit is approximately $0.05 of equivalent Large Language Model (LLM) cost. The exact mapping depends on which model the per-PR worker is using, but the credit unit is stable so you have a price yardstick that doesn't move every time a model release shifts provider costs.

The three scan kinds

Steward computes credits via this formula:

credits = intelligence_weight × language_multiplier

The intelligence weight comes from the scan kind — which kind of evaluation just ran. There are three.

Standard Scan — 0.5 base credits

The deterministic gates (path-based scorecard, complexity, Static Analysis Results Interchange Format (SARIF) ingestion, Developer Certificate of Origin (DCO), Contributor License Agreement (CLA)) running over a full repo. Cheap, runs frequently, no LLM call. Typically fires once per active repo per day to keep the fleet dashboard's repo-wide dimensions current.

Standard Scan, Go repo:     0.5 × 1.0 = 0.5 credits
Standard Scan, Rust repo:   0.5 × 3.0 = 1.5 credits

Deep Analysis — 5.0 credits per dimension × 9 dimensions

The repo-wide LLM-grounded review — the original Steward evaluation flow. Runs through the deterministic scorecard first, then asks an LLM to write structured prose per dimension. Fires on PR open (one full 9-dimension run) and on demand via /steward review.

Deep Analysis, Go repo:     5.0 × 9 × 1.0 =  45.0 credits
Deep Analysis, Java repo:   5.0 × 9 × 2.5 = 112.5 credits
Deep Analysis, Rust repo:   5.0 × 9 × 3.0 = 135.0 credits

Deep is expensive on purpose — it's the surface that actually moves a reputation needle, and the Caliper-first gate means it only runs when the Standard Scan surfaces something worth deeper attention.

Per-PR scoring — flat 0.05 credits

The per-PR LLM-grounded scoring system shipped in #470 — what the PR comment that lands on pull_request.opened is produced by. Flat-rate; the per-PR prompt is the diff + governance, not a per-language stack, so language doesn't factor in.

Per-PR scoring, any repo:   0.05 credits

This is the most-frequent kind by an order of magnitude — fires once per PR open or synchronize. The Pro tier's 40-credit daily cap covers roughly 800 per-PR scorings; for the same budget, Standard scans cover ~80 and a single Deep Analysis on a Rust repo eats ~30% of it in one shot.

Language multipliers

The compute weight per language category:

Category Multiplier Languages
Ultra-Light 1.0× Go, Python, TypeScript, JavaScript
Memory-Heavy 2.5× Java, Dart
Compiler-Heavy 3.0× Rust, C#, C++, Swift

The multiplier exists because the deterministic-pass cost genuinely scales by these categories — a Rust deep analysis touches more substantial AST work than a Go one. The flat-rate per-PR scoring ignores the multiplier because its cost is LLM-bound, not AST-bound.

Unknown languages degrade to Ultra-Light (1.0×). The risk of mis-charging a tenant is to them, not us — we'd rather undercharge than reject a job.

Daily aggregation + the cap

Per the tier table, each tier has a daily credit cap. The accountant is:

  • Every completed evaluation writes its credits_spent value onto its app.evaluation_jobs row (or app.pr_evaluations for per-PR scorings).
  • A partial Postgres index sums today's spend per user per UTC day. The check is cheap enough to run on every enqueue.
  • The pre-check at enqueue time looks at TODAY's running sum. If adding the next call would push you over, the call is refused and the row lands skipped(budget_exhausted).
  • The counter zeros at UTC midnight.

So: it's not a billing meter; it's a circuit breaker. You only "pay" for evaluations that actually completed, and the cap prevents a runaway worst-case-day. Real billing happens on the subscription line item; the credit budget protects you from overage anxiety.

Where the numbers surface

/sponsor/usage

The primary surface. Sections, top to bottom:

Section What it shows
Status cards (Total / Done / Running / Queued / Failed) Evaluation counts over the last 30 days. Counts, not credits — this is the "is the pipeline healthy" view.
Daily volume A 30-day bar chart of completed evaluations per day. Hovering a bar shows the date + count. Peak-day label sits in the header.
Top repos by evaluation count The 5 noisiest repos by evaluation count. Failed-column flag in red. Use this to find a repo whose CI is firing too many redundant pushes.
Credits consumed The running 30-day credit total + a per-language × scan-kind breakdown table. Hidden when no metering data has accumulated yet (the placeholder card explains what arrives when).
Per-repo cost Credits attributed to each repo. The clickable column links to /app/repos/<id>. Repos that have been uninstalled show as (removed) — historical jobs are preserved with the previous full name.

Metering caveats to know

  • Day-1 burn looks high because newly-installed repos backfill an evaluation per recent PR. Wait until day 3 for a representative burn rate.
  • Pre-metering rows return zero credits — jobs that ran before the metering pipeline shipped have no credits_spent value. They don't inflate the totals; they just sit at zero in the per-language table.
  • The placeholder shows when total_credits == "0.000". That's a NUMERIC(12,3) round-trip; treat it as "no metering data," not "zero credits."

What's next

  • Read the usage dashboard — the operator's playbook for the page above with a worked example of a "what does the burn rate spike mean?" workflow.
  • Tiers + credits — the per-tier daily caps these credits aggregate against.
  • Evaluations + dimensions — the per-PR scoring system whose flat 0.05/call shows up most of the time.