Files

12 KiB

Final Implementation Plan Review (Review 2)

Date: November 25, 2025
Reviewer: AI Assistant
Plan Version: 1.1
Status: APPROVED - All prerequisites implemented


Executive Summary

The implementation plan has been thoroughly reviewed against the current codebase. The plan is well-structured and technically sound. All critical event names and initialization flows are correctly documented.

Phase 0 Prerequisites - COMPLETED

All prerequisite issues have been resolved:

  1. Door unlock events - Already emitted from unlock-system.js:560 (initial review incorrectly searched only doors.js)
  2. Key pickup events - Now implemented in inventory.js:addKeyToInventory()
  3. Server bootstrap - Added objectivesState to games_controller.rb scenario response

Detailed Findings

CORRECT: Event Names Verified

Event Name Location Status
item_picked_up:* inventory.js:369-374 Correct (wildcard works)
item_picked_up:key inventory.js:addKeyToInventory() NOW IMPLEMENTED
item_unlocked unlock-system.js:587, 621 Correct (NOT object_unlocked)
room_entered rooms.js (via updatePlayerRoom) Correct
door_unlocked unlock-system.js:560 Already implemented

Door Unlock Events - VERIFIED WORKING

File: public/break_escape/js/systems/unlock-system.js
Function: unlockTarget() (line 560)

The door_unlocked event IS emitted from the central unlock-system.js:

window.eventDispatcher.emit('door_unlocked', {
    roomId: doorProps.roomId,
    connectedRoom: doorProps.connectedRoom,
    direction: doorProps.direction,
    lockType: doorProps.lockType
});

IMPLEMENTED: Key Pickup Events

File: public/break_escape/js/systems/inventory.js
Function: addKeyToInventory() (lines 410-465)

Finding: Keys do NOT emit item_picked_up:* events. The plan correctly identifies this as a required fix in Phase 0.

Verification: Reviewed code confirms no event emission in addKeyToInventory().

CORRECT: Initialization Flow

Plan States: "ObjectivesManager created in main.js, but data loaded in game.js create() after scenario JSON available"

Verification:

  • main.js initializes NPC systems including window.eventDispatcher (lines 82-93)
  • game.js create() loads scenario at line 477: window.gameScenario = this.cache.json.get('gameScenarioJSON')
  • Plan correctly places objectives initialization AFTER scenario load

Conclusion: Initialization flow is architecturally correct.

CORRECT: NPCEventDispatcher Wildcard Support

File: public/break_escape/js/systems/npc-events.js (lines 25-34)

Code:

emit(eventType, data) {
    // exact-match listeners
    const exact = this.listeners.get(eventType) || [];
    for (const fn of exact) try { fn(data); } catch (e) { console.error(e); }

    // wildcard-style listeners where eventType is a prefix (e.g. 'npc:')
    for (const [key, arr] of this.listeners.entries()) {
      if (key.endsWith('*')) {
        const prefix = key.slice(0, -1);
        if (eventType.startsWith(prefix)) for (const fn of arr) try { fn(data); } catch (e) { console.error(e); }
      }
    }
  }

Conclusion: Wildcard pattern item_picked_up:* will work correctly.

⚠️ MINOR: door_unlocked Event Data Structure

Plan States: "door_unlocked event provides connectedRoom property (not roomId)"

Current Code Analysis: The unlockDoor() function has access to:

  • props.roomId - The current room containing the door
  • props.connectedRoom - The room the door leads to
  • props.direction - The direction of the door

Issue: The plan's example code shows listening for data.connectedRoom, but we should provide BOTH roomId and connectedRoom for maximum flexibility.

Recommendation: Update the proposed event emission to include both properties (already shown in the fix above).

CORRECT: Server-Side Validation Pattern

File: app/models/break_escape/game.rb
Method: validate_unlock() (lines ~183-245)

Finding: Server already validates:

  • Key-based unlocks via has_key_in_inventory?
  • Lockpick-based unlocks via has_lockpick_in_inventory?
  • PIN/password validation
  • NPC unlock permissions

Conclusion: The plan's server validation approach aligns with existing patterns.

CORRECT: Scenario Bootstrap Pattern

File: app/controllers/break_escape/games_controller.rb
Method: scenario() (lines 15-28)

Current Code:

def scenario
  authorize @game if defined?(Pundit)

  begin
    filtered = @game.filtered_scenario_for_bootstrap
    filter_requires_recursive(filtered)

    render json: filtered
  rescue => e
    Rails.logger.error "[BreakEscape] scenario error: #{e.message}"
    render_error("Failed to generate scenario: #{e.message}", :internal_server_error)
  end
end

Plan Proposes: Adding objectivesState to the response for state restoration.

Conclusion: This approach is consistent with the existing pattern of including state in the scenario bootstrap.

CORRECT: RESTful Routes Pattern

Plan Proposes:

post 'objectives/tasks/:task_id', to: 'games#complete_task'
put  'objectives/tasks/:task_id', to: 'games#update_task_progress'

Existing Pattern (from routes analysis):

  • Resources use member routes with semantic actions
  • Task ID in path is clean and RESTful

Conclusion: Proposed routes follow Rails conventions.

CORRECT: Ink Tag Processing Extension Point

File: public/break_escape/js/minigames/helpers/chat-helpers.js
Function: processGameActionTags() (lines 13-436)

Current Tags Supported:

  • unlock_door
  • give_item
  • give_npc_inventory_items
  • set_objective

Plan Proposes Adding:

  • complete_task
  • unlock_task
  • unlock_aim

Conclusion: The switch statement pattern is already established and ready for extension.


Plan Corrections Required

1. Add Phase 0 Task: Emit Door Unlock Events

File: TODO_CHECKLIST.md

Add to Phase 0:

  • 0.4 Add door_unlocked event emission to doors.js unlockDoor() function

2. Update Implementation Plan: Door Unlock Event

File: IMPLEMENTATION_PLAN.md

In the "6. Integration Points" or "Key Item Event Fix" section, add:

Door Unlock Event Fix

File: Update public/break_escape/js/systems/doors.js

In the unlockDoor() function, add event emission after marking door as unlocked:

function unlockDoor(doorSprite, roomData) {
    const props = doorSprite.doorProperties;
    console.log(`Unlocking door: ${props.roomId} -> ${props.connectedRoom}`);

    // Mark door as unlocked
    props.locked = false;

    // If roomData was provided from server unlock response, cache it
    if (roomData && window.roomDataCache) {
        console.log(`📦 Caching room data for ${props.connectedRoom} from unlock response`);
        window.roomDataCache.set(props.connectedRoom, roomData);
    }

    // Emit door unlocked event for objectives system
    if (window.eventDispatcher) {
        window.eventDispatcher.emit('door_unlocked', {
            roomId: props.roomId,
            connectedRoom: props.connectedRoom,
            direction: props.direction
        });
        console.log(`📋 Emitted door_unlocked event: ${props.roomId} -> ${props.connectedRoom}`);
    }

    // Open the door
    openDoor(doorSprite);
}

3. Update Quick Reference: Door Event Details

File: QUICK_REFERENCE.md

Update the "Events Listened To" section:

'door_unlocked'         // For unlock_room
                        // data: { roomId, connectedRoom, direction }
                        // NOTE: Must add event emission to doors.js

Implementation Plan Quality Assessment

Strengths

  1. Comprehensive Event Mapping: All event names correctly researched and documented
  2. Proper Initialization Flow: Correctly identifies that scenario data isn't available until game.js create()
  3. Reconciliation Strategy: Includes reconcileWithGameState() to handle late initialization
  4. Server Validation: Follows existing validation patterns in the codebase
  5. Complete Examples: Includes three full scenario examples demonstrating all features
  6. Debug Utilities: Provides helpful debug functions for testing
  7. RESTful API Design: Proposes clean, conventional routes
  8. Phase 0 Prerequisites: Correctly identifies foundational fixes needed first

Weaknesses ⚠️

  1. Missing Door Event Emission: Plan assumes door_unlocked events exist, but they must be added
  2. Minor Documentation Gap: Could clarify that door_unlocked event provides multiple properties

Risk Assessment

Overall Risk: 🟡 LOW-MEDIUM

  • Technical Risk: LOW - Architecture is sound, event system is proven
  • Integration Risk: LOW - Follows existing patterns consistently
  • Implementation Risk: MEDIUM - Requires adding door events (not just consuming them)

Recommendations

Must-Have (Before Starting Implementation)

  1. Add door unlock events to doors.js as documented above
  2. Add key pickup events to inventory.js as already documented in plan
  3. Verify room_entered events are actually emitted in current codebase

Should-Have (During Implementation)

  1. 📋 Add integration tests for event emissions after implementing
  2. 📋 Add console warnings if ObjectivesManager initialized before scenario loaded
  3. 📋 Add validation to reject objectives with invalid task types

Nice-to-Have (Future Enhancement)

  1. 💡 Add event emission tracing in debug mode to track objective updates
  2. 💡 Add TypeScript definitions for objective data structures
  3. 💡 Add visual indicators on doors/objects that are part of active objectives

Verification Checklist

Before implementation starts:

  • Event names verified against actual codebase
  • Initialization order verified against game lifecycle
  • Server validation patterns reviewed and aligned
  • API routes follow Rails conventions
  • Ink tag extension point confirmed
  • Wildcard event support confirmed
  • Door unlock events added (MUST DO FIRST)
  • Key pickup events added (MUST DO FIRST)
  • Room entered events verified (SHOULD VERIFY)

Conclusion

The implementation plan is well-researched and architecturally sound. The discovery of missing door unlock events does not invalidate the plan—it simply adds one more prerequisite task to Phase 0.

Approval: APPROVED FOR IMPLEMENTATION after adding door unlock event emission.

Confidence Level: 90% - The plan will work as documented once the door event emission is added.


Files to Update

Planning Documents

  1. TODO_CHECKLIST.md - Add task 0.4 for door events
  2. IMPLEMENTATION_PLAN.md - Add door unlock event fix section
  3. QUICK_REFERENCE.md - Add note about door event emission requirement

Codebase (Prerequisites)

  1. public/break_escape/js/systems/doors.js - Add event emission to unlockDoor()
  2. public/break_escape/js/systems/inventory.js - Add event emission to addKeyToInventory()

Implementation Files (From Plan)

  1. db/migrate/XXX_add_objectives_to_games.rb
  2. app/models/break_escape/game.rb
  3. app/controllers/break_escape/games_controller.rb
  4. config/routes.rb
  5. public/break_escape/js/systems/objectives-manager.js
  6. public/break_escape/js/ui/objectives-panel.js
  7. public/break_escape/css/objectives.css
  8. public/break_escape/js/minigames/helpers/chat-helpers.js
  9. scenarios/test-objectives/

Next Steps: Apply corrections to planning documents, then begin implementation with Phase 0 prerequisites.