Repository navigation
Conversation
operation-parity and content-digest are siblings over the same operation set,
but they disagreed about which divergences are accepted. operation-parity reads
compare()'s post-allowlist findings; content-digest re-derived its own list from
the raw shared keys and subtracted nothing.
That was not a stricter check, it was an incoherent one. operation-parity
deliberately filters shared-drift out of its own verdict ("already reported,
more precisely, by content-digest below"), so the allowlist's entire
shared-drift direction suppressed a finding that nothing then consumed: nine
documented, predicate-guarded exemptions were dead letters, and the criterion
they were written for failed on them anyway.
The digest now excludes exactly the operations compare() still exempts, at
operation granularity - object and reachable $ref content. Six of the nine
diverge in referenced schemas precisely because of the divergence their entry
documents, so a refs-only carve-out would exempt the stated cause and still fail
on its direct consequence. The residual risk is stated in the file header.
An exemption can only remove an operation from the comparison; it can never turn
a real mismatch into a pass. Six new tests pin both directions: a lapsed
predicate is not subtracted, a non-shared-drift direction is not subtracted, and
a non-allowlisted difference (including a $ref-only one) still fails while a
sibling exemption stands. The exempted count is reported in the evidence line on
pass and on fail, so a growing exemption set stays visible.
opts.allowlistPath is an in-process test seam only, deliberately not env-readable
- the CLI passes no opts, so a real run can only read the committed allowlist.
No allowlist entry was added and no gate was weakened. The allowlist is unchanged
at 11 entries and content-digest still fails on eleven genuine content
differences, itemised in CHANGELOG.md for separate per-operation judgement.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Reviewer's GuideThis PR fixes CONTRACT-001’s inconsistent sibling checks by making Sequence diagram for CONTRACT-001 sibling checks sharing exemptionssequenceDiagram
participant Run as CONTRACT001
participant Compare
participant Allowlist
participant Digest
Run->>Allowlist: read committed allowlist
Run->>Compare: compare(repoDoc, liveDoc, allowlist)
Allowlist-->>Compare: active shared-drift exemptions
Compare-->>Run: post-allowlist findings and allowlisted entries
Run->>Digest: select shared operations
Digest->>Digest: exclude active shared-drift operations
Digest->>Digest: normalize operations and reachable refs
Digest-->>Run: repo/live digest comparison
Run-->>Run: report compared and exempted counts
State diagram for a shared-drift allowlist entrystateDiagram-v2
[*] --> Candidate
Candidate --> Active: expect or expectAbsent matches
Candidate --> Lapsed: predicate no longer matches
Active --> ExcludedFromDigest: direction is shared-drift
Active --> Compared: another direction
Lapsed --> Compared
ExcludedFromDigest --> [*]
Compared --> [*]
Flow diagram for CONTRACT-001 content-digest allowlist handlingflowchart LR
A["repo and live OpenAPI documents"] --> B["indexOperations"]
B --> C["compare with active allowlist"]
C --> D["shared-drift exemptions"]
C --> E["shared operation keys"]
E --> F["exclude exempt operations"]
D --> F
F --> G["normalize operations and reachable refs"]
G --> H["compute repo and live SHA-256 digests"]
H --> I["content-digest result"]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
All reported issues were addressed across 3 files
Architecture diagram
sequenceDiagram
participant CLI as CLI (scripts/ga/main)
participant Check as contract-001-check.mjs
participant Compare as compare()
participant Allowlist as published-drift-allowlist.json
participant Index as indexOperations()
participant Normalize as normalizePair()
participant Digest as content-digest logic
Note over CLI,Digest: CONTRACT-001 content-digest flow
CLI->>Check: run() (no opts - production)
Check->>Check: Load repo spec + live doc
Check->>Index: indexOperations(repoDoc)
Index-->>Check: repoOps
Check->>Index: indexOperations(liveDoc)
Index-->>Check: liveOps
Check->>Check: Compute sharedKeys (intersection)
Check->>Compare: compare(repoOps, liveOps, allowlist)
Compare->>Allowlist: Load and evaluate exemptions
Allowlist-->>Compare: allowlist entries
alt Entry lapsing predicate matches
Compare->>Compare: Include in result.allowlisted
else Entry lapsed or no match
Compare->>Compare: Include in findings (not allowlisted)
end
Compare-->>Check: result { allowlisted, findings }
Check->>Check: Filter allowlisted entries for direction == 'shared-drift'
Check->>Check: Build exemptKeys set (method + path)
Check->>Check: digestKeys = sharedKeys - exemptKeys
Check->>Check: Calculate exemptedCount
loop For each key in digestKeys
Check->>Repo: Get repo operation
Check->>Live: Get live operation
Check->>Normalize: normalizePair(repoOp, liveOp, path, method)
Normalize-->>Check: { repo, live }
Check->>Check: Walk operation + reachable $refs
Check->>Check: Compute repoDigest + liveDigest
end
Check->>Check: Build evidence with counts
Check->>Check: Evaluate content-digest result
alt localDigest === liveDigest
Check-->>CLI: ok: true + detail with counts
else digests differ
Check-->>CLI: ok: false + detail with counts
end
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
🟢 WAVE BugBot — clearNo confident findings on the changed lines. Local review · $0 inference · wave-dispatch |
wave-gateway omits every operation of an operator-paused product from
GET /openapi.json (src/openapi-paused.ts) and declares it at the document
root as x-wave-paused-products. Build 06e4efce1050 (live 2026-10-01)
declares /v1/render, /v1/renders, /v1/enhance and /v1/video-gen. The
compare never read that, so CONTRACT-001 operation-parity FAILED on main
with four unexplained unpublished-repo findings (POST /enhance,
POST /render, GET /render/{jobId}, GET /render/{jobId}/events): red for
a reason no change to this repo can fix.
published-drift-paused.mjs (new leaf, pure): a repo operation that is
ABSENT from the published document under a path prefix the document
itself declares paused is listed as pausedNotPublished and counted in the
headline, never dropped silently. A paused operation that is published is
still compared; an absence with no declaration is still a finding; a
prefix never covers a sibling (/v1/render does not cover /v1/renders).
Live: operation-parity PASS (256 declared, 249 live, 248 shared, 9
allowlisted, 0 draft, 6 paused). content-digest still fails, as on main
(#103).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What this fixes
CONTRACT-001 has two sub-checks. They run over the same operation set, and they disagreed about which divergences are accepted.
operation-parityreadscompare()'s findings, which are post-allowlist.content-digestre-derived its own list from the raw shared keys and subtracted nothing:That is not a stricter check. It is an incoherent one, and the incoherence is load-bearing:
operation-paritydeliberately filtersshared-driftout of its own verdict, with a comment saying that condition is "already reported, more precisely, by content-digest below." So the allowlist's entireshared-driftdirection was suppressing a finding that nothing then consumed — nine documented, owner-attributed, predicate-guarded exemptions were dead letters, and the criterion they were written for failed on them anyway. Either the allowlist means something to this criterion or theshared-driftdirection should not exist; it cannot half-mean something.Confirming the asymmetry before changing anything
Measured against
origin/mainand a snapshot of the published contract fetched 2026-09-11:shared-drift+ 2unpublished-repo. Only the 9 are candidates for subtraction here. (The 11 inoperation-parity's evidence line is the total, not the shared-drift count.)What changed
The digest now excludes exactly the operations
compare()still exempts — nothing more.Granularity is per-operation: an exempted operation contributes neither its own object nor its reachable
$refcontent. That is deliberate and it is measured, not assumed. Six of the nine also diverge in referenced component schemas, precisely because of the divergence their entry documents (a gateway-native or draft-placeholder operation reaches different components than the hand-written one), so a refs-only carve-out would exempt the stated cause and still fail on the consequence that flows from it.The residual risk is stated plainly in the file header rather than hidden: while an exemption stands, a change to a component only that operation reaches is not seen. That is intrinsic to granting the exemption, not introduced here, and it is bounded by machinery that already exists — every entry carries a lapsing predicate, a lapsed entry drops straight back into
findingsand therefore back into this digest, andcompare()separately surfaces entries matching nothing.The exempted count is now reported in the evidence line on pass and fail both, so a growing exemption set is visible in the receipt itself.
opts.allowlistPathis an in-process test seam only, deliberately not env-readable — the CLI passes no opts, so a real run can only ever read the committed allowlist at its fixed path.Proof — local runs only
CI is unmeasured org-wide right now (an account-level billing lock removed the required checks); nothing below comes from CI, and this PR is opened as a draft so auto-merge cannot arm.
contract-001-check.test.mjsnpm run test:ganode --test ".github/scripts/**/*.test.mjs"origin/mainspecThe
pass-aftertest fails onorigin/mainfor the right reason —content-digest.okisfalse !== true, not a missing option.content-digeststill FAILS after this change, and that is the correct outcome. This PR removes a defect in the criterion; it does not clear the criterion. Eleven genuine content differences remain.Both directions are pinned
Subtracting an exemption from a digest is exactly the shape of change that can quietly become a way to switch a criterion off, so showing that an allowlisted difference stops failing is not enough. The new tests also hold that:
$ref-only difference still fails (the reachable-ref fold survives the subtraction);shared-drift, not on path+method.An exemption may only ever remove an operation from the comparison. It may never turn a real mismatch into a pass.
The eleven real differences — reported, not allowlisted
No allowlist entry was added. The allowlist is unchanged at 11. These are itemised in
CHANGELOG.mdfor separate per-operation judgement:nullabledivergence (POST /compose,POST /compose/run,GET /compose/proposals/{proposalId}, plus prose-only diffs onPOST /render,POST /captions,POST /transcribe).CHANGELOG.mdalready records this and states it "does not affect the …shared-driftfinding" — that is true of the operation-level comparator only.content-digestresolves$refcontent and does see it. That sentence needs correcting; this PR corrects it.Error/ErrorBodyschemas the published contract does not define at all (GETandPOST /videos/{videoId}/chapters,POST /videos/{videoId}/chapters/detect). A missing error envelope is a real spec-vs-service gap.SearchIndexRequest/SearchIndexDoc.id.pattern, andBraidPublishRequest.sources.minItems: 2with itsanyOfrequired-one-of. These are the interesting ones: the repo promises a constraint the gateway may not enforce.None is an allowlist candidate on current evidence.
Relationship to #101
Independent, no file overlap in the fix itself. #101 edits
openapi.yaml+contract-drift.json; this editsscripts/ga/*. Both add toCHANGELOG.mdunder[Unreleased]— expect a trivial textual conflict there and nothing more. #101's own body named this defect and left it for a reviewed change; this is that change.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by Sourcery
Align CONTRACT-001 content-digest with operation-parity by applying only active shared-drift exemptions while preserving detection of all other content mismatches.
Bug Fixes:
Enhancements:
Documentation:
Tests: