From 0ef3115ec42b8a6d6833f5feb2bd953e9aa3c325 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 9 Sep 2026 02:21:04 +0100 Subject: [PATCH 1/8] fix(ci): pin standards reusables to main HEAD 8f2ee508 This repo's standards reusable pins are re-pointed at the standards default-branch HEAD, resolved live at sweep time. The prior refs are recorded in the verification line below. Three kinds of drift are repaired together and the body does not claim which one this repo had: an UNREACHABLE sha kills the run at workflow STARTUP, so GitHub reports no check at all rather than a failing one and the gate disappears instead of going red; a FLOATING ref (@main) is unpinned supply chain; a merely STALE but reachable sha silently reintroduces every bug fixed since it. files=6 pins=6 perms=0 permlines=0 from=5b1d00229e5e8c0c0fbfedc7e80f37ea50f49236,81dbf2dd854b1444fd6236fa2352474383b2c2b9,c65436ee3351cd6b0fa14b142938b195efc77586 target=8f2ee508 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_0178nN4Nm3neFRy5K9StZKnB --- .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- .github/workflows/mirror.yml | 2 +- .github/workflows/rust-ci.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 931cef9..80ad396 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -14,4 +14,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@81dbf2dd854b1444fd6236fa2352474383b2c2b9 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 3c08e0a..f3ee0db 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -17,4 +17,4 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@81dbf2dd854b1444fd6236fa2352474383b2c2b9 + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index c0c9631..2a01cf5 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -11,5 +11,5 @@ permissions: contents: read jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@5b1d00229e5e8c0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c secrets: inherit diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index a49ca8a..2813755 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -14,4 +14,4 @@ permissions: contents: read jobs: rust-ci: - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@5b1d00229e5e8c0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 11cf6c5..2eb0795 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -13,7 +13,7 @@ permissions: id-token: write jobs: scorecard: - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@5b1d00229e5e8c0c0fbfedc7e80f37ea50f49236 + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c permissions: contents: read security-events: write diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 9149329..d780d6d 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -17,5 +17,5 @@ jobs: scan: permissions: contents: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@c65436ee3351cd6b0fa14b142938b195efc77586 + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c secrets: inherit From 0cecc2f5d68853709d166e61c423f66110474f69 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 9 Sep 2026 21:42:35 +0100 Subject: [PATCH 2/8] fix(ci): reconcile descriptile policies and validate executable session contracts --- .envrc | 7 +- .github/pull_request_template.md | 6 +- .../{workflows => workflow-templates}/e2e.yml | 5 +- .github/workflows/actions.lock | 93 +++++++++++++++++++ .github/workflows/boj-build.yml | 3 +- .github/workflows/codeql.yml | 9 +- .github/workflows/dependabot-automerge.yml | 3 +- .github/workflows/dogfood-gate.yml | 11 ++- .github/workflows/governance.yml | 3 +- .github/workflows/hypatia-scan.yml | 3 +- .github/workflows/instant-sync.yml | 10 +- .github/workflows/label-triage.yml | 1 + .github/workflows/labels.yml | 1 + .github/workflows/mirror.yml | 1 + .github/workflows/openssf-compliance.yml | 15 +-- .github/workflows/pages.yml | 9 +- .github/workflows/release.yml | 11 ++- .github/workflows/repository-validation.yml | 33 +++++++ .github/workflows/rhodibot.yml | 3 +- .github/workflows/rust-ci.yml | 1 + .github/workflows/scorecard.yml | 1 + .github/workflows/secret-scanner.yml | 1 + .github/workflows/static-analysis-gate.yml | 23 ++--- .machine_readable/ECOSYSTEM.a2ml | 8 -- .machine_readable/META.a2ml | 10 -- .machine_readable/ai/.clinerules | 2 +- .machine_readable/ai/.windsurfrules | 2 +- .machine_readable/ai/AI.a2ml | 2 +- .machine_readable/ai/README.adoc | 4 +- .machine_readable/contractiles/Justfile | 50 +++++----- .machine_readable/contractiles/Mustfile.a2ml | 4 +- .../{6a2 => descriptiles}/0-AI-MANIFEST.a2ml | 0 .../{6a2 => descriptiles}/AGENTIC.a2ml | 0 .../{6a2 => descriptiles}/ECOSYSTEM.a2ml | 0 .../{6a2 => descriptiles}/META.a2ml | 2 + .../{6a2 => descriptiles}/NEUROSYM.a2ml | 0 .../{6a2 => descriptiles}/PLAYBOOK.a2ml | 2 +- .../{6a2 => descriptiles}/README.adoc | 0 .../{6a2 => descriptiles}/STATE.a2ml | 0 .../anchor/0-AI-MANIFEST.a2ml | 0 .../{6a2 => descriptiles}/anchor/ANCHOR.a2ml | 0 .../{6a2 => descriptiles}/anchor/README.adoc | 0 .../policies/MAINTENANCE-AXES.a2ml | 2 +- 0-AI-MANIFEST.a2ml | 2 +- EXPLAINME.adoc | 4 +- Justfile | 58 ++++++------ container/deploy.k9.ncl | 10 +- coordination.k9 | 43 --------- coordination.k9.ncl | 49 ++++++++++ docs/RSR_OUTLINE.adoc | 2 +- docs/governance/MAINTENANCE-CHECKLIST.a2ml | 1 + docs/practice/AI-CONVENTIONS.adoc | 4 +- scripts/validate-session-contracts.sh | 20 ++++ session/README.adoc | 2 +- session/custom-checks.k9 | 15 --- session/custom-checks.k9.ncl | 51 ++++++++++ setup.sh | 12 +-- tests/e2e/template_instantiation_test.sh | 4 +- 58 files changed, 406 insertions(+), 212 deletions(-) rename .github/{workflows => workflow-templates}/e2e.yml (99%) create mode 100644 .github/workflows/actions.lock create mode 100644 .github/workflows/repository-validation.yml delete mode 100644 .machine_readable/ECOSYSTEM.a2ml delete mode 100644 .machine_readable/META.a2ml rename .machine_readable/{6a2 => descriptiles}/0-AI-MANIFEST.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/AGENTIC.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/ECOSYSTEM.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/META.a2ml (97%) rename .machine_readable/{6a2 => descriptiles}/NEUROSYM.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/PLAYBOOK.a2ml (93%) rename .machine_readable/{6a2 => descriptiles}/README.adoc (100%) rename .machine_readable/{6a2 => descriptiles}/STATE.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/anchor/0-AI-MANIFEST.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/anchor/ANCHOR.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/anchor/README.adoc (100%) delete mode 100644 coordination.k9 create mode 100644 coordination.k9.ncl create mode 100644 scripts/validate-session-contracts.sh delete mode 100644 session/custom-checks.k9 create mode 100644 session/custom-checks.k9.ncl diff --git a/.envrc b/.envrc index ef739ef..89f780e 100644 --- a/.envrc +++ b/.envrc @@ -12,15 +12,10 @@ if has guix && [ -f guix.scm ]; then use guix fi -# Load Nix flake if flake.nix exists -if has nix && [ -f flake.nix ]; then -fi - # Project environment variables -export PROJECT_NAME="{{PROJECT_NAME}}" +export PROJECT_NAME="natsci-studio" export RSR_TIER="infrastructure" # export DATABASE_URL="..." -# export API_KEY="..." # Source .env if it exists (gitignored) dotenv_if_exists diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 2132109..65789e9 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -29,9 +29,9 @@ Copyright (c) Jonathan D.A. Jewell ### As Applicable -- [ ] `.machine_readable/STATE.a2ml` updated (if project state changed) -- [ ] `.machine_readable/ECOSYSTEM.a2ml` updated (if integrations changed) -- [ ] `.machine_readable/META.a2ml` updated (if architectural decisions changed) +- [ ] `.machine_readable/descriptiles/STATE.a2ml` updated (if project state changed) +- [ ] `.machine_readable/descriptiles/ECOSYSTEM.a2ml` updated (if integrations changed) +- [ ] `.machine_readable/descriptiles/META.a2ml` updated (if architectural decisions changed) - [ ] Documentation updated for user-facing changes - [ ] `TOPOLOGY.md` updated (if architecture changed) - [ ] `CHANGELOG` or release notes updated diff --git a/.github/workflows/e2e.yml b/.github/workflow-templates/e2e.yml similarity index 99% rename from .github/workflows/e2e.yml rename to .github/workflow-templates/e2e.yml index 819072d..927a624 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflow-templates/e2e.yml @@ -22,13 +22,14 @@ on: - 'tests/**' - '.github/workflows/e2e.yml' pull_request: - branches: [main, master] + branches: ['**'] paths: - 'src/**' - 'ffi/**' - 'tests/**' workflow_dispatch: -permissions: read-all +permissions: + contents: read actions: read concurrency: group: e2e-${{ github.ref }} diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock new file mode 100644 index 0000000..df7f905 --- /dev/null +++ b/.github/workflows/actions.lock @@ -0,0 +1,93 @@ +# This file is machine-generated by `gh actions-lock`. +# Do not edit by hand; run `gh actions-lock` to update. +# Docs: https://gh.io/actions-lockfile +version: 'v0.0.2' +workflows: + '.github/workflows/boj-build.yml': + - 'actions/checkout@v7.0.1' + '.github/workflows/codeql.yml': + - 'actions/checkout@v7.0.1' + - 'github/codeql-action@v3.37.3' + '.github/workflows/dependabot-automerge.yml': + - 'dependabot/fetch-metadata@v3.1.0' + '.github/workflows/dogfood-gate.yml': + - 'actions/checkout@v7.0.1' + '.github/workflows/instant-sync.yml': + - 'peter-evans/repository-dispatch@v4.0.1' + '.github/workflows/openssf-compliance.yml': + - 'actions/checkout@v7.0.1' + '.github/workflows/pages.yml': + - 'actions/checkout@v7.0.1' + - 'actions/deploy-pages@v5.0.0' + - 'actions/upload-pages-artifact@v5.0.0' + '.github/workflows/release.yml': + - 'actions/checkout@v7.0.1' + - 'actions/upload-artifact@v7.0.1' + - 'softprops/action-gh-release@v3.0.2' + '.github/workflows/repository-validation.yml': + - 'actions/checkout@v7.0.1' + '.github/workflows/rhodibot.yml': + - 'actions/checkout@v7.0.1' + '.github/workflows/static-analysis-gate.yml': + - 'actions/checkout@v7.0.1' + - 'actions/download-artifact@v8.0.1' + - 'actions/upload-artifact@v7.0.1' + - 'erlef/setup-beam@v1.24.1' +dependencies: + 'actions/checkout@v7.0.1': + ref: 'v7.0.1' + commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' + owner_id: 44036562 + repo_id: 197814629 + 'actions/deploy-pages@v5.0.0': + ref: 'v5.0.0' + commit: 'sha1-cd2ce8fcbc39b97be8ca5fce6e763baed58fa128' + owner_id: 44036562 + repo_id: 438112499 + 'actions/download-artifact@v8.0.1': + ref: 'v8.0.1' + commit: 'sha1-3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c' + owner_id: 44036562 + repo_id: 192626254 + 'actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f': + ref: 'v7.0.0' + commit: 'sha1-bbbca2ddaa5d8feaa63e36b76fdaad77386f024f' + owner_id: 44036562 + repo_id: 192625955 + 'actions/upload-artifact@v7.0.1': + ref: 'v7.0.1' + commit: 'sha1-043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + owner_id: 44036562 + repo_id: 192625955 + 'actions/upload-pages-artifact@v5.0.0': + ref: 'v5.0.0' + commit: 'sha1-fc324d3547104276b827a68afc52ff2a11cc49c9' + owner_id: 44036562 + repo_id: 496012378 + uses: + - 'actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f' + 'dependabot/fetch-metadata@v3.1.0': + ref: 'v3.1.0' + commit: 'sha1-25dd0e34f4fe68f24cc83900b1fe3fe149efef98' + owner_id: 27347476 + repo_id: 371068214 + 'erlef/setup-beam@v1.24.1': + ref: 'v1.24.1' + commit: 'sha1-54075bcc5e249e4758d363f27d099f55d843f124' + owner_id: 47606891 + repo_id: 331103973 + 'github/codeql-action@v3.37.3': + ref: 'v3.37.3' + commit: 'sha1-4187e74d05793876e9989daffde9c3e66b4acd07' + owner_id: 9919 + repo_id: 259445878 + 'peter-evans/repository-dispatch@v4.0.1': + ref: 'v4.0.1' + commit: 'sha1-28959ce8df70de7be546dd1250a005dd32156697' + owner_id: 18365890 + repo_id: 220359305 + 'softprops/action-gh-release@v3.0.2': + ref: 'v3.0.2' + commit: 'sha1-3d0d9888cb7fd7b750713d6e236d1fcb99157228' + owner_id: 2242 + repo_id: 204253808 diff --git a/.github/workflows/boj-build.yml b/.github/workflows/boj-build.yml index de12acb..63f4519 100644 --- a/.github/workflows/boj-build.yml +++ b/.github/workflows/boj-build.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -21,7 +22,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Trigger BoJ Server (Casket/ssg-mcp) env: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d42c3dc..5e72424 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -6,7 +7,7 @@ on: push: branches: [main, master] pull_request: - branches: [main, master] + branches: ['**'] schedule: - cron: '0 6 1 * *' # monthly 1st 06:00 UTC @@ -35,14 +36,14 @@ jobs: build-mode: none steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Initialize CodeQL - uses: github/codeql-action/init@4187e74d05793876e9989daffde9c3e66b4acd07 # v3 + uses: github/codeql-action/init@v3.37.3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4187e74d05793876e9989daffde9c3e66b4acd07 # v3 + uses: github/codeql-action/analyze@v3.37.3 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index dc5465a..6706ef2 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -54,7 +55,7 @@ jobs: steps: - name: Fetch Dependabot metadata id: meta - uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 + uses: dependabot/fetch-metadata@v3.1.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} # --- Policy gate ------------------------------------------------------- diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index c38650f..f4e1f56 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # @@ -23,7 +24,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Check for A2ML files id: detect @@ -61,7 +62,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Check for K9 files id: detect @@ -104,7 +105,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Scan for invisible characters id: lint @@ -166,7 +167,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Check for Groove manifest id: groove @@ -224,7 +225,7 @@ jobs: if: always() steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Generate dogfooding scorecard run: | diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 80ad396..13373fc 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: Governance @@ -5,7 +6,7 @@ on: push: branches: [main, master] pull_request: - branches: [main, master] + branches: ['**'] workflow_dispatch: permissions: diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index f3ee0db..d65edb6 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: Hypatia Security Scan @@ -5,7 +6,7 @@ on: push: branches: [main, master, develop] pull_request: - branches: [main, master] + branches: ['**'] schedule: - cron: '0 0 * * 0' workflow_dispatch: diff --git a/.github/workflows/instant-sync.yml b/.github/workflows/instant-sync.yml index 577a104..6489936 100644 --- a/.github/workflows/instant-sync.yml +++ b/.github/workflows/instant-sync.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -15,9 +16,12 @@ jobs: dispatch: runs-on: ubuntu-latest timeout-minutes: 15 + env: + FARM_DISPATCH_TOKEN: ${{ secrets.FARM_DISPATCH_TOKEN }} steps: - name: Trigger Propagation - uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v3 + if: env.FARM_DISPATCH_TOKEN != '' + uses: peter-evans/repository-dispatch@v4.0.1 with: token: ${{ secrets.FARM_DISPATCH_TOKEN }} repository: hyperpolymath/.git-private-farm @@ -30,6 +34,10 @@ jobs: "forges": "" } - name: Confirm + if: env.FARM_DISPATCH_TOKEN != '' env: REPO_NAME: ${{ github.event.repository.name }} run: echo "::notice::Propagation triggered for ${REPO_NAME}" + - name: Propagation not configured + if: env.FARM_DISPATCH_TOKEN == '' + run: echo "::notice::FARM_DISPATCH_TOKEN is not configured; propagation was not requested" diff --git a/.github/workflows/label-triage.yml b/.github/workflows/label-triage.yml index 9886e92..814a192 100644 --- a/.github/workflows/label-triage.yml +++ b/.github/workflows/label-triage.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: Label Triage diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index c80b676..83ab941 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: Labels diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 2a01cf5..c24fd19 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 diff --git a/.github/workflows/openssf-compliance.yml b/.github/workflows/openssf-compliance.yml index c711cc8..c47b905 100644 --- a/.github/workflows/openssf-compliance.yml +++ b/.github/workflows/openssf-compliance.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -8,7 +9,7 @@ on: push: branches: [main] pull_request: - branches: [main] + branches: ['**'] workflow_dispatch: permissions: actions: read @@ -20,7 +21,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 with: persist-credentials: false - name: Check SECURITY.md exists and has substance @@ -69,11 +70,11 @@ jobs: exit 1 fi - if [ ! -f ".machine_readable/STATE.a2ml" ]; then - echo "::error::.machine_readable/STATE.a2ml is required" + if [ ! -f ".machine_readable/descriptiles/STATE.a2ml" ]; then + echo "::error::.machine_readable/descriptiles/STATE.a2ml is required" exit 1 fi - echo ".machine_readable/STATE.a2ml: OK" + echo ".machine_readable/descriptiles/STATE.a2ml: OK" - name: Check CHANGELOG exists run: | if [ ! -f "CHANGELOG.md" ] && [ ! -f "CHANGELOG.adoc" ] && [ ! -f "CHANGES.md" ]; then @@ -89,8 +90,8 @@ jobs: # Collect all required files that exist for f in SECURITY.md SECURITY.adoc .github/SECURITY.md LICENSE LICENSE.txt \ CONTRIBUTING.md CONTRIBUTING.adoc README.md README.adoc \ - .machine_readable/STATE.a2ml .machine_readable/META.a2ml \ - .machine_readable/ECOSYSTEM.a2ml CHANGELOG.md CHANGELOG.adoc; do + .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml \ + .machine_readable/descriptiles/ECOSYSTEM.a2ml CHANGELOG.md CHANGELOG.adoc; do [ -f "$f" ] && REQUIRED_FILES="$REQUIRED_FILES $f" done diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 31f3ddc..c97b938 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: GitHub Pages (Ddraig SSG) on: @@ -20,9 +21,9 @@ jobs: image: ghcr.io/stefan-hoeck/idris2-pack@sha256:f0758996a931fb35d9ecb1de273c4d59dabe2a09b433afc7e357f65a08b7e1ff steps: - name: Checkout Site - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 - name: Checkout Ddraig SSG - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 with: repository: hyperpolymath/ddraig-ssg path: .ddraig-ssg @@ -39,7 +40,7 @@ jobs: fi ./.ddraig-ssg/build/exec/ddraig build src _site https://hyperpolymath.github.io/${GITHUB_REPOSITORY#*/} - name: Upload artifact - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 + uses: actions/upload-pages-artifact@v5.0.0 with: path: '_site' deploy: @@ -52,4 +53,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 + uses: actions/deploy-pages@v5.0.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 40a2f6d..938fee7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # @@ -20,7 +21,7 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 - name: Detect project type and build id: build @@ -82,7 +83,7 @@ jobs: changelog: ${{ steps.cliff.outputs.content }} version: ${{ steps.version.outputs.version }} steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 with: fetch-depth: 0 - name: Extract version from tag @@ -107,7 +108,7 @@ jobs: run: | git cliff --output CHANGELOG.md - name: Upload updated CHANGELOG.md - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v7.0.1 with: name: changelog path: CHANGELOG.md @@ -120,7 +121,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/checkout@v7.0.1 # TODO: Download build artifacts if uploading to the release # - uses: actions/download-artifact@v4 @@ -128,7 +129,7 @@ jobs: # name: release-artifacts # path: artifacts/ - name: Create GitHub Release - uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v2 + uses: softprops/action-gh-release@v3.0.2 with: body: ${{ needs.changelog.outputs.changelog }} draft: false diff --git a/.github/workflows/repository-validation.yml b/.github/workflows/repository-validation.yml new file mode 100644 index 0000000..19d28fc --- /dev/null +++ b/.github/workflows/repository-validation.yml @@ -0,0 +1,33 @@ +# This workflow is managed by gh actions-lock. +# SPDX-License-Identifier: MPL-2.0 +name: Repository Validation +on: + push: + branches: [main, master] + pull_request: + workflow_dispatch: +permissions: + contents: read +jobs: + repository-validation: + name: Workflow and session contract validation + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v7.0.1 + with: + persist-credentials: false + - name: Install verified Nickel 1.17.0 + run: | + mkdir -p "$RUNNER_TEMP/nickel-bin" + curl --fail --silent --show-error --location \ + https://github.com/nickel-lang/nickel/releases/download/1.17.0/nickel-x86_64-linux \ + --output "$RUNNER_TEMP/nickel-bin/nickel" + echo "afcdfa6e0fff31760cf229e85997456c02c00b8b3b84ff38f897ac7b3f39ae34 $RUNNER_TEMP/nickel-bin/nickel" | sha256sum --check --strict + chmod +x "$RUNNER_TEMP/nickel-bin/nickel" + echo "$RUNNER_TEMP/nickel-bin" >> "$GITHUB_PATH" + - name: Check workflow conventions + run: bash tests/workflows/validate_workflows_test.sh + - name: Evaluate session contracts + run: bash scripts/validate-session-contracts.sh + diff --git a/.github/workflows/rhodibot.yml b/.github/workflows/rhodibot.yml index 97462fb..a08f97c 100644 --- a/.github/workflows/rhodibot.yml +++ b/.github/workflows/rhodibot.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -30,7 +31,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 with: fetch-depth: 1 - name: Rhodibot — Scan and Fix diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 2813755..d8faafd 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 2eb0795..bfa0325 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 name: OSSF Scorecard diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index d780d6d..190208d 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 diff --git a/.github/workflows/static-analysis-gate.yml b/.github/workflows/static-analysis-gate.yml index 89ee2d0..9d5e743 100644 --- a/.github/workflows/static-analysis-gate.yml +++ b/.github/workflows/static-analysis-gate.yml @@ -1,3 +1,4 @@ +# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 # // Copyright (c) Jonathan D.A. Jewell # SPDX-License-Identifier: MPL-2.0 @@ -22,7 +23,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 with: fetch-depth: 0 - name: Install panic-attack (if available) @@ -119,7 +120,7 @@ jobs: echo "" >> "$GITHUB_STEP_SUMMARY" echo "Skipped: panic-attack not available in this environment." >> "$GITHUB_STEP_SUMMARY" - name: Upload panic-attack findings - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v7.0.1 with: name: panic-attack-findings path: panic-attack-findings.json @@ -138,13 +139,13 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 with: fetch-depth: 0 - name: Setup Elixir for Hypatia scanner id: beam continue-on-error: true - uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 # v1.18.2 + uses: erlef/setup-beam@v1.24.1 with: elixir-version: '1.19.4' otp-version: '28.3' @@ -245,7 +246,7 @@ jobs: echo "" >> "$GITHUB_STEP_SUMMARY" echo "Skipped: Hypatia scanner not available in this environment." >> "$GITHUB_STEP_SUMMARY" - name: Upload hypatia findings - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v7.0.1 with: name: hypatia-findings path: hypatia-findings.json @@ -264,7 +265,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@v7.0.1 with: fetch-depth: 0 - name: Install panic-attack (if available) @@ -326,7 +327,7 @@ jobs: echo "" >> "$GITHUB_STEP_SUMMARY" echo "Skipped: panic-attack not available in this environment." >> "$GITHUB_STEP_SUMMARY" - name: Upload bridge report - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v7.0.1 with: name: bridge-report path: bridge-report.json @@ -348,17 +349,17 @@ jobs: if: always() steps: - name: Download panic-attack findings - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v4 + uses: actions/download-artifact@v8.0.1 with: name: panic-attack-findings path: findings/ - name: Download hypatia findings - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v4 + uses: actions/download-artifact@v8.0.1 with: name: hypatia-findings path: findings/ - name: Download bridge report - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v4 + uses: actions/download-artifact@v8.0.1 with: name: bridge-report path: findings/ @@ -418,7 +419,7 @@ jobs: echo "medium=$MEDIUM" >> "$GITHUB_OUTPUT" echo "low=$LOW" >> "$GITHUB_OUTPUT" - name: Upload unified findings (fleet scanner picks these up) - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v7.0.1 with: name: unified-findings path: findings/unified-findings.json diff --git a/.machine_readable/ECOSYSTEM.a2ml b/.machine_readable/ECOSYSTEM.a2ml deleted file mode 100644 index 0059aed..0000000 --- a/.machine_readable/ECOSYSTEM.a2ml +++ /dev/null @@ -1,8 +0,0 @@ -;; SPDX-License-Identifier: MPL-2.0 -;; Ecosystem position and relationships -(ecosystem - (version "1.0.0") - (name "{{REPO}}") - (type "library") - (purpose "{{REPO_DESCRIPTION}}") - (related-projects)) diff --git a/.machine_readable/META.a2ml b/.machine_readable/META.a2ml deleted file mode 100644 index e64e280..0000000 --- a/.machine_readable/META.a2ml +++ /dev/null @@ -1,10 +0,0 @@ -;; SPDX-License-Identifier: MPL-2.0 -;; Architecture decisions and development practices -(meta - (version "1.0.0") - (project "{{REPO}}") - (architecture-decisions) - (development-practices - (code-review "required") - (branch-protection "enabled") - (ci-cd "github-actions"))) diff --git a/.machine_readable/ai/.clinerules b/.machine_readable/ai/.clinerules index a29ed5f..30d21a5 100644 --- a/.machine_readable/ai/.clinerules +++ b/.machine_readable/ai/.clinerules @@ -2,7 +2,7 @@ # Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} ({{OWNER}}) <{{AUTHOR_EMAIL}}> # Authoritative source: docs/AI-CONVENTIONS.md -# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. +# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/descriptiles/STATE.a2ml. # LICENSE # All original code: MPL-2.0. diff --git a/.machine_readable/ai/.windsurfrules b/.machine_readable/ai/.windsurfrules index a29ed5f..30d21a5 100644 --- a/.machine_readable/ai/.windsurfrules +++ b/.machine_readable/ai/.windsurfrules @@ -2,7 +2,7 @@ # Copyright (c) {{CURRENT_YEAR}} {{AUTHOR}} ({{OWNER}}) <{{AUTHOR_EMAIL}}> # Authoritative source: docs/AI-CONVENTIONS.md -# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/STATE.a2ml. +# STARTUP: Read 0-AI-MANIFEST.a2ml first, then .machine_readable/descriptiles/STATE.a2ml. # LICENSE # All original code: MPL-2.0. diff --git a/.machine_readable/ai/AI.a2ml b/.machine_readable/ai/AI.a2ml index 1f8b521..2643e8d 100644 --- a/.machine_readable/ai/AI.a2ml +++ b/.machine_readable/ai/AI.a2ml @@ -7,7 +7,7 @@ - Prefer to keep generated files out of source control, and regenerate them with the documented commands before committing. ## Workflow -1. Inspect `.machine_readable/STATE.a2ml` for blockers and next actions. +1. Inspect `.machine_readable/descriptiles/STATE.a2ml` for blockers and next actions. 2. Respect any constraints listed inside `.machine_readable/AGENTIC.a2ml` when tooling changes are requested. 3. After finishing edits, update STATE with your outcomes and commit with a concise, imperative message. diff --git a/.machine_readable/ai/README.adoc b/.machine_readable/ai/README.adoc index 7d90fea..a41aed1 100644 --- a/.machine_readable/ai/README.adoc +++ b/.machine_readable/ai/README.adoc @@ -20,5 +20,5 @@ Recommended machine read order: * `.machine_readable/policies/MAINTENANCE-AXES.a2ml` * `.machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml` * `.machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml` -* `.machine_readable/STATE.a2ml` -* `.machine_readable/META.a2ml` +* `.machine_readable/descriptiles/STATE.a2ml` +* `.machine_readable/descriptiles/META.a2ml` diff --git a/.machine_readable/contractiles/Justfile b/.machine_readable/contractiles/Justfile index 0457f2f..9392b5e 100644 --- a/.machine_readable/contractiles/Justfile +++ b/.machine_readable/contractiles/Justfile @@ -52,7 +52,7 @@ info: @echo "Version: {{version}}" @echo "RSR Tier: {{tier}}" @echo "Recipes: $(just --summary | wc -w)" - @[ -f ".machine_readable/STATE.a2ml" ] && grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/STATE.a2ml | head -1 | xargs -I{} echo "Phase: {}" || true + @[ -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: @@ -345,7 +345,7 @@ verify-template: fi # Check for empty SCM files - for f in .machine_readable/6a2/STATE.a2ml .machine_readable/6a2/META.a2ml .machine_readable/6a2/ECOSYSTEM.a2ml; do + for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml; do if [ -f "$f" ] && grep -q '{{'{{'}}' "$f" 2>/dev/null; then echo "⚠ $f still has template placeholders" FOUND=1 @@ -403,10 +403,10 @@ self-assess: fi done - if [ -d ".machine_readable/6a2" ]; then - echo " ✓ .machine_readable/6a2/ — KEEP (SCM checkpoint files)" + if [ -d ".machine_readable/descriptiles" ]; then + echo " ✓ .machine_readable/descriptiles/ — KEEP (SCM checkpoint files)" else - echo " ✗ .machine_readable/6a2/ — MISSING (RSR violation!)" + echo " ✗ .machine_readable/descriptiles/ — MISSING (RSR violation!)" fi if [ -d ".github/workflows" ]; then @@ -559,9 +559,9 @@ verify: check_file "LICENSE" check_either "CONTRIBUTING.md" "CONTRIBUTING.adoc" check_either "README.adoc" "README.md" - check_file ".machine_readable/STATE.a2ml" - check_file ".machine_readable/META.a2ml" - check_file ".machine_readable/ECOSYSTEM.a2ml" + check_file ".machine_readable/descriptiles/STATE.a2ml" + check_file ".machine_readable/descriptiles/META.a2ml" + check_file ".machine_readable/descriptiles/ECOSYSTEM.a2ml" check_either "CHANGELOG.md" "CHANGELOG.adoc" # Check at least 1 workflow exists @@ -1051,7 +1051,7 @@ validate-rsr: for f in .editorconfig .gitignore Justfile README.adoc LICENSE 0-AI-MANIFEST.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done - for f in .machine_readable/STATE.a2ml .machine_readable/META.a2ml .machine_readable/ECOSYSTEM.a2ml .machine_readable/anchors/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do + for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml .machine_readable/anchors/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done for f in licensing/exhibits/EXHIBIT-A-ETHICAL-USE.txt licensing/exhibits/EXHIBIT-B-QUANTUM-SAFE.txt licensing/texts/MPL-2.0.txt; do @@ -1066,15 +1066,15 @@ validate-rsr: for f in docs/governance/MAINTENANCE-CHECKLIST.adoc docs/governance/SOFTWARE-DEVELOPMENT-APPROACH.adoc; do [ -f "$f" ] || MISSING="$MISSING $f" done - if [ -f ".machine_readable/META.a2ml" ]; then - grep -q 'axis-1 = "must > intend > like"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-1" - grep -q 'axis-2 = "corrective > adaptive > perfective"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-2" - grep -q 'axis-3 = "systems > compliance > effects"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-3" - grep -q 'scoping-first = true' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:scoping-first" - grep -q 'idris-unsound-scan = "believe_me/assert_total"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:idris-unsound-scan" - grep -q 'audit-focus = "systems in place, documentation explains actual state, safety/security accounted for, observed effects reviewed"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:audit-focus" - grep -q 'compliance-focus = "seams/compromises/exception register, bounded exceptions, anti-drift checks"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:compliance-focus" - grep -q 'effects-evidence = "benchmark execution/results and maintainer status dialogue/review"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:effects-evidence" + if [ -f ".machine_readable/descriptiles/META.a2ml" ]; then + grep -q 'axis-1 = "must > intend > like"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-1" + grep -q 'axis-2 = "corrective > adaptive > perfective"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-2" + grep -q 'axis-3 = "systems > compliance > effects"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-3" + grep -q 'scoping-first = true' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:scoping-first" + grep -q 'idris-unsound-scan = "believe_me/assert_total"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:idris-unsound-scan" + grep -q 'audit-focus = "systems in place, documentation explains actual state, safety/security accounted for, observed effects reviewed"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:audit-focus" + grep -q 'compliance-focus = "seams/compromises/exception register, bounded exceptions, anti-drift checks"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:compliance-focus" + grep -q 'effects-evidence = "benchmark execution/results and maintainer status dialogue/review"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:effects-evidence" grep -q 'compliance-tooling = "panic-attack"' .machine_readable/policies/MAINTENANCE-AXES.a2ml || MISSING="$MISSING MAINTENANCE-AXES.a2ml:compliance-tooling" grep -q 'effects-tooling = "ecological checking with sustainabot guidance"' .machine_readable/policies/MAINTENANCE-AXES.a2ml || MISSING="$MISSING MAINTENANCE-AXES.a2ml:effects-tooling" grep -q 'source-human = "docs/governance/MAINTENANCE-CHECKLIST.adoc"' .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml || MISSING="$MISSING MAINTENANCE-CHECKLIST.a2ml:source-human" @@ -1088,12 +1088,12 @@ validate-rsr: # Validate STATE.a2ml syntax validate-state: - @if [ -f ".machine_readable/STATE.a2ml" ]; then \ - grep -q '^\[metadata\]' .machine_readable/STATE.a2ml && \ - grep -q 'project\s*=' .machine_readable/STATE.a2ml && \ + @if [ -f ".machine_readable/descriptiles/STATE.a2ml" ]; then \ + grep -q '^\[metadata\]' .machine_readable/descriptiles/STATE.a2ml && \ + grep -q 'project\s*=' .machine_readable/descriptiles/STATE.a2ml && \ echo "STATE.a2ml: valid" || echo "STATE.a2ml: INVALID (missing required sections)"; \ else \ - echo "No .machine_readable/STATE.a2ml found"; \ + echo "No .machine_readable/descriptiles/STATE.a2ml found"; \ fi # Validate AI installation guide completeness (finishbot pre-release check) @@ -1170,14 +1170,14 @@ validate: validate-rsr validate-state validate-ai-install # Update STATE.a2ml timestamp state-touch: - @if [ -f ".machine_readable/STATE.a2ml" ]; then \ - sed -i 's/last-updated = "[^"]*"/last-updated = "'"$(date +%Y-%m-%d)"'"/' .machine_readable/STATE.a2ml && \ + @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/STATE.a2ml 2>/dev/null | head -1 || echo "unknown" + @grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/descriptiles/STATE.a2ml 2>/dev/null | head -1 || echo "unknown" # ═══════════════════════════════════════════════════════════════════════════════ # GUIX & NIX diff --git a/.machine_readable/contractiles/Mustfile.a2ml b/.machine_readable/contractiles/Mustfile.a2ml index 55f8ab4..9c9f869 100644 --- a/.machine_readable/contractiles/Mustfile.a2ml +++ b/.machine_readable/contractiles/Mustfile.a2ml @@ -63,12 +63,12 @@ hooks fail if any check fails. ### six-directory-present - description: 6a2 directory exists with required files -- run: test -d .machine_readable/6a2 && test -f .machine_readable/6a2/META.a2ml && test -f .machine_readable/6a2/ECOSYSTEM.a2ml && test -f .machine_readable/6a2/STATE.a2ml && test -f .machine_readable/6a2/PLAYBOOK.a2ml && test -f .machine_readable/6a2/AGENTIC.a2ml && test -f .machine_readable/6a2/NEUROSYM.a2ml +- 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 6a2 -- run: test -d .machine_readable/6a2/anchors +- run: test -d .machine_readable/descriptiles/anchors - severity: warning ### self-validating-structure diff --git a/.machine_readable/6a2/0-AI-MANIFEST.a2ml b/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml similarity index 100% rename from .machine_readable/6a2/0-AI-MANIFEST.a2ml rename to .machine_readable/descriptiles/0-AI-MANIFEST.a2ml diff --git a/.machine_readable/6a2/AGENTIC.a2ml b/.machine_readable/descriptiles/AGENTIC.a2ml similarity index 100% rename from .machine_readable/6a2/AGENTIC.a2ml rename to .machine_readable/descriptiles/AGENTIC.a2ml diff --git a/.machine_readable/6a2/ECOSYSTEM.a2ml b/.machine_readable/descriptiles/ECOSYSTEM.a2ml similarity index 100% rename from .machine_readable/6a2/ECOSYSTEM.a2ml rename to .machine_readable/descriptiles/ECOSYSTEM.a2ml diff --git a/.machine_readable/6a2/META.a2ml b/.machine_readable/descriptiles/META.a2ml similarity index 97% rename from .machine_readable/6a2/META.a2ml rename to .machine_readable/descriptiles/META.a2ml index d9b09e6..d3b878f 100644 --- a/.machine_readable/6a2/META.a2ml +++ b/.machine_readable/descriptiles/META.a2ml @@ -19,6 +19,8 @@ author = "Jonathan D.A. Jewell (hyperpolymath)" # - { id = "ADR-001", title = "Use Zig for FFI", status = "accepted", date = "2026-02-14" } [development-practices] +code-review = "required" +branch-protection = "enabled" build-tool = "just" container-runtime = "podman" ci-platform = "github-actions" diff --git a/.machine_readable/6a2/NEUROSYM.a2ml b/.machine_readable/descriptiles/NEUROSYM.a2ml similarity index 100% rename from .machine_readable/6a2/NEUROSYM.a2ml rename to .machine_readable/descriptiles/NEUROSYM.a2ml diff --git a/.machine_readable/6a2/PLAYBOOK.a2ml b/.machine_readable/descriptiles/PLAYBOOK.a2ml similarity index 93% rename from .machine_readable/6a2/PLAYBOOK.a2ml rename to .machine_readable/descriptiles/PLAYBOOK.a2ml index 6408e1c..c7bd686 100644 --- a/.machine_readable/6a2/PLAYBOOK.a2ml +++ b/.machine_readable/descriptiles/PLAYBOOK.a2ml @@ -13,7 +13,7 @@ last-updated = "2026-04-11" # target = "container" # container | binary | library | wasm [incident-response] -# 1. Check .machine_readable/STATE.a2ml for current status +# 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 diff --git a/.machine_readable/6a2/README.adoc b/.machine_readable/descriptiles/README.adoc similarity index 100% rename from .machine_readable/6a2/README.adoc rename to .machine_readable/descriptiles/README.adoc diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/descriptiles/STATE.a2ml similarity index 100% rename from .machine_readable/6a2/STATE.a2ml rename to .machine_readable/descriptiles/STATE.a2ml diff --git a/.machine_readable/6a2/anchor/0-AI-MANIFEST.a2ml b/.machine_readable/descriptiles/anchor/0-AI-MANIFEST.a2ml similarity index 100% rename from .machine_readable/6a2/anchor/0-AI-MANIFEST.a2ml rename to .machine_readable/descriptiles/anchor/0-AI-MANIFEST.a2ml diff --git a/.machine_readable/6a2/anchor/ANCHOR.a2ml b/.machine_readable/descriptiles/anchor/ANCHOR.a2ml similarity index 100% rename from .machine_readable/6a2/anchor/ANCHOR.a2ml rename to .machine_readable/descriptiles/anchor/ANCHOR.a2ml diff --git a/.machine_readable/6a2/anchor/README.adoc b/.machine_readable/descriptiles/anchor/README.adoc similarity index 100% rename from .machine_readable/6a2/anchor/README.adoc rename to .machine_readable/descriptiles/anchor/README.adoc diff --git a/.machine_readable/policies/MAINTENANCE-AXES.a2ml b/.machine_readable/policies/MAINTENANCE-AXES.a2ml index eeffd27..c073b9a 100644 --- a/.machine_readable/policies/MAINTENANCE-AXES.a2ml +++ b/.machine_readable/policies/MAINTENANCE-AXES.a2ml @@ -18,7 +18,7 @@ machine-entrypoints = [ ".machine_readable/policies/MAINTENANCE-AXES.a2ml", ".machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml", ".machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml", - ".machine_readable/META.a2ml", + ".machine_readable/descriptiles/META.a2ml", ".machine_readable/ai/README.adoc", ".machine_readable/bot_directives/README.scm", ] diff --git a/0-AI-MANIFEST.a2ml b/0-AI-MANIFEST.a2ml index 86db391..907a430 100644 --- a/0-AI-MANIFEST.a2ml +++ b/0-AI-MANIFEST.a2ml @@ -27,7 +27,7 @@ co-developed-with = "son" [canonical-locations] contractiles = ".machine_readable/contractiles/" -state-descriptive = ".machine_readable/6a2/" +state-descriptive = ".machine_readable/descriptiles/" recalibration-records = ".machine_readable/anchors/" source-libraries = "libs/" tools = "tools/" diff --git a/EXPLAINME.adoc b/EXPLAINME.adoc index d8b6d97..dad7cb7 100644 --- a/EXPLAINME.adoc +++ b/EXPLAINME.adoc @@ -15,8 +15,8 @@ How this is implemented: * The local dispatcher (`session/dispatch.sh`) maps canonical commands to central protocol paths in `standards/session-management-standards`. -* Local files (`session/custom-checks.k9`, `session/local-hooks.sh`, - `coordination.k9`) are integration-only. +* Local files (`session/custom-checks.k9.ncl`, `session/local-hooks.sh`, + `coordination.k9.ncl`) are integration-only. Caveat: diff --git a/Justfile b/Justfile index 5632b4a..1a793c7 100644 --- a/Justfile +++ b/Justfile @@ -53,7 +53,7 @@ info: @echo "Version: {{version}}" @echo "RSR Tier: {{tier}}" @echo "Recipes: $(just --summary | wc -w)" - @[ -f ".machine_readable/STATE.a2ml" ] && grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/STATE.a2ml | head -1 | xargs -I{} echo "Phase: {}" || true + @[ -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: @@ -250,12 +250,8 @@ init: echo "All placeholders replaced successfully!" fi - # K9-SVC validation (if available) - if command -v k9-svc >/dev/null 2>&1; then - echo "" - echo "Running k9-svc validation..." - k9-svc validate . 2>/dev/null || true - fi + # These session policies are Nickel K9 documents. + bash scripts/validate-session-contracts.sh echo "" echo "Running OpenSSF compliance verification..." @@ -346,7 +342,7 @@ verify-template: fi # Check for empty SCM files - for f in .machine_readable/6a2/STATE.a2ml .machine_readable/6a2/META.a2ml .machine_readable/6a2/ECOSYSTEM.a2ml; do + for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml; do if [ -f "$f" ] && grep -q '{{'{{'}}' "$f" 2>/dev/null; then echo "⚠ $f still has template placeholders" FOUND=1 @@ -404,10 +400,10 @@ self-assess: fi done - if [ -d ".machine_readable/6a2" ]; then - echo " ✓ .machine_readable/6a2/ — KEEP (SCM checkpoint files)" + if [ -d ".machine_readable/descriptiles" ]; then + echo " ✓ .machine_readable/descriptiles/ — KEEP (SCM checkpoint files)" else - echo " ✗ .machine_readable/6a2/ — MISSING (RSR violation!)" + echo " ✗ .machine_readable/descriptiles/ — MISSING (RSR violation!)" fi if [ -d ".github/workflows" ]; then @@ -560,9 +556,9 @@ verify: check_file "LICENSE" check_either "CONTRIBUTING.md" "CONTRIBUTING.adoc" check_either "README.adoc" "README.md" - check_file ".machine_readable/STATE.a2ml" - check_file ".machine_readable/META.a2ml" - check_file ".machine_readable/ECOSYSTEM.a2ml" + check_file ".machine_readable/descriptiles/STATE.a2ml" + check_file ".machine_readable/descriptiles/META.a2ml" + check_file ".machine_readable/descriptiles/ECOSYSTEM.a2ml" check_either "CHANGELOG.md" "CHANGELOG.adoc" # Check at least 1 workflow exists @@ -1052,7 +1048,7 @@ validate-rsr: for f in .editorconfig .gitignore Justfile README.adoc LICENSE 0-AI-MANIFEST.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done - for f in .machine_readable/STATE.a2ml .machine_readable/META.a2ml .machine_readable/ECOSYSTEM.a2ml .machine_readable/anchors/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do + for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml .machine_readable/anchors/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done for f in licensing/exhibits/EXHIBIT-A-ETHICAL-USE.txt licensing/exhibits/EXHIBIT-B-QUANTUM-SAFE.txt licensing/texts/MPL-2.0.txt; do @@ -1067,15 +1063,15 @@ validate-rsr: for f in docs/governance/MAINTENANCE-CHECKLIST.adoc docs/governance/SOFTWARE-DEVELOPMENT-APPROACH.adoc; do [ -f "$f" ] || MISSING="$MISSING $f" done - if [ -f ".machine_readable/META.a2ml" ]; then - grep -q 'axis-1 = "must > intend > like"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-1" - grep -q 'axis-2 = "corrective > adaptive > perfective"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-2" - grep -q 'axis-3 = "systems > compliance > effects"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:axis-3" - grep -q 'scoping-first = true' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:scoping-first" - grep -q 'idris-unsound-scan = "believe_me/assert_total"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:idris-unsound-scan" - grep -q 'audit-focus = "systems in place, documentation explains actual state, safety/security accounted for, observed effects reviewed"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:audit-focus" - grep -q 'compliance-focus = "seams/compromises/exception register, bounded exceptions, anti-drift checks"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:compliance-focus" - grep -q 'effects-evidence = "benchmark execution/results and maintainer status dialogue/review"' .machine_readable/META.a2ml || MISSING="$MISSING META.a2ml:effects-evidence" + if [ -f ".machine_readable/descriptiles/META.a2ml" ]; then + grep -q 'axis-1 = "must > intend > like"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-1" + grep -q 'axis-2 = "corrective > adaptive > perfective"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-2" + grep -q 'axis-3 = "systems > compliance > effects"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:axis-3" + grep -q 'scoping-first = true' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:scoping-first" + grep -q 'idris-unsound-scan = "believe_me/assert_total"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:idris-unsound-scan" + grep -q 'audit-focus = "systems in place, documentation explains actual state, safety/security accounted for, observed effects reviewed"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:audit-focus" + grep -q 'compliance-focus = "seams/compromises/exception register, bounded exceptions, anti-drift checks"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:compliance-focus" + grep -q 'effects-evidence = "benchmark execution/results and maintainer status dialogue/review"' .machine_readable/descriptiles/META.a2ml || MISSING="$MISSING META.a2ml:effects-evidence" grep -q 'compliance-tooling = "panic-attack"' .machine_readable/policies/MAINTENANCE-AXES.a2ml || MISSING="$MISSING MAINTENANCE-AXES.a2ml:compliance-tooling" grep -q 'effects-tooling = "ecological checking with sustainabot guidance"' .machine_readable/policies/MAINTENANCE-AXES.a2ml || MISSING="$MISSING MAINTENANCE-AXES.a2ml:effects-tooling" grep -q 'source-human = "docs/governance/MAINTENANCE-CHECKLIST.adoc"' .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml || MISSING="$MISSING MAINTENANCE-CHECKLIST.a2ml:source-human" @@ -1089,12 +1085,12 @@ validate-rsr: # Validate STATE.a2ml syntax validate-state: - @if [ -f ".machine_readable/STATE.a2ml" ]; then \ - grep -q '^\[metadata\]' .machine_readable/STATE.a2ml && \ - grep -q 'project\s*=' .machine_readable/STATE.a2ml && \ + @if [ -f ".machine_readable/descriptiles/STATE.a2ml" ]; then \ + grep -q '^\[metadata\]' .machine_readable/descriptiles/STATE.a2ml && \ + grep -q 'project\s*=' .machine_readable/descriptiles/STATE.a2ml && \ echo "STATE.a2ml: valid" || echo "STATE.a2ml: INVALID (missing required sections)"; \ else \ - echo "No .machine_readable/STATE.a2ml found"; \ + echo "No .machine_readable/descriptiles/STATE.a2ml found"; \ fi # Validate AI installation guide completeness (finishbot pre-release check) @@ -1171,14 +1167,14 @@ validate: validate-rsr validate-state validate-ai-install # Update STATE.a2ml timestamp state-touch: - @if [ -f ".machine_readable/STATE.a2ml" ]; then \ - sed -i 's/last-updated = "[^"]*"/last-updated = "'"$(date +%Y-%m-%d)"'"/' .machine_readable/STATE.a2ml && \ + @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/STATE.a2ml 2>/dev/null | head -1 || echo "unknown" + @grep -oP 'phase\s*=\s*"\K[^"]+' .machine_readable/descriptiles/STATE.a2ml 2>/dev/null | head -1 || echo "unknown" # ═══════════════════════════════════════════════════════════════════════════════ # GUIX & NIX diff --git a/container/deploy.k9.ncl b/container/deploy.k9.ncl index 0ad0d04..65bdacf 100644 --- a/container/deploy.k9.ncl +++ b/container/deploy.k9.ncl @@ -1,3 +1,4 @@ +K9! # SPDX-License-Identifier: MPL-2.0 # deploy.k9.ncl — {{PROJECT_NAME}} deployment component (Hunt level) # @@ -143,7 +144,14 @@ echo "K9: Rollback complete." # Export the component { - pedigree = component_pedigree, + pedigree = component_pedigree & { + name = component_pedigree.metadata.name, + version = component_pedigree.metadata.version, + security = component_pedigree.security & { + leash = 'Hunt, + signature = component_pedigree.security.signature, + }, + }, deployment = deployment, scripts = scripts, diff --git a/coordination.k9 b/coordination.k9 deleted file mode 100644 index ba31125..0000000 --- a/coordination.k9 +++ /dev/null @@ -1,43 +0,0 @@ -# Thin coordination bindings for central session-management standards - -session_management: - source_of_truth: "standards/session-management-standards" - canonical_commands: - - "intake repo " - - "checkpoint change " - - "verify maintenance " - - "verify substantial " - - "verify release " - - "close planned " - - "close urgent " - - "recover repo " - - "handover full " - - "handover split " - - "handover model " - - "handover human " - -signals: - - name: "session.intake" - command: "intake repo " - - name: "session.checkpoint" - command: "checkpoint change " - - name: "session.verify.maintenance" - command: "verify maintenance " - - name: "session.verify.substantial" - command: "verify substantial " - - name: "session.verify.release" - command: "verify release " - - name: "session.close.planned" - command: "close planned " - - name: "session.close.urgent" - command: "close urgent " - - name: "session.recover" - command: "recover repo " - - name: "session.handover.full" - command: "handover full " - - name: "session.handover.split" - command: "handover split " - - name: "session.handover.model" - command: "handover model " - - name: "session.handover.human" - command: "handover human " diff --git a/coordination.k9.ncl b/coordination.k9.ncl new file mode 100644 index 0000000..44ce7c6 --- /dev/null +++ b/coordination.k9.ncl @@ -0,0 +1,49 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# Thin coordination bindings for central session-management standards + +{ + pedigree = { + schema_version = "1.0.0", + metadata = { + name = "session-coordination", + version = "0.1.0", + }, + security = { + leash = 'Kennel, + }, + }, + + session_management = { + source_of_truth = "standards/session-management-standards", + canonical_commands = [ + "intake repo ", + "checkpoint change ", + "verify maintenance ", + "verify substantial ", + "verify release ", + "close planned ", + "close urgent ", + "recover repo ", + "handover full ", + "handover split ", + "handover model ", + "handover human ", + ], + }, + + signals = [ + { name = "session.intake", command = "intake repo " }, + { name = "session.checkpoint", command = "checkpoint change " }, + { name = "session.verify.maintenance", command = "verify maintenance " }, + { name = "session.verify.substantial", command = "verify substantial " }, + { name = "session.verify.release", command = "verify release " }, + { name = "session.close.planned", command = "close planned " }, + { name = "session.close.urgent", command = "close urgent " }, + { name = "session.recover", command = "recover repo " }, + { name = "session.handover.full", command = "handover full " }, + { name = "session.handover.split", command = "handover split " }, + { name = "session.handover.model", command = "handover model " }, + { name = "session.handover.human", command = "handover human " }, + ], +} diff --git a/docs/RSR_OUTLINE.adoc b/docs/RSR_OUTLINE.adoc index f6e9a9a..b2b1603 100644 --- a/docs/RSR_OUTLINE.adoc +++ b/docs/RSR_OUTLINE.adoc @@ -217,7 +217,7 @@ project/ * `Justfile` * `README.adoc` * `LICENSE` (MPL-2.0) -* `.machine_readable/STATE.a2ml` +* `.machine_readable/descriptiles/STATE.a2ml` * `.well-known/security.txt` * `.well-known/ai.txt` * `.well-known/humans.txt` diff --git a/docs/governance/MAINTENANCE-CHECKLIST.a2ml b/docs/governance/MAINTENANCE-CHECKLIST.a2ml index 40db158..203f3c5 100644 --- a/docs/governance/MAINTENANCE-CHECKLIST.a2ml +++ b/docs/governance/MAINTENANCE-CHECKLIST.a2ml @@ -2,6 +2,7 @@ # Cross-repo maintenance baseline (machine-readable canonical) [metadata] +name = "maintenance-checklist" version = "1.1.0" last-updated = "2026-02-24" scope = "cross-repo" diff --git a/docs/practice/AI-CONVENTIONS.adoc b/docs/practice/AI-CONVENTIONS.adoc index 4a6aba1..5df9c03 100644 --- a/docs/practice/AI-CONVENTIONS.adoc +++ b/docs/practice/AI-CONVENTIONS.adoc @@ -12,7 +12,7 @@ Per-tool config files (.cursorrules, .clinerules, etc.) reference this document. ## Session Startup 1. Read `0-AI-MANIFEST.a2ml` FIRST (mandatory gatekeeper). -2. Read `.machine_readable/STATE.a2ml` for current status and blockers. +2. Read `.machine_readable/descriptiles/STATE.a2ml` for current status and blockers. 3. Read `.machine_readable/anchors/ANCHOR.a2ml` for canonical authority boundaries. 4. Read `.machine_readable/policies/MAINTENANCE-AXES.a2ml` for maintenance/audit sequencing. 5. Read `.machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml` for baseline controls. @@ -80,7 +80,7 @@ Use `just` (Justfile) for all build, test, lint, and format tasks. - `0-AI-MANIFEST.a2ml` -- universal AI entry point - `.machine_readable/AGENTIC.a2ml` -- agent permissions and constraints -- `.machine_readable/STATE.a2ml` -- current project state +- `.machine_readable/descriptiles/STATE.a2ml` -- current project state - `.machine_readable/anchors/ANCHOR.a2ml` -- canonical authority and policy boundary - `.machine_readable/policies/MAINTENANCE-AXES.a2ml` -- canonical axis sequencing and audit requirements - `.machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml` -- baseline maintenance checklist policy diff --git a/scripts/validate-session-contracts.sh b/scripts/validate-session-contracts.sh new file mode 100644 index 0000000..779faaf --- /dev/null +++ b/scripts/validate-session-contracts.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# Validate the two session policies with their actual Nickel evaluator. +set -euo pipefail +command -v nickel >/dev/null || { + echo "nickel is required to validate .k9.ncl session policies" >&2 + exit 2 +} +for file in coordination.k9.ncl session/custom-checks.k9.ncl; do + IFS= read -r magic < "$file" + if [[ "$magic" != 'K9!' ]]; then + echo "$file: missing K9! envelope" >&2 + exit 1 + fi + # K9! is a transport envelope, not a Nickel expression. These standalone + # records have no imports; evaluation also exercises their field contracts. + tail -n +2 "$file" | nickel export --format json >/dev/null + echo "$file: Nickel evaluation passed" +done + diff --git a/session/README.adoc b/session/README.adoc index d14a6d7..29139e7 100644 --- a/session/README.adoc +++ b/session/README.adoc @@ -11,7 +11,7 @@ Authoritative protocols live in: This repo keeps only thin bindings: * `+dispatch.sh+` maps canonical commands to central protocol paths. -* `+custom-checks.k9+` defines repo-local policy checks. +* `+custom-checks.k9.ncl+` defines repo-local policy checks. * `+local-hooks.sh+` provides optional repo-specific hook behavior. === Canonical Commands diff --git a/session/custom-checks.k9 b/session/custom-checks.k9 deleted file mode 100644 index bd932fa..0000000 --- a/session/custom-checks.k9 +++ /dev/null @@ -1,15 +0,0 @@ -# Local repository session checks (thin policy layer) -version: "0.1" - -checks: - - id: "session-state-has-next-action" - applies_to: ["close planned", "close urgent", "handover full", "handover split", "handover model", "handover human"] - requirement: "LAST-CANONICAL-COMMAND.md contains next intended action" - - - id: "session-state-has-residual-risks" - applies_to: ["verify maintenance", "verify substantial", "verify release", "recover repo"] - requirement: "Residual risks field is not left blank" - - - id: "session-state-has-recommended-next-protocol" - applies_to: ["intake repo", "checkpoint change", "recover repo", "handover full"] - requirement: "Recommended next protocol is set" diff --git a/session/custom-checks.k9.ncl b/session/custom-checks.k9.ncl new file mode 100644 index 0000000..6f6f36b --- /dev/null +++ b/session/custom-checks.k9.ncl @@ -0,0 +1,51 @@ +K9! +# SPDX-License-Identifier: MPL-2.0 +# Local repository session checks (thin policy layer) + +{ + pedigree = { + schema_version = "1.0.0", + metadata = { + name = "custom-session-checks", + version = "0.1.0", + }, + security = { + leash = 'Kennel, + }, + }, + + checks = [ + { + id = "session-state-has-next-action", + applies_to = [ + "close planned", + "close urgent", + "handover full", + "handover split", + "handover model", + "handover human", + ], + requirement = "LAST-CANONICAL-COMMAND.md contains next intended action", + }, + { + id = "session-state-has-residual-risks", + applies_to = [ + "verify maintenance", + "verify substantial", + "verify release", + "recover repo", + ], + requirement = "Residual risks field is not left blank", + }, + { + id = "session-state-has-recommended-next-protocol", + applies_to = [ + "intake repo", + "checkpoint change", + "recover repo", + "handover full", + ], + requirement = "Recommended next protocol is set", + }, + ], +} diff --git a/setup.sh b/setup.sh index 98702aa..6e255b8 100755 --- a/setup.sh +++ b/setup.sh @@ -6,8 +6,7 @@ # Then hands off to `just setup` for project-specific configuration. # # Usage: -# curl -fsSL https://raw.githubusercontent.com/hyperpolymath/natsci-studio/main/setup.sh | sh -# # or after cloning: +# # After cloning and reviewing this repository: # ./setup.sh # # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) @@ -139,10 +138,7 @@ install_just() { case "$PKG_MGR" in dnf) sudo dnf install -y just ;; - apt) sudo apt-get install -y just 2>/dev/null || { - # just not in older apt repos — use installer - curl -fsSL https://just.systems/install.sh | bash -s -- --to /usr/local/bin - } ;; + apt) sudo apt-get install -y just ;; pacman) sudo pacman -S --noconfirm just ;; apk) sudo apk add just ;; brew) brew install just ;; @@ -152,8 +148,8 @@ install_just() { guix) guix install just ;; nix) nix-env -iA nixpkgs.just ;; *) - info "Using just installer script..." - curl -fsSL https://just.systems/install.sh | bash -s -- --to /usr/local/bin + fail "Install just with a trusted package manager: https://just.systems/" + return 1 ;; esac diff --git a/tests/e2e/template_instantiation_test.sh b/tests/e2e/template_instantiation_test.sh index cc0ccb8..e79f02a 100755 --- a/tests/e2e/template_instantiation_test.sh +++ b/tests/e2e/template_instantiation_test.sh @@ -234,8 +234,8 @@ done log_step "Verifying machine-readable metadata" METADATA_FILES=( - ".machine_readable/STATE.a2ml" - ".machine_readable/META.a2ml" + ".machine_readable/descriptiles/STATE.a2ml" + ".machine_readable/descriptiles/META.a2ml" ) for file in "${METADATA_FILES[@]}"; do From 459bd904ac45140e59f097743a8ae9d7db6cec07 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 9 Sep 2026 23:38:38 +0100 Subject: [PATCH 3/8] fix(ci): consume shared security fixes and resolve Sonar workflow issues --- .github/workflows/dogfood-gate.yml | 1 - .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- .github/workflows/mirror.yml | 11 +++++++++-- .github/workflows/repository-validation.yml | 2 +- .github/workflows/rust-ci.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner.yml | 2 +- 8 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/dogfood-gate.yml b/.github/workflows/dogfood-gate.yml index f4e1f56..51995a4 100644 --- a/.github/workflows/dogfood-gate.yml +++ b/.github/workflows/dogfood-gate.yml @@ -12,7 +12,6 @@ on: push: branches: [main, master] permissions: - actions: read contents: read jobs: # --------------------------------------------------------------------------- diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 13373fc..de406bf 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -15,4 +15,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index d65edb6..dab96a2 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -18,4 +18,4 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index c24fd19..6d6b11b 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -12,5 +12,12 @@ permissions: contents: read jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + secrets: + GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }} + BITBUCKET_SSH_KEY: ${{ secrets.BITBUCKET_SSH_KEY }} + CODEBERG_SSH_KEY: ${{ secrets.CODEBERG_SSH_KEY }} + SOURCEHUT_SSH_KEY: ${{ secrets.SOURCEHUT_SSH_KEY }} + DISROOT_SSH_KEY: ${{ secrets.DISROOT_SSH_KEY }} + GITEA_SSH_KEY: ${{ secrets.GITEA_SSH_KEY }} + RADICLE_KEY: ${{ secrets.RADICLE_KEY }} diff --git a/.github/workflows/repository-validation.yml b/.github/workflows/repository-validation.yml index 19d28fc..3a99055 100644 --- a/.github/workflows/repository-validation.yml +++ b/.github/workflows/repository-validation.yml @@ -20,7 +20,7 @@ jobs: - name: Install verified Nickel 1.17.0 run: | mkdir -p "$RUNNER_TEMP/nickel-bin" - curl --fail --silent --show-error --location \ + curl --proto '=https' --proto-redir '=https' --fail --silent --show-error --location \ https://github.com/nickel-lang/nickel/releases/download/1.17.0/nickel-x86_64-linux \ --output "$RUNNER_TEMP/nickel-bin/nickel" echo "afcdfa6e0fff31760cf229e85997456c02c00b8b3b84ff38f897ac7b3f39ae34 $RUNNER_TEMP/nickel-bin/nickel" | sha256sum --check --strict diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index d8faafd..5ad3e30 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -15,4 +15,4 @@ permissions: contents: read jobs: rust-ci: - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index bfa0325..67c111f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -14,7 +14,7 @@ permissions: id-token: write jobs: scorecard: - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 permissions: contents: read security-events: write diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 190208d..0dbc4b4 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -18,5 +18,5 @@ jobs: scan: permissions: contents: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@8f2ee50841e216cd8c192eeb68953118190f105c + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 secrets: inherit From c670424914604316966a713b29a22d8fe9d2081c Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 10 Sep 2026 01:49:41 +0100 Subject: [PATCH 4/8] fix(ci): finish canonical references and use validated shared gates --- .github/workflow-templates/e2e.yml | 4 ++-- .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- .github/workflows/mirror.yml | 2 +- .github/workflows/repository-validation.yml | 2 ++ .github/workflows/rust-ci.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner.yml | 2 +- .machine_readable/ai/AI.a2ml | 2 +- Justfile | 19 +++++++++---------- docs/RSR_OUTLINE.adoc | 13 +++++++------ scripts/validate-session-contracts.sh | 16 +++++++++++++++- tests/{e2e.sh => templates/e2e.sh.template} | 0 tests/workflows/k9_typecheck_test.sh | 15 +++++++++++++++ 14 files changed, 57 insertions(+), 26 deletions(-) rename tests/{e2e.sh => templates/e2e.sh.template} (100%) create mode 100644 tests/workflows/k9_typecheck_test.sh diff --git a/.github/workflow-templates/e2e.yml b/.github/workflow-templates/e2e.yml index 927a624..40e1f5d 100644 --- a/.github/workflow-templates/e2e.yml +++ b/.github/workflow-templates/e2e.yml @@ -48,7 +48,7 @@ jobs: # - uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable # - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 # - run: cargo build --release -# - run: bash tests/e2e.sh +# - run: bash tests/templates/e2e.sh.template # # OR: cargo test --test end_to_end -- --nocapture ## === ZIG FFI E2E === @@ -62,7 +62,7 @@ jobs: # with: # version: 0.15.0 # - run: cd ffi/zig && zig build test - # - run: bash tests/e2e.sh + # - run: bash tests/templates/e2e.sh.template ## === ELIXIR E2E === # e2e: diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index de406bf..1a736f6 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -15,4 +15,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index dab96a2..63d32d9 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -18,4 +18,4 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 6d6b11b..9cdbe1e 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -12,7 +12,7 @@ permissions: contents: read jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a secrets: GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }} BITBUCKET_SSH_KEY: ${{ secrets.BITBUCKET_SSH_KEY }} diff --git a/.github/workflows/repository-validation.yml b/.github/workflows/repository-validation.yml index 3a99055..02edc53 100644 --- a/.github/workflows/repository-validation.yml +++ b/.github/workflows/repository-validation.yml @@ -28,6 +28,8 @@ jobs: echo "$RUNNER_TEMP/nickel-bin" >> "$GITHUB_PATH" - name: Check workflow conventions run: bash tests/workflows/validate_workflows_test.sh + - name: Check Nickel envelope regression controls + run: bash tests/workflows/k9_typecheck_test.sh - name: Evaluate session contracts run: bash scripts/validate-session-contracts.sh diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 5ad3e30..6856111 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -15,4 +15,4 @@ permissions: contents: read jobs: rust-ci: - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 67c111f..e99b331 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -14,7 +14,7 @@ permissions: id-token: write jobs: scorecard: - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a permissions: contents: read security-events: write diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 0dbc4b4..1b58a6f 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -18,5 +18,5 @@ jobs: scan: permissions: contents: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@8e50188e183222ffeb44f9729dde056a33dded38 + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a secrets: inherit diff --git a/.machine_readable/ai/AI.a2ml b/.machine_readable/ai/AI.a2ml index 2643e8d..f0c73a8 100644 --- a/.machine_readable/ai/AI.a2ml +++ b/.machine_readable/ai/AI.a2ml @@ -8,7 +8,7 @@ ## Workflow 1. Inspect `.machine_readable/descriptiles/STATE.a2ml` for blockers and next actions. -2. Respect any constraints listed inside `.machine_readable/AGENTIC.a2ml` when tooling changes are requested. +2. Respect any constraints listed inside `.machine_readable/descriptiles/AGENTIC.a2ml` when tooling changes are requested. 3. After finishing edits, update STATE with your outcomes and commit with a concise, imperative message. ## Delivery Promises diff --git a/Justfile b/Justfile index 1a793c7..8536a00 100644 --- a/Justfile +++ b/Justfile @@ -250,8 +250,12 @@ init: echo "All placeholders replaced successfully!" fi - # These session policies are Nickel K9 documents. - bash scripts/validate-session-contracts.sh + # CI always provisions Nickel; local initialisation can precede that environment. + if command -v nickel >/dev/null; then + bash scripts/validate-session-contracts.sh + else + echo "Session validation deferred: install Nickel 1.17.0, then run bash scripts/validate-session-contracts.sh" + fi echo "" echo "Running OpenSSF compliance verification..." @@ -648,13 +652,8 @@ test-smoke: # 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!" + @echo "E2E tests are not implemented. Start from tests/templates/e2e.sh.template." >&2 + @exit 2 # Run aspect tests (cross-cutting concern validation) aspect: @@ -1048,7 +1047,7 @@ validate-rsr: for f in .editorconfig .gitignore Justfile README.adoc LICENSE 0-AI-MANIFEST.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done - for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml .machine_readable/anchors/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do + for f in .machine_readable/descriptiles/STATE.a2ml .machine_readable/descriptiles/META.a2ml .machine_readable/descriptiles/ECOSYSTEM.a2ml .machine_readable/descriptiles/anchor/ANCHOR.a2ml .machine_readable/policies/MAINTENANCE-AXES.a2ml .machine_readable/policies/MAINTENANCE-CHECKLIST.a2ml .machine_readable/policies/SOFTWARE-DEVELOPMENT-APPROACH.a2ml; do [ -f "$f" ] || MISSING="$MISSING $f" done for f in licensing/exhibits/EXHIBIT-A-ETHICAL-USE.txt licensing/exhibits/EXHIBIT-B-QUANTUM-SAFE.txt licensing/texts/MPL-2.0.txt; do diff --git a/docs/RSR_OUTLINE.adoc b/docs/RSR_OUTLINE.adoc index b2b1603..03fdcde 100644 --- a/docs/RSR_OUTLINE.adoc +++ b/docs/RSR_OUTLINE.adoc @@ -161,12 +161,13 @@ project/ │ ├── humans.txt │ └── security.txt ├── .machine_readable/ # ALL machine-readable content -│ ├── STATE.a2ml # Project state, progress, blockers -│ ├── META.a2ml # Architecture decisions, governance -│ ├── ECOSYSTEM.a2ml # Ecosystem position, relationships -│ ├── AGENTIC.a2ml # AI agent interaction patterns -│ ├── NEUROSYM.a2ml # Neurosymbolic integration config -│ ├── PLAYBOOK.a2ml # Operational runbook +│ ├── descriptiles/ # Canonical descriptive anchors +│ │ ├── STATE.a2ml # Project state, progress, blockers +│ │ ├── META.a2ml # Architecture decisions, governance +│ │ ├── ECOSYSTEM.a2ml # Ecosystem position, relationships +│ │ ├── AGENTIC.a2ml # AI agent interaction patterns +│ │ ├── NEUROSYM.a2ml # Neurosymbolic integration config +│ │ └── PLAYBOOK.a2ml # Operational runbook │ ├── bot_directives/ # Per-bot rules and constraints │ └── contractiles/ # Policy enforcement contracts │ ├── k9/ # Security levels (Kennel/Yard/Hunt) diff --git a/scripts/validate-session-contracts.sh b/scripts/validate-session-contracts.sh index 779faaf..54dd1cc 100644 --- a/scripts/validate-session-contracts.sh +++ b/scripts/validate-session-contracts.sh @@ -6,6 +6,21 @@ command -v nickel >/dev/null || { echo "nickel is required to validate .k9.ncl session policies" >&2 exit 2 } +if [[ "${1:-}" == --typecheck ]]; then + shift + [[ $# -gt 0 ]] || { echo 'Supply the instantiated Nickel or K9 files to typecheck' >&2; exit 2; } + for file in "$@"; do + IFS= read -r magic < "$file" + if [[ "$magic" == 'K9!' ]]; then + tail -n +2 "$file" | (cd -- "$(dirname -- "$file")" && nickel typecheck) + else + nickel typecheck "$file" + fi + echo "$file: Nickel typecheck passed (deployment not executed)" + done + exit 0 +fi +[[ $# -eq 0 ]] || { echo 'Usage: validate-session-contracts.sh [--typecheck FILE...]' >&2; exit 2; } for file in coordination.k9.ncl session/custom-checks.k9.ncl; do IFS= read -r magic < "$file" if [[ "$magic" != 'K9!' ]]; then @@ -17,4 +32,3 @@ for file in coordination.k9.ncl session/custom-checks.k9.ncl; do tail -n +2 "$file" | nickel export --format json >/dev/null echo "$file: Nickel evaluation passed" done - diff --git a/tests/e2e.sh b/tests/templates/e2e.sh.template similarity index 100% rename from tests/e2e.sh rename to tests/templates/e2e.sh.template diff --git a/tests/workflows/k9_typecheck_test.sh b/tests/workflows/k9_typecheck_test.sh new file mode 100644 index 0000000..5b38a91 --- /dev/null +++ b/tests/workflows/k9_typecheck_test.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +set -euo pipefail +root="$(cd "$(dirname "$0")/../.." && pwd)" +fixture="$(mktemp -d)" +trap 'rm -rf "$fixture"' EXIT +printf '%s\n' '{ value = 1 }' > "$fixture/plain.ncl" +printf '%s\n' 'K9!' '{ value = 1 }' > "$fixture/wrapped.k9.ncl" +printf '%s\n' 'K9!' '{ value = }' > "$fixture/bad.k9.ncl" +bash "$root/scripts/validate-session-contracts.sh" --typecheck "$fixture/plain.ncl" "$fixture/wrapped.k9.ncl" +if bash "$root/scripts/validate-session-contracts.sh" --typecheck "$fixture/bad.k9.ncl"; then + echo 'Invalid Nickel was accepted' >&2 + exit 1 +fi +echo 'PASS: plain and wrapped Nickel accepted; malformed Nickel rejected' From edee29326d1c11e181e3b6993c991a277e00c6dc Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 10 Sep 2026 01:56:30 +0100 Subject: [PATCH 5/8] fix(ci): run required Scorecard analysis before merge --- .github/workflows/scorecard.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index e99b331..ec92cc2 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -3,6 +3,8 @@ name: OSSF Scorecard on: + pull_request: + branches: ["**"] schedule: - cron: '0 4 * * *' workflow_dispatch: From f45f2f23b4214e4dbae0530b34bba5c5d46fb8f1 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 10 Sep 2026 02:51:37 +0100 Subject: [PATCH 6/8] fix(ci): consume scanner contracts and resolve template review findings --- .github/workflows/dependabot-automerge.yml | 2 +- .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- .github/workflows/mirror.yml | 2 +- .github/workflows/rust-ci.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner.yml | 3 +-- .github/workflows/static-analysis-gate.yml | 6 +++--- container/README.adoc | 4 ++-- container/deploy.k9.ncl | 4 ++-- tests/templates/e2e.sh.template | 8 ++++---- tests/workflows/k9_typecheck_test.sh | 1 + 12 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/dependabot-automerge.yml b/.github/workflows/dependabot-automerge.yml index 6706ef2..bbbd9f6 100644 --- a/.github/workflows/dependabot-automerge.yml +++ b/.github/workflows/dependabot-automerge.yml @@ -49,7 +49,7 @@ permissions: jobs: automerge: # Only run for PRs actually authored by Dependabot. - if: github.actor == 'dependabot[bot]' && github.event.pull_request.user.login == 'dependabot[bot]' + if: github.actor_id == '49699333' && github.event.pull_request.user.login == 'dependabot[bot]' runs-on: ubuntu-latest timeout-minutes: 15 steps: diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 1a736f6..3c51090 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -15,4 +15,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 63d32d9..b3c3bae 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -18,4 +18,4 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 9cdbe1e..9087230 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -12,7 +12,7 @@ permissions: contents: read jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 secrets: GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }} BITBUCKET_SSH_KEY: ${{ secrets.BITBUCKET_SSH_KEY }} diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 6856111..688afcd 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -15,4 +15,4 @@ permissions: contents: read jobs: rust-ci: - uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a + uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ec92cc2..a750932 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -16,7 +16,7 @@ permissions: id-token: write jobs: scorecard: - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 permissions: contents: read security-events: write diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index 1b58a6f..6e361d8 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -18,5 +18,4 @@ jobs: scan: permissions: contents: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@e9fa12b965897f485f8ec143e048a424b52f689a - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@da2c748aad55c1a1dcba00b60fe4a35017bc6540 diff --git a/.github/workflows/static-analysis-gate.yml b/.github/workflows/static-analysis-gate.yml index 9d5e743..5cf88d8 100644 --- a/.github/workflows/static-analysis-gate.yml +++ b/.github/workflows/static-analysis-gate.yml @@ -70,7 +70,7 @@ jobs: TOTAL=$(jq '. | length' panic-attack-findings.json 2>/dev/null || echo 0) CRITICAL=$(jq '[.[] | select(.severity == "critical")] | length' panic-attack-findings.json 2>/dev/null || echo 0) HIGH=$(jq '[.[] | select(.severity == "high")] | length' panic-attack-findings.json 2>/dev/null || echo 0) - MEDIUM=$(jq '[.[] | select(.severity == "medium")] | length' panic-attack-findings.json 2>/dev/null || echo 0) + MEDIUM=$(jq '[.[] | select(.severity == "medium" or .severity == "warn")] | length' panic-attack-findings.json 2>/dev/null || echo 0) LOW=$(jq '[.[] | select(.severity == "low")] | length' panic-attack-findings.json 2>/dev/null || echo 0) echo "total=$TOTAL" >> "$GITHUB_OUTPUT" @@ -198,7 +198,7 @@ jobs: TOTAL=$(jq '. | length' hypatia-findings.json 2>/dev/null || echo 0) CRITICAL=$(jq '[.[] | select(.severity == "critical")] | length' hypatia-findings.json 2>/dev/null || echo 0) HIGH=$(jq '[.[] | select(.severity == "high")] | length' hypatia-findings.json 2>/dev/null || echo 0) - MEDIUM=$(jq '[.[] | select(.severity == "medium")] | length' hypatia-findings.json 2>/dev/null || echo 0) + MEDIUM=$(jq '[.[] | select(.severity == "medium" or .severity == "warn")] | length' hypatia-findings.json 2>/dev/null || echo 0) LOW=$(jq '[.[] | select(.severity == "low")] | length' hypatia-findings.json 2>/dev/null || echo 0) echo "total=$TOTAL" >> "$GITHUB_OUTPUT" @@ -410,7 +410,7 @@ jobs: TOTAL=$(jq '.findings | length' findings/unified-findings.json) CRITICAL=$(jq '[.findings[] | select(.severity == "critical")] | length' findings/unified-findings.json) HIGH=$(jq '[.findings[] | select(.severity == "high")] | length' findings/unified-findings.json) - MEDIUM=$(jq '[.findings[] | select(.severity == "medium")] | length' findings/unified-findings.json) + MEDIUM=$(jq '[.findings[] | select(.severity == "medium" or .severity == "warn")] | length' findings/unified-findings.json) LOW=$(jq '[.findings[] | select(.severity == "low")] | length' findings/unified-findings.json) echo "total=$TOTAL" >> "$GITHUB_OUTPUT" diff --git a/container/README.adoc b/container/README.adoc index 78275d2..a147763 100644 --- a/container/README.adoc +++ b/container/README.adoc @@ -154,8 +154,8 @@ For k9-svc managed deployments: [source,bash] ---- -# Validate the deployment component -nickel typecheck container/deploy.k9.ncl +# After just init has replaced template values, typecheck without deploying +bash scripts/validate-session-contracts.sh --typecheck container/deploy.k9.ncl # Deploy (requires Hunt-level authorisation) k9-svc deploy container/deploy.k9.ncl --env production diff --git a/container/deploy.k9.ncl b/container/deploy.k9.ncl index 65bdacf..a666636 100644 --- a/container/deploy.k9.ncl +++ b/container/deploy.k9.ncl @@ -8,8 +8,8 @@ K9! # WARNING: This component can execute shell commands! # It requires explicit authorisation via the Leash system. # -# Usage: -# nickel typecheck container/deploy.k9.ncl +# Usage (after just init replaces the project and numeric port placeholders): +# bash scripts/validate-session-contracts.sh --typecheck container/deploy.k9.ncl # k9-svc validate container/deploy.k9.ncl # k9-svc deploy container/deploy.k9.ncl --env production diff --git a/tests/templates/e2e.sh.template b/tests/templates/e2e.sh.template index 11143fc..2b55c8b 100755 --- a/tests/templates/e2e.sh.template +++ b/tests/templates/e2e.sh.template @@ -8,8 +8,8 @@ # Customise this file for your project. Delete the examples that don't apply. # # Usage: -# bash tests/e2e.sh -# just e2e +# bash tests/templates/e2e.sh.template +# Enable the workflow template only after replacing the examples with real checks. # # Merge requirements (STANDING): All 6 test categories must pass before merge: # P2P, E2E (this file), aspect, execution, lifecycle, benchmarks @@ -17,7 +17,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" PASS=0 FAIL=0 @@ -34,7 +34,7 @@ bold() { printf '\033[1m%s\033[0m\n' "$*"; } # check