fix(okr): fase D akse-B — index-rekkefølge fra kaller, ikke fra disk
Vår alfabetiske `.sort()` i okf-index.mjs lå på akse B (ingest-spec.md:178-181), som krever manifestets ekstraksjonsrekkefølge fra kalleren og eksplisitt forbyr «filesystem enumeration order». Ruling-dokumentet (portfolio-optimiser-commons docs/plan/2026-07-25-ordering-axes-ruling.md §4 @ a67a243) navngir alfabetisk sortering som deterministisk FEIL på denne aksen: B ber ikke om *en* deterministisk rekkefølge, den ber om *kallerens*. Kontrakt (operatør-valgt), implementert i orderEntries(): 1. navn som alt står i indeksen -> beholder linjerekkefølgen (§6 «preserved byte for byte») 2. nye navn med kaller-rang -> kallerens ekstraksjonsrekkefølge 3. nye navn uten kaller-rang -> alfabetisk (3) er en dokumentert genesis-fallback, ikke en B-etterlevelse: CLI-en tar kun en katalog og har ingen kaller-liste å tre gjennom, og alternativet — rå readdirSync-rekkefølge — er nettopp det B forbyr. Fallbacken gjelder bare ved genesis; så snart en indeks finnes vinner (1), så et alfabetisk valg overstyrer aldri en rekkefølge en kaller har etablert. §5 i rulingen: den som arver B arver §6-idempotensen med den. `order` er derfor KUN rangering — medlemskapet leses fortsatt fra disk (akse A, :175-177), så en sti i lista kan aldri opprette eller gjenopplive en fil, og et gate-discardet dokument kan ikke snike seg inn i indeksen. parseExistingIndex bærer nå linkOrder eksplisitt framfor å hvile på JS-objekters innsettingsrekkefølge. innboks-ingest.mjs trer sin faktiske ekstraksjonsrekkefølge gjennom; uten det ville fiksen vært et ubrukt API. Tester: 182 -> 187. Alle fem nye verifisert røde mot mutant (orderEntries -> `[...names].sort()`), de 39 øvrige grønne under samme mutasjon. Ende-til-ende- testen diskriminerer ved at dokumentrekkefølgen (Zulu før Alfa) er den motsatte av den alfabetiske. Ingen versjonsbump; release avventer operatør-go. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EaQkAtvpNCLxWkjdEJ11vx
This commit is contained in:
parent
6b61d63196
commit
3f4e89fe9b
4 changed files with 207 additions and 18 deletions
|
|
@ -193,12 +193,18 @@ export async function ingestInbox(inboxDir, bundleRoot, { onNotice = (msg) => pr
|
|||
writeConcepts(withRelations, { bundleRoot: resolvedBundle, claimed });
|
||||
}
|
||||
|
||||
// Fase 4: indekser det overlevende settet (rot + alle nivaaer).
|
||||
generateIndexes(resolvedBundle);
|
||||
// `survivors` staar i den rekkefoelgen dokumentene ble ekstrahert, og
|
||||
// `s.written` i den rekkefoelgen konseptene ble skrevet pr. dokument -- dette
|
||||
// ER manifestets ekstraksjonsrekkefoelge (akse B, ingest-spec.md:178-181).
|
||||
const allWritten = survivors.flatMap((s) => s.written);
|
||||
|
||||
// Fase 4: indekser det overlevende settet (rot + alle nivaaer). `order` er
|
||||
// kun rangering: medlemskapet leses fortsatt fra disk (akse A), saa en fil som
|
||||
// ble discardet av gaten kan ikke snike seg inn i indeksen via denne lista.
|
||||
generateIndexes(resolvedBundle, { order: allWritten });
|
||||
|
||||
// Fase 5 (belte+seler): alle overlevende skrevne filer maa passere scoped
|
||||
// strict. Feil her er et internt invariant-brudd, ikke en dokument-feil.
|
||||
const allWritten = survivors.flatMap((s) => s.written);
|
||||
if (allWritten.length > 0) {
|
||||
const final = checkBundle(resolvedBundle, { strictIngest: true, files: allWritten });
|
||||
const finalErrors = [...final.missingType, ...final.strictErrors];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue