1
0
Fork 0
portfolio-optimiser-claude/docs/2026-07-04-I5-brief.md
Kjell Tore Guttormsen 32640deffc feat(ingest): I5 — SQL D7-speil, bygget fra commons-spec alene
Speiler MAF I4 fra shared/ingest-spec.md alene: manifest → SQL-konnektor →
materialisert OKF-bundle, byte-identisk med den delte golden-fasiten. Gaten
I4→I5 verifisert løst mot ground truth (MAF-commits d7e5f2f/4f45fe6/1b7612b)
før arbeidet startet. Spec byte-identisk delt, ingen spec-endring (I4).

- ingest.py: SqlSource (type: sql, id, connection_ref); ManifestContract.source
  er nå diskriminert union FileSource | SqlSource på type (http/ukjent tag →
  fail-fast). _render_sql_cell (§5 typed: NULL→"", int→decimal, float→korteste
  round-trip, str→verbatim m/ delt _escape_cell, annet→fail — aldri stille
  coercion). _resolve_connection_ref (env-oppslag §4/§8, usatt → fail-fast).
  _read_sql (read-only sqlite file:?mode=ro, ett SELECT, max_rows §8).
  _read_extraction dispatcher på source.type; materialisering/index/replacement
  uendret fra I3.
- examples/ingest-golden-sql/: repo-lokal golden (byte-frossen kopi av I4s fasit).
- Speiltester (I4s load-bearing-sett, gjennom SQL-konnektoren, detach-bevist røde):
  sql-golden byte-fasit + mutasjonskontroller · typed-cell/NULL (NY §I5-søm) ·
  provenance/navigability/verdict-reservasjon/re-ingest-safety · SqlSource-kontrakt/
  typed-rendering/connection_ref/max_rows/read-only · spec-integritet utvidet med
  connection_ref. Stale type:"sql"-avvisningscase erstattet (sql er gyldig post-I5).
- docs/2026-07-04-I5-brief.md: brief + premiss-verifisering.

Suite 265 passed uten nøkkel/nettverk (239 + 26 nye) · ruff + mypy --strict rene.

[skip-docs] README + docs/extending.md er bevisst utsatt til I7 per sesjonsplan
(programmet batcher ingest-doc der, avgrenset til det D7 faktisk har — CSV + SQL nå,
HTTP/MCP kun pekere). Dokumentert i docs/2026-07-04-I5-brief.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017MM6BWb1hWmJZuXFZ7rjxT
2026-07-04 07:18:59 +02:00

4.6 KiB

I5 — D7-speil av ingest (SQL-kilde) — brief

Forankret i hovedrepoets sesjonsplan ~/repos/portfolio-optimiser/docs/plan/2026-07-03-sesjonsplan-ingest.md §I5 og dette repoets STATE. Bygget fra shared/ingest-spec.md alene — aldri ved reverse-engineering av MAF-koden. Golden-bytene (den delte fasiten fra MAF I4) er lest, siden spec §11 gjør dem til konformanskravet begge stacker reproduserer. Gaten I4→I5 ble verifisert løst mot ground truth (MAF-commits d7e5f2f/4f45fe6/1b7612b, «I4») før arbeidet startet.

Mål (§I5)

Andre kildetype konsumert uendret fra samme delte kontrakt i søskenrepoet: D7s uavhengige SQL-konnektor reproduserer MAF I4s golden byte-identisk fra spec alene. Scope = sql (lokal SQL-database, sqlite-fixture, null nettverk). file var I3; http = ikke i D7 (målbildet: HTTP/MCP demonstreres MAF-only, I6).

Premiss-verifisering (før impl)

  • Spec byte-identisk delt: diff -q shared/ingest-spec.md mot MAF = IDENTISK. Spec dekker sql fullt (§4 connection_ref, §5 typed-cell/NULL, read-only SELECT). I4 gjorde ingen spec-endring (sesjonsplan §I4) → subtree-pull er no-op (bekreftet, ikke kjørt — ingen drift).
  • Golden-stamp: SHA-256(manifest)[:16] = a4b891aea55df97b reprodusert lokalt → matcher ingest_manifest: manifest@a4b891aea55df97b i forventet bundle.
  • Ingen nye operatør-beslutninger: I3s to avgjørelser (golden repo-lokal kopi; okf relaksert for frontmatterløs index) bærer uendret inn i I5. Én lukket økt, ingen commons-runde.

Leveranse

  • examples/ingest-golden-sql/ — repo-lokal golden (byte-frossen kopi av MAF I4s; diff -r tomt): manifest.json, fixture/portefolje.sqlite, ingested-at.txt, expected-bundle/.
  • src/portfolio_optimiser_claude/ingest.py — SQL-utvidelse:
    • SqlSource-modell (type: "sql", id, connection_ref); ManifestContract.source er nå en diskriminert union FileSource | SqlSourcetype (ukjent/http-tag → fail-fast).
    • _render_sql_cell — §5 typed rendering: None(NULL)→"", int→plain decimal, float→ korteste round-trip (repr), str→verbatim (§5-escaping via delt _escape_cell), annet (BLOB o.l.)→fail (aldri stille coercion).
    • _resolve_connection_ref — env-var-oppslag (§4/§8: referanse ved navn, secret aldri i manifest; usatt ref → fail-fast).
    • _read_sql — read-only sqlite (file:…?mode=ro), ett SELECT (driver håndhever én-statement), max_rows fail-fast (§8).
    • _read_extraction — dispatch på source.type (file→CSV, sql→SQL); materialize kaller den (materialisering/index/replacement uendret fra I3).
  • Speiltester (I4s load-bearing-sett, gjennom SQL-konnektoren):
    • test_ingest_sql_golden.py — byte-fasit + idempotens + 3 mutasjonskontroller (endret rad / timestamp / manifest-bytes).
    • test_ingest_sql_loadbearing.py — typed-cell/NULL (NY §I5-søm) · provenance · navigability · verdict-reservasjon (fail-fast før DB åpnes) · re-ingest-safety.
    • test_ingest_sql.pySqlSource-kontrakt, _render_sql_cell-enheter, connection_ref fail-fast, max_rows-tak, read-only-håndhevelse.
    • test_ingest_spec_loadbearing.pyconnection_ref lagt til kontrakt-felt-guarden (D7s sql-impl avhenger nå av at spec dokumenterer feltet).
    • test_ingest.py — stale type:"sql"-avvisningscase erstattet (sql er gyldig post-I5) med http/ukjent-diskriminator-avvisning (honesty-regelen).

SDK-kroker (STATE steg 4 — søk-først)

I5 (SQL) introduserer ingen SDK-flate: ingest er deterministisk, null modellkall. Søk-først SDK-krok-reverifisering (API-drift på create_sdk_mcp_server) er relevant for I6 (HTTP/MCP), ikke I5 — utsatt dit kroken faktisk brukes. Eksisterende SDK-klient uendret og grønn i suiten.

Verifisering (kjørt, grønn)

  • Golden byte-identisk konsumert (5/5, inkl. idempotens + mutasjonskontroller).
  • Speiltester røde ved detach — de nye sømmene bevist load-bearing (detach-bevis-skript): typed-cell/NULL · connection_ref fail-fast · sql-dispatch · spec-integritet (connection_ref).
  • Søskensuite grønn uten nøkkel/nettverk: 265 passed (239 + 26 nye).
  • ruff check + ruff format rene · mypy --strict src: no issues (16 filer).

Åpent (forslag, ikke utført — utenfor I5-scope)

  • Standard-evolusjon: «typet index overalt» som bevisst OKF-endring forblir en egen koordinert commons-RFC (begge specs/golden/okf). Dagens permissive okf er forover-kompatibel.
  • Åpent-speil-synk: I3/I5-koden er ikke pushet til det offentlige open/-speilet (outward-facing → egen operatør-handling).