WebVNWrite/prd.json

422 lines
23 KiB
JSON

{
"project": "WebVNWrite",
"branchName": "ralph/collaboration-and-character-variables",
"description": "Real-time Collaboration & Character/Variable Management - Enable multi-user editing with CRDT sync, presence indicators, audit trail, plus centralized character/variable definitions with dropdown selectors",
"userStories": [
{
"id": "US-054",
"title": "Character and Variable TypeScript types",
"description": "As a developer, I need TypeScript types for Character and Variable models so that the rest of the feature can be built with type safety.",
"acceptanceCriteria": [
"Add Character type to types/flowchart.ts: id (string), name (string), color (string, hex), description (string, optional)",
"Add Variable type to types/flowchart.ts: id (string), name (string), type ('numeric' | 'string' | 'boolean'), initialValue (number | string | boolean), description (string, optional)",
"Update FlowchartData type to include characters: Character[] and variables: Variable[]",
"Update DialogueNodeData to add optional characterId: string field (alongside existing speaker for migration)",
"Update Condition type to add optional variableId: string field (alongside existing variableName for migration)",
"Update VariableNodeData to add optional variableId: string field (alongside existing variableName for migration)",
"Typecheck passes"
],
"priority": 1,
"passes": true,
"notes": ""
},
{
"id": "US-055",
"title": "Database schema update for characters and variables",
"description": "As a developer, I need the database schema to store characters and variables as part of the project's flowchart data.",
"acceptanceCriteria": [
"Create migration that documents the new JSONB structure (characters/variables arrays stored within flowchart_data)",
"Update the default value for flowchart_data column to include characters: [] and variables: []",
"Existing projects with no characters/variables arrays continue to load (handled as empty arrays in app code)",
"Typecheck passes"
],
"priority": 2,
"passes": true,
"notes": "Dependencies: US-054"
},
{
"id": "US-065",
"title": "Searchable combobox component",
"description": "As a developer, I need a reusable searchable combobox component so that all character/variable dropdowns share consistent behavior and styling.",
"acceptanceCriteria": [
"Create components/editor/Combobox.tsx - a reusable searchable dropdown component",
"Props: items (id, label, color?, badge?), value, onChange, placeholder, onAddNew (optional callback)",
"Typing in the input filters the list by name (case-insensitive)",
"Keyboard navigation: arrow keys to move, Enter to select, Escape to close",
"Shows color swatch and/or badge next to item labels when provided",
"'Add new...' option rendered at bottom when onAddNew prop is provided",
"Dropdown positions itself above or below input based on available space",
"Matches existing editor styling (TailwindCSS, dark mode support)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 3,
"passes": true,
"notes": ""
},
{
"id": "US-056",
"title": "Character management UI in project settings",
"description": "As a user, I want a dedicated page to manage my project's characters so that I can define them once and reuse them throughout the flowchart.",
"acceptanceCriteria": [
"Add 'Project Settings' button to editor toolbar",
"Project settings opens as a modal with 'Characters' and 'Variables' tabs",
"Characters tab shows a list of defined characters with name, color swatch, and description",
"'Add Character' button opens inline form with: name (required), color picker (required, defaults to random), description (optional)",
"Each character row has Edit and Delete buttons",
"Deleting a character referenced by nodes shows warning with usage count",
"Character names must be unique within the project (validation error if duplicate)",
"Changes are saved to the flowchart data (same save mechanism as nodes/edges)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 4,
"passes": true,
"notes": "Dependencies: US-054, US-055"
},
{
"id": "US-057",
"title": "Variable management UI in project settings",
"description": "As a user, I want a dedicated page to manage my project's variables so that I can define them with types and initial values for use throughout the flowchart.",
"acceptanceCriteria": [
"Variables tab in project settings modal shows a list of defined variables",
"Each variable displays: name, type badge (numeric/string/boolean), initial value, description",
"'Add Variable' button opens inline form with: name (required), type dropdown (required), initial value (required, input adapts to type), description (optional)",
"Each variable row has Edit and Delete buttons",
"Deleting a variable referenced by nodes/edges shows warning with usage count",
"Variable names must be unique within the project",
"Changes are saved to the flowchart data",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 5,
"passes": true,
"notes": "Dependencies: US-054, US-055"
},
{
"id": "US-058",
"title": "Dialogue node speaker dropdown",
"description": "As a user, I want to select a character from a dropdown in the dialogue node instead of typing a name so that I avoid typos and maintain consistency.",
"acceptanceCriteria": [
"Replace the speaker text input in DialogueNode with the Combobox component",
"Dropdown lists all characters defined in the project, showing color swatch + name",
"Selecting a character sets characterId on the node data",
"Dropdown includes 'Add new character...' option at the bottom",
"Clicking 'Add new character...' opens a mini form inline (name + color) that creates the character and selects it",
"If node has a characterId that doesn't match any defined character, show orange warning border on the dropdown",
"Empty/unset speaker shows placeholder 'Select speaker...'",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 6,
"passes": true,
"notes": "Dependencies: US-056, US-065"
},
{
"id": "US-059",
"title": "Variable node variable dropdown",
"description": "As a user, I want to select a variable from a dropdown in the variable node instead of typing a name so that I avoid typos and maintain consistency.",
"acceptanceCriteria": [
"Replace the variableName text input in VariableNode with the Combobox component",
"Dropdown lists all variables defined in the project, showing type badge + name",
"Selecting a variable sets variableId on the node data",
"Dropdown includes 'Add new variable...' option that opens inline creation form",
"If node references a variableId that doesn't match any defined variable, show orange warning border",
"Operation options (set/add/subtract) are filtered based on selected variable's type (add/subtract only for numeric)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 7,
"passes": true,
"notes": "Dependencies: US-057, US-065"
},
{
"id": "US-060",
"title": "Edge condition variable dropdown",
"description": "As a user, I want to select a variable from a dropdown when setting edge conditions so that I reference valid variables consistently.",
"acceptanceCriteria": [
"Replace the variableName text input in ConditionEditor with the Combobox component",
"Dropdown lists all variables defined in the project, showing type badge + name",
"Selecting a variable sets variableId on the condition object",
"Dropdown includes 'Add new variable...' option",
"If condition references an undefined variableId, show orange warning indicator",
"Operator options are filtered based on variable type (comparison operators for numeric, == and != for string/boolean)",
"Value input adapts to variable type (number input for numeric, text for string, checkbox for boolean)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 8,
"passes": true,
"notes": "Dependencies: US-057, US-065"
},
{
"id": "US-061",
"title": "Choice option condition variable dropdown",
"description": "As a user, I want to select a variable from a dropdown when setting choice option conditions so that I reference valid variables consistently.",
"acceptanceCriteria": [
"Replace the variableName text input in OptionConditionEditor with the Combobox component",
"Dropdown lists all variables defined in the project, showing type badge + name",
"Selecting a variable sets variableId on the option's condition object",
"Dropdown includes 'Add new variable...' option",
"If condition references an undefined variableId, show orange warning indicator",
"Operator and value inputs adapt to variable type (same behavior as US-060)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 9,
"passes": true,
"notes": "Dependencies: US-057, US-065"
},
{
"id": "US-062",
"title": "Auto-migration of existing free-text values",
"description": "As a user, I want my existing projects to automatically create character and variable definitions from free-text values so that I don't have to manually re-enter them.",
"acceptanceCriteria": [
"On project load, if characters array is empty but nodes have speaker values, auto-create Character entries from unique speaker names",
"Auto-created characters get randomly assigned colors and the speaker text as name",
"On project load, if variables array is empty but nodes/edges have variableName values, auto-create Variable entries (default type: numeric, initial value: 0)",
"After auto-creation, update all nodes to set characterId/variableId references pointing to the new entries",
"Show a toast notification: 'Auto-imported N characters and M variables from existing data'",
"Migration only runs once (presence of characters/variables arrays, even if empty, means migration already happened)",
"Typecheck passes"
],
"priority": 10,
"passes": true,
"notes": "Dependencies: US-054, US-058, US-059"
},
{
"id": "US-063",
"title": "Import characters/variables from another project",
"description": "As a user, I want to import character and variable definitions from another project so that I can reuse them without redefining everything.",
"acceptanceCriteria": [
"Add 'Import from project' button in both Characters and Variables tabs of project settings",
"Button opens a modal listing the user's other projects",
"Selecting a project shows its characters (or variables) with checkboxes for selection",
"User can select which entries to import (select all / none / individual)",
"Imported entries are added to the current project (duplicates by name are skipped with a warning)",
"Imported characters keep their colors; imported variables keep their types and initial values",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 11,
"passes": true,
"notes": "Dependencies: US-056, US-057"
},
{
"id": "US-064",
"title": "Export validation for undefined references",
"description": "As a user, I want to be warned before exporting if any nodes reference undefined characters or variables so that I can fix issues before generating output.",
"acceptanceCriteria": [
"Before export, scan all nodes and edges for characterId/variableId references that don't match defined entries",
"If issues found, show a warning modal listing: node type, node content snippet, and the undefined reference",
"Modal offers 'Export anyway' and 'Cancel' options",
"Nodes with undefined references are highlighted on the canvas with orange warning borders when modal is shown",
"If no issues found, export proceeds normally",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 12,
"passes": true,
"notes": "Dependencies: US-058, US-059, US-060, US-061"
},
{
"id": "US-043",
"title": "Database schema for collaboration sessions and audit trail",
"description": "As a developer, I need database tables to track active collaboration sessions and store the full change history for projects.",
"acceptanceCriteria": [
"Create migration adding project_collaborators table: id (uuid), project_id (references projects), user_id (references profiles), role ('owner' | 'editor' | 'viewer'), invited_at (timestamptz), accepted_at (timestamptz)",
"Create collaboration_sessions table: id (uuid), project_id, user_id, cursor_position (jsonb), selected_node_id (text nullable), connected_at (timestamptz), last_heartbeat (timestamptz)",
"Create audit_trail table: id (uuid), project_id, user_id, action_type (text: 'node_add' | 'node_update' | 'node_delete' | 'edge_add' | 'edge_update' | 'edge_delete'), entity_id (text), previous_state (jsonb), new_state (jsonb), created_at (timestamptz)",
"Add RLS policies: collaborators can access sessions/audit for projects they belong to",
"Add index on audit_trail(project_id, created_at) for efficient history queries",
"Typecheck passes"
],
"priority": 13,
"passes": false,
"notes": ""
},
{
"id": "US-045",
"title": "Supabase Realtime channel and connection management",
"description": "As a developer, I need a WebSocket connection layer using Supabase Realtime so that clients can exchange presence and change events in real time.",
"acceptanceCriteria": [
"Create lib/collaboration/realtime.ts module",
"On editor mount, join a Supabase Realtime channel scoped to the project ID",
"Track connection state (connecting, connected, disconnected, reconnecting)",
"Implement heartbeat mechanism (update last_heartbeat every 30 seconds)",
"Auto-reconnect on network interruption with exponential backoff",
"Clean up session record on disconnect/unmount",
"Show connection status indicator in editor toolbar (green=connected, yellow=reconnecting, red=disconnected)",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 14,
"passes": false,
"notes": "Dependencies: US-043"
},
{
"id": "US-044",
"title": "Project sharing and collaborator management",
"description": "As a project owner, I want to invite other users to collaborate on my project so that we can work together.",
"acceptanceCriteria": [
"Add 'Share' button in the editor toolbar",
"Share modal displays current collaborators with roles (owner/editor/viewer)",
"Owner can invite users by email with a selected role",
"Owner can change collaborator roles or remove collaborators",
"Invited users see shared projects on their dashboard with a 'Shared with me' indicator",
"RLS policies updated so collaborators can read/write projects based on their role",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 15,
"passes": false,
"notes": "Dependencies: US-043"
},
{
"id": "US-046",
"title": "Presence indicators for active collaborators",
"description": "As a user, I want to see who else is currently viewing or editing the project so that I am aware of my collaborators.",
"acceptanceCriteria": [
"Display a row of avatar circles in the editor toolbar showing connected users",
"Each avatar shows the user's display_name on hover (tooltip)",
"Each user is assigned a consistent color (derived from user ID hash)",
"Avatars appear when users join and disappear when they leave",
"Maximum 5 avatars shown with '+N' overflow indicator",
"Own avatar not shown in the list",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 16,
"passes": false,
"notes": "Dependencies: US-045"
},
{
"id": "US-048",
"title": "Integrate Yjs CRDT for conflict-free node/edge synchronization",
"description": "As a developer, I need to integrate a CRDT library so that concurrent edits from multiple users merge automatically without data loss.",
"acceptanceCriteria": [
"Install and configure Yjs with a Supabase-compatible provider (or WebSocket provider)",
"Create lib/collaboration/crdt.ts module wrapping Yjs document setup",
"Model flowchart nodes as a Y.Map keyed by node ID",
"Model flowchart edges as a Y.Map keyed by edge ID",
"Local React Flow state changes are synced to the Yjs document",
"Remote Yjs document changes update local React Flow state",
"Initial load populates Yjs document from database state",
"Periodic persistence of Yjs document state to Supabase (debounced 2 seconds)",
"Typecheck passes"
],
"priority": 17,
"passes": false,
"notes": "Dependencies: US-045"
},
{
"id": "US-047",
"title": "Live cursor positions on canvas",
"description": "As a user, I want to see other collaborators' cursor positions on the canvas so that I can understand where they are working.",
"acceptanceCriteria": [
"Broadcast local cursor position to the Realtime channel (throttled to 50ms)",
"Render remote cursors as colored arrows/pointers on the canvas with user name labels",
"Cursor color matches the user's assigned presence color",
"Remote cursors smoothly interpolate between position updates (no jumping)",
"Remote cursors fade out after 5 seconds of inactivity",
"Cursors are rendered in screen coordinates and properly transform with canvas zoom/pan",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 18,
"passes": false,
"notes": "Dependencies: US-045, US-046"
},
{
"id": "US-050",
"title": "Join/leave notifications",
"description": "As a user, I want to be notified when collaborators join or leave the editing session so that I stay aware of the team's activity.",
"acceptanceCriteria": [
"Show a toast notification when a collaborator joins: '[Name] joined'",
"Show a toast notification when a collaborator leaves: '[Name] left'",
"Notifications use the collaborator's assigned color as an accent",
"Notifications auto-dismiss after 3 seconds (matches existing Toast behavior)",
"No notification shown for own join/leave events",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 19,
"passes": false,
"notes": "Dependencies: US-045, US-046"
},
{
"id": "US-049",
"title": "Node editing lock indicators",
"description": "As a user, I want to see when another collaborator is actively editing a specific node so that I can avoid conflicts and wait for them to finish.",
"acceptanceCriteria": [
"When a user focuses/opens a node for editing, broadcast the node ID to the channel",
"Nodes being edited by others show a colored border matching the editor's presence color",
"A small label with the editor's name appears on the locked node",
"Other users can still view but see a 'Being edited by [name]' indicator if they try to edit",
"Lock is released when the user clicks away, closes the node, or disconnects",
"Lock auto-expires after 60 seconds of inactivity as a safety measure",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 20,
"passes": false,
"notes": "Dependencies: US-045, US-048"
},
{
"id": "US-051",
"title": "Audit trail recording",
"description": "As a developer, I need all node and edge changes to be recorded in the audit trail so that users can review history and revert changes.",
"acceptanceCriteria": [
"Every node add/update/delete operation writes a record to audit_trail table",
"Every edge add/update/delete operation writes a record to audit_trail table",
"Records include previous_state (null for additions) and new_state (null for deletions)",
"Records include the acting user's ID and timestamp",
"Writes are batched/debounced to avoid excessive DB calls (max 1 write per second per entity)",
"Audit writes do not block the user's editing flow (fire-and-forget with error logging)",
"Typecheck passes"
],
"priority": 21,
"passes": false,
"notes": "Dependencies: US-043, US-048"
},
{
"id": "US-052",
"title": "Activity history sidebar",
"description": "As a user, I want to view a history of all changes made to the project so that I can see what collaborators have done and when.",
"acceptanceCriteria": [
"Add 'History' button to editor toolbar that opens a right sidebar panel",
"Sidebar displays a chronological list of changes with: user name, action type, entity description, timestamp",
"Entries are grouped by time period (Today, Yesterday, Earlier)",
"Each entry shows the user's presence color as an accent",
"Clicking an entry highlights/selects the affected node or edge on the canvas",
"Paginated loading (20 entries per page) with 'Load more' button",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 22,
"passes": false,
"notes": "Dependencies: US-051"
},
{
"id": "US-053",
"title": "Revert changes from audit trail",
"description": "As a user, I want to revert a specific change from the history so that I can undo mistakes made by myself or collaborators.",
"acceptanceCriteria": [
"Each entry in the activity history sidebar has a 'Revert' button",
"Clicking 'Revert' shows a confirmation dialog with before/after preview",
"Reverting a node addition deletes the node",
"Reverting a node update restores the previous state",
"Reverting a node deletion re-creates the node with its previous state",
"Reverting an edge change follows the same add/update/delete logic",
"The revert itself is recorded as a new audit trail entry",
"Reverted state is synced to all connected clients via CRDT",
"Typecheck passes",
"Verify in browser using dev-browser skill"
],
"priority": 23,
"passes": false,
"notes": "Dependencies: US-052, US-048"
}
]
}