feat(consume): instantiate the K2 consumption skill, and document the pre-pass
Step 12's README section is brought forward to here because the docs gate is
right: a feat commit that ships a new command needs the command documented.
CLAUDE.md's Commands section gains the pre-pass beside `okf build`. Nothing
else moves.
Contract check against a real payload from the 629-concept bundle:
$ .venv/bin/python tools/okf_consume.py <K2-bundle> \
--question 'Hvordan skal prisene fylles ut?' --out /tmp/k2.json
$ .venv/bin/python tools/okf_contract_check.py \
--skill skills/okf-consume/SKILL.md --payload /tmp/k2.json
conformant: 14 rules over 8 excerpts and 621 withheld entries, 0 findings
exit=0
And the two negative controls, because a green checker proves little on its
own -- measured, it returns 0 findings on an empty payload paired with the
unfilled template:
broken denominator identity -> NOT conformant, 2 findings, exit=1
missing payload file -> exit=2
Placeholder scan, known-positive first: the DOTALL scan reports 20 occurrences
on the template and 0 on this copy. The shipped example payload is generated
from the in-repo golden bundle, not from the corpus, and a test regenerates it
byte for byte. No K2 concept path or document title reaches any tracked file
here, checked with a pattern shown able to find against the bundle's own index.
Suite run after git add: 1224 passed, mypy --strict clean on 26 files,
ruff clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5d066f1799
commit
51735fa7a8
6 changed files with 489 additions and 0 deletions
|
|
@ -908,3 +908,92 @@ def test_the_payload_written_by_the_cli_passes_the_checker(tmp_path: Path) -> No
|
|||
)
|
||||
assert checked.returncode == 0, checked.stdout
|
||||
assert "0 findings" in checked.stdout
|
||||
|
||||
|
||||
# --- Step 10: the instantiated skill -----------------------------------------
|
||||
|
||||
SKILL = PROJECT_ROOT / "skills" / "okf-consume" / "SKILL.md"
|
||||
PLACEHOLDER_RE = re.compile(r"<[A-Z][A-Z_]{2,}(?::.*?)?>", re.DOTALL)
|
||||
|
||||
|
||||
def test_the_placeholder_scan_finds_them_in_the_template_before_its_zero_counts() -> None:
|
||||
# The known-positive, run FIRST. The obvious check is blind: a
|
||||
# line-oriented `<[A-Z_]*>` cannot match `<EXTENSION_MARKINGS: …>`,
|
||||
# `<CONDITIONAL_FIELDS: …>` or `<COST_SCALING: …>`, each of which spans
|
||||
# lines. Measured: the naive pattern reports 17 against 20 real occurrences.
|
||||
template = TEMPLATE.read_text(encoding="utf-8")
|
||||
naive = re.findall(r"<[A-Z_]*>", template)
|
||||
thorough = PLACEHOLDER_RE.findall(template)
|
||||
assert len(thorough) >= 20
|
||||
assert len(thorough) > len(naive), "the scan is no better than the blind one"
|
||||
|
||||
|
||||
def test_the_instantiated_skill_has_no_placeholder_left() -> None:
|
||||
assert PLACEHOLDER_RE.findall(SKILL.read_text(encoding="utf-8")) == []
|
||||
|
||||
|
||||
def test_the_instantiated_skill_carries_every_required_section() -> None:
|
||||
text = SKILL.read_text(encoding="utf-8")
|
||||
for section in okf_contract_check.REQUIRED_SECTIONS:
|
||||
assert f"## {section}" in text
|
||||
|
||||
|
||||
def test_the_instantiated_skill_carries_every_marking_and_state_literal() -> None:
|
||||
text = SKILL.read_text(encoding="utf-8")
|
||||
for marking in okf_contract_check.REQUIRED_MARKINGS:
|
||||
assert marking in text, marking
|
||||
for state in (*okf_contract_check.ADJUDICATION_STATES, *okf_contract_check.TRUST_TIERS):
|
||||
assert f"`{state}`" in text, state
|
||||
|
||||
|
||||
def test_every_rule_the_pre_pass_can_emit_is_named_in_the_skill() -> None:
|
||||
# The anti-drift gate. A rule the pre-pass emits and the skill does not
|
||||
# explain is a `withheld` entry no reader can act on, and the copy nobody
|
||||
# reads is the one that goes wrong.
|
||||
text = SKILL.read_text(encoding="utf-8")
|
||||
for rule in okf_consume.WITHHOLDING_RULES:
|
||||
assert rule in text, rule
|
||||
|
||||
|
||||
def test_the_skill_and_a_real_payload_pass_the_checker_together() -> None:
|
||||
payload = _payload()
|
||||
assert okf_contract_check.check(SKILL.read_text(encoding="utf-8"), payload).findings == ()
|
||||
|
||||
|
||||
def test_the_shipped_example_payload_is_current_and_regenerates_byte_for_byte() -> None:
|
||||
# A shipped artefact that has drifted from the tool that made it is worse
|
||||
# than none: it documents a shape the code no longer emits.
|
||||
shipped = (SKILL.parent / "references" / "example-payload.json").read_text(encoding="utf-8")
|
||||
regenerated = okf_consume.serialise(
|
||||
okf_consume.build_payload(GOLDEN, question="Hva sier veiledningen om krav?")
|
||||
)
|
||||
assert shipped == regenerated
|
||||
|
||||
|
||||
def test_no_k2_concept_path_or_document_title_reaches_the_tracked_skill() -> None:
|
||||
# CLAUDE.md's public-file rule, with the pattern widened to the bare
|
||||
# basenames a report is most likely to leak, and shown capable of finding
|
||||
# against the bundle's own index before its zero here is believed.
|
||||
leak = re.compile(
|
||||
r"del-ii-bilag|del-i-vedlegg|del-i-konkurranse|prisskjema|prissammenstilling|stange",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
tracked = [
|
||||
SKILL,
|
||||
SKILL.parent / "references" / "README.md",
|
||||
SKILL.parent / "references" / "example-payload.json",
|
||||
]
|
||||
if K2_BUNDLE.is_dir():
|
||||
control = (K2_BUNDLE / "index.md").read_text(encoding="utf-8")
|
||||
assert leak.findall(control), "the pattern cannot find; its zero below would mean nothing"
|
||||
for path in tracked:
|
||||
assert leak.findall(path.read_text(encoding="utf-8")) == [], path
|
||||
|
||||
|
||||
def test_the_readme_consume_section_states_the_rule_count_the_code_emits() -> None:
|
||||
# A published number must have a test that goes red when it goes false.
|
||||
readme = (PROJECT_ROOT / "README.md").read_text(encoding="utf-8")
|
||||
assert readme.count("## Consume") == 1
|
||||
assert len(okf_consume.WITHHOLDING_RULES) == 6
|
||||
assert "closed set of six" in readme
|
||||
assert "tools/okf_consume.py" in readme
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue