feat(persona): load the falsification skill from commons at call time
[skip-docs] — the invariant row for this plan lands in Step 13, after the mutations. Amendment 2 in the same commit: the framework-neutrality sweep covered only expert-reviewer, so the skill that arrived by subtree pull had no framework guard anywhere. GUARDED_SKILL_DIRS names both, and a fail-closed coverage arm turns red when a future pull brings a third skill that is not listed. Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
21c476bbe7
commit
488a0f2b6c
3 changed files with 276 additions and 3 deletions
|
|
@ -54,3 +54,87 @@ def load_persona_example() -> PersonaExample:
|
|||
rationale=data["rationale"],
|
||||
marker=data["marker"],
|
||||
)
|
||||
|
||||
|
||||
# --- The falsification-reviewer skill (Step 12, D4) ----------------------------------------------
|
||||
# A SECOND shared Agent Skill, read the same way and for the same reason: it is authored in commons
|
||||
# and arrives by ``git subtree pull``, so a loader that consumes it is what keeps it from rotting
|
||||
# silently. Same call-time seam, same fail-fast discipline as the persona example above.
|
||||
|
||||
_FALSIFICATION_EXAMPLE_PATH: Path | None = None
|
||||
|
||||
_FALSIFICATION_SUBPATH = (
|
||||
Path("skills") / "falsification-reviewer" / "references" / "example-evidence.json"
|
||||
)
|
||||
|
||||
|
||||
def _falsification_example_path() -> Path:
|
||||
"""The worked example's location: the test seam if set, else resolved under ``shared_root()``."""
|
||||
if _FALSIFICATION_EXAMPLE_PATH is not None:
|
||||
return _FALSIFICATION_EXAMPLE_PATH
|
||||
return shared_root() / _FALSIFICATION_SUBPATH
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FalsificationConcept:
|
||||
"""One concept the worked example judged, with what the readers should derive from its bytes.
|
||||
|
||||
``frontmatter_verbatim`` is AUTHORITATIVE and is the only field a consumer should materialise
|
||||
from. The example also ships a line-oriented ``frontmatter`` projection, which is informative
|
||||
only: by construction it cannot carry a block form, so materialising from it would turn the
|
||||
unreadable case into an absent one — the tolerant read that widens the answer.
|
||||
"""
|
||||
|
||||
concept_id: str
|
||||
#: The document's frontmatter block exactly as written, newlines and indentation included.
|
||||
frontmatter_verbatim: str
|
||||
state: str
|
||||
reason: str | None
|
||||
items_seen: int
|
||||
trust_tier: str
|
||||
adjudication: str
|
||||
#: Whether the verdict was allowed to rest on this concept.
|
||||
relied_on: bool
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FalsificationExample:
|
||||
"""The falsification reviewer's worked example: one claim, the concepts consulted, the verdict.
|
||||
|
||||
``judgement`` is ``undecided`` in the shipped example, and deliberately not ``survived``: the
|
||||
one concept that could have carried a refutation was unreadable, so the claim was never
|
||||
actually attacked. Returning ``survived`` there would convert a gap in the knowledge base into
|
||||
support for the claim — the inversion this role exists to prevent.
|
||||
"""
|
||||
|
||||
claim: str
|
||||
judgement: str
|
||||
#: Who refuted the claim, or ``None`` when nobody did. A refutation that names no refuter is
|
||||
#: not a refutation (the ``verified``-without-an-actor rule, one layer up).
|
||||
refuter: str | None
|
||||
concepts: tuple[FalsificationConcept, ...]
|
||||
|
||||
|
||||
def load_falsification_example() -> FalsificationExample:
|
||||
"""Read the falsification skill's worked example. Fail-fast: a missing file raises
|
||||
``FileNotFoundError`` and a missing key raises ``KeyError`` (required input, contrast the
|
||||
tolerant Step-7 verdict inbox). Resolves the path at CALL time."""
|
||||
data = json.loads(_falsification_example_path().read_text(encoding="utf-8"))
|
||||
return FalsificationExample(
|
||||
claim=data["claim"],
|
||||
judgement=data["judgement"],
|
||||
refuter=data["refuter"],
|
||||
concepts=tuple(
|
||||
FalsificationConcept(
|
||||
concept_id=c["concept_id"],
|
||||
frontmatter_verbatim=c["frontmatter_verbatim"],
|
||||
state=c["evidence"]["state"],
|
||||
reason=c["evidence"]["reason"],
|
||||
items_seen=c["evidence"]["items_seen"],
|
||||
trust_tier=c["derived"]["trust_tier"],
|
||||
adjudication=c["derived"]["adjudication"],
|
||||
relied_on=c["relied_on"],
|
||||
)
|
||||
for c in data["concepts"]
|
||||
),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue