Repository navigation
drift/06: completeness ratchet — coverage as proof, exemptions as debt - #26
Merged
Merged
Conversation
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>
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.
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
initblocks, secondary constructors, operator functions, getter forms, multi-line computed properties — is an error, never a silent skip.parity-exempt.jsonper 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.verifyreads 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.git merge-base— counters only fall, new entries need an issue (checked in CI viagh api;--offlinein 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.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 (
windowSecstays explicit in Swift, which deliberately has no default — the documented one-sided default).Verification
drift/meta;verifygreen 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.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