open-standards/.github/workflows/standards-build.yml
Transaction Science 6b03da3883
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
ci: install z3 for the two workspaces that need a solver
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]>
2026-08-26 11:53:15 -04:00

126 lines
6.7 KiB
YAML

name: standards workspaces build + test
# Build gate for every Rust workspace in the repo.
#
# It started as three. Then a toolchain bump 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
# broken by the same handful of upstream migrations (hmac -> KeyInit, reqwest
# feature-gating, cipher 0.4 -> 0.5, a struct gaining fields), and all invisible
# because nothing ever compiled them. Partial coverage is how that happens, so
# the matrix now covers everything.
#
# The original case, still the clearest: smart-byte-rs had never been compiled by
# anything, and it did not build. A single wrong `rand` pin — 0.10 against code
# written for 0.8, whose crypto stack requires rand_core 0.6 — silently disabled
# the entire identity pillar, BBS+ included. `cargo check` would have caught it
# on day one. An unbuilt standard is not a standard, so this workflow is the
# floor under every claim the specs make.
#
# One workflow with a matrix rather than sixteen files: the bootstrap step is
# identical everywhere, and a shared dependency change should rebuild all of
# them anyway. `fail-fast: false` so one red workspace does not mask the others.
on:
push:
branches: [main]
pull_request:
# Deliberately NO `paths:` filter.
#
# The first attempt used `**/*.rs` and `**/Cargo.toml`, and the workflow then
# silently did not fire — pushes touching exactly those files triggered other
# workflows but not this one, so `**`-prefixed globs evidently do not match here
# the way they do on GitHub. A build gate that quietly fails to run is worse than
# no gate at all: it reports nothing and everyone assumes green.
#
# This is the repo-wide floor, so it runs on every push and every PR. The cost is
# CI minutes on doc-only changes. The alternative cost is what this branch spent
# a day fixing — five workspaces silently broken because nothing compiled them.
jobs:
build:
name: ${{ matrix.name }}
# Spread across the fleet's runners rather than pinning every job to `linux`.
# These are pure-Rust builds with no platform-specific behaviour, so the
# runner is a capacity choice, not a correctness one — and 16 jobs on a
# single runner queue behind whatever else is using it.
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { name: jcp-rs, dir: jcp/jcp-rs, runner: linux }
- { name: sandbox-rs, dir: sandbox/sandbox-rs, runner: linux }
- { name: smart-byte-rs, dir: smart-byte/smart-byte-rs, runner: linux }
- { name: openpay, dir: openpay, runner: linux-arm64 }
- { name: joule-code-rs, dir: joule-code/joule-code-rs, runner: linux-arm64 }
- { name: map-rs, dir: map/map-rs, runner: linux-arm64 }
- { name: aac-rs, dir: aac/aac-rs, runner: linux-arm64 }
- { name: joulecontract-rs, dir: joulecontract/joulecontract-rs, runner: linux-arm64, z3: true }
- { name: jouledesk-rs, dir: jouledesk/jouledesk-rs, runner: macos }
- { name: arl-rs, dir: arl/arl-rs, runner: macos }
- { name: sense-rs, dir: sense/sense-rs, runner: macos }
- { name: proof-rs, dir: proof/proof-rs, runner: linux, z3: true }
- { name: joulehook-rs, dir: joulehook/joulehook-rs, runner: macos }
- { name: eoc-rs, dir: eoc/eoc-rs, runner: linux }
- { name: mesh-rs, dir: mesh/mesh-rs, runner: linux-arm64 }
- { name: joule-ui-rs, dir: joule-ui/joule-ui-rs, runner: macos }
steps:
- uses: actions/checkout@v5
# Two workspaces shell out to `z3`, and the runner image has no solver.
# Without one, `joulecontract-proof`'s z3 test takes its solver-absent
# branch — which asserts the ladder returns Unproved, "never a fake pass",
# and fails, because the ladder actually escalates past its two real rungs
# to a model STAND-IN that reports Proved. That is a genuine defect in the
# proof standard and is NOT fixed here: the stand-ins are load-bearing in
# proof-cascade and proof-conformance, which has a published vector pack,
# so changing whether a stand-in may close a goal is a deliberate decision
# for that standard's owner. Installing the solver lets CI exercise the
# intended path; it does not make the fallback correct.
# Both z3 jobs are pinned to Linux runners deliberately: the macOS runner is
# a host executor with no apt. `sudo` may or may not exist depending on
# whether the container runs as root, so fall back to a bare invocation.
- name: Install z3
if: matrix.z3
shell: bash
run: |
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq z3
z3 --version
# The docker runner image ships no Rust at all, so rustup is bootstrapped
# here. dtolnay/rust-toolchain cannot be used: it shells out to `rustup`,
# which the image lacks. Harmless where cargo already exists.
- name: Install Rust (workspace pin)
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Cache cargo registry + target
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
${{ matrix.dir }}/target
key: standards-${{ matrix.name }}-${{ hashFiles(format('{0}/Cargo.lock', matrix.dir), 'rust-toolchain.toml') }}
restore-keys: |
standards-${{ matrix.name }}-
# --all-targets is load-bearing: a plain `cargo check` does not build test
# targets, and smart-byte's dev-dependencies drifted independently of its
# normal ones (rand_chacha 0.10 against rand 0.8). The library compiled
# while the tests did not.
- name: Check (all targets)
working-directory: ${{ matrix.dir }}
run: cargo check --workspace --all-targets
- name: Test
working-directory: ${{ matrix.dir }}
run: cargo test --workspace