@kentwynn/kgraph 0.2.10 → 0.2.12

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 (39) hide show
  1. package/README.md +59 -29
  2. package/dist/cli/commands/blame.d.ts +2 -0
  3. package/dist/cli/commands/blame.js +52 -0
  4. package/dist/cli/commands/doctor.js +42 -12
  5. package/dist/cli/commands/impact.js +11 -5
  6. package/dist/cli/commands/init.js +2 -0
  7. package/dist/cli/commands/knowledge.d.ts +2 -0
  8. package/dist/cli/commands/knowledge.js +137 -0
  9. package/dist/cli/commands/pack.d.ts +2 -0
  10. package/dist/cli/commands/pack.js +49 -0
  11. package/dist/cli/commands/repair.js +3 -3
  12. package/dist/cli/commands/stale.d.ts +2 -0
  13. package/dist/cli/commands/stale.js +33 -0
  14. package/dist/cli/commands/visualize.js +7 -6
  15. package/dist/cli/help.js +17 -11
  16. package/dist/cli/index.js +8 -0
  17. package/dist/cognition/cognition-quality.d.ts +5 -0
  18. package/dist/cognition/cognition-quality.js +98 -5
  19. package/dist/cognition/cognition-updater.js +14 -0
  20. package/dist/cognition/compact.js +129 -28
  21. package/dist/cognition/conclusion.d.ts +2 -0
  22. package/dist/cognition/conclusion.js +22 -0
  23. package/dist/context/context-pack.d.ts +3 -0
  24. package/dist/context/context-pack.js +71 -0
  25. package/dist/context/context-query.js +53 -28
  26. package/dist/integrations/adapters/claude-code.js +23 -3
  27. package/dist/integrations/adapters/codex.js +1 -1
  28. package/dist/integrations/adapters/copilot.js +46 -3
  29. package/dist/integrations/workflow-steps.js +17 -8
  30. package/dist/knowledge/atom-store.d.ts +60 -0
  31. package/dist/knowledge/atom-store.js +484 -0
  32. package/dist/storage/kgraph-paths.js +5 -2
  33. package/dist/types/config.d.ts +1 -0
  34. package/dist/types/knowledge.d.ts +92 -0
  35. package/dist/types/knowledge.js +1 -0
  36. package/dist/visualization/graph-builder.d.ts +5 -2
  37. package/dist/visualization/graph-builder.js +43 -18
  38. package/dist/visualization/html-template.js +24 -17
  39. package/package.json +1 -1
@@ -8,10 +8,10 @@ const LANGUAGE_COLORS = {
8
8
  html: '#f97316',
9
9
  };
10
10
  const STATUS_COLORS = {
11
- current: '#10b981',
12
- mixed: '#f59e0b',
11
+ active: '#10b981',
12
+ 'needs-review': '#f59e0b',
13
13
  stale: '#ef4444',
14
- unresolved: '#6b7280',
14
+ archived: '#6b7280',
15
15
  };
16
16
  const SYMBOL_COLORS = {
17
17
  function: '#22c55e',
@@ -20,7 +20,8 @@ const SYMBOL_COLORS = {
20
20
  export: '#f97316',
21
21
  import: '#64748b',
22
22
  };
23
- export function buildGraph(fileMap, symbolMap, dependencyMap, relationshipMap, cognitionNotes) {
23
+ const MAX_ATOM_NODES = 250;
24
+ export function buildGraph(fileMap, symbolMap, dependencyMap, relationshipMap, knowledgeAtoms) {
24
25
  const elements = [];
25
26
  const edgeIds = new Set();
26
27
  const nodeIds = new Set();
@@ -59,22 +60,30 @@ export function buildGraph(fileMap, symbolMap, dependencyMap, relationshipMap, c
59
60
  classes: `symbol ${symbol.kind}`,
60
61
  });
61
62
  }
62
- for (const note of cognitionNotes) {
63
- const id = `cognition-${note.id}`;
63
+ const atomsForGraph = selectAtomsForGraph(knowledgeAtoms);
64
+ for (const atom of atomsForGraph) {
65
+ const id = `atom-${atom.id}`;
64
66
  elements.push({
65
67
  data: {
66
68
  id,
67
- label: note.title,
68
- color: STATUS_COLORS[note.referencesStatus] ?? STATUS_COLORS.unresolved,
69
- type: 'cognition',
70
- referencesStatus: note.referencesStatus,
71
- domain: note.domain ?? '',
72
- relatedFiles: note.relatedFiles,
73
- relatedSymbols: note.relatedSymbols,
69
+ label: atom.topic,
70
+ color: STATUS_COLORS[atom.status] ?? STATUS_COLORS.archived,
71
+ type: 'atom',
72
+ atomId: atom.id,
73
+ atomType: atom.type,
74
+ confidence: atom.confidence,
75
+ status: atom.status,
76
+ sourceCommand: atom.provenance.sourceCommand,
77
+ domain: atom.scopeRefs.domains[0] ?? '',
78
+ relatedFiles: atom.scopeRefs.files,
79
+ relatedSymbols: atom.scopeRefs.symbols,
80
+ supersededBy: atom.lifecycle.supersededBy ?? '',
81
+ supersedes: atom.lifecycle.supersedes,
82
+ invalidatedBy: atom.lifecycle.invalidatedBy ?? [],
74
83
  },
75
- classes: `cognition ${note.referencesStatus}`,
84
+ classes: `atom ${atom.status}`,
76
85
  });
77
- for (const filePath of note.relatedFiles) {
86
+ for (const filePath of atom.scopeRefs.files) {
78
87
  const target = fileMap.files.find((f) => f.path === filePath);
79
88
  if (target) {
80
89
  const edgeId = `${id}-ref-${target.id}`;
@@ -85,10 +94,10 @@ export function buildGraph(fileMap, symbolMap, dependencyMap, relationshipMap, c
85
94
  id: edgeId,
86
95
  source: id,
87
96
  target: target.id,
88
- type: 'cognition-ref',
97
+ type: 'atom-ref',
89
98
  label: '',
90
99
  },
91
- classes: 'cognition-ref',
100
+ classes: 'atom-ref',
92
101
  });
93
102
  }
94
103
  }
@@ -142,12 +151,28 @@ export function buildGraph(fileMap, symbolMap, dependencyMap, relationshipMap, c
142
151
  meta: {
143
152
  fileCount: fileMap.files.length,
144
153
  symbolCount: symbolMap.symbols.length,
145
- cognitionCount: cognitionNotes.length,
154
+ atomCount: knowledgeAtoms.filter((atom) => atom.status !== 'archived').length,
155
+ hiddenAtomCount: Math.max(0, knowledgeAtoms.filter((atom) => atom.status !== 'archived').length -
156
+ atomsForGraph.length),
157
+ cognitionCount: knowledgeAtoms.filter((atom) => atom.status !== 'archived').length,
146
158
  tokenEstimate,
147
159
  generatedAt: new Date().toISOString(),
148
160
  },
149
161
  };
150
162
  }
163
+ function selectAtomsForGraph(atoms) {
164
+ return atoms
165
+ .filter((atom) => atom.status !== 'archived')
166
+ .sort((left, right) => atomGraphScore(right) - atomGraphScore(left))
167
+ .slice(0, MAX_ATOM_NODES);
168
+ }
169
+ function atomGraphScore(atom) {
170
+ const statusScore = atom.status === 'active' ? 6 : atom.status === 'needs-review' ? 4 : 2;
171
+ const confidenceScore = atom.confidence === 'high' ? 3 : atom.confidence === 'medium' ? 2 : 0;
172
+ const evidenceScore = Math.min(4, atom.scopeRefs.files.length + atom.scopeRefs.symbols.length);
173
+ const typeScore = atom.type === 'decision' || atom.type === 'gotcha' ? 1 : 0;
174
+ return statusScore + confidenceScore + evidenceScore + typeScore;
175
+ }
151
176
  function getTokenBucket(tokenEstimate) {
152
177
  const tokens = tokenEstimate ?? 0;
153
178
  if (tokens >= 1000)
@@ -51,10 +51,10 @@ select:hover,button:hover{background:#475569}
51
51
  <body>
52
52
  <div id="toolbar">
53
53
  <span id="t-title">\u29e1 KGraph \u00b7 ${repoName}</span>
54
- <span id="t-stats">${meta.fileCount} files &middot; ${meta.symbolCount} symbols &middot; ${meta.cognitionCount} notes &middot; ~${meta.tokenEstimate} tokens</span>
54
+ <span id="t-stats">${meta.fileCount} files &middot; ${meta.symbolCount} symbols &middot; ${meta.atomCount} atoms${meta.hiddenAtomCount ? ' (' + meta.hiddenAtomCount + ' hidden)' : ''} &middot; ~${meta.tokenEstimate} tokens</span>
55
55
  <div id="t-controls">
56
56
  <label class="clabel"><input type="checkbox" id="tog-lbl" checked> Labels</label>
57
- <label class="clabel"><input type="checkbox" id="tog-cog" checked> Cognition</label>
57
+ <label class="clabel"><input type="checkbox" id="tog-cog" checked> Memory</label>
58
58
  <select id="sel-layout" title="Graph layout algorithm">
59
59
  <option value="dagre">Hierarchical</option>
60
60
  <option value="cose">Force-directed</option>
@@ -85,9 +85,9 @@ select:hover,button:hover{background:#475569}
85
85
  <span class="li"><span class="li-dot" style="background:#475569"></span>200+ tok</span>
86
86
  <span class="li"><span class="li-dot" style="background:#ef4444"></span>1000+ tok</span>
87
87
  <span class="li-sep"></span>
88
- <span class="li-head">Cognition</span>
89
- <span class="li"><span class="li-dia" style="background:#10b981"></span>Current</span>
90
- <span class="li"><span class="li-dia" style="background:#f59e0b"></span>Mixed</span>
88
+ <span class="li-head">Atoms</span>
89
+ <span class="li"><span class="li-dia" style="background:#10b981"></span>Active</span>
90
+ <span class="li"><span class="li-dia" style="background:#f59e0b"></span>Review</span>
91
91
  <span class="li"><span class="li-dia" style="background:#ef4444"></span>Stale</span>
92
92
  <span class="li-sep"></span>
93
93
  <span class="li" style="margin-left:auto;color:#334155;font-size:10px">KGraph v${meta.generatedAt.slice(0, 10)}</span>
@@ -166,7 +166,7 @@ select:hover,button:hover{background:#475569}
166
166
  }
167
167
  },
168
168
  {
169
- selector: 'node.cognition',
169
+ selector: 'node.atom',
170
170
  style: {
171
171
  shape: 'diamond',
172
172
  width: 40,
@@ -212,7 +212,7 @@ select:hover,button:hover{background:#475569}
212
212
  }
213
213
  },
214
214
  {
215
- selector: 'edge.cognition-ref',
215
+ selector: 'edge.atom-ref',
216
216
  style: {
217
217
  width: 1.5,
218
218
  'line-color': '#7dd3fc',
@@ -267,25 +267,32 @@ select:hover,button:hover{background:#475569}
267
267
  symHtml;
268
268
  }
269
269
 
270
- function renderCognitionPanel(d) {
271
- var sc = { current: '#10b981', mixed: '#f59e0b', stale: '#ef4444', unresolved: '#6b7280' }[d.referencesStatus] || '#6b7280';
270
+ function renderAtomPanel(d) {
271
+ var sc = { active: '#10b981', 'needs-review': '#f59e0b', stale: '#ef4444', archived: '#6b7280' }[d.status] || '#6b7280';
272
272
  var files = d.relatedFiles && d.relatedFiles.length
273
273
  ? '<ul class="sb-list">' + d.relatedFiles.map(function (f) { return '<li>' + esc(f) + '</li>'; }).join('') + '</ul>'
274
274
  : '<span class="sb-val">none</span>';
275
275
  var syms = d.relatedSymbols && d.relatedSymbols.length
276
276
  ? d.relatedSymbols.slice(0, 15).map(function (s) { return '<span class="sb-code">' + esc(s) + '</span>'; }).join(' ')
277
277
  : '<span class="sb-val">none</span>';
278
- return '<div class="sb-badge" style="background:' + sc + '22;color:' + sc + ';border:1px solid ' + sc + '44">' + esc(d.referencesStatus) + '</div>' +
278
+ var invalidated = d.invalidatedBy && d.invalidatedBy.length
279
+ ? '<div class="sb-sect"><div class="sb-lbl">Invalidated By</div><ul class="sb-list">' + d.invalidatedBy.map(function (r) { return '<li>' + esc(r) + '</li>'; }).join('') + '</ul></div>'
280
+ : '';
281
+ return '<div class="sb-badge" style="background:' + sc + '22;color:' + sc + ';border:1px solid ' + sc + '44">' + esc(d.status) + '</div>' +
279
282
  '<div class="sb-title">' + esc(d.label) + '</div>' +
283
+ '<div class="sb-sect"><div class="sb-lbl">Atom</div><div class="sb-val"><span class="sb-code">' + esc(d.atomId) + '</span></div></div>' +
284
+ '<div class="sb-sect"><div class="sb-lbl">Type / Confidence</div><div class="sb-val">' + esc(d.atomType) + ' / ' + esc(d.confidence) + '</div></div>' +
285
+ '<div class="sb-sect"><div class="sb-lbl">Source</div><div class="sb-val">' + esc(d.sourceCommand) + '</div></div>' +
280
286
  (d.domain ? '<div class="sb-sect"><div class="sb-lbl">Domain</div><div class="sb-val">' + esc(d.domain) + '</div></div>' : '') +
281
287
  '<div class="sb-sect"><div class="sb-lbl">Related Files</div>' + files + '</div>' +
282
- '<div class="sb-sect"><div class="sb-lbl">Symbols</div><div class="sb-val">' + syms + '</div></div>';
288
+ '<div class="sb-sect"><div class="sb-lbl">Symbols</div><div class="sb-val">' + syms + '</div></div>' +
289
+ invalidated;
283
290
  }
284
291
 
285
292
  cy.on('tap', 'node', function (evt) {
286
293
  var d = evt.target.data();
287
- document.getElementById('sb-type').textContent = d.type === 'cognition' ? 'Cognition Note' : 'File';
288
- document.getElementById('sb-body').innerHTML = d.type === 'cognition' ? renderCognitionPanel(d) : renderFilePanel(d);
294
+ document.getElementById('sb-type').textContent = d.type === 'atom' ? 'Knowledge Atom' : 'File';
295
+ document.getElementById('sb-body').innerHTML = d.type === 'atom' ? renderAtomPanel(d) : renderFilePanel(d);
289
296
  document.getElementById('sidebar').classList.add('open');
290
297
  });
291
298
 
@@ -305,11 +312,11 @@ select:hover,button:hover{background:#475569}
305
312
 
306
313
  document.getElementById('tog-cog').addEventListener('change', function (e) {
307
314
  if (e.target.checked) {
308
- cy.nodes('.cognition').removeClass('hidden');
309
- cy.edges('.cognition-ref').removeClass('hidden');
315
+ cy.nodes('.atom').removeClass('hidden');
316
+ cy.edges('.atom-ref').removeClass('hidden');
310
317
  } else {
311
- cy.nodes('.cognition').addClass('hidden');
312
- cy.edges('.cognition-ref').addClass('hidden');
318
+ cy.nodes('.atom').addClass('hidden');
319
+ cy.edges('.atom-ref').addClass('hidden');
313
320
  }
314
321
  });
315
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kentwynn/kgraph",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "Persistent repo intelligence for AI coding assistants.",
5
5
  "type": "module",
6
6
  "bin": {