K3-21 A. `okf consume` resolves a concept's `parent:` pointer -- a
`segment_id`, unique only inside one document's plan -- among the concepts
sharing its `source_file` (`consume.link_parents`, one pass, no file opened
again) and an excerpt carries `parent: { concept_id, title }`. Conditional
like `req_number`: a concept with no `parent` key moves no byte. A pointer
that lands nowhere is named `parent_unresolved: true`, never dropped.
The door writes ONE line into a heading-only body whose entry has a parent:
`Enclosing section: [<title>](/<bundle-relative path>)` (SPEC SS 5.1 lineage
through links, SS 6.1 the recommended absolute form and the kind in the
prose). Only such a body, so the segmented goldens' declared parents -- bodies
holding text -- are untouched. Appended AFTER structure derivation and
screened on its own (`_screened`, the `description` rule): read as body text
the link was derived into a second, unresolved `references` edge, measured on
the fixture. `segmentation.heading_only` is the one predicate the proposer and
the door share.
`okf check` gains its seventeenth rule, `parent_unfollowable`: a `parent`
that is not a concept_id and title, names its own excerpt, or names a concept
in neither `excerpts` nor `withheld` (together every considered concept).
Contract SS 8 point 6 added, the figure carries `parent`, and "additional
members are not read by the checker" now says the checker reads only the
members SS 8 names. The template tells the reader what `parent` is and that
SS 2.2 lets it read that one concept; `skill.CONDITIONAL_FIELDS` gains
`parent`. README and CLAUDE.md say what consume now reads.
Moved on purpose, each named: the SS 7.4 known-positive IS the contract
document, so `budget.known_positive` moves in every payload (13 238 / 12 893
/ 345 -> 14 455 / 14 083 / 372); `skills/okf-consume/` regenerated from the
segmented golden, whose plan declares s1 and s2 under s0 -- its example
payload now carries both parents; `test_bundle_identity` 16 -> 17 rules;
`test_shell_parent`'s byte test also accounts for the link line.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
703 lines
29 KiB
Python
703 lines
29 KiB
Python
"""Instantiate the consumption skill template for ONE named OKF bundle.
|
|
|
|
`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 first 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; since 2026-09-11 that directory is this
|
|
command's own output for the golden bundle the repository ships.
|
|
|
|
**Why a generator rather than one generic skill.** The measurement this
|
|
paragraph used to rest on is CLOSED 2026-09-10. It read: 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. `contract_check.rule_bundle_identity` now compares the identity a
|
|
skill declares with the identity its payload declares, so all three measured
|
|
pairs are refused at exit 1 with one `bundle_mismatch` finding over 16 rules
|
|
(17 since K3-21's `parent_unfollowable`):
|
|
a skill against another bundle's payload, the unfilled template against a real
|
|
payload, and -- the arm an id comparison would miss -- a payload sharing the
|
|
skill's `bundle_id` at a foreign `ref`. The right pair is untouched at exit 0
|
|
with 0 findings.
|
|
|
|
**The argument for a generator never rested on conformance, and still does
|
|
not.** 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 moved into the package on 2026-09-08 (O5), and so did the reason it could
|
|
not before.** The old objection was exact: a wheel-installed `okf skill` would
|
|
emit a command pointing at `tools/okf_consume.py`, which the wheel does not
|
|
contain. That objection was about what the generated skill NAMES, and the
|
|
answer was to change what it names. The emitted commands are now `okf consume`
|
|
and `okf check` -- names on PATH after an install, resolved by the shell and
|
|
not by this repository's layout. The pre-pass and the checker moved into the
|
|
package in the same step, so both names exist wherever the generated skill
|
|
does. Measured before the move: a skill generated from a checkout carried four
|
|
lines with an absolute path into that checkout, two of them the commands a
|
|
reader is told to run.
|
|
|
|
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.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import re
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
|
|
from . import consume as okf_consume
|
|
from .profiles import BundleProfile, block_scalar
|
|
|
|
#: The template, resolved to a copy that exists wherever this module does.
|
|
#:
|
|
#: A wheel carries `_data/okf-consume-template.md`, force-included from the
|
|
#: authored file below at build time; a source tree carries only the authored
|
|
#: file. Preferring the packaged copy and falling back keeps ONE authored
|
|
#: template -- a committed second copy is the drift this generator exists to
|
|
#: prevent, restated one directory up.
|
|
PACKAGED_TEMPLATE = Path(__file__).resolve().parent / "_data" / "okf-consume-template.md"
|
|
AUTHORED_TEMPLATE = (
|
|
Path(__file__).resolve().parents[2] / "skills" / "okf-consume-template" / "SKILL.md"
|
|
)
|
|
|
|
#: What the generated skill tells a reader to RUN. Names on PATH after an
|
|
#: install, never paths into a checkout: a generated skill is meant to be moved,
|
|
#: shared and run by someone who does not have this repository.
|
|
PRE_PASS_COMMAND = "okf consume"
|
|
CHECKER_COMMAND = "okf check"
|
|
|
|
#: The contract is prose in this repository and is NOT shipped in the wheel, so
|
|
#: the generated skill names it as a document rather than as a path a reader
|
|
#: could open. Naming an absolute path here is what made a generated skill
|
|
#: unmovable; naming a file the reader may not have is honest about which it is.
|
|
CONTRACT = "docs/consumption-contract.md in open/llm-ingestion-okf"
|
|
|
|
|
|
#: 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",
|
|
"parent",
|
|
)
|
|
|
|
#: 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
|
|
|
|
|
|
def template_path() -> Path:
|
|
"""The template this generator instantiates, or a coded refusal.
|
|
|
|
Refuses rather than falling through to a default: a generator that
|
|
silently emitted a skill built from no template would produce a file
|
|
carrying this bundle's numbers and none of the contract's sections.
|
|
"""
|
|
for candidate in (PACKAGED_TEMPLATE, AUTHORED_TEMPLATE):
|
|
if candidate.is_file():
|
|
return candidate
|
|
raise SkillError(
|
|
f"the consumption skill template was not found at {PACKAGED_TEMPLATE} "
|
|
f"or {AUTHORED_TEMPLATE}",
|
|
code="template_missing",
|
|
)
|
|
|
|
|
|
# --- 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:
|
|
`okf check` 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
|
|
okf check --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
|
|
|
|
|
|
# --- Where the reader runs the commands (O6) -----------------------------------
|
|
|
|
#: `okf project` writes the skill to `<root>/.claude/skills/<id>-consume` and
|
|
#: the bundle to `<root>/.okf/<id>`, then tells the reader to start `claude` in
|
|
#: `<root>`. So `<root>` is where the skill's commands are read from, and a path
|
|
#: written relative to it is the one a reader can paste.
|
|
SKILLS_LAYOUT = (".claude", "skills")
|
|
|
|
|
|
def project_root_of(out: Path) -> Path | None:
|
|
"""`<root>/.claude/skills/<name>` -> `<root>`; anything else -> None.
|
|
|
|
Read off the path rather than passed in, so `okf skill` and `okf project`
|
|
reach the same answer without a second parameter that could disagree with
|
|
the layout on disk.
|
|
"""
|
|
resolved = out.resolve()
|
|
if resolved.parts[-3:-1] == SKILLS_LAYOUT:
|
|
return resolved.parents[2]
|
|
return None
|
|
|
|
|
|
def as_written(path: Path, *, base: Path | None) -> str:
|
|
"""The path as the skill states it: relative to `base` when it is under it.
|
|
|
|
A path outside `base` stays absolute on purpose. `../../..` is not more
|
|
portable than `/Users/...`, it is only harder to read, and a skill that
|
|
states a path its reader cannot resolve is worse than one that states an
|
|
honest absolute.
|
|
"""
|
|
resolved = path.resolve()
|
|
if base is None:
|
|
return str(resolved)
|
|
try:
|
|
return resolved.relative_to(base).as_posix()
|
|
except ValueError:
|
|
return str(resolved)
|
|
|
|
|
|
# --- 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.link_parents(
|
|
[
|
|
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_path().read_text(encoding="utf-8")
|
|
text = text.split("---\n", 2)[2]
|
|
base = project_root_of(out)
|
|
text = _rewrite(
|
|
text,
|
|
bundle_root=Path(as_written(bundle_root, base=base)),
|
|
skill_path=Path(as_written(out / "SKILL.md", base=base)),
|
|
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,
|
|
)
|
|
# Claude Code reads this header with a YAML reader, and `description`
|
|
# carries the root index's `bundle_id` raw -- a bundle this library did not
|
|
# build may call itself anything (K3-22).
|
|
description = block_scalar(_description(bundle_id, total, ref))
|
|
header = f"---\nname: {block_scalar(name)}\ndescription: {description}\n---\n"
|
|
return header + text, payload
|
|
|
|
|
|
def identity_line(bundle_id: str, ref: str) -> str:
|
|
"""The one sentence that says which bundle a generated skill belongs to.
|
|
|
|
Authored here because the generator writes it, and read back by
|
|
`contract_check.skill_identity`, whose `bundle_mismatch` rule is the reason
|
|
it has to be findable rather than merely present. Two copies of this
|
|
sentence would drift, and the copy nobody reads is the one that goes wrong,
|
|
so the coupling has its own test.
|
|
"""
|
|
return f"generated by `okf skill` for one bundle: `{bundle_id}` at ref\n`{ref}`"
|
|
|
|
|
|
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 `okf skill`; 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`,** "
|
|
f"{identity_line(bundle_id, 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"{PRE_PASS_COMMAND} \\\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"{CHECKER_COMMAND} \\\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 seven: `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"
|
|
"`source_quota_exceeded` (its source document already holds as many\n"
|
|
"delivered places as `--source-quota` allows, default 2 — the freed place\n"
|
|
"goes to the next candidate, so `k` is still delivered in full),\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
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|