#!/usr/bin/env nu # Typecheck gate for the About projection contract (about-schema.ncl). # This is the ⛓ design gate: it must pass before any gen-about-pages projector # or /about handler work begins. Verifies: # 1. the real ontoref about.ncl exports (positive) # 2. a valid 'Personal instance exports (both kinds expressible) # 3. 'Project with a stray `personal` block is rejected (coherence) # 4. 'Personal missing its `personal` block is rejected (coherence) # # Usage (from outreach/site): # nu scripts/build/test-about-contract.nu # nu scripts/build/test-about-contract.nu --root ../.. def exports [dir: string, body: string] { let tmp = $"($dir)/.about-contract-test.ncl" $body | save -f $tmp let ok = (do { nickel export --format json $tmp } | complete | get exit_code) == 0 rm -f $tmp $ok } def main [--root: string = "../.."] { let pos_dir = $"($root)/.ontoref/positioning" if not ($"($pos_dir)/about-schema.ncl" | path exists) { error make { msg: $"about-schema.ncl not found under ($pos_dir)" } } mut failures = [] # 1 — real instance exports let real_ok = (do { nickel export --format json $"($pos_dir)/about.ncl" } | complete | get exit_code) == 0 if not $real_ok { $failures = ($failures | append "about.ncl (ontoref, 'Project) failed to export") } # 2 — valid personal instance let personal_ok = (exports $pos_dir "let s = import \"about-schema.ncl\" in { kind = 'Personal, level_id = \"t\", personal = { template = \"about.j2\" } } | s.AboutShape | s.AboutCoherence") if not $personal_ok { $failures = ($failures | append "valid 'Personal instance was rejected") } # 3 — 'Project with stray personal block must be rejected let proj_stray_rejected = not (exports $pos_dir "let s = import \"about-schema.ncl\" in { kind = 'Project, level_id = \"t\", personal = { template = \"about.j2\" } } | s.AboutShape | s.AboutCoherence") if not $proj_stray_rejected { $failures = ($failures | append "'Project with stray personal block was accepted (coherence breach)") } # 4 — 'Personal missing its block must be rejected let personal_missing_rejected = not (exports $pos_dir "let s = import \"about-schema.ncl\" in { kind = 'Personal, level_id = \"t\" } | s.AboutShape | s.AboutCoherence") if not $personal_missing_rejected { $failures = ($failures | append "'Personal missing its block was accepted (coherence breach)") } if ($failures | is-empty) { print "about-contract: 4/4 checks pass — ⛓ gate OPEN" } else { for f in $failures { print $" ✗ ($f)" } error make { msg: $"about-contract: ($failures | length) check\(s\) failed — ⛓ gate CLOSED" } } }