coaiajs 0.1.0 → 0.1.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 (181) hide show
  1. package/dist/mcp/config.d.ts +4 -0
  2. package/dist/mcp/config.d.ts.map +1 -0
  3. package/dist/mcp/config.js +52 -26
  4. package/dist/mcp/config.js.map +1 -0
  5. package/dist/mcp/prompts.d.ts +19 -0
  6. package/dist/mcp/prompts.d.ts.map +1 -0
  7. package/dist/mcp/prompts.js +111 -0
  8. package/dist/mcp/prompts.js.map +1 -0
  9. package/dist/mcp/resources.d.ts +5 -0
  10. package/dist/mcp/resources.d.ts.map +1 -0
  11. package/dist/mcp/resources.js +77 -0
  12. package/dist/mcp/resources.js.map +1 -0
  13. package/dist/mcp/server.d.ts.map +1 -0
  14. package/dist/mcp/server.js +164 -73
  15. package/dist/mcp/server.js.map +1 -0
  16. package/dist/mcp/tools/coaiapy-tools.d.ts.map +1 -0
  17. package/dist/mcp/tools/coaiapy-tools.js +1 -0
  18. package/dist/mcp/tools/coaiapy-tools.js.map +1 -0
  19. package/dist/mcp/tools/index.d.ts.map +1 -0
  20. package/dist/mcp/tools/index.js.map +1 -0
  21. package/dist/src/audio.d.ts.map +1 -0
  22. package/dist/src/audio.js.map +1 -0
  23. package/dist/src/cli-helpers.d.ts.map +1 -0
  24. package/dist/src/cli-helpers.js.map +1 -0
  25. package/dist/src/cli.d.ts.map +1 -0
  26. package/dist/src/cli.js.map +1 -0
  27. package/dist/src/config.d.ts.map +1 -0
  28. package/dist/src/config.js.map +1 -0
  29. package/dist/src/environment.d.ts.map +1 -0
  30. package/dist/src/environment.js.map +1 -0
  31. package/dist/src/github.d.ts.map +1 -0
  32. package/dist/src/github.js.map +1 -0
  33. package/dist/src/index.d.ts +13 -0
  34. package/dist/src/index.d.ts.map +1 -0
  35. package/dist/src/index.js +13 -0
  36. package/dist/src/index.js.map +1 -0
  37. package/dist/src/langfuse/client.d.ts.map +1 -0
  38. package/dist/src/langfuse/client.js.map +1 -0
  39. package/dist/src/langfuse/comments.d.ts.map +1 -0
  40. package/dist/src/langfuse/comments.js.map +1 -0
  41. package/dist/src/langfuse/datasets.d.ts.map +1 -0
  42. package/dist/src/langfuse/datasets.js.map +1 -0
  43. package/dist/src/langfuse/index.d.ts.map +1 -0
  44. package/dist/src/langfuse/index.js.map +1 -0
  45. package/dist/src/langfuse/media.d.ts.map +1 -0
  46. package/dist/src/langfuse/media.js.map +1 -0
  47. package/dist/src/langfuse/observations.d.ts.map +1 -0
  48. package/dist/src/langfuse/observations.js.map +1 -0
  49. package/dist/src/langfuse/prompts.d.ts.map +1 -0
  50. package/dist/src/langfuse/prompts.js.map +1 -0
  51. package/dist/src/langfuse/scores.d.ts.map +1 -0
  52. package/dist/src/langfuse/scores.js.map +1 -0
  53. package/dist/src/langfuse/traces.d.ts.map +1 -0
  54. package/dist/src/langfuse/traces.js.map +1 -0
  55. package/dist/src/llm.d.ts.map +1 -0
  56. package/dist/src/llm.js.map +1 -0
  57. package/dist/src/narrative/graph-manager.d.ts.map +1 -0
  58. package/dist/src/narrative/graph-manager.js.map +1 -0
  59. package/dist/src/narrative/index.d.ts +32 -1
  60. package/dist/src/narrative/index.d.ts.map +1 -0
  61. package/dist/src/narrative/index.js +97 -1
  62. package/dist/src/narrative/index.js.map +1 -0
  63. package/dist/src/narrative/markdown-export.d.ts.map +1 -0
  64. package/dist/src/narrative/markdown-export.js.map +1 -0
  65. package/dist/src/narrative/tool-definitions.d.ts.map +1 -0
  66. package/dist/src/narrative/tool-definitions.js.map +1 -0
  67. package/dist/src/narrative/tool-handlers.d.ts.map +1 -0
  68. package/dist/src/narrative/tool-handlers.js.map +1 -0
  69. package/dist/src/narrative/types.d.ts.map +1 -0
  70. package/dist/src/narrative/types.js.map +1 -0
  71. package/dist/src/narrative/validation.d.ts.map +1 -0
  72. package/dist/src/narrative/validation.js.map +1 -0
  73. package/dist/src/pde/index.d.ts +4 -0
  74. package/dist/src/pde/index.d.ts.map +1 -0
  75. package/dist/src/pde/index.js +19 -0
  76. package/dist/src/pde/index.js.map +1 -0
  77. package/dist/src/pde/mcp-handlers.d.ts.map +1 -0
  78. package/dist/src/pde/mcp-handlers.js.map +1 -0
  79. package/dist/src/pde/mcp-tools.d.ts.map +1 -0
  80. package/dist/src/pde/mcp-tools.js.map +1 -0
  81. package/dist/src/pde/session-manager.d.ts.map +1 -0
  82. package/dist/src/pde/session-manager.js.map +1 -0
  83. package/dist/src/pde/stc-mapper.d.ts.map +1 -0
  84. package/dist/src/pde/stc-mapper.js.map +1 -0
  85. package/dist/src/pipeline/index.d.ts.map +1 -0
  86. package/dist/src/pipeline/index.js.map +1 -0
  87. package/dist/src/pipeline/template-engine.d.ts.map +1 -0
  88. package/dist/src/pipeline/template-engine.js.map +1 -0
  89. package/dist/src/planning/index.d.ts +3 -0
  90. package/dist/src/planning/index.d.ts.map +1 -0
  91. package/dist/src/planning/index.js +13 -0
  92. package/dist/src/planning/index.js.map +1 -0
  93. package/dist/src/planning/mcp-handlers.d.ts.map +1 -0
  94. package/dist/src/planning/mcp-handlers.js.map +1 -0
  95. package/dist/src/planning/mcp-tools.d.ts.map +1 -0
  96. package/dist/src/planning/mcp-tools.js.map +1 -0
  97. package/dist/src/planning/plan-parser.d.ts.map +1 -0
  98. package/dist/src/planning/plan-parser.js.map +1 -0
  99. package/dist/src/redis.d.ts.map +1 -0
  100. package/dist/src/redis.js.map +1 -0
  101. package/dist/src/types.d.ts.map +1 -0
  102. package/dist/src/types.js.map +1 -0
  103. package/package.json +66 -1
  104. package/rispecs/00-coaiajs-platform.spec.md +18 -6
  105. package/rispecs/01-core-config.spec.md +7 -37
  106. package/rispecs/02-redis-module.spec.md +2 -1
  107. package/rispecs/03-langfuse-module.spec.md +7 -5
  108. package/rispecs/04-narrative-engine.spec.md +9 -9
  109. package/rispecs/05-pde-engine.spec.md +23 -23
  110. package/rispecs/06-planning-engine.spec.md +14 -13
  111. package/rispecs/07-pipeline-templates.spec.md +7 -7
  112. package/rispecs/08-cli-interface.spec.md +13 -25
  113. package/rispecs/09-mcp-server.spec.md +41 -44
  114. package/rispecs/10-audio-module.spec.md +3 -3
  115. package/rispecs/KINSHIP.md +4 -4
  116. package/rispecs/README.md +33 -7
  117. package/articles/academic/creative-orientation-vs-problem-solving.md +0 -177
  118. package/articles/academic/jsonl-knowledge-graphs-agent-memory.md +0 -142
  119. package/articles/academic/langfuse-observability-llm-pipelines.md +0 -144
  120. package/articles/academic/medicine-wheel-software-architecture.md +0 -163
  121. package/articles/academic/mmot-autonomous-agents.md +0 -156
  122. package/articles/academic/model-context-protocol-interagent.md +0 -161
  123. package/articles/academic/pde-prompt-decomposition.md +0 -186
  124. package/articles/academic/structural-tension-in-ai-agents.md +0 -134
  125. package/articles/reviews/mcp-protocol-design-review.md +0 -170
  126. package/articles/reviews/observability-ai-systems-review.md +0 -176
  127. package/articles/reviews/prompt-engineering-decomposition-review.md +0 -184
  128. package/articles/surveys/agent-orchestration-survey.md +0 -186
  129. package/articles/surveys/knowledge-graph-storage-survey.md +0 -204
  130. package/articles/surveys/structural-tension-methodology-survey.md +0 -154
  131. package/articles/technical/aws-sdk-v3-polly.md +0 -270
  132. package/articles/technical/commander-cli-framework.md +0 -262
  133. package/articles/technical/dotenv-config-patterns.md +0 -360
  134. package/articles/technical/ioredis-vs-redis.md +0 -142
  135. package/articles/technical/langfuse-js-sdk-vs-rest.md +0 -191
  136. package/articles/technical/mcp-sdk-typescript.md +0 -291
  137. package/articles/technical/octokit-github-api.md +0 -293
  138. package/articles/technical/openai-sdk-modern.md +0 -231
  139. package/articles/technical/yaml-parsing-node.md +0 -266
  140. package/articles/technical/zod-runtime-validation.md +0 -212
  141. package/mcp/config.ts +0 -196
  142. package/mcp/server.ts +0 -402
  143. package/mcp/tools/coaiapy-tools.ts +0 -364
  144. package/mcp/tools/index.ts +0 -4
  145. package/src/audio.ts +0 -76
  146. package/src/cli-helpers.ts +0 -86
  147. package/src/cli.ts +0 -1223
  148. package/src/config.ts +0 -172
  149. package/src/environment.ts +0 -171
  150. package/src/github.ts +0 -143
  151. package/src/langfuse/client.ts +0 -105
  152. package/src/langfuse/comments.ts +0 -52
  153. package/src/langfuse/datasets.ts +0 -178
  154. package/src/langfuse/index.ts +0 -33
  155. package/src/langfuse/media.ts +0 -193
  156. package/src/langfuse/observations.ts +0 -131
  157. package/src/langfuse/prompts.ts +0 -157
  158. package/src/langfuse/scores.ts +0 -456
  159. package/src/langfuse/traces.ts +0 -276
  160. package/src/llm.ts +0 -106
  161. package/src/narrative/graph-manager.ts +0 -1358
  162. package/src/narrative/index.ts +0 -32
  163. package/src/narrative/markdown-export.ts +0 -535
  164. package/src/narrative/tool-definitions.ts +0 -635
  165. package/src/narrative/tool-handlers.ts +0 -528
  166. package/src/narrative/types.ts +0 -9
  167. package/src/narrative/validation.ts +0 -179
  168. package/src/pde/index.ts +0 -8
  169. package/src/pde/mcp-handlers.ts +0 -359
  170. package/src/pde/mcp-tools.ts +0 -201
  171. package/src/pde/session-manager.ts +0 -248
  172. package/src/pde/stc-mapper.ts +0 -298
  173. package/src/pipeline/index.ts +0 -7
  174. package/src/pipeline/template-engine.ts +0 -398
  175. package/src/planning/index.ts +0 -13
  176. package/src/planning/mcp-handlers.ts +0 -369
  177. package/src/planning/mcp-tools.ts +0 -155
  178. package/src/planning/plan-parser.ts +0 -587
  179. package/src/redis.ts +0 -97
  180. package/src/types.ts +0 -280
  181. package/tsconfig.json +0 -26
@@ -1,32 +0,0 @@
1
- // narrative/index.ts — Module barrel export
2
-
3
- export { KnowledgeGraphManager } from './graph-manager.js';
4
- export { handleToolCall } from './tool-handlers.js';
5
- export { validate, ValidationSchemas } from './validation.js';
6
- export {
7
- ALL_TOOL_DEFINITIONS,
8
- STC_TOOLS,
9
- NARRATIVE_TOOLS,
10
- KG_TOOLS,
11
- CORE_TOOLS,
12
- } from './tool-definitions.js';
13
- export type { ToolDefinition } from './tool-definitions.js';
14
- export {
15
- exportChartToMarkdown,
16
- exportAllCharts,
17
- exportChartProgress,
18
- exportChartStats,
19
- writeMarkdownToFile,
20
- getDefaultFilename,
21
- } from './markdown-export.js';
22
- export type { MarkdownOptions } from './markdown-export.js';
23
-
24
- // Re-export narrative-relevant types
25
- export type {
26
- Entity,
27
- EntityMetadata,
28
- Relation,
29
- RelationMetadata,
30
- KnowledgeGraph,
31
- McpToolResult,
32
- } from './types.js';
@@ -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
- }