Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/vouch/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ def _rate(numerator: int, denominator: int) -> float | None:

def citation_summary(store: KBStore) -> dict[str, Any]:
claims, findings = health._load_claims_for_lint(store)
sources_present = {s.id for s in store.list_sources()}
# Use the lint source collector, not list_sources(): a corrupt meta.yaml
# is still present on disk (id = directory name) and must not be counted
# as a broken citation — same invariant as health.lint (#81 follow-up).
sources_present, _ = health._collect_sources_for_lint(store)
evidence_present = {e.id for e in store.list_evidence()}

invalid_claim = sum(
Expand Down
14 changes: 14 additions & 0 deletions tests/test_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@ def test_citation_summary_flags_broken_and_invalid(store: KBStore) -> None:
assert summary["claims_with_valid_citation"] == 1


def test_citation_summary_honest_when_source_meta_unreadable(store: KBStore) -> None:
"""Corrupt source meta must not inflate broken_citation — mirrors lint."""
src = store.put_source(b"e")
store.put_claim(Claim(id="c1", text="t", evidence=[src.id]))
meta = store.kb_dir / "sources" / src.id / "meta.yaml"
meta.write_text(
meta.read_text(encoding="utf-8") + "title: conversation \u00e2\u0080\u0094 vouch\n",
encoding="utf-8",
)
summary = stats.citation_summary(store)
assert summary["broken_citation"] == 0
assert summary["claims_with_valid_citation"] == 1


def test_pending_summary_by_agent(store: KBStore) -> None:
src = store.put_source(b"x")
propose_claim(store, text="a", evidence=[src.id], proposed_by="agent-a")
Expand Down
Loading