A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live
devcontext.explain
Why one thing is or is not in a compiled context
What it is
One canonical identifier judged under a request: whether it was selected, reached and excluded, folded into another identifier, held by the index and never reached, or unknown — with the entry, the exclusion or the collapse itself, and the budget the judgement was made under so that `excluded for budget` can be acted on without a second call.
Descriptor
- Canonical id
devcontext.explain- Module
devcontext- Kind
- query
- Stability
- behaviorallyverified
- Provenance
- declaredcached
- Source
apps/majordomus-cli/src/capability/builtin/devcontext.rs- Cache
process, 8 entries, no expiry- Benchmark
required- Tags
- contextprovenanceintrospection
Run
queryA query. It reads and changes nothing.
Projections
| Interface | As | Where |
|---|---|---|
| MCP tool | majordomus_devcontext_explain | - |
| MCP resource | not exposed | - |
| HTTP | GET /api/v1/devcontext/explain | Swagger |
| Command line | majordomus devcontext explain | - |
Schemas
Input · DevContextExplainInput
{
"type": "object",
"additionalProperties": false,
"properties": {
"uri": {
"type": "string",
"description": "The canonical identifier to explain."
},
"issue": {
"type": [
"string",
"null"
],
"description": "An issue id (`I0301`) or its canonical identifier. Its milestone, its dependencies,\nits declared scope and the decisions over that scope follow from it."
},
"milestone": {
"type": [
"string",
"null"
],
"description": "A milestone id or slug, or its canonical identifier."
},
"intent": {
"type": [
"string",
"null"
],
"description": "What the session is trying to do, in words. The only input the compiler infers\nfrom, and every entry it produces says so and carries a confidence below one."
},
"paths": {
"type": "array",
"items": {
"type": "string"
},
"description": "Repository-relative paths the work touches, added to whatever the seeds declare."
},
"uris": {
"type": "array",
"items": {
"type": "string"
},
"description": "Canonical identifiers to seed with directly, for a request about something that is\nneither an issue nor a milestone."
},
"budget_tokens": {
"type": [
"integer",
"null"
],
"format": "uint64",
"minimum": 0,
"description": "The ceiling in estimated tokens; `DEFAULT_BUDGET_TOKENS` when absent."
},
"max_depth": {
"type": [
"integer",
"null"
],
"format": "uint",
"minimum": 0,
"description": "How far from a seed the walk goes; `DEFAULT_MAX_DEPTH` when absent."
},
"floor": {
"type": [
"number",
"null"
],
"format": "double",
"description": "Relevance below which an entry is reported rather than given; `DEFAULT_FLOOR`\nwhen absent."
},
"all_blocking_rules": {
"type": [
"boolean",
"null"
],
"description": "Every blocking rule of the layer, not only the ones the work reaches. Honest and\nusually over budget: the answer then says `over_budget` rather than dropping what it\nmay not drop."
}
},
"required": [
"uri"
],
"description": "The input of `devcontext.explain`: one identifier, and the request to judge it under.",
"title": "DevContextExplainInput"
}Output · Explanation
{
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "What was asked about."
},
"standing": {
"$ref": "#/$defs/DevContextStanding",
"description": "Where it stands."
},
"detail": {
"type": "string",
"description": "The same, in words."
},
"entry": {
"anyOf": [
{
"$ref": "#/$defs/ContextEntry"
},
{
"type": "null"
}
],
"description": "The entry, when it is in the answer."
},
"excluded": {
"anyOf": [
{
"$ref": "#/$defs/Excluded"
},
{
"type": "null"
}
],
"description": "The exclusion, when it was reached and not given."
},
"deduplicated": {
"anyOf": [
{
"$ref": "#/$defs/Deduplicated"
},
{
"type": "null"
}
],
"description": "The collapse it was part of, when it was folded or dropped for another."
},
"budget": {
"$ref": "#/$defs/Budget",
"description": "The budget the judgement was made under, so that \"excluded for budget\" can be acted\non without a second call."
}
},
"required": [
"uri",
"standing",
"detail",
"budget"
],
"description": "Why one identifier is, or is not, in a compiled context.\n\n`standing` says which of the five cases this is, and the three optional fields are the\nevidence for it: at most one of `entry`, `excluded` and `deduplicated` is populated, and\nwhich one is determined by the standing rather than independent of it. `detail` is the\nsame answer in words, so the value is legible without a reader matching them up.\n\n`budget` is always present, including when the answer is `unknown`, and that is the\npoint of carrying it: the commonest reason to ask this question is an entry that did not\nfit, and an explanation that said \"excluded for budget\" without the budget would need a\nsecond call to act on.\n\n```\nuse majordomus_cli::devcontext::{compile, explain, CompileInput, ExplainInput};\nuse majordomus_cli::devcontext::{Explanation, Standing};\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\nlet compiled = compile(&ctx, CompileInput::default()).unwrap();\nlet selected = compiled.selected[0].uri.clone();\n\n// something in the answer: the entry is the evidence, and the other two are empty\nlet e: Explanation =\n explain(&ctx, ExplainInput { uri: selected.clone(), ..Default::default() }).unwrap();\nassert_eq!(e.standing, Standing::Selected);\nassert_eq!(e.entry.as_ref().unwrap().uri, selected);\nassert!(e.excluded.is_none() && e.deduplicated.is_none());\nassert!(!e.detail.is_empty(), \"the standing always reads as a sentence too\");\n\n// something this repository does not hold: an answer, not an error — and the budget\n// the judgement was made under is carried even here\nlet absent: Explanation = explain(\n &ctx,\n ExplainInput { uri: \"majordomus://adr/9999\".into(), ..Default::default() },\n)\n.unwrap();\nassert_eq!(absent.standing, Standing::Unknown);\nassert!(absent.entry.is_none());\nassert_eq!(absent.budget.limit_tokens, compiled.budget.limit_tokens);\n```",
"title": "Explanation",
"$defs": {
"DevContextStanding": {
"oneOf": [
{
"type": "string",
"const": "selected",
"description": "In the answer."
},
{
"type": "string",
"const": "excluded",
"description": "Reached and not given; the exclusion says why."
},
{
"type": "string",
"const": "deduplicated",
"description": "Folded into another identifier, or dropped for one."
},
{
"type": "string",
"const": "not_reached",
"description": "The index holds it and this request never reached it."
},
{
"type": "string",
"const": "unknown",
"description": "The index holds nothing under that identifier."
}
],
"description": "What one identifier's standing in a compiled context is.\nWhere one identifier stands with respect to a compiled context.\n\nThe pair to be careful about is `NotReached` and `Unknown`, because they look alike in a\nrendering and mean opposite things. `NotReached` says the index holds the object and this\nrequest did not reach it — the request is what to change, and raising the depth or the\nbudget may well bring it in. `Unknown` says the index holds nothing under that\nidentifier: the request is fine and the identifier is wrong, or the object is not in\nthis repository. Collapsing the two would send a reader to tune a request that was never\nthe problem.\n\n`Deduplicated` is the third one worth naming: the thing is *in* the answer, under another\nidentifier, which is neither in nor out.\n\n```\nuse majordomus_cli::devcontext::Standing;\n\n// in the answer, one way or another\nlet present = [Standing::Selected, Standing::Deduplicated];\n// reached and not given, so the request is what to change\nlet request_bound = [Standing::Excluded, Standing::NotReached];\nfor s in present {\n assert!(!request_bound.contains(&s));\n}\n\n// the two that must not be confused: one is the request's fault, one is not\nassert_eq!(Standing::NotReached.as_str(), \"not_reached\");\nassert_ne!(Standing::NotReached, Standing::Unknown);\nassert_eq!(\n serde_json::to_value(Standing::NotReached).unwrap(),\n serde_json::json!(Standing::NotReached.as_str()),\n);\n```"
},
"ContextEntry": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "The canonical identifier: `majordomus://<kind>/<identity>`, unique in the answer."
},
"kind": {
"type": "string",
"description": "The kind the layer declared for it."
},
"title": {
"type": [
"string",
"null"
],
"description": "Its title, when it has one."
},
"provenance": {
"$ref": "#/$defs/EntryProvenance",
"description": "Where it lives."
},
"tier": {
"$ref": "#/$defs/Tier",
"description": "Which tier's budget it is spent from."
},
"relevance": {
"type": "number",
"format": "double",
"description": "0.0 to 1.0, deterministic for a given tree and request. The order within a tier."
},
"confidence": {
"type": "number",
"format": "double",
"description": "The highest confidence of any path that reached it."
},
"discovered_by": {
"type": "array",
"items": {
"$ref": "#/$defs/Discovery"
},
"description": "Every path that reached it, best first. Length above one is the evidence that\ndeduplication happened."
},
"depth": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "The shortest number of hops from a seed."
},
"cost_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "Estimated tokens: the file's bytes divided by `BYTES_PER_TOKEN`, never fewer\nthan one. An estimate, said to be one."
},
"cost_bytes": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "The file's bytes, the measured half of the cost."
},
"version": {
"type": [
"string",
"null"
],
"description": "The version or date the object states about itself, when it states one: a rule's\nversion, an ADR's date, an issue's `updated_at`."
},
"status": {
"type": [
"string",
"null"
],
"description": "The status word the object declares, when it declares one."
},
"required": {
"type": "boolean",
"description": "True when a blocking rule, a policy or the scope: never dropped for budget."
},
"facts": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Facts worth carrying about this entry that are not the object's prose — a rule's\nclass, an issue's milestone, the commits an issue's evidence names."
}
},
"required": [
"uri",
"kind",
"provenance",
"tier",
"relevance",
"confidence",
"discovered_by",
"depth",
"cost_tokens",
"cost_bytes",
"required"
],
"description": "One thing the compiler decided a session should be given: what it is, how it was\nreached, what it costs, and how far the compiler trusts it.\n\nNotably, it does **not** carry the prose. The identifier is here and the body is not,\nbecause the body belongs to the object and `objects.get` serves it whole; copying it\nwould put the layer in the answer twice and flatten the structure into text before\nanything had decided what to keep. An entry is a decision about an object, not a copy of\none.\n\nThree of the scalars are derived from `discovered_by` rather than independent of it, and\na reader can check them: `confidence` is the highest of any path's, `depth` the shortest,\nand a `discovered_by` of length above one is the evidence that deduplication happened.\n`required` is the veto — a blocking rule, the policy, the scope, or a seed — and it is\nthe one field that overrides the budget.\n\n```\nuse majordomus_cli::devcontext::{tokens_for, ContextEntry, Selector, Tier};\nuse serde_json::json;\n\n// one ADR, reached twice: once along a declared edge and once by matching the intent\nlet e: ContextEntry = serde_json::from_value(json!({\n \"uri\": \"majordomus://adr/0052\",\n \"kind\": \"adr\",\n \"title\": \"The episode is the boundary\",\n \"provenance\": {\n \"path\": \".ai/repo/adrs/0052.md\", \"directory\": \".ai/repo/adrs\",\n \"source_class\": \"adr\", \"section\": \"adrs\", \"bytes\": 8_192,\n },\n \"tier\": \"decision\",\n \"relevance\": 0.82,\n \"confidence\": 1.0,\n \"discovered_by\": [\n {\"selector\": \"relation\", \"reason\": \"in force over this scope\",\n \"via\": \"majordomus://issue/I0301\", \"edge\": \"governed_by\",\n \"depth\": 1, \"confidence\": 1.0, \"weight\": 0.9},\n {\"selector\": \"intent_match\", \"reason\": \"the intent's words occur in it\",\n \"depth\": 2, \"confidence\": 0.4, \"weight\": 0.4},\n ],\n \"depth\": 1,\n \"cost_tokens\": 2_048,\n \"cost_bytes\": 8_192,\n \"version\": \"2026-09-11\",\n \"status\": \"accepted\",\n \"required\": false,\n})).unwrap();\n\nassert_eq!(e.tier, Tier::Decision);\n\n// the cost is the estimate over the measured bytes, and the answer carries both halves\nassert_eq!(e.cost_tokens, tokens_for(e.cost_bytes));\n\n// the derived scalars agree with the paths they are derived from\nlet best = e.discovered_by.iter().map(|d| d.confidence).fold(0.0_f64, f64::max);\nassert_eq!(e.confidence, best);\nassert_eq!(e.depth, e.discovered_by.iter().map(|d| d.depth).min().unwrap());\n\n// two paths for one entry: the record that four things pointing here is one entry\nassert_eq!(e.discovered_by.len(), 2);\nassert_eq!(e.discovered_by[0].selector, Selector::Relation, \"best path first\");\n\n// and the prose is not here: the identifier is how a caller gets the body\nassert!(e.uri.starts_with(\"majordomus://\"));\n```"
},
"EntryProvenance": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Repository-relative path, forward slashes."
},
"directory": {
"type": "string",
"description": "The directory it sits in."
},
"source_class": {
"type": "string",
"description": "The `sources.yaml` class that discovered it."
},
"section": {
"type": [
"string",
"null"
],
"description": "The manifest section it falls under, when it falls under one."
},
"bytes": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "Size of the file in bytes."
}
},
"required": [
"path",
"directory",
"source_class",
"bytes"
],
"description": "Where the selected thing lives, as the index knows it. Nothing here is authored: every\nfield is the index's own `crate::model::Provenance`, carried rather than restated.\n\nIt is a copy of the index's provenance and not a re-derivation of it, which is the\nproperty worth relying on: no path here was constructed by this module, so a path in an\nanswer is a path the index discovered, and the two cannot disagree about where something\nlives.\n\n`bytes` is the measured half of an entry's cost — the estimate on top of it is\n`tokens_for` — so this is also where the budget's arithmetic starts.\n\n```\nuse majordomus_cli::devcontext::{tokens_for, EntryProvenance};\nuse serde_json::json;\n\nlet p: EntryProvenance = serde_json::from_value(json!({\n \"path\": \".ai/repo/adrs/0052-the-episode-is-the-boundary.md\",\n \"directory\": \".ai/repo/adrs\",\n \"source_class\": \"adr\",\n \"section\": \"adrs\",\n \"bytes\": 8_192,\n})).unwrap();\n\n// the size is what the cost is computed from, and the estimate says so of itself\nassert_eq!(tokens_for(p.bytes), 2_048);\n\n// a file under no manifest section — a root README, say — carries none rather than \"\"\nlet rootish: EntryProvenance = serde_json::from_value(json!({\n \"path\": \"README.md\",\n \"directory\": \".\",\n \"source_class\": \"readme\",\n \"bytes\": 4_000,\n})).unwrap();\nassert!(rootish.section.is_none());\nassert_eq!(rootish.directory, \".\", \"the root is `.`, not the empty string\");\n```"
},
"Tier": {
"oneOf": [
{
"type": "string",
"const": "task",
"description": "What was asked for: the issue, its milestone, the paths named, the intent. Never\ndropped — a context that lost the thing it was compiled about is not a smaller\nanswer, it is the wrong one."
},
{
"type": "string",
"const": "governance",
"description": "What the work will be judged against: the policy, the scope, the directory\ncontracts that reach the named paths, and the rules. A blocking rule is never\ndropped."
},
{
"type": "string",
"const": "source",
"description": "The code and the cases the work touches."
},
{
"type": "string",
"const": "decision",
"description": "The architectural decisions already in force over it."
},
{
"type": "string",
"const": "knowledge",
"description": "What a previous session left: handovers, session records, curated knowledge."
},
{
"type": "string",
"const": "history",
"description": "Supporting evidence: use cases, claims, features, and the rest of the layer."
}
],
"description": "Where an entry sits in the order the budget spends in.\n\nThe order is this repository's own: `lib/context.sh` assembles its sections \"in\nauthority order, highest first, because a worker that runs out of budget must lose the\nleast reliable evidence rather than the most: git, then the task and its policy, then\nblockers, then authored records, then event history.\" These six tiers are that\nsentence, applied to objects instead of to sections.\n\nThe derived `Ord` is load-bearing: the variants are declared in authority order, so\n`<` means \"spent before\" and \"harder to drop\", and the budget's ordering is a plain\n`sort` rather than a table mapping tiers to ranks. A variant added in the wrong place\nwould silently re-rank the whole answer, which is why the declaration order is the one\nthing about this enum to be careful with.\n\n```\nuse majordomus_cli::devcontext::Tier;\n\n// the declaration order *is* the order the budget spends in\nlet mut sorted = Tier::ORDER.to_vec();\nsorted.sort();\nassert_eq!(sorted, Tier::ORDER.to_vec());\n\n// so the strongest authority is the smallest, and it is the one never dropped\nassert_eq!(Tier::ORDER.iter().copied().min(), Some(Tier::Task));\nassert!(Tier::Task < Tier::Governance && Tier::Governance < Tier::History);\n\n// and the serialised word is the lowercase one the report is read under\nassert_eq!(\n serde_json::to_value(Tier::Governance).unwrap(),\n serde_json::json!(Tier::Governance.as_str()),\n);\n```"
},
"Discovery": {
"type": "object",
"properties": {
"selector": {
"$ref": "#/$defs/Selector",
"description": "What reached it."
},
"reason": {
"type": "string",
"description": "Why it was included, in words a person reads without this file."
},
"via": {
"type": [
"string",
"null"
],
"description": "The entry this one was reached from, when it was reached from one."
},
"edge": {
"type": [
"string",
"null"
],
"description": "The edge kind followed, for `Relation`."
},
"depth": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "Hops from a seed; a seed is 0."
},
"confidence": {
"type": "number",
"format": "double",
"description": "1.0 when the repository declared this path, less when it was inferred."
},
"weight": {
"type": "number",
"format": "double",
"description": "What this path contributes to the entry's relevance."
}
},
"required": [
"selector",
"reason",
"depth",
"confidence",
"weight"
],
"description": "One way an entry was reached: which selector, why, how far from a seed, and how much\nthe compiler trusts it. An entry keeps every one of these, because \"five discovery\npaths found the same ADR\" is the interesting fact, not a thing to hide.\n\nA `Discovery` is a *kind* of way in, not one traversal. Thirty-three issues of one\nmilestone all reach that milestone along `belongs_to`, and recording that thirty-three\ntimes would say the answer had thirty-three reasons when it has one — so a path already\nrecorded for the same selector, edge and reason is kept rather than repeated.\n\n`via` and `edge` are present exactly when they mean something: a seed was not reached\nfrom anything and followed no edge, so both are absent and are skipped on the wire\nrather than serialised as null. `confidence` is 1.0 for every declared selector and less\nonly for `Selector::IntentMatch`; `weight` is what this particular path contributes to\nrelevance, which is a different quantity — how much it counts, against how sure it is.\n\n```\nuse majordomus_cli::devcontext::{Discovery, Selector};\nuse serde_json::json;\n\n// the request named it: nothing to come via, no edge followed, depth zero\nlet seed: Discovery = serde_json::from_value(json!({\n \"selector\": \"seed\",\n \"reason\": \"named in the request\",\n \"depth\": 0,\n \"confidence\": 1.0,\n \"weight\": 1.0,\n})).unwrap();\nassert_eq!(seed.selector, Selector::Seed);\nassert!(seed.via.is_none() && seed.edge.is_none());\nassert!(seed.selector.declared() && seed.confidence == 1.0);\n\n// the wire form omits them rather than carrying nulls a reader must skip\nlet wire = serde_json::to_value(&seed).unwrap();\nassert!(wire.get(\"via\").is_none() && wire.get(\"edge\").is_none());\n\n// a relation says both where it came from and which edge it followed\nlet walked: Discovery = serde_json::from_value(json!({\n \"selector\": \"relation\",\n \"reason\": \"the decision in force over this scope\",\n \"via\": \"majordomus://issue/I0301\",\n \"edge\": \"governed_by\",\n \"depth\": 1,\n \"confidence\": 1.0,\n \"weight\": 0.9,\n})).unwrap();\nassert_eq!(walked.edge.as_deref(), Some(\"governed_by\"));\nassert_eq!(walked.via.as_deref(), Some(\"majordomus://issue/I0301\"));\n\n// and a guess says so, in the one field that distinguishes the two halves of an answer\nlet guessed: Discovery = serde_json::from_value(json!({\n \"selector\": \"intent_match\",\n \"reason\": \"the intent's words occur in it\",\n \"depth\": 2,\n \"confidence\": 0.4,\n \"weight\": 0.4,\n})).unwrap();\nassert!(!guessed.selector.declared() && guessed.confidence < 1.0);\n```"
},
"Selector": {
"oneOf": [
{
"type": "string",
"const": "seed",
"description": "Named in the request."
},
{
"type": "string",
"const": "relation",
"description": "Reached along a typed edge of the composed graph."
},
{
"type": "string",
"const": "scope_path",
"description": "Its path lies under a path the request or a seed declares."
},
{
"type": "string",
"const": "contract",
"description": "A directory contract that reaches one of those paths."
},
{
"type": "string",
"const": "governance",
"description": "A rule or policy the layer applies to everything."
},
{
"type": "string",
"const": "session_state",
"description": "A recorded session of this branch or of these paths, the handover the resolver\nchose, the newest checkpoint."
},
{
"type": "string",
"const": "intent_match",
"description": "Inferred: the words of the intent occur in the object's own words."
}
],
"description": "What reached an entry. This is the provenance of the *selection*, and it is a different\nfact from the provenance of the file: `Relation` says the compiler followed an edge the\nlayer declares, `IntentMatch` says it guessed from words. An answer that did not keep\nthem apart could not say which half of itself to trust.\n\nThe division that matters is `Selector::declared`, and it is deliberately lopsided:\nsix of the seven selectors follow something the repository states, and exactly one\nguesses. That ratio is the design. Inference is confined to a single selector so that\nthe inferred part of any answer can be found, weighed and ignored, rather than being\nmixed through the rest at unmarked strength.\n\n```\nuse majordomus_cli::devcontext::Selector;\n\n// exactly one selector infers, and the answer can always be split on it\nlet inferred: Vec<&str> = Selector::ALL\n .iter()\n .filter(|s| !s.declared())\n .map(|s| s.as_str())\n .collect();\nassert_eq!(inferred, [\"intent_match\"]);\n\n// every selector has its own word, so a reason is never ambiguous\nlet mut words: Vec<&str> = Selector::ALL.iter().map(|s| s.as_str()).collect();\nlet before = words.len();\nwords.sort();\nwords.dedup();\nassert_eq!(words.len(), before);\n\n// and the word is the serialised form\nassert_eq!(\n serde_json::to_value(Selector::ScopePath).unwrap(),\n serde_json::json!(\"scope_path\"),\n);\n```"
},
"Excluded": {
"type": "object",
"properties": {
"uri": {
"type": "string",
"description": "The canonical identifier, or the name the layer used when nothing resolves."
},
"kind": {
"type": [
"string",
"null"
],
"description": "Its kind, when it resolved to something."
},
"tier": {
"$ref": "#/$defs/Tier",
"description": "The tier it would have been spent from."
},
"reason": {
"$ref": "#/$defs/ExclusionReason",
"description": "Why it is not in the answer."
},
"detail": {
"type": "string",
"description": "The same, in words."
},
"cost_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "What it would have cost, so that a reader can decide whether to raise the budget."
},
"relevance": {
"type": "number",
"format": "double",
"description": "What its relevance was."
}
},
"required": [
"uri",
"tier",
"reason",
"detail",
"cost_tokens",
"relevance"
],
"description": "One thing the compiler reached and did not give. Excluded is not the same as absent:\nan under-filled context is debugged from this list, not by guessing.\n\n`cost_tokens` is why this type exists in the shape it does. A budget that reported only\n*that* it dropped things would leave a caller guessing at a new ceiling; one that reports\nwhat each omission would have cost turns \"raise the budget\" into arithmetic. `detail`\ncarries the same in words, so the row is legible without the reader doing that\narithmetic themselves.\n\nThe ordering puts the tier first as an explicit rank, because the tier is the precedence\nthe budget spent in; inside a tier a reader is looking for a reason, and the identifier\nends the key so the list is total and the same tree always prints it the same way.\n\n```\nuse majordomus_cli::devcontext::{Excluded, ExclusionReason, Tier};\nuse majordomus_cli::order::canonical;\nuse serde_json::json;\n\nlet row = |uri: &str, tier: &str, reason: &str, cost: u64| -> Excluded {\n serde_json::from_value(json!({\n \"uri\": uri, \"tier\": tier, \"reason\": reason,\n \"detail\": \"as measured\", \"cost_tokens\": cost, \"relevance\": 0.4,\n })).unwrap()\n};\n\nlet mut excluded = vec![\n row(\"majordomus://knowledge/b\", \"history\", \"budget\", 900),\n row(\"majordomus://adr/0001\", \"decision\", \"superseded\", 300),\n row(\"majordomus://knowledge/a\", \"history\", \"budget\", 1_200),\n];\ncanonical(&mut excluded);\n\n// the tier ranks first, so the decision tier precedes history whatever the reason says\nassert_eq!(excluded[0].tier, Tier::Decision);\nassert_eq!(excluded[0].reason, ExclusionReason::Superseded);\n// then the reason, then the identifier — which makes the order total\nlet rest: Vec<&str> = excluded[1..].iter().map(|e| e.uri.as_str()).collect();\nassert_eq!(rest, [\"majordomus://knowledge/a\", \"majordomus://knowledge/b\"]);\n\n// and the row a caller acts on says what it would have cost to keep\nlet biggest = excluded.iter().max_by_key(|e| e.cost_tokens).unwrap();\nassert_eq!(biggest.cost_tokens, 1_200);\n```"
},
"ExclusionReason": {
"oneOf": [
{
"type": "string",
"const": "budget",
"description": "The budget ran out before its tier was filled."
},
{
"type": "string",
"const": "relevance",
"description": "Its relevance fell below the floor the request set."
},
{
"type": "string",
"const": "depth",
"description": "It is beyond the depth the request allows."
},
{
"type": "string",
"const": "stale",
"description": "The object says it is deprecated or superseded."
},
{
"type": "string",
"const": "superseded",
"description": "A newer version of the same thing is in the answer."
},
{
"type": "string",
"const": "unresolved",
"description": "The layer names it and holds nothing under that name."
}
],
"description": "Why something the compiler selected did not survive.\n\nThe six divide into three that a caller can act on by asking again — `Budget`,\n`Relevance` and `Depth` are all consequences of the request's own limits, so raising the\nlimit brings the entry back — and three that are facts about the repository:\n`Stale` and `Superseded` mean the layer itself says this is not the current thing, and\n`Unresolved` means the layer names something it does not hold, which is a dangling\nreference somebody should fix.\n\n```\nuse majordomus_cli::devcontext::ExclusionReason as Why;\n\n// the ones a different request would change, against the ones it would not\nlet request_bound = [Why::Budget, Why::Relevance, Why::Depth];\nlet repository_bound = [Why::Stale, Why::Superseded, Why::Unresolved];\nfor r in repository_bound {\n assert!(!request_bound.contains(&r), \"{} is not the caller's to fix\", r.as_str());\n}\n\n// and the word is the serialised form, snake_case for the two-word one\nassert_eq!(Why::Superseded.as_str(), \"superseded\");\nassert_eq!(\n serde_json::to_value(Why::Unresolved).unwrap(),\n serde_json::json!(Why::Unresolved.as_str()),\n);\n```"
},
"Deduplicated": {
"type": "object",
"properties": {
"kept": {
"type": "string",
"description": "The entry that survived."
},
"dropped": {
"type": "array",
"items": {
"type": "string"
},
"description": "What was folded into it, or dropped for it."
},
"key": {
"type": "string",
"description": "What made them the same thing: `uri`, `path` or `identity`."
},
"detail": {
"type": "string",
"description": "The same, in words."
},
"paths": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many discovery paths reached the surviving entry."
}
},
"required": [
"kept",
"dropped",
"key",
"detail",
"paths"
],
"description": "Two names, one thing. The compiler keeps one entry and records the collapse here, so\nthat \"why is this ADR listed once when four things point at it\" has an answer that is\nstate rather than a log line.\n\nOne type covers two different collapses, and `dropped` is how a reader tells them apart.\n**Structural** collapse is the same identifier reached several ways: nothing was\ndiscarded, so `dropped` is empty and `paths` is the count that makes the row worth\nprinting — this is the record that four things pointing at one ADR produced one entry.\n**Semantic** collapse is two different identifiers standing for one thing, one file\nindexed under two kinds or one rule at two versions: there `dropped` names what lost,\nbecause something really was discarded and a reader is entitled to know what.\n\n```\nuse majordomus_cli::devcontext::Deduplicated;\nuse serde_json::json;\n\n// structural: one identifier, four ways in, nothing discarded\nlet structural: Deduplicated = serde_json::from_value(json!({\n \"kept\": \"majordomus://adr/0052\",\n \"dropped\": [],\n \"key\": \"uri\",\n \"detail\": \"one object reached by 4 discovery path(s)\",\n \"paths\": 4,\n})).unwrap();\nassert!(structural.dropped.is_empty(), \"nothing lost; this is a record, not a decision\");\nassert!(structural.paths > 1, \"which is what makes the row worth printing\");\nassert_eq!(structural.key, \"uri\");\n\n// semantic: two identifiers for one rule, and the older version lost\nlet semantic: Deduplicated = serde_json::from_value(json!({\n \"kept\": \"majordomus://rule/project.x@2\",\n \"dropped\": [\"majordomus://rule/project.x@1\"],\n \"key\": \"identity\",\n \"detail\": \"one rule at two versions; the newer is in the answer\",\n \"paths\": 1,\n})).unwrap();\nassert_eq!(semantic.dropped, [\"majordomus://rule/project.x@1\"]);\nassert_ne!(semantic.kept, semantic.dropped[0], \"two names, and one of them lost\");\n```"
},
"Budget": {
"type": "object",
"properties": {
"limit_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "The ceiling this answer was compiled under, in estimated tokens."
},
"used_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "What the survivors cost."
},
"required_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "What the entries that cannot be dropped cost. Above the limit, the answer is\nover-budget and says so rather than dropping what it must keep."
},
"remaining_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "`limit - used`, floored at zero."
},
"over_budget": {
"type": "boolean",
"description": "True when the required entries alone exceed the limit."
},
"bytes_per_token": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "Bytes per token, the divisor the estimate uses."
},
"tiers": {
"type": "array",
"items": {
"$ref": "#/$defs/TierSpend"
},
"description": "Per tier, in the order the budget spends in."
}
},
"required": [
"limit_tokens",
"used_tokens",
"required_tokens",
"remaining_tokens",
"over_budget",
"bytes_per_token",
"tiers"
],
"description": "The budget, and what became of it.\n\n`over_budget` is the field to read and the one most likely to be misread. It does not\nmean the compiler overspent by accident: every entry the budget has a say over is refused\nthe moment it would not fit, so the only way past the ceiling is through the entries that\nmay not be dropped — the seeds, the policy, the scope, a blocking rule. So\n`over_budget` means *the things this context cannot do without already cost more than you\nallowed*, and `required_tokens` is the explanation of it. The honest answer to that is to\nsay so, not to return a context missing the thing it was compiled about.\n\n`remaining_tokens` is floored at zero rather than going negative, so it is safe to\ndisplay; the overspend is read from `used_tokens` against `limit_tokens`, which is why\nboth are carried.\n\n```\nuse majordomus_cli::devcontext::{Budget, Tier, BYTES_PER_TOKEN};\nuse serde_json::json;\n\nlet tier = |name: &str, tokens: u64, required: usize| json!({\n \"tier\": name, \"meaning\": \"as this tier is for\", \"selected\": 1,\n \"excluded\": 0, \"tokens\": tokens, \"required\": required,\n});\n\n// the undroppable entries alone cost more than the caller allowed\nlet b: Budget = serde_json::from_value(json!({\n \"limit_tokens\": 1_000,\n \"used_tokens\": 2_500,\n \"required_tokens\": 2_500,\n \"remaining_tokens\": 0,\n \"over_budget\": true,\n \"bytes_per_token\": BYTES_PER_TOKEN,\n \"tiers\": [tier(\"task\", 2_000, 1), tier(\"governance\", 500, 1)],\n})).unwrap();\n\nassert!(b.over_budget);\nassert!(b.used_tokens > b.limit_tokens, \"the overspend is read from these two\");\nassert_eq!(b.required_tokens, b.used_tokens, \"all of it was undroppable\");\nassert_eq!(b.remaining_tokens, 0, \"floored, so it is safe to display\");\n\n// the divisor is carried so a caller measuring tokens differently can convert\n// rather than guess what the estimate meant\nassert_eq!(b.bytes_per_token, BYTES_PER_TOKEN);\n\n// and the tiers are reported in the order the budget spends in\nlet order: Vec<Tier> = b.tiers.iter().map(|t| t.tier).collect();\nassert_eq!(order, [Tier::Task, Tier::Governance]);\nassert!(order.windows(2).all(|w| w[0] < w[1]));\n```"
},
"TierSpend": {
"type": "object",
"properties": {
"tier": {
"$ref": "#/$defs/Tier",
"description": "The tier."
},
"meaning": {
"type": "string",
"description": "What it is for."
},
"selected": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many entries survived in it."
},
"excluded": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many were dropped from it for budget."
},
"tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "Tokens the survivors cost."
},
"required": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "Entries in it that cannot be dropped."
}
},
"required": [
"tier",
"meaning",
"selected",
"excluded",
"tokens",
"required"
],
"description": "What one tier cost, how much of it survived, and how much of that could not have been\ndropped.\n\nThere is no per-tier ceiling, which is worth saying because the name suggests one: the\nbudget is a single pot spent in tier order, and this is the *report* of what each tier\ntook from it, not an allowance it was given. A tier with many exclusions is therefore\nnot a tier that hit its own limit — it is a tier that was reached after the pot had been\nspent by the tiers above it.\n\n`meaning` is carried so that a reader deciding what to raise the budget for does not\nhave to look up what `knowledge` holds; `required` is the part of `selected` the budget\nhad no say over.\n\n```\nuse majordomus_cli::devcontext::{Tier, TierSpend};\nuse serde_json::json;\n\nlet t: TierSpend = serde_json::from_value(json!({\n \"tier\": \"governance\",\n \"meaning\": Tier::Governance.meaning(),\n \"selected\": 9,\n \"excluded\": 2,\n \"tokens\": 6_400,\n \"required\": 3,\n})).unwrap();\n\nassert_eq!(t.tier, Tier::Governance);\n// the undroppable part is a part of what survived, never a separate count\nassert!(t.required <= t.selected);\n// and the row explains its own tier, so \"2 excluded\" is actionable\nassert_eq!(t.meaning, Tier::Governance.meaning());\nassert!(t.meaning.contains(\"policy\"));\n```"
}
}
}Examples
These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.
policy
{
"uri": "majordomus://policy/.ai/repo/policy.yaml"
}absent
{
"uri": "majordomus://rule/nothing-like-this@1"
}