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
knowledge_base.status
Whether the deriver is still writing
What it is
The freshness half of the stopped-writer judgement (ADR 0052, applied to the knowledge deriver by ADR 0091): the newest knowledge.derived line, the newest session.closed line, how many closed episodes no derivation names, the candidate counts, and — once a derivation has run in this checkout and the switch is on — whether the newest closed episode went underived past session.freshness.stale_minutes. Episode ids are compared, never line order. Whether the close path still calls the deriver is read from the source by the shell validator, not here.
Descriptor
- Canonical id
knowledge_base.status- Module
knowledge_base- Kind
- query
- Stability
- behaviorallyverified
- Provenance
- declaredcached
- Source
apps/majordomus-cli/src/capability/builtin/knowledge_base.rs- Cache
process, 2 entries, 2s- Benchmark
required- Tags
- knowledgecontinuitysession
Run
queryA query. It reads and changes nothing.
Projections
| Interface | As | Where |
|---|---|---|
| MCP tool | majordomus_knowledge_status | - |
| MCP resource | majordomus://knowledge-status | - |
| HTTP | GET /api/v1/knowledge/status | Swagger |
| Command line | majordomus knowledge status | - |
Schemas
Input · Empty
{
"type": "object",
"additionalProperties": false,
"description": "No input.",
"title": "Empty"
}Output · KnowledgeStatus
{
"type": "object",
"properties": {
"present": {
"type": "boolean",
"description": "Whether anything is here to judge: a ledger line or a candidate. False in a fresh clone."
},
"branch": {
"type": "string",
"description": "The branch this checkout is on, or `DETACHED`."
},
"last_derived": {
"anyOf": [
{
"$ref": "#/$defs/LedgerMark"
},
{
"type": "null"
}
],
"description": "The newest `knowledge.derived` line, or `None` when the deriver has never run here."
},
"last_closed": {
"anyOf": [
{
"$ref": "#/$defs/LedgerMark"
},
{
"type": "null"
}
],
"description": "The newest `session.closed` line, or `None` when no episode has closed here."
},
"closed_without_derivation": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many closed episodes in this ledger no `knowledge.derived` line names."
},
"candidates": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many records carry `status: candidate` under the candidates class."
},
"on_this_branch": {
"type": "integer",
"format": "uint",
"minimum": 0,
"description": "How many of those came from an episode on this branch."
},
"freshness": {
"$ref": "#/$defs/Freshness",
"description": "How old the newest closed episode is, judged against `session.freshness`."
},
"age_minutes": {
"type": [
"integer",
"null"
],
"format": "int64",
"description": "That age in whole minutes, when it could be measured."
},
"freshness_reason": {
"type": "string",
"description": "Why it was judged that way. Never empty."
},
"judged": {
"type": "boolean",
"description": "Whether the stopped-writer judgement was made at all. False, with the reason among\n`findings`, while no episode has closed here, while the switch is off, or while no\nderivation has yet run in this checkout."
},
"stopped_writer": {
"type": "boolean",
"description": "The finding: episodes close here and no derivation followed the newest one within\nthe stale threshold. True only when `judged`."
},
"knowledge_on_end": {
"type": "boolean",
"description": "`session.knowledge_on_end`, as the policy declares it; absent means on."
},
"knowledge_on_compact": {
"type": "boolean",
"description": "`session.knowledge_on_compact`, likewise."
},
"findings": {
"type": "array",
"items": {
"type": "string"
},
"description": "What a reader should know: why the judgement was withheld, or what it found."
}
},
"required": [
"present",
"branch",
"closed_without_derivation",
"candidates",
"on_this_branch",
"freshness",
"freshness_reason",
"judged",
"stopped_writer",
"knowledge_on_end",
"knowledge_on_compact"
],
"description": "Whether the deriver is still writing, and what it last wrote.\n\nThe judgement is ADR 0052's, applied to this writer: while episodes keep closing, a\nderivation follows every close. It compares episode ids, never line order or timestamps\nbetween the two events, because the close derives before it appends `session.closed`.\nIt is the freshness half of the judgement only; whether the close path and the\ncompaction adapter still call the deriver is read from the source by the shell\nvalidator, which is where the source is.\n\n```\nuse majordomus_cli::capability::builtin::knowledge_base::KnowledgeStatus;\nlet fresh: KnowledgeStatus = serde_json::from_str(r#\"{\n \"present\": false, \"branch\": \"master\", \"closed_without_derivation\": 0, \"candidates\": 0,\n \"on_this_branch\": 0, \"freshness\": \"unknown\", \"freshness_reason\": \"no episode has closed here\",\n \"judged\": false, \"stopped_writer\": false, \"knowledge_on_end\": true, \"knowledge_on_compact\": true\n}\"#).unwrap();\nassert!(!fresh.present, \"a fresh clone has no ledger, and that is not a fault\");\nassert!(!fresh.stopped_writer);\n```",
"title": "KnowledgeStatus",
"$defs": {
"LedgerMark": {
"type": "object",
"properties": {
"ts": {
"type": "string",
"description": "The line's timestamp, RFC 3339 in UTC."
},
"episode": {
"type": "string",
"description": "The episode the line is about; empty when the line names none."
}
},
"required": [
"ts"
],
"description": "One ledger line that matters to the judgement: when, and which episode.\n\n```\nuse majordomus_cli::capability::builtin::knowledge_base::LedgerMark;\nlet m: LedgerMark = serde_json::from_str(r#\"{\"ts\":\"2026-09-12T10:00:00Z\",\"episode\":\"e1\"}\"#).unwrap();\nassert_eq!(m.episode, \"e1\");\n```"
},
"Freshness": {
"oneOf": [
{
"type": "string",
"const": "fresh",
"description": "Inside `session.freshness.fresh_minutes`. Current; act on it."
},
{
"type": "string",
"const": "aging",
"description": "Between the two thresholds. Still current, but its age is worth stating."
},
{
"type": "string",
"const": "stale",
"description": "At or beyond `session.freshness.stale_minutes`. History, never current."
},
{
"type": "string",
"const": "unknown",
"description": "Nothing to judge it by: no timestamp, or no thresholds declared."
},
{
"type": "string",
"const": "invalid",
"description": "A timestamp that does not parse, or one in the future."
}
],
"description": "How old a record is, judged against `session.freshness` in the policy.\n\nThis is the second of two independent judgements every record carries, and it exists\nbecause the first one cannot answer this question. `Divergence` says where a record's\ncommit sits relative to HEAD; `advanced` means that commit is an ancestor of this one,\nwhich sounds like agreement and is identically true on the day the record is written and\na month later. Between 2026-09-05 and 2026-09-11 this repository served a handover that\nwas `advanced` and six days dead, and every surface that read this model — MCP, the HTTP\nAPI, the Cockpit — presented its `Next Action` as the thing to do (ADR 0052).\n\nThe thresholds are policy and are read, never restated here: a constant in this file\nwould be a second source of truth for a number the policy owns, and a repository whose\npolicy predates the key is reported as `Freshness::Unknown` naming the missing key\nrather than judged against a default nobody declared.\n\nThe five words divide into two groups, and the division is the one a caller acts on:\n`fresh` and `aging` are current and may be presented as the instruction, `stale` and\n`invalid` must be shown as history, and `unknown` is neither — a record nobody can date\nis not thereby an old record, and treating it as one would quietly discard a briefing\nthat is perfectly good. `Freshness::history` is that division, and it is the only\nplace it is decided.\n\n```\nuse majordomus_cli::capability::builtin::continuity::Freshness;\n\n// the two renderings are one value: the serialised word is the word `as_str` gives,\n// so a reader who met `stale` from MCP and from the command line met one fact\nlet stale = serde_json::to_value(Freshness::Stale).unwrap();\nassert_eq!(stale, serde_json::json!(\"stale\"));\nassert_eq!(stale.as_str(), Some(Freshness::Stale.as_str()));\n\n// and the division a caller acts on: absence of a judgement is not a bad judgement\nassert!(Freshness::Stale.history() && Freshness::Invalid.history());\nassert!(!Freshness::Unknown.history(), \"undated is not old\");\nassert!(!Freshness::Fresh.history() && !Freshness::Aging.history());\n```"
}
}
}Examples
These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.
default
{}