Expand description
The obligations module: what a task owes before it may be called completed, and
whether the evidence that discharged each one still describes this tree.
Two halves, and the difference between them decides the design.
The vocabulary is shipped. share/obligations.yaml is data the distribution
carries beside share/events.yaml and share/kinds.yaml: a token, what discharges
it, and the pathspecs its evidence is taken over. It is identical in every clone and
in every installation, so it is read here the way commands.list reads the command
registry — through crate::share::Share — and it answers in a checkout that has
never run the lifecycle.
The closure is local. The task record and the ledger live under
.ai/local/state/, the half super::continuity documents: never tracked, never
published, one file per checkout. A served instance answers about the checkout the
process was started in and about no other, and a fresh clone has nothing to report —
which is reported as nothing rather than as zero obligations discharged.
It is read, never written. majordomus evidence records; this reads. A second
writer for the same ledger would be a second account of events, which is the thing
ADR 0030 refuses.
The judgement is the validator’s, not a second opinion. mj_validate_obligations
in lib/evidence.sh decides whether a task may be completed; everything below
reproduces its rule — a remote fact is labelled against the commit it was taken at, a
tree-bound fact is re-hashed over the pathspecs its token declares, and the label is
Divergence, whose four words are mj_git_label’s. No fifth vocabulary is invented
here, and where the shell is generous — a token that names neither inputs nor a remote
fact can never go stale — this is generous in the same place rather than stricter in
private.
Where the two can differ, and in which direction. mj_obligation_inputs_hash
interpolates the token’s pathspecs unquoted, so the shell expands them as filename
globs before git ls-files ever sees them; without globstar, ** matches one level.
docs, whose pathspecs include .ai/repo/**/README.md, therefore selects 255 files
there and 261 here, and implementation, whose pathspec is *, selects 1915 there and
2480 here — a bare * expands to the top-level entries that are not dotfiles, so the
whole of .ai/ and .github/ is outside the hash the shell takes. This reader passes
the pathspecs to git verbatim, which is what the vocabulary’s inputs plainly mean, so
its selection is a superset and the disagreement can only run one way: it may call
evidence stale that finish would still accept, and never the reverse. inputs_files
is on every entry so the difference is measurable from the surface rather than argued
about. The repair belongs to lib/evidence.sh — set -f around the git ls-files
call, so that word splitting still happens and pathname expansion does not.
use majordomus_cli::capability::builtin::obligations;
// two capabilities: what a token means, and where this checkout's task stands
let m = obligations::module();
let ids: Vec<&str> = m.capabilities.iter().map(|e| e.capability.id.as_str()).collect();
assert_eq!(ids, ["obligations.vocabulary", "obligations.closure"]);
// and both report; neither records. `majordomus evidence` is the writer.
assert!(m.capabilities.iter().all(|e| e.capability.kind.is_read_only()));Structs§
- Closure
- What this checkout’s active task owes, and how much of it is still true.
- Evidence
- The
task.evidenceline that discharged an obligation, as the ledger holds it. - Obligation
- One token a task may declare in
requires, as the distribution ships it. - Obligation
Closure - One obligation the task declared, joined with what the vocabulary says about it and with the evidence that does or does not discharge it.
- Vocabulary
- The vocabulary the distribution ships: every token there is.
Enums§
- Obligation
State - Where one obligation stands.
Constants§
- CLOSURE_
URI - The URI under which this checkout’s closure is read as an MCP resource.
- OBLIGATIONS_
URI - The URI under which the shipped vocabulary is read as an MCP resource.
Functions§
- listing_
hash - The hash
mj_inputs_hashcomputes, reproduced. - module
- The module: the vocabulary every clone shares, and the closure only this checkout can answer.