Spec-conformance audit (2026-07-04 fleet sweep). The client tracks spec fixture v0.1.24 while the current protocol spec is v0.1.25.12 — several findings below are invisible against the bundled fixture but real against the live spec.
Bugs
EventCreateResponse.charged declared but never mapped — models.ts:218 advertises it, eventCreateResponseFromWire (mappers.ts:173-181) drops it. The additive v0.1.24 field is silently lost.
- Whitelist mappers drop every additive response field by default —
committed/finalized_at_ms were hand-added; cycles_evidence (reserve/commit/release/error responses), ReservationSummary.committed/metadata/committed_metadata/evidence, and EventCreateResponse.charged (above) are absent or dropped. Consider passing through unknown fields (or a raw accessor) so additive spec revisions stop requiring mapper edits.
Spec-currency gaps (fixture v0.1.24 → current v0.1.25.12)
- Bundled
cycles-protocol-v0.yaml fixture is 8+ revisions stale. Update it and re-run the contract tests.
listReservations params: current spec defines from/to, expires_from/to, finalized_from/to, sort_by/sort_dir, include= (metadata / committed_metadata / evidence) — none typed (free-form Record<string,string> passthrough only, client.ts:104).
- Evidence surface:
GET /v1/evidence/{id} + JWKS endpoints and the cycles_evidence response fields exist since v0.1.25.2+ — entirely unmodeled.
ErrorCode enum lacks LIMIT_EXCEEDED (spec v0.1.25.12, used for 429 throttling on the public endpoints). The UNKNOWN fallback keeps it safe, but 429s deserve first-class handling (Retry-After awareness).
Robustness
ReservationStatus and other response enums are closed TS enums cast blindly (mappers.ts:213,233) — the spec explicitly reserves the right to add states. Follow the errorCodeFromString → UNKNOWN pattern or type as Status | string like Amount.unit already does.
- No exception classes /
is*() predicates for BUDGET_FROZEN, BUDGET_CLOSED, MAX_EXTENSIONS_EXCEEDED — reachable only via raw .errorCode compare (errors.ts:75, exceptions.ts:39-65).
Context
Same sweep produced: runcycles/cycles-protocol#120/#121/#122 (spec), cycles-server#222/#223, cycles-server-admin#198/#199/#200, cycles-server-events#101/#102, cycles-dashboard#224, .github#82/#83. The health-check fix (#133) is already merged. Full inventory details available on request.
Spec-conformance audit (2026-07-04 fleet sweep). The client tracks spec fixture v0.1.24 while the current protocol spec is v0.1.25.12 — several findings below are invisible against the bundled fixture but real against the live spec.
Bugs
EventCreateResponse.chargeddeclared but never mapped —models.ts:218advertises it,eventCreateResponseFromWire(mappers.ts:173-181) drops it. The additive v0.1.24 field is silently lost.committed/finalized_at_mswere hand-added;cycles_evidence(reserve/commit/release/error responses),ReservationSummary.committed/metadata/committed_metadata/evidence, andEventCreateResponse.charged(above) are absent or dropped. Consider passing through unknown fields (or arawaccessor) so additive spec revisions stop requiring mapper edits.Spec-currency gaps (fixture v0.1.24 → current v0.1.25.12)
cycles-protocol-v0.yamlfixture is 8+ revisions stale. Update it and re-run the contract tests.listReservationsparams: current spec definesfrom/to,expires_from/to,finalized_from/to,sort_by/sort_dir,include=(metadata / committed_metadata / evidence) — none typed (free-formRecord<string,string>passthrough only,client.ts:104).GET /v1/evidence/{id}+ JWKS endpoints and thecycles_evidenceresponse fields exist since v0.1.25.2+ — entirely unmodeled.ErrorCodeenum lacksLIMIT_EXCEEDED(spec v0.1.25.12, used for 429 throttling on the public endpoints). TheUNKNOWNfallback keeps it safe, but 429s deserve first-class handling (Retry-Afterawareness).Robustness
ReservationStatusand other response enums are closed TS enums cast blindly (mappers.ts:213,233) — the spec explicitly reserves the right to add states. Follow theerrorCodeFromString → UNKNOWNpattern or type asStatus | stringlikeAmount.unitalready does.is*()predicates forBUDGET_FROZEN,BUDGET_CLOSED,MAX_EXTENSIONS_EXCEEDED— reachable only via raw.errorCodecompare (errors.ts:75,exceptions.ts:39-65).Context
Same sweep produced: runcycles/cycles-protocol#120/#121/#122 (spec), cycles-server#222/#223, cycles-server-admin#198/#199/#200, cycles-server-events#101/#102, cycles-dashboard#224, .github#82/#83. The health-check fix (#133) is already merged. Full inventory details available on request.