ktg-plugin-marketplace/test/okf-parity-corpus/manifest.json
Kjell Tore Guttormsen c4b776e4c6 fix(okf-check): required and recommended fields are read at top level only
The frontmatter reader matched `^\s*<key>:` with the m flag — indentation-
agnostic, so a block-form nested entry satisfied a top-level lookup. Measured
against okf/SPEC.md at frozen 3fcbb9f, this is a field confusion, not a near
miss: :467-469 names `resource`, `sources[].resource`, `executor.resource` and
`attester.resource` as DISTINCT fields. Top-level `resource` is the URI of the
asset a concept describes (:196); `sources[].resource` is the material it
derives from (:302). `sources` entries carry their own `title` and `type` too.

The consequence was not confined to warnings. Measured before the fix, a
concept with NO top-level `type:` and a `sources[].type` reported "0 files
without type: / OK: valid OKF bundle" — a false negative on §4.1's only
always-required field. `untyped` IS in the parity signature
(check-okf-parity.mjs:73-76), but okr vendors the same regex, so both impls
were blind identically and the gate stayed green while both were wrong.

Anchoring the key at column 0 fixes it. Flow-form never had the bug: in
`sources: [{ id: s1, resource: fixture }]` the nested key is mid-line, so `^`
cannot match it — measured against llm-ingestion-okf's v0.2 golden bundle
(6e0a7c0, read-only), which warns about `resource` and `description` both
before and after.

The divergence from okr is deliberate and is NOT okr lagging. Their reader is
SHARED, and the nested match is documented as load-bearing for their injector
(lib/frontmatter.mjs:7-9 -> inject:69) — while the same module backs their
scripts/okf-check.mjs:101, which needs the opposite. Pinned as parity fixture
`red-nested-key` (catalog FAILs on the nested type, okr passes it), so the
split is a running red/green signal instead of a note. It flips to `agree`
only if okr scopes the checker's reader without touching inject.

Correcting two premises carried in from the previous session, both measured:
- The reader was NOT flat/top-level-only. It read nested keys, so the suspected
  false POSITIVE on `resource` was actually a false NEGATIVE, opposite sign.
- "No v0.2 bundle exists" held for our own corpora and emitters only.
  llm-ingestion-okf ships a v0.2 golden bundle, where the previous commit's
  version-conditional list has real effect — and behaves correctly there.

docs/okf-second-brain/spec.md is untouched deliberately: it makes no claim
about key scope, so gate and convention do not disagree here.

Tests 103 -> 106 (okf-check 22 -> 25), parity 9/9 -> 10/10. All six suites
green; check-versions 11 OK / 0 WARN / 0 ERROR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RGZGiDPYcHUMSDCVJavRhp
2026-08-01 19:57:29 +02:00

68 lines
5.8 KiB
JSON

{
"_doc": "Expected per-fixture parity outcome for check-okf-parity.mjs. The runner COMPARES actual vs this expectation; it does not judge the fasit. 'diverge' fixtures are the red-proof: the gate MUST go red on them, else the gate itself is broken. Axes are catalog-owned (trinn F D4), spec-adversarial, defined over DEFAULT read-mode (strictIngest OFF).",
"fixtures": {
"green-baseline": {
"axis": "baseline",
"expected": "agree",
"note": "Clean UTF-8/LF conforming bundle. Sanity anchor: proves the gate is not red-on-everything."
},
"red-byte-bom": {
"axis": "byte",
"expected": "diverge",
"note": "Concept file with UTF-8 BOM + CRLF that HAS type: -> catalog's /^---\\n/ fence misses the BOM (falsely untyped), okr normalizes (frontmatter.mjs:23) and reads the type. Diverges on the untyped-set with an IDENTICAL count (the 'agree OK / disagree on members' case)."
},
"red-tree-innboks": {
"axis": "tree",
"expected": "diverge",
"note": "innboks/ drop-zone with a raw frontmatter-less file -> catalog walks it and counts it a concept, okr skips innboks (okf-check.mjs:37-39). Diverges on conceptCount + untyped-set."
},
"red-tree-dotdir": {
"axis": "tree",
"expected": "diverge",
"note": ".hidden/ dot-dir with an untyped .md -> catalog descends, okr skips dot-dirs. Diverges on conceptCount + untyped-set."
},
"red-combined": {
"axis": "byte+tree",
"expected": "diverge",
"note": "The record's canon fixture (svar-catalog.local.md:48): a BOM+CRLF typed concept AND an innboks/ raw file in one bundle -> catalog FAIL(2 untyped) vs okr OK(0 untyped), opposite exit codes. Byte and tree axes each carry their own red proof."
},
"red-marker-layout": {
"axis": "marker",
"expected": "diverge",
"note": "Root index.md carries a layout snapshot (kb-layout-2026-06) in okf_version instead of the upstream version -> catalog enforces the §3 shape rule and FAILs, okr still pure-echoes the value and passes (their CHANGELOG 1.8.1: 'verdiene valideres fortsatt ikke'). Otherwise clean, so the divergence isolates the marker axis. EXPECTED TO FLIP TO 'agree' once okr mirrors the enforcement — this expectation encodes okr's lag, not a permanent design split.",
"note2": "This axis was invisible until the parity signature carried the shape VERDICT: comparing the okf_version value alone reads 'agree' precisely when the impls disagree about whether that value is acceptable."
},
"red-nested-key": {
"axis": "key-scope",
"expected": "diverge",
"note": "A concept with NO top-level `type:` whose only `type:` sits in a block-form `sources[]` entry -> catalog anchors the key at column 0 (okf-frontmatter.mjs, 2026-08-01) and reports it untyped + FAILs; okr's `^\\s*key:` reads the nested entry and passes it as typed. §4.1 makes `type` the only always-required field, and SPEC.md:467-469 names top-level `resource` and `sources[].resource` as DISTINCT fields, so the nested match is a false negative on the required axis.",
"note2": "NOT symmetrical with the other red fixtures: okr's nested lookup is DELIBERATE and load-bearing for their injector (lib/frontmatter.mjs:7-9 -> inject:69). The shared module has one caller that needs nested and one (scripts/okf-check.mjs:101) that must not — so this expectation encodes a real design split, not merely okr's lag. Flips to 'agree' only if okr scopes the checker's reader without touching inject."
},
"green-hierarchical": {
"axis": "tree-hierarchical",
"expected": "agree",
"note": "okr's added requirement (trinn-e-analyse:277): subdir pointers, per-level index.md, a cross-level body relation. No adversarial trigger -> both walk the hierarchy identically. Guards against a corpus that is accidentally flat."
},
"green-nodemodules": {
"axis": "tree",
"expected": "agree",
"note": "SHARED GAP, pinned deliberately: an untyped .md inside node_modules/. BOTH catalog and okr descend into it (okr's isWalkableDir skips only dot-dirs + innboks, not node_modules). They agree today; flagged here for future hardening of both walkers."
},
"green-dupname": {
"axis": "tree",
"expected": "agree",
"note": "Same basename (note.md) at two sibling levels -> both impls key on the full relative path, no basename-collapse. Guards the path.name-collapses-hierarchy class."
}
},
"coveredByRuntimeTests": {
"_doc": "These axes are git/FS-hostile as committed files on macOS, so they live as runtime-materialized meta-tests in check-okf-parity.test.mjs (temp dir), not in this committed corpus.",
"symlink": "Symlinked .md, symlinked dir, and a symlink loop -> both impls skip symlinks (Dirent isFile/isDirectory are false), no crash/hang. Materialized because a committed symlink degrades to a plain path-string file where core.symlinks=false.",
"nfc-nfd-filename": "Precomposed (NFC) vs combining (NFD) filename bytes. platform-sensitive + soft-gated: git core.precomposeunicode normalizes NFD->NFC on macOS checkout, so the divergence cannot be pinned as a committed filename. The test logs if the FS normalized it away and does not hard-fail on this axis alone."
},
"withdrawn": {
"verbatim-trailing-newline": "Trinn E §1 (svar-catalog.local.md:742) withdrew it: linkedin-studio's newline-free serializer applies to ingest/published/, which is excluded from the OKF bundle by design; brain/ files DO get \\n. Re-classified a writer-parameter, not a form axis."
},
"outOfScope": {
"sti-former": "Path-forms (~-expansion, Windows separators, plugin-root anchoring). Trinn E (authoritative over STATE) does not re-list it in the D4 axis enumeration; folded into the §1.2 resolution-order spec text -> STEG 5 discovery convention, not the STEG 3 parity corpus."
}
}