The repository's architecture decisions as objects: list, show, propose one with provenance, and validate the whole set.
The repository's architecture decisions as objects: list, show, propose one with provenance, and validate the whole set.
state-mutating
memory
--json
propose writes status 'proposed' and refuses --status: accepting a decision is a person editing the field. The identity is allocated under a lock over the section directory, so two worktrees proposing at once get two identities; check refuses duplicate identities, a superseded record with no replacement, and one-sided supersession.
Only the codes this command can produce. The full contract is on the commands index.
0ok
2usage
10contract unmet
12missing artifact
13internal error
15refused
Decisions the tool proposes and only a person accepts
An architecture decision is a file under the repository's adrs section: front matter that satisfies the decision schema over a body carrying the context, the decision and its consequences. Nothing registers it — the source class `adr` in the knowledge sources discovers it over the tracked tree, and list, show, check, the doctrine and MCP all read that one catalogue. What the tool writes is always `proposed`, because acceptance is the person's act.
A decision exists because its file does
decision tracked
yes
Given this repository
# Installed, with one decision proposed and committed. Discovery is over the tracked tree,
# so a decision the working copy holds and git does not is not yet part of the layer: the
# commit is what makes the record discoverable, exactly as it is for every other kind.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" adr propose "The registry is the one canonical declaration" --from file:docs/d --tag architecture >/dev/null
git add . && git commit -qm "adr: the registry is the one canonical declaration"
Run
$ majordomus adr list
Output contains
adr-0001
proposed
exit0
One line per decision, in discovery order: the identity, the status, the date it reached it, and the title.
What check examined
decision tracked
yes
Given this repository
# Installed, with one decision proposed and committed. Discovery is over the tracked tree,
# so a decision the working copy holds and git does not is not yet part of the layer: the
# commit is what makes the record discoverable, exactly as it is for every other kind.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" adr propose "The registry is the one canonical declaration" --from file:docs/d --tag architecture >/dev/null
git add . && git commit -qm "adr: the registry is the one canonical declaration"
Run
$ majordomus adr check
Output contains
examined 1 decision\(s\)
every identity unique
exit0
A clean result states what it examined, so that a pass over an empty directory cannot look like a pass over the set.
The status is not the tool's to choose
decision tracked
yes
Given this repository
# Installed, with one decision proposed and committed. Discovery is over the tracked tree,
# so a decision the working copy holds and git does not is not yet part of the layer: the
# commit is what makes the record discoverable, exactly as it is for every other kind.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" adr propose "The registry is the one canonical declaration" --from file:docs/d --tag architecture >/dev/null
git add . && git commit -qm "adr: the registry is the one canonical declaration"
Run
$ majordomus adr propose A decision that accepts itself --status accepted
Output contains
not yours to choose
a person editing the record
exit15
Exit 15 is REFUSED. A tool that can write `accepted` turns its own inference into repository truth, and a reader months later cannot tell which decisions a person actually made.
Asking for one that does not exist
decision tracked
no
Given this repository
# A repository with Majordomus installed and projections generated, and one commit of work.
"$MJ" init >/dev/null
"$MJ" update >/dev/null
mkdir -p lib docs
echo a > lib/a
echo d > docs/d
git add . && git commit -qm base
Run
$ majordomus adr show adr-9999
Output contains
adr list
exit12
Exit 12 is MISSING_ARTIFACT, and the message names the command that lists what does exist.
Which decisions a change set reaches
decision naming a file
yes
Given this repository
# One decision, committed, that names what it put in force. `propose` writes provenance —
# where the record came from — and never `related`, which is the other direction and a
# person's statement: this rule, this file, are what the decision did.
. "$FIXTURE_SETUP/adr-recorded.sh"
adr="$(ls .ai/repo/adrs/0001-*.md)"
sed -i.bak 's|^status: proposed$|status: proposed\
related:\
- rule:majordomus.adr-integrity\
- file:docs/d|' "$adr" && rm -f "$adr.bak"
git add . && git commit -qm "adr: name the rule and the file the decision put in force"
Run
$ majordomus adr affected
Output contains
no decision names anything this change set touches
exit0
Read from what the decisions themselves name: a clean tree reaches nothing, and a change to a named path names the decision behind it. Review notes only — whether a decision still holds after the code it governs moved is not the tool's judgement, so the exit code stays 0.
Reference
The repository's architecture decisions as objects: what was decided, why, what it cost,
and where the record came from. Under the layer's adrs section.
A decision is a file .ai/repo/adrs/<NNNN>-<slug>.md — YAML front matter satisfying
share/schemas/majordomus/adr/adr.v1.schema.json over a body carrying # Context, # Decision and
# Consequences. Nothing registers it: the source class adr in
.ai/repo/knowledge/sources.yaml discovers it over the tracked tree, which is the same
declaration the Rust executable indexes. See SCHEMAS.md for the contract.
majordomus adr list [--status <status>] [--json] every decision: id, status, date, titlemajordomus adr show <id> [--json] the path, then the file as writtenmajordomus adr propose "<title>" [--from <ref>]... write a new decision, status proposed [--tag <tag>]... [--supersedes <id>]majordomus adr check [--json] validate every decision and every referencemajordomus adr affected [--base <ref>|--staged|--worktree] [--json] the decisions a change set touches
list prints one line per discovered decision, invalid ones included; --status
filters to one of proposed, accepted, superseded, rejected.
show prints the repository-relative path on the first line and the file below it. An
id that is not a decision exits 12 and names adr list.
propose writes status: proposed and nothing else. There is no way to write
accepted: --status exits 15 naming the reason, because a tool that can write
accepted turns its own inference into repository truth and a later reader cannot tell
which decisions a person actually made. The identity is allocated under a lock over the
section directory, so two worktrees proposing at the same moment get two identities.
A --from reference is <type>:<value> with the type one of decision, session,
commit, issue, file, test; a file: or test: path that does not exist exits
2. Referenced evidence makes the record provenance.origin: extracted, and an
extracted record with no evidence is refused as an assertion. --supersedes writes both
halves of the relation, so the chain is walkable from either end.
related is the other half of a record's references, and it is authored rather than
written by propose: rule:<id>, claim:<id>, file:<path>, test:<path> — what the
decision put in force, as against provenance.derived_from, which is where it came from.
Each is validated where its type says the target lives, and the extractor turns it into a
graph edge (declares, supports, references, tested_by), so the reverse direction —
which decision put this rule in force — is knowledge edges, not a second list somebody
keeps in step.
check validates every record against the allow-list generated from the schema (no
unknown key), schema: adr/v1, the closed status set, an id whose number equals the
file-name prefix, the required body sections; and across the set: duplicate identities,
a superseded record with no superseded_by, one-sided supersession, and a reference
that resolves to nothing. It exits 10 on any failure.
affected reads a change set — the working tree against HEAD by default, --staged
for the index, --base <ref> for <ref>..HEAD plus the working tree — and names every
decision whose own file changed, or whose related names a path the change touches (a
reference to a directory covers everything below it). Every item is a WARN review note
and the exit code stays 0: whether a decision still holds after the code it governs
moved is the judgement a tool may not make. It is the reverse question the graph answers
— what decided this file? — asked from the change set instead of from a record.
doctor and watch run the same examination through the doctrine
majordomus.adr-integrity. The threshold for recording a decision at all is the rule
majordomus.decision-threshold, which a reviewer decides: the tool validates records and
reports what a change reaches, and never claims to know that a diff embodied a decision.
$ majordomus adr propose "The registry is the one canonical declaration" --from file:docs/CAPABILITIES.mdproposed: adr-0011 The registry is the one canonical declaration.ai/repo/adrs/0011-the-registry-is-the-one-canonical-declaration.mdstatus is "proposed"; accepting it is a person editing that field.$ majordomus adr checkexamined 11 decision(s) in .ai/repo/adrs/every identity unique, every status known, every reference resolves
Evidence
Every case below runs in CI on Linux and macOS. The site refuses to build if a public command has no behavioural case, no negative case, or no demonstration.