@@ -38,6 +38,11 @@ one deliberate `SPARK_Mode (Off)` are documented honestly under
3838
3939== SPARK contract coverage (`total-update/ada/dnfinition/src`)
4040
41+ WARNING: ⚠️ The matrix in this section is **FALSE and SUPERSEDED** — see
42+ <<verified-correction>>. It was written from a source read that never
43+ compiled and was never `gnatprove`-checked. Retained only to show what
44+ was claimed vs. what verification found.
45+
4146Contracts in SPARK live on the package *spec* (`.ads`), not the body
4247(`.adb`); body files carrying zero `Pre/Post` is correct, not theatre.
4348Spec-level coverage:
@@ -93,25 +98,81 @@ behaviour can destabilise the host. The proof-relevant surface, per
9398The Rust crates sit on the application side of this seam; they are never
9499the ABI/FFI boundary, satisfying §"Rust is never the ABI".
95100
96- [#honest-gaps]
97- == Honest gaps
98-
99- * *`backend_interface.ads` (OWED).* This is a pure abstract interface
100- (`type Package_Manager_Backend is interface;`, ~20 `is abstract`
101- primitives: `Install`, `Remove`, `Upgrade`, `Search`, …). It carries
102- no class-wide contracts, so `gnatprove` cannot propagate obligations
103- to the `backend_guix`/`backend_nix` implementations. Adding
104- `Pre'Class`/`Post'Class` to the safety-relevant primitives (notably
105- `Install`/`Remove`/`Upgrade` result states and `Is_Available`
106- preconditions) is the principal remaining SPARK proof obligation.
107- Tracked under `standards#124` / `#127`.
108- * *`plugin_registry.ads` (weak).* One contract only; strengthen
109- registration post-state. Lower priority than the interface.
110- * *`reversibility_types.ads` is deliberately `SPARK_Mode (Off)`.* The
111- in-file comment documents the reason (a record-component / type-name
112- clash on `Rollback_Result.Snapshot_ID`); SPARK is re-enabled once a
113- genuine proof obligation justifies resolving the clash. This is an
114- honest, documented deferral — explicitly *not* the "theatre" pattern.
101+ [#verified-correction]
102+ == ⚠️ Verified correction (standards#127, 2026-05-18) — supersedes the coverage matrix above
103+
104+ WARNING: An adversarial re-verification (gnat / gnatprove + 2-agent
105+ static SPARK-RM swarm, then dynamically spot-confirmed on `origin/main`)
106+ found that the "SPARK contract coverage" matrix and the "real,
107+ *non-theatrical* SPARK/Ada" claim earlier in this document are *false*.
108+ They were written from a source read that **never compiled and was never
109+ `gnatprove`-checked**. The original 2026-05-18 estate audit ("`SPARK_Mode
110+ On`, theatre") was *correct*; the PR#48 reframing was the inaccuracy.
111+ The whole `total-update/ada/dnfinition` SPARK story is *theatre*:
112+
113+ * *`backend_interface.ads` — never compiled; illegal SPARK.*
114+ `Transaction_Item.Package` used an Ada **reserved word** as a field
115+ name (no compiler accepts it). `Install`/`Remove`/`Upgrade`/
116+ `Upgrade_System`/`Autoremove` are *functions* with an `in out`
117+ controlling parameter — **illegal SPARK** (SPARK RM 4.5.2) — under
118+ `pragma SPARK_Mode (On)`. *This PR* fixes the reserved word (renamed
119+ `Pkg`, now compiles), honestly sets `SPARK_Mode (Off)` with rationale,
120+ and adds sound Ada 2022 `Pre'Class`/`Post'Class` on the SPARK-legal
121+ query ops + `plugin_registry` `Pre`s (runtime-checked; the spec for
122+ the OWED refactor).
123+ * *`snapshot_manager.adb:4` — `pragma SPARK_Mode (Off)`* over the entire
124+ safety-critical rollback body. gnatprove proves **nothing** about
125+ rollback. The body also *never compiled*: `:93` calls
126+ `Create_Btrfs_Snapshot`, first declared `:145`, no forward declaration
127+ (Ada visibility error). The headline `Rollback_To_Snapshot` `Post`
128+ rests on `reversibility_types.adb:26-32`
129+ `System_State_Matches_Snapshot` which is `pragma Unreferenced (ID);
130+ return True;` — a **hardcoded-`True` vacuous ghost oracle** — and is
131+ additionally fail-permissive (`or else Status in Failed |
132+ Requires_Reboot`). The "25 Strong" rating is false.
133+ * *`safety_boundary.adb:6` — `pragma SPARK_Mode (Off)`*; and
134+ `safety_boundary.ads:78-101` re-declares `Safe_Install`/`Safe_Remove`/
135+ `Safe_Upgrade`/… as *functions* with `in Out …'Class` (the same
136+ illegal-SPARK construct, *without* even the honesty escape). No
137+ privilege/scope/bound model exists anywhere; the only precondition is
138+ `Is_Valid (Token)` (recovery-point presence). The "15 Strong /
139+ privilege-containment" rating is false.
140+ * *`safety_invariant.ads` — legal SPARK but vacuous.* Contracts are
141+ definitional tautologies over `Ghost` state that the real (SPARK_Mode
142+ Off) enforcement path never updates; e.g. `Lemma_Recovery_Enables_
143+ Rollback` has `Post ≡ Pre` by definition. Proved-but-meaningless.
144+ * *`plugin_registry.ads`* is transitively non-SPARK (uses
145+ `Backend_Access` from the non-SPARK `backend_interface`); its `Pre`s
146+ (strengthened by this PR) cannot be `gnatprove`-discharged until the
147+ refactor below.
148+
149+ === What this PR genuinely delivers (no theatre, no fake green)
150+
151+ . Real bug fix: `backend_interface.ads` now compiles (reserved word).
152+ . Honest SPARK boundary on `backend_interface.ads` + documented OWED.
153+ . Sound Ada 2022 contracts (query-op `Pre'Class`/`Post'Class`,
154+ `Register_Backend` `Pre`, six `plugin_registry` non-empty-ID `Pre`s),
155+ runtime-enforced and serving as the spec for the SPARK refactor.
156+ . This verified, honest stance — replacing the false matrix.
157+
158+ === OWED — large genuine programme, tracked standards#127 (must NOT be faked)
159+
160+ . State-mutating `function` → `procedure (… ; Result : out …)` redesign
161+ across `backend_interface` + every backend (`backend_guix`,
162+ `backend_nix`) + `safety_boundary`, to make the modification path
163+ legal SPARK.
164+ . Bring `snapshot_manager.adb` / `safety_boundary.adb` into
165+ `SPARK_Mode (On)` (they are wholly `Off` today) and fix the
166+ `snapshot_manager.adb` elaboration-order error so it compiles.
167+ . Replace the `System_State_Matches_Snapshot` hardcoded-`True` ghost
168+ with a real state model; connect `safety_invariant` ghost state to the
169+ executing enforcement path so its lemmas are non-vacuous.
170+ . Only then can the safety-critical contracts be `gnatprove`-discharged.
171+
172+ NOTE: the `BUILD_MODE=spark` mode and `gnatprove` are real *tooling*, but
173+ no safety-critical body is analysed by them today. Do not cite ambientops
174+ as "formally verified" until the OWED programme lands.
175+
115176* *`.claude/CLAUDE.md` language drift.* Any stale ReScript/Tauri/Deno
116177 table is superseded by the estate policy and this stance doc; reconcile
117178 separately.
0 commit comments