smart-byte: unbreak the build, and add CI for the three standards workspaces #58

Closed
dcharlot wants to merge 14 commits from ci-standards-workspaces into main
Owner

Closes the precondition that gates every claim in the enforcement-and-evidence work: the identity pillar did not build, and nothing could have told us.

What was found

smart-byte-rs — 47,106 LOC covering BBS+, KERI/ACDC, OID4VCI/VP, mDL, post-quantum signatures — failed cargo check at dependency resolution, before compiling a line. 9 of 22 crates built; 13 did not, including the entire credentials core.

No CI has ever built this workspace, and no local target/ existed. The failure was invisible by construction.

Root cause: one line

rand = "0.10" against code written for rand 0.8. The crypto stack here — ed25519-dalek 2, curve25519-dalek 4, bls12_381 0.8, bulletproofs 5 — all pin rand_core 0.6, which pairs with 0.8. Reverting the pin recovered eight crates on its own, with the original source unmodified. Two edits I made while chasing the 0.9 API were reverted once the correct pin proved them unnecessary.

Nothing was wrong with the cryptography. Seven lines of source changed across three files, all mechanical call-site adjustments; the remainder is manifests.

Result

  • cargo check --workspace --all-targets — clean
  • cargo test --workspace — 616 passing, 0 failing, 90 test binaries
  • BBS+ compiles and passes its vectors for the first time in this repository's history

jcp-rs (11.6s) and sandbox-rs (35+21+7+3 tests) were already healthy and are now gated too.

Two details worth reviewing

--all-targets is load-bearing. A plain cargo check --workspace does not build test targets, and smart-byte's dev-dependencies had drifted independently of its normal ones (rand_chacha 0.10 against rand 0.8). The library compiled while the tests did not. I only caught it by running the tests — that lesson is written into the workflow.

The pin direction is deliberate. I aligned the pin down to the code rather than migrating 41 import sites of cryptographic code up to a newer rand. If the intent was to modernise onto rand 0.10, that is a separate, deliberate piece of work — and it should be done with CI already in place, not before it.


🤖 Generated with Claude Code

Closes the precondition that gates every claim in the enforcement-and-evidence work: **the identity pillar did not build, and nothing could have told us.** ## What was found `smart-byte-rs` — 47,106 LOC covering BBS+, KERI/ACDC, OID4VCI/VP, mDL, post-quantum signatures — failed `cargo check` **at dependency resolution**, before compiling a line. 9 of 22 crates built; 13 did not, including the entire credentials core. No CI has ever built this workspace, and no local `target/` existed. The failure was invisible by construction. ## Root cause: one line `rand = "0.10"` against code written for **rand 0.8**. The crypto stack here — `ed25519-dalek 2`, `curve25519-dalek 4`, `bls12_381 0.8`, `bulletproofs 5` — all pin `rand_core 0.6`, which pairs with 0.8. Reverting the pin recovered eight crates on its own, **with the original source unmodified**. Two edits I made while chasing the 0.9 API were reverted once the correct pin proved them unnecessary. Nothing was wrong with the cryptography. Seven lines of source changed across three files, all mechanical call-site adjustments; the remainder is manifests. ## Result - `cargo check --workspace --all-targets` — clean - `cargo test --workspace` — **616 passing, 0 failing, 90 test binaries** - BBS+ compiles and passes its vectors for the first time in this repository's history `jcp-rs` (11.6s) and `sandbox-rs` (35+21+7+3 tests) were already healthy and are now gated too. ## Two details worth reviewing **`--all-targets` is load-bearing.** A plain `cargo check --workspace` does not build test targets, and smart-byte's dev-dependencies had drifted independently of its normal ones (`rand_chacha 0.10` against rand 0.8). The library compiled while the tests did not. I only caught it by running the tests — that lesson is written into the workflow. **The pin direction is deliberate.** I aligned the pin *down* to the code rather than migrating 41 import sites of cryptographic code *up* to a newer rand. If the intent was to modernise onto rand 0.10, that is a separate, deliberate piece of work — and it should be done with CI already in place, not before it. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The identity pillar did not build. Not "was untested" — `cargo check` failed
at dependency resolution, before a single line was compiled. That went
unnoticed because no CI has ever built this workspace and no target/ tree
existed locally. 9 of 22 crates compiled; 13 did not, including the whole
credentials core: vc, bbs, pq, mdl, acdc, keri-witness, oidc4vc, didcomm,
zk, edv.

Every failure was a dependency declaration that had drifted ahead of the
code. Nothing was wrong with the cryptography.

Root cause, and it is one line: rand = "0.10" against code written for 0.8.
The crypto stack here — ed25519-dalek 2, curve25519-dalek 4, bls12_381 0.8,
bulletproofs 5 — all pin rand_core 0.6, which pairs with rand 0.8. rand 0.9
removed OsRng's infallible RngCore impl; 0.10 removed RngCore from the root
and replaced OsRng with SysRng. Reverting the pin recovered eight crates on
its own and let the original source stand unmodified. Two edits made while
chasing the 0.9 API were reverted once the correct pin proved them
unnecessary.

The rest:
  - rand_core `alloc` (zk) and cbc `std` (nostr): features that do not exist
    in those crates. These blocked *resolution*, so nothing could build.
  - rand_chacha 0.10 -> 0.3 (bbs, zk): dev-dependencies drifted independently
    of normal ones. The library compiled while test targets did not — caught
    only by --all-targets.
  - smart-byte-mdl pinned its own rand = "0.10" and had been partly migrated
    to the 0.9 API. Realigned to the workspace pin, reverted to 0.8 idiom.
  - hmac 0.13 moved new_from_slice from Mac to KeyInit (edv, nostr).
  - reqwest query() is behind the "query" feature (atproto).
  - aes 0.9/cbc 0.2 pull cipher 0.5; code uses the cipher 0.4 API. Aligned
    to aes 0.8 / cbc 0.1.
  - secp256k1 0.31 takes from_byte_array by value, bundles its own rand.

Seven lines of source changed, all mechanical call-site adjustments. The
remainder is manifests.

Result: `cargo check --workspace --all-targets` clean, `cargo test
--workspace` green — 616 passing across 90 test binaries. BBS+, the only
unlinkable credential primitive in the tree, compiles and passes its vectors
for the first time in this repository's history.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ci: build + test the three standards workspaces
All checks were successful
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m19s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m10s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m51s
320c07f3ed
Until now none of jcp-rs, sandbox-rs or smart-byte-rs had CI. The preceding
commit shows what that costs: a single wrong version pin silently disabled
the entire identity pillar, and nothing could detect it because nothing ever
compiled it. `cargo check` would have caught it on day one.

One workflow with a matrix rather than three files — the bootstrap step is
identical, the builds are fast (~15s / ~60s / ~90s), and a shared dependency
change should rebuild all three anyway.

Two details that are load-bearing:

  - The docker runner image ships no Rust, so rustup is bootstrapped in the
    workflow. dtolnay/rust-toolchain cannot help: it shells out to `rustup`,
    which the image lacks.
  - `--all-targets` is not optional. A plain `cargo check --workspace` does
    not build test targets, and smart-byte's dev-dependencies had drifted
    independently of its normal ones. The library compiled while the tests
    did not; only --all-targets surfaced it.

An unbuilt standard is not a standard. This is the floor under every claim
these specs make.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
jcp-action-receipt: AR-1, the composition envelope
All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m17s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m3s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m34s
d3e1c2adda
Implements §5 step 1 of the Action Receipt blueprint: the envelope spec plus a
signed conformance vector pack.

## The gap this closes

Three receipt families ship today, each holding one quarter of what an audit
asks for, and none binds to the others:

  jcp-receipt     authority     grant chain, verdict, budget drawn
  sandbox-proof   environment   attestation, isolation tier, substrate
  JCR-1           work          input hash, measured joules, provenance
  (nothing)       effect        what changed, and whether it can be undone

So no single artifact answers "under what authority did this agent do that,
where did it run, what did it cost, and what did it change?" The encoding is
implemented six independent times across the tree — evidence the *encoding* is
portable, and that the *composition* was never specified. Two families already
gesture at the chain (the proof cell carries a receipt_id, the authority receipt
a payload_hash). The intent was there; the binding was not.

## Envelope, not replacement

AR-1 binds the three by content-id and supplies the fourth. Each family keeps
its own canonical encoding and signer; the envelope reaches into them and never
the reverse, so every existing verifier keeps working unchanged.

No new cryptography: canonical det-CBOR and the tagged COSE_Sign1 envelope are
reused verbatim from jcr1. The only primitive added is a canonical *decoder* —
jcr1 ships an encoder and none was needed downstream until now, and a verifier
needs to read a signed core back. It is the exact inverse of the encoder's
subset (maps, arrays, text, unsigned ints; no floats, bools, nulls, tags),
refuses non-canonical length encodings and trailing bytes, and is pinned to the
encoder by a round-trip property test. Taking a CBOR dependency instead would
have contradicted the crate's own claim.

## Refusal over record-keeping

A format that merely records claims is a log. Three shapes are refused at
verification, re-derived from the wire projection rather than a caller-supplied
struct, so a hand-forged receipt that signs correctly is still rejected:

  1. effect `irreversible` REQUIRES a plan receipt — binding the cascade's
     existing plan/commit split into the evidence.
  2. egress `none` REQUIRES zero bytes — the claim is falsified by its own
     byte count.
  3. egress `attested_enclave` REQUIRES a peer attestation. An unattested
     destination is `third_party` even when the operator believes it
     trustworthy. Trust is not an egress class.

Two further invariants are normative: `grounding` is carried verbatim and never
upgraded from software to hardware, and the three energy provenances never
collapse into one number.

## Conformance pack

7 positive and 3 negative vectors under jcp/conformance/v1/, signed with a
published fixture key so third parties can verify. The negatives are the
substance: each carries a *genuine* signature and must still be refused, so an
implementation that checks signatures and skips the structural rules passes the
positives and fails the pack. That is precisely the failure mode the pack
exists to catch. The emitter asserts both properties before writing, so an
unverifiable vector cannot be published.

tests/conformance.rs consumes the published JSON from disk — the same bytes a
third party downloads — and checks that re-derived receipt ids and canonical
cores match byte-for-byte.

AR-1 does not solve effect revocation; nothing does in general. It makes the
distinction machine-readable at the moment of action, which is the precondition
for reasoning about it afterwards.

20 tests in the crate; jcp-rs workspace green at 258.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ar-verify: the standalone Action Receipt verifier
All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m15s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m12s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m32s
0b29405ea0
Implements §5 step 5 of the blueprint — "the deliverable that creates demand."

A format nobody outside this tree can check is a convention. A format with a
verifier a third party can run is a standard. Everything ar-verify needs arrives
on the command line — an envelope, a public key, a steward — and it touches the
network never.

Two modes:

  ar-verify <envelope> --pubkey <hex> --steward <did>   one receipt
  ar-verify --pack <dir>                                a whole vector pack

## Reports each binding separately

"Invalid" is not a useful audit finding. The verifier prints one line per
checked property — signature, canonical core, profile, receipt id, then the four
bindings (authority / environment / work / effect) and the egress contract, then
each of the three structural rules by name. An auditor learns *which* claim
failed, and can quote it.

On the forged vector the output is the whole thesis in one line:

  FAIL  rule:irreversible-needs-plan
        REFUSED — irreversible effect with no plan receipt.
        The signature is valid; the receipt is not.

## Honest about its own limits

Every successful run prints, unprompted:

  note:bound-artifacts  content-ids bound but NOT resolved — run each family's
                        own verifier for a complete audit

AR-1 proves *which* authority receipt, attestation and work receipt were
referenced. It does not prove those artifacts are sound; that is their own
verifiers' job. A verifier that let a reader believe otherwise would be worse
than none.

## Verified against the published pack

  10 passed, 0 failed
  CONFORMANT — AR-1/basic. Positives verify; negatives are refused despite
  valid signatures.

Exit codes: 0 verified · 1 check failed · 2 bad usage — so it composes into
scripts and CI without parsing prose.

No argument-parsing dependency; hand-rolled, consistent with the workspace's
minimal-dependency posture. Accepts a hex text file or raw envelope bytes,
because an auditor should not have to know which form the sender chose.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ar: end-to-end proof on real hardware — 11.09 J, measured
All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m26s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m6s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m43s
96255f720b
Implements §5 step 6 of the blueprint. One agent action, under a real delegated
grant, with joules read off this host's own counters, sealed into an AR-1
receipt that the standalone verifier checks from the envelope alone.

Only the workload is a stand-in so the example runs anywhere. Everything around
it is the real machinery, and the run proves it rather than asserting it:

  1. grant issued, attenuated to read-only — amplification refused:
     "attenuation would amplify the parent: capability exceeds parent"
  2. decide() → allow, 9750000 µJ remaining on the delegated ceiling
  3. work metered — 11092178 µJ [HwShunt] over 0.35s via ioreport-energy-model
  4. sealed — receipt id 41f14e37953d2908c8fe80607ffc09c0abcf195301cdb5330a91d9
  5. verified from the envelope alone — 820 byte canonical core

Then, independently, through ar-verify with nothing but the envelope, a public
key and a steward:

  ok  binding:authority    grant cf97d7e7393a… · verdict allow · chain depth 2
  ok  binding:environment  tier S0 · grounding hardware · attestation 934fe83df573…
  ok  binding:work         11092178 µJ [HwShunt] · receipt c3308896143e…
  ok  binding:effect       class none
  ok  binding:egress       class none · 0 bytes
  VERIFIED — every binding and rule checked from the envelope alone.

Two honesty properties the example enforces on itself:

  - The tier is stamped from what is actually running. This is in-process with
    no isolation boundary crossed, so it is S0. The sandbox proof matrix already
    demonstrates S5 through S7 on real KVM and CC hardware; claiming S5 here
    without a microVM would be exactly the overreach the ladder exists to
    prevent.
  - The energy provenance is whatever the meter reports, carried verbatim. This
    host has IOReport, so HwShunt is real. On a host without a counter the
    example prints "provenance is Estimator, not HwShunt" rather than inventing
    a measurement.

Also asserts the negative case rather than describing it: a second attenuate()
asking for read+delete is required to fail, so the refusal is demonstrated in
the run instead of claimed in a comment.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ar: bind the real emitters, not placeholder ids
All checks were successful
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m19s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m15s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m40s
453280c328
Closes §5 step 3. The end-to-end example previously bound content-ids it made
up — ContentId::of_bytes(b"jcp-receipt/e2e-allow") and friends. That
demonstrated the envelope's shape while proving nothing about its bindings.

Now every id comes from an artifact that was actually produced:

  - The authority receipt is sealed from the decision that just happened via
    jcp_receipt::seal, and **verified on its own terms** before being bound. A
    receipt that would not survive its own family's verifier has no business in
    an AR-1 envelope.
  - The work receipt is built by sandbox_meter::Receipt::build over the devices
    the meter actually reported — three on this host (CPU, GPU, ANE). `build`
    enforces the provenance/measured coupling itself, so a mislabelled device is
    refused there rather than propagating into AR-1.

## The interop wrinkle worth recording

The two families disagree about content-id *presentation*:

    sandbox_schema::ContentId(pub String)     "b3:<base64url of 32 bytes>"
    jcp_schema::ContentId(pub [u8; 32])       raw digest

Both are BLAKE3 over the same canonical bytes, so they differ only in how they
render. Re-addressing the work receipt's canonical core with jcp's hasher yields
the identical digest — an exact binding, not a hash of a hash. A debug assertion
pins the sandbox rendering so the assumption fails loudly if it ever changes.

This is the kind of seam that only appears when two standards are actually
composed rather than described as composable, and it is why step 3 was worth
doing separately from step 6.

Run on this host:

  2. decide() → allow, 9750000 µJ remaining; authority receipt sealed +
     verified, id 3296ba365377
  3. work metered — 8075375 µJ [HwShunt] over 0.29s via ioreport-energy-model
     work receipt sealed over 3 metered device(s), id 44437820e66e
  5. verified from the envelope alone — 820 byte canonical core

  ar-verify:
    ok  binding:authority  grant cf97d7e7393a… · verdict allow · chain depth 2
    ok  binding:work       8075375 µJ [HwShunt] · receipt 44437820e66e…
    VERIFIED

Co-Authored-By: Claude Opus 4.8 <[email protected]>
cascade: the egress contract — per-resolution, and never stronger than evidence
All checks were successful
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 59s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m14s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m0s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m28s
95f1c00238
Closes §5 step 4, the last item in the blueprint's build sequence. This is the
gap the frontier survey filed as "nobody has shipped a privacy router": a system
that decides between on-device and remote execution and never tells the user
which side their request landed on.

## The design turns on the default

`Egress::Undeclared` is the default, and everything else follows from it. A tier
that has not declared where its work goes is recorded as undeclared — never as
"nothing left the device". Not knowing and knowing nothing happened are
different facts, and only the second is a privacy claim.

    Undeclared        no declaration; NOT a claim, and not publishable
    None              resolved on-device
    AttestedEnclave   left the device to a peer that attested itself
    ThirdParty        left the device unattested — named, counted, and
                      honestly marked unverifiable

`is_publishable()` refuses `Undeclared`, so a receipt cannot be built from a
resolution nobody measured. `Undeclared` and `None` both report zero bytes,
which is precisely why the class must be read rather than the byte count — a
test pins that.

## The runtime stamps it, not the tier

`Tier::egress()` is a defaulted trait method, matching the existing `coord()`
precedent so legacy tiers keep compiling. But the tier does not write the value
into its own `Answer`: the runtime reads the declaration and stamps it onto the
trace it returns. A tier therefore cannot forge the claim by construction, and
cannot silently omit it either.

Both dispatch paths needed the stamp on the *runtime's* trace rather than the
tier's, because both return `Answer { trace, ..answer }` — the spread discards
the tier's copy. That is exactly the sort of thing a test catches and a design
review does not; `a_local_cache_hit_is_recorded_as_local` failed on the first
attempt for this reason.

L0 is the one tier in the base cascade entitled to claim `None`: a hit is served
from this process's own memory.

## Placement

The record lives on `ExecutionTrace`, which already derives `Default` and has a
single literal construction site — so the change lands in 4 files and 201 lines
with no churn. Putting it on `Answer` would have required touching 12 struct
literals plus test files; an earlier attempt at that also tripped `cargo fmt`,
which reformatted 22 unrelated files because the crate was never rustfmt-clean.
Reverted, and the field moved to where it fits.

The dependency direction is preserved: the cascade gains its own egress concept
and takes no dependency on AR-1. Mapping `Egress` onto an Action Receipt's
egress binding is the envelope's job, as it should be.

108 tests green in jouleclaw-cascade.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Latest stable (1.98.0, released 2026-08-18). The pin lives in more places than
is obvious, and missing one means CI silently builds an older compiler than the
dev box:

  - rust-toolchain.toml at the repo root
  - eoc/eoc-rs/rust-toolchain.toml, a second toolchain file
  - five CI workflows that hardcode a version instead of deferring to the file
    (wai-conformance, wai-neural-e2e, wai-byte-equality,
    joule-code-conformance, jouleclaw-public-surface-documented)

standards-build.yml needed no change, because it reads the toolchain file
rather than pinning inline. That is the pattern the other five should adopt.

MSRV raised to 1.98 across 26 manifests, following the earlier decision to have
the declared floor track the pin rather than drift behind it. Note this is a
support-policy change, not a mechanical one: it narrows which compilers can
consume these standards as libraries.

The pin stays exact, never `stable` — a pin that drifts is not a pin.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Updating the toolchain surfaced five workspaces that did not build. Every one
was verified against its ORIGINAL pre-update lockfile and manifest before being
touched: all of them were already broken. None of this was caused by the
dependency update.

The same handful of upstream migrations account for nearly all of it:

  hmac 0.13 moved new_from_slice from Mac to KeyInit
    openpay: op-webhook, op-bnpl, op-ewallets-asia, op-mobile-wallets — plus
    the op-bnpl and op-ewallets-asia *test* targets, which a src-only search
    misses and `--all-targets` does not.

  reqwest 0.13 gates builder methods behind features
    eoc-tools needed "query"; openpay/op-tax needed "form".

  cipher 0.4 -> 0.5
    openpay/op-mobile-wallets declared aes 0.9 (cipher 0.5) while ctr 0.9 and
    aes-gcm 0.10 both sit on cipher 0.4. Aligned aes to 0.8.

  jcp-schema::Grant gained budget_funds and caveats
    mesh-core and joule-ui-interaction examples were never updated. A path
    dependency, so no lockfile change could have caused or fixed this.

Not one line of this is a behaviour change. Every fix is an import, a feature
flag, a version alignment, or two struct fields.

The finding is larger than the diff. smart-byte (47k LOC, fixed earlier today),
openpay (six separate breakages across five crates), eoc, mesh and joule-ui were
all silently broken, all by the same small set of migrations, all invisible
because nothing ever compiled them. The build gate added in this branch
currently covers three workspaces; on this evidence it should cover every one.

Verified after fixing: openpay 1935 tests pass, eoc/mesh/joule-ui build clean.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
deps: cargo update across 18 workspaces
Some checks failed
wai cross-architecture byte-equality / windows-x86_64 (pull_request) Successful in 23s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 40s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Failing after 1m3s
WAI conformance / cargo-class corpora · windows (pull_request) Successful in 1m13s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 1m8s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 1m57s
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 23s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 58s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / jcp-rs (pull_request) Failing after 12s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 39s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m1s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
2688e2b936
Lockfiles only — newest versions WITHIN the semver ranges the manifests already
declare. No manifest constraint was widened by this commit.

That distinction is load-bearing here. `cargo upgrade`, which rewrites manifests
to the latest major, is precisely what killed smart-byte: rand was pinned to
"0.10" against source written for 0.8, and the crypto stack it sits on
(ed25519-dalek, curve25519-dalek, bls12_381, bulletproofs) all require
rand_core 0.6 — so 0.8 is a ceiling those crates impose, not a preference.
Moving past it means waiting for that ecosystem or migrating 41 call sites of
cryptographic code, and neither belongs in a routine update.

Largest moves: smart-byte 207 packages, openpay 189, jouleclaw 182, eoc 164.

Verified on 1.98.0 with the updated lockfiles — 12 workspaces green:

  smart-byte 616   openpay 1935   joule-code 278   jcp 258   map 220
  sandbox 186      aac 89         joulecontract 82  arl 58    sense 38
  proof 31         joulehook 24

One pre-existing failure is deliberately NOT addressed here: jouledesk's
`the_joule_budget_is_enforced_across_tags` seals two decisions where the budget
permits one. It fails identically on the original lockfile, so it is not a
dependency problem — it is a budget-enforcement defect in the Joule Desk
standard, and a ceiling that seals a receipt for work it refused deserves its
own fix and its own commit rather than burial in a dependency sweep.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
jouledesk: the test was wrong, not the ledger — and gate every workspace
Some checks failed
WAI conformance / cargo-class corpora · windows (pull_request) Successful in 1m15s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 1m16s
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 22s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m49s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 7m55s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / arl-rs (pull_request) Has been cancelled
standards workspaces build + test / eoc-rs (pull_request) Has been cancelled
standards workspaces build + test / jcp-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-ui-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / joulehook-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / proof-rs (pull_request) Has been cancelled
standards workspaces build + test / sandbox-rs (pull_request) Has been cancelled
standards workspaces build + test / sense-rs (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
6bf70ef77e
Two changes, both consequences of the same sweep.

## jouledesk: correct the test, keep the behaviour

`the_joule_budget_is_enforced_across_tags` asserted one sealed decision and
found two. The code is right and the assertion was wrong.

Three doc comments say so: `TagOutcome` — "every variant sealed to the ledger";
its `Denied` variant — "outside the model, sealed all the same"; and `ledger()`
— "every sealed decision, in order". The sibling test draws the line exactly
where the design does: an *unheld capability* never reaches dispatch and leaves
the ledger empty, whereas a *budget refusal* is a decision made against a grant
the teammate actually held, stopped by the ceiling. That is evidence, and it
seals like any other decision.

So: one task ran (`spent_uj` = 100_000, unchanged) and two decisions were made
(ledger = 2). The test conflated "dispatched" with "sealed". Corrected, with the
distinction written down so it does not get re-broken — a refusal that left no
trace would defeat the point of enforcing outside the model.

No behaviour changed. 17 tests pass.

## Gate every workspace, not three

The matrix went from 3 to 16. It started at three because those were the
workspaces the Action Receipt depends on; then bumping the toolchain compiled
the rest for the first time and found five more that did not build — smart-byte
(47k LOC), openpay (six separate breakages across five crates), eoc, mesh and
joule-ui. All of them broken by the same handful of upstream migrations. All
invisible because nothing ever compiled them.

Partial coverage is precisely how that happens, so the path filter is now
`**/*.rs` and `**/Cargo.{toml,lock}` and the matrix covers everything.
`fail-fast: false` so one red workspace cannot mask the others.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ci: run the build gate unconditionally — the path filter was silently suppressing it
Some checks failed
WAI conformance / cargo-class corpora · windows (pull_request) Successful in 1m13s
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 23s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 1m24s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 1m39s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 4m32s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Has been cancelled
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Has been cancelled
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
standards workspaces build + test / aac-rs (pull_request) Has been cancelled
standards workspaces build + test / arl-rs (pull_request) Has been cancelled
standards workspaces build + test / eoc-rs (pull_request) Has been cancelled
standards workspaces build + test / jcp-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-code-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-ui-rs (pull_request) Has been cancelled
standards workspaces build + test / joulecontract-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / joulehook-rs (pull_request) Has been cancelled
standards workspaces build + test / map-rs (pull_request) Has been cancelled
standards workspaces build + test / mesh-rs (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
standards workspaces build + test / proof-rs (pull_request) Has been cancelled
standards workspaces build + test / sandbox-rs (pull_request) Has been cancelled
standards workspaces build + test / sense-rs (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
ebea6d7ffc
The expanded matrix never fired. Pushes touching `.rs` and `Cargo.toml` files
triggered the wai workflows (whose filters matched their own workflow file) but
not this one, whose filter was `**/*.rs` and `**/Cargo.{toml,lock}` — globs that
evidently do not match here the way they do on GitHub.

That is the worst possible failure mode for a build gate: it reports nothing,
and everyone reads the absence of red as green. This branch exists because five
workspaces were silently broken for want of anything compiling them; a gate that
silently declines to compile them is the same bug wearing a workflow file.

So: no `paths:` filter. It runs on every push and every PR. The cost is CI
minutes on doc-only changes, which is a rounding error against the cost of the
thing it prevents.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ci: spread the matrix across three runners
Some checks failed
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 22s
standards workspaces build + test / aac-rs (pull_request) Successful in 4m51s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Failing after 1m2s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 59s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 3m27s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m47s
standards workspaces build + test / joulecontract-rs (pull_request) Failing after 2m9s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m13s
standards workspaces build + test / map-rs (pull_request) Successful in 1m38s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m1s
standards workspaces build + test / mesh-rs (pull_request) Successful in 3m10s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m35s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 15s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 30s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 14s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Failing after 1m4s
standards workspaces build + test / openpay (pull_request) Successful in 8m2s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 20s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 42s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 40s
standards workspaces build + test / arl-rs (pull_request) Successful in 23m26s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 14m8s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 15m0s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 13m17s
standards workspaces build + test / proof-rs (pull_request) Successful in 13m46s
standards workspaces build + test / sense-rs (pull_request) Successful in 14m22s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 27s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 1m2s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 30s
41a1cd7042
Sixteen jobs were pinned to `runs-on: linux`, and the fleet has one linux
runner. The run was not failing to trigger — it was queued behind other work,
which the tasks API does not show (it lists tasks already picked up, so a queued
run looks like an absent one). Six runs were sitting in `waiting`.

These are pure-Rust builds with no platform-specific behaviour, so the runner is
a capacity choice rather than a correctness one: 4 on linux, 6 on linux-arm64,
6 on macos.

One trap worth recording: the matrix key was first written as `on:`, which YAML
parses as the boolean `true` — the same gotcha that makes a workflow's top-level
`on:` parse as `true` rather than a string key. `matrix.on` would have resolved
to nothing and every job would have had an empty `runs-on`. Renamed to `runner`.
A schema check caught it before it shipped, which is the only reason it is a
footnote instead of another silent non-firing gate.

The existing rustup bootstrap already covers all three: it installs on the
docker images that ship no Rust, and prepends ~/.cargo/bin on the macOS host
runner whose launchd PATH omits it.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
ci: install z3 for the two workspaces that need a solver
Some checks failed
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Failing after 1m4s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 50s
WAI conformance / cargo-class corpora · windows (pull_request) Successful in 1m18s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 57s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 22s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 45s
standards workspaces build + test / map-rs (pull_request) Successful in 33s
standards workspaces build + test / mesh-rs (pull_request) Successful in 30s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m48s
standards workspaces build + test / openpay (pull_request) Successful in 1m30s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m14s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 19s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 38s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 19s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m1s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m34s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 16s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 30s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 13s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Failing after 1m4s
standards workspaces build + test / arl-rs (pull_request) Successful in 16m0s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 11m35s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 11m23s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 11m3s
standards workspaces build + test / sense-rs (pull_request) Successful in 10m46s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 35s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 1m48s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 39s
6b03da3883
The first full matrix run surfaced a real defect, which this commit does NOT
fix — it only lets CI exercise the intended path.

`joulecontract-proof`'s `a_real_postcondition_discharges_through_z3` fails on a
runner because the image has no z3. The test is written to handle that: its
solver-absent branch asserts

    // no solver present: the SMT rung returns Unproved, never a fake pass
    assert!(matches!(entry.status, DischargeStatus::Unproved(_)));

and that assertion is what fails. Reproduced in the exact runner image
(catthehacker/ubuntu:act-22.04, arm64), the ladder returns:

    status Proved · closed_by Some(BigModel) · provenance Estimator
    attempts: Automation(false) → Smt(false) → SmallModel(false) → BigModel(TRUE)

`real_ladder()` is [Propositional, Z3Smt, SmallModel, FrontierModel]. The first
two are real; proof-solvers' own docs call the model rungs "honest stand-ins",
and FrontierModel returns `proved(goal)` unconditionally for its goal kind. So
with no solver installed, a stand-in closes the goal and reports Proved with 50 J
of estimated cost attached. The same module states the contract it breaks: "A
solver returns Proved only when a verifier would accept the artifact."

The test is right and the ladder does not honour it.

This is left unfixed on purpose. The stand-ins are load-bearing in proof-cascade
and proof-conformance, and proof-conformance ships a published vector pack —
changing whether a stand-in may close a goal would invalidate it. That is a
deliberate call for the proof standard's owner, not a side effect of a CI fix.

So: install z3 where it is needed, and record the defect where whoever picks it
up will find it. Both z3 jobs are pinned to Linux runners because the macOS
runner is a host executor with no apt; proof-rs moved from macos to linux for
that reason.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
dcharlot closed this pull request 2026-08-30 15:52:19 -04:00
Some checks failed
wai cross-architecture byte-equality / windows-x86_64 (pull_request) Successful in 27s
standards workspaces build + test / aac-rs (pull_request) Successful in 53s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Failing after 1m4s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 50s
WAI conformance / cargo-class corpora · windows (pull_request) Successful in 1m18s
jouleclaw public surface must stay documented / Public-surface audit (jouleclaw-rs) (pull_request) Successful in 57s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
WAI conformance / cross-arch byte-equality · windows (pull_request) Successful in 22s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 45s
standards workspaces build + test / map-rs (pull_request) Successful in 33s
standards workspaces build + test / mesh-rs (pull_request) Successful in 30s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m48s
standards workspaces build + test / openpay (pull_request) Successful in 1m30s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m14s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 19s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 38s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 19s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m1s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m34s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 16s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 30s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 13s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Failing after 1m4s
standards workspaces build + test / arl-rs (pull_request) Successful in 16m0s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 11m35s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 11m23s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 11m3s
standards workspaces build + test / sense-rs (pull_request) Successful in 10m46s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 35s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 1m48s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 39s

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!58
No description provided.