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.explain

Jeden kanonický identifikátor posouzený pod požadavkem: zda byl vybrán, dosažen a vyloučen, sloučen do jiného identifikátoru, držen indexem a nikdy nedosažen, nebo neznámý — se samotným záznamem, vyloučením nebo sloučením a rozpočtem, pod nímž bylo posouzení provedeno, aby se na `excluded for budget` dalo reagovat bez druhého volání.

Jeden kanonický identifikátor posouzený pod požadavkem: zda byl vybrán, dosažen a vyloučen, sloučen do jiného identifikátoru, držen indexem a nikdy nedosažen, nebo neznámý — se samotným záznamem, vyloučením nebo sloučením a rozpočtem, pod nímž bylo posouzení provedeno, aby se na `excluded for budget` dalo reagovat bez druhého volání.

Zpřístupnění

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

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

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 · DevContextExplainInput

Vstup devcontext.explain: jeden identifikátor a požadavek, pod kterým se má posuzovat.
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.
uri string ano Kanonický identifikátor k vysvětlení.
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.explain`: one identifier, and the request to judge it under.",
  "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"
    },
    "uri": {
      "description": "The canonical identifier to explain.",
      "type": "string"
    },
    "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"
    }
  },
  "required": [
    "uri"
  ],
  "title": "DevContextExplainInput",
  "type": "object"
}

výstup · Explanation

Proč je jeden identifikátor v sestaveném kontextu, nebo proč v něm není.

standing říká, o který z pěti případů jde, a tři volitelná pole jsou jeho důkazem: nejvýše jedno z entry, excluded a deduplicated je vyplněno a které, to určuje stav, ne nezávisle na něm. detail je tatáž odpověď slovy, takže hodnota je čitelná, aniž by je čtenář musel párovat.

budget je vždy přítomné, i když je odpověď unknown, a právě to je smysl jeho nošení: nejčastější důvod k této otázce je položka, která se nevešla, a vysvětlení, které by řeklo „vyloučeno kvůli rozpočtu“ bez rozpočtu, by k jednání vyžadovalo druhé volání.

use majordomus_cli::devcontext::{compile, explain, CompileInput, ExplainInput};
use majordomus_cli::devcontext::{Explanation, Standing};
use majordomus_cli::synthetic::SyntheticRepository;

let repo = SyntheticRepository::small().unwrap();
let ctx = repo.context().unwrap();
let compiled = compile(&ctx, CompileInput::default()).unwrap();
let selected = compiled.selected[0].uri.clone();

// something in the answer: the entry is the evidence, and the other two are empty
let e: Explanation =
    explain(&ctx, ExplainInput { uri: selected.clone(), ..Default::default() }).unwrap();
assert_eq!(e.standing, Standing::Selected);
assert_eq!(e.entry.as_ref().unwrap().uri, selected);
assert!(e.excluded.is_none() && e.deduplicated.is_none());
assert!(!e.detail.is_empty(), "the standing always reads as a sentence too");

// something this repository does not hold: an answer, not an error — and the budget
// the judgement was made under is carried even here
let absent: Explanation = explain(
    &ctx,
    ExplainInput { uri: "majordomus://adr/9999".into(), ..Default::default() },
)
.unwrap();
assert_eq!(absent.standing, Standing::Unknown);
assert!(absent.entry.is_none());
assert_eq!(absent.budget.limit_tokens, compiled.budget.limit_tokens);
vlastnosttyppovinnépopis
rozpočet reference ano Rozpočet, za kterého se posuzovalo, aby se na „vyloučeno kvůli rozpočtu“ dalo reagovat bez druhého volání.
deduplikováno jedno ze 2 ne Sloučení, jehož byl součástí, pokud byl sloučen nebo zahozen ve prospěch jiného.
detail string ano Totéž, slovy.
vstup jedno ze 2 ne Položka, když je v odpovědi.
vyloučeno jedno ze 2 ne Vyloučení, když bylo dosaženo a nebylo zadáno.
postavení reference ano Jak to stojí.
uri string ano Na co se ptalo.
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"
    },
    "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"
    },
    "DevContextStanding": {
      "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```",
      "oneOf": [
        {
          "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.",
          "type": "string"
        }
      ]
    },
    "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"
        }
      ]
    },
    "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"
        }
      ]
    },
    "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": "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```",
  "properties": {
    "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."
    },
    "deduplicated": {
      "anyOf": [
        {
          "$ref": "#/$defs/Deduplicated"
        },
        {
          "type": "null"
        }
      ],
      "description": "The collapse it was part of, when it was folded or dropped for another."
    },
    "detail": {
      "description": "The same, in words.",
      "type": "string"
    },
    "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."
    },
    "standing": {
      "$ref": "#/$defs/DevContextStanding",
      "description": "Where it stands."
    },
    "uri": {
      "description": "What was asked about.",
      "type": "string"
    }
  },
  "required": [
    "uri",
    "standing",
    "detail",
    "budget"
  ],
  "title": "Explanation",
  "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ž 8 položek v procesu, omezený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
directpokryto2policy studený+teplý
chybí studený+teplý
mcppokryto2policy studený+teplý
chybí studený+teplý
httppokryto2policy studený+teplý
chybí studený+teplý

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