Sil-Q implementation
The public contract is documented in GAME_GUIDE.md. Current
validation and experiment status are in LAUNCH_READINESS.md.
The runtime uses silq-session-v4, silq-observation-v2 and silq-response-v1.
Isolation and native state
The game service owns the native engine, private random streams, append-only
journal, request receipts and scorer. The agent container receives only public
client modules, the guide/manual, and its persistent workspace. It has neither
the game binary nor private state. The internal network, dropped capabilities,
read-only filesystems and container limits are defined in compose/compose.yaml.
The native adapter exposes rendered screens plus player-visible status, displayed creatures, known inventory, native prompt types and drawn messages. Menu overlays, hallucination and other unavailable information are explicit. Monster membership includes native detection and memory; it does not establish current line of sight. Hidden-state and side-effect tests check the projection.
Upstream repairs are checked patches against the pinned source revision. GRADING_AUDIT.md records native command, visibility, RNG and scoring repairs. Test-only setup remains absent from the production engine.
Python architecture
Pydantic schemas validate JSON boundaries without extra fields or scalar coercion. Enums name endpoints, events, modes and trial states; dataclasses hold mutable runtime/replay state. JSON conversion occurs at persistence and transport boundaries.
| Responsibility | Module in silq_eval/ |
|---|---|
| Public observations and responses | models.py, protocol.py |
| Session schedule and input validation | contract.py, requests.py |
| Native process and bounded reads | native.py |
| HTTP framing and authentication | transport.py |
| Journal schemas and integrity | journal.py, evidence.py |
| Trial transitions | lifecycle.py |
| Reconstruction and summary verification | audit.py |
| Durable receipts and recovery | durable.py, replay.py |
| CLI and HTTP client | client.py, client_api.py |
| Client intent and frame history | history.py |
| Actions, prompt guards and event projection | actions.py, controls.py, presentation.py |
| Readable output | rendering.py |
| Native victory and progress | scoring.py, progress.py |
| Inspect task and protected snapshots | task.py, operator.py |
reconstruct returns a typed ReplayState; recovery consumes it directly.
Each journal event has a schema and transition handler. Hash checks use the
original JSON before normalization. Reconstructed summaries include timestamps,
progress and pending operations, rather than trusting cached totals.
Input and recovery
Named actions and typed replies validate the native prompt and the latest trial/frame. Guarded key batches stop at action/prompt boundaries and report unsent keys. Raw input remains available. Acknowledgment dismisses only native message pages; it may let an unfinished native turn continue. There is no built-in combat, navigation or resting strategy.
The CLI persists intent before transmission and archives complete public frames. A durable request ID binds the entire body. Exact retries return the committed response without executing twice. Recovery replays the same random stream and compares every accepted native frame, including protected state. Mismatched sources, receipts or replay fail closed. Deadlines stay absolute across downtime.
Scoring and admission
Victory requires the native terminal escape transition and actual possession of a Silmaril. Rendered text and model claims never award a win. Depth, acquisition and ascent are independent diagnostics. Every metric shares one authenticated, finalized scoring snapshot reconstructed from accepted native observations.
Admission requires a complete evaluation, exact replay, verified model requests,
complete tool results, public-view review, bound evidence and no unresolved
environment failure or infrastructure limit. Under success-within-budget-v1,
trial time/key exhaustion is a valid zero outcome. A protected session_expired
event proves that the original session deadline was reached; only then may a
partial schedule count, with unfinished/unstarted games scoring zero and earlier
wins retained. Inspect time limits must match that evidence. Operator stops,
cost/token limits and provider/native failures cannot become budget outcomes.
An Inspect time-limit event can explain only trailing canceled generations or
unfinished calls in the last tool batch; it must match protected session expiry.
Earlier errors or missing results remain failures. Cancellation never invents
API usage or a completed response, and the qualitative review covers its effects.
complete denotes a completed evaluation; schedule_complete requires every
scheduled game to have ended. Missing public frames require
observation_review.py coverage naming each trial/frame exactly once, with
supporting evidence. Deliberate agent summaries are distinguished from interface
loss; unprinted fields are not claimed as model-visible evidence.
Experiments and reporting
experiments.py is the only dispatch path; launch.py freezes source, images,
schedules, pricing and commands without making model requests. Worker locks,
launch intents and authorization rechecks prevent duplicate or stale dispatch.
Research readiness binds the exact plan and environment. Max additionally
requires the reviewed medium gate. See README.md for
templates and commands.
Time, input, retry and container budgets are frozen before dispatch. A null cost cap disables dollar-based stopping while retaining usage accounting. Resource telemetry is separate from the native outcome. Reports retain every registered attempt and compute capability statistics only for complete admitted conditions.
Current reports include depth per scheduled game and protected elapsed-time
trajectories, jewel acquisition and carrying-ascent. Unstarted games have zero
attainment but no trajectory. No observation accepted at or after a deadline
earns progress. Model-specific pricing is frozen in each manifest: GPT-5.5's
long-context uplift is session-wide; Astra's is per-request. The primary cost
field is estimated_session_priced_usd; missing usage leaves the total unknown.
Historical results retain their original materials, exclusions and scores. Historical runtime and controller-specific validators are available in frozen run sources and Git history; the active runtime has no v1/v2 compatibility branches.