portfolio-optimiser/docs
Kjell Tore Guttormsen c02c1addba fix(semretrieval): refuse a non-finite embedding instead of scoring it (kø-(l)/S3.1 MINOR)
`cosine`'s docstring claimed its guard was load-bearing because "a NaN reaching the
ranking sort key would corrupt ordering silently rather than failing loudly" — but the
guard tested `norm == 0.0` only, which a NaN or inf norm passes straight through. The
claim was prose, not behaviour.

Measured, not assumed: `cosine(unit, nan_vector)` AND `cosine(unit, inf_vector)` both
returned `nan`, and a NaN sort key made ranking INPUT-ORDER-DEPENDENT — six permutations
of the same three candidates produced four distinct orderings. That defeats the total
order `HybridRanker` documents ("`id` makes the result independent of input order").

Refuse rather than coerce, and deliberately NOT symmetric with the zero-norm branch: a
zero vector is a legitimate handled state (`FakeEmbedder` returns `np.zeros` by design),
whereas a non-finite component only ever means the INJECTED embedder is broken. Scoring
it `0.0` would launder that into "no semantic similarity" while ranking proceeded on a
forged signal — validation, never repair, mirroring `read_spend`.

Reachable via the documented `Embedder` extension point, not the shipped fake; scoped to
the norms (90% principle — a finite-normed dot-product overflow is not chased).

Also corrects `docs/extending.md`, which stated `SEMANTIC_WEIGHT_DEFAULT = 0.5` while the
code has said `0.25` since the weight was lowered.

625 -> 630 tests. Load-bearing MEASURED against the WHOLE suite, five mutations all red:
detach the guard entirely · coerce to 0.0 instead of raising · check only the first norm ·
drop "non-finite" from the message · (control) detach the zero-norm branch, which fails
ONLY the zero-norm test — the new guard does not mask the existing one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018V9vNBmxAmgJ2JMoHByiHS
2026-08-03 21:48:50 +02:00
..
fase1-spikes fix(fase1): spike B fan-out measures real conversation bleed, not a counter 2026-06-24 11:09:55 +02:00
plan docs(security): plan llm-ingestion-guard inclusion at ingest/inbox persist-gates 2026-07-16 07:43:30 +02:00
rapport docs(i7): reproduserbar grep i statusrapport rad #10/#11 (--exclude selv-referanse) 2026-07-04 23:34:26 +02:00
research docs(research): MAF 1.9.0 capability map — feature-utilization for Fase 2 [skip-docs] 2026-06-24 11:36:26 +02:00
2026-06-24-two-approaches-brief.md docs: plain-text brief — goal + two approaches (MAF vs Claude Agent SDK) + learning goal 2026-06-24 09:21:31 +02:00
2026-06-26-fot-i-bakken.md docs(fot-i-bakken): ground-truth-verifisert levert-vs-lovet — agentiske lag inerte 2026-06-26 15:25:03 +02:00
2026-07-15-foundry-auth-recipe.md docs(s41): verified Foundry auth recipe + necessary-but-not-sufficient note 2026-07-15 11:24:18 +02:00
extending.md fix(semretrieval): refuse a non-finite embedding instead of scoring it (kø-(l)/S3.1 MINOR) 2026-08-03 21:48:50 +02:00
knowledge-base-recipe.md docs(s53): knowledge-base recipe (D-H item 1) — team process, honest 1-2 week expectation, no wizard 2026-07-23 21:53:53 +02:00
review-2026-07.md docs(review): kryssmodell-review 2026-07 (14 funn, 11 detach-bevis) + revidert roadmap + sesjonsplan Fase 2-6 2026-07-10 06:28:11 +02:00