Order 20260827T151230Z-5121410292-from-.claude, K2 of 4 mapping orders. Written by a prior Fable 5 session that died before committing; this session verified and commits it, does not rewrite it. Self-check gate re-run independently: 138 pipe rows, 18 without a backtick command = 9 table separators + 9 table headers -> 0 data rows lack a command. Matches the sender's claimed numbers exactly. KNOWN INCOMPLETENESS, not fixed here: the document's own trailing "Selvsjekk-porten" section (last section, ending the file) is an unfilled template — literal placeholders SELFCHECK_TOTAL, SELFCHECK_NOCMD, SELFCHECK_SEP, SELFCHECK_HDR, SELFCHECK_SENTENCE were never substituted with the computed values, because the writing session died before running its own closing self-check command. The body (Del A, B, C) is complete; only this trailing section is a stub. Left as-is per order (do not rewrite the deliverable). No code changes, no new measurement arm, no re-emission of bundles, no publishing, no recommendation on closing any gap — mapping-phase order. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
526 lines
69 KiB
Markdown
526 lines
69 KiB
Markdown
# OKF-nøkkelinventaret — 17 SPEC-nøkler og 33 egne, hver klassifisert med kommando
|
||
|
||
**Ordre K2/4** `20260827T151230Z-5121410292-from-.claude` · kartleggingsfase: ingen
|
||
kodeendring, ingen anbefaling om lukking, ingen ny målearm. Skrevet 2026-08-28 av en
|
||
Fable 5-økt **uten advisor**; kommandokravet er den eneste kontrollen. Hvert tall under
|
||
er produsert av kommandoen som står ved siden av det. Der noe ikke er målt står
|
||
«ikke målt»; der noe er antatt står «antatt»; der en seksjon ikke er lest står «ikke lest».
|
||
|
||
Inventaret bor her fordi `profiles.py` er stedet et navnevalg tas i biblioteket — men
|
||
**korpusets** nøkler velges i `vegnormal-okf/src/vegnormal_okf/bundle.py`, og det
|
||
repoet er lest, aldri skrevet. Hva som gjøres med et funn er fase 2/3 sitt, ikke dette
|
||
dokumentets.
|
||
|
||
## 0. Grunnlaget
|
||
|
||
### 0.1 Gate: SPEC-teksten er re-verifisert mot GitHub HEAD (28.08 kl 03)
|
||
|
||
```
|
||
curl -s -o /tmp/kc-spec.md 'https://raw.githubusercontent.com/GoogleCloudPlatform/knowledge-catalog/HEAD/okf/SPEC.md'; echo "curl exit=$?"
|
||
# -> curl exit=0 (37748 bytes)
|
||
diff /tmp/kc-spec.md ~/repos/_okf-canonical/SPEC.md | wc -l
|
||
# -> 0
|
||
wc -l ~/repos/_okf-canonical/SPEC.md; sed -n 3p ~/repos/_okf-canonical/SPEC.md
|
||
# -> 1006 · **Version 0.2**
|
||
git -C ~/repos/_okf-canonical log -1 --format='%h %ci' # -> ad30107 2026-08-21
|
||
git -C ~/repos/_okf-upstream log -1 --format='%h %ci' # -> 9a15b13 2026-08-24 (ORDREN SA 3fcbb9f)
|
||
git -C ~/repos/_okf-upstream reflog --date=iso -1 # -> checkout: 3fcbb9f -> origin/main, 2026-08-27 19:57:35 +0200
|
||
```
|
||
|
||
Utfallet er 0. `.claude` sin måling 27.08 kl 17 står, og grunnlaget holder. **Én
|
||
observasjon utenfor ordren:** den lokale `_okf-upstream`-kopien ble flyttet fra
|
||
`3fcbb9f` til `origin/main` (`9a15b13`) 27.08 kl 19:57 — etter at programplanen
|
||
skrev «baselinjen er den målte verdien, ikke det `git log` sier når K3 kjører».
|
||
Ingenting i dette dokumentet leses fra `_okf-upstream` unntatt v0.1-historikken
|
||
(§ 0.5), som er commit-adressert og upåvirket av HEAD.
|
||
|
||
### 0.2 Materialet og variablene
|
||
|
||
Alle kommandoer kjøres fra `~/repos/llm-ingestion-okf` med disse variablene satt:
|
||
|
||
```
|
||
S=~/repos/_okf-canonical/SPEC.md
|
||
B=~/repos/vegnormal-okf/build
|
||
E=$B/A-n500-2024 # EMITTERT av vegnormal-okf: krav/N500/id-*.md + normal/N500.md — 270 md-filer, ingen index.md
|
||
M=$B/F3-n500-2024-importert # IMPORTERT gjennom Dør C (guard 1.2.0): 270 konsepter + 1 index.md, flat — det armene F3/F4 leste
|
||
I=src/llm_ingestion_okf # dette repoet (importøren / emitterne A og B)
|
||
P=$I/profiles.py
|
||
V=~/repos/vegnormal-okf/docs/VEGNORMAL_V1.md
|
||
K1=~/repos/vegnormal-okf/docs/okf-spec-konformitet.md # ordre K1, levert 27.08
|
||
K3=~/repos/vegnormal-okf/docs/okf-eksempelkorpus.md # ordre K3, levert 28.08
|
||
R=~/repos/vegnormal-okf/docs/2026-08-26-resonnering-resultater.md
|
||
G=~/repos/llm-ingestion-pipeline-security/src/llm_ingestion_guard/okf.py # guard-kilden; installert 1.2.0 måles i .venv
|
||
```
|
||
|
||
Nevnere: `find $E -name '*.md' | wc -l` → **270** · `ls $M/*.md | wc -l` → **271**
|
||
(270 konsepter + `index.md`) · `find $B -name '*.md' ! -name index.md | wc -l` →
|
||
**48 983** (hele `build/`, alle armer og grenbaser) · `wc -l $P` → **1047** ·
|
||
`.venv/bin/python -c "import importlib.metadata as m; print(m.version('llm-ingestion-guard'))"`
|
||
→ **1.2.0** (= pinnen `pyproject.toml` l.35/113).
|
||
|
||
### 0.3 Tallene 17, 3 og 33 — produsert av kommando og avstemt mot operatørens
|
||
|
||
**17 SPEC-nøkler (§ 4 og § 5):**
|
||
|
||
```
|
||
sed -n 153,436p $S | grep -oE '^\s*(- )?[a-z_]+:' | sed -E 's/^[[:space:]]*(- )?//; s/://' | sort | uniq -c
|
||
# author 1 · description 3 · generated 3 · id 1 · last_modified 1 · resource 3 · sources 1 · stale_after 1
|
||
# status 1 · tags 3 · title 4 · type 3 · usage_count 1 · usage_window 1 · verified 2
|
||
sed -n 153,436p $S | grep -oE '^\s*(- )?[a-z_]+:' | sed -E 's/^[[:space:]]*(- )?//; s/://' | sort -u | wc -l
|
||
# -> 15
|
||
```
|
||
|
||
Kommandoen gir **15 unike navn**. `resource` og `title` forekommer både på toppnivå
|
||
(§ 4.1) og inne i en `sources`-oppføring (§ 5.1) med **ulik betydning** (asset-URI vs
|
||
kildens URI; konseptets navn vs kildens navn). Telles `sources[].resource` og
|
||
`sources[].title` som egne nøkler, blir det 15 + 2 = **17 — operatørens tall.**
|
||
Toppnivå alene er 11; § 5.1 lister nøyaktig seks oppføringsnøkler (l.303–313:
|
||
`resource`, `id`, `title`, `author`, `usage_count`, `last_modified`). `by`/`at` (feltene
|
||
i `generated`/`verified`-mappingene, l.377–389) er ikke talt; med dem ville det vært 19.
|
||
**Avstemt: 17 = 11 toppnivå + 6 `sources`-oppføringsnøkler.** Del A har én rad per nøkkel.
|
||
|
||
**3 i bruk hos oss:**
|
||
|
||
```
|
||
for k in type title description resource tags sources usage_window generated verified status stale_after; do printf '%s=%s ' $k "$(grep -l "^$k:" $M/*.md | wc -l | tr -d ' ')"; done; echo
|
||
# -> type=270 title=270 description=0 resource=0 tags=0 sources=0 usage_window=0 generated=0 verified=0 status=270 stale_after=0
|
||
find $E -name '*.md' -print0 | xargs -0 grep -l '^sources:' | wc -l # -> 270
|
||
```
|
||
|
||
**3 i M (`type`, `title`, `status`) — operatørens tall holder for bundlen armene leste.**
|
||
I E er det **4**: `sources` skrives 270/270 av emitteren og fjernes før import fordi
|
||
guarden avviser formen (G30; målt på nytt mot 1.2.0 i § 0.7). Avstemt.
|
||
|
||
**33 egne:**
|
||
|
||
```
|
||
for f in $M/*.md; do awk 'NR==1 && $0!="---"{exit} NR>1 && $0=="---"{exit} NR>1 && /^[A-Za-z_][A-Za-z0-9_]*:/{sub(/:.*/,""); print}' "$f"; done | sort -u | wc -l
|
||
# -> 36
|
||
# 36 − 3 spec-nøkler (type, title, status) = 33 — operatørens tall, i M.
|
||
find $B -name '*.md' ! -name index.md -print0 | xargs -0 awk 'FNR==1 && $0!="---"{nextfile} FNR>1 && $0=="---"{nextfile} FNR>1 && /^[A-Za-z_][A-Za-z0-9_]*:/{sub(/:.*/,""); print}' | sort -u | wc -l
|
||
# -> 44 over hele build/ (48 983 filer): 40 egne + type, title, status, sources
|
||
```
|
||
|
||
**Avstemt: 33 i M; 40 over hele `build/`.** De 7 ekstra er `erstatter`,
|
||
`erstattere_i_bundlen` (kun N100:2023-erstatter-bundlene), `gren`, `gren_direkte`,
|
||
`krav_i_normalen`, `grener_i_normalen` (kun grenbaser) og `viser_til_tabellnote` (0 i
|
||
N500). Del B.1 bærer alle 40 og merker hvilke 33 som står i M. Én nøkkel til er
|
||
**definert men aldri skrevet**: `viser_til_note` (`lenker.py` l.48, `fn`-klassen) —
|
||
`find $B -name '*.md' ! -name index.md -print0 | xargs -0 grep -l '^viser_til_note:' | wc -l`
|
||
→ **0** av 48 983 (kjent-positiv, samme spørring: `viser_til_formel` → 203). Den er
|
||
ikke en rad, fordi ingen bundle bærer den.
|
||
|
||
### 0.4 Premisset om `profiles.py` l.295 og l.770 — verifisert, ikke ordrett
|
||
|
||
```
|
||
grep -n 'while remaining v0.1 on every axis upstream owns' $P; echo exit=$?
|
||
# -> exit=1 (0 treff: frasen finnes IKKE ordrett på én linje)
|
||
grep -n 'v0.1 on every axis upstream' $P
|
||
# -> 295: ratified it (V1, `54e0ec7`), while remaining v0.1 on every axis upstream
|
||
# -> 770:# §5 layer, while the profile remains v0.1 on every axis upstream owns.
|
||
tr '\n' ' ' < $P | tr -s ' ' | grep -o 'remain[a-z]* v0.1 on every axis upstream owns'
|
||
# -> remaining v0.1 on every axis upstream owns (l.295–296, brutt over linjeskift)
|
||
# -> remains v0.1 on every axis upstream owns (l.770, annen bøyning)
|
||
```
|
||
|
||
Samme funn som K1 (§ 13): **ordrett for l.295 (over to linjer), i variant for l.770.**
|
||
Et linjebasert `grep` på frasen gir null — det er den samme fella som K1s `MUST NOT`.
|
||
|
||
**Hva det betyr for nøklene:** begge linjene beskriver `DEFAULT` sin `ownership`
|
||
(commons' ingest-spec § 7-lag). «v0.1 på hver akse upstream eier» betyr at `DEFAULT`
|
||
navngir **ingen** av v0.2-familiene i § 5 unntatt `generated`, som den skriver i O2-form
|
||
fordi commons ratifiserte den (`sed -n 805p $P` → `ownership=OwnershipPolicy(actor="process:okf-ingest")`).
|
||
Bibliotekets v0.2-støtte er profilen `OKF_V0_2` (`sed -n 1006p $P`), som **navngir**
|
||
`sources`, `verified`, `status`, `stale_after` (l.947–950) og § 10.2-feltene (l.942) og
|
||
**skriver** bare `sources` av dem (`materialize.py` l.241–242, kun under den profilen).
|
||
Korpusets emitter bruker ingen profil (K1: `grep -c BundleProfile src/vegnormal_okf/*.py`
|
||
→ 0), og Dør C importerer under `DEFAULT` (`sed -n 365p $I/importer.py` →
|
||
`profile: BundleProfile = DEFAULT`). Premisset gjelder altså importørens indeks- og
|
||
eierskapslag — ikke hva korpuset bærer.
|
||
|
||
### 0.5 Hvilke av de 17 kom TIL i v0.2 — målt mot v0.1-teksten, ikke antatt
|
||
|
||
```
|
||
git -C ~/repos/_okf-upstream log --format='%h %ci %s' -- okf/SPEC.md | tail -1
|
||
# -> ee67a5c 2026-06-11 Import Open Knowledge Format reference enrichment agent (#28)
|
||
git -C ~/repos/_okf-upstream show ee67a5c:okf/SPEC.md | sed -n 3p
|
||
# -> **Version 0.1 — Draft**
|
||
git -C ~/repos/_okf-upstream show ee67a5c:okf/SPEC.md | grep -oE '^\s*(- )?[a-z_]+:' | sed -E 's/^[[:space:]]*(- )?//; s/://' | sort -u | tr '\n' ' '
|
||
# -> description resource tags timestamp title type (6 nøkler i v0.1)
|
||
git -C ~/repos/_okf-upstream log --format='%h %ci %s' -S'Version 0.2' -- okf/SPEC.md | tail -1
|
||
# -> 780fe9d 2026-07-24 okf: migrate format and tooling to Open Knowledge Format v0.2 (#227)
|
||
sed -n 813,832p $S | grep -oE '`[a-z_]+`' | sort -u | tr '\n' ' '
|
||
# -> § 13.2: attester author computation description executor generated last_modified parameters resource runtime sources stale_after status tags title type usage_count usage_window verified
|
||
```
|
||
|
||
| kom i | nøkler | antall | kommando |
|
||
|---|---|---:|---|
|
||
| **v0.1, båret videre** | `type`, `title`, `description`, `resource`, `tags` | 5 | `git -C ~/repos/_okf-upstream show ee67a5c:okf/SPEC.md \| grep -oE '^\s*(- )?[a-z_]+:'` → de 6 over, minus `timestamp` |
|
||
| **v0.2, nye** | `sources`, `sources[].resource`, `sources[].id`, `sources[].title`, `sources[].author`, `sources[].usage_count`, `sources[].last_modified`, `usage_window`, `generated`, `verified`, `status`, `stale_after` | 12 | `sed -n 813,832p $S` (§ 13.2 «New frontmatter families») — de seks oppføringsnøklene er del av den nye `sources`-familien |
|
||
| **v0.1, avviklet** | `timestamp` → `generated.at` | 1 | `sed -n 805,808p $S` (§ 13.1) · `sed -n 42p $P` → `_TIMESTAMP_FALLBACK_PAIR = frozenset({"timestamp", "generated"})` |
|
||
|
||
**Konsekvens:** av de tre nøklene korpuset bruker er to v0.1 (`type`, `title`) og én
|
||
v0.2 (`status`); E skriver dessuten `sources` (v0.2) og 0 `timestamp`. Korpuset er
|
||
dermed **ikke «v0.1»** — det skriver to v0.2-nøkler og ingen v0.1-eksklusiv. `DEFAULT`
|
||
skriver v0.1-nøklene + `generated` i v0.2-form. `STRICT_V1` navngir `timestamp`
|
||
(`sed -n 819p $P`), som er den avviklede v0.1-nøkkelen — det er den eneste profilen
|
||
som gjør det, og den speiler en annen konsuments ratifiserte kontrakt (B.2).
|
||
|
||
### 0.6 Tidsformatet — hva VI skriver, målt
|
||
|
||
Regelen: `sed -n 284,285p $S` → «Every timestamp-valued key in OKF is an ISO 8601
|
||
datetime with an explicit UTC offset». Nøklene den binder: `generated.at`,
|
||
`verified[].at`, `sources[].last_modified`, `usage_window.{from,to}`, `stale_after` (5).
|
||
|
||
| hvem | nøkkel | form skrevet | konform | kommando |
|
||
|---|---|---|---|---|
|
||
| bibliotek, Dør A | `ingested_at` + `generated.at` | `2026-07-16T12:00:00Z` — 10/10 i goldens | **ja** (`Z` er spec-ens eget eksempel) | `grep -rhoE '^(ingested_at\|generated\|timestamp\|date\|stale_after): .*' examples \| sort \| uniq -c` → `5 generated: { by: process:okf-ingest, at: 2026-07-16T12:00:00Z }`, `5 ingested_at: 2026-07-16T12:00:00Z` · porten: `sed -n 37p $I/materialize.py` → `_INGESTED_AT_RE = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$")`, `sed -n 49p` (`validate_ingested_at`), `sed -n 235p` (`generated` avledes av samme verdi) |
|
||
| bibliotek, Dør B | `generated` | literalen `true` — ingen `at` i det hele tatt | **ikke en tidsverdi**; malformert etter § 5.2 (se Del A, `generated`) | `sed -n 143p $I/inbox.py` → `"generated": "true",` |
|
||
| korpus (E og M) | de fem spec-tidsnøklene | **0 skrevet** | ikke utløst | `for k in generated verified stale_after last_modified usage_window; do printf '%s=%s ' $k "$(find $E -name '*.md' -print0 \| xargs -0 grep -c "^ *$k:" \| awk -F: '{s+=$NF}END{print s}')"; done` → alle 0 |
|
||
| korpus | `kravdato` (egen nøkkel) | `YYYY-MM-DD`, 269/269; 0 med `T` | **utenfor regelen** (produsentnøkkel, `VEGNORMAL_V1 § 4.2` l.214) — men blir den noen gang mappet til en spec-tidsnøkkel, er formen feil; upstreams leser gjør en dato-only `stale_after` til *aldri stale* (`docs/plan/okf-2026-08-timestamp-tightening.md` l.144) | `find $E -name '*.md' -print0 \| xargs -0 grep -h '^kravdato:' \| grep -cE "^kravdato: '?[0-9]{4}-[0-9]{2}-[0-9]{2}'?$"` → 269 · `… \| grep -cE 'T[0-9]{2}:'` → 0 |
|
||
| bibliotek, `STRUCTURED_V1` | `date` (egen nøkkel, deklarert av kaller) | testene bruker `YYYY-MM-DD` | utenfor regelen (produsentnøkkel) | `grep -ho 'date: [0-9][^"\\]*' tests/*.py \| sort \| uniq -c` → `date: 2024-06-01`, `2026-01-01`, `2026-08-27` |
|
||
| bibliotek, `STRICT_V1` | `timestamp` (wikiens nøkkel, avviklet i v0.2) | testene bruker `Z`-form | formen er datetime; nøkkelen er § 13.1-avviklet | `grep -ho '"timestamp": "[^"]*"' tests/*.py \| sort -u` → `"2026-07-25T12:00:00Z"` |
|
||
|
||
**Hva vi skriver er konformt der regelen binder (10/10), og vi skriver ingen av de tre
|
||
nøklene den strammet inn** (`stale_after`, `last_modified`, `usage_window`). Den gamle
|
||
`YYYY-MM-DD`-formen finnes hos oss bare i produsentnøkler (`kravdato`, `date`).
|
||
|
||
### 0.7 Guard 1.2.0 — hva porten faktisk slipper gjennom (probe, ikke målearm)
|
||
|
||
Kjørt mot den installerte guarden i `.venv` (samme som Dør C bruker), med kjent-positiv
|
||
først. Dette er verdiformer, ikke en tiende arm.
|
||
|
||
```
|
||
.venv/bin/python -c '
|
||
from llm_ingestion_guard import okf
|
||
for n, d in {
|
||
"KJENT-POSITIV title": "---\ntype: Krav\ntitle: Krav 5.1-1 Generelt\n---\nb\n",
|
||
"description en linje": "---\ntype: Krav\ndescription: One sentence summarising the concept.\n---\nb\n",
|
||
"description brettet": "---\ntype: Krav\ndescription: One sentence that\n continues on a second line.\n---\nb\n",
|
||
"tags flow": "---\ntype: Krav\ntags: [a, b]\n---\nb\n",
|
||
"tags blokkliste": "---\ntype: Krav\ntags:\n - a\n - b\n---\nb\n",
|
||
"sources blokk-mappinger": "---\ntype: Krav\nsources:\n - resource: https://x\n title: N500:2024\n---\nb\n",
|
||
"sources flow-sekvens": "---\ntype: t\nsources: [{ id: a, resource: fixture }]\n---\nb\n",
|
||
"generated flow-mapping": "---\ntype: Krav\ngenerated: { by: process:okf-ingest, at: 2026-07-16T12:00:00Z }\n---\nb\n",
|
||
"generated: true (Dor B)": "---\ntype: Krav\ngenerated: true\n---\nb\n",
|
||
}.items():
|
||
try: okf.parse_frontmatter(d); print("PASS ", n)
|
||
except Exception as e: print("REJECT", n, "->", str(e)[:70])'
|
||
```
|
||
|
||
| verdi | guard 1.2.0 | betydning |
|
||
|---|---|---|
|
||
| `title` én linje (kjent-positiv) | PASS | spørringen kan skille — `okf.parse_frontmatter` returnerer `({'type': 'Krav', 'title': …}, body)` |
|
||
| `description` én linje | **PASS** | en énlinjes `description` ville passert Dør C i dag (`okf.parse_frontmatter` → `{'description': 'One sentence …'}`) |
|
||
| `description` brettet over to linjer | REJECT | `nested mappings are not supported in OKF frontmatter` — G33s «29/53 brettet» står for upstreams bundler (`~/.claude/docs/okf-bundle-prosessen.md` l.130) |
|
||
| `tags: [a, b]` | REJECT | `value begins with a disallowed YAML indicator '['` |
|
||
| `tags:` blokkliste | **PASS** | G33s «44/53 blokk avvist … ingen sekvens-verditype» gjelder en eldre guard; 1.2.0 leser `['a', 'b']` (`okf.parse_frontmatter`) |
|
||
| `sources:` blokk-sekvens av mappinger (E-formen, `bundle.py` l.167) | REJECT | `a mapping is not expressible in OKF frontmatter` — **G30 står ved 1.2.0** (registeret sa «UMÅLT mot 1.2.0», l.133; nå målt) |
|
||
| `sources: [{ … }]` flow-sekvens (Dør A under `OKF_V0_2`, `materialize.py` l.241) | REJECT | vår egen golden avvises: `.venv/bin/python -c 'from llm_ingestion_guard import okf; okf.parse_frontmatter(open("examples/ingest-golden-okf-v0-2/expected-bundle/ingest-sales.md").read())'` → `OKFFrontmatterError … '['` — den «målte begrensningen» i `$P` l.998–1005 (mot 0.2.0) **står fortsatt** |
|
||
| `generated: { by, at }` flow-mapping | **PASS** | 1.2.0 leser mappingen som `{'by': …, 'at': …}` — kommentaren i `$P` l.998–1003 («no expressible form») er foreldet for denne nøkkelen |
|
||
| `generated: true` (Dør B) | PASS | passerer porten som streng `'true'`; porten dømmer form, ikke § 5.2 |
|
||
|
||
Guardens mapping-nøkkel-allowlist: `sed -n 89,92p $G` → `by at from to id title author usage_count last_modified` — nøyaktig § 5.1/§ 5.2s feltnavn, **uten `resource`**, som er hvorfor `sources[].resource` inne i en mapping stopper (registerets G30-forklaring, l.133).
|
||
|
||
---
|
||
|
||
## Del A — de 17 nøklene SPEC navngir (§ 4 og § 5)
|
||
|
||
`bruker vi den` svares for **biblioteket** (dørene og profilene i `$I`) og **korpuset**
|
||
(E emittert / M importert), fordi de tar hvert sitt valg. `hva det koster oss` navngir
|
||
måling, arm og celle der en finnes; ellers «ikke målt».
|
||
|
||
| nøkkel | § | hva den er til | v | bruker vi den | hvorfor / hvorfor ikke | hva det koster oss | KOMMANDO |
|
||
|---|---|---|---|---|---|---|---|
|
||
| `type` | 4.1 REQUIRED (l.163–185) | kind of concept; routing/filtering; the only always-required key; values not registered centrally | 0.1 | **bib: ja** — Dør A (manifestets `okf_type`) og B (`inbox.py` l.132) skriver; `OKF_V0_2` krever (l.1011). **korpus: 270/270** (`Krav` 269, `Normal` 1) | påkrevd; verdiene er egendefinerte som § 4.1 tillater; `verdict` er reservert av commons (l.29) | 0 avvik — 270/270 passerte § 11 (K1 S11b); ingen arm skiller på `type` | `grep -h '^type:' $M/*.md \| sort \| uniq -c` → `269 type: Krav`, `1 type: Normal` · `sed -n 1011p $P` → `required=frozenset({"type"})` |
|
||
| `title` | 4.1 recommended (l.192–193) | display name; consumers MAY derive from filename | 0.1 | **bib: ja** — A og B skriver (`inbox.py` l.133); B utleder ved fravær (`structure.py` l.58). **korpus: 270/270** = `<req_number> <seksjonstittel>` (`bundle.py` l.194) | siterbar overskrift (`VEGNORMAL_V1 § 4` l.176) | **indeksen bruker den ikke som lenketekst:** Dør C setter konsept-id som label (`importer.py` l.268), så UUID står to ganger per rad og `title` legges som fasett bak — UUID 27,7 % + `title:`-felt 16,6 % av indeksen (K1 S8b, l.173; 75 837 tegn / 270 rader). Ikke målt som celler | `grep -l '^title:' $M/*.md \| wc -l` → 270 · `grep -c '^- \[krav/N500/id-' $M/index.md` → 270 · `grep -c ' — title: ' $M/index.md` → 270 · `sed -n 268,275p $I/importer.py` |
|
||
| `description` | 4.1 recommended (l.194–196); 8 SHOULD (l.527) | one-sentence summary; «Used by `index.md` generators, search snippets, and previews» | 0.1 | **bib: ingen dør skriver den.** `STRICT_V1` navngir (l.818) og bærer den i indeksmalen (l.859); `DEFAULT`/`OKF_V0_2`-malen har ingen plass (l.797). **korpus: 0/270 (E), 0/270 (M)** | ikke skrevet; `VEGNORMAL_V1` nevner den ikke (0 av 1073 linjer, kjent-positiv `` `kravtype` `` → 8), `bundle.py` navngir den ikke (0) | **se A.3** — indeksplassen § 8 gir den er fylt med en fasettdump; oppslagsaksen taper 4/13 (F4 9/13 mot R 13/13); hypotesen om årsak er **ikke målt** | `grep -l '^description:' $M/*.md \| wc -l` → 0 · `find $E -name '*.md' -print0 \| xargs -0 grep -l '^description:' \| wc -l` → 0 · `grep -l '^title:' $M/*.md \| wc -l` → 270 (kjent-positiv) · `grep -c '\`description\`' $V` → 0 · `grep -c '"description"' ~/repos/vegnormal-okf/src/vegnormal_okf/bundle.py` → 0 |
|
||
| `resource` | 4.1 recommended (l.197–199) | URI that uniquely identifies the underlying asset; absent for abstract concepts | 0.1 | **bib: nei** — ingen dør skriver, ingen profil navngir (§ B.2-enumereringen: 35 navn, `resource` ikke blant dem). **korpus: 0** på toppnivå; den ene URI-en vi har står i `sources[].resource` | ikke skrevet; om kilde-API-et tilbyr en per-krav-URI er **ikke undersøkt** | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c '^resource:' \| awk -F: '{s+=$NF}END{print s}'` → 0 · kjent-positiv `'^ - resource:'` → 270 · `grep -c '\`resource\`' $V` → 1 (l.383, om `sources`) |
|
||
| `tags` | 4.1 recommended (l.200–201); 3.1 (l.148–151) | YAML list of short strings; tag-browsing views are synthesized from it | 0.1 | **bib: aldri** skrevet eller lest (1 treff i 11 moduler, om HTML-tags). **korpus: 0** | ingen tverrgående kategorisering er definert utover `type`/`kravtype`/`seksjon` (`grep -c '\`tags\`' $V` → 0) | ikke målt. Porten: blokkliste passerer 1.2.0, flow avvises (§ 0.7) | `grep -n tags $I/*.py` → `extract.py:86` (HTML) · `grep -l '^tags:' $M/*.md \| wc -l` → 0 · `grep -c '^tags:' $S` → 3 (spec-ens egne eksempler, kjent-positiv) |
|
||
| `sources` | 5.1 (l.287–364) | provenance: the materials a concept derives from; list of entries | 0.2 | **bib: navngitt i `OKF_V0_2`** (l.947), **skrevet av Dør A kun under den profilen** som flow-sekvens (`materialize.py` l.241–242; golden 1/1) — **som guard 1.2.0 avviser** (§ 0.7). Parseren leser den ikke tilbake (`materialize.py` l.119, skalar). **korpus: E 270/270** blokk-sekvens av mappinger (`bundle.py` l.167–177); **M 0/270 — fjernet før import** (G30, står ved 1.2.0) | skrives fordi § 5.1 er den konforme formen (`VEGNORMAL_V1 § 9` l.381); fjernes fordi porten avviser mapping-i-sekvens | **proveniensen finnes ikke i noe armene leste:** 0/270 i M. Etter import er `utgave` (B.1) eneste bærer av utgaven. Ikke målt som celler | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^sources:' \| wc -l` → 270 · `grep -l '^sources:' $M/*.md \| wc -l` → 0 · `sed -n 241,242p $I/materialize.py` · `grep -rl '^sources:' examples \| wc -l` → 1 |
|
||
| `sources[].resource` | 5.1 REQUIRED i oppføringen (l.303–306) | artifact a consumer can follow (URL, bundle path, `references/`) **or a scope descriptor** («all queries in project X») | 0.2 | **bib:** Dør A skriver `resource: fixture`-plassholder i golden (l.184–). **korpus: E 270/270** — én absolutt URL til kilde-API-et, samme for alle (K1 N13) | peker tilbake til kilden | ikke målt (0 i M, se `sources`) | `find $E -name '*.md' -print0 \| xargs -0 grep -h '^ - resource:' \| sort -u \| wc -l` → 1 · `… \| grep -c '^ - resource: https://'` → 270 |
|
||
| `sources[].id` | 5.1 SHOULD når kroppen siterer (l.307–309) | stable key for per-claim attribution via `[^id]` footnotes (l.348–364) | 0.2 | **bib:** golden skriver `id: golden-v0-2-sales`. **korpus: 0** — ingen kropp siterer med fotnote | ikke utløst (K1 N10: 0 `[^`) | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c '^ id:' \| awk -F: '{s+=$NF}END{print s}'` → 0 · kjent-positiv `'^ title:'` → 270 · `grep -l '\[\^' $M/*.md \| wc -l` → 0 |
|
||
| `sources[].title` | 5.1 optional (l.310–311) | human-readable label for the source | 0.2 | **bib: nei.** **korpus: E 270/270** = `productTitle` (`bundle.py` l.177) | kildens navn | **dupliserer `utgave` 270/270 byte for byte** (B.1) — etter G30 er duplikatet det som overlever | `n=0; m=0; for f in $(find $E -name '*.md'); do u=$(grep -m1 '^utgave:' "$f" \| sed 's/^utgave: //'); s=$(grep -m1 '^ title:' "$f" \| sed 's/^ title: //'); m=$((m+1)); [ -n "$u" ] && [ "$u" = "$s" ] && n=$((n+1)); done; echo "$n av $m"` → `270 av 270` |
|
||
| `sources[].author` | 5.1 credibility signal (l.319–320); § 7 actor form | who/what produced the source — an authority signal | 0.2 | **bib: nei** (`materialize.py` l.188: «a manifest source has no author»). **korpus: 0** | ikke skrevet; kilden er et forvaltningsorgan, ikke en aktør i § 7-form — **ikke vurdert** | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c '^ author:' \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `sources[].usage_count` | 5.1 credibility signal (l.321–326) | how often `resource` was exercised over `usage_window` — liveness | 0.2 | **bib: nei. korpus: 0** | ingen brukstall finnes for kilden | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c 'usage_count' \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `sources[].last_modified` | 5.1 credibility signal (l.327–329); tidsnøkkel | when the source itself last changed — recency, distinct from `generated.at` | 0.2 | **bib: nei** (l.188). **korpus: 0** — den nærmeste egne nøkkelen er `kravdato` (dato-only, per krav, ikke per kilde) | om kilde-API-et bærer en endringsdato per produkt er **ikke undersøkt** | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c 'last_modified' \| awk -F: '{s+=$NF}END{print s}'` → 0 · `grep -c 'last_modified' $P` → 0 |
|
||
| `usage_window` | 5.1 sibling of `sources` (l.330–334); tidsnøkkel | `{ from, to }` datetime range framing every `usage_count` | 0.2 | **bib: nei. korpus: 0** | ikke utløst uten `usage_count` | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -c 'usage_window' \| awk -F: '{s+=$NF}END{print s}'` → 0 · `grep -c usage_window $P` → 0 |
|
||
| `generated` | 5.2 (l.366–380); `by` REQUIRED (l.377) | how the current content was produced: `{ by: <actor>, at: <datetime> }`; supersedes v0.1 `timestamp` (13.1) | 0.2 | **bib: ja, i TO former.** Dør A: O2-mappingen `{ by: process:okf-ingest, at: <ingested_at> }` (commons § 7 l.217; `$P` l.805; 5/5 goldens). Dør B: literalen `true` (`inbox.py` l.143) — **ingen `by`, malformert etter § 5.2**; eierskapet leser begge (`OwnershipPolicy.owns`, l.317–323). **korpus: 0/270** — Dør C skriver verbatim, emitteren skriver den ikke | A: commons ratifiserte O2 (V1, `54e0ec7`). B: Phase 2-literalen beholdes for ikke å gjøre alt Dør B har skrevet eierløst (kommentar l.137–141). Korpus: `trust_tier` valgt i stedet (B.1) | for en spec-konsument har korpusets 270 konsepter **ingen produsent** — ikke skillbare fra håndskrevne (§ 1 «honesty»). Dør B-bundler bærer en `generated` ingen v0.2-leser kan lese `by` av — hva upstreams leser gjør med `'true'` er **ikke målt** | `sed -n 143p $I/inbox.py` → `"generated": "true",` · `grep -rh '^generated:' examples \| sort -u` → `generated: { by: process:okf-ingest, at: 2026-07-16T12:00:00Z }` · `grep -l '^generated:' $M/*.md \| wc -l` → 0 · `sed -n 377p $S` → «`generated.by`: REQUIRED within `generated`» |
|
||
| `verified` | 5.2 (l.383–398); 5.3 (l.401–410) | verification events `[{ by, at }]`; **trust tier is derived from it**, never stored | 0.2 | **bib: navngitt** (l.948), ingen dør skriver; parseren kan ikke lese blokklisten (K1 N16; `materialize.py` l.119). **korpus: 0/270** — i stedet en lagret `trust_tier: unverified` 270/270 (B.1) | `VEGNORMAL_V1 § 8` (l.362): ingen automatikk setter «verified»; formen ble en egen nøkkel, ikke § 5.2-listen | **U6:** `hjemmel`/`fraviksmyndighet` er menneskekuratert (`§ 5` l.223) men ingen `verified` bærer det — 270 konsepter der det kuraterte feltet står som `unverified` med resten. Ikke målt på noen arm (armene leser ikke `trust_tier`, K1 N32) | `grep -l '^verified:' $M/*.md \| wc -l` → 0 · `grep -h '^trust_tier:' $M/*.md \| sort \| uniq -c` → `270 trust_tier: unverified` · `sed -n 403,407p $S` |
|
||
| `status` | 5.4 (l.412–422) | `draft \| stable \| deprecated`; **absent ⇒ `stable`** | 0.2 | **bib: navngitt** i `OKF_V0_2` (l.949) og som fasett i `STRUCTURED_V1` (l.885); ingen dør skriver den selv. **korpus: 270/270 `stable`** (`bundle.py` l.34, `VEGNORMAL_V1 § 6` l.274); over hele build 884 `deprecated` / 6 209 `stable` (K1 S5c) | verdiene er i enumet; mappingen er kildens publiseringsstatus | 0 avvik. Indeksen bærer `; status: stable` på 270/270 rader = **4 590 av 77 611 bytes (5,9 %)** for verdien § 5.4 gjør til default ved fravær. Ikke målt som celler | `grep -h '^status:' $M/*.md \| sort \| uniq -c` → `270 status: stable` · `grep -o '; status: stable' $M/index.md \| wc -c` → 4590 · `wc -c < $M/index.md` → 77611 · `sed -n 422p $S` → «Absent `status` ⇒ `stable`.» |
|
||
| `stale_after` | 5.5 (l.424–435); tidsnøkkel | absolute instant; stale when `now >= stale_after` | 0.2 | **bib: navngitt** (l.950), ikke skrevet. **korpus: 0** | normalene har kildens gyldighet (`kravdato`, `utgave`), som ikke er en `stale_after` (K1 S5d) | ikke målt | `grep -l '^stale_after:' $M/*.md \| wc -l` → 0 · `grep -c '"stale_after"' $P` → 1 (l.950) |
|
||
|
||
### A.2 Nøkler SPEC navngir utenfor § 4–5 som `profiles.py` også navngir
|
||
|
||
Ikke blant de 17 (ordren avgrenset til § 4 og § 5), men de er i bibliotekets navnerom
|
||
og hører derfor i inventaret — 6 rader, alle 0 i korpuset.
|
||
|
||
| nøkkel | § | hva | bruker vi den | kostnad | KOMMANDO |
|
||
|---|---|---|---|---|---|
|
||
| `runtime` | 10.2 REQUIRED for `Attested Computation` (l.588–591) | how to run the computation; defines what `parameters` mean | **bib: navngitt** (l.942), typebetinget påkrevd (l.1017); ikke skrevet. **korpus: 0** — et krav bærer ingen sanksjonert beregning (K1 N27) | ikke relevant | `sed -n 942p $P` · `sed -n 1017p $P` · `grep -l '^type: Attested Computation' $M/*.md \| wc -l` → 0 |
|
||
| `parameters` | 10.2 (l.592–594) | typed, named holes `{ name, type, required }` | som over | ikke relevant | `grep -c '^parameters:' $M/*.md \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `computation` | 10.2 (l.595–597); stifelt 6.2 | path to the computation file; absent ⇒ body fence | som over | ikke relevant | `grep -c '^computation:' $M/*.md \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `executor` | 10.2 (l.598–602) | `{ resource, receipt }` — how it is run, what a run returns | som over; importøren rapporterer uløste pekere (`UnverifiedReference`, K1 N32) | ikke relevant | `grep -c '^executor:' $M/*.md \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `attester` | 10.2 (l.603–605) | deterministic check `{ resource }` | som over | ikke relevant | `grep -c '^attester:' $M/*.md \| awk -F: '{s+=$NF}END{print s}'` → 0 |
|
||
| `okf_version` | 8 (l.512–513) MAY; 12 (l.776–778) | `okf_version: "0.2"` in the **root** `index.md` frontmatter — the only frontmatter an index may carry | **bib: ja** — `OKF_V0_2` navngir plassen (l.1023), `STRICT_V1` krever den (l.867); verdien er kallerens (D5/E1). Golden skriver `okf_version: 0.2` **usitert** (spec-eksempelet er `"0.2"`; upstreams leser koerserer til `float`, A-E6). **korpus: M-indeksen har ingen** | ikke målt | `grep -c okf_version $M/index.md` → 0 · `sed -n 1,3p examples/ingest-golden-okf-v0-2/expected-bundle/index.md` → `---` / `okf_version: 0.2` / `---` · `sed -n 776,778p $S` |
|
||
|
||
### A.3 `description` — nøkkelen med egen underseksjon
|
||
|
||
**1. Fraværet, med nevner og kjent-positiv.**
|
||
|
||
```
|
||
grep -l '^description:' $M/*.md | wc -l # -> 0 (nevner 271, hvorav 270 konsepter)
|
||
find $E -name '*.md' -print0 | xargs -0 grep -l '^description:' | wc -l # -> 0 (nevner 270)
|
||
grep -l '^title:' $M/*.md | wc -l # -> 270 (kjent-positiv: samme spørring finner)
|
||
grep -c '`description`' $V # -> 0 (profilen nevner den ikke; kjent-positiv `kravtype` -> 8)
|
||
grep -c '"description"' ~/repos/vegnormal-okf/src/vegnormal_okf/bundle.py # -> 0 (emitteren navngir den ikke)
|
||
```
|
||
|
||
Nøkkelen er **ikke valgt bort — den er aldri vurdert**: verken kontrakten eller
|
||
emitteren nevner den. Det er en annen tilstand enn «forkastet».
|
||
|
||
**2. Hva spec sier den er til.** `sed -n 194,196p $S` → «A single sentence summarizing
|
||
the concept. Used by `index.md` generators, search snippets, and previews.» `sed -n 527p $S`
|
||
→ «Entries SHOULD include the description from the linked concept's frontmatter.»
|
||
**Den er den eneste nøkkelen § 8 navngir som innhold i en indeksoppføring.**
|
||
|
||
**3. Hva upstream gjør (K3, allerede målt — sitert, ikke re-målt).** `sed -n 177p $K3`
|
||
(rad A4d): `description` til stede i **9/10, 9/9, 9/9, 26/26** av de fire
|
||
referansebundlenes konsepter, mot **0/270** hos oss. `sed -n 150p $K3` (A3e): upstreams
|
||
indeks-beskrivelse er frontmatterens `description` **ordrett** for de genererte bundlene.
|
||
|
||
**4. Hva vår indeks bærer i stedet.** Plassen § 8 gir `description` er fylt med en
|
||
serialisert frontmatter-dump:
|
||
|
||
```
|
||
head -1 $M/index.md | cut -c1-120
|
||
# -> - [krav/N500/id-0000b3ff-…](import-krav-n500-id-0000b3ff-….md) — title: …; req_number: …; seksjon: …; seksjonstittel: …; kravtype: …; status: …
|
||
grep -c ' — title: ' $M/index.md # -> 270
|
||
grep -oE '(^|; )[a-z_]+: ' $M/index.md | sed 's/^; //' | sort | uniq -c
|
||
# -> 269 kravtype · 269 req_number · 269 seksjon · 269 seksjonstittel · 270 status · 270 title (og 0 description)
|
||
```
|
||
|
||
K1 S8b (`sed -n 173p $K1`) målte formen: 75 837 tegn / 270 rader; UUID 27,7 %,
|
||
`title:`-felt 16,6 %, fasettnavn 16,0 %; § 8-formen `* [Title](fil) - ` **uten**
|
||
description ville vært 37,9 % av dagens størrelse. Hva en `description` ville lagt
|
||
til, er ikke målt — ingen finnes å måle.
|
||
|
||
**5. Armene — oppslag skilt fra relasjon (R l.780–787, sitert):**
|
||
|
||
| arm | relasjon (13) | oppslag (13) | T4 (3) | sum | tegn/celle (17-nevner) | kommando |
|
||
|---|---:|---:|---:|---:|---:|---|
|
||
| R flatt BM25-søk | 0/13 | **13/13** | — | 15/29 | 3 209 (0,4 % av V) | `sed -n 28p $R` · `sed -n 552,554p $R` |
|
||
| G GraphRAG | 4/13 | **13/13** | 3/3 | 20/29 | 162 654 | `sed -n 787p $R` |
|
||
| F simulert fasett | 13/13 | 9/13 | 3/3 | 25/29 | 80 627 | `sed -n 782p $R` |
|
||
| F2 ekte Dør C, `STRUCTURED_V1`-fasetter (indeks = `title` + `status`) | 13/13 | 8/13 | 2/3 | 23/29 | 103 706 | `sed -n 783p $R` · `grep -oE '(^\|; )[a-z_]+: ' $B/F2-n500-2024-importert/index.md \| sort -u` → `status`, `title` |
|
||
| F3 ekte Dør C, korpusets nøkler | 13/13 | 7/13 | 2/3 | 22/29 | 162 820 | `sed -n 784p $R` |
|
||
| **F4** = F3 sortert på `req_number` | 13/13 | **9/13** | 3/3 | 25/29 | 162 740 (22,6 %) | `sed -n 785p $R` · `sed -n 35p $R` |
|
||
|
||
**Oppslag: R 13/13 og G 13/13 mot F4 9/13** — det er de 4 cellene «den svake
|
||
oppslagsaksen» består av. Relasjon: 13/13 i alle OKF-armer, 0/13 i R.
|
||
|
||
**6. Hypotesen, som hypotese.** «0 `description` er den enkleste forklaringen på at
|
||
oppslag taper» er **ikke målt**: ingen arm har lest en indeks med `description` (K1 S8c:
|
||
«ikke målt»). Og det finnes en **målt konkurrerende forklaring** i samme dokument:
|
||
`sed -n 545,548p $R` — G tar 13/13 på oppslag fordi den bærer `requirement_level` per
|
||
seksjon fra kilden (T7 veiledningsfelle 4/4 mot 2/4; T8 mutert hypotese 5/5 mot 3/5) —
|
||
det er **modalitet (U2)**, ikke en beskrivelse. Begge står åpne. Fase 2 velger hva som
|
||
måles; dette dokumentet gjør det ikke.
|
||
|
||
**7. Porten.** En énlinjes `description` **passerer guard 1.2.0** (§ 0.7); en brettet
|
||
avvises. G33s «29/53 brettet» (`~/.claude/docs/okf-bundle-prosessen.md` l.130) gjelder
|
||
upstreams bundler, ikke en verdi vi selv ville skrevet.
|
||
|
||
**8. Biblioteket.** Selv med `description` i frontmatter ville Dør C under `DEFAULT`
|
||
ikke løftet den inn i indeksen: `sed -n 797p $P` → `link_template="- [{label}]({target})"`
|
||
(ingen plass); `STRUCTURED_V1` sine fasettnøkler navngir den ikke
|
||
(`sed -n 882,891p $P`); bare `STRICT_V1` bærer den (`sed -n 859p $P` →
|
||
`* [{label}]({target}) - {description}`). **Spaken ligger i profilvalget, som S8c fant
|
||
for § 8-formen.**
|
||
|
||
---
|
||
|
||
## Del B — de egne nøklene
|
||
|
||
### B.0 Klassene, og hvordan «spec har den alt» er tolket
|
||
|
||
Ordren gir tre klasser og krever nøyaktig én per nøkkel. Klasse (1) «en OKF-nøkkel under
|
||
et annet navn» er brukt slik: **spec spesifiserer en plass for den samme informasjonen
|
||
— en nøkkel ELLER en strukturell plass** (kroppslenke § 6.1, fotnote → `sources[].id`
|
||
§ 5.1, seksjonsoverskrift § 8, utledning § 5.3). Uten den lesningen ville ingen av
|
||
relasjonsnøklene kunne klassifiseres i det hele tatt, for § 6.1 har ingen nøkkel — og det
|
||
er nettopp den klassen som er dyrest: en konsument som leter på spec-plassen finner
|
||
ingenting. Tolkningen står her så klassifiseringen kan etterprøves, ikke bare leses.
|
||
|
||
`dupliserer` navngir det som **allerede finnes** et annet sted i samme dokument eller
|
||
bundle, målt. `kostnad` navngir måling/arm/celle eller «ikke målt».
|
||
|
||
### B.1 Korpusets 33 nøkler (+ 7 i andre bundler) — hentet av kommandoen i § 0.3
|
||
|
||
Tellinger: `M`/`E` = filer i den importerte/emitterte N500-bundlen (nevner 270 konsepter);
|
||
`build` = filer over hele `build/` (nevner 48 983). Kilde-linjer i `bundle.py` (`bundle.py`
|
||
= `~/repos/vegnormal-okf/src/vegnormal_okf/bundle.py`), `lenker.py`, `gren.py` samme katalog.
|
||
|
||
| nøkkel | M / E / build | hva den bærer | klasse | begrunnelse — spec-plass (1) / hvorfor spec ikke bærer den (2) / hvorfor påfunn (3) | dupliserer | kostnad | KOMMANDO |
|
||
|---|---|---|:---:|---|---|---|---|
|
||
| `kravtype` | 269 / 269 / 48 355 | normativ modalitet `skal\|bør\|kan`, kildens `vocab-term` totalt mappet, aldri utledet (`VEGNORMAL_V1 § 4.1` l.194; `bundle.py` l.31) | **(2)** | spec bærer ikke modalitet: K1 § M — 1 treff på `modal\|normativ\|shall\|…` i 1006 linjer, og det om spec-ens egen tekst (l.701); `RECOMMENDED`/`OPTIONAL` 0. Et normativt korpus uten skillet krav/anbefaling er verre enn ingen bundle (U2). Verdien er kildens, ikke vår | kroppens `## Krav` / `## Veiledning (ikke-normativ)` (269/171) bærer skillet strukturelt (K1 M2) | **indeksraden** bærer `kravtype:` 269/270 (K1 M3) — det eneste stedet en konsument ser modaliteten før den åpner filen, og det **forsvinner ved § 8-formen** med mindre `description` bærer den. G tar T7 4/4 på nettopp modalitet mot OKF 2/4 (`sed -n 545,548p $R`) | `grep -h '^kravtype:' $M/*.md \| sort \| uniq -c` → `269 kravtype: skal` · `grep -c 'kravtype: ' $M/index.md` → 269 · `sed -n 31p bundle.py` |
|
||
| `normal` | 270 / 270 / 48 983 | normalens referanse, `meta.standardReference` (`N500`) (`§ 4` l.178; `bundle.py` l.199, 285) | **(3)** | ikke spec-forankret, og informasjonen finnes alt: konsept-id-en ER stien (§ 2 l.78–79) og katalogsegmentet er normalen (`krav/N500/…`, `VEGNORMAL_V1 § 3` l.95–99); etter Dør C står den i filnavnet (`import-krav-n500-…`). Ingen arm eller indeks leser den (0 i indeksen) | **konsept-id-ens katalogsegment 269/269** (`krav/N500/` ↔ `normal: N500`) | ikke målt | `find $E/krav -name '*.md' -print0 \| xargs -0 grep -h '^normal:' \| sort \| uniq -c` → `269 normal: N500` · `find $E/krav -type d` → `krav/N500` · `grep -c 'normal: ' $M/index.md` → 0 |
|
||
| `utgave` | 270 / 270 / 48 983 | utgavetittel `productTitle` (`N500:2024`) (`§ 4` l.180; `bundle.py` l.200, 286) | **(1)** | **`sources[].title`, § 5.1 l.310** — samme verdi skrives to steder i samme dokument (`bundle.py` l.177 og l.200), 270/270 byte-identisk | **`sources[].title` 270/270** | etter G30 er `utgave` **eneste** bærer av utgaven i M (`sources` 0/270) — duplikatet er i dag det som overlever porten. Ikke målt som celler | kommandoen i Del A `sources[].title` → `270 av 270` · `grep -l '^utgave:' $M/*.md \| wc -l` → 270 · `grep -l '^sources:' $M/*.md \| wc -l` → 0 |
|
||
| `req_number` | 269 / 269 / 48 355 | kravets nummer i kilden, `a["req-number"]` — **posisjon, ikke identitet** (`§ 4` l.181; `§ 3` l.107–117) | **(2)** | spec har ingen nøkkel for et dokumentnummer; nærmeste er `title` (fri tekst) og #10s ledende konsept (katalognavn, ikke nummer). Korpuset siterer krav ved nummer, og **rekkefølgen er en målt ytelsesegenskap:** F3 → F4 (samme indeks sortert på `req_number`) = 12/17 → 14/17, 22/29 → 25/29 (`sed -n 35p $R`, `sed -n 784,785p $R`). Egen ordre `…3790625395`, ikke slått sammen her | **`title` begynner med `req_number` 269/269** (`bundle.py` l.194: `f"{piece.req_number} {piece.section_title}"`) | indeksraden bærer den 269/270 som fasett; `title:`-feltet (16,6 %, K1 S8b) bærer den én gang til | `n=0; m=0; for f in $(find $E/krav -name '*.md'); do t=$(grep -m1 '^title:' "$f" \| sed "s/^title: //; s/^'//; s/'\$//"); r=$(grep -m1 '^req_number:' "$f" \| sed "s/^req_number: //; s/^'//; s/'\$//"); m=$((m+1)); case "$t" in "$r"*) n=$((n+1));; esac; done; echo "$n av $m"` → `269 av 269` · `grep -c 'req_number: ' $M/index.md` → 269 |
|
||
| `kravdato` | 269 / 269 / 48 355 | kravets `valid-from`, ISO-dato UTC; følger kravet, ikke utgaven (`§ 4.2` l.214–220) | **(2)** | spec har ingen «gyldig fra»: `generated.at` er innholdets endring, `sources[].last_modified` er kildens endring, `stale_after` er utløp — ingen er ikrafttredelse. Dato-only-formen er lovlig fordi nøkkelen er vår (§ 0.6) | ingen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -h '^kravdato:' \| grep -cE "^kravdato: '?[0-9]{4}-[0-9]{2}-[0-9]{2}'?$"` → 269 · `sed -n 214,220p $V` |
|
||
| `hjemmel` | 270 / 270 / 48 983 | rettslig hjemmel, **kuratert av et menneske per normal**, arvet ned på hvert krav (`§ 5` l.223–257) | **(2)** | ingen OKF-analogi (U4): spec kjenner `resource` (asset) og `sources` (materiale), ikke rettsgrunnlag. Kuratert fordi kilden ikke bærer den strukturert (attributtlisten l.233–236) | ingen | **U6:** kuratert verdi uten `verified` — 270 konsepter der det menneskeleste feltet står som `unverified` (K1 § U). Ikke målt som celler | `grep -l '^hjemmel:' $M/*.md \| wc -l` → 270 · `grep -h '^trust_tier:' $M/*.md \| sort -u` → `trust_tier: unverified` · `sed -n 223,230p $V` |
|
||
| `fraviksmyndighet` | 270 / 270 / 48 983 | hvem som kan gi fravik; kuratert; fast streng `ikke uttalt i kilden` der kilden er taus (`§ 5` l.259–272) | **(2)** | som `hjemmel` (U4). Et **erklært fravær** er en verdi spec ikke har noen plass for (U5/U8-seamen) | ingen | som `hjemmel`; ikke målt | `grep -l '^fraviksmyndighet:' $M/*.md \| wc -l` → 270 · `grep -h '^fraviksmyndighet:' $M/*.md \| sort \| uniq -c \| wc -l` → antall distinkte verdier · `sed -n 259,272p $V` |
|
||
| `hjemmel_sitat` | 1 / 1 / 628 | sitatet fra kilden `hjemmel` er lest av, som belegg (`§ 5` l.244–246; `bundle.py` l.288) — kun på `Normal` | **(3)** | innholdet er nødvendig (etterprøvbarhet); **nøkkelen** er det ikke, og den er ikke spec-forankret: spec-ens plass for «belegget for en påstand» er kroppen med `[^id]`-fotnote til en `sources`-oppføring (§ 5.1 l.348–364). Et sitat er prosa, og frontmatter-skalaren kan ikke bære et lengre sitat uten brett (§ 0.7) | ingen (verdien er unik) | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^hjemmel_sitat:'` → `normal/N500.md` (1) · `sed -n 348,352p $S` |
|
||
| `fraviksmyndighet_sitat` | 1 / 1 / 628 | som over, for `fraviksmyndighet` (`bundle.py` l.290) | **(3)** | som `hjemmel_sitat` | ingen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^fraviksmyndighet_sitat:' \| wc -l` → 1 |
|
||
| `trust_tier` | 270 / 270 / 48 983 | lagret tillitsnivå `unverified\|verified` (`§ 8` l.362–379; `bundle.py` l.56, 206) | **(1)** | **§ 5.3 l.401–407: tieren UTLEDES av `verified`** — «No `verified` key ⇒ unverified». En lagret `unverified` sier det en spec-konsument utleder av fraværet uansett; vokabularet er 2 verdier mot spec-ens 3 tiers; og den dagen et menneske signerer, er spec-plassen `verified: [{ by: human:<id>, at }]` (§ 7 l.500, K1 N20), ikke denne nøkkelen. K1 S5b fant det samme | **fraværet av `verified`** (270/270 bærer `unverified` og 0 bærer `verified`) | 0 informasjon for en spec-konsument; armene leser den ikke (K1 N32: 0 filer). U6 hviler på den | `grep -h '^trust_tier:' $M/*.md \| sort \| uniq -c` → `270 trust_tier: unverified` · `grep -l '^verified:' $M/*.md \| wc -l` → 0 · `sed -n 403,407p $S` |
|
||
| `seksjon` | 269 / 269 / 48 355 | seksjonsnummeret kravet står i, fra forfedrene i treet (`§ 4` l.187; `bundle.py` l.207) | **(2)** | spec har ingen nøkkel for plass i et hierarki; dens bærer er katalogtreet + § 8-indeks per katalog (+ #10s ledende konsept). Vår bundle har **1 katalog** etter import (K1 N21), så treet bærer ingenting, og nummeret finnes ingen andre steder. Grenformen partisjonerer på den (`VEGNORMAL_V1 § 16`) | ingen (nummeret) | fasett i indeksen 269/270; N101: 7/352 krav uten seksjon (kildens vedlegg, `2026-08-25-grenformen-og-tallene.md § 4.1`) | `grep -c 'seksjon: ' $M/index.md` → 269 · `find $M -type d \| wc -l` → 1 · `grep -l '^seksjon:' $M/*.md \| wc -l` → 269 |
|
||
| `seksjonstittel` | 269 / 269 / 48 355 | seksjonens overskrift (`§ 4` l.188; `bundle.py` l.208) | **(1)** | **§ 8 «Section / Group Heading» (l.517)** er spec-plassen for en seksjonstittel som grupperer konsepter — og vår indeks har 0 overskrifter (K1 S8a). Dessuten er verdien alt i `title` | **`title` = `req_number` + ` ` + `seksjonstittel` 269/269** (`bundle.py` l.194) — halen av tittelen er nøkkelen | fasett i indeksen 269/270 (del av fasettnavnenes 16,0 %, K1 S8b) — verdien står altså **to ganger per indeksrad** (i `title:` og i `seksjonstittel:`) | `grep -c 'seksjonstittel: ' $M/index.md` → 269 · `grep -c '^#' $M/index.md` → 0 · `sed -n 194p bundle.py` |
|
||
| `lenker` | 14 / 14 / 1 140 | blokkliste av konsept-id-er kravet viser til (`statement`-xref) — eneste klasse som peker på noe bundlen bærer (`§ 13.2` l.559; `lenker.py` l.37) | **(1)** | **§ 6.1 l.439–466: markdown-lenke i kroppen.** 17 unike mål, alle løser til en fil (K1 S6a); 0 lenker i noen kropp (K1 N18). En konsument som bygger graf av § 6.1-kanter ser 0 kanter | ingen — men **`viser_til_krav` bærer samme referanser som tekst** (`lenker.py` l.297–299: begge skrives for hver `statement`) | **indeksen: 0/270** (K1 N6, Funn 1 i `STATE`: blokklister blir tom streng i `parse_frontmatter`). Relasjonsspørsmål: 13/13 i F, F2 **og** F3 (`sed -n 624,625p $R`) — F2-indeksen bar bare `title` + `status`, så relasjonene ble svart fra filene, ikke fra nøkkelen i indeksen | `grep -l '^lenker:' $M/*.md \| wc -l` → 14 · `grep -c 'lenker' $M/index.md` → 0 · `sed -n 297,299p lenker.py` |
|
||
| `viser_til_krav` | 14 / 14 / 1 140 | kildens tekst for `statement`-referanser (`§ 13.1` l.531–557; `lenker.py` l.41) | **(1)** | § 6.1-lenke i kroppen, med lenketeksten som «kildens tekst» — nøyaktig § 6.1s form `[tekst](/sti)`. K3 målte at upstream bærer arten i overskriften + fotnote (idéboka U1) | **`lenker`** — samme referanser, id der og tekst her (`lenker.py` l.297–299) | som `lenker` | `grep -l '^viser_til_krav:' $M/*.md \| wc -l` → 14 · `diff <(grep -l '^lenker:' $M/*.md) <(grep -l '^viser_til_krav:' $M/*.md) \| wc -l` → 0 (samme 14 filer) |
|
||
| `viser_til_kapittel` | 24 / 24 / 5 609 | seksjonsoverskrift for `sec`-referanser (`lenker.py` l.42) | **(1)** | § 6.1: en lenke til seksjonen — som **ikke er et konsept** (`VEGNORMAL_V1 § 2` l.72–88), så målet finnes ikke i bundlen; § 6.1 l.464 tillater brutte lenker eksplisitt («not-yet-written knowledge»). Grenformens seksjonsbaser er det nærmeste målet | ingen | indeksen 0; relasjon 13/13 uavhengig (se `lenker`) | `grep -l '^viser_til_kapittel:' $M/*.md \| wc -l` → 24 · `sed -n 464,466p $S` |
|
||
| `viser_til_tabell` | 31 / 31 / 5 362 | kildens tekst for `table`-referanser (`lenker.py` l.43) | **(1)** | § 6.1-lenke, eller ren prosa når tabellen ikke er et mål (tabeller bæres i kroppen som HTML, `§ 14.3`) | ingen | indeksen 0 | `grep -l '^viser_til_tabell:' $M/*.md \| wc -l` → 31 |
|
||
| `viser_til_figur` | 23 / 23 / 3 451 | figurens bildetekst for `fig`-referanser (`lenker.py` l.44) | **(1)** | § 6.1-lenke — til noe bundlen **ikke bærer** (`§ 14` l.598: figurer erklært, ikke båret); en brutt lenke er lovlig (l.464) | figurinventaret i `Normal`-kroppen navngir samme figur (`bundle.py` `_figure_inventory`) | indeksen 0 | `grep -l '^viser_til_figur:' $M/*.md \| wc -l` → 23 |
|
||
| `viser_til_referanse` | 97 / 97 / 5 707 | kildens tekst for `bibr` — litteraturreferanser (`lenker.py` l.45) | **(1)** | **§ 5.1 `sources` + `[^id]`-fotnote (l.348–364)** er spec-ens plass for en litteraturreferanse per påstand. Vi har 0 fotnoter og én `sources`-oppføring (kilde-API-et) | ingen | indeksen 0. Den mest brukte relasjonsnøkkelen (97 filer) står på en plass ingen spec-konsument leser | `grep -l '^viser_til_referanse:' $M/*.md \| wc -l` → 97 · `grep -l '\[\^' $M/*.md \| wc -l` → 0 |
|
||
| `viser_til_tillegg` | 3 / 3 / 74 | kildens tekst for `app`-referanser (`lenker.py` l.46) | **(1)** | § 6.1-lenke/prosa, som `viser_til_kapittel` | ingen | indeksen 0 | `grep -l '^viser_til_tillegg:' $M/*.md \| wc -l` → 3 |
|
||
| `viser_til_ekstern` | 2 / 2 / 2 950 | `ext-link`-URL-er ordrett, inkl. kryss-normal (`§ 13.3` l.569–573; `lenker.py` l.38) | **(1)** | **§ 6.1 absolutt URL i kroppen** («an absolute URL (for example `https://...`)», § 6.2 l.473) — nøyaktig formen; kryss-normal blir aldri `lenker` fordi målet er en annen bundle | ingen | indeksen 0 | `grep -l '^viser_til_ekstern:' $M/*.md \| wc -l` → 2 |
|
||
| `viser_til_formel` | 1 / 1 / 203 | kildens tekst for `disp-formula` (`lenker.py` l.49) | **(1)** | § 6.1-lenke/prosa; formler er kildens prosa, ikke `computation` (K1 N27) | ingen | indeksen 0 | `grep -l '^viser_til_formel:' $M/*.md \| wc -l` → 1 |
|
||
| `viser_til_tabellnote` | 0 / 0 / 1 000 | kildens tekst for `table-fn` (`lenker.py` l.47) — **ikke i N500** | **(1)** | som `viser_til_tabell` | ingen | ikke målt (0 i M) | `find $B -name '*.md' ! -name index.md -print0 \| xargs -0 grep -l '^viser_til_tabellnote:' \| wc -l` → 1000 · `grep -l '^viser_til_tabellnote:' $M/*.md \| wc -l` → 0 |
|
||
| `krav_i_kilden` | 1 / 1 / 628 | kildens eget kravtall (`requirementTypeCounts` summert) — **skal** være lik `krav_i_bundlen`, ellers bygges ingen bundle (`§ 7` l.291–311; `bundle.py` l.293) | **(2)** | spec har ingen representasjon av **dekning/fullstendighet** (`grep -n -i 'coverage\|completeness\|complete' $S` → 2 treff, begge om «completed order»/«incomplete» i eksempler; kjent-positiv `frontmatter` → 28). Uten erklæringen leses en bundle som fullstendig, og det er den ikke (l.293–295). Negativ tilstand — U5-seamen | kroppens `## Dekning` sier det samme i prosa (`bundle.py` l.313: «Bundlen bærer {built} krav av {declared}») | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -h '^krav_i_kilden:\|^krav_i_bundlen:'` → to like tall · `sed -n 291,311p $V` |
|
||
| `krav_i_bundlen` | 1 / 1 / 628 | krav profilen faktisk skrev (`bundle.py` l.294); omskrevet i grenbaser (`§ 16.3` l.1021) | **(2)** | som `krav_i_kilden` — de to er ett invariant | `## Dekning`-prosaen | ikke målt | samme kommando · `sed -n 1021,1030p $V` |
|
||
| `tabeller_i_krav` | 1 / 1 / 625 | tabeller båret strukturelt inne i krav (`§ 7` l.328–337) | **(2)** | dekningserklæring; spec har ingen | `## Dekning`-prosaen (`bundle.py` l.316–319) | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^tabeller_i_krav:' \| wc -l` → 1 |
|
||
| `tabeller_uten_label` | 1 / 1 / 625 | bårne tabeller uten label i kilden | **(2)** | dekningserklæring | ingen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^tabeller_uten_label:' \| wc -l` → 1 |
|
||
| `tabeller_utelatt` | 1 / 1 / 628 | tabeller i kilden bundlen ikke bærer (`§ 7` l.302) | **(2)** | dekningserklæring — «det bundlen IKKE bærer» har ingen spec-plass (U5) | `## Dekning`-prosaen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^tabeller_utelatt:' \| wc -l` → 1 |
|
||
| `figurer_i_krav` | 1 / 1 / 625 | figurer navngitt inne i krav (`§ 14.3`) | **(2)** | dekningserklæring | figurinventaret i kroppen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^figurer_i_krav:' \| wc -l` → 1 |
|
||
| `figurer_utelatt` | 1 / 1 / 628 | figurer i kilden som ikke følger med (`§ 7` l.303, `§ 14`) | **(2)** | dekningserklæring | `## Dekning`-prosaen + inventartabellen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^figurer_utelatt:' \| wc -l` → 1 |
|
||
| `figurer_uten_tittel` | 1 / 1 / 625 | figurer uten bildetekst (`§ 14.2`) | **(2)** | dekningserklæring | ingen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^figurer_uten_tittel:' \| wc -l` → 1 |
|
||
| `bilder_uten_figurnummer` | 1 / 1 / 625 | bilder utenfor enhver figur (`bundle.py` l.247–253) | **(2)** | dekningserklæring | inventartabellens `### Bilder uten figurnummer` | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^bilder_uten_figurnummer:' \| wc -l` → 1 |
|
||
| `lenker_utelatt` | 1 / 1 / 625 | xref i prosa mellom kravene, tapt med prosaen (`§ 13.5` l.590–595) | **(2)** | dekningserklæring; 1 169 av 3 161 xref over korpuset står utenfor krav | `## Dekning`-prosaen (`bundle.py` l.326–327) | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^lenker_utelatt:' \| wc -l` → 1 · `sed -n 590,595p $V` |
|
||
| `lenker_slaatt_sammen` | 1 / 1 / 625 | referanser samme krav siterte to ganger, skrevet én gang (`§ 13.4`; `bundle.py` `merged`) | **(2)** | dekningserklæring — forklarer differansen mellom kildens xref-tall og bundlens | ingen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -l '^lenker_slaatt_sammen:' \| wc -l` → 1 |
|
||
| `tegn_utenfor_krav` | 1 / 1 / 628 | tegn prosa som ikke står i noe krav (`§ 7` l.304; `bundle.py` l.308) | **(2)** | dekningserklæring | `## Dekning`-prosaen | ikke målt | `find $E -name '*.md' -print0 \| xargs -0 grep -h '^tegn_utenfor_krav:'` → ett tall |
|
||
| `erstatter` | 0 / 0 / 70 | forgjengerens konsept-id når et krav er omskrevet mellom utgaver — to betingelser, aldri tekstlikhet (`§ 3` l.129–168; `bundle.py` l.211) — **ikke i N500** | **(2)** | spec-ens livssyklus er `status: deprecated` på den gamle (§ 5.4) + lenke; **ingen etterfølgernøkkel**, og upstream #11 (deletion semantics) er åpen uten PR (U3). K3 B2d: upstream legger erstatteren i `description`-prosa (`sed -n 270p $K3`). Kjeden kan ikke følges maskinelt fra spec-plassen | ingen | ikke målt (0 i M); N100 2022→2023: 10 skrevet, 43 kandidater riktig avvist av betingelse 2 (`§ 3` l.150–160) | `find $B/FX-n100-2023-erstatter -name '*.md' -print0 \| xargs -0 grep -l '^erstatter:' \| wc -l` → 10 · `grep -l '^erstatter:' $M/*.md \| wc -l` → 0 · `sed -n 129,135p $V` |
|
||
| `erstattere_i_bundlen` | 0 / 0 / 75 | antall `erstatter` skrevet — kun når en forgjenger ble sendt inn (`§ 7` l.298–300; `bundle.py` l.297) | **(2)** | dekningserklæring for `erstatter` (samme betingede tilstedeværelse) | ingen | ikke målt | `find $B/FX-n100-2023-erstatter -name '*.md' -print0 \| xargs -0 grep -h '^erstattere_i_bundlen:'` → `erstattere_i_bundlen: 10` |
|
||
| `gren` | 0 / 0 / 542 | seksjonsnummeret en grenbase dekker; `kart` i kartbasen (`§ 16.3` l.1021–1030; `gren.py` l.206, 253) | **(2)** | grenformen finnes fordi konsumentens (po) `read_bundle` stopper ved basegrensen — «basegrensen er det eneste stedet OKF-navigasjonen stopper» (`2026-08-25-grenformen-og-tallene.md § 3`). Spec-ens eget svar på «åpne én del» er § 8 per katalog + #10 — som S8c fant ikke er bygget. Nøkkelen erklærer en **bevisst ufullstendig** bundle; ufullstendighet har ingen spec-plass (U5) | `krav_i_bundlen` omskrives i samme base | grenform målt: kart + dyreste gren 13 634 mot 85 937 tokens for N500 (−84,1 %); ikke målt på resonneringsarmene | `find $B -name '*.md' ! -name index.md -print0 \| xargs -0 grep -h '^gren:' \| sort \| uniq -c \| sort -rn \| head -3` · `sed -n 1021,1030p $V` |
|
||
| `gren_direkte` | 0 / 0 / 528 | `ja` når grenen bare bærer krav skrevet direkte i seksjonen (`§ 16.3`) | **(2)** | som `gren` | ingen | ikke målt | `find $B -name '*.md' ! -name index.md -print0 \| xargs -0 grep -h '^gren_direkte:' \| sort \| uniq -c` |
|
||
| `krav_i_normalen` | 0 / 0 / 528 | hele normalens kravtall, så delen kan leses mot helheten (`§ 16.3`) | **(2)** | som `gren` — dekning for en del | `krav_i_kilden` i samme base (uendret, l.1032) | ikke målt | `find $B -name '*.md' ! -name index.md -print0 \| xargs -0 grep -l '^krav_i_normalen:' \| wc -l` → 528 |
|
||
| `grener_i_normalen` | 0 / 0 / 542 | antall grener, så en konsument vet hvor mange baser som finnes (`§ 16.3`) | **(2)** | som `gren`. Merk: dette er informasjonen en § 8-rotindeks bærer ved å liste underkataloger (l.529: `* [Subdirectory](subdir/)`) | ingen | ikke målt | `find $B -name '*.md' ! -name index.md -print0 \| xargs -0 grep -l '^grener_i_normalen:' \| wc -l` → 542 |
|
||
|
||
**Fordelingen, produsert av kommando på dette dokumentet:**
|
||
|
||
```
|
||
awk -F'|' '/^\| `/ && NF>=9 && $5 ~ /\*\*\([123]\)\*\*/ {gsub(/[ *]/,"",$5); c[$5]++} END {for (k in c) print k, c[k]}' docs/okf-nokkelinventar.md | sort
|
||
# -> (1) 13 · (2) 24 · (3) 3 = 40 rader i B.1
|
||
```
|
||
|
||
Av de 33 i M: **(1) 12** (`utgave`, `trust_tier`, `seksjonstittel`, `lenker`, åtte
|
||
`viser_til_*`), **(2) 18** (`kravtype`, `req_number`, `kravdato`, `hjemmel`,
|
||
`fraviksmyndighet`, `seksjon`, tolv dekningsnøkler), **(3) 3** (`normal`,
|
||
`hjemmel_sitat`, `fraviksmyndighet_sitat`). De 7 utenfor M: (1) 1, (2) 6.
|
||
|
||
### B.2 Bibliotekets 21 nøkler utenfor spec (`profiles.py`)
|
||
|
||
Enumerert av kommando, ikke lest av:
|
||
|
||
```
|
||
.venv/bin/python -c '
|
||
from llm_ingestion_okf import profiles as p
|
||
spec = {"type","title","description","resource","tags","sources","usage_window","generated","verified","status","stale_after","runtime","parameters","computation","executor","attester","okf_version"}
|
||
allk = {}
|
||
for n in ("DEFAULT","STRICT_V1","STRUCTURED_V1","OKF_V0_2"):
|
||
for k in (*getattr(p,n).frontmatter.order, *getattr(p,n).index.root_frontmatter): allk.setdefault(k, []).append(n)
|
||
own = {k:v for k,v in allk.items() if k not in spec}
|
||
print(len(allk), "navn;", len(own), "utenfor spec")
|
||
for k,v in sorted(own.items()): print(f" {k:18s} {",".join(v)}")'
|
||
# -> 35 navn; 21 utenfor spec
|
||
```
|
||
|
||
**Eier** avgjør hvor en omdøping ville landet, og det er ikke alltid her: `DEFAULT` sine
|
||
seks er commons' ingest-spec § 7 (`~/repos/portfolio-optimiser-commons/ingest-spec.md`
|
||
l.204–217, «spec changes go via commons»); `STRICT_V1` sine åtte er wikiens ratifiserte
|
||
kontrakt (`docs/phase-3-split-table.md`, O2: «changing another repo's contract from
|
||
here violates O2»). Bare `STRUCTURED_V1` sine sju og `okf_spec_commit`/`bundle_profile`
|
||
er valg tatt i dette repoet.
|
||
|
||
| nøkkel | profil | eier | hva | klasse | spec-plass (1) / begrunnelse (2) / (3) | dupliserer | KOMMANDO |
|
||
|---|---|---|---|:---:|---|---|---|
|
||
| `source_system` | DEFAULT, STRUCTURED_V1, OKF_V0_2 | commons § 7 | manifestets `source.id` (l.213) | **(1)** | **`sources[].id`, § 5.1 l.307** — en stabil nøkkel for kilden. Golden skriver begge med samme verdi | `sources[].id` i `OKF_V0_2`-golden (`id: golden-v0-2-sales` = `source_system: golden-v0-2-sales`) | `sed -n 213p ~/repos/portfolio-optimiser-commons/ingest-spec.md` · `grep -h '^source_system:\|^sources:' examples/ingest-golden-okf-v0-2/expected-bundle/ingest-sales.md` |
|
||
| `source_query` | DEFAULT, STRUCTURED_V1, OKF_V0_2 | commons § 7 | spørringen som hentet innholdet, whitespace-kollapset (l.214) | **(1)** | **`sources[].resource` som «scope descriptor», § 5.1 l.303–306** («a population or scope descriptor … for example `all queries in BigQuery project X`») — en SQL/sti-spørring er nøyaktig det | ingen i dag (Dør A skriver `resource: fixture`-plassholder under `OKF_V0_2`, l.184–) | `sed -n 303,306p $S` · `sed -n 184,199p $I/materialize.py` |
|
||
| `source_file` | DEFAULT (Dør B) | dette repoet (Phase 2) | filnavnet som ble sluppet i innboksen (`inbox.py` l.134) | **(1)** | **`sources[].resource` som bundle-relativ sti eller `references/`-sti, § 5.1 l.303–305 + § 6.3** | ingen | `sed -n 134p $I/inbox.py` · `sed -n 479,486p $S` |
|
||
| `source_sha256` | DEFAULT (Dør B) | dette repoet | SHA-256 av kildebytene (`inbox.py` l.135) | **(2)** | spec har **ingen integritetsdigest**: `grep -n -i 'sha\|hash\|digest\|checksum' $S` → 6 treff, alle substrenger (`shaped`, `sharded`, `shared`, `distinguishable`); kjent-positiv `frontmatter` → 28. Innholdsidentitet er Dør C sitt eierskapsbevis (CLAUDE.md, Door C) | ingen | `grep -n -i 'sha\|hash\|digest\|checksum' $S \| cut -c1-60` |
|
||
| `ingested_at` | DEFAULT, STRUCTURED_V1, OKF_V0_2 | commons § 7 | det eksplisitte tidsargumentet, ordrett (l.215) | **(1)** | **`generated.at`, § 5.2 l.378** — og `DEFAULT` skriver alt begge med **samme verdi 5/5** (commons l.217: «`at` repeats the `ingested_at` value verbatim»). Dokumentet bærer tidspunktet to ganger, med vilje hos commons | **`generated.at` 5/5 goldens** | `n=0; for f in $(grep -rl '^ingested_at:' examples); do a=$(grep -m1 '^ingested_at: ' "$f" \| cut -d' ' -f2); g=$(grep -m1 -o 'at: [^ }]*' "$f" \| cut -d' ' -f2); [ "$a" = "$g" ] && n=$((n+1)); done; echo $n` → 5 |
|
||
| `ingest_manifest` | DEFAULT, STRUCTURED_V1, OKF_V0_2 | commons § 7 | manifestreferansen `{stem}@{hash16}` (l.216) — sammen med `generated.by` **eierskapsstempelet** (l.84) | **(2)** | pekeren kunne vært `sources[].resource` → `references/<manifest>` (§ 6.3 «run instructions»), men **hash16-delen** har ingen spec-plass (ingen digest, se `source_sha256`), og commons gjør nettopp hashen til eierskapsbevis fordi «the key's mere presence does not» (l.217) | delvis: pekeren, ikke hashen | `sed -n 84,86p ~/repos/portfolio-optimiser-commons/ingest-spec.md` · `grep -h '^ingest_manifest:' examples/*/expected-bundle/*.md \| head -1` |
|
||
| `number` | STRUCTURED_V1 | dette repoet | dokumentnummer, utledet av filnavn/tittel (`structure.py` l.232–237) | **(2)** | som `req_number` (B.1): spec har ingen nummer-nøkkel; rekkefølge er en målt egenskap (F4). Utledet → merket i `derived` | `title`/filstammen den ble utledet av | `sed -n 232,237p $I/structure.py` |
|
||
| `parent` | STRUCTURED_V1 | dette repoet | foreldrenummeret, utledet av `number` (l.240–241) | **(1)** | **§ 6.1 l.454–457: «parent/child» er den første relasjonsarten spec navngir**, båret av lenke + prosa; og § 3s katalogtre er den implisitte forelderen (§ 2 l.85 «implicit parent/child hierarchy») | `number` (den er en funksjon av den) | `sed -n 240,241p $I/structure.py` · `sed -n 454,457p $S` |
|
||
| `status` | STRUCTURED_V1 (fasett) | — | spec-nøkkel, projisert i indeksen | spec | (i Del A) | — | `sed -n 885p $P` |
|
||
| `date` | STRUCTURED_V1, STRICT_V1 | dette repoet / wiki | dokumentdato, deklarert av kaller; `YYYY-MM-DD` i testene (§ 0.6) | **(2)** | som `kravdato`: ingen spec-tidsnøkkel betyr «dokumentets dato» (`generated.at` = innholdsendring, `last_modified` = kildeendring) | ingen | `grep -ho 'date: [0-9][^"\\]*' tests/*.py \| sort -u` |
|
||
| `version` | STRUCTURED_V1, STRICT_V1 | dette repoet / wiki | dokumentets versjon, deklarert (l.255) | **(2)** | spec har ingen dokumentversjon (§ 12 er formatets versjon); nærmeste er `sources[].title`/`utgave`-mønsteret i korpuset | ingen | `sed -n 255p $I/structure.py` · `grep -n 'version' $S \| grep -v 'okf_version\|Version 0\|version bump\|<version>' \| wc -l` → 0 om dokumentversjon (ikke lest i detalj: treffene er formatversjon og aktørversjon) |
|
||
| `supersedes` | STRUCTURED_V1 | dette repoet | hvilke dokumenter dette erstatter, deklarert (l.257) | **(2)** | som `erstatter` (B.1): ingen etterfølgernøkkel, upstream #11 åpen (U3) | ingen | `sed -n 257p $I/structure.py` |
|
||
| `references` | STRUCTURED_V1 | dette repoet | kryssreferanser — **utledet av § 6.1-lenker i kroppen** (`_LINK`, l.54; l.246) når ikke deklarert | **(1)** | **§ 6.1 — nøkkelen er bokstavelig talt en frontmatter-kopi av kroppens markdown-lenker** (regexen `\[[^\]]*\]\(([^)\s]+)\)` l.54). Egen ordre `…507632913` (12/12 falske), ikke slått sammen her | **kroppens lenker** (kilden den utledes fra) | `sed -n 54p $I/structure.py` · `sed -n 243,248p $I/structure.py` |
|
||
| `derived` | STRUCTURED_V1 | dette repoet | hvilke av nøklene foran som ble **utledet**, ikke lest (l.898–902) | **(2)** | spec skiller ikke lest fra utledet på feltnivå — samme hull som U6 (trust per felt). «An unmarked heuristic is worse than none» (CLAUDE.md, Door B) | ingen | `sed -n 898,902p $P` |
|
||
| `timestamp` | STRICT_V1 | wiki | dokumentets tidsstempel (v0.1-nøkkelen) | **(1)** | **`generated.at` — spec sier det selv, § 13.1 l.805** («`timestamp` is superseded by `generated.at`»). Profilen nekter å navngi begge (l.42). Wikiens kontrakt; omdøping er deres kall (O2) | ingen (wikien skriver ikke `generated`) | `sed -n 805,808p $S` · `sed -n 819p $P` · `sed -n 42p $P` |
|
||
| `layer` | STRICT_V1 | wiki | bundle-laget (`concepts`/`releases`), bundet til sti og `type` (`phase-3-split-table.md` l.166–168) | **(2)** | spec-ens lag er katalogen (§ 3) — men wikien binder lag ⇄ sti ⇄ `source_tier` ⇄ `type` som ERROR-gate (l.63), og en spec-konsument kan ikke lese det av stien alene | stien (`concepts/` ⇄ `layer: concepts`, l.166) | `sed -n 166,168p docs/phase-3-split-table.md` |
|
||
| `source_tier` | STRICT_V1 | wiki | kildens troverdighetsklasse (`official-docs`/`changelog-derived`, l.167–168) | **(1)** | **§ 5.1 l.314–318: troverdighet er «*inferred* from the signals … not stored»** (`author`, `usage_count`, `last_modified`) — en lagret klasse er det spec eksplisitt ikke gjør, samme form som `trust_tier` (B.1) | `layer` (bundet 1:1 til det, l.166–168) | `sed -n 314,318p $S` · `sed -n 167,168p docs/phase-3-split-table.md` |
|
||
| `source_url` | STRICT_V1 | wiki | kildens URL | **(1)** | **`sources[].resource`, § 5.1 l.303** (absolutt URL) | ingen | `sed -n 303,304p $S` · `sed -n 822p $P` |
|
||
| `source_sha` | STRICT_V1 | wiki | kildens innholdshash | **(2)** | som `source_sha256`: ingen digest i spec | ingen | `sed -n 823p $P` |
|
||
| `summary` | STRICT_V1 (nullable) | wiki | lengre sammendrag, kan være `null` (`phase-3-split-table.md` l.11, 150) | **(1)** | **`description`, § 4.1 l.194** — men wikien bærer **begge** (`description` påkrevd, `summary` valgfri, l.119–134), så det er en andre, lengre beskrivelse. Hva som skiller dem semantisk hos wikien: **ikke lest** (deres kontraktdokument er ikke her) | `description` (delvis) | `sed -n 826p $P` · `sed -n 853p $P` · `sed -n 150p docs/phase-3-split-table.md` |
|
||
| `bundle_profile` | STRICT_V1 (rotindeks) | dette repoet / wiki | hvilken profil bundlen ble skrevet under | **(2)** | § 12 kjenner bare `okf_version`; hvilken **kontrakt** utover formatet et dokument følger har ingen spec-plass | ingen | `sed -n 867p $P` |
|
||
| `okf_spec_commit` | STRICT_V1 (rotindeks) | dette repoet / wiki | commiten i upstream-repoet spec-teksten ble lest ved | **(2)** | § 12 versjonerer med `<major>.<minor>`, og v0.2 ble **strammet inn på plass uten versjonsbump** (23.08-runden: «declaring conformance to v0.2 without also naming a commit is now ambiguous», `docs/plan/okf-2026-08-timestamp-tightening.md` § Step 4). Nøkkelen finnes fordi spec-ens eget versjonsskjema ikke bærer det | ingen | `grep -n 'without also naming a commit' docs/plan/okf-2026-08-timestamp-tightening.md` · `sed -n 867p $P` |
|
||
|
||
Fordeling B.2 (20 egne + `status`): **(1) 9** (`source_system`, `source_query`,
|
||
`source_file`, `ingested_at`, `parent`, `references`, `timestamp`, `source_tier`,
|
||
`source_url`, `summary` — 10 med `summary`), **(2) 11**. Kommando:
|
||
`awk -F'|' '/^\| `/ && $6 ~ /\*\*\(1\)\*\*/' docs/okf-nokkelinventar.md | wc -l`
|
||
teller (1)-rader i B.2-formatet (kolonne 6); B.1 har klassen i kolonne 5.
|
||
|
||
### B.3 Duplikatene, samlet — det ordren ba om eksplisitt
|
||
|
||
Hver linje er en verdi som **finnes to steder**, målt:
|
||
|
||
| duplikat | hvor | målt | kommando |
|
||
|---|---|---|---|
|
||
| `utgave` = `sources[].title` | E, samme dokument | 270/270 byte-identisk | Del A `sources[].title` |
|
||
| `req_number` = prefikset av `title` | E/M | 269/269 | B.1 `req_number` |
|
||
| `seksjonstittel` = halen av `title` | E/M, konstruert `bundle.py` l.194 | 269/269 ved konstruksjon | `sed -n 194p bundle.py` |
|
||
| `normal` = katalogsegmentet i konsept-id | E | 269/269 (`krav/N500/` ↔ `N500`) | B.1 `normal` |
|
||
| `trust_tier: unverified` = fraværet av `verified` | E/M | 270/270 og 0/270 | B.1 `trust_tier` |
|
||
| `lenker` ↔ `viser_til_krav` | E/M | samme 14 filer, samme referanser (id vs tekst) | B.1 `viser_til_krav` |
|
||
| `status: stable` i indeksraden = § 5.4-defaulten | M `index.md` | 270 rader, 4 590 bytes (5,9 %) | Del A `status` |
|
||
| `title` i indeksraden + konsept-id som lenketekst | M `index.md` | UUID to ganger per rad, 27,7 % | Del A `title` |
|
||
| `ingested_at` = `generated.at` | bibliotek, Dør A | 5/5 goldens | B.2 `ingested_at` |
|
||
| `references` (STRUCTURED_V1) = kroppens § 6.1-lenker | bibliotek, Dør B | ved konstruksjon (`structure.py` l.54) | B.2 `references` |
|
||
| dekningstall = `## Dekning`-prosaen | E `Normal`-konseptet | `krav_i_kilden`/`krav_i_bundlen`/`tabeller_utelatt`/`figurer_utelatt`/`tegn_utenfor_krav`/`lenker_utelatt` gjentas i kroppen | `sed -n 313,327p bundle.py` |
|
||
|
||
---
|
||
|
||
## Del C — utover v0.2 (notert, ikke handlet på)
|
||
|
||
Idéboka bor i `.claude` (`~/.claude/docs/okf-utover-v02.md`), og dette repoet skriver
|
||
ikke i andre repo. Kandidatene sendes derfor til `.claude` i svaret på ordren, i
|
||
idébokas format, slik K1 gjorde. To nye, begge fra tall i dette dokumentet:
|
||
|
||
**U12 — Indeksens rekkefølge er en egenskap uten spec-plass.** § 8 sier ingenting om
|
||
oppføringenes rekkefølge (`grep -n -i 'order\|sorted\|ordering' $S` → 13 treff, alle
|
||
`orders`-eksempelet og «reordered» om `sources[].id`; 0 om indeksrekkefølge). Målt:
|
||
samme indeks sortert på `req_number` = +2 celler (F3 12/17 → F4 14/17). *Kostnad i
|
||
dag:* Dør C sorterer på konseptsti, som for et UUID-korpus er ingen sortering. *Tilbake-
|
||
spilling:* usikker — kan være en produsentkonvensjon (#10 rører hierarki, ikke rekkefølge).
|
||
Egen ordre `…3790625395` finnes alt; dette er notatet, ikke ordren.
|
||
|
||
**U13 — Integritetsdigest.** Spec har ingen innholdshash (6 treff på
|
||
`sha|hash|digest|checksum`, alle substrenger). Tre uavhengige kontrakter fant opp én:
|
||
`source_sha256` (Dør B), `source_sha` (wikien), `ingest_manifest`s hash16 (commons) —
|
||
og Dør C beviser eierskap ved innholdsidentitet. *Kostnad i dag:* ikke målt. *Tilbake-
|
||
spilling:* mulig — upstream #8 (JSON Schema) er stedet en slik nøkkel ville måttet
|
||
navngis.
|
||
|
||
---
|
||
|
||
## Selvsjekk-porten (kjørt på den ferdige filen)
|
||
|
||
```
|
||
grep -c '^|' docs/okf-nokkelinventar.md # -> SELFCHECK_TOTAL rader totalt
|
||
grep '^|' docs/okf-nokkelinventar.md | grep -vc '`' # -> SELFCHECK_NOCMD rader UTEN backtick-kommando
|
||
grep -c '^|---' docs/okf-nokkelinventar.md # -> SELFCHECK_SEP skillelinjer
|
||
grep '^|' docs/okf-nokkelinventar.md | grep -v '`' | grep -vc '^|---' # -> SELFCHECK_HDR header-rader (uten backtick)
|
||
```
|
||
|
||
SELFCHECK_SENTENCE
|