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:
- ✅ Door unlock events - Already emitted from
unlock-system.js:560(initial review incorrectly searched only doors.js) - ✅ Key pickup events - Now implemented in
inventory.js:addKeyToInventory() - ✅ Server bootstrap - Added
objectivesStatetogames_controller.rbscenario 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.jsinitializes NPC systems includingwindow.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 doorprops.connectedRoom- The room the door leads toprops.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_doorgive_itemgive_npc_inventory_itemsset_objective
Plan Proposes Adding:
complete_taskunlock_taskunlock_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_unlockedevent emission todoors.jsunlockDoor()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 ✅
- Comprehensive Event Mapping: All event names correctly researched and documented
- Proper Initialization Flow: Correctly identifies that scenario data isn't available until
game.js create() - Reconciliation Strategy: Includes
reconcileWithGameState()to handle late initialization - Server Validation: Follows existing validation patterns in the codebase
- Complete Examples: Includes three full scenario examples demonstrating all features
- Debug Utilities: Provides helpful debug functions for testing
- RESTful API Design: Proposes clean, conventional routes
- Phase 0 Prerequisites: Correctly identifies foundational fixes needed first
Weaknesses ⚠️
- Missing Door Event Emission: Plan assumes
door_unlockedevents exist, but they must be added - Minor Documentation Gap: Could clarify that
door_unlockedevent 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)
- ✅ Add door unlock events to
doors.jsas documented above - ✅ Add key pickup events to
inventory.jsas already documented in plan - ✅ Verify room_entered events are actually emitted in current codebase
Should-Have (During Implementation)
- 📋 Add integration tests for event emissions after implementing
- 📋 Add console warnings if ObjectivesManager initialized before scenario loaded
- 📋 Add validation to reject objectives with invalid task types
Nice-to-Have (Future Enhancement)
- 💡 Add event emission tracing in debug mode to track objective updates
- 💡 Add TypeScript definitions for objective data structures
- 💡 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
TODO_CHECKLIST.md- Add task 0.4 for door eventsIMPLEMENTATION_PLAN.md- Add door unlock event fix sectionQUICK_REFERENCE.md- Add note about door event emission requirement
Codebase (Prerequisites)
public/break_escape/js/systems/doors.js- Add event emission tounlockDoor()public/break_escape/js/systems/inventory.js- Add event emission toaddKeyToInventory()
Implementation Files (From Plan)
db/migrate/XXX_add_objectives_to_games.rbapp/models/break_escape/game.rbapp/controllers/break_escape/games_controller.rbconfig/routes.rbpublic/break_escape/js/systems/objectives-manager.jspublic/break_escape/js/ui/objectives-panel.jspublic/break_escape/css/objectives.csspublic/break_escape/js/minigames/helpers/chat-helpers.jsscenarios/test-objectives/
Next Steps: Apply corrections to planning documents, then begin implementation with Phase 0 prerequisites.