cr733(p2): journal draw bookkeeping as a ledger edit (composes zone-change hub) - #6560
Conversation
📝 WalkthroughWalkthroughDraw bookkeeping is moved into resolved ledger edits with explicit replay validation. Draw effects use the ledger for card and empty-library accounting, while integration tests verify serialized command replay, object identity, counters, facts, hand contents, and library order. ChangesResolved draw bookkeeping
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant DrawEffect
participant DrawLedger
participant ResolvedCommandApplier
participant GameState
DrawEffect->>DrawLedger: Resolve card or empty-library draw
DrawLedger->>ResolvedCommandApplier: Apply CardsDrawn edit
ResolvedCommandApplier->>GameState: Update counters, flags, cards, and first-draw fact
GameState-->>DrawEffect: Updated draw state
DrawEffect-->>DrawEffect: Emit CardDrawn and enqueue first-draw offer when applicable
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/engine/tests/integration/cr733_resolved_draw.rs (2)
73-136: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplay coverage omits the empty-library / partial-draw ledger path.
This test only replays a fully-settled 2-card draw. The PR's empty-library accounting — a
CardsDrawnedit withdrawn_object: Noneandresulting_drew_from_empty_library, plus theDrawnObjectStillInLibrary/DrawnObjectMismatchguards — is never driven through the journal/replay comparison here. A regression that broke empty-library or partial-draw replay would stay green.Consider a sibling case: seed fewer library cards than the draw count, resolve, then replay and assert
drew_from_empty_libraryand the drawn-card ledger match. Want me to draft it?As per path instructions: "A test must exercise the FAILURE path the fix prevents and drive the engine through its production pipeline."
🤖 Prompt for 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. In `@crates/engine/tests/integration/cr733_resolved_draw.rs` around lines 73 - 136, Extend the integration coverage beside divination_draw_replays_zone_changes_and_ledger_bookkeeping_exactly with a partial draw scenario whose library contains fewer cards than Divination draws. Resolve and replay it through the production pipeline, then compare the journals and assert the CardsDrawn edit for the empty-library attempt uses drawn_object: None with resulting_drew_from_empty_library, while preserving the existing drawn-object and guard behavior for the card that was drawn.Source: Path instructions
27-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winKeep the shuffle action in this replay helper
LibraryShuffleis the only branch that drops the production side effect by passing&mut Vec::new(). If shuffle replay events matter here, thread a real sink through this helper so the test exercises the same outcome as the resolver.🤖 Prompt for 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. In `@crates/engine/tests/integration/cr733_resolved_draw.rs` around lines 27 - 66, Update apply_semantic_command to accept a mutable shuffle-event sink and pass that sink to apply_resolved_library_shuffle instead of creating a temporary Vec::new(). Thread the same sink through every caller so LibraryShuffle replay preserves the production side effect.
🤖 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.
Nitpick comments:
In `@crates/engine/tests/integration/cr733_resolved_draw.rs`:
- Around line 73-136: Extend the integration coverage beside
divination_draw_replays_zone_changes_and_ledger_bookkeeping_exactly with a
partial draw scenario whose library contains fewer cards than Divination draws.
Resolve and replay it through the production pipeline, then compare the journals
and assert the CardsDrawn edit for the empty-library attempt uses drawn_object:
None with resulting_drew_from_empty_library, while preserving the existing
drawn-object and guard behavior for the card that was drawn.
- Around line 27-66: Update apply_semantic_command to accept a mutable
shuffle-event sink and pass that sink to apply_resolved_library_shuffle instead
of creating a temporary Vec::new(). Thread the same sink through every caller so
LibraryShuffle replay preserves the production side effect.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 45196b84-dc78-4e47-a08e-4a115719e480
📒 Files selected for processing (5)
crates/engine/src/game/effects/draw.rscrates/engine/src/game/ledger.rscrates/engine/src/types/resolved_commands.rscrates/engine/tests/integration/cr733_resolved_draw.rscrates/engine/tests/integration/main.rs
Parse changes introduced by this PR✓ No card-parse changes detected. |
…hange hub) (phase-rs#6560) Co-authored-by: matthewevans <matthewevans@users.noreply.github.com>
Summary by CodeRabbit
Bug Fixes
Tests