Skip to content

majordomus evidence

Record that one obligation the active task declared has been discharged, as a ledger line carrying the hash of the files that obligation names.

Record that one obligation the active task declared has been discharged, as a ledger line carrying the hash of the files that obligation names.

  • state-mutating
  • task
  • active task required
  • --json

Syntax

majordomus evidence --covers <token> [--type <kind>] (--command <cmd> | --artifact <ref>) [--result <r>] [--json]

Lifecycle

  1. Set up
  2. Begin
  3. Work
  4. Verify
  5. Conclude
  6. Inspect

Other commands at this stage:context, checkpoint, decision, question, prompt, skills, capture.

Reads

  • share/obligations.yaml
  • .ai/local/state/current.yaml

Writes

  • .ai/local/state/ledger.jsonl

Exit codes

Only the codes this command can produce. The full contract is on the commands index.

  • 0 ok
  • 2 usage
  • 12 missing artifact
  • 13 internal error
  • 15 refused

What the task owed, and what proves it

A task's scope says where a worker may write. Its requires says what the worker owes. Evidence discharges one obligation, and carries the hash of the files that obligation names, so that changing any of them takes the proof away rather than leaving it behind.

Recording a discharge

active task
yes
the task owes tests
yes

Given this repository

# ... and an active task that owes an obligation, with work done inside its scope. The
# obligation is written into the record the way a caller would declare it, because what the
# scenario is about is the discharge, not how the list got there.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" start "narrow the parser" --scope lib >/dev/null
echo work >> lib/a
python3 - <<'PY'
import io
p = '.ai/local/state/current.yaml'
s = io.open(p, encoding='utf-8').read()
io.open(p, 'w', encoding='utf-8').write(s.replace('outcome:', 'requires:\n  - tests\noutcome:'))
PY

Run

$ majordomus evidence --covers tests --type test --command bash test/run.sh

Output contains

  • evidence: tests recorded

exit 0

The line lands in the ledger, which is already append-only and integrity-checked, and carries the hash of the tracked files the obligation names. Nothing else is written; a second store of evidence would be a second account of the same facts.

For something the task never promised

active task
yes
the task owes tests
yes

Given this repository

# ... and an active task that owes an obligation, with work done inside its scope. The
# obligation is written into the record the way a caller would declare it, because what the
# scenario is about is the discharge, not how the list got there.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" start "narrow the parser" --scope lib >/dev/null
echo work >> lib/a
python3 - <<'PY'
import io
p = '.ai/local/state/current.yaml'
s = io.open(p, encoding='utf-8').read()
io.open(p, 'w', encoding='utf-8').write(s.replace('outcome:', 'requires:\n  - tests\noutcome:'))
PY

Run

$ majordomus evidence --covers docs --command scripts/ci/reference-check

Output contains

  • does not require 'docs'

exit 15

Recording evidence against an obligation nobody declared is how a checklist grows entries nobody asked for. The refusal names what the task does require.

Without a command or an artifact

active task
yes
the task owes tests
yes

Given this repository

# ... and an active task that owes an obligation, with work done inside its scope. The
# obligation is written into the record the way a caller would declare it, because what the
# scenario is about is the discharge, not how the list got there.
. "$FIXTURE_SETUP/installed.sh"
"$MJ" start "narrow the parser" --scope lib >/dev/null
echo work >> lib/a
python3 - <<'PY'
import io
p = '.ai/local/state/current.yaml'
s = io.open(p, encoding='utf-8').read()
io.open(p, 'w', encoding='utf-8').write(s.replace('outcome:', 'requires:\n  - tests\noutcome:'))
PY

Run

$ majordomus evidence --covers tests

Output contains

  • narrative is not evidence

exit 2

An assertion that something was done is the thing this command exists to replace. Either a command produced the evidence or an artifact points at it.

With no active task

active task
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 evidence --covers tests --command bash test/run.sh

Output contains

  • no active task

exit 12

An obligation is owed by a task. With nothing to attach it to, the evidence would describe no promise.

Reference

Record that one obligation the active task declared has been discharged.

majordomus evidence --covers <token> [--type <kind>] (--command <cmd> | --artifact <ref>) [--result <r>] [--json]

A task's scope says where a worker may write; its requires says what the worker owes before the outcome completed is available. The tokens are declared in share/obligations.yaml — implementation, tests, docs, generated, rules, commit, push, target, pages, deploy, verify — each naming the command that discharges it and, where the fact is local, the pathspecs its evidence is taken over.

Four of them are never recorded here. commit, push, target and pages name facts the tool can establish — a clean tree, a remote-tracking ref that reaches the head, a trunk that reaches it, a published site that serves it — and check and finish settle those live at HEAD instead of asking a worker to transcribe them. Recording one has no effect: an established obligation discharges by being true and refuses by being false. Where the checkout cannot settle it (no remote, no default branch recorded, a site that never answered) the token falls back to the recorded line, and the finding says which it was. deploy and verify stay hand-recorded, and share/obligations.yaml says in one line why: a deployment is a fact about a machine this repository never contacts.

--command or --artifact is required: narrative is not evidence. A token the vocabulary does not declare exits 2; a token the active task never promised exits 15, because recording evidence for something nobody asked for is how a checklist grows entries nobody wanted.

Writes: a task.evidence line in the ledger, carrying the obligation, how it was taken, the command or artifact, and the hash of the tracked files the obligation names. Nothing else is written; the ledger is already append-only, ordered and integrity-checked, and its envelope already carries the head, the branch and the session.

That hash is the point. Evidence discharges an obligation only while the recomputed hash of its inputs equals the recorded one, so a change to any file the obligation names takes the proof away rather than leaving it behind — the same currency question the site's own source_hash asks, asked of a test result. An obligation whose fact is remote (a push, an integration, a publication, a deployment) has no inputs and is bound instead to the commit it was taken at, judged exact | advanced | diverged | different_context like every other record here.

check and finish evaluate every obligation on every run through the doctrine majordomus.obligation-closure, so a stale evidence is visible before someone builds on it; only an outcome of completed is refused. A worker reporting blocked is being honest, and refusing that would teach them to claim completed instead.

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.

Guarantees this command carries