What does whoever works next need to know? Read-only. Assembles durable state into one briefing and prints it. Nothing is persisted, no model is called, and the output is a projection: every line is recomputed from the records and git each time it runs.
Section order is authority order. Git first, because it is the only thing that cannot be stale; then the task and the profile that constrains it; then blockers, which change what may be accepted; then authored records; then event history last, because it is the weakest evidence about the present.
| Section | Source | Included when |
|---|---|---|
GIT | git | always |
TASK | state/current.yaml | a task is active and the profile's context.task is not false |
PROFILE | profiles/<name>.yaml | the task names a profile that exists |
CONTEXT DOCUMENTS | .ai/**/README.md (the context contract) | a task is active; the effective chain is listed for each of its scope paths |
OPEN QUESTIONS | state/open-questions.md | any unresolved entry names this task |
DECISIONS | state/decisions.md | context.decisions: true (this task) or context.architecture_notes: true (the repository) |
REASONING | state/reasoning/<task>/, rendered by majordomus-cli reasoning status --report | the task has reasoning records and context.decisions: true |
LATEST CHECKPOINT | state/checkpoints/ | a checkpoint resolves for this task |
LATEST COMPATIBLE HANDOVER | state/handovers/ | a handover resolves for this worktree and branch |
| knowledge candidates | .ai/repo/knowledge/candidates/ | in the derived briefing, after the open questions and before the handover: the candidates awaiting review whose episode was on this branch, count and ids, bounded; unattributed ones on their own line; absence printed rather than omitted |
KNOWLEDGE POINTERS | the knowledge graph (majordomus knowledge), compiled on this read | context.knowledge: true and the task names an issue: see below |
FILES TOUCHED IN SCOPE | git | context.relevant_files: true |
RECENT HISTORY | state/ledger.jsonl | context.recent_history_depth is above zero |
PROMPT | prompts/<name>.md | --prompt <name> was given |
This is the only code that reads a profile's context block, which is what makes those
fields state rather than documentation.
Budget. context.builder_budget_lines in the policy, or --budget-lines. When the
assembled text exceeds it, sections are dropped in a fixed order — history, files,
decisions, then the bodies of the checkpoint and the handover, which degrade to a pointer
rather than disappearing. Git, task, profile and blockers are never dropped. Every drop is
named under EXCLUDED with its reason, so an under-filled context is debugged from the
exclusion list instead of guessed at. Exit 10 if what cannot be dropped is already over
budget.
Knowledge pointers. A bounded slice of the knowledge graph, not the graph: one line per
pointer — the relation that selected it, the kind, the id, the source path and the title.
Selection follows only edges a file states, in this order, each tier in byte order of the
id: the issue the task was started for, the issues it depends_on, its milestone, the
claims that milestone declares, and every node whose source is a path the task or the issue
names in its scope. Nothing is searched and nothing is scored — a document whose words
match the issue's but that nothing references is not selected. The list stops at the
profile's context.knowledge_max_items (the policy's context.max_list_items when unset,
and never above it), and a last line counts the rest with majordomus knowledge related issue:<id>, which prints them. The section is absent, and named under EXCLUDED with the
reason, when the profile does not set context.knowledge: true, and when the task names no
issue under a policy whose intent.binding is not off; with no task, or with binding off
and no issue, it is simply absent. Only the kinds and paths the selection can reach are compiled,
so it costs about two seconds on a plan of four hundred issues rather than the eight a whole
compile takes; it is a few lines of a 300-line budget. When the issue the task names is not
a node — its record left the version-control index, or is gone — the section prints a
stale line saying which and why, and still lists what the graph does hold. Under a tight
budget it is dropped with the derived listings, after files and before the context
documents, and so long before git, the task, the profile and the open questions, which are
never dropped; the drop names the command that prints the pointers.
--for <provider> wraps the same body with a header naming the provider and its
always-loaded file. The body does not change: the canonical context is provider-neutral,
and a provider that needed different facts would be a different policy, not a different
rendering.
--json emits one object: git, task, sections[] (each with id, lines and
text), excluded[] (each with item and reason), and budget. The same selection as
the text form, because both are assembled once and rendered twice.
$ majordomus context
# Majordomus context — 2026-09-03T19:41:02Z
# a projection of durable state, not a source of truth: validate every line against git