open-standards/.github/workflows/wai-quantum-contract.yml
Transaction Science 8e7bbaa30f
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 8s
standards workspaces build + test / macOS energy backends (pull_request) Has been skipped
wai-quantum contract / does this change touch it (pull_request) Successful in 6s
wai-quantum contract / the policy is linked, and the deprecations page reads (pull_request) Successful in 5s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m25s
wai-quantum contract / API compatibility · linux (pull_request) Successful in 4m8s
wai-quantum contract / schemas and the committed tool lists · linux (pull_request) Successful in 5m53s
wai-quantum-contract.yml: the baselines are the versions just published
wai-quantum 0.8.0, wai-quantum-cli 0.2.3 and wai-quantum-qpu 0.4.0 are on
crates.io, so the API is checked against them from here on.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-01 22:22:03 -05:00

311 lines
16 KiB
YAML

name: wai-quantum contract
# The version and deprecation contract (wai/wai-quantum/VERSIONING.md), on
# Linux:
#
# - api: cargo-semver-checks, built from crates.io at a pinned version,
# compares wai-quantum, wai-quantum-cli and wai-quantum-qpu with the last
# version of each on crates.io (the baselines below). It checks every change as if for a minor
# release, so that each breaking change is listed, and fails only on a
# breaking change made without a major bump. Before 1.0 the first non-zero
# component is the major (0.6.16 to 0.7.0 is a major bump). A step warns
# when crates.io holds a newer version than a baseline here, so a baseline
# does not go stale unseen.
# - schemas: the schema tests, each by name. The engine's: every schema file
# reads and names itself, every method's job, a set, a result's provenance,
# every error-correction answer, a mitigated job, every answer of the
# variational and algorithm library and every engine tool's
# answer follow their schemas with no member they do not name, and receipts issued
# before results named their engine and schema still verify, their digests
# pinned. Both MCP servers': every tool's answer follows its outputSchema,
# the committed tool lists (wai-quantum-cli/docs/local-mcp.json and
# service-mcp.json) are the live lists, the agent docs are what the binary
# generates, and initialize reports the versions. The job service's job in
# each status, a set's among them, and its receipt key set after a rotation;
# the command line's scheduler lease, its harness's report, corpus and token
# counts, and the course's progress file; the answer layer's documents, a
# correctness record, the views page's manifest, the course, its exercises
# and its checks. The provider protocol's messages and
# answers. Then a full
# JSON Schema implementation (wai/wai-quantum/ci/check_schemas.py) reads
# every schema file and both tool lists, and holds a release build's
# answers to them.
# - policy: every README of a WAI Quantum package links the policy, and the
# deprecations page's table is well formed.
#
# The receipts' legacy pins and the conformance corpora run where they always
# have (wai-energy-receipts.yml, wai-conformance.yml).
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
on:
push:
branches: [main]
paths:
- 'wai/wai-quantum/**'
- 'wai/wai-quantum-cli/**'
- 'wai/wai-quantum-service/**'
- 'wai/wai-quantum-qpu/**'
# The schema tests read the answer layer's conformance set and the harness's corpus.
- 'wai/quantum-conformance/answers/**'
- 'wai/quantum-conformance/eval/**'
- 'wai/wai-quantum-py/README.md'
- 'wai/wai-quantum-desktop/README.md'
- 'wai/quantum-studio/README.md'
- 'wai/tools/wai-quantum-editor/README.md'
- 'wai/tools/tree-sitter-openqasm/README.md'
- 'rust-toolchain.toml'
- '.github/workflows/wai-quantum-contract.yml'
pull_request:
paths:
- 'wai/wai-quantum/**'
- 'wai/wai-quantum-cli/**'
- 'wai/wai-quantum-service/**'
- 'wai/wai-quantum-qpu/**'
# The schema tests read the answer layer's conformance set and the harness's corpus.
- 'wai/quantum-conformance/answers/**'
- 'wai/quantum-conformance/eval/**'
- 'wai/wai-quantum-py/README.md'
- 'wai/wai-quantum-desktop/README.md'
- 'wai/quantum-studio/README.md'
- 'wai/tools/wai-quantum-editor/README.md'
- 'wai/tools/tree-sitter-openqasm/README.md'
- 'rust-toolchain.toml'
- '.github/workflows/wai-quantum-contract.yml'
jobs:
# Does this pull request's own diff touch the paths above? This forge matches a
# workflow's `paths:` against the push, so a merge of main into a branch fires the
# workflow whatever the pull request changes; every job here waits on this answer.
# A push to main, or anything the script cannot determine, answers `true`
# (scripts/pr-touches-paths.py).
relevant:
name: does this change touch it
runs-on: linux-arm64
outputs:
run: ${{ steps.gate.outputs.run }}
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- id: gate
run: |
set -euo pipefail
r=$(python3 scripts/pr-touches-paths.py .github/workflows/wai-quantum-contract.yml \
"${{ github.event.pull_request.base.sha }}" \
"${{ github.event.pull_request.head.sha }}")
echo "this change touches the wai-quantum contract: $r"
echo "run=$r" >> "$GITHUB_OUTPUT"
api:
name: API compatibility · linux
needs: relevant
if: needs.relevant.outputs.run == 'true'
runs-on: linux
timeout-minutes: 60
env:
# The last version of each on crates.io. Raise each when a release is published.
WAI_QUANTUM_BASELINE: "0.8.0"
WAI_QUANTUM_CLI_BASELINE: "0.2.3"
WAI_QUANTUM_QPU_BASELINE: "0.4.0"
# Built from its source on crates.io, at this version.
SEMVER_CHECKS: "0.51.0"
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.98.0
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 --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install cargo-semver-checks ${{ env.SEMVER_CHECKS }}
shell: bash
run: |
set -euo pipefail
cargo install cargo-semver-checks --version "$SEMVER_CHECKS" --locked --root "$RUNNER_TEMP/semver"
echo "$RUNNER_TEMP/semver/bin" >> "$GITHUB_PATH"
- name: The baselines are the last versions published
shell: bash
working-directory: ${{ runner.temp }}
run: |
set -euo pipefail
for pair in "wai-quantum $WAI_QUANTUM_BASELINE" "wai-quantum-cli $WAI_QUANTUM_CLI_BASELINE" "wai-quantum-qpu $WAI_QUANTUM_QPU_BASELINE"; do
set -- $pair
latest=$(cargo info "$1" 2>/dev/null | sed -n 's/^version: *\([^ ]*\).*/\1/p' | head -1 || true)
if [ -z "$latest" ]; then
echo "::warning::crates.io did not say which version of $1 is the last; the check runs against $2"
elif [ "$latest" != "$2" ]; then
echo "::warning::crates.io's last version of $1 is $latest, and this workflow's baseline is $2: raise the baseline"
else
echo "$1: the baseline $2 is the last version on crates.io"
fi
done
- name: API compatibility, against the last versions published
shell: bash
run: |
set -euo pipefail
# The major of a version: the first non-zero component (0.6.16 -> 0.6, 1.2.3 -> 1).
major() { IFS=. read -r a b _ <<< "$1"; if [ "$a" = 0 ]; then echo "0.$b"; else echo "$a"; fi; }
# Every change is checked as if for a minor release, so that each breaking
# change is listed; a breaking change fails the step only when the major
# is still the baseline's. A build that fails is a failure either way.
check() {
local dir=$1 base=$2 cur log
cur=$(sed -n 's/^version *= *"\([^"]*\)".*/\1/p' "$dir/Cargo.toml" | head -1)
log="$RUNNER_TEMP/semver-$(basename "$dir").log"
echo "== $dir: $base -> $cur, the major $(major "$base") -> $(major "$cur")"
if cargo semver-checks check-release --manifest-path "$dir/Cargo.toml" --baseline-version "$base" --release-type minor 2>&1 | tee "$log"; then
echo "$dir: no breaking change against $base"
elif ! grep -q 'semver requires new major version' "$log"; then
echo "::error::$dir: the check did not run to its end (above)"
return 1
elif [ "$(major "$cur")" != "$(major "$base")" ]; then
echo "::warning::$dir: breaking changes against $base, listed above; allowed, as the major is bumped to $(major "$cur")"
else
echo "::error::$dir: a breaking change against $base, listed above, without a major bump: raise $(major "$base") (before 1.0, the 0.y component), and say what to do instead in the changelog"
return 1
fi
}
r=0
check wai/wai-quantum "$WAI_QUANTUM_BASELINE" || r=1
check wai/wai-quantum-cli "$WAI_QUANTUM_CLI_BASELINE" || r=1
check wai/wai-quantum-qpu "$WAI_QUANTUM_QPU_BASELINE" || r=1
exit $r
schemas:
name: schemas and the committed tool lists · linux
needs: relevant
if: needs.relevant.outputs.run == 'true'
runs-on: linux
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.98.0, and uv
shell: bash
run: |
export PATH="$HOME/.local/bin:$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 --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
command -v uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: The engine's schemas, and receipts issued before
shell: bash
working-directory: wai/wai-quantum
run: |
set -euo pipefail
cargo test --locked --release --no-default-features --features quantum_engine,quantum_receipt,quantum_qec,quantum_noise --lib engine::schema:: 2>&1 | tee "$RUNNER_TEMP/engine.log"
for t in every_schema_reads_names_itself_and_refers_only_to_what_is_there \
the_checker_reads_the_subset_it_names_and_refuses_what_it_should \
every_check_s_answer_follows_its_schema \
every_method_s_job_follows_the_job_schemas \
a_new_result_names_its_engine_and_schema_and_its_receipt_binds_them \
error_correction_and_mitigation_follow_their_schemas \
the_answer_layer_the_correctness_record_and_the_views_bundle_follow_their_schemas \
the_course_its_exercises_and_its_checks_follow_their_schemas \
the_variational_and_algorithm_answers_follow_their_schema \
receipts_issued_before_results_named_them_still_verify; do
grep -q "^test engine::schema::tests::$t \.\.\. ok$" "$RUNNER_TEMP/engine.log" || { echo "::error::$t did not run and pass"; exit 1; }
done
- name: The command line's MCP server, its committed tool list and its docs
shell: bash
working-directory: wai/wai-quantum-cli
run: |
set -euo pipefail
cargo test --locked --release --bin wai-quantum 2>&1 | tee "$RUNNER_TEMP/cli.log"
for t in mcp::tests::the_schemas_read_and_name_themselves \
mcp::tests::every_tool_s_answer_follows_its_output_schema \
mcp::tests::the_committed_tool_list_is_this_server_s_live_list \
mcp::tests::an_agent_initializes_lists_the_tools_and_runs_a_circuit \
guide::tests::the_committed_docs_are_what_the_binary_generates \
guide::tests::the_docs_list_exactly_the_servers_tools_and_name_no_version \
tests::the_command_line_parses_as_documented \
task::tests::a_lease_follows_its_schema \
eval::tests::a_scripted_run_reports_what_the_engine_found \
eval::tests::the_corpus_is_the_task_set_written_three_ways \
learn::tests::progress_is_kept_in_one_file_and_marks_a_pass_once; do
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/cli.log" || { echo "::error::$t did not run and pass"; exit 1; }
done
- name: The job service's MCP server, its committed tool list, its job and its receipt keys
shell: bash
working-directory: wai/wai-quantum-service
run: |
set -euo pipefail
cargo test --locked --release -- mcp:: jobs:: receipt:: 2>&1 | tee "$RUNNER_TEMP/service.log"
for t in mcp::tests::the_schemas_read_and_the_versions_are_reported \
mcp::tests::every_tool_s_answer_follows_its_output_schema \
mcp::tests::every_tool_has_a_schema_and_a_description \
mcp::tests::the_command_line_s_snapshot_is_this_server_s_live_list \
jobs::tests::a_job_s_form_follows_the_job_schema \
receipt::tests::a_rotation_keeps_the_old_key_published_with_its_window_and_a_signed_transition; do
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/service.log" || { echo "::error::$t did not run and pass"; exit 1; }
done
- name: The provider protocol's messages
shell: bash
working-directory: wai/wai-quantum-qpu
run: |
set -euo pipefail
cargo test --locked --release --test protocol_schema 2>&1 | tee "$RUNNER_TEMP/qpu.log"
for t in the_schema_names_the_protocol_s_own_constants every_message_and_answer_follows_the_protocol_s_schema; do
grep -q "^test $t \.\.\. ok$" "$RUNNER_TEMP/qpu.log" || { echo "::error::$t did not run and pass"; exit 1; }
done
# A second implementation of JSON Schema, sharing no code with the engine's
# checker: every schema file and both tool lists valid 2020-12 schemas, every
# reference resolving, and a release build's answers holding to them.
- name: The schemas, read by a full JSON Schema implementation
shell: bash
run: |
set -euo pipefail
(cd wai/wai-quantum-cli && cargo build --locked --release)
uv venv -q --python 3.12 "$RUNNER_TEMP/schemas"
uv pip install -q --python "$RUNNER_TEMP/schemas/bin/python" --require-hashes -r wai/wai-quantum-py/tests/requirements.lock
"$RUNNER_TEMP/schemas/bin/python" -I wai/wai-quantum/ci/check_schemas.py wai wai/wai-quantum-cli/target/release/wai-quantum
policy:
name: the policy is linked, and the deprecations page reads
needs: relevant
if: needs.relevant.outputs.run == 'true'
runs-on: linux
timeout-minutes: 10
steps:
- uses: actions/checkout@v5
- name: Every README of a WAI Quantum package links the policy
shell: bash
run: |
set -euo pipefail
for f in wai/wai-quantum/README.md wai/wai-quantum-cli/README.md wai/wai-quantum-service/README.md \
wai/wai-quantum-qpu/README.md wai/wai-quantum-py/README.md wai/wai-quantum-desktop/README.md \
wai/quantum-studio/README.md wai/tools/wai-quantum-editor/README.md wai/tools/tree-sitter-openqasm/README.md; do
grep -q 'wai/wai-quantum/VERSIONING.md\|(VERSIONING.md)' "$f" || { echo "::error::$f does not link the policy (wai/wai-quantum/VERSIONING.md)"; exit 1; }
done
echo "every README links the policy"
- name: The deprecations page's table is well formed
shell: bash
run: |
set -euo pipefail
python3 -I - wai/wai-quantum/DEPRECATIONS.md <<'EOF'
import re, sys
lines = open(sys.argv[1], encoding="utf-8").read().splitlines()
head = "| Package | Item | Deprecated in | Replacement | Removed in |"
assert head in lines, "the table's header is " + head
at = lines.index(head)
assert re.fullmatch(r"\|(---\|){5}", lines[at + 1]), lines[at + 1]
semver = re.compile(r"\d+\.\d+\.\d+")
rows = []
for line in lines[at + 2:]:
if not line.startswith("|"):
break
cells = [c.strip() for c in line.strip("|").split("|")]
assert len(cells) == 5 and all(cells[:4]), f"a row names its package, item, version and replacement: {line}"
assert semver.fullmatch(cells[2]), f"deprecated in a version: {line}"
assert cells[4] == "" or semver.fullmatch(cells[4]), f"removed in a version, or not yet: {line}"
rows.append(cells)
print(f"{len(rows)} deprecated item(s) listed")
EOF