qnce-engine 0.1.0 → 1.2.0

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 (53) hide show
  1. package/README.md +248 -0
  2. package/dist/cli/audit.js +6 -4
  3. package/dist/cli/audit.js.map +1 -1
  4. package/dist/cli/init.js +11 -9
  5. package/dist/cli/init.js.map +1 -1
  6. package/dist/cli/perf.d.ts +30 -0
  7. package/dist/cli/perf.d.ts.map +1 -0
  8. package/dist/cli/perf.js +219 -0
  9. package/dist/cli/perf.js.map +1 -0
  10. package/dist/engine/core.d.ts +104 -8
  11. package/dist/engine/core.d.ts.map +1 -1
  12. package/dist/engine/core.js +288 -7
  13. package/dist/engine/core.js.map +1 -1
  14. package/dist/engine/demo-story.js +4 -1
  15. package/dist/engine/demo-story.js.map +1 -1
  16. package/dist/index.js +24 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/narrative/branching/engine-simple.d.ts +84 -0
  19. package/dist/narrative/branching/engine-simple.d.ts.map +1 -0
  20. package/dist/narrative/branching/engine-simple.js +349 -0
  21. package/dist/narrative/branching/engine-simple.js.map +1 -0
  22. package/dist/narrative/branching/index.d.ts +12 -0
  23. package/dist/narrative/branching/index.d.ts.map +1 -0
  24. package/dist/narrative/branching/index.js +56 -0
  25. package/dist/narrative/branching/index.js.map +1 -0
  26. package/dist/narrative/branching/models.d.ts +223 -0
  27. package/dist/narrative/branching/models.d.ts.map +1 -0
  28. package/dist/narrative/branching/models.js +6 -0
  29. package/dist/narrative/branching/models.js.map +1 -0
  30. package/dist/performance/HotReloadDelta.d.ts +107 -0
  31. package/dist/performance/HotReloadDelta.d.ts.map +1 -0
  32. package/dist/performance/HotReloadDelta.js +333 -0
  33. package/dist/performance/HotReloadDelta.js.map +1 -0
  34. package/dist/performance/ObjectPool.d.ts +150 -0
  35. package/dist/performance/ObjectPool.d.ts.map +1 -0
  36. package/dist/performance/ObjectPool.js +297 -0
  37. package/dist/performance/ObjectPool.js.map +1 -0
  38. package/dist/performance/PerfReporter.d.ts +123 -0
  39. package/dist/performance/PerfReporter.d.ts.map +1 -0
  40. package/dist/performance/PerfReporter.js +281 -0
  41. package/dist/performance/PerfReporter.js.map +1 -0
  42. package/dist/performance/ThreadPool.d.ts +107 -0
  43. package/dist/performance/ThreadPool.d.ts.map +1 -0
  44. package/dist/performance/ThreadPool.js +348 -0
  45. package/dist/performance/ThreadPool.js.map +1 -0
  46. package/docs/PERFORMANCE.md +355 -0
  47. package/docs/branching/ERD.md +214 -0
  48. package/docs/branching/PDM.md +443 -0
  49. package/docs/branching/RELEASE-v1.2.0.md +169 -0
  50. package/examples/branching-advanced-demo.ts +339 -0
  51. package/examples/branching-quickstart.ts +314 -0
  52. package/examples/quickstart-demo.js +82 -0
  53. package/package.json +21 -8
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Core branching entities for dynamic narrative flow management
3
+ * Built on Sprint #2 performance infrastructure with object pooling support
4
+ */
5
+ import { NarrativeNode, QNCEState } from '../../engine/core';
6
+ /**
7
+ * Top-level story container with branching metadata
8
+ */
9
+ export interface QNCEStory {
10
+ id: string;
11
+ title: string;
12
+ version: string;
13
+ metadata: StoryMetadata;
14
+ chapters: Chapter[];
15
+ branchingConfig: BranchingConfig;
16
+ }
17
+ export interface StoryMetadata {
18
+ author: string;
19
+ description: string;
20
+ tags: string[];
21
+ createDate: Date;
22
+ lastModified: Date;
23
+ estimatedPlaytime: number;
24
+ }
25
+ export interface BranchingConfig {
26
+ maxActiveBranches: number;
27
+ branchCacheSize: number;
28
+ enableDynamicInsertion: boolean;
29
+ enableAnalytics: boolean;
30
+ performanceMode: boolean;
31
+ }
32
+ /**
33
+ * Chapter: Logical grouping of narrative flows with branching points
34
+ */
35
+ export interface Chapter {
36
+ id: string;
37
+ title: string;
38
+ description?: string;
39
+ flows: NarrativeFlow[];
40
+ branches: BranchPoint[];
41
+ prerequisites?: ChapterPrerequisites;
42
+ metadata: ChapterMetadata;
43
+ }
44
+ export interface ChapterPrerequisites {
45
+ requiredFlags: Record<string, unknown>;
46
+ requiredChoices: string[];
47
+ minPlaytime?: number;
48
+ }
49
+ export interface ChapterMetadata {
50
+ difficulty: 'easy' | 'medium' | 'hard';
51
+ themes: string[];
52
+ estimatedDuration: number;
53
+ branchComplexity: number;
54
+ }
55
+ /**
56
+ * NarrativeFlow: Sequence of connected nodes with entry/exit points
57
+ */
58
+ export interface NarrativeFlow {
59
+ id: string;
60
+ name: string;
61
+ description?: string;
62
+ nodes: NarrativeNode[];
63
+ entryPoints: FlowEntryPoint[];
64
+ exitPoints: FlowExitPoint[];
65
+ flowType: FlowType;
66
+ metadata: FlowMetadata;
67
+ }
68
+ export type FlowType = 'linear' | 'branching' | 'conditional' | 'procedural';
69
+ export interface FlowEntryPoint {
70
+ id: string;
71
+ nodeId: string;
72
+ conditions?: BranchCondition[];
73
+ priority: number;
74
+ }
75
+ export interface FlowExitPoint {
76
+ id: string;
77
+ nodeId: string;
78
+ targetFlowId?: string;
79
+ conditions?: BranchCondition[];
80
+ }
81
+ export interface FlowMetadata {
82
+ complexity: number;
83
+ avgCompletionTime: number;
84
+ playerChoiceCount: number;
85
+ aiGeneratedContent: boolean;
86
+ }
87
+ /**
88
+ * BranchPoint: Dynamic branching logic between flows
89
+ */
90
+ export interface BranchPoint {
91
+ id: string;
92
+ name: string;
93
+ sourceFlowId: string;
94
+ sourceNodeId: string;
95
+ branchOptions: BranchOption[];
96
+ branchType: BranchType;
97
+ conditions?: BranchCondition[];
98
+ metadata: BranchMetadata;
99
+ }
100
+ export type BranchType = 'choice-driven' | 'flag-conditional' | 'time-based' | 'procedural' | 'conditional';
101
+ export interface BranchOption {
102
+ id: string;
103
+ targetFlowId: string;
104
+ targetNodeId?: string;
105
+ displayText: string;
106
+ conditions?: BranchCondition[];
107
+ flagEffects?: Record<string, unknown>;
108
+ weight: number;
109
+ }
110
+ export interface BranchCondition {
111
+ type: 'flag' | 'choice' | 'time' | 'random' | 'custom';
112
+ operator: 'equals' | 'not_equals' | 'greater' | 'less' | 'contains' | 'exists';
113
+ key: string;
114
+ value: unknown;
115
+ evaluator?: (state: QNCEState, context: BranchContext) => boolean;
116
+ }
117
+ export interface BranchMetadata {
118
+ usageCount: number;
119
+ avgTraversalTime: number;
120
+ playerPreference: number;
121
+ lastUsed: Date;
122
+ }
123
+ /**
124
+ * BranchContext: Runtime state for branch evaluation and tracking
125
+ */
126
+ export interface BranchContext {
127
+ currentStory: QNCEStory;
128
+ currentChapter: Chapter;
129
+ currentFlow: NarrativeFlow;
130
+ activeState: QNCEState;
131
+ branchHistory: BranchHistoryEntry[];
132
+ pendingBranches: PendingBranch[];
133
+ analytics: BranchAnalytics;
134
+ }
135
+ export interface BranchHistoryEntry {
136
+ id: string;
137
+ branchPointId: string;
138
+ chosenOptionId: string;
139
+ timestamp: Date;
140
+ executionTime: number;
141
+ context: Partial<QNCEState>;
142
+ }
143
+ export interface PendingBranch {
144
+ id: string;
145
+ branchPointId: string;
146
+ triggerConditions: BranchCondition[];
147
+ timeoutMs?: number;
148
+ createdAt: Date;
149
+ }
150
+ export interface BranchAnalytics {
151
+ totalBranchesTraversed: number;
152
+ avgBranchDecisionTime: number;
153
+ mostPopularBranches: string[];
154
+ abandonmentPoints: string[];
155
+ completionRate: number;
156
+ sessionStartTime: Date;
157
+ }
158
+ /**
159
+ * Dynamic branching operations for runtime story modification
160
+ */
161
+ export interface DynamicBranchOperation {
162
+ type: 'insert' | 'remove' | 'modify';
163
+ branchId: string;
164
+ targetLocation: BranchLocation;
165
+ payload?: Partial<BranchPoint>;
166
+ conditions?: BranchCondition[];
167
+ }
168
+ export interface BranchLocation {
169
+ chapterId: string;
170
+ flowId: string;
171
+ nodeId: string;
172
+ insertionPoint: 'before' | 'after' | 'replace';
173
+ }
174
+ /**
175
+ * Dynamic flow insertion for procedural content
176
+ */
177
+ export interface DynamicFlowOperation {
178
+ type: 'insert' | 'remove' | 'modify';
179
+ flowId: string;
180
+ targetChapterId: string;
181
+ flow?: NarrativeFlow;
182
+ entryConditions?: BranchCondition[];
183
+ }
184
+ /**
185
+ * Pool-aware branch entities for performance optimization
186
+ */
187
+ export interface PooledBranchContext extends BranchContext {
188
+ poolId: string;
189
+ acquisitionTime: number;
190
+ maxLifetime: number;
191
+ }
192
+ export interface PooledBranchPoint extends BranchPoint {
193
+ poolId: string;
194
+ activeReferences: number;
195
+ lastAccessed: number;
196
+ }
197
+ /**
198
+ * Interfaces for AI-driven content generation and branching
199
+ */
200
+ export interface AIBranchingContext {
201
+ playerProfile: PlayerProfile;
202
+ narrativeContext: NarrativeContext;
203
+ generationHints: AIGenerationHints;
204
+ }
205
+ export interface PlayerProfile {
206
+ playStyle: 'explorer' | 'achiever' | 'socializer' | 'killer';
207
+ preferences: Record<string, number>;
208
+ historicalChoices: string[];
209
+ averageDecisionTime: number;
210
+ }
211
+ export interface NarrativeContext {
212
+ currentTone: string;
213
+ thematicElements: string[];
214
+ characterRelationships: Record<string, number>;
215
+ plotTension: number;
216
+ }
217
+ export interface AIGenerationHints {
218
+ maxBranchDepth: number;
219
+ desiredComplexity: number;
220
+ contentThemes: string[];
221
+ avoidElements: string[];
222
+ }
223
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../src/narrative/branching/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ // QNCE Branching System - Platform Data Model (PDM)
3
+ // Sprint #3 - Advanced Narrative & AI Integration
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ // All interfaces are exported above and ready for engine integration
6
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../src/narrative/branching/models.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,kDAAkD;;AAuRlD,qEAAqE"}
@@ -0,0 +1,107 @@
1
+ export interface StoryDelta {
2
+ nodeChanges: NodeDelta[];
3
+ assetChanges: AssetDelta[];
4
+ timestamp: number;
5
+ }
6
+ export interface NodeDelta {
7
+ nodeId: string;
8
+ changeType: 'added' | 'modified' | 'removed';
9
+ oldNode?: any;
10
+ newNode?: any;
11
+ affectedFields: string[];
12
+ }
13
+ export interface AssetDelta {
14
+ assetId: string;
15
+ changeType: 'added' | 'modified' | 'removed';
16
+ oldAsset?: any;
17
+ newAsset?: any;
18
+ sizeChange: number;
19
+ }
20
+ /**
21
+ * Delta Comparison Engine for Hot-Reload Story Updates
22
+ * Identifies minimal changes needed to update narrative content
23
+ */
24
+ export declare class StoryDeltaComparator {
25
+ /**
26
+ * Compare two story configurations and generate delta
27
+ */
28
+ compareStories(oldStory: any, newStory: any): StoryDelta;
29
+ /**
30
+ * Deep comparison of narrative nodes
31
+ */
32
+ private compareNodes;
33
+ /**
34
+ * Compare assets (future: images, audio, etc.)
35
+ */
36
+ private compareAssets;
37
+ /**
38
+ * Fine-grained field comparison for nodes
39
+ */
40
+ private findChangedFields;
41
+ /**
42
+ * Asset comparison logic
43
+ */
44
+ private assetsAreDifferent;
45
+ /**
46
+ * Deep equality check for objects
47
+ */
48
+ private deepEqual;
49
+ }
50
+ /**
51
+ * Hot-Reload Delta Patcher
52
+ * Applies story deltas with minimal engine disruption
53
+ */
54
+ export declare class StoryDeltaPatcher {
55
+ private engine;
56
+ constructor(engine: any);
57
+ /**
58
+ * Apply delta patch to running engine
59
+ * Target: <2ms frame stall for hot-reload
60
+ */
61
+ applyDelta(delta: StoryDelta): Promise<PatchResult>;
62
+ /**
63
+ * Validate delta is safe to apply
64
+ */
65
+ private validateDelta;
66
+ /**
67
+ * Apply node changes to story data
68
+ */
69
+ private applyNodeChanges;
70
+ /**
71
+ * Fast synchronous node changes for small deltas (no async overhead)
72
+ */
73
+ private applyNodeChangesFast;
74
+ /**
75
+ * Apply asset changes (placeholder for future implementation)
76
+ */
77
+ private applyAssetChanges;
78
+ /**
79
+ * Batch node changes by type for efficient processing
80
+ */
81
+ private batchNodeChanges;
82
+ /**
83
+ * Process a batch of node changes
84
+ */
85
+ private processBatch;
86
+ /**
87
+ * Apply individual node change
88
+ */
89
+ private applyNodeChange;
90
+ /**
91
+ * Refresh engine state after patch
92
+ */
93
+ private refreshEngineState;
94
+ }
95
+ export interface PatchResult {
96
+ success: boolean;
97
+ patchId: string;
98
+ duration: number;
99
+ nodesChanged?: number;
100
+ assetsChanged?: number;
101
+ error?: string;
102
+ }
103
+ export declare function createDeltaTools(engine: any): {
104
+ comparator: StoryDeltaComparator;
105
+ patcher: StoryDeltaPatcher;
106
+ };
107
+ //# sourceMappingURL=HotReloadDelta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HotReloadDelta.d.ts","sourceRoot":"","sources":["../../src/performance/HotReloadDelta.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IAC7C,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;IAC7C,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,oBAAoB;IAE/B;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,GAAG,UAAU;IAUxD;;OAEG;IACH,OAAO,CAAC,YAAY;IA+CpB;;OAEG;IACH,OAAO,CAAC,aAAa;IA4CrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;OAEG;IACH,OAAO,CAAC,SAAS;CAuBlB;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAM;gBAER,MAAM,EAAE,GAAG;IAIvB;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAmDzD;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;YACW,gBAAgB;IAS9B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;YACW,iBAAiB;IAK/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;YACW,YAAY;IAY1B;;OAEG;IACH,OAAO,CAAC,eAAe;IAgCvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAI3B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,GAAG;;;EAK3C"}
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ // S2-T3: Hot-Reload Delta Patching - Initial Spike
3
+ // Explore delta comparison logic for story content updates
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.StoryDeltaPatcher = exports.StoryDeltaComparator = void 0;
6
+ exports.createDeltaTools = createDeltaTools;
7
+ /**
8
+ * Delta Comparison Engine for Hot-Reload Story Updates
9
+ * Identifies minimal changes needed to update narrative content
10
+ */
11
+ class StoryDeltaComparator {
12
+ /**
13
+ * Compare two story configurations and generate delta
14
+ */
15
+ compareStories(oldStory, newStory) {
16
+ const timestamp = performance.now();
17
+ return {
18
+ nodeChanges: this.compareNodes(oldStory.nodes || [], newStory.nodes || []),
19
+ assetChanges: this.compareAssets(oldStory.assets || [], newStory.assets || []),
20
+ timestamp
21
+ };
22
+ }
23
+ /**
24
+ * Deep comparison of narrative nodes
25
+ */
26
+ compareNodes(oldNodes, newNodes) {
27
+ const deltas = [];
28
+ const oldNodeMap = new Map(oldNodes.map(n => [n.id, n]));
29
+ const newNodeMap = new Map(newNodes.map(n => [n.id, n]));
30
+ // Check for removed nodes
31
+ for (const [nodeId, oldNode] of oldNodeMap) {
32
+ if (!newNodeMap.has(nodeId)) {
33
+ deltas.push({
34
+ nodeId,
35
+ changeType: 'removed',
36
+ oldNode,
37
+ affectedFields: ['*']
38
+ });
39
+ }
40
+ }
41
+ // Check for added and modified nodes
42
+ for (const [nodeId, newNode] of newNodeMap) {
43
+ const oldNode = oldNodeMap.get(nodeId);
44
+ if (!oldNode) {
45
+ // New node
46
+ deltas.push({
47
+ nodeId,
48
+ changeType: 'added',
49
+ newNode,
50
+ affectedFields: ['*']
51
+ });
52
+ }
53
+ else {
54
+ // Check for modifications
55
+ const affectedFields = this.findChangedFields(oldNode, newNode);
56
+ if (affectedFields.length > 0) {
57
+ deltas.push({
58
+ nodeId,
59
+ changeType: 'modified',
60
+ oldNode,
61
+ newNode,
62
+ affectedFields
63
+ });
64
+ }
65
+ }
66
+ }
67
+ return deltas;
68
+ }
69
+ /**
70
+ * Compare assets (future: images, audio, etc.)
71
+ */
72
+ compareAssets(oldAssets, newAssets) {
73
+ const deltas = [];
74
+ const oldAssetMap = new Map(oldAssets.map(a => [a.id, a]));
75
+ const newAssetMap = new Map(newAssets.map(a => [a.id, a]));
76
+ // Check for removed assets
77
+ for (const [assetId, oldAsset] of oldAssetMap) {
78
+ if (!newAssetMap.has(assetId)) {
79
+ deltas.push({
80
+ assetId,
81
+ changeType: 'removed',
82
+ oldAsset,
83
+ sizeChange: -(oldAsset.size || 0)
84
+ });
85
+ }
86
+ }
87
+ // Check for added and modified assets
88
+ for (const [assetId, newAsset] of newAssetMap) {
89
+ const oldAsset = oldAssetMap.get(assetId);
90
+ if (!oldAsset) {
91
+ // New asset
92
+ deltas.push({
93
+ assetId,
94
+ changeType: 'added',
95
+ newAsset,
96
+ sizeChange: newAsset.size || 0
97
+ });
98
+ }
99
+ else if (this.assetsAreDifferent(oldAsset, newAsset)) {
100
+ // Modified asset
101
+ deltas.push({
102
+ assetId,
103
+ changeType: 'modified',
104
+ oldAsset,
105
+ newAsset,
106
+ sizeChange: (newAsset.size || 0) - (oldAsset.size || 0)
107
+ });
108
+ }
109
+ }
110
+ return deltas;
111
+ }
112
+ /**
113
+ * Fine-grained field comparison for nodes
114
+ */
115
+ findChangedFields(oldNode, newNode) {
116
+ const changedFields = [];
117
+ const allFields = new Set([...Object.keys(oldNode), ...Object.keys(newNode)]);
118
+ for (const field of allFields) {
119
+ if (!this.deepEqual(oldNode[field], newNode[field])) {
120
+ changedFields.push(field);
121
+ }
122
+ }
123
+ return changedFields;
124
+ }
125
+ /**
126
+ * Asset comparison logic
127
+ */
128
+ assetsAreDifferent(oldAsset, newAsset) {
129
+ // Simple comparison - in practice, would use checksums/hashes
130
+ return JSON.stringify(oldAsset) !== JSON.stringify(newAsset);
131
+ }
132
+ /**
133
+ * Deep equality check for objects
134
+ */
135
+ deepEqual(a, b) {
136
+ if (a === b)
137
+ return true;
138
+ if (a === null || b === null)
139
+ return false;
140
+ if (typeof a !== typeof b)
141
+ return false;
142
+ if (typeof a === 'object') {
143
+ if (Array.isArray(a) !== Array.isArray(b))
144
+ return false;
145
+ const keysA = Object.keys(a);
146
+ const keysB = Object.keys(b);
147
+ if (keysA.length !== keysB.length)
148
+ return false;
149
+ for (const key of keysA) {
150
+ if (!keysB.includes(key))
151
+ return false;
152
+ if (!this.deepEqual(a[key], b[key]))
153
+ return false;
154
+ }
155
+ return true;
156
+ }
157
+ return false;
158
+ }
159
+ }
160
+ exports.StoryDeltaComparator = StoryDeltaComparator;
161
+ /**
162
+ * Hot-Reload Delta Patcher
163
+ * Applies story deltas with minimal engine disruption
164
+ */
165
+ class StoryDeltaPatcher {
166
+ engine;
167
+ constructor(engine) {
168
+ this.engine = engine;
169
+ }
170
+ /**
171
+ * Apply delta patch to running engine
172
+ * Target: <2ms frame stall for hot-reload
173
+ */
174
+ async applyDelta(delta) {
175
+ const startTime = performance.now();
176
+ const patchId = `patch-${Date.now()}`;
177
+ try {
178
+ // Phase 1: Validate delta can be applied safely (sync, fast)
179
+ const validation = this.validateDelta(delta);
180
+ if (!validation.safe) {
181
+ return {
182
+ success: false,
183
+ patchId,
184
+ duration: performance.now() - startTime,
185
+ error: validation.error
186
+ };
187
+ }
188
+ // Phase 2: Apply changes synchronously for speed
189
+ // For small deltas (<10 changes), apply immediately
190
+ // For larger deltas, use optimized batch processing
191
+ if (delta.nodeChanges.length <= 10) {
192
+ this.applyNodeChangesFast(delta.nodeChanges);
193
+ }
194
+ else {
195
+ await this.applyNodeChanges(delta.nodeChanges);
196
+ }
197
+ // Phase 3: Skip asset changes for now (async operation)
198
+ // Assets can be updated in background without frame stall
199
+ // Phase 4: Minimal state refresh
200
+ this.refreshEngineState();
201
+ const duration = performance.now() - startTime;
202
+ return {
203
+ success: true,
204
+ patchId,
205
+ duration,
206
+ nodesChanged: delta.nodeChanges.length,
207
+ assetsChanged: delta.assetChanges.length
208
+ };
209
+ }
210
+ catch (error) {
211
+ return {
212
+ success: false,
213
+ patchId,
214
+ duration: performance.now() - startTime,
215
+ error: error instanceof Error ? error.message : 'Unknown error'
216
+ };
217
+ }
218
+ }
219
+ /**
220
+ * Validate delta is safe to apply
221
+ */
222
+ validateDelta(delta) {
223
+ // Check if current node would be affected
224
+ const currentNodeId = this.engine.getState().currentNodeId;
225
+ const currentNodeChange = delta.nodeChanges.find(c => c.nodeId === currentNodeId);
226
+ if (currentNodeChange && currentNodeChange.changeType === 'removed') {
227
+ return {
228
+ safe: false,
229
+ error: 'Cannot remove currently active node'
230
+ };
231
+ }
232
+ // Additional safety checks could go here
233
+ return { safe: true };
234
+ }
235
+ /**
236
+ * Apply node changes to story data
237
+ */
238
+ async applyNodeChanges(nodeChanges) {
239
+ // Batch node changes to minimize engine updates
240
+ const batches = this.batchNodeChanges(nodeChanges);
241
+ for (const batch of batches) {
242
+ await this.processBatch(batch);
243
+ }
244
+ }
245
+ /**
246
+ * Fast synchronous node changes for small deltas (no async overhead)
247
+ */
248
+ applyNodeChangesFast(nodeChanges) {
249
+ for (const change of nodeChanges) {
250
+ this.applyNodeChange(change);
251
+ }
252
+ }
253
+ /**
254
+ * Apply asset changes (placeholder for future implementation)
255
+ */
256
+ async applyAssetChanges(assetChanges) {
257
+ // Future: Implement asset hot-reload
258
+ console.log(`Would apply ${assetChanges.length} asset changes`);
259
+ }
260
+ /**
261
+ * Batch node changes by type for efficient processing
262
+ */
263
+ batchNodeChanges(nodeChanges) {
264
+ const batches = [];
265
+ const batchSize = 25; // Larger batch size for efficiency
266
+ for (let i = 0; i < nodeChanges.length; i += batchSize) {
267
+ batches.push(nodeChanges.slice(i, i + batchSize));
268
+ }
269
+ return batches;
270
+ }
271
+ /**
272
+ * Process a batch of node changes
273
+ */
274
+ async processBatch(batch) {
275
+ // Use requestAnimationFrame or setTimeout to yield control
276
+ return new Promise(resolve => {
277
+ setTimeout(() => {
278
+ for (const change of batch) {
279
+ this.applyNodeChange(change);
280
+ }
281
+ resolve();
282
+ }, 0);
283
+ });
284
+ }
285
+ /**
286
+ * Apply individual node change
287
+ */
288
+ applyNodeChange(change) {
289
+ // Access engine's internal story data
290
+ const storyData = this.engine.storyData;
291
+ switch (change.changeType) {
292
+ case 'added':
293
+ storyData.nodes.push(change.newNode);
294
+ break;
295
+ case 'removed':
296
+ const removeIndex = storyData.nodes.findIndex((n) => n.id === change.nodeId);
297
+ if (removeIndex >= 0) {
298
+ storyData.nodes.splice(removeIndex, 1);
299
+ }
300
+ break;
301
+ case 'modified':
302
+ const modifyIndex = storyData.nodes.findIndex((n) => n.id === change.nodeId);
303
+ if (modifyIndex >= 0) {
304
+ // Only update changed fields for minimal disruption
305
+ for (const field of change.affectedFields) {
306
+ if (field === '*') {
307
+ storyData.nodes[modifyIndex] = change.newNode;
308
+ }
309
+ else {
310
+ storyData.nodes[modifyIndex][field] = change.newNode[field];
311
+ }
312
+ }
313
+ }
314
+ break;
315
+ }
316
+ }
317
+ /**
318
+ * Refresh engine state after patch
319
+ */
320
+ refreshEngineState() {
321
+ // Minimal state refresh - avoid full reinitialization
322
+ // Future: Could trigger cache invalidation, UI updates, etc.
323
+ }
324
+ }
325
+ exports.StoryDeltaPatcher = StoryDeltaPatcher;
326
+ // Factory function for creating delta tools
327
+ function createDeltaTools(engine) {
328
+ return {
329
+ comparator: new StoryDeltaComparator(),
330
+ patcher: new StoryDeltaPatcher(engine)
331
+ };
332
+ }
333
+ //# sourceMappingURL=HotReloadDelta.js.map