Skip to content

majordomus update

Regenerate every provider instruction file from the one policy, deterministically.

Regenerate every provider instruction file from the one policy, deterministically.

  • generated-output-mutating
  • system

Running it twice leaves the byte-identical file. Each projection carries its own stamp, and a target whose content matches neither its stamp nor the new output is a hand edit, refused rather than overwritten.

Syntax

majordomus update [--dry-run] [--diff <target>] [--force]

Lifecycle

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

Other commands at this stage:init, migrate.

Reads

  • .ai/repo/policy.yaml
  • .ai/repo/profiles/
  • share/providers/

Writes

  • projections[].target
  • .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
  • 10 contract unmet
  • 12 missing artifact
  • 15 refused

Regenerating the provider instructions

One policy, several provider instruction files, generated deterministically. Running it twice leaves byte-identical files, which is what makes a stamp able to detect a hand edit.

The projections have never been generated

already generated
no

Given this repository

# Installed, but the provider instruction files have not been generated yet.
"$MJ" init >/dev/null
mkdir -p lib && echo a > lib/a && git add . && git commit -qm base

Run

$ majordomus update

Output contains

  • create CLAUDE.md
  • carries its own stamp

exit 0

Each target named in the policy's projections is written, and a stamp of each is recorded together with the hash of the policy that produced it.

Running it again with nothing changed

already generated
yes

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 update

Output contains

  • unchanged CLAUDE.md

exit 0

Deterministic output is not a nicety here. If regeneration produced a different file each time, a stamp could never distinguish a hand edit from the generator's own noise.

Reference

Regenerate provider projections from policy. Deterministic: same policy, same output, byte for byte.

Reads: policy, profiles, providers/*.tmpl. Writes: every projections[].target, one projections.updated ledger line. Nothing else: each target carries its own provenance.

Behaviour:

  • --dry-run prints what would change; --diff <target> shows the diff for one. For a region projection the diff is of the region, not of the host document.
  • Refuses (15) to overwrite content whose current hash matches neither the stamp it carries nor the new output, unless --force. A target with no stamp at all was not written by update and is refused the same way. A hand edit is never silently lost; the refusal names the file and the --diff command that shows it.
  • mode: region (see SCHEMAS.md) generates only the text between the majordomus:begin and majordomus:end markers. The rest of the target is copied through byte for byte, an absent region is appended once, and malformed markers are refused (15). This is how a repository that already has a hand-written CLAUDE.md adopts Majordomus without losing it.
  • Appends projections.updated to the ledger.
  • Every file-mode target begins with a stamp naming this command, the policy hash it came from and the hash of the content below it; a region-mode target carries the same two hashes in its begin marker. That stamp is the provenance doctor and watch compare against, on a fresh clone as much as here.
  • The always-loaded projection is checked against the budget after generation; over budget is 10 and nothing is written. For a region projection the budget measures the generated region, and doctor reports the host document's own length as INFO.
  • The Rust executable renders the same targets from the same inputs, byte for byte: majordomus generate providers writes them and majordomus generate --check (which CI runs) exits 10 naming every target that differs from the policy or is missing. update is the interactive writer with its refusals; generate --check is the gate. Test case 93 proves the two agree in both directions.

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