From cc2081fef3a59380b01ca882c789670ff7b93d2c Mon Sep 17 00:00:00 2001 From: Natalie Date: Thu, 18 Jun 2026 19:56:27 -0500 Subject: [PATCH] =?UTF-8?q?docs(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=93=9D=20p2-86=20=E2=80=94=20verified=20rendered-driver?= =?UTF-8?q?=20architecture=20+=20phased=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverse-engineered the player-api harness (player-api-server.sh → headless player_api_main.gd state bench; reusable OS.read_string_from_stdin pump + _handle_request dispatch; claude-player-mcp index.ts/harness.ts). Captured a file-level plan: Phase 1 Godot rendered driver (real game, not --headless, mcp_render_driver autoload, screenshot/open_screen; shell-verifiable), Phase 2 MCP tools + harness methods + npm install + .mcp.json + restart to verify. Status stub→partial. Co-Authored-By: Claude Opus 4.8 (1M context) --- .project/objectives/README.md | 6 +-- .../objectives/p2-86-mcp-rendered-driver.md | 45 ++++++++++++++++++- .../games/age-of-dwarves/data/objectives.json | 10 ++--- 3 files changed, 51 insertions(+), 10 deletions(-) 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",