fix(@projects/@magic-civilization): 🐛 update claude-player-api demo stop criteria

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-11 09:57:11 -07:00
parent f948d2968e
commit 3ef338725e

View file

@ -639,11 +639,41 @@ that cite the precise schema mismatch blocking them.
- `src/simulator/api-gdext/src/lib.rs``GdGameState::init`
updated for new `trade_ledger` field.
## 2026-05-12 — Phase 13 STOP (demo would surface degenerate AI; render path absent)
## 2026-05-12 — Phase 13 STOP (render bridge from GdPlayerApi state does not exist)
Per brief hard-stop rule: "Claude-vs-AI demo produces no AI activity in
any 5-turn block → STOP, document, exit (signals a regression somewhere
in the AI driver)."
Two independent hard-stop conditions. Leading with the structural one
because it doesn't depend on any AI-behaviour debate.
### Primary blocker — render path
Phase 13 requires "Capture screenshots every 5 turns". The current
headless harness (`claude_player_main.gd`) is JSON-Lines only — no
scene tree, no TileMap, no camera. Production proof scenes
(`gameplay_arc_proof.tscn`, `world_map.tscn`, etc.) render from the
`GameState` autoload, not from a `GdPlayerApi`-held state. There is
NO path today that takes the JSON state held by
`GdPlayerApi.load_state_json` and renders it visually.
Wiring this requires either:
1. **Render bridge** — extract the proof-scene rendering pipeline into
a function that takes a `GdGameState` instance (not the
autoload), so the harness can pass its bootstrapped + ticked state
for capture.
2. **Two-process orchestration** — one process drives the JSON pump,
another reads its events and replays them into a renderable scene
on the side.
Either is its own objective with its own surface area. Neither was
specced in p2-67 Phase 0-9 because Phase 13 was scoped as "use the
existing render path" without verifying one existed for this state
shape.
### Secondary blocker — degenerate AI behaviour
Per brief hard-stop rule: "Claude-vs-AI demo produces no AI activity
in any 5-turn block → STOP, document, exit (signals a regression
somewhere in the AI driver)."
### Evidence
@ -658,31 +688,10 @@ turn 4 → slot 1 actions_applied=0, slot 2 actions_applied=0
```
A 25-turn run would produce identical zero-activity blocks for turns
5-9, 10-14, 15-19, 20-24. The hard-stop fires multiple times. Driving
the demo would produce a video of Claude playing solitaire while the
AI sits motionless — not the "Claude vs production AI" promise.
### Independent blocker — render path
Phase 13 also requires "Capture screenshots every 5 turns". The
current headless harness (`claude_player_main.gd`) is JSON-Lines only
— no scene tree, no TileMap, no camera. Production proof scenes
(`gameplay_arc_proof.tscn` etc.) render from `GameState` autoload,
not from a `GdPlayerApi`-held state. There is no path today that
takes the JSON state held by `GdPlayerApi.load_state_json` and renders
it visually.
Wiring this requires either:
1. **Render bridge** — extract the proof-scene rendering pipeline into
a function that takes a `GdGameState` instance (not the
autoload), so the harness can pass its bootstrapped + ticked state
for capture.
2. **Two-process orchestration** — one process drives the JSON pump,
another reads its events and replays them into a renderable scene
on the side.
Either is its own objective with its own surface area.
5-9, 10-14, 15-19, 20-24. The hard-stop fires multiple times. Even
with the render bridge in place, the resulting video would be Claude
playing solitaire while the AI sits motionless — not the "Claude vs
production AI" promise.
### What WAS validated this session
@ -725,6 +734,21 @@ with a parallel observation store in mc-player-api)."
"is tile (col, row) visible to player P at the current turn?" so the
projector can mark each `TileView` as visible / fogged / hidden.
### What's actually missing
**Not** "ObservationStore is the wrong shape" — `ObservationStore` is
fine as a *query surface*: `get_turn(turn).tile_indices.contains(idx)`
answers "was tile X visible to player P at turn T", which is exactly
what a fog projector needs for "Visible / Fogged / Hidden" classification.
What's **missing** is the Rust-side visibility *producer*. Today
`record_turn(turn, grid, visible_tile_indices: &[u16])` takes
pre-computed visibility — the caller (presumably GDScript `Vision.gd`
or an equivalent Rust port that hasn't been ported yet) owns the
"compute which tiles are visible to player P right now" calculation.
There is no `mc-observation` API that takes `(GameState, PlayerId)`
and returns a visible-tile set.
### What `ObservationStore` actually is
A per-player CLIMATE / WEATHER observation history for the Chronicle