|
| 1 | +// SPDX-License-Identifier: MPL-2.0 |
| 2 | +// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk> |
| 3 | += Echidna Contractiles |
| 4 | +Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk> |
| 5 | +:toc: |
| 6 | +:sectnums: |
| 7 | + |
| 8 | +This directory holds Echidna's *contractiles* — the machine-readable |
| 9 | +contracts that make the project's invariants, trust boundary, recovery |
| 10 | +story, drift tolerances, hard-stop conditions, and north-star intent |
| 11 | +legible to CI, the contractile CLI, and Hypatia rules. |
| 12 | + |
| 13 | +Echidna is a trust-hardened neurosymbolic theorem-proving platform, so |
| 14 | +these contracts are not decorative: `must` and `trust` gate merges, |
| 15 | +`bust` declares deprecated-path hard-stops, and `dust` governs how |
| 16 | +recovery happens without losing the audit trail. |
| 17 | + |
| 18 | +The estate-level audit semantics (what each verb *means* and the |
| 19 | +minimum bar for "real contract vs template residue") are defined in |
| 20 | +`standards/contractiles/CANONICAL-TEMPLATES.adoc`. The normative |
| 21 | +per-file specification is `docs/CONTRACTILE-SPEC.adoc`. This README |
| 22 | +documents the local realisation. |
| 23 | + |
| 24 | +== Layout — the trident shape |
| 25 | + |
| 26 | +Each verb lives in its own directory as a complete *trident* plus a |
| 27 | +coherence manifest: |
| 28 | + |
| 29 | +* `<Verb>file.a2ml` — the project-specific *declaration* (data: the |
| 30 | + actual invariants / trust actions / tolerances / intents). |
| 31 | +* `<verb>.ncl` — the paired Nickel *runner* (pedigree + schema + run |
| 32 | + policy). Imports `../_base.ncl`. |
| 33 | +* `<verb>.k9.ncl` — the *K9 trust-tier component* (execution surface, |
| 34 | + evidence sinks, session-open/close negotiation). Imports the Hunt |
| 35 | + base via `../k9/template-hunt.k9.ncl` and `../_base.ncl`. |
| 36 | +* `<verb>.manifest.a2ml` — the *trident coherence manifest* (file roles, |
| 37 | + cross-refs, signature, history). |
| 38 | + |
| 39 | +Filenames use the lowercase verb in the `.ncl`/`.manifest` names and |
| 40 | +noun-form PascalCase in the A2ML declaration (e.g. `intend.ncl` + |
| 41 | +`Intentfile.a2ml`, `must.ncl` + `Mustfile.a2ml`). |
| 42 | + |
| 43 | +`_base.ncl` provides the shared `pedigree_schema`, `run_defaults`, and |
| 44 | +`probe_schema` that every runner merges into. `INDEX.a2ml` is the |
| 45 | +machine-readable registry of all verbs — consumers should read it |
| 46 | +rather than hard-coding the verb list. |
| 47 | + |
| 48 | +== Verbs (6 + k9 exception) |
| 49 | + |
| 50 | +[cols="1,2,3", options="header"] |
| 51 | +|=== |
| 52 | +| Verb | Declaration | Role (and gating) |
| 53 | + |
| 54 | +| `must` |
| 55 | +| `must/Mustfile.a2ml` |
| 56 | +| Release-blocking physical-state invariants (LICENSE/README presence, |
| 57 | + banned hardcoded paths, no Dockerfile/Makefile, …). *Gating* — |
| 58 | + hard `exit-nonzero`. Specialises in subtle invariant-erosion. |
| 59 | + |
| 60 | +| `trust` |
| 61 | +| `trust/Trustfile.a2ml` |
| 62 | +| Trust boundary, allowed/denied actions, provenance + supply-chain |
| 63 | + integrity, dispatcher-trust (`T###` namespace). *Gating* — hard |
| 64 | + `exit-nonzero`. Primary defence against unsound proofs leaving the |
| 65 | + dispatcher. |
| 66 | + |
| 67 | +| `adjust` |
| 68 | +| `adjust/Adjustfile.a2ml` |
| 69 | +| Drift tolerances + corrective actions; deterministic auto-fix where |
| 70 | + declared. Advisory (`continue-with-warnings`), Yard tier. |
| 71 | + |
| 72 | +| `dust` |
| 73 | +| `dust/Dustfile.a2ml` |
| 74 | +| Fine-grained recovery / rollback / deprecation with audit-trail |
| 75 | + preservation (`D###` namespace). Destructive actions are dry-run by |
| 76 | + default and require `--apply` + per-item approval. Advisory. |
| 77 | + |
| 78 | +| `bust` |
| 79 | +| `bust/Bustfile.a2ml` |
| 80 | +| Breakage / expiry / hard-stop — declares "this is broken / must-not-run" |
| 81 | + (e.g. deprecated paths that still exist). *Gating* — hard `exit-nonzero`. |
| 82 | + |
| 83 | +| `intend` |
| 84 | +| `intend/Intentfile.a2ml` |
| 85 | +| North-star: committed next-actions (`[[intents]]`, with probes) AND |
| 86 | + horizon aspirations (`[[wishes]]`, near/mid/far, no probes). |
| 87 | + Non-gating (report only). Absorbed the deprecated `lust` verb |
| 88 | + 2026-04-18. |
| 89 | +|=== |
| 90 | + |
| 91 | +NOTE: The `lust` verb was deprecated 2026-04-18 (name had unwanted |
| 92 | +associations); its `[[wishes]]` semantics now live inside |
| 93 | +`intend/Intentfile.a2ml` as a second section alongside `[[intents]]`. |
| 94 | +Any `lust/` directory is drift and should be removed. |
| 95 | + |
| 96 | +== Intentfile: commitments vs aspirations — two sections, one file |
| 97 | + |
| 98 | +* `[[intents]]` is the *commitment axis*: tracked next-actions with |
| 99 | + observable probes. Status progresses |
| 100 | + `declared → in_progress → done / deferred / retired`. |
| 101 | +* `[[wishes]]` is the *aspiration axis*: horizon goals grouped |
| 102 | + near/mid/far, no probes. Status progresses |
| 103 | + `declared → in_progress → achieved / abandoned`. |
| 104 | + |
| 105 | +If something is concrete enough to have a probe, it is an intent; a |
| 106 | +horizon-level desire that might never be acted on is a wish. A wish can |
| 107 | +graduate into an intent when a concrete plan materialises. Intent is |
| 108 | +guidance, never evidence of completion. |
| 109 | + |
| 110 | +== k9 — service-automation layer (EXCEPTION to the one-verbfile rule) |
| 111 | + |
| 112 | +`k9` is *not* a contractile verb and deliberately does not follow the |
| 113 | +`<Verb>file.a2ml` + `<verb>.ncl` pattern. It is the graded automation |
| 114 | +surface (three trust tiers) that validates or enforces the verb |
| 115 | +declarations: |
| 116 | + |
| 117 | +* *Kennel* — pure data; no subprocess, filesystem write, or network. |
| 118 | +* *Yard* — Nickel evaluation with contracts/validation; no side effects. |
| 119 | +* *Hunt* — full execution surface; must declare side effects, support |
| 120 | + dry-run, and be signed before being trusted. |
| 121 | + |
| 122 | +Each per-verb `<verb>.k9.ncl` declares a `paired_xfile` pointing at its |
| 123 | +contractile (e.g. `../must/Mustfile.a2ml`); a floating k9 component with |
| 124 | +no paired xfile is non-conformant. |
| 125 | + |
| 126 | +[NOTE] |
| 127 | +==== |
| 128 | +*Local k9-base status.* Echidna's three trust-tier templates currently |
| 129 | +live under `../svc/k9/` (`template-kennel.k9.ncl`, `template-yard.k9.ncl`, |
| 130 | +`template-hunt.k9.ncl`). The per-verb `<verb>.k9.ncl` components import the |
| 131 | +canonical `../k9/template-hunt.k9.ncl` base path used estate-wide; that |
| 132 | +shared Hunt base is a known estate-level gap (the same import is unresolved |
| 133 | +in `standards`) and is tracked by the machine-readable respec programme |
| 134 | +rather than patched per-repo here. The runner `.ncl` files (which import |
| 135 | +only `_base.ncl`) `nickel typecheck` clean. |
| 136 | +==== |
| 137 | + |
| 138 | +== Fill-in / maintenance rules |
| 139 | + |
| 140 | +. Every declaration must hold real, project-specific content — no |
| 141 | + generic samples, no `rsr-template` residue. |
| 142 | +. `Mustfile` must encode invariants the toolchain can actually check. |
| 143 | +. `Trustfile` must name the real keys, policies, and authority |
| 144 | + boundaries. Per estate policy, licence/SPDX findings are *flag-only* |
| 145 | + here — never auto-edited. |
| 146 | +. `Dustfile` must describe real rollback/deprecation behaviour and what |
| 147 | + evidence persists after a rollback. |
| 148 | +. `Bustfile` must declare real breakage / expiry / hard-stop conditions. |
| 149 | +. `Intentfile` must separate probed `[[intents]]` from horizon |
| 150 | + `[[wishes]]`. |
| 151 | +. Pair each `k9/*.k9.ncl` to a specific contractile via `paired_xfile`. |
0 commit comments