Files
arena/environments/grand_exchange_live/tests/context.py
T
kartiandClaude Opus 5 f953c03bd1 grand-exchange-live: protocol layer, taskset, config, widened reference gate
The stepped engine becomes a runnable taskset. protocol.py is both the
render/parse boundary and the security boundary: TurnView carries the live
Market, so view.market.items[i].prices is the whole held-out series and a
foresight policy reading it earned +9.4% on the oracle. The renderer emits only
observed ticks, the trace carries plain scalars, and a sentinel scan of every
rendered turn fails if either reopens. House rule 1 had no other enforcement.

Replies are a delta sheet and parsing never raises — NaN, Infinity, 1e309 and
20k-deep nesting all resolve to a hold, because the one-shot form has already
shown what a real model sends when it gives up.

LiveExchangeEnv.run drives the engine host-side with the harness left null. Two
things learned the hard way and worth keeping: a terminated Segment mid-window
holds the remaining looks instead of raising, and rewards are recorded INSIDE
the interaction, before close. Recording after close writes the traces correctly
and leaves every eval.log line reading reward=0.000 — the canonical verifiers
reference does it after the block; do not copy it there.

The reference-family gate is widened from four named rungs to the whole 8x8
(requote_band, idle_share) family: no member may out-earn the shipped reference
by more than 1.02x, and any that does must still score >= 0.90. That is the check
that caught the first draft's fake 0.152 gap, now shipped rather than remembered.

Also guards `clean` on the reference being profitable, here and in the one-shot
form. Against a reference that lost money the bar is negative, so doing nothing
cleared it and inaction collected a quarter of the reward. Unreachable while
viable_market admits only profitable references; one relaxed filter from
reachable, and exactly the floor house rule 3 forbids. Probe values unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 17:44:20 -07:00

41 lines
1.5 KiB
Python

"""Import the package under test, installed or not — and get the same one every time.
Two facts collide here. `probe.py` and half of this suite must run with NOTHING installed,
which is why the package is registered as a namespace pointing at the source directory and
its leaf modules are imported under it: `__init__` never executes, so `verifiers` is never
required. And `test_taskset.py` needs the opposite — `verifiers` present and
`grand_exchange_live` resolving to the REAL package, because `import_taskset` reads
`__all__` off whatever is in `sys.modules` and a namespace shim has none.
A shim installed by whichever test module imported first would decide that for the whole
process. So the decision is made once, here, and every test module imports this before it
imports anything else: the real package if it is importable, the shim if it is not.
"""
from __future__ import annotations
import sys
import types
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def shim(package: Path) -> None:
"""Register `package` as a namespace so its leaf modules import without its `__init__`."""
module = types.ModuleType(package.name)
module.__path__ = [str(package)]
sys.modules[package.name] = module
try:
import grand_exchange_live
INSTALLED = getattr(grand_exchange_live, "__all__", None) is not None
except ImportError:
# The package is there and `verifiers` is not, which is the no-dependency path.
INSTALLED = False
if not INSTALLED:
shim(ROOT / ROOT.name)