fix(wiki): quarantine zero-citation pages instead of publishing (audit C-4)
compile_all's quarantine gate was guarded by `total_claims > 0`, so a page with no parseable citations — including the LLM-outage case where compile_concept returns an empty page — fell through to the publish branch and was written to wiki/ + marked compiled. Such a page carries zero grounding evidence. Now: total_claims == 0 (or grounding_rate below threshold) quarantines and does NOT update the compile-state, so a transient LLM failure retries next run instead of freezing an empty/uncited page as 'compiled'. Empty bodies are recorded but not written as draft files. Regression test reproduces the exact bypass (uncited LLM output -> quarantined, not published). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -722,17 +722,23 @@ def compile_all(
|
||||
# Detect conflicts between chunks from different bibkeys
|
||||
report.conflicts.extend(_detect_conflicts(concept.slug, chunks))
|
||||
|
||||
# Quarantine check: compute grounding rate
|
||||
# Quarantine check: compute grounding rate.
|
||||
# A page with NO citations at all (total_claims == 0) carries zero grounding
|
||||
# evidence — this also covers the LLM-outage case where compile_concept
|
||||
# returns an empty page — and must NOT be published (audit C-4). Previously
|
||||
# the `total_claims > 0` guard let such pages fall through to wiki/.
|
||||
total_claims = len(page.claims)
|
||||
grounded_claims = sum(1 for c in page.claims if c.grounded)
|
||||
grounding_rate = grounded_claims / total_claims if total_claims > 0 else 0.0
|
||||
|
||||
if total_claims > 0 and grounding_rate < settings.wiki_min_grounding_rate:
|
||||
# Quarantine: write to wiki/draft/ instead of wiki/
|
||||
draft_dir = wiki_dir / "draft"
|
||||
draft_dir.mkdir(parents=True, exist_ok=True)
|
||||
page_path = draft_dir / f"{concept.slug}.md"
|
||||
page_path.write_text(page.markdown, encoding="utf-8")
|
||||
if total_claims == 0 or grounding_rate < settings.wiki_min_grounding_rate:
|
||||
# Quarantine and do NOT update the compile-state, so a transient failure
|
||||
# (e.g. LLM outage) is retried on the next run instead of being frozen as
|
||||
# "compiled". An empty body is not worth a draft file — just record it.
|
||||
if page.markdown.strip():
|
||||
draft_dir = wiki_dir / "draft"
|
||||
draft_dir.mkdir(parents=True, exist_ok=True)
|
||||
(draft_dir / f"{concept.slug}.md").write_text(page.markdown, encoding="utf-8")
|
||||
report.quarantined.append(concept.slug)
|
||||
else:
|
||||
# Write page to wiki/
|
||||
|
||||
Reference in New Issue
Block a user