fix(gate,propose): okf build runs a real guard; a code fence declares no structure
Two defects reported from outside by claude-code-llm-wiki (order 20260915T202332Z-228694739), both reproduced against this tree before anything moved. F1 -- the packaged CLI never ran the guard. corpus.measure wired an unconditional approve-everything stub into process_inbox and 0 of 90 add_argument calls named a gate, so the one path most people use screened nothing while pyproject.toml made the guard a mandatory runtime dependency and the README recommended a composition the command line could not reach. --gate takes guard-trusted-source (default), guard-user-upload or none. corpus.resolve_gate is the one name->callable map, with the guard imported lazily so importing the package still does not pull it in; an unknown name RAISES rather than falling back, because a fallback reproduces the defect with an extra step. The gate's NAME goes into the section 9 log.md -- a stub is only dangerous when nothing downstream can see it -- and --gate none renders NOTHING WAS SCREENED. The default was chosen on a measurement: over the 453 concept bodies of the pinned reference bundle, PRESET_TRUSTED_SOURCE persists 453 of 453 and PRESET_USER_UPLOAD holds 1, costing that concept's whole source document. Neither tier waves anything through -- an invisible carrier and a CRITICAL finding fail secure at both. Door B's library default is UNCHANGED at PRESET_USER_UPLOAD: an inbox drop is an untrusted upload, an operator pointing this command at their own folder is not. The second tier ships as guard_adapter.inbox_gate_trusted_source, the three-line adapter that module's docstring already described, never a preset parameter. process_inbox(segmentations=..., gate=inbox_gate) now has a test. Before this, `grep -rl inbox_gate tests/` gave 1 file with 0 occurrences of `segment` -- the recommended composition was untested, which is how the defect survived. F2 -- a fenced code block declared structure. `# Use the opus[1m] alias` inside a ```bash fence became a level-1 ATX heading: the document was refused entirely where the line carried [ or ] (5 of 191 pages of the reporter's corpus), and the concept TITLE came from somebody's shell session on 62 of 191 (32.5 %). The fix is in the proposer and never in Door B's title rule -- that rule is right, and a heading that was never a heading is what has to stop being proposed. propose.fenced_lines is computed once per text and no rule reads a fenced line, including Arm D's outline RUN, which selects from the whole line list. Backtick and tilde fences, three leading spaces, a closing fence at least as long as its opener, and no backtick in a backtick fence's info string -- that last one keeps a line holding only `okf build` from silencing a document. MEASURED ON THE BYTES, and this is the number that decides: the 43-document reference corpus built atb6da09c(from git archive, never the editable tree) and rebuilt at the shipped defaults differ in log.md alone, by the one added bullet. 865 concept files on both sides, every concept byte-identical. Found by that control and NOT caused by this work: the pinned artifact K2-bundle-default-20260912 was written 2026-09-09, two days beforeed0418fchanged title: quoting, so it differs from what HEAD produces on 42 concept files. test_default_bundle_pin stays green because it pins the count and the hit@8 ranks, not the bytes. Re-pinning is the operator's call. Suite 1896 passed / 1 skipped (+27 from 1869). ruff, ruff format and mypy --strict clean. No version bump, no tag, no push. Report: docs/2026-09-15-f1-f2-gaten-og-kodefencen.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
b6da09cc97
commit
332961a19c
11 changed files with 1194 additions and 10 deletions
|
|
@ -280,3 +280,40 @@ def test_the_threshold_document_carries_the_boundary_bar_and_its_single_corpus()
|
|||
assert f"`{BOUNDARY_THRESHOLD.metric}` | **2 759/2 761**" in text
|
||||
assert "1 corpus" in text
|
||||
assert BOUNDARY_THRESHOLD.corpora == 1
|
||||
|
||||
|
||||
# --- the CLI's default persist gate ----------------------------------------
|
||||
#
|
||||
# F1 (reported 2026-09-15): `okf build` injected a permissive stub and no
|
||||
# argument in the package named a gate, so the command screened nothing while
|
||||
# the guard was a mandatory runtime dependency and the README recommended a
|
||||
# composition the command line could not reach. What made that survivable for
|
||||
# months is that nothing tied the README's claim to the code's behaviour. This
|
||||
# does. A published promise is a test obligation.
|
||||
|
||||
_GATE_LINE = re.compile(r"^<!-- cli-default-gate: (.+) -->$", re.MULTILINE)
|
||||
|
||||
|
||||
def test_the_readme_names_the_gate_the_build_command_actually_defaults_to() -> None:
|
||||
from llm_ingestion_okf import cli
|
||||
|
||||
match = _GATE_LINE.search(README.read_text(encoding="utf-8"))
|
||||
assert match is not None, (
|
||||
"README.md carries no `<!-- cli-default-gate: ... -->` marker; without it "
|
||||
"the documented default can drift from the one the command applies, which "
|
||||
"is exactly how F1 survived"
|
||||
)
|
||||
assert match.group(1).strip() == cli.DEFAULT_GATE
|
||||
|
||||
|
||||
def test_the_readme_names_every_gate_the_command_accepts() -> None:
|
||||
"""A tier reachable but undocumented is a tier nobody can choose.
|
||||
|
||||
The stricter one matters most: a caller whose folder IS an untrusted drop
|
||||
has to be able to find `guard-user-upload` without reading the source.
|
||||
"""
|
||||
from llm_ingestion_okf.corpus import GATE_NAMES
|
||||
|
||||
text = README.read_text(encoding="utf-8")
|
||||
for name in GATE_NAMES:
|
||||
assert f"`{name}`" in text, f"README does not name the gate {name}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue