diff --git a/.project/objectives/README.md b/.project/objectives/README.md
index 51e77d10..af813e03 100644
--- a/.project/objectives/README.md
+++ b/.project/objectives/README.md
@@ -16,9 +16,9 @@
|---|---|---|---|---|---|---|---|
| **P0** | 44 | 0 | 0 | 0 | 0 | 0 | 44 |
| **P1** | 79 | 0 | 13 | 1 | 0 | 1 | 94 |
-| **P2** | 102 | 0 | 16 | 7 | 5 | 1 | 131 |
+| **P2** | 102 | 0 | 17 | 6 | 5 | 1 | 131 |
| **P3 (oos)** | 22 | 0 | 2 | 0 | 0 | 29 | 53 |
-| **total** | **247** | **0** | **31** | **8** | **5** | **31** | **322** |
+| **total** | **247** | **0** | **32** | **7** | **5** | **31** | **322** |
@@ -317,7 +317,7 @@
| [p2-83](p2-83.md) | ❌ missing | Phase/round state machine + speculative parallel simulation of player-action-independent turn work | [simulator-infra](../team-leads/simulator-infra.md) | 2026-06-09 |
| [p2-84](p2-84.md) | ❌ missing | "Dev-only compute profiling — per-feature CPU/RAM/GPU cost over time, trigger-attributed, zero-cost in release" | [simulator-infra](../team-leads/simulator-infra.md) | 2026-06-09 |
| [p2-85](p2-85-poi-sprites-and-tooltips.md) | 🔴 stub | "POI sprites + hover tooltips — lairs (and resources) legible on the map" | [asset-sprite](../team-leads/asset-sprite.md) | 2026-06-18 |
-| [p2-86](p2-86-mcp-rendered-driver.md) | 🔴 stub | "Claude-player MCP — rendered driver mode (drive UI + capture screenshots)" | [simulator-infra](../team-leads/simulator-infra.md) | 2026-06-18 |
+| [p2-86](p2-86-mcp-rendered-driver.md) | 🟡 partial | "Claude-player MCP — rendered driver mode (drive UI + capture screenshots)" | [simulator-infra](../team-leads/simulator-infra.md) | 2026-06-18 |
## Out of Scope (Game 2 / Game 3)
diff --git a/.project/objectives/p2-86-mcp-rendered-driver.md b/.project/objectives/p2-86-mcp-rendered-driver.md
index f1d00f5a..278e41a7 100644
--- a/.project/objectives/p2-86-mcp-rendered-driver.md
+++ b/.project/objectives/p2-86-mcp-rendered-driver.md
@@ -2,7 +2,7 @@
id: p2-86
title: "Claude-player MCP — rendered driver mode (drive UI + capture screenshots)"
priority: p2
-status: stub
+status: partial
scope: game1
category: tooling
owner: simulator-infra
@@ -39,7 +39,48 @@ complementing the headless state API.
- [ ] Proof: from a Claude session, open `city_screen` and capture a screenshot
via the MCP tool.
+## Verified architecture (2026-06-18) + implementation plan
+
+Reverse-engineered the existing harness so the build has exact integration points:
+
+- `scripts/player-api-server.sh` spawns Godot **`--headless --rendering-method
+ gl_compatibility res://engine/scenes/headless/player_api_main.tscn`** and pipes
+ stdin/stdout JSON-Lines.
+- `player_api_main.gd` is a **state bench** (builds `GdGameState` + `GdPlayerApi`,
+ no rendered scenes). Its **stdin pump is reusable**: `_pump()` loops
+ `OS.read_string_from_stdin(4096)` yielding `await get_tree().process_frame`
+ between reads, `_handle_request()` dispatches `view`/`act`/`suggest`/`shutdown`
+ and writes one JSON line per response via `print`.
+- `tooling/claude-player-mcp/`: `index.ts` (3 tools), `harness.ts` (`HarnessClient`
+ spawns the server script, correlates responses by `id`), `types.ts`.
+
+**Phase 1 — Godot rendered driver (shell-verifiable, no MCP needed):**
+1. New launch path `scripts/player-api-render-server.sh` (or a `CP_RENDER=1` branch
+ in the existing script): launch the **real game** (`res://engine/scenes/main/main.tscn`),
+ **NOT `--headless`**, `--rendering-method gl_compatibility`, with `MC_MCP_RENDER=1`.
+2. Requires **auto-start** (the `--auto-start-game` gap): boot straight into a
+ seeded game past the menu so screenshots are meaningful. Carve this out as a
+ shared dependency (also useful for the prologue/sprite proofs).
+3. New `mcp_render_driver.gd` (autoload, active only on `MC_MCP_RENDER=1`): run the
+ same stdin-pump pattern in `_process`; handle:
+ - `screenshot` → `get_viewport().get_texture().get_image().save_png(path)` (wait
+ one frame after any scene change), respond `{ok:true, path}` (+ optional base64).
+ - `open_screen` → drive `SceneManager` / open `city_screen` / `tech_tree` / etc.
+ - reuse `act`/`view`/`end_turn` against the live game where applicable.
+4. **Verify Phase 1 by piping raw JSON-Lines** to the script (no MCP): send
+ `{"type":"open_screen","screen":"city"}` then `{"type":"screenshot"}`, assert a
+ non-empty PNG of the real screen is produced.
+
+**Phase 2 — MCP wiring (needs restart to verify):**
+5. `index.ts`: add `magic_civ_screenshot`, `magic_civ_open_screen(screen)` tools;
+ `harness.ts`: add `screenshot()`/`openScreen()` methods (same `id` correlation).
+6. `npm install` (never run — p2-67 phase 13) + build; add the `magic-civ` entry to
+ `.mcp.json`; **restart Claude** to surface the tools; drive `open_screen("city")`
+ + `screenshot` from a session as the acceptance proof.
+
## Notes
- Rendered mode needs a display/GPU surface — ties to the CPU/GPU cloud node
- story (`MAGIC_CIV_CLOUD_HANDOFF.md`). Headless state mode (p2-67) is unchanged.
+ story (`MAGIC_CIV_CLOUD_HANDOFF.md`); plum windowed works. Headless state mode
+ (p2-67) is unchanged.
+- Auto-start (step 2) is a shared prerequisite worth its own small objective.
diff --git a/public/games/age-of-dwarves/data/objectives.json b/public/games/age-of-dwarves/data/objectives.json
index cfe38ddd..f4b1de3e 100644
--- a/public/games/age-of-dwarves/data/objectives.json
+++ b/public/games/age-of-dwarves/data/objectives.json
@@ -1,12 +1,12 @@
{
- "generated_at": "2026-06-19T00:49:07Z",
+ "generated_at": "2026-06-19T00:56:27Z",
"totals": {
- "partial": 31,
- "stub": 8,
+ "done": 247,
"missing": 5,
"oos": 31,
- "done": 247,
"in_progress": 0,
+ "stub": 7,
+ "partial": 32,
"total": 322
},
"objectives": [
@@ -2694,7 +2694,7 @@
"id": "p2-86",
"title": "\"Claude-player MCP — rendered driver mode (drive UI + capture screenshots)\"",
"priority": "p2",
- "status": "stub",
+ "status": "partial",
"scope": "game1",
"owner": "simulator-infra",
"updated_at": "2026-06-18",
|