What is wrong
The repository measures branch coverage and then gates on lines.
Branch data is produced and preserved — scripts/coverage.sh exports LCOV
BRDA records and runs scripts/aggregate_lcov_branches.py to collapse
llvm-cov's per-template-instantiation noise into one record per source branch,
deliberately keeping branch coverage rather than dropping it. Codecov receives
it: the report carries 903 branches for include/morph and 2,279
repo-wide.
Nothing anywhere states a branch target. Every status and every component in
codecov.yml scores lines. So a branch taken one way only is visible in the
report and gates nothing.
On master that is 120 partial lines inside include/morph — 120 places
where a condition has been evaluated but only ever come out one way. Inverting
the if at any of them cannot fail a test, because no test has ever observed
the other arm.
Worst files:
| partials |
misses |
file |
| 19 |
5 |
include/morph/core/bridge.hpp |
| 19 |
5 |
include/morph/core/remote.hpp |
| 15 |
2 |
include/morph/util/rational.hpp |
| 12 |
36 |
include/morph/forms/forms.hpp |
| 12 |
52 |
include/morph/offline/sqlite_offline_queue.hpp |
| 6 |
1 |
include/morph/forms/instance_constraints.hpp |
| 5 |
1 |
include/morph/forms/views.hpp |
| 5 |
3 |
include/morph/core/registry.hpp |
bridge.hpp and remote.hpp are the two files the whole framework's dispatch
and wire behaviour live in.
Why a line target cannot substitute
A line target is satisfied by executing a line. if (a && b) is one line and
counts as covered the moment control reaches it, whatever a and b were. The
condition this repository actually wants held — a wrong comparison, a dropped
!, a < that should be <= is caught by a test — is a statement about
branches (and, at full strength, about MC/DC: each condition independently
shown to affect the outcome), not about lines.
This is the property SQLite states as its headline test claim, and it is the
reason it states it in terms of MC/DC rather than statements.
The constraint that makes the naive fix wrong
aggregate_lcov_branches.py exists because llvm-cov emits a BRDA record per
template instantiation, and morph is a header-only template library. A raw
branch percentage over un-aggregated records is meaningless here — dozens of
spurious partials for one source branch. Any branch target must be set on the
aggregated records that script produces, and its aggregation is therefore
load-bearing for the gate rather than merely cosmetic.
Second constraint: llvm-cov reports branch coverage, not MC/DC. Clang has
-fcoverage-mcdc (LLVM 18+), which is a different instrumentation mode with its
own limits — notably a hard cap on conditions per decision. Whether morph adopts
it, and at what cost, is part of this ticket rather than assumed by it.
Verification status: reproduced
Codecov API, branch master: include/morph aggregates to lines 5,716,
branches 903, partial lines 120. Per-file partial counts above are from the same
response. aggregate_lcov_branches.py (199 lines) and the BRDA handling in
scripts/coverage.sh:158-172 read from master.
Not verified: how many of the 120 are genuinely unreachable rather than
untested. Some certainly are — codecov.yml already documents a class of
llvm-cov closing-brace artifacts — and the split between "no test wrote this"
and "no input can reach this" is the substance of the work, not a preliminary to
it.
What would close this
- Branch coverage for
include/morph is reported as its own number and carries
a target, set from a measured ceiling in the way every line target in
codecov.yml already is.
- Each of the 120 partial lines is in exactly one of two states: covered by a
test that exercises the other arm, or recorded as unreachable with the
reason, in the manner codecov.yml's existing artifact audits use. A bare
suppression is not a disposition.
- A decision on
-fcoverage-mcdc is recorded either way — adopted, with its
condition-count cap and its cost stated, or declined, with why branch
coverage is judged sufficient here.
Blocked by morph#403: include/morph/net's 903-branch denominator excludes
a whole subsystem today, so both the count and the ceiling would be measured
against the wrong tree.
What is wrong
The repository measures branch coverage and then gates on lines.
Branch data is produced and preserved —
scripts/coverage.shexports LCOVBRDArecords and runsscripts/aggregate_lcov_branches.pyto collapsellvm-cov's per-template-instantiation noise into one record per source branch,
deliberately keeping branch coverage rather than dropping it. Codecov receives
it: the report carries 903 branches for
include/morphand 2,279repo-wide.
Nothing anywhere states a branch target. Every
statusand every component incodecov.ymlscores lines. So a branch taken one way only is visible in thereport and gates nothing.
On
masterthat is 120 partial lines insideinclude/morph— 120 placeswhere a condition has been evaluated but only ever come out one way. Inverting
the
ifat any of them cannot fail a test, because no test has ever observedthe other arm.
Worst files:
include/morph/core/bridge.hppinclude/morph/core/remote.hppinclude/morph/util/rational.hppinclude/morph/forms/forms.hppinclude/morph/offline/sqlite_offline_queue.hppinclude/morph/forms/instance_constraints.hppinclude/morph/forms/views.hppinclude/morph/core/registry.hppbridge.hppandremote.hppare the two files the whole framework's dispatchand wire behaviour live in.
Why a line target cannot substitute
A line target is satisfied by executing a line.
if (a && b)is one line andcounts as covered the moment control reaches it, whatever
aandbwere. Thecondition this repository actually wants held — a wrong comparison, a dropped
!, a<that should be<=is caught by a test — is a statement aboutbranches (and, at full strength, about MC/DC: each condition independently
shown to affect the outcome), not about lines.
This is the property SQLite states as its headline test claim, and it is the
reason it states it in terms of MC/DC rather than statements.
The constraint that makes the naive fix wrong
aggregate_lcov_branches.pyexists because llvm-cov emits aBRDArecord pertemplate instantiation, and morph is a header-only template library. A raw
branch percentage over un-aggregated records is meaningless here — dozens of
spurious partials for one source branch. Any branch target must be set on the
aggregated records that script produces, and its aggregation is therefore
load-bearing for the gate rather than merely cosmetic.
Second constraint: llvm-cov reports branch coverage, not MC/DC. Clang has
-fcoverage-mcdc(LLVM 18+), which is a different instrumentation mode with itsown limits — notably a hard cap on conditions per decision. Whether morph adopts
it, and at what cost, is part of this ticket rather than assumed by it.
Verification status: reproduced
Codecov API, branch
master:include/morphaggregates to lines 5,716,branches 903, partial lines 120. Per-file partial counts above are from the same
response.
aggregate_lcov_branches.py(199 lines) and theBRDAhandling inscripts/coverage.sh:158-172read frommaster.Not verified: how many of the 120 are genuinely unreachable rather than
untested. Some certainly are —
codecov.ymlalready documents a class ofllvm-cov closing-brace artifacts — and the split between "no test wrote this"
and "no input can reach this" is the substance of the work, not a preliminary to
it.
What would close this
include/morphis reported as its own number and carriesa target, set from a measured ceiling in the way every line target in
codecov.ymlalready is.test that exercises the other arm, or recorded as unreachable with the
reason, in the manner
codecov.yml's existing artifact audits use. A baresuppression is not a disposition.
-fcoverage-mcdcis recorded either way — adopted, with itscondition-count cap and its cost stated, or declined, with why branch
coverage is judged sufficient here.
Blocked by morph#403:
include/morph/net's 903-branch denominator excludesa whole subsystem today, so both the count and the ceiling would be measured
against the wrong tree.