feat(cli): okf project/consume/check/skill, and a generated skill with no path into a checkout
The reading direction existed only for someone standing in a clone. `consume`, `contract_check` and `skill` moved from `tools/` into the package and are reachable as `okf consume`, `okf check` and `okf skill`; `okf project` is new and does the whole thing in one command. The red measurement: a consumption skill generated from a checkout carried 4 lines naming that checkout by absolute path, 2 of them the commands the skill tells a reader to run. It now names `okf consume` and `okf check`, and a test asserts this repository appears in it nowhere, with a known-positive so the zero is a measurement rather than a search that could not find. The `tools/` files stay as ALIASES, not re-exports: a re-export binds copies of the names into a second module object, so a caller patching one patches a binding the implementation never reads. Two tests that monkeypatch okf_consume went green again only under the alias. Every published reproduction block runs unchanged. The template and docs/consumption-contract.md (the section 7.4 known-positive) are force-included into the wheel from the file they are authored in, so both travel with the commands that cannot run without them and there is still one authored copy of each. Step 0, before any of it: okf build's default gained Arm E (--table-grid), with --no-table-grid as its opt-out. The default moved to D plus F earlier the same day on Arm F's published 5 of 12 -- a figure measured with Arm E ON. Without it the fold has no joined table to fold, and the shipped default scored 2 of 12 with docx 0 of 3. Measured on the operator's folder: 30 md / 15 concepts on the new default against 43 / 28 without Arm E. Install measurement from a fresh uv tool install, empty folder, this repository nowhere on PYTHONPATH: 5 documents in, 15 concepts out, 0 references to tools/ in the generated skill, okf check conformant (15 rules, 0 findings). Deviation stated rather than hidden: the order asked that tests/test_okf_consume.py be left untouched. Two assertions in it read a PATH, which is the one thing this work changes. Both were moved and the second made stronger -- it now asserts every command the README recipe names is a subcommand the CLI registers, which a file existing on disk never proved. Suite 1414 -> 1427. ruff clean, mypy --strict clean over 21 files. Record: docs/2026-09-08-o5-okf-project.md Co-Authored-By: Claude <claude-opus-5>
This commit is contained in:
parent
efa92ce170
commit
f6fea13299
21 changed files with 4017 additions and 2833 deletions
1693
tools/okf_consume.py
1693
tools/okf_consume.py
File diff suppressed because it is too large
Load diff
|
|
@ -1,497 +1,34 @@
|
|||
"""Check a consumption skill and one pre-pass payload against the contract.
|
||||
#!/usr/bin/env python3
|
||||
"""Thin entry point. The implementation is `llm_ingestion_okf.contract_check`.
|
||||
|
||||
`docs/consumption-contract.md` is normative prose. Prose has no test, so this
|
||||
command reads the mechanically checkable half of it: the payload shape (SS 3, 5,
|
||||
6, 7, 8) and the fixed vocabulary a conformant `SKILL.md` must carry (SS 4, 6).
|
||||
It moved into the package on 2026-09-08 (O5): the generated consumption skill's
|
||||
check step named this file by absolute path into a checkout, so the one command
|
||||
that tells a reader whether their payload conforms was unreachable from an
|
||||
install. The command is now `okf check`, on PATH.
|
||||
|
||||
**What it cannot see, said here rather than implied.** The division of labour
|
||||
(SS 2) and the prohibitions (SS 9) are properties of a RUN -- whether an agent
|
||||
went looking for context the pre-pass withheld, whether a retrieval tool was
|
||||
pointed at the verdict layer. No static check reaches them. Conformance here is
|
||||
the floor, never the proof, and a green run means the payload carries what a
|
||||
claim would have to rest on -- not that the claim was made honestly.
|
||||
This file stays because the published reproduction blocks name it, and a
|
||||
measurement whose command no longer runs is a measurement nobody can repeat.
|
||||
|
||||
**Every rule has its own code.** One "invalid" verdict over fourteen different
|
||||
defects is a diagnostic no caller can act on. The codes are the contract's
|
||||
paragraphs made addressable.
|
||||
|
||||
**The report carries denominators**, because the contract requires them of its
|
||||
consumers and a checker exempting itself would be stating the rule it breaks:
|
||||
how many rules ran, over how many excerpts and withheld entries.
|
||||
|
||||
Exit codes are three, not two: 0 conformant, 1 non-conformant, 2 the check did
|
||||
not run. Collapsing 2 into 1 would report an unread file as a failed check.
|
||||
|
||||
It lives outside `src/`, so it never enters a wheel and no consumer's install
|
||||
surface changes because it exists.
|
||||
No logic here, deliberately: a second copy of a contract rule is a second thing
|
||||
that can pass while the shipped one fails.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
#: SS 4.1. Five literals, spelled exactly. `[unverifiable-from-bundle]` is one
|
||||
#: literal string -- no variants, no translations -- so this is a membership
|
||||
#: test on the literal, never on a translated concept name.
|
||||
REQUIRED_MARKINGS = (
|
||||
"extracted",
|
||||
"derived",
|
||||
"[unverifiable-from-bundle]",
|
||||
"[unread]",
|
||||
"[sourced-not-sufficient]",
|
||||
)
|
||||
|
||||
#: SS 6.1. A closed set of three, and the third is a real state: `unknown` says
|
||||
#: the concept carries no `adjudication` key, which is what an older bundle
|
||||
#: looks like. Collapsing it into `proposed` or into absence reports "not
|
||||
#: judged" where the truth is "we cannot tell", and only one of those is a fact
|
||||
#: about the concept.
|
||||
ADJUDICATION_STATES = ("proposed", "adjudicated", "unknown")
|
||||
|
||||
#: SS 6.2, from SPEC SS 5.3: derived from `verified`, lowest to highest.
|
||||
TRUST_TIERS = ("unverified", "machine-confirmed", "human-reviewed")
|
||||
|
||||
#: The level-2 headings a conformant skill carries. Checked by name because the
|
||||
#: alternative -- searching the prose for the obligation -- passes on any
|
||||
#: document that happens to use the words.
|
||||
REQUIRED_SECTIONS = (
|
||||
"Pre-pass",
|
||||
"Division of labour",
|
||||
"Markings",
|
||||
"States",
|
||||
"Budget",
|
||||
"Denominators",
|
||||
"Prohibitions",
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Finding:
|
||||
"""One contract paragraph, unmet, named by its code."""
|
||||
|
||||
code: str
|
||||
message: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Report:
|
||||
"""Findings plus the denominators they were measured over."""
|
||||
|
||||
findings: tuple[Finding, ...]
|
||||
rules_evaluated: int
|
||||
excerpts_examined: int
|
||||
withheld_examined: int
|
||||
|
||||
def render(self) -> str:
|
||||
denominator = (
|
||||
f"{self.rules_evaluated} rules over {self.excerpts_examined} excerpts "
|
||||
f"and {self.withheld_examined} withheld entries"
|
||||
)
|
||||
if not self.findings:
|
||||
return f"conformant: {denominator}, 0 findings"
|
||||
lines = [f"NOT conformant: {denominator}, {len(self.findings)} findings"]
|
||||
lines += [f" {finding.code}: {finding.message}" for finding in self.findings]
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Context:
|
||||
"""What every rule reads. `payload` is empty when the payload is not a
|
||||
mapping at all, so each rule stays a total function over its input."""
|
||||
|
||||
skill: str
|
||||
payload: Mapping[str, Any]
|
||||
payload_is_mapping: bool
|
||||
|
||||
|
||||
def _mapping(value: object) -> Mapping[str, Any]:
|
||||
return value if isinstance(value, Mapping) else {}
|
||||
|
||||
|
||||
def _sequence(value: object) -> Sequence[Any]:
|
||||
if isinstance(value, Sequence) and not isinstance(value, (str, bytes)):
|
||||
return value
|
||||
return ()
|
||||
|
||||
|
||||
def _text(value: object) -> str:
|
||||
return value if isinstance(value, str) else ""
|
||||
|
||||
|
||||
def _whole(value: object) -> int | None:
|
||||
# `bool` is an `int` in Python and would make `True` a budget. Excluded by
|
||||
# name rather than trusted not to arrive.
|
||||
return value if isinstance(value, int) and not isinstance(value, bool) else None
|
||||
|
||||
|
||||
# --- Payload rules -----------------------------------------------------------
|
||||
|
||||
|
||||
def rule_payload_shape(ctx: Context) -> list[Finding]:
|
||||
if ctx.payload_is_mapping:
|
||||
return []
|
||||
return [Finding("payload_invalid", "the payload is not a JSON object (SS 8)")]
|
||||
|
||||
|
||||
def rule_contract_version(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping or _text(ctx.payload.get("contract")):
|
||||
return []
|
||||
return [
|
||||
Finding(
|
||||
"contract_unversioned",
|
||||
"the payload names no `contract` revision, so a reader cannot tell "
|
||||
"which revision it is holding (SS 8.2)",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def rule_bundle_ref(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
bundle = _mapping(ctx.payload.get("bundle"))
|
||||
findings = []
|
||||
if not _text(bundle.get("ref")):
|
||||
findings.append(
|
||||
Finding(
|
||||
"ref_missing",
|
||||
"the payload names no bundle `ref`; a version is the producer's "
|
||||
"assertion, a ref is a fact about bytes (SS 3.3)",
|
||||
)
|
||||
)
|
||||
if not _text(bundle.get("bundle_id")):
|
||||
findings.append(Finding("ref_missing", "the payload names no `bundle.bundle_id` (SS 3.1)"))
|
||||
return findings
|
||||
|
||||
|
||||
def rule_excerpt_source_marking(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
findings = []
|
||||
for position, raw in enumerate(_sequence(ctx.payload.get("excerpts"))):
|
||||
excerpt = _mapping(raw)
|
||||
for key in ("bundle_id", "concept_id", "sha256"):
|
||||
if not _text(excerpt.get(key)):
|
||||
findings.append(
|
||||
Finding(
|
||||
"source_marking_incomplete",
|
||||
f"excerpt {position} carries no {key!r}; identity across "
|
||||
"bundles is the (bundle_id, concept_id) tuple with the "
|
||||
"digest of the bytes it was taken from (SS 3.1, SS 3.2)",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
def rule_excerpt_named(ctx: Context) -> list[Finding]:
|
||||
"""SS 8: every excerpt carries a `title`.
|
||||
|
||||
Added 2026-09-08 on a measurement, not a preference: `portfolio-optimiser`
|
||||
ran three paid arms in which the pre-pass delivered the gold concept at rank
|
||||
1 of 8 on 3 of 3 bundles and the model answered correctly on 1 of 3, because
|
||||
the excerpt carried `concept_id` and `text` and nothing a reader could name
|
||||
the document by. A payload no answer can cite from is not conformant; the
|
||||
identity fields are what SS 3.1's tuple is FOR.
|
||||
"""
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
return [
|
||||
Finding(
|
||||
"excerpt_unnamed",
|
||||
f"excerpt {position} carries no 'title'; an excerpt a reader cannot "
|
||||
"name is one an answer cannot cite, whatever its rank (SS 8)",
|
||||
)
|
||||
for position, raw in enumerate(_sequence(ctx.payload.get("excerpts")))
|
||||
if not _text(_mapping(raw).get("title"))
|
||||
]
|
||||
|
||||
|
||||
def rule_excerpt_states(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
findings = []
|
||||
closed: tuple[tuple[str, tuple[str, ...]], ...] = (
|
||||
("adjudication", ADJUDICATION_STATES),
|
||||
("trust_tier", TRUST_TIERS),
|
||||
)
|
||||
for position, raw in enumerate(_sequence(ctx.payload.get("excerpts"))):
|
||||
excerpt = _mapping(raw)
|
||||
for key, allowed in closed:
|
||||
if key not in excerpt:
|
||||
findings.append(
|
||||
Finding(
|
||||
"state_missing",
|
||||
f"excerpt {position} carries no {key!r}; the third state is "
|
||||
"written explicitly, never omitted -- omission collapses "
|
||||
'"we cannot tell" into a fact about the concept (SS 6.1)',
|
||||
)
|
||||
)
|
||||
continue
|
||||
value = _text(excerpt.get(key))
|
||||
if value not in allowed:
|
||||
findings.append(
|
||||
Finding(
|
||||
"state_not_in_set",
|
||||
f"excerpt {position} has {key}={value!r}, outside the closed "
|
||||
f"set {allowed} (SS 6)",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
def rule_denominator_identity(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
counts = _mapping(ctx.payload.get("denominators"))
|
||||
values = {key: _whole(counts.get(key)) for key in ("considered", "withheld", "delivered")}
|
||||
missing = sorted(key for key, value in values.items() if value is None)
|
||||
if missing:
|
||||
return [
|
||||
Finding(
|
||||
"denominator_identity",
|
||||
f"the payload reports no whole-number {', '.join(missing)}; a count "
|
||||
"that is not reported is unmeasured, not zero (SS 5.1)",
|
||||
)
|
||||
]
|
||||
considered = values["considered"]
|
||||
withheld = values["withheld"]
|
||||
delivered = values["delivered"]
|
||||
assert considered is not None and withheld is not None and delivered is not None
|
||||
if considered != withheld + delivered:
|
||||
return [
|
||||
Finding(
|
||||
"denominator_identity",
|
||||
f"considered ({considered}) != withheld ({withheld}) + delivered "
|
||||
f"({delivered}); a count that does not close is not a denominator "
|
||||
"(SS 5.2)",
|
||||
)
|
||||
]
|
||||
return []
|
||||
|
||||
|
||||
def rule_denominator_lists(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
counts = _mapping(ctx.payload.get("denominators"))
|
||||
findings = []
|
||||
for key, member in (("delivered", "excerpts"), ("withheld", "withheld")):
|
||||
declared = _whole(counts.get(key))
|
||||
if declared is None:
|
||||
continue
|
||||
actual = len(_sequence(ctx.payload.get(member)))
|
||||
if declared != actual:
|
||||
findings.append(
|
||||
Finding(
|
||||
"denominator_list_mismatch",
|
||||
f"denominators.{key} is {declared} but {member} holds {actual}; "
|
||||
"the count and the list are two statements of one fact (SS 8.1)",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
def rule_withheld_rules(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
findings = []
|
||||
for position, raw in enumerate(_sequence(ctx.payload.get("withheld"))):
|
||||
entry = _mapping(raw)
|
||||
for key in ("concept_id", "rule"):
|
||||
if not _text(entry.get(key)):
|
||||
findings.append(
|
||||
Finding(
|
||||
"cut_undeclared",
|
||||
f"withheld entry {position} carries no {key!r}; a visible "
|
||||
"drop is worth more than a silent one (SS 5.3)",
|
||||
)
|
||||
)
|
||||
return findings
|
||||
|
||||
|
||||
def rule_budget_declared(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
budget = _mapping(ctx.payload.get("budget"))
|
||||
findings = []
|
||||
for key in ("unit", "instrument"):
|
||||
if not _text(budget.get(key)):
|
||||
findings.append(
|
||||
Finding(
|
||||
"budget_undeclared",
|
||||
f"the budget names no {key!r}; a number without its instrument "
|
||||
"and unit is not a measurement (SS 7.1)",
|
||||
)
|
||||
)
|
||||
limit = _whole(budget.get("limit"))
|
||||
if limit is None or limit <= 0:
|
||||
findings.append(
|
||||
Finding(
|
||||
"budget_undeclared",
|
||||
'"bounded" without a bound is a denominator failure in prose (SS 7.1)',
|
||||
)
|
||||
)
|
||||
if _whole(budget.get("spent")) is None:
|
||||
findings.append(Finding("budget_undeclared", "the budget reports no `spent` (SS 7.2)"))
|
||||
return findings
|
||||
|
||||
|
||||
def rule_budget_gate(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
budget = _mapping(ctx.payload.get("budget"))
|
||||
limit = _whole(budget.get("limit"))
|
||||
spent = _whole(budget.get("spent"))
|
||||
if limit is None or spent is None or spent <= limit:
|
||||
return []
|
||||
return [
|
||||
Finding(
|
||||
"budget_exceeded",
|
||||
f"spent ({spent}) exceeds limit ({limit}); the cut strategy is wrong "
|
||||
"for this bundle, which is a finding requiring a decision and never "
|
||||
"a retry with a narrower question (SS 7.3)",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def rule_instrument_validated(ctx: Context) -> list[Finding]:
|
||||
if not ctx.payload_is_mapping:
|
||||
return []
|
||||
known = _mapping(_mapping(ctx.payload.get("budget")).get("known_positive"))
|
||||
expected = _whole(known.get("expected"))
|
||||
measured = _whole(known.get("measured"))
|
||||
if expected is None or measured is None or expected <= 0 or not _text(known.get("case")):
|
||||
return [
|
||||
Finding(
|
||||
"instrument_unvalidated",
|
||||
"the budget carries no usable `known_positive` (case, expected, "
|
||||
"measured); an instrument that has not reproduced a known figure "
|
||||
"has not been shown to count (SS 7.4)",
|
||||
)
|
||||
]
|
||||
if expected != measured:
|
||||
return [
|
||||
Finding(
|
||||
"instrument_unvalidated",
|
||||
f"the known-positive expected {expected} and the instrument "
|
||||
f"measured {measured} (SS 7.4)",
|
||||
)
|
||||
]
|
||||
return []
|
||||
|
||||
|
||||
# --- Skill rules -------------------------------------------------------------
|
||||
|
||||
|
||||
def rule_skill_sections(ctx: Context) -> list[Finding]:
|
||||
return [
|
||||
Finding(
|
||||
"skill_section_missing",
|
||||
f"the skill carries no `## {section}` section (SS 8 of this checker's "
|
||||
"reading; the headings are fixed so they can be checked by name)",
|
||||
)
|
||||
for section in REQUIRED_SECTIONS
|
||||
if f"## {section}" not in ctx.skill
|
||||
]
|
||||
|
||||
|
||||
def rule_skill_markings(ctx: Context) -> list[Finding]:
|
||||
return [
|
||||
Finding(
|
||||
"skill_marking_missing",
|
||||
f"the skill does not carry the required marking {marking!r} verbatim "
|
||||
"(SS 4.1); one literal string, no variants, no translations",
|
||||
)
|
||||
for marking in REQUIRED_MARKINGS
|
||||
if marking not in ctx.skill
|
||||
]
|
||||
|
||||
|
||||
def rule_skill_states(ctx: Context) -> list[Finding]:
|
||||
return [
|
||||
Finding(
|
||||
"skill_state_missing",
|
||||
f"the skill does not name the state {state!r}, so its consumer cannot "
|
||||
"be held to the closed set (SS 6)",
|
||||
)
|
||||
for state in (*ADJUDICATION_STATES, *TRUST_TIERS)
|
||||
if f"`{state}`" not in ctx.skill
|
||||
]
|
||||
|
||||
|
||||
#: Every rule, in report order. `len(RULES)` is the denominator the report
|
||||
#: quotes: "how many rules ran" is the number that makes "0 findings" mean
|
||||
#: something.
|
||||
RULES: tuple[Callable[[Context], list[Finding]], ...] = (
|
||||
rule_payload_shape,
|
||||
rule_contract_version,
|
||||
rule_bundle_ref,
|
||||
rule_excerpt_source_marking,
|
||||
rule_excerpt_named,
|
||||
rule_excerpt_states,
|
||||
rule_denominator_identity,
|
||||
rule_denominator_lists,
|
||||
rule_withheld_rules,
|
||||
rule_budget_declared,
|
||||
rule_budget_gate,
|
||||
rule_instrument_validated,
|
||||
rule_skill_sections,
|
||||
rule_skill_markings,
|
||||
rule_skill_states,
|
||||
)
|
||||
|
||||
|
||||
def check(skill_text: str, payload: object) -> Report:
|
||||
"""Run every rule. No rule short-circuits another: a caller fixing one
|
||||
defect should not discover a second only on the next run."""
|
||||
is_mapping = isinstance(payload, Mapping)
|
||||
ctx = Context(
|
||||
skill=skill_text,
|
||||
payload=payload if isinstance(payload, Mapping) else {},
|
||||
payload_is_mapping=is_mapping,
|
||||
)
|
||||
findings: list[Finding] = []
|
||||
for rule in RULES:
|
||||
findings.extend(rule(ctx))
|
||||
return Report(
|
||||
findings=tuple(findings),
|
||||
rules_evaluated=len(RULES),
|
||||
excerpts_examined=len(_sequence(ctx.payload.get("excerpts"))),
|
||||
withheld_examined=len(_sequence(ctx.payload.get("withheld"))),
|
||||
)
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("--skill", type=Path, required=True, help="the SKILL.md to check")
|
||||
parser.add_argument("--payload", type=Path, required=True, help="one pre-pass payload (JSON)")
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(argv)
|
||||
try:
|
||||
skill_text = args.skill.read_text(encoding="utf-8")
|
||||
except OSError as exc:
|
||||
print(f"could not read the skill: {exc}")
|
||||
return 2
|
||||
try:
|
||||
payload = json.loads(args.payload.read_text(encoding="utf-8"))
|
||||
except OSError as exc:
|
||||
print(f"could not read the payload: {exc}")
|
||||
return 2
|
||||
except json.JSONDecodeError as exc:
|
||||
print(f"the payload is not readable JSON: {exc}")
|
||||
return 2
|
||||
report = check(skill_text, payload)
|
||||
print(report.render())
|
||||
return 1 if report.findings else 0
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||||
|
||||
from llm_ingestion_okf import contract_check as _impl # noqa: E402
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
raise SystemExit(_impl.main())
|
||||
|
||||
# ALIASED, not re-exported. `import okf_contract_check` must hand back the packaged module
|
||||
# ITSELF: a re-export binds copies of the names into a second module object, so
|
||||
# a caller patching one of them patches a binding the implementation never
|
||||
# reads. Measured on the move: two tests that monkeypatch `okf_contract_check` went green
|
||||
# again only under the alias. Guarded by the `__main__` branch above, because
|
||||
# aliasing `sys.modules["__main__"]` would replace the running script.
|
||||
sys.modules[__name__] = _impl
|
||||
|
|
|
|||
|
|
@ -1,589 +1,33 @@
|
|||
"""Instantiate the consumption skill template for ONE named OKF bundle.
|
||||
#!/usr/bin/env python3
|
||||
"""Thin entry point. The implementation is `llm_ingestion_okf.skill`.
|
||||
|
||||
`skills/okf-consume-template/SKILL.md` is a template whose own rule is that a
|
||||
copy leaving a `<PLACEHOLDER>` unfilled "is not configured, it is unfinished".
|
||||
Filling it by hand is what produced `skills/okf-consume/` for one corpus. This
|
||||
command does the same thing for any bundle, from values it measures rather than
|
||||
values someone remembered.
|
||||
It moved into the package on 2026-09-08 (O5). The objection that kept it out --
|
||||
a wheel-installed `okf skill` would emit a command pointing at a file the wheel
|
||||
does not carry -- was about what the GENERATED skill names, and it was answered
|
||||
by changing that: the emitted commands are `okf consume` and `okf check`, names
|
||||
on PATH, and both moved into the package in the same step.
|
||||
|
||||
**Why a generator rather than one generic skill.** Measured 2026-09-08: the
|
||||
contract checker passes the UNFILLED template against a real payload (exit 0, 15
|
||||
rules, 0 findings), and passes a skill built for a different bundle against this
|
||||
one's payload. So the checker cannot tell the two forms apart, and the choice
|
||||
could not be made on conformance. It was made on what the skill has to state:
|
||||
§ 5's denominators, § 7.6's breaking point and § 6.4's conditional-field list
|
||||
are all per-bundle numbers. A generic skill can either leave them as holes -- the
|
||||
template's own definition of unfinished -- or carry another corpus's numbers,
|
||||
which is worse, because a stated cost that is false for this bundle is a
|
||||
measurement failure and not merely a gap. Instantiating is what makes them true.
|
||||
And with several bundles connected at once, a generic skill has nothing to
|
||||
select on: each generated skill carries the bundle's id in its own name.
|
||||
|
||||
**Zero model calls, zero network, no clock.** The same bundle bytes produce the
|
||||
same skill bytes. It lives outside `src/`, so it never enters a wheel and no
|
||||
consumer's install surface changes because it exists -- and a wheel-installed
|
||||
`okf skill` would emit a command pointing at `tools/okf_consume.py`, which the
|
||||
wheel does not contain.
|
||||
|
||||
Exit codes are three, as elsewhere in this chain: 0 the skill was written, 1 the
|
||||
run happened and refused, 2 the run did not happen.
|
||||
This file stays because `docs/2026-09-07-okf-konsumskill-maaling.md` names it,
|
||||
and a measurement whose command no longer runs is a measurement nobody can
|
||||
repeat.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from collections import Counter
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
|
||||
import okf_consume # noqa: E402
|
||||
|
||||
from llm_ingestion_okf.profiles import BundleProfile # noqa: E402
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
TEMPLATE = PROJECT_ROOT / "skills" / "okf-consume-template" / "SKILL.md"
|
||||
CONTRACT = PROJECT_ROOT / "docs" / "consumption-contract.md"
|
||||
PRE_PASS = PROJECT_ROOT / "tools" / "okf_consume.py"
|
||||
CHECKER = PROJECT_ROOT / "tools" / "okf_contract_check.py"
|
||||
|
||||
#: The profile the pre-pass reads a bundle under, spelled so the generated skill
|
||||
#: can name it in § 9.2's sentence. The pre-pass's own default; a bundle built
|
||||
#: under another profile needs a copy of this tool that says so.
|
||||
PROFILE_NAME = "SEGMENTED_OKF_V0_2"
|
||||
|
||||
#: The conditional frontmatter keys the generated skill reports a denominator
|
||||
#: for. Every one of them is written by SOME producer and not by others, which
|
||||
#: is exactly what § 6.4 says a consumer must be told about rather than left to
|
||||
#: infer from an absence.
|
||||
CONDITIONAL_FIELDS = (
|
||||
"adjudication",
|
||||
"bundle_id",
|
||||
"verified",
|
||||
"req_number",
|
||||
"sources",
|
||||
)
|
||||
|
||||
#: Tokens too short to carry a question. The same floor the pre-pass's own
|
||||
#: matcher uses, so the derived example question cannot be shorter than what the
|
||||
#: ranker can see.
|
||||
MIN_QUESTION_TOKEN = 5
|
||||
|
||||
|
||||
class SkillError(Exception):
|
||||
"""The generator refused. Carries the code, like the rest of this chain."""
|
||||
|
||||
def __init__(self, message: str, *, code: str) -> None:
|
||||
super().__init__(message)
|
||||
self.code = code
|
||||
|
||||
|
||||
# --- The blocks the template hands over verbatim ------------------------------
|
||||
|
||||
#: Every template block this generator rewrites WHOLE, by exact string. Held to
|
||||
#: the template by a test: an edit that moves one of these would otherwise
|
||||
#: produce a skill silently missing that rewrite, which is the drift the
|
||||
#: instantiated copy exists to avoid.
|
||||
TEMPLATE_HEADER = """**This file is a template.** Every `<PLACEHOLDER>` is a hole a per-corpus copy
|
||||
fills; none of them has a default, and a copy that leaves one unfilled is not
|
||||
configured, it is unfinished. The section headings are fixed:
|
||||
`tools/okf_contract_check.py` reads them, and a missing one makes the skill
|
||||
non-conformant rather than merely thin."""
|
||||
|
||||
TEMPLATE_PRE_PASS = """```sh
|
||||
<PRE_PASS_COMMAND> --bundle-root <BUNDLE_ROOT> --ref <REF> --out <PAYLOAD_PATH>
|
||||
```"""
|
||||
|
||||
TEMPLATE_CHECK = """```sh
|
||||
python3 tools/okf_contract_check.py --skill <SKILL_PATH> --payload <PAYLOAD_PATH>
|
||||
```"""
|
||||
|
||||
TEMPLATE_CONTRACT_LINE = (
|
||||
"The contract this skill is held to is `docs/consumption-contract.md`. Where this"
|
||||
)
|
||||
|
||||
TEMPLATE_EXTENSIONS = """**Extensions, if this corpus needs any.** `<EXTENSION_MARKINGS: for each, the
|
||||
literal, what it means here, and which of the five it would otherwise collapse
|
||||
into. Write "none" if there are none.>`"""
|
||||
|
||||
TEMPLATE_CONDITIONAL = """**Conditionally-written fields in this corpus.** `<CONDITIONAL_FIELDS: each
|
||||
field this profile writes only when a build-time condition held, and what its
|
||||
absence does and does not mean. Absence is a measurement, not a fact.>`"""
|
||||
|
||||
TEMPLATE_SCALING = """**Scaling.** `<COST_SCALING: whether cost tracks the question or the corpus, what
|
||||
the whole bundle at this ref costs by the same instrument, and the corpus size
|
||||
at which this strategy stops fitting the budget.>`"""
|
||||
|
||||
TEMPLATE_DENOMINATORS = """The payload reports three counts — `considered`, `withheld`, `delivered` — and
|
||||
`considered == withheld + delivered`. Carry them into your output."""
|
||||
|
||||
TEMPLATE_ENUMERATION = (
|
||||
"- **No directory enumeration** unless `<PROFILE_NAME>` says the index is derived."
|
||||
)
|
||||
|
||||
TEMPLATE_OUTPUT = "Write to `<OUT>`. It must carry: the bundle ref; the findings, each with a"
|
||||
|
||||
REPLACED_BLOCKS = (
|
||||
TEMPLATE_HEADER,
|
||||
TEMPLATE_PRE_PASS,
|
||||
TEMPLATE_CHECK,
|
||||
TEMPLATE_CONTRACT_LINE,
|
||||
TEMPLATE_EXTENSIONS,
|
||||
TEMPLATE_CONDITIONAL,
|
||||
TEMPLATE_SCALING,
|
||||
TEMPLATE_DENOMINATORS,
|
||||
TEMPLATE_ENUMERATION,
|
||||
TEMPLATE_OUTPUT,
|
||||
)
|
||||
|
||||
|
||||
# --- What the generator measures ----------------------------------------------
|
||||
|
||||
|
||||
def slug(value: str) -> str:
|
||||
"""A Claude Code skill name from a bundle id: lowercase, hyphen-joined."""
|
||||
reduced = re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
|
||||
return reduced or "okf"
|
||||
|
||||
|
||||
def example_question(titles: list[str]) -> str:
|
||||
"""A question this bundle really answers, derived rather than invented.
|
||||
|
||||
The most frequent long token across the concepts' own titles, byte-sorted on
|
||||
a tie. Derived because the shipped payload has to be one this bundle
|
||||
produces: a question sharing no token with any concept is withheld under
|
||||
`no_lexical_match` and the pre-pass refuses, so a hand-picked constant would
|
||||
fail on the first bundle that does not happen to contain it.
|
||||
"""
|
||||
counts: Counter[str] = Counter()
|
||||
for title in titles:
|
||||
counts.update(
|
||||
{token for token in okf_consume.normalise(title) if len(token) >= MIN_QUESTION_TOKEN}
|
||||
)
|
||||
if not counts:
|
||||
# Every title is short or empty. Fall back to the longest title as it
|
||||
# stands, which by construction matches at least its own concept.
|
||||
longest = max(titles, key=lambda title: (len(title), title), default="")
|
||||
if not longest:
|
||||
raise SkillError(
|
||||
"no concept in this bundle carries a title, so no example "
|
||||
"question can be derived from it; pass --example-question",
|
||||
code="no_example_question",
|
||||
)
|
||||
return longest
|
||||
top = min(counts.items(), key=lambda item: (-item[1], item[0]))[0]
|
||||
return f"Hva sier denne bundelen om {top}?"
|
||||
|
||||
|
||||
def field_counts(concepts: list[okf_consume.Concept]) -> dict[str, int]:
|
||||
"""How many concepts carry each conditional field. Set membership, never a
|
||||
guess from two equal totals.
|
||||
|
||||
The `source_*` rows are DISCOVERED from the bundle rather than listed here,
|
||||
for the same reason the excerpt carries them by prefix: a fixed list reports
|
||||
a denominator for the producers someone thought of, and says nothing about
|
||||
the locator this producer actually chose.
|
||||
"""
|
||||
discovered = sorted(
|
||||
{
|
||||
key
|
||||
for concept in concepts
|
||||
for key in concept.frontmatter
|
||||
if key.startswith(okf_consume.SOURCE_KEY_PREFIX)
|
||||
}
|
||||
)
|
||||
fields = (*CONDITIONAL_FIELDS, *discovered)
|
||||
counts = {field: 0 for field in fields}
|
||||
for concept in concepts:
|
||||
for field in fields:
|
||||
if concept.frontmatter.get(field, "").strip() or (
|
||||
field == "sources" and concept.sources_present
|
||||
):
|
||||
counts[field] += 1
|
||||
return counts
|
||||
|
||||
|
||||
def whole_bundle_cost(concepts: list[okf_consume.Concept]) -> int:
|
||||
"""What every concept in this bundle would cost by the gate's own
|
||||
instrument, if a single answer delivered all of them."""
|
||||
total = 0
|
||||
for concept in concepts:
|
||||
excerpt = okf_consume.excerpt_for(concept)
|
||||
if excerpt is not None:
|
||||
total += okf_consume.excerpt_weight(excerpt)
|
||||
return total
|
||||
|
||||
|
||||
def directory_control(bundle_root: Path, *, profile: BundleProfile) -> tuple[int, int]:
|
||||
"""The index walk against the method § 9.2 forbids the CONSUMER from using.
|
||||
|
||||
Run HERE, once, at generation time -- never on the question path. § 9.2
|
||||
binds a consumer reaching for context at query time; a build-time control is
|
||||
what turns "the walk loses nothing" from an assumption into a number the
|
||||
generated skill can quote.
|
||||
"""
|
||||
walked = len(okf_consume.enumerate_concepts(bundle_root, profile=profile))
|
||||
suffix = profile.paths.concept_suffix
|
||||
reserved = {profile.index.name, "log.md"}
|
||||
on_disk = len([path for path in bundle_root.rglob(f"*{suffix}") if path.name not in reserved])
|
||||
return walked, on_disk
|
||||
|
||||
|
||||
# --- The instantiation --------------------------------------------------------
|
||||
|
||||
|
||||
def render(
|
||||
bundle_root: Path,
|
||||
*,
|
||||
out: Path,
|
||||
profile: BundleProfile = okf_consume.DEFAULT_PROFILE,
|
||||
question: str | None = None,
|
||||
) -> tuple[str, dict[str, object]]:
|
||||
"""The skill text and the example payload that proves it, for one bundle."""
|
||||
bundle_root = bundle_root.resolve()
|
||||
bundle_id = okf_consume.root_bundle_id_of(bundle_root, profile=profile)
|
||||
ref = okf_consume.bundle_ref(bundle_root, profile=profile)
|
||||
concept_ids = okf_consume.enumerate_concepts(bundle_root, profile=profile)
|
||||
concepts = [
|
||||
okf_consume.read_concept(
|
||||
bundle_root / f"{concept_id}{profile.paths.concept_suffix}",
|
||||
bundle_root=bundle_root,
|
||||
root_bundle_id=bundle_id,
|
||||
)
|
||||
for concept_id in concept_ids
|
||||
]
|
||||
if not concepts:
|
||||
raise SkillError(
|
||||
f"{bundle_root} has an index but no concept under it; a skill for an "
|
||||
"empty bundle would state denominators of zero it never measured",
|
||||
code="bundle_empty",
|
||||
)
|
||||
total = len(concepts)
|
||||
asked = question or example_question([concept.title for concept in concepts])
|
||||
payload = okf_consume.build_payload(bundle_root, question=asked, profile=profile)
|
||||
counts = field_counts(concepts)
|
||||
walked, on_disk = directory_control(bundle_root, profile=profile)
|
||||
cost = whole_bundle_cost(concepts)
|
||||
denominators = payload["denominators"]
|
||||
assert isinstance(denominators, dict)
|
||||
budget = payload["budget"]
|
||||
assert isinstance(budget, dict)
|
||||
withheld = payload["withheld"]
|
||||
assert isinstance(withheld, list)
|
||||
bookkeeping = okf_consume.measure(json.dumps(withheld, ensure_ascii=False))
|
||||
per_withheld = bookkeeping / len(withheld) if withheld else 0.0
|
||||
breaking = int(okf_consume.DEFAULT_LIMIT / per_withheld) if per_withheld else 0
|
||||
|
||||
name = f"{slug(bundle_id)}-consume"
|
||||
text = TEMPLATE.read_text(encoding="utf-8")
|
||||
text = text.split("---\n", 2)[2]
|
||||
text = _rewrite(
|
||||
text,
|
||||
bundle_root=bundle_root,
|
||||
skill_path=out.resolve() / "SKILL.md",
|
||||
bundle_id=bundle_id,
|
||||
ref=ref,
|
||||
name=name,
|
||||
total=total,
|
||||
counts=counts,
|
||||
walked=walked,
|
||||
on_disk=on_disk,
|
||||
cost=cost,
|
||||
asked=asked,
|
||||
spent=int(budget["spent"]),
|
||||
delivered=int(denominators["delivered"]),
|
||||
bookkeeping=bookkeeping,
|
||||
breaking=breaking,
|
||||
)
|
||||
header = f"---\nname: {name}\ndescription: {_description(bundle_id, total, ref)}\n---\n"
|
||||
return header + text, payload
|
||||
|
||||
|
||||
def _description(bundle_id: str, total: int, ref: str) -> str:
|
||||
return (
|
||||
f"Answer one question about the OKF bundle `{bundle_id}` ({total} concepts, "
|
||||
f"ref {ref}) from a bounded payload assembled by a deterministic pre-pass, "
|
||||
"marking every claim with its source, its title and its provenance locator. "
|
||||
"Use whenever a question is about what that bundle's documents require, say "
|
||||
"or contain. Generated by tools/okf_skill.py; every value below is measured "
|
||||
"against this bundle at this ref."
|
||||
)
|
||||
|
||||
|
||||
def _rewrite(
|
||||
text: str,
|
||||
*,
|
||||
bundle_root: Path,
|
||||
skill_path: Path,
|
||||
bundle_id: str,
|
||||
ref: str,
|
||||
name: str,
|
||||
total: int,
|
||||
counts: dict[str, int],
|
||||
walked: int,
|
||||
on_disk: int,
|
||||
cost: int,
|
||||
asked: str,
|
||||
spent: int,
|
||||
delivered: int,
|
||||
bookkeeping: int,
|
||||
breaking: int,
|
||||
) -> str:
|
||||
replacements: list[tuple[str, str]] = [
|
||||
(
|
||||
TEMPLATE_HEADER,
|
||||
"**This file is an instantiated copy of "
|
||||
"`skills/okf-consume-template/SKILL.md`,** generated by "
|
||||
f"`tools/okf_skill.py` for one bundle: `{bundle_id}` at ref\n"
|
||||
f"`{ref}`. Every value below was measured against those bytes. If the\n"
|
||||
"bundle moves, the ref moves with it and this file is stale — regenerate\n"
|
||||
"it rather than editing a number here. The section headings are fixed:\n"
|
||||
"the contract checker reads them by name.",
|
||||
),
|
||||
(
|
||||
TEMPLATE_PRE_PASS,
|
||||
"```sh\n"
|
||||
f"python3 {PRE_PASS} \\\n"
|
||||
f" {bundle_root} \\\n"
|
||||
' --question "your question" \\\n'
|
||||
f" --ref {ref} \\\n"
|
||||
" --out /tmp/payload.json\n"
|
||||
"```\n\n"
|
||||
"`--ref` is an **assertion**, never an override: the identity is computed\n"
|
||||
"from the bytes either way, and a mismatch refuses. Read the pre-pass's\n"
|
||||
"own exit status, which carries three values: **0** a payload was written,\n"
|
||||
"**1** the run happened and refused, **2** the run did not happen at all.",
|
||||
),
|
||||
(
|
||||
TEMPLATE_CHECK,
|
||||
"```sh\n"
|
||||
f"python3 {CHECKER} \\\n"
|
||||
f" --skill {skill_path} \\\n"
|
||||
" --payload /tmp/payload.json\n"
|
||||
"```",
|
||||
),
|
||||
(
|
||||
TEMPLATE_CONTRACT_LINE,
|
||||
f"The contract this skill is held to is `{CONTRACT}`. Where this",
|
||||
),
|
||||
(
|
||||
TEMPLATE_EXTENSIONS,
|
||||
"**Extensions, if this corpus needs any: none.** This generated skill adds\n"
|
||||
"no marking to the required five. § 4.3 makes the undeclared extension the\n"
|
||||
"defect, so the absence is stated rather than left to be inferred — and a\n"
|
||||
"corpus that does need a sixth needs a hand-edited copy that declares it.",
|
||||
),
|
||||
(
|
||||
TEMPLATE_CONDITIONAL,
|
||||
_conditional_table(total, counts),
|
||||
),
|
||||
(
|
||||
TEMPLATE_SCALING,
|
||||
_scaling(
|
||||
total=total,
|
||||
cost=cost,
|
||||
asked=asked,
|
||||
spent=spent,
|
||||
delivered=delivered,
|
||||
bookkeeping=bookkeeping,
|
||||
breaking=breaking,
|
||||
),
|
||||
),
|
||||
(
|
||||
TEMPLATE_DENOMINATORS,
|
||||
_denominators(total, asked=asked, delivered=delivered),
|
||||
),
|
||||
(
|
||||
TEMPLATE_ENUMERATION,
|
||||
_enumeration(walked, on_disk),
|
||||
),
|
||||
(
|
||||
TEMPLATE_OUTPUT,
|
||||
"Write to the path the caller names, or to your answer if none was named.\n"
|
||||
"It must carry: the bundle ref; the findings, each with a",
|
||||
),
|
||||
("`<CORPUS>` bundle", f"`{bundle_id}` bundle"),
|
||||
("# <CORPUS> consumption", f"# {bundle_id} consumption"),
|
||||
("<BUDGET_LIMIT>", str(okf_consume.DEFAULT_LIMIT)),
|
||||
("<BUDGET_UNIT>", okf_consume.BUDGET_UNIT),
|
||||
("<BUDGET_INSTRUMENT>", okf_consume.BUDGET_INSTRUMENT),
|
||||
("<KNOWN_POSITIVE_CASE>", okf_consume.KNOWN_POSITIVE_CASE),
|
||||
("<KNOWN_POSITIVE_EXPECTED>", str(okf_consume.KNOWN_POSITIVE_EXPECTED)),
|
||||
]
|
||||
for old, new in replacements:
|
||||
if old not in text:
|
||||
raise SkillError(
|
||||
f"the template no longer carries the block this generator rewrites: {old[:70]!r}",
|
||||
code="template_drift",
|
||||
)
|
||||
text = text.replace(old, new)
|
||||
assert name # kept in the signature so a caller cannot forget to name the skill
|
||||
return text
|
||||
|
||||
|
||||
def _conditional_table(total: int, counts: dict[str, int]) -> str:
|
||||
rows = "\n".join(
|
||||
f"| `{field}` | **{count} of {total}** | "
|
||||
f"{'the producer wrote none for that concept' if count else 'no concept in this bundle carries it'} | "
|
||||
"that the source document lacks what the field asserts |"
|
||||
for field, count in counts.items()
|
||||
)
|
||||
return (
|
||||
"**Conditionally-written fields in this bundle, with what each absence does\n"
|
||||
"and does not mean.** Every count is over the same denominator — "
|
||||
f"**{total} concepts**, the set the index walk reaches. § 6.4: absence is a\n"
|
||||
"measurement about the producer, never a fact about the source.\n\n"
|
||||
"| Field | Present on | Absence means | Absence does NOT mean |\n"
|
||||
"|---|---|---|---|\n"
|
||||
f"{rows}\n\n"
|
||||
"A field present on **0 of "
|
||||
f"{total}** is a measured zero, not an unmeasured one: the count was taken\n"
|
||||
"over every concept, and it is reported so a negative claim resting on it\n"
|
||||
"carries its denominator."
|
||||
)
|
||||
|
||||
|
||||
def _scaling(
|
||||
*,
|
||||
total: int,
|
||||
cost: int,
|
||||
asked: str,
|
||||
spent: int,
|
||||
delivered: int,
|
||||
bookkeeping: int,
|
||||
breaking: int,
|
||||
) -> str:
|
||||
share = (spent / cost * 100) if cost else 0.0
|
||||
return (
|
||||
"**Scaling. Cost tracks the question, not the corpus.** Measured on this\n"
|
||||
f"bundle at generation time, with the question `{asked}`: the delivered set\n"
|
||||
f"was **{delivered} excerpts** costing **{spent} {okf_consume.BUDGET_UNIT}**,\n"
|
||||
f"against a whole bundle that would cost **{cost}** by the same instrument if\n"
|
||||
f"one answer delivered all {total} concepts — so that answer was about\n"
|
||||
f"**{share:.1f} %** of the corpus. One question is one measurement: a\n"
|
||||
"different question moves `spent` and this figure with it.\n\n"
|
||||
"**The breaking point, stated so it can be observed to have been passed.**\n"
|
||||
"The `withheld` list carries one entry per considered concept and grows\n"
|
||||
f"linearly: here it is **{bookkeeping} bytes** for {total} concepts. At roughly\n"
|
||||
f"**{breaking} concepts** the bookkeeping alone reaches the "
|
||||
f"{okf_consume.DEFAULT_LIMIT}-byte\n"
|
||||
"limit, and although it is not counted against `spent`, a payload whose\n"
|
||||
"bookkeeping dwarfs its content has stopped being a cut. The pre-pass also\n"
|
||||
"reads every concept body on every run, so the same growth is a wall-clock\n"
|
||||
"cost with no precomputed index behind it."
|
||||
)
|
||||
|
||||
|
||||
def _denominators(total: int, *, asked: str, delivered: int) -> str:
|
||||
return (
|
||||
"The payload reports three counts — `considered`, `withheld`, `delivered` — and\n"
|
||||
"`considered == withheld + delivered`. Carry them into your output.\n\n"
|
||||
f"For this bundle `considered` is **{total}**, every concept the index walk\n"
|
||||
"reaches, never the post-ranking shortlist. A concept dropped at the ranking\n"
|
||||
"stage is `withheld` **with its rule**, not invisible, and the rules are a\n"
|
||||
"closed set of six: `verdict_layer_excluded` (a verdict-layer file, § 9.1),\n"
|
||||
"`verified_unreadable` (a `verified` value this reader cannot decode, so no\n"
|
||||
"tier can be derived), `no_lexical_match` (the concept shares no token with\n"
|
||||
"the question), `over_budget_alone` (one excerpt exceeds the whole limit),\n"
|
||||
"`below_k` (ranked outside the shortlist the cut considers) and\n"
|
||||
"`over_budget_after_knapsack` (it ranked inside the shortlist and the pack\n"
|
||||
"had no room). Naming the rule is what makes a drop visible.\n\n"
|
||||
"**One limitation to carry into every negative claim.** `no_lexical_match` is\n"
|
||||
'a per-concept relevance drop, not a whole-question "this bundle has no\n'
|
||||
f'answer" gate: on the generation question `{asked}` it still returned\n'
|
||||
f"{delivered} excerpts. **An empty `excerpts` list is evidence of absence; a\n"
|
||||
"full one is not evidence of presence.** When the delivered excerpts do not\n"
|
||||
"actually answer the question, say `[sourced-not-sufficient]` and report that\n"
|
||||
"the cut found nothing responsive."
|
||||
)
|
||||
|
||||
|
||||
def _enumeration(walked: int, on_disk: int) -> str:
|
||||
agreement = (
|
||||
f"which costs nothing here: the walk reaches **{walked}** concepts and a\n"
|
||||
f" directory walk finds **{on_disk}**"
|
||||
if walked == on_disk
|
||||
else f"and the two disagree — the walk reaches **{walked}** concepts where a\n"
|
||||
f" directory walk finds **{on_disk}**, so some concept is unreachable through\n"
|
||||
" the index and the bundle's producer should be told"
|
||||
)
|
||||
return (
|
||||
"- **No directory enumeration.** This bundle is read under the\n"
|
||||
f" `{PROFILE_NAME}` profile, whose index policy declares\n"
|
||||
" `entries_match_directory = False`, so § 9.2's permission does not apply.\n"
|
||||
f" The pre-pass walks the **index tree** instead, {agreement}\n"
|
||||
" (controlled once at generation time, never on the question path). Do not\n"
|
||||
" enumerate a directory yourself either."
|
||||
)
|
||||
|
||||
|
||||
def generate(
|
||||
bundle_root: Path,
|
||||
*,
|
||||
out: Path,
|
||||
profile: BundleProfile = okf_consume.DEFAULT_PROFILE,
|
||||
question: str | None = None,
|
||||
force: bool = False,
|
||||
) -> Path:
|
||||
"""Write `out/SKILL.md` and its reference payload. Returns the skill path."""
|
||||
target = out / "SKILL.md"
|
||||
if target.exists() and not force:
|
||||
raise SkillError(
|
||||
f"{target} already exists; pass --force to replace it. A silent "
|
||||
"overwrite would destroy a hand-edited copy whose extra measurements "
|
||||
"this generator cannot reproduce",
|
||||
code="target_occupied",
|
||||
)
|
||||
text, payload = render(bundle_root, out=out, profile=profile, question=question)
|
||||
(out / "references").mkdir(parents=True, exist_ok=True)
|
||||
target.write_text(text, encoding="utf-8")
|
||||
(out / "references" / "example-payload.json").write_text(
|
||||
okf_consume.serialise(payload), encoding="utf-8"
|
||||
)
|
||||
return target
|
||||
|
||||
|
||||
def parse_args(argv: list[str] | None) -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument("bundle", type=Path, help="the OKF bundle to instantiate a skill for")
|
||||
parser.add_argument(
|
||||
"--out", type=Path, required=True, help="the skill directory to write (SKILL.md inside)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--example-question",
|
||||
default=None,
|
||||
help="the question the shipped reference payload answers. Derived from the "
|
||||
"bundle's own titles when omitted",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force", action="store_true", help="replace an existing SKILL.md at --out"
|
||||
)
|
||||
return parser.parse_args(argv)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = parse_args(argv)
|
||||
try:
|
||||
written = generate(
|
||||
args.bundle, out=args.out, question=args.example_question, force=args.force
|
||||
)
|
||||
except okf_consume.ConsumeError as exc:
|
||||
print(f"refused ({exc.code}): {exc}")
|
||||
return 1
|
||||
except SkillError as exc:
|
||||
print(f"refused ({exc.code}): {exc}")
|
||||
return 1
|
||||
except OSError as exc:
|
||||
print(f"the run did not happen: {exc}")
|
||||
return 2
|
||||
print(f"wrote {written}")
|
||||
return 0
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||||
|
||||
from llm_ingestion_okf import skill as _impl # noqa: E402
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
raise SystemExit(_impl.main())
|
||||
|
||||
# ALIASED, not re-exported. `import okf_skill` must hand back the packaged module
|
||||
# ITSELF: a re-export binds copies of the names into a second module object, so
|
||||
# a caller patching one of them patches a binding the implementation never
|
||||
# reads. Measured on the move: two tests that monkeypatch `okf_skill` went green
|
||||
# again only under the alias. Guarded by the `__main__` branch above, because
|
||||
# aliasing `sys.modules["__main__"]` would replace the running script.
|
||||
sys.modules[__name__] = _impl
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue