Skip to content

HTTP API: economics

What a coding session consumes with Majordomus installed and without it, from recorded runs: matched control and treatment sessions judged by the same hidden acceptance tests, the provider's usage as it reported it, and every number labelled with its measurement class (observed, counted, derived, estimated, counterfactual). One calculator; every surface is a projection of it, and the verdict states only what the methodology's publication rule allows.

Rendered from docs/generated/openapi.json, which the executable generates from its capability registry and CI refuses stale. The raw document is at /openapi.json; a running server serves the same document at its own /openapi.json and Swagger UI at /swagger.

economics

What a coding session consumes with Majordomus installed and without it, from recorded runs: matched control and treatment sessions judged by the same hidden acceptance tests, the provider's usage as it reported it, and every number labelled with its measurement class (observed, counted, derived, estimated, counterfactual). One calculator; every surface is a projection of it, and the verdict states only what the methodology's publication rule allows.

GET /api/v1/economics economics.summary

Token economics summary

Every metric of the economics benchmark with its value, measurement class, sample size, distribution and bootstrap interval; every pair of runs with its status (valid, control failed, treatment failed, incomparable, ...); results by segment; the state of each suite's evidence (current, stale, incompatible); and the one statement the publication rule allows. Context reduction and total-token reduction are separate metrics and are never merged.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=8, ttl_seconds=5)
  • MCP tool majordomus_economics
  • MCP resource {"name": "economics", "uri": "majordomus://economics"}
  • $ economics summary

Query parameters

nametyperequireddescriptionexamples
suite string no Only this suite. narrowed: "pilot"
category string no Only tasks of this category. narrowed: "bug-fix"
task string no Only this task. narrowed: "vat-rounding"
model string no Only runs that asked for this model. narrowed: "claude-sonnet-5"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/economics?suite=pilot&category=bug-fix&task=vat-rounding&model=claude-sonnet-5"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 EconomicsSummary Token economics summary: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.
GET /api/v1/economics/check economics.check

Refuse unsupported economics claims

Scan the repository's hand-written prose and claim sentences for a quantity (a percentage, 'N times fewer') stated next to the economics vocabulary, and check every claim the methodology binds to a metric: a bound claim may be guaranteed only while its metric's evidence meets the binding and is current. `ok: false` names every finding.

  • query
  • behaviorally_verified
  • benchmark required
  • cache disabled
  • MCP tool majordomus_economics_check
  • $ economics check

No parameters.

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/economics/check"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 EconomicsCheckReport Refuse unsupported economics claims: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.
GET /api/v1/economics/explain economics.explain

Explain one economics metric

One metric and everything it rests on: its formula, its measurement class and what that class means, the pairs and runs behind it (including the invalid ones), excluded runs, the suites and revisions, and the commands that reproduce it. A repository that declares no methodology has no metric, and any id is answered with `present: false` and the statement why, not refused.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=32, ttl_seconds=5)
  • MCP tool majordomus_economics_explain
  • $ economics explain

Query parameters

nametyperequireddescriptionexamples
metric string yes The metric's id, as `economics.summary` lists it. primary: "effective_token_reduction"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/economics/explain?metric=effective_token_reduction"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 EconomicsExplanation Explain one economics metric: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.
GET /api/v1/economics/runs economics.runs

Recorded benchmark runs

The raw facts every economics metric is computed from: each recorded run with its task, variant, repetition, model, revision, success-gate verdicts and the totals derived from its provider usage, and the path of its record.

  • query
  • behaviorally_verified
  • benchmark required
  • cache process (max_entries=16, ttl_seconds=5)
  • MCP tool majordomus_economics_runs
  • $ economics runs

Query parameters

nametyperequireddescriptionexamples
suite string no Only this suite. narrowed: "pilot"
task string no Only this task. narrowed: "vat-rounding"
variant string no Only this variant. narrowed: "baseline"

Try it

The port is whatever the server logged; 8741 is the one it asks for first. The values are the operation's first example.

curl -s "http://127.0.0.1:8741/api/v1/economics/runs?suite=pilot&task=vat-rounding&variant=baseline"

Tested by apps/majordomus-cli/tests/http_serve.rs, which replays the route with these values against a server on a real socket.

Responses

statusbodymeaning
200 EconomicsRunList Recorded benchmark runs: the result.
400 ErrorBody invalid_input: The input does not fit the schema: a parameter of the wrong type, an unknown one, or a value the capability rejects.
404 ErrorBody not_found: The input names something the repository does not hold.
500 ErrorBody internal: The capability failed for a reason of its own; the message names it.
default ErrorBody Any other failure the transport reports: 405 method_not_allowed for another method on this path, 400 invalid_input for a body that is not a JSON object.

Schemas

The components only this tag's operations use. Each row is the type's own field, its doc comment the description; a type another page owns links there.

EconomicsCheck

object
One success gate's verdict on a run.

use majordomus_cli::economics::model::EconomicsCheck;
let c = EconomicsCheck { id: "tests_kept".into(), passed: true, detail: "0 deleted".into() };
let back: EconomicsCheck = serde_json::from_value(serde_json::to_value(&c).unwrap()).unwrap();
assert_eq!(back, c);
propertytyperequireddescription
id string yes The gate's id.
passed boolean yes Whether it passed.
detail string yes What was found.

Used by EconomicsRunView

EconomicsCheckReport

object
The answer of economics.check, the same over the CLI, HTTP and MCP: how much was read and every refusal. ok is true exactly when findings is empty. scanned counts the hand-written files read, docs/CLAIMS.yaml included and generated files excluded; claims_checked counts the methodology's claim bindings, whatever their status.

use majordomus_cli::economics::claims::{check, EconomicsCheckReport};
let dir = tempfile::tempdir().unwrap();
let git = std::process::Command::new("git")
    .env_remove("GIT_DIR").env_remove("GIT_WORK_TREE").env_remove("GIT_INDEX_FILE")
    .arg("-C").arg(dir.path()).args(["init", "-q"]).status().unwrap();
assert!(git.success());
let report: EconomicsCheckReport = check(dir.path());
assert!(report.ok && report.findings.is_empty(), "an empty repository claims nothing");
let json = serde_json::to_value(&report).unwrap();
assert_eq!(json["claims_checked"], 0);
assert_eq!(serde_json::from_value::<EconomicsCheckReport>(json).unwrap(), report);
propertytyperequireddescription
ok boolean yes No finding.
scanned integer (uint) yes Files scanned.
claims_checked integer (uint) yes Bound claims checked.
findings array of EconomicsFinding → EconomicsFinding yes Every finding.

Used by economics.check

EconomicsClass

"observed" | "counted" | "derived" | "estimated" | "counterfactual"
How a number came to be. The classes are ordered from strongest to weakest, and a value computed from several inputs is never stronger than the weakest of them.

use majordomus_cli::economics::model::EconomicsClass;
assert_eq!(serde_json::to_value(EconomicsClass::Counterfactual).unwrap(), "counterfactual");
let parsed: EconomicsClass = serde_json::from_value("observed".into()).unwrap();
assert!(parsed < EconomicsClass::Estimated, "a stronger class sorts first");
  • observedReturned by the provider or its harness at run time and recorded unmodified.
  • countedComputed deterministically from bytes on disk with a named, pinned tokenizer.
  • derivedArithmetic over observed or counted values.
  • estimatedA number standing in for one nobody measured. Never compared, never published.
  • counterfactualWhat a mechanism would have avoided, modelled rather than observed.

Used by EconomicsMetric

EconomicsContextView

object
The context suite's latest measurement, in brief.

use std::collections::BTreeMap;
use majordomus_cli::economics::model::{EconomicsContextView, EconomicsTokenizer};
let v = EconomicsContextView {
    revision: "8d37d011ef".into(), measured_at: "2026-09-24T10:00:00Z".into(),
    tokenizer: EconomicsTokenizer {
        encoding: "o200k_base".into(), implementation: "tiktoken-rs 0.12.0".into(),
    },
    seeds: 2, candidate_tokens: 20_000, considered_tokens: 300_000, selected_tokens: 15_000,
    estimated_selected_tokens: 16_000,
    excluded_tokens: BTreeMap::from([("budget".into(), 5_000)]),
    seeds_over_budget_counted: 0, budget_tokens: 8_000,
};
assert_eq!(v.selected_tokens + v.excluded_tokens["budget"], v.candidate_tokens);
assert_eq!(serde_json::to_value(&v).unwrap()["tokenizer"]["encoding"], "o200k_base");
propertytyperequireddescription
revision string yes The revision measured.
measured_at string yes When.
tokenizer EconomicsTokenizer → EconomicsTokenizer yes The tokenizer.
seeds integer (uint) yes Seeds measured.
candidate_tokens integer (uint64) yes Counted candidate tokens (relevant: selected or cut by the budget), all seeds.
considered_tokens integer (uint64) yes Counted tokens of everything the compiler reached, all seeds.
selected_tokens integer (uint64) yes Counted selected tokens, all seeds.
estimated_selected_tokens integer (uint64) yes The compiler's own estimate of the selected tokens, all seeds.
excluded_tokens map of integer (uint64) yes Counted tokens left out, by reason, all seeds.
seeds_over_budget_counted integer (uint) yes Seeds whose counted selection exceeds the compiler's budget.
budget_tokens integer (uint64) yes The compiler's budget.

Used by EconomicsSummary

EconomicsDistribution

object
The shape of a set of per-pair values.

use majordomus_cli::economics::model::EconomicsDistribution;
let d: EconomicsDistribution = serde_json::from_value(serde_json::json!({
    "n": 1, "mean": 0.4, "median": 0.4, "p25": 0.4, "p75": 0.4, "p95": 0.4,
    "min": 0.4, "max": 0.4
}))
.unwrap();
assert!(d.sd.is_none(), "one value has no sample standard deviation");
assert!(d.min <= d.p25 && d.p25 <= d.median && d.median <= d.p75 && d.p75 <= d.max);
propertytyperequireddescription
n integer (uint) yes How many values.
mean number (double) yes Arithmetic mean.
median number (double) yes Median.
p25 number (double) yes 25th percentile.
p75 number (double) yes 75th percentile.
p95 number (double) yes 95th percentile.
min number (double) yes Smallest.
max number (double) yes Largest.
sd number | null no Sample standard deviation; absent for one value.

Used by EconomicsMetric EconomicsSegment

EconomicsExclusion

object
One run excluded under the outlier rule.

use majordomus_cli::economics::model::{EconomicsExclusion, EconomicsOutlierPolicy};
let o: EconomicsOutlierPolicy = serde_json::from_value(serde_json::json!({
    "rule": "A run is excluded only by naming it here with a reason.",
    "excluded": [{ "run": "vat-rounding--baseline--r2", "reason": "provider outage" }]
}))
.unwrap();
let first: &EconomicsExclusion = &o.excluded[0];
assert_eq!(first.run, "vat-rounding--baseline--r2");
let unexplained = serde_json::json!({ "run": "vat-rounding--baseline--r1" });
assert!(serde_json::from_value::<EconomicsExclusion>(unexplained).is_err());
propertytyperequireddescription
run string yes The run's id.
reason string yes Why.

Used by EconomicsExplanation

EconomicsExplanation

object
The answer of economics.explain: one metric, and everything it rests on.

A repository that declares no benchmark methodology measures nothing, so it has no metric to explain: it is answered as economics.summary answers it — present: false, the statement why, no metric and no number — rather than refused, because a repository that does not benchmark itself is not a malformed request. A metric id that a declared methodology does not have is still refused.

use majordomus_cli::economics::model::{EconomicsClass, EconomicsExplanation};
let e: EconomicsExplanation = serde_json::from_value(serde_json::json!({
    "present": true,
    "metric": { "id": "context_reduction_ratio", "title": "Context reduction",
        "class": "derived", "inputs": "counted", "unit": "ratio",
        "formula": "median over seeds of 1 - selected_tokens / candidate_tokens",
        "status": "not_measured", "n": 0, "suite": "context" },
    "class_meaning": "Arithmetic over observed or counted values.", "methodology": 1,
    "suites": [], "pairs": [], "excluded": [], "variants": [],
    "reproduce": ["majordomus economics measure --suite context"]
}))
.unwrap();
assert_eq!(e.metric.unwrap().inputs, Some(EconomicsClass::Counted));
assert!(e.pairs.is_empty(), "a counted metric rests on seeds, not on pairs");

let none: EconomicsExplanation = serde_json::from_value(serde_json::json!({
    "present": false, "statement": "No verified total-token-savings claim is available",
    "class_meaning": "", "suites": [], "pairs": [], "excluded": [], "variants": [],
    "reproduce": []
}))
.unwrap();
assert!(none.metric.is_none() && none.methodology.is_none(), "nothing declared, no number");
propertytyperequireddescription
present boolean yes Whether a methodology is declared here at all.
statement string | null no Why there is nothing to explain, when present is false.
metric EconomicsMetric | null → EconomicsMetric no The metric; absent when no methodology is declared.
class_meaning string yes What its class means, in the methodology's words.
methodology integer | null no The methodology version; absent when none is declared.
suites array of EconomicsSuiteView → EconomicsSuiteView yes The suites it draws on.
pairs array of EconomicsPair → EconomicsPair yes The pairs it rests on, valid or not, when it rests on pairs.
excluded array of EconomicsExclusion → EconomicsExclusion yes Runs excluded under the outlier rule.
variants array of EconomicsVariant → EconomicsVariant yes The arms compared.
reproduce array of string yes How to reproduce it.

Used by economics.explain

EconomicsFinding

object
One thing the check refuses. detail names the remedy, so a finding can be acted on without reading the methodology. A finding about a claim or a file rather than a line carries no line, and its JSON omits the key. The kinds:

  • unsupported_quantity: a number typed into hand-written prose next to the economics vocabulary.
  • claim_unsupported: a claim binding that does not hold — the bound claim is missing from docs/CLAIMS.yaml, or it is guaranteed while its metric does not stand where the binding says or its evidence is not current.
  • claim_unbound: a guaranteed claim says tokens, context or cost go down and no binding ties it to a metric.
  • claim_duplicate: one claim id appears more than once in docs/CLAIMS.yaml.
  • declarations_unreadable: the benchmark declarations cannot be read, so no binding can be shown to hold.
  • claims_unreadable: docs/CLAIMS.yaml exists and cannot be read or parsed.
  • scan_failed: the prose could not be listed or a file in it could not be read, so nothing can be said to be clean.
use majordomus_cli::economics::claims::EconomicsFinding;
let finding = EconomicsFinding {
    kind: "claim_unsupported".into(),
    path: "docs/CLAIMS.yaml".into(),
    line: None,
    detail: "set the claim to planned, or record the evidence".into(),
};
let json = serde_json::to_value(&finding).unwrap();
assert!(json.get("line").is_none(), "no line, no key");
assert_eq!(serde_json::from_value::<EconomicsFinding>(json).unwrap(), finding);
propertytyperequireddescription
kind string yes unsupported_quantity, claim_unsupported, claim_unbound, claim_duplicate, declarations_unreadable, claims_unreadable or scan_failed.
path string yes Repository-relative path.
line integer | null no 1-based line, when the finding is about a line.
detail string yes What was found, and what to do about it.

Used by EconomicsCheckReport

EconomicsFreshness

"current" | "stale" | "incompatible" | "no_evidence"
How recorded evidence stands against the repository as it is now.

use majordomus_cli::economics::model::EconomicsFreshness;
assert_eq!(serde_json::to_value(EconomicsFreshness::NoEvidence).unwrap(), "no_evidence");
let f: EconomicsFreshness = serde_json::from_value("incompatible".into()).unwrap();
assert_eq!(f, EconomicsFreshness::Incompatible);
  • currentRecorded under this methodology, and nothing it depends on changed since.
  • staleRecorded under this methodology, but a mechanism it measured changed since.
  • incompatibleRecorded under another methodology version: not comparable at all.
  • no_evidenceNothing recorded.

Used by EconomicsSuiteView

EconomicsHistoryPoint

object
A recorded measurement over time: one entry per recorded context run.

use majordomus_cli::economics::model::EconomicsHistoryPoint;
let p: EconomicsHistoryPoint = serde_json::from_value(serde_json::json!({
    "suite": "context", "methodology": 1, "revision": "8d37d011ef",
    "at": "2026-09-24T10:00:00Z", "metric": "context_reduction_ratio", "value": 0.62, "n": 40
}))
.unwrap();
assert_eq!((p.methodology, p.n), (1, 40));
assert_eq!(serde_json::to_value(&p).unwrap()["metric"], "context_reduction_ratio");
propertytyperequireddescription
suite string yes The suite.
methodology integer (uint32) yes The methodology version, so that incompatible versions are never drawn as one line.
revision string yes The revision.
at string yes When.
metric string yes The metric.
value number (double) yes Its value.
n integer (uint) yes How many values it rests on.

Used by EconomicsSummary

EconomicsHypothesis

object
A statement the benchmark exists to test. Never a result.

use majordomus_cli::economics::model::EconomicsHypothesis;
let h: EconomicsHypothesis = serde_json::from_value(serde_json::json!({
    "id": "continuity",
    "statement": "Work that spans sessions gains the most.",
    "status": "untested"
}))
.unwrap();
assert_eq!(h.status, "untested");
assert_eq!(serde_json::to_value(&h).unwrap()["id"], "continuity");
propertytyperequireddescription
id string yes A slug.
statement string yes What is hypothesised.
status string yes untested, supported, refuted — set by a person reading the evidence.

Used by EconomicsSummary

EconomicsInterval

object
A bootstrap interval, with everything needed to reproduce it.

use majordomus_cli::economics::model::EconomicsInterval;
let i: EconomicsInterval = serde_json::from_value(serde_json::json!({
    "level_bp": 9500, "low": 0.21, "high": 0.38,
    "method": "bootstrap percentile of the median", "resamples": 10000, "seed": 20260924
}))
.unwrap();
assert!(i.low <= i.high);
assert_eq!(serde_json::to_value(&i).unwrap()["seed"], 20260924, "the seed travels with it");
propertytyperequireddescription
level_bp integer (uint32) yes Confidence in basis points.
low number (double) yes Lower bound.
high number (double) yes Upper bound.
method string yes How it was computed: a cluster bootstrap over tasks for every metric over pairs or runs, whose repetitions of one task are not independent, and an independent bootstrap over seeds for the context suite.
resamples integer (uint32) yes Resamples.
seed integer (uint64) yes Generator seed.

Used by EconomicsMetric

EconomicsMetric

object
One metric: its value, where it comes from, and how much it can bear.

use majordomus_cli::economics::model::{EconomicsClass, EconomicsMetric, EconomicsMetricStatus};
let m: EconomicsMetric = serde_json::from_value(serde_json::json!({
    "id": "effective_token_reduction", "title": "Effective token reduction",
    "class": "derived", "inputs": "observed", "unit": "ratio",
    "formula": "median of 1 - treatment / control", "status": "not_measured", "n": 0,
    "suite": "pilot"
}))
.unwrap();
assert_eq!(m.inputs, Some(EconomicsClass::Observed));
assert!(m.value.is_none() && m.status == EconomicsMetricStatus::NotMeasured);
assert!(serde_json::to_value(&m).unwrap().get("value").is_none(), "no value, not a zero");
propertytyperequireddescription
id string yes The metric's id.
title string yes A name.
class EconomicsClass → EconomicsClass yes The measurement class.
inputs EconomicsClass | null → EconomicsClass no For a derived metric, the class of what it was derived from: a reduction derived from observed usage is not the same evidence as one derived from counted bytes.
unit string yes ratio, tokens, calls.
formula string yes The formula, in words.
not string | null no What the metric is not, where it is easily mistaken for something else.
value number | null no The headline value; absent when nothing was measured.
status EconomicsMetricStatus → EconomicsMetricStatus yes Where it stands.
n integer (uint) yes How many values it rests on.
distribution EconomicsDistribution | null → EconomicsDistribution no Their distribution.
interval EconomicsInterval | null → EconomicsInterval no The interval, when enough values exist.
suite string yes The suite.
evidence array of string no The runs, pairs or seeds it rests on.
warnings array of string no What a reader must know before using it.

Used by EconomicsExplanation EconomicsSummary

EconomicsMetricStatus

"verified" | "preliminary" | "measured" | "not_measured"
Where a metric stands against the publication rule: whether its value may back a claim, is a result too thin to claim anything, or was never measured at all.

use majordomus_cli::economics::model::EconomicsMetricStatus;
assert_eq!(serde_json::to_value(EconomicsMetricStatus::NotMeasured).unwrap(), "not_measured");
let s: EconomicsMetricStatus = serde_json::from_value("preliminary".into()).unwrap();
assert_ne!(s, EconomicsMetricStatus::Verified, "a preliminary result is not a claim");
  • verifiedMeasured, and meets the publication rule. Only the primary metric over all the evidence can be: the rule is evaluated for it and for nothing else, so no secondary metric and no narrowed slice is ever verified.
  • preliminaryMeasured, but no claim may rest on it: below the publication rule, narrowed by a query, or a metric the rule was never evaluated for. A result, not a claim.
  • measuredMeasured deterministically; the publication rule for sampled data does not apply.
  • not_measuredNothing recorded to compute it from.

Used by EconomicsMetric

EconomicsPair

object
A control run and its treatment run, and what follows from them.

use majordomus_cli::economics::model::{EconomicsPair, EconomicsPairStatus};
let p: EconomicsPair = serde_json::from_value(serde_json::json!({
    "suite": "pilot", "task": "vat-rounding", "category": "bugfix", "sessions": 1,
    "repetition": 2, "control": "vat-rounding--baseline--r2", "status": "missing",
    "reasons": ["no treatment run recorded"]
}))
.unwrap();
assert_eq!(p.status, EconomicsPairStatus::Missing);
assert!(p.treatment.is_none() && p.token_reduction.is_none(), "no side, no reduction");
propertytyperequireddescription
suite string yes The suite.
task string yes The task.
category string yes The task's category.
sessions integer (uint) yes Sessions the task spans.
repetition integer (uint32) yes The repetition.
control string | null no The control run's id, when recorded.
treatment string | null no The treatment run's id, when recorded.
status EconomicsPairStatus → EconomicsPairStatus yes Whether it counts.
reasons array of string no Why not, when it does not.
control_usage EconomicsUsage | null → EconomicsUsage no The control's totals.
treatment_usage EconomicsUsage | null → EconomicsUsage no The treatment's totals.
token_reduction number | null no 1 - treatment / control on total tokens. Negative: the treatment cost more. Present on a valid pair, and on an excluded pair that would otherwise be valid, so that the outlier rule's effect can be shown both ways; only valid pairs enter a metric other than effective_token_reduction.including_excluded. The same holds for every reduction and overhead below.
cost_reduction number | null no The same on the harness's cost projection.
tool_call_reduction number | null no The same on tool calls.
continuation_reduction number | null no The same on the tokens of the last session only: what continuing cost.
first_request_overhead integer | null no First-request input of the treatment minus that of the control: what the treatment adds before the model has done anything.

Used by EconomicsExplanation EconomicsSummary

EconomicsPairCounts

object
Pair counts of a suite, so that nothing is dropped out of sight.

use majordomus_cli::economics::model::EconomicsPairCounts;
let c = EconomicsPairCounts {
    declared: 14, attempted: 12, valid: 9, control_failed: 1,
    treatment_failed: 1, both_failed: 0, other: 1,
};
let accounted = c.valid + c.control_failed + c.treatment_failed + c.both_failed + c.other;
assert_eq!(accounted, c.attempted, "every attempted pair is in exactly one bucket");
assert_eq!(EconomicsPairCounts::default().declared, 0);
propertytyperequireddescription
declared integer (uint) yes Pairs the suite declares.
attempted integer (uint) yes Pairs with at least one run recorded.
valid integer (uint) yes Pairs that count.
control_failed integer (uint) yes Pairs whose control failed.
treatment_failed integer (uint) yes Pairs whose treatment failed.
both_failed integer (uint) yes Pairs where both failed.
other integer (uint) yes Pairs not comparable, missing a side, lacking usage, or excluded.

Used by EconomicsSuiteView

EconomicsPairStatus

"valid" | "control_failed" | "treatment_failed" | "both_failed" | "usage_unavailable" | "incomparable" | "missing" | "excluded"
Why a pair does or does not count.

use majordomus_cli::economics::model::EconomicsPairStatus;
assert_eq!(serde_json::to_value(EconomicsPairStatus::ControlFailed).unwrap(), "control_failed");
let s: EconomicsPairStatus = serde_json::from_value("usage_unavailable".into()).unwrap();
assert_ne!(s, EconomicsPairStatus::Valid);
  • validBoth runs succeeded, are comparable and report usage.
  • control_failedThe control run failed a success gate.
  • treatment_failedThe treatment run failed a success gate.
  • both_failedBoth failed.
  • usage_unavailableA run reports no usage to compare.
  • incomparableThe runs differ in something the methodology requires them to share.
  • missingOne side was never recorded.
  • excludedA run is excluded under the outlier rule.

Used by EconomicsPair

EconomicsPublicationPolicy

object
When a quantitative total-token claim may be published. Every threshold must hold.

use majordomus_cli::economics::model::EconomicsPublicationPolicy;
let rule = serde_json::json!({
    "min_valid_pairs": 30, "min_categories": 4, "min_pairs_per_category": 5,
    "min_repetitions": 3, "min_valid_pair_rate_bp": 8000, "max_interval_width_bp": 2000,
    "require_current": true
});
let p: EconomicsPublicationPolicy = serde_json::from_value(rule.clone()).unwrap();
assert!(p.require_current && p.min_valid_pairs == 30);
let mut lax = rule;
lax.as_object_mut().unwrap().remove("require_current");
assert!(serde_json::from_value::<EconomicsPublicationPolicy>(lax).is_err(), "no default");
propertytyperequireddescription
min_valid_pairs integer (uint) yes Valid matched pairs, at least.
min_categories integer (uint) yes Task categories with enough pairs, at least.
min_pairs_per_category integer (uint) yes Pairs a category needs to count towards min_categories.
min_repetitions integer (uint32) yes Repetitions of every task and variant, at least.
min_valid_pair_rate_bp integer (uint32) yes Valid pairs over attempted pairs, in basis points, at least.
max_interval_width_bp integer (uint32) yes Width of the interval, in basis points of reduction, at most.
require_current boolean yes Whether the evidence must be current (its mechanism unchanged since it was recorded).

Used by EconomicsSummary

EconomicsRunList

object
The answer of economics.runs: the raw facts every metric is computed from.

use majordomus_cli::economics::model::EconomicsRunList;
let l: EconomicsRunList =
    serde_json::from_value(serde_json::json!({ "count": 0, "runs": [] })).unwrap();
assert_eq!(l.count, l.runs.len());
assert!(l.diagnostics.is_empty(), "no diagnostics listed means none");
propertytyperequireddescription
count integer (uint) yes How many.
runs array of EconomicsRunView → EconomicsRunView yes The runs, sorted by id.
diagnostics array of string no Records that could not be read.

Used by economics.runs

EconomicsRunView

object
One run in brief, with its derived totals.

use majordomus_cli::economics::model::EconomicsRunView;
let v: EconomicsRunView = serde_json::from_value(serde_json::json!({
    "id": "vat-rounding--majordomus--r1", "suite": "pilot", "task": "vat-rounding",
    "variant": "majordomus", "repetition": 1, "model": "claude-sonnet-5",
    "revision": "8d37d011ef", "completed": false, "checks": [], "sessions": 1,
    "path": ".ai/repo/benchmarks/economics/runs/pilot/vat-rounding--majordomus--r1.json"
}))
.unwrap();
assert!(v.usage.is_none(), "a run whose provider reported no usage has no totals");
assert!(v.path.ends_with(&format!("{}.json", v.id)));
propertytyperequireddescription
id string yes The run's id.
suite string yes The suite.
task string yes The task.
variant string yes The variant.
repetition integer (uint32) yes The repetition.
model string yes The model requested.
revision string yes The revision.
completed boolean yes Whether every success gate passed.
checks array of EconomicsCheck → EconomicsCheck yes Each gate's verdict.
sessions integer (uint) yes Sessions.
usage EconomicsUsage | null → EconomicsUsage no Totals, when the provider reported usage.
path string yes Where the raw record is.

Used by EconomicsRunList

EconomicsSegment

object
A metric's value within one segment of the pairs.

use majordomus_cli::economics::model::EconomicsSegment;
let s: EconomicsSegment = serde_json::from_value(serde_json::json!({
    "dimension": "category", "value": "multi-session", "n": 0
}))
.unwrap();
assert!(s.token_reduction.is_none(), "a segment with no valid pair has no distribution");
propertytyperequireddescription
dimension string yes category, sessions, complexity.
value string yes The segment.
n integer (uint) yes Valid pairs in it.
token_reduction EconomicsDistribution | null → EconomicsDistribution no Distribution of per-pair token reduction.

Used by EconomicsSummary

EconomicsSuiteView

object
A suite and the state of its evidence.

use majordomus_cli::economics::model::{
    EconomicsFreshness, EconomicsPairCounts, EconomicsSuiteView,
};
let v = EconomicsSuiteView {
    id: "pilot".into(), kind: "live".into(), version: 1, title: "Pilot".into(),
    model: Some("claude-sonnet-5".into()), freshness: EconomicsFreshness::NoEvidence,
    freshness_detail: Some("no run recorded".into()), runs: 0,
    pairs: EconomicsPairCounts { declared: 14, ..EconomicsPairCounts::default() },
    revisions: vec![], harnesses: vec![], models_reported: vec![],
};
let json = serde_json::to_value(&v).unwrap();
assert_eq!(json["freshness"], "no_evidence");
assert_eq!(json["pairs"]["declared"], 14, "declared pairs show even when none ran");
propertytyperequireddescription
id string yes The suite.
kind string yes live or context.
version integer (uint32) yes Its version.
title string yes A name.
model string | null no The model, for a live suite.
freshness EconomicsFreshness → EconomicsFreshness yes Where its evidence stands.
freshness_detail string | null no Why, when not current.
runs integer (uint) yes Runs recorded.
pairs EconomicsPairCounts → EconomicsPairCounts yes Pair counts.
revisions array of string no The revisions the evidence was recorded at.
harnesses array of string no The harness versions that ran it.
models_reported array of string no The models the harness reported.

Used by EconomicsExplanation EconomicsSummary

EconomicsSummary

object
The answer of economics.summary: every metric, where each comes from, and the one statement the evidence allows.

use majordomus_cli::economics::model::EconomicsSummary;
let s: EconomicsSummary = serde_json::from_value(serde_json::json!({
    "present": false,
    "verdict": { "publishable": false, "statement": "No methodology is declared." },
    "metrics": [], "suites": [], "pairs": [], "segments": [], "history": [],
    "variants": [], "hypotheses": []
}))
.unwrap();
assert!(s.methodology.is_none() && s.publication.is_none() && s.diagnostics.is_empty());
let json = serde_json::to_value(&s).unwrap();
assert!(json.get("methodology").is_none(), "an absent methodology is absent, not null");
propertytyperequireddescription
present boolean yes Whether a methodology is declared here at all.
methodology integer | null no The methodology version.
question string | null no The question.
primary_metric string | null no The primary metric's id.
verdict EconomicsVerdict → EconomicsVerdict yes What the total-token evidence allows to be said.
metrics array of EconomicsMetric → EconomicsMetric yes Every metric.
suites array of EconomicsSuiteView → EconomicsSuiteView yes Every suite and its evidence.
pairs array of EconomicsPair → EconomicsPair yes Every pair, valid or not.
segments array of EconomicsSegment → EconomicsSegment yes Token reduction by segment.
context EconomicsContextView | null → EconomicsContextView no The context suite in brief.
history array of EconomicsHistoryPoint → EconomicsHistoryPoint yes The metric over recorded measurements.
variants array of EconomicsVariant → EconomicsVariant yes The arms of the experiment.
hypotheses array of EconomicsHypothesis → EconomicsHypothesis yes The hypotheses, as hypotheses.
publication EconomicsPublicationPolicy | null → EconomicsPublicationPolicy no The publication rule.
diagnostics array of string no Problems reading the declarations or the evidence.

Used by economics.summary

EconomicsTokenizer

object
The identity of a tokenizer, recorded with every count it produced.

use majordomus_cli::economics::model::EconomicsTokenizer;
let t: EconomicsTokenizer = serde_json::from_value(serde_json::json!({
    "encoding": "o200k_base", "implementation": "tiktoken-rs 0.12.0"
}))
.unwrap();
let other = EconomicsTokenizer { implementation: "tiktoken-rs 0.13.0".into(), ..t.clone() };
assert_ne!(t, other, "the same encoding from another implementation is another tokenizer");
propertytyperequireddescription
encoding string yes The encoding: o200k_base.
implementation string yes The implementation and its pinned version.

Used by EconomicsContextView

EconomicsUsage

object
A run's totals, derived from its raw usage.

use majordomus_cli::economics::model::EconomicsUsage;
let u = EconomicsUsage {
    input_uncached: 10, cache_write: 90, cache_read: 900, output: 50,
    total_input: 1000, total: 1050, requests: 3, ..EconomicsUsage::default()
};
assert_eq!(u.total_input, u.input_uncached + u.cache_write + u.cache_read);
let json = serde_json::to_value(&u).unwrap();
assert!(json.get("reasoning").is_none() && json.get("cost_microusd").is_none());
propertytyperequireddescription
input_uncached integer (uint64) yes Input neither read from nor written to the cache.
cache_write integer (uint64) yes Input written to the cache.
cache_read integer (uint64) yes Input read from the cache.
output integer (uint64) yes Output, reasoning included.
reasoning integer | null no Reasoning tokens, when every request reported them.
total_input integer (uint64) yes All input.
total integer (uint64) yes All input and output.
requests integer (uint64) yes Provider requests.
tool_calls integer (uint64) yes Tool calls.
cost_microusd integer | null no The harness's cost projection, in millionths of a dollar, when every session had one.

Used by EconomicsPair EconomicsRunView

EconomicsVariant

object
One arm of the experiment: what the session runs with, and what it runs without.

use majordomus_cli::economics::model::EconomicsVariant;
let v: EconomicsVariant = serde_json::from_value(serde_json::json!({
    "id": "baseline", "role": "control", "title": "Without Majordomus",
    "description": "The fixture repository as a competent team keeps it."
}))
.unwrap();
assert_eq!(v.role, "control");
assert!(v.excludes.is_empty(), "an arm that names no exclusion excludes nothing");
propertytyperequireddescription
id string yes baseline, majordomus, ...
role string yes control or treatment.
title string yes A short name.
description string yes Exactly what the arm consists of.
excludes array of string no What the arm deliberately does not include.

Used by EconomicsExplanation EconomicsSummary

EconomicsVerdict

object
The one sentence the evidence allows, and why it allows no stronger one.

use majordomus_cli::economics::model::EconomicsVerdict;
let v: EconomicsVerdict = serde_json::from_value(serde_json::json!({
    "publishable": false,
    "statement": "No quantitative token claim: 9 valid pairs of the 30 the rule requires.",
    "unmet": ["min_valid_pairs: 9 < 30"]
}))
.unwrap();
assert!(!v.publishable);
assert_eq!(v.unmet.len(), 1, "every threshold not met is named");
propertytyperequireddescription
publishable boolean yes Whether a quantitative total-token claim meets the publication rule.
statement string yes The strongest statement the evidence supports, generated, never typed.
unmet array of string no Every publication threshold not met.

Used by EconomicsSummary

Searches the titles and descriptions of every page this site publishes.