feat(synthesis): F-13 synthesis/lead-engine — grounded leads + conjecture quarantine #3
@@ -102,6 +102,13 @@ class Lead:
|
|||||||
# Derived: claim-level grounding decisions (empty for conjectures).
|
# Derived: claim-level grounding decisions (empty for conjectures).
|
||||||
claims: list[Claim] = field(default_factory=list)
|
claims: list[Claim] = field(default_factory=list)
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
if not self.provenance:
|
||||||
|
raise ValueError(
|
||||||
|
f"Lead '{self.id}' must carry at least one Provenance entry. "
|
||||||
|
"For gap leads with no chunks, use a topic-marker Provenance."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Protocols
|
# Protocols
|
||||||
@@ -432,7 +439,7 @@ def find_gaps(
|
|||||||
f"The retrieval layer returned no chunks for topic '{topic}'.\n"
|
f"The retrieval layer returned no chunks for topic '{topic}'.\n"
|
||||||
"No grounded statement is possible; this is the absence itself."
|
"No grounded statement is possible; this is the absence itself."
|
||||||
),
|
),
|
||||||
provenance=[],
|
provenance=[Provenance(bibkey="(none)", locator=f"topic:{topic}")],
|
||||||
confidence=1.0,
|
confidence=1.0,
|
||||||
status="unverified",
|
status="unverified",
|
||||||
suggested_validation=(
|
suggested_validation=(
|
||||||
@@ -797,12 +804,7 @@ def write_leads(leads: list[Lead], leads_dir: str) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _update_index(root: Path) -> None:
|
def _update_index(root: Path) -> None:
|
||||||
"""Re-build ``root/INDEX.md`` from the on-disk files.
|
"""Re-build ``root/INDEX.md`` from the on-disk files (full rebuild, not append-only)."""
|
||||||
|
|
||||||
Append-only semantics: previously listed ids that no longer have a
|
|
||||||
file are still recorded under "Removed" so the index never silently
|
|
||||||
loses provenance.
|
|
||||||
"""
|
|
||||||
grounded_dir = root / "grounded"
|
grounded_dir = root / "grounded"
|
||||||
conj_dir = root / "conjectures"
|
conj_dir = root / "conjectures"
|
||||||
grounded_files = sorted(grounded_dir.glob("*.md")) if grounded_dir.exists() else []
|
grounded_files = sorted(grounded_dir.glob("*.md")) if grounded_dir.exists() else []
|
||||||
|
|||||||
@@ -78,6 +78,19 @@ def test_lead_missing_provenance_field_raises() -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_lead_empty_provenance_raises() -> None:
|
||||||
|
"""Constructing Lead with empty provenance list raises ValueError."""
|
||||||
|
with pytest.raises(ValueError, match="at least one Provenance"):
|
||||||
|
Lead(
|
||||||
|
id="L-0004",
|
||||||
|
kind="connection",
|
||||||
|
title="x",
|
||||||
|
body="y",
|
||||||
|
provenance=[],
|
||||||
|
confidence=0.5,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_lead_id_format_helper() -> None:
|
def test_lead_id_format_helper() -> None:
|
||||||
"""The internal _make_lead_id helper produces zero-padded L-XXXX strings."""
|
"""The internal _make_lead_id helper produces zero-padded L-XXXX strings."""
|
||||||
from codex.synthesis import _make_lead_id
|
from codex.synthesis import _make_lead_id
|
||||||
|
|||||||
Reference in New Issue
Block a user