Skip to content

fix(coverage): count coverage gaps by one shared rule - #83

Merged
dejo1307 merged 1 commit into
mainfrom
fix/receipt-coverage-gap-classification
Jul 9, 2026
Merged

fix(coverage): count coverage gaps by one shared rule#83
dejo1307 merged 1 commit into
mainfrom
fix/receipt-coverage-gap-classification

Conversation

@dejo1307

@dejo1307 dejo1307 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

The snapshot receipt classified a service as a coverage gap whenever it had any unresolved outbound call site, while coverage_report and the coverage explainer both required outbound == 0 — no resolved edges at all. Since unresolved is derived as detected - resolved - external, every healthy client service has some, so the receipt's metric saturated: it equalled services_total on healthy input and could not signal ill health. llm_context.md prints that number behind a warning sign, so the file an agent reads without a tool call carried the inflated count.

Hoist the rule into facts.ClassifyService, with facts.DependsOnCount replacing the two duplicate outbound counters. coverageSummary, buildCoverageReport and the coverage explainer now all classify through it, so they cannot drift apart again. Also decouple UnresolvedEdges from the gap condition — it accumulates for every service, gapped or not.

On a four-service multi-repo snapshot the receipt now agrees with coverage_report; unresolved_edges is unchanged. facts.jsonl and insights.json are byte-identical across the change.

No cacheVersion bump: coverageSummary feeds receipt.json only (via both engine.go and global_receipt.go), no extractor output changes, and TestGolden passes without -update.

The existing svcCoverage test helper attaches no relations, so every fixture had outbound == 0 and TestCoverageSummary_ExternalBucket returned the same answer under either rule. Add the case that distinguishes them.

The snapshot receipt classified a service as a coverage gap whenever it
had any unresolved outbound call site, while coverage_report and the
coverage explainer both required outbound == 0 — no resolved edges at
all. Since unresolved is derived as detected - resolved - external, every
healthy client service has some, so the receipt's metric saturated: it
equalled services_total on healthy input and could not signal ill health.
llm_context.md prints that number behind a warning sign, so the file an
agent reads without a tool call carried the inflated count.

Hoist the rule into facts.ClassifyService, with facts.DependsOnCount
replacing the two duplicate outbound counters. coverageSummary,
buildCoverageReport and the coverage explainer now all classify through
it, so they cannot drift apart again. Also decouple UnresolvedEdges from
the gap condition — it accumulates for every service, gapped or not.

On a four-service multi-repo snapshot the receipt now agrees with
coverage_report; unresolved_edges is unchanged. facts.jsonl and
insights.json are byte-identical across the change.

No cacheVersion bump: coverageSummary feeds receipt.json only (via both
engine.go and global_receipt.go), no extractor output changes, and
TestGolden passes without -update.

The existing svcCoverage test helper attaches no relations, so every
fixture had outbound == 0 and TestCoverageSummary_ExternalBucket returned
the same answer under either rule. Add the case that distinguishes them.
@dejo1307
dejo1307 merged commit c748456 into main Jul 9, 2026
4 checks passed
@dejo1307
dejo1307 deleted the fix/receipt-coverage-gap-classification branch July 18, 2026 06:54
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