okf asked outright whether the v1.0 gate requires 'the tagged artifact resolves 0.3.1' or 'the fixture set passes against 0.3.1'. It is the second, and the answer is locked here so a later session cannot quietly upgrade the ask into a release request against their operator. They refused to widen their published range to run the measurement, and the refusal is better than the ask it answers: widening a published range in order to generate the evidence that would justify widening it is circular, and a red result would then have meant unwinding a release to fix a test setup. The measurement has to be able to say no. Their scratch-venv method -- outside the project environment, --no-deps, guard installed from the v0.3.1 tag, resolved version asserted from importlib.metadata -- satisfies the gate exactly.
32 KiB
Re-planlagt roadmap — v1.0 (Python) + Node/TS-port
Forfattet: Fable 5, 2026-07-09 (kryssmodell-review, docs/review-2026-07.md);
promotert til live sesjonsplan 2026-07-10. Sporet docs-fil; hjem = Forgejo open/
(eneste sanksjonerte offentlige flate, aldri GitHub). Utfyller docs/PLAN.md
(høynivå byggeplan) med detaljerte, Opus-eksekverbare sesjon-specer.
Mållinje (bindende): (a) en shippet, klasseledende v1.0 av Python-biblioteket (lukk review-funn + format/kvalitets-gaps, konsolider terskler, verifiser novelty-claimet, docs, versjons-sync + publish), OG (b) en Node/TS-port over den delte JSON-lexicon. Node-porten starter FØRST når Python-v1.0-surfacen er frosset og scan-ren (Session G). Stream 4 (pre-adaptasjons-scan) og consumer-integrasjon hører til «Ambisiøse utvidelser» (review Del 1), ikke v1.0-sekvensen.
REVIDERT 2026-07-25 — v1.0-gaten er strammet, og en 0.3.0 er skutt inn foran G. Setningen over sier at consumer-integrasjon IKKE er del av v1.0-sekvensen. Den gjelder ikke lenger. Operatør-beslutning: 1.0.0 gates på at den første ekte integrasjonen kommer grønt tilbake (
llm-ingestion-okfsteg 4 / deres v0.4.0), ikke på vår egen suite. Begrunnelse: 522 egenskrevne tester + en egenskrevet coverage-matrise beviser at koden gjør det vi designet, ikke at designet overlever kontakt med virkeligheten. Bevisbyrden kom utenfra — okf fant, i sin FØRSTE utveksling med oss, at main hadde divergert fra v0.2.0 påimport_bundle, og at CHANGELOG manglet tre atferdsendringer. Koden bestod; utgivelses-hygienen gjorde det ikke. v1.0 er primært et governance-løfte under semver, så det løftet avgis først etter én validert release-syklus.
v0.3.0er derfor kuttet 2026-07-25 (tag pushet;467b9e3). Den bærer Session A/A2/B ut til konsumenter som fortsatt pinnerv0.2.0og dermed ikke har noe av hardningen — og den er det som i det hele tatt gjør ekte tilbakemelding mulig. Minor og ikke patch fordi A2 (0772daf) satteallow_reserved=Truesom default og dermed LØSNET en gate. Node-porten (TRACK 2) er fortsatt blokkert bak G.
Endringer mot låst roadmap (STATE «re-sekvensert 2026-07-06»): steg 2 «modne
guarden» utvides med review-injiserte fiks-sesjoner (A/B/C/D/E) FØR release (G).
.pdf (steg 2i) blir en eksplisitt operatør-beslutning (Session F) med anbefaling
om konsesjon. Node-porten (gammelt steg 3) splittes i P0-P7 med en delt
parity-fixture som ryggrad.
Format per sesjon: Mål · Scope-grense · Avhengigheter · Filer · TDD-plan ·
Nøkkelantakelser (+ test) · Verifisering. Testkommando alltid:
PYTHONPATH=src .venv/bin/pytest …. Én sesjon ≈ «Les STATE.md og følg instruksen».
TRACK 1 — Python v1.0
Session A — Aktivt-innhold-detektor wiret inn i gaten (injisert av review MAJOR #1)
- Mål:
screen_outputogokf.import_bundleskal surface EchoLeak-klassen (markdown-bilde/lenke/refdef/autolink/aktiv-HTML) som findings som materdisposition— uten å bryte report/mutasjon-separasjonen. - Scope-grense: rører IKKE lexicon/entropy/secret-logikk, contract, fence,
sanitize. Ingen ny runtime-dep (stdlib-only).
neutralizes muterende API beholdes uendret (bakoverkompatibelt). - Avhengigheter: ingen (kan starte først).
- Filer: nytt
src/llm_ingestion_guard/active_content.py(report-onlyscan_active_content(text, source) -> Report, OWASP LLM05); refaktorneutralize.pytil å dele regex-tabellen; editoutput.py(scan_outputsteg 6: kallscan_active_content); edit__init__.py(eksporterscan_active_content); edittests/test_showcase.py+tests/test_okf_showcase.py(plant EchoLeak-vektor); nytests/test_active_content.py. - TDD-plan (failing FØRST):
test_active_content.py::test_markdown_image_is_reported—scan_active_content("")inneholder labelactive:markdown-image, severity HIGH. (Rødt: modulen finnes ikke.)test_screen_output_reports_echoleak—screen_output("", PRESET_USER_UPLOAD).dispositioner QUARANTINE_REVIEW+ (ikke WARN).test_okf_import_flags_body_echoleak— bundle med markdown-bilde i body → aggregat ≠ WARN.- Minimal impl: del regexene, report-only pass, wire i
scan_output. - Regresjon: hele suiten grønn (neutralize-tester uendret).
- Nøkkelantakelser (+ test):
- «neutralize og den nye detektoren kan dele samme regex-tabell uten
atferdsendring i neutralize.» Test: eksisterende
tests/test_neutralize.pypasserer uendret etter refaktor. - «severity-valget (HIGH for bilde) gir ønsket disposition under begge preset.» Test: assertion 2/3 over. Risiko hvis feil: for lav severity → fortsatt WARN; testes eksplisitt.
- «neutralize og den nye detektoren kan dele samme regex-tabell uten
atferdsendring i neutralize.» Test: eksisterende
- Verifisering:
PYTHONPATH=src .venv/bin/pytest tests/test_active_content.py tests/test_showcase.py tests/test_okf_showcase.py→ alle grønne.PYTHONPATH=src .venv/bin/python -c "from llm_ingestion_guard import screen_output, PRESET_USER_UPLOAD, Disposition; d=screen_output('', PRESET_USER_UPLOAD); assert d.disposition is not Disposition.WARN, d"→ exit 0.python -c "import tomllib,pathlib; assert tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['dependencies']==[]"→ exit 0 (kjerne-invariant intakt).
Session A2 — OKF reservert-fil-håndtering (index.md/log.md) (injisert av review MAJOR #2)
- Mål:
import_bundleskal behandle legitime reserverte strukturfiler (index.md/log.md, spec §3.1/§6/§7) som skann-body-men-ikke-path-rejekt, ikke hard-avvise dem — og faktisk skanneindex.md-bodyen (lest først, høyest-prioritert injeksjonsflate). Behold shadow-rejektet i upload/front-end-konteksten. - Scope-grense: rører IKKE
validate_concept_paths oppførsel i upload-konteksten (front-end shadow-reject beholdes). Ingen endring i T1/T2/T3-gatene. Kun mode-b bundle-import-grenen. - Avhengigheter: ingen kode-avhengighet av A; men bør landes FØR G (frys). Kan parallelliseres med A/B/C.
- Filer: edit
src/llm_ingestion_guard/okf.py(_validate_concept/import_bundle: reservert-basenavn → skann-gren i stedet for path-reject;link_graphuendret); edittests/test_okf.py+tests/test_okf_showcase.py(nytt: legitimt bundle medindex.md/log.mdADMITer; injeksjon iindex.mdFANGES; shadow-upload i front-end REJECTer fortsatt). - TDD-plan (failing FØRST):
test_okf.py::test_legit_index_and_log_admit— bundle {index.md, log.md, tables/users.md} (rene) → aggregat WARN, ingenerrorpå index/log. (Rødt i dag: FAIL_SECURE, verifisert i review-proben.)test_okf.py::test_injection_in_index_body_is_caught— injeksjon iindex.md-body → concept-report haroverride:ignore-previous. (Rødt i dag: findings=[].)test_okf_inbox_uploads.py::test_reserved_name_upload_is_rejected— MÅ fortsatt REJECTe (front-end shadow-reject bevart).- Minimal impl: skill reservert-basenavn i bundle-import (skann-body) fra upload-materialisering (shadow-reject).
- Nøkkelantakelser (+ test):
- «index.md/log.md kan skannes som tekst uten path-reject uten å svekke shadow-vernet i upload-konteksten.» Test: assertion 1-3 samlet — legit bundle admits, index-injeksjon fanges, upload-shadow rejects.
- Risiko:
okf_version-frontmatter er tillatt KUN i bundle-rootindex.md(spec). Hvis body-skann kjørerparse_frontmatterpå en index.md kan strict-gaten tripp. Test:test_index_with_okf_version_frontmatter_admits— skann index.md-body, ikke reject på lovligokf_version.
- Verifisering:
PYTHONPATH=src .venv/bin/pytest tests/test_okf.py tests/test_okf_showcase.py tests/test_okf_inbox_uploads.py→ alle grønne.PYTHONPATH=src .venv/bin/python -c "from llm_ingestion_guard import okf; r=okf.import_bundle({'index.md':'---\nokf_version: 0.1\n---\n# Listing\n','tables/users.md':'---\ntype: t\n---\nclean\n'}); assert r.disposition.value=='warn', [ (c.path,c.disposition.value,c.error) for c in r.concepts ]"→ exit 0.
Session B — base64-innpakket secret-egress (injisert av review MINOR)
- Mål: decode-and-rescan skal også kjøre
scan_secret_egressover dekodet base64-plaintext, så en base64-innpakket credential fanges av LLM02-gaten. - Scope-grense: kun
output.pydecode-rescan-løkken (steg 3). Ingen endring i entropy-klassifisering, lexicon, eller egress-mønstrene selv. - Avhengigheter: ingen (uavhengig av A; kan parallelliseres).
- Filer: edit
src/llm_ingestion_guard/output.py(steg 3: legg tilscan_secret_egress(blob.decoded)meddecoded:egress:*-relabel); edittests/test_output.py; edit README honest-limits (restgap: hex-innpakket). - TDD-plan:
test_output.py::test_base64_wrapped_secret_is_caught— output med base64(AWS-nøkkel, fragment-bygget gitleaks-safe) → finding-labeldecoded:egress:aws-access-key-id. (Rødt i dag — Probe 3 bekreftet [].)- Minimal impl: i decode-rescan-løkken, kjør også
scan_secret_egresspåblob.decoded, relabeldecoded:<label>, bær blob-offset. - Restgap-test: hex-innpakket secret er FORTSATT ikke fanget → dokumenter som honest-limit (bevisst avgrensning, ikke stille miss).
- Nøkkelantakelser (+ test):
- «evidence bærer aldri secret-verdien, også for den dekodede varianten.» Test:
assert nøkkel-fragmentet ikke i
finding.evidence.
- «evidence bærer aldri secret-verdien, også for den dekodede varianten.» Test:
assert nøkkel-fragmentet ikke i
- Verifisering:
PYTHONPATH=src .venv/bin/pytest tests/test_output.py→ N grønne (N = før +2).PYTHONPATH=src .venv/bin/python /path/to/probe.py(Probe 3 fra reviewen) → base64-linjen viser nådecoded:egress:aws-access-key-id.
Session C — Novelty-survey + README/BRIEF-reframe (injisert av review MAJOR #2)
- Mål: erstatt det uverifiserte/absolutte novelty-claimet med den forsvarbare kompositt-kontrakt-formen; oppdater BRIEF §11 fra «assumed» til verifisert-med- avgrensning.
- Scope-grense: docs only (
BRIEF.md,README.md). Ingen kodeendring. Ingen ny absolutt novelty-setning. - Avhengigheter: ingen.
- Filer: edit
docs/BRIEF.md§11; editREADME.mdposisjonering; ev. editdocs/PLAN.md-posisjonering (§19-45) — men PLAN er live-plan, la Opus avgjøre om den røres eller kun refereres. - TDD-plan (docs — verifiserbar via review, ikke pytest): ingen failing test;
i stedet en verifiseringslogg i BRIEF §11 som lister
ipi-scanner+aig-guardianmed URL og hvorfor de ikke motbeviser kompositt-kontraktet. - Nøkkelantakelser (+ test):
- «ingen bibliotek pakker det fulle firdelte kontraktet som minimal-dep kode.» Test: gjenta PyPI/GitHub-surveyen (søk «RAG ingestion security», «write-time prompt injection», «ipi-scanner», «ingest guard»); bekreft at ingen ny kandidat dekker karantene+isolasjon+scan-før-persist+fail-secure samlet. Merk dato.
- Verifisering:
grep -n "assumed, not verified" docs/BRIEF.md→ tom (claimet ikke lenger uverifisert);grep -niE "query-time.*or hosted|the only" README.md→ ingen absolutt formulering igjen.
Session D — Kalibrerings-konsolidering (injisert av review Akse 4; Node-prereq)
- Mål: samle alle kalibrerings-konstanter (entropy-gulv, MAX_SCAN_CHARS,
rot13-min, cognitive-load-lengder, disposition-rangeringer) i én dokumentert flate
calibration.py, så Node-porten kan speile nøyaktig samme tall. - Scope-grense: ren refaktor — null atferdsendring. Ingen terskeljustering (det er en separat, senere kalibrerings-oppgave). Kun flytting + navngiving.
- Avhengigheter: bør komme ETTER A (så aktivt-innhold-severities også bor der).
- Filer: nytt
src/llm_ingestion_guard/calibration.py; editentropy.py,lexicon.py,disposition.py,active_content.pytil å importere derfra. - TDD-plan:
- Snapshot-test FØRST: kjør hele suiten, lagre at 321(+delta) er grønne.
- Flytt konstanter; importer.
- Regresjon: identisk testresultat (ingen ny/endret assertion) beviser null atferdsendring.
- Nøkkelantakelser (+ test): «flyttingen endrer ingen verdi.» Test: hele
suiten grønn uendret; en eksplisitt
test_calibration.pyasserter de konkrete tallene (5.4/128, 5.1/64, 4.7/40, 1_000_000, 40, 2000/2500) som en frossen kontrakt Node-porten deler. - Verifisering:
PYTHONPATH=src .venv/bin/pytest→ samme antall grønne som før sesjonen (ingen delta i test-count utovertest_calibration.py).
Session E — Docs/versjons-sync + SECURITY/CONTRIBUTING + honest-limits (injisert av review MINORs)
- Mål: fjern versjons-drift; legg til manglende åpen-kildekode-artefakter; oppdater honest-limits med de residualene reviewen avdekket.
- Scope-grense: docs/metadata only. Ingen kodeendring.
- Avhengigheter: etter A/B/C (så honest-limits reflekterer faktisk tilstand).
- Filer:
README.md(badgetests-275→faktisk N; statusv0.1→v1.0; honest-limits: HIGH-i-trusted-prosa-residual, base64/hex-secret-restgap, quarantine-floor-note);docs/BRIEF.md:6-7(fjern «No code yet»); nyttSECURITY.md(disclosure-policy, Forgejo-kontakt); nyttCONTRIBUTING.md. - TDD-plan: ingen pytest; verifiser via grep-sjekker under.
- Nøkkelantakelser (+ test): «badge-tallet matcher faktisk suite.» Test:
badge-N ==
pytest-output. - Verifisering:
PYTHONPATH=src .venv/bin/pytest -q | tail -1→ «N passed»;grep -n "tests-${N}_passing" README.mdtreffer.grep -niE "v0\.1|275_passing|No code yet" README.md docs/BRIEF.md→ tom.test -f SECURITY.md && test -f CONTRIBUTING.md→ exit 0.
Session F — .pdf-beslutning (operatør-gate; to gjensidig utelukkende spor)
- Mål: avklar det siste format-gapet. Anbefaling: konsesjon (F1).
- Rasjonale for konsesjon: front-end er en dev-scoped showcase, ikke shippet
kode; README honest-limits sier allerede pdf-ekstraksjon er upålitelig; å legge
til
reportlabKUN for å lage white-on-white-test-fixtures er uforholdsmessig (to nye dev-deps for et demo-format). Binærlag-carriers (OCR/font-stego) er uansett eksplisitt out-of-scope. Konsesjon svekker ikke v1.0. - Spor F1 (anbefalt) — Konseder
.pdfpermanent:- Filer:
README.mdhonest-limits (.pdf= bevisst honest-limit, ikke TODO);docs/PLAN.md§247-tabell (marker.pdf-raden «conceded»). - Verifisering:
grep -n "pdf" README.mdviser konsesjon, ikke «known gap».
- Filer:
- Spor F2 (kun hvis operatør vil ha .pdf) — Bygg
.pdf-slice:- Operatør-gate FØRST: bekreft
pypdf(lesing) +reportlab(skrive white-on-white fixtures) som nye[dev]-deps — aldri core. Kjerne-invariantdependencies=[]MÅ holde. - Filer:
pyproject.toml([dev]+=pypdf,reportlab);tests/inbox_frontend.py(_extract_pdf+ dispatch.pdf);tests/test_okf_inbox_uploads.py(slice 2i:_make_pdfmed white-on-white + normal-tekst injeksjon, detach-proof). - TDD:
test_pdf_whiteonwhite_injection_is_caught(rødt) →_extract_pdf→ grønt;test_pdf_detach_proof. - Verifisering:
PYTHONPATH=src .venv/bin/pytest tests/test_okf_inbox_uploads.py→ +N grønne;python -c "import tomllib,pathlib; d=tomllib.loads(pathlib.Path('pyproject.toml').read_text()); assert d['project']['dependencies']==[] and 'pypdf' in ' '.join(d['project']['optional-dependencies']['dev'])"→ exit 0.
- Operatør-gate FØRST: bekreft
- Avhengigheter: uavhengig; kan gjøres når som helst før G.
Session G — v1.0 freeze + release (FRYSER Python-surfacen — Node-prereq)
- Mål: shippe v1.0.0; fryse den offentlige surfacen som porten oversetter.
- Scope-grense: ingen ny feature. Kun versjons-bump, CHANGELOG, tag, push.
- Avhengigheter: A, B, C, D, E, F ferdig ✅ (alle review-funn lukket/konsedert per
2026-07-25) PLUSS den reviderte gaten: første ekte integrasjon grønn — se
REVIDERT-blokken øverst. Konkret:
llm-ingestion-okfsteg 4 / v0.4.0 kjører grønt motv0.3.1(de har FORPLIKTET seg til å kjøre Door B+C-fixtures og sende resultatet UANSETT utfall — et rødt FP-resultat er like verdifullt), OG ingen API-formsendring ut av den integrasjonen som ikke er absorbert. Ett validertintegratedteller mer enn femplanned-erklæringer; vi venter IKKE på de øvrige (ms-ai-architect bygde sitt eget,okrer operatør-parkert). - ⚠️ GATEN KAN IKKE ÅPNES AV ET GRØNT SVAR ALENE — verifiser hvilken versjon som ble
resolvet (funnet 2026-07-25, premiss-verifisering). Setningen «v0.4.0 kjører grønt
mot v0.3.1» var skrevet mot en pin vi ikke hadde lest. okf pinner guarden
>=0.2,<0.3i[project].dependenciesog[tool.uv.sources]-taggen tilv0.2.0— verifisert på deresv0.4.0-tag OG deres HEAD (4ea00a9).<0.3ekskluderer både 0.3.0 og 0.3.1. Kjører de fixturene på et uendret tre, feiler det ikke — uv resolver v0.2.0, constrainten er tilfredsstilt, og fixturene kommer grønt tilbake fordi v0.2.0 aldri hadde regresjonen. Et grønt svar er dermed det ENESTE utfallet som intet forteller og ser ut som det forteller alt. Gate-kravet, presist formulert (okf spurte rett ut 2026-07-25 — svaret er låst): gaten krever at fixture-settet passerer mot guard 0.3.1, med den resolvede versjonen lest fraimportlib.metadataved kjøretid og oppgitt i resultatet. Gaten krever IKKE at okfs taggede artefakt kan resolve 0.3.1 — det er en RELEASE- beslutning eid av deres operatør, ikke et bevis om vår kalibrering. Vi stiller ingen release-forespørsel. Målingen skal kunne si nei uten at noen først har shippet et utvidet range; ville vi krevd det motsatte, ville vi bedt dem utgi en range som slipper inn en versjon de ennå ikke har målt. Deres metode (scratch-venv utenfor prosjektmiljøet,--no-deps, guard installert direkte frav0.3.1-taggen, resolved versjon assertert) tilfredsstiller gaten. - Transitiv ankomst teller IKKE som integrasjon (portfolio-optimisers innsikt, 2026-07-25). okf v0.4.0 gjør guarden til en OBLIGATORISK runtime-dep, så en konsument kan få oss i grafen uten å velge oss — og i dag lander de da på v0.2.0, uten 0.3.0-hardningen og uten 0.3.1-fiksen. Stille under-forsvar, ikke brudd. En konsument som fikk oss ved uhell måler ingenting med hensikt; grønt derfra beviser mindre enn rødt fra en som valgte oss.
- Filer:
pyproject.toml(version = "1.0.0",Development Status :: 3 → 5 - Production/Stable);README.mdbadge + ****Status:** \v0.3`, alpha-linjen** + **install-pinnen@v0.3.1**;init.pyversion;CHANGELOG.md. **NB — entryen kan ikke lenger «liste A-F»:** A/A2/B ligger allerede ute under[0.3.0].[1.0.0]skal referere[0.3.0]+[0.3.1]` for atferdsendringene og selv bære frysepunktet (API-stabilitet + det integrasjonen beviste), ikke gjenta dem. - TDD-plan: ingen ny test; hele suiten grønn er release-gaten.
- Nøkkelantakelser (+ test): «alle versjonsreferanser er synkrone.» Test:
grep alle fire filer for versjonsstreng, bekreft
1.0.0overalt. - Verifisering:
PYTHONPATH=src .venv/bin/pytest→ alle grønne.grep -rn "1\.0\.0" pyproject.toml README.md src/llm_ingestion_guard/__init__.py CHANGELOG.md→ treffer i alle fire;grep -rn "0\.3\.0" …→ ingen dangling ref utenfor CHANGELOG-historikken.- Install-pinnen i README må verifiseres mot den NYE taggen i en ren venv (anonym
pip install …@v1.0.0) — README skal aldri avertere en kommando vi ikke har kjørt. git tag v1.0.0+ push tilopen/(durabelt autorisert). STATE.md røres ikke av tag (local-only).
Session H — 0.3.1: regresjonsfiks for aktivt-innhold-kalibrering (LANDET 2026-07-25)
LANDET —
6e9b816, tagv0.3.1pushet. Begge defekter fikset sammen; repro-tabellen under er kjørt på nytt og snudd (ordinær lenke/bilde/autolink/refdef →warnpå BEGGE dører; exfil-formet →fail_secure). 577 tester grønne, coverage-matrise exit 0 (128/128 recall, 6/6 gap holder), anonym ren-venv-install av@v0.3.1verifisert. Nye residualer skrevet inn idocs/LIMITATIONS.md(beaconing, kort opak URL-del, percent-escape-FP) og asserteres av matrisen. Alle 7 varslede repo har fått MÅLINGENE. Neste: Session G. 0.4.0 er akse-separasjon (deteksjon ≠ disposisjon), ikke ny preset.
- Mål: gjøre den utrustede upload-stien brukbar igjen uten å miste EchoLeak- deteksjonen, og lukke testgatens blindfelt som slapp regresjonen forbi 522 grønne tester.
- Utløser:
llm-ingestion-okfprojiserte konsekvensen fra CHANGELOG-teksten FØR 0.3.0 ble kuttet; vi shippet før vi leste innboksen. De traff retningen og undervurderte alvoret.
Målt på v0.3.0 (ikke antatt) — begge dører, PRESET_USER_UPLOAD / origin=EXTERNAL:
| dokument | utfall |
|---|---|
| ingen lenker | warn |
| én ordinær lenke / autolink / refdef | quarantine_review |
| én ordinær bilde-referanse | fail_secure |
| relativt/lokalt bilde | warn |
-
Rotårsak — tre UAVHENGIGE defekter som forsterker hverandre:
- Severity følger konstruksjons-TYPE, ikke URL-FORM.
markdown-image: HIGHfyrer på ethvert eksternt bilde. Exfil-primitivet er ikke «et bilde» — det er en URL som bærer data utover.bærer ingenting. - Quarantine-floor fyrer på ENHVER finding (
policy.quarantine_default and report.found). Premisset «findings er unntaket» brøt da hver lenke ble en finding. Dette er den allerede dokumenterte «vakuøs quarantine-floor»-residualen. - FP-korpuset kunne strukturelt ikke fange det:
_FALSE_POSITIVE(6 prosa-snutter) har NULL markdown-lenker/bilder; asserteres KUN underPRESET_TRUSTED_SOURCE(hvor alt girwarnuansett); og kjører_scan_input, såscan_outputsteg 6 — deractive_contentfaktisk bor — berøres aldri av korpuset.
- Severity følger konstruksjons-TYPE, ikke URL-FORM.
-
Begge kodeendringer trengs sammen (verifisert): kun (1) → floor karantenerer fortsatt; kun (2) → HIGH-bilde fail_secure'er fortsatt.
-
Scope-grense: INGEN ny offentlig API. Ny mellom-preset er 0.4.0, ikke denne. Rør ikke trusted-tier-residualen (HIGH-i-trusted→WARN). Ingen omskriving/neutralize i gaten — biblioteket reparerer ikke stille (bekreftet som bærende av okf).
-
Avhengigheter: ingen.
-
Filer:
calibration.py(alle nye tall — låst konvensjon),active_content.py(form-analyse),disposition.py(floor-terskel),tests/test_corpus.py(blindfeltet),tests/test_active_content.py,coverage.py,CHANGELOG.md,docs/LIMITATIONS.md. -
TDD-plan (failing test FØRST — Iron Law):
- Utvid
_FALSE_POSITIVEmed REALISTISKE markdown-dokumenter (ordinær lenke, bilde, autolink, refdef, blandet) og legg til et FP-testtilfelle som kjørerscreen_outputunderPRESET_USER_UPLOAD. Dette skal være rødt før noen kildeendring — det er beviset på at gaten nå faktisk dekker regresjonen. - Form-analyse i
active_content: ordinær ekstern URL (bar sti, ingen query, ingen høy-entropi-segment) → LOW; exfil-form → behold HIGH/MEDIUM. Gjenbrukentropy- modulen; ikke oppfinn ny heuristikk.data-uriograw-htmlbeholder HIGH ubetinget (aktive uansett URL-form). - Floor-terskel i
_base_disposition: fyrer på MEDIUM+ i stedet for enhver finding. - Adversarielt mot-korpus: exfil-formede URL-er (query som bærer verdi, høy-entropi sti-segment/subdomene, percent/base64-payload) MÅ fortsatt nå HIGH → fail_secure.
- Utvid
-
Nøkkelantakelser (+ test):
- «0.3.1 er ærlig som patch, ikke minor.» VERIFISERT 2026-07-25: lexicon har 0
LOW/INFO-mønstre (40 high / 22 medium / 21 critical) og ingen annen detektor
produserer LOW. Floor-endringen er derfor en no-op for alt som fantes før 0.3.0 —
den løsner ingenting for en v0.2.0-konsument. Re-test:
python -c "…Counter(severity)…"skal fortsatt vise null LOW/INFO. - «form-heuristikken har ikke falske negativer på ekte exfil.» Test: mot-korpuset i TDD-steg 4. Dette er den farlige antakelsen — en for grov «ordinær»-definisjon gjenåpner EchoLeak.
- «ren beaconing forblir udekket.» Et bilde som kun trigger et fetch uten å bære data
(IP/metadata-lekkasje) faller til LOW. Dette er et BEVISST nytt hull og skal skrives
inn i
docs/LIMITATIONS.md, ikke ties i hjel.
- «0.3.1 er ærlig som patch, ikke minor.» VERIFISERT 2026-07-25: lexicon har 0
LOW/INFO-mønstre (40 high / 22 medium / 21 critical) og ingen annen detektor
produserer LOW. Floor-endringen er derfor en no-op for alt som fantes før 0.3.0 —
den løsner ingenting for en v0.2.0-konsument. Re-test:
-
Verifisering:
PYTHONPATH=src .venv/bin/pytest→ alle grønne (-qskjuler summary — dropp den).python -m llm_ingestion_guard.coverage→ exit 0; ingen dokumentert gap-assertion brutt, og de nye FP-tilfellene er representert i matrisen.- Repro-tabellen øverst kjørt på nytt: ordinær lenke/bilde/autolink/refdef →
warnpå BEGGE dører; exfil-formet bilde →fail_secureunder upload-preset. - Versjons-sync 0.3.0→0.3.1 i alle fire filer + README install-pin; anonym ren-venv
pip install …@v0.3.1før README averterer den. - Coord til de 7 varslede repoene med MÅLINGER, ikke beskrivelse (vi lovet det).
🔒 Konsument-varslingsplikt — to LÅSTE løfter (gitt 2026-07-25)
Begge er gitt til navngitte konsumenter som bygger på nåværende atferd. De bor HER og
ikke bare i STATE.md, fordi STATE er LOCAL-ONLY og gitignored — et løfte som kun
finnes der overlever ikke en maskin. Å bryte ett av disse stille er en release-defekt,
ikke en preferanse.
- Gradering av ordinære lenker/bilder under
PRESET_USER_UPLOAD— enhver endring krever varsel tillinkedin-studiofør den shippes. De pinner v0.3.1 ved wiring og bygger på 0.3.1-formen; en stille re-stramming lander som produksjonsincident hos dem, ikke som en release-note. Gjelder også 0.4.0: akse-separasjonen skal endre DISPOSISJON, ikke graderingen — viser det seg feil under scoping, fyrer løftet. - Relativ-mål-asymmetrien (relative lenker/bilder i en OKF-bundle flagges ikke) —
lukkes den, får
llm-ingestion-okfvarsel før det shippes. Den er en Door C-egenskap, ikke et guard-gap: et merget konsept skrives VERBATIM, så vi reparerer og omskriver ikke (designprinsipp 3). Men lukking endrer hva som ankommer deres persist-gate.
Kjent, ikke modellert: okf rapporterer at percent-escapes når filnavn gjennom en
slugger — dvs. %20 produseres SYSTEMATISK fra dokumenttitler, ikke tilfeldig. Vår
percent-escape-FP ble kalibrert mot dokumentasjons-URL-er der escapes er insidentelle.
Er okfs mekanisme representativ, er dette en strukturell FP-klasse og ikke en sjelden
form. Måles i deres re-run og i linkedin-studios korpus.
TRACK 2 — Node/TS-port (stream 3). Starter etter Session G.
Ryggrad: en delt parity-fixture (fixtures/parity/*.json: input → forventede labels/severities) som BÅDE Python og TS må tilfredsstille. Uten den porter du et
bevegelig mål. Den delte injection_lexicon.json splittes aldri (PLAN §13.3).
Session P0 — Parity-fixture-ryggrad + TS-scaffold
- Mål: etabler golden-fixtures + TS-prosjektskjelett; Python-impl asserter mot fixtures.
- Scope-grense: ingen TS-detektor-logikk ennå; kun scaffold + fixtures + Python- parity-test.
- Avhengigheter: Session G (frossen surface) + D (kalibrering konsolidert).
- Filer:
fixtures/parity/{sanitize,lexicon,entropy,output,okf}.json; nytests/test_parity_fixtures.py(Python-siden);node/package.json,node/tsconfig.json,node/vitest.config.ts. - TDD-plan:
test_parity_fixtures.pykjører hvert fixture-input gjennom Python- impl og asserter forventede labels (rødt til fixtures skrives, så grønt). - Nøkkelantakelse (+ test): «fixtures fanger den faktiske Python-atferden.» Test: Python-parity-test grønn.
- Verifisering:
PYTHONPATH=src .venv/bin/pytest tests/test_parity_fixtures.py→ grønt;cd node && npm i && npx vitest run→ tomt/skjelett kjører.
Session P1 — report + severity + lexicon-loader (TS)
- Mål: TS-typene + loader som leser SAMME
injection_lexicon.json. - Avhengigheter: P0.
- Filer:
node/src/report.ts,node/src/lexicon-loader.ts,node/test/*.test.ts. - TDD: vitest: loader kompilerer alle mønstre; antall == Python
load_lexicon(). - Nøkkelantakelse (+ test): «JS-regex-motoren aksepterer alle mønstrene uten flag-oversettelsestap.» Test: hver pattern kompilerer; parity på pattern-count.
- Verifisering:
cd node && npx vitest run test/lexicon-loader.test.ts→ grønt; count ==PYTHONPATH=src .venv/bin/python -c "from llm_ingestion_guard.lexicon import load_lexicon; print(len(load_lexicon()))".
Session P2 — sanitize + entropy + normalize (TS)
- Avhengigheter: P1.
- Filer:
node/src/sanitize.ts,node/src/entropy.ts,node/src/normalize.ts. - TDD: vitest kjører
fixtures/parity/{sanitize,entropy}.json→ samme labels. - Nøkkelantakelse (+ test): «base64/rot13/homoglyph-primitiver gir bit-lik output i JS og Python.» Test: parity-fixtures grønne begge sider.
- Verifisering:
cd node && npx vitest run(sanitize+entropy) grønt mot fixtures.
Session P3 — lexicon.scan + variant-set (TS)
- Avhengigheter: P2.
- Filer:
node/src/lexicon.ts. - TDD:
fixtures/parity/lexicon.json(raw/normalized/folded/rot13-varianter) → samme dedupede labels. - Nøkkelantakelse (+ test): «dedup-by-id og variant-rekkefølge matcher.» Test: parity-fixture med multi-variant-treff.
- Verifisering:
cd node && npx vitest run test/lexicon.test.tsgrønt.
Session P4 — output + active_content + neutralize + disposition (TS)
- Avhengigheter: P3. (Inkluderer aktivt-innhold fra Session A.)
- Filer:
node/src/output.ts,node/src/active_content.ts,node/src/neutralize.ts,node/src/disposition.ts. - TDD:
fixtures/parity/output.json+ disposition-tabell-fixtures. - Nøkkelantakelse (+ test): «fail-closed + carrier/CRITICAL any-tier + compound matcher Python.» Test: disposition-parity-fixtures inkl. transform_failed-caset.
- Verifisering:
cd node && npx vitest run(output+disposition) grønt mot fixtures.
Session P5 — contract-asserters + top-level bookends (TS)
- Avhengigheter: P4.
- Filer:
node/src/contract.ts,node/src/index.ts(prepareInput/screenOutput). - TDD: tool-carrying request raiser; credential-leak raiser; happy path passerer.
- Verifisering:
cd node && npx vitest run test/contract.test.tsgrønt.
Session P6 — OKF-adapter (TS)
- Avhengigheter: P5.
- Filer:
node/src/okf.ts. - TDD: port
_poisoned_bundle/_clean_bundlefratest_okf_showcase.pysom fixture; samme aggregat-disposition + link-graf. - Nøkkelantakelse (+ test): «strict frontmatter-parser gir samme reject-set.» Test: OKF-parity-fixture (T2/T3/T4/T5a/dangling).
- Verifisering:
cd node && npx vitest run test/okf.test.tsgrønt.
Session P7 — Parity-CI + Node-README + versjons-sync + tag
- Avhengigheter: P6.
- Filer:
node/README.md,node/package.json(versionsynk med Python-linjen), CI-hook som kjører begge suiter mot samme fixtures. - Verifisering: både
PYTHONPATH=src .venv/bin/pytestogcd node && npx vitest rungrønne mot sammefixtures/parity/; versjonsstreng synk; tag + push tilopen/.
Avhengighetsgraf + anbefalt sekvens
A ─┐
A2 ─┤ (A, A2, B, C uavhengige; kjør i den rekkefølgen som passer)
B ─┤
C ─┤
├─► D ─► E ─┐
F ─┘ ├─► G (v1.0 FRYS) ─► P0 ─► P1 ─► P2 ─► P3 ─► P4 ─► P5 ─► P6 ─► P7
│
(F operatør-gated, uavhengig, må være lukket/konsedert før G)
- A, A2, B, C kan tas i valgfri rekkefølge (uavhengige). Start med A eller A2 (begge review-MAJOR; A = unsafe admit, A2 = over-block + uskannet index.md).
- D etter A (så aktivt-innhold-severities bor i
calibration.py). - E etter A/B/C (honest-limits skal reflektere faktisk tilstand).
- F når som helst før G; anbefalt spor F1 (konsesjon). Dep-tillegg (F2) er operatør-gate uansett.
- G er frysepunktet. Node-porten (P0-P7) starter FØRST etter G, ellers porter du et bevegelig mål. P0 avhenger også av D (kalibrering konsolidert).
- P0-P7 er sekvensielle (hver bygger på forrige), med parity-fixture som felles kontrakt.
.pdf-beslutningen sitter i F (før G). Python-frysen sitter i G (før P0).