Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

devcontext.compile

Objekty, které by měla dostat relace pracující na tomto úkolu, milníku, záměru nebo sadě cest: každý s kanonickým identifikátorem, původem z indexu, každou cestou objevení, která k němu vedla, s důvodem a jistotou, jeho verzí, vrstvou a cenou v odhadovaných tokenech — následované vším, k čemu se došlo a co nebylo dáno, s důvodem u každého, vším, co se sloučilo do jednoho záznamu, každou dvojicí, která si neodpovídá, a výdaji po vrstvách proti rozpočtu. Deterministické pro daný strom a požadavek; otisk indexu, z něhož bylo sestaveno, je v odpovědi.

Objekty, které by měla dostat relace pracující na tomto úkolu, milníku, záměru nebo sadě cest: každý s kanonickým identifikátorem, původem z indexu, každou cestou objevení, která k němu vedla, s důvodem a jistotou, jeho verzí, vrstvou a cenou v odhadovaných tokenech — následované vším, k čemu se došlo a co nebylo dáno, s důvodem u každého, vším, co se sloučilo do jednoho záznamu, každou dvojicí, která si neodpovídá, a výdaji po vrstvách proti rozpočtu. Deterministické pro daný strom a požadavek; otisk indexu, z něhož bylo sestaveno, je v odpovědi.

  • query
  • behaviorally_verified
  • module devcontext
  • #context
  • #session
  • #planning
  • #introspection

Zpřístupnění

Kde je tato jedna definice dosažitelná. Absence je explicitní: povrch, který není uveden, ji nenese.

povrchjako
MCPnástroj majordomus_devcontext
HTTPGET /api/v1/devcontext operationId devcontext.compile
příkazová řádkamajordomus devcontext compile

Schémata

Kanonický vstup a výstup z typů Rustu; schéma nástroje MCP a parametry a odpovědi OpenAPI se odvozují z nich.

vstup · DevContextInput

Vstup devcontext.compile: o čem sestavit kontext.
vlastnosttyppovinnépopis
all_blocking_rules boolean | null ne Každé blokující pravidlo vrstvy, nejen ta, k nimž práce dosáhne. Poctivé a obvykle nad rozpočtem: odpověď pak říká over_budget, místo aby vypustila, co vypustit nesmí.
budget_tokens integer | null ne Strop v odhadovaných tokenech; DEFAULT_BUDGET_TOKENS, když chybí.
spodní mez number | null ne Relevance, pod kterou se záznam hlásí, ne podává; DEFAULT_FLOOR, když chybí.
intent string | null ne Co se relace snaží udělat, slovy. Jediný vstup, ze kterého kompilátor usuzuje, a každý záznam, který vytvoří, to uvádí a nese jistotu pod jedna.
issue string | null ne Id úkolu (I0301) nebo jeho kanonický identifikátor. Z něj vyplývá jeho milník, jeho závislosti, jeho deklarovaný rozsah a rozhodnutí nad tímto rozsahem.
max_depth integer | null ne Jak daleko od zárodku procházení sahá; DEFAULT_MAX_DEPTH, když chybí.
milestone string | null ne Id nebo slug milníku, případně jeho kanonický identifikátor.
cesty array ne Cesty relativní k repozitáři, kterých se práce dotýká, přidané k tomu, co deklarují seedy.
uris array ne Kanonické identifikátory, ze kterých se přímo vychází, pro požadavek na něco, co není úkol ani milník.
JSON Schema
{
  "additionalProperties": false,
  "description": "The input of `devcontext.compile`: what to compile a context about.",
  "properties": {
    "all_blocking_rules": {
      "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.",
      "type": [
        "boolean",
        "null"
      ]
    },
    "budget_tokens": {
      "description": "The ceiling in estimated tokens; `DEFAULT_BUDGET_TOKENS` when absent.",
      "format": "uint64",
      "minimum": 0,
      "type": [
        "integer",
        "null"
      ]
    },
    "floor": {
      "description": "Relevance below which an entry is reported rather than given; `DEFAULT_FLOOR`\nwhen absent.",
      "format": "double",
      "type": [
        "number",
        "null"
      ]
    },
    "intent": {
      "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.",
      "type": [
        "string",
        "null"
      ]
    },
    "issue": {
      "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.",
      "type": [
        "string",
        "null"
      ]
    },
    "max_depth": {
      "description": "How far from a seed the walk goes; `DEFAULT_MAX_DEPTH` when absent.",
      "format": "uint",
      "minimum": 0,
      "type": [
        "integer",
        "null"
      ]
    },
    "milestone": {
      "description": "A milestone id or slug, or its canonical identifier.",
      "type": [
        "string",
        "null"
      ]
    },
    "paths": {
      "description": "Repository-relative paths the work touches, added to whatever the seeds declare.",
      "items": {
        "type": "string"
      },
      "type": "array"
    },
    "uris": {
      "description": "Canonical identifiers to seed with directly, for a request about something that is\nneither an issue nor a milestone.",
      "items": {
        "type": "string"
      },
      "type": "array"
    }
  },
  "title": "DevContextInput",
  "type": "object"
}

výstup · CompiledContext

Zkompilovaný vývojový kontext: co dát relaci, co se vynechalo, co se do čeho sbalilo a rozpočet, pod nímž se o tom všem rozhodlo.

Toto je kanonická podoba. Vykreslení do promptu je navazující projekce této hodnoty a neprovádí se zde — díky struktuře může volající znovu rozpočtovat, přeřadit nebo vysvětlit výběr, aniž by ho překompiloval.

Nad každou odpovědí platí dva invarianty a ty ji činí bezpečnou k cachování a porovnávání. fingerprint se vztahuje k indexu, z něhož byla sestavena, takže stejný požadavek proti stejnému otisku je stejná odpověď a jiný otisk je jiný strom — volající rozliší dva stromy, aniž by se ptal. A budget.used_tokens je přesně součet nákladů selected, takže aritmetika v rozpočtu popisuje seznam vedle ní, ne průchod, který byl mezitím odfiltrován.

use majordomus_cli::devcontext::{compile, CompileInput, CompiledContext};
use majordomus_cli::devcontext::{Tier, DEFAULT_BUDGET_TOKENS};
use majordomus_cli::synthetic::SyntheticRepository;

let repo = SyntheticRepository::small().unwrap();
let ctx = repo.context().unwrap();

let c: CompiledContext = compile(&ctx, CompileInput::default()).unwrap();

// the answer says which tree it is true of, and nothing else has to be asked
assert_eq!(c.schema, 1);
assert!(!c.fingerprint.is_empty(), "an answer that names no tree is not one");

// the budget describes the list beside it
let spent: u64 = c.selected.iter().map(|e| e.cost_tokens).sum();
assert_eq!(c.budget.used_tokens, spent);
assert_eq!(c.budget.limit_tokens, DEFAULT_BUDGET_TOKENS);

// every tier is reported, so an empty tier is visibly empty rather than missing
assert_eq!(c.budget.tiers.len(), Tier::ORDER.len());

// a request that named nothing has no seeds and is still an answer
assert!(c.seeds.is_empty());

// and recompiling the same request over the same tree gives the same answer
let again: CompiledContext = compile(&ctx, CompileInput::default()).unwrap();
assert_eq!(again.fingerprint, c.fingerprint);
assert_eq!(again.selected.len(), c.selected.len());
vlastnosttyppovinnépopis
rozpočet reference ano Rozpočet a jeho útrata podle úrovní.
konflikty array ano Co se s čím neshoduje.
deduplikováno array ano Co se do čeho sloučilo.
diagnostika array ano Co kompilátor nemohl přečíst: zdroj znalostí, který vrstva jmenuje a nedrží, záznam relace, který už nepopisuje tento checkout. Nikdy chyba: chybějící zdroj je odpověď.
vyloučeno array ano Co bylo dosaženo a nedáno, s důvodem u každého.
otisk string ano Index, ze kterého byl tento výstup zkompilován, přes cestu a obsah každého objektu. Dvě odpovědi se stejným otiskem a stejným požadavkem jsou táž odpověď; jiný otisk je jiný strom.
git reference ano Head, o kterém je odpověď pravdivá.
schema integer ano Formát této odpovědi.
seedy array ano O co se žádalo.
vybráno array ano Co relaci dát, v pořadí, v jakém se utrácí rozpočet: úroveň, pak relevance, pak kanonický identifikátor.
JSON Schema
{
  "$defs": {
    "Budget": {
      "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```",
      "properties": {
        "bytes_per_token": {
          "description": "Bytes per token, the divisor the estimate uses.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "limit_tokens": {
          "description": "The ceiling this answer was compiled under, in estimated tokens.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "over_budget": {
          "description": "True when the required entries alone exceed the limit.",
          "type": "boolean"
        },
        "remaining_tokens": {
          "description": "`limit - used`, floored at zero.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "required_tokens": {
          "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.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "tiers": {
          "description": "Per tier, in the order the budget spends in.",
          "items": {
            "$ref": "#/$defs/TierSpend"
          },
          "type": "array"
        },
        "used_tokens": {
          "description": "What the survivors cost.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "limit_tokens",
        "used_tokens",
        "required_tokens",
        "remaining_tokens",
        "over_budget",
        "bytes_per_token",
        "tiers"
      ],
      "type": "object"
    },
    "CommitReference": {
      "description": "One commit the layer itself names, and the record that named it.\n\nThe pair is the fact, not the commit alone. One commit named by three records is three\nreferences, because each record is a separate claim about what that commit was for, and\nfolding them would lose the attribution — which is the only reason to carry a commit here\nat all. So `named_by` ends the ordering key, and two references to one commit both\nsurvive.\n\n```\nuse majordomus_cli::devcontext::CommitReference;\nuse majordomus_cli::order::canonical;\nuse serde_json::json;\n\nlet by = |commit: &str, record: &str| -> CommitReference {\n    serde_json::from_value(json!({\"commit\": commit, \"named_by\": record})).unwrap()\n};\n\nlet mut commits = vec![\n    by(\"cd04012\", \"majordomus://session/b\"),\n    by(\"cd04012\", \"majordomus://session/a\"),\n    by(\"5e31dd4\", \"majordomus://issue/I0301\"),\n];\ncanonical(&mut commits);\n\n// filed under the commit, which is what a reader looks for\nlet order: Vec<&str> = commits.iter().map(|c| c.commit.as_str()).collect();\nassert_eq!(order, [\"5e31dd4\", \"cd04012\", \"cd04012\"]);\n\n// and the record ends the key, so one commit named twice stays two facts\nassert_eq!(commits[1].named_by, \"majordomus://session/a\");\nassert_eq!(commits[2].named_by, \"majordomus://session/b\");\n\n// `covers` is what the record said the commit was for, when it said\nlet with_reason = by(\"cd04012\", \"majordomus://session/a\");\nassert!(with_reason.covers.is_none(), \"absent rather than an empty sentence\");\n```",
      "properties": {
        "commit": {
          "description": "The commit as the record wrote it.",
          "type": "string"
        },
        "covers": {
          "description": "What the record says the commit was for.",
          "type": [
            "string",
            "null"
          ]
        },
        "named_by": {
          "description": "The entry that named it.",
          "type": "string"
        }
      },
      "required": [
        "commit",
        "named_by"
      ],
      "type": "object"
    },
    "Conflict": {
      "description": "Two things in the answer that do not agree, named rather than silently ordered.\n\nThe compiler could have resolved every disagreement by keeping one side, and for\ndeduplication it does. A conflict is what is left when both sides are legitimately in\nthe answer and they still do not agree — so the resolution belongs to the session\nreading it, and the compiler's job is to make sure the disagreement is visible rather\nthan implied by the order of two rows.\n\n`current` is the side the compiler treats as current, which is a statement about\nrecency, not correctness: `supersedes` means the layer declared one to replace the other,\n`version` means two versions of one thing are both here.\n\n```\nuse majordomus_cli::devcontext::Conflict;\nuse majordomus_cli::order::canonical;\nuse serde_json::json;\n\nlet row = |current: &str, against: &str, kind: &str| -> Conflict {\n    serde_json::from_value(json!({\n        \"current\": current, \"against\": against, \"kind\": kind,\n        \"detail\": \"both are in the answer and they disagree\",\n    })).unwrap()\n};\n\nlet mut conflicts = vec![\n    row(\"majordomus://rule/project.x@2\", \"majordomus://rule/project.x@1\", \"version\"),\n    row(\"majordomus://adr/0052\", \"majordomus://adr/0031\", \"supersedes\"),\n];\ncanonical(&mut conflicts);\n\n// filed under the kind of disagreement, so like reads with like\nlet kinds: Vec<&str> = conflicts.iter().map(|c| c.kind.as_str()).collect();\nassert_eq!(kinds, [\"supersedes\", \"version\"]);\n\n// and both sides are always named: the pair is the fact, not the winner alone\nfor c in &conflicts {\n    assert_ne!(c.current, c.against);\n    assert!(!c.detail.is_empty());\n}\n```",
      "properties": {
        "against": {
          "description": "The entry it stands against.",
          "type": "string"
        },
        "current": {
          "description": "The entry the compiler treats as current.",
          "type": "string"
        },
        "detail": {
          "description": "The same, in words.",
          "type": "string"
        },
        "kind": {
          "description": "What kind of disagreement: `supersedes` or `version`.",
          "type": "string"
        }
      },
      "required": [
        "current",
        "against",
        "kind",
        "detail"
      ],
      "type": "object"
    },
    "ContextEntry": {
      "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```",
      "properties": {
        "confidence": {
          "description": "The highest confidence of any path that reached it.",
          "format": "double",
          "type": "number"
        },
        "cost_bytes": {
          "description": "The file's bytes, the measured half of the cost.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "cost_tokens": {
          "description": "Estimated tokens: the file's bytes divided by `BYTES_PER_TOKEN`, never fewer\nthan one. An estimate, said to be one.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "depth": {
          "description": "The shortest number of hops from a seed.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "discovered_by": {
          "description": "Every path that reached it, best first. Length above one is the evidence that\ndeduplication happened.",
          "items": {
            "$ref": "#/$defs/Discovery"
          },
          "type": "array"
        },
        "facts": {
          "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.",
          "type": "object"
        },
        "kind": {
          "description": "The kind the layer declared for it.",
          "type": "string"
        },
        "provenance": {
          "$ref": "#/$defs/EntryProvenance",
          "description": "Where it lives."
        },
        "relevance": {
          "description": "0.0 to 1.0, deterministic for a given tree and request. The order within a tier.",
          "format": "double",
          "type": "number"
        },
        "required": {
          "description": "True when a blocking rule, a policy or the scope: never dropped for budget.",
          "type": "boolean"
        },
        "status": {
          "description": "The status word the object declares, when it declares one.",
          "type": [
            "string",
            "null"
          ]
        },
        "tier": {
          "$ref": "#/$defs/Tier",
          "description": "Which tier's budget it is spent from."
        },
        "title": {
          "description": "Its title, when it has one.",
          "type": [
            "string",
            "null"
          ]
        },
        "uri": {
          "description": "The canonical identifier: `majordomus://<kind>/<identity>`, unique in the answer.",
          "type": "string"
        },
        "version": {
          "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`.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "required": [
        "uri",
        "kind",
        "provenance",
        "tier",
        "relevance",
        "confidence",
        "discovered_by",
        "depth",
        "cost_tokens",
        "cost_bytes",
        "required"
      ],
      "type": "object"
    },
    "Deduplicated": {
      "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```",
      "properties": {
        "detail": {
          "description": "The same, in words.",
          "type": "string"
        },
        "dropped": {
          "description": "What was folded into it, or dropped for it.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "kept": {
          "description": "The entry that survived.",
          "type": "string"
        },
        "key": {
          "description": "What made them the same thing: `uri`, `path` or `identity`.",
          "type": "string"
        },
        "paths": {
          "description": "How many discovery paths reached the surviving entry.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "kept",
        "dropped",
        "key",
        "detail",
        "paths"
      ],
      "type": "object"
    },
    "Diagnostic": {
      "description": "One finding about the declarative state, named by a stable code, tied to a path where\nthere is one, and carrying the command that reproduces it where there is one.",
      "properties": {
        "code": {
          "description": "A stable machine-readable code, e.g. `unknown_key`, `duplicate_identity`.",
          "type": "string"
        },
        "message": {
          "description": "What is wrong, for a person; the code is for a program.",
          "type": "string"
        },
        "path": {
          "description": "Repository-relative path of the file concerned, when there is one.",
          "type": [
            "string",
            "null"
          ]
        },
        "severity": {
          "$ref": "#/$defs/Severity",
          "description": "How bad."
        }
      },
      "required": [
        "severity",
        "code",
        "message"
      ],
      "type": "object"
    },
    "Discovery": {
      "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```",
      "properties": {
        "confidence": {
          "description": "1.0 when the repository declared this path, less when it was inferred.",
          "format": "double",
          "type": "number"
        },
        "depth": {
          "description": "Hops from a seed; a seed is 0.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "edge": {
          "description": "The edge kind followed, for `Relation`.",
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "description": "Why it was included, in words a person reads without this file.",
          "type": "string"
        },
        "selector": {
          "$ref": "#/$defs/Selector",
          "description": "What reached it."
        },
        "via": {
          "description": "The entry this one was reached from, when it was reached from one.",
          "type": [
            "string",
            "null"
          ]
        },
        "weight": {
          "description": "What this path contributes to the entry's relevance.",
          "format": "double",
          "type": "number"
        }
      },
      "required": [
        "selector",
        "reason",
        "depth",
        "confidence",
        "weight"
      ],
      "type": "object"
    },
    "EntryProvenance": {
      "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```",
      "properties": {
        "bytes": {
          "description": "Size of the file in bytes.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "directory": {
          "description": "The directory it sits in.",
          "type": "string"
        },
        "path": {
          "description": "Repository-relative path, forward slashes.",
          "type": "string"
        },
        "section": {
          "description": "The manifest section it falls under, when it falls under one.",
          "type": [
            "string",
            "null"
          ]
        },
        "source_class": {
          "description": "The `sources.yaml` class that discovered it.",
          "type": "string"
        }
      },
      "required": [
        "path",
        "directory",
        "source_class",
        "bytes"
      ],
      "type": "object"
    },
    "Excluded": {
      "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```",
      "properties": {
        "cost_tokens": {
          "description": "What it would have cost, so that a reader can decide whether to raise the budget.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        },
        "detail": {
          "description": "The same, in words.",
          "type": "string"
        },
        "kind": {
          "description": "Its kind, when it resolved to something.",
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "$ref": "#/$defs/ExclusionReason",
          "description": "Why it is not in the answer."
        },
        "relevance": {
          "description": "What its relevance was.",
          "format": "double",
          "type": "number"
        },
        "tier": {
          "$ref": "#/$defs/Tier",
          "description": "The tier it would have been spent from."
        },
        "uri": {
          "description": "The canonical identifier, or the name the layer used when nothing resolves.",
          "type": "string"
        }
      },
      "required": [
        "uri",
        "tier",
        "reason",
        "detail",
        "cost_tokens",
        "relevance"
      ],
      "type": "object"
    },
    "ExclusionReason": {
      "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```",
      "oneOf": [
        {
          "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.",
          "type": "string"
        }
      ]
    },
    "GitContext": {
      "description": "The head this answer was compiled against. A compiled context is only true of one tree,\nand these three fields plus the index fingerprint are what say which.\n\n`branch` and `head` are optional because a checkout can legitimately have neither — a\ndetached head, or a tree that is not a git repository at all — and the absence is carried\nrather than faked. `working_tree` is not optional, because there is always something to\nsay: when git cannot be reached it carries `unavailable: <reason>` instead of a status,\nso a reader is never left unable to tell \"clean\" from \"not asked\".\n\n`commits` is derived from the selected entries' own records and never from a log walk.\nThat is the difference between \"the commits this work says it produced\" and \"what\nhappened to be committed recently\", and only the first is context.\n\n```\nuse majordomus_cli::devcontext::GitContext;\nuse serde_json::json;\n\n// a tree the compiler could read\nlet known: GitContext = serde_json::from_value(json!({\n    \"branch\": \"master\",\n    \"head\": \"cd04012f1b1dc21fd493e2be14938ffdfaccc8fa\",\n    \"working_tree\": \"clean\",\n})).unwrap();\nassert_eq!(known.branch.as_deref(), Some(\"master\"));\nassert!(known.commits.is_empty(), \"no selected record named a commit\");\n\n// and one it could not: the status field still says something a reader can act on\nlet unknown: GitContext = serde_json::from_value(json!({\n    \"working_tree\": \"unavailable: not a git repository\",\n})).unwrap();\nassert!(unknown.head.is_none() && unknown.branch.is_none());\nassert!(\n    unknown.working_tree.starts_with(\"unavailable: \"),\n    \"never silently indistinguishable from clean\",\n);\n```",
      "properties": {
        "branch": {
          "description": "The branch, when the checkout is on one.",
          "type": [
            "string",
            "null"
          ]
        },
        "commits": {
          "description": "Commits the selected entries name as their own evidence, newest record first.\nDerived from the layer's records, never from a log walk.",
          "items": {
            "$ref": "#/$defs/CommitReference"
          },
          "type": "array"
        },
        "head": {
          "description": "The head commit.",
          "type": [
            "string",
            "null"
          ]
        },
        "working_tree": {
          "description": "`clean`, `dirty`, or what git said.",
          "type": "string"
        }
      },
      "required": [
        "working_tree"
      ],
      "type": "object"
    },
    "Seed": {
      "description": "What the request asked to compile a context about.\n\nA seed is the request echoed back after resolution, and it is in the answer so that a\ncaller can see what their short name turned into. `from` names the request field it came\nfrom — `issue`, `milestone`, `uris`, `paths`, `intent` — which is how the same identifier\narriving two ways stays two seeds rather than one.\n\n`resolved` is populated only when resolution actually changed something: name a\nmilestone by its slug and it carries the canonical identity, name it by that identity and\nthere was nothing to resolve, so the field is absent. A path and an intent are not\nresolved against the index at all — their `uri` is the literal the request gave.\n\n```\nuse majordomus_cli::devcontext::Seed;\nuse serde_json::json;\n\n// named by a slug: the answer says what it became\nlet by_slug: Seed = serde_json::from_value(json!({\n    \"uri\": \"majordomus://milestone/M04\",\n    \"kind\": \"milestone\",\n    \"from\": \"milestone\",\n    \"resolved\": \"M04\",\n})).unwrap();\nassert_eq!(by_slug.resolved.as_deref(), Some(\"M04\"));\n\n// named canonically: nothing was resolved, so nothing is reported\nlet canonical: Seed = serde_json::from_value(json!({\n    \"uri\": \"majordomus://issue/I0301\",\n    \"kind\": \"issue\",\n    \"from\": \"issue\",\n})).unwrap();\nassert!(canonical.resolved.is_none());\n\n// and a path is carried verbatim: its `uri` is not a canonical identifier at all\nlet path: Seed = serde_json::from_value(json!({\n    \"uri\": \"apps/majordomus-cli/src\",\n    \"kind\": \"path\",\n    \"from\": \"paths\",\n})).unwrap();\nassert!(!path.uri.starts_with(\"majordomus://\"));\nassert_eq!(path.from, \"paths\", \"which request field it came from\");\n```",
      "properties": {
        "from": {
          "description": "Where it came from: which field of the request.",
          "type": "string"
        },
        "kind": {
          "description": "`issue`, `milestone`, `path`, `intent`, or the kind of the object named.",
          "type": "string"
        },
        "resolved": {
          "description": "What the compiler resolved it to, when the request named something by a short name.",
          "type": [
            "string",
            "null"
          ]
        },
        "uri": {
          "description": "The canonical identifier of the seed, or the literal the request gave for an\nintent or a path.",
          "type": "string"
        }
      },
      "required": [
        "uri",
        "kind",
        "from"
      ],
      "type": "object"
    },
    "Selector": {
      "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```",
      "oneOf": [
        {
          "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.",
          "type": "string"
        }
      ]
    },
    "Severity": {
      "description": "How bad a diagnostic is. `Error` excludes the file it concerns from the index and puts\nthe index into the degraded state; `Warning` and `Info` do neither.",
      "oneOf": [
        {
          "const": "info",
          "description": "Worth knowing; changes nothing.",
          "type": "string"
        },
        {
          "const": "warning",
          "description": "Something to look at; the object is still served.",
          "type": "string"
        },
        {
          "const": "error",
          "description": "The file is excluded and the index is degraded.",
          "type": "string"
        }
      ]
    },
    "Tier": {
      "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```",
      "oneOf": [
        {
          "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.",
          "type": "string"
        }
      ]
    },
    "TierSpend": {
      "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```",
      "properties": {
        "excluded": {
          "description": "How many were dropped from it for budget.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "meaning": {
          "description": "What it is for.",
          "type": "string"
        },
        "required": {
          "description": "Entries in it that cannot be dropped.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "selected": {
          "description": "How many entries survived in it.",
          "format": "uint",
          "minimum": 0,
          "type": "integer"
        },
        "tier": {
          "$ref": "#/$defs/Tier",
          "description": "The tier."
        },
        "tokens": {
          "description": "Tokens the survivors cost.",
          "format": "uint64",
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "tier",
        "meaning",
        "selected",
        "excluded",
        "tokens",
        "required"
      ],
      "type": "object"
    }
  },
  "description": "A compiled development context: what to give a session, what was left out, what\ncollapsed into what, and the budget it was all decided under.\n\nThis is the canonical form. Rendering it as a prompt is a downstream projection of this\nvalue and is not performed here — the structure is what lets a caller re-budget, re-order\nor explain the selection without recompiling it.\n\nTwo invariants hold over every answer, and they are what make it safe to cache and to\ncompare. `fingerprint` is over the index this was compiled from, so the same request\nagainst the same fingerprint is the same answer and a different fingerprint is a\ndifferent tree — a caller can tell two trees apart without asking. And\n`budget.used_tokens` is exactly the sum of `selected`'s costs, so the arithmetic in the\nbudget describes the list beside it rather than a walk that has since been filtered.\n\n```\nuse majordomus_cli::devcontext::{compile, CompileInput, CompiledContext};\nuse majordomus_cli::devcontext::{Tier, DEFAULT_BUDGET_TOKENS};\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\n\nlet c: CompiledContext = compile(&ctx, CompileInput::default()).unwrap();\n\n// the answer says which tree it is true of, and nothing else has to be asked\nassert_eq!(c.schema, 1);\nassert!(!c.fingerprint.is_empty(), \"an answer that names no tree is not one\");\n\n// the budget describes the list beside it\nlet spent: u64 = c.selected.iter().map(|e| e.cost_tokens).sum();\nassert_eq!(c.budget.used_tokens, spent);\nassert_eq!(c.budget.limit_tokens, DEFAULT_BUDGET_TOKENS);\n\n// every tier is reported, so an empty tier is visibly empty rather than missing\nassert_eq!(c.budget.tiers.len(), Tier::ORDER.len());\n\n// a request that named nothing has no seeds and is still an answer\nassert!(c.seeds.is_empty());\n\n// and recompiling the same request over the same tree gives the same answer\nlet again: CompiledContext = compile(&ctx, CompileInput::default()).unwrap();\nassert_eq!(again.fingerprint, c.fingerprint);\nassert_eq!(again.selected.len(), c.selected.len());\n```",
  "properties": {
    "budget": {
      "$ref": "#/$defs/Budget",
      "description": "The budget and its per-tier spend."
    },
    "conflicts": {
      "description": "What does not agree with what.",
      "items": {
        "$ref": "#/$defs/Conflict"
      },
      "type": "array"
    },
    "deduplicated": {
      "description": "What collapsed into what.",
      "items": {
        "$ref": "#/$defs/Deduplicated"
      },
      "type": "array"
    },
    "diagnostics": {
      "description": "What the compiler could not read: a knowledge source the layer names and does not\nhold, a session record that no longer describes this checkout. Never an error: an\nabsent source is an answer.",
      "items": {
        "$ref": "#/$defs/Diagnostic"
      },
      "type": "array"
    },
    "excluded": {
      "description": "What was reached and not given, with the reason for each.",
      "items": {
        "$ref": "#/$defs/Excluded"
      },
      "type": "array"
    },
    "fingerprint": {
      "description": "The index this was compiled from, over every object's path and content. Two answers\nwith the same fingerprint and the same request are the same answer; a different\nfingerprint is a different tree.",
      "type": "string"
    },
    "git": {
      "$ref": "#/$defs/GitContext",
      "description": "The head the answer is true of."
    },
    "schema": {
      "description": "The format of this answer.",
      "format": "uint64",
      "minimum": 0,
      "type": "integer"
    },
    "seeds": {
      "description": "What was asked for.",
      "items": {
        "$ref": "#/$defs/Seed"
      },
      "type": "array"
    },
    "selected": {
      "description": "What to give the session, in the order the budget spent: tier, then relevance, then\ncanonical identifier.",
      "items": {
        "$ref": "#/$defs/ContextEntry"
      },
      "type": "array"
    }
  },
  "required": [
    "schema",
    "fingerprint",
    "git",
    "seeds",
    "selected",
    "excluded",
    "deduplicated",
    "conflicts",
    "budget",
    "diagnostics"
  ],
  "title": "CompiledContext",
  "type": "object"
}

Politiky

benchmark
povinné — cíl na každém transportu, který expozice deklaruje; případy jsou ty ze vstupního typu
cache
process: až 16 záznamů v procesu, vymezených otiskem registru

Cíle benchmarku

Odvozeno z registru pro tento repozitář: jeden požadavek na transport a případy, které poskytuje typ vstupu. Celá matice je na stránce měření výkonu.

transportstatepřípadytargets
directpokryto4no-seed studený+teplý
issue studený+teplý
milestone studený+teplý
intent studený+teplý
mcppokryto4no-seed studený+teplý
issue studený+teplý
milestone studený+teplý
intent studený+teplý
httppokryto4no-seed studený+teplý
issue studený+teplý
milestone studený+teplý
intent studený+teplý

Prohledává názvy a popisy všech stránek, které tento web publikuje.