Parent epic: #82
Depends on: #95
Sprint: v0.3 Sprint 1 - App, Combat, Deterministic Gates
Summary
Add a checked-in Codex provider wrapper that the native app can launch as a configured Codex command. The wrapper should let Codex act only through the constrained ClawDnD player facade and existing move/state contracts, not as a second game-state writer.
Architecture invariant
Codex may reason about a turn, but it must not mutate snapshot.json, engine store files, QA state, world content, skills, prompts, or DM/canon content. It should communicate through the same player-facing action contract used by dashboard moves and servers/engine/player_server.py.
Proposed architecture
Create scripts/play_codex_actor.sh as a small supervisor wrapper:
- Validate repo root and required env from the native app:
CLAWDND_PROVIDER=codex, CLAWDND_WORLD, CLAWDND_RUN_ID, CLAWDND_PLAY_PORT, and budget caps.
- Create an isolated run directory under
play-state/<run-id>/codex-provider/ or a temp state root for smoke mode.
- Generate a Codex MCP config that exposes the player facade only, likely
servers/engine/player_server.py, with actor identity and move sink set through env.
- Run
codex exec non-interactively with a tightly scoped prompt that produces legal player moves only.
- Capture stdout/stderr into provider logs that the native app already tails.
The first PR may ship a dry-run/smoke mode before allowing real turn execution.
Code map
scripts/play_codex_actor.sh: new wrapper.
servers/engine/player_server.py: constrained action facade to reuse; add tests only if the contract needs hardening.
servers/engine/tests/test_player_facade.py
servers/engine/tests/test_player_facade_actor.py
macos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift: set the default suggested Codex command only if it remains fail-closed and explicit.
macos/ClawDnDApp/Sources/ClawDnDApp/Views/ProvidersView.swift: display setup/status text.
Non-goals
- Do not run live story QA.
- Do not edit
skills/, content/worlds/, qa/play_*.txt, or rubrics.
- Do not let Codex call engine writer tools directly.
- Do not make Codex the DM.
Acceptance criteria
- Native app can detect Codex and show a configured command path.
- Wrapper has a
--dry-run or --smoke mode that validates env and generated config without starting a real model session.
- Any real mode uses the player facade or move JSONL, never direct snapshot writes.
- Focused tests prove actor binding and move allowlist still hold.
- Provider logs show command, run id, port, and redacted config location.
Focused validation
cd /Volumes/LEXAR/repos/ClawDnD
bash -n scripts/play_codex_actor.sh
uv run --directory servers/engine --group dev pytest -q tests/test_player_facade.py tests/test_player_facade_actor.py
CLAWDND_PROVIDER=codex \
CLAWDND_WORLD=baldurs-gate \
CLAWDND_RUN_ID=codex-smoke \
CLAWDND_PLAY_PORT=8765 \
scripts/play_codex_actor.sh --dry-run
Original-agent handoff
Inspect these first:
servers/engine/player_server.py
scripts/play.sh
scripts/play_party.sh
macos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift
Parent epic: #82
Depends on: #95
Sprint: v0.3 Sprint 1 - App, Combat, Deterministic Gates
Summary
Add a checked-in Codex provider wrapper that the native app can launch as a configured Codex command. The wrapper should let Codex act only through the constrained ClawDnD player facade and existing move/state contracts, not as a second game-state writer.
Architecture invariant
Codex may reason about a turn, but it must not mutate
snapshot.json, engine store files, QA state, world content, skills, prompts, or DM/canon content. It should communicate through the same player-facing action contract used by dashboard moves andservers/engine/player_server.py.Proposed architecture
Create
scripts/play_codex_actor.shas a small supervisor wrapper:CLAWDND_PROVIDER=codex,CLAWDND_WORLD,CLAWDND_RUN_ID,CLAWDND_PLAY_PORT, and budget caps.play-state/<run-id>/codex-provider/or a temp state root for smoke mode.servers/engine/player_server.py, with actor identity and move sink set through env.codex execnon-interactively with a tightly scoped prompt that produces legal player moves only.The first PR may ship a dry-run/smoke mode before allowing real turn execution.
Code map
scripts/play_codex_actor.sh: new wrapper.servers/engine/player_server.py: constrained action facade to reuse; add tests only if the contract needs hardening.servers/engine/tests/test_player_facade.pyservers/engine/tests/test_player_facade_actor.pymacos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift: set the default suggested Codex command only if it remains fail-closed and explicit.macos/ClawDnDApp/Sources/ClawDnDApp/Views/ProvidersView.swift: display setup/status text.Non-goals
skills/,content/worlds/,qa/play_*.txt, or rubrics.Acceptance criteria
--dry-runor--smokemode that validates env and generated config without starting a real model session.Focused validation
cd /Volumes/LEXAR/repos/ClawDnD bash -n scripts/play_codex_actor.sh uv run --directory servers/engine --group dev pytest -q tests/test_player_facade.py tests/test_player_facade_actor.py CLAWDND_PROVIDER=codex \ CLAWDND_WORLD=baldurs-gate \ CLAWDND_RUN_ID=codex-smoke \ CLAWDND_PLAY_PORT=8765 \ scripts/play_codex_actor.sh --dry-runOriginal-agent handoff
Inspect these first:
servers/engine/player_server.pyscripts/play.shscripts/play_party.shmacos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift