Skip to main content

Module obligations

Module obligations 

Source
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.evidence line that discharged an obligation, as the ledger holds it.
Obligation
One token a task may declare in requires, as the distribution ships it.
ObligationClosure
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§

ObligationState
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_hash computes, reproduced.
module
The module: the vocabulary every clone shares, and the closure only this checkout can answer.