From ffc8c328690b614ea5555e5efb7dd0ecfbd12c17 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 7 Sep 2026 03:32:28 +0100 Subject: [PATCH 01/13] Date the FRG assessment and clarify the Me projection boundary --- .claude/CLAUDE.md | 16 ++++++------ .github/workflows/actions.lock | 22 ++++++++-------- .github/workflows/governance.yml | 4 +-- .github/workflows/hypatia-scan.yml | 6 +++-- .github/workflows/pages.yml | 4 +-- .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 | 0 .../{6a2 => descriptiles}/NEUROSYM.a2ml | 0 .../{6a2 => descriptiles}/PLAYBOOK.a2ml | 0 .../{6a2 => descriptiles}/README.adoc | 0 .../{6a2 => descriptiles}/STATE.a2ml | 5 ++++ CHANGELOG.adoc | 2 +- DEBT.adoc | 4 +-- Justfile | 4 +-- README.adoc | 2 +- ROADMAP.adoc | 2 +- docs/wiki/README.md | 2 +- docs/wiki/internals/formal-verification.md | 2 +- docs/wiki/roadmap/compiler.md | 2 +- docs/wiki/roadmap/language.md | 2 +- docs/wiki/roadmap/overview.md | 2 +- docs/wiki/roadmap/tooling.md | 2 +- spec/FRG-PROFILE.adoc | 25 ++++++++++++++----- 26 files changed, 66 insertions(+), 46 deletions(-) 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 (100%) rename .machine_readable/{6a2 => descriptiles}/NEUROSYM.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/PLAYBOOK.a2ml (100%) rename .machine_readable/{6a2 => descriptiles}/README.adoc (100%) rename .machine_readable/{6a2 => descriptiles}/STATE.a2ml (98%) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 144741d..48ca2e4 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -3,15 +3,15 @@ ## Machine-Readable Artefacts -The following files in `.machine_readable/6a2/` contain structured project +The following files in `.machine_readable/descriptiles/` contain structured project metadata (a2ml format; the earlier `.scm` root-level names are retired): -- `6a2/STATE.a2ml` - Current project state and progress -- `6a2/META.a2ml` - Architecture decisions (ADRs) and development practices -- `6a2/ECOSYSTEM.a2ml` - Position in the ecosystem and related projects -- `6a2/AGENTIC.a2ml` - AI agent interaction patterns -- `6a2/NEUROSYM.a2ml` - Neurosymbolic integration config -- `6a2/PLAYBOOK.a2ml` - Operational runbook +- `descriptiles/STATE.a2ml` - Current project state and progress +- `descriptiles/META.a2ml` - Architecture decisions (ADRs) and development practices +- `descriptiles/ECOSYSTEM.a2ml` - Position in the ecosystem and related projects +- `descriptiles/AGENTIC.a2ml` - AI agent interaction patterns +- `descriptiles/NEUROSYM.a2ml` - Neurosymbolic integration config +- `descriptiles/PLAYBOOK.a2ml` - Operational runbook Self-validation / service metadata lives in `.machine_readable/svc/` (`svc/k9/my-lang-metadata.k9.ncl`, `svc/README.adoc`). The scope-arrest anchor @@ -36,7 +36,7 @@ is the top-level `ANCHOR.scope-arrest.2026-01-01.Jewell.scm`. | **Bash/POSIX Shell** | Scripts, automation | Keep minimal | | **JavaScript** | Only where AffineScript cannot | MCP protocol glue, Bun APIs | | **Nickel** | Configuration language | For complex configs | -| **Guile Scheme** | State/meta files | `.machine_readable/6a2/{STATE,META,ECOSYSTEM}.a2ml` (the earlier `.scm` names are retired) | +| **Guile Scheme** | State/meta files | `.machine_readable/descriptiles/{STATE,META,ECOSYSTEM}.a2ml` (the earlier `.scm` names are retired) | | **Julia** | Batch scripts, data processing | Per RSR | | **OCaml** | AffineScript compiler | Language-specific | | **Ada** | Safety-critical systems | Where required | diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index 53dac06..74ca1e8 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -5,11 +5,11 @@ version: 'v0.0.2' workflows: '.github/workflows/cflite_batch.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'github/codeql-action@v4.37.8' + - 'github/codeql-action@v4.37.9' - 'google/clusterfuzzlite@884713a6c30a92e5e8544c39945cd7cb630abcd1' '.github/workflows/cflite_pr.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'github/codeql-action@v4.37.8' + - 'github/codeql-action@v4.37.9' - 'google/clusterfuzzlite@884713a6c30a92e5e8544c39945cd7cb630abcd1' '.github/workflows/checker-scaling.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' @@ -17,7 +17,7 @@ workflows: - 'dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772' '.github/workflows/codeql.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'github/codeql-action@v4.37.8' + - 'github/codeql-action@v4.37.9' '.github/workflows/coverage.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' @@ -32,7 +32,7 @@ workflows: - 'hyperpolymath/standards@08586a12bb64b98268fe9ebf552998aa2433a3c2' '.github/workflows/pages.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - - 'actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128' + - 'actions/deploy-pages@v5.0.1' - 'actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9' '.github/workflows/proofs.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' @@ -58,9 +58,9 @@ dependencies: commit: 'sha1-3d3c42e5aac5ba805825da76410c181273ba90b1' owner_id: 44036562 repo_id: 197814629 - 'actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128': - ref: 'v5.0.0' - commit: 'sha1-cd2ce8fcbc39b97be8ca5fce6e763baed58fa128' + 'actions/deploy-pages@v5.0.1': + ref: 'v5.0.1' + commit: 'sha1-368f82528645a54fb793d4d04e342629a3f51346' owner_id: 44036562 repo_id: 438112499 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a': @@ -74,7 +74,7 @@ dependencies: owner_id: 44036562 repo_id: 192625955 'actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9': - ref: 'v5.0.0' + ref: 'fc324d3547104276b827a68afc52ff2a11cc49c9' commit: 'sha1-fc324d3547104276b827a68afc52ff2a11cc49c9' owner_id: 44036562 repo_id: 496012378 @@ -110,9 +110,9 @@ dependencies: commit: 'sha1-f205ea1c3313d32999d8d6a48b4f6530d4437b38' owner_id: 9919 repo_id: 259445878 - 'github/codeql-action@v4.37.8': - ref: 'v4.37.8' - commit: 'sha1-db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28' + 'github/codeql-action@v4.37.9': + ref: 'v4.37.9' + commit: 'sha1-cdf488f595d80d6e07e03d4674febd5ab45fa938' owner_id: 9919 repo_id: 259445878 'google/clusterfuzzlite@884713a6c30a92e5e8544c39945cd7cb630abcd1': diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 414cca0..635e8b5 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -1,5 +1,5 @@ -# SPDX-License-Identifier: MPL-2.0 # This workflow is managed by gh actions-lock. +# SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell name: Governance @@ -17,4 +17,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@fcb566cfb8a86cea2d3666bf65a4f177a49b1313 diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 251da4a..9e465ae 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -1,5 +1,5 @@ -# SPDX-License-Identifier: MPL-2.0 # This workflow is managed by gh actions-lock. +# SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell name: Hypatia Security Scan @@ -20,4 +20,6 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@fcb566cfb8a86cea2d3666bf65a4f177a49b1313 + with: + block-on-high: true diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index d2ed55e..968549b 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -1,5 +1,5 @@ -# SPDX-License-Identifier: MPL-2.0 # This workflow is managed by gh actions-lock. +# SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell name: GitHub Pages (Ddraig SSG) @@ -54,4 +54,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5 + uses: actions/deploy-pages@v5.0.1 diff --git a/.machine_readable/contractiles/Mustfile.a2ml b/.machine_readable/contractiles/Mustfile.a2ml index b14c4c8..e81dcab 100644 --- a/.machine_readable/contractiles/Mustfile.a2ml +++ b/.machine_readable/contractiles/Mustfile.a2ml @@ -34,7 +34,7 @@ pre-commit hooks fail if any check fails. my-lang is a CONSUMER of the RSR ### ai-manifest - description: 0-AI-MANIFEST.a2ml must exist (under 6a2/) -- run: test -f .machine_readable/6a2/0-AI-MANIFEST.a2ml +- run: test -f .machine_readable/descriptiles/0-AI-MANIFEST.a2ml - severity: critical ### governance-docs @@ -69,7 +69,7 @@ pre-commit hooks fail if any check fails. my-lang is a CONSUMER of the RSR ### 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/6a2 && 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 ### scope-arrest-anchor 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 100% rename from .machine_readable/6a2/META.a2ml rename to .machine_readable/descriptiles/META.a2ml 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 100% rename from .machine_readable/6a2/PLAYBOOK.a2ml rename to .machine_readable/descriptiles/PLAYBOOK.a2ml 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 98% rename from .machine_readable/6a2/STATE.a2ml rename to .machine_readable/descriptiles/STATE.a2ml index 0d4ae6c..0021c81 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/descriptiles/STATE.a2ml @@ -162,3 +162,8 @@ ci-pr = "PRs #143/#146/#147 merged 2026-07-27; no open PRs" proof-build = "pass — coqc 10/10 solo-core modules (Quantity, EchoMode, ResourceAlgebra, SoloCore, Tropical, Context, ContextProps, EchoResidue, EchoMeasure, SessionPi; local full clean rebuild 2026-06-14); idris2 --build OK; all per-rung Print Assumptions closed (R-ladder, M1, S1.0–S3c.3-msg, E4)" known-local-limitation = "my-llvm cannot be built in the maintainer's WSL environment (no system LLVM 21). `cargo build --workspace` FAILS there; `--exclude my-llvm` succeeds. Do not read a bare workspace build failure as a regression without checking for the llvm-sys compile_error." superseded-branch = "origin/feat/stdlib-fs-env-format — SUPERSEDED, safe to delete: main carries every builtin it adds PLUS fs_list_dir, its stdlib.rs is 355 lines behind, it conflicts on stdlib.rs + CONTRIBUTING.md, and it is 188 commits behind main" + +[language-portfolio-audit-20260907] +scope = "Evidence audit and scoped repairs; no blanket readiness upgrade" +report = "https://github.com/hyperpolymath/nextgen-languages/blob/main/docs/audits/2026-09-07-language-portfolio.md" +metadata-path = ".machine_readable/descriptiles/" diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 21abb76..9c6235c 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -52,7 +52,7 @@ described `+src/+`, `+config/+` and `+scripts/+` directories that do not exist) with the real 15-crate workspace layout, the `+solo ⊂ duet ⊂ ensemble+` containment hierarchy (with `+me+` as a projector outside it), and the CI gate map. -* docs: `+README.md+` and `+.machine_readable/6a2/STATE.a2ml+` now +* docs: `+README.md+` and `+.machine_readable/descriptiles/STATE.a2ml+` now record the dialects as nested subsets rather than four co-equal surfaces, and carry a security-posture section distinguishing expiring baseline debt from permanent scoped exemptions. diff --git a/DEBT.adoc b/DEBT.adoc index c4fa4d8..4fe2b42 100644 --- a/DEBT.adoc +++ b/DEBT.adoc @@ -11,7 +11,7 @@ duplicating them: proof-status registry * link:PROOF-NEEDS.md[`+PROOF-NEEDS.md+`] — proof-side cleanup notes * link:TESTING.md[`+TESTING.md+`] — per-crate coverage measurements -* link:.machine_readable/6a2/STATE.a2ml[`+.machine_readable/6a2/STATE.a2ml+`] +* link:.machine_readable/descriptiles/STATE.a2ml[`+.machine_readable/descriptiles/STATE.a2ml+`] — authoritative machine state Severity: *HIGH* = correctness, licensing or security exposure · @@ -140,7 +140,7 @@ licences. ==== L-4 — AGPL text committed while policy bans AGPL · MEDIUM `+LICENSES/AGPL-3.0-or-later.txt+` (34 KB) is present; nothing in the -tree declares AGPL, and `+.machine_readable/6a2/AGENTIC.a2ml+` states +tree declares AGPL, and `+.machine_readable/descriptiles/AGENTIC.a2ml+` states _"`Never use AGPL licence`"_. Licence scanners will report AGPL for this repository. *Next:* delete unless a dependency genuinely requires the text. diff --git a/Justfile b/Justfile index 470785c..6b19c55 100644 --- a/Justfile +++ b/Justfile @@ -70,7 +70,7 @@ pipeline: # Prepare a release release VERSION: @echo "Releasing {{VERSION}}..." - @echo "Set version = \"{{VERSION}}\" in Cargo.toml [workspace.package] and .machine_readable/6a2/STATE.a2ml, then tag." + @echo "Set version = \"{{VERSION}}\" in Cargo.toml [workspace.package] and .machine_readable/descriptiles/STATE.a2ml, then tag." # Run dialect demos (per golden-path contract) # Usage: just demo [dialect] @@ -124,7 +124,7 @@ verify: #!/usr/bin/env bash set -uo pipefail fail=0 - for p in .machine_readable .machine_readable/6a2/STATE.a2ml \ + for p in .machine_readable .machine_readable/descriptiles/STATE.a2ml \ .hypatia-baseline.json .hypatia-ignore \ proofs/STATUS.md Cargo.toml; do if [[ -e "$p" ]]; then echo "[OK] $p" diff --git a/README.adoc b/README.adoc index d17278f..6a8a383 100644 --- a/README.adoc +++ b/README.adoc @@ -430,7 +430,7 @@ cannot be satisfied (a keyword-matching `+coq_axiom+`, a keyword-matching `+transmute+`, and `+unsafe_block+` — a bare `+unsafe\s*\{+` regex whose "`requires SAFETY comment`" is never actually checked). See `+[security-posture]+` in -link:.machine_readable/6a2/STATE.a2ml[`+.machine_readable/6a2/STATE.a2ml+`] +link:.machine_readable/descriptiles/STATE.a2ml[`+.machine_readable/descriptiles/STATE.a2ml+`] for the machine-readable version. === Contributing diff --git a/ROADMAP.adoc b/ROADMAP.adoc index 3f904be..03ba132 100644 --- a/ROADMAP.adoc +++ b/ROADMAP.adoc @@ -11,7 +11,7 @@ toc::[] [NOTE] ==== This roadmap is *derived*, not authoritative. The machine-readable source of -truth is `.machine_readable/6a2/STATE.a2ml`; for proofs specifically it is +truth is `.machine_readable/descriptiles/STATE.a2ml`; for proofs specifically it is `proofs/STATUS.md`. Where they disagree with this file, they win. ==== diff --git a/docs/wiki/README.md b/docs/wiki/README.md index 9486ea3..a1a1e3b 100644 --- a/docs/wiki/README.md +++ b/docs/wiki/README.md @@ -105,7 +105,7 @@ integration is one capability among many — not the defining feature. ## Project status - **Version:** `0.2.0` (early-alpha, experimental; no tagged release) — see - [`.machine_readable/6a2/STATE.a2ml`](../../.machine_readable/6a2/STATE.a2ml) + [`.machine_readable/descriptiles/STATE.a2ml`](../../.machine_readable/descriptiles/STATE.a2ml) for the authoritative state, and [`proofs/STATUS.md`](../../proofs/STATUS.md) for the proof-status registry. - **Scope:** Solo dialect only in `f0` (per the diff --git a/docs/wiki/internals/formal-verification.md b/docs/wiki/internals/formal-verification.md index 294864b..0fcb9d0 100644 --- a/docs/wiki/internals/formal-verification.md +++ b/docs/wiki/internals/formal-verification.md @@ -107,4 +107,4 @@ and asserts `progress` is axiom-free. a typed hole (`?todo_*`) or a bare `Definition : Prop` is an *obligation*, never a result. - Architecture decisions are recorded as ADRs in - [`.machine_readable/6a2/META.a2ml`](../../../.machine_readable/6a2/META.a2ml). + [`.machine_readable/descriptiles/META.a2ml`](../../../.machine_readable/descriptiles/META.a2ml). diff --git a/docs/wiki/roadmap/compiler.md b/docs/wiki/roadmap/compiler.md index c43e052..6ffb162 100644 --- a/docs/wiki/roadmap/compiler.md +++ b/docs/wiki/roadmap/compiler.md @@ -4,7 +4,7 @@ # Compiler Roadmap > [!WARNING] -> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/6a2/STATE.a2ml` are authoritative. +> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/descriptiles/STATE.a2ml` are authoritative. This document outlines the development plan for the My Language compiler infrastructure. diff --git a/docs/wiki/roadmap/language.md b/docs/wiki/roadmap/language.md index e9e8ce7..f11d182 100644 --- a/docs/wiki/roadmap/language.md +++ b/docs/wiki/roadmap/language.md @@ -4,7 +4,7 @@ # Language Roadmap > [!WARNING] -> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/6a2/STATE.a2ml` are authoritative. +> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/descriptiles/STATE.a2ml` are authoritative. This document details the evolution of My Language's core features and syntax. diff --git a/docs/wiki/roadmap/overview.md b/docs/wiki/roadmap/overview.md index cb54803..0376519 100644 --- a/docs/wiki/roadmap/overview.md +++ b/docs/wiki/roadmap/overview.md @@ -4,7 +4,7 @@ # My Language Roadmap Overview > [!WARNING] -> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/6a2/STATE.a2ml` are authoritative. +> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/descriptiles/STATE.a2ml` are authoritative. *Last Updated: 2025-12-17* diff --git a/docs/wiki/roadmap/tooling.md b/docs/wiki/roadmap/tooling.md index 13acca2..17674fb 100644 --- a/docs/wiki/roadmap/tooling.md +++ b/docs/wiki/roadmap/tooling.md @@ -4,7 +4,7 @@ # Tooling Roadmap > [!WARNING] -> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/6a2/STATE.a2ml` are authoritative. +> **Status markers on this page are stale** (last updated 2025-12-17). Several items marked *Planned* have shipped (LLVM backend, formatter, linter, LSP), and the Type Checker marked *Complete* is in fact the open `#typeck` obligation. [`ROADMAP.adoc`](https://github.com/hyperpolymath/my-lang/blob/main/ROADMAP.adoc) and `.machine_readable/descriptiles/STATE.a2ml` are authoritative. This document outlines the development plan for My Language development tools. diff --git a/spec/FRG-PROFILE.adoc b/spec/FRG-PROFILE.adoc index 2582231..39e1be2 100644 --- a/spec/FRG-PROFILE.adoc +++ b/spec/FRG-PROFILE.adoc @@ -9,9 +9,9 @@ |=== | Field | Value -| Language | My (`.my`, four dialects) +| Language | My (`.my`; Solo, Duet, Ensemble; Me projection) | Repository | https://github.com/hyperpolymath/my-lang -| Current FRG Grade | *X* (no formalisation in any qualifying prover; PROOF-NEEDS.md explicitly records that template ABI scaffolding was removed without replacement) +| Historical FRG Grade (2026-05-28) | *X* (no formalisation in any qualifying prover; PROOF-NEEDS.md explicitly records that template ABI scaffolding was removed without replacement) | Assessed | 2026-05-28 | Assessor | Jonathan D.A. Jewell | FRG Spec Version | 1.0 @@ -21,7 +21,20 @@ | Qualifying Prover(s) | (none mechanised at the calculus level) |=== -== About this profile +== Assessment horizon and reassessment + +This document preserves the 2026-05-28 assessment; its absence claims must not +be treated as a fresh inventory. The September portfolio audit found additional +formal development and a proof-status registry in a local My checkout which was +not present at the fetched main revision. Reconcile and validate that unpublished +work before assigning a new grade to main. No grade upgrade is made here. + +The current dialect hierarchy is Solo, Duet, Ensemble. Me is an agent-generated +projection over it. Historical references below to a fourth static Me dialect +are superseded; a future profile must state the projection's elaboration and +behavior obligations separately from dialect inclusion. + +== Historical assessment My is FRG-X. The `proofs/` directory exists with dialect-aligned subdirectories suggesting *intended* per-dialect formalisation, but @@ -156,9 +169,9 @@ For My, the following FRG tightening applies: formalisation must start at the simplest and add layered obligations. * *Grade D tightening:* Preservation MUST be stated *per dialect*: - preservation-solo, preservation-duet, preservation-ensemble, - preservation-me, with explicit composition rules for the - inclusion `solo ⊆ duet ⊆ ensemble ⊆ me`. + preservation-solo, preservation-duet, preservation-ensemble, with + explicit composition rules for `solo ⊆ duet ⊆ ensemble`. The Me + projection requires its own elaboration and behavior correspondence. * *Grade C tightening:* The borrow checker MUST be modelled in the formal calculus, not stubbed out. (My's borrow-check is genuine per `crates/my-lint/`; the formal encoding must match.) From 070a7d600ff8d63b77200d0293afa68337a705f7 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 7 Sep 2026 04:17:02 +0100 Subject: [PATCH 02/13] fix(ci): resolve audit blockers and reviewed toolchain gaps --- .github/workflows/governance.yml | 4 +- .github/workflows/hypatia-scan.yml | 4 +- .../contractiles/Adjustfile.a2ml | 2 +- .machine_readable/contractiles/Mustfile.a2ml | 6 +- .../dust/detach-echo-types-plugin.a2ml | 2 +- .../dust/uninstall-coq-toolchain.a2ml | 2 +- .../descriptiles/0-AI-MANIFEST.a2ml | 4 +- .machine_readable/descriptiles/PLAYBOOK.a2ml | 2 +- .machine_readable/descriptiles/README.adoc | 2 +- DEBT.adoc | 2 +- README.adoc | 2 +- SECURITY.md | 9 + .../.machine_readable/6a2/PLAYBOOK.a2ml | 2 +- scripts/apply-baseline.sh | 277 ++++++++++++++++++ spec/FRG-PROFILE.adoc | 2 +- 15 files changed, 304 insertions(+), 18 deletions(-) create mode 100644 SECURITY.md create mode 100644 scripts/apply-baseline.sh diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index 635e8b5..a6c8100 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -1,5 +1,5 @@ -# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 +# This workflow is managed by gh actions-lock. # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell name: Governance @@ -17,4 +17,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@fcb566cfb8a86cea2d3666bf65a4f177a49b1313 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@3bc7de609f3fea6ddb5d584010e7568fba40686f diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 9e465ae..6815023 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -1,5 +1,5 @@ -# This workflow is managed by gh actions-lock. # SPDX-License-Identifier: MPL-2.0 +# This workflow is managed by gh actions-lock. # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell name: Hypatia Security Scan @@ -20,6 +20,6 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@fcb566cfb8a86cea2d3666bf65a4f177a49b1313 + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@3bc7de609f3fea6ddb5d584010e7568fba40686f with: block-on-high: true diff --git a/.machine_readable/contractiles/Adjustfile.a2ml b/.machine_readable/contractiles/Adjustfile.a2ml index ebeed11..8b73d08 100644 --- a/.machine_readable/contractiles/Adjustfile.a2ml +++ b/.machine_readable/contractiles/Adjustfile.a2ml @@ -40,7 +40,7 @@ actions. Advisory — it warns and trends, it does not block. - severity: advisory ### status-doc-currency -- description: proofs/STATUS.md + 6a2/STATE.a2ml reflect the actual proof state +- description: proofs/STATUS.md + descriptiles/STATE.a2ml reflect the actual proof state - tolerance: Status registry matches the mechanised cores - corrective: Refresh STATUS.md / STATE.a2ml after any proof rung lands - severity: advisory diff --git a/.machine_readable/contractiles/Mustfile.a2ml b/.machine_readable/contractiles/Mustfile.a2ml index e81dcab..77d3cfa 100644 --- a/.machine_readable/contractiles/Mustfile.a2ml +++ b/.machine_readable/contractiles/Mustfile.a2ml @@ -33,7 +33,7 @@ pre-commit hooks fail if any check fails. my-lang is a CONSUMER of the RSR - severity: critical ### ai-manifest -- description: 0-AI-MANIFEST.a2ml must exist (under 6a2/) +- description: 0-AI-MANIFEST.a2ml must exist (under descriptiles/) - run: test -f .machine_readable/descriptiles/0-AI-MANIFEST.a2ml - severity: critical @@ -68,8 +68,8 @@ pre-commit hooks fail if any check fails. my-lang is a CONSUMER of the RSR - severity: critical ### six-directory-present -- description: 6a2 directory exists with required files -- run: test -d .machine_readable/6a2 && 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 +- description: descriptiles directory exists with required files +- run: test -d .machine_readable/descriptiles && test -f .machine_readable/descriptiles/META.a2ml && test -f .machine_readable/descriptiles/ECOSYSTEM.a2ml && test -f .machine_readable/descriptiles/STATE.a2ml && test -f .machine_readable/descriptiles/PLAYBOOK.a2ml && test -f .machine_readable/descriptiles/AGENTIC.a2ml && test -f .machine_readable/descriptiles/NEUROSYM.a2ml - severity: critical ### scope-arrest-anchor diff --git a/.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml b/.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml index ff593b1..bc68939 100644 --- a/.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml +++ b/.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml @@ -62,7 +62,7 @@ be a significant architectural change requiring a clear extension boundary. ### 5-update-6a2-state - description: Update STATE.a2ml to reflect echo-types as plugin, not built-in - corrective: > - In 6a2/STATE.a2ml: update echo_integration_status from 'built_in' to 'plugin'. + In descriptiles/STATE.a2ml: update echo_integration_status from 'built_in' to 'plugin'. Add an ADR in META.a2ml documenting the boundary decision. ## Completion Criteria diff --git a/.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml b/.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml index 57583df..a55ff51 100644 --- a/.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml +++ b/.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml @@ -47,7 +47,7 @@ what must be preserved, and what downstream consumers must be informed of. ### 5-update-6a2-state - description: Update STATE.a2ml and META.a2ml to reflect Coq retirement - corrective: > - In 6a2/STATE.a2ml: mark coq_core as retired; in 6a2/META.a2ml: remove + In descriptiles/STATE.a2ml: mark coq_core as retired; in descriptiles/META.a2ml: remove ADR-009 (open-context subst) as Coq-specific or generalise it. ### 6-notify-downstream diff --git a/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml b/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml index 89f4d36..7f05b3e 100644 --- a/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml +++ b/.machine_readable/descriptiles/0-AI-MANIFEST.a2ml @@ -1,11 +1,11 @@ # SPDX-License-Identifier: MPL-2.0 # SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell -# AI Manifest for 6a2 Directory +# AI Manifest for Descriptiles Directory ## Purpose -This manifest declares the AI-assistant context for the 6a2 machine-readable metadata directory. +This manifest declares the AI-assistant context for the descriptiles machine-readable metadata directory. ## Canonical Locations diff --git a/.machine_readable/descriptiles/PLAYBOOK.a2ml b/.machine_readable/descriptiles/PLAYBOOK.a2ml index bc3004c..22bdf45 100644 --- a/.machine_readable/descriptiles/PLAYBOOK.a2ml +++ b/.machine_readable/descriptiles/PLAYBOOK.a2ml @@ -12,7 +12,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/descriptiles/README.adoc b/.machine_readable/descriptiles/README.adoc index 8342608..64f16e6 100644 --- a/.machine_readable/descriptiles/README.adoc +++ b/.machine_readable/descriptiles/README.adoc @@ -1,7 +1,7 @@ // SPDX-License-Identifier: CC-BY-SA-4.0 // SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell -# A2ML 6a2 Directory +# A2ML Descriptiles Directory This directory contains the 6 core A2ML machine-readable metadata files for this repository. diff --git a/DEBT.adoc b/DEBT.adoc index 4fe2b42..b550018 100644 --- a/DEBT.adoc +++ b/DEBT.adoc @@ -478,7 +478,7 @@ reconcile or scope the patterns to new code. nearly all commented placeholders; `+AGENTIC.a2ml+` (2026-04-11) is comment-only and states _"`Never place state files in repository root`"_ while four sit at root. Two different `+0-AI-MANIFEST.a2ml+` files exist -(root = S-expression, `+6a2/+` = Markdown) with contradictory content. +(root = S-expression, `+descriptiles/+` = Markdown) with contradictory content. `+svc/README.adoc+` documents a `+k9/+` directory that does not exist (the file lives in `+self-validating/+`). *Next:* fill or delete; deduplicate the manifest. diff --git a/README.adoc b/README.adoc index 6a8a383..dbb198d 100644 --- a/README.adoc +++ b/README.adoc @@ -44,7 +44,7 @@ note]. |`+frontier-practices/+` |Forward-looking research experiments (not shipped). -|`+.machine_readable/+` |Machine-facing state. `+6a2/STATE.a2ml+` is the +|`+.machine_readable/+` |Machine-facing state. `+descriptiles/STATE.a2ml+` is the authoritative project-state file for agents; `+contractiles/+` holds the Mustfile / Dustfile invariant and recovery contracts. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..9fbb409 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,9 @@ + +# Security policy + +Report suspected vulnerabilities privately to the contact listed in +[security.txt](.well-known/security.txt). Include the affected commit, reproduction +steps and expected impact. Do not include credentials in public issues or PRs. + +This repository contains research and development work; a successful CI run +does not certify all language designs, proofs or deployment configurations. diff --git a/playground/.machine_readable/6a2/PLAYBOOK.a2ml b/playground/.machine_readable/6a2/PLAYBOOK.a2ml index bc3004c..22bdf45 100644 --- a/playground/.machine_readable/6a2/PLAYBOOK.a2ml +++ b/playground/.machine_readable/6a2/PLAYBOOK.a2ml @@ -12,7 +12,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/scripts/apply-baseline.sh b/scripts/apply-baseline.sh new file mode 100644 index 0000000..0916c7b --- /dev/null +++ b/scripts/apply-baseline.sh @@ -0,0 +1,277 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: MPL-2.0 +# +# apply-baseline.sh — filter Hypatia findings against a per-repo baseline. +# +# Inputs: +# $1 = path to findings JSON (array of {severity, rule_module, type, file, ...}) +# $2 = path to .hypatia-baseline.json (array of baseline entries, see schema) +# $3 = mode: "advisory" | "blocking" (default: advisory) +# +# Outputs (stdout): +# Filtered findings JSON. Each finding gets one of: +# - removed entirely (matched by baseline, no severity_override) +# - kept with downgraded `severity` (matched, severity_override set) +# - kept unchanged with `baseline_status: "new"` +# Plus a top-level summary written to $GITHUB_STEP_SUMMARY if set. +# +# Exit codes: +# 0 = all unfiltered findings have severity below blocking threshold +# (or advisory mode) +# 1 = one or more unfiltered findings >= high in blocking mode +# 2 = invalid input (missing files, malformed JSON, or a baseline that +# violates the schema — see below) +# +# Dependencies: bash, jq. +# +# Schema enforcement: the baseline is structurally validated here, in jq, +# mirroring .machine_readable/hypatia-baseline.schema.json (required keys, +# file XOR file_pattern, closed key set, severity enums, rule_module/type/ +# tracking_issue/expires_at shapes). This script is the single place every +# baseline passes through (both reusable workflows call it), so validating +# here needs no extra tooling or checkout — and a malformed baseline FAILS +# (exit 2) rather than silently matching nothing, which is how suppression +# bugs creep in. Keep this mirror in sync when the schema changes. + +set -euo pipefail + +FINDINGS_FILE="${1:-}" +BASELINE_FILE="${2:-}" +MODE="${3:-advisory}" +BLOCKING_THRESHOLD="${BLOCKING_THRESHOLD:-high}" +TODAY="$(date -u +%Y-%m-%d)" + +if [[ -z "$FINDINGS_FILE" || -z "$BASELINE_FILE" ]]; then + echo "usage: apply-baseline.sh <.hypatia-baseline.json> [advisory|blocking]" >&2 + exit 2 +fi + +if [[ ! -f "$FINDINGS_FILE" ]]; then + echo "error: findings file not found: $FINDINGS_FILE" >&2 + exit 2 +fi + +# Missing baseline is not an error — treat as empty array. +if [[ ! -f "$BASELINE_FILE" ]]; then + BASELINE_JSON='[]' +else + BASELINE_JSON="$(cat "$BASELINE_FILE")" +fi + +FINDINGS_JSON="$(cat "$FINDINGS_FILE")" + +# Validate inputs are JSON arrays. +echo "$FINDINGS_JSON" | jq -e 'type == "array"' >/dev/null || { + echo "error: findings JSON is not an array" >&2 + exit 2 +} +echo "$BASELINE_JSON" | jq -e 'type == "array"' >/dev/null || { + echo "error: baseline JSON is not an array" >&2 + exit 2 +} + +# Structural validation against the baseline schema (see header). +SCHEMA_ERRORS="$(jq -r ' + def known: ["severity","rule_module","type","file","file_pattern", + "severity_override","expires_at","note","tracking_issue"]; + def sevs: ["critical","high","medium","low","info"]; + [ to_entries[] | .key as $i | .value as $e | + if ($e|type) != "object" then "entry[\($i)]: not an object" + else ( + (["severity","rule_module","type"][] + | select(($e[.]|type) != "string") + | "entry[\($i)]: required key \(.) missing or not a string"), + (if (($e|has("file")) == ($e|has("file_pattern"))) + then "entry[\($i)]: exactly one of file / file_pattern is required" + else empty end), + ($e | keys[] + | select(. as $k | known | index($k) | not) + | "entry[\($i)]: unknown key \(.)"), + (if ($e.severity|type) == "string" and ((sevs|index($e.severity))|not) + then "entry[\($i)]: invalid severity \($e.severity)" else empty end), + (if ($e.rule_module|type) == "string" + and (($e.rule_module|test("^[a-z][a-z0-9_]*$"))|not) + then "entry[\($i)]: rule_module fails pattern: \($e.rule_module)" + else empty end), + # `type` accepts three shapes, and the third is not cosmetic: + # snake_case — the Hypatia rule modules (unsafe_block, ...) + # SD007/HYP-S009 codes — structural_drift and canonical-home rules + # CamelCase — SCORECARD PROBE NAMES (DependencyPinning, + # BranchProtection, ...). Hypatia emits these + # verbatim from Scorecard, and without this + # alternative NO SCORECARD FINDING COULD BE + # BASELINED BY ANY REPOSITORY — the validator + # rejected the whole file with exit 2, which + # reads as "your baseline is malformed" rather + # than "this finding is unrepresentable". + # Found 2026-08-06 in metadatastician/stapeln. + (if ($e.type|type) == "string" + and (($e.type|test("^([a-z][a-z0-9_]*|[A-Z]{2,3}(-[A-Z])?[0-9]{3}|[A-Z][A-Za-z0-9]+)$"))|not) + then "entry[\($i)]: type fails pattern: \($e.type)" else empty end), + (if ($e|has("file")) and ((($e.file|type) != "string") or ($e.file == "")) + then "entry[\($i)]: file must be a non-empty string" else empty end), + (if ($e|has("file_pattern")) + and ((($e.file_pattern|type) != "string") or ($e.file_pattern == "")) + then "entry[\($i)]: file_pattern must be a non-empty string" + else empty end), + (if ($e|has("severity_override")) + and (((sevs + ["advisory"])|index($e.severity_override))|not) + then "entry[\($i)]: invalid severity_override \($e.severity_override)" + else empty end), + (if ($e|has("expires_at")) + and ((($e.expires_at|type) != "string") + or (($e.expires_at|test("^[0-9]{4}-[0-9]{2}-[0-9]{2}$"))|not)) + then "entry[\($i)]: expires_at must be an ISO date (YYYY-MM-DD)" + else empty end), + (if ($e|has("tracking_issue")) + and ((($e.tracking_issue|type) != "string") + or (($e.tracking_issue|test("^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+#[0-9]+$"))|not)) + then "entry[\($i)]: tracking_issue must look like owner/repo#N" + else empty end) + ) end + ] | .[] +' <<<"$BASELINE_JSON")" + +if [[ -n "$SCHEMA_ERRORS" ]]; then + echo "error: baseline violates hypatia-baseline.schema.json:" >&2 + echo "$SCHEMA_ERRORS" >&2 + exit 2 +fi + +# Pre-filter baseline: drop expired entries (>=today). +ACTIVE_BASELINE="$(jq --arg today "$TODAY" ' + map(select((.expires_at // "9999-12-31") >= $today)) +' <<<"$BASELINE_JSON")" + +EXPIRED_COUNT="$(jq 'length' <<<"$BASELINE_JSON")" +ACTIVE_COUNT="$(jq 'length' <<<"$ACTIVE_BASELINE")" +EXPIRED_COUNT=$((EXPIRED_COUNT - ACTIVE_COUNT)) + +# Match each finding against the active baseline. Returns the matched +# baseline entry (or null) for each finding. +ANNOTATED="$(jq -n \ + --argjson findings "$FINDINGS_JSON" \ + --argjson baseline "$ACTIVE_BASELINE" ' + # Two captures are essential here: + # `f as $finding` — without this, references like `f.file` inside the + # select() get re-evaluated against the current baseline entry (the + # re-bound `.`), not the finding. Binding $finding once captures the + # finding before we enter the map(select()) over the baseline. + # + # `(.file_pattern? // null) as $pat` — inside `test(arg)` the dot + # rebinds to the input of test ($finding.file, a string), so + # referencing `.file_pattern` there would error with "Cannot index + # string". Capture the entry pattern first, then reference $pat + # inside the test() regex argument. + def match_entry(f): + f as $finding + | $baseline + | map(select( + .severity == $finding.severity + and .rule_module == $finding.rule_module + and .type == $finding.type + and ( + (.file? // null) == $finding.file + or ( + (.file_pattern? // null) as $pat + | $pat != null + and ($finding.file | test( + $pat + | gsub("\\*\\*"; "DOUBLESTAR") + | gsub("\\*"; "[^/]*") + | gsub("DOUBLESTAR"; ".*") + | "^" + . + "$" + )) + ) + ) + )) + | first // null; + + $findings + | map( + . as $f + | match_entry(.) as $m + | if $m == null then + . + {baseline_status: "new"} + else + . + { + baseline_status: "acknowledged", + baseline_note: ($m.note // null), + baseline_tracking_issue: ($m.tracking_issue // null) + } + | if $m.severity_override then + .severity = $m.severity_override + | .baseline_status = "downgraded" + else + . + end + end + ) +')" + +# Split into kept (will be evaluated by the gate) and suppressed (silently +# acknowledged, surfaced only in summary). +KEPT="$(jq '[.[] | select(.baseline_status != "acknowledged")]' <<<"$ANNOTATED")" +SUPPRESSED="$(jq '[.[] | select(.baseline_status == "acknowledged")]' <<<"$ANNOTATED")" + +# Severity rank for blocking decision. +rank() { + case "$1" in + critical) echo 5 ;; + high) echo 4 ;; + medium) echo 3 ;; + low) echo 2 ;; + info) echo 1 ;; + advisory) echo 0 ;; + *) echo 0 ;; + esac +} + +THRESHOLD_RANK="$(rank "$BLOCKING_THRESHOLD")" +MAX_KEPT_RANK=0 +while IFS= read -r sev; do + r="$(rank "$sev")" + if (( r > MAX_KEPT_RANK )); then MAX_KEPT_RANK=$r; fi +done < <(jq -r '.[].severity' <<<"$KEPT") + +KEPT_COUNT="$(jq 'length' <<<"$KEPT")" +SUPPRESSED_COUNT="$(jq 'length' <<<"$SUPPRESSED")" +TOTAL_COUNT="$(jq 'length' <<<"$FINDINGS_JSON")" + +# Write summary if running inside Actions. +if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then + { + echo "## Hypatia baseline filter" + echo + echo "| | Count |" + echo "|---|---|" + echo "| Total findings | $TOTAL_COUNT |" + echo "| Acknowledged by baseline | $SUPPRESSED_COUNT |" + echo "| Remaining (kept for gate) | $KEPT_COUNT |" + echo "| Expired baseline entries | $EXPIRED_COUNT |" + echo + echo "Mode: \`$MODE\` · Blocking threshold: \`$BLOCKING_THRESHOLD\`" + if (( EXPIRED_COUNT > 0 )); then + echo + echo ":warning: $EXPIRED_COUNT baseline entries are past their \`expires_at\` and were ignored." + fi + } >> "$GITHUB_STEP_SUMMARY" +fi + +# Always emit the annotated findings so downstream steps can use them. +jq -n --argjson kept "$KEPT" --argjson suppressed "$SUPPRESSED" '{ + findings_kept: $kept, + findings_suppressed: $suppressed +}' + +# Gate decision. +if [[ "$MODE" == "advisory" ]]; then + exit 0 +fi + +if (( MAX_KEPT_RANK >= THRESHOLD_RANK )); then + echo "::error::Gate failed: $KEPT_COUNT unfiltered finding(s) at or above '$BLOCKING_THRESHOLD'." >&2 + exit 1 +fi + +exit 0 diff --git a/spec/FRG-PROFILE.adoc b/spec/FRG-PROFILE.adoc index 39e1be2..215a892 100644 --- a/spec/FRG-PROFILE.adoc +++ b/spec/FRG-PROFILE.adoc @@ -73,7 +73,7 @@ foundations evidence starts to interact). * *TypeLL level claimed:* L4 (Type compatibility) *operationally* * *Honest level for FRG:* L4 — implementation enforces affine / borrow / progressive-disclosure types, but no mechanised soundness - claim. The dialect structure (solo / duet / ensemble / me) + claim. The dialect structure (solo / duet / ensemble; Me is a projection) *aspires* to layered type-safety progression but no formal encoding establishes this. * *Levels not yet claimed:* L5-L10. Progressive-disclosure pedagogy From 0c3feeba3806e128b087a0f199681596ae2cc44d Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:35:41 +0100 Subject: [PATCH 03/13] Document parametric proof boundary and close baseline policy gaps --- .github/workflows/cflite_batch.yml | 2 +- .github/workflows/cflite_pr.yml | 2 +- .github/workflows/codeql.yml | 4 +-- .github/workflows/label-triage.yml | 1 + .github/workflows/labels.yml | 1 + .github/workflows/pages.yml | 2 +- .github/workflows/push-email-notify.yml | 2 +- docs/proof-debt.md | 43 +++++++++++++++++++++++++ 8 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 docs/proof-debt.md diff --git a/.github/workflows/cflite_batch.yml b/.github/workflows/cflite_batch.yml index 4674221..53a67aa 100644 --- a/.github/workflows/cflite_batch.yml +++ b/.github/workflows/cflite_batch.yml @@ -30,7 +30,7 @@ jobs: sanitizer: ${{ matrix.sanitizer }} mode: batch output-sarif: true - - uses: github/codeql-action/upload-sarif@v4.37.9 + - uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # Only upload when a SARIF was actually produced: a CLEAN fuzz run # (no crashes) writes no `vulnerabilities.sarif`, and an unconditional # `always()` upload then fails with "Path does not exist". diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml index e02ef45..6bb0e84 100644 --- a/.github/workflows/cflite_pr.yml +++ b/.github/workflows/cflite_pr.yml @@ -33,7 +33,7 @@ jobs: sanitizer: ${{ matrix.sanitizer }} mode: code-change output-sarif: true - - uses: github/codeql-action/upload-sarif@v4.37.9 + - uses: github/codeql-action/upload-sarif@cdf488f595d80d6e07e03d4674febd5ab45fa938 # Only upload when a SARIF was actually produced: a CLEAN fuzz run # (no crashes) writes no `vulnerabilities.sarif`, and an unconditional # `always()` upload then fails with "Path does not exist". diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3557acc..e63db92 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,11 +36,11 @@ jobs: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Initialize CodeQL - uses: github/codeql-action/init@v4.37.9 + uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.37.9 + uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/label-triage.yml b/.github/workflows/label-triage.yml index 9886e92..e61baef 100644 --- a/.github/workflows/label-triage.yml +++ b/.github/workflows/label-triage.yml @@ -46,6 +46,7 @@ permissions: jobs: triage: runs-on: ubuntu-latest + timeout-minutes: 5 steps: - name: Classify and label env: diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index c80b676..e4a5601 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -32,6 +32,7 @@ permissions: jobs: sync: runs-on: ubuntu-latest + timeout-minutes: 5 steps: - name: Apply canonical labels env: diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 968549b..2a96278 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -54,4 +54,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v5.0.1 + uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 diff --git a/.github/workflows/push-email-notify.yml b/.github/workflows/push-email-notify.yml index 2753481..e256152 100644 --- a/.github/workflows/push-email-notify.yml +++ b/.github/workflows/push-email-notify.yml @@ -41,7 +41,7 @@ jobs: timeout-minutes: 5 steps: - name: Send push notification email - uses: hyperpolymath/smtp-notify-action@v0.2.0 # NOSONAR — pin authority is actions.lock (sha1-ede1191ef6ff3ac02c4f4d9efdf837ee517e11d7) + uses: hyperpolymath/smtp-notify-action@ede1191ef6ff3ac02c4f4d9efdf837ee517e11d7 # NOSONAR — pin authority is actions.lock (sha1-ede1191ef6ff3ac02c4f4d9efdf837ee517e11d7) with: server_address: ${{ secrets.SMTP_HOST }} server_port: ${{ secrets.SMTP_PORT }} diff --git a/docs/proof-debt.md b/docs/proof-debt.md new file mode 100644 index 0000000..79229ea --- /dev/null +++ b/docs/proof-debt.md @@ -0,0 +1,43 @@ + +# Proof debt and the trusted boundary + +This register distinguishes abstract interface obligations from global axioms. +It records the published source inspected on 2026-09-07; it does not promote +unpublished proof work or establish that every language feature is verified. + +## (a) Discharged in concrete instances + +The 15 `Axiom` declarations in +`proofs/verification/coq/solo-core/ResourceAlgebra.v` are fields of Coq module +types: ten `SEMIRING` laws, three additional `ORDERED_SEMIRING` order laws, and +two `RESIDUE_MEASURE` homomorphism laws. An abstract soundness functor is +conditional on these fields. A concrete implementation must supply proofs of +the fields when checked against its module signature. + +The source identifies `Linear3`, `Tropical` and `EchoTraceTropical` as concrete +instances. Their instantiated theorem dependencies, rather than the spelling +`Axiom` inside a module type, determine the global trusted base. The existing +`proofs.yml` workflow checks concrete assumption closure. Passing the structural +trusted-base policy only establishes that these sites are documented; it is +not a new execution of the Coq checker or a proof of the Rust implementation. + +## (b) Budgeted boundaries + +No new refutation budget or runtime extraction guarantee is claimed by this +audit. See `proofs/STATUS.adoc` for the scope of existing checks. + +## (c) Necessary global axioms + +The interface fields above are not classified as necessary global axioms. +This review does not certify the dependency closure of every proof in the tree. + +## (d) Open obligations + +- **Owner:** repository maintainer, @hyperpolymath. +- **Scope:** the model/implementation correspondence and remaining obligations + recorded in `proofs/STATUS.adoc` and `proofs/ALIGNMENT-PLAN.adoc`. +- **Plan:** keep each theorem tied to its actual language fragment, concrete + resource algebra and executable checker; close the correspondence obligations + with compiler/proof checks and counterexample tests before expanding claims. +- **Deadline:** INDEFINITE: these are separate research obligations, not + discharged by the documentation and CI repairs in this PR. From 8a15bf3a83b21ae76020e3791d735d1cd00f53f9 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:58:53 +0100 Subject: [PATCH 04/13] Use the audited immutable scan helper and least-privilege governance --- .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index a6c8100..ad20c76 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -17,4 +17,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@3bc7de609f3fea6ddb5d584010e7568fba40686f + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@3c3acc19951b39c8ffe68b917aae4cc2e5b232e5 diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 6815023..76a7cfb 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -20,6 +20,6 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@3bc7de609f3fea6ddb5d584010e7568fba40686f + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@3c3acc19951b39c8ffe68b917aae4cc2e5b232e5 with: block-on-high: true From 81215cb777219b313360668a50ce23fe8be712c9 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Mon, 7 Sep 2026 09:41:32 +0100 Subject: [PATCH 05/13] Reject ambiguous baseline matches and publish security reporting contact --- .github/workflows/governance.yml | 2 +- .github/workflows/hypatia-scan.yml | 2 +- .well-known/security.txt | 4 ++++ scripts/apply-baseline.sh | 22 ++++++++++++++++++---- 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 .well-known/security.txt diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index ad20c76..7f81e8e 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -17,4 +17,4 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@3c3acc19951b39c8ffe68b917aae4cc2e5b232e5 + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@469605210e767ee94d1c7a9c13cb6a1d0a78cad1 diff --git a/.github/workflows/hypatia-scan.yml b/.github/workflows/hypatia-scan.yml index 76a7cfb..6b6edf5 100644 --- a/.github/workflows/hypatia-scan.yml +++ b/.github/workflows/hypatia-scan.yml @@ -20,6 +20,6 @@ permissions: jobs: scan: - uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@3c3acc19951b39c8ffe68b917aae4cc2e5b232e5 + uses: hyperpolymath/standards/.github/workflows/hypatia-scan-reusable.yml@469605210e767ee94d1c7a9c13cb6a1d0a78cad1 with: block-on-high: true diff --git a/.well-known/security.txt b/.well-known/security.txt new file mode 100644 index 0000000..08c7fcd --- /dev/null +++ b/.well-known/security.txt @@ -0,0 +1,4 @@ +Contact: https://github.com/hyperpolymath/my-lang/security/advisories/new +Expires: 2027-09-07T00:00:00Z +Preferred-Languages: en +Policy: https://github.com/hyperpolymath/my-lang/blob/main/SECURITY.md diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 0916c7b..72c1568 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -39,6 +39,14 @@ FINDINGS_FILE="${1:-}" BASELINE_FILE="${2:-}" MODE="${3:-advisory}" BLOCKING_THRESHOLD="${BLOCKING_THRESHOLD:-high}" +case "$MODE" in + advisory|blocking) ;; + *) echo "error: invalid baseline mode: $MODE" >&2; exit 2 ;; +esac +case "$BLOCKING_THRESHOLD" in + info|low|medium|high|critical) ;; + *) echo "error: invalid blocking threshold: $BLOCKING_THRESHOLD" >&2; exit 2 ;; +esac TODAY="$(date -u +%Y-%m-%d)" if [[ -z "$FINDINGS_FILE" || -z "$BASELINE_FILE" ]]; then @@ -152,6 +160,15 @@ EXPIRED_COUNT=$((EXPIRED_COUNT - ACTIVE_COUNT)) ANNOTATED="$(jq -n \ --argjson findings "$FINDINGS_JSON" \ --argjson baseline "$ACTIVE_BASELINE" ' + # Tokenise the two supported wildcards; every other character is literal. + # No sentinel substitution: a real filename may contain DOUBLESTAR. + def glob_regex: + [scan("\\*\\*|\\*|[^*]") + | if . == "**" then ".*" + elif . == "*" then "[^/]*" + elif inside(".\\+?^$()[]{}|") then "\\" + . + else . end] + | "\\A" + join("") + "\\z"; # Two captures are essential here: # `f as $finding` — without this, references like `f.file` inside the # select() get re-evaluated against the current baseline entry (the @@ -177,10 +194,7 @@ ANNOTATED="$(jq -n \ | $pat != null and ($finding.file | test( $pat - | gsub("\\*\\*"; "DOUBLESTAR") - | gsub("\\*"; "[^/]*") - | gsub("DOUBLESTAR"; ".*") - | "^" + . + "$" + | glob_regex )) ) ) From 2c01b717ad29cbf75d2ac46178fa65330c5d8504 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:41:28 +0000 Subject: [PATCH 06/13] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`a?= =?UTF-8?q?udit/language-safety-20260907`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @hyperpolymath. The following files were modified: * `scripts/apply-baseline.sh` These file types are not supported: * `.claude/CLAUDE.md` * `.github/workflows/cflite_batch.yml` * `.github/workflows/cflite_pr.yml` * `.github/workflows/codeql.yml` * `.github/workflows/governance.yml` * `.github/workflows/hypatia-scan.yml` * `.github/workflows/label-triage.yml` * `.github/workflows/labels.yml` * `.github/workflows/pages.yml` * `.github/workflows/push-email-notify.yml` * `.machine_readable/contractiles/Adjustfile.a2ml` * `.machine_readable/contractiles/Mustfile.a2ml` * `.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml` * `.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml` * `.machine_readable/descriptiles/0-AI-MANIFEST.a2ml` * `.machine_readable/descriptiles/AGENTIC.a2ml` * `.machine_readable/descriptiles/ECOSYSTEM.a2ml` * `.machine_readable/descriptiles/META.a2ml` * `.machine_readable/descriptiles/NEUROSYM.a2ml` * `.machine_readable/descriptiles/PLAYBOOK.a2ml` * `.machine_readable/descriptiles/README.adoc` * `.machine_readable/descriptiles/STATE.a2ml` * `.well-known/security.txt` * `CHANGELOG.adoc` * `DEBT.adoc` * `Justfile` * `README.adoc` * `ROADMAP.adoc` * `SECURITY.md` * `docs/proof-debt.md` * `docs/wiki/README.md` * `docs/wiki/internals/formal-verification.md` * `docs/wiki/roadmap/compiler.md` * `docs/wiki/roadmap/language.md` * `docs/wiki/roadmap/overview.md` * `docs/wiki/roadmap/tooling.md` * `playground/.machine_readable/6a2/PLAYBOOK.a2ml` * `spec/FRG-PROFILE.adoc` From b430b14c623f3722231739971651f961efc176cd Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 20:06:32 +0100 Subject: [PATCH 07/13] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`a?= =?UTF-8?q?udit/language-safety-20260907`=20(#184)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @hyperpolymath. * https://github.com/hyperpolymath/my-lang/pull/182#issuecomment-5564263936 The following files were modified: * `scripts/apply-baseline.sh`
These file types are not supported * `.claude/CLAUDE.md` * `.github/workflows/cflite_batch.yml` * `.github/workflows/cflite_pr.yml` * `.github/workflows/codeql.yml` * `.github/workflows/governance.yml` * `.github/workflows/hypatia-scan.yml` * `.github/workflows/label-triage.yml` * `.github/workflows/labels.yml` * `.github/workflows/pages.yml` * `.github/workflows/push-email-notify.yml` * `.machine_readable/contractiles/Adjustfile.a2ml` * `.machine_readable/contractiles/Mustfile.a2ml` * `.machine_readable/contractiles/dust/detach-echo-types-plugin.a2ml` * `.machine_readable/contractiles/dust/uninstall-coq-toolchain.a2ml` * `.machine_readable/descriptiles/0-AI-MANIFEST.a2ml` * `.machine_readable/descriptiles/AGENTIC.a2ml` * `.machine_readable/descriptiles/ECOSYSTEM.a2ml` * `.machine_readable/descriptiles/META.a2ml` * `.machine_readable/descriptiles/NEUROSYM.a2ml` * `.machine_readable/descriptiles/PLAYBOOK.a2ml` * `.machine_readable/descriptiles/README.adoc` * `.machine_readable/descriptiles/STATE.a2ml` * `.well-known/security.txt` * `CHANGELOG.adoc` * `DEBT.adoc` * `Justfile` * `README.adoc` * `ROADMAP.adoc` * `SECURITY.md` * `docs/proof-debt.md` * `docs/wiki/README.md` * `docs/wiki/internals/formal-verification.md` * `docs/wiki/roadmap/compiler.md` * `docs/wiki/roadmap/language.md` * `docs/wiki/roadmap/overview.md` * `docs/wiki/roadmap/tooling.md` * `playground/.machine_readable/6a2/PLAYBOOK.a2ml` * `spec/FRG-PROFILE.adoc`
ℹ️ Note
CodeRabbit cannot perform edits on its own pull requests yet.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- scripts/apply-baseline.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 72c1568..17a90f3 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -228,7 +228,7 @@ ANNOTATED="$(jq -n \ KEPT="$(jq '[.[] | select(.baseline_status != "acknowledged")]' <<<"$ANNOTATED")" SUPPRESSED="$(jq '[.[] | select(.baseline_status == "acknowledged")]' <<<"$ANNOTATED")" -# Severity rank for blocking decision. +# rank assigns a numeric rank to a severity level for blocking decisions. rank() { case "$1" in critical) echo 5 ;; From 8fdf63928e940b7850a9e9507771d18b517701db Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 02:51:19 +0000 Subject: [PATCH 08/13] docs(baseline): clarify severity ranking behavior --- scripts/apply-baseline.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 17a90f3..407d92f 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -228,7 +228,8 @@ ANNOTATED="$(jq -n \ KEPT="$(jq '[.[] | select(.baseline_status != "acknowledged")]' <<<"$ANNOTATED")" SUPPRESSED="$(jq '[.[] | select(.baseline_status == "acknowledged")]' <<<"$ANNOTATED")" -# rank assigns a numeric rank to a severity level for blocking decisions. +# Print the numeric rank used to compare a severity with the blocking threshold. +# Unknown severities receive the lowest rank (zero). rank() { case "$1" in critical) echo 5 ;; From 2703fb1295141507e651a331dbc3168aa9af12ef Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 04:52:33 +0100 Subject: [PATCH 09/13] Clarify baseline glob and entry-matching documentation (#187) Refine inline documentation in `apply-baseline.sh` to explain glob-to-regex conversion and baseline-entry matching behavior more concisely. This is documentation-only and does not change runtime behavior. Validation was not run. [View coding task](https://app.coderabbit.ai/code/tasks/20942833-2154-5aeb-9d2c-074de20e1f64?source=coding_agent_github_pr_description) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- scripts/apply-baseline.sh | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 407d92f..46ed1a0 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -160,8 +160,9 @@ EXPIRED_COUNT=$((EXPIRED_COUNT - ACTIVE_COUNT)) ANNOTATED="$(jq -n \ --argjson findings "$FINDINGS_JSON" \ --argjson baseline "$ACTIVE_BASELINE" ' - # Tokenise the two supported wildcards; every other character is literal. - # No sentinel substitution: a real filename may contain DOUBLESTAR. + # Convert a glob pattern to an anchored regular expression. `*` matches + # within one path segment, while `**` can cross directory boundaries. + # All other characters are matched literally. def glob_regex: [scan("\\*\\*|\\*|[^*]") | if . == "**" then ".*" @@ -169,17 +170,9 @@ ANNOTATED="$(jq -n \ elif inside(".\\+?^$()[]{}|") then "\\" + . else . end] | "\\A" + join("") + "\\z"; - # Two captures are essential here: - # `f as $finding` — without this, references like `f.file` inside the - # select() get re-evaluated against the current baseline entry (the - # re-bound `.`), not the finding. Binding $finding once captures the - # finding before we enter the map(select()) over the baseline. - # - # `(.file_pattern? // null) as $pat` — inside `test(arg)` the dot - # rebinds to the input of test ($finding.file, a string), so - # referencing `.file_pattern` there would error with "Cannot index - # string". Capture the entry pattern first, then reference $pat - # inside the test() regex argument. + # Return the first active baseline entry whose severity, rule module, and type + # match a finding, and whose exact file path equals the finding file or whose + # file pattern matches it; return null if there is no match. def match_entry(f): f as $finding | $baseline From 3be18014411dab22769d92148105d74e3e95ca0a Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:29:56 +0000 Subject: [PATCH 10/13] fix(baseline): reject invalid finding severities --- scripts/apply-baseline.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 46ed1a0..871ff2e 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -73,6 +73,13 @@ echo "$FINDINGS_JSON" | jq -e 'type == "array"' >/dev/null || { echo "error: findings JSON is not an array" >&2 exit 2 } +echo "$FINDINGS_JSON" | jq -e ' + all(.[]; .severity == "critical" or .severity == "high" or .severity == "medium" + or .severity == "low" or .severity == "info" or .severity == "advisory") +' >/dev/null || { + echo "error: findings JSON contains an invalid severity" >&2 + exit 2 +} echo "$BASELINE_JSON" | jq -e 'type == "array"' >/dev/null || { echo "error: baseline JSON is not an array" >&2 exit 2 @@ -221,8 +228,7 @@ ANNOTATED="$(jq -n \ KEPT="$(jq '[.[] | select(.baseline_status != "acknowledged")]' <<<"$ANNOTATED")" SUPPRESSED="$(jq '[.[] | select(.baseline_status == "acknowledged")]' <<<"$ANNOTATED")" -# Print the numeric rank used to compare a severity with the blocking threshold. -# Unknown severities receive the lowest rank (zero). +# Print the numeric rank used to compare a validated severity with the blocking threshold. rank() { case "$1" in critical) echo 5 ;; @@ -231,7 +237,7 @@ rank() { low) echo 2 ;; info) echo 1 ;; advisory) echo 0 ;; - *) echo 0 ;; + *) exit 2 ;; esac } From db90895e03d91cf5ba9db8717983e8f184e444a4 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:16:38 +0000 Subject: [PATCH 11/13] docs(baseline): document rank failure for invalid severities --- scripts/apply-baseline.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 871ff2e..471079f 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -228,7 +228,8 @@ ANNOTATED="$(jq -n \ KEPT="$(jq '[.[] | select(.baseline_status != "acknowledged")]' <<<"$ANNOTATED")" SUPPRESSED="$(jq '[.[] | select(.baseline_status == "acknowledged")]' <<<"$ANNOTATED")" -# Print the numeric rank used to compare a validated severity with the blocking threshold. +# Print the numeric rank used to compare a validated severity with the blocking +# threshold. Exit with status 2 if called with any other value. rank() { case "$1" in critical) echo 5 ;; From 84b1213c8d525966917024c0fa277a06e438c439 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:50:41 +0000 Subject: [PATCH 12/13] Generate docstrings for PR #182 --- scripts/apply-baseline.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 471079f..2529245 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -87,8 +87,10 @@ echo "$BASELINE_JSON" | jq -e 'type == "array"' >/dev/null || { # Structural validation against the baseline schema (see header). SCHEMA_ERRORS="$(jq -r ' + # Return every key permitted in a baseline entry. def known: ["severity","rule_module","type","file","file_pattern", "severity_override","expires_at","note","tracking_issue"]; + # Return the values permitted in the `severity` field of a baseline entry. def sevs: ["critical","high","medium","low","info"]; [ to_entries[] | .key as $i | .value as $e | if ($e|type) != "object" then "entry[\($i)]: not an object" From 3ceeaa31fa44365a8ef4992f9ef840ceabcfb236 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 12:11:55 +0100 Subject: [PATCH 13/13] Reject unrecognized finding severities before baseline ranking (#188) Validate every finding severity against the supported critical, high, medium, low, info, and advisory values before applying the baseline. Report unique invalid values and exit with an error so unknown severities cannot silently receive an incorrect rank. Validation was not run. [View coding task](https://app.coderabbit.ai/code/tasks/13de6bd8-8749-4174-9d1d-feff6708c4b9?source=coding_agent_github_pr_description) Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com> --- scripts/apply-baseline.sh | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/apply-baseline.sh b/scripts/apply-baseline.sh index 2529245..d6baa55 100644 --- a/scripts/apply-baseline.sh +++ b/scripts/apply-baseline.sh @@ -73,13 +73,17 @@ echo "$FINDINGS_JSON" | jq -e 'type == "array"' >/dev/null || { echo "error: findings JSON is not an array" >&2 exit 2 } -echo "$FINDINGS_JSON" | jq -e ' - all(.[]; .severity == "critical" or .severity == "high" or .severity == "medium" - or .severity == "low" or .severity == "info" or .severity == "advisory") -' >/dev/null || { - echo "error: findings JSON contains an invalid severity" >&2 +INVALID_FINDING_SEVERITIES="$(jq -r ' + [ .[] | (try .severity catch null) + | select(. as $severity | ["critical", "high", "medium", "low", "info", "advisory"] | index($severity) | not) ] + | unique + | .[] | @json +' <<<"$FINDINGS_JSON")" +if [[ -n "$INVALID_FINDING_SEVERITIES" ]]; then + echo "error: findings contain unrecognized severity values:" >&2 + echo "$INVALID_FINDING_SEVERITIES" >&2 exit 2 -} +fi echo "$BASELINE_JSON" | jq -e 'type == "array"' >/dev/null || { echo "error: baseline JSON is not an array" >&2 exit 2