Skip to content
Cockpit0.29.0
A snapshot: read at commit 707a04c7ce8 on 2026-10-18T00:06:01Z by majordomus 0.29.0. Nothing on this page is read again. See it live

test/cases/49_roadmap_doctrine.sh

An object of kind test

What it is

URI
majordomus://test/test/cases/49_roadmap_doctrine.sh
Kind
test
Identity
test/cases/49_roadmap_doctrine.sh
Path
test/cases/49_roadmap_doctrine.sh
Provenance
declared
Media type
text/plain
As a capability
test.test/cases/49_roadmap_doctrine.sh

Front matter

{}

Content

# The roadmap is a projection, never a document.
#
# A doctrine that only passes is not evidence of anything, so this case moves the exit code
# in both directions: a document that invents a release, and a document that hides one. The
# third case is the one that matters longest — with no roadmap section at all, the check
# holds trivially, because the doctrine exists to refuse the regression rather than to
# require the table.
. "$ROOT/test/lib.sh"
"$MJ" init >/dev/null; "$MJ" update >/dev/null
# A fresh checkout has neither declared enforcement hook, and their absence is a real doctor
# failure that would mask the ones this case is about.
mkdir -p .git/hooks
printf '#!/usr/bin/env bash\nmajordomus doctor\n' > .git/hooks/pre-commit
printf '#!/usr/bin/env bash\nmajordomus finish --check\n' > .git/hooks/pre-push
chmod +x .git/hooks/pre-commit .git/hooks/pre-push
PATH="$(dirname "$MJ"):$PATH"; export PATH
pj_init

rm_milestone() { # ID VERSION ORDER [DEP ...]
  local id="$1" ver="$2" ord="$3"; shift 3
  { cat <<Y
id: $id
title: Milestone $id
slug: $id
version: "$ver"
order: $ord
priority: p1
problem: "A problem worth solving."
outcome: "The outcome once it is solved."
acceptance_criteria:
  - The outcome is reached
validation:
  - true
evidence_required:
  - proof
Y
    if [ $# -gt 0 ]; then printf 'depends_on:\n'; for d in "$@"; do printf -- '  - %s\n' "$d"; done; fi
  } > ".ai/repo/project/milestones/$id.yaml"
}
readme() { # write a README with the given version rows
  { printf '# Fixture\n\n## Roadmap\n\n| version | adds |\n|---|---|\n'
    for v in "$@"; do printf '| %s | something |\n' "$v"; done
    printf '\n## Contributing\n\nRead it, and AGENTS.md.\n'
  } > README.md
}

rm_milestone alpha 0.1 10
rm_milestone beta  0.2 20 alpha
expect_exit 0 "$MJ" plan validate

# --- a table that matches the model in both directions is allowed
readme 0.1 0.2
expect_exit 0 "$MJ" doctor
expect_grep 'OK   roadmap'

# --- a document that invents a release the model does not declare
readme 0.1 0.2 2.0
expect_exit 10 "$MJ" doctor
expect_grep 'FAIL roadmap'
expect_grep 'lists version\(s\) no milestone declares: 2.0'
# and watch reports the same thing as drift rather than passing it
expect_exit 11 "$MJ" watch

# --- a document that hides a release the model does declare
readme 0.1
expect_exit 10 "$MJ" doctor
expect_grep 'omits milestone version\(s\) the model declares: 0.2'

# --- adding a milestone makes a previously honest table dishonest, with the table untouched
readme 0.1 0.2
expect_exit 0 "$MJ" doctor
rm_milestone gamma 0.3 30 beta
expect_exit 10 "$MJ" doctor
expect_grep 'omits milestone version\(s\) the model declares: 0.3'

# --- a roadmap section that lists no versions is prose pointing at the projection, not a
#     second authority. This is the intended end state once the table is replaced by a link.
{ printf '# Fixture\n\n## Roadmap\n\nThe roadmap is not written here; run `majordomus plan roadmap`.\n\n'
  printf '## Contributing\n\nRead it, and AGENTS.md.\n'; } > README.md
expect_exit 0 "$MJ" doctor
expect_grep 'lists no versions'

# --- with no roadmap section the check holds trivially: the doctrine refuses the
#     regression, it does not require the table
printf '# Fixture\n\nNo roadmap here. See AGENTS.md.\n' > README.md
expect_exit 0 "$MJ" doctor
expect_grep 'no authored roadmap section'

# --- the doctrine is declared, dispatched, and names a claim that exists
"$MJ" doctrine list | grep -q '^majordomus.roadmap-integrity ' || { echo "    majordomus.roadmap-integrity is not in the registry"; exit 1; }
"$MJ" doctrine list | grep -qE '^majordomus.roadmap-integrity +blocking' || { echo "    majordomus.roadmap-integrity is not blocking"; exit 1; }
grep -q '^  - id: roadmap-derived$' "$ROOT/docs/CLAIMS.yaml" || { echo "    the claim it names is not in CLAIMS.yaml"; exit 1; }
[ -f "$ROOT/docs/claims/roadmap-derived.md" ] || { echo "    the claim has no detail page"; exit 1; }