45 lines
2.2 KiB
Python
45 lines
2.2 KiB
Python
"""Spike B tests — Magentic unbounded footgun (G1/B4) + fan-out state isolation (G2/B7).
|
|
|
|
These drive the real GA builders with the fake client (no endpoint), de-risked by the
|
|
Step 2 builder smoke. Pattern: tests/test_backends.py.
|
|
"""
|
|
|
|
from portfolio_optimiser.reference_domain import load_reference_projects
|
|
from spikes.b_footguns import (
|
|
bounded_magentic_terminates,
|
|
fresh_instance_conversation_isolation,
|
|
shared_instance_conversation_bleed,
|
|
unbounded_magentic_self_terminates,
|
|
)
|
|
|
|
|
|
async def test_unbounded_magentic_does_not_self_terminate() -> None:
|
|
# max_round_count=None never finalizes — only the external guard stops it (B4).
|
|
self_terminated = await unbounded_magentic_self_terminates(guard_rounds=8)
|
|
assert self_terminated is False # the guard fired, not a natural stop
|
|
|
|
|
|
async def test_bounded_magentic_terminates_within_limit() -> None:
|
|
# An explicit max_round_count makes the same never-satisfied manager stop cleanly.
|
|
assert await bounded_magentic_terminates(max_round_count=2) is True
|
|
|
|
|
|
async def test_shared_instance_bleeds_conversation_across_projects() -> None:
|
|
ids = [p.id for p in load_reference_projects()]
|
|
assert len(ids) >= 2 # need >=2 projects to show cross-run bleed (portfolio grew via SC1)
|
|
seen = await shared_instance_conversation_bleed(ids)
|
|
# Reusing ONE built workflow accumulates the MAF thread across runs: each run's
|
|
# participant receives the EARLIER projects' prompts too (genuine G2/B7 bleed),
|
|
# measured by message CONTENT — not a call counter.
|
|
assert seen[0] == [ids[0]] # first run is clean — nothing prior to bleed
|
|
assert set(seen[-1]) == set(ids) # last run saw every project's prompt
|
|
# Strictly monotonic growth = conversation history accumulating, not coincidence.
|
|
assert all(set(seen[i]) < set(seen[i + 1]) for i in range(len(seen) - 1))
|
|
|
|
|
|
async def test_fresh_instance_isolates_conversation_across_projects() -> None:
|
|
ids = [p.id for p in load_reference_projects()]
|
|
seen = await fresh_instance_conversation_isolation(ids)
|
|
# A fresh instance per project gives each run a clean thread -> a participant sees
|
|
# ONLY its own project -> zero cross-run contamination (the B7 mitigation works).
|
|
assert seen == [[pid] for pid in ids]
|