Skip to content

fix(tracker): converge hidden hand cards after target slots fill#22

Merged
llsccm merged 3 commits into
devfrom
codex/hand-slot-candidate-range
Jul 12, 2026
Merged

fix(tracker): converge hidden hand cards after target slots fill#22
llsccm merged 3 commits into
devfrom
codex/hand-slot-candidate-range

Conversation

@llsccm

@llsccm llsccm commented Jul 12, 2026

Copy link
Copy Markdown
Owner

概述

⑤ 的长链路 E2E 暴露了一个收敛缺口:随机暗牌转移后,当目标座位手牌槽被明牌占满,来源两张暗牌仍保留不可能的目标座位候选(seats=[2,3])。本 PR 定向修复该缺口,使其收敛为 seats=[2]。base 为 dev

根因(诊断确认)

转移约束组只声明了 expectedSlotsBySeat、缺 expectedSlotsByLocation

  • 暗牌被提升为 hand 完整位置候选(带 subZoneCandidates)后,ConstraintGroup.resolve() 的座位层消除(expectedSlotsBySeat 分支)刻意跳过subZoneCandidates 的牌,交由位置层处理;
  • 但该组位置层约束为空,故 seat3 名额清零后,没有任何约束剔除暗牌的 seat3 候选。

明牌能收敛是走了 Room 的 known-only 排他分支;暗牌走不到那条分支,只能靠位置层——而位置层缺失。

修复

markRandomHandTransferCandidatesroomMovement/candidates.ts)建组时同步镜像一份 hand 位置约束:

expectedSlotsByLocation = { fromSeat/hand: N-K, targetSeat/hand: K }

removeCardsFromConstraintGroups 本就随成员解析离组同步扣减 expectedSlotsByLocation,故明牌 42/46/47 解析到 seat3 离组后,seat3/hand 名额降到 0,位置层消除即剔除 130/131 的 seat3 候选 → seats=[2]。计数层(unknownCardCount)一直正确,本次只修 seats 投影。

测试

  • tests/tracker/randomTransferLifecycle.test.ts 断言与终态 inline snapshot 由旧的 [2,3] 改锁 [2];130/131 仍 known:false(暗牌身份不泄露)。
  • pnpm test:tracker — 23 文件 / 170 项通过(无回归)
  • pnpm typecheck:tracker / pnpm lint / pnpm build:prod / git diff --check — 全通过

范围说明

原设想的完整候选范围模型(handSlotRange.tscandidateMin/Max)经诊断确认与本验收目标正交(它管匿名实体物化计数,不管本处 seats 消除),未纳入本次改动;如需匿名计数精度可作单独后续。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • 修复随机手牌转移中,隐藏卡牌候选因名额约束不匹配而无法正确收敛的问题。
    • 让候选座位在约束调整后更准确收敛至仅包含有效席位,避免保留不可能候选项。
  • Tests
    • 更新随机手牌转移全流程回归断言与快照,确保候选座位结果稳定一致。
  • Documentation
    • 更新实施与机制说明文档,补充手牌暗取/约束解析/收敛相关的关键验证要点与基线遍历数据。

markRandomHandTransferCandidates now mirrors its per-seat quota into expectedSlotsByLocation ({fromSeat/hand: N-K, targetSeat/hand: K}). Hidden transfer entities get promoted to hand location candidates (with subZoneCandidates), which the seat-layer elimination deliberately skips; with no location-layer constraint the group could never prune their seat once the target's slots filled, so they kept an impossible candidate seat (130/131 stayed {2,3} after seat 3 was full).

removeCardsFromConstraintGroups already decrements expectedSlotsByLocation as members resolve and leave, so the mirrored quota drops to 0 and the location layer prunes the stale seat, converging them to seats=[2]. Counts were already correct; this only fixes the seats projection.

Flip the randomTransferLifecycle E2E star-assertion and end-state snapshot from the old [2,3] to the fixed [2]. 170 tracker tests, typecheck:tracker, lint, build:prod green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@llsccm, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8bdbdd82-2c68-4124-a661-50f66df4c5b5

📥 Commits

Reviewing files that changed from the base of the PR and between c4eb674 and 4c3dcdc.

📒 Files selected for processing (1)
  • docs/agents/lifecycle.md
📝 Walkthrough

Walkthrough

修正随机手牌转移候选的 hand 位置槽位约束,使隐藏卡牌的候选席位从 [2, 3] 收敛为 [2],并同步更新测试、生命周期说明及项目约定文档。

Changes

随机手牌转移候选修复

Layer / File(s) Summary
补齐 hand 位置约束
src/tracker/roomMovement/candidates.ts, src/tracker/ConstraintGroup.ts
为来源与目标 hand 创建位置候选键,并使用 expectedSlotsByLocation 维护槽位约束,同时补充对应收敛规则说明。
更新生命周期回归验证
tests/tracker/randomTransferLifecycle.test.ts, docs/agents/card_tracker.md, docs/agents/serena.md
隐藏卡牌 130/131 的候选席位与快照更新为 [2],并同步候选推断、槽位统计及验证规则。
细化生命周期流程文档
docs/agents/lifecycle.md
补充初始化、Room 创建、视图挂载、消息处理、卡牌移动收敛及源码索引说明。
同步项目约定文档
CLAUDE.md, docs/agents/conventions.md, docs/agents/overview.md
移除 window.XC 共享命名空间约定,并更新模块与测试覆盖范围描述。

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

Possibly related PRs

  • llsccm/tracker#12:涉及 locationCandidates 与席位候选投影迁移。
  • llsccm/tracker#20:涉及同一 roomMovement 子模块及随机手牌转移候选逻辑。
🚥 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 标题准确概括了该 PR 的核心修复:在目标手牌槽位填满后收敛隐藏手牌候选。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/hand-slot-candidate-range

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements a targeted fix for the random hand transfer constraint resolution. Specifically, it updates markRandomHandTransferCandidates in src/tracker/roomMovement/candidates.ts to populate expectedSlotsByLocation alongside expectedSlotsBySeat. This ensures that when a seat's hand slots are fully occupied, location-level elimination correctly removes impossible seat candidates for hidden cards (e.g., converging to seats=[2] instead of incorrectly retaining [2, 3]). The implementation report and end-to-end lifecycle tests have been updated to reflect this fix and verify the correct convergence behavior. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@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 `@docs/agents/lifecycle.md`:
- Line 55: 更新 lifecycle 文档中关于 EXIT 阶段的描述,使其匹配 src/index.js 的实际顺序:先将
window.console.log 覆盖为 console.info,再向 SGSMODULE 元素广播 'EXIT',最后删除
SGSMODULE;将“清空还原”改为准确描述覆盖行为。
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 21fc66a0-89a0-4599-bd2f-e0a7ca4fc040

📥 Commits

Reviewing files that changed from the base of the PR and between dd01433 and c4eb674.

📒 Files selected for processing (9)
  • CLAUDE.md
  • docs/agents/card_tracker.md
  • docs/agents/conventions.md
  • docs/agents/lifecycle.md
  • docs/agents/overview.md
  • docs/agents/serena.md
  • plans/anonymous-card-entity-optimization-plan.md
  • plans/random-hand-transfer-and-anonymous-entity-implementation-report.md
  • src/tracker/ConstraintGroup.ts
💤 Files with no reviewable changes (3)
  • docs/agents/conventions.md
  • plans/anonymous-card-entity-optimization-plan.md
  • plans/random-hand-transfer-and-anonymous-entity-implementation-report.md

Comment thread docs/agents/lifecycle.md Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@llsccm
llsccm merged commit 7e545e7 into dev Jul 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant