docs(requirements): draft reconciled requirement set (128 rows, 8 namespaces)

Reconciles the scattered requirements onto the owner-job namespaces.

- docs/REQUIREMENTS.md: 128 requirements across CAPTURE, METADATA, REVIEW,
  PUBLISH, SETTINGS, APP, OPS, QUALITY
- docs/STRUCTURE.md: Test may be a path, a requirement ID, or - ;
  a shipped path must exist
- tools/check_requirements.py: resolve test refs accordingly
- .audit/2026-09-18-reconciliation-decisions.md: full decision record plus
  18 deferred rulings for the final cleanup pass

Gate: python tools/check_requirements.py -> PASS
This commit is contained in:
2026-09-18 10:38:30 -07:00
parent b42e3cb8ce
commit 238fcc4f15
4 changed files with 351 additions and 17 deletions
+15 -5
View File
@@ -73,6 +73,7 @@ def main() -> int:
# 3-5. requirement rows
ids: dict[str, str] = {}
test_refs: list[tuple[str, str, str, str]] = []
if not REQUIREMENTS.exists():
errors.append("docs/REQUIREMENTS.md is missing")
else:
@@ -93,11 +94,20 @@ def main() -> int:
ids[rid] = loc
if scope not in SCOPES:
errors.append(f"{loc} {rid} invalid scope '{scope}'")
if scope in {"shipped", "M3"}:
if test.strip() in PLACEHOLDER:
errors.append(f"{loc} {rid} scope {scope} needs a Test path")
elif not (ROOT / test.strip()).exists():
errors.append(f"{loc} {rid} test path not found: {test.strip()}")
test_ref = test.strip()
if test_ref not in PLACEHOLDER:
test_refs.append((loc, rid, test_ref, scope))
# 5. resolve test references: an existing path, a requirement ID, or —
for loc, rid, ref, scope in test_refs:
if ID_TOKEN.match(ref):
if ref not in ids:
errors.append(f"{loc} {rid} test ref {ref} is not a defined requirement")
elif "/" in ref or "\\" in ref or "." in ref:
if scope == "shipped" and not (ROOT / ref).exists():
errors.append(f"{loc} {rid} shipped test path not found: {ref}")
else:
errors.append(f"{loc} {rid} invalid Test ref '{ref}' (use a path, an ID, or —)")
# 6. requirement rows appear only in REQUIREMENTS.md
for path in sorted(DOCS.rglob("*.md")):