Sil-Q evaluation

A coding agent plays Sil-Q through its 80×27 terminal. The protected service owns the engine, private randomness, and scoring. A win requires taking a Silmaril from Morgoth's crown and escaping with it.

The September 2026 study completed ten Astra-medium sessions, each with eight practice games and two scored games: 0 wins in 20 scored games. Across all 100 games, 99 ended in death and one practice game was retired. Both Astra-max attempts were interrupted before scored play and excluded; the controls were canceled. There is no scored max result or measured effect of practice.

Report and replays · Report source · Results · Methods · Scope amendment

Current harness

Revision 0.5.0 uses silq-session-v2. It adds durable request receipts, verified replay after service restart, persistent client workspaces, and experiment supervision. Completion and victory are separate metrics; authenticated final scoring freezes outcomes.

Engineering checks passed 246 tests (two optional plotting tests skipped), native sanitizer and replay checks, and real container restart and scoring checks with zero model requests. Fresh model pilots, direct public play, and resource calibration are still needed before new research. Historical results retain their frozen implementation and materials.

Development

Use Python 3.11 or later, uv, and Docker with Compose. From this directory:

uv sync --frozen
uv run python scripts/bootstrap.py
uv run pytest -q -rs
uv run python scripts/native_qa.py --output /tmp/silq-native-qa.json
uv run python scripts/qa_inspect.py --output .private/qa-new --report /tmp/silq-inspect-qa.json
uv run python scripts/qa_recovery.py --output .private/qa-recovery-new

These checks make no model requests. Bootstrap builds the development image tags. To preserve existing tags, build separate Docker service and client targets and pass --service-image and --client-image to the smoke tests. Output directories and run names are single-use. CI runs the engineering checks.

Experiments

Copy experiments/development.template.json and set the name, images, limits, and bundle count. Its default limits have not been calibrated for this revision. Preparation freezes source, images, schedules, and commands without model calls:

cp experiments/development.template.json /tmp/silq-development.json
uv run python scripts/experiments.py prepare /tmp/silq-development.json --output .private/experiment-new
uv run python scripts/experiments.py status .private/experiment-new/experiment.json

To launch development model sessions, resume supervision, and review a closed run:

uv run python scripts/experiments.py run .private/experiment-new/experiment.json --workers 1
uv run python scripts/experiments.py resume .private/experiment-new/experiment.json --workers 1
uv run python scripts/audit_run.py .private/run-name

Workers survive supervisor exit. Locks and saved launch intents prevent duplicate Inspect launches. Failures stop queued launches; ambiguous exits require review. resume resumes supervision, not an interrupted Inspect conversation. Client notes, code, and request history persist in each run's workspace/. Only the service mounts state/. Keep both run directories and experiment manifests private.

Research dispatch requires fresh development, direct-play, resource, and production evidence, plus a readiness record whose experiment_sha256 binds the prepared plan. Max dispatch remains blocked until the new format has a reviewed medium-result gate. The older cohort.py and scope rules describe the closed study.

The audit wrapper checks request identity, native replay, tool history, and public observations. It reads report findings as well as exit codes. Truncated views and boundary flags need review; they do not automatically invalidate a loss. Admission requires qualitative review and evidence hashes.

Requests and recovery

The game guide documents the CLI. GET /state reads the current public frame and GET /overall reads the schedule. Mutation bodies contain exactly these fields:

Endpoint Fields
POST /start request_id, next trial
POST /act request_id, current trial, current frame, keys
POST /finish request_id, current trial, current frame

Each new mutation uses a canonical UUID. Retrying the same endpoint and body returns its stored status and response, including after restart. Reusing an ID with different content fails. The CLI saves requests before sending them; silq retry retrieves the last request's receipt.

Recovery replays the original random stream and compares every committed native frame, including private state. Changed code, data, configuration, or receipts block recovery. Only an unterminated final journal line can be removed; its bytes are retained. Historical v1 sessions require their frozen service images.

An interrupted batch returns its executed prefix. A pending key is replayed on the same stream and its output accepted at recovery time; remaining keys are not sent. Read the returned state before continuing. A start interrupted before trial creation returns an error and can be issued deliberately with a new ID.

Deadlines remain absolute across downtime. An ending observed before the deadline retains its result after restart. Infrastructure failures remain invalid. One service can own a session at a time; HTTP connections and idle waits are bounded.

Results and historical records

analysis/ contains results, reviews, engineering records, screenshots, and the original guide versions. site/ contains the report, figures, and public replays. .private/ retains logs, journals, source snapshots, schedules, and image archives. Run-specific validators live in scripts/historical/; report and replay builders live in scripts/reporting/. See the script index.

Development history, selection rationale, study resource limits, and the September 9 audit describe earlier stages. Native errata explain errors in the materials used by the agents.

To rebuild the report and check its replay viewer:

uv run --frozen --with markdown python -m scripts.reporting.build_site
uv run --frozen --with playwright python scripts/reporting/qa_site.py

uv run --frozen --with matplotlib python -m scripts.reporting.plot_max_case renders the reviewed max case studies, including exclusions.