docs(s31): close the review's honesty gap — narrow semantic claims to the shipped mechanism

This commit is contained in:
Kjell Tore Guttormsen 2026-07-25 13:00:13 +02:00
commit 9e149c6847
5 changed files with 81 additions and 36 deletions

View file

@ -35,19 +35,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`costsim` seam note was reworded from the stale "fylles av S5.4 verdirapport" to a truthful
forward reference so `costsim`'s own output no longer claims the wiring is done.
- Semantic retrieval seam (S3.1): a new MAF-free `semretrieval.py` adds an `Embedder`/`Retriever`
pair and a `HybridRanker` blending brute-force numpy cosine over embedded proposal features with
the existing structural score, exposed as `--semantic-retrieval` (valid in both run modes).
**Off by default and additive**: with no retriever installed the store delegates to
pair and a `HybridRanker` blending a numpy cosine term over the embedded feature triple (sorted
cost codes, measure type, magnitude bucket) with the existing structural score, exposed as
`--semantic-retrieval`. **What ships is the seam, not better retrieval quality**: the bundled
`FakeEmbedder` is a deterministic sha256 projection with no semantics, so over a structural tie
the order is deterministic but arbitrary. A real embedder is selected from a CLOSED registry via
`--embedder-config` / `build_embedder` — deliberately never an import path, so a config file can
never name arbitrary code to load.
**Off by default and additive**: with no retriever passed the store delegates to
`StructuralRetriever`, which reproduces the pre-seam ranking exactly, so the text-excluded
default and every existing test are unchanged. Turning it on is a deliberate, gated reversal of
that default, since an embedder does see proposal text. Determinism is pinned rather than hoped
for: BLAS threads are fixed before numpy is imported, vectors are C-contiguous float64, and
ranking uses the total order `(-round(score, 9), id)`. Ships an optional, rebuildable
`vectors.npy` + `vectors.jsonl` store (byte-identical regardless of insertion order; fail-fast
on a row/line mismatch; missing loads as `None`). numpy is confined to `semretrieval.py` and
never enters `okf.py`, `retrieval.py` or `shared/`. The real embeddings client remains a
config-only extension point — the shipped `FakeEmbedder` is a deterministic hash projection with
no semantics, so this buys a scaling *seam*, not better retrieval quality.
default and every existing test are unchanged. The embedding excludes `description`, matching
`similarity` ("text is ignored by design") and the verdict-id hash — so a flag-on run reads no
surface text either, and a genuine expert verdict can no longer be outranked by the framework's
own echo of the query. The ranker is passed PER CALL, never assigned to the caller's store, so
the opt-in cannot outlive the run that asked for it. Accepted in both run modes; in
single-project mode it requires `--bundle-dir` and `--verdict-dir` and is refused — never
silently ignored — without them.
Determinism, precisely: ranking order rests on the total order `(-round(score, 9), id)`; the
BLAS thread pins set before numpy is imported (`VECLIB_MAXIMUM_THREADS` for Accelerate,
`OPENBLAS`/`MKL`/`OMP` for other backends) defend the narrower claim that vector artifacts are
byte-identical across environments. Ships an optional, rebuildable `vectors.npy` +
`vectors.jsonl` store (byte-identical regardless of insertion order; fail-fast on a row/line
mismatch; missing loads as `None`) — an authoring primitive with no caller in `src/`, offered to
extenders like `write_verdict` and `promote_verdict`. numpy is confined to `semretrieval.py` and
never enters `okf.py`, `retrieval.py` or `shared/`.
- Azure/Foundry offline preflight config gate (`preflight.py`, S4.1).
- Offline live-dry-run drill (`--live-dry-run`, S4.2): walks the whole path up to the eager
client build and stops before the first model call — zero chat calls.
@ -58,8 +69,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`allow_egress` opt-in. Not auto-wired into `run.py`.
- `docs/knowledge-base-recipe.md` (S5.3, D-H item 1): the documented team process (technical +
domain expert) for building a knowledge base, with the honest 12 week expectation.
- Test suite: 488 passing tests (4 skips are live-provider-only), every wired seam covered by a
load-bearing test that goes red when the seam is detached.
- Test suite: 512 passing tests (4 skips are live-provider-only). Every wired seam is covered by a
load-bearing test that goes red when the seam is detached — including, since the S3.1 review
remediation, the `--semantic-retrieval` wiring at `main()` level. That claim did not hold for
S3.1 as first shipped: the flag was covered only below the CLI, so hardcoding it off left the
suite green. Each remediated seam now carries a recorded detach point, verified by mutation.
### Notes
- Licensed under the MIT License (see `LICENSE`).