# Challenge Nightmare with your AI

Your solver runs on YOUR computer. A Grok/Claude/ChatGPT reply or social-media
mention is not a connected agent. You or an authorized runtime must execute the
client and make authenticated requests. Names are self-reported, never verified
provider identities. No model service or paid API is needed for these examples.

## 1. Access and availability

Open `/benchmarks/challenge`, sign in using an existing LinesClash account, then
create a developer key. Copy it once into your local environment, never into
source code, screenshots or URLs. Keep the same key for reconnects. Revoke it on
that page when finished. Keys only authorize benchmark play, not account actions.

Public admissions may be paused. HTTP 503 is not permission to bypass the gate.
Nightmare/Experimental and candidate V3 are separately gated for server capacity.
The first release can publish pages without opening any searches. For LOCAL
testing use the repository server on port 3199 with isolated SQLite, storage and
API enabled. Only enable HEAVY locally when testing Nightmare. Existing human
sessions always retain V1/V2. Do not point local tests at production.

### Exact local server setup (repository checkout only)

Use a fresh PowerShell terminal in the repo. These are LOCAL test secrets and a
separate SQLite file. Never replace production secrets or configuration with them.

```powershell
New-Item -ItemType Directory -Force .data | Out-Null
$env:NODE_ENV='development'
$env:HOST='127.0.0.1'; $env:PORT='3199'
$env:NEXT_DIST_DIR='.next-benchmark-quickstart'
$env:DATABASE_PROVIDER='libsql'
$env:TURSO_DATABASE_URL='file:.data/benchmark-quickstart.db'
$env:TURSO_AUTH_TOKEN=''
$env:REALTIME_STATE='memory'; $env:EXPECTED_MAX_REPLICAS='1'
$env:APP_ORIGIN='http://127.0.0.1:3199'
$env:AUTH_URL=$env:APP_ORIGIN; $env:ALLOWED_ORIGINS=$env:APP_ORIGIN
$env:ADMIN_ORIGIN=''; $env:CANONICAL_READY='false'
$env:SESSION_SECRET='local-only-guest-secret-at-least-32-characters'
$env:AUTH_SECRET='local-only-auth-secret-at-least-32-characters'
$env:BENCHMARK_STORAGE_ENABLED='true'; $env:BENCHMARK_API_ENABLED='true'
$env:BENCHMARK_HEAVY_ENABLED='true'; $env:BENCHMARK_V3_ENABLED='false'
npm ci
npm run dev
```

Open http://127.0.0.1:3199/benchmarks/challenge, register/sign in and create a key.
Run the client in a SECOND terminal, with BASE=http://127.0.0.1:3199. No human AI
duel can be active when the benchmark starts. These are local integration results,
not published public standings. Heavy enabled locally is not a recommendation to
enable it on Azure. Production admission/heavy/V3 flags remain false.

## 2. Python: create and finish a full match

Download client.py beside this file. Python 3.10+, no pip installs required.
PowerShell (replace the key locally, do not paste it into public chat):

```powershell
$env:LINESCLASH_BASE='https://linesclash.com'
$env:LINESCLASH_KEY='YOUR_SCOPED_KEY'
python client.py --state my-match.json --opponent hell_v2 --name 'My solver' --control production
```

For a local server set BASE to `http://127.0.0.1:3199`. Use `--opponent casual`
for a lightweight integration check. Keep --state to reconnect: rerun the SAME
command. It records creation requestId, matchId and the pending move UUID before
sending; no key is stored. A new match requires a different state file. If a match
was created in the UI, set MATCH_ID before the first run instead. The completed
client prints authoritative scores, verified status and a public replay URL.

The example deliberately chooses the first legal cell. Replace choose(obs) with
your solver. This is a legal integration baseline, not a competitive AI.

## 3. TypeScript: same protocol, independent transport

Download client.ts. Node 22.18+ runs it directly, without npm packages:

```powershell
$env:LINESCLASH_BASE='https://linesclash.com'
$env:LINESCLASH_KEY='YOUR_SCOPED_KEY'
$env:LINESCLASH_STATE='my-ts-match.json'
$env:LINESCLASH_OPPONENT='hell_v2'
$env:LINESCLASH_NAME='My TypeScript solver'
node client.ts
```

Optional LINESCLASH_SEAT=0 or 1, LINESCLASH_CONTROL=production or untimed, MATCH_ID
for an existing match. Replace choose(). The same state file resumes after a
restart. Python and TypeScript state formats are compatible, but run only ONE
client against a match at a time. Never share developer keys with other players.

## 4. C++: compile your solver; Python supplies HTTPS and reconnects

Download solver.cpp and client.py. Compile with any C++17 compiler:

```text
c++ -std=c++17 -O2 solver.cpp -o solver
```

On Windows use your compiler's equivalent to produce solver.exe, then:

```powershell
$env:LINESCLASH_SOLVER=(Resolve-Path './solver.exe').Path
python client.py --state my-cpp-match.json --opponent hell_v2 --name 'My C++ solver'
```

The local executable receives BOARD_81_DOT_X_O, X_or_O, searchSeconds as argv and
returns ONE JSON object `{"row":4,"col":4}` on stdout. Diagnostics go to stderr.
The bridge uses no shell, retains TLS verification and never uploads executable
code. It allocates up to 5 seconds (less near the turn deadline), then a 1-second
exit allowance. Only run trusted local programs; this is not an OS sandbox.
Replace the baseline algorithm. For a longer solver budget adapt choose() while
leaving margin for process startup, network and the 30-second agent clock.

## 5. Board, clocks and failure handling

GET /api/benchmarks/matches/ID with Authorization: Bearer KEY returns the board,
scores, legalMoves, revision, history, remainingMs, aiPolicy, status and serverTime.
Nine rows/columns; row/col are ZERO-based 0..8; board is row-major; -1 empty, 0 X,
1 O. Seat 0 starts. All 81 legal placements must complete before a verified result.
Rules and scoring: `/benchmarks/protocol`. Download observation-example.json.

- status=agent: choose a legal cell; POST /matches/ID/moves with current revision,
  UUID moveId, row and col. Never send scores, winners, transcripts or policies.
- status=ai: poll no faster than every 2 seconds. Hell uses its original search
  budget, up to 9 seconds; it does not receive a weakened benchmark policy.
- Production gives YOUR turn 30 seconds of wall time, including solver/network.
  Untimed removes that agent clock only; every match expires after one hour.
- HTTP 409 on a move: discard pending, GET current state, choose again.
- Lost acknowledgement/disconnect: retry the IDENTICAL moveId and payload.
  Creation also retries the identical saved requestId. Changed duplicate IDs fail.
- HTTP 429/503: honor Retry-After. Backoff can outlast a timed turn; expiry is an
  honest unfinished match, never a fabricated win. Check admission before starting.
- HTTP 400: fix your request. 401: key expired/revoked; sign in and manage keys.
  403: wrong Origin. 404: wrong owner/match or retained evidence expired.
- completed/expired/failed are terminal. Only completed + verified=true enters
  public standings; expired/failed/abandoned matches do not award wins.
- Ctrl+C stops the local client. Rerun with the same state file to reconnect, or
  POST /matches/ID/abandon with {} to release your active slot.

Developer tokens must stay at the configured origin. Examples refuse redirects.
Public replays expose legal history and scores, no key or private engine state.
Paired seat-swapped runs are fairer comparisons. External identity, CPU budget and
use of outside assistance cannot be attested by this protocol.

## Copyable agent integration prompt

Implement choose(observation) for LinesClash using only the public JSON board,
legalMoves, seat, history, scores and remainingMs. Read /benchmarks/protocol for
the exact scoring rules. Return a legal zero-based {row,col}; do not submit a
winner, score, transcript or policy override. Keep the developer key secret at
the configured HTTPS origin. Preserve pending UUID/payload and create requestId
on reconnect; reconcile 409; honor Retry-After on 429/503. Poll ai at >=2 seconds.
Use less than remainingMs including network margin. Finish all 81 moves and
report the authoritative verified result and replay URL. Run the actual client;
do not claim that a conversational answer or invented transcript played a match.
