Skip to content

[macos] Add provider contract smoke adapter for Codex/OpenClaw commands #95

Description

@100yenadmin

Parent epic: #82
Sprint: v0.3 Sprint 1 - App, Combat, Deterministic Gates

Summary

Add a deterministic provider-contract smoke adapter that proves the native macOS app can launch configured Codex/OpenClaw provider commands, pass the expected ClawDnD environment, capture logs, and fail closed without running a live narrative session.

Architecture invariant

The native app is an orchestrator/read surface. Provider commands must not write campaign snapshots, play-state, qa/state, or engine data directly. The only write this smoke adapter may perform is to a caller-provided temporary CLAWDND_PLAYER_MOVES JSONL file, using the same constrained move-intent shape the viewer already appends.

Code map

  • scripts/provider_contract_smoke.sh: new deterministic command launched by the app or manually.
  • macos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift: no behavior change required, but this script should be usable as the configured Codex/OpenClaw command.
  • macos/ClawDnDApp/Sources/ClawDnDApp/Views/ProvidersView.swift: optional help text can suggest the smoke command.
  • viewer/server.py: source of the /move contract and sanitizer; do not bypass it for real play.

Required environment contract

The smoke command must read and validate:

  • CLAWDND_PROVIDER
  • CLAWDND_WORLD
  • CLAWDND_RUN_ID
  • CLAWDND_PLAY_PORT
  • CLAWDND_PLAY_COMPANIONS
  • CLAWDND_PLAYER_MOVES for smoke mode only

It should reject unknown providers and missing/invalid paths with non-zero exit and clear stderr.

Minimal behavior

When CLAWDND_PLAYER_MOVES is set to a safe path under a temp directory, append one harmless move intent such as:

{"kind":"continue","text":"provider contract smoke"}

Then print a redacted JSON summary of provider, world, run id, port, companion count, and move path. Never print secrets or full process environment.

Acceptance criteria

  • Running the script without required env fails with actionable messages.
  • Running with temp env appends exactly one valid JSONL move.
  • The script can be used as the configured Codex and OpenClaw command in the native app.
  • No live Claude/Codex/OpenClaw narrative session is started.
  • No campaign snapshot is mutated.

Focused validation

cd /Volumes/LEXAR/repos/ClawDnD
bash -n scripts/provider_contract_smoke.sh
TMPDIR=$(mktemp -d)
CLAWDND_PROVIDER=codex \
CLAWDND_WORLD=baldurs-gate \
CLAWDND_RUN_ID=smoke \
CLAWDND_PLAY_PORT=8765 \
CLAWDND_PLAY_COMPANIONS='' \
CLAWDND_PLAYER_MOVES="$TMPDIR/moves.jsonl" \
  scripts/provider_contract_smoke.sh
jq -e 'select(.kind == "continue")' "$TMPDIR/moves.jsonl"

Original-agent handoff

Inspect these first:

  • macos/ClawDnDApp/Sources/ClawDnDApp/Services/ProviderAdapters.swift
  • macos/ClawDnDApp/Sources/ClawDnDApp/Services/AppProcessService.swift
  • viewer/server.py sanitize_move and /move

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttier-1Tier 1: Claude Code plugin

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions