qnce-engine 1.2.0 โ†’ 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +713 -7
  2. package/dist/cli/audit.js +0 -0
  3. package/dist/cli/init.js +0 -0
  4. package/dist/cli/perf.d.ts.map +1 -1
  5. package/dist/cli/perf.js +2 -1
  6. package/dist/cli/perf.js.map +1 -1
  7. package/dist/cli/play.d.ts +4 -0
  8. package/dist/cli/play.d.ts.map +1 -0
  9. package/dist/cli/play.js +259 -0
  10. package/dist/cli/play.js.map +1 -0
  11. package/dist/engine/condition.d.ts +69 -0
  12. package/dist/engine/condition.d.ts.map +1 -0
  13. package/dist/engine/condition.js +195 -0
  14. package/dist/engine/condition.js.map +1 -0
  15. package/dist/engine/core.d.ts +274 -3
  16. package/dist/engine/core.d.ts.map +1 -1
  17. package/dist/engine/core.js +1148 -9
  18. package/dist/engine/core.js.map +1 -1
  19. package/dist/engine/demo-story.d.ts.map +1 -1
  20. package/dist/engine/demo-story.js +99 -13
  21. package/dist/engine/demo-story.js.map +1 -1
  22. package/dist/engine/errors.d.ts +76 -0
  23. package/dist/engine/errors.d.ts.map +1 -0
  24. package/dist/engine/errors.js +178 -0
  25. package/dist/engine/errors.js.map +1 -0
  26. package/dist/engine/types.d.ts +445 -0
  27. package/dist/engine/types.d.ts.map +1 -0
  28. package/dist/engine/types.js +9 -0
  29. package/dist/engine/types.js.map +1 -0
  30. package/dist/engine/validation.d.ts +110 -0
  31. package/dist/engine/validation.d.ts.map +1 -0
  32. package/dist/engine/validation.js +261 -0
  33. package/dist/engine/validation.js.map +1 -0
  34. package/dist/examples/examples/autosave-undo-demo.js +248 -0
  35. package/dist/examples/examples/persistence-demo.js +63 -0
  36. package/dist/examples/src/engine/condition.js +194 -0
  37. package/dist/examples/src/engine/core.js +1382 -0
  38. package/dist/examples/src/engine/demo-story.js +200 -0
  39. package/dist/examples/src/engine/types.js +8 -0
  40. package/dist/examples/src/index.js +35 -0
  41. package/dist/examples/src/integrations/react.js +322 -0
  42. package/dist/examples/src/narrative/branching/engine-simple.js +348 -0
  43. package/dist/examples/src/narrative/branching/index.js +55 -0
  44. package/dist/examples/src/narrative/branching/models.js +5 -0
  45. package/dist/examples/src/performance/ObjectPool.js +296 -0
  46. package/dist/examples/src/performance/PerfReporter.js +280 -0
  47. package/dist/examples/src/performance/ThreadPool.js +347 -0
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +12 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/integrations/react.d.ts +200 -0
  53. package/dist/integrations/react.d.ts.map +1 -0
  54. package/dist/integrations/react.js +365 -0
  55. package/dist/integrations/react.js.map +1 -0
  56. package/dist/narrative/branching/engine-simple.js +3 -3
  57. package/dist/narrative/branching/engine-simple.js.map +1 -1
  58. package/dist/narrative/branching/engine.d.ts +1 -0
  59. package/dist/narrative/branching/engine.d.ts.map +1 -0
  60. package/dist/narrative/branching/engine.js +2 -0
  61. package/dist/narrative/branching/engine.js.map +1 -0
  62. package/dist/narrative/branching/models.d.ts.map +1 -1
  63. package/dist/performance/HotReloadDelta.d.ts +25 -8
  64. package/dist/performance/HotReloadDelta.d.ts.map +1 -1
  65. package/dist/performance/HotReloadDelta.js +10 -15
  66. package/dist/performance/HotReloadDelta.js.map +1 -1
  67. package/dist/ui/__tests__/AutosaveIndicator.test.d.ts +2 -0
  68. package/dist/ui/__tests__/AutosaveIndicator.test.d.ts.map +1 -0
  69. package/dist/ui/__tests__/AutosaveIndicator.test.js +329 -0
  70. package/dist/ui/__tests__/AutosaveIndicator.test.js.map +1 -0
  71. package/dist/ui/__tests__/UndoRedoControls.test.d.ts +2 -0
  72. package/dist/ui/__tests__/UndoRedoControls.test.d.ts.map +1 -0
  73. package/dist/ui/__tests__/UndoRedoControls.test.js +245 -0
  74. package/dist/ui/__tests__/UndoRedoControls.test.js.map +1 -0
  75. package/dist/ui/__tests__/autosave-simple.test.d.ts +2 -0
  76. package/dist/ui/__tests__/autosave-simple.test.d.ts.map +1 -0
  77. package/dist/ui/__tests__/autosave-simple.test.js +29 -0
  78. package/dist/ui/__tests__/autosave-simple.test.js.map +1 -0
  79. package/dist/ui/__tests__/setup.d.ts +2 -0
  80. package/dist/ui/__tests__/setup.d.ts.map +1 -0
  81. package/dist/ui/__tests__/setup.js +40 -0
  82. package/dist/ui/__tests__/setup.js.map +1 -0
  83. package/dist/ui/__tests__/smoke-test.d.ts +2 -0
  84. package/dist/ui/__tests__/smoke-test.d.ts.map +1 -0
  85. package/dist/ui/__tests__/smoke-test.js +18 -0
  86. package/dist/ui/__tests__/smoke-test.js.map +1 -0
  87. package/dist/ui/__tests__/smoke-test.test.d.ts +2 -0
  88. package/dist/ui/__tests__/smoke-test.test.d.ts.map +1 -0
  89. package/dist/ui/__tests__/smoke-test.test.js +18 -0
  90. package/dist/ui/__tests__/smoke-test.test.js.map +1 -0
  91. package/dist/ui/__tests__/useKeyboardShortcuts.test.d.ts +2 -0
  92. package/dist/ui/__tests__/useKeyboardShortcuts.test.d.ts.map +1 -0
  93. package/dist/ui/__tests__/useKeyboardShortcuts.test.js +374 -0
  94. package/dist/ui/__tests__/useKeyboardShortcuts.test.js.map +1 -0
  95. package/dist/ui/components/AutosaveIndicator.d.ts +18 -0
  96. package/dist/ui/components/AutosaveIndicator.d.ts.map +1 -0
  97. package/dist/ui/components/AutosaveIndicator.js +175 -0
  98. package/dist/ui/components/AutosaveIndicator.js.map +1 -0
  99. package/dist/ui/components/UndoRedoControls.d.ts +16 -0
  100. package/dist/ui/components/UndoRedoControls.d.ts.map +1 -0
  101. package/dist/ui/components/UndoRedoControls.js +144 -0
  102. package/dist/ui/components/UndoRedoControls.js.map +1 -0
  103. package/dist/ui/hooks/useKeyboardShortcuts.d.ts +22 -0
  104. package/dist/ui/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  105. package/dist/ui/hooks/useKeyboardShortcuts.js +162 -0
  106. package/dist/ui/hooks/useKeyboardShortcuts.js.map +1 -0
  107. package/dist/ui/index.d.ts +9 -0
  108. package/dist/ui/index.d.ts.map +1 -0
  109. package/dist/ui/index.js +14 -0
  110. package/dist/ui/index.js.map +1 -0
  111. package/dist/ui/types.d.ts +141 -0
  112. package/dist/ui/types.d.ts.map +1 -0
  113. package/dist/ui/types.js +51 -0
  114. package/dist/ui/types.js.map +1 -0
  115. package/examples/autosave-undo-demo.ts +306 -0
  116. package/examples/branching-demo-simple.ts +0 -0
  117. package/examples/branching-demo.ts +0 -0
  118. package/examples/persistence-demo.ts +84 -0
  119. package/examples/tsconfig.json +13 -0
  120. package/examples/ui-components-demo.tsx +320 -0
  121. package/examples/validation-demo-story.json +177 -0
  122. package/examples/validation-demo.js +163 -0
  123. package/package.json +23 -3
package/README.md CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  **Quantum Narrative Convergence Engine** - A framework-agnostic TypeScript library for creating interactive narrative experiences with quantum-inspired mechanics.
4
4
 
5
- > **๐Ÿš€ NEW in v1.2.0:** Advanced Branching API with AI integration, dynamic content management, and comprehensive analytics. Plus enterprise-grade performance optimization.
5
+ > **๐Ÿš€ NEW in v1.2.0:** Complete state persistence, advanced branching with AI integration, autosave & undo/redo system, conditional choice display, and comprehensive UI components with React integration.
6
+
7
+ [![npm version](https://badge.fury.io/js/qnce-engine.svg)](https://badge.fury.io/js/qnce-engine)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
10
 
7
11
  ## Core Concepts
8
12
 
@@ -10,7 +14,13 @@
10
14
  - **Collapse:** Player choices "collapse" the narrative to a specific path, updating state and flags
11
15
  - **Entanglement:** Early decisions affect later outcomes, enabling complex, interconnected stories
12
16
 
13
- ## โœจ Advanced Features (v1.2.0)
17
+ ## โœจ What's New in v1.2.0
18
+
19
+ ### ๐Ÿ’พ State Persistence & Checkpoints
20
+ - **Complete save/load system** with data integrity validation
21
+ - **Lightweight checkpoints** for undo/redo functionality
22
+ - **Automatic state serialization** with metadata and versioning
23
+ - **Migration support** for upgrading saved states between versions
14
24
 
15
25
  ### ๐ŸŒฟ Advanced Branching System
16
26
  - **Multi-path narratives** with conditional logic and flag-based branching
@@ -18,6 +28,197 @@
18
28
  - **Real-time branch insertion/removal** for live content updates
19
29
  - **Comprehensive analytics** for narrative optimization
20
30
 
31
+ ### ๐Ÿ”„ Autosave & Undo/Redo System
32
+ - **Intelligent state tracking** with automatic snapshots on key events
33
+ - **Sub-millisecond undo/redo operations** with configurable history depth
34
+ - **Autosave throttling** prevents excessive saves during rapid changes
35
+ - **Memory efficient** with automatic cleanup and history limits
36
+
37
+ ### ๐ŸŽฏ Conditional Choice Display
38
+ - **Flag-based choice filtering** with complex logical expressions
39
+ - **Custom validation rules** for advanced choice availability
40
+ - **Real-time choice updates** based on dynamic game state
41
+ - **Intuitive condition syntax** supporting multiple data types
42
+
43
+ ### ๐Ÿ–ฅ๏ธ UI Integration & React Components
44
+ - **Ready-to-use React components** for common UI patterns
45
+ - **Keyboard shortcuts** with customizable bindings
46
+ - **Accessibility features** with ARIA support and screen reader compatibility
47
+ - **Theming system** with customizable appearance
48
+
49
+ ### โšก Enterprise Performance
50
+ - **Object pooling** reduces memory allocations by 90%+
51
+ - **Background processing** for non-blocking operations
52
+ - **Hot-reload capabilities** with <3.5ms story updates
53
+ - **Comprehensive monitoring** with built-in CLI tools
54
+
55
+ #### Basic Flag-Based Conditions
56
+
57
+ ```typescript
58
+ import { createQNCEEngine } from 'qnce-engine';
59
+
60
+ const storyData = {
61
+ currentNodeId: 'town-square',
62
+ nodes: {
63
+ 'town-square': {
64
+ id: 'town-square',
65
+ text: 'You stand in the bustling town square.',
66
+ choices: [
67
+ {
68
+ id: 'enter-tavern',
69
+ text: 'Enter the tavern',
70
+ nextNodeId: 'tavern-inside'
71
+ },
72
+ {
73
+ id: 'approach-guard',
74
+ text: 'Approach the suspicious guard',
75
+ nextNodeId: 'guard-encounter',
76
+ condition: 'flags.curiosity >= 3' // Only show if curious enough
77
+ },
78
+ {
79
+ id: 'use-disguise',
80
+ text: 'Use your disguise to blend in',
81
+ nextNodeId: 'disguised-approach',
82
+ condition: 'flags.hasDisguise && !flags.disguiseUsed'
83
+ }
84
+ ]
85
+ }
86
+ },
87
+ flags: {}
88
+ };
89
+
90
+ const engine = createQNCEEngine(storyData);
91
+
92
+ // Set flags to test conditional choices
93
+ engine.setFlag('curiosity', 4);
94
+ engine.setFlag('hasDisguise', true);
95
+
96
+ // Get available choices - only those meeting conditions
97
+ const choices = engine.getAvailableChoices();
98
+ console.log(`Available choices: ${choices.length}`); // Shows 3 choices
99
+
100
+ // Change flags to see different options
101
+ engine.setFlag('curiosity', 1); // Below threshold
102
+ const reducedChoices = engine.getAvailableChoices();
103
+ console.log(`Available choices: ${reducedChoices.length}`); // Shows 2 choices
104
+ ```
105
+
106
+ #### Complex Conditional Expressions
107
+
108
+ ```typescript
109
+ const complexStory = {
110
+ currentNodeId: 'critical-moment',
111
+ nodes: {
112
+ 'critical-moment': {
113
+ id: 'critical-moment',
114
+ text: 'The fate of the kingdom hangs in the balance.',
115
+ choices: [
116
+ {
117
+ id: 'diplomatic-solution',
118
+ text: 'Attempt diplomatic negotiation',
119
+ nextNodeId: 'peaceful-resolution',
120
+ condition: 'flags.charisma >= 5 && flags.hasAlliance'
121
+ },
122
+ {
123
+ id: 'magical-intervention',
124
+ text: 'Cast the ancient spell',
125
+ nextNodeId: 'magical-outcome',
126
+ condition: 'flags.magicPower > 3 && flags.spellComponents >= 2 && !flags.cursed'
127
+ },
128
+ {
129
+ id: 'time-limited-escape',
130
+ text: 'Escape through the secret passage',
131
+ nextNodeId: 'secret-escape',
132
+ condition: 'context.timeElapsed < 300 && flags.knowsSecretPath'
133
+ },
134
+ {
135
+ id: 'sacrifice-play',
136
+ text: 'Make the ultimate sacrifice',
137
+ nextNodeId: 'heroic-end',
138
+ condition: '(flags.loyalty >= 8 || flags.desperate) && flags.hasArtifact'
139
+ }
140
+ ]
141
+ }
142
+ },
143
+ flags: {}
144
+ };
145
+ ```
146
+
147
+ #### Custom Condition Evaluators
148
+
149
+ For advanced scenarios, you can provide custom logic for condition evaluation:
150
+
151
+ ```typescript
152
+ // Set up custom evaluator for complex game logic
153
+ engine.setConditionEvaluator((expression, context) => {
154
+ // Custom logic for special conditions
155
+ if (expression === 'canUseSpecialAbility') {
156
+ return context.flags.level >= 10 &&
157
+ context.flags.mana > 50 &&
158
+ !context.flags.abilityOnCooldown;
159
+ }
160
+
161
+ if (expression.startsWith('inventory:')) {
162
+ const itemName = expression.replace('inventory:', '');
163
+ return context.flags[`has_${itemName}`] === true;
164
+ }
165
+
166
+ // Fall back to default expression evaluation
167
+ return null;
168
+ });
169
+
170
+ // Use custom conditions in story
171
+ const storyWithCustom = {
172
+ currentNodeId: 'boss-fight',
173
+ nodes: {
174
+ 'boss-fight': {
175
+ id: 'boss-fight',
176
+ text: 'The dragon roars menacingly.',
177
+ choices: [
178
+ {
179
+ id: 'special-attack',
180
+ text: 'Use your special ability',
181
+ nextNodeId: 'special-victory',
182
+ condition: 'canUseSpecialAbility'
183
+ },
184
+ {
185
+ id: 'use-potion',
186
+ text: 'Drink healing potion',
187
+ nextNodeId: 'healed-state',
188
+ condition: 'inventory:healing_potion'
189
+ }
190
+ ]
191
+ }
192
+ }
193
+ };
194
+ ```
195
+
196
+ #### Condition Validation & Debugging
197
+
198
+ ```typescript
199
+ // Validate conditions during development
200
+ try {
201
+ engine.validateCondition('flags.strength >= 5 && flags.weapon');
202
+ console.log('Condition is valid');
203
+ } catch (error) {
204
+ console.error('Invalid condition:', error.message);
205
+ }
206
+
207
+ // Get flags referenced in a condition for debugging
208
+ const referencedFlags = engine.getConditionFlags('flags.curiosity >= 3 && flags.hasKey');
209
+ console.log('Referenced flags:', referencedFlags); // ['curiosity', 'hasKey']
210
+
211
+ // Clear custom evaluator
212
+ engine.clearConditionEvaluator();
213
+ ```
214
+
215
+ #### Performance Considerations
216
+
217
+ - **Expression Caching:** Conditions are compiled once and cached for subsequent evaluations
218
+ - **Safe Evaluation:** All expressions are sanitized to prevent code injection
219
+ - **Minimal Overhead:** Choice filtering adds <1ms to `getAvailableChoices()` calls
220
+ - **Error Isolation:** Invalid conditions don't affect other choices in the same node
221
+
21
222
  ### โšก Performance Infrastructure
22
223
  - **๐ŸŠโ€โ™‚๏ธ Object Pooling:** 90%+ allocation reduction, eliminating GC pressure
23
224
  - **๐Ÿงต Background Processing:** Non-blocking cache preloading and telemetry writes
@@ -96,6 +297,129 @@ const poolStats = engine.getPoolStats();
96
297
  console.log(`Pool efficiency: ${poolStats.flow.hitRate}%`);
97
298
  ```
98
299
 
300
+ ### ๐Ÿ’พ State Persistence & Checkpoints
301
+
302
+ QNCE Engine provides robust state persistence and checkpointing, allowing you to save and load the complete narrative state. This is useful for implementing save games, undo/redo functionality, and scenario replay.
303
+
304
+ **Key Features:**
305
+ - **Full State Serialization:** Save and load the entire engine state, including narrative position, flags, history, and branching context.
306
+ - **Lightweight Checkpoints:** Create fast, in-memory snapshots for undo operations or temporary state saves.
307
+ - **Data Integrity:** Optional checksum verification ensures that saved data is not corrupted.
308
+ - **Cross-Version Compatibility:** A migration system helps upgrade older save states to the latest version.
309
+
310
+ **Example Usage:**
311
+
312
+ ```typescript
313
+ import { createQNCEEngine, DEMO_STORY } from 'qnce-engine';
314
+
315
+ const engine = createQNCEEngine(DEMO_STORY);
316
+
317
+ // ...progress through the story...
318
+ const choices = engine.getAvailableChoices();
319
+ if (choices.length > 0) {
320
+ engine.selectChoice(choices[0]);
321
+ }
322
+
323
+
324
+ // Save the current state to a JSON string
325
+ const savedState = await engine.saveState();
326
+ console.log('State saved!');
327
+
328
+ // ...later, or in a new session...
329
+
330
+ // Create a new engine instance
331
+ const newEngine = createQNCEEngine(DEMO_STORY);
332
+
333
+ // Load the state
334
+ await newEngine.loadState(JSON.parse(savedState));
335
+
336
+ console.log('State loaded successfully!');
337
+ console.log('Current Node:', newEngine.getCurrentNode().text);
338
+
339
+ // Create a lightweight checkpoint
340
+ const checkpoint = await engine.createCheckpoint('Before a risky choice');
341
+
342
+ // ...make a choice...
343
+
344
+ // Restore to the checkpoint
345
+ await engine.restoreFromCheckpoint(checkpoint.id);
346
+ console.log('Restored to checkpoint:', engine.getCurrentNode().text);
347
+ ```
348
+
349
+ ### ๐Ÿ”„ Autosave & Undo/Redo System
350
+
351
+ QNCE Engine v1.2.0 introduces an advanced autosave and undo/redo system that automatically tracks state changes and provides instant rollback capabilities with sub-millisecond performance.
352
+
353
+ **Key Features:**
354
+ - **Automatic State Tracking:** Intelligently captures state snapshots on key events (choice selection, flag changes, state loading)
355
+ - **High-Performance Undo/Redo:** Sub-millisecond undo/redo operations with configurable history depth
356
+ - **Autosave Throttling:** Configurable throttling prevents excessive saves during rapid state changes
357
+ - **Memory Efficient:** Capped history with automatic cleanup of older entries
358
+
359
+ **Basic Usage:**
360
+
361
+ ```typescript
362
+ import { createQNCEEngine, DEMO_STORY } from 'qnce-engine';
363
+
364
+ const engine = createQNCEEngine(DEMO_STORY);
365
+
366
+ // Autosave is enabled by default and will track state changes automatically
367
+ console.log('Can undo:', engine.canUndo()); // false initially
368
+
369
+ // Make some choices (autosave will track each change)
370
+ const choices = engine.getAvailableChoices();
371
+ engine.selectChoice(choices[0]);
372
+
373
+ console.log('Can undo:', engine.canUndo()); // true after making a choice
374
+
375
+ // Undo the last action
376
+ const undoResult = engine.undo();
377
+ if (undoResult.success) {
378
+ console.log('Undid:', undoResult.description);
379
+ console.log('Can redo:', engine.canRedo()); // true
380
+ }
381
+
382
+ // Redo the undone action
383
+ const redoResult = engine.redo();
384
+ if (redoResult.success) {
385
+ console.log('Redid:', redoResult.description);
386
+ }
387
+
388
+ // Get history summary
389
+ const history = engine.getHistorySummary();
390
+ console.log(`History: ${history.undoCount} undo, ${history.redoCount} redo entries`);
391
+ ```
392
+
393
+ **Advanced Configuration:**
394
+
395
+ ```typescript
396
+ // Configure undo/redo system
397
+ engine.configureUndoRedo({
398
+ maxUndoEntries: 100, // Maximum undo operations to remember
399
+ maxRedoEntries: 50, // Maximum redo operations to remember
400
+ enabled: true // Enable/disable undo/redo tracking
401
+ });
402
+
403
+ // Configure autosave behavior
404
+ engine.configureAutosave({
405
+ enabled: true, // Enable/disable autosave
406
+ throttleMs: 100, // Minimum time between saves (milliseconds)
407
+ events: ['choice', 'flag', 'load'] // Which events trigger autosave
408
+ });
409
+
410
+ // Manual autosave trigger
411
+ await engine.autosave();
412
+
413
+ // Clear all undo/redo history
414
+ engine.clearHistory();
415
+ ```
416
+
417
+ **Performance Guarantees:**
418
+ - Undo operations: <1ms for normal state
419
+ - Redo operations: <1ms for normal state
420
+ - Autosave overhead: <1ms per operation
421
+ - Memory efficient with configurable history limits
422
+
99
423
  ### Live Performance Monitoring
100
424
 
101
425
  ```bash
@@ -269,6 +593,7 @@ The main engine class for managing narrative state.
269
593
  #### Methods
270
594
 
271
595
  - `getCurrentNode()`: Get the current narrative node
596
+ - `goToNodeById(nodeId)`: Navigate directly to a node by its ID
272
597
  - `getState()`: Get the complete engine state
273
598
  - `getFlags()`: Get current narrative flags
274
599
  - `getHistory()`: Get choice history
@@ -335,26 +660,267 @@ Creates:
335
660
  - package.json with QNCE dependencies
336
661
  - README with usage instructions
337
662
 
663
+ ### qnce-play
664
+
665
+ Interactive narrative sessions with full undo/redo support:
666
+
667
+ ```bash
668
+ qnce-play story.json
669
+ ```
670
+
671
+ Features:
672
+ - Real-time narrative playthrough
673
+ - Instant undo/redo with `u` and `r` commands
674
+ - State inspection and debugging
675
+ - Performance monitoring
676
+ - Session save/load functionality
677
+
678
+ ### qnce-perf
679
+
680
+ **NEW in v1.2.0:** Real-time performance monitoring and analytics:
681
+
682
+ ```bash
683
+ # Launch interactive performance dashboard
684
+ qnce-perf dashboard
685
+
686
+ # Live monitoring with custom update interval
687
+ qnce-perf live [interval-ms]
688
+
689
+ # Export performance data to JSON
690
+ qnce-perf export [--format json|csv] [--output filename]
691
+
692
+ # Single performance snapshot
693
+ qnce-perf snapshot story.json
694
+ ```
695
+
696
+ **Dashboard Features:**
697
+ - Real-time memory usage and allocation tracking
698
+ - Object pool efficiency monitoring
699
+ - Performance hotspot identification
700
+ - Live story update timing analysis
701
+ - Historical performance trend graphs
702
+
703
+ **Live Monitoring:**
704
+ ```bash
705
+ # Monitor with 1-second updates
706
+ qnce-perf live 1000
707
+
708
+ # Default 500ms updates
709
+ qnce-perf live
710
+ ```
711
+
712
+ **Export Options:**
713
+ ```bash
714
+ # Export to JSON with full metrics
715
+ qnce-perf export --format json --output metrics.json
716
+
717
+ # Export to CSV for spreadsheet analysis
718
+ qnce-perf export --format csv --output performance.csv
719
+
720
+ # Stream to stdout
721
+ qnce-perf export
722
+ ```
723
+
338
724
  ## Integration Examples
339
725
 
340
- ### React Hook
726
+ ### React Hooks
727
+
728
+ QNCE provides comprehensive React hooks for seamless integration:
341
729
 
342
730
  ```typescript
731
+ import { useQNCE, useUndoRedo, useAutosave } from 'qnce-engine/react';
732
+ import { DEMO_STORY } from 'qnce-engine';
733
+
734
+ function NarrativeComponent() {
735
+ // Core narrative hook
736
+ const { engine, currentNode, choices, flags, selectChoice, resetNarrative } = useQNCE(DEMO_STORY);
737
+
738
+ // Undo/redo functionality
739
+ const {
740
+ undo,
741
+ redo,
742
+ canUndo,
743
+ canRedo,
744
+ undoCount,
745
+ redoCount,
746
+ clearHistory
747
+ } = useUndoRedo(engine);
748
+
749
+ // Autosave status
750
+ const { isAutosaveEnabled, lastAutosave } = useAutosave(engine);
751
+
752
+ return (
753
+ <div>
754
+ <h2>Current Scene</h2>
755
+ <p>{currentNode.text}</p>
756
+
757
+ <h3>Choices</h3>
758
+ {choices.map((choice, index) => (
759
+ <button key={index} onClick={() => selectChoice(choice)}>
760
+ {choice.text}
761
+ </button>
762
+ ))}
763
+
764
+ <div className="controls">
765
+ <button onClick={undo} disabled={!canUndo}>
766
+ Undo ({undoCount})
767
+ </button>
768
+ <button onClick={redo} disabled={!canRedo}>
769
+ Redo ({redoCount})
770
+ </button>
771
+ <button onClick={resetNarrative}>Reset</button>
772
+ <button onClick={clearHistory}>Clear History</button>
773
+ </div>
774
+
775
+ <div className="status">
776
+ <p>Autosave: {isAutosaveEnabled ? 'Enabled' : 'Disabled'}</p>
777
+ {lastAutosave && <p>Last saved: {lastAutosave.toLocaleTimeString()}</p>}
778
+ </div>
779
+
780
+ <details>
781
+ <summary>Debug Info</summary>
782
+ <pre>{JSON.stringify(flags, null, 2)}</pre>
783
+ </details>
784
+ </div>
785
+ );
786
+ }
787
+ ```
788
+
789
+ ### React UI Components
790
+
791
+ QNCE provides pre-built React components for common UI patterns:
792
+
793
+ #### UndoRedoControls Component
794
+
795
+ A complete undo/redo control panel with accessibility features:
796
+
797
+ ```typescript
798
+ import { UndoRedoControls } from 'qnce-engine/ui';
343
799
  import { createQNCEEngine } from 'qnce-engine';
344
- import { useState, useEffect } from 'react';
800
+
801
+ function MyApp() {
802
+ const engine = createQNCEEngine(DEMO_STORY);
803
+
804
+ return (
805
+ <div>
806
+ {/* Narrative content */}
807
+
808
+ {/* Undo/Redo Controls */}
809
+ <UndoRedoControls
810
+ engine={engine}
811
+ size="md" // sm, md, lg
812
+ layout="horizontal" // horizontal, vertical
813
+ showLabels={true} // Show text labels
814
+ labels={{ // Custom labels
815
+ undo: "Go Back",
816
+ redo: "Go Forward"
817
+ }}
818
+ onUndo={(result) => console.log('Undo:', result)}
819
+ onRedo={(result) => console.log('Redo:', result)}
820
+ theme={{ // Custom theming
821
+ colors: {
822
+ primary: '#007bff',
823
+ disabled: '#6c757d'
824
+ },
825
+ borderRadius: { md: '8px' }
826
+ }}
827
+ />
828
+ </div>
829
+ );
830
+ }
831
+ ```
832
+
833
+ #### AutosaveIndicator Component
834
+
835
+ Visual indicator for autosave status with animations:
836
+
837
+ ```typescript
838
+ import { AutosaveIndicator } from 'qnce-engine/ui';
839
+
840
+ function MyApp() {
841
+ const engine = createQNCEEngine(DEMO_STORY);
842
+
843
+ return (
844
+ <div>
845
+ {/* Narrative content */}
846
+
847
+ {/* Autosave Status */}
848
+ <AutosaveIndicator
849
+ engine={engine}
850
+ variant="detailed" // minimal, detailed, icon-only
851
+ position="top-right" // inline, top-right, bottom-left, etc.
852
+ showTimestamp={true} // Show last save time
853
+ autoHideDelay={3000} // Auto-hide after 3 seconds
854
+ messages={{ // Custom messages
855
+ idle: "Ready to save",
856
+ saving: "Saving...",
857
+ saved: "All changes saved",
858
+ error: "Save failed"
859
+ }}
860
+ theme={{ // Custom theming
861
+ colors: {
862
+ success: '#28a745',
863
+ error: '#dc3545',
864
+ warning: '#ffc107'
865
+ }
866
+ }}
867
+ />
868
+ </div>
869
+ );
870
+ }
871
+ ```
872
+
873
+ #### Keyboard Shortcuts
874
+
875
+ Built-in keyboard support with the `useKeyboardShortcuts` hook:
876
+
877
+ ```typescript
878
+ import { useKeyboardShortcuts } from 'qnce-engine/ui';
879
+
880
+ function MyApp() {
881
+ const engine = createQNCEEngine(DEMO_STORY);
882
+
883
+ // Enable keyboard shortcuts
884
+ useKeyboardShortcuts(engine, {
885
+ undo: ['ctrl+z', 'cmd+z'], // Undo shortcuts
886
+ redo: ['ctrl+y', 'cmd+shift+z'], // Redo shortcuts
887
+ save: ['ctrl+s', 'cmd+s'], // Manual save
888
+ disabled: false // Enable/disable all shortcuts
889
+ });
890
+
891
+ return (
892
+ <div>
893
+ {/* Your narrative UI */}
894
+ <p>Press Ctrl+Z to undo, Ctrl+Y to redo, Ctrl+S to save</p>
895
+ </div>
896
+ );
897
+ }
898
+ ```
899
+
900
+ ### Basic React Hook (Legacy)
901
+
902
+ ```typescript
903
+ import { createQNCEEngine } from 'qnce-engine';
904
+ import { useState, useCallback } from 'react';
345
905
 
346
906
  function useQNCE(storyData) {
347
907
  const [engine] = useState(() => createQNCEEngine(storyData));
348
908
  const [currentNode, setCurrentNode] = useState(engine.getCurrentNode());
349
909
  const [flags, setFlags] = useState(engine.getFlags());
350
910
 
351
- const selectChoice = (choice) => {
911
+ const selectChoice = useCallback((choice) => {
352
912
  engine.selectChoice(choice);
353
913
  setCurrentNode(engine.getCurrentNode());
354
914
  setFlags(engine.getFlags());
355
- };
915
+ }, [engine]);
356
916
 
357
- return { currentNode, flags, selectChoice };
917
+ const goToNodeById = useCallback((nodeId) => {
918
+ engine.goToNodeById(nodeId);
919
+ setCurrentNode(engine.getCurrentNode());
920
+ setFlags(engine.getFlags());
921
+ }, [engine]);
922
+
923
+ return { currentNode, flags, selectChoice, goToNodeById };
358
924
  }
359
925
  ```
360
926
 
@@ -424,6 +990,12 @@ The repository includes comprehensive examples demonstrating all features:
424
990
  - **Features:** Complex narrative flows, conditional branching, analytics
425
991
  - **Story:** "The Mysterious Library" - Interactive mystery with multiple paths
426
992
 
993
+ ### ๐Ÿ’พ Autosave & Undo Demo (NEW in v1.2.0)
994
+ - **File:** `examples/autosave-undo-demo.ts`
995
+ - **Features:** Autosave, undo/redo, performance monitoring, state management
996
+ - **Run:** `npm run demo:autosave`
997
+ - **Performance:** Demonstrates <1ms undo/redo with real-time metrics
998
+
427
999
  ### ๐Ÿงช Validation Scripts
428
1000
  - **Real-world testing:** `scripts/validation-real-world.ts`
429
1001
  - **Comprehensive testing:** `scripts/validation-comprehensive.ts`
@@ -433,6 +1005,13 @@ The repository includes comprehensive examples demonstrating all features:
433
1005
  npm run build
434
1006
  node dist/examples/branching-quickstart.js
435
1007
 
1008
+ # Run the new autosave demo
1009
+ npm run demo:autosave
1010
+
1011
+ # Try the interactive CLI tool
1012
+ npm run build
1013
+ qnce-play examples/demo-story.json
1014
+
436
1015
  # Run validation tests
437
1016
  npm run build
438
1017
  node dist/scripts/validation-real-world.js
@@ -471,3 +1050,130 @@ MIT - See LICENSE file for details.
471
1050
  ---
472
1051
 
473
1052
  **QNCE Engine** - Empowering interactive narratives with quantum-inspired mechanics.
1053
+
1054
+ ## ๐Ÿ›ก๏ธ Choice Validation System
1055
+
1056
+ Ensure only valid choices can be executed with comprehensive validation rules.
1057
+
1058
+ ### Basic Validation
1059
+
1060
+ ```typescript
1061
+ import { createQNCEEngine } from 'qnce-engine';
1062
+
1063
+ const engine = createQNCEEngine(storyData);
1064
+
1065
+ try {
1066
+ // makeChoice() automatically validates before executing
1067
+ engine.makeChoice(0);
1068
+ } catch (error) {
1069
+ if (error instanceof ChoiceValidationError) {
1070
+ console.error('Invalid choice:', error.message);
1071
+ console.log('Available choices:', error.availableChoices);
1072
+ }
1073
+ }
1074
+ ```
1075
+
1076
+ ### Advanced Choice Requirements
1077
+
1078
+ Define complex validation rules on your choices:
1079
+
1080
+ ```typescript
1081
+ // Choice with flag requirements
1082
+ const flagBasedChoice = {
1083
+ text: 'Use the magic key',
1084
+ nextNodeId: 'unlock_door',
1085
+ flagRequirements: {
1086
+ hasKey: true,
1087
+ playerLevel: 5
1088
+ }
1089
+ };
1090
+
1091
+ // Choice with inventory requirements
1092
+ const inventoryChoice = {
1093
+ text: 'Buy expensive sword',
1094
+ nextNodeId: 'shop_success',
1095
+ inventoryRequirements: {
1096
+ gold: 1000,
1097
+ gems: 2
1098
+ }
1099
+ };
1100
+
1101
+ // Time-based availability
1102
+ const timedChoice = {
1103
+ text: 'Enter the tavern',
1104
+ nextNodeId: 'tavern',
1105
+ timeRequirements: {
1106
+ availableAfter: new Date('2025-01-01T18:00:00'),
1107
+ availableBefore: new Date('2025-01-01T24:00:00')
1108
+ }
1109
+ };
1110
+
1111
+ // Disabled choice
1112
+ const disabledChoice = {
1113
+ text: 'Broken bridge',
1114
+ nextNodeId: 'fall',
1115
+ enabled: false
1116
+ };
1117
+ ```
1118
+
1119
+ ### Custom Validation Rules
1120
+
1121
+ Create your own validation logic:
1122
+
1123
+ ```typescript
1124
+ import {
1125
+ StandardValidationRules,
1126
+ createChoiceValidator
1127
+ } from 'qnce-engine';
1128
+
1129
+ const validator = createChoiceValidator();
1130
+
1131
+ // Add custom rule
1132
+ validator.addRule({
1133
+ name: 'custom-rule',
1134
+ priority: 10,
1135
+ validate: (choice, context) => {
1136
+ // Your custom logic
1137
+ if (choice.text.includes('danger') && !context.state.flags.brave) {
1138
+ return {
1139
+ isValid: false,
1140
+ reason: 'You must be brave to take this path!',
1141
+ failedConditions: ['requires-bravery']
1142
+ };
1143
+ }
1144
+ return { isValid: true };
1145
+ }
1146
+ });
1147
+
1148
+ // Apply to engine
1149
+ engine.setChoiceValidator(validator);
1150
+ ```
1151
+
1152
+ ### Validation Error Handling
1153
+
1154
+ ```typescript
1155
+ import {
1156
+ ChoiceValidationError,
1157
+ isChoiceValidationError
1158
+ } from 'qnce-engine';
1159
+
1160
+ try {
1161
+ engine.makeChoice(2);
1162
+ } catch (error) {
1163
+ if (isChoiceValidationError(error)) {
1164
+ // Get user-friendly message
1165
+ const message = error.getUserFriendlyMessage();
1166
+ console.log(message);
1167
+
1168
+ // Get debug information
1169
+ const debugInfo = error.getDebugInfo();
1170
+ console.log('Failed conditions:', debugInfo.validationResult.failedConditions);
1171
+
1172
+ // Show alternatives
1173
+ console.log('Available choices:');
1174
+ error.availableChoices?.forEach((choice, i) => {
1175
+ console.log(`${i + 1}. ${choice.text}`);
1176
+ });
1177
+ }
1178
+ }
1179
+ ```