docs(checks): add structure pin harness
Fails closed until ownership, calendar home, UX demotion, TEST-SPEC honesty, and Gate A lock phrases hold. Reviewers re-run docs/checks/check-structure.sh.
This commit is contained in:
Executable
+95
@@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Structure pin for docs/structure-pass. Exit 0 only when ownership, calendar home,
|
||||||
|
# UX demotion, TEST-SPEC honesty, and Gate A lock phrases all hold.
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
fail=0
|
||||||
|
|
||||||
|
ok() { printf 'OK %s\n' "$1"; }
|
||||||
|
bad() { printf 'FAIL %s\n' "$1"; fail=1; }
|
||||||
|
|
||||||
|
# Ownership table only (AGENTS §0), not casual mentions elsewhere.
|
||||||
|
ownership_block=$(awk '/^## 0\. Where each doc lives$/,/^## /{if(/^## 0/) next; if(/^## / && !/^## 0/) exit; print}' AGENTS.md)
|
||||||
|
# Include through end of table: stop at next ## that is not 0
|
||||||
|
ownership_block=$(awk '
|
||||||
|
/^## 0\. Where each doc lives$/ {p=1; next}
|
||||||
|
/^## / && p {exit}
|
||||||
|
p {print}
|
||||||
|
' AGENTS.md)
|
||||||
|
|
||||||
|
for doc in 'docs/UX-DESIGN.md' 'deploy/INVENTORY.md' 'docs/TEST-SPEC.md'; do
|
||||||
|
if printf '%s\n' "$ownership_block" | grep -Fq "\`$doc\`"; then
|
||||||
|
ok "AGENTS §0 lists $doc"
|
||||||
|
else
|
||||||
|
bad "AGENTS §0 ownership missing $doc"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if grep -Eqi 'non-normative|not normative' docs/UX-DESIGN.md \
|
||||||
|
&& grep -Eq 'UX\.md' docs/UX-DESIGN.md; then
|
||||||
|
ok "UX-DESIGN demoted to non-normative and points at UX.md"
|
||||||
|
else
|
||||||
|
bad "UX-DESIGN header must say non-normative and point at UX.md"
|
||||||
|
fi
|
||||||
|
if grep -Eqi 'phone and PC|signed UX' docs/UX-DESIGN.md; then
|
||||||
|
ok "UX-DESIGN defers to phone+PC / signed UX"
|
||||||
|
else
|
||||||
|
bad "UX-DESIGN must defer to phone+PC matrix / signed UX.md"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eq 'Gate A.*Docs freeze|Docs freeze' docs/IMPL-PLAN.md \
|
||||||
|
&& grep -Eq 'Gate B' docs/IMPL-PLAN.md \
|
||||||
|
&& grep -Eq 'Gate C' docs/IMPL-PLAN.md; then
|
||||||
|
ok "IMPL-PLAN owns Gates meanings"
|
||||||
|
else
|
||||||
|
bad "IMPL-PLAN must contain Gates A/B/C meanings"
|
||||||
|
fi
|
||||||
|
|
||||||
|
agents_gate_rows=$(grep -cE '^\| Gate [ABC] \|' AGENTS.md || true)
|
||||||
|
if [[ "$agents_gate_rows" -eq 0 ]]; then
|
||||||
|
ok "AGENTS has no Gates meanings table rows"
|
||||||
|
else
|
||||||
|
bad "AGENTS still has $agents_gate_rows Gates table rows; move meanings to IMPL-PLAN"
|
||||||
|
fi
|
||||||
|
if grep -Fq 'docs/IMPL-PLAN.md' AGENTS.md; then
|
||||||
|
ok "AGENTS points at IMPL-PLAN for phase/gate depth"
|
||||||
|
else
|
||||||
|
bad "AGENTS must point at docs/IMPL-PLAN.md for gate/phase depth"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eqi 'not (yet )?on (this branch|main)|Phase 0 deliverable|when (the )?code lands|targets until|do not (exist|treat).*(present|checked.in)' docs/TEST-SPEC.md; then
|
||||||
|
ok "TEST-SPEC states harness paths are targets until code lands"
|
||||||
|
else
|
||||||
|
bad "TEST-SPEC §2 must say frontend/e2e and backend/tests are targets until code exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -Eqi 'Phase 0 deliverable|not (yet )?in (the )?tree|aspirational|scaffold target' deploy/docker-compose.yml docs/DEPLOYMENT.md; then
|
||||||
|
ok "deploy docs label missing tree paths as Phase 0 targets"
|
||||||
|
else
|
||||||
|
bad "compose or DEPLOYMENT must label frontend/backend Dockerfiles as Phase 0 targets"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r phrase; do
|
||||||
|
[[ -z "$phrase" ]] && continue
|
||||||
|
if grep -Fq "$phrase" AGENTS.md; then
|
||||||
|
ok "lock phrase present: $phrase"
|
||||||
|
else
|
||||||
|
bad "missing lock phrase in AGENTS.md: $phrase"
|
||||||
|
fi
|
||||||
|
done <<'LOCKS'
|
||||||
|
bdft = sqft × thickness_in
|
||||||
|
SLAB-UAT-*
|
||||||
|
WOO_BASE_URL
|
||||||
|
https://
|
||||||
|
authoritative for math
|
||||||
|
Confidence 0.7
|
||||||
|
draft → calibrated → ready → publishing → published
|
||||||
|
LOCKS
|
||||||
|
|
||||||
|
if [[ "$fail" -ne 0 ]]; then
|
||||||
|
printf '\ncheck-structure: FAILED\n'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
printf '\ncheck-structure: PASSED\n'
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user