|
| 1 | +K9! |
| 2 | +# SPDX-License-Identifier: MPL-2.0 |
| 3 | +# K9 Yard-level validator: MUST-check |
| 4 | +# Security Level: Yard (Nickel evaluation with contracts; no I/O) |
| 5 | +# |
| 6 | +# Runnable surface of the hard invariants declared in |
| 7 | +# ../../MUST.contractile and ../../contractiles/must/Mustfile.a2ml. |
| 8 | +# CI (quality.yml) runs this on every PR; `error`-severity failures block |
| 9 | +# merge. Keep the check IDs aligned with Mustfile.a2ml section names. |
| 10 | + |
| 11 | +{ |
| 12 | + pedigree = { |
| 13 | + schema_version = "1.0.0", |
| 14 | + component_type = "must-validator", |
| 15 | + security = { |
| 16 | + leash = 'Yard, |
| 17 | + trust_level = "validated-config", |
| 18 | + allow_network = false, |
| 19 | + allow_filesystem_write = false, |
| 20 | + allow_subprocess = false, |
| 21 | + }, |
| 22 | + metadata = { |
| 23 | + name = "must-check", |
| 24 | + version = "1.0.0", |
| 25 | + description = "Machine-checks the nextgen-languages MUST invariants (hub-level hygiene; submodule trees are each repo's own concern).", |
| 26 | + author = "Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>", |
| 27 | + paired_files = [ |
| 28 | + "../../MUST.contractile", |
| 29 | + "../../contractiles/must/Mustfile.a2ml", |
| 30 | + ], |
| 31 | + }, |
| 32 | + }, |
| 33 | + |
| 34 | + # Each check declares a severity and a shell predicate (exit 0 = pass). |
| 35 | + # A K9 'Yard runner evaluates these; it does not itself run the shell — |
| 36 | + # the predicate string is handed to the CI executor named in `run`. |
| 37 | + checks = { |
| 38 | + license_present = { |
| 39 | + description = "LICENSE file must exist", |
| 40 | + severity = 'error, |
| 41 | + predicate = "test -f LICENSE", |
| 42 | + }, |
| 43 | + |
| 44 | + ai_manifest_present = { |
| 45 | + description = "0-AI-MANIFEST.a2ml entry point must exist", |
| 46 | + severity = 'error, |
| 47 | + predicate = "test -f 0-AI-MANIFEST.a2ml", |
| 48 | + }, |
| 49 | + |
| 50 | + machine_readable_dir = { |
| 51 | + description = ".machine_readable/ directory preserved", |
| 52 | + severity = 'error, |
| 53 | + predicate = "test -d .machine_readable", |
| 54 | + }, |
| 55 | + |
| 56 | + no_root_scm_duplication = { |
| 57 | + description = "No STATE/META/ECOSYSTEM state file orphaned in repo root (canonical home is .machine_readable/6a2/)", |
| 58 | + severity = 'error, |
| 59 | + predicate = "! ls STATE.* META.* ECOSYSTEM.* 2>/dev/null | head -1 | grep -q .", |
| 60 | + }, |
| 61 | + |
| 62 | + six_a_two_complete = { |
| 63 | + description = "The 6a2 metadata set is complete (>= 6 .a2ml files)", |
| 64 | + severity = 'warning, |
| 65 | + predicate = "test $(ls .machine_readable/6a2/*.a2ml 2>/dev/null | wc -l) -ge 6", |
| 66 | + }, |
| 67 | + |
| 68 | + spdx_on_machine_readable = { |
| 69 | + description = "Every .a2ml under .machine_readable/ carries an SPDX header", |
| 70 | + severity = 'warning, |
| 71 | + predicate = "! grep -rL 'SPDX-License-Identifier' .machine_readable --include='*.a2ml' 2>/dev/null | head -1 | grep -q .", |
| 72 | + }, |
| 73 | + |
| 74 | + no_agpl = { |
| 75 | + description = "No AGPL references in dotfiles (estate policy is MPL-2.0)", |
| 76 | + severity = 'error, |
| 77 | + predicate = "! grep -rE 'AGPL-3[.]0' .gitignore .gitattributes .editorconfig 2>/dev/null | head -1 | grep -q .", |
| 78 | + }, |
| 79 | + |
| 80 | + actions_sha_pinned = { |
| 81 | + description = "Third-party GitHub Actions are SHA-pinned (reusable callers to hyperpolymath/standards excepted)", |
| 82 | + severity = 'warning, |
| 83 | + predicate = "! grep -rEn 'uses:[[:space:]]+[^#]+@(main|master|v[0-9]+)[[:space:]]*$' .github/workflows 2>/dev/null | grep -v 'hyperpolymath/standards' | head -1 | grep -q .", |
| 84 | + }, |
| 85 | + |
| 86 | + hypatia_waiver_registry = { |
| 87 | + description = "Hypatia accepted-findings registry exists (NEUROSYM.a2ml)", |
| 88 | + severity = 'warning, |
| 89 | + predicate = "grep -q '\\[accepted-findings\\]' .machine_readable/6a2/NEUROSYM.a2ml", |
| 90 | + }, |
| 91 | + |
| 92 | + kitchenspeak_postulate_axiom = { |
| 93 | + description = "KitchenSpeak Agda postulates remain annotated as trusted base (AXIOM marker)", |
| 94 | + severity = 'warning, |
| 95 | + predicate = "test ! -d kitchenspeak/proofs/agda || ! grep -rl 'postulate' kitchenspeak/proofs/agda --include='*.agda' 2>/dev/null | xargs -r grep -L 'AXIOM' 2>/dev/null | head -1 | grep -q .", |
| 96 | + }, |
| 97 | + }, |
| 98 | + |
| 99 | + run = { |
| 100 | + executor = "ci:quality.yml", |
| 101 | + on_error_severity = "exit-nonzero", # error-severity failures block merge |
| 102 | + on_warning_severity = "report-only", |
| 103 | + report_format = "a2ml", |
| 104 | + }, |
| 105 | +} |
0 commit comments