A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live
devcontext.policy
The compiler's own rules
What it is
What the compiler decides and how: the tiers in the order the budget spends in with the kinds that land in each, every edge kind the composed graph declares with the relevance multiplier the compiler follows it by in each direction — or the reason it refuses to follow it at all — the selectors with which of them infer rather than read, and the defaults for the budget, the depth and the relevance floor. Read this rather than inferring the policy from an answer.
Descriptor
- Canonical id
devcontext.policy- Module
devcontext- Kind
- query
- Stability
- behaviorallyverified
- Provenance
- declared
- Source
apps/majordomus-cli/src/capability/builtin/devcontext.rs- Cache
disabled- Benchmark
required- Tags
- contextintrospection
Run
queryA query. It reads and changes nothing.
Projections
| Interface | As | Where |
|---|---|---|
| MCP tool | majordomus_devcontext_policy | - |
| MCP resource | majordomus://devcontext/policy | - |
| HTTP | GET /api/v1/devcontext/policy | Swagger |
| Command line | majordomus devcontext policy | - |
Schemas
Input · Empty
{
"type": "object",
"additionalProperties": false,
"description": "No input.",
"title": "Empty"
}Output · CompilerPolicy
{
"type": "object",
"properties": {
"schema": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "The format of this answer."
},
"graph": {
"type": "string",
"description": "The graph the relations are read from."
},
"tiers": {
"type": "array",
"items": {
"$ref": "#/$defs/TierRule"
},
"description": "The tiers, in the order the budget spends in."
},
"edges": {
"type": "array",
"items": {
"$ref": "#/$defs/EdgeRule"
},
"description": "Every edge kind the composed graph has, followed or refused."
},
"selectors": {
"type": "array",
"items": {
"$ref": "#/$defs/SelectorRule"
},
"description": "The selectors, and which of them infer."
},
"default_budget_tokens": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "The default ceiling in estimated tokens."
},
"default_max_depth": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "The default depth limit."
},
"default_floor": {
"type": "number",
"format": "double",
"description": "The default relevance floor."
},
"bytes_per_token": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "Bytes per estimated token."
}
},
"required": [
"schema",
"graph",
"tiers",
"edges",
"selectors",
"default_budget_tokens",
"default_max_depth",
"default_floor",
"bytes_per_token"
],
"description": "The compiler's own rules, so that a caller reads the decision instead of inferring it\nfrom an answer.\n\nThis is the answer to \"why did I get that\", asked once rather than reverse-engineered\nfrom every context. It is a projection of the tables and constants this module is built\nfrom — `Tier::ORDER`, `select::EDGES`, `Selector::ALL` and the four defaults\n— and holds no numbers of its own, so the published rules and the code that applies them\ncannot drift apart.\n\nThe defaults are here because they are what a request gets when it says nothing, and a\ncaller tuning a request needs to know what it is tuning away from.\n\n```\nuse majordomus_cli::devcontext::{policy, CompilerPolicy, Selector, Tier};\nuse majordomus_cli::devcontext::{BYTES_PER_TOKEN, DEFAULT_BUDGET_TOKENS};\nuse majordomus_cli::devcontext::{DEFAULT_FLOOR, DEFAULT_MAX_DEPTH};\nuse majordomus_cli::graph;\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\nlet rules: CompilerPolicy = policy(&ctx).unwrap();\n\n// it names the graph it reads relations from, rather than leaving it to be guessed\nassert_eq!(rules.schema, 1);\nassert_eq!(rules.graph, graph::COMPOSED);\n\n// the three tables are complete\nassert_eq!(rules.tiers.len(), Tier::ORDER.len());\nassert_eq!(rules.selectors.len(), Selector::ALL.len());\nassert!(!rules.edges.is_empty());\n\n// and the published defaults are the constants a silent request actually gets\nassert_eq!(rules.default_budget_tokens, DEFAULT_BUDGET_TOKENS);\nassert_eq!(rules.default_max_depth, DEFAULT_MAX_DEPTH);\nassert_eq!(rules.default_floor, DEFAULT_FLOOR);\nassert_eq!(rules.bytes_per_token, BYTES_PER_TOKEN);\n```",
"title": "CompilerPolicy",
"$defs": {
"TierRule": {
"type": "object",
"properties": {
"tier": {
"$ref": "#/$defs/Tier",
"description": "The tier."
},
"position": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "Its position in the order the budget spends in; 1 is spent first."
},
"meaning": {
"type": "string",
"description": "What it is for."
},
"kinds": {
"type": "array",
"items": {
"type": "string"
},
"description": "The kinds of object that land in it."
}
},
"required": [
"tier",
"position",
"meaning",
"kinds"
],
"description": "One tier, as the policy reports it: its place in the spend order, what it is for, and\nwhich kinds of object land in it.\n\n`position` is 1-based and exists because the wire form has no inherent order a consumer\ncan rely on — the `Tier` enum's `Ord` is a Rust fact, not a JSON one — so the rank is\nmade explicit for the readers that are not this crate. `kinds` is the inverse of\n`tier_for_kind`, published so that a caller can see where a kind will land without\ncompiling an answer and looking.\n\n```\nuse majordomus_cli::devcontext::{policy, tier_for_kind, Tier, TierRule};\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\nlet rules = policy(&ctx).unwrap();\n\n// the first tier spent is the one that is never dropped, at position 1\nlet first: &TierRule = &rules.tiers[0];\nassert_eq!(first.tier, Tier::Task);\nassert_eq!(first.position, 1, \"1-based, so the order survives serialisation\");\n\n// every tier is reported, in the order the budget spends in, and explains itself\nassert_eq!(rules.tiers.len(), Tier::ORDER.len());\nfor (i, r) in rules.tiers.iter().enumerate() {\n assert_eq!(r.position, i + 1);\n assert_eq!(r.meaning, r.tier.meaning());\n}\n\n// and every kind is listed under the tier the classifier puts it in, exactly once —\n// so the published table and the function behind it cannot disagree\nlet mut listed = 0usize;\nfor r in &rules.tiers {\n for kind in &r.kinds {\n assert_eq!(tier_for_kind(kind), r.tier, \"{kind} is listed under the wrong tier\");\n listed += 1;\n }\n}\nlet mut all: Vec<&str> = rules.tiers.iter().flat_map(|r| &r.kinds).map(String::as_str).collect();\nall.sort();\nall.dedup();\nassert_eq!(all.len(), listed, \"a kind is listed under one tier only\");\n```"
},
"Tier": {
"oneOf": [
{
"type": "string",
"const": "task",
"description": "What was asked for: the issue, its milestone, the paths named, the intent. Never\ndropped — a context that lost the thing it was compiled about is not a smaller\nanswer, it is the wrong one."
},
{
"type": "string",
"const": "governance",
"description": "What the work will be judged against: the policy, the scope, the directory\ncontracts that reach the named paths, and the rules. A blocking rule is never\ndropped."
},
{
"type": "string",
"const": "source",
"description": "The code and the cases the work touches."
},
{
"type": "string",
"const": "decision",
"description": "The architectural decisions already in force over it."
},
{
"type": "string",
"const": "knowledge",
"description": "What a previous session left: handovers, session records, curated knowledge."
},
{
"type": "string",
"const": "history",
"description": "Supporting evidence: use cases, claims, features, and the rest of the layer."
}
],
"description": "Where an entry sits in the order the budget spends in.\n\nThe order is this repository's own: `lib/context.sh` assembles its sections \"in\nauthority order, highest first, because a worker that runs out of budget must lose the\nleast reliable evidence rather than the most: git, then the task and its policy, then\nblockers, then authored records, then event history.\" These six tiers are that\nsentence, applied to objects instead of to sections.\n\nThe derived `Ord` is load-bearing: the variants are declared in authority order, so\n`<` means \"spent before\" and \"harder to drop\", and the budget's ordering is a plain\n`sort` rather than a table mapping tiers to ranks. A variant added in the wrong place\nwould silently re-rank the whole answer, which is why the declaration order is the one\nthing about this enum to be careful with.\n\n```\nuse majordomus_cli::devcontext::Tier;\n\n// the declaration order *is* the order the budget spends in\nlet mut sorted = Tier::ORDER.to_vec();\nsorted.sort();\nassert_eq!(sorted, Tier::ORDER.to_vec());\n\n// so the strongest authority is the smallest, and it is the one never dropped\nassert_eq!(Tier::ORDER.iter().copied().min(), Some(Tier::Task));\nassert!(Tier::Task < Tier::Governance && Tier::Governance < Tier::History);\n\n// and the serialised word is the lowercase one the report is read under\nassert_eq!(\n serde_json::to_value(Tier::Governance).unwrap(),\n serde_json::json!(Tier::Governance.as_str()),\n);\n```"
},
"EdgeRule": {
"type": "object",
"properties": {
"edge": {
"type": "string",
"description": "The edge kind, as the composed graph names it."
},
"means": {
"type": "string",
"description": "What the graph asserts by it."
},
"forward": {
"type": [
"number",
"null"
],
"format": "double",
"description": "The relevance multiplier when followed source to target; absent when refused."
},
"reverse": {
"type": [
"number",
"null"
],
"format": "double",
"description": "The multiplier when followed target to source; absent when refused."
},
"reason": {
"type": "string",
"description": "Why the target is context for the source, or why the edge is refused."
},
"refused": {
"type": "boolean",
"description": "True when the compiler will not follow it in either direction."
}
},
"required": [
"edge",
"means",
"reason",
"refused"
],
"description": "One edge of the composed graph, and what the compiler does with it.\n\nEvery edge kind the graph declares gets a row, followed or not, which is the property\nthat makes this projection worth reading: an edge added to the graph and not to the\ntraversal table appears here as `refused` with a reason saying the compiler has no rule\nfor it, rather than being silently unfollowed. A table that only listed the edges it\nfollowed could not tell you what it was ignoring.\n\n`forward` and `reverse` are absent rather than zero when the edge is not followed that\nway, so \"not followed\" is one representation and not two. `means` is the graph's own\naccount of the relation; `reason` is this compiler's account of why it is or is not\ncontext, in both directions.\n\n```\nuse majordomus_cli::devcontext::{edge_policy, policy, EdgeRule};\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\nlet rules = policy(&ctx).unwrap();\n\n// one row per edge kind the graph declares, followed or refused\nlet edges: &[EdgeRule] = &rules.edges;\nassert!(!edges.is_empty(), \"the graph declares edges\");\nfor e in edges {\n // the row always says what the relation is and what was decided about it\n assert!(!e.means.is_empty() && !e.reason.is_empty(), \"{}\", e.edge);\n\n if e.refused {\n // not followed in either direction, and absent rather than zero\n assert!(e.forward.is_none() && e.reverse.is_none(), \"{}\", e.edge);\n assert!(edge_policy(&e.edge).is_none(), \"{} is refused and in the table\", e.edge);\n } else {\n // followed at least one way, at a weight the table declares\n assert!(e.forward.is_some() || e.reverse.is_some(), \"{}\", e.edge);\n let p = edge_policy(&e.edge).expect(\"a followed edge has a policy\");\n assert_eq!(e.forward, (p.forward > 0.0).then_some(p.forward));\n assert_eq!(e.reverse, (p.reverse > 0.0).then_some(p.reverse));\n }\n}\n```"
},
"SelectorRule": {
"type": "object",
"properties": {
"selector": {
"$ref": "#/$defs/Selector",
"description": "The selector."
},
"declared": {
"type": "boolean",
"description": "Declared by the repository, or inferred by the compiler."
}
},
"required": [
"selector",
"declared"
],
"description": "One selector, and whether what it produces was declared or inferred.\n\nTwo fields, and the second is the whole reason the projection exists: a caller consuming\na compiled context needs to know which selectors it can trust as repository fact, and\nderiving that from the answer would mean inferring it from confidence values. Published\nhere, it is a rule rather than a pattern a reader noticed.\n\n```\nuse majordomus_cli::devcontext::{policy, Selector, SelectorRule};\nuse majordomus_cli::synthetic::SyntheticRepository;\n\nlet repo = SyntheticRepository::small().unwrap();\nlet ctx = repo.context().unwrap();\nlet rules = policy(&ctx).unwrap();\n\n// every selector is published, and each row agrees with the selector it names\nlet selectors: &[SelectorRule] = &rules.selectors;\nassert_eq!(selectors.len(), Selector::ALL.len());\nfor r in selectors {\n assert_eq!(r.declared, r.selector.declared());\n}\n\n// and the inferring one is named, so the guessed half of an answer can be found\nlet inferred: Vec<Selector> =\n selectors.iter().filter(|r| !r.declared).map(|r| r.selector).collect();\nassert_eq!(inferred, [Selector::IntentMatch]);\n```"
},
"Selector": {
"oneOf": [
{
"type": "string",
"const": "seed",
"description": "Named in the request."
},
{
"type": "string",
"const": "relation",
"description": "Reached along a typed edge of the composed graph."
},
{
"type": "string",
"const": "scope_path",
"description": "Its path lies under a path the request or a seed declares."
},
{
"type": "string",
"const": "contract",
"description": "A directory contract that reaches one of those paths."
},
{
"type": "string",
"const": "governance",
"description": "A rule or policy the layer applies to everything."
},
{
"type": "string",
"const": "session_state",
"description": "A recorded session of this branch or of these paths, the handover the resolver\nchose, the newest checkpoint."
},
{
"type": "string",
"const": "intent_match",
"description": "Inferred: the words of the intent occur in the object's own words."
}
],
"description": "What reached an entry. This is the provenance of the *selection*, and it is a different\nfact from the provenance of the file: `Relation` says the compiler followed an edge the\nlayer declares, `IntentMatch` says it guessed from words. An answer that did not keep\nthem apart could not say which half of itself to trust.\n\nThe division that matters is `Selector::declared`, and it is deliberately lopsided:\nsix of the seven selectors follow something the repository states, and exactly one\nguesses. That ratio is the design. Inference is confined to a single selector so that\nthe inferred part of any answer can be found, weighed and ignored, rather than being\nmixed through the rest at unmarked strength.\n\n```\nuse majordomus_cli::devcontext::Selector;\n\n// exactly one selector infers, and the answer can always be split on it\nlet inferred: Vec<&str> = Selector::ALL\n .iter()\n .filter(|s| !s.declared())\n .map(|s| s.as_str())\n .collect();\nassert_eq!(inferred, [\"intent_match\"]);\n\n// every selector has its own word, so a reason is never ambiguous\nlet mut words: Vec<&str> = Selector::ALL.iter().map(|s| s.as_str()).collect();\nlet before = words.len();\nwords.sort();\nwords.dedup();\nassert_eq!(words.len(), before);\n\n// and the word is the serialised form\nassert_eq!(\n serde_json::to_value(Selector::ScopePath).unwrap(),\n serde_json::json!(\"scope_path\"),\n);\n```"
}
}
}Examples
These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.
default
{}