coaiajs 0.3.0 → 0.3.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 (175) hide show
  1. package/KINSHIP.md +1 -1
  2. package/README.md +191 -75
  3. package/dist/mcp/config.d.ts.map +1 -0
  4. package/dist/mcp/config.js +0 -2
  5. package/dist/mcp/config.js.map +1 -0
  6. package/dist/mcp/prompts.d.ts.map +1 -0
  7. package/dist/mcp/prompts.js.map +1 -0
  8. package/dist/mcp/resources.d.ts.map +1 -0
  9. package/dist/mcp/resources.js.map +1 -0
  10. package/dist/mcp/server.d.ts.map +1 -0
  11. package/dist/mcp/server.js +1 -1
  12. package/dist/mcp/server.js.map +1 -0
  13. package/dist/mcp/tools/coaiapy-tools.d.ts.map +1 -0
  14. package/dist/mcp/tools/coaiapy-tools.js.map +1 -0
  15. package/dist/mcp/tools/index.d.ts.map +1 -0
  16. package/dist/mcp/tools/index.js.map +1 -0
  17. package/dist/src/audio.d.ts.map +1 -0
  18. package/dist/src/audio.js.map +1 -0
  19. package/dist/src/cli-helpers.d.ts.map +1 -0
  20. package/dist/src/cli-helpers.js.map +1 -0
  21. package/dist/src/cli.d.ts.map +1 -0
  22. package/dist/src/cli.js.map +1 -0
  23. package/dist/src/config.d.ts.map +1 -0
  24. package/dist/src/config.js.map +1 -0
  25. package/dist/src/environment.d.ts.map +1 -0
  26. package/dist/src/environment.js.map +1 -0
  27. package/dist/src/github.d.ts.map +1 -0
  28. package/dist/src/github.js.map +1 -0
  29. package/dist/src/index.d.ts +1 -0
  30. package/dist/src/index.d.ts.map +1 -0
  31. package/dist/src/index.js +1 -0
  32. package/dist/src/index.js.map +1 -0
  33. package/dist/src/langfuse/client.d.ts.map +1 -0
  34. package/dist/src/langfuse/client.js.map +1 -0
  35. package/dist/src/langfuse/comments.d.ts.map +1 -0
  36. package/dist/src/langfuse/comments.js.map +1 -0
  37. package/dist/src/langfuse/datasets.d.ts.map +1 -0
  38. package/dist/src/langfuse/datasets.js.map +1 -0
  39. package/dist/src/langfuse/index.d.ts.map +1 -0
  40. package/dist/src/langfuse/index.js.map +1 -0
  41. package/dist/src/langfuse/media.d.ts.map +1 -0
  42. package/dist/src/langfuse/media.js.map +1 -0
  43. package/dist/src/langfuse/observations.d.ts.map +1 -0
  44. package/dist/src/langfuse/observations.js.map +1 -0
  45. package/dist/src/langfuse/prompts.d.ts.map +1 -0
  46. package/dist/src/langfuse/prompts.js.map +1 -0
  47. package/dist/src/langfuse/scores.d.ts.map +1 -0
  48. package/dist/src/langfuse/scores.js.map +1 -0
  49. package/dist/src/langfuse/traces.d.ts.map +1 -0
  50. package/dist/src/langfuse/traces.js.map +1 -0
  51. package/dist/src/llm.d.ts.map +1 -0
  52. package/dist/src/llm.js.map +1 -0
  53. package/dist/src/narrative/graph-manager.d.ts.map +1 -0
  54. package/dist/src/narrative/graph-manager.js.map +1 -0
  55. package/dist/src/narrative/index.d.ts.map +1 -0
  56. package/dist/src/narrative/index.js.map +1 -0
  57. package/dist/src/narrative/markdown-export.d.ts.map +1 -0
  58. package/dist/src/narrative/markdown-export.js.map +1 -0
  59. package/dist/src/narrative/tool-definitions.d.ts.map +1 -0
  60. package/dist/src/narrative/tool-definitions.js.map +1 -0
  61. package/dist/src/narrative/tool-handlers.d.ts.map +1 -0
  62. package/dist/src/narrative/tool-handlers.js.map +1 -0
  63. package/dist/src/narrative/types.d.ts.map +1 -0
  64. package/dist/src/narrative/types.js.map +1 -0
  65. package/dist/src/narrative/validation.d.ts.map +1 -0
  66. package/dist/src/narrative/validation.js.map +1 -0
  67. package/dist/src/pde/index.d.ts.map +1 -0
  68. package/dist/src/pde/index.js.map +1 -0
  69. package/dist/src/pde/mcp-handlers.d.ts.map +1 -0
  70. package/dist/src/pde/mcp-handlers.js.map +1 -0
  71. package/dist/src/pde/mcp-tools.d.ts.map +1 -0
  72. package/dist/src/pde/mcp-tools.js.map +1 -0
  73. package/dist/src/pde/session-manager.d.ts.map +1 -0
  74. package/dist/src/pde/session-manager.js.map +1 -0
  75. package/dist/src/pde/stc-mapper.d.ts.map +1 -0
  76. package/dist/src/pde/stc-mapper.js.map +1 -0
  77. package/dist/src/pipeline/index.d.ts.map +1 -0
  78. package/dist/src/pipeline/index.js.map +1 -0
  79. package/dist/src/pipeline/template-engine.d.ts.map +1 -0
  80. package/dist/src/pipeline/template-engine.js.map +1 -0
  81. package/dist/src/planning/index.d.ts.map +1 -0
  82. package/dist/src/planning/index.js.map +1 -0
  83. package/dist/src/planning/mcp-handlers.d.ts.map +1 -0
  84. package/dist/src/planning/mcp-handlers.js.map +1 -0
  85. package/dist/src/planning/mcp-tools.d.ts.map +1 -0
  86. package/dist/src/planning/mcp-tools.js.map +1 -0
  87. package/dist/src/planning/plan-parser.d.ts.map +1 -0
  88. package/dist/src/planning/plan-parser.js.map +1 -0
  89. package/dist/src/redis.d.ts.map +1 -0
  90. package/dist/src/redis.js.map +1 -0
  91. package/dist/src/types.d.ts.map +1 -0
  92. package/dist/src/types.js.map +1 -0
  93. package/dist/src/version.d.ts.map +1 -0
  94. package/dist/src/version.js.map +1 -0
  95. package/llms-full.txt +361 -0
  96. package/llms.txt +43 -0
  97. package/package.json +79 -12
  98. package/.claude/settings.local.json +0 -17
  99. package/.claude-plugin/marketplace.json +0 -26
  100. package/articles/academic/NOTES.md +0 -1
  101. package/articles/academic/README.md +0 -1
  102. package/articles/academic/creative-orientation-vs-problem-solving.md +0 -177
  103. package/articles/academic/jsonl-knowledge-graphs-agent-memory.md +0 -142
  104. package/articles/academic/langfuse-observability-llm-pipelines.md +0 -144
  105. package/articles/academic/medicine-wheel-software-architecture.md +0 -163
  106. package/articles/academic/mmot-autonomous-agents.md +0 -156
  107. package/articles/academic/model-context-protocol-interagent.md +0 -161
  108. package/articles/academic/pde-prompt-decomposition.md +0 -186
  109. package/articles/academic/structural-tension-in-ai-agents.md +0 -134
  110. package/articles/reviews/mcp-protocol-design-review.md +0 -170
  111. package/articles/reviews/observability-ai-systems-review.md +0 -176
  112. package/articles/reviews/prompt-engineering-decomposition-review.md +0 -184
  113. package/articles/surveys/agent-orchestration-survey.md +0 -186
  114. package/articles/surveys/knowledge-graph-storage-survey.md +0 -204
  115. package/articles/surveys/structural-tension-methodology-survey.md +0 -154
  116. package/articles/technical/aws-sdk-v3-polly.md +0 -270
  117. package/articles/technical/commander-cli-framework.md +0 -262
  118. package/articles/technical/dotenv-config-patterns.md +0 -360
  119. package/articles/technical/ioredis-vs-redis.md +0 -142
  120. package/articles/technical/langfuse-js-sdk-vs-rest.md +0 -191
  121. package/articles/technical/mcp-sdk-typescript.md +0 -291
  122. package/articles/technical/octokit-github-api.md +0 -293
  123. package/articles/technical/openai-sdk-modern.md +0 -231
  124. package/articles/technical/yaml-parsing-node.md +0 -266
  125. package/articles/technical/zod-runtime-validation.md +0 -212
  126. package/coaiajs-langfuse-claude-plugin/.claude-plugin/marketplace.json +0 -16
  127. package/coaiajs-langfuse-claude-plugin/.claude-plugin/plugin.json +0 -10
  128. package/coaiajs-langfuse-claude-plugin/.mcp.json +0 -8
  129. package/coaiajs-langfuse-claude-plugin/README.md +0 -60
  130. package/mcp/config.ts +0 -225
  131. package/mcp/prompts.ts +0 -131
  132. package/mcp/resources.ts +0 -84
  133. package/mcp/server.ts +0 -519
  134. package/mcp/tools/coaiapy-tools.ts +0 -366
  135. package/mcp/tools/index.ts +0 -4
  136. package/src/audio.ts +0 -76
  137. package/src/cli-helpers.ts +0 -86
  138. package/src/cli.ts +0 -1261
  139. package/src/config.ts +0 -207
  140. package/src/environment.ts +0 -171
  141. package/src/github.ts +0 -143
  142. package/src/index.ts +0 -82
  143. package/src/langfuse/client.ts +0 -105
  144. package/src/langfuse/comments.ts +0 -52
  145. package/src/langfuse/datasets.ts +0 -178
  146. package/src/langfuse/index.ts +0 -37
  147. package/src/langfuse/media.ts +0 -193
  148. package/src/langfuse/observations.ts +0 -155
  149. package/src/langfuse/prompts.ts +0 -157
  150. package/src/langfuse/scores.ts +0 -456
  151. package/src/langfuse/traces.ts +0 -353
  152. package/src/llm.ts +0 -106
  153. package/src/narrative/graph-manager.ts +0 -1358
  154. package/src/narrative/index.ts +0 -188
  155. package/src/narrative/markdown-export.ts +0 -535
  156. package/src/narrative/tool-definitions.ts +0 -635
  157. package/src/narrative/tool-handlers.ts +0 -528
  158. package/src/narrative/types.ts +0 -9
  159. package/src/narrative/validation.ts +0 -179
  160. package/src/pde/index.ts +0 -34
  161. package/src/pde/mcp-handlers.ts +0 -359
  162. package/src/pde/mcp-tools.ts +0 -201
  163. package/src/pde/session-manager.ts +0 -248
  164. package/src/pde/stc-mapper.ts +0 -298
  165. package/src/pipeline/index.ts +0 -7
  166. package/src/pipeline/template-engine.ts +0 -398
  167. package/src/planning/index.ts +0 -32
  168. package/src/planning/mcp-handlers.ts +0 -369
  169. package/src/planning/mcp-tools.ts +0 -155
  170. package/src/planning/plan-parser.ts +0 -587
  171. package/src/redis.ts +0 -111
  172. package/src/types.ts +0 -281
  173. package/src/version.ts +0 -39
  174. package/test/config.test.mjs +0 -93
  175. package/tsconfig.json +0 -26
@@ -1,535 +0,0 @@
1
- /**
2
- * Markdown Export Module for COAIA Narrative
3
- *
4
- * Provides markdown generation for structural tension charts,
5
- * narrative beats, and associated data structures.
6
- */
7
-
8
- import { promises as fs } from 'fs';
9
- import path from 'path';
10
- import type { Entity, KnowledgeGraph } from '../types.js';
11
- import type { KnowledgeGraphManager } from './graph-manager.js';
12
-
13
- export interface MarkdownOptions {
14
- includeMetadata?: boolean;
15
- includeObservations?: boolean;
16
- observationLimit?: number;
17
- includeToc?: boolean;
18
- outputPath?: string;
19
- }
20
-
21
- // ─── Utility Functions ────────────────────────────────────────────────
22
-
23
- function escapeMarkdown(text: string): string {
24
- return text
25
- .replace(/\\/g, '\\\\')
26
- .replace(/\*/g, '\\*')
27
- .replace(/\[/g, '\\[')
28
- .replace(/\]/g, '\\]')
29
- .replace(/\(/g, '\\(')
30
- .replace(/\)/g, '\\)');
31
- }
32
-
33
- function formatDateForMarkdown(dateStr?: string): string {
34
- if (!dateStr) return 'No due date';
35
- const date = new Date(dateStr);
36
- const now = new Date();
37
- const days = Math.ceil((date.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
38
-
39
- if (days < 0) return `Overdue by ${Math.abs(days)} days`;
40
- if (days === 0) return 'Due today';
41
- if (days === 1) return 'Due tomorrow';
42
- if (days <= 7) return `Due in ${days} days`;
43
- return `${date.toLocaleDateString()}`;
44
- }
45
-
46
- function formatProgressBar(progress: number): string {
47
- const width = 20;
48
- const filled = Math.round(progress * width);
49
- const empty = width - filled;
50
- const bar = '█'.repeat(filled) + '░'.repeat(empty);
51
- const percent = Math.round(progress * 100);
52
- return `[${bar}] ${percent}%`;
53
- }
54
-
55
- function getStatusIcon(completed: boolean): string {
56
- return completed ? '✅' : '⏳';
57
- }
58
-
59
- function slugify(text: string): string {
60
- return text
61
- .toLowerCase()
62
- .replace(/[^\w\s-]/g, '')
63
- .replace(/\s+/g, '-')
64
- .replace(/-+/g, '-');
65
- }
66
-
67
- // ─── Single Chart Export ──────────────────────────────────────────────
68
-
69
- export async function exportChartToMarkdown(
70
- chartId: string,
71
- manager: KnowledgeGraphManager,
72
- options: MarkdownOptions = {},
73
- ): Promise<string> {
74
- const graph = await manager.readGraph();
75
- const {
76
- includeMetadata = true,
77
- includeObservations = true,
78
- observationLimit = 0,
79
- } = options;
80
-
81
- const chart = graph.entities.find(
82
- e =>
83
- e.entityType === 'structural_tension_chart' &&
84
- e.metadata?.chartId === chartId,
85
- );
86
-
87
- if (!chart) {
88
- return `# Error\n\nChart '${chartId}' not found.`;
89
- }
90
-
91
- let md = '';
92
-
93
- md += `# Chart: ${chartId}\n\n`;
94
-
95
- if (includeMetadata) {
96
- if (chart.metadata?.createdAt) {
97
- const created = new Date(chart.metadata.createdAt).toLocaleString();
98
- md += `> **Created**: ${created}\n`;
99
- }
100
- if (chart.metadata?.parentChart) {
101
- md += `> **Parent Chart**: ${chart.metadata.parentChart} (Level ${chart.metadata.level})\n`;
102
- } else {
103
- md += `> **Master Chart** (Level ${chart.metadata?.level || 0})\n`;
104
- }
105
- if (chart.metadata?.dueDate) {
106
- md += `> **Due**: ${formatDateForMarkdown(chart.metadata.dueDate)}\n`;
107
- }
108
- md += '\n';
109
- }
110
-
111
- // Desired Outcome
112
- const outcome = graph.entities.find(
113
- e =>
114
- e.name === `${chartId}_desired_outcome` &&
115
- e.entityType === 'desired_outcome',
116
- );
117
- md += '## Desired Outcome\n\n';
118
- if (outcome) {
119
- md += `${escapeMarkdown(outcome.observations[0])}\n\n`;
120
- } else {
121
- md += '*(Unknown)*\n\n';
122
- }
123
-
124
- // Current Reality
125
- const currentReality = graph.entities.find(
126
- e =>
127
- e.name === `${chartId}_current_reality` &&
128
- e.entityType === 'current_reality',
129
- );
130
- md += '## Current Reality\n\n';
131
- if (currentReality && currentReality.observations.length > 0) {
132
- if (includeObservations && observationLimit > 0) {
133
- const obs = currentReality.observations.slice(-observationLimit);
134
- obs.forEach(o => (md += `- ${escapeMarkdown(o)}\n`));
135
- } else if (includeObservations) {
136
- currentReality.observations.forEach(o => (md += `- ${escapeMarkdown(o)}\n`));
137
- } else {
138
- md += `- ${escapeMarkdown(currentReality.observations[currentReality.observations.length - 1])}\n`;
139
- }
140
- md += '\n';
141
- } else {
142
- md += '*(Not assessed)*\n\n';
143
- }
144
-
145
- // Progress & Structural Tension
146
- const actionSteps = graph.entities.filter(
147
- e => e.entityType === 'action_step' && e.metadata?.chartId === chartId,
148
- );
149
- const completed = actionSteps.filter(
150
- a => a.metadata?.completionStatus === true,
151
- ).length;
152
- const total = actionSteps.length;
153
- const progress = total > 0 ? completed / total : 0;
154
-
155
- md += '## Structural Tension\n\n';
156
- md += `${formatProgressBar(progress)}\n\n`;
157
- md += `- **Completed**: ${completed}/${total} action steps\n\n`;
158
-
159
- // Action Steps
160
- if (actionSteps.length > 0) {
161
- md += '## Action Steps\n\n';
162
- actionSteps.forEach((step, idx) => {
163
- const isComplete = step.metadata?.completionStatus === true;
164
- const status = getStatusIcon(isComplete);
165
- const stepId = (step.metadata?.chartId as string) || `step_${idx + 1}`;
166
-
167
- md += `### ${status} ${escapeMarkdown(step.observations[0])}\n\n`;
168
- md += `- **ID**: ${stepId}\n`;
169
- md += `- **Status**: ${isComplete ? 'Completed' : 'In Progress'}\n`;
170
- if (step.metadata?.dueDate) {
171
- md += `- **Due**: ${formatDateForMarkdown(step.metadata.dueDate)}\n`;
172
- }
173
-
174
- if (step.observations.length > 1 && includeObservations) {
175
- md += `- **Notes**:\n`;
176
- step.observations.slice(1).forEach(note => {
177
- md += ` - ${escapeMarkdown(note)}\n`;
178
- });
179
- }
180
- md += '\n';
181
- });
182
- }
183
-
184
- // Narrative Beats
185
- const narrativeBeats = graph.entities
186
- .filter(
187
- e =>
188
- e.entityType === 'narrative_beat' && e.metadata?.chartId === chartId,
189
- )
190
- .sort((a, b) => ((a.metadata?.act as number) || 0) - ((b.metadata?.act as number) || 0));
191
-
192
- if (narrativeBeats.length > 0) {
193
- md += '## Narrative Beats\n\n';
194
- narrativeBeats.forEach(beat => {
195
- const act = beat.metadata?.act || '?';
196
- const type = beat.metadata?.type_dramatic || 'Unknown';
197
- const universes = (beat.metadata?.universes as string[]) || [];
198
-
199
- md += `### Act ${act}: ${escapeMarkdown(type as string)}\n\n`;
200
-
201
- if (universes.length > 0) {
202
- md += `- **Universes**: ${universes.join(', ')}\n`;
203
- }
204
- if (beat.metadata?.timestamp) {
205
- const ts = new Date(beat.metadata.timestamp).toLocaleString();
206
- md += `- **Timestamp**: ${ts}\n`;
207
- }
208
-
209
- if (beat.metadata?.narrative?.description) {
210
- md += `\n**Description**:\n\n${escapeMarkdown(beat.metadata.narrative.description)}\n`;
211
- }
212
-
213
- if (beat.metadata?.narrative?.prose) {
214
- md += `\n**Prose**:\n\n${escapeMarkdown(beat.metadata.narrative.prose)}\n`;
215
- }
216
-
217
- if (
218
- beat.metadata?.narrative?.lessons &&
219
- beat.metadata.narrative.lessons.length > 0
220
- ) {
221
- md += `\n**Lessons**:\n\n`;
222
- beat.metadata.narrative.lessons.forEach(lesson => {
223
- md += `- ${escapeMarkdown(lesson)}\n`;
224
- });
225
- }
226
-
227
- const dirs = beat.metadata?.fourDirections;
228
- if (
229
- dirs &&
230
- (dirs.north_vision ||
231
- dirs.east_intention ||
232
- dirs.south_emotion ||
233
- dirs.west_introspection)
234
- ) {
235
- md += `\n**Four Directions**:\n\n`;
236
- if (dirs.north_vision) md += `- **North (Vision)**: ${escapeMarkdown(dirs.north_vision)}\n`;
237
- if (dirs.east_intention) md += `- **East (Intention)**: ${escapeMarkdown(dirs.east_intention)}\n`;
238
- if (dirs.south_emotion) md += `- **South (Emotion)**: ${escapeMarkdown(dirs.south_emotion)}\n`;
239
- if (dirs.west_introspection) md += `- **West (Introspection)**: ${escapeMarkdown(dirs.west_introspection)}\n`;
240
- }
241
-
242
- md += '\n';
243
- });
244
- }
245
-
246
- return md;
247
- }
248
-
249
- // ─── All Charts Export ────────────────────────────────────────────────
250
-
251
- export async function exportAllCharts(
252
- manager: KnowledgeGraphManager,
253
- options: MarkdownOptions = {},
254
- ): Promise<string> {
255
- const graph = await manager.readGraph();
256
- const { includeToc = true } = options;
257
-
258
- const charts = graph.entities.filter(
259
- e => e.entityType === 'structural_tension_chart',
260
- );
261
- const masterCharts = charts.filter(c => c.metadata?.level === 0);
262
-
263
- let md = '# Structural Tension Charts\n\n';
264
-
265
- if (includeToc && masterCharts.length > 0) {
266
- md += '## Table of Contents\n\n';
267
- masterCharts.forEach(master => {
268
- const cId = (master.metadata?.chartId as string) || master.name;
269
- const slug = slugify(cId);
270
- md += `- [${cId}](#${slug})\n`;
271
- });
272
- md += '\n---\n\n';
273
- }
274
-
275
- masterCharts.forEach((master, masterIdx) => {
276
- const cId = (master.metadata?.chartId as string) || master.name;
277
-
278
- md += `## ${cId}\n\n`;
279
-
280
- const outcome = graph.entities.find(
281
- e =>
282
- e.name === `${cId}_desired_outcome` &&
283
- e.entityType === 'desired_outcome',
284
- );
285
- md += `**Desired Outcome**: ${outcome?.observations[0] || 'Unknown'}\n\n`;
286
-
287
- const cr = graph.entities.find(
288
- e =>
289
- e.name === `${cId}_current_reality` &&
290
- e.entityType === 'current_reality',
291
- );
292
- if (cr && cr.observations.length > 0) {
293
- md += `**Current Reality**: ${cr.observations[cr.observations.length - 1]}\n\n`;
294
- }
295
-
296
- const actionSteps = graph.entities.filter(
297
- e => e.entityType === 'action_step' && e.metadata?.chartId === cId,
298
- );
299
- const completed = actionSteps.filter(
300
- a => a.metadata?.completionStatus === true,
301
- ).length;
302
- const total = actionSteps.length;
303
- const progress = total > 0 ? completed / total : 0;
304
-
305
- md += `**Progress**: ${formatProgressBar(progress)} (${completed}/${total})\n\n`;
306
-
307
- if (master.metadata?.dueDate) {
308
- md += `**Due**: ${formatDateForMarkdown(master.metadata.dueDate)}\n\n`;
309
- }
310
-
311
- const actionCharts = charts.filter(
312
- c => c.metadata?.parentChart === cId && c.metadata?.level === 1,
313
- );
314
-
315
- if (actionCharts.length > 0) {
316
- md += '### Action Steps\n\n';
317
- actionCharts.forEach(actionChart => {
318
- const actionChartId = actionChart.metadata?.chartId as string;
319
- const actionOutcome = graph.entities.find(
320
- e =>
321
- e.name === `${actionChartId}_desired_outcome` &&
322
- e.entityType === 'desired_outcome',
323
- );
324
- const actionActions = graph.entities.filter(
325
- e =>
326
- e.entityType === 'action_step' &&
327
- e.metadata?.chartId === actionChartId,
328
- );
329
-
330
- const actionCompleted = actionActions.filter(
331
- a => a.metadata?.completionStatus === true,
332
- ).length;
333
- const actionTotal = actionActions.length;
334
- const actionProgress =
335
- actionTotal > 0 ? actionCompleted / actionTotal : 0;
336
- const isComplete = actionChart.metadata?.completionStatus === true;
337
- const status = isComplete ? '✅' : actionProgress > 0 ? '🔄' : '⏳';
338
-
339
- md += `- ${status} **${escapeMarkdown(actionOutcome?.observations[0] || 'Unknown')}**\n`;
340
- md += ` - ID: ${actionChartId}\n`;
341
- if (actionChart.metadata?.dueDate) {
342
- md += ` - Due: ${formatDateForMarkdown(actionChart.metadata.dueDate)}\n`;
343
- }
344
- if (actionTotal > 0) {
345
- md += ` - Progress: ${formatProgressBar(actionProgress)}\n`;
346
- }
347
- });
348
- md += '\n';
349
- }
350
-
351
- if (masterIdx < masterCharts.length - 1) {
352
- md += '---\n\n';
353
- }
354
- });
355
-
356
- return md;
357
- }
358
-
359
- // ─── Progress Report ──────────────────────────────────────────────────
360
-
361
- export async function exportChartProgress(
362
- chartId: string,
363
- manager: KnowledgeGraphManager,
364
- ): Promise<string> {
365
- const graph = await manager.readGraph();
366
-
367
- const chart = graph.entities.find(
368
- e =>
369
- e.entityType === 'structural_tension_chart' &&
370
- e.metadata?.chartId === chartId,
371
- );
372
-
373
- if (!chart) {
374
- return `# Error\n\nChart '${chartId}' not found.`;
375
- }
376
-
377
- const outcome = graph.entities.find(
378
- e => e.name === `${chartId}_desired_outcome`,
379
- );
380
- const actions = graph.entities.filter(
381
- e => e.entityType === 'action_step' && e.metadata?.chartId === chartId,
382
- );
383
-
384
- const completed = actions.filter(
385
- a => a.metadata?.completionStatus === true,
386
- );
387
- const incomplete = actions.filter(
388
- a => a.metadata?.completionStatus !== true,
389
- );
390
- const progress = actions.length > 0 ? completed.length / actions.length : 0;
391
-
392
- let md = `# Progress Report: ${chartId}\n\n`;
393
-
394
- md += `**Goal**: ${outcome?.observations[0] || 'Unknown'}\n\n`;
395
-
396
- md += `## Overall Progress\n\n`;
397
- md += `${formatProgressBar(progress)}\n\n`;
398
-
399
- md += '## Completed Actions\n\n';
400
- if (completed.length > 0) {
401
- completed.forEach((action, idx) => {
402
- md += `${idx + 1}. ${escapeMarkdown(action.observations[0])}\n`;
403
- if (action.metadata?.dueDate) {
404
- md += ` - Completed: ${formatDateForMarkdown(action.metadata.dueDate)}\n`;
405
- }
406
- });
407
- } else {
408
- md += '*No completed actions yet.*\n';
409
- }
410
- md += '\n';
411
-
412
- md += '## Remaining Actions\n\n';
413
- if (incomplete.length > 0) {
414
- incomplete.forEach((action, idx) => {
415
- md += `${idx + 1}. ${escapeMarkdown(action.observations[0])}\n`;
416
- if (action.metadata?.dueDate) {
417
- md += ` - Due: ${formatDateForMarkdown(action.metadata.dueDate)}\n`;
418
- }
419
- });
420
- } else {
421
- md += '*All actions completed!*\n';
422
- }
423
- md += '\n';
424
-
425
- const currentReality = graph.entities.find(
426
- e => e.name === `${chartId}_current_reality`,
427
- );
428
- if (currentReality && currentReality.observations.length > 0) {
429
- md += '## Current Reality Notes\n\n';
430
- currentReality.observations.slice(-5).forEach(obs => {
431
- md += `- ${escapeMarkdown(obs)}\n`;
432
- });
433
- }
434
-
435
- return md;
436
- }
437
-
438
- // ─── Statistics ───────────────────────────────────────────────────────
439
-
440
- export async function exportChartStats(
441
- manager: KnowledgeGraphManager,
442
- ): Promise<string> {
443
- const graph = await manager.readGraph();
444
-
445
- const charts = graph.entities.filter(
446
- e => e.entityType === 'structural_tension_chart',
447
- );
448
- const masterCharts = charts.filter(c => c.metadata?.level === 0);
449
- const actionCharts = charts.filter(c => c.metadata?.level === 1);
450
-
451
- const allActions = graph.entities.filter(
452
- e => e.entityType === 'action_step',
453
- );
454
- const completedActions = allActions.filter(
455
- a => a.metadata?.completionStatus === true,
456
- );
457
-
458
- const narrativeBeats = graph.entities.filter(
459
- e => e.entityType === 'narrative_beat',
460
- );
461
-
462
- const overdueCharts = charts.filter(chart => {
463
- if (!chart.metadata?.dueDate) return false;
464
- const dueDate = new Date(chart.metadata.dueDate);
465
- return dueDate < new Date();
466
- });
467
-
468
- let md = '# Structural Tension Charts Statistics\n\n';
469
-
470
- md += '## Overview\n\n';
471
- md += `| Metric | Count |\n`;
472
- md += `|--------|-------|\n`;
473
- md += `| Master Charts | ${masterCharts.length} |\n`;
474
- md += `| Action Step Charts | ${actionCharts.length} |\n`;
475
- md += `| Total Charts | ${charts.length} |\n`;
476
- md += `| Narrative Beats | ${narrativeBeats.length} |\n`;
477
- md += '\n';
478
-
479
- md += '## Completion Status\n\n';
480
- md += `| Status | Count |\n`;
481
- md += `|--------|-------|\n`;
482
- md += `| Completed Actions | ${completedActions.length}/${allActions.length} |\n`;
483
- const overallProgress =
484
- allActions.length > 0
485
- ? Math.round((completedActions.length / allActions.length) * 100)
486
- : 0;
487
- md += `| Overall Progress | ${overallProgress}% |\n`;
488
- md += '\n';
489
-
490
- if (overdueCharts.length > 0) {
491
- md += '## ⚠️ Overdue Charts\n\n';
492
- overdueCharts.forEach((chart, idx) => {
493
- const chartId = (chart.metadata?.chartId as string) || chart.name;
494
- md += `${idx + 1}. **${chartId}** - Due: ${formatDateForMarkdown(chart.metadata?.dueDate)}\n`;
495
- });
496
- } else {
497
- md += '## ✅ Status\n\n';
498
- md += 'All charts are on track!\n';
499
- }
500
- md += '\n';
501
-
502
- return md;
503
- }
504
-
505
- // ─── File Output ──────────────────────────────────────────────────────
506
-
507
- export async function writeMarkdownToFile(
508
- content: string,
509
- outputPath: string,
510
- ): Promise<void> {
511
- const dir = path.dirname(outputPath);
512
- try {
513
- await fs.mkdir(dir, { recursive: true });
514
- } catch (_e) {
515
- // Directory may exist
516
- }
517
- await fs.writeFile(outputPath, content, 'utf-8');
518
- }
519
-
520
- export function getDefaultFilename(exportType: string, chartId?: string): string {
521
- const timestamp = new Date().toISOString().split('T')[0];
522
-
523
- switch (exportType) {
524
- case 'chart':
525
- return `${chartId}-export-${timestamp}.md`;
526
- case 'list':
527
- return `structural-tension-charts-${timestamp}.md`;
528
- case 'progress':
529
- return `${chartId}-progress-${timestamp}.md`;
530
- case 'stats':
531
- return `statistics-${timestamp}.md`;
532
- default:
533
- return `export-${timestamp}.md`;
534
- }
535
- }