← Research

The Recovea Score

This page explains the 0-100 Recovea Score in the right rail of the Unit economics page, served by GET /platform/v1/roi/score on Growth and above. No workspace has a score today.

What it is

The Score is an in-product spend hygiene index for one workspace, 0-100, higher is healthier. It is the plain integer average of a set of named factors, each itself 0-100. It is not a rating of a model, a provider, or a vendor, and it is not a public badge. No badge surface exists in phase 0. Every response carries beta: true and a link to this page.

How it is computed

The Score carries no money. Its inputs are factor integers from the scoring engine. No float touches any path here.

  1. Factors. The ROI store returns an ordered list of { name, score }. name is an opaque label. score is an integer, documented range 0-100.
  2. Absent is null. No factor list, or an empty one, returns score: null with factors: []. We never substitute a zero, a default, or an average over a partial set.
  3. Headline. With sum the factor total and count their number, headline = (sum + count / 2) / count. Both divisions truncate toward zero, so count / 2 floors before it is added. For an even count this is round-half-up. For an odd count an exact half cannot occur, so the rule is round-half-up in every case.
  4. Payload. The headline is score, factors return verbatim in engine order, beta is true, and methodology comes from one link registry, structurally tested to resolve to a public recovea.ai/research page.
  5. Gate. Below Growth the endpoint returns the plan fence carrying real captured measured spend, not a score. Reading requires the ReadObservability capability.

Worked example, the vector pinned by our test suite:

FactorScore
attribution coverage71
cache discipline58
route concentration63

sum = 192, count = 3, count / 2 = 1, (192 + 1) / 3 = 193 / 3 = 64 after truncation. The rail would render 64/100. Those three names are test fixtures, not a shipped factor set. No factor definition exists in the codebase.

Money elsewhere in the product is integer micro-USD at 1,000,000 to the dollar. Receipts and ledger rows chain under recovea-chain-v1, the only recipe production writes: SHA-256 over canonical field strings joined with U+001F, lowercase hex. A second recipe, recovea-receipt-v1, is published with golden vectors, but nothing in the API writes it.

What it does not include

  • Output quality. Nothing here inspects a completion.
  • Provider invoices, credits, discounts, committed-use terms, taxes, or your Recovea subscription.
  • Prompts, completions, header values, raw paths.
  • Traffic that did not pass through the Recovea gateway.
  • Any verified figure. Basis has no Verified variant in phase 0.
  • Any cohort, percentile, or benchmark against other workspaces.

Limits and current status

  • The engine is not shipped. SqlxRoiStore::score_factors hard-returns Ok(None). There is no score table, no score column, and no scoring job in any migration. Every Growth workspace receives score: null and factors: [], and the rail renders -/100. No workspace has ever had a score.
  • The factor range is documented, not enforced. score is a u8 with no clamp, and the headline is not clamped either. A factor above 100 would pass through and overflow the UI bar. Nothing can produce one today, because nothing produces factors at all.
  • Budgets. Only workspace-scoped caps reach the gateway. The cap snapshot message is workspace-scoped by construction, and the snapshot query filters scope_kind = 'workspace'. Key- and project-scoped budgets can be created and stored, but nothing enforces them in path yet.
  • Alerts. The sweep clock is rate(1 minute), so a fast burst can cross a threshold and reach a cap between checks. Alerts warn on the way up. They are not an ordering guarantee.
  • Counterfactual. Savings are measured with applied hard-false. An absent lever row means off, and no lever is activated in any deployed environment, so the realized model always equals the baseline.
  • CPSO. Figures are at list price. The live / settled badge is a calendar comparison only: a row reads settled the moment the month ends, whether or not anything reconciled. Invoice reconciliation at period close is planned, not wired.
  • Spend and attribution layer drift. The same money is read from different tables depending on caller. Workspace-scope budget spend sums rollup_daily, key-scope budget spend sums receipts, and project scope returns None, so a project budget is skipped rather than assumed zero. CPSO and route spend read receipts; attribution cuts read rollup_cuts and rollup_tag_cuts. The rollups are written inside the ingest transaction, so they should agree, but nothing continuously proves it, and the CPSO query ignores the cost_state column. The request feed's env is hardcoded to live, because receipts has no environment column.

Where to check us

  1. Call the endpoint. On a Growth workspace it returns score: null, factors: [], beta: true. That is the whole truth today. A non-null score without a matching update to this page is our bug.
  2. Re-derive the headline when factors ship. Sum factors[].score, add floor(count / 2), divide by count with integer truncation. It must equal score exactly.
  3. Re-derive the money underneath. Export with the key-authed GET /v1/ledger/export?period=YYYY-MM&format=csv. Rows carry recipe, previous_hash, row_hash, cost_micro_usd, price_list_version, and token counts. Re-price each row from its tokens and pinned price version, then re-derive each row_hash with SHA-256 and confirm the links. A published price version never changes, and verification never calls home. The session route GET /platform/v1/ledger/export serves the same rows in camelCase; the field map for both is on the ledger page.