ava-langgraph-narrative-intelligence 0.1.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.
- package/README.md +268 -0
- package/dist/graphs/index.cjs +1511 -0
- package/dist/graphs/index.cjs.map +1 -0
- package/dist/graphs/index.d.cts +2 -0
- package/dist/graphs/index.d.ts +2 -0
- package/dist/graphs/index.js +1468 -0
- package/dist/graphs/index.js.map +1 -0
- package/dist/index-Btxk3nQm.d.cts +430 -0
- package/dist/index-CgXXxuIH.d.ts +430 -0
- package/dist/index-CweT-D3c.d.cts +122 -0
- package/dist/index-D-zWH42e.d.cts +66 -0
- package/dist/index-D71kh3nE.d.cts +213 -0
- package/dist/index-DApls3w2.d.ts +66 -0
- package/dist/index-UamXITgg.d.ts +122 -0
- package/dist/index-v9AlRC0M.d.ts +213 -0
- package/dist/index.cjs +2753 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2654 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/index.cjs +654 -0
- package/dist/integrations/index.cjs.map +1 -0
- package/dist/integrations/index.d.cts +2 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.js +614 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/ncp-tXS9Jr9e.d.cts +132 -0
- package/dist/ncp-tXS9Jr9e.d.ts +132 -0
- package/dist/nodes/index.cjs +226 -0
- package/dist/nodes/index.cjs.map +1 -0
- package/dist/nodes/index.d.cts +2 -0
- package/dist/nodes/index.d.ts +2 -0
- package/dist/nodes/index.js +196 -0
- package/dist/nodes/index.js.map +1 -0
- package/dist/schemas/index.cjs +550 -0
- package/dist/schemas/index.cjs.map +1 -0
- package/dist/schemas/index.d.cts +2 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +484 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/unified_state_bridge-CIDm1kuf.d.cts +266 -0
- package/dist/unified_state_bridge-CIDm1kuf.d.ts +266 -0
- package/package.json +91 -0
- package/src/graphs/coherence_engine.ts +1027 -0
- package/src/graphs/index.ts +47 -0
- package/src/graphs/three_universe_processor.ts +1136 -0
- package/src/index.ts +181 -0
- package/src/integrations/index.ts +17 -0
- package/src/integrations/redis_state.ts +691 -0
- package/src/nodes/emotional_classifier.ts +289 -0
- package/src/nodes/index.ts +17 -0
- package/src/schemas/index.ts +75 -0
- package/src/schemas/ncp.ts +312 -0
- package/src/schemas/unified_state_bridge.ts +681 -0
- package/src/tests/coherence_engine.test.ts +273 -0
- package/src/tests/three_universe_processor.test.ts +309 -0
- package/src/tests/unified_state_bridge.test.ts +360 -0
|
@@ -0,0 +1,1511 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/graphs/index.ts
|
|
21
|
+
var graphs_exports = {};
|
|
22
|
+
__export(graphs_exports, {
|
|
23
|
+
EventType: () => EventType,
|
|
24
|
+
GapSeverity: () => GapSeverity,
|
|
25
|
+
GapType: () => GapType,
|
|
26
|
+
NarrativeCoherenceEngine: () => NarrativeCoherenceEngine,
|
|
27
|
+
RoutingTarget: () => RoutingTarget,
|
|
28
|
+
ThreeUniverseProcessor: () => ThreeUniverseProcessor,
|
|
29
|
+
analyzeCeremonyPerspective: () => analyzeCeremonyPerspective,
|
|
30
|
+
analyzeEngineerPerspective: () => analyzeEngineerPerspective,
|
|
31
|
+
analyzeStoryEnginePerspective: () => analyzeStoryEnginePerspective,
|
|
32
|
+
ceremonyIntentKeywords: () => ceremonyIntentKeywords,
|
|
33
|
+
createCoherenceScore: () => createCoherenceScore,
|
|
34
|
+
createComponentScore: () => createComponentScore,
|
|
35
|
+
createGap: () => createGap,
|
|
36
|
+
createTrinityAssessment: () => createTrinityAssessment,
|
|
37
|
+
engineerIntentKeywords: () => engineerIntentKeywords,
|
|
38
|
+
storyEngineIntentKeywords: () => storyEngineIntentKeywords,
|
|
39
|
+
synthesizePerspectives: () => synthesizePerspectives
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(graphs_exports);
|
|
42
|
+
|
|
43
|
+
// src/schemas/unified_state_bridge.ts
|
|
44
|
+
function createUniversePerspective(universe, intent, confidence, options = {}) {
|
|
45
|
+
return {
|
|
46
|
+
universe,
|
|
47
|
+
intent,
|
|
48
|
+
confidence,
|
|
49
|
+
suggestedFlows: options.suggestedFlows ?? [],
|
|
50
|
+
context: options.context ?? {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function createThreeUniverseAnalysis(engineer, ceremony, storyEngine, leadUniverse, coherenceScore) {
|
|
54
|
+
return {
|
|
55
|
+
engineer,
|
|
56
|
+
ceremony,
|
|
57
|
+
storyEngine,
|
|
58
|
+
leadUniverse,
|
|
59
|
+
coherenceScore,
|
|
60
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createStoryBeat(id, sequence, content, narrativeFunction, act, options = {}) {
|
|
64
|
+
return {
|
|
65
|
+
id,
|
|
66
|
+
sequence,
|
|
67
|
+
content,
|
|
68
|
+
narrativeFunction,
|
|
69
|
+
act,
|
|
70
|
+
universeAnalysis: options.universeAnalysis,
|
|
71
|
+
leadUniverse: options.leadUniverse ?? "story_engine" /* STORY_ENGINE */,
|
|
72
|
+
emotionalTone: options.emotionalTone ?? "neutral",
|
|
73
|
+
thematicTags: options.thematicTags ?? [],
|
|
74
|
+
characterId: options.characterId,
|
|
75
|
+
characterArcImpact: options.characterArcImpact ?? 0,
|
|
76
|
+
source: options.source ?? "generator",
|
|
77
|
+
sourceEventId: options.sourceEventId,
|
|
78
|
+
timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
79
|
+
enrichmentsApplied: options.enrichmentsApplied ?? [],
|
|
80
|
+
qualityScore: options.qualityScore ?? 0.5
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/graphs/three_universe_processor.ts
|
|
85
|
+
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
86
|
+
EventType2["GITHUB_PUSH"] = "github.push";
|
|
87
|
+
EventType2["GITHUB_ISSUE"] = "github.issue";
|
|
88
|
+
EventType2["GITHUB_PR"] = "github.pull_request";
|
|
89
|
+
EventType2["GITHUB_COMMENT"] = "github.comment";
|
|
90
|
+
EventType2["GITHUB_REVIEW"] = "github.review";
|
|
91
|
+
EventType2["USER_INPUT"] = "user.input";
|
|
92
|
+
EventType2["AGENT_ACTION"] = "agent.action";
|
|
93
|
+
EventType2["SYSTEM_EVENT"] = "system.event";
|
|
94
|
+
return EventType2;
|
|
95
|
+
})(EventType || {});
|
|
96
|
+
function engineerIntentKeywords() {
|
|
97
|
+
return {
|
|
98
|
+
feature_implementation: [
|
|
99
|
+
"feat:",
|
|
100
|
+
"feature",
|
|
101
|
+
"add",
|
|
102
|
+
"implement",
|
|
103
|
+
"create",
|
|
104
|
+
"new"
|
|
105
|
+
],
|
|
106
|
+
bug_fix: ["fix:", "bug", "hotfix", "patch", "resolve", "correct"],
|
|
107
|
+
refactor: ["refactor", "refact:", "cleanup", "restructure", "reorganize"],
|
|
108
|
+
documentation: ["docs:", "doc:", "documentation", "readme", "comment"],
|
|
109
|
+
testing: ["test:", "tests:", "testing", "spec", "coverage"],
|
|
110
|
+
dependency: ["deps:", "dependency", "upgrade", "update", "bump"],
|
|
111
|
+
configuration: ["config:", "configure", "settings", "env"],
|
|
112
|
+
performance: ["perf:", "performance", "optimize", "speed", "cache"],
|
|
113
|
+
security: ["security", "sec:", "vulnerability", "auth", "permission"],
|
|
114
|
+
ci_cd: ["ci:", "cd:", "pipeline", "workflow", "build"]
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function analyzeEngineerPerspective(state) {
|
|
118
|
+
const event = state.event;
|
|
119
|
+
const eventType = state.eventType;
|
|
120
|
+
let content = "";
|
|
121
|
+
const payload = event.payload;
|
|
122
|
+
if (payload) {
|
|
123
|
+
const commits = payload.commits;
|
|
124
|
+
if (commits) {
|
|
125
|
+
content = commits.map((c) => c.message || "").join(" ");
|
|
126
|
+
} else if (payload.issue) {
|
|
127
|
+
const issue = payload.issue;
|
|
128
|
+
content = (issue.title || "") + " " + (issue.body || "");
|
|
129
|
+
} else if (payload.pull_request) {
|
|
130
|
+
const pr = payload.pull_request;
|
|
131
|
+
content = (pr.title || "") + " " + (pr.body || "");
|
|
132
|
+
}
|
|
133
|
+
} else if (event.content) {
|
|
134
|
+
content = event.content;
|
|
135
|
+
}
|
|
136
|
+
const contentLower = content.toLowerCase();
|
|
137
|
+
const keywords = engineerIntentKeywords();
|
|
138
|
+
const intentScores = {};
|
|
139
|
+
for (const [intent2, terms] of Object.entries(keywords)) {
|
|
140
|
+
const score = terms.filter(
|
|
141
|
+
(term) => contentLower.includes(term.toLowerCase())
|
|
142
|
+
).length;
|
|
143
|
+
if (score > 0) {
|
|
144
|
+
intentScores[intent2] = score / terms.length;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
let intent;
|
|
148
|
+
let confidence;
|
|
149
|
+
if (Object.keys(intentScores).length > 0) {
|
|
150
|
+
intent = Object.entries(intentScores).reduce(
|
|
151
|
+
(a, b) => a[1] > b[1] ? a : b
|
|
152
|
+
)[0];
|
|
153
|
+
confidence = Math.min(0.95, 0.6 + intentScores[intent] * 0.4);
|
|
154
|
+
} else {
|
|
155
|
+
intent = "maintenance";
|
|
156
|
+
confidence = 0.5;
|
|
157
|
+
}
|
|
158
|
+
const flowMap = {
|
|
159
|
+
feature_implementation: [
|
|
160
|
+
"code_review",
|
|
161
|
+
"integration_test",
|
|
162
|
+
"documentation_update"
|
|
163
|
+
],
|
|
164
|
+
bug_fix: ["regression_test", "root_cause_analysis", "changelog_update"],
|
|
165
|
+
refactor: ["architecture_review", "performance_test", "code_quality"],
|
|
166
|
+
documentation: ["doc_review", "example_validation"],
|
|
167
|
+
testing: ["coverage_analysis", "test_quality_review"],
|
|
168
|
+
dependency: ["security_scan", "compatibility_test"],
|
|
169
|
+
configuration: ["validation_test", "rollback_plan"],
|
|
170
|
+
performance: ["benchmark", "profiling", "optimization_review"],
|
|
171
|
+
security: ["security_audit", "penetration_test", "credential_scan"],
|
|
172
|
+
ci_cd: ["pipeline_validation", "deployment_test"],
|
|
173
|
+
maintenance: ["standard_ci"]
|
|
174
|
+
};
|
|
175
|
+
const suggestedFlows = flowMap[intent] || ["standard_ci"];
|
|
176
|
+
const context = {
|
|
177
|
+
detectedKeywords: Object.entries(intentScores).filter(([, v]) => v > 0).map(([k]) => k),
|
|
178
|
+
contentLength: content.length,
|
|
179
|
+
eventType,
|
|
180
|
+
technicalScope: determineTechnicalScope(content, event),
|
|
181
|
+
estimatedComplexity: estimateComplexity(content, event)
|
|
182
|
+
};
|
|
183
|
+
const perspective = createUniversePerspective(
|
|
184
|
+
"engineer" /* ENGINEER */,
|
|
185
|
+
intent,
|
|
186
|
+
confidence,
|
|
187
|
+
{ suggestedFlows, context }
|
|
188
|
+
);
|
|
189
|
+
return { ...state, engineerPerspective: perspective };
|
|
190
|
+
}
|
|
191
|
+
function determineTechnicalScope(content, _event) {
|
|
192
|
+
const contentLower = content.toLowerCase();
|
|
193
|
+
if (["api", "endpoint", "route"].some((kw) => contentLower.includes(kw))) {
|
|
194
|
+
return "api_layer";
|
|
195
|
+
}
|
|
196
|
+
if (["database", "schema", "migration"].some((kw) => contentLower.includes(kw))) {
|
|
197
|
+
return "data_layer";
|
|
198
|
+
}
|
|
199
|
+
if (["ui", "component", "frontend"].some((kw) => contentLower.includes(kw))) {
|
|
200
|
+
return "presentation_layer";
|
|
201
|
+
}
|
|
202
|
+
if (["test", "spec"].some((kw) => contentLower.includes(kw))) {
|
|
203
|
+
return "testing";
|
|
204
|
+
}
|
|
205
|
+
if (["config", "env", "settings"].some((kw) => contentLower.includes(kw))) {
|
|
206
|
+
return "configuration";
|
|
207
|
+
}
|
|
208
|
+
return "general";
|
|
209
|
+
}
|
|
210
|
+
function estimateComplexity(content, event) {
|
|
211
|
+
const payload = event.payload;
|
|
212
|
+
if (payload) {
|
|
213
|
+
const commits = payload.commits;
|
|
214
|
+
if (commits) {
|
|
215
|
+
if (commits.length > 5) return "high";
|
|
216
|
+
if (commits.length > 2) return "medium";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (content.length > 500) return "high";
|
|
220
|
+
if (content.length > 100) return "medium";
|
|
221
|
+
return "low";
|
|
222
|
+
}
|
|
223
|
+
function ceremonyIntentKeywords() {
|
|
224
|
+
return {
|
|
225
|
+
co_creation: ["we", "together", "team", "pair", "collaborate", "co-author"],
|
|
226
|
+
gratitude_expression: [
|
|
227
|
+
"thanks",
|
|
228
|
+
"thank you",
|
|
229
|
+
"grateful",
|
|
230
|
+
"appreciate",
|
|
231
|
+
"credit"
|
|
232
|
+
],
|
|
233
|
+
witnessing: ["witness", "observe", "acknowledge", "see", "recognize"],
|
|
234
|
+
sacred_pause: ["pause", "reflect", "consider", "contemplate", "breathe"],
|
|
235
|
+
relationship_building: [
|
|
236
|
+
"connect",
|
|
237
|
+
"relationship",
|
|
238
|
+
"community",
|
|
239
|
+
"support"
|
|
240
|
+
],
|
|
241
|
+
healing: ["heal", "restore", "repair", "reconcile", "mend"],
|
|
242
|
+
celebration: [
|
|
243
|
+
"celebrate",
|
|
244
|
+
"milestone",
|
|
245
|
+
"achievement",
|
|
246
|
+
"success",
|
|
247
|
+
"complete"
|
|
248
|
+
],
|
|
249
|
+
offering: ["offer", "gift", "contribute", "share", "give"]
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function analyzeCeremonyPerspective(state) {
|
|
253
|
+
const event = state.event;
|
|
254
|
+
const contributors = extractContributors(event);
|
|
255
|
+
const content = extractContent(event);
|
|
256
|
+
const contentLower = content.toLowerCase();
|
|
257
|
+
const keywords = ceremonyIntentKeywords();
|
|
258
|
+
const intentScores = {};
|
|
259
|
+
for (const [intent2, terms] of Object.entries(keywords)) {
|
|
260
|
+
const score = terms.filter((term) => contentLower.includes(term)).length;
|
|
261
|
+
if (score > 0) {
|
|
262
|
+
intentScores[intent2] = score / terms.length;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (contributors.length > 1) {
|
|
266
|
+
intentScores.co_creation = (intentScores.co_creation || 0) + 0.5;
|
|
267
|
+
}
|
|
268
|
+
let intent;
|
|
269
|
+
let confidence;
|
|
270
|
+
if (Object.keys(intentScores).length > 0) {
|
|
271
|
+
intent = Object.entries(intentScores).reduce(
|
|
272
|
+
(a, b) => a[1] > b[1] ? a : b
|
|
273
|
+
)[0];
|
|
274
|
+
confidence = Math.min(0.95, 0.5 + intentScores[intent] * 0.4);
|
|
275
|
+
} else {
|
|
276
|
+
intent = "individual_offering";
|
|
277
|
+
confidence = 0.6;
|
|
278
|
+
}
|
|
279
|
+
const flowMap = {
|
|
280
|
+
co_creation: ["witness_collaboration", "honor_contributions", "amplify_voices"],
|
|
281
|
+
gratitude_expression: [
|
|
282
|
+
"amplify_acknowledgment",
|
|
283
|
+
"record_connection",
|
|
284
|
+
"reciprocity_check"
|
|
285
|
+
],
|
|
286
|
+
witnessing: ["hold_space", "reflect_back", "presence"],
|
|
287
|
+
sacred_pause: ["create_silence", "contemplation_prompt", "breathing_space"],
|
|
288
|
+
relationship_building: [
|
|
289
|
+
"map_connections",
|
|
290
|
+
"strengthen_ties",
|
|
291
|
+
"introduce_support"
|
|
292
|
+
],
|
|
293
|
+
healing: ["compassion_response", "restoration_path", "forgiveness_space"],
|
|
294
|
+
celebration: ["amplify_joy", "community_acknowledgment", "gratitude_circle"],
|
|
295
|
+
offering: ["receive_gracefully", "honor_gift", "share_forward"],
|
|
296
|
+
individual_offering: [
|
|
297
|
+
"witness_work",
|
|
298
|
+
"hold_space",
|
|
299
|
+
"gentle_acknowledgment"
|
|
300
|
+
]
|
|
301
|
+
};
|
|
302
|
+
const suggestedFlows = flowMap[intent] || ["witness_work", "hold_space"];
|
|
303
|
+
const context = {
|
|
304
|
+
contributors,
|
|
305
|
+
isCollaborative: contributors.length > 1,
|
|
306
|
+
senderEnergy: assessEnergy(content),
|
|
307
|
+
witnessingNeeded: needsWitnessing(content, event),
|
|
308
|
+
relationshipDepth: assessRelationshipDepth(contributors, event),
|
|
309
|
+
sevenGenerationRelevance: assessLongTermImpact(content, event)
|
|
310
|
+
};
|
|
311
|
+
const perspective = createUniversePerspective(
|
|
312
|
+
"ceremony" /* CEREMONY */,
|
|
313
|
+
intent,
|
|
314
|
+
confidence,
|
|
315
|
+
{ suggestedFlows, context }
|
|
316
|
+
);
|
|
317
|
+
return { ...state, ceremonyPerspective: perspective };
|
|
318
|
+
}
|
|
319
|
+
function extractContributors(event) {
|
|
320
|
+
const contributors = [];
|
|
321
|
+
if (event.sender) {
|
|
322
|
+
contributors.push(event.sender);
|
|
323
|
+
}
|
|
324
|
+
const payload = event.payload;
|
|
325
|
+
if (payload) {
|
|
326
|
+
const commits = payload.commits;
|
|
327
|
+
if (commits) {
|
|
328
|
+
for (const commit of commits) {
|
|
329
|
+
const author = commit.author?.name;
|
|
330
|
+
if (author && !contributors.includes(author)) {
|
|
331
|
+
contributors.push(author);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const issue = payload.issue;
|
|
336
|
+
if (issue) {
|
|
337
|
+
const user = issue.user;
|
|
338
|
+
if (user?.login && !contributors.includes(user.login)) {
|
|
339
|
+
contributors.push(user.login);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const pr = payload.pull_request;
|
|
343
|
+
if (pr) {
|
|
344
|
+
const user = pr.user;
|
|
345
|
+
if (user?.login && !contributors.includes(user.login)) {
|
|
346
|
+
contributors.push(user.login);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return contributors.length > 0 ? contributors : ["unknown"];
|
|
351
|
+
}
|
|
352
|
+
function extractContent(event) {
|
|
353
|
+
if (event.content) {
|
|
354
|
+
return event.content;
|
|
355
|
+
}
|
|
356
|
+
const payload = event.payload;
|
|
357
|
+
if (payload) {
|
|
358
|
+
const parts = [];
|
|
359
|
+
const commits = payload.commits;
|
|
360
|
+
if (commits) {
|
|
361
|
+
parts.push(...commits.map((c) => c.message || ""));
|
|
362
|
+
}
|
|
363
|
+
const issue = payload.issue;
|
|
364
|
+
if (issue) {
|
|
365
|
+
parts.push(issue.title || "");
|
|
366
|
+
parts.push(issue.body || "");
|
|
367
|
+
}
|
|
368
|
+
const pr = payload.pull_request;
|
|
369
|
+
if (pr) {
|
|
370
|
+
parts.push(pr.title || "");
|
|
371
|
+
parts.push(pr.body || "");
|
|
372
|
+
}
|
|
373
|
+
const comment = payload.comment;
|
|
374
|
+
if (comment) {
|
|
375
|
+
parts.push(comment.body || "");
|
|
376
|
+
}
|
|
377
|
+
return parts.filter(Boolean).join(" ");
|
|
378
|
+
}
|
|
379
|
+
return "";
|
|
380
|
+
}
|
|
381
|
+
function assessEnergy(content) {
|
|
382
|
+
const contentLower = content.toLowerCase();
|
|
383
|
+
if (["urgent", "critical", "asap", "emergency"].some(
|
|
384
|
+
(w) => contentLower.includes(w)
|
|
385
|
+
)) {
|
|
386
|
+
return "urgent_flow";
|
|
387
|
+
}
|
|
388
|
+
if (["excited", "happy", "great", "awesome"].some(
|
|
389
|
+
(w) => contentLower.includes(w)
|
|
390
|
+
)) {
|
|
391
|
+
return "joyful_flow";
|
|
392
|
+
}
|
|
393
|
+
if (["stuck", "blocked", "help", "issue"].some(
|
|
394
|
+
(w) => contentLower.includes(w)
|
|
395
|
+
)) {
|
|
396
|
+
return "seeking_support";
|
|
397
|
+
}
|
|
398
|
+
if (["thoughtful", "consider", "reflect"].some(
|
|
399
|
+
(w) => contentLower.includes(w)
|
|
400
|
+
)) {
|
|
401
|
+
return "contemplative_flow";
|
|
402
|
+
}
|
|
403
|
+
return "steady_flow";
|
|
404
|
+
}
|
|
405
|
+
function needsWitnessing(content, _event) {
|
|
406
|
+
const contentLower = content.toLowerCase();
|
|
407
|
+
if (["first", "new", "trying", "learning", "help"].some(
|
|
408
|
+
(w) => contentLower.includes(w)
|
|
409
|
+
)) {
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
if (["complete", "achieve", "milestone", "done"].some(
|
|
413
|
+
(w) => contentLower.includes(w)
|
|
414
|
+
)) {
|
|
415
|
+
return true;
|
|
416
|
+
}
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
function assessRelationshipDepth(contributors, _event) {
|
|
420
|
+
if (contributors.length > 2) return "community";
|
|
421
|
+
if (contributors.length > 1) return "pair";
|
|
422
|
+
return "individual";
|
|
423
|
+
}
|
|
424
|
+
function assessLongTermImpact(content, _event) {
|
|
425
|
+
const contentLower = content.toLowerCase();
|
|
426
|
+
let score = 0.3;
|
|
427
|
+
if (["architecture", "foundation", "core", "framework"].some(
|
|
428
|
+
(w) => contentLower.includes(w)
|
|
429
|
+
)) {
|
|
430
|
+
score += 0.3;
|
|
431
|
+
}
|
|
432
|
+
if (["document", "guide", "tutorial", "example"].some(
|
|
433
|
+
(w) => contentLower.includes(w)
|
|
434
|
+
)) {
|
|
435
|
+
score += 0.2;
|
|
436
|
+
}
|
|
437
|
+
if (["breaking", "migration", "deprecate"].some(
|
|
438
|
+
(w) => contentLower.includes(w)
|
|
439
|
+
)) {
|
|
440
|
+
score += 0.2;
|
|
441
|
+
}
|
|
442
|
+
return Math.min(1, score);
|
|
443
|
+
}
|
|
444
|
+
function storyEngineIntentKeywords() {
|
|
445
|
+
return {
|
|
446
|
+
inciting_incident: ["init", "start", "begin", "new", "first", "introduce"],
|
|
447
|
+
rising_action: ["add", "implement", "build", "develop", "progress", "continue"],
|
|
448
|
+
turning_point: ["feat:", "major", "significant", "pivot", "change", "transform"],
|
|
449
|
+
complication: ["issue", "problem", "bug", "error", "conflict", "challenge"],
|
|
450
|
+
crisis: ["critical", "urgent", "breaking", "emergency", "blocker"],
|
|
451
|
+
climax: ["complete", "finish", "final", "release", "launch", "deploy"],
|
|
452
|
+
resolution: ["fix", "resolve", "close", "merge", "done"],
|
|
453
|
+
denouement: ["cleanup", "refactor", "optimize", "polish", "improve"]
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
function analyzeStoryEnginePerspective(state) {
|
|
457
|
+
const event = state.event;
|
|
458
|
+
const content = extractContent(event);
|
|
459
|
+
const contentLower = content.toLowerCase();
|
|
460
|
+
const keywords = storyEngineIntentKeywords();
|
|
461
|
+
const intentScores = {};
|
|
462
|
+
for (const [intent2, terms] of Object.entries(keywords)) {
|
|
463
|
+
const score = terms.filter((term) => contentLower.includes(term)).length;
|
|
464
|
+
if (score > 0) {
|
|
465
|
+
intentScores[intent2] = score / terms.length;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
let intent;
|
|
469
|
+
let confidence;
|
|
470
|
+
if (Object.keys(intentScores).length > 0) {
|
|
471
|
+
intent = Object.entries(intentScores).reduce(
|
|
472
|
+
(a, b) => a[1] > b[1] ? a : b
|
|
473
|
+
)[0];
|
|
474
|
+
confidence = Math.min(0.95, 0.55 + intentScores[intent] * 0.4);
|
|
475
|
+
} else {
|
|
476
|
+
intent = "rising_action";
|
|
477
|
+
confidence = 0.5;
|
|
478
|
+
}
|
|
479
|
+
const actMap = {
|
|
480
|
+
inciting_incident: 1,
|
|
481
|
+
rising_action: 2,
|
|
482
|
+
turning_point: 2,
|
|
483
|
+
complication: 2,
|
|
484
|
+
crisis: 2,
|
|
485
|
+
climax: 3,
|
|
486
|
+
resolution: 3,
|
|
487
|
+
denouement: 3
|
|
488
|
+
};
|
|
489
|
+
const act = actMap[intent] || 2;
|
|
490
|
+
const functionMap = {
|
|
491
|
+
inciting_incident: "inciting_incident",
|
|
492
|
+
rising_action: "rising_action",
|
|
493
|
+
turning_point: "turning_point",
|
|
494
|
+
complication: "complication",
|
|
495
|
+
crisis: "crisis",
|
|
496
|
+
climax: "climax",
|
|
497
|
+
resolution: "resolution",
|
|
498
|
+
denouement: "denouement"
|
|
499
|
+
};
|
|
500
|
+
const narrativeFunction = functionMap[intent] || "beat";
|
|
501
|
+
const flowMap = {
|
|
502
|
+
inciting_incident: ["establish_stakes", "introduce_characters", "set_tone"],
|
|
503
|
+
rising_action: ["advance_narrative", "develop_characters", "build_tension"],
|
|
504
|
+
turning_point: ["mark_pivot", "shift_perspective", "update_arc"],
|
|
505
|
+
complication: ["deepen_conflict", "raise_stakes", "add_obstacle"],
|
|
506
|
+
crisis: ["peak_tension", "force_decision", "approach_climax"],
|
|
507
|
+
climax: ["resolve_main_conflict", "character_transformation", "theme_revelation"],
|
|
508
|
+
resolution: ["tie_loose_ends", "show_consequences", "new_equilibrium"],
|
|
509
|
+
denouement: ["reflect_journey", "hint_future", "final_image"]
|
|
510
|
+
};
|
|
511
|
+
const suggestedFlows = flowMap[intent] || [
|
|
512
|
+
"advance_narrative",
|
|
513
|
+
"update_arc_position"
|
|
514
|
+
];
|
|
515
|
+
const dramaticTension = calculateDramaticTension(intent, content);
|
|
516
|
+
const context = {
|
|
517
|
+
act,
|
|
518
|
+
narrativeFunction,
|
|
519
|
+
dramaticTension,
|
|
520
|
+
suggestedNextBeat: suggestNextBeat(intent),
|
|
521
|
+
characterImpact: assessCharacterImpact(content),
|
|
522
|
+
themeResonance: assessThemeResonance(content),
|
|
523
|
+
pacingSuggestion: suggestPacing(intent, dramaticTension)
|
|
524
|
+
};
|
|
525
|
+
const perspective = createUniversePerspective(
|
|
526
|
+
"story_engine" /* STORY_ENGINE */,
|
|
527
|
+
intent,
|
|
528
|
+
confidence,
|
|
529
|
+
{ suggestedFlows, context }
|
|
530
|
+
);
|
|
531
|
+
return { ...state, storyEnginePerspective: perspective };
|
|
532
|
+
}
|
|
533
|
+
function calculateDramaticTension(intent, content) {
|
|
534
|
+
const baseTension = {
|
|
535
|
+
inciting_incident: 0.4,
|
|
536
|
+
rising_action: 0.5,
|
|
537
|
+
turning_point: 0.7,
|
|
538
|
+
complication: 0.6,
|
|
539
|
+
crisis: 0.9,
|
|
540
|
+
climax: 1,
|
|
541
|
+
resolution: 0.4,
|
|
542
|
+
denouement: 0.2
|
|
543
|
+
};
|
|
544
|
+
let tension = baseTension[intent] || 0.5;
|
|
545
|
+
const contentLower = content.toLowerCase();
|
|
546
|
+
if (["urgent", "critical", "breaking"].some((w) => contentLower.includes(w))) {
|
|
547
|
+
tension = Math.min(1, tension + 0.2);
|
|
548
|
+
}
|
|
549
|
+
if (["minor", "small", "trivial"].some((w) => contentLower.includes(w))) {
|
|
550
|
+
tension = Math.max(0.1, tension - 0.2);
|
|
551
|
+
}
|
|
552
|
+
return Math.round(tension * 100) / 100;
|
|
553
|
+
}
|
|
554
|
+
function suggestNextBeat(currentIntent) {
|
|
555
|
+
const nextBeatMap = {
|
|
556
|
+
inciting_incident: "rising_action",
|
|
557
|
+
rising_action: "complication",
|
|
558
|
+
turning_point: "rising_action",
|
|
559
|
+
complication: "crisis",
|
|
560
|
+
crisis: "climax",
|
|
561
|
+
climax: "resolution",
|
|
562
|
+
resolution: "denouement",
|
|
563
|
+
denouement: "inciting_incident"
|
|
564
|
+
// New cycle
|
|
565
|
+
};
|
|
566
|
+
return nextBeatMap[currentIntent] || "rising_action";
|
|
567
|
+
}
|
|
568
|
+
function assessCharacterImpact(content) {
|
|
569
|
+
const contentLower = content.toLowerCase();
|
|
570
|
+
if (["transform", "change", "grow", "learn"].some(
|
|
571
|
+
(w) => contentLower.includes(w)
|
|
572
|
+
)) {
|
|
573
|
+
return "transformative";
|
|
574
|
+
}
|
|
575
|
+
if (["challenge", "struggle", "overcome"].some(
|
|
576
|
+
(w) => contentLower.includes(w)
|
|
577
|
+
)) {
|
|
578
|
+
return "character_testing";
|
|
579
|
+
}
|
|
580
|
+
if (["connect", "relationship", "team"].some((w) => contentLower.includes(w))) {
|
|
581
|
+
return "relational";
|
|
582
|
+
}
|
|
583
|
+
return "incremental";
|
|
584
|
+
}
|
|
585
|
+
function assessThemeResonance(content) {
|
|
586
|
+
const contentLower = content.toLowerCase();
|
|
587
|
+
const themes = [];
|
|
588
|
+
if (["together", "team", "collaborate"].some((w) => contentLower.includes(w))) {
|
|
589
|
+
themes.push("collaboration");
|
|
590
|
+
}
|
|
591
|
+
if (["integrate", "connect", "bridge"].some((w) => contentLower.includes(w))) {
|
|
592
|
+
themes.push("integration");
|
|
593
|
+
}
|
|
594
|
+
if (["coherent", "consistent", "unified"].some(
|
|
595
|
+
(w) => contentLower.includes(w)
|
|
596
|
+
)) {
|
|
597
|
+
themes.push("coherence");
|
|
598
|
+
}
|
|
599
|
+
if (["transform", "change", "evolve"].some((w) => contentLower.includes(w))) {
|
|
600
|
+
themes.push("transformation");
|
|
601
|
+
}
|
|
602
|
+
return themes.length > 0 ? themes.join(", ") : "development";
|
|
603
|
+
}
|
|
604
|
+
function suggestPacing(intent, tension) {
|
|
605
|
+
if (tension > 0.8) return "accelerate";
|
|
606
|
+
if (tension < 0.3) return "breathe";
|
|
607
|
+
if (intent === "inciting_incident" || intent === "climax") return "emphasize";
|
|
608
|
+
return "steady";
|
|
609
|
+
}
|
|
610
|
+
function synthesizePerspectives(state) {
|
|
611
|
+
const engineer = state.engineerPerspective;
|
|
612
|
+
const ceremony = state.ceremonyPerspective;
|
|
613
|
+
const storyEngine = state.storyEnginePerspective;
|
|
614
|
+
if (!engineer || !ceremony || !storyEngine) {
|
|
615
|
+
return {
|
|
616
|
+
...state,
|
|
617
|
+
error: "Missing one or more perspectives"
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
const lead = determineLeadUniverse(engineer, ceremony, storyEngine);
|
|
621
|
+
const coherence = calculateCoherence(engineer, ceremony, storyEngine);
|
|
622
|
+
const analysis = createThreeUniverseAnalysis(
|
|
623
|
+
engineer,
|
|
624
|
+
ceremony,
|
|
625
|
+
storyEngine,
|
|
626
|
+
lead,
|
|
627
|
+
coherence
|
|
628
|
+
);
|
|
629
|
+
return {
|
|
630
|
+
...state,
|
|
631
|
+
analysis,
|
|
632
|
+
leadUniverse: lead,
|
|
633
|
+
coherenceScore: coherence
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
function determineLeadUniverse(engineer, ceremony, storyEngine) {
|
|
637
|
+
const ceremonyContext = ceremony.context;
|
|
638
|
+
if (ceremonyContext.witnessingNeeded) {
|
|
639
|
+
return "ceremony" /* CEREMONY */;
|
|
640
|
+
}
|
|
641
|
+
if (ceremonyContext.isCollaborative) {
|
|
642
|
+
return "ceremony" /* CEREMONY */;
|
|
643
|
+
}
|
|
644
|
+
const storyContext = storyEngine.context;
|
|
645
|
+
if (storyContext.dramaticTension > 0.8) {
|
|
646
|
+
return "story_engine" /* STORY_ENGINE */;
|
|
647
|
+
}
|
|
648
|
+
if (storyContext.narrativeFunction === "climax" || storyContext.narrativeFunction === "turning_point") {
|
|
649
|
+
return "story_engine" /* STORY_ENGINE */;
|
|
650
|
+
}
|
|
651
|
+
const engineerContext = engineer.context;
|
|
652
|
+
if (engineerContext.estimatedComplexity === "high") {
|
|
653
|
+
return "engineer" /* ENGINEER */;
|
|
654
|
+
}
|
|
655
|
+
if (engineer.intent === "security" || engineer.intent === "bug_fix") {
|
|
656
|
+
return "engineer" /* ENGINEER */;
|
|
657
|
+
}
|
|
658
|
+
const perspectives = [
|
|
659
|
+
[engineer, "engineer" /* ENGINEER */],
|
|
660
|
+
[ceremony, "ceremony" /* CEREMONY */],
|
|
661
|
+
[storyEngine, "story_engine" /* STORY_ENGINE */]
|
|
662
|
+
];
|
|
663
|
+
return perspectives.reduce(
|
|
664
|
+
(a, b) => a[0].confidence > b[0].confidence ? a : b
|
|
665
|
+
)[1];
|
|
666
|
+
}
|
|
667
|
+
function calculateCoherence(engineer, ceremony, storyEngine) {
|
|
668
|
+
const avgConfidence = (engineer.confidence + ceremony.confidence + storyEngine.confidence) / 3;
|
|
669
|
+
let bonus = 0;
|
|
670
|
+
const engineerUrgent = ["security", "bug_fix", "performance"].includes(
|
|
671
|
+
engineer.intent
|
|
672
|
+
);
|
|
673
|
+
const ceremonyUrgent = ceremony.context.senderEnergy === "urgent_flow";
|
|
674
|
+
const storyUrgent = storyEngine.context.dramaticTension > 0.7;
|
|
675
|
+
if ([engineerUrgent, ceremonyUrgent, storyUrgent].filter(Boolean).length >= 2) {
|
|
676
|
+
bonus += 0.1;
|
|
677
|
+
}
|
|
678
|
+
const confidences = [
|
|
679
|
+
engineer.confidence,
|
|
680
|
+
ceremony.confidence,
|
|
681
|
+
storyEngine.confidence
|
|
682
|
+
];
|
|
683
|
+
const confidenceSpread = Math.max(...confidences) - Math.min(...confidences);
|
|
684
|
+
const penalty = confidenceSpread * 0.2;
|
|
685
|
+
const coherence = avgConfidence + bonus - penalty;
|
|
686
|
+
return Math.round(Math.max(0, Math.min(1, coherence)) * 100) / 100;
|
|
687
|
+
}
|
|
688
|
+
var ThreeUniverseProcessor = class {
|
|
689
|
+
tracingCallback;
|
|
690
|
+
constructor(options = {}) {
|
|
691
|
+
this.tracingCallback = options.tracingCallback;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Process an event through all three universes.
|
|
695
|
+
*
|
|
696
|
+
* @param event The event data (webhook payload, user input, etc.)
|
|
697
|
+
* @param eventType Type of event (e.g., "github.push", "user.input")
|
|
698
|
+
* @returns ThreeUniverseAnalysis with all perspectives and synthesis
|
|
699
|
+
*/
|
|
700
|
+
process(event, eventType = "unknown") {
|
|
701
|
+
let state = {
|
|
702
|
+
event,
|
|
703
|
+
eventType
|
|
704
|
+
};
|
|
705
|
+
state = analyzeEngineerPerspective(state);
|
|
706
|
+
state = analyzeCeremonyPerspective(state);
|
|
707
|
+
state = analyzeStoryEnginePerspective(state);
|
|
708
|
+
state = synthesizePerspectives(state);
|
|
709
|
+
if (state.error) {
|
|
710
|
+
throw new Error(`Processing error: ${state.error}`);
|
|
711
|
+
}
|
|
712
|
+
const analysis = state.analysis;
|
|
713
|
+
if (this.tracingCallback && analysis) {
|
|
714
|
+
const eventId = event.eventId || event.id || `${eventType}_${Date.now()}`;
|
|
715
|
+
const eventContent = this.extractEventContent(event);
|
|
716
|
+
this.tracingCallback(
|
|
717
|
+
eventId,
|
|
718
|
+
eventContent,
|
|
719
|
+
perspectiveToRecord(analysis.engineer),
|
|
720
|
+
perspectiveToRecord(analysis.ceremony),
|
|
721
|
+
perspectiveToRecord(analysis.storyEngine),
|
|
722
|
+
analysis.leadUniverse,
|
|
723
|
+
analysis.coherenceScore
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
return analysis;
|
|
727
|
+
}
|
|
728
|
+
extractEventContent(event) {
|
|
729
|
+
if (event.content) {
|
|
730
|
+
return String(event.content).slice(0, 500);
|
|
731
|
+
}
|
|
732
|
+
const payload = event.payload;
|
|
733
|
+
if (payload && typeof payload === "object") {
|
|
734
|
+
const issue = payload.issue;
|
|
735
|
+
if (issue?.title) return issue.title;
|
|
736
|
+
const pr = payload.pull_request;
|
|
737
|
+
if (pr?.title) return pr.title;
|
|
738
|
+
const comment = payload.comment;
|
|
739
|
+
if (comment?.body) return comment.body.slice(0, 500);
|
|
740
|
+
}
|
|
741
|
+
if (event.message) {
|
|
742
|
+
return String(event.message).slice(0, 500);
|
|
743
|
+
}
|
|
744
|
+
return `Event: ${event.eventType || "unknown"}`;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Convenience method for processing GitHub webhooks.
|
|
748
|
+
*/
|
|
749
|
+
processWebhook(webhookPayload) {
|
|
750
|
+
let eventType = "github.push";
|
|
751
|
+
const payload = webhookPayload.payload;
|
|
752
|
+
if (payload) {
|
|
753
|
+
if (payload.issue) {
|
|
754
|
+
eventType = "github.issue";
|
|
755
|
+
} else if (payload.pull_request) {
|
|
756
|
+
eventType = "github.pull_request";
|
|
757
|
+
} else if (payload.comment) {
|
|
758
|
+
eventType = "github.comment";
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return this.process(webhookPayload, eventType);
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Create a story beat from event and analysis.
|
|
765
|
+
*/
|
|
766
|
+
createBeatFromAnalysis(event, analysis, sequence) {
|
|
767
|
+
const functionMap = {
|
|
768
|
+
inciting_incident: "inciting_incident" /* INCITING_INCIDENT */,
|
|
769
|
+
rising_action: "rising_action" /* RISING_ACTION */,
|
|
770
|
+
turning_point: "turning_point" /* TURNING_POINT */,
|
|
771
|
+
complication: "complication" /* COMPLICATION */,
|
|
772
|
+
crisis: "crisis" /* CRISIS */,
|
|
773
|
+
climax: "climax" /* CLIMAX */,
|
|
774
|
+
resolution: "resolution" /* RESOLUTION */,
|
|
775
|
+
denouement: "denouement" /* DENOUEMENT */
|
|
776
|
+
};
|
|
777
|
+
const storyIntent = analysis.storyEngine.intent;
|
|
778
|
+
const narrativeFunc = functionMap[storyIntent] || "beat" /* BEAT */;
|
|
779
|
+
const act = analysis.storyEngine.context.act || 2;
|
|
780
|
+
let content = extractContent(event);
|
|
781
|
+
if (!content) {
|
|
782
|
+
content = String(event.eventType || "event");
|
|
783
|
+
}
|
|
784
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
785
|
+
const beatId = `beat_${timestamp}`;
|
|
786
|
+
let sourceEventId;
|
|
787
|
+
const payload = event.payload;
|
|
788
|
+
if (payload) {
|
|
789
|
+
const headCommit = payload.head_commit;
|
|
790
|
+
if (headCommit?.id) {
|
|
791
|
+
sourceEventId = headCommit.id;
|
|
792
|
+
} else if (payload.issue) {
|
|
793
|
+
const issue = payload.issue;
|
|
794
|
+
sourceEventId = String(issue.id);
|
|
795
|
+
} else if (payload.pull_request) {
|
|
796
|
+
const pr = payload.pull_request;
|
|
797
|
+
sourceEventId = String(pr.id);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return createStoryBeat(beatId, sequence, content.slice(0, 500), narrativeFunc, act, {
|
|
801
|
+
universeAnalysis: analysis,
|
|
802
|
+
leadUniverse: analysis.leadUniverse,
|
|
803
|
+
source: "processor",
|
|
804
|
+
sourceEventId
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
function perspectiveToRecord(perspective) {
|
|
809
|
+
return {
|
|
810
|
+
universe: perspective.universe,
|
|
811
|
+
intent: perspective.intent,
|
|
812
|
+
confidence: perspective.confidence,
|
|
813
|
+
suggestedFlows: perspective.suggestedFlows,
|
|
814
|
+
context: perspective.context
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/graphs/coherence_engine.ts
|
|
819
|
+
var GapType = /* @__PURE__ */ ((GapType2) => {
|
|
820
|
+
GapType2["STRUCTURAL"] = "structural";
|
|
821
|
+
GapType2["THEMATIC"] = "thematic";
|
|
822
|
+
GapType2["CHARACTER"] = "character";
|
|
823
|
+
GapType2["SENSORY"] = "sensory";
|
|
824
|
+
GapType2["CONTINUITY"] = "continuity";
|
|
825
|
+
return GapType2;
|
|
826
|
+
})(GapType || {});
|
|
827
|
+
var GapSeverity = /* @__PURE__ */ ((GapSeverity2) => {
|
|
828
|
+
GapSeverity2["CRITICAL"] = "critical";
|
|
829
|
+
GapSeverity2["MODERATE"] = "moderate";
|
|
830
|
+
GapSeverity2["MINOR"] = "minor";
|
|
831
|
+
return GapSeverity2;
|
|
832
|
+
})(GapSeverity || {});
|
|
833
|
+
var RoutingTarget = /* @__PURE__ */ ((RoutingTarget2) => {
|
|
834
|
+
RoutingTarget2["STORYTELLER"] = "storyteller";
|
|
835
|
+
RoutingTarget2["STRUCTURIST"] = "structurist";
|
|
836
|
+
RoutingTarget2["ARCHITECT"] = "architect";
|
|
837
|
+
RoutingTarget2["AUTHOR"] = "author";
|
|
838
|
+
return RoutingTarget2;
|
|
839
|
+
})(RoutingTarget || {});
|
|
840
|
+
function createGap(id, gapType, severity, description, suggestedRoute, options = {}) {
|
|
841
|
+
return {
|
|
842
|
+
id,
|
|
843
|
+
gapType,
|
|
844
|
+
severity,
|
|
845
|
+
description,
|
|
846
|
+
location: options.location ?? {},
|
|
847
|
+
suggestedRoute,
|
|
848
|
+
resolved: options.resolved ?? false,
|
|
849
|
+
resolution: options.resolution
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
function createComponentScore(score, status, options = {}) {
|
|
853
|
+
return {
|
|
854
|
+
score,
|
|
855
|
+
status,
|
|
856
|
+
issues: options.issues ?? [],
|
|
857
|
+
suggestions: options.suggestions ?? []
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
function createCoherenceScore(overall, narrativeFlow, characterConsistency, pacing, themeSaturation, continuity) {
|
|
861
|
+
return {
|
|
862
|
+
overall,
|
|
863
|
+
narrativeFlow,
|
|
864
|
+
characterConsistency,
|
|
865
|
+
pacing,
|
|
866
|
+
themeSaturation,
|
|
867
|
+
continuity,
|
|
868
|
+
analyzedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
function createTrinityAssessment(mia, miette, ava8, priorities = []) {
|
|
872
|
+
return { mia, miette, ava8, priorities };
|
|
873
|
+
}
|
|
874
|
+
var NarrativeCoherenceEngine = class {
|
|
875
|
+
strictMode;
|
|
876
|
+
gapCounter;
|
|
877
|
+
constructor(options = {}) {
|
|
878
|
+
this.strictMode = options.strictMode ?? false;
|
|
879
|
+
this.gapCounter = 0;
|
|
880
|
+
}
|
|
881
|
+
generateGapId() {
|
|
882
|
+
this.gapCounter += 1;
|
|
883
|
+
return `gap_${this.gapCounter}`;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Analyze narrative flow - how smoothly the story progresses.
|
|
887
|
+
*
|
|
888
|
+
* Checks:
|
|
889
|
+
* - Beat transitions (jarring vs smooth)
|
|
890
|
+
* - Logical causality between beats
|
|
891
|
+
* - Pacing consistency
|
|
892
|
+
*/
|
|
893
|
+
analyzeNarrativeFlow(state) {
|
|
894
|
+
const beats = state.beats;
|
|
895
|
+
const issues = [];
|
|
896
|
+
const suggestions = [];
|
|
897
|
+
let score;
|
|
898
|
+
let status;
|
|
899
|
+
if (beats.length < 2) {
|
|
900
|
+
score = 50;
|
|
901
|
+
issues.push("Too few beats to assess flow");
|
|
902
|
+
suggestions.push("Add more story beats to establish narrative rhythm");
|
|
903
|
+
} else {
|
|
904
|
+
const functions = beats.map((b) => b.narrativeFunction);
|
|
905
|
+
let hasProperStructure = false;
|
|
906
|
+
for (let i = 0; i < functions.length; i++) {
|
|
907
|
+
const func = functions[i];
|
|
908
|
+
if (["setup", "introduction", "discovery"].includes(func)) {
|
|
909
|
+
hasProperStructure = true;
|
|
910
|
+
break;
|
|
911
|
+
} else if (["confrontation", "crisis", "climax"].includes(func)) {
|
|
912
|
+
if (!hasProperStructure) {
|
|
913
|
+
issues.push(`Beat ${i + 1} escalates without proper setup`);
|
|
914
|
+
hasProperStructure = true;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
let prevTone;
|
|
919
|
+
let jarringTransitions = 0;
|
|
920
|
+
for (let i = 0; i < beats.length; i++) {
|
|
921
|
+
const beat = beats[i];
|
|
922
|
+
if (prevTone && beat.emotionalTone) {
|
|
923
|
+
const jarringPairs = [
|
|
924
|
+
["devastating", "joyful"],
|
|
925
|
+
["fearful", "peaceful"],
|
|
926
|
+
["triumphant", "devastating"]
|
|
927
|
+
];
|
|
928
|
+
for (const [p1, p2] of jarringPairs) {
|
|
929
|
+
if (prevTone.toLowerCase().includes(p1) && beat.emotionalTone.toLowerCase().includes(p2) || prevTone.toLowerCase().includes(p2) && beat.emotionalTone.toLowerCase().includes(p1)) {
|
|
930
|
+
jarringTransitions += 1;
|
|
931
|
+
issues.push(`Jarring emotional transition at Beat ${i + 1}`);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
prevTone = beat.emotionalTone;
|
|
936
|
+
}
|
|
937
|
+
let baseScore = 85;
|
|
938
|
+
baseScore -= jarringTransitions * 10;
|
|
939
|
+
baseScore -= issues.filter((i) => i.includes("without proper setup")).length * 15;
|
|
940
|
+
score = Math.max(0, Math.min(100, baseScore));
|
|
941
|
+
if (jarringTransitions > 0) {
|
|
942
|
+
suggestions.push("Add transitional beats to smooth emotional shifts");
|
|
943
|
+
}
|
|
944
|
+
if (!hasProperStructure) {
|
|
945
|
+
suggestions.push(
|
|
946
|
+
"Consider adding setup beats before major confrontations"
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
if (score >= 70) {
|
|
951
|
+
status = "good";
|
|
952
|
+
} else if (score >= 50) {
|
|
953
|
+
status = "warning";
|
|
954
|
+
} else {
|
|
955
|
+
status = "critical";
|
|
956
|
+
}
|
|
957
|
+
state.narrativeFlowScore = createComponentScore(score, status, {
|
|
958
|
+
issues,
|
|
959
|
+
suggestions
|
|
960
|
+
});
|
|
961
|
+
return state;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Analyze character consistency across the narrative.
|
|
965
|
+
*
|
|
966
|
+
* Checks:
|
|
967
|
+
* - Character voice consistency
|
|
968
|
+
* - Arc progression logic
|
|
969
|
+
* - Relationship evolution coherence
|
|
970
|
+
*/
|
|
971
|
+
analyzeCharacterConsistency(state) {
|
|
972
|
+
const beats = state.beats;
|
|
973
|
+
const characters = state.characters;
|
|
974
|
+
const issues = [];
|
|
975
|
+
const suggestions = [];
|
|
976
|
+
let score;
|
|
977
|
+
let status;
|
|
978
|
+
if (characters.length === 0) {
|
|
979
|
+
score = 50;
|
|
980
|
+
issues.push("No character data provided");
|
|
981
|
+
suggestions.push("Define character states to enable consistency analysis");
|
|
982
|
+
} else {
|
|
983
|
+
const characterBeats = {};
|
|
984
|
+
for (const char of characters) {
|
|
985
|
+
characterBeats[char.id] = [];
|
|
986
|
+
}
|
|
987
|
+
for (let i = 0; i < beats.length; i++) {
|
|
988
|
+
const beat = beats[i];
|
|
989
|
+
if (beat.characterId && characterBeats[beat.characterId]) {
|
|
990
|
+
characterBeats[beat.characterId].push(i);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
for (const [charId, appearances] of Object.entries(characterBeats)) {
|
|
994
|
+
if (appearances.length >= 2) {
|
|
995
|
+
for (let i = 1; i < appearances.length; i++) {
|
|
996
|
+
const gap = appearances[i] - appearances[i - 1];
|
|
997
|
+
if (gap > 5) {
|
|
998
|
+
const char = characters.find((c) => c.id === charId);
|
|
999
|
+
const name = char?.name || charId;
|
|
1000
|
+
issues.push(`Character '${name}' disappears for ${gap} beats`);
|
|
1001
|
+
suggestions.push(
|
|
1002
|
+
`Consider adding '${name}' to beats between ${appearances[i - 1] + 1} and ${appearances[i] + 1}`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
for (const char of characters) {
|
|
1009
|
+
if (char.arcPosition < 0.1 && beats.length > 5) {
|
|
1010
|
+
issues.push(`Character '${char.name}' has minimal arc progression`);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
let baseScore = 90;
|
|
1014
|
+
baseScore -= issues.filter((i) => i.includes("disappears")).length * 8;
|
|
1015
|
+
baseScore -= issues.filter((i) => i.includes("minimal arc")).length * 12;
|
|
1016
|
+
score = Math.max(0, Math.min(100, baseScore));
|
|
1017
|
+
}
|
|
1018
|
+
if (score >= 70) {
|
|
1019
|
+
status = "good";
|
|
1020
|
+
} else if (score >= 50) {
|
|
1021
|
+
status = "warning";
|
|
1022
|
+
} else {
|
|
1023
|
+
status = "critical";
|
|
1024
|
+
}
|
|
1025
|
+
state.characterConsistencyScore = createComponentScore(score, status, {
|
|
1026
|
+
issues,
|
|
1027
|
+
suggestions
|
|
1028
|
+
});
|
|
1029
|
+
return state;
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Analyze narrative pacing.
|
|
1033
|
+
*
|
|
1034
|
+
* Checks:
|
|
1035
|
+
* - Tension/relief distribution
|
|
1036
|
+
* - Beat density per section
|
|
1037
|
+
* - Climax positioning
|
|
1038
|
+
*/
|
|
1039
|
+
analyzePacing(state) {
|
|
1040
|
+
const beats = state.beats;
|
|
1041
|
+
const issues = [];
|
|
1042
|
+
const suggestions = [];
|
|
1043
|
+
let score;
|
|
1044
|
+
let status;
|
|
1045
|
+
if (beats.length < 3) {
|
|
1046
|
+
score = 50;
|
|
1047
|
+
issues.push("Too few beats to assess pacing");
|
|
1048
|
+
suggestions.push("Add more beats to establish proper pacing rhythm");
|
|
1049
|
+
} else {
|
|
1050
|
+
const functions = beats.map((b) => b.narrativeFunction.toLowerCase());
|
|
1051
|
+
const climaxPositions = functions.map((f, i) => f.includes("climax") ? i : -1).filter((i) => i >= 0);
|
|
1052
|
+
if (climaxPositions.length === 0) {
|
|
1053
|
+
issues.push("No climax beat identified");
|
|
1054
|
+
suggestions.push("Ensure at least one beat has a climax function");
|
|
1055
|
+
} else {
|
|
1056
|
+
const lastClimax = climaxPositions[climaxPositions.length - 1];
|
|
1057
|
+
const total = beats.length;
|
|
1058
|
+
if (lastClimax < total * 0.5) {
|
|
1059
|
+
issues.push("Climax occurs too early in the narrative");
|
|
1060
|
+
suggestions.push(
|
|
1061
|
+
"Move climax to later in the story or add post-climax resolution beats"
|
|
1062
|
+
);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
const highTensionFuncs = [
|
|
1066
|
+
"confrontation",
|
|
1067
|
+
"crisis",
|
|
1068
|
+
"climax",
|
|
1069
|
+
"revelation"
|
|
1070
|
+
];
|
|
1071
|
+
let consecutiveHigh = 0;
|
|
1072
|
+
let maxConsecutive = 0;
|
|
1073
|
+
for (const func of functions) {
|
|
1074
|
+
if (highTensionFuncs.some((ht) => func.includes(ht))) {
|
|
1075
|
+
consecutiveHigh += 1;
|
|
1076
|
+
maxConsecutive = Math.max(maxConsecutive, consecutiveHigh);
|
|
1077
|
+
} else {
|
|
1078
|
+
consecutiveHigh = 0;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
if (maxConsecutive > 3) {
|
|
1082
|
+
issues.push(
|
|
1083
|
+
`Found ${maxConsecutive} consecutive high-tension beats`
|
|
1084
|
+
);
|
|
1085
|
+
suggestions.push(
|
|
1086
|
+
"Add breathing room with quieter beats between intense moments"
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
let baseScore = 85;
|
|
1090
|
+
if (climaxPositions.length === 0) {
|
|
1091
|
+
baseScore -= 20;
|
|
1092
|
+
} else if (climaxPositions[climaxPositions.length - 1] < beats.length * 0.5) {
|
|
1093
|
+
baseScore -= 15;
|
|
1094
|
+
}
|
|
1095
|
+
baseScore -= Math.min(20, maxConsecutive * 5);
|
|
1096
|
+
score = Math.max(0, Math.min(100, baseScore));
|
|
1097
|
+
}
|
|
1098
|
+
if (score >= 70) {
|
|
1099
|
+
status = "good";
|
|
1100
|
+
} else if (score >= 50) {
|
|
1101
|
+
status = "warning";
|
|
1102
|
+
} else {
|
|
1103
|
+
status = "critical";
|
|
1104
|
+
}
|
|
1105
|
+
state.pacingScore = createComponentScore(score, status, {
|
|
1106
|
+
issues,
|
|
1107
|
+
suggestions
|
|
1108
|
+
});
|
|
1109
|
+
return state;
|
|
1110
|
+
}
|
|
1111
|
+
/**
|
|
1112
|
+
* Analyze how well themes permeate the narrative.
|
|
1113
|
+
*
|
|
1114
|
+
* Checks:
|
|
1115
|
+
* - Theme presence across beats
|
|
1116
|
+
* - Theme introduction and payoff
|
|
1117
|
+
* - Theme strength consistency
|
|
1118
|
+
*/
|
|
1119
|
+
analyzeThemeSaturation(state) {
|
|
1120
|
+
const beats = state.beats;
|
|
1121
|
+
const themes = state.themes;
|
|
1122
|
+
const issues = [];
|
|
1123
|
+
const suggestions = [];
|
|
1124
|
+
let score;
|
|
1125
|
+
let status;
|
|
1126
|
+
if (themes.length === 0) {
|
|
1127
|
+
score = 50;
|
|
1128
|
+
issues.push("No themes defined");
|
|
1129
|
+
suggestions.push(
|
|
1130
|
+
"Define thematic threads to enable saturation analysis"
|
|
1131
|
+
);
|
|
1132
|
+
} else {
|
|
1133
|
+
const themeCoverage = {};
|
|
1134
|
+
for (const theme of themes) {
|
|
1135
|
+
let beatsWithTheme = 0;
|
|
1136
|
+
for (const beat of beats) {
|
|
1137
|
+
if (beat.thematicTags?.includes(theme.id)) {
|
|
1138
|
+
beatsWithTheme += 1;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const coverage = beatsWithTheme / Math.max(beats.length, 1);
|
|
1142
|
+
themeCoverage[theme.name] = coverage;
|
|
1143
|
+
if (coverage < 0.2 && theme.strength > 0.5) {
|
|
1144
|
+
issues.push(
|
|
1145
|
+
`Theme '${theme.name}' is important but appears rarely`
|
|
1146
|
+
);
|
|
1147
|
+
suggestions.push(
|
|
1148
|
+
`Weave '${theme.name}' into more beats to fulfill its promise`
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
if (coverage > 0.3 && theme.strength < 0.3) {
|
|
1152
|
+
issues.push(
|
|
1153
|
+
`Theme '${theme.name}' appears often but lacks impact`
|
|
1154
|
+
);
|
|
1155
|
+
suggestions.push(
|
|
1156
|
+
`Strengthen the thematic weight of '${theme.name}' in key beats`
|
|
1157
|
+
);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
const coverageValues = Object.values(themeCoverage);
|
|
1161
|
+
const avgCoverage = coverageValues.reduce((a, b) => a + b, 0) / Math.max(coverageValues.length, 1);
|
|
1162
|
+
let baseScore = Math.min(100, avgCoverage * 100 + 20);
|
|
1163
|
+
baseScore -= issues.filter((i) => i.includes("rarely")).length * 10;
|
|
1164
|
+
baseScore -= issues.filter((i) => i.includes("lacks impact")).length * 8;
|
|
1165
|
+
score = Math.max(0, Math.min(100, baseScore));
|
|
1166
|
+
}
|
|
1167
|
+
if (score >= 70) {
|
|
1168
|
+
status = "good";
|
|
1169
|
+
} else if (score >= 50) {
|
|
1170
|
+
status = "warning";
|
|
1171
|
+
} else {
|
|
1172
|
+
status = "critical";
|
|
1173
|
+
}
|
|
1174
|
+
state.themeSaturationScore = createComponentScore(score, status, {
|
|
1175
|
+
issues,
|
|
1176
|
+
suggestions
|
|
1177
|
+
});
|
|
1178
|
+
return state;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Analyze narrative continuity.
|
|
1182
|
+
*
|
|
1183
|
+
* Checks:
|
|
1184
|
+
* - Timeline consistency
|
|
1185
|
+
* - Detail consistency across beats
|
|
1186
|
+
* - Setting/location coherence
|
|
1187
|
+
*/
|
|
1188
|
+
analyzeContinuity(state) {
|
|
1189
|
+
const beats = state.beats;
|
|
1190
|
+
const issues = [];
|
|
1191
|
+
const suggestions = [];
|
|
1192
|
+
let score;
|
|
1193
|
+
let status;
|
|
1194
|
+
if (beats.length < 2) {
|
|
1195
|
+
score = 70;
|
|
1196
|
+
issues.push("Too few beats for continuity analysis");
|
|
1197
|
+
} else {
|
|
1198
|
+
const sequences = beats.map((b) => b.sequence);
|
|
1199
|
+
const sortedSequences = [...sequences].sort((a, b) => a - b);
|
|
1200
|
+
if (JSON.stringify(sequences) !== JSON.stringify(sortedSequences)) {
|
|
1201
|
+
issues.push("Beat sequences are not in order");
|
|
1202
|
+
suggestions.push("Reorder beats to ensure logical sequence progression");
|
|
1203
|
+
}
|
|
1204
|
+
if (sequences.length !== new Set(sequences).size) {
|
|
1205
|
+
issues.push("Duplicate beat sequence numbers found");
|
|
1206
|
+
suggestions.push("Ensure each beat has a unique sequence number");
|
|
1207
|
+
}
|
|
1208
|
+
const maxSeq = Math.max(...sequences);
|
|
1209
|
+
const expected = new Set(
|
|
1210
|
+
Array.from({ length: maxSeq }, (_, i) => i + 1)
|
|
1211
|
+
);
|
|
1212
|
+
const actual = new Set(sequences);
|
|
1213
|
+
const missing = [...expected].filter((x) => !actual.has(x));
|
|
1214
|
+
if (missing.length > 0 && missing.length <= 3) {
|
|
1215
|
+
issues.push(`Missing beat sequences: ${missing.sort().join(", ")}`);
|
|
1216
|
+
suggestions.push("Fill in missing beat sequences or renumber");
|
|
1217
|
+
}
|
|
1218
|
+
let baseScore = 90;
|
|
1219
|
+
baseScore -= issues.filter((i) => i.includes("not in order")).length * 20;
|
|
1220
|
+
baseScore -= issues.filter((i) => i.includes("Duplicate")).length * 15;
|
|
1221
|
+
baseScore -= issues.filter((i) => i.includes("Missing")).length * 5;
|
|
1222
|
+
score = Math.max(0, Math.min(100, baseScore));
|
|
1223
|
+
}
|
|
1224
|
+
if (score >= 70) {
|
|
1225
|
+
status = "good";
|
|
1226
|
+
} else if (score >= 50) {
|
|
1227
|
+
status = "warning";
|
|
1228
|
+
} else {
|
|
1229
|
+
status = "critical";
|
|
1230
|
+
}
|
|
1231
|
+
state.continuityScore = createComponentScore(score, status, {
|
|
1232
|
+
issues,
|
|
1233
|
+
suggestions
|
|
1234
|
+
});
|
|
1235
|
+
return state;
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Calculate the overall coherence score from components.
|
|
1239
|
+
*/
|
|
1240
|
+
calculateOverallScore(state) {
|
|
1241
|
+
const components = [
|
|
1242
|
+
state.narrativeFlowScore,
|
|
1243
|
+
state.characterConsistencyScore,
|
|
1244
|
+
state.pacingScore,
|
|
1245
|
+
state.themeSaturationScore,
|
|
1246
|
+
state.continuityScore
|
|
1247
|
+
];
|
|
1248
|
+
const validScores = components.filter((c) => c !== void 0).map((c) => c.score);
|
|
1249
|
+
if (validScores.length > 0) {
|
|
1250
|
+
const weights = [1.2, 1.2, 1, 1, 0.8];
|
|
1251
|
+
const weightedSum = validScores.reduce(
|
|
1252
|
+
(sum, s, i) => sum + s * weights[i],
|
|
1253
|
+
0
|
|
1254
|
+
);
|
|
1255
|
+
const totalWeight = weights.slice(0, validScores.length).reduce((a, b) => a + b, 0);
|
|
1256
|
+
state.overallScore = weightedSum / totalWeight;
|
|
1257
|
+
} else {
|
|
1258
|
+
state.overallScore = 50;
|
|
1259
|
+
}
|
|
1260
|
+
return state;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Identify narrative gaps from component analyses.
|
|
1264
|
+
*/
|
|
1265
|
+
identifyGaps(state) {
|
|
1266
|
+
const gaps = [];
|
|
1267
|
+
const componentMappings = [
|
|
1268
|
+
["narrativeFlowScore", "structural" /* STRUCTURAL */],
|
|
1269
|
+
["characterConsistencyScore", "character" /* CHARACTER */],
|
|
1270
|
+
["pacingScore", "structural" /* STRUCTURAL */],
|
|
1271
|
+
["themeSaturationScore", "thematic" /* THEMATIC */],
|
|
1272
|
+
["continuityScore", "continuity" /* CONTINUITY */]
|
|
1273
|
+
];
|
|
1274
|
+
for (const [componentKey, gapType] of componentMappings) {
|
|
1275
|
+
const component = state[componentKey];
|
|
1276
|
+
if (component?.issues) {
|
|
1277
|
+
for (const issue of component.issues) {
|
|
1278
|
+
let severity;
|
|
1279
|
+
if (component.status === "critical") {
|
|
1280
|
+
severity = "critical" /* CRITICAL */;
|
|
1281
|
+
} else if (issue.includes("rarely") || issue.includes("disappears")) {
|
|
1282
|
+
severity = "moderate" /* MODERATE */;
|
|
1283
|
+
} else {
|
|
1284
|
+
severity = "minor" /* MINOR */;
|
|
1285
|
+
}
|
|
1286
|
+
let route;
|
|
1287
|
+
if (gapType === "structural" /* STRUCTURAL */) {
|
|
1288
|
+
route = "structurist" /* STRUCTURIST */;
|
|
1289
|
+
} else if (gapType === "character" /* CHARACTER */) {
|
|
1290
|
+
route = "storyteller" /* STORYTELLER */;
|
|
1291
|
+
} else if (gapType === "thematic" /* THEMATIC */) {
|
|
1292
|
+
route = "structurist" /* STRUCTURIST */;
|
|
1293
|
+
} else if (gapType === "sensory" /* SENSORY */) {
|
|
1294
|
+
route = "storyteller" /* STORYTELLER */;
|
|
1295
|
+
} else {
|
|
1296
|
+
route = "author" /* AUTHOR */;
|
|
1297
|
+
}
|
|
1298
|
+
gaps.push(
|
|
1299
|
+
createGap(
|
|
1300
|
+
this.generateGapId(),
|
|
1301
|
+
gapType,
|
|
1302
|
+
severity,
|
|
1303
|
+
issue,
|
|
1304
|
+
route,
|
|
1305
|
+
{ location: { component: componentKey } }
|
|
1306
|
+
)
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
const severityOrder = {
|
|
1312
|
+
["critical" /* CRITICAL */]: 0,
|
|
1313
|
+
["moderate" /* MODERATE */]: 1,
|
|
1314
|
+
["minor" /* MINOR */]: 2
|
|
1315
|
+
};
|
|
1316
|
+
gaps.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
|
|
1317
|
+
state.gaps = gaps;
|
|
1318
|
+
return state;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Generate Trinity perspective assessment (Mia/Miette/Ava8).
|
|
1322
|
+
*
|
|
1323
|
+
* Each persona provides feedback aligned with their perspective:
|
|
1324
|
+
* - Mia 🧠: Structural/logical analysis
|
|
1325
|
+
* - Miette 🌸: Emotional/resonance analysis
|
|
1326
|
+
* - Ava8 🎨: Atmospheric/sensory analysis
|
|
1327
|
+
*/
|
|
1328
|
+
generateTrinityAssessment(state) {
|
|
1329
|
+
const gaps = state.gaps || [];
|
|
1330
|
+
const flow = state.narrativeFlowScore;
|
|
1331
|
+
const character = state.characterConsistencyScore;
|
|
1332
|
+
const pacing = state.pacingScore;
|
|
1333
|
+
const theme = state.themeSaturationScore;
|
|
1334
|
+
const continuity = state.continuityScore;
|
|
1335
|
+
const miaParts = [];
|
|
1336
|
+
if (flow) {
|
|
1337
|
+
miaParts.push(`Structure is ${flow.score.toFixed(0)}% sound.`);
|
|
1338
|
+
if (flow.issues.length > 0) {
|
|
1339
|
+
miaParts.push(`Key structural gap: ${flow.issues[0]}`);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
if (pacing && pacing.score < 70) {
|
|
1343
|
+
miaParts.push(`Pacing needs attention (${pacing.score.toFixed(0)}%).`);
|
|
1344
|
+
if (pacing.suggestions.length > 0) {
|
|
1345
|
+
miaParts.push(pacing.suggestions[0]);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
if (continuity && continuity.score < 80) {
|
|
1349
|
+
miaParts.push(
|
|
1350
|
+
`Continuity has ${continuity.issues.length} issues to address.`
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
const mia = miaParts.length > 0 ? miaParts.join(" ") : "Structure analysis unavailable.";
|
|
1354
|
+
const mietteParts = [];
|
|
1355
|
+
if (character) {
|
|
1356
|
+
if (character.score >= 80) {
|
|
1357
|
+
mietteParts.push("Character arcs are resonating well.");
|
|
1358
|
+
} else {
|
|
1359
|
+
mietteParts.push(
|
|
1360
|
+
`Character consistency is ${character.score.toFixed(0)}%.`
|
|
1361
|
+
);
|
|
1362
|
+
if (character.issues.length > 0) {
|
|
1363
|
+
mietteParts.push(`The emotional gap: ${character.issues[0]}`);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
if (theme) {
|
|
1368
|
+
if (theme.score >= 70) {
|
|
1369
|
+
mietteParts.push("Themes are landing with emotional weight.");
|
|
1370
|
+
} else {
|
|
1371
|
+
mietteParts.push("Themes need stronger emotional anchoring.");
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (flow?.issues) {
|
|
1375
|
+
const jarring = flow.issues.filter((i) => i.includes("Jarring"));
|
|
1376
|
+
if (jarring.length > 0) {
|
|
1377
|
+
mietteParts.push("Emotional transitions feel abrupt in places.");
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const miette = mietteParts.length > 0 ? mietteParts.join(" ") : "Emotional analysis unavailable.";
|
|
1381
|
+
const ava8Parts = [];
|
|
1382
|
+
const sensoryGaps = gaps.filter((g) => g.gapType === "sensory" /* SENSORY */);
|
|
1383
|
+
if (sensoryGaps.length > 0) {
|
|
1384
|
+
ava8Parts.push(`Found ${sensoryGaps.length} sensory gaps to address.`);
|
|
1385
|
+
}
|
|
1386
|
+
if (pacing && pacing.score >= 70) {
|
|
1387
|
+
ava8Parts.push("Atmospheric rhythm feels balanced.");
|
|
1388
|
+
} else {
|
|
1389
|
+
ava8Parts.push("Atmosphere could use more grounding moments.");
|
|
1390
|
+
}
|
|
1391
|
+
if (pacing?.issues.some((i) => i.includes("consecutive high-tension"))) {
|
|
1392
|
+
ava8Parts.push(
|
|
1393
|
+
"The dense tension sections may benefit from visual breathing room."
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
const ava8 = ava8Parts.length > 0 ? ava8Parts.join(" ") : "Atmospheric analysis unavailable.";
|
|
1397
|
+
const priorities = [];
|
|
1398
|
+
const criticalGaps = gaps.filter(
|
|
1399
|
+
(g) => g.severity === "critical" /* CRITICAL */
|
|
1400
|
+
);
|
|
1401
|
+
if (criticalGaps.length > 0) {
|
|
1402
|
+
priorities.push(...criticalGaps.slice(0, 3).map((g) => g.description));
|
|
1403
|
+
} else {
|
|
1404
|
+
const moderateGaps = gaps.filter(
|
|
1405
|
+
(g) => g.severity === "moderate" /* MODERATE */
|
|
1406
|
+
);
|
|
1407
|
+
if (moderateGaps.length > 0) {
|
|
1408
|
+
priorities.push(
|
|
1409
|
+
...moderateGaps.slice(0, 3).map((g) => g.description)
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
if (priorities.length === 0) {
|
|
1414
|
+
priorities.push("Minor polish items only - narrative is coherent");
|
|
1415
|
+
}
|
|
1416
|
+
state.trinityAssessment = createTrinityAssessment(
|
|
1417
|
+
mia,
|
|
1418
|
+
miette,
|
|
1419
|
+
ava8,
|
|
1420
|
+
priorities
|
|
1421
|
+
);
|
|
1422
|
+
return state;
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Build the final coherence result object.
|
|
1426
|
+
*/
|
|
1427
|
+
buildCoherenceResult(state) {
|
|
1428
|
+
state.coherenceScore = createCoherenceScore(
|
|
1429
|
+
state.overallScore || 50,
|
|
1430
|
+
state.narrativeFlowScore || createComponentScore(50, "warning"),
|
|
1431
|
+
state.characterConsistencyScore || createComponentScore(50, "warning"),
|
|
1432
|
+
state.pacingScore || createComponentScore(50, "warning"),
|
|
1433
|
+
state.themeSaturationScore || createComponentScore(50, "warning"),
|
|
1434
|
+
state.continuityScore || createComponentScore(50, "warning")
|
|
1435
|
+
);
|
|
1436
|
+
return state;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Analyze narrative coherence.
|
|
1440
|
+
*
|
|
1441
|
+
* @param beats List of story beats to analyze
|
|
1442
|
+
* @param characters Optional list of character states
|
|
1443
|
+
* @param themes Optional list of thematic threads
|
|
1444
|
+
* @param includeMetadata Whether to include full analysis state
|
|
1445
|
+
* @returns CoherenceResult with coherenceScore, gaps, and trinityAssessment
|
|
1446
|
+
*/
|
|
1447
|
+
analyze(beats, characters = [], themes = [], includeMetadata = false) {
|
|
1448
|
+
let state = {
|
|
1449
|
+
beats,
|
|
1450
|
+
characters,
|
|
1451
|
+
themes
|
|
1452
|
+
};
|
|
1453
|
+
state = this.analyzeNarrativeFlow(state);
|
|
1454
|
+
state = this.analyzeCharacterConsistency(state);
|
|
1455
|
+
state = this.analyzePacing(state);
|
|
1456
|
+
state = this.analyzeThemeSaturation(state);
|
|
1457
|
+
state = this.analyzeContinuity(state);
|
|
1458
|
+
state = this.calculateOverallScore(state);
|
|
1459
|
+
state = this.identifyGaps(state);
|
|
1460
|
+
state = this.generateTrinityAssessment(state);
|
|
1461
|
+
state = this.buildCoherenceResult(state);
|
|
1462
|
+
if (includeMetadata) {
|
|
1463
|
+
return state;
|
|
1464
|
+
} else {
|
|
1465
|
+
return {
|
|
1466
|
+
coherenceScore: state.coherenceScore,
|
|
1467
|
+
gaps: state.gaps || [],
|
|
1468
|
+
trinityAssessment: state.trinityAssessment
|
|
1469
|
+
};
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Group gaps by their routing target.
|
|
1474
|
+
*
|
|
1475
|
+
* @param gaps List of identified gaps
|
|
1476
|
+
* @returns Dictionary mapping routing target to list of gaps
|
|
1477
|
+
*/
|
|
1478
|
+
getRoutingSuggestions(gaps) {
|
|
1479
|
+
const routing = {
|
|
1480
|
+
["storyteller" /* STORYTELLER */]: [],
|
|
1481
|
+
["structurist" /* STRUCTURIST */]: [],
|
|
1482
|
+
["architect" /* ARCHITECT */]: [],
|
|
1483
|
+
["author" /* AUTHOR */]: []
|
|
1484
|
+
};
|
|
1485
|
+
for (const gap of gaps) {
|
|
1486
|
+
routing[gap.suggestedRoute].push(gap);
|
|
1487
|
+
}
|
|
1488
|
+
return routing;
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1492
|
+
0 && (module.exports = {
|
|
1493
|
+
EventType,
|
|
1494
|
+
GapSeverity,
|
|
1495
|
+
GapType,
|
|
1496
|
+
NarrativeCoherenceEngine,
|
|
1497
|
+
RoutingTarget,
|
|
1498
|
+
ThreeUniverseProcessor,
|
|
1499
|
+
analyzeCeremonyPerspective,
|
|
1500
|
+
analyzeEngineerPerspective,
|
|
1501
|
+
analyzeStoryEnginePerspective,
|
|
1502
|
+
ceremonyIntentKeywords,
|
|
1503
|
+
createCoherenceScore,
|
|
1504
|
+
createComponentScore,
|
|
1505
|
+
createGap,
|
|
1506
|
+
createTrinityAssessment,
|
|
1507
|
+
engineerIntentKeywords,
|
|
1508
|
+
storyEngineIntentKeywords,
|
|
1509
|
+
synthesizePerspectives
|
|
1510
|
+
});
|
|
1511
|
+
//# sourceMappingURL=index.cjs.map
|