portfolio-optimiser/src/portfolio_optimiser
Kjell Tore Guttormsen 8d1d29edf0 fix(ingest): narrow mcp_timeout to our OWN deadline, not the exception type (kø-z follow-up)
Advisor review of the prior commit (5269b7d) found the except TimeoutError
branch was wider than the brief asked for: builtin TimeoutError is also
socket.timeout (3.10+) and asyncio.TimeoutError (3.11+), so any TimeoutError
reaching that clause got relabeled mcp_timeout regardless of source. Gate on
anyio.CancelScope.cancelled_caught instead, mirroring _unwrap_ingest_error's
ownership rule (own it, wrap it; otherwise, untouched).

Measured: no live trigger exists today (MCP's own internal read-timeout
converts to McpError before reaching us; a server-side TimeoutError becomes
an ordinary isError result) -- pinned with a synthetic test raising from
StdioServerParameters construction, inside our fail_after scope but before
either nested task group, so it arrives ungrouped. Four mutations red against
the full 625-test suite: drop the translation, revert to asyncio.wait_for,
relabel the code, and drop the cancelled_caught gate.

Also promotes anyio to a declared direct dependency (was transitive via mcp
only) -- ingest_mcp.py now imports it directly.
2026-08-03 21:22:00 +02:00
..
data feat(validator): anchor the deterministic gate to the project's real cost baseline (S4.0) 2026-08-03 17:19:31 +02:00
__init__.py feat(s53): load_dimension fail-fast loader (MAF-free, mirrors load_goal_config) 2026-07-23 21:31:32 +02:00
backends.py fix(s41): pass required credential in AzureFoundryBackend.create_chat_client 2026-07-15 11:18:40 +02:00
budget.py feat(budget): enforce a global portfolio token cap before the call, not after it (S3.4/F10) 2026-07-31 21:34:48 +02:00
contracts.py feat(fase1): GoalContract + GoalConfig standalone fail-fast loader (F1) 2026-07-07 08:01:53 +02:00
costsim.py docs(s54): --report CLI surface + truthful costsim kost_mot_verdi seam note 2026-07-24 01:38:10 +02:00
datasource.py feat(fase2b): OKF-navigated bundle context replaces chunk-stuffing 2026-06-30 06:42:19 +02:00
dimension.py feat(s53): load_dimension fail-fast loader (MAF-free, mirrors load_goal_config) 2026-07-23 21:31:32 +02:00
generate.py feat(validator): anchor the deterministic gate to the project's real cost baseline (S4.0) 2026-08-03 17:19:31 +02:00
hitl.py fix(s51): close 2 review MINORs — non-UTF-8 skip + affected_codes parity 2026-07-15 20:59:01 +02:00
ingest.py feat(ingest): bound the default http transport in time, in front of the pinned library (S2.4) 2026-08-03 14:54:04 +02:00
ingest_mcp.py fix(ingest): narrow mcp_timeout to our OWN deadline, not the exception type (kø-z follow-up) 2026-08-03 21:22:00 +02:00
ir.py feat(validator): anchor the deterministic gate to the project's real cost baseline (S4.0) 2026-08-03 17:19:31 +02:00
ledger.py fix(money): quantize NOK to øre in one order, from one source (kø-p) 2026-08-03 20:08:59 +02:00
notify.py fix(s52): resolve ConsoleNotifier default stream at call time 2026-07-17 03:18:00 +02:00
okf.py feat(validator): anchor the deterministic gate to the project's real cost baseline (S4.0) 2026-08-03 17:19:31 +02:00
outbox.py feat(s42): byte-deterministic write_run_config outbox writer 2026-07-15 12:39:42 +02:00
persona.py feat(shared-root): S3 — configurable shared-root resolver with load-bearing override test 2026-07-03 01:10:05 +02:00
preflight.py fix(s41): close review WARN — OSError refusal + scheme/profile branch coverage 2026-07-15 11:58:10 +02:00
provenance.py feat(fase2): first-class Pydantic provenance stamp 2026-06-24 13:26:55 +02:00
reference_domain.py feat(fase2a): optional Project.bundle_dir + loader (backward-compat, S2.0) 2026-07-15 07:03:15 +02:00
retrieval.py fix(retrieval): fail-closed on uncanonicalisable paths (embedded null byte) 2026-07-21 08:00:11 +02:00
run.py fix(money): quantize NOK to øre in one order, from one source (kø-p) 2026-08-03 20:08:59 +02:00
semretrieval.py fix(s31): close 1 review MAJOR — bound the blend weight so the hybrid preserves structural order 2026-07-25 20:03:37 +02:00
shared_root.py test(okf): lock link_in_index success-path byte/order preservation + honest shared_root claim 2026-07-21 09:38:56 +02:00
simulation.py feat(s42): live_dry_run cut in run_project + DryRunReport 2026-07-15 18:05:16 +02:00
validator.py feat(validator): anchor the deterministic gate to the project's real cost baseline (S4.0) 2026-08-03 17:19:31 +02:00
value_report.py feat(s54): value_report text + deterministic JSON formatters 2026-07-24 01:29:31 +02:00
verdicts.py feat(verdicts): key each verdict on its own candidate, not the bundle's one IR projection (S3.2) 2026-08-03 16:44:58 +02:00
workflow.py feat(fase3): make the maker-checker checker actually gate the reasoning 2026-06-30 07:24:30 +02:00