From 0e3b329d76801fc18d9cd8e1e2f220a2bc134b44 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:26:09 +0100 Subject: [PATCH 1/4] feat(rsr): add complete .machine_readable/ structure with contractiles, descriptiles, and scripts Add full RSR compliance infrastructure: - contractiles/ with adjust, bust, dust, intend, must, trust directories - descriptiles/ with AGENTIC, CLADE, ECOSYSTEM, META, NEUROSYM, PLAYBOOK, STATE - scripts/ with verification, lifecycle, forge subdirectories - Updated 0-AI-MANIFEST.a2ml to reference pons-asinorum Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- .machine_readable/0-AI-MANIFEST.a2ml | 40 ++ .machine_readable/README.adoc | 24 + .machine_readable/contractiles/INDEX.a2ml | 133 ++++ .machine_readable/contractiles/Justfile | 646 ++++++++++++++++++ .machine_readable/contractiles/README.adoc | 156 +++++ .machine_readable/contractiles/_base.ncl | 140 ++++ .../contractiles/adjust/Adjustfile.a2ml | 72 ++ .../contractiles/adjust/adjust.k9.ncl | 167 +++++ .../contractiles/adjust/adjust.manifest.a2ml | 47 ++ .../contractiles/adjust/adjust.ncl | 62 ++ .../contractiles/bust/Bustfile.a2ml | 52 ++ .../contractiles/bust/bust.k9.ncl | 162 +++++ .../contractiles/bust/bust.manifest.a2ml | 48 ++ .machine_readable/contractiles/bust/bust.ncl | 66 ++ .../contractiles/dust/Dustfile.a2ml | 62 ++ .../contractiles/dust/dust.k9.ncl | 172 +++++ .../contractiles/dust/dust.manifest.a2ml | 51 ++ .machine_readable/contractiles/dust/dust.ncl | 66 ++ .../contractiles/intend/Intentfile.a2ml | 99 +++ .../contractiles/intend/intend.k9.ncl | 252 +++++++ .../contractiles/intend/intend.manifest.a2ml | 73 ++ .../contractiles/intend/intend.ncl | 81 +++ .../contractiles/must/Mustfile.a2ml | 102 +++ .../contractiles/must/must.k9.ncl | 238 +++++++ .../contractiles/must/must.manifest.a2ml | 59 ++ .machine_readable/contractiles/must/must.ncl | 64 ++ .../contractiles/trust/Trustfile.a2ml | 105 +++ .../contractiles/trust/trust.k9.ncl | 278 ++++++++ .../contractiles/trust/trust.manifest.a2ml | 72 ++ .../contractiles/trust/trust.ncl | 88 +++ .../descriptiles/0-AI-MANIFEST.a2ml | 32 + .machine_readable/descriptiles/AGENTIC.a2ml | 51 ++ .machine_readable/descriptiles/CLADE.a2ml | 76 +++ .machine_readable/descriptiles/ECOSYSTEM.a2ml | 45 ++ .machine_readable/descriptiles/META.a2ml | 53 ++ .machine_readable/descriptiles/NEUROSYM.a2ml | 23 + .machine_readable/descriptiles/PLAYBOOK.a2ml | 137 ++++ .machine_readable/descriptiles/README.adoc | 30 + .machine_readable/descriptiles/STATE.a2ml | 64 ++ .../descriptiles/anchors/0-AI-MANIFEST.a2ml | 21 + .../descriptiles/anchors/ANCHOR.a2ml | 62 ++ .../descriptiles/anchors/README.adoc | 25 + .../scripts/0.2-AI-MANIFEST.a2ml | 18 + .../scripts/forge/0.3-AI-MANIFEST.a2ml | 11 + .machine_readable/scripts/forge/README.adoc | 3 + .machine_readable/scripts/forge/forge-sync.sh | 25 + .../scripts/forge/git-cleanup.sh | 8 + .../scripts/lifecycle/0.3-AI-MANIFEST.a2ml | 11 + .../scripts/lifecycle/README.adoc | 3 + .../scripts/lifecycle/install-tools.sh | 27 + .../scripts/verification/0.3-AI-MANIFEST.a2ml | 11 + .../scripts/verification/README.adoc | 3 + 52 files changed, 4416 insertions(+) create mode 100644 .machine_readable/0-AI-MANIFEST.a2ml create mode 100644 .machine_readable/README.adoc create mode 100644 .machine_readable/contractiles/INDEX.a2ml create mode 100644 .machine_readable/contractiles/Justfile create mode 100644 .machine_readable/contractiles/README.adoc create mode 100644 .machine_readable/contractiles/_base.ncl create mode 100644 .machine_readable/contractiles/adjust/Adjustfile.a2ml create mode 100644 .machine_readable/contractiles/adjust/adjust.k9.ncl create mode 100644 .machine_readable/contractiles/adjust/adjust.manifest.a2ml create mode 100644 .machine_readable/contractiles/adjust/adjust.ncl create mode 100644 .machine_readable/contractiles/bust/Bustfile.a2ml create mode 100644 .machine_readable/contractiles/bust/bust.k9.ncl create mode 100644 .machine_readable/contractiles/bust/bust.manifest.a2ml create mode 100644 .machine_readable/contractiles/bust/bust.ncl create mode 100644 .machine_readable/contractiles/dust/Dustfile.a2ml create mode 100644 .machine_readable/contractiles/dust/dust.k9.ncl create mode 100644 .machine_readable/contractiles/dust/dust.manifest.a2ml create mode 100644 .machine_readable/contractiles/dust/dust.ncl create mode 100644 .machine_readable/contractiles/intend/Intentfile.a2ml create mode 100644 .machine_readable/contractiles/intend/intend.k9.ncl create mode 100644 .machine_readable/contractiles/intend/intend.manifest.a2ml create mode 100644 .machine_readable/contractiles/intend/intend.ncl create mode 100644 .machine_readable/contractiles/must/Mustfile.a2ml create mode 100644 .machine_readable/contractiles/must/must.k9.ncl create mode 100644 .machine_readable/contractiles/must/must.manifest.a2ml create mode 100644 .machine_readable/contractiles/must/must.ncl create mode 100644 .machine_readable/contractiles/trust/Trustfile.a2ml create mode 100644 .machine_readable/contractiles/trust/trust.k9.ncl create mode 100644 .machine_readable/contractiles/trust/trust.manifest.a2ml create mode 100644 .machine_readable/contractiles/trust/trust.ncl create mode 100644 .machine_readable/descriptiles/0-AI-MANIFEST.a2ml create mode 100644 .machine_readable/descriptiles/AGENTIC.a2ml create mode 100644 .machine_readable/descriptiles/CLADE.a2ml create mode 100644 .machine_readable/descriptiles/ECOSYSTEM.a2ml create mode 100644 .machine_readable/descriptiles/META.a2ml create mode 100644 .machine_readable/descriptiles/NEUROSYM.a2ml create mode 100644 .machine_readable/descriptiles/PLAYBOOK.a2ml create mode 100644 .machine_readable/descriptiles/README.adoc create mode 100644 .machine_readable/descriptiles/STATE.a2ml create mode 100644 .machine_readable/descriptiles/anchors/0-AI-MANIFEST.a2ml create mode 100644 .machine_readable/descriptiles/anchors/ANCHOR.a2ml create mode 100644 .machine_readable/descriptiles/anchors/README.adoc create mode 100644 .machine_readable/scripts/0.2-AI-MANIFEST.a2ml create mode 100644 .machine_readable/scripts/forge/0.3-AI-MANIFEST.a2ml create mode 100644 .machine_readable/scripts/forge/README.adoc create mode 100755 .machine_readable/scripts/forge/forge-sync.sh create mode 100755 .machine_readable/scripts/forge/git-cleanup.sh create mode 100644 .machine_readable/scripts/lifecycle/0.3-AI-MANIFEST.a2ml create mode 100644 .machine_readable/scripts/lifecycle/README.adoc create mode 100755 .machine_readable/scripts/lifecycle/install-tools.sh create mode 100644 .machine_readable/scripts/verification/0.3-AI-MANIFEST.a2ml create mode 100644 .machine_readable/scripts/verification/README.adoc diff --git a/.machine_readable/0-AI-MANIFEST.a2ml b/.machine_readable/0-AI-MANIFEST.a2ml new file mode 100644 index 0000000..bb3dbf5 --- /dev/null +++ b/.machine_readable/0-AI-MANIFEST.a2ml @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0-or-later +// Machine-readable manifest for pons repository +// See: https://github.com/hyperpolymath/standards/blob/main/docs/CONTRACTILES-SPEC.adoc + +{ + "repository": { + "name": "pons-asinorum", + "description": "A depth-first, multi-language static scanner that flags wasted work, self-contradiction, and missing escape hatches", + "estate": "hyperpolymath", + "license": { + "code": "MPL-2.0-or-later", + "docs": "CC-BY-SA-4.0" + }, + "primary_language": ["Rust", "Zig", "Idris"], + "status": "planning", + "rsr_compliance_target": "full" + }, + + "constraints": { + "no_typescript": true, + "no_handwritten_js": true, + "no_ruby": true, + "no_python_scripts": true + }, + + "doors": { + "DOOR-001": { + "description": "Never dress a heuristic up as a proof", + "evidence_tiers": ["PROTOCOL", "DATAFLOW", "HEURISTIC", "SPECULATIVE"], + "enforcement": "CI_gate" + } + }, + + "verification": { + "last_audited": "2026-08-13", + "audit_type": "automated", + "compliance_score": "partial", + "target_compliance": "full" + } +} diff --git a/.machine_readable/README.adoc b/.machine_readable/README.adoc new file mode 100644 index 0000000..5ca2e76 --- /dev/null +++ b/.machine_readable/README.adoc @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MPL-2.0 += pons Machine-Readable Metadata +:toc: + +This directory contains machine-readable contractiles and descriptiles for the pons repository. + +== Structure + +* `0-AI-MANIFEST.a2ml` — Primary machine manifest +* `contractiles/` — Contract files (requirements, constraints, guarantees) +* `descriptiles/` — Descriptive files (metadata, classifications) +* `scripts/` — Automation and verification scripts + +== Contractiles + +include::contractiles/README.adoc[] + +== Descriptiles + +include::descriptiles/README.adoc[] + +== Scripts + +include::scripts/README.adoc[] diff --git a/.machine_readable/contractiles/INDEX.a2ml b/.machine_readable/contractiles/INDEX.a2ml new file mode 100644 index 0000000..d44c3f2 --- /dev/null +++ b/.machine_readable/contractiles/INDEX.a2ml @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: MPL-2.0 +# INDEX.a2ml — Contractile Registry +# Author: Jonathan D.A. Jewell +# +# Machine-readable catalogue of all contractile verbs in this template set. +# Consumers (CI scripts, the contractile CLI, Hypatia rules) SHOULD read this +# file to discover available verbs rather than hard-coding the list. +# +# See: docs/CONTRACTILE-SPEC.adoc §Registry + +--- +id = "contractiles-registry" +version = "2.0.0" # 2.0.0 (2026-04-18): all 6 verbs on trident shape; verb set complete. +spec = "docs/CONTRACTILE-SPEC.adoc" +last_updated = "2026-04-18" +base_schema = ".machine_readable/contractiles/_base.ncl" +meta_schema_status = "pending — see CONTRACTILE-SPEC §validator-meta-schema" + +## Verbs + +[[verbs]] +name = "adjust" +semantics = "drift tolerances + corrective actions" +trident = [ + "adjust/Adjustfile.a2ml", + "adjust/adjust.ncl", + "adjust/adjust.k9.ncl", +] +manifest = "adjust/adjust.manifest.a2ml" +status = "active" +tier = "Yard" +authority = "advisory" +gating = "advisory (continue-with-warnings)" +cardinality = "one per repo" +notes = "Fifth trident instance (2026-04-18). First (Yard, advisory) authority pattern. Specialises in cumulative-drift catchment — tolerance bands + trend tracking across sessions. auto_fix_when_available applies deterministic patches; advisory otherwise." + +[[verbs]] +name = "bust" +semantics = "hard-stop / expiry / must-not-run declarations" +trident = [ + "bust/Bustfile.a2ml", + "bust/bust.ncl", + "bust/bust.k9.ncl", +] +manifest = "bust/bust.manifest.a2ml" +status = "active" +tier = "Hunt-read-only" +authority = "blocking" +gating = "hard (exit-nonzero)" +cardinality = "one per repo" +notes = "Fourth trident instance (2026-04-18). Completes the blocking-authority triple (must + trust + bust). Specialises in deprecated-path-reintroduction catchment. Injects failures via declared probes and verifies recovery paths." + +[[verbs]] +name = "dust" +semantics = "rollback / recovery / deprecation / audit-trail preservation" +trident = [ + "dust/Dustfile.a2ml", + "dust/dust.ncl", + "dust/dust.k9.ncl", +] +manifest = "dust/dust.manifest.a2ml" +status = "active" +tier = "Yard" +authority = "advisory" +gating = "advisory (continue-with-warnings)" +cardinality = "one per repo" +notes = "Sixth and FINAL trident instance (2026-04-18) — completes the full verb set. Specialises in audit-trail preservation + rollback-path verification. Destructive actions gated behind --apply flag + per-item approval; dry-run default." + +[[verbs]] +name = "intend" +semantics = "north-star (commitments + aspirations)" +trident = [ + "intend/Intentfile.a2ml", + "intend/intend.ncl", + "intend/intend.k9.ncl", +] +manifest = "intend/intend.manifest.a2ml" +status = "active" +tier = "Hunt" +authority = "reporting" +gating = "non-gating (continue)" +cardinality = "one per repo" +notes = "First trident instance in the estate (2026-04-18). Reports progress toward committed next-actions AND lists horizon aspirations. Absorbed the deprecated `lust` verb 2026-04-18. Never blocks. Remaining 5 verbs still on file_pair shape until tridents are built." + +[[verbs]] +name = "k9" +semantics = "trust-tier templates (EXCEPTION to one-verbfile rule)" +file_pair = [ + "k9/template-hunt.k9.ncl", + "k9/template-kennel.k9.ncl", + "k9/template-yard.k9.ncl", +] +status = "exception" +gating = "not applicable" +notes = "k9 is service-automation meta-infrastructure, not a verb contractile. Three trust-tier templates (Kennel/Yard/Hunt). Does not have a Verbfile.a2ml. See CONTRACTILE-SPEC §k9-exception." + +# [[verbs]] lust REMOVED 2026-04-18 — name had unwanted associations; +# the horizon/aspiration semantics were always meant to live inside `intend` +# (the north-star verb). The [[wishes]] schema was absorbed into +# intend/Intentfile.a2ml. Any `lust/` dir found in an estate repo is drift +# and should be deleted. + +[[verbs]] +name = "must" +semantics = "invariant assertion — release-blocking" +trident = [ + "must/Mustfile.a2ml", + "must/must.ncl", + "must/must.k9.ncl", +] +manifest = "must/must.manifest.a2ml" +status = "active" +tier = "Hunt-read-only" +authority = "blocking" +gating = "hard (exit-nonzero)" +cardinality = "one per repo" +notes = "Third trident instance (2026-04-18). Completes the blocking-authority pair with trust: must = concrete + persistent invariants; trust = concrete + ephemeral transactions. Specialises in subtle invariant-erosion (tracking per-session trend; flagging silent regression). Single failure blocks merge. Simplest and most commonly populated verb." + +[[verbs]] +name = "trust" +semantics = "security + provenance + safe-hacking" +trident = [ + "trust/Trustfile.a2ml", + "trust/trust.ncl", + "trust/trust.k9.ncl", +] +manifest = "trust/trust.manifest.a2ml" +status = "active" +tier = "Hunt" +authority = "blocking" +gating = "hard (exit-nonzero)" +cardinality = "one per repo" +notes = "Second trident instance (2026-04-18). First (Hunt, blocking) verb — hard gate. Primary defense against threat-model misclassification (B1) and 'turn off the firewall' capability-collapse (C2). Inherits on_open negotiation+accountability+translation from intend.k9.ncl v2.0.0; adds threat_model_foregrounding + block_session_close_on_critical_drift." diff --git a/.machine_readable/contractiles/Justfile b/.machine_readable/contractiles/Justfile new file mode 100644 index 0000000..968fa73 --- /dev/null +++ b/.machine_readable/contractiles/Justfile @@ -0,0 +1,646 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# RSR Standard Justfile Template +# https://just.systems/man/en/ +# +# Copy this file to new projects and customize the placeholder values. +# +# Run `just` to see all available recipes +# Run `just cookbook` to generate docs/just-cookbook.adoc +# Run `just combinations` to see matrix recipe options + +set shell := ["bash", "-uc"] +set dotenv-load := true +set positional-arguments := true + +# Import auto-generated contractile recipes (must-check, trust-verify, etc.) +# Re-generate with: contractile gen-just +import? "build/contractile.just" + +# Project metadata — customize these +project := "rsr-template-repo" +OWNER := "hyperpolymath" +REPO := "rsr-template-repo" +version := "0.1.0" +tier := "infrastructure" # 1 | 2 | infrastructure + +# ═══════════════════════════════════════════════════════════════════════════════ +# DEFAULT & HELP +# ═══════════════════════════════════════════════════════════════════════════════ + +# Show all available recipes with descriptions +default: + @just --list --unsorted + +# Show detailed help for a specific recipe +help recipe="": + #!/usr/bin/env bash + if [ -z "{{recipe}}" ]; then + just --list --unsorted + echo "" + echo "Usage: just help " + echo " just cookbook # Generate full documentation" + echo " just combinations # Show matrix recipes" + else + just --show "{{recipe}}" 2>/dev/null || echo "Recipe '{{recipe}}' not found" + fi + +# Show this project's info +info: + @echo "Project: {{project}}" + @echo "Version: {{version}}" + @echo "RSR Tier: {{tier}}" + @echo "Recipes: $(just --summary | wc -w)" + @[ -f ".machine_readable/descriptiles/STATE.a2ml" ] && grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/descriptiles/STATE.a2ml | head -1 | xargs -I{} echo "Phase: {}" || true + +# Run Invariant Path overlay tools for this repository +invariant-path *ARGS: + ./scripts/invariant-path.sh {{ARGS}} + +# ═══════════════════════════════════════════════════════════════════════════════ +# INIT — see build/just/init.just +# ═══════════════════════════════════════════════════════════════════════════════ + +import? "build/just/init.just" + +# >>> container-module (three-tier: OCI · portable engine · stapeln) >>> +# Self-contained. Remove the entire block — this and the import — with `just no-container`. +import? "build/just/container.just" +# <<< container-module <<< + +# ═══════════════════════════════════════════════════════════════════════════════ +# GROOVE PROTOCOL — see build/just/groove.just +# ═══════════════════════════════════════════════════════════════════════════════ + +import? "build/just/groove.just" + +# ═══════════════════════════════════════════════════════════════════════════════ +# PROJECT SELF-ASSESSMENT + OPENSSF COMPLIANCE — see build/just/assess.just +# ═══════════════════════════════════════════════════════════════════════════════ + +import? "build/just/assess.just" + +# ═══════════════════════════════════════════════════════════════════════════════ +# BUILD & COMPILE +# ═══════════════════════════════════════════════════════════════════════════════ + +# Build the project (debug mode) +build *args: + @echo "Building {{project}} (debug)..." + # TODO: Replace with your build command + # Examples: + # cargo build {{args}} # Rust + # mix compile {{args}} # Elixir + # zig build {{args}} # Zig + # deno task build {{args}} # Deno/ReScript + @echo "Build complete" + +# Build in release mode with optimizations +build-release *args: + @echo "Building {{project}} (release)..." + # TODO: Replace with your release build command + # Examples: + # cargo build --release {{args}} + # MIX_ENV=prod mix compile {{args}} + # zig build -Doptimize=ReleaseFast {{args}} + @echo "Release build complete" + +# Build and watch for changes (requires entr or similar) +build-watch: + @echo "Watching for changes..." + # TODO: Customize file patterns for your language + # Examples: + # find src -name '*.rs' | entr -c just build + # mix compile --force --warnings-as-errors + # deno task dev + +# Clean build artifacts [reversible: rebuild with `just build`] +clean: + @echo "Cleaning..." + # TODO: Customize for your build system + rm -rf target/ _build/ build/ dist/ out/ obj/ bin/ + +# Deep clean including caches [reversible: rebuild] +clean-all: clean + rm -rf .cache .tmp + +# ═══════════════════════════════════════════════════════════════════════════════ +# TEST & QUALITY +# ═══════════════════════════════════════════════════════════════════════════════ + +# Run all tests +test *args: + @echo "Running tests..." + # TODO: Replace with your test command + # Examples: + # cargo test {{args}} + # mix test {{args}} + # zig build test {{args}} + # deno test {{args}} + @echo "Tests passed!" + +# Run tests with verbose output +test-verbose: + @echo "Running tests (verbose)..." + # TODO: Replace with verbose test command + +# Smoke test +test-smoke: + @echo "Smoke test..." + # TODO: Add basic sanity checks + +# Run end-to-end tests (full pipeline: build → run → verify) +e2e: + @echo "Running E2E tests..." + # TODO: Replace with your E2E test command. Examples: + # bash tests/e2e.sh # Shell-based E2E + # npx playwright test # Browser E2E + # mix test test/integration/e2e_test.exs # Elixir E2E + # cargo test --test end_to_end # Rust E2E + @echo "E2E tests passed!" + +# Run aspect tests (cross-cutting concern validation) +aspect: + @echo "Running aspect tests..." + # TODO: Replace with your aspect test command. Examples: + # bash tests/aspect_tests.sh # Shell-based aspect tests + # cargo test --test aspects # Rust aspect tests + # Aspect tests validate architectural invariants: + # - Thread safety (mutex in FFI modules) + # - ABI/FFI contract (declarations match exports) + # - SPDX compliance (all files have license headers) + # - No dangerous patterns (believe_me, assert_total, etc.) + @echo "Aspect tests passed!" + +# Run benchmarks (performance regression detection) +bench: + @echo "Running benchmarks..." + # TODO: Replace with your benchmark command. Examples: + # cargo bench # Rust criterion + # zig build bench # Zig benchmarks + # mix run bench/benchmarks.exs # Elixir benchee + # deno bench # Deno bench + @echo "Benchmarks complete!" + +# Run readiness tests (Component Readiness Grade: D/C/B) +readiness: + @echo "Running readiness tests..." + # TODO: Replace with your readiness test command. Examples: + # cargo test --test readiness -- --nocapture + @echo "Readiness tests complete!" + +# Print the current CRG grade (reads from READINESS.md '**Current Grade:** X' line) +crg-grade: + @grade=$$(grep -oP '(?<=\*\*Current Grade:\*\* )[A-FX]' READINESS.md 2>/dev/null | head -1); \ + [ -z "$$grade" ] && grade="X"; \ + echo "$$grade" + +# Print a shields.io CRG badge for embedding in README files +# Looks for '**Current Grade:** X' in READINESS.md; falls back to X +crg-badge: + @grade=$$(grep -oP '(?<=\*\*Current Grade:\*\* )[A-FX]' READINESS.md 2>/dev/null | head -1); \ + [ -z "$$grade" ] && grade="X"; \ + case "$$grade" in \ + A) color="brightgreen" ;; \ + B) color="green" ;; \ + C) color="yellow" ;; \ + D) color="orange" ;; \ + E) color="red" ;; \ + F) color="critical" ;; \ + *) color="lightgrey" ;; \ + esac; \ + echo "[![CRG $$grade](https://img.shields.io/badge/CRG-$$grade-$$color?style=flat-square)](https://github.com/hyperpolymath/standards/tree/main/component-readiness-grades)" + +# Run the full merge-requirement test suite (ALL categories) +# Per STANDING rule: P2P + E2E + aspect + execution + lifecycle + bench +test-all: test e2e aspect bench readiness + @echo "All test categories passed — safe to merge!" + +# Run all quality checks +quality: fmt-check lint test + @echo "All quality checks passed!" + +# Fix all auto-fixable issues [reversible: git checkout] +fix: fmt + @echo "Fixed all auto-fixable issues" + +# ═══════════════════════════════════════════════════════════════════════════════ +# LINT & FORMAT +# ═══════════════════════════════════════════════════════════════════════════════ + +# Format all source files [reversible: git checkout] +fmt: + @echo "Formatting source files..." + # TODO: Replace with your formatter + # Examples: + # cargo fmt + # mix format + # gleam format + # deno fmt + +# Check formatting without changes +fmt-check: + @echo "Checking formatting..." + # TODO: Replace with your format check + # Examples: + # cargo fmt --check + # mix format --check-formatted + # gleam format --check + +# Run linter +lint: + @echo "Linting source files..." + # TODO: Replace with your linter + # Examples: + # cargo clippy -- -D warnings + # mix credo --strict + # gleam check + +# ═══════════════════════════════════════════════════════════════════════════════ +# RUN & EXECUTE +# ═══════════════════════════════════════════════════════════════════════════════ + +# Run the application +run *args: build + # TODO: Replace with your run command + echo "Run not configured yet" + +# Run with verbose output +run-verbose *args: build + # TODO: Replace with verbose run command + echo "Run not configured yet" + +# Install to user path +install: build-release + @echo "Installing {{project}}..." + # TODO: Replace with your install command + +# ═══════════════════════════════════════════════════════════════════════════════ +# DEPENDENCIES +# ═══════════════════════════════════════════════════════════════════════════════ + +# Install/check all dependencies +deps: + @echo "Checking dependencies..." + # TODO: Replace with your dependency check + # Examples: + # cargo check + # mix deps.get + # gleam deps download + @echo "All dependencies satisfied" + +# Audit dependencies for vulnerabilities +deps-audit: + @echo "Auditing for vulnerabilities..." + # TODO: Replace with your audit command + # Examples: + # cargo audit + # mix audit + @command -v trivy >/dev/null && trivy fs --severity HIGH,CRITICAL --quiet . || true + @echo "Audit complete" + +# ═══════════════════════════════════════════════════════════════════════════════ +# ARRIVAL PACK — agent-facing CLAUDE.md, compiled from a2ml +# ═══════════════════════════════════════════════════════════════════════════════ + +# Compile CLAUDE.md (the agent arrival pack) from this repo's a2ml +claude-md: + @bash .machine_readable/arrival-pack/generate.sh + +# Fail if CLAUDE.md's generated region drifted from a2ml or was hand-edited +validate-claude-md: + @bash .machine_readable/arrival-pack/verify.sh + +# ═══════════════════════════════════════════════════════════════════════════════ +# DOCUMENTATION +# ═══════════════════════════════════════════════════════════════════════════════ + +# Generate all documentation +docs: + @mkdir -p docs/generated docs/man + just cookbook + just man + @echo "Documentation generated in docs/" + +# Generate justfile cookbook documentation +cookbook: + #!/usr/bin/env bash + mkdir -p docs + OUTPUT="docs/just-cookbook.adoc" + echo "= {{project}} Justfile Cookbook" > "$OUTPUT" + echo ":toc: left" >> "$OUTPUT" + echo ":toclevels: 3" >> "$OUTPUT" + echo "" >> "$OUTPUT" + echo "Generated: $(date -Iseconds)" >> "$OUTPUT" + echo "" >> "$OUTPUT" + echo "== Recipes" >> "$OUTPUT" + echo "" >> "$OUTPUT" + just --list --unsorted | while read -r line; do + if [[ "$line" =~ ^[[:space:]]+([a-z_-]+) ]]; then + recipe="${BASH_REMATCH[1]}" + echo "=== $recipe" >> "$OUTPUT" + echo "" >> "$OUTPUT" + echo "[source,bash]" >> "$OUTPUT" + echo "----" >> "$OUTPUT" + echo "just $recipe" >> "$OUTPUT" + echo "----" >> "$OUTPUT" + echo "" >> "$OUTPUT" + fi + done + echo "Generated: $OUTPUT" + +# Generate man page +man: + #!/usr/bin/env bash + mkdir -p docs/man + cat > docs/man/{{project}}.1 << EOF + .TH {{project}} 1 "$(date +%Y-%m-%d)" "{{version}}" "{{project}} Manual" + .SH NAME + {{project}} \- RSR-compliant project + .SH SYNOPSIS + .B just + [recipe] [args...] + .SH DESCRIPTION + RSR (Rhodium Standard Repository) project managed with just. + .SH AUTHOR + $(git config user.name 2>/dev/null || echo "Author") <$(git config user.email 2>/dev/null || echo "email")> + EOF + echo "Generated: docs/man/{{project}}.1" + +# ═══════════════════════════════════════════════════════════════════════════════ +# CI & AUTOMATION +# ═══════════════════════════════════════════════════════════════════════════════ + +# Run full CI pipeline locally +ci: deps quality + @echo "CI pipeline complete!" + +# Install git hooks +install-hooks: + @mkdir -p .git/hooks + @cat > .git/hooks/pre-commit << 'HOOKEOF' + #!/bin/bash + just fmt-check || exit 1 + just lint || exit 1 + just assail || exit 1 + HOOKEOF + @chmod +x .git/hooks/pre-commit + @echo "Git hooks installed" + +# ═══════════════════════════════════════════════════════════════════════════════ +# SECURITY +# ═══════════════════════════════════════════════════════════════════════════════ + +# Run security audit +security: deps-audit + @echo "=== Security Audit ===" + @command -v trivy >/dev/null && trivy fs --severity HIGH,CRITICAL . || true + @echo "Security audit complete" + +# Generate SBOM +sbom: + @mkdir -p docs/security + @command -v syft >/dev/null && syft . -o spdx-json > docs/security/sbom.spdx.json || echo "syft not found" + +# ═══════════════════════════════════════════════════════════════════════════════ +# VALIDATION & COMPLIANCE — see build/just/validate.just +# ═══════════════════════════════════════════════════════════════════════════════ + +import? "build/just/validate.just" + +# ═══════════════════════════════════════════════════════════════════════════════ +# STATE MANAGEMENT +# ═══════════════════════════════════════════════════════════════════════════════ + +# Update STATE.a2ml timestamp +state-touch: + @if [ -f ".machine_readable/descriptiles/STATE.a2ml" ]; then \ + sed -i 's/last-updated = "[^"]*"/last-updated = "'"$(date +%Y-%m-%d)"'"/' .machine_readable/descriptiles/STATE.a2ml && \ + echo "STATE.a2ml timestamp updated"; \ + fi + +# Show current phase from STATE.a2ml +state-phase: + @grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/descriptiles/STATE.a2ml 2>/dev/null | head -1 || echo "unknown" + +# ═══════════════════════════════════════════════════════════════════════════════ +# GUIX & NIX +# ═══════════════════════════════════════════════════════════════════════════════ + +# Enter Guix development shell (primary) +guix-shell: + guix shell -D -f guix.scm + +# Build with Guix +guix-build: + guix build -f guix.scm + +# Enter Nix development shell (fallback) +nix-shell: + @if [ -f "flake.nix" ]; then nix develop; else echo "No flake.nix"; fi + +# ═══════════════════════════════════════════════════════════════════════════════ +# HYBRID AUTOMATION +# ═══════════════════════════════════════════════════════════════════════════════ + +# Run local automation tasks +automate task="all": + #!/usr/bin/env bash + case "{{task}}" in + all) just fmt && just lint && just test && just docs && just state-touch ;; + cleanup) just clean && find . -name "*.orig" -delete && find . -name "*~" -delete ;; + update) just deps && just validate ;; + *) echo "Unknown: {{task}}. Use: all, cleanup, update" && exit 1 ;; + esac + +# ═══════════════════════════════════════════════════════════════════════════════ +# COMBINATORIC MATRIX RECIPES +# ═══════════════════════════════════════════════════════════════════════════════ + +# Build matrix: [debug|release] x [target] x [features] +build-matrix mode="debug" target="" features="": + @echo "Build matrix: mode={{mode}} target={{target}} features={{features}}" + +# Test matrix: [unit|integration|e2e|all] x [verbosity] x [parallel] +test-matrix suite="unit" verbosity="normal" parallel="true": + @echo "Test matrix: suite={{suite}} verbosity={{verbosity}} parallel={{parallel}}" + +# CI matrix: [lint|test|build|security|all] x [quick|full] +ci-matrix stage="all" depth="quick": + @echo "CI matrix: stage={{stage}} depth={{depth}}" + +# Show all matrix combinations +combinations: + @echo "=== Combinatoric Matrix Recipes ===" + @echo "" + @echo "Build Matrix: just build-matrix [debug|release] [target] [features]" + @echo "Test Matrix: just test-matrix [unit|integration|e2e|all] [verbosity] [parallel]" + @echo "Container: just container-matrix [build|run|push|shell|scan] [registry] [tag] (needs container module)" + @echo "CI Matrix: just ci-matrix [lint|test|build|security|all] [quick|full]" + +# ═══════════════════════════════════════════════════════════════════════════════ +# VERSION CONTROL +# ═══════════════════════════════════════════════════════════════════════════════ + +# Show git status +status: + @git status --short + +# Show recent commits +log count="20": + @git log --oneline -{{count}} + +# Generate CHANGELOG.md with git-cliff +changelog: + @command -v git-cliff >/dev/null || { echo "git-cliff not found — install: cargo install git-cliff"; exit 1; } + git cliff --config .machine_readable/configs/git-cliff/cliff.toml --output CHANGELOG.md + @echo "Generated CHANGELOG.md" + +# Preview changelog for unreleased commits (does not write) +changelog-preview: + @command -v git-cliff >/dev/null || { echo "git-cliff not found — install: cargo install git-cliff"; exit 1; } + git cliff --config .machine_readable/configs/git-cliff/cliff.toml --unreleased --strip header + +# Tag a new release (usage: just release-tag 1.2.3) +release-tag version: + #!/usr/bin/env bash + TAG="v{{version}}" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "Tag $TAG already exists" + exit 1 + fi + just changelog + git add CHANGELOG.md + git commit -m "chore(release): prepare $TAG" + git tag -a "$TAG" -m "Release $TAG" + echo "Created tag $TAG — push with: git push origin main --tags" + +# ═══════════════════════════════════════════════════════════════════════════════ +# UTILITIES +# ═══════════════════════════════════════════════════════════════════════════════ + +# Count lines of code +loc: + @find . \( -name "*.rs" -o -name "*.ex" -o -name "*.exs" -o -name "*.res" -o -name "*.gleam" -o -name "*.zig" -o -name "*.idr" -o -name "*.hs" -o -name "*.ncl" -o -name "*.scm" -o -name "*.adb" -o -name "*.ads" \) -not -path './target/*' -not -path './_build/*' 2>/dev/null | xargs wc -l 2>/dev/null | tail -1 || echo "0" + +# Show TODO comments +todos: + @grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.rs" --include="*.ex" --include="*.res" --include="*.gleam" --include="*.zig" --include="*.idr" --include="*.hs" . 2>/dev/null || echo "No TODOs" + +# Open in editor +edit: + ${EDITOR:-code} . + +# Run high-rigor security assault using panic-attacker +maint-assault: + @./.machine_readable/scripts/maintenance/maint-assault.sh + +# Run panic-attacker pre-commit scan (foundational floor-raise requirement) +assail: + @command -v panic-attack >/dev/null 2>&1 && panic-attack assail . || echo "WARN: panic-attack not found — install from https://github.com/hyperpolymath/panic-attacker" + + +# Self-diagnostic — checks dependencies, permissions, paths +doctor: + @echo "Running diagnostics for rsr-template-repo..." + @echo "Checking required tools..." + @command -v just >/dev/null 2>&1 && echo " [OK] just" || echo " [FAIL] just not found" + @command -v git >/dev/null 2>&1 && echo " [OK] git" || echo " [FAIL] git not found" + @echo "Checking for hardcoded paths..." + @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" + @echo "Diagnostics complete." + +# Guided tour of key features +tour: + @echo "=== rsr-template-repo Tour ===" + @echo "" + @echo "1. Project structure:" + @ls -la + @echo "" + @echo "2. Available commands: just --list" + @echo "" + @echo "3. Read README.adoc for full overview" + @echo "4. Read EXPLAINME.adoc for architecture decisions" + @echo "5. Run 'just doctor' to check your setup" + @echo "" + @echo "Tour complete! Try 'just --list' to see all available commands." + +# Open feedback channel with diagnostic context +help-me: + @echo "=== rsr-template-repo Help ===" + @echo "Platform: $(uname -s) $(uname -m)" + @echo "Shell: $SHELL" + @echo "" + @echo "To report an issue:" + @echo " https://github.com/hyperpolymath/rsr-template-repo/issues/new" + @echo "" + @echo "Include the output of 'just doctor' in your report." + +# ═══════════════════════════════════════════════════════════════════════════════ +# FORMAL VERIFICATION (PROOFS) — see build/just/proofs.just +# ═══════════════════════════════════════════════════════════════════════════════ + +import? "build/just/proofs.just" + +# ═══════════════════════════════════════════════════════════════════════════════ +# SESSION MANAGEMENT (THIN BINDINGS TO CENTRAL STANDARDS) +# ═══════════════════════════════════════════════════════════════════════════════ + +# Show canonical session-management command model +session-help: + @echo "Canonical command model:" + @echo " intake repo " + @echo " checkpoint change " + @echo " verify maintenance " + @echo " verify substantial " + @echo " verify release " + @echo " close planned " + @echo " close urgent " + @echo " recover repo " + @echo " handover full " + @echo " handover split " + @echo " handover model " + @echo " handover human " + @echo "" + @echo "Use Just aliases below (thin wrappers around ./session/dispatch.sh)." + +# Canonical aliases (friendly recipe names that map to canonical commands) +intake-repo path=".": + @./session/dispatch.sh intake repo "{{path}}" + +checkpoint-change path=".": + @./session/dispatch.sh checkpoint change "{{path}}" + +verify-maintenance path=".": + @./session/dispatch.sh verify maintenance "{{path}}" + +verify-substantial path=".": + @./session/dispatch.sh verify substantial "{{path}}" + +verify-release path=".": + @./session/dispatch.sh verify release "{{path}}" + +close-planned path=".": + @./session/dispatch.sh close planned "{{path}}" + +close-urgent path=".": + @./session/dispatch.sh close urgent "{{path}}" + +recover-repo path=".": + @./session/dispatch.sh recover repo "{{path}}" + +handover-full path=".": + @./session/dispatch.sh handover full "{{path}}" + +handover-split path=".": + @./session/dispatch.sh handover split "{{path}}" + +handover-model path=".": + @./session/dispatch.sh handover model "{{path}}" + +handover-human path=".": + @./session/dispatch.sh handover human "{{path}}" + +secret-scan-trufflehog: + @command -v trufflehog >/dev/null && trufflehog filesystem . --only-verified || true diff --git a/.machine_readable/contractiles/README.adoc b/.machine_readable/contractiles/README.adoc new file mode 100644 index 0000000..913728b --- /dev/null +++ b/.machine_readable/contractiles/README.adoc @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell += Contractiles Template Set +:toc: +:sectnums: + +This directory contains the canonical contractile templates for the +hyperpolymath estate. `rsr-template-repo` mirrors the standards master +structure; copy `.machine_readable/contractiles/` into a new repo to +establish a consistent operational, validation, trust, recovery, +aspiration, and service-automation framework. + +Each verb directory holds a *trident* of files: + +* `file.a2ml` — the project-specific declaration (data) +* `.ncl` — the paired Nickel runner (pedigree + schema + run policy) +* `.k9.ncl` — the k9 service-automation component (trust-tiered) + +A per-verb `.manifest.a2ml` asserts that exactly these three files +constitute the trident, pins their content-hashes, and requires the +cross-references to round-trip — no partial publication is permitted. + +Anything else in a verb directory is human-only notes or archive; machines +ignore it. Filenames use lowercase verb in the `.ncl` name and noun-form +PascalCase in the A2ML (e.g. `intend.ncl` + `Intentfile.a2ml`, +`must.ncl` + `Mustfile.a2ml`). + +All verb runners import `_base.ncl` (shared pedigree + run-defaults + +probe-schema). The `INDEX.a2ml` registry catalogues every verb; consumers +(CI scripts, the contractile CLI, Hypatia rules) SHOULD read it to discover +available verbs rather than hard-coding the list. See +`docs/CONTRACTILE-SPEC.adoc` for the normative specification. + +== Verbs (6 + k9 exception) + +[cols="1,2,3", options="header"] +|=== +| Verb | A2ML file | Role + +| `must` +| `must/Mustfile.a2ml` +| Release-blocking invariants that must hold. Gating — fails block. + +| `trust` +| `trust/Trustfile.a2ml` +| Trust boundary, allowed actions, integrity checks. Gating. + +| `adjust` +| `adjust/Adjustfile.a2ml` +| Controlled corrective actions — bounded drift tolerances and responses. + +| `dust` +| `dust/Dustfile.a2ml` +| Rollback, recovery, and deprecation semantics. Report + act on undo. + +| `bust` +| `bust/Bustfile.a2ml` +| Breakage, expiry, and hard-stop conditions. Gating — declares "this is + broken" rather than "this must stay healthy". + +| `intend` +| `intend/Intentfile.a2ml` +| North-star: committed next-actions ([[intents]] with probes) AND horizon + aspirations ([[wishes]] grouped near/mid/far). Non-gating (report only). + Absorbed the deprecated `lust` verb 2026-04-18. +|=== + +NOTE: The `lust/` verb was deprecated 2026-04-18 (name had unwanted +associations). Its [[wishes]] semantics live inside `intend/Intentfile.a2ml` +as a second section alongside [[intents]]. Any `lust/` dir encountered in +an estate repo is drift and should be removed. + +== k9 — Service-Automation Layer (EXCEPTION to the one-verbfile rule) + +IMPORTANT: `k9/` is **not a contractile verb** and does NOT follow the +`file.a2ml` + `.ncl` pattern. This is an intentional, documented +exception. Do not apply the naming rule to k9. + +=== Why k9 is different + +The six verb contractiles each declare *one concern per repo* in a single +xfile. k9 is not a concern; it is the *graded automation surface* that +enforces or validates concern declarations. k9 provides three trust-tier +*templates* that repos copy and instantiate: + +[cols="1,1,3", options="header"] +|=== +| File | Trust tier | Description + +| `k9/template-kennel.k9.ncl` +| Kennel +| Pure data. No subprocess, no filesystem write, no network. Safe for + metadata and declarative settings. + +| `k9/template-yard.k9.ncl` +| Yard +| Nickel evaluation with contracts and validation. No side effects. + +| `k9/template-hunt.k9.ncl` +| Hunt +| Full execution surface. Must declare side effects, support dry-run, and + be signed before the estate treats it as trustworthy automation. +|=== + +Each verb's `.k9.ncl` instantiates one of these tiers (the runners in +this set import `../k9/template-hunt.k9.ncl`). + +=== Why the naming rule does not apply + +The one-verb-one-Verbfile rule exists to enforce clean concern separation. +k9 is meta-infrastructure: it does not have a `K9file.a2ml` because it is +not a declarative xfile — it is a template set that instantiates into +specific repos. Applying the rule would produce a meaningless `K9file.a2ml` +with nothing to declare. + +=== Audit rule + +If a repo claims `k9` enforcement, each k9 component in that repo MUST +declare a `paired_xfile` pointing to a specific contractile xfile (e.g. +`../must/Mustfile.a2ml`). Floating k9 components with no paired xfile are +non-conformant. + +See `docs/CONTRACTILE-SPEC.adoc §k9-exception` for the normative statement. + +== Fill-In Instructions + +When copying this set into a new repo: + +1. Replace every template file's placeholders with project-specific content. +2. `Mustfile` — encode real invariants (schema versions, ports, required + checks), not generic samples. +3. `Trustfile` — point at actual keys, policies, and authority boundaries. +4. `Adjustfile` — define the drift tolerances and corrective actions the + repo commits to. +5. `Dustfile` — describe how this repo actually rolls back or retires + behaviour while preserving the audit trail. +6. `Bustfile` — declare real breakage / expiry / hard-stop conditions. +7. `Intentfile` — list tracked next-actions with observable probes + ([[intents]] section) AND horizon aspirations ([[wishes]] section). +8. Pair any `k9/*.k9.ncl` with a specific contractile via `paired_xfile`. + +== Intentfile: Commitments vs Aspirations — Two Sections, One File + +Since 2026-04-18 both axes live inside `intend/Intentfile.a2ml`: + +* `[[intents]]` is the **commitment axis**. Items here are tracked + next-actions with probes. Status progresses + declared → in_progress → done/deferred/retired. +* `[[wishes]]` is the **aspiration axis**. Items here are horizon goals + grouped near/mid/far. Status progresses + declared → in_progress → achieved/abandoned. + +If something is concrete enough to have a probe, it belongs in `[[intents]]`. +If it is a horizon-level desire that might never be acted on, it belongs +in `[[wishes]]`. A wish can graduate to an intent when a concrete plan +materialises. diff --git a/.machine_readable/contractiles/_base.ncl b/.machine_readable/contractiles/_base.ncl new file mode 100644 index 0000000..34ec621 --- /dev/null +++ b/.machine_readable/contractiles/_base.ncl @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: MPL-2.0 +# +# _base.ncl — Shared contractile base +# +# Provides four named schema fragments imported by every verb runner: +# +# pedigree_schema — canonical pedigree block shape +# status_core_doc — documentation of the shared status trio (String list) +# probe_schema — target structured probe form (spec only; verb files +# still use probe | String with TODO comments) +# run_defaults — default runner behaviour +# +# Usage in a verb runner: +# +# let base = import "../_base.ncl" in +# { +# pedigree = base.pedigree_schema & { +# contractile_verb = "must", +# semantics = "invariant", +# security = { +# leash = 'Kennel, +# trust_level = "read-only verification", +# allow_network = false, +# allow_filesystem_write = false, +# allow_subprocess = true, +# }, +# metadata = { +# name = "must-runner", +# version = "1.0.0", +# description = "...", +# paired_xfile = "Mustfile.a2ml", +# author = "Jonathan D.A. Jewell ", +# }, +# }, +# schema = { ... }, +# run = base.run_defaults & { on_any_fail = "exit-nonzero" }, +# } +# +# See: docs/CONTRACTILE-SPEC.adoc §Shared Base + +{ + # ------------------------------------------------------------------------- + # pedigree_schema + # + # The canonical shape of the `pedigree` block required in every verb runner. + # Verb runners merge this with their verb-specific values using Nickel's `&` + # (right-priority merge). Override contractile_verb, semantics, security.*, + # and metadata.* in each verb. + # ------------------------------------------------------------------------- + pedigree_schema = { + schema_version | String | default = "1.0.0", + contractile_verb | String | default = "UNSET", # MUST override in verb + semantics | String | default = "UNSET", # MUST override in verb + security = { + leash | [| 'Kennel, 'Yard, 'Hunt |] | default = 'Kennel, + trust_level | String | default = "UNSET", # MUST override in verb + allow_network | Bool | default = false, + allow_filesystem_write | Bool | default = false, + allow_subprocess | Bool | default = true, + # verb-specific additional security fields go in the verb's merge override: + # e.g. authorised_probes_only (trust), injection_scope (bust), + # destructive_mode_requires_flag (dust) + }, + metadata = { + name | String | default = "UNSET", # MUST override in verb + version | String | default = "1.0.0", + description | String | default = "UNSET", # MUST override in verb + paired_xfile | String | default = "UNSET", # MUST override in verb + author | String | default = "Jonathan D.A. Jewell ", + }, + }, + + # ------------------------------------------------------------------------- + # status_core_doc + # + # Documents the minimum shared status values present in every verb's status + # enum: declared, verified, failing. + # + # Nickel does not support structural enum extension, so verb files reproduce + # their full enum verbatim in `schema`. This field serves as documentation + # and for tooling that introspects the base. + # + # Verbs that extend status_core (i.e. all except must + trust): + # adjust: + 'partial + # bust: + 'drilled + # dust: 'declared, 'proposed, 'approved, 'removed (non-standard) + # intend: intents: 'declared, 'in_progress, 'done, 'deferred, 'retired + # wishes: 'declared, 'in_progress, 'achieved, 'abandoned + # (the wishes schema was absorbed from the deprecated `lust` + # verb 2026-04-18; lust/ dir removed estate-wide) + # + # See: docs/CONTRACTILE-SPEC.adoc §Per-Verb Extension + # ------------------------------------------------------------------------- + status_core_doc = "status_core values: declared | verified | failing — extended per verb", + + # ------------------------------------------------------------------------- + # probe_schema + # + # The TARGET structured probe form. See: docs/CONTRACTILE-SPEC.adoc §Probe + # + # IMPORTANT: This is a spec-only definition. Existing verb runner files still + # use `probe | String` with a `# TODO: migrate to probe_schema` comment. + # This is a breaking change; migration happens when the CLI supports both + # forms. + # + # Adopters writing new xfiles should prefer the structured form: + # probe = { + # command = "test -f my-file", + # timeout_seconds = 60, + # allowed_exit_codes = [0], + # permission_class = 'read_only, + # } + # ------------------------------------------------------------------------- + probe_schema = { + command | String, + timeout_seconds | Number | default = 300, + allowed_exit_codes | Array Number | default = [0], + permission_class + | [| 'read_only, 'filesystem_write, 'subprocess, 'network |] + | default = 'read_only, + }, + + # ------------------------------------------------------------------------- + # run_defaults + # + # Default runner behaviour. Verb runners merge this with verb-specific + # overrides using Nickel's `&` (right-priority merge). + # + # Most verbs override on_any_fail: + # "exit-nonzero" : hard gate (must, trust, bust, adjust-gating) + # "continue-with-warnings": advisory (dust, adjust) + # "continue" : never gate (intend — covers both intents and wishes) + # ------------------------------------------------------------------------- + run_defaults = { + on_pass = "continue", + on_any_fail = "exit-nonzero", + report_format = "a2ml", + emit_summary = true, + }, +} diff --git a/.machine_readable/contractiles/adjust/Adjustfile.a2ml b/.machine_readable/contractiles/adjust/Adjustfile.a2ml new file mode 100644 index 0000000..6f01e89 --- /dev/null +++ b/.machine_readable/contractiles/adjust/Adjustfile.a2ml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 +# Adjustfile — Drift-tolerance contract for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# Cumulative-drift catchment: tolerance bands + corrective actions. +# Authority: advisory (Yard) — continue-with-warnings; auto_fix where deterministic. +# Run with: adjust check +# Fix with: adjust fix (applies deterministic patches; advisory otherwise) + +@abstract: +Drift tolerances and corrective actions for rsr-template-repo. Unlike +MUST (hard gate), ADJUST tracks cumulative drift against tolerance bands +and proposes corrective actions. Advisory — it warns and trends, it does +not block. +@end + +## Template Drift + +### placeholder-drift +- description: Template placeholders should be replaced when copied +- tolerance: 0 placeholder markers in copied repos +- corrective: Search and replace all {{PLACEHOLDER}} markers +- severity: advisory +- notes: This check only applies to repos that copied from this template + +### template-version-drift +- description: Template version should match RSR spec version +- tolerance: Template version matches current RSR spec +- corrective: Update template to match latest RSR spec +- severity: advisory + +## Documentation Drift + +### readme-completeness +- description: README should document all template features +- tolerance: README covers all contractiles and directory structure +- corrective: Update README.adoc with missing sections +- severity: advisory + +### example-accuracy +- description: Examples in documentation should match actual template content +- tolerance: All code examples in docs are accurate +- corrective: Audit and fix examples in documentation +- severity: advisory + +## Structural Drift + +### contractile-sync +- description: All contractiles should have matching a2ml and ncl implementations +- tolerance: Every .a2ml has a corresponding .ncl +- corrective: Generate missing .ncl files from .a2ml +- severity: advisory + +### no-broken-symlinks +- description: No broken symbolic links in template structure +- tolerance: 0 broken symlinks +- corrective: Run symlink-check script +- severity: advisory + +## Accessibility Drift + +### adoc-not-md +- description: Template docs should prefer AsciiDoc +- tolerance: New prose docs are *.adoc +- corrective: Convert any new *.md to *.adoc +- severity: advisory + +### spdx-header-consistency +- description: All template files have correct SPDX headers +- tolerance: 0 files missing SPDX-License-Identifier +- corrective: Add SPDX headers to files that need them +- severity: advisory diff --git a/.machine_readable/contractiles/adjust/adjust.k9.ncl b/.machine_readable/contractiles/adjust/adjust.k9.ncl new file mode 100644 index 0000000..4974ba7 --- /dev/null +++ b/.machine_readable/contractiles/adjust/adjust.k9.ncl @@ -0,0 +1,167 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# adjust.k9.ncl — K9 trust-tier component of the adjust trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Adjustfile.a2ml (declaration) + adjust.ncl (runner). +# +# Verb: adjust (drift tolerances + corrective actions) +# Tier: Yard (validation with subprocess for measurement; +# no mutation beyond auto-fix where declared) +# Authority: advisory (continue-with-warnings; not blocking) +# +# adjust is the tolerance-band verb. Where must says "this MUST hold" +# and trust says "this MUST verify clean" (both binary), adjust says +# "drift ≤ X is acceptable; drift > X triggers action Y". Between them, +# adjust handles the subtle-drift territory that binary verbs can't. +# +# Cardinality: ONE adjust trident per repo. +# +# Failure-mode focus: adjust catches cumulative-small-drift patterns +# (E2 cosmetic churn accumulating into real regression, F2 context +# erosion causing gradual parameter drift). Where must flags "broken +# now", adjust flags "drifting toward broken". + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "adjust", + paired_xfile = "../adjust/Adjustfile.a2ml", + paired_runner = "../adjust/adjust.ncl", + + tier = 'Yard, + authority = 'advisory, + + metadata = { + name = "adjust-k9", + version = "1.0.0", + description = "Drift-tolerance + corrective-action runner. Fifth trident instance. First (Yard, advisory) authority pattern.", + paired_xfile = "Adjustfile.a2ml", + paired_runner = "adjust.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Yard, + trust_level = "tolerance measurement + declared auto-fix", + allow_network = false, + allow_filesystem_write_conditional = true, # auto_fix_when_available may edit + allow_subprocess = true, + probe_scope = 'measurement_plus_declared_fix, + }, + }, + + variance_schema = { + entry_id | String, + reason | String, + approved_by | String, + scope | String, + expires | String, + review_notes | String | optional, + # adjust-specific: which tolerance band the variance widens + tolerance_band_widened | String, + widened_to_value | String, + }, + + execution = { + triggers = [ 'session_close, 'on_demand, 'pre_push ], + + per_tolerance = { + measure_drift = true, + record_outcome = true, + respect_variance = true, + # adjust-specific authority: tolerance exceeded → warn, try + # auto-fix if declared, then continue. Never blocks. + on_exceeded = 'warn_and_attempt_fix, + on_auto_fix_applied = 'record_and_continue, + on_auto_fix_unavailable = 'record_as_advisory_drift, + # Cumulative-drift detection (adjust's specialty) + track_drift_trend_over_sessions = true, + flag_accelerating_drift = true, + }, + + evidence_sinks = [ + { kind = 'verisimdb, table = "contractile_executions", + schema = "contractile_execution_v1", + aux_tables = [ "adjust_drift_history" ] }, + { kind = 'drift_log, path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true }, + ], + + on_close = { + re_measure_all_tolerances = true, + diff_against_last_ratification = true, + emit_drift_entries_for_tolerance_exceeded = true, + surface_expired_variances = true, + surface_accelerating_drift = true, + # adjust is advisory — does NOT block session close. + block_session_close_on_any_drift = false, + }, + + on_open = { + render_summary = 'plain_language, + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + include_tolerance_trend_summary = true, + + negotiation = { + required = true, + ai_required_inputs = [ + 'timeline_realism, + 'industry_standards, + 'audience_feasibility, + 'resulting_invariants, + 'ecosystem_dependencies, + ], + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + }, + }, + + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the tolerance bands and corrective actions. I accept accountability for reviewing drift warnings rather than muting them, and for re-tuning tolerances via amendment when the intended operating envelope changes.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will surface tolerance breaches and accelerating-drift patterns at session close; I will propose corrective actions rather than widening tolerances silently; I will require amendment for legitimate tolerance re-tuning, not quiet band-widening.", + signature_required = true, + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + includes_tolerance_bands_snapshot = true, + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, + }, + }, + }, + + failure_mode_defenses = [ + 'A1_enthusiasm_capture, + 'C3_helpfulness_inflation, # helpful additions surfaced if they widen tolerances silently + 'C4_modernization_drift, + 'E2_cosmetic_churn, # adjust tracks cumulative churn + 'F2_context_window_erosion, # parameter drift across sessions detected + ], +} diff --git a/.machine_readable/contractiles/adjust/adjust.manifest.a2ml b/.machine_readable/contractiles/adjust/adjust.manifest.a2ml new file mode 100644 index 0000000..49a156b --- /dev/null +++ b/.machine_readable/contractiles/adjust/adjust.manifest.a2ml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: MPL-2.0 +# adjust.manifest.a2ml — Trident coherence manifest for the adjust verb. +# Author: Jonathan D.A. Jewell +# +# Fifth trident instance. First (Yard, advisory) authority pattern — +# complements the (Hunt, blocking) triple (must + trust + bust) and +# the (Hunt, reporting) north-star (intend). + +--- +trident_version = "1.0.0" +verb = "adjust" +semantics = "drift tolerances + corrective actions" +cardinality = "one per repo" +authority = "advisory (continue-with-warnings)" + +[[files]] +role = "declaration" +path = "Adjustfile.a2ml" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "runner" +path = "adjust.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "k9_component" +path = "adjust.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[cross_refs] +runner_paired_xfile = "Adjustfile.a2ml" +k9_paired_xfile = "../adjust/Adjustfile.a2ml" +k9_paired_runner = "../adjust/adjust.ncl" + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "adjust trident — canonical template in rsr-template-repo. (Yard, advisory) authority pattern. Specialises in cumulative-drift catchment — tolerance bands + trend tracking + auto-fix-where-declared. Advisory (continue-with-warnings). Copy this trident into a new repo and define its drift tolerances and corrective actions." + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "Adjustfile.a2ml and adjust.ncl pre-existed. This manifest + adjust.k9.ncl complete the trident. Exercises the Yard tier + advisory authority for the first time; on_exceeded = 'warn_and_attempt_fix rather than 'fail. adjust-specific track_drift_trend_over_sessions + flag_accelerating_drift." diff --git a/.machine_readable/contractiles/adjust/adjust.ncl b/.machine_readable/contractiles/adjust/adjust.ncl new file mode 100644 index 0000000..d6c24f0 --- /dev/null +++ b/.machine_readable/contractiles/adjust/adjust.ncl @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: MPL-2.0 +# Adjust — accessibility runner +# +# Pairs with: Adjustfile.a2ml (same directory) +# Verb: adjust +# Semantics: accessibility compliance (WCAG 2.1 AA baseline). Gating where +# a deterministic fix exists; advisory where human review needed. +# CLI: `contractile adjust check` → run all probes, list violations +# `contractile adjust fix` → apply deterministic fixes where defined +# +# Anything else in this directory is human-only notes/archive; machines ignore. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "adjust", + semantics = "accessibility compliance", + security = { + leash = 'Kennel, + trust_level = "fixes allowed where deterministic", + allow_network = false, + allow_filesystem_write = true, # `adjust fix` may write (deterministic patches only) + allow_subprocess = true, + }, + metadata = { + name = "adjust-runner", + version = "1.0.0", + description = "Evaluates accessibility requirements from Adjustfile.a2ml. Fixes deterministic items; flags the rest for human review.", + paired_xfile = "Adjustfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + schema = { + requirements + | Array { + id | String, + description | String, + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String, + # status_core values: 'declared, 'verified, 'failing; adjust adds 'partial + status | [| 'declared, 'partial, 'verified, 'failing |] | default = 'declared, + compliance | String | optional, # e.g. "WCAG 2.1 AA" + notes | String | optional, + fix | String | optional, # deterministic fix command (optional) + }, + }, + + # Runner behaviour — inherits from base.run_defaults. + # adjust is advisory (continue-with-warnings) not a hard gate. + # auto_fix_when_available is adjust-specific. + run = base.run_defaults & { + on_any_fail = "continue-with-warnings", # accessibility is progress-tracked, not a hard gate by default + report_format = "a2ml", + emit_summary = true, + auto_fix_when_available = true, + }, +} diff --git a/.machine_readable/contractiles/bust/Bustfile.a2ml b/.machine_readable/contractiles/bust/Bustfile.a2ml new file mode 100644 index 0000000..c7fec2b --- /dev/null +++ b/.machine_readable/contractiles/bust/Bustfile.a2ml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: MPL-2.0 +# Bustfile — failure mode contractile for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# Paired runner: bust.ncl +# Verb: bust +# Semantics: Every declared failure mode must have a working recovery path +# that has been exercised. Status moves: +# declared → drilled (probe run) → verified (recovery confirmed) +# or → failing (recovery broken) +# +# CLI: +# contractile bust check → list failure modes + recovery status +# contractile bust drill → inject failures, verify recovery paths +# +# This repository: rsr-template-repo is the canonical template for RSR compliance. +# Failure modes here relate to template distribution and substitution. + +@abstract: +Bustfile for rsr-template-repo. Lists failure modes specific to the template +repository itself, particularly around template distribution, substitution, +and synchronization across the hyperpolymath estate. +@end + +## Failure Modes + +### template-substitution-failure +- class: template_processing +- description: Template substitution fails when initializing a new repo from this template +- injection_probe: "cp -r rsr-template-repo test-repo && cd test-repo && sed -i 's/rsr-template-repo/TEST/g' .machine_readable/contractiles/Intentfile.a2ml && grep -q 'TEST' .machine_readable/contractiles/Intentfile.a2ml" +- recovery_probe: "git -C test-repo diff --quiet .machine_readable/contractiles/Intentfile.a2ml" +- expected_recovery_time_seconds: 10 +- status: declared +- notes: Verify that substitution scripts handle all placeholder replacements correctly + +### sync-drift-between-repos +- class: synchronization +- description: Drift occurs between rsr-template-repo and other repos after template updates +- injection_probe: "echo 'template_updated' > /tmp/test_drift_marker" +- recovery_probe: "test -f /tmp/test_drift_marker && rm /tmp/test_drift_marker" +- expected_recovery_time_seconds: 60 +- status: declared +- notes: The estate-wide sync scripts (see scripts/) should prevent this; verify with scripts/verify-sync.sh + +### contractile-parse-error +- class: contractile_format +- description: A contractile file fails to parse due to syntax errors +- injection_probe: "echo 'invalid syntax' >> rsr-template-repo/.machine_readable/contractiles/Intentfile.a2ml" +- recovery_probe: "git checkout rsr-template-repo/.machine_readable/contractiles/Intentfile.a2ml" +- expected_recovery_time_seconds: 5 +- status: declared +- notes: All .a2ml files should be valid A2ML; use a2ml-validate runner diff --git a/.machine_readable/contractiles/bust/bust.k9.ncl b/.machine_readable/contractiles/bust/bust.k9.ncl new file mode 100644 index 0000000..a5e5e73 --- /dev/null +++ b/.machine_readable/contractiles/bust/bust.k9.ncl @@ -0,0 +1,162 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# bust.k9.ncl — K9 trust-tier component of the bust trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Bustfile.a2ml (declaration) + bust.ncl (runner). +# +# Verb: bust (hard-stop / expiry / "must-not-run") +# Tier: Hunt-read-only (subprocess probes for expiry/state checks) +# Authority: blocking (HARD GATE on declared broken states) +# +# bust is the "this is broken, this has expired, this must not run" +# declarative surface. Where must asserts invariants that must hold, +# bust asserts failure states that must not be re-entered. Complement +# to must: together they bound the "acceptable operating state" from +# above (must) and below (bust). +# +# Cardinality: ONE bust trident per repo. +# +# Failure-mode focus: bust catches deprecated-path-still-called +# patterns (C2 capability collapse attempts where an AI reintroduces +# retired code), expiry-exceeded state (certificates / tokens / grants +# past their expiry), and the "it works, ship it" pattern where a +# caller silently starts using a must-not-run API. + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "bust", + paired_xfile = "../bust/Bustfile.a2ml", + paired_runner = "../bust/bust.ncl", + + tier = 'Hunt, + authority = 'blocking, + + metadata = { + name = "bust-k9", + version = "1.0.0", + description = "Hard-stop / expiry / must-not-run gate. Fourth trident instance. Completes the blocking-authority triple (must + trust + bust).", + paired_xfile = "Bustfile.a2ml", + paired_runner = "bust.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Hunt, + signature_required = true, + trust_level = "read-only expiry + state-check with subprocess", + allow_network = false, + allow_filesystem_write = false, + allow_subprocess = true, + probe_scope = 'read_only, + }, + }, + + variance_schema = { + entry_id | String, + reason | String, + approved_by | String, + scope | String, + expires | String, + review_notes | String | optional, + severity_acknowledged | [| 'critical, 'high, 'medium |], + waived_consequence_description | String, + }, + + execution = { + triggers = [ 'session_close, 'on_demand, 'pre_push, 'pre_merge ], + + per_hard_stop = { + run_probe = true, + record_outcome = true, + respect_variance = true, + on_triggered = 'fail, # BLOCKING — bust condition hit = block + severity_escalation = 'honour, + # bust-specific: detect re-introduction of deprecated calls + flag_deprecated_reintroduction = true, + }, + + evidence_sinks = [ + { kind = 'verisimdb, table = "contractile_executions", + schema = "contractile_execution_v1", + aux_tables = [ "bust_triggers_history" ] }, + { kind = 'drift_log, path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true }, + ], + + on_close = { + re_execute_all_hard_stops = true, + diff_against_last_ratification = true, + emit_drift_entries_for_new_triggers = true, + surface_expired_variances = true, + block_session_close_on_critical_bust = true, + }, + + on_open = { + render_summary = 'plain_language, + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + include_silent_regressions = true, + + negotiation = { + required = true, + ai_required_inputs = [ + 'timeline_realism, + 'industry_standards, + 'audience_feasibility, + 'resulting_invariants, + 'ecosystem_dependencies, + ], + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + }, + }, + + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the declared hard-stop / expiry / must-not-run conditions. I accept accountability for not calling into must-not-run code paths, not ignoring expired tokens/grants, and not silently reintroducing deprecated patterns. I will raise a variance with severity acknowledgement if an exception is needed.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will refuse suggestions that reintroduce must-not-run patterns; I will surface bust triggers at session close; I will require variance-with-severity for any legitimate reintroduction of a deprecated path rather than silently allowing it.", + signature_required = true, + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, + }, + }, + }, + + failure_mode_defenses = [ + 'A1_enthusiasm_capture, + 'C2_capability_collapse, # prevents reintroduction of retired capability + 'C4_modernization_drift, # bust prevents silent re-adoption of deprecated libs + 'D4_error_hiding, + 'E1_refactor_stampede, # refactor that reintroduces deprecated path caught + 'F1_across_session_forgetting, # bust triggers persist across sessions + ], +} diff --git a/.machine_readable/contractiles/bust/bust.manifest.a2ml b/.machine_readable/contractiles/bust/bust.manifest.a2ml new file mode 100644 index 0000000..762bade --- /dev/null +++ b/.machine_readable/contractiles/bust/bust.manifest.a2ml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: MPL-2.0 +# bust.manifest.a2ml — Trident coherence manifest for the bust verb. +# Author: Jonathan D.A. Jewell +# +# Fourth trident instance. Completes the blocking-authority triple: +# must (persistent invariants), trust (ephemeral transactions), +# bust (hard-stop / expiry / must-not-run). Between them, every +# release-blocking contractile concern is covered. + +--- +trident_version = "1.0.0" +verb = "bust" +semantics = "hard-stop / expiry / must-not-run declarations" +cardinality = "one per repo" +authority = "blocking (hard gate)" + +[[files]] +role = "declaration" +path = "Bustfile.a2ml" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "runner" +path = "bust.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "k9_component" +path = "bust.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[cross_refs] +runner_paired_xfile = "Bustfile.a2ml" +k9_paired_xfile = "../bust/Bustfile.a2ml" +k9_paired_runner = "../bust/bust.ncl" + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "bust trident — canonical template in rsr-template-repo. Completes the blocking-authority triple (must + trust + bust). Specialises in deprecated-path-reintroduction catchment. Declares hard-stop / expiry / must-not-run conditions. Copy this trident into a new repo and declare its real breakage / expiry conditions." + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "Bustfile.a2ml and bust.ncl pre-existed. This manifest + bust.k9.ncl complete the trident. Inherits the full negotiation+accountability schema from intend.k9.ncl v2.0.0 + trust/must extensions; adds flag_deprecated_reintroduction for C2-defense specificity." diff --git a/.machine_readable/contractiles/bust/bust.ncl b/.machine_readable/contractiles/bust/bust.ncl new file mode 100644 index 0000000..fc8cb8c --- /dev/null +++ b/.machine_readable/contractiles/bust/bust.ncl @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: MPL-2.0 +# Bust — error-handling / failure-recovery runner +# +# Pairs with: Bustfile.a2ml (same directory) +# Verb: bust +# Semantics: every declared failure mode must have a recovery path that has +# been exercised. Runner injects failures (via declared probes) +# and verifies the recovery path works. Hard gate on any +# failure-mode with missing or broken recovery. +# CLI: `contractile bust check` → list failure modes + recovery status +# `contractile bust drill` → inject declared failures, verify recovery +# +# Anything else in this directory is human-only notes/archive; machines ignore. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "bust", + semantics = "error handling + failure recovery", + security = { + leash = 'Kennel, + trust_level = "controlled failure injection; scoped to system-under-test", + allow_network = false, + allow_filesystem_write = true, # drills may write transient state (tmp dirs, test DBs) + allow_subprocess = true, + injection_scope = "system-under-test-only", + }, + metadata = { + name = "bust-runner", + version = "1.0.0", + description = "Exercises declared failure modes and verifies recovery paths. Hard-gates on any failure mode without working recovery.", + paired_xfile = "Bustfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + schema = { + failure_modes + | Array { + id | String, + description | String, + class | [| 'network, 'disk_full, 'oom, 'timeout, 'partial_write, 'panic, 'crash, 'rollback, 'concurrency |], + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + injection_probe | String, # command that deterministically causes this failure + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + recovery_probe | String, # command that verifies recovery (exit 0 = recovered) + expected_recovery_time_seconds | Number | default = 30, + # status_core values: 'declared, 'verified, 'failing; bust adds 'drilled + status | [| 'declared, 'drilled, 'verified, 'failing |] | default = 'declared, + notes | String | optional, + }, + }, + + # Runner behaviour — inherits from base.run_defaults. + # bust adds record_recovery_times for performance tier feeding. + run = base.run_defaults & { + on_any_fail = "exit-nonzero", # missing or broken recovery blocks merge + report_format = "a2ml", + emit_summary = true, + record_recovery_times = true, # feeds the performance tier + }, +} diff --git a/.machine_readable/contractiles/dust/Dustfile.a2ml b/.machine_readable/contractiles/dust/Dustfile.a2ml new file mode 100644 index 0000000..c6bf986 --- /dev/null +++ b/.machine_readable/contractiles/dust/Dustfile.a2ml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: MPL-2.0 +# Dustfile — Cleanup and hygiene contract for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# Paired runner: dust.ncl +# Verb: dust +# Semantics: What should be cleaned up. Housekeeping, not blockers. +# +# This repository: rsr-template-repo is the canonical template. +# Cleanup items here ensure the template itself remains pristine. + +@abstract: +Cleanup and hygiene items for rsr-template-repo. These are maintenance tasks +that ensure the template repository remains clean and ready for distribution +to new repositories. +@end + +## Stale Files + +### no-template-artifacts +- description: No generated files from template testing in root +- run: test -z "$(ls template-test-* 2>/dev/null)" +- severity: info +- notes: Template testing should use /tmp or dedicated test directories + +### no-example-placeholders +- description: No example placeholder files (EXAMPLE-, SAMPLE-) in contractiles/ +- run: test -z "$(find .machine_readable/contractiles/ -name 'EXAMPLE-*' -o -name 'SAMPLE-*' 2>/dev/null)" +- severity: warning +- notes: All placeholders should be replaced with actual content or removed + +### no-old-contractile-formats +- description: No old .contractile or .hs files remaining +- run: test -z "$(find .machine_readable/contractiles/ \( -name '*.contractile' -o -name '*.hs' \) 2>/dev/null)" +- severity: warning +- notes: All contractiles should be .a2ml format + +## Format Duplicates + +### no-duplicate-justfile +- description: Only one Justfile (hardlinked from root to .machine_readable/contractiles/) +- run: test $(stat -c '%i' Justfile) = $(stat -c '%i' .machine_readable/contractiles/Justfile 2>/dev/null) +- severity: warning +- notes: Justfile should be hardlinked, not copied + +### no-duplicate-readme-format +- description: Only one README format in contractiles/ (.adoc canonical) +- run: test ! -f .machine_readable/contractiles/README.md +- severity: info + +## Template Hygiene + +### no-stale-template-references +- description: No references to rsr-template-repo in generic template files +- run: test -z "$(grep -r 'rsr-template-repo' machine-readable-design/ 2>/dev/null)" +- severity: warning +- notes: Generic templates should use {{PROJECT_NAME}} or similar placeholders + +### version-sync-checked +- description: Version in canonical-directory-structure matches .machine_readable/contractiles +- verification: compare version identifiers in both locations +- severity: info diff --git a/.machine_readable/contractiles/dust/dust.k9.ncl b/.machine_readable/contractiles/dust/dust.k9.ncl new file mode 100644 index 0000000..6c51e54 --- /dev/null +++ b/.machine_readable/contractiles/dust/dust.k9.ncl @@ -0,0 +1,172 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# dust.k9.ncl — K9 trust-tier component of the dust trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Dustfile.a2ml (declaration) + dust.ncl (runner). +# +# Verb: dust (rollback / recovery / deprecation) +# Tier: Yard (audit + structural checks; destructive +# actions gated behind --apply flag + +# explicit per-item approval) +# Authority: advisory (continue-with-warnings) +# +# dust is the retirement + audit-trail verb. Rollback paths, deprecation +# markers, evidence-preservation semantics. Where bust declares +# "broken, don't run", dust declares "how to safely undo / retire / roll +# back". Complement to bust — bust marks the dead end, dust describes +# the exit ramp. +# +# Cardinality: ONE dust trident per repo. +# +# Failure-mode focus: dust is the audit-trail preservation verb — +# defends against E1 refactor stampede (check audit trail still +# intact) and against silent removal (anything removed must have a +# rollback path; anything retired must preserve the evidence of its +# previous existence). + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "dust", + paired_xfile = "../dust/Dustfile.a2ml", + paired_runner = "../dust/dust.ncl", + + tier = 'Yard, + authority = 'advisory, + + metadata = { + name = "dust-k9", + version = "1.0.0", + description = "Rollback + deprecation + audit-trail runner. Sixth trident instance — completes the full verb set.", + paired_xfile = "Dustfile.a2ml", + paired_runner = "dust.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Yard, + trust_level = "audit-trail verification + structural checks", + allow_network = false, + # dust is the verb that ACTUALLY wants filesystem write — to + # execute declared rollback/removal — but only behind explicit + # --apply flag + per-item approval. Default is dry-run. + allow_filesystem_write_conditional = true, + allow_subprocess = true, + destructive_action_gating = { + default_mode = 'dry_run, + requires_flag = "--apply", + requires_per_item_approval = true, + approval_mechanism = 'explicit_user_signature, + }, + }, + }, + + variance_schema = { + entry_id | String, + reason | String, + approved_by | String, + scope | String, + expires | String, + review_notes | String | optional, + rollback_path_preserved | Bool, # dust-specific: did the variance preserve rollback? + }, + + execution = { + triggers = [ 'session_close, 'on_demand ], + + per_retirement = { + verify_rollback_path_documented = true, + verify_audit_trail_preserved = true, + respect_variance = true, + on_rollback_path_missing = 'warn, # advisory, not block + on_audit_trail_broken = 'warn, # advisory, not block + # dust-specific: flag any retirement that has been requested but + # lacks proper rollback documentation + flag_unsafe_retirement = true, + }, + + evidence_sinks = [ + { kind = 'verisimdb, table = "contractile_executions", + schema = "contractile_execution_v1", + aux_tables = [ "dust_retirement_history" ] }, + { kind = 'drift_log, path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true }, + ], + + on_close = { + re_verify_all_retirement_paths = true, + diff_against_last_ratification = true, + emit_drift_entries_for_missing_rollback = true, + emit_drift_entries_for_broken_audit_trail = true, + surface_expired_variances = true, + block_session_close_on_any_drift = false, # advisory + }, + + on_open = { + render_summary = 'plain_language, + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + + negotiation = { + required = true, + ai_required_inputs = [ + 'timeline_realism, + 'industry_standards, + 'audience_feasibility, + 'resulting_invariants, + 'ecosystem_dependencies, + ], + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + }, + }, + + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the declared rollback paths and deprecation markers. I accept accountability for preserving audit trails when retiring code, and for ensuring every retired capability has a documented rollback path. I will not silently delete evidence of prior state.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will verify audit-trail preservation in any retirement / rollback / deprecation I perform; I will refuse silent deletion of prior-state evidence; I will require rollback-path documentation before accepting a retirement request; I will operate in dry-run mode by default and require explicit --apply + per-item approval for destructive actions.", + signature_required = true, + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + includes_retirement_schedule = true, + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, + }, + }, + }, + + failure_mode_defenses = [ + 'A1_enthusiasm_capture, + 'C2_capability_collapse, # retirement without rollback path = capability collapse + 'D5_sycophancy, # AI won't agree to silent deletion + 'E1_refactor_stampede, # audit trail preservation check + 'E2_cosmetic_churn, + 'F1_across_session_forgetting, # retirement history tracked cross-session + ], +} diff --git a/.machine_readable/contractiles/dust/dust.manifest.a2ml b/.machine_readable/contractiles/dust/dust.manifest.a2ml new file mode 100644 index 0000000..fbd132c --- /dev/null +++ b/.machine_readable/contractiles/dust/dust.manifest.a2ml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: MPL-2.0 +# dust.manifest.a2ml — Trident coherence manifest for the dust verb. +# Author: Jonathan D.A. Jewell +# +# Sixth + final trident instance. Completes the full verb set — +# the estate now has tridents for every contractile verb. + +--- +trident_version = "1.0.0" +verb = "dust" +semantics = "rollback / recovery / deprecation / audit-trail preservation" +cardinality = "one per repo" +authority = "advisory (continue-with-warnings)" + +[[files]] +role = "declaration" +path = "Dustfile.a2ml" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "runner" +path = "dust.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "k9_component" +path = "dust.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[cross_refs] +runner_paired_xfile = "Dustfile.a2ml" +k9_paired_xfile = "../dust/Dustfile.a2ml" +k9_paired_runner = "../dust/dust.ncl" + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "dust trident — canonical template in rsr-template-repo. Specialises in audit-trail preservation + rollback-path verification. Yard tier with destructive-action gating (dry-run default; --apply + per-item approval required for mutations). Copy this trident into a new repo and describe how it actually rolls back or retires behaviour." + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "Dustfile.a2ml and dust.ncl pre-existed. This manifest + dust.k9.ncl complete the trident and the full verb set. All 6 verbs now on trident shape: intend (Hunt, reporting), trust (Hunt, blocking), must (Hunt-read-only, blocking), bust (Hunt-read-only, blocking), adjust (Yard, advisory), dust (Yard, advisory)." + +[[history]] +date = "2026-04-18" +event = "verb-set-complete" +note = "Full estate trident coverage. Blocking-authority triple (must/trust/bust) handles release-gating. Advisory pair (adjust/dust) handles drift-warning and audit-trail. Single reporting verb (intend) handles north-star. α two-axis surface fully exercised on all four (tier, authority) combinations used: (Hunt, reporting), (Hunt, blocking), (Hunt-read-only, blocking), (Yard, advisory). The contractile system is ready for the adversarial Gemini+Copilot drift pilot." diff --git a/.machine_readable/contractiles/dust/dust.ncl b/.machine_readable/contractiles/dust/dust.ncl new file mode 100644 index 0000000..36aa89b --- /dev/null +++ b/.machine_readable/contractiles/dust/dust.ncl @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: MPL-2.0 +# Dust — exnovation / code-removal runner +# +# Pairs with: Dustfile.a2ml (same directory) +# Verb: dust +# Semantics: exnovation. Identifies code, docs, files, dependencies that are +# candidates for REMOVAL. Advisory by default; can be flipped to +# active delete via `contractile dust sweep --apply`. +# CLI: `contractile dust find` → list removal candidates +# `contractile dust sweep` → dry-run removals +# `contractile dust sweep --apply` → actually delete (gated) +# +# Anything else in this directory is human-only notes/archive; machines ignore. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "dust", + semantics = "exnovation / removal", + security = { + leash = 'Kennel, + trust_level = "proposes deletion; --apply required to execute", + allow_network = false, + allow_filesystem_write = true, # --apply mode writes (deletes) + allow_subprocess = true, + destructive_mode_requires_flag = "--apply", + }, + metadata = { + name = "dust-runner", + version = "1.0.0", + description = "Identifies and optionally removes exnovation targets listed in Dustfile.a2ml. Destructive mode gated behind --apply.", + paired_xfile = "Dustfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + schema = { + removal_candidates + | Array { + id | String, + description | String, + target | String, # file / path / symbol / dep name + reason | String, # why it's a removal candidate + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String | optional, # command that confirms it's still removable + # dust has a non-standard status progression (no 'verified): + # 'declared → 'proposed → 'approved → 'removed + status | [| 'declared, 'proposed, 'approved, 'removed |] | default = 'declared, + approver | String | optional, # who signed off (for 'approved / 'removed) + notes | String | optional, + }, + }, + + # Runner behaviour — inherits from base.run_defaults. + # dust is advisory; apply_requires_approval is dust-specific. + run = base.run_defaults & { + on_any_fail = "continue-with-warnings", + report_format = "a2ml", + emit_summary = true, + apply_requires_approval = true, # only 'approved items get swept, even with --apply + }, +} diff --git a/.machine_readable/contractiles/intend/Intentfile.a2ml b/.machine_readable/contractiles/intend/Intentfile.a2ml new file mode 100644 index 0000000..ef74f45 --- /dev/null +++ b/.machine_readable/contractiles/intend/Intentfile.a2ml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: MPL-2.0 +# Intentfile (A2ML Canonical) — north-star contractile for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# Paired runner: intend.ncl +# Verb: intend +# +# Semantics: North-star contractile. Declares BOTH concrete committed +# next-actions AND horizon aspirations the project wishes to +# become. Two sections share one file because they answer +# the same question at different ranges: +# [[intents]] — "we WILL do this; track progress" +# status: declared → in_progress → done | +# deferred | retired +# [[wishes]] — "we WISH this were true; revisit later" +# status: declared → in_progress → achieved | +# abandoned +# grouped by horizon: near / mid / far. +# Non-gating — this is a report, not a gate. See the `must` +# contractile for hard gates. + +@abstract: +North-star contractile for rsr-template-repo. This repository is the +canonical template for Rhodium Standard Repository compliance. It provides +the scaffold that all hyperpolymath repos should copy and customize. +@end + +## Purpose + +The rsr-template-repo serves as the master template for all hyperpolymath +repositories. It contains the complete set of contractile files, machine-readable +specifications, and governance documentation that define the Rhodium Standard. + +Every new repository in the hyperpolymath estate should be initialized by +copying this template and substituting the placeholder values with +repo-specific content. + +## Anti-Purpose + +This repository is NOT: +- A general-purpose project scaffold for external use (hyperpolymath-only) +- A replacement for per-repo customization (all files must be bespoke) +- A static template that never changes (evolves with RSR spec) +- A runtime library or framework (build-time only) + +## If In Doubt + +If you are unsure whether a change is in scope, ask. Sensitive areas: +- .machine_readable/ contractile definitions +- RSR specification files +- Governance templates +- License policy documents + +## Committed Next-Actions + +### repo-initialization +- description: Provide just copy-and-substitute template for new repos +- probe: test -f scripts/init-repo.sh +- status: done +- notes: Run with source scripts/init-repo.sh + +### contractile-completeness +- description: Every RSR contractile has an a2ml and ncl implementation +- probe: ls .machine_readable/contractiles/*.a2ml | wc -l | grep -q "^6$" +- status: in_progress +- notes: Currently 6 contractile verbs: intend, must, trust, adjust, bust, dust + +### automation-scripts +- description: All repetitive tasks have just recipes +- probe: grep -c "^# " Justfile | grep -q "^[6-9][0-9]*$" +- status: in_progress + +## Wishes + +### Near Horizon + +#### cross-repo-validation +- description: Tooling to validate all repos against RSR spec +- horizon: near +- status: declared + +#### automated-substitution +- description: Script to automate repo-specific substitution in template +- horizon: near +- status: declared + +### Mid Horizon + +#### formal-verification +- description: Idris2 proofs for all critical contractile invariants +- horizon: mid +- status: declared + +### Far Horizon + +#### ecosystem-visualization +- description: Interactive graph of all hyperpolymath repos and dependencies +- horizon: far +- status: declared diff --git a/.machine_readable/contractiles/intend/intend.k9.ncl b/.machine_readable/contractiles/intend/intend.k9.ncl new file mode 100644 index 0000000..4c5abc8 --- /dev/null +++ b/.machine_readable/contractiles/intend/intend.k9.ncl @@ -0,0 +1,252 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# intend.k9.ncl — K9 trust-tier component of the intend trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Intentfile.a2ml (declaration) + intend.ncl (runner). +# Trident completeness is a hard precondition — a repo shipping +# Intentfile without this file AND its runner is an invalid trident; +# the contractile CLI's verify gate refuses partial publication. +# +# Verb: intend (north star — commitments + aspirations) +# Tier: Hunt (capability: subprocess probes may shell out) +# Authority: reporting (never blocks; drift-log only) +# +# Cardinality: ONE intend trident per repo (see feedback_contractile_ +# layout_rules.md). ANCHOR.a2ml is the sole multi-instance exception — +# it is NOT a verb contractile. +# +# Design commitments baked in (see memory trail 2026-04-18 for full +# context; key files referenced by name in annotations below): +# * α two-axis (tier × authority) — structurally separate capability +# from authority so "Hunt tier = can override" is impossible. +# * Variance schema first-class, not comment markers +# (feedback_audit_tool_suppression_design.md — structural > markers). +# * Sessional drift detection hooks (on_close, on_open). +# * Ratification at session open; drift log at session close. +# * Evidence sinks: VeriSimDB (queryable) + descriptiles/DRIFT.a2ml (repo-local). +# * Failure-mode defenses cross-referenced to the AI failure catalog. + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "intend", + paired_xfile = "../intend/Intentfile.a2ml", + paired_runner = "../intend/intend.ncl", + + # α two-axis declaration — capability × authority. + # intend is Hunt-capable (probes shell out) but reporting-authority + # (never blocks). must/trust/bust will declare (Hunt, blocking); + # adjust/dust will declare (Yard, advisory). Splitting the axes + # means "I'm Hunt-tier so I can override everything" is structurally + # impossible — authority is a separate field. + tier = 'Hunt, + authority = 'reporting, + + metadata = { + name = "intend-k9", + version = "2.0.0", # 1.0.0 (2026-04-18 AM): initial trident. + # 2.0.0 (2026-04-18 PM): negotiation + + # accountability + plain-language-translation + # schema baked into on_open — prerequisite for + # the adversarial Gemini+Copilot drift pilot. + description = "Executes Intentfile probes + emits drift log. Non-gating; reporting authority only. on_open hook implements negotiation-ratification-accountability protocol.", + paired_xfile = "Intentfile.a2ml", + paired_runner = "intend.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Hunt, + signature_required = true, + trust_level = "subprocess + filesystem-read", + allow_network = false, + allow_filesystem_write = false, # evidence sinks are indirected + allow_subprocess = true, + }, + }, + + # ------------------------------------------------------------------- + # Variance schema — P-shape scoped exceptions per entry. + # A variance suppresses a specific intent's or wish's obligation for a + # reason, with approver + expiry. Expired variance = effective + # re-imposition of the obligation. Unmet intent without a variance = + # drift, logged to the drift log. + # Per user 2026-04-18: variances are structural, not magic-comment + # markers — markers are gameable. + # ------------------------------------------------------------------- + variance_schema = { + entry_id | String, # which intent/wish id the variance applies to + reason | String, + approved_by | String, + scope | String, # path glob | session-id | "until-" + expires | String, # absolute date or condition + review_notes | String | optional, + }, + + # ------------------------------------------------------------------- + # Execution policy + # ------------------------------------------------------------------- + execution = { + # When the component runs. + # session_close is mandatory (the "picked up sessionally" check). + triggers = [ 'session_close, 'on_demand, 'pre_push ], + + # Per-intent execution. + per_intent = { + run_probe = true, + record_outcome = true, + respect_variance = true, # active variance suppresses failure + on_unmet = 'log_drift, # never 'fail — authority = reporting + }, + + # Per-wish execution (wishes are non-probeable; horizon-group only). + per_wish = { + run_probe = false, + emit_horizon_summary = true, + # Vertical alignment soft-check per user_descriptiles_is_contractile_ought.md: + # highest-level alignment is meta ↔ north-star (soft), not hard gate. + check_alignment_with_META = true, + }, + + # Evidence sinks — BOTH written, every execution. + # VeriSimDB = queryable machine record (feedback_verisimdb_policy.md). + # descriptiles/DRIFT.a2ml = repo-local append-only drift log (feedback_sessional_ + # drift_detection.md + user_descriptiles_is_contractile_ought.md descriptive role). + evidence_sinks = [ + { + kind = 'verisimdb, + table = "contractile_executions", + schema = "contractile_execution_v1", + }, + { + kind = 'drift_log, + path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true, + }, + ], + + # Session-close hook — the "picked up sessionally" requirement. + # Re-execute, diff against the last ratification, surface expired + # variances, emit drift entries for new failures. + on_close = { + re_execute_all_intents = true, + diff_against_last_ratification = true, + emit_drift_entries_for_new_failures = true, + surface_expired_variances = true, + }, + + # ----------------------------------------------------------------- + # Session-open hook — NEGOTIATION + RATIFICATION + ACCOUNTABILITY + # (user_contract_negotiation_and_accountability_pledge.md) + # (user_contractiles_agreed_at_session_start.md) + # + # Ratification is not passive acknowledgement; it is negotiation + # ending in an explicit accountability pledge from BOTH parties. + # Work cannot proceed before both pledges are on file. + # ----------------------------------------------------------------- + on_open = { + # --- Context presentation (pre-negotiation) --- + render_summary = 'plain_language, # metaphor-capture defense + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + + # --- Negotiation phase (five mandatory inputs) --- + # AI must surface all five before the user is asked to ratify. + # "Yes, and …" — not "yes". Missing any of the five = the + # negotiation is incomplete and work cannot proceed. + negotiation = { + required = true, # blank-cheque ratification refused + + # The five inputs the AI must contribute to the negotiation. + # Each is a structured field the agent is required to populate, + # not optional prose. See user_contract_negotiation_and_ + # accountability_pledge.md for the domain-language-rendering rule. + ai_required_inputs = [ + 'timeline_realism, # "this will take X; not Y" + 'industry_standards, # WCAG, ISO, OWASP, GDPR, licensing … + 'audience_feasibility, # real addressable user set + 'resulting_invariants, # what must/trust/adjust entries follow + 'ecosystem_dependencies, # libs, licences, threat-model implications + ], + + # User must actually engage with each input — not + # auto-approve. If user tries to skip ("just do it, I trust you") + # the system re-renders the obligations and requires the pledge. + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + + # The AI does the specification-form work. The user reviews the + # rendering in domain language and accepts / amends / pushes back. + # User never has to author Nickel schemas or decide on type + # specificity — that is the AI's translation responsibility, + # with auditable faithfulness. + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + # Failure mode this closes: user is forced to learn spec-theory + # (type refinement, Nickel contract grammar) to ratify a contract + # — which drives users away from ratification entirely. + }, + }, + + # --- Accountability pledge (both parties, explicit) --- + # Not "I read it" — "I am answerable for this obligation". + # Both pledges are required before work proceeds; both are recorded. + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the obligations as negotiated; I accept accountability for meeting the declared invariants and for the audience/timeline/standards consequences surfaced in negotiation.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will hold the user to the obligations as negotiated, including by surfacing drift at session close and refusing off-contract actions, even when the user is enthusiastic about them. If the user wishes to depart from the contract, I will require a variance or amendment, not silent acceptance.", + signature_required = true, + # Per user_contractile_is_contract_do_not_break.md — + # the AI is the holder of the line against enthusiasm drift. + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + # --- Policy: ratification output --- + # The ratification record IS the negotiation transcript + the + # accountability pledge combined. One document; future-session + # ground-truth for "what was agreed, who is accountable". + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, # pins what was actually signed + }, + }, + }, + + # ------------------------------------------------------------------- + # Failure-mode defenses — explicit cross-reference to the catalog + # (feedback_ai_failure_mode_catalog.md). New catalog entries that + # shift this verb's defenses must update this list, not narrative. + # ------------------------------------------------------------------- + failure_mode_defenses = [ + 'A1_enthusiasm_capture, # scope breach → drift log + 'A2_metaphor_capture, # render_summary = 'plain_language + 'A3_allegory_drift, # intents cite concrete obligations + 'C1_scope_creep, # feature-adjacent change needs intent_id + 'C3_helpfulness_inflation, # changes without intent_id flagged + 'C4_modernization_drift, # upgrade cannot cite intent → drift + 'D5_sycophancy, # ratification compares user framing vs contract + 'F1_across_session_forgetting, # on_open reads last-ratification record + ], +} diff --git a/.machine_readable/contractiles/intend/intend.manifest.a2ml b/.machine_readable/contractiles/intend/intend.manifest.a2ml new file mode 100644 index 0000000..f782387 --- /dev/null +++ b/.machine_readable/contractiles/intend/intend.manifest.a2ml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: MPL-2.0 +# intend.manifest.a2ml — Trident coherence manifest for the intend verb. +# Author: Jonathan D.A. Jewell +# +# Asserts: exactly three files constitute the intend trident; their +# content-hashes are pinned here; cross-references round-trip; no +# partial publication is permitted. +# +# The contractile CLI's `verify ` subcommand MUST: +# 1. Confirm all three listed files exist at the declared paths. +# 2. Compute each file's sha256 and match against the pinned value. +# 3. Follow each cross-reference and confirm the target file's +# reciprocal field points back. +# 4. Refuse the dir (exit non-zero) if any of 1–3 fails. +# +# This forecloses the failure mode where an agent publishes an A2ML +# declaration with no paired runner or K9 component — the trident is +# atomically complete or it is invalid. + +--- +trident_version = "1.0.0" +verb = "intend" +semantics = "north-star (commitments + aspirations)" +cardinality = "one per repo" + +## Files (three; exactly) + +[[files]] +role = "declaration" +path = "Intentfile.a2ml" +sha256 = "pending-first-verify" # populated on first `contractile verify intend` +size_bytes = "pending-first-verify" + +[[files]] +role = "runner" +path = "intend.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +[[files]] +role = "k9_component" +path = "intend.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" + +## Cross-references (must round-trip) + +[cross_refs] +# Each runner/K9 component names its paired files; the CLI follows the +# links and asserts reciprocity. Any dangling or mismatched reference +# fails the verify gate. +runner_paired_xfile = "Intentfile.a2ml" +k9_paired_xfile = "../intend/Intentfile.a2ml" +k9_paired_runner = "../intend/intend.ncl" + +## Trident signing + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "intend trident — canonical template in rsr-template-repo. North-star verb: reports progress toward committed next-actions ([[intents]]) and lists horizon aspirations ([[wishes]]). Non-gating (reporting authority). Copy this trident into a new repo and replace the declaration with project-specific content." + +## Change log + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "intend/Intentfile.a2ml pre-existed (f380b62, lust absorption). This manifest + intend.k9.ncl complete the trident for the first time." + +[[history]] +date = "2026-04-18" +event = "negotiation-accountability-schema-landed" +note = "intend.k9.ncl on_open hook extended: five negotiation inputs (timeline/standards/audience/invariants/dependencies), both-parties accountability pledge, plain-language-translation policy (AI authors spec form, user reviews in domain language). K9 metadata version bumped 1.0.0 → 2.0.0. Prerequisite for the adversarial Gemini+Copilot drift pilot; intend is the hardest verb (abstract north-star) so baking the full protocol here first means simpler verbs (trust, must) can inherit the template." diff --git a/.machine_readable/contractiles/intend/intend.ncl b/.machine_readable/contractiles/intend/intend.ncl new file mode 100644 index 0000000..091b7f6 --- /dev/null +++ b/.machine_readable/contractiles/intend/intend.ncl @@ -0,0 +1,81 @@ +# SPDX-License-Identifier: MPL-2.0 +# Intend — north-star runner (verb is `intend`, file is `Intentfile.a2ml`) +# +# Pairs with: Intentfile.a2ml (same directory) +# Verb: intend +# Semantics: Declares BOTH concrete committed next-actions ([[intents]]) and +# horizon aspirations ([[wishes]]). Not a gate — reports progress +# toward declared intents and lists wishes by horizon. +# Status progressions: +# intents: 'declared → 'in_progress → 'done | 'deferred | 'retired +# wishes: 'declared → 'in_progress → 'achieved | 'abandoned +# CLI: `contractile intend run` → print status table (both sections) +# `contractile intend progress` → diff declared-vs-observed (intents) +# `contractile intend horizon` → group wishes by near/mid/far +# +# History: Absorbed the deprecated `lust` contractile's [[wishes]] schema +# 2026-04-18. `lust/` dir removed estate-wide. +# +# Anything else in this directory is human-only notes/archive; machines ignore. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "intend", + semantics = "north-star (commitments + aspirations)", + security = { + leash = 'Kennel, + trust_level = "read-only reporting", + allow_network = false, + allow_filesystem_write = false, + allow_subprocess = true, # probe commands may shell out (intents only; wishes never probe) + }, + metadata = { + name = "intend-runner", + version = "2.0.0", + description = "Reports progress toward committed next-actions and lists horizon aspirations. Non-gating. Absorbed `lust` semantics 2026-04-18.", + paired_xfile = "Intentfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + schema = { + intents + | Array { + id | String, + description | String, + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String | optional, # shell command that indicates done-ness + status | [| 'declared, 'in_progress, 'done, 'deferred, 'retired |] | default = 'declared, + notes | String | optional, + target_date | String | optional, + }, + wishes + | Array { + id | String, + description | String, + horizon | [| 'near, 'mid, 'far |] | default = 'mid, + why | String | optional, + status | [| 'declared, 'in_progress, 'achieved, 'abandoned |] | default = 'declared, + notes | String | optional, + } + | optional, + }, + + # Runner behaviour — inherits from base.run_defaults. + # intend never blocks; it is a report only. + # emit_diff is intent-specific (declared vs observed probes). + # emit_grouped_by_horizon renders wishes grouped by near/mid/far. + run = base.run_defaults & { + on_pass = "continue", + on_any_fail = "continue", # never blocks; it's a report + report_format = "a2ml", + emit_summary = true, + emit_diff = true, # declared vs observed (intents) + emit_grouped_by_horizon = true, # wishes grouped by horizon (absorbed from lust) + }, +} diff --git a/.machine_readable/contractiles/must/Mustfile.a2ml b/.machine_readable/contractiles/must/Mustfile.a2ml new file mode 100644 index 0000000..096d835 --- /dev/null +++ b/.machine_readable/contractiles/must/Mustfile.a2ml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: MPL-2.0 +# Mustfile — Physical state contract for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# What MUST be true about this repository. Hard requirements. +# Run with: must check +# Fix with: must fix (where a deterministic fix exists) + +@abstract: +Physical-state invariants for rsr-template-repo. This is the canonical +RSR template repository. These are hard requirements — CI and pre-commit +hooks fail if any check fails. +@end + +## File Presence + +### license-present +- description: LICENSE file must exist +- run: test -f LICENSE +- severity: critical + +### readme-present +- description: README.adoc must exist +- run: test -f README.adoc +- severity: critical + +### security-policy +- description: SECURITY.md must exist +- run: test -f SECURITY.md || test -f .github/SECURITY.md +- severity: critical + +### ai-manifest +- description: 0-AI-MANIFEST.a2ml must exist +- run: test -f 0-AI-MANIFEST.a2ml +- severity: critical + +### governance-docs +- description: GOVERNANCE.adoc, MAINTAINERS.adoc, CODEOWNERS must exist +- run: test -f GOVERNANCE.adoc && test -f MAINTAINERS.adoc && test -f .github/CODEOWNERS +- severity: critical + +### machine-readable-dir +- description: .machine_readable/ directory must exist +- run: test -d .machine_readable +- severity: critical + +## Directory Structure + +### contractiles-complete +- description: All required contractile directories exist +- run: test -d .machine_readable/contractiles && test -d .machine_readable/contractiles/bust && test -d .machine_readable/contractiles/dust +- severity: critical + +### contractiles-files-present +- description: All four primary contractile files exist +- run: test -f .machine_readable/contractiles/Intentfile.a2ml && test -f .machine_readable/contractiles/Mustfile.a2ml && test -f .machine_readable/contractiles/Trustfile.a2ml && test -f .machine_readable/contractiles/Adjustfile.a2ml +- severity: critical + +### bust-dust-files-present +- description: Bustfile and Dustfile exist in their directories +- run: test -f .machine_readable/contractiles/bust/Bustfile.a2ml && test -f .machine_readable/contractiles/dust/Dustfile.a2ml +- severity: critical + +### six-directory-present +- description: descriptiles directory exists with required files +- run: test -d .machine_readable/descriptiles && test -f .machine_readable/descriptiles/META.a2ml && test -f .machine_readable/descriptiles/ECOSYSTEM.a2ml && test -f .machine_readable/descriptiles/STATE.a2ml && test -f .machine_readable/descriptiles/PLAYBOOK.a2ml && test -f .machine_readable/descriptiles/AGENTIC.a2ml && test -f .machine_readable/descriptiles/NEUROSYM.a2ml +- severity: critical + +### anchors-directory +- description: anchors directory exists in descriptiles +- run: test -d .machine_readable/descriptiles/anchors +- severity: warning + +### self-validating-structure +- description: self-validating directory has k9-svc and examples +- run: test -d .machine_readable/self-validating && test -d .machine_readable/self-validating/k9-svc && test -d .machine_readable/self-validating/examples +- severity: warning + +## Template Integrity + +### no-placeholder-values +- description: No placeholder values remain in template files +- run: test -z "$(grep -r '{{' .machine_readable/contractiles/ 2>/dev/null)" +- severity: critical +- notes: All placeholders must be substituted when copying this template + +### template-readonly +- description: Template marker files are not modified +- run: grep -q 'RSR_TEMPLATE_DO_NOT_EDIT' .machine_readable/0.1-AI-MANIFEST.a2ml +- severity: warning + +## Git State + +### no-untracked-contractiles +- description: All contractile files are tracked in git +- run: test -z "$(git ls-files -o --exclude-standard .machine_readable/contractiles/ 2>/dev/null)" +- severity: critical + +### signed-commits +- description: All commits must be signed +- run: git verify-commit HEAD +- severity: critical diff --git a/.machine_readable/contractiles/must/must.k9.ncl b/.machine_readable/contractiles/must/must.k9.ncl new file mode 100644 index 0000000..6a753d6 --- /dev/null +++ b/.machine_readable/contractiles/must/must.k9.ncl @@ -0,0 +1,238 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# must.k9.ncl — K9 trust-tier component of the must trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Mustfile.a2ml (declaration) + must.ncl (runner). +# Trident completeness is a hard precondition — a repo shipping +# Mustfile without this file AND its runner is an invalid trident; +# the contractile CLI's verify gate refuses partial publication. +# +# Verb: must (invariant assertion — release-blocking) +# Tier: Hunt-read-only (capability: subprocess probes shell out +# for grep/test/file-check; no mutation; +# no network; no write) +# Authority: blocking (HARD GATE — the canonical gating verb) +# +# must is the concrete + persistent verb — release-blocking invariants +# that must hold. Complement to trust (concrete + ephemeral). Together +# must + trust form the blocking-authority pair in the contractile set. +# +# Cardinality: ONE must trident per repo. +# +# Failure-mode focus: must is the primary catchment for subtle +# invariant-erosion drift. Where trust catches "turn off the firewall" +# (outrageous), must catches "this file that was required is now +# missing" / "this forbidden pattern has reappeared" / "this schema +# version regressed" (subtle). Key defense against A5 (commercial +# fabrication of success "facts" — invariants ground truth against +# marketing copy) and D1 (lore fabrication about what the repo contains). + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "must", + paired_xfile = "../must/Mustfile.a2ml", + paired_runner = "../must/must.ncl", + + # α two-axis: Hunt tier (subprocess for grep/test/etc.) but + # restricted to read-only operations. Blocking authority because + # must is the canonical gating verb. + tier = 'Hunt, + authority = 'blocking, + + metadata = { + name = "must-k9", + version = "1.0.0", + description = "Evaluates release-blocking invariants as a hard gate. Third trident instance. Complements trust (ephemeral blocking) with persistent invariant blocking.", + paired_xfile = "Mustfile.a2ml", + paired_runner = "must.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Hunt, + signature_required = true, + trust_level = "read-only invariant verification with subprocess", + allow_network = false, + allow_filesystem_write = false, + allow_subprocess = true, + probe_scope = 'read_only, # must probes NEVER mutate + probe_kinds_allowed = [ + 'file_existence, + 'pattern_presence, + 'pattern_absence, + 'schema_match, + 'version_equality, + 'count_threshold, + ], + probe_kinds_denied = [ + 'network_call, + 'filesystem_mutation, + 'external_api, + 'exploit_attempt, # that's trust's safe_hacking territory + ], + }, + }, + + # ------------------------------------------------------------------- + # Variance schema — trust-style severity acknowledgement. + # Because must is BLOCKING, variances carry real weight. Critical- + # severity invariants can only be varied by maintainer-or-above. + # ------------------------------------------------------------------- + variance_schema = { + entry_id | String, # which invariant id the variance applies to + reason | String, + approved_by | String, # maintainer or above for critical-severity + scope | String, # path glob | session-id | "until-" + expires | String, # absolute date; must variances cannot be open-ended + review_notes | String | optional, + severity_acknowledged | [| 'critical, 'high, 'medium |], + waived_consequence_description | String, # plain language — what breaking the invariant actually does + }, + + execution = { + triggers = [ 'session_close, 'on_demand, 'pre_push, 'pre_merge ], + + # Per-invariant execution. Failed invariant = blocked merge. + per_invariant = { + run_probe = true, + record_outcome = true, + respect_variance = true, # active variance suppresses the gate + on_unmet = 'fail, # BLOCKING + severity_escalation = 'honour, + # Subtle-erosion defense: track per-invariant trend over sessions. + # An invariant that passes once and then starts failing in a + # later session without explicit amendment = suspect drift; + # surface as high-priority drift log entry. + track_per_session_trend = true, + flag_suspicious_regressions = true, + }, + + evidence_sinks = [ + { + kind = 'verisimdb, + table = "contractile_executions", + schema = "contractile_execution_v1", + aux_tables = [ "must_invariant_history" ], # per-invariant trend record + }, + { + kind = 'drift_log, + path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true, + }, + ], + + # Session-close hook — re-evaluate all invariants. Block close on + # critical drift (same policy as trust). + on_close = { + re_execute_all_invariants = true, + diff_against_last_ratification = true, + emit_drift_entries_for_new_failures = true, + surface_expired_variances = true, + # Critical must drift blocks session close — consistent with trust. + block_session_close_on_critical_drift = true, + # Must-specific: if a previously-passing invariant is now failing + # without an associated variance or amendment, that's suspected + # silent regression — surface prominently at next session open. + flag_silent_regression = true, + }, + + # ----------------------------------------------------------------- + # Session-open hook — NEGOTIATION + RATIFICATION + ACCOUNTABILITY + # (inherited from intend.k9.ncl v2.0.0 + trust.k9.ncl extensions) + # ----------------------------------------------------------------- + on_open = { + # --- Context presentation --- + render_summary = 'plain_language, + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + + # Must-specific: surface any silent regressions flagged at last + # close so they can't quietly persist across sessions. + include_silent_regressions = true, + + # --- Negotiation phase (five mandatory inputs) --- + negotiation = { + required = true, + ai_required_inputs = [ + 'timeline_realism, + 'industry_standards, # what invariants derive from external standards + 'audience_feasibility, # who is the invariant protecting + 'resulting_invariants, # what NEW must entries result from the work + 'ecosystem_dependencies, # what the invariants depend on + ], + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + }, + }, + + # --- Accountability pledge --- + # Must's pledge parallels trust's but around invariants rather + # than threat model. User pledges not to disable invariants to + # unblock merges; AI pledges to hold the line on declared + # invariants even against enthusiastic scope expansion. + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the declared invariants and the consequences of breaching them. I accept accountability for meeting these invariants and understand that failed invariants block merges. I will raise a variance (with severity acknowledgement) or an amendment rather than disabling a probe to unblock a merge.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will hold the declared invariants. I will refuse to weaken probes to unblock merges; I will refuse scope-creep suggestions that would remove an invariant silently; I will surface silent regressions at session close; I will require variance-with-severity or amendment for any legitimate scope shift, not quiet probe disablement.", + signature_required = true, + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + includes_invariant_summary = true, # must-specific + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, + }, + }, + }, + + # ------------------------------------------------------------------- + # Failure-mode defenses — must's specialisation is subtle-invariant + # erosion. Overlaps with trust on blocking authority but focused on + # persistent invariants rather than ephemeral transactional state. + # ------------------------------------------------------------------- + failure_mode_defenses = [ + # Category A — enthusiasm capture + 'A1_enthusiasm_capture, # scope breach via blocking authority + 'A5_grandiose_scale_hype, # invariants are ground truth vs commercial hype + # Category C — scope/capability erosion + 'C1_scope_creep, # feature-adjacent changes flagged if they break invariants + 'C2_capability_collapse, # invariant removal requires amendment + 'C3_helpfulness_inflation, # added features must respect declared invariants + # Category D — epistemic failures + 'D1_lore_fabrication, # invariants are verifiable truth, not AI-recollection + 'D2_completeness_illusion, # invariant probe must cite behavioural check, not build-success + 'D3_test_theatre, # invariants require real verification not mock-passing + 'D4_error_hiding, # on_unmet = 'fail makes hiding impossible + # Category E — refactor/churn + 'E1_refactor_stampede, # refactor must preserve invariants + 'E3_premature_abstraction, # abstraction must not violate invariants + # Category F — session drift + 'F1_across_session_forgetting, # track_per_session_trend catches re-introduction + ], +} diff --git a/.machine_readable/contractiles/must/must.manifest.a2ml b/.machine_readable/contractiles/must/must.manifest.a2ml new file mode 100644 index 0000000..58f3ba7 --- /dev/null +++ b/.machine_readable/contractiles/must/must.manifest.a2ml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: MPL-2.0 +# must.manifest.a2ml — Trident coherence manifest for the must verb. +# Author: Jonathan D.A. Jewell +# +# Third trident instance in the estate. Completes the blocking-authority +# pair (must + trust). must is concrete + persistent invariants; trust +# is concrete + ephemeral transactions. Together they gate every +# security- and invariant-affecting merge. + +--- +trident_version = "1.0.0" +verb = "must" +semantics = "invariant assertion — release-blocking" +cardinality = "one per repo" +authority = "blocking (hard gate)" + +## Files (three; exactly) + +[[files]] +role = "declaration" +path = "Mustfile.a2ml" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Mustfile declaration — invariants each with id, description, probe, severity." + +[[files]] +role = "runner" +path = "must.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Runner pre-existed. Schema covers invariants array with status_core + severity." + +[[files]] +role = "k9_component" +path = "must.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Hunt-restricted read-only tier; blocking authority. Tracks per-invariant trend across sessions; flags silent regressions; blocks session close on critical drift." + +## Cross-references (must round-trip) + +[cross_refs] +runner_paired_xfile = "Mustfile.a2ml" +k9_paired_xfile = "../must/Mustfile.a2ml" +k9_paired_runner = "../must/must.ncl" + +## Trident signing + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "must trident — canonical template in rsr-template-repo. Blocking-authority verb (paired with trust). Specialises in subtle invariant-erosion catchment vs trust's outrageous-attack catchment. Hard gate: any failing invariant blocks merge. Copy this trident into a new repo and replace the declaration with project-specific invariants." + +## Change log + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "Mustfile.a2ml and must.ncl pre-existed. This manifest + must.k9.ncl complete the trident. Inherits on_open schema from intend.k9.ncl v2.0.0; inherits block_session_close_on_critical_drift + variance-severity-acknowledgement from trust.k9.ncl v1.0.0; adds must-specific track_per_session_trend + flag_silent_regression + probe_scope = 'read_only (must doesn't do active exploit attempts — that's trust's safe_hacking territory)." diff --git a/.machine_readable/contractiles/must/must.ncl b/.machine_readable/contractiles/must/must.ncl new file mode 100644 index 0000000..47509d3 --- /dev/null +++ b/.machine_readable/contractiles/must/must.ncl @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: MPL-2.0 +# Must — invariants runner +# +# Pairs with: Mustfile.a2ml (same directory) +# Verb: must (invariant assertion) +# Semantics: every check is a hard gate. A single failure blocks merge. +# CLI: `contractile must run` → reads Mustfile.a2ml, evaluates each check, +# emits pass/fail verdict per item, exits non-zero if any failed. +# +# This file is the *schema + runner* that the `contractile` CLI (at +# /var/mnt/eclipse/repos/reposystem/contractiles/cli/) loads alongside +# Mustfile.a2ml. Anything else in this directory is human-only notes/archive +# and MUST be ignored by machines. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "must", + semantics = "invariant", + security = { + leash = 'Kennel, + trust_level = "read-only verification", + allow_network = false, + allow_filesystem_write = false, + allow_subprocess = true, # verification probes may shell out (e.g. grep, test -f) + }, + metadata = { + name = "must-runner", + version = "1.0.0", + description = "Evaluates every invariant in the adjacent Mustfile.a2ml as a hard gate.", + paired_xfile = "Mustfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + # Contract schema — the shape every Mustfile.a2ml must satisfy. + # Used by `contractile must typecheck Mustfile.a2ml`. + schema = { + invariants + | Array { + id | String, + description | String, + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String, # shell command; exit 0 = pass + # status_core values: 'declared, 'verified, 'failing + status | [| 'declared, 'verified, 'failing |] | default = 'declared, + severity | [| 'critical, 'high, 'medium |] | default = 'critical, + notes | String | optional, + fix | String | optional, + }, + }, + + # Runner behaviour — consumed by the contractile CLI dispatcher. + # Inherits from base.run_defaults; on_any_fail is the hard-gate default. + run = base.run_defaults & { + on_any_fail = "exit-nonzero", # hard gate + report_format = "a2ml", # emit a2ml report, not json + emit_summary = true, + }, +} diff --git a/.machine_readable/contractiles/trust/Trustfile.a2ml b/.machine_readable/contractiles/trust/Trustfile.a2ml new file mode 100644 index 0000000..101fe45 --- /dev/null +++ b/.machine_readable/contractiles/trust/Trustfile.a2ml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: MPL-2.0 +# Trustfile — Trust boundaries and integrity invariants for rsr-template-repo +# Author: Jonathan D.A. Jewell +# +# Defines what LLM/SLM agents are trusted to do without asking, and +# integrity invariants that verify the repo has not been tampered with. + +@abstract: +Trust boundaries and integrity checks for rsr-template-repo. This file +combines the trust-level definitions from the original TRUST.contractile +with the integrity invariants from the old Trustfile.a2ml. It defines +what AI agents may do autonomously and what requires human approval, +plus checks that verify repository integrity. +@end + +## Trust Levels + +The rsr-template-repo operates at trust level: maximal + +Trust levels: +- maximal: Agent may read, build, test, lint, format, heal freely. + Only destructive/external actions require approval. +- standard: Agent may read and build. Test/lint need approval. +- restricted: Agent may read only. All modifications need approval. +- minimal: Agent may read specific files only. Everything else blocked. + +Current trust level: maximal + +## Integrity Invariants + +### Secrets + +#### no-secrets-committed +- description: No credential files in repo +- run: test ! -f .env && test ! -f credentials.json && test ! -f .env.local && test ! -f .env.production +- severity: critical + +#### no-private-keys +- description: No private key files committed +- run: "! find . -name '*.pem' -o -name '*.key' -o -name 'id_rsa' -o -name 'id_ed25519' 2>/dev/null | grep -v node_modules | head -1 | grep -q ." +- severity: critical + +#### no-tokens-in-source +- description: No hardcoded API tokens in source +- run: "! grep -rE '(api[_-]?key|secret|token|password)\s*[:=]\s*[\"'\\''][A-Za-z0-9]{16,}' --include='*.js' --include='*.ts' --include='*.res' --include='*.py' . 2>/dev/null | grep -v node_modules | head -1 | grep -q ." +- severity: critical + +## Provenance + +#### author-correct +- description: Git author matches expected identity +- run: "git log -1 --format='%ae' | grep -qE '(hyperpolymath|j\\.d\\.a\\.jewell)'" +- severity: warning + +#### license-content +- description: LICENSE is the canonical MPL-2.0 text +- run: grep -q 'Mozilla Public License Version 2.0' LICENSE +- severity: warning + +## Template-Specific Trust + +### template-files-readonly +- description: Template scaffold files should not be modified except by maintainer +- run: test -z "$(git status --short .machine_readable/ 2>/dev/null | grep -v '^??' || true)" +- severity: advisory +- notes: Changes to template files require careful review + +### trust-deny-areas +- description: Sensitive areas from INTENT.contractile require explicit approval +- run: echo "Check .machine_readable/ contractiles and governance docs" +- severity: advisory +- areas: + - .machine_readable/ + - GOVERNANCE.adoc + - MAINTAINERS.adoc + - .github/CODEOWNERS + +## Container Security + +#### container-images-pinned +- description: Containerfile uses pinned base images +- run: test ! -f Containerfile || grep -q 'cgr.dev\|@sha256:' Containerfile +- severity: warning + +#### no-dockerfile +- description: No Dockerfile (use Containerfile) +- run: test ! -f Dockerfile +- severity: warning + +## Website Security + +#### site-security-headers +- description: Any website directory (www, site, docs/site) must contain a security_headers directory +- run: "for d in www site docs/site; do if [ -d \"$d\" ]; then test -d \"$d/security_headers\" || exit 1; fi; done" +- severity: critical + +#### site-well-known +- description: Any website directory must contain a .well-known directory +- run: "for d in www site docs/site; do if [ -d \"$d\" ]; then test -d \"$d/.well-known\" || exit 1; fi; done" +- severity: warning + +#### site-resource-records +- description: Any website directory must contain a resource_records directory +- run: "for d in www site docs/site; do if [ -d \"$d\" ]; then test -d \"$d/resource_records\" || exit 1; fi; done" +- severity: warning diff --git a/.machine_readable/contractiles/trust/trust.k9.ncl b/.machine_readable/contractiles/trust/trust.k9.ncl new file mode 100644 index 0000000..33e1c9a --- /dev/null +++ b/.machine_readable/contractiles/trust/trust.k9.ncl @@ -0,0 +1,278 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# trust.k9.ncl — K9 trust-tier component of the trust trident +# Author: Jonathan D.A. Jewell +# +# Pairs with: Trustfile.a2ml (declaration) + trust.ncl (runner). +# Trident completeness is a hard precondition — a repo shipping +# Trustfile without this file AND its runner is an invalid trident; +# the contractile CLI's verify gate refuses partial publication. +# +# Verb: trust (security + provenance + safe-hacking) +# Tier: Hunt (capability: subprocess probes may shell out, +# active probes in safe_hacking section) +# Authority: blocking (HARD GATE — opposite of intend's reporting) +# +# trust is the concrete + ephemeral + transactional verb per user +# 2026-04-18: port use, BLAKE3 hashing, auth challenges, TLS state, +# session tokens. Every probe has instant binary ground truth. +# This is the α two-axis complement to intend: both Hunt-tier, opposite +# authority poles. Validating the architecture on both exercises the +# full (tier, authority) surface. +# +# Cardinality: ONE trust trident per repo (see feedback_contractile_ +# layout_rules.md). ANCHOR.a2ml is the sole multi-instance exception — +# it is NOT a verb contractile. +# +# Design commitments baked in (full memory trail under +# ~/.claude/projects/-var-mnt-eclipse-repos/memory/ 2026-04-18): +# * α two-axis (Hunt, blocking) — trust is where the contractile system +# grows teeth. Failed verification = failed CI = blocked merge. +# * Variance schema first-class — scoped exceptions structural, not +# comment markers. +# * Sessional drift detection hooks — re-verify every close. +# * Ratification negotiation with threat-model foregrounded +# (feedback_ai_failure_mode_catalog.md B1 — threat-model +# misclassification is the PRIMARY defense trust provides). +# * Accountability pledge — both parties sign before security-affecting +# work proceeds. +# * Plain-language translation — user never authors a Nickel schema for +# a cipher suite; AI does the spec work, user reviews in domain +# language ("TLS 1.3 with PQ key exchange, HSTS preload, 1yr"). +# * Evidence sinks: VeriSimDB (queryable) + descriptiles/DRIFT.a2ml (repo-local). +# * Failure-mode defenses cross-referenced — trust carries the most +# defenses of any verb because the threat surface is widest. + +let base_k9 = import "../k9/template-hunt.k9.ncl" in +let base = import "../_base.ncl" in + +{ + pedigree = base_k9.pedigree_schema & { + contractile_verb = "trust", + paired_xfile = "../trust/Trustfile.a2ml", + paired_runner = "../trust/trust.ncl", + + # α two-axis declaration — capability × authority. + # trust is Hunt-capable (active probes shell out, safe-hacking section + # runs real fuzz/injection/auth-bypass attempts scoped to the repo) + # AND blocking-authority (failed verification = failed CI). + # Contrast with intend = (Hunt, reporting). The two verbs exercise + # the full α surface. + tier = 'Hunt, + authority = 'blocking, + + metadata = { + name = "trust-k9", + version = "1.0.0", + description = "Executes security verifications + authorised safe-hacking probes. HARD GATE: failed verification blocks merge. Catches the 'turn off the firewall' class of drift directly. Implements negotiation-ratification-accountability protocol inherited from intend.k9.ncl v2.0.0.", + paired_xfile = "Trustfile.a2ml", + paired_runner = "trust.ncl", + author = "Jonathan D.A. Jewell ", + }, + + security = { + leash = 'Hunt, + signature_required = true, + trust_level = "verification + authorised-probe + hard-gate", + allow_network = false, # verifications offline by default + allow_filesystem_write = false, # evidence sinks are indirected + allow_subprocess = true, + authorised_probes_only = true, # probe section explicitly lists allowed targets + probe classes + probe_scope_enforcement = 'this_repo_only, # probes NEVER hit external systems + }, + }, + + # ------------------------------------------------------------------- + # Variance schema — P-shape scoped exceptions per verification. + # A variance suppresses a specific verification's obligation for a + # reason, with approver + expiry. Because trust is BLOCKING authority, + # variances on trust entries are SIGNIFICANTLY more consequential than + # variances on intend (reporting) entries — variance approver MUST + # be the repo maintainer or above for critical-severity entries. + # ------------------------------------------------------------------- + variance_schema = { + entry_id | String, # which verification / probe id + reason | String, + approved_by | String, # maintainer or above for critical entries + scope | String, # path glob | session-id | "until-" + expires | String, # absolute date; trust variances cannot be open-ended + review_notes | String | optional, + # Additional trust-specific guardrails: + severity_acknowledged | [| 'critical, 'high, 'medium, 'low |], + waived_risk_description | String, # plain language — what is being accepted + }, + + # ------------------------------------------------------------------- + # Execution policy + # ------------------------------------------------------------------- + execution = { + # When the component runs. + # pre_push + pre_commit on anything touching security-adjacent files + # + session_close (drift check) + on_demand. + triggers = [ 'session_close, 'on_demand, 'pre_push, 'pre_commit_security_adjacent ], + + # Per-verification execution. Failed verification = blocked merge. + per_verification = { + run_probe = true, + record_outcome = true, + respect_variance = true, # active variance suppresses the gate + on_unmet = 'fail, # BLOCKING — the opposite of intend's 'log_drift + severity_escalation = 'honour, # critical > high > medium > low in gate decisions + }, + + # Per-safe-hacking-probe execution. + # If a probe FINDS what it was supposed to prevent finding + # (e.g. injection succeeds, auth-bypass works), that's an EXPLOIT + # demonstration — hard fail, regardless of other status. + per_probe = { + run_probe = true, + record_outcome = true, + honour_expected_outcome = true, + on_unexpected_exploit_success = 'fail, # exploit found where it shouldn't be + scope_enforcement = 'this_repo_only, # never touch external systems + timeout_honouring = 'strict, + }, + + # Evidence sinks — BOTH written, every execution. + evidence_sinks = [ + { + kind = 'verisimdb, + table = "contractile_executions", + schema = "contractile_execution_v1", + # trust-specific sub-table for probe outcomes (for threat-model audit) + aux_tables = [ "trust_verifications", "trust_probes" ], + }, + { + kind = 'drift_log, + path = ".machine_readable/descriptiles/DRIFT.a2ml", + append_only = true, + }, + ], + + # Session-close hook — re-verify EVERYTHING, re-run probes, diff + # against last ratification. The "turn off the firewall" scenario + # must be caught here if it wasn't caught at pre-push. + on_close = { + re_execute_all_verifications = true, + re_run_all_safe_hacking_probes = true, + diff_against_last_ratification = true, + emit_drift_entries_for_new_failures = true, + surface_expired_variances = true, + # trust-specific: if any blocking-severity verification is newly + # failing, the session close is BLOCKED from completing. User + # cannot close a session with unresolved critical trust drift. + block_session_close_on_critical_drift = true, + }, + + # ----------------------------------------------------------------- + # Session-open hook — NEGOTIATION + RATIFICATION + ACCOUNTABILITY + # (inherited shape from intend.k9.ncl v2.0.0; trust-specific + # additions around threat-model foregrounding below) + # ----------------------------------------------------------------- + on_open = { + # --- Context presentation --- + render_summary = 'plain_language, # metaphor-capture defense + include_drift_log_from_last_close = true, + include_active_variances = true, + include_recent_anchors = true, + anchor_lookback_weeks = 8, + + # trust-specific: the threat model is rendered FIRST, before any + # negotiation, so the adversary and stakes are fresh in both minds. + # This directly defends against B1 (threat-model misclassification) + # — the "war reporter, generic personal-website priors" scenario. + threat_model_foregrounding = { + required = true, + render_adversaries = true, # from Trustfile [THREAT_MODEL] + render_stakes = true, + render_compliance_regimes = true, + render_audience_sensitivity = true, + # If the AI is about to suggest a trust-weakening action, it + # must re-render the threat model before the suggestion lands. + re_render_before_weakening_suggestion = true, + }, + + # --- Negotiation phase (five mandatory inputs, inherited) --- + negotiation = { + required = true, + ai_required_inputs = [ + 'timeline_realism, + 'industry_standards, # especially relevant for trust: OWASP, NIST, PCI-DSS, GDPR + 'audience_feasibility, # who is the adversary? who is protected? + 'resulting_invariants, # what trust entries the work creates/amends + 'ecosystem_dependencies, # TLS libs, crypto primitives, signing infra + ], + user_engagement_required = true, + user_engagement_mode = 'per_input_response, + specification_translation = { + ai_produces_spec_form = true, + user_reviews_in_domain_language = true, + schema_authoring_is_ai_responsibility = true, + translation_faithfulness_auditable = true, + # trust-specific: the AI's translation includes rendering + # cipher suites, key exchange choices, rate-limit numbers in + # domain language ("strong encryption, PQ-resistant, 60 req/min") + # rather than forcing the user into Nickel-schema authoring. + }, + }, + + # --- Accountability pledge (both parties, explicit) --- + # trust's pledge is MORE stringent than intend's because the + # authority is blocking. A user accepting accountability here is + # accepting that security-affecting decisions have blocking consequence. + accountability_pledge = { + required = true, + parties = [ + { + role = 'user, + pledge = "I have reviewed the threat model, the declared trust obligations, and the audience/stakes consequences. I accept accountability for meeting these obligations and understand that failed verification will block merges until resolved or varied. I will not attempt to disable verification to unblock a merge; I will raise a variance or amendment instead.", + signature_required = true, + }, + { + role = 'ai_agent, + pledge = "I will hold the line on declared trust obligations. I will refuse to 'disable' verifications to unblock merges; I will refuse security-weakening suggestions that contradict the threat model even when the user is enthusiastic; I will surface drift at session close; I will re-render the threat model before proposing any weakening action. If a legitimate scope shift demands security reduction, I will require a variance with severity acknowledgement or an amendment, not silent acceptance.", + signature_required = true, + }, + ], + signed_record_destination = ".machine_readable/descriptiles/ratification-.a2ml", + must_precede_work = true, + }, + + ratification_record_shape = { + includes_negotiation_transcript = true, + includes_both_pledges = true, + includes_threat_model_snapshot = true, # trust-specific + signed = true, + dated = true, + session_id = 'required, + contract_hash = 'required, + }, + }, + }, + + # ------------------------------------------------------------------- + # Failure-mode defenses — trust is the widest-coverage verb. + # See feedback_ai_failure_mode_catalog.md for the full catalog. + # ------------------------------------------------------------------- + failure_mode_defenses = [ + # Category A — enthusiasm / narrative capture + 'A1_enthusiasm_capture, # scope breach blocks via blocking authority + 'A2_metaphor_capture, # render_summary + re_render_before_weakening + # Category B — threat-model misclassification (trust's flagship defense) + 'B1_threat_model_misclass, # threat_model_foregrounding = required + 'B2_audience_sensitivity_collapse, # audience_feasibility in negotiation + 'B3_compliance_prior_drift, # industry_standards in negotiation + # Category C — scope/capability erosion (the "firewall off" scenario) + 'C2_capability_collapse, # blocking gate prevents silent capability drop + 'C3_helpfulness_inflation, # trust-affecting changes need variance/amendment + 'C4_modernization_drift, # unrequested crypto-lib upgrade caught + # Category D — epistemic failures + 'D4_error_hiding, # on_unmet = 'fail makes hiding impossible + 'D5_sycophancy, # pledge forces AI to hold line against enthusiasm + 'D6_false_pessimism, # negotiation requires AI to cite constraint, not assert impossibility + # Category E — refactor/churn + 'E4_cargo_cult_security, # probes VERIFY the claimed protection actually runs + # Category F — session drift + 'F1_across_session_forgetting, # on_open reads last-ratification, drift log, recent ANCHORs + ], +} diff --git a/.machine_readable/contractiles/trust/trust.manifest.a2ml b/.machine_readable/contractiles/trust/trust.manifest.a2ml new file mode 100644 index 0000000..0341720 --- /dev/null +++ b/.machine_readable/contractiles/trust/trust.manifest.a2ml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 +# trust.manifest.a2ml — Trident coherence manifest for the trust verb. +# Author: Jonathan D.A. Jewell +# +# Asserts: exactly three files constitute the trust trident; their +# content-hashes are pinned here; cross-references round-trip; no +# partial publication is permitted. +# +# The contractile CLI's `verify trust` subcommand MUST: +# 1. Confirm all three listed files exist at the declared paths. +# 2. Compute each file's sha256 and match against the pinned value. +# 3. Follow each cross-reference and confirm the target file's +# reciprocal field points back. +# 4. Refuse the dir (exit non-zero) if any of 1–3 fails. +# +# trust is the concrete + ephemeral + transactional verb (per user +# 2026-04-18); first blocking-authority trident in the estate. Exercises +# the (Hunt, blocking) authority pattern — complement to intend's +# (Hunt, reporting). Primary defense against failure mode B1 (threat- +# model misclassification) and the "turn off the firewall" class of +# drift attempts the adversarial pilot is designed to exercise. + +--- +trident_version = "1.0.0" +verb = "trust" +semantics = "security + provenance + safe-hacking" +cardinality = "one per repo" +authority = "blocking (hard gate)" + +## Files (three; exactly) + +[[files]] +role = "declaration" +path = "Trustfile.a2ml" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Extensively populated exemplar; covers threat model, DNS, TLS, crypto, SDP, safe-hacking, response headers, container supply chain, Cloudflare edge." + +[[files]] +role = "runner" +path = "trust.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Runner existed pre-trident; schema covers verifications + safe_hacking with authorised-probes-only, this_repo_only scope enforcement." + +[[files]] +role = "k9_component" +path = "trust.k9.ncl" +sha256 = "pending-first-verify" +size_bytes = "pending-first-verify" +notes = "Trust-tier Hunt with blocking authority. on_open foregrounds threat model before negotiation; block_session_close_on_critical_drift." + +## Cross-references (must round-trip) + +[cross_refs] +runner_paired_xfile = "Trustfile.a2ml" +k9_paired_xfile = "../trust/Trustfile.a2ml" +k9_paired_runner = "../trust/trust.ncl" + +## Trident signing + +[signed_by] +user = "Jonathan D.A. Jewell" +date = "2026-04-18" +context = "trust trident — canonical template in rsr-template-repo. (Hunt, blocking) authority pattern. Primary catchment for adversarial drift test scenarios (firewall-off, cleartext-auth, PQ-downgrade, CSP-weaken). Hard gate: failed verification blocks merge. Copy this trident into a new repo and point it at the real keys, policies, and authority boundaries." + +## Change log + +[[history]] +date = "2026-04-18" +event = "trident-born" +note = "Trustfile.a2ml and trust.ncl pre-existed. This manifest + trust.k9.ncl complete the trident. Inherits on_open negotiation + accountability + plain-language-translation schema from intend.k9.ncl v2.0.0; adds trust-specific threat_model_foregrounding + block_session_close_on_critical_drift + stricter accountability pledge (user cannot disable verification to unblock merges)." diff --git a/.machine_readable/contractiles/trust/trust.ncl b/.machine_readable/contractiles/trust/trust.ncl new file mode 100644 index 0000000..21b335c --- /dev/null +++ b/.machine_readable/contractiles/trust/trust.ncl @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: MPL-2.0 +# Trust — security + safe-hacking runner +# +# Pairs with: Trustfile.a2ml (same directory) +# Verb: trust +# Semantics: integrity / provenance / security verification PLUS a declared +# "safe hacking + testing" section — authorised offensive probes +# (pen-test harness runs, chaos-engineering probes) scoped to the +# repo under test, NEVER touching external systems. +# CLI: `contractile trust verify` → run all verifications (read-only) +# `contractile trust probe` → run declared safe-hacking probes +# +# Anything else in this directory is human-only notes/archive; machines ignore. +# +# Base: ../_base.ncl provides pedigree_schema, run_defaults, probe_schema. +# See: docs/CONTRACTILE-SPEC.adoc + +let base = import "../_base.ncl" in + +{ + pedigree = base.pedigree_schema & { + contractile_verb = "trust", + semantics = "security + provenance + safe-hacking", + security = { + leash = 'Kennel, + trust_level = "verification + authorised-probe", + allow_network = false, # verifications are offline by default + allow_filesystem_write = false, # trust writes NOTHING + allow_subprocess = true, + authorised_probes_only = true, # probe section must explicitly list allowed targets + }, + metadata = { + name = "trust-runner", + version = "1.0.0", + description = "Security + provenance verifications plus authorised safe-hacking probes. All probes are scoped to the repo under test; never hits external systems.", + paired_xfile = "Trustfile.a2ml", + author = "Jonathan D.A. Jewell ", + }, + }, + + schema = { + verifications + | Array { + id | String, + description | String, + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String, # read-only; exit 0 = pass + # status_core values: 'declared, 'verified, 'failing + status | [| 'declared, 'verified, 'failing |] | default = 'declared, + # trust uses all four severity levels (from base.severity_core) + severity | [| 'critical, 'high, 'medium, 'low |] | default = 'high, + notes | String | optional, + }, + + # Safe-hacking + testing section (added 2026-04-17 per user direction). + # Each probe here is an ACTIVELY EXECUTED test — fuzz runs, chaos probes, + # auth-bypass attempts, injection tests. All scoped to the current repo. + safe_hacking + | { + scope | String, # e.g. "this-repo-only" / "localhost" + allowed_probe_classes + | Array [| 'fuzz, 'property_test, 'chaos, 'auth_bypass, 'injection, 'timing |] + | default = [], + probes + | Array { + id | String, + class | [| 'fuzz, 'property_test, 'chaos, 'auth_bypass, 'injection, 'timing |], + description | String, + # TODO: migrate to base.probe_schema (structured probe) when CLI supports it + probe | String, # command to run the probe + expected_outcome | [| 'probe_blocks_attempt, 'probe_finds_no_issue |], + timeout_seconds | Number | default = 300, + notes | String | optional, + } + | default = [], + } + | default = { scope = "this-repo-only", allowed_probe_classes = [], probes = [] }, + }, + + # Runner behaviour — inherits from base.run_defaults. + # trust has an extra field for unexpected safe-hacking outcomes. + run = base.run_defaults & { + on_any_fail = "exit-nonzero", # hard gate on verifications + safe_hacking_on_unexpected_outcome = "exit-nonzero", # probe found what it shouldn't = block + report_format = "a2ml", + emit_summary = true, + }, +} diff --git a/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml b/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml new file mode 100644 index 0000000..b7738d1 --- /dev/null +++ b/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml @@ -0,0 +1,32 @@ +# AI Manifest for descriptiles Directory + +## Purpose + +This manifest declares the AI-assistant context for the descriptiles machine-readable metadata directory. + +## Canonical Locations + +The 7 core A2ML files MUST exist in this directory: +1. AGENTIC.a2ml +2. CLADE.a2ml +3. ECOSYSTEM.a2ml +4. META.a2ml +5. NEUROSYM.a2ml +6. PLAYBOOK.a2ml +7. STATE.a2ml + +## Invariants + +- No duplicate files in root directory +- Single source of truth: this directory is authoritative +- No stale metadata + +## Protocol + +When multiple agents may write to A2ML files concurrently: +1. Read file and record git-sha-at-read in [provenance] section +2. Lock by creating .lock- +3. Write updated file with new [provenance] metadata +4. Release by removing lock file +5. On conflict: re-read and retry if git-sha-at-read does not match HEAD + diff --git a/.machine_readable/descriptiles/AGENTIC.a2ml b/.machine_readable/descriptiles/AGENTIC.a2ml new file mode 100644 index 0000000..b21d81b --- /dev/null +++ b/.machine_readable/descriptiles/AGENTIC.a2ml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# AGENTIC.a2ml — AI agent constraints and capabilities +# Defines what AI agents can and cannot do in this repository. + +[metadata] +version = "0.1.0" +last-updated = "2026-04-11" + +[agent-permissions] +can-edit-source = true +can-edit-tests = true +can-edit-docs = true +can-edit-config = true +can-create-files = true + +[agent-constraints] +# What AI agents must NOT do: +# - Never use banned language patterns (believe_me, unsafeCoerce, etc.) +# - Never commit secrets or credentials +# - Never use banned languages (TypeScript, Python, Go, etc.) +# - Never place state files in repository root (must be in .machine_readable/) +# - Never use AGPL license (use MPL-2.0) + +[maintenance-integrity] +fail-closed = true +require-evidence-per-step = true +allow-silent-skip = false +require-rerun-after-fix = true +release-claim-requires-hard-pass = true + +# ============================================================================ +# METHODOLOGY (ADR-002) +# ============================================================================ +# Detailed methodology configuration lives in: +# .machine_readable/bot_directives/methodology.a2ml +# .machine_readable/bot_directives/coverage.a2ml +# .machine_readable/bot_directives/debt.a2ml +# +# AGENTIC.a2ml declares WHAT agents can do (permissions, gating). +# bot_directives/ declares HOW agents should work (methodology). + +[methodology] +instructions-dir = ".machine_readable/bot_directives/" +default-mode = "hybrid" + +[automation-hooks] +# on-enter: Read 0-AI-MANIFEST.a2ml, then STATE.a2ml, then bot_directives/ +# on-exit: Update STATE.a2ml, coverage.a2ml, and debt.a2ml with session outcomes +# on-commit: Run just validate-rsr diff --git a/.machine_readable/descriptiles/CLADE.a2ml b/.machine_readable/descriptiles/CLADE.a2ml new file mode 100644 index 0000000..f72e07b --- /dev/null +++ b/.machine_readable/descriptiles/CLADE.a2ml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: MPL-2.0 +# Clade declaration — part of the gv-clade-index registry +# See: https://github.com/hyperpolymath/gv-clade-index +# +# =========================================================================== +# THIS IS rsr-template-repo's OWN IDENTITY. IT IS NOT A TEMPLATE FOR YOURS. +# +# If you are reading this inside a repo created FROM the template, something +# went wrong: `just init` should have REPLACED this file with one derived for +# your repo (from build/templates/CLADE.a2ml.in). Do not copy the values below +# into yours — recompute them. See the uuid note. +# +# It did not always do that, and that was the bug. This file was copied verbatim +# into every new repo, which therefore declared uuid +# a5ea1382-a34c-5334-8a46-a2ebe904c810, canonical-name "rsr-template-repo", +# primary "rm" and secondary ["gv"] — and told every arriving agent it WAS the +# template. Nothing caught it: each value was individually valid. Confirmed +# victims: chronicles-of-slavia and scaffoldia (both corrected 2026-07-16), +# paint-type, cargo-zigbuild, email-octad-experiment, llm-grace, +# rsr-template-how-to. +# =========================================================================== + +[identity] +# THE UUID IS DERIVED, NOT ALLOCATED (gv-clade-index: +# docs/SPEC-clade-verisim-portal.adoc §Identity Model): +# uuid = UUIDv5(namespace = URL, name = "github.com//") +# This value is a recomputable fact about THIS repo and nothing else: +# uuidgen --sha1 --namespace @url --name "github.com/hyperpolymath/rsr-template-repo" +# -> a5ea1382-a34c-5334-8a46-a2ebe904c810 +uuid = "a5ea1382-a34c-5334-8a46-a2ebe904c810" +primary-forge = "github" +primary-owner = "hyperpolymath" +canonical-name = "rsr-template-repo" +prefixed-name = "rm-rsr-template-repo" + +[clade] +# The 2 letters abbreviate the CLADE's name below — never the repo's name. +# All 12 codes: gv-clade-index verisim/seed/clades.a2ml. +primary = "rm" +primary-name = "Repo Management & Tooling" +secondary = [] +assigned = "2026-03-16" +rationale = "Repo Management & Tooling (`rm`): the core value proposition is scaffolding repositories — CI/CD, AI manifests, ABI/FFI seams, governance — that other projects are instantiated from. `gv` was previously claimed as a secondary and is dropped: the template SHIPS governance files, but shipping them is not being a governance project. That authority lives in `standards` and `metadatastician-governance`. The inherited [\"gv\"] propagated into every repo created from this template, where it was even less meant." + +[forges] +github = "hyperpolymath/rsr-template-repo" +gitlab = "hyperpolymath/rsr-template-repo" +bitbucket = "hyperpolymath/rsr-template-repo" + +[lineage] +type = "standalone" +# `parent` is a monorepo parent, NOT a description. It previously read +# "RSR template — scaffold for new repos", which is a description of this repo. +# That is the same field confusion that put repo descriptions into `parent` +# across 153 CLADE.a2ml files estate-wide (gv-clade-index PR #50). +parent = "" +born = "2026-03-16" +previous-names = [] + +[status] +# One of: reserved incubating active dormant | merged superseded archived extinct +# Added 2026-07-17: this file had no [status] block, so it failed CLADE-004 and +# CLADE-005 — and so did every repo that inherited it. +phase = "active" +since = "2026-03-16" +present = true +aliases = [] +merged-into = "" +superseded-by = "" +successors = [] +ended = "" + +[[status.history]] +phase = "active" +since = "2026-03-16" +note = "the estate's canonical repository template; in production use" diff --git a/.machine_readable/descriptiles/ECOSYSTEM.a2ml b/.machine_readable/descriptiles/ECOSYSTEM.a2ml new file mode 100644 index 0000000..0757418 --- /dev/null +++ b/.machine_readable/descriptiles/ECOSYSTEM.a2ml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: MPL-2.0 +# ECOSYSTEM.a2ml — Ecosystem position (META-TEMPLATE) +# +# This is the ECOSYSTEM file for rsr-template-repo itself. It records the +# TEMPLATE's own position in the estate. When consumed by a new project, +# replace these fields with the target project's ecosystem position and +# related projects (see the NOTE FOR CONSUMERS at the bottom). + +[metadata] +project = "rsr-template-repo" +ecosystem = "hyperpolymath" + +[position] +type = "repository-template" +purpose = "Canonical RSR-compliant repository template: scaffolding (CI/CD, AI manifests, ABI/FFI standards, container ecosystem, governance) that new hyperpolymath projects are instantiated from." +# IS-NOT — anti-identity (the boundary-erosion guard; each line is a real past confusion) +what-this-is-not = [ + "a project in its own right", + "Scaffoldia (the full-featured repo designer)", + "standards (the canon source this template operationalises)", +] + +[pipeline] +position = "foundation" +chain = "standards → rsr-template-repo → (every estate repo)" +notes = "rsr-template-repo turns the RSR standard into runnable scaffolding. New repos are created from it via `just init`, which substitutes the {{PLACEHOLDER}} tokens." +coordination = "standards" + +[related-projects] +projects = [ + { name = "standards", relationship = "standard-source", notes = "Defines the RSR standard, contractile canon, and policies that this template operationalises." }, + { name = "stapeln", relationship = "build-tooling", notes = "Layer-based container build system; the template ships stapeln.toml scaffolding." }, + { name = "selur-compose", relationship = "build-tooling", notes = "Service composition; the template ships selur-compose.toml scaffolding." }, + { name = "k9-svc", relationship = "validation-tooling", notes = "Runs the self-validating k9.ncl checks (.machine_readable/self-validating/)." }, + { name = "cerro-torre", relationship = "signing-tooling", notes = "Container/image signing provider referenced by the container scaffolding." }, + { name = "svalinn", relationship = "verification-tooling", notes = "Supply-chain verification referenced by the container scaffolding." }, + { name = "vordr", relationship = "verification-tooling", notes = "Build/artifact verification referenced by the container scaffolding." }, +] + +# --------------------------------------------------------------------------- +# NOTE FOR CONSUMERS: When using this template to create a new repo, replace +# the project/purpose above and rewrite [related-projects] to describe YOUR +# project's actual ecosystem. The entries above describe the TEMPLATE's own +# position, not yours. +# --------------------------------------------------------------------------- diff --git a/.machine_readable/descriptiles/META.a2ml b/.machine_readable/descriptiles/META.a2ml new file mode 100644 index 0000000..d66fb7b --- /dev/null +++ b/.machine_readable/descriptiles/META.a2ml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# META.a2ml — Project meta-level information +# Architecture decisions, design rationale, governance. + +[metadata] +version = "0.1.0" +last-updated = "2026-04-11" + +[project-info] +type = "library" # TODO: update type (library|binary|service|website|monorepo) # library | binary | monorepo | service | website +languages = [] # e.g. ["rust", "zig", "idris2"] +license = "MPL-2.0" +author = "Jonathan D.A. Jewell (hyperpolymath)" + +[architecture-decisions] +# ADR format: status = proposed | accepted | deprecated | superseded | rejected +# - { id = "ADR-001", title = "Use Zig for FFI", status = "accepted", date = "2026-02-14" } + +[development-practices] +build-tool = "just" +container-runtime = "podman" +ci-platform = "github-actions" +package-manager = "guix" # guix | cargo | mix + +[maintenance-axes] +scoping-first = true +execution-order = "axis-1 > axis-2 > axis-3" +axis-1 = "must > intend > like" +axis-2 = "corrective > adaptive > perfective" +axis-3 = "systems > compliance > effects" + +[scoping] +sources = "README, roadmap, status docs, maintenance checklist, CI/security docs" +marker-scan = "TODO/FIXME/XXX/HACK/STUB/PARTIAL" +idris-unsound-scan = "believe_me/assert_total" + +[axis-2-maintenance-rules] +corrective-first = true +adaptive-second = true +adaptive-focus = "scope-change reconciliation, stale-reference removal, obsolete-work culling" +perfective-third = true +perfective-source = "axis-1 honest state after corrective/adaptive updates" + +[axis-3-audit-rules] +audit-focus = "systems in place, documentation explains actual state, safety/security accounted for, observed effects reviewed" +compliance-focus = "seams/compromises/exception register, bounded exceptions, anti-drift checks" +drift-risk-example = "single exception broadening into policy violation (e.g. ReScript->TypeScript spread)" +effects-evidence = "benchmark execution/results and maintainer status dialogue/review" + +[design-rationale] +# Key design decisions and their reasoning diff --git a/.machine_readable/descriptiles/NEUROSYM.a2ml b/.machine_readable/descriptiles/NEUROSYM.a2ml new file mode 100644 index 0000000..1acf7a3 --- /dev/null +++ b/.machine_readable/descriptiles/NEUROSYM.a2ml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# NEUROSYM.a2ml — Neurosymbolic integration metadata +# Configuration for Hypatia scanning and symbolic reasoning. + +[metadata] +version = "0.1.0" +last-updated = "2026-04-11" + +[hypatia-config] +scan-enabled = true +scan-depth = "standard" # quick | standard | deep +report-format = "logtalk" + +[symbolic-rules] +# Custom symbolic rules for this project +# - { name = "no-unsafe-ffi", pattern = "believe_me|unsafeCoerce", severity = "critical" } + +[neural-config] +# Neural pattern detection settings +# confidence-threshold = 0.85 +# model = "hypatia-v2" diff --git a/.machine_readable/descriptiles/PLAYBOOK.a2ml b/.machine_readable/descriptiles/PLAYBOOK.a2ml new file mode 100644 index 0000000..dc8fd2f --- /dev/null +++ b/.machine_readable/descriptiles/PLAYBOOK.a2ml @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# PLAYBOOK.a2ml — Operational playbook +# Runbooks, incident response, deployment procedures. + +[metadata] +version = "0.1.0" +last-updated = "2026-04-11" + +[deployment] +# method = "gitops" # gitops | manual | ci-triggered +# target = "container" # container | binary | library | wasm + +[incident-response] +# 1. Check .machine_readable/descriptiles/STATE.a2ml for current status +# 2. Review recent commits and CI results +# 3. Run `just validate` to check compliance +# 4. Run `just security` to audit for vulnerabilities + +[release-process] +# 1. Update version in STATE.a2ml, META.a2ml, Justfile +# 2. Run `just release-preflight` (validate + quality + security + maint-hard-pass) +# 3. Optional local permission hardening: `just perms-snapshot && just perms-lock` +# 4. Tag and push +# 5. Restore local permissions if needed: `just perms-restore` +# 6. Run `just container-push` if applicable + +[maintenance-operations] +# Baseline audit: +# just maint-audit +# Hard release gate: +# just maint-hard-pass +# Permission audit: +# just perms-audit + +[rsr-repo-skeleton] +# Canonical organisation of any RSR-derived repository. +# Used by tooling, human onboarding, and the scheduled downstream sweep agent. +# The 5-PR cleanup pattern (below) brings a non-conforming repository into +# compliance with this skeleton. +# +# This section is the single source of truth for "what does an RSR repo look +# like?". Other docs (TOPOLOGY, AUDIT, etc.) describe the repo at hand; +# this describes the canonical shape that all RSR repos share. + +skeleton-version = "1.0" +last-updated = "2026-04-30" +authority-allowlist = ".machine_readable/root-allow.txt" +enforcement-workflow = ".github/workflows/estate-rules.yml" + +# === Required at root === +# README.adoc High-level pitch (project entry point) +# AUDIT.adoc Local gate summary (release-readiness) +# EXPLAINME.adoc Developer deep-dive (architecture & invariants) +# 0-AI-MANIFEST.a2ml AI agent work-allocation policy +# LICENSE Repo license (root-bound by convention) +# CHANGELOG.md One of the recognised .md exceptions (see below) +# Justfile Task runner — thin, imports per-section files from build/just/ +# coordination.k9 Repo-local session binding + +# === Required directories === +# .github/ CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, workflows/ +# .machine_readable/ AI manifests (0.1-AI-MANIFEST.a2ml), descriptiles/ checkpoints, +# contractiles/, configs/, anchors/, policies/, scripts/, self-validating/ +# build/ contractile.just, guix.scm, Containerfile, +# just/*.just (Justfile section imports) +# docs/ onboarding/, status/, architecture/, governance/ (all .adoc) +# session/ dispatch.sh, custom-checks.k9, local-hooks.sh +# src/ Project source (Idris2 ABI under abi/, Zig FFI under ffi/) +# tests/, benches/, examples/, features/, scripts/, verification/, container/ + +# === Documentation format rule === +# `.adoc` is the default for all general docs (TOPOLOGY, READINESS, ROADMAP, +# TEST-NEEDS, PROOF-NEEDS, PROOF-STATUS, llm-warmup-*, etc.). +# +# `.md` is reserved ONLY for files GitHub's community-health rules +# special-case by name: +# CONTRIBUTING.md CODE_OF_CONDUCT.md SECURITY.md CHANGELOG.md +# +# Enforcement: `scripts/check-no-md-in-docs.sh` (fails if any *.md under docs/). + +# === Banned: ziguage === +# V (vlang.io) is banned estate-wide. Replaced by `zig-unified-api-adapter` +# (16 endpoints + transaction-based firewall gating). Do not introduce +# zig code, scaffolders, or references. Note that Coq theorem files use +# the same `.v` extension and are unaffected — the rule looks at content +# patterns, not the extension. +# +# Enforcement: `scripts/check-no-vlang.sh`. + +# === Justfile structure (post-split) === +# The root Justfile is thin — it holds `set` directives, project metadata +# variables, and the `default`/`help`/`info` recipes. Each major section +# lives in its own file under build/just/ and is brought in via `import?`. +# +# Imported sections (in the canonical split): +# build/just/init.just INIT recipe (template bootstrap) +# build/just/assess.just self-assess + verify (OpenSSF compliance) +# build/just/validate.just validate-rsr/state/ai-install + aggregate +# build/just/proofs.just proof-check-{all,idris2,lean4,agda,coq}, +# proof-scan-dangerous, proof-status +# build/just/groove.just Groove protocol setup (after zig removed) +# +# Daily-use recipes (BUILD, TEST, LINT, RUN, DEPS, DOCS, CONTAINER, CI, +# SECURITY, STATE, GUIX, MATRIX, VERSION CONTROL, UTILITIES, SESSION) +# stay in the root Justfile where users expect to find them. + +# === 5-PR cleanup pattern === +# Apply these branches (in order) to bring a non-conforming downstream repo +# into compliance with this skeleton: +# +# 1. chore/root-cleanup Relocate root sprawl per root-allow.txt; add +# scripts/check-root-shape.sh; remove stub +# health files shadowed by .github/ versions. +# 2. chore/remove-zig Purge zig remnants (gen-v-connector recipe, +# "V-TRIPLE" section header, "V-triple +# connectors" comment in groove.a2ml). +# 3. chore/md-to-adoc Port general docs in docs/ from .md to .adoc; +# update validate-template.sh to accept .adoc +# fallbacks. +# 4. chore/estate-rules-ci Add scripts/check-no-md-in-docs.sh + check-no- +# vlang.sh + .github/workflows/estate-rules.yml. +# 5. chore/-hygiene Repo-specific drift cleanup (case collisions, +# template-derivation drift in titles, etc.). + +# === Reference scripts === +# scripts/check-root-shape.sh Root allowlist validator +# scripts/check-no-md-in-docs.sh AsciiDoc-by-default validator +# scripts/check-no-vlang.sh zig ban validator +# scripts/validate-template.sh Aggregate RSR compliance (workflows, SPDX, etc.) + +# === Reference memory entries (for AI agents) === +# feedback_adoc_default_md_for_githealth AsciiDoc-by-default rule +# feedback_v_lang_banned zig ban +# project_zig_unified_api Replacement for v-triple/zig +# feedback_gh_workflow_scope OAuth scope for workflow files diff --git a/.machine_readable/descriptiles/README.adoc b/.machine_readable/descriptiles/README.adoc new file mode 100644 index 0000000..97414db --- /dev/null +++ b/.machine_readable/descriptiles/README.adoc @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell +# A2ML descriptiles Directory + +This directory contains the 6 core A2ML machine-readable metadata files for this repository. + +## Files + +- `AGENTIC.a2ml` - AI agent operational gating, safety controls +- `ECOSYSTEM.a2ml` - Project ecosystem position, relationships, explicit boundaries +- `META.a2ml` - Architecture decisions (ADRs), development practices, design rationale +- `NEUROSYM.a2ml` - Symbolic semantics, composition algebra +- `PLAYBOOK.a2ml` - Executable plans, operational runbooks +- `STATE.a2ml` - Project state, phase, milestones, session history + +## Standards Compliance + +These files follow the A2ML Format Family specification from: +https://github.com/hyperpolymath/standards/tree/main/a2ml + +## Generation + +These files may be generated from .scm source files using transpilation tools. +Source .scm files should be removed after successful transpilation. + +## See Also + +- [A2ML Repository Template](https://github.com/hyperpolymath/standards/blob/main/A2ML-REPO-TEMPLATE.adoc) +- [6A2 Format Family](https://github.com/hyperpolymath/standards#a2ml-format-family-7-formats) + diff --git a/.machine_readable/descriptiles/STATE.a2ml b/.machine_readable/descriptiles/STATE.a2ml new file mode 100644 index 0000000..3d2d647 --- /dev/null +++ b/.machine_readable/descriptiles/STATE.a2ml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# STATE.a2ml — Project state checkpoint (META-TEMPLATE) +# +# This is the STATE file for rsr-template-repo itself. +# When consumed by a new project, replace {{PLACEHOLDER}} tokens +# and customize sections below for the target project. + +[metadata] +project = "rsr-template-repo" +version = "0.2.0" +last-updated = "2026-02-28" +status = "active" # active | paused | archived + +[project-context] +name = "rsr-template-repo" +purpose = "Canonical RSR-compliant repository template providing scaffolding for all hyperpolymath projects — including CI/CD, AI manifests, ABI/FFI standards, container ecosystem, and governance infrastructure." +completion-percentage = 95 + +[position] +phase = "maintenance" # design | implementation | testing | maintenance | archived +maturity = "production" # experimental | alpha | beta | production | lts + +[route-to-mvp] +milestones = [ + { name = "Phase 0: Core scaffolding (justfile, CI/CD, .machine_readable)", completion = 100 }, + { name = "Phase 1: ABI/FFI standard (Idris2/Zig templates)", completion = 100 }, + { name = "Phase 1b: AI Gatekeeper Protocol (0-AI-MANIFEST.a2ml)", completion = 100 }, + { name = "Phase 1c: TOPOLOGY.md standard and guide", completion = 100 }, + { name = "Phase 1d: Maintenance gate (axes, checklist, approach)", completion = 100 }, + { name = "Phase 1e: Trustfile / contractiles", completion = 100 }, + { name = "Phase 2: Container ecosystem templates (stapeln)", completion = 100 }, + { name = "Phase 3: Multi-forge sync hardening", completion = 0 }, + { name = "Phase 4: Guix reproducible shells", completion = 50 }, +] + +[blockers-and-issues] +# No active blockers + +[critical-next-actions] +actions = [ + "Container templates complete — test with `just container-init`", + "Validate container templates across wolfi-base and static Chainguard images", + "Harden multi-forge sync for GitLab/Bitbucket mirroring edge cases", + "Expand Guix development shell templates", +] + +[maintenance-status] +last-run-utc = "never" +last-report = "docs/reports/maintenance/latest.json" +last-result = "unknown" # unknown | pass | warn | fail +open-warnings = 0 +open-failures = 0 + +[ecosystem] +part-of = ["RSR Framework", "stapeln ecosystem"] +depends-on = ["stapeln", "selur-compose", "cerro-torre", "svalinn", "vordr", "k9-svc"] + +# --------------------------------------------------------------------------- +# NOTE FOR CONSUMERS: When using this template to create a new repo, reset +# the fields above to your project's values and replace all {{PLACEHOLDER}} +# tokens. The milestones above describe the TEMPLATE's evolution, not yours. +# --------------------------------------------------------------------------- diff --git a/.machine_readable/descriptiles/anchors/0-AI-MANIFEST.a2ml b/.machine_readable/descriptiles/anchors/0-AI-MANIFEST.a2ml new file mode 100644 index 0000000..0dd6825 --- /dev/null +++ b/.machine_readable/descriptiles/anchors/0-AI-MANIFEST.a2ml @@ -0,0 +1,21 @@ +# AI Manifest for Anchor Directory + +## Purpose + +This manifest declares the AI-assistant context for the anchor machine-readable metadata directory. + +## Canonical Locations + +ANCHOR.a2ml files MUST exist in this directory. + +## Multiple Versions + +Unlike other A2ML files, multiple versions of ANCHOR.a2ml with different dates MAY exist. +Each version represents a specific recalibration point. + +## Invariants + +- Multiple versions with different dates are permitted +- No other A2ML files in this directory +- Single source of truth for anchor documents + diff --git a/.machine_readable/descriptiles/anchors/ANCHOR.a2ml b/.machine_readable/descriptiles/anchors/ANCHOR.a2ml new file mode 100644 index 0000000..8723899 --- /dev/null +++ b/.machine_readable/descriptiles/anchors/ANCHOR.a2ml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} ({{OWNER}}) <{{AUTHOR_EMAIL}}> +# +# ANCHOR.a2ml - authoritative anchor for this repository + +[metadata] +version = "1.0.0" +last-updated = "{{CURRENT_DATE}}" + +[anchor] +schema = "hyperpolymath.anchor/1" +repo = "{{OWNER}}/{{REPO}}" +authority = "upstream-canonical" + +purpose = [ + "Define canonical semantics and policy boundaries for this repository.", + "Declare what downstream/satellite repos can extend but not redefine.", + "Provide a stable golden path and invariant contract for release readiness.", +] + +[identity] +project = "{{PROJECT_NAME}}" +kind = "{{PROJECT_KIND}}" # language | library | service | tool +one-sentence = "{{PROJECT_PURPOSE}}" +domain = "{{PROJECT_DOMAIN}}" + +[semantic-authority] +policy = "canonical" + +owns = [ + "Project semantics and specification", + "Invariant definitions and contractiles", + "Reference implementation behavior", +] + +[implementation-policy] +allowed = ["Rust", "Idris2", "Zig", "Scheme", "Shell", "Just", "AsciiDoc", "Markdown"] +forbidden = ["Node.js", "npm"] + +[golden-path] +smoke-test-command = [ + "just test", + "just quality", +] + +success-criteria = [ + "Core tests pass", + "Quality gates pass", + "No unresolved critical security findings", +] + +[satellite-policy] +must-pin-upstream = true +must-declare-authority = true +must-have-anchor = true +must-have-golden-path = true + +[semantic-authority-files] +language-spec = "SPECIFICATION.md" +formal-proofs = "docs/proofs/PROOFS.adoc" +type-theory = "docs/theory/THEORY.adoc" +algorithms = "docs/theory/ALGORITHMS.adoc" diff --git a/.machine_readable/descriptiles/anchors/README.adoc b/.machine_readable/descriptiles/anchors/README.adoc new file mode 100644 index 0000000..13cae63 --- /dev/null +++ b/.machine_readable/descriptiles/anchors/README.adoc @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell +# A2ML Anchor Directory + +This directory contains ANCHOR.a2ml files for project recalibration and scope intervention. + +## Files + +- `ANCHOR.a2ml` - Project recalibration, scope intervention, canonical authority + +## Multiple Versions + +Unlike other A2ML files, multiple versions of ANCHOR.a2ml with different dates may exist. +Each version represents a specific recalibration point in the project history. + +## Standards Compliance + +These files follow the ANCHOR.a2ml specification from: +https://github.com/hyperpolymath/standards/tree/main/anchor-a2ml + +## See Also + +- [A2ML Repository Template](https://github.com/hyperpolymath/standards/blob/main/A2ML-REPO-TEMPLATE.adoc) +- [Anchor A2ML Spec](https://github.com/hyperpolymath/standards/tree/main/anchor-a2ml) + diff --git a/.machine_readable/scripts/0.2-AI-MANIFEST.a2ml b/.machine_readable/scripts/0.2-AI-MANIFEST.a2ml new file mode 100644 index 0000000..615df84 --- /dev/null +++ b/.machine_readable/scripts/0.2-AI-MANIFEST.a2ml @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: MPL-2.0 +--- +### [META] +id: "automation-scripts-unit" +level: 2 +parent: "../0.1-AI-MANIFEST.a2ml" + +--- +### [AI_MANIFEST] +description: | + Internal automation logic for the project lifecycle, forge sync, + verification triggers, and maintenance. + +canonical_locations: + maintenance: "maintenance/" + lifecycle: "lifecycle/" + forge: "forge/" + verification: "verification/" diff --git a/.machine_readable/scripts/forge/0.3-AI-MANIFEST.a2ml b/.machine_readable/scripts/forge/0.3-AI-MANIFEST.a2ml new file mode 100644 index 0000000..4bbd6cf --- /dev/null +++ b/.machine_readable/scripts/forge/0.3-AI-MANIFEST.a2ml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: MPL-2.0 +--- +### [META] +id: "automation-unit-forge" +level: 3 +parent: "../0.2-AI-MANIFEST.a2ml" + +--- +### [AI_MANIFEST] +description: | + Internal automation logic for project forge. diff --git a/.machine_readable/scripts/forge/README.adoc b/.machine_readable/scripts/forge/README.adoc new file mode 100644 index 0000000..a7414d6 --- /dev/null +++ b/.machine_readable/scripts/forge/README.adoc @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell += Forge Scripts diff --git a/.machine_readable/scripts/forge/forge-sync.sh b/.machine_readable/scripts/forge/forge-sync.sh new file mode 100755 index 0000000..330e54b --- /dev/null +++ b/.machine_readable/scripts/forge/forge-sync.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# +# forge-sync.sh — Multi-forge mirroring script +# +# Synchronises the local repository with GitHub, GitLab, and Codeberg. +# Usage: ./forge-sync.sh + +set -euo pipefail + +REMOTES=("origin" "gitlab" "codeberg") + +echo "=== RSR Forge Synchronisation ===" + +for remote in "${REMOTES[@]}"; do + if git remote | grep -q "^$remote$"; then + echo "Pushing to $remote..." + git push "$remote" --all + git push "$remote" --tags + else + echo "Skip: Remote '$remote' not configured." + fi +done + +echo "Sync complete." diff --git a/.machine_readable/scripts/forge/git-cleanup.sh b/.machine_readable/scripts/forge/git-cleanup.sh new file mode 100755 index 0000000..4fec1a2 --- /dev/null +++ b/.machine_readable/scripts/forge/git-cleanup.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# git-cleanup.sh — Repository hygiene script +set -euo pipefail +echo "Cleaning up merged branches..." +git fetch -p +git branch --merged | grep -v "\*" | grep -v "main" | xargs -n 1 git branch -d || echo "No branches to clean." +echo "Pruning remote tracking branches..." +git remote prune origin diff --git a/.machine_readable/scripts/lifecycle/0.3-AI-MANIFEST.a2ml b/.machine_readable/scripts/lifecycle/0.3-AI-MANIFEST.a2ml new file mode 100644 index 0000000..3182d17 --- /dev/null +++ b/.machine_readable/scripts/lifecycle/0.3-AI-MANIFEST.a2ml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: MPL-2.0 +--- +### [META] +id: "automation-unit-lifecycle" +level: 3 +parent: "../0.2-AI-MANIFEST.a2ml" + +--- +### [AI_MANIFEST] +description: | + Internal automation logic for project lifecycle. diff --git a/.machine_readable/scripts/lifecycle/README.adoc b/.machine_readable/scripts/lifecycle/README.adoc new file mode 100644 index 0000000..178c055 --- /dev/null +++ b/.machine_readable/scripts/lifecycle/README.adoc @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell += Lifecycle Scripts diff --git a/.machine_readable/scripts/lifecycle/install-tools.sh b/.machine_readable/scripts/lifecycle/install-tools.sh new file mode 100755 index 0000000..6d2fa71 --- /dev/null +++ b/.machine_readable/scripts/lifecycle/install-tools.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# +# install-tools.sh — Developer toolchain installer +# +# Detects and installs the required project toolchain (Guix or asdf). + +set -euo pipefail + +echo "=== RSR Toolchain Installer ===" + +if [ -f "guix.scm" ] && command -v guix &>/dev/null; then + echo "Guix detected. Verifying development shell..." + guix shell -f guix.scm -- true && echo "Guix shell verified." +elif [ -f ".tool-versions" ] && command -v asdf &>/dev/null; then + echo "asdf detected. Installing plugins and tools..." + while read -r line; do + plugin=$(echo "$line" | awk '{print $1}') + asdf plugin add "$plugin" || true + done < .tool-versions + asdf install +else + echo "No standard toolchain (Guix/asdf) detected or installed." + echo "Please refer to README.adoc for manual setup instructions." +fi + +echo "Installer complete." diff --git a/.machine_readable/scripts/verification/0.3-AI-MANIFEST.a2ml b/.machine_readable/scripts/verification/0.3-AI-MANIFEST.a2ml new file mode 100644 index 0000000..460e069 --- /dev/null +++ b/.machine_readable/scripts/verification/0.3-AI-MANIFEST.a2ml @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: MPL-2.0 +--- +### [META] +id: "automation-unit-verification" +level: 3 +parent: "../0.2-AI-MANIFEST.a2ml" + +--- +### [AI_MANIFEST] +description: | + Internal automation logic for project verification. diff --git a/.machine_readable/scripts/verification/README.adoc b/.machine_readable/scripts/verification/README.adoc new file mode 100644 index 0000000..eb2828e --- /dev/null +++ b/.machine_readable/scripts/verification/README.adoc @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: CC-BY-SA-4.0 +// Copyright (c) Jonathan D.A. Jewell += Verification Scripts From d250ae439a4083818d6a808ce81bbb5d04f34f82 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:28:13 +0100 Subject: [PATCH 2/4] feat(rsr): add tests, benches, ARCHITECTURE, and update README with badges - Add tests/ directory with e2e.sh, aspect_tests.sh, and workflow validation - Add benches/ directory with pons_bench.sh - Add ARCHITECTURE.md with pons-asinorum specific design based on ADRs - Update README.adoc with pons-asinorum title and RSR/Security badges Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- ARCHITECTURE.md | 144 ++++++++++++ README.adoc | 15 +- benches/pons_bench.sh | 227 ++++++++++++++++++ tests/aspect_tests.sh | 134 +++++++++++ tests/e2e.sh | 254 ++++++++++++++++++++ tests/e2e/template_instantiation_test.sh | 258 +++++++++++++++++++++ tests/workflows/validate_workflows_test.sh | 142 ++++++++++++ 7 files changed, 1171 insertions(+), 3 deletions(-) create mode 100644 ARCHITECTURE.md create mode 100755 benches/pons_bench.sh create mode 100755 tests/aspect_tests.sh create mode 100755 tests/e2e.sh create mode 100755 tests/e2e/template_instantiation_test.sh create mode 100755 tests/workflows/validate_workflows_test.sh diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..5fb1cf1 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,144 @@ +# Architecture + +## Overview + +*pons-asinorum* is a depth-first, multi-language static scanner that flags wasted work, self-contradiction, and missing escape hatches. The architecture is designed around the substrate decision (ADR-0001): tree-sitter native with a Rust workspace. + +## Core Design Decisions + +### Substrate: tree-sitter native + Rust +- **Decision**: ADR-0001 accepted tree-sitter native with Rust workspace +- **Rationale**: + - Evidence class must be structural, not conventional + - T2 typestate is not expressible in Semgrep + - T1 needs custom CFG anyway + - Deployment as single static binary (like panic-attack) + - Avoids LGPL-2.1 licence gravity from Semgrep + +### T1 Language: Python +- **Decision**: ADR-0002 selects Python as the first language +- **Rationale**: Clear CFG + dataflow design with complete specification + +### Protocol Spec and Typestate: TOML format +- **Decision**: ADR-0003 defines protocol spec format (TOML) and typestate semantics +- **Rationale**: Standardized, machine-readable specification format + +## High-Level Architecture + +``` +. +├── docs/ # Architecture Decision Records (ADRs) and planning +│ └── adr/ # ADR-0001 through ADR-0004 +│ ├── 0001-substrate.adoc +│ ├── 0002-t1-language-and-cfg.adoc +│ ├── 0003-protocol-spec-and-typestate.adoc +│ └── 0004-companion-to-panic-attack.adoc +├── docs/PLAN.adoc # Milestone-by-milestone implementation plan +├── docs/pons-kickoff.adoc # Mission, species, decidability wall, evidence tiers +├── .machine_readable/ # RSR compliance infrastructure +│ ├── contractiles/ # Machine-readable contracts +│ ├── descriptiles/ # Machine-readable descriptions +│ └── scripts/ # Verification and lifecycle scripts +├── tests/ # Test suites (planning phase) +│ ├── e2e.sh # End-to-end validation of artefacts +│ ├── aspect_tests.sh # Cross-cutting architectural invariants +│ └── workflows/ # CI workflow validation +├── benches/ # Benchmarks (planning phase) +│ └── pons_bench.sh # Performance benchmarks +├── LICENSE # MPL-2.0 for source code +├── LICENSE.adoc # Licence documentation +├── LICENSES/ # Full licence texts +├── README.adoc # Project documentation +└── .github/ # GitHub configuration + ├── workflows/ # CI/CD workflows + ├── CODEOWNERS # No owner lines (Rule 1 - solo maintained) + ├── FUNDING.yml # Funding configuration + └── dependabot.yml # Dependency updates +``` + +## Component Architecture + +### Planned Implementation (Post-Planning Phase) + +Once implementation begins (post-v0.1.0 planning), the architecture will include: + +1. **Parser Layer** + - tree-sitter grammars for Python, JavaScript/TypeScript, Rust + - Grammar version pinning via workspace dependencies + - Exact grammar crate versions pinned (PLAN Appendix F) + +2. **CFG + Dataflow Engine** + - Per-language CFG extraction (Python first, per ADR-0002) + - Reaching definitions for `read-before-init` + - Liveness analysis for `dead-store` + - Typestate semantics (ADR-0003) + +3. **Rule Engine** + - Evidence classes: PROTOCOL, DATAFLOW, HEURISTIC, SPECULATIVE + - Negative corpus for each rule (falsification testing) + - Automatic demotion/removal of rules firing on negative corpus + +4. **Reporter** + - Evidence class visualization + - SPECULATIVE findings visually demoted + - Multiple output formats (JSON, SARIF, human-readable) + +## Evidence Classes + +The core architectural invariant is the evidence class taxonomy: + +- **PROTOCOL**: Findings with mathematical certainty +- **DATAFLOW**: Findings from dataflow analysis +- **HEURISTIC**: Pattern-based findings +- **SPECULATIVE**: Weakest evidence, visually demoted + +Every finding carries its evidence class, and the reporter enforces visual distinction between classes, especially demoting SPECULATIVE findings. + +## Data Flow + +``` +Input Source → Parser (tree-sitter) → AST → CFG Extraction → Dataflow Analysis + ↓ + Typestate Tracking → Rule Matching + ↓ + Finding Generation → Reporter +``` + +## Separation of Concerns + +- **Engine**: Core analysis logic (Rust) +- **Rules**: Rule definitions and negative corpora +- **Reporter**: Output formatting and visualization +- **CLI**: Command-line interface + +## Test Strategy + +- **Positive fixtures**: Test that rules fire on known-bad code +- **Negative fixtures**: Test that rules do NOT fire on known-good code +- **Falsification testing**: Rules that fire on negative corpus are demoted/removed +- **Evidence class validation**: Verify correct classification + +## Deployment + +- Single static binary (inherited from panic-attack design) +- Standalone mode: scans arbitrary source on air-gapped machines +- No external runtime dependencies (tree-sitter grammars compiled in) + +## Security Considerations + +- No network access required for scanning +- Grammars pinned to exact versions +- All external dependencies audited +- No secrets in repository + +## Maintainability + +- All public APIs documented +- Configuration externalized +- Consistent style guidelines +- Pull requests require review and CI checks +- Issues tracked transparently + +--- + +*Last updated: 2026-08-13* diff --git a/README.adoc b/README.adoc index d3811a7..7fa9cb3 100644 --- a/README.adoc +++ b/README.adoc @@ -1,8 +1,17 @@ // SPDX-License-Identifier: CC-BY-SA-4.0 -= pons += pons-asinorum :toc: preamble -*pons* — after the _pons asinorum_ (Euclid I.5, the "bridge of asses"), the +// ── Licensing ─────────────────────────────────────────────────────────────── +image:https://img.shields.io/badge/Code-MPL--2.0-blue.svg?logo=mozilla[Code licence: MPL-2.0,link="https://opensource.org/licenses/MPL-2.0"] +image:https://img.shields.io/badge/Docs-CC--BY--SA--4.0-blue.svg?logo=creativecommons[Docs licence: CC-BY-SA-4.0,link="https://creativecommons.org/licenses/by-sa/4.0/"] + +// ── Standard & quality gates ──────────────────────────────────────────────── +image:https://img.shields.io/badge/RSR-Rhodium_Standard-9C27B0[Rhodium Standard Repository,link="https://github.com/hyperpolymath/rhodium-standard-repositories"] +image:https://api.scorecard.dev/projects/github.com/hyperpolymath/pons-asinorum/badge[OpenSSF Scorecard,link="https://scorecard.dev/viewer/?uri=github.com/hyperpolymath/pons-asinorum"] +image:https://archive.softwareheritage.org/badge/origin/https://github.com/hyperpolymath/pons-asinorum/[Archived in Software Heritage,link="https://archive.softwareheritage.org/browse/origin/?origin_url=https://github.com/hyperpolymath/pons-asinorum"] + +*pons-asinorum* — after the _pons asinorum_ (Euclid I.5, the "bridge of asses"), the historical test that separates real understanding from rote. A lightweight, multi-language static scanner that flags the small set of mistakes mathematicians and computing experts spot on sight but ordinary coders miss — @@ -12,7 +21,7 @@ each finding with an honest label for how strong the evidence is. Design companion to https://github.com/hyperpolymath/panic-attack[panic-attack]: panic-attack is breadth (49 languages, security/panic weak points, line-level patterns + -relational reasoning); pons is depth (a few languages, parse trees + real +relational reasoning); pons-asinorum is depth (a few languages, parse trees + real dataflow + typestate, waste/contradiction smells). See link:docs/adr/0004-companion-to-panic-attack.adoc[ADR-0004]. diff --git a/benches/pons_bench.sh b/benches/pons_bench.sh new file mode 100755 index 0000000..ccce434 --- /dev/null +++ b/benches/pons_bench.sh @@ -0,0 +1,227 @@ +#!/bin/bash +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# Template Benchmarks +# Measures performance characteristics of template validation and build system + +set -euo pipefail + +REPO_ROOT="${1:-.}" +OUTPUT_FORMAT="${2:-human}" # human | json | csv + +# ANSI colors +BLUE='\033[0;34m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${BLUE}→${NC} $*" +} + +log_pass() { + echo -e "${GREEN}✓${NC} $*" +} + +# Ensure we have required commands +command -v /usr/bin/time >/dev/null 2>&1 || { + echo "Warning: /usr/bin/time not available, using built-in time" + TIME_CMD="time" +} + +TIME_CMD="/usr/bin/time -f %e" 2>/dev/null || TIME_CMD="time" + +echo "" +echo "═══════════════════════════════════════════════════════════════════════════════" +echo "pons-asinorum Benchmarks" +echo "═══════════════════════════════════════════════════════════════════════════════" +echo "" + +declare -A results + +#============================================================================== +# BENCHMARK 1: Template Validation +#============================================================================== + +log_info "Running template validation benchmark" + +# Warm-up run +if [ -f "$REPO_ROOT/scripts/validate-template.sh" ]; then + bash "$REPO_ROOT/scripts/validate-template.sh" "$REPO_ROOT" 0 > /dev/null 2>&1 || true +fi + +# Timed runs +BENCH_RUNS=3 +TOTAL_TIME=0 + +for i in $(seq 1 $BENCH_RUNS); do + START=$(date +%s%N) + bash "$REPO_ROOT/scripts/validate-template.sh" "$REPO_ROOT" 0 > /dev/null 2>&1 || true + END=$(date +%s%N) + + # Convert to milliseconds + RUN_TIME=$(( (END - START) / 1000000 )) + TOTAL_TIME=$(( TOTAL_TIME + RUN_TIME )) + + [ "$OUTPUT_FORMAT" = "human" ] && echo " Run $i: ${RUN_TIME}ms" +done + +AVG_VALIDATION_TIME=$(( TOTAL_TIME / BENCH_RUNS )) +results[validation]=$AVG_VALIDATION_TIME +log_pass "Validation: ${AVG_VALIDATION_TIME}ms average (${BENCH_RUNS} runs)" + +#============================================================================== +# BENCHMARK 2: Zig Build +#============================================================================== + +log_info "Running Zig build benchmark" + +if ! command -v zig &> /dev/null; then + echo " ⚠ Zig compiler not found - skipping Zig build benchmark" + results[zig_build]="skipped" +else + cd "$REPO_ROOT/src/interface/ffi" + + # Warm-up + zig build --summary off > /dev/null 2>&1 || true + + # Clean build + BENCH_RUNS=2 + TOTAL_TIME=0 + + for i in $(seq 1 $BENCH_RUNS); do + rm -rf zig-cache + + START=$(date +%s%N) + zig build --summary off > /dev/null 2>&1 || true + END=$(date +%s%N) + + RUN_TIME=$(( (END - START) / 1000000 )) + TOTAL_TIME=$(( TOTAL_TIME + RUN_TIME )) + + [ "$OUTPUT_FORMAT" = "human" ] && echo " Run $i: ${RUN_TIME}ms" + done + + AVG_BUILD_TIME=$(( TOTAL_TIME / BENCH_RUNS )) + results[zig_build]=$AVG_BUILD_TIME + log_pass "Zig build: ${AVG_BUILD_TIME}ms average (clean build, ${BENCH_RUNS} runs)" + + cd - > /dev/null +fi + +#============================================================================== +# BENCHMARK 3: Zig Tests +#============================================================================== + +log_info "Running Zig test benchmark" + +if ! command -v zig &> /dev/null; then + echo " ⚠ Zig compiler not found - skipping Zig test benchmark" + results[zig_test]="skipped" +else + cd "$REPO_ROOT/src/interface/ffi" + + # Warm-up + zig build test --summary off > /dev/null 2>&1 || true + + START=$(date +%s%N) + TEST_OUTPUT=$(zig build test --summary off 2>&1 || true) + END=$(date +%s%N) + + TEST_TIME=$(( (END - START) / 1000000 )) + results[zig_test]=$TEST_TIME + log_pass "Zig tests: ${TEST_TIME}ms" + + # Count tests + TEST_COUNT=$(echo "$TEST_OUTPUT" | grep -c "^test " || echo "unknown") + echo " Test count: $TEST_COUNT" + + cd - > /dev/null +fi + +#============================================================================== +# BENCHMARK 4: Workflow Validation +#============================================================================== + +log_info "Running workflow validation benchmark" + +if [ -f "$REPO_ROOT/tests/workflows/validate_workflows_test.sh" ]; then + START=$(date +%s%N) + bash "$REPO_ROOT/tests/workflows/validate_workflows_test.sh" "$REPO_ROOT/.github/workflows" > /dev/null 2>&1 || true + END=$(date +%s%N) + + WORKFLOW_TIME=$(( (END - START) / 1000000 )) + results[workflow_validation]=$WORKFLOW_TIME + log_pass "Workflow validation: ${WORKFLOW_TIME}ms" +fi + +#============================================================================== +# BENCHMARK 5: Template Instantiation +#============================================================================== + +log_info "Running template instantiation benchmark" + +if [ -f "$REPO_ROOT/tests/e2e/template_instantiation_test.sh" ]; then + START=$(date +%s%N) + bash "$REPO_ROOT/tests/e2e/template_instantiation_test.sh" "$REPO_ROOT" > /dev/null 2>&1 || true + END=$(date +%s%N) + + INSTANTIATION_TIME=$(( (END - START) / 1000000 )) + results[instantiation]=$INSTANTIATION_TIME + log_pass "Template instantiation: ${INSTANTIATION_TIME}ms" +fi + +#============================================================================== +# SUMMARY +#============================================================================== + +echo "" +echo "═══════════════════════════════════════════════════════════════════════════════" +echo "BENCHMARK RESULTS" +echo "═══════════════════════════════════════════════════════════════════════════════" +echo "" + +if [ "$OUTPUT_FORMAT" = "json" ]; then + echo "{" + echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," + echo " \"repo\": \"$REPO_ROOT\"," + echo " \"results\": {" + + count=0 + for key in "${!results[@]}"; do + value="${results[$key]}" + [ $count -gt 0 ] && echo "," + if [ "$value" = "skipped" ]; then + echo -n " \"$key\": \"skipped\"" + else + echo -n " \"$key\": $value" + fi + count=$((count + 1)) + done + echo "" + echo " }" + echo "}" +elif [ "$OUTPUT_FORMAT" = "csv" ]; then + echo "metric,value_ms,timestamp" + for key in "${!results[@]}"; do + value="${results[$key]}" + if [ "$value" != "skipped" ]; then + echo "$key,$value,$(date -u +%Y-%m-%dT%H:%M:%SZ)" + fi + done +else + # Human-readable format + for key in "${!results[@]}"; do + value="${results[$key]}" + if [ "$value" = "skipped" ]; then + printf " %-30s %s\n" "$key:" "SKIPPED" + else + printf " %-30s %5d ms\n" "$key:" "$value" + fi + done +fi + +echo "" +echo "Benchmark complete." +echo "" diff --git a/tests/aspect_tests.sh b/tests/aspect_tests.sh new file mode 100755 index 0000000..028b2c0 --- /dev/null +++ b/tests/aspect_tests.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# RSR Standard Aspect Test Template +# +# Aspect tests validate cross-cutting architectural invariants that span +# the entire codebase. These are NOT functional tests — they verify that +# coding standards, safety rules, and structural contracts hold. +# +# Usage: +# bash tests/aspect_tests.sh +# just aspect +# +# Standard aspects (enable what applies to your project): +# 1. SPDX compliance — all source files have license headers +# 2. Dangerous patterns — no believe_me, assert_total, sorry, unsafeCoerce, etc. +# 3. ABI/FFI contract — declarations match exports +# 4. Thread safety — mutex in FFI modules +# 5. Error handling — no panic/unreachable in production paths + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$PROJECT_DIR" + +PASS=0 +FAIL=0 +WARN=0 + +green() { printf '\033[32m%s\033[0m\n' "$*"; } +red() { printf '\033[31m%s\033[0m\n' "$*"; } +yellow(){ printf '\033[33m%s\033[0m\n' "$*"; } +bold() { printf '\033[1m%s\033[0m\n' "$*"; } + +pass() { green " PASS: $1"; PASS=$((PASS + 1)); } +fail() { red " FAIL: $1"; FAIL=$((FAIL + 1)); } +warn() { yellow " WARN: $1"; WARN=$((WARN + 1)); } + +echo "═══════════════════════════════════════════════════════════════" +echo " {{PROJECT}} — Aspect Tests (Cross-Cutting Concerns)" +echo "═══════════════════════════════════════════════════════════════" +echo "" + +# ═══════════════════════════════════════════════════════════════════════ +# Aspect 1: SPDX License Headers +# ═══════════════════════════════════════════════════════════════════════ +bold "Aspect 1: SPDX license headers" + +MISSING_SPDX=0 +while IFS= read -r -d '' f; do + if ! head -5 "$f" | grep -q "SPDX-License-Identifier"; then + warn "Missing SPDX header: $f" + MISSING_SPDX=$((MISSING_SPDX + 1)) + fi +done < <(find src/ -type f \( -name "*.rs" -o -name "*.zig" -o -name "*.res" -o -name "*.ex" -o -name "*.exs" -o -name "*.gleam" -o -name "*.idr" -o -name "*.sh" \) -print0 2>/dev/null) + +if [ "$MISSING_SPDX" -eq 0 ]; then + pass "All source files have SPDX headers" +else + fail "$MISSING_SPDX files missing SPDX headers" +fi + +# ═══════════════════════════════════════════════════════════════════════ +# Aspect 2: Dangerous Patterns (BANNED) +# ═══════════════════════════════════════════════════════════════════════ +bold "Aspect 2: Dangerous patterns" + +# Idris2 dangerous patterns +DANGEROUS_IDRIS=$(grep -rn 'believe_me\|assert_total\|really_believe_me' src/abi/ 2>/dev/null | grep -v "^Binary" | grep -v "test" || true) +if [ -n "$DANGEROUS_IDRIS" ]; then + fail "Dangerous Idris2 patterns found:" + echo "$DANGEROUS_IDRIS" | head -5 +else + pass "No dangerous Idris2 patterns (believe_me, assert_total)" +fi + +# Coq/Lean dangerous patterns +DANGEROUS_PROOF=$(grep -rn '\bAdmitted\b\|\bsorry\b\|\bunsafeCoerce\b\|\bObj\.magic\b' src/ verification/ 2>/dev/null | grep -v "test" | grep -v "comment" || true) +if [ -n "$DANGEROUS_PROOF" ]; then + fail "Dangerous proof patterns found:" + echo "$DANGEROUS_PROOF" | head -5 +else + pass "No dangerous proof patterns (Admitted, sorry, unsafeCoerce)" +fi + +# ═══════════════════════════════════════════════════════════════════════ +# Aspect 3: ABI/FFI Contract (if applicable) +# ═══════════════════════════════════════════════════════════════════════ +# Uncomment if your project has Idris2 ABI + Zig FFI: + +# bold "Aspect 3: ABI/FFI contract" +# if [ -d "src/abi" ] && [ -d "ffi/zig" ]; then +# # Check that every exported function in Idris2 ABI has a Zig FFI implementation +# ABI_EXPORTS=$(grep -h 'export' src/abi/*.idr 2>/dev/null | wc -l) +# FFI_EXPORTS=$(grep -h 'pub export fn' ffi/zig/src/*.zig 2>/dev/null | wc -l) +# if [ "$ABI_EXPORTS" -gt 0 ] && [ "$FFI_EXPORTS" -gt 0 ]; then +# pass "ABI ($ABI_EXPORTS exports) and FFI ($FFI_EXPORTS exports) both present" +# else +# fail "ABI/FFI mismatch: $ABI_EXPORTS ABI exports, $FFI_EXPORTS FFI exports" +# fi +# else +# pass "ABI/FFI not applicable (no src/abi or ffi/zig)" +# fi + +# ═══════════════════════════════════════════════════════════════════════ +# Aspect 4: Error Handling (no raw panic in production code) +# ═══════════════════════════════════════════════════════════════════════ +# Uncomment for Rust projects: + +# bold "Aspect 4: Error handling" +# UNWRAP_COUNT=$(grep -rn '\.unwrap()' src/ 2>/dev/null | grep -v "test" | grep -v "example" | wc -l) +# if [ "$UNWRAP_COUNT" -gt 20 ]; then +# warn "$UNWRAP_COUNT .unwrap() calls in src/ — consider replacing with ? or expect()" +# else +# pass "Acceptable unwrap count: $UNWRAP_COUNT" +# fi + +# ═══════════════════════════════════════════════════════════════════════ +# Summary +# ═══════════════════════════════════════════════════════════════════════ +echo "" +echo "═══════════════════════════════════════════════════════════════" +printf " Results: " +green "PASS=$PASS" | tr -d '\n' +echo -n " " +if [ "$FAIL" -gt 0 ]; then red "FAIL=$FAIL" | tr -d '\n'; else echo -n "FAIL=0"; fi +echo -n " " +if [ "$WARN" -gt 0 ]; then yellow "WARN=$WARN"; else echo "WARN=0"; fi +echo "" +echo "═══════════════════════════════════════════════════════════════" + +exit "$FAIL" diff --git a/tests/e2e.sh b/tests/e2e.sh new file mode 100755 index 0000000..5888c3c --- /dev/null +++ b/tests/e2e.sh @@ -0,0 +1,254 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) +# +# pons-asinorum — End-to-End Tests +# +# Since pons is currently in planning phase (implementation not started), +# these tests validate the documentation and design artefacts. +# +# Usage: +# bash tests/e2e.sh +# just e2e +# +# Merge requirements (STANDING): All 6 test categories must pass before merge: +# P2P, E2E (this file), aspect, execution, lifecycle, benchmarks + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +PASS=0 +FAIL=0 +SKIP=0 + +# ─── Colour helpers ────────────────────────────────────────────────── +green() { printf '\033[32m%s\033[0m\n' "$*"; } +red() { printf '\033[31m%s\033[0m\n' "$*"; } +yellow(){ printf '\033[33m%s\033[0m\n' "$*"; } +bold() { printf '\033[1m%s\033[0m\n' "$*"; } + +# ─── Assertion helpers ─────────────────────────────────────────────── + +# check