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 +21 -0
- package/README.md +111 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +523 -0
- package/dist/generated-llm-guidance.d.ts +2 -0
- package/dist/generated-llm-guidance.js +498 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1879 -0
- package/dist/validation.d.ts +28 -0
- package/dist/validation.js +145 -0
- package/package.json +62 -0
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
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();
|