Only the codes this command can produce. The full contract is on the commands index.
0ok
2usage
12missing artifact
Why it was done this way
A decision records a choice between real alternatives together with its reason. An entry is never edited or deleted; a later decision supersedes an earlier one and both stay readable.
Recording a decision with its reason
reason given
yes
Given this repository
# ... and an active task scoped to lib, with work done inside that scope.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" start "narrow the parser" --scope lib >/dev/null
echo work >> lib/a
Run
$ majordomus decision add refuse tabs in the parser --why two encodings for one token
Output contains
recorded: refuse tabs in the parser
exit0
The task id and the git head are computed and attached, so a decision can always be placed against the state of the repository when it was taken.
Reading them back
reason given
yes
Given this repository
# An active task that has already produced a checkpoint, a decision and an open question.
. "$FIXTURE_SETUP/active-task.sh"
printf 'the parser now refuses tabs\n' | "$MJ" checkpoint >/dev/null
"$MJ" decision add "refuse tabs in the parser" --why "two encodings for one token" >/dev/null
"$MJ" question add "should tabs be an error or a warning?" >/dev/null
Run
$ majordomus decision list
Output contains
refuse tabs in the parser
Why: two encodings
exit0
The reason is part of the record, not a commit message someone may or may not have written. A decision without one is the thing a later worker cannot safely revisit.
Reference
Record or read durable decisions. One append-only file: state/decisions.md.
decision add "<what>" --why "<why>" appends an entry with the task relation and git head
computed. --why is required: a decision with no recorded reason cannot be reviewed later,
only re-argued. --rejected and --evidence are optional and default to -.
An entry is never edited or deleted. --supersedes "<text>" records that a later decision
replaced an earlier one. The text is matched against the titles of the recorded decisions
only, must identify exactly one of them, and that title is what is recorded; text matching
no title, or more than one, is refused, so a supersession always points at one real
decision. decision list marks a replaced entry with Superseded by: <title>.
decision list [--task <id>] [--limit <n>] prints entries newest first; decision show "<text>" prints the first entry whose title contains that text, or exits 12.
Decisions, questions, checkpoints, handovers and knowledge observe prepare attribution
once. An explicit caller identity resolves its own open episode or none; an unknown identity
never borrows the checkout's pointer. With no supplied identity, exactly one local open
episode is unambiguous; zero or several produce an event with no session, and status may
still show the pointer as a guess. A record relates the active task unless a different
episode that is still open opened it (its task.started event names that episode); a task
whose opener closed, or that opened outside an episode, is carried on by whoever continues
it, and a handover never closes another live episode's task. Markdown uses none for an
absent task; the event omits task_id. The record is still written.
The deep-work profile sets verification.decision_record_required: true; finish then
refuses completed unless an entry names the task.
$ majordomus decision add "Normalise the callback URI before comparing state" \ --why "the mismatch is a trailing-slash difference, not a forged state parameter" \ --rejected "relaxing the comparison, which would accept genuinely forged states" \ --evidence "test/auth/callback_test.exs:41"recorded: Normalise the callback URI before comparing state
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.