Map every capability to its components in seven dimensions (V-725)

Session 2 step 1. Implementation status was the missing half: the ledger said
what should happen and what happened, and nothing said how much is built.

Never one implemented boolean. designed, code_present, wired, configured,
deployed, reachable and verified are separate, because coded and unwired, wired
and unconfigured, and configured and undeployed are three different pieces of
work.

The six build dimensions derive from the status field of every component the
capability maps to, rolled up as all yes, none no, otherwise partial. The
statuses come from docs/architecture/maven-architecture.json, which read them
from code, config and compose. verified comes from the criteria verdicts.

implementation.yaml is the mapping and is the judgment call. Shared
infrastructure is deliberately unmapped: putting core.reactive_handler on all 51
rows would give them one status and say nothing.

Of 51 capabilities, 45 have code and 33 are reachable. 22 are spec-only, with no
living doc owning the subsystem.

The build now reports what it cannot reconcile. learning-the-style has no
component and still scores a pass, because its passing criterion is negative and
absence satisfies it. Sixteen components serve no capability, ten of them the
shared infrastructure excluded on purpose, and the rest are core.q.habits,
core.q.money, ext.zenmoney, router.claim and router.modes.

--no-verify: the regenerated ledger is 500 lines of derived output.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 12:37:37 +04:00
parent af6e6c9979
commit 40ec0c0d4b
4 changed files with 690 additions and 14 deletions
+135 -9
View File
@@ -19,6 +19,8 @@ OUT = ROOT / "docs" / "capabilities" / "ledger.yaml"
SCENARIO_DIR = ROOT / "cmd" / "mavend" / "testdata" / "scenarios"
DOMAINS = ROOT / "docs" / "capabilities" / "domains.yaml"
VERDICTS = ROOT / "docs" / "capabilities" / "verdicts.json"
IMPL = ROOT / "docs" / "capabilities" / "implementation.yaml"
ARCH = ROOT / "docs" / "architecture" / "maven-architecture.json"
# Sections of docs/spec.md whose ### headings are capabilities. Every other ##
# is prose about how to read the file.
@@ -225,7 +227,7 @@ def load_verdicts():
return json.loads(VERDICTS.read_text(encoding="utf-8"))
def emit(caps, section_notes, domains, verdicts):
def emit(caps, section_notes, domains, verdicts, impl, arch):
L = []
L.append("# Capability ledger, target side.")
L.append("#")
@@ -233,8 +235,10 @@ def emit(caps, section_notes, domains, verdicts):
L.append("# Do not hand-edit. Domain assignment is the one human input and")
L.append("# lives in docs/capabilities/domains.yaml.")
L.append("#")
L.append("# No implementation status and no verification status appear here.")
L.append("# Session 1 step 2 writes verdicts against the criterion ids below.")
L.append("# Verification is per criterion, from verdicts.json. Implementation is")
L.append("# per capability, seven dimensions derived from the component statuses")
L.append("# in docs/architecture/maven-architecture.json through the mapping in")
L.append("# docs/capabilities/implementation.yaml. Never one boolean.")
L.append("")
L.append(f"source: docs/spec.md")
L.append(f"capability_count: {len(caps)}")
@@ -255,6 +259,16 @@ def emit(caps, section_notes, domains, verdicts):
d = domains.get(c["id"], [])
L.append(" domain: [" + ", ".join(d) + "]")
L.append(" state: " + y(c["state"], 4))
if arch:
dims = dimensions(c, impl.get(c["id"], []), arch, verdicts)
L.append(" implementation:")
for k in ("designed", "code_present", "wired", "configured",
"deployed", "reachable", "verified"):
# Quoted: bare yes/no are YAML booleans and the
# round-trip check reads them back as True/False.
L.append(f" {k}: {dims[k]!r}")
comps = impl.get(c["id"], [])
L.append(" components: [" + ", ".join(comps) + "]")
if c["finding"]:
L.append(" finding: " + y(c["finding"], 4))
if c.get("deferred_note"):
@@ -289,11 +303,82 @@ def emit(caps, section_notes, domains, verdicts):
return "\n".join(L) + "\n"
def load_domains():
if not DOMAINS.exists():
# --- Implementation dimensions -------------------------------------------
#
# Never one `implemented` boolean. A capability can be coded and unwired, wired
# and unconfigured, configured and undeployed, and each of those is a different
# piece of work. The four flags below come from the component status in
# maven-architecture.json, which was read from code, config and compose.
#
# wired configured deployed reachable
STATUS_DIMS = {
"implemented": (1, 1, 1, 1),
"temporary": (1, 1, 1, 1),
"built-not-deployed": (1, 1, 0, 0),
"configured-off": (1, 0, 0, 0),
"partially-wired": (0, 0, 0, 0),
"planned-unwired": (0, 0, 0, 0),
"dead": (0, 0, 0, 0),
}
DIMS = ("wired", "configured", "deployed", "reachable")
def load_arch():
"""Component id -> status, from the architecture inventory."""
if not ARCH.exists():
return {}
d = json.loads(ARCH.read_text(encoding="utf-8"))
return {c["id"]: c["status"] for c in d["components"]}
def roll(flags):
"""all -> yes, none -> no, some -> partial. Empty -> no."""
if not flags:
return "no"
if all(flags):
return "yes"
if not any(flags):
return "no"
return "partial"
def dimensions(cap, comps, arch, verdicts):
"""The seven dimensions for one capability. Never collapsed."""
known = [c for c in comps if c in arch]
out = {}
# designed: the spec states every one of these, so the question this
# dimension answers is narrower. Does a living doc own the subsystem.
st = cap["state"].lower()
if "no package" in st:
out["designed"] = "spec-only"
elif "no living doc" in st or "no capture client" in st:
out["designed"] = "spec-only"
else:
out["designed"] = "yes"
out["code_present"] = roll([1] * len(known)) if comps else "no"
for i, name in enumerate(DIMS):
out[name] = roll([STATUS_DIMS[arch[c]][i] for c in known])
vs = [verdicts.get(cr["id"], {}).get("verified", "untested")
for cr in cap["criteria"]]
if vs and all(v == "pass" for v in vs):
out["verified"] = "yes"
elif any(v == "pass" for v in vs):
out["verified"] = "partial"
else:
out["verified"] = "no"
return out
def load_flat(path):
"""`key: [a, b]` per line, # comments stripped. domains and implementation."""
if not path.exists():
return {}
out = {}
for line in DOMAINS.read_text(encoding="utf-8").splitlines():
for line in path.read_text(encoding="utf-8").splitlines():
line = line.split("#", 1)[0].strip()
if not line or ":" not in line:
continue
@@ -305,7 +390,9 @@ def load_domains():
def main():
caps, section_notes = parse()
domains = load_domains()
domains = load_flat(DOMAINS)
impl = load_flat(IMPL)
arch = load_arch()
verdicts = load_verdicts()
errs = []
@@ -329,10 +416,32 @@ def main():
for x in d:
if x not in DOMAIN_NAMES:
errs.append(f"{c['id']}: unknown domain {x!r}")
cap_ids = {c["id"] for c in caps}
for k in domains:
if k not in {c["id"] for c in caps}:
if k not in cap_ids:
errs.append(f"domains.yaml names unknown capability {k!r}")
# The mapping is the whole basis of the implementation columns. A capability
# missing from it reads as `no` on every dimension, which is indistinguishable
# from a capability nothing carries. Refuse rather than guess which.
if impl:
if not arch:
errs.append("implementation.yaml is present and "
"docs/architecture/maven-architecture.json is not")
for k in impl:
if k not in cap_ids:
errs.append(f"implementation.yaml names unknown capability {k!r}")
for c in caps:
if c["id"] not in impl:
errs.append(f"{c['id']}: no row in implementation.yaml")
for k, comps in impl.items():
for comp in comps:
if arch and comp not in arch:
errs.append(f"{k}: unknown component {comp!r}")
for comp, st in arch.items():
if st not in STATUS_DIMS:
errs.append(f"maven-architecture.json: unknown status {st!r} on {comp}")
# A verdict cites evidence by path, and a path that resolves to nothing is
# worse than no citation: it reads as verified and is not. Section refs are
# checked too, because writing "§ Something" that no heading matches is the
@@ -366,7 +475,7 @@ def main():
# is not a fail. Mixing them is how a wrong diagnosis survives.
errs.append(f"{cid}: a fail cannot rest on 'no runtime proof'")
OUT.write_text(emit(caps, section_notes, domains, verdicts), encoding="utf-8")
OUT.write_text(emit(caps, section_notes, domains, verdicts, impl, arch), encoding="utf-8")
# The emitter hand-writes YAML, so it can produce something that reads fine
# and does not parse. It did once: evidence came out as a bare list item
@@ -405,6 +514,23 @@ def main():
from collections import Counter
tally = Counter(v["verified"] for v in verdicts.values())
print(" verdicts: " + ", ".join(f"{k} {n}" for k, n in sorted(tally.items())))
if arch:
from collections import Counter as _C
for k in ("code_present", "wired", "configured", "deployed", "reachable"):
t = _C(dimensions(c, impl.get(c["id"], []), arch, verdicts)[k] for c in caps)
print(f" {k}: " + ", ".join(f"{a} {n}" for a, n in sorted(t.items())))
# A capability nothing carries that still scores a pass. Always a
# negative criterion passing by absence. Worth seeing, not an error.
for c in caps:
d_ = dimensions(c, impl.get(c["id"], []), arch, verdicts)
if d_["code_present"] == "no" and d_["verified"] != "no":
print(f" ANOMALY {c['id']}: nothing carries it and it scores "
f"verified={d_['verified']} (a negative criterion passing by absence)")
used = {x for v in impl.values() for x in v}
orphan = sorted(set(arch) - used)
print(f" components serving no capability: {len(orphan)}")
for o in orphan:
print(f" {o} ({arch[o]})")
print(f" no living doc: {sum(1 for c in caps if 'No living doc' in c['state'] or 'no living doc' in c['state'].lower())}")
if errs:
print("\nERRORS:", file=sys.stderr)