Skip to content

Plan

milestones are outcome specifications and issues are execution contracts; status, execution waves and the next ready issue are derived from the dependency graph, never stored

milestones are outcome specifications and issues are execution contracts; status, execution waves and the next ready issue are derived from the dependency graph, never stored

Where it lives

The command that acts on it

majordomus plan

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

  • state-mutating
  • --json
majordomus plan <subcommand> [options]

See it refuse, and accept

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.

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.

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.

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.

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.

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.

What enforces it

What is guaranteed

The moments this answers