pi-harness-runtime 1.1.95 → 1.1.97

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 (226) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/harness/loop-runtime.ts +3 -0
  3. package/index.ts +130 -29
  4. package/package.json +2 -1
  5. package/packages/a2a-adapter/package.json +1 -1
  6. package/packages/architecture-generator/package.json +1 -1
  7. package/packages/auth/package.json +1 -1
  8. package/packages/autonomous-refactor/package.json +1 -1
  9. package/packages/autonomous-runtime/package.json +1 -1
  10. package/packages/cache-strategy/package.json +1 -1
  11. package/packages/capability-registry/package.json +1 -1
  12. package/packages/checkpoint/package.json +1 -1
  13. package/packages/cli-plugin-sdk/package.json +1 -1
  14. package/packages/clipboard/package.json +1 -1
  15. package/packages/clipboard-plugin/package.json +1 -1
  16. package/packages/code-generation/package.json +1 -1
  17. package/packages/code-review/package.json +1 -1
  18. package/packages/codex-adapter/package.json +1 -1
  19. package/packages/config-capture/package.json +1 -1
  20. package/packages/context-compiler/package.json +1 -1
  21. package/packages/context-discovery/package.json +1 -1
  22. package/packages/context-manager/package.json +1 -1
  23. package/packages/cookie-sanitizer/package.json +1 -1
  24. package/packages/cost-optimizer/package.json +1 -1
  25. package/packages/dependency-analyzer/package.json +1 -1
  26. package/packages/django-plugin/package.json +1 -1
  27. package/packages/doc-generator/package.json +1 -1
  28. package/packages/evaluation-engine/package.json +1 -1
  29. package/packages/evaluation-runner/package.json +1 -1
  30. package/packages/event-bus/package.json +1 -1
  31. package/packages/event-store/package.json +1 -1
  32. package/packages/experience-replay/package.json +1 -1
  33. package/packages/feedback-collector/package.json +1 -1
  34. package/packages/file-copy-helper/package.json +1 -1
  35. package/packages/framework-detector/package.json +1 -1
  36. package/packages/framework-plugin-sdk/package.json +1 -1
  37. package/packages/frappe-plugin/package.json +1 -1
  38. package/packages/generic-web-plugin/package.json +1 -1
  39. package/packages/health-monitor/package.json +1 -1
  40. package/packages/intent-analyzer/package.json +1 -1
  41. package/packages/jev-judge/package.json +1 -1
  42. package/packages/knowledge-graph/package.json +1 -1
  43. package/packages/knowledge-retrieval/package.json +1 -1
  44. package/packages/laravel-plugin/package.json +1 -1
  45. package/packages/learning-engine/package.json +1 -1
  46. package/packages/mcp-adapter/package.json +1 -1
  47. package/packages/memory-engine/package.json +1 -1
  48. package/packages/milestone-manager/package.json +1 -1
  49. package/packages/model-registry/package.json +1 -1
  50. package/packages/nextjs-plugin/package.json +1 -1
  51. package/packages/notification/package.json +1 -1
  52. package/packages/observability/package.json +1 -1
  53. package/packages/okf-indexer/package.json +1 -1
  54. package/packages/performance-optimizer/package.json +1 -1
  55. package/packages/privilege-broker/package.json +1 -1
  56. package/packages/project-analyzer/package.json +1 -1
  57. package/packages/project-bootstrap/package.json +1 -1
  58. package/packages/projection-engine/package.json +1 -1
  59. package/packages/prompt-compiler/package.json +1 -1
  60. package/packages/prompt-versioning/package.json +1 -1
  61. package/packages/provider-adapter-sdk/package.json +1 -1
  62. package/packages/provider-router/package.json +1 -1
  63. package/packages/provider-selector/package.json +1 -1
  64. package/packages/providers/package.json +1 -1
  65. package/packages/qdrant-skills/dist/client.d.ts +51 -0
  66. package/packages/qdrant-skills/dist/client.d.ts.map +1 -0
  67. package/packages/qdrant-skills/dist/client.js +105 -0
  68. package/packages/qdrant-skills/dist/client.js.map +1 -0
  69. package/packages/qdrant-skills/dist/embedder.d.ts +39 -0
  70. package/packages/qdrant-skills/dist/embedder.d.ts.map +1 -0
  71. package/packages/qdrant-skills/dist/embedder.js +101 -0
  72. package/packages/qdrant-skills/dist/embedder.js.map +1 -0
  73. package/packages/qdrant-skills/dist/index.d.ts +25 -0
  74. package/packages/qdrant-skills/dist/index.d.ts.map +1 -0
  75. package/packages/qdrant-skills/dist/index.js +25 -0
  76. package/packages/qdrant-skills/dist/index.js.map +1 -0
  77. package/packages/qdrant-skills/package.json +27 -0
  78. package/packages/qdrant-skills/src/client.ts +178 -0
  79. package/packages/qdrant-skills/src/embedder.ts +137 -0
  80. package/packages/qdrant-skills/src/index.ts +42 -0
  81. package/packages/quota-manager/package.json +1 -1
  82. package/packages/rate-limiter/package.json +1 -1
  83. package/packages/react-vite-plugin/package.json +1 -1
  84. package/packages/release-manager/package.json +1 -1
  85. package/packages/requirement-compiler/package.json +1 -1
  86. package/packages/runtime/package.json +1 -1
  87. package/packages/scheduler/package.json +1 -1
  88. package/packages/scheduler-adapter/package.json +1 -1
  89. package/packages/session/package.json +1 -1
  90. package/packages/session-api/package.json +1 -1
  91. package/packages/session-export/package.json +1 -1
  92. package/packages/shared-context/package.json +1 -1
  93. package/packages/skill-mcp-client/package.json +1 -1
  94. package/packages/skill-registry/package.json +1 -1
  95. package/packages/skills/dist/index.d.ts +40 -0
  96. package/packages/skills/dist/index.d.ts.map +1 -0
  97. package/packages/skills/dist/index.js +84 -0
  98. package/packages/skills/dist/index.js.map +1 -0
  99. package/packages/skills/dist/linter.d.ts +38 -0
  100. package/packages/skills/dist/linter.d.ts.map +1 -0
  101. package/packages/skills/dist/linter.js +323 -0
  102. package/packages/skills/dist/linter.js.map +1 -0
  103. package/packages/skills/dist/loader.d.ts +74 -0
  104. package/packages/skills/dist/loader.d.ts.map +1 -0
  105. package/packages/skills/dist/loader.js +280 -0
  106. package/packages/skills/dist/loader.js.map +1 -0
  107. package/packages/skills/dist/parser.d.ts +32 -0
  108. package/packages/skills/dist/parser.d.ts.map +1 -0
  109. package/packages/skills/dist/parser.js +459 -0
  110. package/packages/skills/dist/parser.js.map +1 -0
  111. package/packages/skills/dist/scanner.d.ts +33 -0
  112. package/packages/skills/dist/scanner.d.ts.map +1 -0
  113. package/packages/skills/dist/scanner.js +257 -0
  114. package/packages/skills/dist/scanner.js.map +1 -0
  115. package/packages/skills/dist/skill-commands.d.ts +33 -0
  116. package/packages/skills/dist/skill-commands.d.ts.map +1 -0
  117. package/packages/skills/dist/skill-commands.js +239 -0
  118. package/packages/skills/dist/skill-commands.js.map +1 -0
  119. package/packages/skills/dist/skill-tool.d.ts +120 -0
  120. package/packages/skills/dist/skill-tool.d.ts.map +1 -0
  121. package/packages/skills/dist/skill-tool.js +239 -0
  122. package/packages/skills/dist/skill-tool.js.map +1 -0
  123. package/packages/skills/dist/skill-versioning.d.ts +123 -0
  124. package/packages/skills/dist/skill-versioning.d.ts.map +1 -0
  125. package/packages/skills/dist/skill-versioning.js +240 -0
  126. package/packages/skills/dist/skill-versioning.js.map +1 -0
  127. package/packages/skills/dist/types.d.ts +226 -0
  128. package/packages/skills/dist/types.d.ts.map +1 -0
  129. package/packages/skills/dist/types.js +21 -0
  130. package/packages/skills/dist/types.js.map +1 -0
  131. package/packages/skills/package.json +46 -0
  132. package/packages/skills/src/index.ts +95 -0
  133. package/packages/skills/src/linter.ts +371 -0
  134. package/packages/skills/src/loader.ts +335 -0
  135. package/packages/skills/src/parser.ts +548 -0
  136. package/packages/skills/src/scanner.ts +322 -0
  137. package/packages/skills/src/skill-commands.ts +318 -0
  138. package/packages/skills/src/skill-tool.ts +324 -0
  139. package/packages/skills/src/skill-versioning.ts +345 -0
  140. package/packages/skills/src/types.ts +259 -0
  141. package/packages/skills/test/init-skills.test.ts +118 -0
  142. package/packages/sprint-planner/package.json +1 -1
  143. package/packages/subscription-engine/package.json +1 -1
  144. package/packages/task-compiler/package.json +1 -1
  145. package/packages/tencentdb-memory/package.json +1 -1
  146. package/packages/tencentdb-sync/package.json +1 -1
  147. package/packages/test-data-generator/package.json +1 -1
  148. package/packages/test-generator/package.json +1 -1
  149. package/packages/todo-bd-sync/package.json +1 -1
  150. package/packages/token-estimation/package.json +1 -1
  151. package/packages/token-optimizer/package.json +1 -1
  152. package/packages/trajectory/dist/src/curator.d.ts +189 -0
  153. package/packages/trajectory/dist/src/curator.d.ts.map +1 -0
  154. package/packages/trajectory/dist/src/curator.js +340 -0
  155. package/packages/trajectory/dist/src/curator.js.map +1 -0
  156. package/packages/trajectory/dist/src/journey-renderer.d.ts +53 -0
  157. package/packages/trajectory/dist/src/journey-renderer.d.ts.map +1 -0
  158. package/packages/trajectory/dist/src/journey-renderer.js +324 -0
  159. package/packages/trajectory/dist/src/journey-renderer.js.map +1 -0
  160. package/packages/trajectory/dist/src/learning-graph.d.ts +159 -0
  161. package/packages/trajectory/dist/src/learning-graph.d.ts.map +1 -0
  162. package/packages/trajectory/dist/src/learning-graph.js +258 -0
  163. package/packages/trajectory/dist/src/learning-graph.js.map +1 -0
  164. package/packages/trajectory/dist/src/memory-store.d.ts +146 -0
  165. package/packages/trajectory/dist/src/memory-store.d.ts.map +1 -0
  166. package/packages/trajectory/dist/src/memory-store.js +472 -0
  167. package/packages/trajectory/dist/src/memory-store.js.map +1 -0
  168. package/packages/trajectory/dist/src/review-fork.d.ts +164 -0
  169. package/packages/trajectory/dist/src/review-fork.d.ts.map +1 -0
  170. package/packages/trajectory/dist/src/review-fork.js +332 -0
  171. package/packages/trajectory/dist/src/review-fork.js.map +1 -0
  172. package/packages/trajectory/dist/src/write-approval.d.ts +136 -0
  173. package/packages/trajectory/dist/src/write-approval.d.ts.map +1 -0
  174. package/packages/trajectory/dist/src/write-approval.js +281 -0
  175. package/packages/trajectory/dist/src/write-approval.js.map +1 -0
  176. package/packages/trajectory/package.json +1 -1
  177. package/packages/trajectory/src/curator.ts +485 -0
  178. package/packages/trajectory/src/journey-renderer.ts +399 -0
  179. package/packages/trajectory/src/learning-graph.ts +363 -0
  180. package/packages/trajectory/src/memory-store.ts +578 -0
  181. package/packages/trajectory/src/review-fork.ts +450 -0
  182. package/packages/trajectory/src/write-approval.ts +372 -0
  183. package/packages/tui/package.json +1 -1
  184. package/packages/types/package.json +1 -1
  185. package/packages/workflow-events/package.json +1 -1
  186. package/packages/workspace-scanner/package.json +1 -1
  187. package/packages/worktree/package.json +1 -1
  188. package/packages/write-review/dist/blackboard.d.ts +98 -0
  189. package/packages/write-review/dist/blackboard.d.ts.map +1 -0
  190. package/packages/write-review/dist/blackboard.js +289 -0
  191. package/packages/write-review/dist/blackboard.js.map +1 -0
  192. package/packages/write-review/dist/event-bus.d.ts +106 -0
  193. package/packages/write-review/dist/event-bus.d.ts.map +1 -0
  194. package/packages/write-review/dist/event-bus.js +294 -0
  195. package/packages/write-review/dist/event-bus.js.map +1 -0
  196. package/packages/write-review/dist/gate.d.ts +37 -0
  197. package/packages/write-review/dist/gate.d.ts.map +1 -0
  198. package/packages/write-review/dist/gate.js +138 -0
  199. package/packages/write-review/dist/gate.js.map +1 -0
  200. package/packages/write-review/dist/index.d.ts +22 -0
  201. package/packages/write-review/dist/index.d.ts.map +1 -0
  202. package/packages/write-review/dist/index.js +60 -0
  203. package/packages/write-review/dist/index.js.map +1 -0
  204. package/packages/write-review/dist/injection.d.ts +40 -0
  205. package/packages/write-review/dist/injection.d.ts.map +1 -0
  206. package/packages/write-review/dist/injection.js +179 -0
  207. package/packages/write-review/dist/injection.js.map +1 -0
  208. package/packages/write-review/dist/review.d.ts +54 -0
  209. package/packages/write-review/dist/review.d.ts.map +1 -0
  210. package/packages/write-review/dist/review.js +154 -0
  211. package/packages/write-review/dist/review.js.map +1 -0
  212. package/packages/write-review/dist/trigger.d.ts +39 -0
  213. package/packages/write-review/dist/trigger.d.ts.map +1 -0
  214. package/packages/write-review/dist/trigger.js +107 -0
  215. package/packages/write-review/dist/trigger.js.map +1 -0
  216. package/packages/write-review/dist/types.d.ts +78 -0
  217. package/packages/write-review/dist/types.d.ts.map +1 -0
  218. package/packages/write-review/dist/types.js +26 -0
  219. package/packages/write-review/dist/types.js.map +1 -0
  220. package/packages/write-review/package.json +1 -1
  221. package/packages/write-review/src/event-bus.ts +351 -0
  222. package/packages/write-review/src/index.ts +1 -0
  223. package/packages/write-review/src/injection.ts +25 -3
  224. package/proactive-compact.ts +51 -7
  225. package/scripts/sync-skills.ts +275 -0
  226. package/scripts/sync-to-qdrant.ts +398 -0
@@ -0,0 +1,399 @@
1
+ /**
2
+ * Journey Renderer - ASCII timeline visualization of learning
3
+ *
4
+ * Renders the learning journey as an ASCII timeline.
5
+ * Based on Hermes Agent's Learning Journey visualization.
6
+ */
7
+
8
+ import type { LearningNode, NodeType } from "./learning-graph.js";
9
+ import { getGlobalLearningGraph } from "./learning-graph.js";
10
+
11
+ /**
12
+ * Render options
13
+ */
14
+ export interface JourneyRenderOptions {
15
+ /** Maximum width */
16
+ width: number;
17
+ /** Maximum height */
18
+ height: number;
19
+ /** Show colors */
20
+ color: boolean;
21
+ /** Show all nodes or recent only */
22
+ showAll: boolean;
23
+ /** Limit to specific type */
24
+ type?: NodeType;
25
+ /** Limit to recent N nodes */
26
+ limit?: number;
27
+ }
28
+
29
+ /**
30
+ * Default render options
31
+ */
32
+ export const DEFAULT_RENDER_OPTIONS: JourneyRenderOptions = {
33
+ width: 80,
34
+ height: 40,
35
+ color: true,
36
+ showAll: false,
37
+ };
38
+
39
+ /**
40
+ * Color codes
41
+ */
42
+ const COLORS = {
43
+ reset: "\x1b[0m",
44
+ bold: "\x1b[1m",
45
+ dim: "\x1b[2m",
46
+ skill: "\x1b[36m", // cyan
47
+ memory: "\x1b[33m", // yellow
48
+ pattern: "\x1b[32m", // green
49
+ antiPattern: "\x1b[31m", // red
50
+ date: "\x1b[90m", // gray
51
+ accent: "\x1b[94m", // blue
52
+ };
53
+
54
+ /**
55
+ * Get color for node type
56
+ */
57
+ function getColor(type: NodeType, color: boolean): string {
58
+ if (!color) return "";
59
+ switch (type) {
60
+ case "skill":
61
+ return COLORS.skill;
62
+ case "memory":
63
+ return COLORS.memory;
64
+ case "pattern":
65
+ return COLORS.pattern;
66
+ case "anti-pattern":
67
+ return COLORS.antiPattern;
68
+ default:
69
+ return "";
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Get icon for node type
75
+ */
76
+ function getIcon(type: NodeType): string {
77
+ switch (type) {
78
+ case "skill":
79
+ return "[S]";
80
+ case "memory":
81
+ return "[M]";
82
+ case "pattern":
83
+ return "[P]";
84
+ case "anti-pattern":
85
+ return "[!]";
86
+ default:
87
+ return "[?]";
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Format date for display
93
+ */
94
+ function formatDate(isoDate: string): string {
95
+ const date = new Date(isoDate);
96
+ return date.toLocaleDateString("en-US", {
97
+ month: "short",
98
+ day: "numeric",
99
+ year: "numeric",
100
+ });
101
+ }
102
+
103
+ /**
104
+ * Truncate text with ellipsis
105
+ */
106
+ function truncate(text: string, maxLen: number): string {
107
+ if (text.length <= maxLen) return text;
108
+ return text.slice(0, maxLen - 3) + "...";
109
+ }
110
+
111
+ /**
112
+ * Render a single node
113
+ */
114
+ function renderNode(node: LearningNode, options: JourneyRenderOptions): string[] {
115
+ const lines: string[] = [];
116
+ const color = getColor(node.type, options.color);
117
+ const icon = getIcon(node.type);
118
+ const reset = options.color ? COLORS.reset : "";
119
+
120
+ // Calculate available width for content
121
+ const headerWidth = options.width - 8;
122
+ const dateWidth = 14;
123
+ const contentWidth = headerWidth - dateWidth - 4;
124
+
125
+ // Header line
126
+ const header = `${color}${icon}${reset} ${color}${truncate(node.name, contentWidth - icon.length - 1)}${reset}`;
127
+ const dateStr = `${COLORS.date}${formatDate(node.created_at)}${reset}`;
128
+ lines.push(`${header.padEnd(headerWidth)}${dateStr}`);
129
+
130
+ // Description (if present and space allows)
131
+ if (node.description && options.height > 2) {
132
+ const descLines = wrapText(node.description, contentWidth - 2);
133
+ for (const line of descLines.slice(0, 2)) {
134
+ lines.push(
135
+ `${color} ${truncate(line, contentWidth - 2)}${reset}`
136
+ );
137
+ }
138
+ }
139
+
140
+ // Metadata line
141
+ const metaParts: string[] = [];
142
+ if (node.usage_count > 0) {
143
+ metaParts.push(`${node.usage_count} uses`);
144
+ }
145
+ if (node.confidence !== undefined) {
146
+ metaParts.push(`${Math.round(node.confidence * 100)}% confidence`);
147
+ }
148
+ if (node.author) {
149
+ metaParts.push(`by ${node.author}`);
150
+ }
151
+ if (node.created_from) {
152
+ metaParts.push(`from trajectory`);
153
+ }
154
+
155
+ if (metaParts.length > 0 && options.height > 3) {
156
+ lines.push(
157
+ `${COLORS.dim} ${metaParts.join(" | ")}${reset}`
158
+ );
159
+ }
160
+
161
+ return lines;
162
+ }
163
+
164
+ /**
165
+ * Wrap text to width
166
+ */
167
+ function wrapText(text: string, maxWidth: number): string[] {
168
+ const words = text.split(/\s+/);
169
+ const lines: string[] = [];
170
+ let currentLine = "";
171
+
172
+ for (const word of words) {
173
+ if ((currentLine + " " + word).trim().length <= maxWidth) {
174
+ currentLine = (currentLine + " " + word).trim();
175
+ } else {
176
+ if (currentLine) {
177
+ lines.push(currentLine);
178
+ }
179
+ currentLine = word;
180
+ }
181
+ }
182
+
183
+ if (currentLine) {
184
+ lines.push(currentLine);
185
+ }
186
+
187
+ return lines;
188
+ }
189
+
190
+ /**
191
+ * Render the journey timeline
192
+ */
193
+ export function renderJourney(options?: Partial<JourneyRenderOptions>): string {
194
+ const opts = { ...DEFAULT_RENDER_OPTIONS, ...options };
195
+ const graph = getGlobalLearningGraph();
196
+
197
+ // Get nodes based on options
198
+ let nodes: LearningNode[];
199
+ if (opts.type) {
200
+ nodes = graph.getRecent(opts.type, opts.limit);
201
+ } else if (opts.showAll) {
202
+ nodes = graph.getTimeline();
203
+ } else {
204
+ nodes = graph.getTimeline(opts.limit ?? 20);
205
+ }
206
+
207
+ // Build output
208
+ const lines: string[] = [];
209
+
210
+ // Header
211
+ const border = "═".repeat(Math.min(opts.width, 80));
212
+ lines.push(`${COLORS.accent}${border}${COLORS.reset}`);
213
+ lines.push(
214
+ `${COLORS.bold}LEARNING JOURNEY${COLORS.reset}`.padStart(Math.floor((opts.width + 16) / 2))
215
+ );
216
+ lines.push(`${COLORS.accent}${border}${COLORS.reset}`);
217
+
218
+ // Stats line
219
+ const stats = graph.getStats();
220
+ lines.push(
221
+ `${COLORS.dim}${stats.totalNodes} items learned | ${stats.byType.skill} skills | ${stats.byType.memory} memories | ${stats.byType.pattern} patterns${COLORS.reset}`
222
+ );
223
+ lines.push("");
224
+
225
+ // Legend
226
+ lines.push(`${COLORS.skill}[S] Skill${COLORS.reset} ${COLORS.memory}[M] Memory${COLORS.reset} ${COLORS.pattern}[P] Pattern${COLORS.reset} ${COLORS.antiPattern}[!] Anti-pattern${COLORS.reset}`);
227
+ lines.push("");
228
+
229
+ // Divider
230
+ lines.push(`${COLORS.dim}${"─".repeat(Math.min(opts.width, 80))}${COLORS.reset}`);
231
+
232
+ // Nodes
233
+ if (nodes.length === 0) {
234
+ lines.push(`${COLORS.dim}No learning history yet.${COLORS.reset}`);
235
+ } else {
236
+ const nodeLines: string[] = [];
237
+ for (const node of nodes) {
238
+ nodeLines.push(...renderNode(node, opts));
239
+ nodeLines.push(""); // Empty line between nodes
240
+ }
241
+
242
+ // Trim and limit
243
+ const trimmedLines = nodeLines.join("\n").split("\n").slice(0, opts.height - 10);
244
+ lines.push(...trimmedLines);
245
+ }
246
+
247
+ // Footer
248
+ lines.push("");
249
+ lines.push(`${COLORS.dim}Use --json for raw graph data${COLORS.reset}`);
250
+
251
+ return lines.join("\n");
252
+ }
253
+
254
+ /**
255
+ * Render as JSON
256
+ */
257
+ export function renderJourneyJSON(): string {
258
+ const graph = getGlobalLearningGraph();
259
+ return JSON.stringify(graph.getGraph(), null, 2);
260
+ }
261
+
262
+ /**
263
+ * Render summary
264
+ */
265
+ export function renderSummary(): string {
266
+ const graph = getGlobalLearningGraph();
267
+ const stats = graph.getStats();
268
+ const lines: string[] = [];
269
+
270
+ lines.push(`${COLORS.bold}Learning Journey Summary${COLORS.reset}`);
271
+ lines.push("─".repeat(40));
272
+ lines.push("");
273
+ lines.push(`${COLORS.bold}Total Items:${COLORS.reset} ${stats.totalNodes}`);
274
+ lines.push("");
275
+ lines.push(`${COLORS.bold}By Type:${COLORS.reset}`);
276
+ lines.push(` ${COLORS.skill}Skills:${COLORS.reset} ${stats.byType.skill}`);
277
+ lines.push(` ${COLORS.memory}Memories:${COLORS.reset} ${stats.byType.memory}`);
278
+ lines.push(` ${COLORS.pattern}Patterns:${COLORS.reset} ${stats.byType.pattern}`);
279
+ lines.push(` ${COLORS.antiPattern}Anti-patterns:${COLORS.reset} ${stats.byType["anti-pattern"]}`);
280
+ lines.push("");
281
+ lines.push(`${COLORS.bold}Most Used:${COLORS.reset}`);
282
+
283
+ for (const node of stats.mostUsed) {
284
+ const color = getColor(node.type, true);
285
+ const reset = COLORS.reset;
286
+ lines.push(
287
+ ` ${color}${node.name}${reset} (${node.usage_count} uses)`
288
+ );
289
+ }
290
+
291
+ return lines.join("\n");
292
+ }
293
+
294
+ /**
295
+ * Render node list
296
+ */
297
+ export function renderNodeList(type?: NodeType): string {
298
+ const graph = getGlobalLearningGraph();
299
+
300
+ let nodes: LearningNode[];
301
+ if (type) {
302
+ nodes = graph.getNodesByType(type);
303
+ } else {
304
+ nodes = graph.getAllNodes();
305
+ }
306
+
307
+ if (nodes.length === 0) {
308
+ return "No nodes found.";
309
+ }
310
+
311
+ const lines: string[] = [];
312
+ lines.push(`${COLORS.bold}Nodes:${COLORS.reset}`);
313
+ lines.push("");
314
+
315
+ for (const node of nodes) {
316
+ const color = getColor(node.type, true);
317
+ const reset = COLORS.reset;
318
+ lines.push(
319
+ `${color}${node.id}${reset} ${node.type}: ${node.name}`
320
+ );
321
+ }
322
+
323
+ return lines.join("\n");
324
+ }
325
+
326
+ /**
327
+ * Animate journey build-up
328
+ */
329
+ export async function animateJourney(
330
+ onFrame: (output: string) => void,
331
+ options?: Partial<JourneyRenderOptions>
332
+ ): Promise<void> {
333
+ const opts = { ...DEFAULT_RENDER_OPTIONS, ...options };
334
+ const graph = getGlobalLearningGraph();
335
+ const nodes = graph.getTimeline();
336
+
337
+ if (nodes.length === 0) {
338
+ onFrame(renderJourney(opts));
339
+ return;
340
+ }
341
+
342
+ // Show nodes progressively
343
+ for (let i = 0; i < Math.min(nodes.length, opts.height - 10); i++) {
344
+ const partialGraph = nodes.slice(0, i + 1);
345
+ const output = renderJourney({ ...opts, showAll: false });
346
+ onFrame(output);
347
+ await new Promise((resolve) => setTimeout(resolve, 100));
348
+ }
349
+ }
350
+
351
+ // CLI helper
352
+ export function parseJourneyArgs(args: string[]): {
353
+ command: string;
354
+ options: Partial<JourneyRenderOptions>;
355
+ } {
356
+ const command = args[0] ?? "render";
357
+ const options: Partial<JourneyRenderOptions> = {};
358
+
359
+ for (let i = 1; i < args.length; i++) {
360
+ const arg = args[i];
361
+ switch (arg) {
362
+ case "--json":
363
+ return { command: "json", options };
364
+ case "--list":
365
+ return { command: "list", options };
366
+ case "--summary":
367
+ return { command: "summary", options };
368
+ case "--no-color":
369
+ options.color = false;
370
+ break;
371
+ case "--width":
372
+ options.width = parseInt(args[++i], 10) || 80;
373
+ break;
374
+ case "--height":
375
+ options.height = parseInt(args[++i], 10) || 40;
376
+ break;
377
+ case "--limit":
378
+ options.limit = parseInt(args[++i], 10) || 20;
379
+ break;
380
+ case "--all":
381
+ options.showAll = true;
382
+ break;
383
+ case "--skill":
384
+ case "--skills":
385
+ options.type = "skill";
386
+ break;
387
+ case "--memory":
388
+ case "--memories":
389
+ options.type = "memory";
390
+ break;
391
+ case "--pattern":
392
+ case "--patterns":
393
+ options.type = "pattern";
394
+ break;
395
+ }
396
+ }
397
+
398
+ return { command, options };
399
+ }