@codified/cli 0.3.5 → 0.3.6

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 (105) hide show
  1. package/dist/commands/add.d.ts +3 -0
  2. package/dist/commands/add.d.ts.map +1 -0
  3. package/dist/commands/add.js +163 -0
  4. package/dist/commands/add.js.map +1 -0
  5. package/dist/commands/bootstrap.d.ts.map +1 -0
  6. package/dist/commands/bootstrap.js +141 -0
  7. package/dist/commands/bootstrap.js.map +1 -0
  8. package/dist/commands/check.d.ts +3 -0
  9. package/dist/commands/check.d.ts.map +1 -0
  10. package/dist/commands/check.js +332 -0
  11. package/dist/commands/check.js.map +1 -0
  12. package/dist/commands/cleanup.d.ts +3 -0
  13. package/dist/commands/cleanup.d.ts.map +1 -0
  14. package/dist/commands/cleanup.js +166 -0
  15. package/dist/commands/cleanup.js.map +1 -0
  16. package/dist/commands/collect.d.ts +26 -0
  17. package/dist/commands/collect.d.ts.map +1 -0
  18. package/dist/commands/collect.js +269 -0
  19. package/dist/commands/collect.js.map +1 -0
  20. package/dist/commands/connect.d.ts +3 -0
  21. package/dist/commands/connect.d.ts.map +1 -0
  22. package/dist/commands/connect.js +321 -0
  23. package/dist/commands/connect.js.map +1 -0
  24. package/dist/commands/explain.d.ts +3 -0
  25. package/dist/commands/explain.d.ts.map +1 -0
  26. package/dist/commands/explain.js +527 -0
  27. package/dist/commands/explain.js.map +1 -0
  28. package/dist/commands/export.d.ts +3 -0
  29. package/dist/commands/export.d.ts.map +1 -0
  30. package/dist/commands/export.js +59 -0
  31. package/dist/commands/export.js.map +1 -0
  32. package/dist/commands/gaps.d.ts +3 -0
  33. package/dist/commands/gaps.d.ts.map +1 -0
  34. package/dist/commands/gaps.js +315 -0
  35. package/dist/commands/gaps.js.map +1 -0
  36. package/dist/commands/graph.d.ts +3 -0
  37. package/dist/commands/graph.d.ts.map +1 -0
  38. package/dist/commands/graph.js +293 -0
  39. package/dist/commands/graph.js.map +1 -0
  40. package/dist/commands/import-cmd.d.ts +3 -0
  41. package/dist/commands/import-cmd.d.ts.map +1 -0
  42. package/dist/commands/import-cmd.js +199 -0
  43. package/dist/commands/import-cmd.js.map +1 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +215 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/project.d.ts +3 -0
  48. package/dist/commands/project.d.ts.map +1 -0
  49. package/dist/commands/project.js +179 -0
  50. package/dist/commands/project.js.map +1 -0
  51. package/dist/commands/reset.d.ts +3 -0
  52. package/dist/commands/reset.d.ts.map +1 -0
  53. package/dist/commands/reset.js +157 -0
  54. package/dist/commands/reset.js.map +1 -0
  55. package/dist/commands/search.d.ts +3 -0
  56. package/dist/commands/search.d.ts.map +1 -0
  57. package/dist/commands/search.js +183 -0
  58. package/dist/commands/search.js.map +1 -0
  59. package/dist/commands/start.d.ts.map +1 -0
  60. package/dist/commands/start.js +205 -0
  61. package/dist/commands/start.js.map +1 -0
  62. package/dist/commands/status.d.ts.map +1 -0
  63. package/dist/commands/status.js +242 -0
  64. package/dist/commands/status.js.map +1 -0
  65. package/dist/commands/timeline.d.ts +3 -0
  66. package/dist/commands/timeline.d.ts.map +1 -0
  67. package/dist/commands/timeline.js +424 -0
  68. package/dist/commands/timeline.js.map +1 -0
  69. package/dist/commands/triage.d.ts +3 -0
  70. package/dist/commands/triage.d.ts.map +1 -0
  71. package/dist/commands/triage.js +336 -0
  72. package/dist/commands/triage.js.map +1 -0
  73. package/dist/commands/up.d.ts +3 -0
  74. package/dist/commands/up.d.ts.map +1 -0
  75. package/dist/commands/up.js +312 -0
  76. package/dist/commands/up.js.map +1 -0
  77. package/dist/commands/watch.d.ts +3 -0
  78. package/dist/commands/watch.d.ts.map +1 -0
  79. package/dist/commands/watch.js +224 -0
  80. package/dist/commands/watch.js.map +1 -0
  81. package/dist/index.d.ts +2 -0
  82. package/dist/index.d.ts.map +1 -0
  83. package/dist/index.js +574 -491
  84. package/dist/index.js.map +1 -0
  85. package/dist/lib/config.d.ts +52 -0
  86. package/dist/lib/config.d.ts.map +1 -0
  87. package/dist/lib/config.js +142 -0
  88. package/dist/lib/config.js.map +1 -0
  89. package/dist/lib/docker.d.ts +23 -0
  90. package/dist/lib/docker.d.ts.map +1 -0
  91. package/dist/lib/docker.js +84 -0
  92. package/dist/lib/docker.js.map +1 -0
  93. package/dist/lib/migrate.d.ts +9 -0
  94. package/dist/lib/migrate.d.ts.map +1 -0
  95. package/dist/lib/migrate.js +97 -0
  96. package/dist/lib/migrate.js.map +1 -0
  97. package/dist/lib/paths.d.ts +9 -0
  98. package/dist/lib/paths.d.ts.map +1 -0
  99. package/dist/lib/paths.js +28 -0
  100. package/dist/lib/paths.js.map +1 -0
  101. package/dist/lib/prompt.d.ts +14 -0
  102. package/dist/lib/prompt.d.ts.map +1 -0
  103. package/dist/lib/prompt.js +87 -0
  104. package/dist/lib/prompt.js.map +1 -0
  105. package/package.json +1 -1
@@ -0,0 +1,527 @@
1
+ // codify explain — Claude-powered narrative synthesis from the context graph
2
+ import { Command } from "commander";
3
+ import { createHash } from "node:crypto";
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
5
+ import { resolve } from "node:path";
6
+ import { loadProjectConfig } from "../lib/config.js";
7
+ // --- Cache helpers ---
8
+ const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
9
+ function getCacheDir() {
10
+ return resolve(process.cwd(), ".codify", "cache");
11
+ }
12
+ function getCacheKey(question) {
13
+ return createHash("sha256")
14
+ .update(question.toLowerCase().trim())
15
+ .digest("hex");
16
+ }
17
+ function readCache(question) {
18
+ const cacheDir = getCacheDir();
19
+ const key = getCacheKey(question);
20
+ const cachePath = resolve(cacheDir, `${key}.json`);
21
+ if (!existsSync(cachePath))
22
+ return null;
23
+ try {
24
+ const raw = readFileSync(cachePath, "utf-8");
25
+ const entry = JSON.parse(raw);
26
+ const age = Date.now() - entry.cachedAt;
27
+ if (age > CACHE_TTL_MS)
28
+ return null; // expired
29
+ return entry;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ function writeCache(question, narrative, nodeCount, gapCount, edgeCount) {
36
+ const cacheDir = getCacheDir();
37
+ mkdirSync(cacheDir, { recursive: true });
38
+ const key = getCacheKey(question);
39
+ const cachePath = resolve(cacheDir, `${key}.json`);
40
+ const entry = {
41
+ question,
42
+ narrative,
43
+ cachedAt: Date.now(),
44
+ nodeCount,
45
+ gapCount,
46
+ edgeCount,
47
+ };
48
+ writeFileSync(cachePath, JSON.stringify(entry, null, 2), "utf-8");
49
+ }
50
+ // --- Color helpers (ANSI escape codes) ---
51
+ const RESET = "\x1b[0m";
52
+ const BOLD = "\x1b[1m";
53
+ const DIM = "\x1b[2m";
54
+ const CYAN = "\x1b[36m";
55
+ const GREEN = "\x1b[32m";
56
+ const YELLOW = "\x1b[33m";
57
+ const MAGENTA = "\x1b[35m";
58
+ const WHITE = "\x1b[37m";
59
+ const RED = "\x1b[31m";
60
+ const BLUE = "\x1b[34m";
61
+ function typeColor(type) {
62
+ const colors = {
63
+ Decision: "\x1b[33m", // yellow
64
+ Feature: "\x1b[32m", // green
65
+ Metric: "\x1b[36m", // cyan
66
+ CustomerSignal: "\x1b[35m", // magenta
67
+ CodeArtifact: "\x1b[34m", // blue
68
+ Discussion: "\x1b[37m", // white
69
+ Gap: "\x1b[31m", // red
70
+ Study: "\x1b[36m", // cyan
71
+ Person: "\x1b[33m", // yellow
72
+ };
73
+ return `${colors[type] ?? DIM}${type}${RESET}`;
74
+ }
75
+ function truncate(str, maxLen) {
76
+ if (str.length <= maxLen)
77
+ return str;
78
+ return str.slice(0, maxLen - 3) + "...";
79
+ }
80
+ function stripAnsi(str) {
81
+ // eslint-disable-next-line no-control-regex
82
+ return str.replace(/\x1b\[[0-9;]*m/g, "");
83
+ }
84
+ // --- Command definition ---
85
+ export const explainCommand = new Command("explain")
86
+ .description("Ask a question about your project — answered with a Claude-powered narrative synthesis from the context graph")
87
+ .argument("<question>", "Natural language question (e.g. \"why did we choose PostgreSQL over MongoDB\")")
88
+ .option("--json", "Output raw JSON for piping")
89
+ .option("--no-color", "Plain text output (strip ANSI codes)")
90
+ .option("--limit <n>", "Max nodes to include in context", "20")
91
+ .option("--fresh", "Bypass cache and regenerate response")
92
+ .action(async (question, opts) => {
93
+ try {
94
+ await loadProjectConfig();
95
+ // Check for ANTHROPIC_API_KEY before doing anything else
96
+ if (!process.env.ANTHROPIC_API_KEY) {
97
+ console.error("\n ERROR: ANTHROPIC_API_KEY not set.");
98
+ console.error(" Export your API key: export ANTHROPIC_API_KEY=sk-...\n");
99
+ process.exit(1);
100
+ }
101
+ const { getPool, closePool } = await import("@codify/graph");
102
+ const pool = getPool();
103
+ try {
104
+ await pool.query("SELECT 1");
105
+ }
106
+ catch {
107
+ console.error(" ERROR: Cannot connect to PostgreSQL. Run 'codify init' first.\n");
108
+ process.exit(1);
109
+ }
110
+ const limit = parseInt(opts.limit, 10);
111
+ if (isNaN(limit) || limit < 1) {
112
+ console.error("\n ERROR: --limit must be a positive integer.\n");
113
+ process.exit(1);
114
+ }
115
+ const useColor = opts.color !== false;
116
+ // Print header
117
+ if (!opts.json) {
118
+ const header = useColor
119
+ ? `\n ${BOLD}Codify — Explain${RESET}\n`
120
+ : "\n Codify -- Explain\n";
121
+ console.log(header);
122
+ const questionLine = useColor
123
+ ? ` ${DIM}Question:${RESET} ${CYAN}${question}${RESET}\n`
124
+ : ` Question: ${question}\n`;
125
+ console.log(questionLine);
126
+ const searching = useColor
127
+ ? ` ${DIM}Searching the context graph...${RESET}`
128
+ : " Searching the context graph...";
129
+ console.log(searching);
130
+ }
131
+ // --- Check cache before doing expensive work ---
132
+ if (!opts.fresh) {
133
+ const cached = readCache(question);
134
+ if (cached) {
135
+ const ageMinutes = Math.floor((Date.now() - cached.cachedAt) / 60000);
136
+ if (opts.json) {
137
+ const jsonOutput = {
138
+ question: cached.question,
139
+ narrative: cached.narrative,
140
+ nodes_searched: cached.nodeCount,
141
+ gaps_found: cached.gapCount,
142
+ relationships_found: cached.edgeCount,
143
+ cached: true,
144
+ cached_minutes_ago: ageMinutes,
145
+ };
146
+ console.log(JSON.stringify(jsonOutput, null, 2));
147
+ await closePool();
148
+ return;
149
+ }
150
+ const cacheNote = useColor
151
+ ? `\n ${YELLOW}Cached response (${ageMinutes} minutes ago). Use --fresh to regenerate.${RESET}\n`
152
+ : `\n Cached response (${ageMinutes} minutes ago). Use --fresh to regenerate.\n`;
153
+ console.log(cacheNote);
154
+ // Render cached narrative
155
+ const sections = parseNarrativeSections(cached.narrative);
156
+ for (const section of sections) {
157
+ const heading = useColor
158
+ ? ` ${BOLD}${sectionColor(section.heading)}${section.heading}${RESET}`
159
+ : ` ${section.heading}`;
160
+ console.log(heading);
161
+ console.log("");
162
+ const bodyLines = section.body.split("\n");
163
+ for (const line of bodyLines) {
164
+ const outputLine = useColor ? ` ${line}` : ` ${stripAnsi(line)}`;
165
+ console.log(outputLine);
166
+ }
167
+ console.log("");
168
+ }
169
+ if (sections.length === 0) {
170
+ const bodyLines = cached.narrative.split("\n");
171
+ for (const line of bodyLines) {
172
+ const outputLine = useColor ? ` ${line}` : ` ${stripAnsi(line)}`;
173
+ console.log(outputLine);
174
+ }
175
+ console.log("");
176
+ }
177
+ const footer = useColor
178
+ ? ` ${DIM}---${RESET}\n ${DIM}Synthesized from ${cached.nodeCount} context nodes, ${cached.gapCount} gaps, and ${cached.edgeCount} relationships${RESET}`
179
+ : ` ---\n Synthesized from ${cached.nodeCount} context nodes, ${cached.gapCount} gaps, and ${cached.edgeCount} relationships`;
180
+ console.log(footer);
181
+ console.log("");
182
+ await closePool();
183
+ return;
184
+ }
185
+ }
186
+ // --- Search for relevant nodes ---
187
+ // Split keywords, ILIKE against properties::text and metadata::text (same pattern as search.ts)
188
+ const keywords = question.split(/\s+/).filter((w) => w.length > 1);
189
+ const conditions = [
190
+ "superseded_by IS NULL",
191
+ "layer = ANY($1)",
192
+ ];
193
+ const params = [["permanent", "draft", "hot"]];
194
+ let paramIdx = 2;
195
+ if (keywords.length > 0) {
196
+ const keywordConditions = keywords.map((kw) => {
197
+ params.push(`%${kw}%`);
198
+ const idx = paramIdx++;
199
+ return `(properties::text ILIKE $${idx} OR metadata::text ILIKE $${idx} OR $${idx} = ANY(tags))`;
200
+ });
201
+ conditions.push(`(${keywordConditions.join(" OR ")})`);
202
+ }
203
+ params.push(limit);
204
+ const sql = `SELECT id, type, properties, metadata, freshness, confidence, tags, layer, created_at, updated_at
205
+ FROM nodes
206
+ WHERE ${conditions.join(" AND ")}
207
+ ORDER BY freshness DESC
208
+ LIMIT $${paramIdx}`;
209
+ const result = await pool.query(sql, params);
210
+ const nodes = result.rows;
211
+ // --- Also search for gaps ---
212
+ const gapConditions = [
213
+ "superseded_by IS NULL",
214
+ "type = 'Gap'",
215
+ "layer = ANY($1)",
216
+ ];
217
+ const gapParams = [["permanent", "draft", "hot"]];
218
+ let gapParamIdx = 2;
219
+ if (keywords.length > 0) {
220
+ const gapKeywordConditions = keywords.map((kw) => {
221
+ gapParams.push(`%${kw}%`);
222
+ const idx = gapParamIdx++;
223
+ return `(properties::text ILIKE $${idx} OR metadata::text ILIKE $${idx} OR $${idx} = ANY(tags))`;
224
+ });
225
+ gapConditions.push(`(${gapKeywordConditions.join(" OR ")})`);
226
+ }
227
+ gapParams.push(5);
228
+ const gapSql = `SELECT id, type, properties, metadata, freshness, confidence, tags, layer, created_at, updated_at
229
+ FROM nodes
230
+ WHERE ${gapConditions.join(" AND ")}
231
+ ORDER BY freshness DESC
232
+ LIMIT $${gapParamIdx}`;
233
+ const gapResult = await pool.query(gapSql, gapParams);
234
+ const gaps = gapResult.rows;
235
+ // --- Get connected edges for each node to build richer context ---
236
+ const nodeIds = nodes.map((n) => n.id);
237
+ let edgeContext = [];
238
+ if (nodeIds.length > 0) {
239
+ const edgeSql = `
240
+ SELECT
241
+ e.source_id,
242
+ e.target_id,
243
+ e.type as edge_type,
244
+ sn.type as source_type,
245
+ COALESCE(sn.properties->>'title', sn.properties->>'name', sn.id::text) as source_title,
246
+ tn.type as target_type,
247
+ COALESCE(tn.properties->>'title', tn.properties->>'name', tn.id::text) as target_title
248
+ FROM edges e
249
+ JOIN nodes sn ON sn.id = e.source_id
250
+ JOIN nodes tn ON tn.id = e.target_id
251
+ WHERE e.source_id = ANY($1) OR e.target_id = ANY($1)
252
+ LIMIT 50`;
253
+ const edgeResult = await pool.query(edgeSql, [nodeIds]);
254
+ edgeContext = edgeResult.rows;
255
+ }
256
+ // No results at all
257
+ if (nodes.length === 0 && gaps.length === 0) {
258
+ if (opts.json) {
259
+ console.log(JSON.stringify({
260
+ question,
261
+ narrative: null,
262
+ error: "No context found in the graph for this question.",
263
+ nodes_searched: 0,
264
+ gaps_found: 0,
265
+ }, null, 2));
266
+ await closePool();
267
+ return;
268
+ }
269
+ const msg = useColor
270
+ ? `\n ${YELLOW}No context found in the graph for this question.${RESET}`
271
+ : "\n No context found in the graph for this question.";
272
+ console.log(msg);
273
+ console.log("");
274
+ const hint = useColor
275
+ ? ` ${DIM}Try broader keywords, or run 'codify bootstrap' to build the graph.${RESET}`
276
+ : " Try broader keywords, or run 'codify bootstrap' to build the graph.";
277
+ console.log(hint);
278
+ console.log("");
279
+ await closePool();
280
+ return;
281
+ }
282
+ // --- Build context summary for Claude ---
283
+ const now = new Date();
284
+ const nodeSummaries = [];
285
+ for (const node of nodes) {
286
+ const props = node.properties ?? {};
287
+ const meta = node.metadata ?? {};
288
+ const combined = { ...props, ...meta };
289
+ const title = combined.title ??
290
+ combined.name ??
291
+ combined.description ??
292
+ node.id;
293
+ // Compute age for freshness warning
294
+ const updatedAt = node.updated_at ? new Date(node.updated_at) : null;
295
+ let ageStr = "";
296
+ if (updatedAt) {
297
+ const ageDays = Math.floor((now.getTime() - updatedAt.getTime()) / (1000 * 60 * 60 * 24));
298
+ if (ageDays > 180) {
299
+ ageStr = ` [STALE: last updated ${Math.floor(ageDays / 30)} months ago]`;
300
+ }
301
+ else if (ageDays > 60) {
302
+ ageStr = ` [last updated ${Math.floor(ageDays / 30)} months ago]`;
303
+ }
304
+ else if (ageDays > 14) {
305
+ ageStr = ` [last updated ${Math.floor(ageDays / 7)} weeks ago]`;
306
+ }
307
+ }
308
+ const description = combined.description ?? "";
309
+ const rationale = combined.rationale ?? "";
310
+ const status = combined.status ?? "";
311
+ const confidence = `${(node.confidence * 100).toFixed(0)}% confidence`;
312
+ const freshness = `${(node.freshness * 100).toFixed(0)}% freshness`;
313
+ const parts = [`[${node.type}] "${title}"${ageStr} (${confidence}, ${freshness})`];
314
+ if (description)
315
+ parts.push(` Description: ${description}`);
316
+ if (rationale)
317
+ parts.push(` Rationale: ${rationale}`);
318
+ if (status)
319
+ parts.push(` Status: ${status}`);
320
+ parts.push(` Layer: ${node.layer}`);
321
+ nodeSummaries.push(parts.join("\n"));
322
+ }
323
+ // Build gap summaries
324
+ const gapSummaries = [];
325
+ for (const gap of gaps) {
326
+ const props = gap.properties ?? {};
327
+ const meta = gap.metadata ?? {};
328
+ const desc = (props.description ?? meta.description ?? "No description");
329
+ const gapType = (props.gapType ?? meta.gapType ?? "unknown");
330
+ const severity = (props.severity ?? meta.severity ?? "medium");
331
+ const gapStatus = (props.status ?? meta.status ?? "detected");
332
+ gapSummaries.push(`[${gapType}] (${severity}, ${gapStatus}): ${desc}`);
333
+ }
334
+ // Build edge relationship summaries
335
+ const edgeSummaries = [];
336
+ for (const edge of edgeContext) {
337
+ edgeSummaries.push(`[${edge.source_type}] "${edge.source_title}" --${edge.edge_type}--> [${edge.target_type}] "${edge.target_title}"`);
338
+ }
339
+ if (!opts.json) {
340
+ const synth = useColor
341
+ ? ` ${DIM}Found ${nodes.length} nodes, ${gaps.length} gaps, ${edgeContext.length} relationships. Synthesizing...${RESET}`
342
+ : ` Found ${nodes.length} nodes, ${gaps.length} gaps, ${edgeContext.length} relationships. Synthesizing...`;
343
+ console.log(synth);
344
+ console.log("");
345
+ }
346
+ // --- Build the Claude prompt ---
347
+ const synthesisPrompt = [
348
+ "You are a context analyst for a software team. Given the following graph data, synthesize a coherent narrative that answers the question.",
349
+ "",
350
+ "Structure your response with these sections (use exactly these headings with ## prefix):",
351
+ "## Context",
352
+ "What background is relevant to this question.",
353
+ "",
354
+ "## Key Findings",
355
+ "Key decisions, features, or facts discovered. Include rationale where available.",
356
+ "",
357
+ "## Evidence",
358
+ "What data, customer signals, studies, or code artifacts support these findings.",
359
+ "",
360
+ "## Gaps & Warnings",
361
+ "What's missing, stale, or uncertain. Flag low-confidence items and stale data.",
362
+ "",
363
+ "## Summary",
364
+ "A concise 2-3 sentence summary.",
365
+ "",
366
+ "Rules:",
367
+ "- Write in clear, direct prose — not bullet lists of raw data",
368
+ "- If data is marked [STALE], include a freshness warning (e.g., 'Note: this information is X months old and may be outdated')",
369
+ "- If there are gaps, call them out explicitly (e.g., 'This decision was made without customer evidence')",
370
+ "- If confidence is below 50%, flag it as uncertain",
371
+ "- Only include sections that have relevant data — skip empty sections",
372
+ "- Keep it concise but thorough. Aim for 150-400 words.",
373
+ "",
374
+ `## Question: ${question}`,
375
+ "",
376
+ "## Graph Nodes:",
377
+ ...nodeSummaries,
378
+ ];
379
+ if (edgeSummaries.length > 0) {
380
+ synthesisPrompt.push("", "## Relationships:", ...edgeSummaries);
381
+ }
382
+ if (gapSummaries.length > 0) {
383
+ synthesisPrompt.push("", "## Known Gaps:", ...gapSummaries);
384
+ }
385
+ // --- Call Claude ---
386
+ const Anthropic = (await import("@anthropic-ai/sdk")).default;
387
+ const anthropic = new Anthropic({
388
+ apiKey: process.env.ANTHROPIC_API_KEY,
389
+ });
390
+ const response = await anthropic.messages.create({
391
+ model: "claude-sonnet-4-20250514",
392
+ max_tokens: 2048,
393
+ messages: [
394
+ {
395
+ role: "user",
396
+ content: synthesisPrompt.join("\n"),
397
+ },
398
+ ],
399
+ });
400
+ const narrativeBlock = response.content.find((b) => b.type === "text");
401
+ const narrative = narrativeBlock ? narrativeBlock.text : "Unable to synthesize narrative.";
402
+ // --- Save response to cache ---
403
+ try {
404
+ writeCache(question, narrative, nodes.length, gaps.length, edgeContext.length);
405
+ }
406
+ catch {
407
+ // Cache write failure is non-fatal — just skip it
408
+ }
409
+ // --- JSON output mode ---
410
+ if (opts.json) {
411
+ const jsonOutput = {
412
+ question,
413
+ narrative,
414
+ nodes_searched: nodes.length,
415
+ gaps_found: gaps.length,
416
+ relationships_found: edgeContext.length,
417
+ nodes: nodes.map((n) => ({
418
+ id: n.id,
419
+ type: n.type,
420
+ title: (n.properties?.title ?? n.properties?.name ?? n.metadata?.title ?? n.metadata?.name ?? n.id),
421
+ freshness: n.freshness,
422
+ confidence: n.confidence,
423
+ layer: n.layer,
424
+ })),
425
+ };
426
+ console.log(JSON.stringify(jsonOutput, null, 2));
427
+ await closePool();
428
+ return;
429
+ }
430
+ // --- Pretty terminal output ---
431
+ // Parse narrative sections and render with color
432
+ const sections = parseNarrativeSections(narrative);
433
+ for (const section of sections) {
434
+ const heading = useColor
435
+ ? ` ${BOLD}${sectionColor(section.heading)}${section.heading}${RESET}`
436
+ : ` ${section.heading}`;
437
+ console.log(heading);
438
+ console.log("");
439
+ // Indent the body text
440
+ const bodyLines = section.body.split("\n");
441
+ for (const line of bodyLines) {
442
+ const outputLine = useColor ? ` ${line}` : ` ${stripAnsi(line)}`;
443
+ console.log(outputLine);
444
+ }
445
+ console.log("");
446
+ }
447
+ // If no sections were parsed, just print the raw narrative
448
+ if (sections.length === 0) {
449
+ const bodyLines = narrative.split("\n");
450
+ for (const line of bodyLines) {
451
+ const outputLine = useColor ? ` ${line}` : ` ${stripAnsi(line)}`;
452
+ console.log(outputLine);
453
+ }
454
+ console.log("");
455
+ }
456
+ // Footer
457
+ const footer = useColor
458
+ ? ` ${DIM}---${RESET}\n ${DIM}Synthesized from ${nodes.length} context nodes, ${gaps.length} gaps, and ${edgeContext.length} relationships${RESET}`
459
+ : ` ---\n Synthesized from ${nodes.length} context nodes, ${gaps.length} gaps, and ${edgeContext.length} relationships`;
460
+ console.log(footer);
461
+ console.log("");
462
+ await closePool();
463
+ }
464
+ catch (err) {
465
+ const message = err instanceof Error ? err.message : String(err);
466
+ if (message.includes("ECONNREFUSED")) {
467
+ console.error("\n ERROR: Cannot connect to Codify services.");
468
+ console.error(" Run 'codify init' to start the infrastructure.\n");
469
+ }
470
+ else if (message.includes("ANTHROPIC_API_KEY")) {
471
+ console.error("\n ERROR: ANTHROPIC_API_KEY not set.");
472
+ console.error(" Export your API key: export ANTHROPIC_API_KEY=sk-...\n");
473
+ }
474
+ else {
475
+ console.error(`\n ERROR: ${message}\n`);
476
+ }
477
+ process.exit(1);
478
+ }
479
+ });
480
+ function parseNarrativeSections(narrative) {
481
+ const sections = [];
482
+ const lines = narrative.split("\n");
483
+ let currentHeading = null;
484
+ let currentBody = [];
485
+ for (const line of lines) {
486
+ const headingMatch = line.match(/^#{1,3}\s+(.+)/);
487
+ if (headingMatch) {
488
+ // Save previous section
489
+ if (currentHeading !== null) {
490
+ sections.push({
491
+ heading: currentHeading,
492
+ body: currentBody.join("\n").trim(),
493
+ });
494
+ }
495
+ currentHeading = headingMatch[1];
496
+ currentBody = [];
497
+ }
498
+ else {
499
+ currentBody.push(line);
500
+ }
501
+ }
502
+ // Save last section
503
+ if (currentHeading !== null) {
504
+ sections.push({
505
+ heading: currentHeading,
506
+ body: currentBody.join("\n").trim(),
507
+ });
508
+ }
509
+ return sections;
510
+ }
511
+ function sectionColor(heading) {
512
+ const lower = heading.toLowerCase();
513
+ if (lower.includes("context"))
514
+ return CYAN;
515
+ if (lower.includes("finding"))
516
+ return GREEN;
517
+ if (lower.includes("decision"))
518
+ return GREEN;
519
+ if (lower.includes("evidence"))
520
+ return BLUE;
521
+ if (lower.includes("gap") || lower.includes("warning"))
522
+ return YELLOW;
523
+ if (lower.includes("summary"))
524
+ return MAGENTA;
525
+ return WHITE;
526
+ }
527
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/commands/explain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const exportCommand: Command;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SAiEtB,CAAC"}
@@ -0,0 +1,59 @@
1
+ // codify export — export the context graph to a JSON file
2
+ import { Command } from "commander";
3
+ import { writeFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { loadProjectConfig } from "../lib/config.js";
6
+ export const exportCommand = new Command("export")
7
+ .description("Export the context graph to a JSON file")
8
+ .option("-o, --output <file>", "Output file path")
9
+ .action(async (opts) => {
10
+ try {
11
+ await loadProjectConfig();
12
+ const { getPool, closePool } = await import("@codify/graph");
13
+ const pool = getPool();
14
+ try {
15
+ await pool.query("SELECT 1");
16
+ }
17
+ catch {
18
+ console.error(" ERROR: Cannot connect to PostgreSQL. Run 'codify init' first.\n");
19
+ process.exit(1);
20
+ }
21
+ // Query all active nodes (not superseded)
22
+ const nodesResult = await pool.query(`SELECT * FROM nodes WHERE superseded_by IS NULL ORDER BY created_at`);
23
+ // Query all edges
24
+ const edgesResult = await pool.query(`SELECT * FROM edges ORDER BY created_at`);
25
+ const nodes = nodesResult.rows;
26
+ const edges = edgesResult.rows;
27
+ // Determine output filename
28
+ const today = new Date().toISOString().split("T")[0];
29
+ const defaultFilename = `codify-export-${today}.json`;
30
+ const outputFile = resolve(process.cwd(), opts.output ?? defaultFilename);
31
+ // Build export payload
32
+ const payload = {
33
+ version: "0.3.3",
34
+ exportedAt: new Date().toISOString(),
35
+ nodes,
36
+ edges,
37
+ metadata: {
38
+ totalNodes: nodes.length,
39
+ totalEdges: edges.length,
40
+ projectPath: process.cwd(),
41
+ },
42
+ };
43
+ writeFileSync(outputFile, JSON.stringify(payload, null, 2) + "\n", "utf-8");
44
+ console.log(`\n Exported ${nodes.length} nodes and ${edges.length} edges to ${outputFile}\n`);
45
+ await closePool();
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ if (message.includes("ECONNREFUSED")) {
50
+ console.error("\n ERROR: Cannot connect to Codify services.");
51
+ console.error(" Run 'codify init' to start the infrastructure.\n");
52
+ }
53
+ else {
54
+ console.error(`\n ERROR: ${message}\n`);
55
+ }
56
+ process.exit(1);
57
+ }
58
+ });
59
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;KACjD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,CAAC;QACH,MAAM,iBAAiB,EAAE,CAAC;QAE1B,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAE7D,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;YACnF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,0CAA0C;QAC1C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAClC,qEAAqE,CACtE,CAAC;QAEF,kBAAkB;QAClB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAClC,yCAAyC,CAC1C,CAAC;QAEF,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;QAC/B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;QAE/B,4BAA4B;QAC5B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,eAAe,GAAG,iBAAiB,KAAK,OAAO,CAAC;QACtD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC;QAE1E,uBAAuB;QACvB,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,KAAK;YACL,KAAK;YACL,QAAQ,EAAE;gBACR,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;aAC3B;SACF,CAAC;QAEF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAE5E,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,MAAM,cAAc,KAAK,CAAC,MAAM,aAAa,UAAU,IAAI,CAAC,CAAC;QAE/F,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEjE,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;YAC/D,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,IAAI,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const gapsCommand: Command;
3
+ //# sourceMappingURL=gaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gaps.d.ts","sourceRoot":"","sources":["../../src/commands/gaps.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmGpC,eAAO,MAAM,WAAW,SAmRpB,CAAC"}