Spec-conformance audit (2026-07-04 fleet sweep). The bundled spec fixture (tests/fixtures/cycles-protocol-v0.yaml) predates the v0.1.25 window-filter/evidence revisions — the current protocol spec is v0.1.25.12, so some "not in spec" assumptions in the codebase are stale.
Robustness (highest value)
- Closed enums on the hot path raise
ValidationError on additive spec values. Decision (models.py:28) is validated on every guarded call (lifecycle.py:264, streaming.py:210); Unit (models.py:11) via Amount in every response. The spec's extensibility rule says clients MUST tolerate unknown values; ErrorCode.from_string → UNKNOWN (models.py:83-90) is the house pattern — extend it to Decision/Unit/ReservationStatus/single-value statuses (e.g. _missing_ → UNKNOWN sentinel).
- Exception
request_id sourced from the error body only (lifecycle.py:187-196); if the body is malformed the X-Request-Id header (already captured, client.py:44) is never threaded into the exception.
Spec-currency gaps
- Update the bundled fixture to the current spec and re-run
test_contract.py.
listReservations/getBalances are untyped **query_params passthroughs — fine on the wire, but the current spec's from/to, expires_*, finalized_*, sort_by/sort_dir, include= deserve typed/documented surface (the passthrough regression tests added in v0.4.2/.3 cover only the window bounds).
- Evidence surface (
GET /v1/evidence/{id}, JWKS, cycles_evidence response fields) unmodeled; additive fields are silently dropped by extra='ignore' — callers can only reach them via raw response.body.
ErrorCode lacks LIMIT_EXCEEDED (spec v0.1.25.12, 429 throttling on public endpoints) — tolerated as UNKNOWN today.
Context
Same sweep produced spec PRs runcycles/cycles-protocol#120/#121/#122 and server-side fixes across cycles-server/-admin/-events/-dashboard. The health-check fix (#74) is already merged. Full inventory details available on request.
Spec-conformance audit (2026-07-04 fleet sweep). The bundled spec fixture (
tests/fixtures/cycles-protocol-v0.yaml) predates the v0.1.25 window-filter/evidence revisions — the current protocol spec is v0.1.25.12, so some "not in spec" assumptions in the codebase are stale.Robustness (highest value)
ValidationErroron additive spec values.Decision(models.py:28) is validated on every guarded call (lifecycle.py:264,streaming.py:210);Unit(models.py:11) viaAmountin every response. The spec's extensibility rule says clients MUST tolerate unknown values;ErrorCode.from_string → UNKNOWN(models.py:83-90) is the house pattern — extend it toDecision/Unit/ReservationStatus/single-value statuses (e.g._missing_→UNKNOWNsentinel).request_idsourced from the error body only (lifecycle.py:187-196); if the body is malformed theX-Request-Idheader (already captured,client.py:44) is never threaded into the exception.Spec-currency gaps
test_contract.py.listReservations/getBalancesare untyped**query_paramspassthroughs — fine on the wire, but the current spec'sfrom/to,expires_*,finalized_*,sort_by/sort_dir,include=deserve typed/documented surface (the passthrough regression tests added in v0.4.2/.3 cover only the window bounds).GET /v1/evidence/{id}, JWKS,cycles_evidenceresponse fields) unmodeled; additive fields are silently dropped byextra='ignore'— callers can only reach them via rawresponse.body.ErrorCodelacksLIMIT_EXCEEDED(spec v0.1.25.12, 429 throttling on public endpoints) — tolerated asUNKNOWNtoday.Context
Same sweep produced spec PRs runcycles/cycles-protocol#120/#121/#122 and server-side fixes across cycles-server/-admin/-events/-dashboard. The health-check fix (#74) is already merged. Full inventory details available on request.