Skip to content

ci(spark): SPARK Theatre Gate reusable workflow (#135)#141

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/spark-theatre-gate-135
May 19, 2026
Merged

ci(spark): SPARK Theatre Gate reusable workflow (#135)#141
hyperpolymath merged 1 commit into
mainfrom
feat/spark-theatre-gate-135

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

What

Adds .github/workflows/spark-theatre-gate.yml — the estate SPARK Theatre
Gate
, a reusable (workflow_call) anti-theatre lint that also self-runs on
standards.

Implements standards#135 ("standards CI lint: ... fail SPARK_Mode On
with zero contracts"), sub-issue of the proof-debt epic #124.

Rules

Per SPARK_Mode-On Ada unit, only when the repo shows no GNATprove evidence
(no workflow ref, no gnatprove build recipe, no gnatprove output artifact):

  • T1 — header proof-claim without prover (hard fail, always). A strong
    proof assertion (formally verified, SPARK Proof Level, (Gold), all preconditions and postconditions are verified, proving the invariant holds) in the file header banner. Header-scoped on purpose so an
    incidental phrase in a body comment (e.g. an enum-literal description) does
    not false-fire.
  • T2 — zero-contract SPARK_Mode (warn by default). SPARK_Mode (On) with
    no Pre/Post/Global/Depends/Contract_Cases. Emitted as a warning so
    the ~13 repos mid Ada/SPARK→Rust/SPARK migration are not broken on rollout;
    escalates to a hard failure when a caller passes
    enforce_zero_contract: true (the [Estate] standards CI lint: seam-less Rust + zero-contract SPARK_Mode #135 end-state).

Genuine SPARK repos (echidna, stapeln, …) pass — GNATprove evidence suppresses
both rules. The gate only bites a regression that re-introduces a hollow
"verified" claim.

Verification (local harness, mirrors the workflow scanner)

Target Result
standards self-run PASS
ambientops after the safety_boundary demotion PASS (T2 warn only, no T1)
ambientops with pre-demotion safety_boundary banner restored T1-FAIL (regression correctly caught)
ambientops/.../strategy_matrix.ads:53 enum comment "Formally verified" not flagged (header-scoping works)

Rollout

This PR lands the gate + self-test. Consumer adoption is a 3-line caller per
repo (the ambientops caller ships with the item-2 ambientops PR). T2→hard-fail
escalation is deferred per #135 until the migration tail clears.

Refs #124
Refs #135

Estate anti-theatre lint, sub-issue of the proof-debt epic. Per
SPARK_Mode-On Ada unit, with no repo-wide GNATprove evidence:

  T1 (hard fail): a strong proof assertion ("formally verified",
      "SPARK Proof Level", "(Gold)", "all preconditions and
      postconditions are verified", "proving the invariant holds") in
      the FILE HEADER BANNER. Header-scoped so an incidental phrase in a
      body comment (e.g. an enum-literal description) does not false-fire
      — verified against ambientops strategy_matrix.ads:53.

  T2 (warn; hard fail when enforce_zero_contract: true): SPARK_Mode (On)
      with zero Pre/Post/Global/Depends/Contract_Cases. Warning by
      default so the ~13 repos mid Ada/SPARK->Rust/SPARK migration are
      not broken on rollout; escalates to failure per #135 end-state.

Genuine SPARK repos pass: GNATprove evidence (CI ref / build recipe /
gnatprove output) suppresses both rules. Verified locally:

  * standards self-run            -> PASS
  * ambientops post-demotion      -> PASS (T2 warn only, no T1)
  * ambientops w/ pre-demotion
    safety_boundary banner        -> T1-FAIL (regression caught)

Reusable via workflow_call; also self-runs on push/PR to main.

Refs #124
Refs #135

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 101 issues detected

Severity Count
🔴 Critical 63
🟠 High 28
🟡 Medium 10

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Issue in quality.yml",
    "type": "missing_workflow",
    "file": "quality.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in security-policy.yml",
    "type": "missing_workflow",
    "file": "security-policy.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance-reusable.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Action hyperpolymath/standards/.github/workflows/governance-reusable.yml@main needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Python file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml-templates/state-scm-to-v2.py",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/a2ml/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/lol/test/vitest.config.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "TypeScript file detected -- banned language",
    "type": "banned_language_file",
    "file": "/home/runner/work/standards/standards/k9-svc/bindings/deno/mod.ts",
    "action": "flag",
    "rule_module": "cicd_rules",
    "severity": "critical"
  },
  {
    "reason": "believe_me undermines formal verification (1 occurrences, CWE-704)",
    "type": "believe_me",
    "file": "/home/runner/work/standards/standards/lol/src/abi/Locale.idr",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "critical"
  },
  {
    "reason": "Wildcard CORS -- restrict to specific origins or use env var (1 occurrences, CWE-942)",
    "type": "js_wildcard_cors",
    "file": "/home/runner/work/standards/standards/consent-aware-http/examples/reference-implementations/deno/aibdp_middleware.js",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 4620037 into main May 19, 2026
16 of 18 checks passed
@hyperpolymath hyperpolymath deleted the feat/spark-theatre-gate-135 branch May 19, 2026 15:12
hyperpolymath added a commit to hyperpolymath/ambientops that referenced this pull request May 19, 2026
…te (P0) (#51)

## What

Closes the **P0** of the estate Rust/SPARK audit
(`PROOF-DEBT-AND-RUST-SPARK-AUDIT-2026-05-18.adoc`): ambientops bannered
the
dnfinition reversibility subsystem as "formally verified" SPARK while
GNATprove was never wired in, the ghost/lemma bodies were stubbed to
`return True` / `null;`, **and the subsystem did not even compile** — so
the
proof claims were pure theatre.

## Honest demotion (no false proof claims remain)

| Unit | Change |
|---|---|
| `safety_boundary.ads/.adb` | banner `(formally verified)` →
`(runtime-enforced; NOT formally verified)`, `SPARK_Mode` → `Off`,
honest `PROOF STATUS` note, `Is_Valid` de-ghosted (real runtime fn),
obligation **O-SAFE-2** |
| `reversibility_types.ads` | `SPARK_Mode Off`, **O-REV-1..4**;
`Rollback_Result.Snapshot_ID`→`Target_Snapshot` (name-clash) |
| `reversibility_types.adb` | **deleted** — spec is types + expression
functions only |
| `snapshot_manager.ads/.adb` | `SPARK_Mode Off` + HONESTY NOTE;
consumer updated for the `Target_Snapshot` rename |
| `safety_invariant.ads/.adb` | `SPARK_Mode Off`, broken `Refined_State`
removed |

`PROOF-NEEDS.md` records **O-REV-1..4 / O-SAFE-1..2** as the
authoritative
UNPROVEN obligation list (Idris2 model).

## Build verification — now actually performed

The first revision could not `gprbuild` (project `with "ncurses"`, no
provider). Resolved by adding **`checkonly.gpr`**, a scoped
compile-check over
`reversibility/safety/backends/platform` that omits the unrelated,
unprovided
ncurses TUI dependency. Doing so exposed — and this PR fixes — **3 real
legality blockers that were the concrete reason the subsystem never
built**
(hence why the proof claims could be theatre at all):

1. `backend_interface.ads` — record field named `Package` (Ada reserved
   word). Hard legality error. Renamed → `Pkg` (unreferenced; local).
2. `safety_boundary.ads` — `Is_Valid` was `with Ghost` but called in
real
runtime checks: ghost-without-proof in executable code, also illegal
once
   `SPARK_Mode` is Off. Aspect removed.
3. `snapshot_manager.adb` — un-propagated fallout of the
`Rollback_Result.Snapshot_ID → Target_Snapshot` demotion rename. 5 refs
   fixed.

Result (`gprbuild -gnatc` via `checkonly.gpr`):

| Unit | Result |
|---|---|
| `safety_boundary.adb` | **compiles, 0 errors** |
| `safety_invariant.adb` | **compiles, 0 errors** |
| `reversibility_types.ads` | **compiles, 0 errors** |
| `snapshot_manager.adb` | only 3 residual errors — all pre-existing
undefined `Create_{Btrfs,ZFS,LVM}_Snapshot` stubs, unrelated to the
SPARK demotion (separate "never implemented" debt, out of P0 scope) |

The demotion is now **proven legal Ada, not merely asserted**.

## Regression guard

`.github/workflows/spark-proof-gate.yml` — self-contained SPARK Theatre
Gate
over `total-update/ada`: **T1** (header proof-claim, no prover)
hard-fails;
**T2** (zero-contract `SPARK_Mode`) warns during the migration tail.
Mirrors
the estate reusable gate (**hyperpolymath/standards#141**); collapses to
a
3-line `uses:` caller once that merges. Verified to PASS on the final
tree and
to catch the pre-demotion `safety_boundary` banner regression (T1).

Refs hyperpolymath/standards#124
Refs hyperpolymath/standards#127

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant