All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 9s
standards workspaces build + test / arl-rs (arl/arl-rs, arl-rs, linux) (pull_request) Successful in 30s
standards workspaces build + test / joulespec-proofs (joulespec/joulespec-rs, joulespec-proofs, true, macos) (pull_request) Successful in 1m0s
standards workspaces build + test / eoc-rs (eoc/eoc-rs, -p eoc-meter --features cuda, eoc-rs, linux) (pull_request) Successful in 1m3s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 31s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m18s
standards workspaces build + test / pool-rs (pool/pool-rs, pool-rs, linux) (pull_request) Successful in 29s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m48s
standards workspaces build + test / proof-rs (proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 47s
standards workspaces build + test / sense-rs (sense/sense-rs, sense-rs, linux) (pull_request) Successful in 31s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m45s
standards workspaces build + test / joulespec-rs (true, joulespec/joulespec-rs, true, joulespec-rs, linux) (pull_request) Successful in 1m25s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 4m24s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, -p sandbox-tee --features amd-kds,intel-pcs, sandbox-rs, linux) (pull_request) Successful in 3m28s
standards workspaces build + test / smart-byte-rs (smart-byte/smart-byte-rs, smart-byte-rs, linux) (pull_request) Successful in 4m17s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 10m44s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 4m13s
standards workspaces build + test / aac-rs (aac-conformance, aac/aac-rs, aac-rs, linux-arm64) (pull_request) Successful in 3m53s
standards workspaces build + test / joulecontract-rs (joulecontract/joulecontract-rs, joulecontract-rs, linux-arm64, true) (pull_request) Successful in 1m9s
standards workspaces build + test / map-rs (map-conformance, map/map-rs, map-rs, linux-arm64) (pull_request) Successful in 1m25s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 1m9s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m10s
standards workspaces build + test / openpay (openpay, openpay, linux-arm64) (pull_request) Successful in 3m48s
Two things asked for: a benchmark corpus, and a second verification method. ## The corpus The wire vectors certify that an implementation round-trips a receipt's bytes. They say nothing about whether it reached the right verdict, because they carry one scenario. `conformance/v1/evaluation/` is the other half: ten cases, each a complete set of evaluation inputs plus the verdict §3 requires, chosen so a plausible but generous implementation disagrees — a mean where a minimum is required, an unevidenced obligation skipped rather than emptying the grade, `E3` on a killed counter-artifact whose anchor is unstated, `E4` because a prover succeeded, a witness for a clause's previous wording discarded instead of flagged, a `reviewed` label taken at face value when the reviewer is the clause's own author. Each case states its direction. Most catch over-grading; one catches under-grading, and that one is load-bearing: an implementation that graded nothing at all would pass every over-grading case, so a corpus with one direction rewards a rule that refuses everything. A test asserts the shape of the set rather than trusting it was built as described. The expectations are written by hand from §3 and are never read back out of this implementation — a corpus whose expectations are whatever the code produced certifies agreement with itself. That earned its keep immediately: seven of the ten were wrong on first authoring, all the same mistake and mine rather than the evaluator's. They assumed the attestation axis came from who signed a witness, where §2.8 computes it from who authored the work; with no work declared it is absent. The fix was not to copy the observed value in, which would have buried the misunderstanding, but to declare work in every case so the axis is exercised at all. ## What a second method bought, and what it did not The quotient-bound statement abandoned in the previous commit was retried under a solver reasoning with a bitvector theory rather than bit-blasting to a propositional problem. It settled four of the statement's conditions in about eight seconds — where the default engine had shown no per-property progress in twenty-four minutes — and then spent over fifty minutes on the fifth. So the method moved the wall without removing it, and §8 now says that instead of implying a solver choice would fix it. The harness is kept as the reproducible record of a negative result, behind a `cfg` nobody sets so an ordinary run does not hang on it. A second finding from the same runs, recorded in `conformance/v1/README.md`: a wall-clock wrapper around a prover is not enough. Both abandoned runs outlived the `timeout` meant to bound them, because the prover is a driver that spawns the checker and a timeout reaches only the driver. The producer kills the process group, which is why its budget works where the shell's did not — the design was right for a reason that has now been observed twice. Co-Authored-By: Claude Opus 5 <[email protected]>
185 lines
9.5 KiB
Markdown
185 lines
9.5 KiB
Markdown
# JouleSpec conformance — `v1`
|
|
|
|
Two packs live here. They answer different questions and only one of them is
|
|
reproducible, which is the first thing to know about them.
|
|
|
|
## `vectors/` — the certifiable surface
|
|
|
|
Fixed keys, fixed clauses, fixed witnesses and **fixed energy**, producing
|
|
receipt bytes that must not change without a version bump. This is the pack the
|
|
charter's conformance test refers to: an implementation certifies itself by
|
|
round-tripping these files.
|
|
|
|
The witness set carries one of every rung the format can express — `cited`,
|
|
`exercised`, `falsifiable`, `proved` — plus a witness bound to an earlier
|
|
artifact state, so a verifier that mishandles staleness fails the pack rather
|
|
than passing it quietly. A pack that exercised one rung would certify one rung,
|
|
and a test asserts the coverage.
|
|
|
|
The verdict these bytes assert is worth reading, because it is the doctrine in
|
|
miniature: two obligations are well evidenced, one carries only the
|
|
implementer's citation, and the specification's grade is therefore **`E0`**.
|
|
The attestation is `A0` for the same reason — the only surviving witness on
|
|
that clause is the implementer's own. One clause is a non-goal with no
|
|
evidence, which is correct and carries no grade, and a quarter of the declared
|
|
work energy cites no clause at all.
|
|
|
|
Regenerate with:
|
|
|
|
```
|
|
JOULESPEC_GEN_VECTORS=1 cargo test -p joulespec-core --test vectors
|
|
```
|
|
|
|
Without that variable the test asserts the committed bytes, so a change to the
|
|
wire format fails in CI rather than shipping.
|
|
|
|
## `evaluation/` — the verdicts, not the bytes
|
|
|
|
The vectors certify that an implementation round-trips a receipt's **bytes**.
|
|
They say nothing about whether it reaches the right **verdict**, because they
|
|
carry one scenario. [`evaluation/`](evaluation) is the other half: cases whose
|
|
correct answer a too-generous implementation gets wrong, each with the inputs
|
|
to evaluate and the verdict §3 requires. Its
|
|
[README](evaluation/README.md) says what each trap is and why the expectations
|
|
are written by hand rather than read back out of this implementation — a
|
|
distinction that caught seven authoring errors of mine while it was being
|
|
built.
|
|
|
|
## The self-conformance record
|
|
|
|
`spec.json`, `witnesses.json`, `state.json`, `receipt.cbor` and `receipt.json`
|
|
in this directory are **not** vectors. They are the output of running the
|
|
reference producer against the reference implementation:
|
|
|
|
```
|
|
joulespec harvest --manifest conformance/v1/harvest.toml \
|
|
--out conformance/v1 --require-grade E3
|
|
```
|
|
|
|
The clauses are the conformance items of [`SPEC.md`](../../SPEC.md) §7, read
|
|
from the published document rather than copied into the manifest — so the
|
|
manifest cannot drift from the specification. Reword an item and its obligation
|
|
address moves, and every witness bound to the old wording stops applying.
|
|
|
|
Each obligation is mapped to a check in `joulespec-rs`, and each mapping
|
|
declares a **counter-artifact**: a one-occurrence edit that should make that
|
|
check fail. The harvester applies it, runs the check, requires a *failure*,
|
|
and reverts. Only then does the witness reach `E3`.
|
|
|
|
### Proofs, beside the checks
|
|
|
|
Two obligations also carry a **proof**, discharged by a bit-precise model
|
|
checker over the whole input domain rather than at sampled points. A proof
|
|
entry is distinguished in the manifest by carrying a `formalization` — the
|
|
binding from clause prose to formal statement — because §2.6 forbids a
|
|
producer formalizing a clause itself, and making the binding the thing that
|
|
selects the prover enforces that structurally rather than by a check someone
|
|
could forget.
|
|
|
|
The prover path refuses the same way the check path does, one rung up:
|
|
|
|
| Observed | Read as |
|
|
|---|---|
|
|
| verified, every declared cover satisfied | the statement holds over a non-empty domain |
|
|
| verified, a cover never reached | **a finding** — proved over a domain the harness's own assumptions emptied |
|
|
| a property violated | the refutation a counter-artifact is applied to obtain |
|
|
| undecided, or killed by the budget | **a finding** — neither verdict, and never credited as either |
|
|
|
|
The second row is why the producer parses the property table instead of the
|
|
verdict line. A model checker reports success for an over-constrained harness
|
|
in the same words it uses for one that examined everything, so a gate reading
|
|
the verdict alone passes vacuous proofs. The fourth row is why each harness
|
|
carries a wall-clock budget: a solver asked a question it cannot settle does
|
|
not say so, it keeps going.
|
|
|
|
Both proofs sit at **`E2`, not `E4`**, and the report says so in those words.
|
|
Their statements were refuted against a counter-artifact, so the vacuity axis
|
|
is satisfied; what is missing is an independently cross-checked formalization.
|
|
Nobody but the author has confirmed that either statement says what its clause
|
|
says, and §2.6 caps that at `E2`. The rung is reachable by this producer — it
|
|
needs a second party, not more code.
|
|
|
|
### What the proofs cost, and what they caught
|
|
|
|
The reason the ladder has a rung above `E3` is visible here as a measurement
|
|
rather than an argument. The counter-artifact on C7 narrows the ratio rule's
|
|
arithmetic from 128 to 64 bits, where a large input overflows the
|
|
parts-per-million scale:
|
|
|
|
- the **entire test suite passes** under that mutation — 85 tests, none of
|
|
which reaches an input above roughly `u64::MAX / 1_000_000`;
|
|
- the **prover refutes it** in a fraction of a second.
|
|
|
|
That is `E3` and `E4` disagreeing on our own code, in the direction the ladder
|
|
predicts.
|
|
|
|
The cost is not uniform, and that matters more for budgeting than it might
|
|
seem. The same function, the same input domain and the same solver gave:
|
|
|
|
- **the statement that its arithmetic is total** — no overflow, no division by
|
|
zero — discharged in under a tenth of a second;
|
|
- **the statement that its quotient is bounded by the scale** — which requires
|
|
reasoning about the output bits of a 128-bit division — *did not converge*
|
|
in twenty-four minutes.
|
|
|
|
Naming a solver that reasons with a bitvector theory instead of bit-blasting
|
|
moved that wall without removing it: it settled four of the statement's
|
|
conditions in about eight seconds and then spent over fifty minutes on the
|
|
fifth. The harness is kept, behind a `cfg` nobody sets so an ordinary run does
|
|
not hang on it, as the reproducible record of a negative result.
|
|
|
|
Only the first is claimed. The second is named in the harness's own
|
|
documentation as deliberately unstated, because a harness that quietly
|
|
narrowed its domain until it converged would report exactly the same success
|
|
over a much smaller claim. The lesson for an operator is that the top rung's
|
|
affordability is a property of the statement and of the method together,
|
|
neither of which the ladder mentions — which is why the budget is declared per
|
|
harness and not once for a workspace.
|
|
|
|
A second lesson, from the same run: a wall-clock wrapper around the prover is
|
|
not enough. Both abandoned runs outlived the `timeout` that was supposed to
|
|
bound them, because the prover is a driver that spawns the checker and a
|
|
timeout reaches only the driver. The producer kills the **process group**,
|
|
which is why its budget works where the shell's did not.
|
|
|
|
**These receipts are not reproducible, by construction.** Their energy figures
|
|
come from a wall clock, graded `Estimator`, because no meter is wired to this
|
|
harness yet. Re-running the harvest produces different microjoules and
|
|
therefore different receipt bytes. That is the honest behaviour of a measured
|
|
quantity and the reason the certifiable pack above holds energy fixed.
|
|
|
|
## What the harvest found
|
|
|
|
Running this against the implementation it describes did what the `E3` rung
|
|
exists to do, and found two things inspection had not:
|
|
|
|
1. **A check that could not see its subject.** One footprint test narrowed to a
|
|
single member, and on a one-element footprint `all` and `any` are the same
|
|
function — so the conjunction itself was never checked. Mutating `all` to
|
|
`any` left the test passing. A second test now covers it.
|
|
2. **Dead logic in the implementation.** `applies_at` guarded on the artifact
|
|
state having no enumerable parts, and that guard could not change a single
|
|
verdict: an `all` over a non-empty footprint against no parts is already
|
|
false. The guard looked like care. It is gone.
|
|
|
|
A third report was a mistake in the manifest rather than in the code — a
|
|
counter-artifact aimed at a branch its check never takes, which the harvester
|
|
correctly reported as a check that cannot see its subject. The distinction
|
|
between those two readings is the operator's to make, and the harvester
|
|
reports what it observed rather than guessing which it is.
|
|
|
|
A fourth finding came from extending this standard rather than from running
|
|
it. Extracting two rules into named functions — so a prover could be asked
|
|
about them — moved the text that two existing counter-artifacts were aimed at,
|
|
by one indentation level in one case. Both mutations silently stopped
|
|
describing any edit at all. The harvester refused to run, which is the correct
|
|
outcome but a late one, so it now validates every counter-artifact's anchor
|
|
**before** running anything. Tolerating a missing anchor would have been the
|
|
real failure: two clauses would have gone on looking falsifiably evidenced
|
|
while nothing was being mutated.
|
|
|
|
The harvester exits non-zero on a finding, so a pipeline can gate on it. CI
|
|
runs it on every change to this standard. Where no model checker is installed
|
|
the proof entries are reported as not run — an absence, not a pass — and the
|
|
clauses fall back to their check evidence. The prover's own output parsing is
|
|
covered by tests in CI regardless, including both traps above.
|