Skip to content

drift/06: completeness ratchet — coverage as proof, exemptions as debt - #26

Merged
bhelm merged 2 commits into
drift/metafrom
drift/06-coverage-ratchet
Aug 18, 2026
Merged

bhelm merged 2 commits into
drift/metafrom
drift/06-coverage-ratchet

Conversation

@bhelm

@bhelm bhelm commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Plan step 6 of #17: the completeness ratchet — from here on, the pilot module pair is machine-tightened: every twin declaration is differential-covered, platform-test-covered (with executed-lines proof), or explicitly exempted with a reason and an issue.

Shape

  • Declaration-level lexer (stdlib, reusing the ledger's parser primitives) that fails closed: unknown declaration syntax — Kotlin init blocks, secondary constructors, operator functions, getter forms, multi-line computed properties — is an error, never a silent skip.
  • Inverted, sharded exemptions: only exceptions are checked in (parity-exempt.json per module directory); differential membership is derived from the runner dispatchers at runtime, never a second hand-kept list. Pilot bootstrap: differential=2, platform-test=0, exempt=2719 — every entry with reason + issue.
  • Coverage as proof, not a label: verify reads llvm-cov lcov (FN/FNDA function records) and JaCoCo XML (method counters, descriptor-arity disambiguated so an executed overload can never vouch for an unexecuted same-name sibling). Line coverage only as an announced fallback for method-less reports. JaCoCo is wired to the exact JVM runner task; its agent artifacts are pinned in the dependency-verification metadata.
  • Merge-base ratchet: shards and entries compare against the actual git merge-base — counters only fall, new entries need an issue (checked in CI via gh api; --offline in CI is a hard error), and deleting merge-base shards is a disarmed error, not a silent notice. This closes the working-tree hole where a baseline and its violation land in the same PR.
  • Trigger inversion: the workflow runs on every PR + push to main; the path decision happens inside the job ("no-op" instead of "skipped", so the check is requirable), and the touched-set includes the harness, tools, shards and the workflow itself.

It earns its keep immediately

The coverage proof caught a real blind spot before landing: both parity runners always passed the defaulted parameters explicitly, so the languages' own default expressions never executed — a drifted Kotlin default would have been invisible. Bare cases now call the production functions with defaults omitted on both sides; the cross-comparison itself checks default parity (windowSec stays explicit in Swift, which deliberately has no default — the documented one-sided default).

Verification

  • 51 unittest probes green (lexer fail-closed forms, shard integrity, disarm, issue enforcement, coverage semantics incl. same-line overload case, CI inversion).
  • Ratchet clean against drift/meta; verify green with fresh real coverage from both runners (Swift lcov + Gradle JaCoCo, errors=0). Before the bare-case fix, the Kotlin default lines were correctly rejected — the sharpness proof.
  • Full suites unchanged green: Swift 1429 / 2 skipped / 0; Android 3977 / 0 / 6.

Review

Two independent Codex rounds, both red, both folded in: round 1 found seven real holes (fail-closed gaps incl. 297 phantom inventory entries from bodyless Kotlin type spans, the CI filter blind to its own tooling, shard deletion as silent disarm, issue-field removal, same-line coverage greenwashing, offline-in-CI); round 2 confirmed six of seven fixes clean and caught the JaCoCo descriptor matching, fixed here. Remaining honest limit: Linux-Swift ↔ JVM is the always-on proxy pair for shipped Darwin/ART (#17 §limits).

Part of the drift-control plan in #17.

🤖 Generated with Claude Code

bhelm and others added 2 commits August 18, 2026 04:42
The coverage proof exposed a real blind spot: both runners always
passed stepSec/minBeatsPerWindow explicitly, so the languages' own
default expressions never executed — a drifted Kotlin default would
have been invisible to the differential. Cases whose args carry only
rr now call the production function bare on both sides; the
cross-comparison itself checks default parity. windowSec stays
explicit on the Swift side, which deliberately has no default for it
(the documented one-sided default; Kotlin's is cross-checked by its
runner's existing constant assertion).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tools/parity_ratchet.py (stdlib, reusing the ledger's parser
primitives): a declaration-level lexer that fails closed on unknown
syntax — including Kotlin init blocks, secondary constructors,
operator functions and getter forms; inverted, sharded exemption
files (only exceptions are checked in, per module directory, every
entry carrying a reason and an issue reference); differential
membership derived from the runner dispatchers at runtime. A module
pair without shards at the merge base is "not yet covered" (notice);
a pair whose merge-base shards disappear is disarmed and red. Armed
module by module, starting with StrandAnalytics <-> com.noop.analytics
(differential=2, platform-test=0, exempt=2719).

Coverage is proof, not a label: parity_ratchet verify reads llvm-cov
lcov (FN/FNDA function records) and JaCoCo XML (method counters with
descriptor-arity disambiguation, so an executed overload can never
vouch for an unexecuted same-name sibling); line coverage is only a
fallback for method-less reports and says so. The proof caught a real
gap before landing: the runners never executed the Kotlin
default-parameter lines (fixed in the previous commit).

The merge-base ratchet compares shards and entries against the actual
git merge-base; counters may only fall, every entry needs an issue
(checked in CI via gh api; --offline in CI is a hard error). CI runs
on every pull request and push to main with the path decision inside
the job — "no-op" instead of "skipped" — and the touched-set includes
the harness, tools, shards and the workflow itself, not only the
production twin trees.

Two independent review rounds hardened all of the above (round 1:
lexer fail-closed holes incl. 297 phantom inventory entries from
bodyless Kotlin type spans, CI filter blind to its own tooling, shard
deletion as silent disarm, issue-field removal, same-line coverage
greenwashing, offline-in-CI; round 2: JaCoCo descriptor matching).
Verified on this machine: 51 unittest probes green; ratchet clean
against drift/meta; verify green with fresh real coverage from both
runners (errors=0).

Part of the drift-control plan in #17 (step 6).

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bhelm
bhelm merged commit 03e1a96 into drift/meta Aug 18, 2026
1 of 2 checks passed
@github-actions
github-actions Bot deleted the drift/06-coverage-ratchet branch August 31, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant