coaian 0.7.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2025 Shane Holloman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # coaia-narrative
2
+
3
+ **Creative Orientation AI Agentic Memories - Extended with Narrative Beat Support**
4
+
5
+ A complete MCP server extending structural tension charts with multi-universe narrative beat capture for comprehensive incident documentation and creative-oriented memory management.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g coaia-narrative
11
+ ```
12
+
13
+ ## What's Included
14
+
15
+ ### šŸ“” MCP Server (`coaia-narrative`)
16
+ Model Context Protocol server for AI assistants (Claude, Gemini, etc.) to create and manage structural tension charts.
17
+
18
+ ### šŸ–„ļø CLI Visualizer (`cnarrative`) ✨ NEW in v0.6.0
19
+ Human-friendly command-line interface for viewing and analyzing your charts with rich visual formatting.
20
+
21
+ ## Quick Start
22
+
23
+ ```bash
24
+ # Use MCP server with AI assistants
25
+ coaia-narrative --memory-path ./memory.jsonl
26
+
27
+ # Visualize charts as a human
28
+ cnarrative list # See all charts
29
+ cnarrative view chart_1234567890 # Detailed view
30
+ cnarrative stats # Summary statistics
31
+ cnarrative help # Full CLI guide
32
+ ```
33
+
34
+ **šŸ“– See [CLI_GUIDE.md](./CLI_GUIDE.md) for complete CLI documentation.**
35
+
36
+ ## MCP Server Usage
37
+
38
+ ```bash
39
+ # Run with default memory file
40
+ npx coaia-narrative
41
+
42
+ # Run with custom memory path
43
+ npx coaia-narrative --memory-path ./my-charts.jsonl
44
+
45
+ # In Claude Desktop (claude_desktop_config.json)
46
+ {
47
+ "mcpServers": {
48
+ "coaia-narrative": {
49
+ "command": "npx",
50
+ "args": ["-y", "coaia-narrative", "--memory-path", "./narrative-memory.jsonl"],
51
+ "env": {
52
+ "COAIA_TOOLS": "STC_TOOLS,NARRATIVE_TOOLS"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ## Core Features
60
+
61
+ ### Structural Tension Charts (Proven Foundation)
62
+ - **list_active_charts** - View all charts and progress
63
+ - **create_structural_tension_chart** - Create new chart with desired outcome + current reality + action steps
64
+ - **add_action_step** - Add strategic actions (creates telescoped sub-charts)
65
+ - **telescope_action_step** - Break down actions into detailed sub-charts
66
+ - **mark_action_complete** - Complete actions and update current reality
67
+
68
+ ### Narrative Beat Support (Extended Capability)
69
+ Documents complex incidents across three archetypal universes:
70
+ - **Engineer-world**: Technical/analytical perspective
71
+ - **Ceremony-world**: Relational/spiritual protocol awareness
72
+ - **Story-engine-world**: Narrative/creative progression
73
+
74
+ ## Creative Orientation Principles
75
+
76
+ āœ… **Focus on Creation** - "What do you want to create?" not "What needs fixing?"
77
+ āœ… **Structural Tension** - Honest current reality + clear desired outcome creates natural momentum
78
+ āœ… **Advancing Patterns** - Success builds momentum; completed actions flow into reality
79
+ āœ… **Multi-Universe Awareness** - Technical + relational + narrative perspectives simultaneously
80
+
81
+ ## Tool Configuration
82
+
83
+ ```bash
84
+ # Default: Both STCs and narrative tools
85
+ COAIA_TOOLS="STC_TOOLS,NARRATIVE_TOOLS" npx coaia-narrative
86
+
87
+ # Structural tension charts only
88
+ COAIA_TOOLS="STC_TOOLS" npx coaia-narrative
89
+
90
+ # Minimal core tools
91
+ COAIA_TOOLS="CORE_TOOLS" npx coaia-narrative
92
+ ```
93
+
94
+ ## Memory Format
95
+
96
+ Memory stored as JSONL with:
97
+ - **Entity records** - Structural tension charts, current reality, desired outcomes, action steps
98
+ - **Relation records** - Links between entities showing chart hierarchy and advancement
99
+ - **Narrative records** - Extended narrative beat entities with multi-universe perspective
100
+
101
+ All records are backward compatible JSONL format.
102
+
103
+ ## Status
104
+
105
+ **āœ… Production Ready** - MCP server fully functional and tested
106
+
107
+ Builds with `npm run build` and launches successfully with all tools available.
108
+
109
+ ## License
110
+
111
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * COAIA Narrative CLI - Interactive Chart Visualizer
4
+ *
5
+ * Essential commands for human interaction with structural tension charts
6
+ * Provides visual, intuitive interface for chart management
7
+ */
8
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,523 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * COAIA Narrative CLI - Interactive Chart Visualizer
4
+ *
5
+ * Essential commands for human interaction with structural tension charts
6
+ * Provides visual, intuitive interface for chart management
7
+ */
8
+ import { promises as fs } from 'fs';
9
+ import path from 'path';
10
+ import minimist from 'minimist';
11
+ // ==================== UTILITIES ====================
12
+ async function loadGraph(memoryPath) {
13
+ try {
14
+ const data = await fs.readFile(memoryPath, "utf-8");
15
+ const lines = data.split("\n").filter(line => line.trim() !== "");
16
+ return lines.reduce((graph, line) => {
17
+ const item = JSON.parse(line);
18
+ if (item.type === "entity")
19
+ graph.entities.push(item);
20
+ if (item.type === "relation")
21
+ graph.relations.push(item);
22
+ return graph;
23
+ }, { entities: [], relations: [] });
24
+ }
25
+ catch (error) {
26
+ if (error.code === "ENOENT") {
27
+ return { entities: [], relations: [] };
28
+ }
29
+ throw error;
30
+ }
31
+ }
32
+ function formatDate(dateStr) {
33
+ if (!dateStr)
34
+ 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
+ if (days < 0)
39
+ return `āš ļø Overdue by ${Math.abs(days)} days`;
40
+ if (days === 0)
41
+ return "šŸ“… Due today";
42
+ if (days === 1)
43
+ return "šŸ“… Due tomorrow";
44
+ if (days <= 7)
45
+ return `šŸ“… Due in ${days} days`;
46
+ return `šŸ“… ${date.toLocaleDateString()}`;
47
+ }
48
+ function getProgressBar(progress, width = 20) {
49
+ const filled = Math.round(progress * width);
50
+ const empty = width - filled;
51
+ const bar = 'ā–ˆ'.repeat(filled) + 'ā–‘'.repeat(empty);
52
+ const percent = Math.round(progress * 100);
53
+ return `${bar} ${percent}%`;
54
+ }
55
+ function wordWrap(text, maxWidth) {
56
+ const words = text.split(' ');
57
+ const lines = [];
58
+ let currentLine = '';
59
+ for (const word of words) {
60
+ if ((currentLine + word).length <= maxWidth) {
61
+ currentLine += (currentLine ? ' ' : '') + word;
62
+ }
63
+ else {
64
+ if (currentLine)
65
+ lines.push(currentLine);
66
+ currentLine = word;
67
+ }
68
+ }
69
+ if (currentLine)
70
+ lines.push(currentLine);
71
+ return lines;
72
+ }
73
+ // ==================== COMMANDS ====================
74
+ async function listCharts(memoryPath) {
75
+ const graph = await loadGraph(memoryPath);
76
+ const charts = graph.entities.filter(e => e.entityType === 'structural_tension_chart');
77
+ if (charts.length === 0) {
78
+ console.log('\nšŸ“Š No structural tension charts found.\n');
79
+ console.log('šŸ’” Create your first chart with: cnarrative create\n');
80
+ return;
81
+ }
82
+ console.log('\n╔═══════════════════════════════════════════════════════════════════════════════╗');
83
+ console.log('ā•‘ šŸ“Š STRUCTURAL TENSION CHARTS - ACTIVE HIERARCHY ā•‘');
84
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
85
+ const masterCharts = charts.filter(c => c.metadata?.level === 0);
86
+ for (const master of masterCharts) {
87
+ const chartId = master.metadata?.chartId || master.name.replace('_chart', '');
88
+ const outcome = graph.entities.find(e => e.name === `${chartId}_desired_outcome` && e.entityType === 'desired_outcome');
89
+ const currentReality = graph.entities.find(e => e.name === `${chartId}_current_reality` && e.entityType === 'current_reality');
90
+ const actionSteps = graph.entities.filter(e => e.entityType === 'action_step' && e.metadata?.chartId === chartId);
91
+ const completed = actionSteps.filter(a => a.metadata?.completionStatus === true).length;
92
+ const total = actionSteps.length;
93
+ const progress = total > 0 ? completed / total : 0;
94
+ // Master chart header
95
+ console.log(`ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”`);
96
+ console.log(`│ šŸŽÆ MASTER CHART: ${chartId.padEnd(60)} │`);
97
+ console.log(`ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤`);
98
+ // Desired Outcome
99
+ const outcomeText = outcome?.observations[0] || 'Unknown';
100
+ const outcomeLines = wordWrap(outcomeText, 73);
101
+ console.log(`│ 🌟 DESIRED OUTCOME: │`);
102
+ outcomeLines.forEach(line => {
103
+ console.log(`│ ${line.padEnd(73)} │`);
104
+ });
105
+ // Progress
106
+ console.log(`│ │`);
107
+ console.log(`│ ${getProgressBar(progress, 40).padEnd(73)} │`);
108
+ console.log(`│ Completed: ${completed}/${total} action steps`.padEnd(76) + '│');
109
+ // Due date
110
+ console.log(`│ ${formatDate(master.metadata?.dueDate).padEnd(73)} │`);
111
+ // Current Reality
112
+ console.log(`│ │`);
113
+ console.log(`│ šŸ” CURRENT REALITY: │`);
114
+ const realityText = currentReality?.observations.slice(-3).join('; ') || 'Not assessed';
115
+ const realityLines = wordWrap(realityText, 73);
116
+ realityLines.forEach(line => {
117
+ console.log(`│ ${line.padEnd(73)} │`);
118
+ });
119
+ console.log(`ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜`);
120
+ // Action steps (telescoped charts)
121
+ const actionCharts = charts.filter(c => c.metadata?.parentChart === chartId && c.metadata?.level === 1);
122
+ if (actionCharts.length > 0) {
123
+ console.log(`\n šŸ“‹ ACTION STEPS:\n`);
124
+ actionCharts.forEach((actionChart, idx) => {
125
+ const actionChartId = actionChart.metadata?.chartId;
126
+ const actionOutcome = graph.entities.find(e => e.name === `${actionChartId}_desired_outcome` && e.entityType === 'desired_outcome');
127
+ const actionActions = graph.entities.filter(e => e.entityType === 'action_step' && e.metadata?.chartId === actionChartId);
128
+ const actionCompleted = actionActions.filter(a => a.metadata?.completionStatus === true).length;
129
+ const actionTotal = actionActions.length;
130
+ const actionProgress = actionTotal > 0 ? actionCompleted / actionTotal : 0;
131
+ const isComplete = actionChart.metadata?.completionStatus === true;
132
+ const isLast = idx === actionCharts.length - 1;
133
+ const prefix = isLast ? ' └──' : ' ā”œā”€ā”€';
134
+ const status = isComplete ? 'āœ…' : (actionProgress > 0 ? 'šŸ”„' : 'ā³');
135
+ console.log(`${prefix} ${status} ${actionOutcome?.observations[0] || 'Unknown'}`);
136
+ console.log(` ${isLast ? ' ' : '│ '} ID: ${actionChartId} | ${formatDate(actionChart.metadata?.dueDate)}`);
137
+ if (actionTotal > 0) {
138
+ console.log(` ${isLast ? ' ' : '│ '} ${getProgressBar(actionProgress, 30)}`);
139
+ }
140
+ console.log('');
141
+ });
142
+ }
143
+ else {
144
+ console.log(`\n šŸ“‹ No action steps yet.\n`);
145
+ }
146
+ console.log('');
147
+ }
148
+ console.log('═'.repeat(79));
149
+ console.log(`šŸ’” Use 'cnarrative view <chartId>' to see detailed chart information`);
150
+ console.log(`šŸ’” Use 'cnarrative help' to see all available commands\n`);
151
+ }
152
+ async function viewChart(chartId, memoryPath) {
153
+ const graph = await loadGraph(memoryPath);
154
+ const chart = graph.entities.find(e => e.entityType === 'structural_tension_chart' && e.metadata?.chartId === chartId);
155
+ if (!chart) {
156
+ console.log(`\nāŒ Chart '${chartId}' not found.\n`);
157
+ console.log(`šŸ’” Use 'cnarrative list' to see available charts.\n`);
158
+ return;
159
+ }
160
+ const outcome = graph.entities.find(e => e.name === `${chartId}_desired_outcome` && e.entityType === 'desired_outcome');
161
+ const currentReality = graph.entities.find(e => e.name === `${chartId}_current_reality` && e.entityType === 'current_reality');
162
+ const actionSteps = graph.entities.filter(e => e.entityType === 'action_step' && e.metadata?.chartId === chartId);
163
+ const narrativeBeats = graph.entities.filter(e => e.entityType === 'narrative_beat' && e.metadata?.chartId === chartId).sort((a, b) => (a.metadata?.act || 0) - (b.metadata?.act || 0));
164
+ console.log('\n╔═══════════════════════════════════════════════════════════════════════════════╗');
165
+ console.log(`ā•‘ STRUCTURAL TENSION CHART VIEW ā•‘`);
166
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
167
+ console.log(`šŸ“Š Chart ID: ${chartId}`);
168
+ console.log(`šŸ“… Created: ${new Date(chart.metadata?.createdAt || '').toLocaleString()}`);
169
+ console.log(`šŸ“… ${formatDate(chart.metadata?.dueDate)}`);
170
+ if (chart.metadata?.parentChart) {
171
+ console.log(`šŸ”— Parent Chart: ${chart.metadata.parentChart} (Level ${chart.metadata.level})`);
172
+ }
173
+ else {
174
+ console.log(`šŸŽÆ Master Chart (Level ${chart.metadata?.level || 0})`);
175
+ }
176
+ console.log('\n' + '─'.repeat(79));
177
+ console.log('\n🌟 DESIRED OUTCOME (What you want to CREATE):');
178
+ console.log('─'.repeat(79));
179
+ const outcomeText = outcome?.observations[0] || 'Unknown';
180
+ wordWrap(outcomeText, 75).forEach(line => console.log(` ${line}`));
181
+ console.log('\n' + '─'.repeat(79));
182
+ console.log('\nšŸ” CURRENT REALITY (Where you are NOW):');
183
+ console.log('─'.repeat(79));
184
+ if (currentReality && currentReality.observations.length > 0) {
185
+ currentReality.observations.forEach((obs, idx) => {
186
+ console.log(` ${idx + 1}. ${obs}`);
187
+ });
188
+ }
189
+ else {
190
+ console.log(' (Not assessed)');
191
+ }
192
+ console.log('\n' + '─'.repeat(79));
193
+ console.log('\n⚔ STRUCTURAL TENSION:');
194
+ console.log('─'.repeat(79));
195
+ const completed = actionSteps.filter(a => a.metadata?.completionStatus === true).length;
196
+ const total = actionSteps.length;
197
+ const progress = total > 0 ? completed / total : 0;
198
+ console.log(` The gap between current reality and desired outcome creates natural`);
199
+ console.log(` momentum toward resolution. Progress advances the system toward equilibrium.`);
200
+ console.log(`\n ${getProgressBar(progress, 50)}`);
201
+ console.log(` ${completed} of ${total} action steps completed\n`);
202
+ if (actionSteps.length > 0) {
203
+ console.log('─'.repeat(79));
204
+ console.log('\nšŸ“‹ ACTION STEPS (Strategic intermediary results):');
205
+ console.log('─'.repeat(79) + '\n');
206
+ actionSteps.forEach((step, idx) => {
207
+ const isComplete = step.metadata?.completionStatus === true;
208
+ const status = isComplete ? 'āœ…' : 'ā³';
209
+ const stepDue = formatDate(step.metadata?.dueDate);
210
+ console.log(` ${idx + 1}. ${status} ${step.observations[0]}`);
211
+ console.log(` Entity: ${step.name}`);
212
+ console.log(` ${stepDue}`);
213
+ if (step.observations.length > 1) {
214
+ console.log(` Progress notes:`);
215
+ step.observations.slice(1).forEach(note => {
216
+ console.log(` • ${note}`);
217
+ });
218
+ }
219
+ console.log('');
220
+ });
221
+ }
222
+ // Display narrative beats
223
+ if (narrativeBeats.length > 0) {
224
+ console.log('─'.repeat(79));
225
+ console.log('\nšŸ“– NARRATIVE BEATS (Story progression):');
226
+ console.log('─'.repeat(79) + '\n');
227
+ narrativeBeats.forEach((beat, idx) => {
228
+ const act = beat.metadata?.act || '?';
229
+ const type = beat.metadata?.type_dramatic || 'Unknown';
230
+ const universes = beat.metadata?.universes || [];
231
+ const timestamp = beat.metadata?.timestamp
232
+ ? new Date(beat.metadata.timestamp).toLocaleString()
233
+ : 'Unknown';
234
+ console.log(` ${idx + 1}. Act ${act}: ${type}`);
235
+ console.log(` šŸŒ Universes: ${universes.join(', ')}`);
236
+ console.log(` šŸ•’ Timestamp: ${timestamp}`);
237
+ if (beat.metadata?.narrative?.description) {
238
+ console.log(`\n šŸ“ Description:`);
239
+ wordWrap(beat.metadata.narrative.description, 72).forEach(line => {
240
+ console.log(` ${line}`);
241
+ });
242
+ }
243
+ if (beat.metadata?.narrative?.prose) {
244
+ console.log(`\n ✨ Prose:`);
245
+ wordWrap(beat.metadata.narrative.prose, 72).forEach(line => {
246
+ console.log(` ${line}`);
247
+ });
248
+ }
249
+ if (beat.metadata?.narrative?.lessons && beat.metadata.narrative.lessons.length > 0) {
250
+ console.log(`\n šŸ’” Lessons:`);
251
+ beat.metadata.narrative.lessons.forEach(lesson => {
252
+ wordWrap(lesson, 68).forEach((line, i) => {
253
+ console.log(` ${i === 0 ? '•' : ' '} ${line}`);
254
+ });
255
+ });
256
+ }
257
+ // Four Directions if present
258
+ const dirs = beat.metadata?.fourDirections;
259
+ if (dirs && (dirs.north_vision || dirs.east_intention || dirs.south_emotion || dirs.west_introspection)) {
260
+ console.log(`\n 🧭 Four Directions:`);
261
+ if (dirs.north_vision)
262
+ console.log(` North (Vision): ${dirs.north_vision}`);
263
+ if (dirs.east_intention)
264
+ console.log(` East (Intention): ${dirs.east_intention}`);
265
+ if (dirs.south_emotion)
266
+ console.log(` South (Emotion): ${dirs.south_emotion}`);
267
+ if (dirs.west_introspection)
268
+ console.log(` West (Introspection): ${dirs.west_introspection}`);
269
+ }
270
+ // Relational alignment if assessed
271
+ const align = beat.metadata?.relationalAlignment;
272
+ if (align?.assessed && align.score !== null) {
273
+ console.log(`\n šŸ¤ Relational Alignment: ${align.score}/10`);
274
+ if (align.principles && align.principles.length > 0) {
275
+ console.log(` Principles: ${align.principles.join(', ')}`);
276
+ }
277
+ }
278
+ console.log('');
279
+ });
280
+ }
281
+ // Check for telescoped sub-charts
282
+ const subCharts = graph.entities.filter(e => e.entityType === 'structural_tension_chart' &&
283
+ e.metadata?.parentChart === chartId);
284
+ if (subCharts.length > 0) {
285
+ console.log('─'.repeat(79));
286
+ console.log('\nšŸ”­ TELESCOPED SUB-CHARTS:');
287
+ console.log('─'.repeat(79) + '\n');
288
+ subCharts.forEach(sub => {
289
+ const subId = sub.metadata?.chartId;
290
+ const subOutcome = graph.entities.find(e => e.name === `${subId}_desired_outcome`);
291
+ console.log(` • ${subOutcome?.observations[0] || 'Unknown'}`);
292
+ console.log(` Chart ID: ${subId}`);
293
+ console.log('');
294
+ });
295
+ }
296
+ console.log('═'.repeat(79));
297
+ console.log(`šŸ’” Use 'cnarrative update ${chartId}' to modify this chart`);
298
+ console.log(`šŸ’” Use 'cnarrative list' to see all charts\n`);
299
+ }
300
+ function showHelp() {
301
+ console.log(`
302
+ ╔═══════════════════════════════════════════════════════════════════════════════╗
303
+ ā•‘ COAIA NARRATIVE CLI - Structural Tension Chart Visualizer ā•‘
304
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
305
+
306
+ USAGE:
307
+ cnarrative <command> [options]
308
+
309
+ COMMANDS:
310
+
311
+ šŸ“Š VIEWING COMMANDS
312
+ ───────────────────────────────────────────────────────────────────────────────
313
+ list List all structural tension charts in hierarchy
314
+ view <chartId> View detailed information for a specific chart
315
+
316
+ šŸ“ˆ QUICK STATS
317
+ ───────────────────────────────────────────────────────────────────────────────
318
+ stats Show summary statistics across all charts
319
+ progress <chartId> Show progress details for a specific chart
320
+
321
+ āš™ļø UTILITY
322
+ ───────────────────────────────────────────────────────────────────────────────
323
+ help Show this help message
324
+ version Show version information
325
+
326
+ OPTIONS:
327
+
328
+ --memory-path <path> Path to memory JSONL file (default: ./memory.jsonl)
329
+ -M <path> Short alias for --memory-path
330
+ --no-color Disable colored output
331
+ --json Output in JSON format
332
+
333
+ EXAMPLES:
334
+
335
+ # List all charts with visual hierarchy
336
+ cnarrative list
337
+
338
+ # View detailed information for a specific chart
339
+ cnarrative view chart_1234567890
340
+
341
+ # View chart using custom memory path
342
+ cnarrative view chart_123 --memory-path /path/to/memory.jsonl
343
+
344
+ # Same using short alias
345
+ cnarrative view chart_123 -M /path/to/memory.jsonl
346
+
347
+ # Get statistics in JSON format
348
+ cnarrative stats --json
349
+
350
+ PHILOSOPHY:
351
+
352
+ Structural Tension Charts organize creative processes around desired outcomes
353
+ rather than problem-solving. The unresolved tension between current reality
354
+ and desired outcome naturally seeks resolution through advancing patterns.
355
+
356
+ 🌟 Desired Outcome = What you want to CREATE
357
+ šŸ” Current Reality = Honest assessment of where you are NOW
358
+ ⚔ Structural Tension = The gap that creates natural momentum
359
+ šŸ“‹ Action Steps = Strategic intermediary results
360
+
361
+ MORE INFO:
362
+
363
+ MCP Server: Use 'coaia-narrative' (MCP protocol) for AI assistant integration
364
+ Documentation: See README.md for complete methodology
365
+ Author: Based on Robert Fritz's Structural Tension principles
366
+
367
+ `);
368
+ }
369
+ async function showStats(memoryPath, jsonOutput = false) {
370
+ const graph = await loadGraph(memoryPath);
371
+ const charts = graph.entities.filter(e => e.entityType === 'structural_tension_chart');
372
+ const masterCharts = charts.filter(c => c.metadata?.level === 0);
373
+ const actionCharts = charts.filter(c => c.metadata?.level === 1);
374
+ const narrativeBeats = graph.entities.filter(e => e.entityType === 'narrative_beat');
375
+ let totalActions = 0;
376
+ let completedActions = 0;
377
+ let overdueCharts = 0;
378
+ const now = new Date();
379
+ charts.forEach(chart => {
380
+ const chartId = chart.metadata?.chartId;
381
+ if (!chartId)
382
+ return;
383
+ const actions = graph.entities.filter(e => e.entityType === 'action_step' && e.metadata?.chartId === chartId);
384
+ totalActions += actions.length;
385
+ completedActions += actions.filter(a => a.metadata?.completionStatus === true).length;
386
+ if (chart.metadata?.dueDate) {
387
+ const dueDate = new Date(chart.metadata.dueDate);
388
+ if (dueDate < now && chart.metadata?.completionStatus !== true) {
389
+ overdueCharts++;
390
+ }
391
+ }
392
+ });
393
+ const stats = {
394
+ totalCharts: charts.length,
395
+ masterCharts: masterCharts.length,
396
+ actionCharts: actionCharts.length,
397
+ narrativeBeats: narrativeBeats.length,
398
+ totalActions,
399
+ completedActions,
400
+ overdueCharts,
401
+ overallProgress: totalActions > 0 ? completedActions / totalActions : 0
402
+ };
403
+ if (jsonOutput) {
404
+ console.log(JSON.stringify(stats, null, 2));
405
+ return;
406
+ }
407
+ console.log('\n╔═══════════════════════════════════════════════════════════════════════════════╗');
408
+ console.log('ā•‘ šŸ“Š STRUCTURAL TENSION CHARTS STATISTICS ā•‘');
409
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
410
+ console.log(` šŸ“‹ Total Charts: ${stats.totalCharts}`);
411
+ console.log(` • Master Charts: ${stats.masterCharts}`);
412
+ console.log(` • Action Step Charts: ${stats.actionCharts}`);
413
+ console.log('');
414
+ console.log(` āœ… Action Steps: ${stats.completedActions} / ${stats.totalActions} completed`);
415
+ console.log(` ${getProgressBar(stats.overallProgress, 50)}`);
416
+ console.log('');
417
+ if (stats.narrativeBeats > 0) {
418
+ console.log(` šŸ“– Narrative Beats: ${stats.narrativeBeats}`);
419
+ console.log('');
420
+ }
421
+ if (stats.overdueCharts > 0) {
422
+ console.log(` āš ļø Overdue Charts: ${stats.overdueCharts}`);
423
+ }
424
+ else {
425
+ console.log(` ✨ All charts on track!`);
426
+ }
427
+ console.log('\n' + '═'.repeat(79) + '\n');
428
+ }
429
+ async function showProgress(chartId, memoryPath) {
430
+ const graph = await loadGraph(memoryPath);
431
+ const chart = graph.entities.find(e => e.entityType === 'structural_tension_chart' && e.metadata?.chartId === chartId);
432
+ if (!chart) {
433
+ console.log(`\nāŒ Chart '${chartId}' not found.\n`);
434
+ return;
435
+ }
436
+ const outcome = graph.entities.find(e => e.name === `${chartId}_desired_outcome`);
437
+ const actions = graph.entities.filter(e => e.entityType === 'action_step' && e.metadata?.chartId === chartId);
438
+ const completed = actions.filter(a => a.metadata?.completionStatus === true);
439
+ const incomplete = actions.filter(a => a.metadata?.completionStatus !== true);
440
+ const progress = actions.length > 0 ? completed.length / actions.length : 0;
441
+ console.log('\n╔═══════════════════════════════════════════════════════════════════════════════╗');
442
+ console.log('ā•‘ CHART PROGRESS REPORT ā•‘');
443
+ console.log('ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n');
444
+ console.log(`šŸ“Š Chart: ${chartId}`);
445
+ console.log(`🌟 Goal: ${outcome?.observations[0] || 'Unknown'}\n`);
446
+ console.log(`${getProgressBar(progress, 60)}\n`);
447
+ console.log(`āœ… Completed: ${completed.length}`);
448
+ if (completed.length > 0) {
449
+ completed.forEach(action => {
450
+ console.log(` • ${action.observations[0]}`);
451
+ });
452
+ }
453
+ console.log('');
454
+ console.log(`ā³ Remaining: ${incomplete.length}`);
455
+ if (incomplete.length > 0) {
456
+ incomplete.forEach(action => {
457
+ const due = formatDate(action.metadata?.dueDate);
458
+ console.log(` • ${action.observations[0]} (${due})`);
459
+ });
460
+ }
461
+ console.log('\n' + '═'.repeat(79) + '\n');
462
+ }
463
+ // ==================== MAIN ====================
464
+ async function main() {
465
+ const args = minimist(process.argv.slice(2));
466
+ const command = args._[0];
467
+ const memoryPath = args['memory-path'] || args['M'] || path.join(process.cwd(), 'memory.jsonl');
468
+ const jsonOutput = args.json === true;
469
+ try {
470
+ switch (command) {
471
+ case 'list':
472
+ case 'ls':
473
+ await listCharts(memoryPath);
474
+ break;
475
+ case 'view':
476
+ case 'show':
477
+ if (!args._[1]) {
478
+ console.log('\nāŒ Error: Chart ID required\n');
479
+ console.log('Usage: cnarrative view <chartId>\n');
480
+ process.exit(1);
481
+ }
482
+ await viewChart(args._[1], memoryPath);
483
+ break;
484
+ case 'stats':
485
+ case 'statistics':
486
+ await showStats(memoryPath, jsonOutput);
487
+ break;
488
+ case 'progress':
489
+ if (!args._[1]) {
490
+ console.log('\nāŒ Error: Chart ID required\n');
491
+ console.log('Usage: cnarrative progress <chartId>\n');
492
+ process.exit(1);
493
+ }
494
+ await showProgress(args._[1], memoryPath);
495
+ break;
496
+ case 'help':
497
+ case '--help':
498
+ case '-h':
499
+ showHelp();
500
+ break;
501
+ case 'version':
502
+ case '--version':
503
+ case '-v':
504
+ console.log('\nCOAIA Narrative CLI v0.5.0');
505
+ console.log('Structural Tension Chart Visualizer\n');
506
+ break;
507
+ default:
508
+ if (!command) {
509
+ showHelp();
510
+ }
511
+ else {
512
+ console.log(`\nāŒ Unknown command: ${command}\n`);
513
+ console.log(`šŸ’” Use 'cnarrative help' to see available commands\n`);
514
+ process.exit(1);
515
+ }
516
+ }
517
+ }
518
+ catch (error) {
519
+ console.error('\nāŒ Error:', error.message, '\n');
520
+ process.exit(1);
521
+ }
522
+ }
523
+ main();