Skip to content

Commit a8418b8

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/standards-repo-architecture-6j606d
# Conflicts: # .machine_readable/REGISTRY.a2ml
2 parents fff81ff + 79088f0 commit a8418b8

47 files changed

Lines changed: 3745 additions & 44 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.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/governance-reusable.yml

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,52 @@ jobs:
106106
mix deps.get && mix escript.build
107107
fi
108108
109+
# A reusable workflow only auto-checks-out its own YAML, not sibling
110+
# scripts. Sparse-check-out standards' scripts/ to get apply-baseline.sh,
111+
# mirroring the language-policy job below. Pinned to main because
112+
# github.workflow_sha resolves to the *caller* repo's SHA (which would 404).
113+
- name: Check out standards for the baseline filter
114+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
115+
with:
116+
repository: hyperpolymath/standards
117+
ref: main
118+
path: .standards-checkout
119+
sparse-checkout: |
120+
scripts
121+
sparse-checkout-cone-mode: false
122+
109123
- name: Run Hypatia scan (Baseline validation)
124+
env:
125+
# Preserve the historical strictness: fail on ANY finding not
126+
# acknowledged by .hypatia-baseline.json (not just >= high). Set to
127+
# 'high' to only block on high/critical.
128+
BLOCKING_THRESHOLD: info
110129
run: |
111130
echo "Scanning repository: ${{ github.repository }} (checking baseline)"
112-
HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.json
113-
114-
FINDING_COUNT=$(jq '. | length' hypatia-findings.json 2>/dev/null || echo 0)
115-
116-
if [ "$FINDING_COUNT" -gt 0 ]; then
117-
echo "::error::Baseline validation failed. Found $FINDING_COUNT findings not in baseline."
118-
exit 1
119-
fi
120-
echo "Baseline validation successful. No new findings."
131+
HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.raw.json
132+
133+
# Relativize finding paths before matching. Hypatia's honest_completion
134+
# and code_safety modules emit ABSOLUTE host paths in `.file`
135+
# (Path.expand(repo)), while .hypatia-baseline.json uses repo-relative
136+
# paths per the schema + docs/HYPATIA-BASELINE-FORMAT.adoc. Strip the
137+
# workspace prefix so baseline file/file_pattern entries can match, and
138+
# map the repo root itself to "." so root-scoped findings (no_tests)
139+
# match. Upstream fix tracked in hypatia#566; this is the stopgap.
140+
jq --arg root "$PWD" '
141+
map(if (.file? // "") == $root then .file = "."
142+
elif (.file? // "") | startswith($root + "/")
143+
then .file = (.file | ltrimstr($root + "/"))
144+
else . end)
145+
' hypatia-findings.raw.json > hypatia-findings.json
146+
147+
# Filter against the per-repo baseline. apply-baseline.sh KEEPS every
148+
# finding not matched by an active (non-expired) baseline entry — so a
149+
# genuinely new finding still fails the gate (no silent-green) — and
150+
# suppresses only exact matches. Exits non-zero iff a kept finding is at
151+
# or above BLOCKING_THRESHOLD. (Validated against synthetic fixtures;
152+
# see the PR description.)
153+
bash .standards-checkout/scripts/apply-baseline.sh \
154+
hypatia-findings.json .hypatia-baseline.json blocking
121155
language-policy:
122156
name: Language / package anti-pattern policy
123157
runs-on: ${{ inputs.runs-on }}

.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: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,40 @@ 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
54+
55+
- name: Verify compliance dashboard is current
56+
run: |
57+
if ! bash scripts/build-scorecards.sh --check --strict; then
58+
{
59+
echo "### Compliance dashboard drift"
60+
echo ""
61+
echo "COMPLIANCE-DASHBOARD.md is stale, a scorecard is malformed/orphaned,"
62+
echo "or a registered spec has no scorecard. Fix locally:"
63+
echo ""
64+
echo '```sh'
65+
echo "just scorecards # regenerate the dashboard"
66+
echo "just scorecards-check-strict"
67+
echo '```'
68+
} >> "$GITHUB_STEP_SUMMARY"
69+
exit 1
70+
fi

.machine_readable/REGISTRY.a2ml

Lines changed: 2 additions & 2 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:8177d3a56c342d99383c26ef5ac481842dc8adfb885499d75b490729ecad7dfb"
39+
source_hash = "sha256:7c51aab6fe43b04bc795647ae9b3d4813ca82f6182399c2987e17edfd50b36f5"
4040
route = "the typed/verified machine-readable document format"
4141

4242
[[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]]
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# SPDX-License-Identifier: CC-BY-SA-4.0
2+
# 0-ai-gatekeeper-protocol.scorecard.a2ml
3+
# Hand-authored source. Regenerate the dashboard with: just scorecards
4+
# Schema: .machine_readable/scorecards/scorecard.schema.json
5+
6+
[scorecard]
7+
spec_id = "0-ai-gatekeeper-protocol"
8+
version = "1.0.0"
9+
assessed_date = "2026-07-03"
10+
assessor = "estate-audit"
11+
12+
[[must]]
13+
id = "M1"
14+
text = "The repository MUST contain exactly one AI manifest file, named 0-AI-MANIFEST.a2ml (or a permitted alias), located in the repository root, per docs/AI-MANIFEST-SPEC.adoc §File Naming."
15+
system = "none (no automated validator script checks this in CI; verified manually via directory listing)"
16+
status = "pass"
17+
evidence = "find confirms exactly one manifest at /home/user/standards/0-ai-gatekeeper-protocol/0-AI-MANIFEST.a2ml; no AI.a2ml, !AI.a2ml, or duplicate found at root."
18+
effects = "If violated, downstream MCP/FUSE parsers (mcp-repo-guardian, repo-guardian-fs) that assume a single canonical manifest path would pick an arbitrary or wrong file, breaking attestation for every consuming repo/agent."
19+
20+
[[must]]
21+
id = "M2"
22+
text = "The manifest MUST contain all required sections defined by AI-MANIFEST-SPEC.adoc §Required Sections (Warning Header, What Is This, Canonical Locations, Core Invariants, Repository Structure, Attestation Proof)."
23+
system = "none (no parser/linter script in this repo enforces the spec against 0-AI-MANIFEST.a2ml; mcp-repo-guardian's manifest_test.js only tests inline reimplementations of parsing logic, not a repo-facing validator CLI)"
24+
status = "pass"
25+
evidence = "Manual read of /home/user/standards/0-ai-gatekeeper-protocol/0-AI-MANIFEST.a2ml confirms presence of '# ⚠️ STOP', '## WHAT IS THIS?', '## CANONICAL LOCATIONS', '## CORE INVARIANTS', '## REPOSITORY STRUCTURE', and '## ATTESTATION PROOF' headings."
26+
effects = "Missing sections would leave AI agents without required guardrail information, defeating the protocol's stated purpose across all adopting repos."
27+
28+
[[must]]
29+
id = "M3"
30+
text = "The repository's own machine-readable state MUST accurately reflect this repository (not stale template boilerplate), since the manifest itself declares 'No stale metadata' as a Core Invariant."
31+
system = "none"
32+
status = "fail"
33+
effects = "/home/user/standards/0-ai-gatekeeper-protocol/.machine_readable/6a2/STATE.a2ml declares project = \"rsr-template-repo\" (name = \"Rsr Template Repo\", completion-percentage = 5, generic scaffolding actions like 'Define project scope and objectives'), i.e. it is an un-edited template copy, not this repo's actual state — directly violating the protocol's own 'no stale metadata' invariant it asks every other repo to uphold. Any agent trusting STATE.a2ml for context (as the manifest's own Session Startup Checklist instructs) would be misled about project identity/status, undermining the protocol's core value proposition."
34+
35+
[[must]]
36+
id = "M4"
37+
text = "Core manifest-parsing/session/guard logic (as implemented for FFI/offline consumption) MUST have an automated test suite that passes."
38+
system = "cargo test --manifest-path repo-guardian-fs/tests-offline/Cargo.toml (Rust unit tests for manifest parsing, session management, and path-guard invariant enforcement)"
39+
status = "pass"
40+
evidence = "Ran `cargo test` in /home/user/standards/0-ai-gatekeeper-protocol/repo-guardian-fs/tests-offline: 29 passed; 0 failed (manifest hashing, canonical-location extraction, invariant detection, session ack/expiry, path-traversal/SCM-duplication guard tests, and a dogfood test parsing the repo's real 0-AI-MANIFEST.a2ml)."
41+
effects = "If these regress, any FFI/native consumer (e.g. Zig bindings, future editor plugins) linking against this logic would silently mis-enforce or fail to enforce invariants."
42+
43+
[[must]]
44+
id = "M5"
45+
text = "The repo-guardian-fs FUSE enforcement component MUST build/compile so the 'OS-level enforcement for ANY tool/agent' claim in README.adoc is actually deliverable."
46+
system = "cargo build (in repo-guardian-fs/, main crate, not tests-offline)"
47+
status = "fail"
48+
effects = "`cargo build` in /home/user/standards/0-ai-gatekeeper-protocol/repo-guardian-fs fails with 58+ compile errors in the fuse3 v0.7.3 dependency (missing Future::poll impl, type-inference errors) on the installed Rust toolchain — exactly the known incompatibility documented in tests-offline/Cargo.toml's own comment ('fuse3 v0.7.3 fails to compile on Rust stable >= 1.80'). The FUSE wrapper, one of the protocol's three enforcement mechanisms advertised in README.adoc §Components, is currently non-functional for any real mount/enforcement use, affecting every non-MCP AI agent (Gemini, Copilot, ChatGPT) that the README says relies on it."
49+
50+
[[should]]
51+
id = "S1"
52+
text = "Documentation links referenced from README.adoc and 0-AI-MANIFEST.a2ml (docs/ARCHITECTURE.md, docs/INTEGRATION.md, docs/ENFORCEMENT.md, examples/github-workflows/, examples/claude-config.json) SHOULD exist and resolve."
53+
system = "none (no link-checker workflow present)"
54+
status = "fail"
55+
effects = "docs/ only contains AI-MANIFEST-SPEC.adoc, CITATIONS.adoc, FEEDBACK-TO-ANTHROPIC.md, RATIONALE.md (confirmed via `ls docs/`); examples/ only contains 0-AI-MANIFEST.a2ml and web-project-deno.json (confirmed via `ls examples/`). ARCHITECTURE.md, INTEGRATION.md, ENFORCEMENT.md, github-workflows/, and claude-config.json are all missing. Both README.adoc and the manifest itself (which is the file every AI agent is told to read FIRST) point new users/agents to dead links, undermining trust in the protocol's own dogfooding."
56+
57+
[[should]]
58+
id = "S2"
59+
text = "CONTRIBUTING.md SHOULD accurately describe the actual build/test workflow for this specific repository."
60+
system = "none"
61+
status = "fail"
62+
effects = "/home/user/standards/0-ai-gatekeeper-protocol/CONTRIBUTING.md instructs contributors to run `just test` and references `spec/` and `tests/` directories (Perimeter 2-3 language from a generic template), but no Justfile exists anywhere under 0-ai-gatekeeper-protocol/ and there is no spec/ or top-level tests/ directory (real tests live in repo-guardian-fs/tests-offline/ and mcp-repo-guardian/test/). New contributors following CONTRIBUTING.md literally would hit an immediate 'command not found' and be unable to run any tests."
63+
64+
[[should]]
65+
id = "S3"
66+
text = "The mcp-repo-guardian Deno/TypeScript test suite (manifest_test.js, 36 Deno.test cases covering parsing, security/injection, session and guard logic) SHOULD be executed automatically in CI on every push/PR."
67+
system = "none (no workflow in .github/workflows/ or .gitlab-ci.yml under mcp-repo-guardian/ invokes `deno test`; deno.json defines a `test` task but nothing calls it in CI)"
68+
status = "fail"
69+
effects = "Regressions in the TypeScript/ReScript-compiled manifest/session/guard logic (src/Manifest.mjs, Session.mjs, Guards.mjs) that ships as the actual MCP server enforcement path would not be caught until manually run; Claude/MCP-based consumers of mcp-repo-guardian are the primary enforcement channel per README.adoc, so this is the most consumer-facing untested surface."
70+
71+
[[should]]
72+
id = "S4"
73+
text = "License metadata SHOULD be internally consistent (SPDX headers, LICENSE file body, and README/manifest license statements should agree on one license identifier)."
74+
system = "none"
75+
status = "manual-only"
76+
effects = "LICENSE file's SPDX-License-Identifier header says MPL-2.0 but the body text is the GNU AGPLv3 license; README.adoc footer states 'PMPL-1.0-or-later'; 0-AI-MANIFEST.a2ml Core Invariant #4 and Meta section also say 'PMPL-1.0-or-later'; most workflow/source files carry MPL-2.0 SPDX headers; docs/AI-MANIFEST-SPEC.adoc and README.adoc top banner say CC-BY-SA-4.0. At least three different licenses (MPL-2.0, AGPLv3, PMPL-1.0-or-later, CC-BY-SA-4.0) are asserted across the same repository for different artifacts without a clear per-file mapping, which is a governance/legal judgement call, not something a script can resolve — downstream consumers redistributing code or docs face real licensing ambiguity."
77+
78+
[[could]]
79+
id = "C1"
80+
text = "The protocol COULD reach a state where FUSE-level (repo-guardian-fs) and MCP-level (mcp-repo-guardian) enforcement are both externally audited/certified as reliable universal gatekeepers across all major AI coding assistants (Claude, Gemini, Copilot, ChatGPT)."
81+
system = "none"
82+
status = "aspirational"
83+
effects = "This is a reach goal beyond current scope; no downstream repo depends on it today, but achieving it would let the whole hyperpolymath ecosystem rely on a single certified enforcement layer instead of ad hoc per-agent trust."
84+
85+
[[could]]
86+
id = "C2"
87+
text = "The .machine_readable/6a2/*.a2ml files for this repo (STATE, META, ECOSYSTEM, AGENTIC, NEUROSYM, PLAYBOOK) COULD each be kept current and repo-specific rather than templated placeholders."
88+
system = "none"
89+
status = "fail"
90+
effects = "Beyond STATE.a2ml (see M3), consumers of AGENTIC.a2ml/PLAYBOOK.a2ml for session-startup guidance would get generic template content instead of protocol-specific operational guidance, reducing the value of the 'read STATE/AGENTIC first' checklist the manifest itself prescribes."

0 commit comments

Comments
 (0)