portfolio-optimiser/tests/test_scripted_client_consolidation.py
Kjell Tore Guttormsen 756b1d5b5c feat(s33): wave executor with per-project snapshot and deterministic merge barrier
Replaces run_portfolio's sequential loop with a wave loop over _waves(ids, k):
each wave takes a per-project snapshot of the shared store, runs the wave under
one asyncio.gather in a single event loop, then crosses a merge barrier that
folds each project's NEW verdicts back in wave-submission order. Step 2's
contract goes GREEN; runs stays in project_ids order because gather resolves in
argument order, not completion order.

TWO PLAN CORRECTIONS, both found by the RED-first test rather than by reading:

1. The plan specified sorting the merged verdicts on `project_id`. Measured, that
   produces a deterministic order which is the WRONG one: lexicographic gives
   BRU/FV42/RV13 while the sequential pass gives FV42/RV13/BRU. It satisfies
   "deterministic" while breaking "identical to concurrency=1" — and the second is
   the actual contract. The merge preserves submission order instead.

2. The plan named the barrier's sort as the load-bearing seam. It is not — with
   per-project snapshots the wave list is never reordered by completion, so a
   sorted() there would re-sort an already-ordered list and read as a guard while
   guarding nothing. The SNAPSHOT is the half that carries the load. Rather than
   ship a decorative sort, both halves were measured (scratchpad-restore, never
   git checkout):

     detach _wave_snapshot  -> RED (store lands in completion order)
     detach merge ordering  -> RED (reversed wave order diverges)

   Both restored byte-identical (sha 42b01d46).

The snapshot carries `retriever` across deliberately: dropping it would silently
downgrade a caller-owned store's S3.1 semantic-retrieval opt-in mid-pass.

Also strengthens the scripted-client consolidation guard, which the probe broke by
being a legitimate third _inner_get_response def-site. It pinned a literal count
of 2 — the wrong shape: it failed on any new legitimate subclass while still
passing if someone pasted a duplicated body into an already-listed file. It now
pins the property (registered sites, scripted-lineage overrides must delegate via
super(), foreign-lineage doubles must genuinely be foreign). Verified load-bearing:
removing both delegation sites turns it RED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LQapztREtC2mkr5oU811pr
2026-07-31 15:56:13 +02:00

120 lines
6 KiB
Python

"""S2.5 (Step 9) consolidation guard (T-2.5e): the four scripted ``_inner_get_response`` bodies
collapsed to ONE canonical client (``simulation.ScriptedChatClient``); conftest's three test doubles
now SUBCLASS it. These grep-guards lock that in — they go RED if a divergent ``_inner_get_response``
is re-added, if a ``src``→``tests`` import creeps in, or if a double stops subclassing the canonical.
The guard is a regression lock over an already-verified consolidation: before the collapse there were
five ``def _inner_get_response`` sites (four scripted + test_step5's own-lineage double); after, two.
"""
from __future__ import annotations
import re
from pathlib import Path
_ROOT = Path(__file__).resolve().parents[1]
def _py_files(base: str) -> list[Path]:
return sorted((_ROOT / base).rglob("*.py"))
# Files permitted to define ``_inner_get_response``. The invariant this guard protects is that the
# scripted BODY is not duplicated — not that the def-site count is frozen. Adding a file here is a
# deliberate act: a new entry must either be the canonical, or a thin override that DELEGATES to it
# (which ``test_delegating_overrides_call_super`` below then enforces mechanically).
_CANONICAL_SITE = "src/portfolio_optimiser/simulation.py"
# Overrides in the SCRIPTED lineage — they subclass ``ScriptedChatClient``, so a body of their own
# would be a copy of the canonical. They must delegate.
_DELEGATING_OVERRIDES = [
# S3.3 ordering probe: yields to the event loop N times, then delegates. It cannot live in the
# reply-selector seam, which the canonical calls synchronously and so can never await.
"tests/test_portfolio_concurrent_loadbearing.py",
]
# Doubles in a DIFFERENT lineage (``spikes._harness.FakeChatClient``). There is no canonical
# scripted body above them to delegate to, so the delegation rule does not apply — but the
# separation is asserted rather than assumed, so a file cannot be parked here to dodge the rule.
_FOREIGN_LINEAGE = ["tests/test_step5_refine_loadbearing.py"]
def test_inner_get_response_collapsed_to_two_sites() -> None:
"""The four scripted clients collapse to ONE canonical ``_inner_get_response``
(``simulation.py``). Every other def-site must be a registered, DELEGATING override — never a
fourth copy of the body.
The guard originally pinned a literal count of 2. That made it fail on any new legitimate
subclass while still passing if someone pasted a duplicated body into an already-listed file —
a count is the wrong shape for the invariant. The list below plus
``test_delegating_overrides_call_super`` pin the property itself."""
sites = [
p.relative_to(_ROOT).as_posix()
for base in ("src", "tests")
for p in _py_files(base)
if p.name != Path(__file__).name # this guard file references the pattern in prose
and "def _inner_get_response" in p.read_text(encoding="utf-8")
]
expected = sorted([_CANONICAL_SITE, *_DELEGATING_OVERRIDES, *_FOREIGN_LINEAGE])
assert sorted(sites) == expected, (
f"unregistered ``_inner_get_response`` def-site — the scripted body must not be copied. "
f"Expected {expected}, got: {sites}"
)
def test_foreign_lineage_doubles_are_genuinely_foreign() -> None:
"""A file listed as foreign lineage must NOT subclass the scripted canonical.
Without this, ``_FOREIGN_LINEAGE`` would be an escape hatch: any scripted-lineage subclass
could be moved into that list to skip the delegation rule below."""
for site in _FOREIGN_LINEAGE:
text = (_ROOT / site).read_text(encoding="utf-8")
assert "ScriptedChatClient" not in text, (
f"{site} is registered as foreign lineage but references ``ScriptedChatClient`` — if it "
"is in the scripted lineage it belongs in _DELEGATING_OVERRIDES and must delegate"
)
def test_delegating_overrides_call_super() -> None:
"""Every scripted-lineage override actually DELEGATES to the canonical rather than
reimplementing it.
This is the strength the literal count never had: without it, a file already on the list could
grow a full copy of the scripted body and the consolidation would be cosmetic again."""
for site in _DELEGATING_OVERRIDES:
text = (_ROOT / site).read_text(encoding="utf-8")
# Match the delegation ITSELF — ``super()._inner_get_response`` or the explicit
# ``super(Cls, self)._inner_get_response`` form a nested function needs. Searching for
# "super(" and "_inner_get_response" independently would pass on any file that merely
# calls ``super().__init__`` near a def, which is accidental-green, not a guard.
assert re.search(r"super\([^)]*\)\._inner_get_response", text), (
f"{site} defines ``_inner_get_response`` but never delegates to the canonical via "
"``super()._inner_get_response`` — that is a duplicated body, which is exactly what "
"this guard exists to prevent"
)
def test_no_src_imports_tests() -> None:
"""No ``src`` module imports from ``tests`` — the canonical lives in ``src/simulation.py`` so
``conftest`` imports ``src``, never the reverse (the forbidden src→tests direction)."""
offenders = [
p.relative_to(_ROOT).as_posix()
for p in _py_files("src")
if ("from tests" in (text := p.read_text(encoding="utf-8")) or "import tests" in text)
]
assert offenders == [], f"src must not import tests: {offenders}"
def test_conftest_doubles_subclass_canonical() -> None:
"""conftest's three test doubles genuinely SUBCLASS the canonical ``ScriptedChatClient``
(delegating the shared body) — so the consolidation is real, not cosmetic."""
from conftest import (
ScriptedChatClient,
SyntheticUsageChatClient,
_ProjectAwareUsageChatClient,
_RecordingChatClient,
)
assert issubclass(SyntheticUsageChatClient, ScriptedChatClient)
assert issubclass(_ProjectAwareUsageChatClient, ScriptedChatClient)
assert issubclass(_RecordingChatClient, ScriptedChatClient)