fix(coverage): reconcile contradictory LCOV opener counts - #538
seonghobae wants to merge 45 commits into
Conversation
PR #490 removed the local `schedule` trigger from the hourly contextual-orchestrator workflow so the organisation `.github` development coordinator owns the cadence, but the contract test still required `cron: "47 * * * *"`. The shared Python branch-coverage job has been failing on main since that merge. The test now asserts the absence of any local `schedule` trigger instead of a cron expression, and the runbook describes central admission rather than minute 47. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A draft pull request iterating rapidly cancels and re-enqueues the two repository-local workflows on every push. Measured on 2026-09-14 at 19:07Z, all 90 cancelled runs among the 100 most recently completed runs belonged to one draft branch, against 10 successful and 2 failed runs. Queued work was spread evenly at nine runs per branch, so the queue itself was fair; the churn was one branch cancelling and replacing its own runs faster than they could finish. Both workflows now guard every job on the pull request not being a draft, and `ci.yml` adds `ready_for_review` to its trigger types so the gates it skipped run in full the moment a draft is marked ready. No gate is removed and no gate is weakened: a draft cannot merge, and a job skipped by `if` satisfies a required check. The paired contract test asserts the guard appears once per job in each workflow, so a future job cannot be added without it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The draft guard in this branch covers exploratory iteration on drafts. It cannot cover a pull request that is ready for review, where cancelling a superseded run is correct behaviour and the waste comes from push cadence rather than CI configuration. Records the remaining half as a contract: while the queue is behind, an intermediate head cannot merge, so the runner time its cancelled run consumed is taken from work that can. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The batching contract as written could be read as a reason to delay a fix for a failing required check. That inverts the intent: batching exists because an intermediate head cannot merge, so a commit that changes what the queue can merge must not be held back. Names the three cases explicitly, following the same exemptions a peer session recorded for contextual-orchestrator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`is_executable_source_line` excluded any line that is only a string
literal, to drop formatting noise from the authored-line denominator. A
Rust match arm whose entire body is one literal has exactly that shape,
so every such arm was invisible to the line-coverage gate and a zero
count for it could never fail the contract.
Four arms in `psychometric_core`'s error Display had never been executed.
The gate reported PASS at 11141/11141 over the same LCOV report that
contained their zero counts.
The exclusion now yields when the previous meaningful line ends the arm
pattern with `=>` or `=> {`, which distinguishes an arm body from a
literal continuing an ordinary binding. Comment lines between the pattern
and the body are skipped.
Adds the four missing Display assertions so the newly counted arms are
covered, and two checker tests pinning both directions of the narrowed
rule.
With the narrowed rule the authored-line denominator grows from 11141 to
11360. It fails at 11356/11360 on the report taken before the Display
tests, and passes at 11360/11360 after them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`Ok(())` on its own line was listed with structural punctuation such as `});` and `};` and dropped from the authored-line denominator. It is not punctuation: it is the success path of a fallible function, and a zero count on it means that function never succeeded under test. Removing it from the exclusion set adds 148 lines to the workspace denominator, all of them already covered, so this is a regression guard rather than a repair. The gate reports 11507/11507 where it previously reported 11360/11360. The existing noise-filter fixture used that line as its example of a structural record; it now asserts the opposite, which also restores coverage of the two checker branches that fixture was the only caller of. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Preserve #523 queue-control work while inheriting #525's valid coverage-gate delta through an ordinary two-parent merge. The inherited change makes standalone string match-arm bodies and Ok(()) success returns count as executable authored production lines, adds the corresponding checker regressions, and covers the four MANIFESTVARstd Display arms that the corrected denominator exposes. No force update, no denominator weakening, and no predecessor check transfer.
RED contracts for the two current review findings on #523: both repository-local PR workflows must subscribe to converted_to_draft so an in-flight ready run can be cancelled, and authored-line coverage must retain match-arm string bodies after one-line or multiline Rust block comments. No implementation change in this commit.
…nt arm bodies Repair both current #523 review findings after the RED contracts in 4279910. Repository-local PR workflows now subscribe to converted_to_draft so the PR-scoped concurrency group cancels an in-flight ready run when the PR returns to draft. The authored-line classifier now skips standalone one-line and multiline Rust block comments while walking backward from a string-literal match-arm body, including the LCOV denominator path. Keep the fix narrow: no gate weakening, no coverage exclusion, and no runner bypass.
RED for the current #523 review finding. A match-arm label with a trailing Rust line comment must still make its standalone string body executable for authored-line and LCOV denominator accounting, including a string-pattern URL containing `//`. No classifier implementation change in this commit.
`cargo deny check` fails on main. RUSTSEC-2026-0285 (GHSA-2mjx-qc3c-rqvc, CVE-2025-61730) reports that rustls accepted TLS 1.3 handshake messages across encryption level boundaries, and the workspace pinned `rustls = "=0.23.43"`, below the fixed `0.23.45`. The pin reaches the dependency graph twice, directly through `service_tls` and transitively through `sqlx-core` under `persistence_postgres`, so the whole workspace carried the vulnerable version. Because the requirement is an exact pin, `cargo update -p rustls` could not move it; the manifest had to change. This is a patch-level move within 0.23 and touches only the pin and the lockfile. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The block-comment handling added for #523's review findings left the Python gate at 99%: four statements and three partial branches in `_is_match_arm_body` had no test. Four fixtures reach them: a blank line between the arm label and its literal body, a multi-line comment whose opener owns its line, a trailing `/* note */` on the arm label, and a multi-line comment opened by the arm label itself. One branch could not be reached. A line starting with `/*` is consumed by the earlier guard, so the text before the opener in the combined `/* ... */` case is never empty and its emptiness check was dead. Removed, with the reason recorded where it stood. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…tract' into fix/rustls-tls-handshake-advisory
My earlier commit on this branch added a `## [Unreleased]` heading above `## [0.2.0]` without noticing the file already had one below it, leaving two sections with the same name. The advisory entry moves into the existing Unreleased `### Security` subsection and the duplicate heading is gone. The pre-existing ordering, where `[0.2.0]` sits above `[Unreleased]`, is left alone. Keep a Changelog puts Unreleased first, so that is a real defect, but it belongs with GAP-014's remaining CHANGELOG work rather than a security-fix branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Restore the stacked parent's root CHANGELOG entry and preserve #526's security release note as a CHANGELOG.d fragment, matching the repository's existing non-force conflict-disposition pattern. The fragment records only RUSTSEC-2026-0285 / GHSA-2mjx-qc3c-rqvc as the rustls advisory identity and explicitly distinguishes CVE-2025-61730 as the functionally similar Go crypto/tls issue. This removes the incorrect rustls CVE attribution from the tree without discarding the security note.
`main` fails its own line-coverage gate at 11140/11141. The single missing line is `persistence_postgres/src/migration.rs:140`, and the record is impossible: line 140 opens an `if` whose body on line 141 reports two executions, so the condition cannot have run zero times. Nothing in the source is uncovered. The counter is wrong, and the gate counts it as a production gap, so every branch based on `main` inherits a failing job regardless of content. `drop_contradictory_zero_counts` removes a zero count when the line opens a brace-delimited block and the first line inside it carries a positive count. That pairing is a logical contradiction, so the zero cannot be evidence of uncovered behavior. The rule is deliberately narrow. A zero whose body also reports zero is a real gap and is kept. A zero on a line that opens no block is kept. A zero with no measured line beneath it is kept. Tests pin all three, so the exclusion cannot widen into hiding genuine gaps. With it, plain `main` reports PASS at 11140/11140. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughCI의 pull request 이벤트와 draft 실행 조건을 조정했습니다. Rust 커버리지 판정과 LCOV 집계를 수정했습니다. rustls 버전, 시간별 운영 방식, 오류 메시지 테스트를 갱신했습니다. ChangesCI 큐 제어
Rust 커버리지 집계
rustls 보안 업데이트
시간별 NIM 운영 방식
오류 메시지 계약 검증
Priority: ⬆️ High Estimated code review effort: 4 (Complex) | ~45 minutes Change: Bug fix · Severity of issue fixed: High Possibly related PRs
Merge Risk: ⚪ Minimal · up to The reviewed changes include regression coverage for the revised coverage accounting and workflow boundaries. No concrete remaining merge-blocking risk is identified. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Second independent sample, different author and different subsystemI said in the description that I had verified the mechanism on #416 (
Three trees, two of them other people's work on unrelated subsystems, all showing the identical impossible record. The counts around it match to the digit, which is what you would expect if the artifact is a property of the file and toolchain rather than of any change. That is now strong enough to say the 18 pull requests failing What it does not changeThe fix here is still the narrow rule, not a coverage exemption. A zero count is dropped only when a line strictly inside the block it opens carries a positive count, which cannot both be true. Genuine gaps keep failing, and the four tests pin that in both directions. Neither branch was modified. Both were fetched read-only into a scratch worktree. |
seonghobae
left a comment
There was a problem hiding this comment.
Valid finding, but the current causal repair violates the repository's own coverage-denominator rule. drop_contradictory_zero_counts deletes the authored opener from line_counts, and the claimed result changes 11140/11141 into 11140/11140. The evidence proves the opener's zero count is contradictory because a nested body executed; it does not prove the authored opener ceased to exist. Preserve the denominator and repair the measurement instead: when an executable block opener has count 0 and the immediately nested measured body has a positive count, promote/canonicalize the opener to a positive covered count (or equivalent evidence-preserving representation), so the expected result is 11141/11141, while opener/body both zero, non-block zeros, and unproven cases remain uncovered. Add a regression that asserts both total count and covered count stay 3/3 for the synthetic (2,9),(3,0),(4,2),(6,7) case. Carry this correction only through the #523 successor lineage; the current stale-base synthetic merge ref is not authority.
|
Fresh exact-head settlement on
Security RCA is exact and external to this branch's product/source delta. Dependency-review job Canonical owner paths are TEPP #498 for the repository-specific dependency-graph incident and |
Lead dig (2026-09-19T130411Z) — merge-prep, not hold-and-forgetOwner: @seonghobae (PR author). Diff validated as substantive/valid (coverage LCOV opener reconciliation + rustls advisory + hourly NIM cleanup). Core repo/python/coverage checks are GREEN; 6 RED are bot/advisory/platform — not grounds to abandon. FAILURE ownership
Repair worker: Orca Independent review: same shared GitHub identity authored this PR → cannot APPROVE own PR. Needs a different identity when gates are green. Evidence dig: lead worktree |
Main-target successor authority
This PR is the protected-
mainsuccessor carrying #523's foundation/lifecycle delta, #526'srustls >=0.23.45advisory repair, #538's denominator-preserving LCOV reconciliation, and the current CodeQL-required workflow repair through ordinary-forward history.Current exact head:
f335624cea977fea7d7fe6f36871868557fe2bb7. Protected base remainsmain@a243f18da4a4ca8a8d068c39922537f1f8ed6ad0.Inherited repairs
rustls 0.23.43advisory failure.rustls = 0.23.45rather than suppressing RUSTSEC-2026-0285 / GHSA-2mjx-qc3c-rqvc.df389349...,680790b...,d304335...,dbe58f1...,758e06d..., and0a6947b...preserve the lexical and fail-closed coverage edge repairs without denominator shrink, skip/xfail, or threshold changes.#594 CodeQL Actions RED → causal repair
Canonical
.githubdispatch run35276762974for required CodeQL run35045658451produced twoactions/cache-poisoning/poisonable-stepfindings in.github/workflows/hourly-nim-product-development.yml. Both findings are in thepackage_product_incrementverifier after the immutable generated proposal has been applied. The verifier then restored~/.cargo/binwithactions/cache@v5; on a miss, the post action could persist bytes mutated while release-quality gates execute proposal code under static default-branch cache keys.Ordinary-forward RED
af3e0bc5dcbf4d5248ca5ace862680b09378dca8, corrected without removing the RED at24241780ee791d4811e06b9ec1dc3a04556836c3, addstests/quality/test_hourly_nim_cache_boundary.py. It requires the verifier to contain noactions/cache@and to retain pinned direct installs ofcargo-nextest 0.9.140,cargo-deny 0.19.7, andcargo-llvm-cov 0.8.6.Causal repair
f335624cea977fea7d7fe6f36871868557fe2bb7removes the two writable cache actions and their cache-hit branches, and installs the same pinned tools directly before any proposal code is executed. The immutable artifact/patch identity checks, exact-base checkout, credential stripping, Python/Rust/rustdoc/dependency/coverage gates, and separate late publication boundary remain unchanged. No CodeQL suppression, SARIF-gate weakening, cache-rule exclusion, force push, or destructive rebase is used.The same central dispatch also showed a separate Python-shard failure at
Verify GHAS base/head CodeQL configuration identity; Python SARIF itself had zero findings. That remains an independent GHAS configuration-identity prerequisite and is not claimed fixed by #594.Promotion boundary
This exact head must reacquire all evidence before merge: denominator-preserving authored line/branch 100%, repository/Python branch 100%, Live PostgreSQL, rustfmt/Clippy/tests/rustdoc, dependency policy free of RUSTSEC-2026-0285, Documentation Quality, Security Scan, Semgrep, exact-head CodeQL with the two Actions cache-poisoning findings removed, organization-required workflows, resolved valid findings, and qualifying independent approval.
Issue #498 remains fail-closed because repository Dependency Graph support is an administrator-owned prerequisite. Predecessor PRs #523 and #526 stay open until normal #538 landing or separately verified complete inheritance. No bypass, self-approval, advisory suppression, predecessor-head evidence transfer, destructive rebase, or force push is permitted.
Summary by CodeRabbit
보안 업데이트
CI 개선
품질 개선
문서