refactor(ingest): adopt shared llm-ingestion-okf v0.3.1 behind a thin adapter
Door A (manifest -> connector -> deterministic materialization -> index) is no longer implemented here. src/portfolio_optimiser/ingest.py becomes a thin consumer seam over the shared library, git-pinned to v0.3.1 on the same Forgejo channel portfolio-optimiser-claude uses. Net -626/+385; ingest.py 599 -> 145 lines. shared/ingest-spec.md remains the normative spec: the library implements it, it does not replace it. Spec changes continue to go via commons. Acceptance criterion met and proven: all three golden bundles (file/sql/http) are byte-exact before and after, including the idempotence re-run. examples/ and shared/ carry ZERO modifications -- the fasit was not adjusted to fit. The rejection set was verified equivalent, not assumed: all 22 malformations the repo's pydantic models refused are refused by the library, with typed codes (okf_type_reserved, credential_embedded, extraction_id_duplicate, ...). Test rebinding (invariants preserved, vehicle changed): the library has zero runtime dependencies by design, so pydantic is unavailable to it. ManifestV1.model_validate(dict) -> load_manifest_bytes(bytes); ValidationError -> ManifestError; model_fields -> dataclasses.fields; PathSecurityError -> SourceError(path_escape); ValueError -> MaterializationError(ingested_at_invalid). Tests now also pin the refusal `code`, the library's documented stability contract -- a sharper assertion than "some validation error was raised". Two accepted behavioural deltas, recorded rather than silently dropped: - Title whitespace is stored verbatim instead of collapsed at validation, so the frontmatter title and the index label are no longer guaranteed identical for irregular whitespace. Both behaviours are spec-conformant (the spec is SILENT; the old one was a repo-local pinned decision). Queued as a commons-amendment candidate so both stacks pin the same answer. Goldens unaffected. - The section 8 audit log moves to logger llm_ingestion_okf.materialize. Nothing in the repo consumed the old channel. Also: the `type` discriminator is no longer a dataclass field, so the spec cross-check asserts it explicitly -- without that line the swap would have silently narrowed the test. New tests/test_ingest_library_seam.py pins the seam itself: the restated section 5 stamp formula against the stamp the library actually writes (the one place the adapter does not purely delegate, since v0.3.1 exposes no stamp helper), the local-only allow_network default, the list[Path] unwrapping, and a guard that the adapter never regrows local Door A machinery. All four verified RED when detached, as were both golden regressions under a byte-level render mutation. Door A is UNGATED: it calls no guard before writing to disk. Gating untrusted content remains the caller's responsibility (guard wiring still planned). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4jNN186eVqfe1x5DnTU6r
This commit is contained in:
parent
7ec60618b0
commit
0a11af74a4
9 changed files with 385 additions and 626 deletions
|
|
@ -57,7 +57,16 @@ The role keys (`proposer`, `checker`, `default`) let you assign a distinct model
|
|||
The **ingest layer** (`ingest.py`, spec `shared/ingest-spec.md`) is a second, distinct source
|
||||
seam from the retriever above: one JSON **manifest** per source coupling declares a `source.type`
|
||||
and a list of extractions; `materialize(...)` runs the connector for that type and writes an OKF
|
||||
bundle. The spec ships three source families — `file`/CSV (I2), `sql` (I4), and **`http`** (I6) —
|
||||
bundle.
|
||||
|
||||
> **Where to change it (2026-07-20):** `ingest.py` is a thin adapter — Door A is implemented by
|
||||
> the shared [`llm-ingestion-okf`](https://git.fromaitochitta.com/open/llm-ingestion-okf) library
|
||||
> (git-pinned to `v0.3.1`), so connectors, materialization and index generation improve in ONE
|
||||
> place across every consumer. `shared/ingest-spec.md` remains the normative spec — the library
|
||||
> implements it, it does not replace it, and spec changes go via commons. The API below is
|
||||
> unchanged; only the implementation moved. Note that Door A is **ungated**: it calls no
|
||||
> security guard before writing to disk, so gating untrusted content is the caller's
|
||||
> responsibility (see `docs/plan/2026-07-16-llm-ingestion-guard-inclusion.md`). The spec ships three source families — `file`/CSV (I2), `sql` (I4), and **`http`** (I6) —
|
||||
and `http` is the framework's **worked extension-point example**: it shows exactly how a third,
|
||||
network-transport family plugs into the same connector / materialization / gate contracts.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue