Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 3 additions & 21 deletions .github/workflows/governance.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,16 @@
# SPDX-License-Identifier: MPL-2.0
# governance.yml β€” single wrapper calling the shared estate governance bundle
# in hyperpolymath/standards instead of carrying per-repo copies.
#
# Replaces the per-repo governance scaffolding removed in the same commit:
# quality.yml, guix-nix-policy.yml, npm-bun-blocker.yml, ts-blocker.yml,
# security-policy.yml, rsr-antipattern.yml, wellknown-enforcement.yml,
# workflow-linter.yml
#
# Load-bearing build/security workflows stay standalone in the repo
# (rust-ci, codeql, dependabot, release, scan/mirror/pages plumbing).

# SPDX-License-Identifier: PMPL-1.0-or-later
name: Governance

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch:

# Estate guardrail: cancel superseded runs so re-pushes / rebased PR
# updates do not pile up queued runs against the shared account-wide
# Actions concurrency pool. Applied only to read-only check workflows
# (no publish/mutation), so cancelling a superseded run is always safe.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
governance:
uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@3f34549c03274ec7a74683068f03a492b0fa805f # main 2026-06-01 (R5 generic β€” standards#330; consumes .github/canonical-references/)
uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@5a93d9d57cc04de4002d6d0ecd336fc7a8698910
19 changes: 4 additions & 15 deletions .github/workflows/hypatia-scan.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# SPDX-License-Identifier: MPL-2.0
# Thin wrapper around hyperpolymath/standards hypatia-scan-reusable.yml.
# See standards#191 for the reusable's purpose and design.

# SPDX-License-Identifier: PMPL-1.0-or-later
name: Hypatia Security Scan

on:
Expand All @@ -13,18 +10,10 @@ on:
- cron: '0 0 * * 0'
workflow_dispatch:

# Estate guardrail: cancel superseded runs so re-pushes don't pile up.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read
security-events: write
pull-requests: write
security-events: read

jobs:
hypatia:
uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@6cd3772824e59c8c9affeab66061e25383544242
timeout-minutes: 10
secrets: inherit
scan:
Comment thread
hyperpolymath marked this conversation as resolved.
uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@5a93d9d57cc04de4002d6d0ecd336fc7a8698910
108 changes: 0 additions & 108 deletions .github/workflows/scorecard-enforcer.yml

This file was deleted.

23 changes: 10 additions & 13 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# SPDX-License-Identifier: MPL-2.0
name: Scorecards supply-chain security
# SPDX-License-Identifier: PMPL-1.0-or-later
name: OSSF Scorecard

on:
branch_protection_rule:
schedule:
- cron: '23 4 * * 1'
push:
branches: [main]
branches: [main, master]
schedule:
- cron: '0 4 * * *'
workflow_dispatch:

permissions: read-all
permissions:
contents: read

jobs:
analysis:
permissions:
security-events: write
id-token: write
uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@e03686486e11b662834d7090dffae54c3e96fd59 # main 2026-05-28 (SPDX bump #249)
secrets: inherit
scorecard:
uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@5a93d9d57cc04de4002d6d0ecd336fc7a8698910
Comment thread
hyperpolymath marked this conversation as resolved.
6 changes: 6 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,9 @@ deploy-release:
url: "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
only:
- tags

trufflehog:
stage: security
image: trufflesecurity/trufflehog:latest
script:
- trufflehog git file://. --only-verified --fail
Comment thread
hyperpolymath marked this conversation as resolved.
2 changes: 1 addition & 1 deletion .machine_readable/contractiles/INDEX.a2ml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ 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."
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. All six verbs are now complete tridents (declaration + runner + k9 component) with coherence manifests."

[[verbs]]
name = "k9"
Expand Down
151 changes: 151 additions & 0 deletions .machine_readable/contractiles/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
= Echidna Contractiles
Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
:toc:
:sectnums:

This directory holds Echidna's *contractiles* β€” the machine-readable
contracts that make the project's invariants, trust boundary, recovery
story, drift tolerances, hard-stop conditions, and north-star intent
legible to CI, the contractile CLI, and Hypatia rules.

Echidna is a trust-hardened neurosymbolic theorem-proving platform, so
these contracts are not decorative: `must` and `trust` gate merges,
`bust` declares deprecated-path hard-stops, and `dust` governs how
recovery happens without losing the audit trail.

The estate-level audit semantics (what each verb *means* and the
minimum bar for "real contract vs template residue") are defined in
`standards/contractiles/CANONICAL-TEMPLATES.adoc`. The normative
per-file specification is `docs/CONTRACTILE-SPEC.adoc`. This README
documents the local realisation.

== Layout β€” the trident shape

Each verb lives in its own directory as a complete *trident* plus a
coherence manifest:

* `<Verb>file.a2ml` β€” the project-specific *declaration* (data: the
actual invariants / trust actions / tolerances / intents).
* `<verb>.ncl` β€” the paired Nickel *runner* (pedigree + schema + run
policy). Imports `../_base.ncl`.
* `<verb>.k9.ncl` β€” the *K9 trust-tier component* (execution surface,
evidence sinks, session-open/close negotiation). Imports the Hunt
base via `../k9/template-hunt.k9.ncl` and `../_base.ncl`.
* `<verb>.manifest.a2ml` β€” the *trident coherence manifest* (file roles,
cross-refs, signature, history).

Filenames use the lowercase verb in the `.ncl`/`.manifest` names and
noun-form PascalCase in the A2ML declaration (e.g. `intend.ncl` +
`Intentfile.a2ml`, `must.ncl` + `Mustfile.a2ml`).

`_base.ncl` provides the shared `pedigree_schema`, `run_defaults`, and
`probe_schema` that every runner merges into. `INDEX.a2ml` is the
machine-readable registry of all verbs β€” consumers should read it
rather than hard-coding the verb list.

== Verbs (6 + k9 exception)

[cols="1,2,3", options="header"]
|===
| Verb | Declaration | Role (and gating)

| `must`
| `must/Mustfile.a2ml`
| Release-blocking physical-state invariants (LICENSE/README presence,
banned hardcoded paths, no Dockerfile/Makefile, …). *Gating* β€”
hard `exit-nonzero`. Specialises in subtle invariant-erosion.

| `trust`
| `trust/Trustfile.a2ml`
| Trust boundary, allowed/denied actions, provenance + supply-chain
integrity, dispatcher-trust (`T###` namespace). *Gating* β€” hard
`exit-nonzero`. Primary defence against unsound proofs leaving the
dispatcher.

| `adjust`
| `adjust/Adjustfile.a2ml`
| Drift tolerances + corrective actions; deterministic auto-fix where
declared. Advisory (`continue-with-warnings`), Yard tier.

| `dust`
| `dust/Dustfile.a2ml`
| Fine-grained recovery / rollback / deprecation with audit-trail
preservation (`D###` namespace). Destructive actions are dry-run by
default and require `--apply` + per-item approval. Advisory.

| `bust`
| `bust/Bustfile.a2ml`
| Breakage / expiry / hard-stop β€” declares "this is broken / must-not-run"
(e.g. deprecated paths that still exist). *Gating* β€” hard `exit-nonzero`.

| `intend`
| `intend/Intentfile.a2ml`
| North-star: committed next-actions (`[[intents]]`, with probes) AND
horizon aspirations (`[[wishes]]`, near/mid/far, no probes).
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 now live inside
`intend/Intentfile.a2ml` as a second section alongside `[[intents]]`.
Any `lust/` directory is drift and should be removed.

== Intentfile: commitments vs aspirations β€” two sections, one file

* `[[intents]]` is the *commitment axis*: tracked next-actions with
observable probes. Status progresses
`declared β†’ in_progress β†’ done / deferred / retired`.
* `[[wishes]]` is the *aspiration axis*: horizon goals grouped
near/mid/far, no probes. Status progresses
`declared β†’ in_progress β†’ achieved / abandoned`.

If something is concrete enough to have a probe, it is an intent; a
horizon-level desire that might never be acted on is a wish. A wish can
graduate into an intent when a concrete plan materialises. Intent is
guidance, never evidence of completion.

== k9 β€” service-automation layer (EXCEPTION to the one-verbfile rule)

`k9` is *not* a contractile verb and deliberately does not follow the
`<Verb>file.a2ml` + `<verb>.ncl` pattern. It is the graded automation
surface (three trust tiers) that validates or enforces the verb
declarations:

* *Kennel* β€” pure data; no subprocess, filesystem write, or network.
* *Yard* β€” Nickel evaluation with contracts/validation; no side effects.
* *Hunt* β€” full execution surface; must declare side effects, support
dry-run, and be signed before being trusted.

Each per-verb `<verb>.k9.ncl` declares a `paired_xfile` pointing at its
contractile (e.g. `../must/Mustfile.a2ml`); a floating k9 component with
no paired xfile is non-conformant.

[NOTE]
====
*Local k9-base status.* Echidna's three trust-tier templates currently
live under `../svc/k9/` (`template-kennel.k9.ncl`, `template-yard.k9.ncl`,
`template-hunt.k9.ncl`). The per-verb `<verb>.k9.ncl` components import the
canonical `../k9/template-hunt.k9.ncl` base path used estate-wide; that
shared Hunt base is a known estate-level gap (the same import is unresolved
in `standards`) and is tracked by the machine-readable respec programme
rather than patched per-repo here. The runner `.ncl` files (which import
only `_base.ncl`) `nickel typecheck` clean.
====

== Fill-in / maintenance rules

. Every declaration must hold real, project-specific content β€” no
generic samples, no `rsr-template` residue.
. `Mustfile` must encode invariants the toolchain can actually check.
. `Trustfile` must name the real keys, policies, and authority
boundaries. Per estate policy, licence/SPDX findings are *flag-only*
here β€” never auto-edited.
. `Dustfile` must describe real rollback/deprecation behaviour and what
evidence persists after a rollback.
. `Bustfile` must declare real breakage / expiry / hard-stop conditions.
. `Intentfile` must separate probed `[[intents]]` from horizon
`[[wishes]]`.
. Pair each `k9/*.k9.ncl` to a specific contractile via `paired_xfile`.
Loading