Skip to content

test: add coverage tooling and de-duplicate the suite's helpers and cases - #86

Merged
samkeen merged 4 commits into
mainfrom
claude/test-coverage-curation-ueb3r8
Jul 25, 2026
Merged

test: add coverage tooling and de-duplicate the suite's helpers and cases#86
samkeen merged 4 commits into
mainfrom
claude/test-coverage-curation-ueb3r8

Conversation

@samkeen

@samkeen samkeen commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Adds source-based coverage (cargo-llvm-cov) and does the first pass of a
curation sweep over the test suite.

Coverage

  • just coverage / coverage-html / coverage-lcov measure b2-core, mirroring
    what just test runs, so the number is as fast as the suite and pulls in no ML
    deps. just coverage-all adds the CLI adapter (its tests spawn the instrumented
    b2 binary, so process-level runs count); that one is heavier on a cold cache
    because b2-cli depends on b2-embed.
  • Real-model paths stay out on purpose: they are exercised by just eval, not by
    cargo test, so instrumenting them would report a permanent, meaningless 0%.

Shared helpers
tests/common/mod.rs held three items while nine files carried their own
byte-identical reindexed(), six their own count(), four their own
ingest_golden(), three their own index_conn(), and ingest_resolver.rs
re-declared FixedId/copy_dir/golden_vault_copy outright. All now live in
common. The tracing Capture writer is deliberately left duplicated in the two
files that need it — hoisting it would make ~28 test binaries link
tracing-subscriber to serve two, and those two are documented as needing their own
binary anyway.

Duplicate cases folded into their canonical home

  • tests/links.rs deleted: it re-tested src/link.rs, which has its own unit
    tests. Its four genuinely-unique cases (the lowercase verb-lookalike hazard, the
    document-order pair, alias vs caption, the : separator + tail verb) moved
    in beside them.
  • vault.rs now asserts the unknown-ref refusal once across read/neighbors/
    explain/similar, and index-first honesty once across search/list_notes; the
    per-op singles in read.rs, explain.rs and list.rs are gone.
  • Stamping is stamp.rs's subject alone; the partial restatements in vault.rs
    and ingest_resolver.rs are gone.
  • graph.rs's two neighbour tests were one edge set viewed from each end; merged.
  • roundtrip.rs drops the no-frontmatter case, which props.rs's 512-case
    round-trip property already covers, and says so.

231 tests, from 245. No behaviour is newly untested; cargo test -p b2-core green.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01GjVA1fAW4ncDhUJ5cGHezt

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation for search behavior when swapping embedding models, with clear mismatch handling until reindexing completes.
    • Strengthened link/relation parsing so ordinary prose isn’t misinterpreted as typed edges, and : is accepted as an explanation separator.
    • Enhanced snippet display so matched terms remain visible within the surrounding window.
  • Tests

    • Expanded and refocused coverage across links, relations, graph navigation, resolution, chunking, and search.
    • Improved embedding batch validation coverage (and removed a now-obsolete ignored batch integration test).
  • Documentation

    • Added and documented cargo llvm-cov/just coverage workflows; updated testing conventions; cleaned up coverage artifacts ignore rules.

claude added 3 commits July 25, 2026 04:50
…ases

Adds source-based coverage (cargo-llvm-cov) and does the first pass of a
curation sweep over the test suite.

Coverage
- `just coverage` / `coverage-html` / `coverage-lcov` measure b2-core, mirroring
  what `just test` runs, so the number is as fast as the suite and pulls in no ML
  deps. `just coverage-all` adds the CLI adapter (its tests spawn the instrumented
  `b2` binary, so process-level runs count); that one is heavier on a cold cache
  because b2-cli depends on b2-embed.
- Real-model paths stay out on purpose: they are exercised by `just eval`, not by
  `cargo test`, so instrumenting them would report a permanent, meaningless 0%.

Shared helpers
`tests/common/mod.rs` held three items while nine files carried their own
byte-identical `reindexed()`, six their own `count()`, four their own
`ingest_golden()`, three their own `index_conn()`, and `ingest_resolver.rs`
re-declared `FixedId`/`copy_dir`/`golden_vault_copy` outright. All now live in
`common`. The tracing `Capture` writer is deliberately left duplicated in the two
files that need it — hoisting it would make ~28 test binaries link
tracing-subscriber to serve two, and those two are documented as needing their own
binary anyway.

Duplicate cases folded into their canonical home
- `tests/links.rs` deleted: it re-tested `src/link.rs`, which has its own unit
  tests. Its four genuinely-unique cases (the lowercase verb-lookalike hazard, the
  document-order pair, `alias` vs `caption`, the `:` separator + tail verb) moved
  in beside them.
- `vault.rs` now asserts the unknown-ref refusal once across read/neighbors/
  explain/similar, and index-first honesty once across search/list_notes; the
  per-op singles in `read.rs`, `explain.rs` and `list.rs` are gone.
- Stamping is `stamp.rs`'s subject alone; the partial restatements in `vault.rs`
  and `ingest_resolver.rs` are gone.
- `graph.rs`'s two neighbour tests were one edge set viewed from each end; merged.
- `roundtrip.rs` drops the no-frontmatter case, which `props.rs`'s 512-case
  round-trip property already covers, and says so.

231 tests, from 245. No behaviour is newly untested; `cargo test -p b2-core` green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjVA1fAW4ncDhUJ5cGHezt
…behind #[ignore]

Second curation pass. The first one removed duplication; this one fixes tests that
claimed more than they checked and adds the ones the coverage report showed missing.

Gaps closed (b2-core lines 91.13% → 92.06%, regions 87.78% → 88.86%, functions
94.27% → 95.52%)
- `relation.rs` had **no tests at all** and `is_symmetric` was never executed —
  `contradicts` being its own inverse is the one non-trivial fact in the relation
  vocabulary, and nothing asserted it. Now 76.92% → 100%, covering the closed core's
  membership, symmetry, and the tail-verb fallbacks for both symmetry and labels.
- `vault::query_snippet` was entirely uncovered: every fixture chunk is shorter than
  the 160-char snippet budget, so the windowing branch — the thing that makes a
  section-sized chunk show the matched term rather than its head — never ran. Its own
  comment flags a Unicode clamp hazard. `tests/search.rs` now exercises both the
  window and the head fallback.
- `search` failing fast on a model swap is documented in CLAUDE.md as load-bearing
  ("rather than returning silently-wrong results") and had no test. `tests/embed.rs`
  now covers the swap → refusal → reindex-heals cycle, including that `open` leaves
  the stored vectors alone.
- `graph_filtered_search` had the "no silent cap above the reachable set" half
  pinned but not that `limit` truncates below it; added beside it.

Tests that overclaimed
- `chunks.rs::weights_are_a_lever_a_giant_heading_weight_pulls_the_cut` applied no
  giant weight — it used `BreakWeights::default()`, so the `weights` lever was never
  tested. It now compares default against flattened heading weights and asserts the
  cuts actually move, which is what the name promised.
- `ui`'s `npm test` hand-enumerated ten files, so a new `*.test.ts` was silently
  skipped until someone remembered package.json. Now node's own runner over a glob.

#[ignore]
`b2-embed/tests/batch.rs` was the repo's only `#[ignore]`, against CLAUDE.md's own
rule, and so had effectively never run. Batched-vs-single embedding equivalence is a
correctness gate for every stored vector, so it moves into the eval harness — where
real-model work belongs, and where `just eval` actually runs it on every invocation.
The convention now says so explicitly.

`cargo test -p b2-core` 236 green, `-p b2-cli` 41 green, `npm test` 10 green,
fmt/clippy clean (the two remaining clippy warnings predate this branch).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjVA1fAW4ncDhUJ5cGHezt
`just coverage-app` mirrors `just check-app`: builds ui/dist first, then covers
b2-desktop's own unit tests. Kept out of the other coverage recipes for the same
reason clippy keeps it out of the fast gate — it needs the platform webview
toolchain. A low number there is expected by design; the host is a dumb adapter
and its behaviour is covered by the façade suite.

Unverified in this environment: b2-desktop needs GTK system libraries that the
container lacks, so the recipe is written to match check-app's working pattern
rather than confirmed by a run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjVA1fAW4ncDhUJ5cGHezt
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fa6a549-0249-487a-9fa1-423d35bd02b9

📥 Commits

Reviewing files that changed from the base of the PR and between a8806d2 and c8908ba.

📒 Files selected for processing (2)
  • crates/b2-embed/examples/eval.rs
  • justfile

📝 Walkthrough

Walkthrough

The PR centralizes core integration-test fixtures, adds coverage for parsing, relations, chunking, search, graph, and embedding contracts, introduces an eval-time batch embedding gate, and adds repository coverage workflows plus frontend test discovery updates.

Changes

Core validation

Layer / File(s) Summary
Shared integration-test foundation
crates/b2-core/tests/common/*, crates/b2-core/tests/*.rs
Shared vault, indexing, counting, and ingestion helpers replace duplicated test setup across core integration tests.
Behavioral contract coverage
crates/b2-core/src/{link,relation}.rs, crates/b2-core/tests/{chunks,embed,graph,search,vault}.rs
Tests cover relation parsing, heading weighting, model-dimension mismatches, graph directions, search limits and snippets, and missing-reference behavior.
Batch embedding correctness gate
crates/b2-embed/examples/eval.rs
Evaluation now compares batch and single-text embeddings before continuing.
Coverage and test workflows
.gitignore, CLAUDE.md, justfile, ui/package.json
Coverage recipes and artifact exclusions were added, testing guidance was expanded, and frontend tests now run from a glob pattern.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EvalRun
  participant LocalEmbedder
  participant BatchCheck
  EvalRun->>LocalEmbedder: load model
  EvalRun->>BatchCheck: validate batch embeddings
  BatchCheck->>LocalEmbedder: embed batch texts
  BatchCheck->>LocalEmbedder: embed texts individually
  BatchCheck-->>EvalRun: pass or return validation error
Loading

Possibly related PRs

Suggested reviewers: claude

Poem

I’m a rabbit with tests in my burrow,
Where shared little helpers now grow.
Batch vectors compare,
Coverage blooms there,
And every new test gets a go!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: new coverage tooling plus test-suite helper and case deduplication.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/test-coverage-curation-ueb3r8

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/b2-embed/examples/eval.rs`:
- Around line 395-402: Update the cosine validation in the batched-versus-single
embedding check to reject non-finite values before evaluating the 0.9999
threshold. Ensure NaN and infinities return the existing descriptive error path,
while finite cosine results retain the current threshold behavior.

In `@justfile`:
- Around line 60-61: Remove the unsupported --summary-only argument from the
cargo llvm-cov commands in the coverage, coverage-all, and coverage-app targets,
leaving their existing package and coverage options unchanged so the default
summary output is generated successfully.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: efd6cb59-12b9-489c-8e8b-f9af28da55b1

📥 Commits

Reviewing files that changed from the base of the PR and between 4b9391e and a8806d2.

⛔ Files ignored due to path filters (1)
  • ui/ui/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (29)
  • .gitignore
  • CLAUDE.md
  • crates/b2-core/src/link.rs
  • crates/b2-core/src/relation.rs
  • crates/b2-core/tests/add.rs
  • crates/b2-core/tests/cancel.rs
  • crates/b2-core/tests/chunks.rs
  • crates/b2-core/tests/common/mod.rs
  • crates/b2-core/tests/dirs.rs
  • crates/b2-core/tests/discover.rs
  • crates/b2-core/tests/embed.rs
  • crates/b2-core/tests/explain.rs
  • crates/b2-core/tests/graph.rs
  • crates/b2-core/tests/ingest_resolver.rs
  • crates/b2-core/tests/links.rs
  • crates/b2-core/tests/list.rs
  • crates/b2-core/tests/mv.rs
  • crates/b2-core/tests/project_embed.rs
  • crates/b2-core/tests/read.rs
  • crates/b2-core/tests/rm_delete.rs
  • crates/b2-core/tests/roundtrip.rs
  • crates/b2-core/tests/search.rs
  • crates/b2-core/tests/vault.rs
  • crates/b2-core/tests/write.rs
  • crates/b2-core/tests/write_frontmatter.rs
  • crates/b2-embed/examples/eval.rs
  • crates/b2-embed/tests/batch.rs
  • justfile
  • ui/package.json
💤 Files with no reviewable changes (2)
  • crates/b2-embed/tests/batch.rs
  • crates/b2-core/tests/links.rs

Comment thread crates/b2-embed/examples/eval.rs
Comment thread justfile Outdated
…(CodeRabbit)

Two review findings on #86.

`check_batch_matches_single` gated on `cos <= 0.9999`, but every comparison against
a NaN is false — so a NaN cosine would pass the gate silently, which is the one
failure mode a correctness check must not have. Non-finite is now rejected first,
with its own message.

The coverage recipes passed `--summary-only`, which cargo-llvm-cov documents as
valid only alongside --json/--lcov/--cobertura. It is dropped, though not for the
reason reported: 0.8.7 accepts and ignores it in text mode, so the recipes ran fine
(they produced the numbers in the PR description). The flag simply buys nothing —
the default text report already is the per-file summary — and would break if a
later release starts enforcing the documented constraint. Noted in the justfile so
it does not come back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GjVA1fAW4ncDhUJ5cGHezt
@samkeen
samkeen merged commit 4fb9944 into main Jul 25, 2026
1 check was pending
@samkeen
samkeen deleted the claude/test-coverage-curation-ueb3r8 branch July 25, 2026 16:22
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.

2 participants