@kentwynn/kgraph 0.1.13 → 0.1.15
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/dist/cognition/cognition-updater.d.ts +6 -6
- package/dist/cognition/cognition-updater.js +45 -20
- package/dist/cognition/markdown-note-parser.js +7 -18
- package/dist/integrations/adapters/claude-code.js +1 -1
- package/dist/integrations/adapters/codex.js +1 -1
- package/dist/integrations/adapters/copilot.js +1 -1
- package/dist/integrations/adapters/cursor.js +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import type { ScanResult } from
|
|
1
|
+
import type { CognitionNote, ReferenceStatus } from '../types/cognition.js';
|
|
2
|
+
import type { KGraphWorkspace } from '../types/config.js';
|
|
3
|
+
import type { ScanResult } from '../types/maps.js';
|
|
4
4
|
export interface UpdateResult {
|
|
5
5
|
processed: CognitionNote[];
|
|
6
6
|
warnings: string[];
|
|
7
7
|
}
|
|
8
|
-
export declare function updateCognition(workspace: KGraphWorkspace, currentMaps: Pick<ScanResult,
|
|
9
|
-
export declare function refreshCognitionReferenceStatuses(workspace: KGraphWorkspace, currentMaps: Pick<ScanResult,
|
|
10
|
-
export declare function evaluateReferenceStatus(relatedFiles: string[], relatedSymbols: string[], currentMaps: Pick<ScanResult,
|
|
8
|
+
export declare function updateCognition(workspace: KGraphWorkspace, currentMaps: Pick<ScanResult, 'files' | 'symbols'>, dryRun?: boolean): Promise<UpdateResult>;
|
|
9
|
+
export declare function refreshCognitionReferenceStatuses(workspace: KGraphWorkspace, currentMaps: Pick<ScanResult, 'files' | 'symbols'>): Promise<void>;
|
|
10
|
+
export declare function evaluateReferenceStatus(relatedFiles: string[], relatedSymbols: string[], currentMaps: Pick<ScanResult, 'files' | 'symbols'>): ReferenceStatus;
|
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
import { readFile } from
|
|
2
|
-
import path from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { archiveInboxNote, listInboxNotes, readCognitionNotes, slugify, writeCognitionNote, writeDomainRecord, } from '../storage/cognition-store.js';
|
|
4
|
+
import { parseMarkdownNote } from './markdown-note-parser.js';
|
|
5
5
|
export async function updateCognition(workspace, currentMaps, dryRun = false) {
|
|
6
6
|
const inboxNotes = await listInboxNotes(workspace);
|
|
7
7
|
const processed = [];
|
|
8
8
|
const warnings = [];
|
|
9
9
|
for (const inboxPath of inboxNotes) {
|
|
10
10
|
try {
|
|
11
|
-
const raw = await readFile(inboxPath,
|
|
11
|
+
const raw = await readFile(inboxPath, 'utf8');
|
|
12
12
|
const parsed = parseMarkdownNote(raw);
|
|
13
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g,
|
|
14
|
-
const id = `${timestamp}-${slugify(parsed.title) || path.basename(inboxPath,
|
|
13
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
14
|
+
const id = `${timestamp}-${slugify(parsed.title) || path.basename(inboxPath, '.md')}`;
|
|
15
15
|
const archivedPath = path.join(workspace.processedInteractionsPath, `${timestamp}-${path.basename(inboxPath)}`);
|
|
16
16
|
const note = {
|
|
17
17
|
...parsed,
|
|
18
18
|
id,
|
|
19
|
-
sourceInboxPath: path
|
|
20
|
-
|
|
19
|
+
sourceInboxPath: path
|
|
20
|
+
.relative(workspace.rootPath, inboxPath)
|
|
21
|
+
.split(path.sep)
|
|
22
|
+
.join('/'),
|
|
23
|
+
processedPath: path
|
|
24
|
+
.relative(workspace.rootPath, archivedPath)
|
|
25
|
+
.split(path.sep)
|
|
26
|
+
.join('/'),
|
|
21
27
|
createdAt: new Date().toISOString(),
|
|
22
|
-
referencesStatus: evaluateReferenceStatus(parsed.relatedFiles, parsed.relatedSymbols, currentMaps)
|
|
28
|
+
referencesStatus: evaluateReferenceStatus(parsed.relatedFiles, parsed.relatedSymbols, currentMaps),
|
|
23
29
|
};
|
|
24
30
|
processed.push(note);
|
|
25
31
|
warnings.push(...parsed.warnings.map((warning) => `${path.basename(inboxPath)}: ${warning}`));
|
|
@@ -38,9 +44,28 @@ export async function updateCognition(workspace, currentMaps, dryRun = false) {
|
|
|
38
44
|
export async function refreshCognitionReferenceStatuses(workspace, currentMaps) {
|
|
39
45
|
const notes = await readCognitionNotes(workspace);
|
|
40
46
|
for (const note of notes) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
// Re-parse relatedSymbols from the archived raw markdown if available.
|
|
48
|
+
// This migrates old notes that were parsed with the old plain-text heuristic
|
|
49
|
+
// (which produced false positives like JWT, CSRF, TODO) to the current
|
|
50
|
+
// backtick-only logic.
|
|
51
|
+
let relatedSymbols = note.relatedSymbols;
|
|
52
|
+
if (note.processedPath) {
|
|
53
|
+
try {
|
|
54
|
+
const raw = await readFile(path.join(workspace.rootPath, note.processedPath), 'utf8');
|
|
55
|
+
relatedSymbols = parseMarkdownNote(raw).relatedSymbols;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// archived file missing — keep stored symbols
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const nextStatus = evaluateReferenceStatus(note.relatedFiles, relatedSymbols, currentMaps);
|
|
62
|
+
if (nextStatus !== note.referencesStatus ||
|
|
63
|
+
relatedSymbols !== note.relatedSymbols) {
|
|
64
|
+
await writeCognitionNote(workspace, {
|
|
65
|
+
...note,
|
|
66
|
+
relatedSymbols,
|
|
67
|
+
referencesStatus: nextStatus,
|
|
68
|
+
});
|
|
44
69
|
}
|
|
45
70
|
}
|
|
46
71
|
}
|
|
@@ -49,21 +74,21 @@ export function evaluateReferenceStatus(relatedFiles, relatedSymbols, currentMap
|
|
|
49
74
|
const symbolNames = new Set(currentMaps.symbols.map((symbol) => symbol.name));
|
|
50
75
|
const references = [
|
|
51
76
|
...relatedFiles.map((file) => filePaths.has(file)),
|
|
52
|
-
...relatedSymbols.map((symbol) => symbolNames.has(symbol))
|
|
77
|
+
...relatedSymbols.map((symbol) => symbolNames.has(symbol)),
|
|
53
78
|
];
|
|
54
79
|
if (references.length === 0) {
|
|
55
|
-
return
|
|
80
|
+
return 'unresolved';
|
|
56
81
|
}
|
|
57
82
|
if (references.every(Boolean)) {
|
|
58
|
-
return
|
|
83
|
+
return 'current';
|
|
59
84
|
}
|
|
60
85
|
if (references.every((value) => !value)) {
|
|
61
|
-
return
|
|
86
|
+
return 'stale';
|
|
62
87
|
}
|
|
63
|
-
return
|
|
88
|
+
return 'mixed';
|
|
64
89
|
}
|
|
65
90
|
function toDomainRecord(note, currentMaps) {
|
|
66
|
-
const name = note.domain ??
|
|
91
|
+
const name = note.domain ?? 'general';
|
|
67
92
|
const fileSet = new Set(currentMaps.files.map((file) => file.path));
|
|
68
93
|
const symbolSet = new Set(currentMaps.symbols.map((symbol) => symbol.name));
|
|
69
94
|
return {
|
|
@@ -72,6 +97,6 @@ function toDomainRecord(note, currentMaps) {
|
|
|
72
97
|
tags: note.tags,
|
|
73
98
|
files: note.relatedFiles.filter((file) => fileSet.has(file)),
|
|
74
99
|
symbols: note.relatedSymbols.filter((symbol) => symbolSet.has(symbol)),
|
|
75
|
-
cognitionNotes: [note.id]
|
|
100
|
+
cognitionNotes: [note.id],
|
|
76
101
|
};
|
|
77
102
|
}
|
|
@@ -14,7 +14,7 @@ export function parseMarkdownNote(markdown) {
|
|
|
14
14
|
summary: sections.Summary,
|
|
15
15
|
sections,
|
|
16
16
|
relatedFiles: unique(extractMatches(combined, PATH_REF)),
|
|
17
|
-
relatedSymbols: unique(extractSymbolRefs(
|
|
17
|
+
relatedSymbols: unique(extractSymbolRefs(sections)),
|
|
18
18
|
warnings,
|
|
19
19
|
};
|
|
20
20
|
}
|
|
@@ -59,23 +59,12 @@ function parseSections(body) {
|
|
|
59
59
|
function extractMatches(text, regex) {
|
|
60
60
|
return [...text.matchAll(regex)].map((match) => match[1]);
|
|
61
61
|
}
|
|
62
|
-
function extractSymbolRefs(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'Decisions',
|
|
69
|
-
'Debugging',
|
|
70
|
-
'Conclusions',
|
|
71
|
-
]);
|
|
72
|
-
// Backtick-quoted: accept any identifier in backticks
|
|
73
|
-
const backtickSymbols = [...text.matchAll(/`([A-Za-z_$][\w$]{2,})`/g)].map((m) => m[1]);
|
|
74
|
-
// Plain text: only camelCase, PascalCase, ALL_CAPS, or snake_case (must contain uppercase or underscore after first char)
|
|
75
|
-
const plainSymbols = [...text.matchAll(/\b([A-Za-z_$][\w$]{2,})\b/g)]
|
|
76
|
-
.map((m) => m[1])
|
|
77
|
-
.filter((item) => /[A-Z_]/.test(item.slice(1)));
|
|
78
|
-
return unique([...backtickSymbols, ...plainSymbols].filter((item) => !stopwords.has(item) && !item.includes('.')));
|
|
62
|
+
function extractSymbolRefs(sections) {
|
|
63
|
+
// Prefer declared symbols in the Key Symbols section; fall back to backtick
|
|
64
|
+
// items across all sections. Never use plain-text heuristics — they produce
|
|
65
|
+
// false positives for domain vocabulary like JWT, CSRF, TODO, Next, etc.
|
|
66
|
+
const text = sections['Key Symbols'] ?? Object.values(sections).join('\n');
|
|
67
|
+
return [...text.matchAll(/`([A-Za-z_$][\w$]{2,})`/g)].map((m) => m[1]);
|
|
79
68
|
}
|
|
80
69
|
function unique(items) {
|
|
81
70
|
return [...new Set(items)];
|
|
@@ -14,7 +14,7 @@ Before exploring the repository, run \`kgraph context "<topic>"\` to load existi
|
|
|
14
14
|
1. Infer the topic from the user's request.
|
|
15
15
|
2. Run \`kgraph context "<topic>"\`.
|
|
16
16
|
3. Use the returned files, symbols, relationships, and cognition before broad exploration.
|
|
17
|
-
4. **After completing the work**,
|
|
17
|
+
4. **After completing the work**, write a Markdown note to \`.kgraph/inbox/<slug>.md\` **only if** you discovered something a future session would need to re-derive — a gotcha, constraint, non-obvious decision, or bug. Skip capture for read-only reviews or sessions where nothing new was found. When you do capture, immediately run \`kgraph update\`.
|
|
18
18
|
5. If you created, moved, deleted, or renamed files or symbols during this session, run \`kgraph scan\` and report the summary. Skip it otherwise.
|
|
19
19
|
6. Run \`kgraph visualize\` when the user wants to inspect the dependency graph — opens an interactive graph at http://localhost:4242 with PNG export.
|
|
20
20
|
7. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|
|
@@ -21,7 +21,7 @@ Workflow:
|
|
|
21
21
|
1. Infer the current topic from the user request.
|
|
22
22
|
2. Run \`kgraph context "<topic>"\` before broad repo exploration.
|
|
23
23
|
3. Use KGraph's returned files, symbols, relationships, and cognition as navigation hints.
|
|
24
|
-
4. **After completing the work**,
|
|
24
|
+
4. **After completing the work**, write a Markdown note to \`.kgraph/inbox/<slug>.md\` **only if** you discovered something a future session would need to re-derive — a gotcha, constraint, non-obvious decision, or bug. Skip capture for read-only reviews or sessions where nothing new was found. When you do capture, immediately run \`kgraph update\`.
|
|
25
25
|
5. If you created, moved, deleted, or renamed files or symbols during this session, run \`kgraph scan\`. Skip it otherwise.
|
|
26
26
|
6. Run \`kgraph visualize\` when the user wants to inspect the dependency graph — opens an interactive graph at http://localhost:4242 with PNG export.
|
|
27
27
|
7. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|
|
@@ -5,7 +5,7 @@ export const copilotAdapter = {
|
|
|
5
5
|
instructions: `## KGraph Workflow
|
|
6
6
|
|
|
7
7
|
1. **Before exploring the repository**, run \`kgraph context "<topic>"\` to load existing repo intelligence. Use the returned files, symbols, and cognition before any broad exploration.
|
|
8
|
-
2. **After
|
|
8
|
+
2. **After completing work**, write a Markdown note to \`.kgraph/inbox/<slug>.md\` **only if** you discovered something a future session would need to re-derive — a gotcha, architectural constraint, non-obvious decision, or bug. For routine or read-only sessions where nothing new was found, skip capture entirely. When you do capture, immediately run \`kgraph update\`.
|
|
9
9
|
3. If you created, moved, deleted, or renamed files or symbols, run \`kgraph scan\`.
|
|
10
10
|
|
|
11
11
|
The inbox note must use this structure:
|
|
@@ -10,7 +10,7 @@ alwaysApply: true
|
|
|
10
10
|
## KGraph Workflow
|
|
11
11
|
|
|
12
12
|
- **Before exploring the repository**, run \`kgraph context "<topic>"\` to load existing repo intelligence. Use the returned files, symbols, and cognition before any broad exploration.
|
|
13
|
-
- **After
|
|
13
|
+
- **After completing work**, write a Markdown note to \`.kgraph/inbox/<slug>.md\` (title, Key Files, Key Symbols, Decisions sections) **only if** you discovered something a future session would need to re-derive — a gotcha, constraint, non-obvious decision, or bug. Skip capture for read-only reviews or sessions where nothing new was found. When you do capture, immediately run \`kgraph update\`.
|
|
14
14
|
- If you created, moved, deleted, or renamed files or symbols, run \`kgraph scan\`.
|
|
15
15
|
- Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
|
|
16
16
|
- Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|