feat(okf): conform the context seam to the pulled navigation + stamp-integrity contracts

The commons pull (7aa53fc -> a2b57d2) rewrote method-spec §3 Step 1 and added two §11
seams. Measuring okf.py against the new normative text found six contradictions; this
closes all six, gated by the commons-owned nav-goldens that came with the pull.

method-spec §3 Step 1 (navigate_bundle / bundle_context):
- follow cross-links RECURSIVELY, depth-first in first-seen order (there was no
  recursion at all — only the root index's links were read, so no hierarchy was
  navigable even with the other fixes in place);
- resolve a leading `/` against the BUNDLE ROOT, anything else against the LINKING
  file's directory, and drop the retired "a path separator means out-of-bundle"
  heuristic, which conflated depth with escape and forbade valid nesting;
- de-duplicate on the RESOLVED path (`./a.md` == `a.md` == `/a.md`), which is also
  what terminates cycles;
- exclude index files by BASENAME at every level, so a nested index is navigation and
  never renders as content (flat rendering regardless of depth);
- bind index_summary to the ROOT index alone.

safe_resolve stays the sole in-/out-of-bundle test, fail-closed: a target that fails to
resolve for ANY reason is skipped, never raised.

ingest-spec §3 (write_concept_file): it is the repo's one authoring primitive that
materialises a concept file from caller-supplied frontmatter, so it now refuses the
COMPLETE ownership stamp (`generated: true` + `ingest_manifest`) with IngestStampError,
while permitting either field alone. A validation, never a repair — nothing is written.

Gates (tests/test_okf.py, 529 -> 537):
- nav-golden-hierarchy and nav-golden-escape compared against the shipped
  expected-read-context.md fasit (trailing-whitespace normalisation only, which the
  fixture README explicitly permits; internal blank-line structure stays gated);
- traversal order pinned separately from the rendered output, so a right-looking render
  from a wrong walk still fails;
- unit seams for the recursion in isolation, resolved-path dedup, and the leading-`/`
  rule's breach case (a real out-of-bundle file addressed by its absolute path).

Load-bearing MEASURED, not asserted: seven mutations each go red — detach the recursion,
restore the separator prefilter, dedup on the raw target, read `/` as filesystem-absolute,
render nested index bodies as content, drop the stamp guard, and the fully naive navigator
with no boundary check (which is what makes the `/`-trap test bite). okf.py restored from a
checksum-verified copy after each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WetWTHpdRbqinN5XHFTaTb
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 21:07:29 +02:00
commit 0d50ab89d3
3 changed files with 288 additions and 29 deletions

View file

@ -29,7 +29,26 @@ _MAF_FREE_MODULES = [
"semretrieval.py",
]
BUNDLE_DIR = Path(__file__).resolve().parents[1] / "shared" / "examples" / "bygg-energi-mikro"
_EXAMPLES_DIR = Path(__file__).resolve().parents[1] / "shared" / "examples"
BUNDLE_DIR = _EXAMPLES_DIR / "bygg-energi-mikro"
def _normalise_trailing_ws(text: str) -> str:
"""The ONLY normalisation the nav-golden gate applies, and the README explicitly permits it
("byte-exact or after trailing-whitespace normalization"): per-line trailing whitespace and the
file's terminating newline. Internal blank-line structure is NOT normalised — the serialisation
shape (``## {type}: {title}`` + blank line + body, sections separated by one blank line) stays
gated, so a renderer that drops or doubles a separator still goes RED."""
return "\n".join(line.rstrip() for line in text.rstrip("\n").split("\n"))
def _nav_golden(case: str) -> tuple[str, str]:
"""A commons-owned nav-golden case: ``(bundle_dir, expected_read_context)``. The fixture class
is bundle-in / read-context-out the only shape that can express method-spec §3 Step 1's
cross-implementation property "two conformant implementations MUST produce an identical
read-context from the same bundle"."""
root = _EXAMPLES_DIR / case
return str(root / "bundle"), (root / "expected-read-context.md").read_text(encoding="utf-8")
def test_navigate_classifies_every_typed_file() -> None:
@ -84,6 +103,106 @@ def test_bundle_context_excludes_verdict_layer() -> None:
assert "progressiv disclosure" in context.lower() # the index summary is the entry point
def test_nav_golden_hierarchy_read_context_matches_commons_fasit() -> None:
"""CONFORMANCE GATE (method-spec §3 Step 1, commons-owned nav-golden). The positive case: the
rendered read-context of a HIERARCHICAL bundle must equal the shipped ``expected-read-context.md``
the cross-implementation fasit. One assertion covers the whole Q3 navigation contract at once:
recursive depth-first traversal, both link forms, resolved-path dedup, cycle termination, the
root-only binding of the missing-index rule, recursive verdict exclusion, and FLAT rendering
(nested index bodies are navigation, never content)."""
bundle_dir, expected = _nav_golden("nav-golden-hierarchy")
context = okf.bundle_context(okf.navigate_bundle(bundle_dir))
assert _normalise_trailing_ws(context) == _normalise_trailing_ws(expected)
def test_nav_golden_hierarchy_traversal_is_depth_first_first_seen() -> None:
"""The fasit above pins the RENDERED output; this pins the TRAVERSAL that produced it, so a
renderer that accidentally reproduced the right text from a wrong walk still goes RED. Order is
the commons README's trace verbatim: root index -> overview -> /a/index -> a/doc-a ->
a/verdict-nested (REACHED, then excluded by type) -> a/b/index -> a/b/doc-b, with ``/a/index.md``
and ``/overview.md`` deduped on their RESOLVED paths (cycle termination). ``c/orphan.md`` is
unreachable a link-following navigator never sees it, a directory-walking one wrongly would,
and ``c/`` having no ``index.md`` is NOT an error (that rule binds the bundle root alone)."""
bundle_dir, _ = _nav_golden("nav-golden-hierarchy")
bundle = okf.navigate_bundle(bundle_dir)
assert [f.name for f in bundle.files] == [
"index.md",
"overview.md",
"a/index.md",
"a/doc-a.md",
"a/verdict-nested.md",
"a/b/index.md",
"a/b/doc-b.md",
]
# Verdict exclusion is a TYPE check on each reached file, applied recursively — never a property
# of the link graph: the nested verdict IS navigated, and IS kept out of the context.
assert [f.name for f in bundle.verdicts] == ["a/verdict-nested.md"]
assert [f.name for f in bundle.context_files] == ["overview.md", "a/doc-a.md", "a/b/doc-b.md"]
def test_nav_golden_escape_read_context_matches_commons_fasit() -> None:
"""CONFORMANCE GATE, negative case (a gate that can only pass proves nothing). Every link but
the first escapes the bundle; a conformant navigator skips them all, reads none of them, RAISES
NOTHING, and still returns the one valid sibling. The decoy really exists one level up."""
bundle_dir, expected = _nav_golden("nav-golden-escape")
bundle = okf.navigate_bundle(bundle_dir)
assert [f.name for f in bundle.files] == ["index.md", "valid.md"]
context = okf.bundle_context(bundle)
assert _normalise_trailing_ws(context) == _normalise_trailing_ws(expected)
# The decoy's CONTENT, not its filename: the name legitimately appears in the index body as the
# (skipped) link target, so asserting on the name would pass for a navigator that read the file.
decoy = (_EXAMPLES_DIR / "nav-golden-escape" / "SHOULD-NOT-BE-READ.md").read_text(
encoding="utf-8"
)
assert decoy.split("---")[-1].strip() not in context
def test_navigate_follows_links_recursively(tmp_path) -> None:
"""§11 "Navigation boundary", the RECURSION on its own: a pure same-directory chain
``index -> a.md -> b.md``. Deliberately flat, so it is isolated from link-form and boundary
concerns a navigator that only reads the ROOT index's links returns ``[index, a]`` and goes
RED here even though every target is a legal same-dir sibling."""
(tmp_path / "index.md").write_text("---\ntype: index\n---\n\n- [A](a.md)\n", encoding="utf-8")
(tmp_path / "a.md").write_text(
"---\ntype: project\n---\n\nA body\n\n- [B](b.md)\n", encoding="utf-8"
)
(tmp_path / "b.md").write_text("---\ntype: reference\n---\n\nB body\n", encoding="utf-8")
bundle = okf.navigate_bundle(str(tmp_path))
assert [f.name for f in bundle.files] == ["index.md", "a.md", "b.md"]
def test_navigate_dedups_on_resolved_path(tmp_path) -> None:
"""Dedup is on the RESOLVED path, not the raw target string: ``./a.md``, ``a.md`` and ``/a.md``
are one entry. A navigator de-duplicating raw targets reads (and renders) the same file three
times and goes RED."""
(tmp_path / "index.md").write_text(
"---\ntype: index\n---\n\n- [1](a.md)\n- [2](./a.md)\n- [3](/a.md)\n", encoding="utf-8"
)
(tmp_path / "a.md").write_text("---\ntype: project\n---\n\nA body\n", encoding="utf-8")
bundle = okf.navigate_bundle(str(tmp_path))
assert [f.name for f in bundle.files] == ["index.md", "a.md"]
def test_navigate_root_relative_link_is_bundle_root_not_filesystem(tmp_path) -> None:
"""§11 "Navigation boundary", the ratified leading-``/`` rule and its breach. A leading ``/``
denotes the BUNDLE ROOT, never a filesystem-absolute path so an index carrying the real
absolute path of a file OUTSIDE the bundle resolves to ``{bundle}/{that path}`` (missing ->
skipped), and the outside file is never opened. An implementation reading ``/`` as
filesystem-absolute exfiltrates it: that is the path-traversal breach the escape golden's
``/etc/passwd`` trap describes, made assertable here with a file this test owns."""
outside = tmp_path / "outside.md"
outside.write_text("---\ntype: secret\n---\n\nEXFIL-SENTINEL\n", encoding="utf-8")
bundle_dir = tmp_path / "bundle"
bundle_dir.mkdir()
(bundle_dir / "index.md").write_text(
f"---\ntype: index\n---\n\n- [trap]({outside.resolve().as_posix()})\n", encoding="utf-8"
)
bundle = okf.navigate_bundle(str(bundle_dir))
assert [f.name for f in bundle.files] == ["index.md"] # resolved under the bundle -> missing
assert all("EXFIL-SENTINEL" not in f.body for f in bundle.files)
assert "EXFIL-SENTINEL" not in okf.bundle_context(bundle)
def _dimension_bundle(tmp_path) -> str:
(tmp_path / "index.md").write_text(
"---\ntype: index\n---\n\n# Bundle\n\n"
@ -227,6 +346,34 @@ def test_render_frontmatter_single_lines_scalars(tmp_path) -> None:
assert parsed["decision"] == "approved" # the trailing key was NOT lost to a spurious ---
def test_write_concept_file_refuses_complete_ingest_stamp(tmp_path) -> None:
"""§11 "Stamp integrity (curated writers)" (ingest-spec §3, third bullet). The ingest stamp is
the SOLE mark separating ingest-owned files from curated ones and re-materialization deletes
what carries it. ``write_concept_file`` materialises a concept file from CALLER-SUPPLIED
frontmatter, so it is exactly the authoring primitive that could forge the stamp; it MUST refuse
the COMPLETE stamp and write NOTHING. A validation, never a repair: the file must not appear
stamp-stripped either."""
fm = {"type": "reference", "generated": "true", "ingest_manifest": "bygg@0123456789abcdef"}
with pytest.raises(okf.IngestStampError):
okf.write_concept_file(str(tmp_path), "forged.md", fm, "body\n")
assert not (tmp_path / "forged.md").exists() # refused, not silently repaired
def test_write_concept_file_permits_either_stamp_field_alone(tmp_path) -> None:
"""The check is on the COMPLETE stamp, never on the individual field names: curated content may
legitimately carry a single provenance field, and a genuine verbatim round-trip is preserved.
Both halves alone are written unchanged."""
okf.write_concept_file(str(tmp_path), "a.md", {"type": "reference", "generated": "true"}, "b\n")
okf.write_concept_file(
str(tmp_path),
"b.md",
{"type": "reference", "ingest_manifest": "bygg@0123456789abcdef"},
"b\n",
)
assert okf.parse_frontmatter(tmp_path / "a.md")["generated"] == "true"
assert okf.parse_frontmatter(tmp_path / "b.md")["ingest_manifest"] == "bygg@0123456789abcdef"
def _minimal_bundle(tmp_path) -> str:
(tmp_path / "index.md").write_text(
"---\ntype: index\n---\n\n# Bundle\n\n- [proj](bygg.md)\n", encoding="utf-8"