Skip to content

DL-6: Comprehensive Story Outlines & Plot Threads#97

Merged
spuentesp merged 3 commits into
masterfrom
feature/DL-6-story-outlines-plot-threads
Jan 4, 2026
Merged

DL-6: Comprehensive Story Outlines & Plot Threads#97
spuentesp merged 3 commits into
masterfrom
feature/DL-6-story-outlines-plot-threads

Conversation

@spuentesp
Copy link
Copy Markdown
Owner

Summary

Implements DL-6: Manage Story Outlines & Plot Threads with comprehensive narrative engine support including beat progression tracking, mystery mechanics, foreshadowing/payoff patterns, and automatic pacing metrics.

Story Outlines (MongoDB)

Schemas

  • StoryBeat: Beat progression with status tracking, scene completion mapping
  • MysteryStructure: Clue discovery mechanics with visibility states
  • BranchingPoint: Multi-path narrative support
  • PacingMetrics: Automatic tension/completion calculation
  • StoryOutlineCreate/Update/Response: Full CRUD with beat manipulation

MongoDB Tools

  • mongodb_create_story_outline: Create outline with automatic pacing calculation
  • mongodb_get_story_outline: Retrieve outline with all beats/mystery structure
  • mongodb_update_story_outline: Partial updates supporting beat manipulation, mystery updates, clue discovery

Plot Threads (Neo4j)

Schemas

  • PlotThreadCreate/Update/Response: Thread with relationship management
  • ThreadDeadline: Time pressure mechanics
  • PlotThreadFilter/ListResponse: Flexible querying with pagination

Neo4j Tools

  • neo4j_create_plot_thread: Creates thread node + 5 relationship types (HAS_THREAD, ADVANCED_BY, INVOLVES, FORESHADOWS, REVEALS)
  • neo4j_get_plot_thread: Retrieve with all relationship collections
  • neo4j_update_plot_thread: Update with status transition validation
  • neo4j_list_plot_threads: Filter by story_id, type, status, priority, entity_id

Base Schemas

Added 9 new enums for narrative tracking:

  • PlotThreadType, PlotThreadStatus, BeatStatus
  • StoryStructureType, ArcTemplate
  • ThreadPriority, ThreadUrgency
  • ClueVisibility, PayoffStatus

Tests

All 194 tests passing

  • Story outline CRUD operations (13 tests)
  • Plot thread CRUD with relationship management (21 tests)
  • Beat manipulation (add, remove, update, reorder)
  • Mystery clue discovery
  • Status transition validation
  • Filtering and pagination
  • Error handling for all edge cases

Architecture Highlights

  • Beats in MongoDB (flexible planning) vs Threads in Neo4j (canonical truth)
  • Additive-only relationships to preserve complete narrative history
  • Status state machines with validated transitions
  • Pacing metrics automatically computed from beat completion ratios

Use Cases Implemented

  • DL-6: Manage Story Outlines & Plot Threads (primary)
  • Supports: P-1, P-8, ST-1, ST-4, CF-3

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 4, 2026 07:57
@github-actions github-actions Bot added area/data-layer Data layer changes needs-tests No tests touched labels Jan 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 4, 2026

\nTests not detected in this PR. Please add/confirm coverage where applicable.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements comprehensive narrative engine support for DL-6 (Manage Story Outlines & Plot Threads), introducing story beat progression tracking, mystery mechanics, foreshadowing/payoff patterns, and automatic pacing metrics. The implementation spans MongoDB for flexible story outline planning and Neo4j for canonical plot thread tracking with relationship management.

Key changes:

  • Added comprehensive story outline schemas with beat progression, mystery structures, and pacing metrics stored in MongoDB
  • Implemented plot thread management in Neo4j with 5 relationship types and status transition validation
  • Introduced 9 new enums for narrative tracking including thread types, priorities, and clue visibility states

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/data-layer/src/monitor_data/tools/neo4j_tools.py Fixed Cypher WHERE clause by adding parentheses around OR condition for proper label filtering
packages/data-layer/src/monitor_data/tools/mongodb_tools.py Enhanced beat manipulation operations with order preservation, comprehensive validation for reorder operations, and null-check for mystery structure
packages/data-layer/src/monitor_data/schemas/story_outlines.py Updated datetime handling to use timezone-aware UTC timestamps and made description field optional with empty string default
packages/data-layer/src/monitor_data/schemas/base.py Reordered ClueVisibility enum values alphabetically (hidden, discovered, revealed)
.gitignore Added MCP plugin workspace directory and uv.lock to ignored files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1071 to +1080
if len(params.reorder_beats) != len(beats_by_id):
raise ValueError(
f"reorder_beats must include all {len(beats_by_id)} beat IDs. "
f"Got {len(params.reorder_beats)} IDs instead."
)
reordered: list[StoryBeat] = []
for beat_id in params.reorder_beats:
beat_id_str = str(beat_id)
if beat_id_str in beats_by_id:
beat = beats_by_id[beat_id_str]
beat.order = len(reordered)
reordered.append(beat)
if beat_id_str not in beats_by_id:
raise ValueError(f"Beat ID {beat_id} not found in current beats")
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

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

The validation logic for checking if all beat IDs are included in the reorder operation is missing test coverage. Consider adding test cases for:

  1. Attempting to reorder with fewer beat IDs than currently exist (should raise ValueError)
  2. Attempting to reorder with an invalid beat ID that doesn't exist in current beats (should raise ValueError)

These tests would ensure the new validation behaves correctly when users provide incomplete or incorrect reorder lists.

Copilot uses AI. Check for mistakes.
Comment on lines +1103 to +1106
if mystery is None:
raise ValueError(
"Cannot mark clue as discovered: story outline has no mystery structure"
)
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

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

The validation logic that checks if mystery structure is None when marking a clue as discovered is missing test coverage. Consider adding a test case that attempts to mark a clue as discovered when the story outline has mystery_structure field present in the document but set to None. This would verify that the ValueError is correctly raised in this edge case.

Copilot uses AI. Check for mistakes.
@github-actions github-actions Bot added the type/tests Tests touched label Jan 4, 2026
sPuentesPrieto and others added 3 commits January 4, 2026 17:37
Addressed all 9 review comments from Copilot code review:

## Critical Fixes

1. **P1: Guard clue discovery** - Added None check for mystery_structure
   to prevent AttributeError when marking clues discovered on outlines
   without mystery structures

2. **Validate reorder_beats** - Added validation to ensure reorder_beats
   includes all beat IDs to prevent silent data loss

3. **Preserve beat order** - Fixed update_beats to preserve original
   order by iterating and replacing in place instead of using dictionary

4. **Fix deprecated datetime** - Replaced datetime.utcnow() with
   datetime.now(timezone.utc) in story_outlines.py for Python 3.12+
   compatibility

## Code Improvements

5. **Clarify WHERE clause** - Added parentheses around OR condition in
   neo4j_get_plot_thread for clarity

6. **Make description optional** - Added default empty string to
   StoryBeat.description for flexibility during planning

7. **Reorder enum values** - Reordered ClueVisibility enum to follow
   logical progression: HIDDEN → DISCOVERED → REVEALED

8. **Document beat operations** - Added comprehensive documentation of
   beat operation order and potential conflicts in docstring

All 194 tests passing ✅

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added tests for new validation logic introduced in review fixes:
- test_update_story_outline_mark_clue_discovered_no_mystery_structure:
  Validates error when trying to mark clue discovered without mystery structure
- test_update_story_outline_reorder_beats_incomplete:
  Validates error when reorder_beats doesn't include all beat IDs

These tests cover the guard conditions added in the review fixes commit.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@spuentesp spuentesp force-pushed the feature/DL-6-story-outlines-plot-threads branch from f23fa80 to b4ba9d1 Compare January 4, 2026 20:37
@spuentesp spuentesp merged commit d427e0f into master Jan 4, 2026
10 checks passed
@spuentesp spuentesp deleted the feature/DL-6-story-outlines-plot-threads branch April 25, 2026 00:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/data-layer Data layer changes needs-tests No tests touched type/tests Tests touched

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants