# NEX2 (Nex-N2-mini) — live fleet bench + teamwork games (B70 Turbo)

Model: **NEX2 / Nex-N2-mini** (arch `qwen3_5_moe`, 35B/~3B active), **Q5_K_M**, llama.cpp SYCL on a single
**Intel Arc Pro B70** (30.3 GiB), `llama-server`. Ship config `-ngl 99 -fa on -ctk/-ctv q8_0 -b 8192
-ub 4096`, `GGML_SYCL_DISABLE_DNN=1`, `--jinja`. Served on **:8092** (prod `:8090` untouched).

Run date 2026-06-29 (UTC). Artifacts under `results/live_evals/nex2/`.

## 1. Live agent-fleet bench, `-np 32 -c 131072` (real concurrent requests, :8092)

Real OpenAI-API requests fired simultaneously through the live server (`concurrent_agents.py`).
Aggregate decode = sum(generated tokens) / batch wall-clock; per-agent = mean server-side decode t/s.

| class | prompt_n | agents | aggregate decode t/s | per-agent t/s |
|---|---:|---:|---:|---:|
| tool | 124 | 1  | 62.67  | 82.27 |
| tool | 124 | 8  | 142.34 | 19.78 |
| tool | 124 | 16 | 162.99 | 11.21 |
| **tool** | 124 | **32** | **224.28** | 7.86 |
| structured | 442 | 32 | 165.26 | 6.56 |
| novel | 774 | 32 | 81.88 | 5.46 |

**Headline:** at 32 concurrent agents NEX2 sustains ~165–224 t/s aggregate decode on the tool/structured
classes (vs ~63 agg / 82 per-agent single-agent). The `novel×32` aggregate (81.9) is low **not** because
of throughput but because the model emitted **short completions** there (~75 tok/agent vs the 256 cap) —
per-agent decode (5.46) is in line with the others. NEX2's curve is otherwise indistinguishable from
AgentWorld/Ornith (identical arch + quant + serve).

## 2. Teamwork build games (frogger + maze)

Canonical `agentic-arcade/teamwork` harness on `:8092`, **team 6 / merge-top 2 / 15-min**, thinking OFF,
served `-np 6 -c 262144`. (Rounds are atomic, so a slow round overruns the budget; NEX2's rounds were
long — frogger 1,211 s, maze 2,364 s — so each game fit exactly **1 team round**.)

| game | rounds | winner | seed→final bytes | jsdom valid | notes |
|---|---:|---|---|:--:|---|
| **frogger** | 1 | worker | 23,132 → 28,146 | ✅ | clean seed first try; 6/6 workers valid |
| **maze** | 1 | merged | 22,902 → 30,749 | ✅ | reseed ×1 to a clean seed, then 6/6 workers valid; merger won |

## 3. Code-quality eval (Claude Opus 4.8 judge, /50 rubric)

Each dimension /10: **Completeness · Correctness · Structure · Robustness · Polish.**

| game | chars | **/50** | Comp | Corr | Struct | Robust | Polish |
|---|---:|---:|:--:|:--:|:--:|:--:|:--:|
| **Frogger** | 28,146 | **37** | 9 | 6 | 9 | 6 | 7 |
| **Maze** | 30,749 | **31** | 8 | 3 | 8 | 4 | 8 |

### Frogger — 37/50

Clean IIFE build, `getContext('2d')` correct, data-driven `levels[]`, smooth eased tile-to-tile movement,
mobile touch D-pad, rounded-rect sprites (cars with windows/wheels, floats, detailed frog), responsive
canvas scaling, menu/victory/game-over cards. **It is winnable** — reaching the top row scores +1000 and
calls `startNextLevel()`, and clearing both levels triggers a real Victory screen (lines 710–713 →
`startNextLevel` → VICTORY). This is the key improvement over Ornith's frogger (which was unwinnable).

Bugs found by source review:
- **The river has no drowning.** `checkCollisions()` (lines 645–682) carries the frog if it overlaps a
  float, and otherwise only checks vehicles — there is **no "in water, not on a float → die"** branch. On
  the river level you can walk straight across open water to the goal; the floats are decorative, so the
  river's signature risk/reward is absent.
- **Dead progress-scoring code.** `getTile()` always returns `progress: 0`, so the `tile.progress` scoring
  block (line 700) never runs.
- **Per-frame HUD DOM thrash.** `updateHUD()` removes and recreates the HUD `<div>` every frame — works,
  but wasteful.
- No audio/SFX.

Winnable + clean structure (Corr 6 / Struct 9), docked for the toothless river and missing audio.

### Maze — 31/50

The most *ambitious and polished* build in the campaign so far: a carved-corridor maze generator, **four
robot archetypes** (standard/shield/fast/turret with distinct hp/speed/fire/AI), health/ammo/score
pickups, an ammo system, escalating waves, screen shake + damage flash, an animated rotating exit, glowing
pulsing pickups, radial-gradient bullets, and **eight distinct Web Audio SFX** (incl. procedural noise).
`getContext('2d')` correct, validates clean (7/7 assertions, no JS errors).

**But the entire shooter core is dead — one missing field breaks three things:**

- **Robot instances never get a radius.** `ROBOT_TYPES` defines `radius` per type (lines 120–150), but
  `loadRoom` builds each robot **without copying it** (line 389 maps `{type,x,y,…}` — no `r`). So `robot.r`
  is `undefined` everywhere, and three systems silently break:
  1. **Robots are invisible.** `drawRobotBody` does `const r = robot.r` (line 908) → every draw coord is
     `NaN` → nothing renders. The elaborate 4-type robot art never shows.
  2. **You can't shoot them.** Bullet→robot test `dist(b, robot) < b.r + robot.r` (line 569) → `+undefined`
     = `NaN` → always false. Player bullets pass through.
  3. **They can't touch you.** Robot→player test `dist(player, r) < player.r + r.r` (line 677) → `NaN` →
     always false.
- **No bullet→player collision exists at all.** Robot-fired bullets are only tested against walls and
  robots — never the player — so even the robots' shooting is harmless.

Net: a beautiful maze where you collect pickups and walk to the exit past invisible, inert ghosts. Every
*peripheral* system works and looks great (Polish 8), but for a "Robot-Filled Maze **Shooter**" the
shooting, the enemies, and the danger are all gone → Correctness 3.

### Cross-model pattern (NEX2 + Ornith)

Both qwen3_5_moe models hit the **same maze failure class**: a radius/size is defined on the entity *type*
but **never assigned to the entity instance**, so radius-based collisions evaluate to `NaN` and the core
shoot/avoid loop dies — while the game still loads cleanly and passes the static assertion gate. NEX2's
variant is worse (robots also fail to render). The teamwork harness keeps builds *runnable*; it does not
catch **semantic** logic gaps, because the validator asks "does it load without JS errors," not "does the
core verb fire." Both NEX2 games still land below AgentWorld-35B's teamwork games (41–42/50).

## Reproduce
```bash
bash /home/frosty40/qworld_turbo/bench/run_live_evals.sh \
  /home/frosty40/models/nex-n2-mini/sweep/NX2-Q5_K_M.gguf nex2 nex2 8092
```
