Skip to content

fix(ai): halt empty NamedChoice escape and refuse DB-less restore (#6393) - #6741

Merged
matthewevans merged 3 commits into
phase-rs:mainfrom
claytonlin1110:fix/6393-ai-controller-stuck
Jul 29, 2026
Merged

fix(ai): halt empty NamedChoice escape and refuse DB-less restore (#6393)#6741
matthewevans merged 3 commits into
phase-rs:mainfrom
claytonlin1110:fix/6393-ai-controller-stuck

Conversation

@claytonlin1110

@claytonlin1110 claytonlin1110 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • NamedChoice AI fallback_action now picks a legal ChooseOption from legal_actions (fixes CardName prompts with empty options after restore when all_card_names is populated).
  • AI controller escape never fabricates PassPriority for non-Priority waits — empty legal set notifies ai-controller-stuck:<type> and stops immediately.
  • restoreState hard-fails if the card DB failed to load, so we never soft-restore into a CardName softlock without rehydrate.

Closes #6393

Test plan

  • cargo test -p phase-ai --lib named_choice_card_name_fallback
  • Vitest: aiController.test.ts + wasm-adapter.test.ts (51 passed)
  • Manual: restore a mid-game save with an AI NamedChoice (CardName) and confirm either a legal guess advances or restore fails cleanly if the card DB is unavailable

Validation Failures

  • Isolated /review-impl subagent unavailable (API/model routing); Bugbot found no bugs. Plan was CLEAN before implement.

Summary by CodeRabbit

  • New Features
    • Added an engine-provided, deadlock-safe AI fallback action for stalled decision moments, available to both the engine worker and the WASM fallback.
  • Bug Fixes
    • State restoration and multiplayer resume now fail fast with a clear error when the card database can’t be loaded.
    • Improved AI controller escape handling: it no longer fabricates actions for non-priority waits, and it cleanly halts with a clear “engine lost” notification when no valid escape exists.
    • Fixed card-name choice fallback after rehydration by deriving options from current legal actions (and returning none when no legal choices exist).
  • Tests
    • Added/updated regression coverage for fallback, halt, and card-database failure paths.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c69cc7e9-ea85-45e4-a7a7-f3d28cac8d75

📥 Commits

Reviewing files that changed from the base of the PR and between 7fb505d and d17b508.

⛔ Files ignored due to path filters (1)
  • client/src/wasm/engine_wasm.d.ts is excluded by !client/src/wasm/**, !**/*.d.ts
📒 Files selected for processing (10)
  • client/src/adapter/__tests__/wasm-adapter.test.ts
  • client/src/adapter/engine-worker-client.ts
  • client/src/adapter/engine-worker.ts
  • client/src/adapter/types.ts
  • client/src/adapter/wasm-adapter.ts
  • client/src/game/controllers/__tests__/aiController.test.ts
  • client/src/game/controllers/aiController.ts
  • crates/engine-wasm/src/lib.rs
  • crates/phase-ai/src/lib.rs
  • crates/phase-ai/src/search.rs
🚧 Files skipped from review as they are similar to previous changes (9)
  • crates/phase-ai/src/lib.rs
  • client/src/game/controllers/aiController.ts
  • client/src/adapter/engine-worker-client.ts
  • client/src/adapter/engine-worker.ts
  • crates/engine-wasm/src/lib.rs
  • crates/phase-ai/src/search.rs
  • client/src/adapter/tests/wasm-adapter.test.ts
  • client/src/adapter/wasm-adapter.ts
  • client/src/game/controllers/tests/aiController.test.ts

📝 Walkthrough

Walkthrough

The adapter now requires a loaded card database before restoration operations. Engine-owned AI fallback actions are exposed through WASM and worker adapters, while the controller halts safely when no escape action exists.

Changes

AI fallback and controller safety

Layer / File(s) Summary
Compute legal engine fallback actions
crates/phase-ai/src/search.rs, crates/phase-ai/src/lib.rs, crates/engine-wasm/src/lib.rs
NamedChoice fallback actions are selected from engine-legal actions, return null when unavailable, and are exposed through WASM.
Transport fallback actions and halt safely
client/src/adapter/types.ts, client/src/adapter/wasm-adapter.ts, client/src/adapter/engine-worker.ts, client/src/adapter/engine-worker-client.ts, client/src/game/controllers/*
Fallback actions flow through worker and main-thread adapters; non-Priority controller paths avoid fabricated actions and stop when no escape exists, with regression coverage.

Card database restoration

Layer / File(s) Summary
Require card database for restoration
client/src/adapter/wasm-adapter.ts, client/src/adapter/__tests__/wasm-adapter.test.ts
Restore, multiplayer resume, and database warming now require a loaded card database; failure tests verify worker operations are skipped.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: bug

Suggested reviewers: matthewevans, lgray

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing empty NamedChoice escape handling and hard-failing DB-less restore for #6393.
Linked Issues check ✅ Passed The changes address the reported relaunch stall by handling empty or invalid escapes and preventing restore when the card database is unavailable.
Out of Scope Changes check ✅ Passed The modified client, adapter, WASM, and phase-ai code all support the stuck-AI relaunch fix and do not show unrelated scope creep.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/adapter/wasm-adapter.ts`:
- Around line 590-596: Factor the card-database load validation currently in the
guard around cardDbLoaded into a shared helper, then invoke it from both the
existing restoration method and resumeMultiplayerHostState before rehydration or
state resume proceeds. Ensure either failed load path throws instead of
continuing with DB-less state, and add regression coverage proving
resumeMultiplayerHostState rejects a failed card database load.

In `@client/src/game/controllers/aiController.ts`:
- Around line 282-303: Remove client-side selection of result.actions[0] from
the non-Priority path in the controller method containing the
adapter.getLegalActions() call. Add or use an adapter API that returns the
engine-selected fallback action, then dispatch that action when available and
return null otherwise; retain the existing Priority handling and pending-cast
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5a740f69-2c22-46e9-b5a8-e4d9f46e2c96

📥 Commits

Reviewing files that changed from the base of the PR and between 6e0ecd1 and 5970c2b.

📒 Files selected for processing (5)
  • client/src/adapter/__tests__/wasm-adapter.test.ts
  • client/src/adapter/wasm-adapter.ts
  • client/src/game/controllers/__tests__/aiController.test.ts
  • client/src/game/controllers/aiController.ts
  • crates/phase-ai/src/search.rs

Comment thread client/src/adapter/wasm-adapter.ts
Comment thread client/src/game/controllers/aiController.ts Outdated

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required changes

[HIGH] Guard P2P host resume against a failed card-database load. Evidence: client/src/adapter/wasm-adapter.ts:662-668 deliberately swallows loadCardDbFromUrl() failures and then calls resumeMultiplayerHostState; client/src/adapter/p2p-adapter.ts:1171-1172 reaches that path for a resumed host; and crates/engine-wasm/src/lib.rs:1658-1662 rehydrates only when CARD_DB is present. Why it matters: a persisted host can resume with definitions absent, reintroducing the DB-less restored-state failure this PR fixes for the ordinary restore path. Suggested fix: factor the successful-load requirement into one shared restore/resume DB guard, use it before both rehydration paths, and add a regression proving a failed DB load rejects P2P host resume without invoking the engine resume call.

[HIGH] Keep non-Priority escape-action selection engine-owned. Evidence: client/src/game/controllers/aiController.ts:296-304 selects result.actions[0] for every non-Priority wait, while the selected-AI action seam is the adapter/WASM getAiAction path at client/src/adapter/wasm-adapter.ts:428-433. Why it matters: legal-action ordering is not an engine decision contract, so the frontend can choose different gameplay merely because enumeration order changes. Suggested fix: expose an engine-selected nullable fallback action through the adapter/WASM boundary; for non-Priority waits, dispatch only that action or halt when it is null. Keep the existing Priority special case.

Current-head check evidence: Rust, frontend, WASM, and card-data checks succeeded. The paired-seed and decision-cost AI gates remain in progress; they are not the basis for these requested changes.

…ase-rs#6393)

CardName prompts keep options empty and synthesize from all_card_names; fallback must use legal_actions, and the client must not fabricate PassPriority (or soft-restore without a card DB) after relaunch softlocks.

Co-authored-by: Cursor <cursoragent@cursor.com>
@matthewevans matthewevans self-assigned this Jul 29, 2026
…e-rs#6393)

P2P host resume now shares restoreState's hard card-DB requirement. Non-Priority AI escape dispatches getAiFallbackAction (WASM fallback_action) instead of inventing from legal-action list order.

Co-authored-by: Cursor <cursoragent@cursor.com>
@claytonlin1110
claytonlin1110 force-pushed the fix/6393-ai-controller-stuck branch from 7fb505d to dcc929a Compare July 29, 2026 05:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/adapter/wasm-adapter.ts`:
- Around line 673-680: Update resumeMultiplayerHostState in the adapter to await
the fallback branch, ensuring MainThreadFallback.resumeMultiplayerHostState
returns its enqueue() promise typed as Promise<void> so queued WASM execution
and errors remain attached. Keep the direct engine branch behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: abfb8d2c-943f-4ec9-8798-75ff9b325093

📥 Commits

Reviewing files that changed from the base of the PR and between 5970c2b and 7fb505d.

⛔ Files ignored due to path filters (1)
  • client/src/wasm/engine_wasm.d.ts is excluded by !client/src/wasm/**, !**/*.d.ts
📒 Files selected for processing (10)
  • client/src/adapter/__tests__/wasm-adapter.test.ts
  • client/src/adapter/engine-worker-client.ts
  • client/src/adapter/engine-worker.ts
  • client/src/adapter/types.ts
  • client/src/adapter/wasm-adapter.ts
  • client/src/game/controllers/__tests__/aiController.test.ts
  • client/src/game/controllers/aiController.ts
  • crates/engine-wasm/src/lib.rs
  • crates/phase-ai/src/lib.rs
  • crates/phase-ai/src/search.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/phase-ai/src/search.rs
  • client/src/game/controllers/aiController.ts

Comment thread client/src/adapter/wasm-adapter.ts Outdated
@matthewevans

Copy link
Copy Markdown
Member

Maintainer fixup d17b5089cfd1b7ec2a4c223ed563e463f7088ecf now awaits the queued main-thread fallback resume and adds a regression that propagates its error. Current-head Rust, frontend, and AI checks are running; approval/enqueue will resume after they settle.

@matthewevans matthewevans removed their assignment Jul 29, 2026
@matthewevans matthewevans added the bug Bug fix label Jul 29, 2026
@matthewevans matthewevans self-assigned this Jul 29, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer review complete: the current head carries the fallback-resume error-propagation fix and its regression coverage. Required CI checks are green; remaining AI advisory checks may continue under merge-when-ready.

@matthewevans
matthewevans added this pull request to the merge queue Jul 29, 2026
@matthewevans

Copy link
Copy Markdown
Member

Current-head maintainer review is approved. Required Rust and frontend checks are green; the paired-seed AI and decision-cost advisory gates remain in progress. I also attempted the authorized auto-merge action, but GitHub still reports autoMergeRequest: null; this PR is held, not treated as enqueued. Resume after those gates settle and the platform accepts an armed merge/queue request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ai controller stuck — Just had a game get stuck in relaunch because Ai controller stuck.

2 participants