ci(sdk): wire binary-compatibility-validator — committed .api dumps + blocking apiCheck gate - #2730
Merged
Merged
Conversation
… blocking apiCheck gate Closes #2723. The SDK had no public-API surface tracking: a signature change in sceneview, arsceneview or sceneview-core shipped silently unless a reviewer happened to notice. For an AI-first SDK whose llms.txt promises exact signatures, that is the doc-drift bug class at the binary level. - Apply Kotlin binary-compatibility-validator 0.18.1 at the root build, scoped via apiValidation {} to the three published library modules (sceneview, arsceneview, sceneview-core). Samples/demos and the npm-published JS-only sceneview-web module are ignored. - Commit the initial apiDump output: sceneview.api (3221 lines), arsceneview.api (2436), sceneview-core.api (1522). - Add a BLOCKING `API compatibility` job to ci.yml (same tier as unit tests, path-gated on `android`) running `./gradlew apiCheck`. - CONTRIBUTING.md → "Public API changes": apiDump → commit the .api diff makes the public-API delta reviewable; ties to the llms.txt invariant. - Note-only check-doc-drift.sh interplay (.api diff is a deterministic future signal; no coupling today). JVM surface only: sceneview-core's jvm("android") dump already captures the shared commonMain API. Native/JS klib ABI validation stays disabled (experimental + not buildable on the ubuntu CI runner) and is documented as a follow-up. Co-Authored-By: Claude Opus <noreply@anthropic.com>
…ording, apiCheck in local gates (#2730) - CONTRIBUTING.md + build.gradle: the sceneview-web exclusion claimed its API 'is validated separately at the JS layer' — no such automated gate exists (only the hand-written sceneview-web.d.ts). Reworded honestly, pointing at shortlist #2642 item 12 (.d.ts drift gate) as the follow-up. - CLAUDE.md: 9th entry in the 'Quality gates (must pass before any push to main)' list — public-API ABI must match the committed .api dumps. - pre-push-check.sh: new [11/11] apiCheck step (steps renumbered /10 -> /11) so the documented local pre-push gate actually catches an ABI break before CI does; failure output points at apiDump for intentional changes. Verified: bash -n clean, ./gradlew -q apiCheck exit 0 on this branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
Author
Review-fanout verdict: MERGE_AFTER_WARNINGS → warnings fixed → auto-merge armed4/4 reviewers, 0 confirmed ERRORs, breakingApi=false (code/doc: PASS_WITH_WARNINGS · security/impact: PASS). Both warnings fixed in the follow-up commit:
Re-verified: |
ThomasGorisse
enabled auto-merge (squash)
July 16, 2026 15:29
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2723.
What & why
The SDK had no public-API surface tracking — a signature change in
sceneview,arscenevieworsceneview-coreshipped silently unless a reviewer happened to notice. For an AI-first SDK whosellms.txtpromises exact signatures, that is the doc-drift bug class at the binary level (shortlist #2642 item 4).This wires Kotlin's
binary-compatibility-validator0.18.1into the root build, commits the initial.apidumps, and adds a blockingapiCheckCI gate.Changes
build.gradle+gradle/libs.versions.toml— apply BCV0.18.1at the root;apiValidation {}scopes validation to the three published library modules and ignores samples/demos +sceneview-web..apidumps —sceneview/api/sceneview.api(3221 lines),arsceneview/api/arsceneview.api(2436),sceneview-core/api/sceneview-core.api(1522). Verified non-empty and meaningful: they containScene,ARScene, every node type (ModelNode,CameraNode,LightNode, …), and the sharedcommonMaincore surface (animation/collision/math/geometry)..github/workflows/ci.yml— newAPI compatibilityjob (./gradlew apiCheck), BLOCKING, same tier asUnit tests, path-gated onandroid(which includessceneview-core/**). Not advisory: a redapiCheckfails the PR via theCI Gateaggregator.CONTRIBUTING.md— new "Public API changes" section:apiDump→ commit the.apidiff → the public-API delta is reviewable; tied to thellms.txtinvariant.changelog.d/2723-binary-compat-validator.md—Added..claude/scripts/check-doc-drift.sh— note-only comment: the.apidiff is a deterministic future signal it could consume (no coupling today, per the issue).Gradle task results (local, macOS)
./gradlew apiDump→ BUILD SUCCESSFUL (generated all three.apifiles)../gradlew apiCheck→ BUILD SUCCESSFUL on the fresh dumps. Log confirms the klib path is skipped as designed:klibApiCheck SKIPPED,iosX64ApiBuild SKIPPED../gradlew :sceneview:compileReleaseKotlin :arsceneview:compileReleaseKotlin apiCheck(pre-push rule) → BUILD SUCCESSFUL.check-workflow-scripts.sh→ OK;test-check-doc-drift.sh→ 7 passed, 0 failed;ci.ymlparses as valid YAML.Differential proof — the gate BITES
Temporarily added a public function to
sceneview-corecommonMain and ranapiCheck:apiCheckfailed (non-zero exit), named the exact new symbol, and told the author how to fix it. Reverted the change →apiCheckBUILD SUCCESSFUL again. So a public-signature change with a stale committed dump is a hard CI failure.Scope / honest exclusions
sceneview,arsceneview,sceneview-core.sceneview-coreis KMP — itsjvm("android")target dump already captures the entire sharedcommonMainpublic API, so the common surface is covered.sceneview-webexcluded: JS-only KMP module published to npm, not Maven. Its singlejs(IR)target has no JVM/bytecode surface for the JVM-based validator; its API is validated separately at the JS layer.klib { enabled = false }, the default): still experimental, and the iOS native klibs are not buildable on the ubuntu-latest runner that hostsapiCheck. Tracked as a follow-up once it stabilises and a macOS CI leg can host it.This PR changes the CI contract (adds a new blocking gate + commits generated artifacts that a reviewer should eyeball). It should go through the review-fanout at the orchestrator level rather than fire-and-forget auto-merge.