Skip to content

majordomus plan

The milestone and issue model — validate it, read it, and move one issue through it.

The milestone and issue model — validate it, read it, and move one issue through it.

  • state-mutating
  • plan
  • --json

Ten read-only subcommands and four that write one lifecycle marker each. The class names the command as a whole, which is what a single field can say; the syntax section separates READ from WRITE. It operates on the project model rather than on the active task record, so it needs no task.

Syntax

majordomus plan <subcommand> [options]

Lifecycle

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

Other commands at this stage:start, session.

Reads

  • .ai/repo/project/

Writes

  • .ai/repo/project/

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

The model, validated and read

plan reads a canonical project model and moves one issue through it. Status is never stored — it is derived from what was recorded about an issue and from the state of its dependencies. Every scenario here is executed against the real binary by test/cases/34_command_fixtures.sh.

A model that parses and hangs together

dependency satisfied
no
model present
yes

Given this repository

# Installed, with a canonical project model carrying one milestone and two issues, the
# second depending on the first. The helpers come from test/lib.sh, which the fixture
# runner has already sourced.
. "$FIXTURE_SETUP/installed.sh"
pj_init
pj_milestone M000
pj_issue I0001 M000
pj_issue I0002 M000 I0001

Run

$ majordomus plan validate

Output contains

  • milestone
  • issue
  • 0 failure

exit 0

Schemas, references, the dependency graph and status consistency, in one pass. A key nobody reads is an error here for the same reason it is an error in the policy: an unread field is a belief nothing checks.

A repository with no project model

dependency satisfied
no
model present
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 plan validate

Output contains

  • no canonical project model

exit 12

Exit 12 is MISSING_ARTIFACT: the repository is not set up for a project model, which is a different fact from a model that fails to parse.

What can be started now

dependency satisfied
no
model present
yes

Given this repository

# Installed, with a canonical project model carrying one milestone and two issues, the
# second depending on the first. The helpers come from test/lib.sh, which the fixture
# runner has already sourced.
. "$FIXTURE_SETUP/installed.sh"
pj_init
pj_milestone M000
pj_issue I0001 M000
pj_issue I0002 M000 I0001

Run

$ majordomus plan ready

Output contains

  • I0001

exit 0

I0002 depends on I0001, so only I0001 is ready. Readiness is derived from the graph rather than labelled on the issue, so it cannot disagree with the dependencies.

What is waiting, and on what

dependency satisfied
no
model present
yes

Given this repository

# Installed, with a canonical project model carrying one milestone and two issues, the
# second depending on the first. The helpers come from test/lib.sh, which the fixture
# runner has already sourced.
. "$FIXTURE_SETUP/installed.sh"
pj_init
pj_milestone M000
pj_issue I0001 M000
pj_issue I0002 M000 I0001

Run

$ majordomus plan blocked

Output contains

  • I0002

exit 0

The complement of ready, and it names the dependency rather than only the fact of being blocked — the useful question is what to finish first.

A subcommand it does not have

dependency satisfied
no
model present
yes

Given this repository

# Installed, with a canonical project model carrying one milestone and two issues, the
# second depending on the first. The helpers come from test/lib.sh, which the fixture
# runner has already sourced.
. "$FIXTURE_SETUP/installed.sh"
pj_init
pj_milestone M000
pj_issue I0001 M000
pj_issue I0002 M000 I0001

Run

$ majordomus plan explain

Output contains

  • plan

exit 2

Exit 2 is USAGE. A mistyped subcommand is refused rather than treated as a default, so a script cannot silently ask a different question from the one it meant.

Reference

Read the canonical project model, and move one issue through its lifecycle. A milestone is an executable specification of an outcome; an issue is a bounded execution contract; the dependency graph between the issues decides what may be executed next. See docs/PLANNING.md for the semantics.

Reads: .ai/repo/project/project.yaml, .ai/repo/project/milestones/*.yaml, .ai/repo/project/issues/*.yaml, share/allow/{project,milestone,issue}.txt. Writes: one lifecycle field in one issue file, and one ledger event — start, verify, evidence and done only. Every other subcommand writes nothing.

majordomus plan validate         schemas, references, the DAG, status consistency
majordomus plan status           milestone progress and the next executable issue
majordomus plan list             one line per issue: id, status, wave, milestone, title
majordomus plan show <id>        the full record of one milestone or issue
majordomus plan ready            issues whose dependencies are all satisfied
majordomus plan blocked          issues waiting on a dependency, and on which one
majordomus plan waves            topological execution waves, derived from the graph
majordomus plan graph            the dependency DAG as Mermaid
majordomus plan next             the one issue a worker should take now
majordomus plan body <id>        the provider-neutral projection body for one record
majordomus plan start <id>       record that execution began
majordomus plan verify <id>      record that implementation is complete, evidence pending
majordomus plan evidence <id>    attach one piece of evidence
majordomus plan done <id>        record completion

Options: --json on the read subcommands a surface consumes; --milestone <id> to restrict list, ready, blocked, waves and graph; --covers, --type, --command, --result and --artifact on evidence.

Behaviour:

  • No status is stored anywhere. BLOCKED, READY, ACTIVE, VERIFY, DONE and CANCELLED are derived from what an issue records about itself and from the state of its dependencies, by lib/project.awk. Writing a status: field is an unknown key.
  • validate reports unknown keys, unknown and self dependencies, duplicate ids, cycles, issues executing ahead of a dependency, and issues with no acceptance criteria. It exits 10 when any finding is a failure, 0 when only warnings remain.
  • start refuses (15) an issue that is not READY, naming what it waits on. verify refuses an issue that is not ACTIVE.
  • evidence refuses (15) a token the issue does not declare, and refuses (2) without a --command or an --artifact: narrative is not evidence. It appends to the issue's own file with the commit and the timestamp.
  • done refuses (10) while any declared evidence token is uncovered, and refuses (15) while a dependency is not DONE. Every writing subcommand prints the next ready issue after the graph has been recomputed.
  • Exits 12 when the record named does not exist, or when the repository has no canonical project model at all — the model is opt-in, and doctor skips it rather than failing where it is absent.

The same model is projected to GitHub by scripts/github-sync and to the website by scripts/generate-site-data. Neither re-derives a status; both read this engine.

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