Skip to content

Commit 5fa7a83

Browse files
Estate audit & optimization — Wave 0: kill the false green (holes before goals) (#453)
## Context This is the first wave of a meticulous, estate-wide **must / should / could / systems / compliance / effects** audit-and-uplift program anchored in `standards` (the ~290-repo control plane). A 7-agent read-only recon found the core problem: the *declarations* are rich but the *enforcement is largely theatre* — validators pass vacuously, mandatory-check runners aren't wired, and there's no post-action check on agent claims. Per estate doctrine (`RSR-PHILOSOPHY.adoc`) the program is ordered **holes before goals**, **solutions at source**, **always fail loudly**. This PR is the branch trunk; subsequent waves land as further commits. ## Wave 0 — Kill the false green (this commit) Every validator that reported success while checking nothing, or masked real errors behind `|| true`, is now state-aware and **provably able to fail**, each backed by a red-team regression fixture. | Fix | File | Hole closed | |---|---|---| | State-aware 6scm check | `a2ml/scripts/check-6scm.sh` | Exited 0 vacuously once `.scm` sources migrated to 6a2; now fails on orphan-mirror drift / out-of-sync, and declares itself retired (not "in sync") when obsolete | | Real Mustfile validation | `.github/workflows/boj-build.yml` + `scripts/check-mustfile-structure.sh` | Replaced `echo "K9 validation would run here"` with a real structural check — every Mustfile check must carry a severity + a means of discharge (`- run:` or `- verification:`); hollow checks fail loudly | | Arg parsing (#387) | `rhodium-standard-repositories/rsr-audit.sh` | Documented `--format json` silently didn't work; invalid format now exits 4 instead of defaulting to text; bare-positional form kept for back-compat | | De-mask `\|\| true` | `Justfile` `validate` + `scripts/rsr-selfaudit.sh` | A broken audit (exit 4) was swallowed as green; now a low grade is informational/non-blocking but an audit *error* fails loudly. `registry-check` stays the hard gate | | De-hardcode paths | `audit-contractiles.sh` | Removed `/var/mnt/eclipse/...` owner-machine paths (couldn't run in CI); takes args/`$CONTRACTILE_AUDIT_REPOS`, never audits zero repos | ## Verification - `scripts/tests/wave0-false-green-test.sh` — **13/13**, exercising the pass *and* fail path of every fixed validator (`just false-green-test`). - Existing `check-workflow-staleness-test.sh` still passes; `boj-build.yml` validates as YAML; all changed scripts pass `bash -n`. - The real Mustfile passes structural validation (17 checks); a hollow check fails; `rsr-audit --format json` emits JSON; an errored audit fails `validate`. ## Not touched (by policy / scope) - **Licence/SPDX** — flag-only throughout; no header edits. - **`continue-on-error` soft-gates** — left in place (documented, with real blocking equivalents elsewhere); honest-labelling / promotion is a Wave 1 item, not a blanket removal that would manufacture red noise. ## Coming in later waves (same branch) Wave 1 (wire the automation that never runs), Wave 3 (MUST/SHOULD/COULD scorecards + compliance dashboard), Wave 4 (the `did-you-actually-do-that` post-action claim-verifier spec — the missing LLM-regulation tier), Wave 5 (AffineScript testing standard + template), Wave 6 (campaign issues cross-linking #426/#451/#437/#381/#387/#446, release hygiene). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- _Generated by [Claude Code](https://claude.ai/code/session_0114ps6mY5jAH4SzbGxeuYjc)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 6df21b1 commit 5fa7a83

14 files changed

Lines changed: 538 additions & 36 deletions

File tree

.github/workflows/boj-build.yml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,22 @@ jobs:
6666

6767
- name: K9-SVC Validation
6868
run: |
69+
set -euo pipefail
6970
echo "Running K9-SVC contractile validation..."
70-
if [ -f .machine_readable/contractiles/must/Mustfile.a2ml ]; then
71-
echo "✅ Mustfile found - running validation"
72-
# Placeholder for actual K9 validation
73-
echo "K9 validation would run here"
74-
else
75-
echo "❌ Mustfile not found"
76-
exit 1
77-
fi
71+
# Real structural validation (no placeholder): every Mustfile check
72+
# must carry a severity and a means of discharge (run or verification).
73+
# A hollow check fails loudly. See scripts/check-mustfile-structure.sh
74+
# (unit-tested by scripts/tests/wave0-false-green-test.sh).
75+
bash scripts/check-mustfile-structure.sh
76+
77+
- name: Mustfile Enforcement (execute the checks)
78+
run: |
79+
set -euo pipefail
80+
# Execute the Mustfile's `- run:` invariants — the mandatory checks
81+
# that were previously declared but never run by any CI job. A failing
82+
# critical/high check fails the build (fail loudly); warning-severity
83+
# failures are reported but non-blocking. See scripts/run-mustfile.sh.
84+
bash scripts/run-mustfile.sh
7885
7986
- name: Contractile Check
8087
run: |

.github/workflows/hypatia-scan-reusable.yml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,20 @@ jobs:
132132
panic-attack-findings.json
133133
retention-days: 90
134134

135-
- name: Check for critical issues
135+
- name: Check for critical issues (ADVISORY — does not gate)
136136
if: steps.scan.outputs.critical > 0
137137
run: |
138-
echo "Critical issues found!"
139-
echo "Review hypatia-findings.json for details."
140-
# Warn but don't fail — fix forward
138+
# This scan is ADVISORY / fix-forward: it never fails the build. The
139+
# label and summary state that explicitly so a green check carrying
140+
# critical findings is not mistaken for "no critical findings".
141+
# (Promotion to blocking is tracked with the baseline reconciliation,
142+
# standards#399/#437.)
143+
echo "::warning title=Hypatia (ADVISORY, non-blocking)::${{ steps.scan.outputs.critical }} critical finding(s). This scan does not gate — review hypatia-findings.json and fix forward."
144+
{
145+
echo "### Hypatia scan — ADVISORY (does not gate)"
146+
echo ""
147+
echo "**${{ steps.scan.outputs.critical }} critical finding(s)** reported."
148+
echo "This scan is fix-forward and **never fails the build**; a green"
149+
echo "check here does not mean zero critical findings. See the"
150+
echo "\`hypatia-scan-findings\` artifact. Blocking promotion: standards#399/#437."
151+
} >> "$GITHUB_STEP_SUMMARY"

.github/workflows/registry-verify.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,23 @@ jobs:
3131

3232
- name: Verify registry + derived topology are current
3333
run: |
34-
bash scripts/build-registry.sh --check
34+
if ! bash scripts/build-registry.sh --check; then
35+
{
36+
echo "### Registry drift detected"
37+
echo ""
38+
echo "A tracked file under a spec home (or STATE.a2ml) changed without"
39+
echo "regenerating the derived registry/topology. Fix locally:"
40+
echo ""
41+
echo '```sh'
42+
echo "just registry # or: bash scripts/build-registry.sh"
43+
echo "git add .machine_readable/REGISTRY.a2ml TOPOLOGY.md"
44+
echo '```'
45+
echo ""
46+
echo "Install the pre-commit guard so this is caught before push:"
47+
echo ""
48+
echo '```sh'
49+
echo "just hooks-install"
50+
echo '```'
51+
} >> "$GITHUB_STEP_SUMMARY"
52+
exit 1
53+
fi

.machine_readable/REGISTRY.a2ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ name = "A2ML — Attested Markup Language"
3636
stream = "foundation"
3737
home = "a2ml/"
3838
canonical_doc = "a2ml/README.adoc"
39-
source_hash = "sha256:5f070c778ad112229878e2d551b564e2ec885d2239c6f348c0a96b700091d84a"
39+
source_hash = "sha256:9ed18e704be7f0f8f991edf9dcced013691e8b62c8d7cd5a27a3d7a91c0f27dd"
4040
route = "the typed/verified machine-readable document format"
4141

4242
[[spec]]
@@ -45,7 +45,7 @@ name = "K9 Self-Validating Components"
4545
stream = "foundation"
4646
home = "k9-svc/"
4747
canonical_doc = "k9-svc/README.adoc"
48-
source_hash = "sha256:2fa2fe6394de60ac7da8672dcfeb21aa65919a7df83e8cf9ee9b82b2260ab0a8"
48+
source_hash = "sha256:cf2afa97e93597731bdb18f8c56beba3fd553c77e19c02ad9515a919cc4bec00"
4949
route = "self-validating components with embedded contracts + deploy logic"
5050

5151
[[spec]]
@@ -216,7 +216,7 @@ name = "RSR — Rhodium Standard Repositories"
216216
stream = "governance"
217217
home = "rhodium-standard-repositories/"
218218
canonical_doc = "rhodium-standard-repositories/README.adoc"
219-
source_hash = "sha256:01e6373ae01939b5ed24c72e1c4ace7ea55559b3fc765a956bc2e7ad722b244b"
219+
source_hash = "sha256:3e721ecb348d176a2e1ba82bb6ea6b9365e8375c4ca80f1f3f4c9e9e343269f8"
220220
route = "the repository-compliance standard every repo is graded against"
221221

222222
[[spec]]

Justfile

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,35 @@ staleness-test:
4141
@echo "=== propagate-workflow-pins ==="
4242
@bash scripts/tests/propagate-workflow-pins-test.sh
4343

44-
# Aggregate compliance gate: registry drift (hard dep) + RSR self-audit (informational)
44+
# Wave-0 anti-false-green regression: proves each fixed validator CAN fail
45+
false-green-test:
46+
@bash scripts/tests/wave0-false-green-test.sh
47+
48+
# Wave-1 automation regression: Mustfile runner + hook installer
49+
automation-test:
50+
@bash scripts/tests/wave1-automation-test.sh
51+
52+
# Structural validation of the Mustfile contract (severity + run/verification per check)
53+
mustfile-check path=".machine_readable/contractiles/must/Mustfile.a2ml":
54+
@bash scripts/check-mustfile-structure.sh "{{path}}"
55+
56+
# Execute the Mustfile's `- run:` checks (critical/high failures block)
57+
must-check path=".machine_readable/contractiles/must/Mustfile.a2ml":
58+
@bash scripts/run-mustfile.sh "{{path}}"
59+
60+
# Install this repo's git hooks into .git/hooks/ (pre-commit guards)
61+
hooks-install:
62+
@bash hooks/install.sh
63+
64+
# Aggregate compliance gate: registry drift is the HARD gate (registry-check,
65+
# a hard dep). The RSR self-audit is INFORMATIONAL — a monorepo is not expected
66+
# to score Gold — but a *broken* audit (exit 4 / unexpected) must fail loudly
67+
# rather than pass silently under a blanket `|| true` (Wave-0 false-green fix).
4568
validate: registry-check
46-
@echo "=== validate: RSR compliance gate ==="
47-
@bash rhodium-standard-repositories/rsr-audit.sh . text || true
48-
@echo "=== validate: done (see rsr-audit output above) ==="
69+
@echo "=== validate: registry drift (HARD GATE) — passed as a dependency above ==="
70+
@echo "=== validate: RSR self-audit (INFORMATIONAL grade; errors fail loudly) ==="
71+
@bash scripts/rsr-selfaudit.sh .
72+
@echo "=== validate: done ==="
4973

5074
# Print role-appropriate LLM warm-up context (machine front door)
5175
llm-context role="dev":
@@ -127,6 +151,10 @@ doctor:
127151
@command -v git >/dev/null 2>&1 && echo " [OK] git" || echo " [FAIL] git not found"
128152
@echo "Checking for hardcoded paths..."
129153
@grep -rn '$HOME\|$ECLIPSE_DIR' --include='*.rs' --include='*.ex' --include='*.res' --include='*.gleam' --include='*.sh' . 2>/dev/null | head -5 || echo " [OK] No hardcoded paths"
154+
@echo "Checking optional imports (import? does not fail when absent — report it)..."
155+
@test -f contractile.just && echo " [OK] contractile.just present (import resolved)" || echo " [INFO] contractile.just absent — its recipes are unavailable (needs the external 'contractile' generator)"
156+
@echo "Checking git hooks are installed..."
157+
@test -f "$(git rev-parse --git-dir)/hooks/pre-commit" && echo " [OK] pre-commit hook installed" || echo " [INFO] pre-commit hook not installed — run 'just hooks-install'"
130158
@echo "Diagnostics complete."
131159

132160
# Auto-repair common issues

a2ml/scripts/check-6scm.sh

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,57 @@
11
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
#
4+
# check-6scm.sh — verify the .machine_readable/6scm/ mirror is honest.
5+
#
6+
# The 6scm mirror duplicated the legacy Scheme (.scm) descriptor set into
7+
# .machine_readable/6scm/ so tools that only read Scheme had a copy. That
8+
# metadata has migrated to .machine_readable/6a2/ (A2ML / descriptiles), so
9+
# for most repos there are no .scm sources left to mirror.
10+
#
11+
# A validator that validates nothing must not report success. This script
12+
# therefore distinguishes three states LOUDLY (never a silent green):
13+
#
14+
# 1. Sources present -> real diff check; fail on missing/out-of-sync mirror.
15+
# 2. No sources, no mirror -> OBSOLETE no-op: exit 0 with an explicit
16+
# "retired" message (it does NOT claim "in sync").
17+
# 3. No sources, but an orphaned mirror with files -> DRIFT: fail loudly.
18+
#
19+
# See CANONICAL-NAMES.adoc (6a2/descriptiles supersedes the legacy set) and
20+
# standards Wave-0 "kill the false green" remediation.
21+
222
set -euo pipefail
323

24+
SCM_NAMES=(AGENTIC.scm ECOSYSTEM.scm META.scm NEUROSYM.scm PLAYBOOK.scm STATE.scm)
25+
MIRROR_DIR=".machine_readable/6scm"
26+
27+
# Collect the sources that actually exist.
28+
sources=()
29+
for f in "${SCM_NAMES[@]}"; do
30+
[ -f ".machine_readable/$f" ] && sources+=("$f")
31+
done
32+
33+
# State 2/3: no sources to mirror — the mechanism is obsolete for this repo.
34+
if [ "${#sources[@]}" -eq 0 ]; then
35+
orphans=0
36+
if [ -d "$MIRROR_DIR" ]; then
37+
while IFS= read -r _; do orphans=$((orphans + 1)); done \
38+
< <(find "$MIRROR_DIR" -type f 2>/dev/null)
39+
fi
40+
if [ "$orphans" -gt 0 ]; then
41+
echo "DRIFT: $MIRROR_DIR holds $orphans mirror file(s) but no .scm sources exist." >&2
42+
echo " The 6scm mirror is obsolete (metadata migrated to .machine_readable/6a2/)." >&2
43+
echo " Remove $MIRROR_DIR and retire the sync-6scm/check-6scm recipes." >&2
44+
exit 1
45+
fi
46+
echo "OBSOLETE (no-op): no .scm sources; 6scm mirror retired (superseded by 6a2/descriptiles). Nothing to mirror."
47+
exit 0
48+
fi
49+
50+
# State 1: sources exist — the mirror must be present and byte-identical.
451
missing=0
5-
for f in AGENTIC.scm ECOSYSTEM.scm META.scm NEUROSYM.scm PLAYBOOK.scm STATE.scm; do
52+
for f in "${sources[@]}"; do
653
src=".machine_readable/$f"
7-
dst=".machine_readable/6scm/$f"
8-
if [ ! -f "$src" ]; then
9-
continue
10-
fi
54+
dst="$MIRROR_DIR/$f"
1155
if [ ! -f "$dst" ]; then
1256
echo "Missing mirror: $dst" >&2
1357
missing=1
@@ -19,4 +63,7 @@ for f in AGENTIC.scm ECOSYSTEM.scm META.scm NEUROSYM.scm PLAYBOOK.scm STATE.scm;
1963
fi
2064
done
2165

66+
if [ "$missing" -eq 0 ]; then
67+
echo "6scm mirror in sync (${#sources[@]} source(s) verified)."
68+
fi
2269
exit $missing

audit-contractiles.sh

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,28 @@ set -euo pipefail
88
echo "═══════════════════════════════════════════════════════════════════════════════"
99
echo " Hyperpolymath Contractile System Audit"
1010
echo " $(date '+%Y-%m-%d %H:%M:%S')"
11-
echo "════╕══════════════════════════════════════════════════════════════════════════════"
11+
echo "═══════════════════════════════════════════════════════════════════════════════"
1212
echo ""
1313

14-
# Repositories to audit
15-
REPOS=(
16-
"/var/mnt/eclipse/repos/burble"
17-
"/var/mnt/eclipse/repos/panll"
18-
"/var/mnt/eclipse/repos/nextgen-databases"
19-
"/var/mnt/eclipse/repos/rescript"
20-
"/var/mnt/eclipse/repos/standards"
21-
)
14+
# Repositories to audit.
15+
# Previously these were hardcoded to the owner's machine (/var/mnt/eclipse/...),
16+
# so the script could not run in CI or on any other host (Wave-0 fix). Supply
17+
# repos explicitly as positional args, or via $CONTRACTILE_AUDIT_REPOS
18+
# (colon-separated). With neither set, default to auditing THIS repo so a bare
19+
# invocation is still useful — and never silently audit zero repos.
20+
if [ "$#" -gt 0 ]; then
21+
REPOS=("$@")
22+
elif [ -n "${CONTRACTILE_AUDIT_REPOS:-}" ]; then
23+
IFS=':' read -r -a REPOS <<< "$CONTRACTILE_AUDIT_REPOS"
24+
else
25+
SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
26+
REPOS=("$SELF_DIR")
27+
fi
28+
29+
if [ "${#REPOS[@]}" -eq 0 ]; then
30+
echo "error: no repositories to audit (pass paths as args or set CONTRACTILE_AUDIT_REPOS)" >&2
31+
exit 2
32+
fi
2233

2334
# Contractile types to check
2435
# `lust` deprecated 2026-04-18 — wishes absorbed into intend/Intentfile.a2ml

hooks/install.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env bash
2+
# SPDX-License-Identifier: MPL-2.0
3+
#
4+
# install.sh — install this repo's git hooks into .git/hooks/.
5+
#
6+
# The hooks in hooks/ (pre-commit language-policy + registry-drift guard, SPDX,
7+
# SHA-pin and permission validators) only run if they are present in
8+
# .git/hooks/. Nothing installed them automatically, so their guards were
9+
# effectively optional (a contributor had to know to `cp` them). This installer
10+
# wires them once. Idempotent; safe to re-run.
11+
#
12+
# Usage: bash hooks/install.sh (install / refresh)
13+
# just hooks-install (same, via recipe)
14+
#
15+
# It installs a thin .git/hooks/pre-commit that execs hooks/pre-commit from the
16+
# work tree, so the tracked hook stays the single source of truth and updates
17+
# take effect without re-installing.
18+
19+
set -euo pipefail
20+
21+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
22+
GITDIR="$(git -C "$ROOT" rev-parse --git-dir 2>/dev/null || true)"
23+
if [ -z "$GITDIR" ]; then
24+
echo "error: not a git repository: $ROOT" >&2
25+
exit 1
26+
fi
27+
# Normalise to an absolute path (git-dir may be relative to ROOT).
28+
case "$GITDIR" in
29+
/*) : ;;
30+
*) GITDIR="$ROOT/$GITDIR" ;;
31+
esac
32+
33+
HOOKDIR="$GITDIR/hooks"
34+
mkdir -p "$HOOKDIR"
35+
36+
installed=0
37+
for src in "$ROOT"/hooks/pre-commit; do
38+
[ -f "$src" ] || continue
39+
name="$(basename "$src")"
40+
dst="$HOOKDIR/$name"
41+
cat > "$dst" <<EOF
42+
#!/usr/bin/env bash
43+
# SPDX-License-Identifier: MPL-2.0
44+
# Auto-installed by hooks/install.sh — execs the tracked hook so the work-tree
45+
# copy stays the single source of truth. Do not edit; edit hooks/$name instead.
46+
exec "\$(git rev-parse --show-toplevel)/hooks/$name" "\$@"
47+
EOF
48+
chmod +x "$dst"
49+
echo "installed: $dst -> hooks/$name"
50+
installed=$((installed + 1))
51+
done
52+
53+
if [ "$installed" -eq 0 ]; then
54+
echo "error: no hooks found to install under $ROOT/hooks/" >&2
55+
exit 1
56+
fi
57+
echo "$installed hook(s) installed into $HOOKDIR"

rhodium-standard-repositories/rsr-audit.sh

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,34 @@ RSR_FREEZE_DATE="2025-12-27"
3030
# Configuration
3131
# =============================================================================
3232

33-
REPO_PATH="${1:-.}"
34-
OUTPUT_FORMAT="${2:-text}"
33+
# Argument parsing (standards#387).
34+
# Historically the second positional arg was read verbatim as the format, so the
35+
# DOCUMENTED `--format json` form silently fell through to the text default while
36+
# only the bare positional `text|json|html` worked. Accept both now, and reject
37+
# an unknown format loudly (exit 4) instead of silently defaulting.
38+
REPO_PATH="."
39+
OUTPUT_FORMAT="text"
40+
_repo_seen=0
41+
while [[ $# -gt 0 ]]; do
42+
case "$1" in
43+
--format=*)
44+
OUTPUT_FORMAT="${1#*=}"; shift ;;
45+
--format)
46+
OUTPUT_FORMAT="${2:-}"; shift 2 || { echo "error: --format needs a value" >&2; exit 4; } ;;
47+
text|json|html)
48+
# Backward-compatible bare positional format (e.g. Justfile passes `. text`).
49+
OUTPUT_FORMAT="$1"; shift ;;
50+
-*)
51+
echo "error: unknown option: $1" >&2; exit 4 ;;
52+
*)
53+
if [[ $_repo_seen -eq 0 ]]; then REPO_PATH="$1"; _repo_seen=1; shift
54+
else echo "error: unexpected argument: $1" >&2; exit 4; fi ;;
55+
esac
56+
done
57+
case "$OUTPUT_FORMAT" in
58+
text|json|html) ;;
59+
*) echo "error: invalid --format '$OUTPUT_FORMAT' (want: text|json|html)" >&2; exit 4 ;;
60+
esac
3561
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
3662

3763
# Compliance thresholds

0 commit comments

Comments
 (0)