proof: z3 could be made to prove a false claim; meter solver subprocesses where they ran #213
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/meter-solver-subprocesses"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Soundness first: z3 could be made to prove a false claim
Reviewing this branch turned up a hole that predates it.
Resident session. proof-solvers' resident z3 session used a fixed end marker to find each answer. A goal containing that marker,
(echo "@@END@@"), shifted every later verdict by one, so a FALSE claim (x > 0for allx) came backProvedand was sealed.Four more holes with the same root:
(echo "unsat").Refutedwith a model.set-optionacross(reset).(exit)disabled it for every later goal.Fixed in
82b27962, its own commit:(check-sat)and a marker drawn fresh per script, and the answer is the line just before that marker.(errormakes the goal undecided.exit,includeand output-channel options.Proved, and the wedge test hung. The reviewer's reproduction now gives the false claimRefuted.Metering
Z3Server. It used to model each decision as wall time × 15 W. Each resident decision is now read off z3's own process tree with sandbox-meter'sTreeMeter.Z3Server::declared_self_contained, orPROOF_Z3_SELF_CONTAINED=1for proof-cli. Such a reading is sealedHwShunt, rounded up to whole µJ.proof-schema'sEnergyhas no coverage field, so a gapped reading is never sealed.z3onPATHcould be a wrapper forwarding to a container or a remote host. Such a wrapper read about 50× short and was sealed as a reading. The resolved absolute path of z3 is recorded with each account.resident_z3_ladder(self_contained: bool).Estimator, never a measured zero graded above the proof it reuses. Older cache files still load. SPEC §7 now says this.prove_local.prove_accelerator(Linux). The workload's actual run is spanned by the machine meter: RAPL and NVML, each only where live, labelled machine-wide. A zero GPU delta is no reading: power samples stand in, and with no samples the proof is refused.sample_secsis removed.Evidence
proc_pid_rusageoracle on the z3 pid, to the nanojoule. At the production settle bound, every decision read whole.Cpu308 J (RAPL,HwShunt) andGpu160 J (ModelBased, because NVML is implausible on that GPU), and the cell verified. The RAPL span equals the sysfs oracle (ratio 1.000).proof/conformance/v1.Not covered
🤖 Generated with Claude Code
The resident z3 tree tests (proof-solvers tests/z3_tree.rs) and the local engine tree tests (sandbox-proof) are gated to Apple Silicon macOS, and the matrix legs for proof-rs and sandbox-rs run on Linux, so they would run nowhere. The macOS energy job now runs both and greps the line each metered run prints ('z3 tree meter:', 'local engine tree:'): a missing z3 or a per-process counter that is not live prints another line and fails the step. Likewise the accelerator proof's RAPL path only runs on real counters: the jetson-hub hardware job now runs sandbox-proof's accelerator tests and fails unless the RAPL bracket line was printed, and triggers on sandbox-proof changes. Co-Authored-By: Claude Opus 5.5 <[email protected]>With positive evidence in the engine tree's reading that the engine used the GPU (Gpu { ns }: its clients' recorded time), prove_local still sealed the machine-wide meter's records, which on every Apple Silicon host checked are the estimator's single Cpu record for the run. SPEC 6.2 forbids exactly that: accelerator energy is neither folded into the Cpu record nor omitted. prove_accelerator refuses the analogous run (no GPU figure), and the doc called the fold acceptable ("the GPU's share included"). prove_local now refuses to seal, saying why, when the reading shows GPU time, a member holding a GPU client whose time is unknown, or in-process Neural Engine model memory (the Npu class, same rule), and the records to be sealed carry no record of that class. A GPU reader that could not read is no evidence; a machine meter with its own Gpu/Npu records (IOReport live) carries each class and is unaffected. Tested on synthetic reading shapes. A real run-to-completion Metal child was tried: its GPU client had lost its time by the stop walk in every run (only the Exited gap), so the doc now says the evidence is what the reading holds and is usually gone for an exited engine. The same doc said the span "holds the whole run of every process in the tree"; the suspended child already carries a little energy at the start walk (its creation), taken as the baseline. It now says the span holds the tree from the engine's first instruction to its exit. Co-Authored-By: Claude Opus 5.5 <[email protected]>