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/32_schema_integrity.sh
An object of kind test
What it is
- URI
majordomus://test/test/cases/32_schema_integrity.sh- Kind
test- Identity
test/cases/32_schema_integrity.sh- Path
test/cases/32_schema_integrity.sh- Provenance
- declared
- Media type
text/plain- As a capability
- test.test/cases/32_schema_integrity.sh
Front matter
{}Content
# majordomus-covers: none
# majordomus-negative: doctor
# Schema integrity: the rules resolve in one stated order, every kind that carries metadata
# declares a schema, and every schema is applied by something.
#
# The point of this case is the pair. Checking only that kinds have schemas leaves a schema
# file nothing applies — it describes nothing, is enforced nowhere, and drifts away from the
# shape it was written for with nothing to notice. Checking only that schemas are named
# leaves a kind carrying its front matter through unvalidated, which looks exactly like a
# kind that validates. Both directions are provoked below, one at a time, because a check
# that passes because the other one failed proves nothing.
. "$ROOT/test/lib.sh"
"$MJ" init >/dev/null; "$MJ" update >/dev/null
mkdir -p lib && echo a > lib/a && git add . && git commit -qm base
# The repository under test uses the distribution beside the tool, so the fixtures below are
# a copy of it: a case may not edit the tree it is run from.
share="$T/share"
cp -R "$ROOT/share" "$share"
export MAJORDOMUS_SHARE="$share"
# A fresh repository is not green — it has no use cases, no project model and no skills, and
# says so. So every restore below is checked by the finding this rule owns, not by doctor's
# exit code, which would be asserting other rules' business.
schema_ok() {
"$MJ" doctor > "$T/ok" 2>&1 || true
grep -qE 'OK +schema +share/kinds.yaml' "$T/ok" && grep -qE 'OK +schema +share/schemas' "$T/ok" && return 0
echo " the schema findings are not clean after restoring the tree"
grep -iE ' schema ' "$T/ok" | sed 's/^/ | /'
exit 1
}
# ---------------------------------------------------------------- the healthy tree
"$MJ" doctor > "$T/out" 2>&1 || true
grep -qF 'resolve in one order' "$T/out" \
|| { echo " doctor does not report the order the rules resolve in"; grep -i schema "$T/out" | sed 's/^/ | /'; exit 1; }
grep -qE 'OK +schema +share/kinds.yaml' "$T/out" \
|| { echo " a tree whose kinds all declare a schema is not reported as one"; grep -i schema "$T/out" | sed 's/^/ | /'; exit 1; }
grep -qE 'OK +schema +share/schemas' "$T/out" \
|| { echo " a tree whose schemas are all applied is not reported as one"; grep -i schema "$T/out" | sed 's/^/ | /'; exit 1; }
# ---------------------------------------------------------------- a kind with no schema
# The front matter of a kind without one is carried through unvalidated, silently. That is
# the failure this half exists for, so it must be loud.
cp "$share/kinds.yaml" "$T/kinds.keep"
awk '/^ prompt:/ { p = 1 } p && /^ schema: majordomus\.prompt\/v1$/ { next } { print }' "$T/kinds.keep" > "$share/kinds.yaml"
expect_exit 10 "$MJ" doctor
expect_grep 'declare no schema'
expect_grep 'prompt'
cp "$T/kinds.keep" "$share/kinds.yaml"
schema_ok
# ---------------------------------------------------------------- a schema nothing applies
# The other direction: a file that describes something no kind reads and no allow-list is
# read for. It is not an error in any single object, which is exactly why nothing else
# catches it.
#
# The fixture sits where the real schemas sit — two directories down, because the identifier
# `majordomus.nothing/v1` fixes the path — and that placement is the assertion. This case
# used to drop the file directly in share/schemas/, the one depth the check's glob could
# reach, so it went on passing while the check examined none of the schemas actually shipped.
mkdir -p "$share/schemas/majordomus/nothing"
printf '{"$schema":"https://json-schema.org/draft/2020-12/schema","title":"Nothing","type":"object"}\n' \
> "$share/schemas/majordomus/nothing/nothing.v1.schema.json"
expect_exit 10 "$MJ" doctor
expect_grep 'applied by nothing'
expect_grep 'nothing'
rm -rf "$share/schemas/majordomus/nothing"
schema_ok
# ...and a schema applied through its allow-list rather than by a kind still counts, which is
# how the local half of the layer — not indexed, so no kind can name it — is covered at all.
schema_ok # an allow-list-applied schema is not an orphan
for n in current session; do
[ -f "$share/allow/$n.txt" ] || { echo " share/allow/$n.txt is absent; the schema reaches nothing"; exit 1; }
grep -rqE "(ALLOW_DIR|share/allow)/$n\.txt" "$ROOT/lib" \
|| { echo " nothing reads share/allow/$n.txt, so $n.schema.json applies to nothing"; exit 1; }
done
# ---------------------------------------------------------------- a schema that is not JSON
mkdir -p "$share/schemas/majordomus/broken"
printf 'not json at all\n' > "$share/schemas/majordomus/broken/broken.v1.schema.json"
expect_exit 10 "$MJ" doctor
expect_grep 'do not parse as JSON'
rm -rf "$share/schemas/majordomus/broken"
schema_ok
# ---------------------------------------------------------------- the order is total
# A set that does not resolve has no order, so nothing can be dispatched over it. The refusal
# comes from the doctrine loader before any validator runs, and it names the dependency that
# is missing rather than reporting a count over a set it could not build. Asserted here
# because it is what makes the order a contract and not a best effort.
mkdir -p .ai/repo/rules/project
cat > .ai/repo/rules/project/dangling.v1.md <<'RULE'
---
id: project.dangling
version: 1
kind: rule
title: A rule that depends on one nobody wrote
description: Exists only to prove that an unresolvable set is reported as one.
statement: This rule cannot resolve, because the rule it depends on does not exist.
status: active
class: advisory
depends_on: [majordomus.no-such-rule@1]
---
# Rationale
Provoked by the schema-integrity case.
RULE
"$MJ" doctor > "$T/unresolved" 2>&1 || true
grep -qF 'the rules do not resolve, so nothing can be enforced' "$T/unresolved" \
|| { echo " an unresolvable rule set was not refused"; tail -n 3 "$T/unresolved" | sed 's/^/ | /'; exit 1; }
grep -qF 'majordomus.no-such-rule@1' "$T/unresolved" \
|| { echo " the refusal does not name the dependency that is missing"; tail -n 3 "$T/unresolved" | sed 's/^/ | /'; exit 1; }
expect_no_grep 'OK +schema' "$T/unresolved" # nothing was dispatched, so nothing reported
rm -f .ai/repo/rules/project/dangling.v1.md
schema_ok