@kentwynn/kgraph 0.1.17 → 0.1.19
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/README.md +23 -1
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +31 -3
- package/dist/cli/commands/repair.d.ts +2 -0
- package/dist/cli/commands/repair.js +31 -0
- package/dist/cli/commands/workflow.js +13 -3
- package/dist/cli/help.d.ts +7 -0
- package/dist/cli/help.js +24 -0
- package/dist/cli/index.js +2 -0
- package/dist/cognition/cognition-quality.d.ts +25 -0
- package/dist/cognition/cognition-quality.js +111 -0
- package/dist/integrations/adapters/claude-code.js +18 -10
- package/dist/integrations/adapters/codex.js +12 -9
- package/dist/integrations/adapters/copilot.js +22 -7
- package/dist/integrations/adapters/cursor.js +6 -3
- package/dist/scanner/ts-symbol-extractor.js +6 -0
- package/dist/storage/cognition-store.d.ts +1 -0
- package/dist/storage/cognition-store.js +6 -0
- package/dist/types/maps.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -100,6 +100,17 @@ kgraph doctor
|
|
|
100
100
|
|
|
101
101
|
After useful AI work, assistants can save durable notes into `.kgraph/inbox/`. The next `kgraph` run processes those notes automatically. You can also process them directly with `kgraph update`.
|
|
102
102
|
|
|
103
|
+
Normal agent flow is intentionally small:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
kgraph "topic"
|
|
107
|
+
# work normally
|
|
108
|
+
# if repo files changed, write an inbox note when the change has future value
|
|
109
|
+
kgraph
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use `kgraph doctor --quality` and `kgraph repair --dry-run` only when stale or noisy cognition references start making context harder to trust.
|
|
113
|
+
|
|
103
114
|
## Main Commands
|
|
104
115
|
|
|
105
116
|
```bash
|
|
@@ -128,9 +139,17 @@ Refreshes maps and cognition without returning topic-specific context.
|
|
|
128
139
|
|
|
129
140
|
```bash
|
|
130
141
|
kgraph doctor
|
|
142
|
+
kgraph doctor --quality
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Checks whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files. Use `--quality` when context shows stale/noisy cognition references.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
kgraph repair --dry-run
|
|
149
|
+
kgraph repair
|
|
131
150
|
```
|
|
132
151
|
|
|
133
|
-
|
|
152
|
+
`repair --dry-run` previews cleanup for noisy cognition references, such as framework names recorded as files or local variables recorded as symbols. `repair` applies that cleanup. Run repair intentionally when stale references make context noisy; it is not part of every normal workflow.
|
|
134
153
|
|
|
135
154
|
## Optional Step Commands
|
|
136
155
|
|
|
@@ -255,6 +274,8 @@ Run the local TypeScript CLI without installing globally:
|
|
|
255
274
|
npm run kgraph -- init
|
|
256
275
|
npm run kgraph -- "auth token refresh"
|
|
257
276
|
npm run kgraph -- doctor
|
|
277
|
+
npm run kgraph -- doctor --quality
|
|
278
|
+
npm run kgraph -- repair --dry-run
|
|
258
279
|
```
|
|
259
280
|
|
|
260
281
|
Test the built package as a global local install:
|
|
@@ -265,6 +286,7 @@ npm install -g .
|
|
|
265
286
|
kgraph --version
|
|
266
287
|
kgraph doctor
|
|
267
288
|
kgraph "auth token refresh"
|
|
289
|
+
kgraph repair --dry-run
|
|
268
290
|
```
|
|
269
291
|
|
|
270
292
|
Package checks:
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
|
+
import { type CognitionQualityReport } from '../../cognition/cognition-quality.js';
|
|
2
3
|
export declare function registerDoctorCommand(program: Command): void;
|
|
4
|
+
export declare function printQualityReport(report: CognitionQualityReport): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readdir } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { analyzeCognitionQuality, } from '../../cognition/cognition-quality.js';
|
|
3
4
|
import { loadConfig } from '../../config/config.js';
|
|
4
5
|
import { listIntegrations } from '../../integrations/integration-store.js';
|
|
5
6
|
import { assertWorkspace, pathExists, resolveWorkspace, } from '../../storage/kgraph-paths.js';
|
|
@@ -9,7 +10,8 @@ export function registerDoctorCommand(program) {
|
|
|
9
10
|
program
|
|
10
11
|
.command('doctor')
|
|
11
12
|
.description('Check KGraph workspace health and next actions')
|
|
12
|
-
.
|
|
13
|
+
.option('--quality', 'Report stale or noisy cognition references')
|
|
14
|
+
.action((options) => runCommand(async () => {
|
|
13
15
|
const rootPath = process.cwd();
|
|
14
16
|
const workspace = resolveWorkspace(rootPath);
|
|
15
17
|
const checks = [];
|
|
@@ -37,8 +39,8 @@ export function registerDoctorCommand(program) {
|
|
|
37
39
|
ok: mapStatus,
|
|
38
40
|
detail: mapStatus ? 'structural maps are present' : 'run `kgraph scan` or just `kgraph`',
|
|
39
41
|
});
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
const maps = mapStatus ? await readMaps(workspace) : undefined;
|
|
43
|
+
if (maps) {
|
|
42
44
|
checks.push({
|
|
43
45
|
label: 'scan result',
|
|
44
46
|
ok: true,
|
|
@@ -79,6 +81,12 @@ export function registerDoctorCommand(program) {
|
|
|
79
81
|
.join('; '),
|
|
80
82
|
});
|
|
81
83
|
printChecks(checks);
|
|
84
|
+
if (options.quality && maps) {
|
|
85
|
+
console.log('');
|
|
86
|
+
console.log('KGraph Cognition Quality');
|
|
87
|
+
console.log('');
|
|
88
|
+
printQualityReport(await analyzeCognitionQuality(workspace, maps));
|
|
89
|
+
}
|
|
82
90
|
if (checks.some((check) => !check.ok)) {
|
|
83
91
|
process.exitCode = 1;
|
|
84
92
|
}
|
|
@@ -98,3 +106,23 @@ function printChecks(checks) {
|
|
|
98
106
|
console.log(`${check.ok ? 'OK' : 'FAIL'} ${check.label}: ${check.detail}`);
|
|
99
107
|
}
|
|
100
108
|
}
|
|
109
|
+
export function printQualityReport(report) {
|
|
110
|
+
console.log(`Notes: ${report.noteCount}`);
|
|
111
|
+
console.log(`Mixed/stale/unresolved notes: ${report.mixedOrStaleCount}`);
|
|
112
|
+
console.log(`Noisy file refs: ${report.noisyFileRefCount}`);
|
|
113
|
+
console.log(`Noisy symbol refs: ${report.noisySymbolRefCount}`);
|
|
114
|
+
if (report.changes.length === 0) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
console.log('');
|
|
118
|
+
for (const change of report.changes) {
|
|
119
|
+
console.log(`- ${change.title}`);
|
|
120
|
+
for (const ref of change.removedFileRefs) {
|
|
121
|
+
console.log(` remove file ref: ${ref}`);
|
|
122
|
+
}
|
|
123
|
+
for (const ref of change.removedSymbolRefs) {
|
|
124
|
+
console.log(` remove symbol ref: ${ref}`);
|
|
125
|
+
}
|
|
126
|
+
console.log(` next status: ${change.nextStatus}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { repairCognition } from '../../cognition/cognition-quality.js';
|
|
2
|
+
import { assertWorkspace } from '../../storage/kgraph-paths.js';
|
|
3
|
+
import { mapsExist, readMaps } from '../../storage/map-store.js';
|
|
4
|
+
import { KGraphError, runCommand } from '../errors.js';
|
|
5
|
+
import { printQualityReport } from './doctor.js';
|
|
6
|
+
export function registerRepairCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('repair')
|
|
9
|
+
.description('Clean noisy stale references from KGraph cognition')
|
|
10
|
+
.option('--dry-run', 'Show proposed cognition cleanup without writing files')
|
|
11
|
+
.action((options) => runCommand(async () => {
|
|
12
|
+
const workspace = await assertWorkspace(process.cwd());
|
|
13
|
+
if (!(await mapsExist(workspace))) {
|
|
14
|
+
throw new KGraphError('KGraph maps are missing. Run `kgraph scan` first.');
|
|
15
|
+
}
|
|
16
|
+
const maps = await readMaps(workspace);
|
|
17
|
+
const report = await repairCognition(workspace, maps, Boolean(options.dryRun));
|
|
18
|
+
console.log(options.dryRun
|
|
19
|
+
? 'KGraph Repair Dry Run'
|
|
20
|
+
: 'KGraph Repair');
|
|
21
|
+
console.log('');
|
|
22
|
+
printQualityReport(report);
|
|
23
|
+
if (report.changes.length === 0) {
|
|
24
|
+
console.log('No noisy cognition references found.');
|
|
25
|
+
}
|
|
26
|
+
else if (options.dryRun) {
|
|
27
|
+
console.log('');
|
|
28
|
+
console.log('Run `kgraph repair` to apply these changes.');
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
@@ -3,13 +3,19 @@ import { refreshCognitionReferenceStatuses } from '../../cognition/cognition-upd
|
|
|
3
3
|
import { loadConfig } from '../../config/config.js';
|
|
4
4
|
import { queryContext } from '../../context/context-query.js';
|
|
5
5
|
import { scanRepository } from '../../scanner/repo-scanner.js';
|
|
6
|
-
import { assertWorkspace } from '../../storage/kgraph-paths.js';
|
|
6
|
+
import { assertWorkspace, pathExists, resolveWorkspace, } from '../../storage/kgraph-paths.js';
|
|
7
7
|
import { readMaps, writeMaps } from '../../storage/map-store.js';
|
|
8
8
|
import { runCommand } from '../errors.js';
|
|
9
|
+
import { renderRootHelp, renderWorkflowBanner } from '../help.js';
|
|
9
10
|
import { renderContextMarkdown } from './context.js';
|
|
10
11
|
export async function runDefaultWorkflow(query) {
|
|
11
12
|
await runCommand(async () => {
|
|
12
13
|
const topic = query?.trim();
|
|
14
|
+
const candidateWorkspace = resolveWorkspace(process.cwd());
|
|
15
|
+
if (!topic && !(await pathExists(candidateWorkspace.kgraphPath))) {
|
|
16
|
+
console.log(renderRootHelp());
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
13
19
|
const workspace = await assertWorkspace(process.cwd());
|
|
14
20
|
const config = await loadConfig(workspace);
|
|
15
21
|
const previousMaps = await readMaps(workspace);
|
|
@@ -26,12 +32,16 @@ export async function runDefaultWorkflow(query) {
|
|
|
26
32
|
symbols: scan.symbols,
|
|
27
33
|
});
|
|
28
34
|
const update = await updateCognition(workspace, { files: scan.files, symbols: scan.symbols }, false);
|
|
29
|
-
console.log(
|
|
35
|
+
console.log(renderWorkflowBanner({
|
|
36
|
+
files: scan.files.length,
|
|
37
|
+
symbols: scan.symbols.length,
|
|
38
|
+
cognitionNotes: update.processed.length,
|
|
39
|
+
}));
|
|
40
|
+
console.log('');
|
|
30
41
|
for (const warning of [...scan.warnings, ...update.warnings]) {
|
|
31
42
|
console.warn(`Warning: ${warning}`);
|
|
32
43
|
}
|
|
33
44
|
if (!topic) {
|
|
34
|
-
console.log('Add a topic to return compact context, for example: kgraph "auth token refresh"');
|
|
35
45
|
return;
|
|
36
46
|
}
|
|
37
47
|
const maps = await readMaps(workspace);
|
package/dist/cli/help.d.ts
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
1
|
export declare function renderRootHelp(useColor?: boolean): string;
|
|
2
|
+
interface WorkflowBannerStats {
|
|
3
|
+
files: number;
|
|
4
|
+
symbols: number;
|
|
5
|
+
cognitionNotes: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function renderWorkflowBanner(stats: WorkflowBannerStats, useColor?: boolean): string;
|
|
8
|
+
export {};
|
package/dist/cli/help.js
CHANGED
|
@@ -30,6 +30,9 @@ export function renderRootHelp(useColor = supportsColor()) {
|
|
|
30
30
|
command('context "auth token refresh"', 'Optional: return context without scanning or updating'),
|
|
31
31
|
command('update', 'Optional: process only .kgraph/inbox Markdown cognition notes'),
|
|
32
32
|
command('doctor', 'Check workspace health and next actions'),
|
|
33
|
+
command('doctor --quality', 'Report stale/noisy cognition references'),
|
|
34
|
+
command('repair --dry-run', 'Preview cognition reference cleanup'),
|
|
35
|
+
command('repair', 'Clean noisy stale cognition references'),
|
|
33
36
|
command('visualize', 'Interactive dependency graph at http://localhost:4242'),
|
|
34
37
|
command('history', 'Timeline of processed cognition sessions'),
|
|
35
38
|
'',
|
|
@@ -51,6 +54,27 @@ export function renderRootHelp(useColor = supportsColor()) {
|
|
|
51
54
|
'',
|
|
52
55
|
].join('\n');
|
|
53
56
|
}
|
|
57
|
+
export function renderWorkflowBanner(stats, useColor = supportsColor()) {
|
|
58
|
+
const theme = new Chalk({ level: useColor ? 3 : 0 });
|
|
59
|
+
const command = (name, description) => ` ${theme.green(name.padEnd(30))} ${description}`;
|
|
60
|
+
return [
|
|
61
|
+
'',
|
|
62
|
+
theme.hex('#7dd3fc').bold(renderLogo()),
|
|
63
|
+
'',
|
|
64
|
+
` ${theme.bold('KGraph')} ${theme.dim('repo intelligence refreshed')}`,
|
|
65
|
+
'',
|
|
66
|
+
theme.bold('Refresh Complete'),
|
|
67
|
+
command('files', String(stats.files)),
|
|
68
|
+
command('symbols', String(stats.symbols)),
|
|
69
|
+
command('cognition notes processed', String(stats.cognitionNotes)),
|
|
70
|
+
'',
|
|
71
|
+
theme.bold('Next'),
|
|
72
|
+
command('kgraph "auth token refresh"', 'Return compact context for a topic'),
|
|
73
|
+
command('kgraph doctor', 'Check workspace health'),
|
|
74
|
+
command('kgraph doctor --quality', 'Check cognition quality'),
|
|
75
|
+
command('kgraph --help', 'Show all commands'),
|
|
76
|
+
].join('\n');
|
|
77
|
+
}
|
|
54
78
|
function renderLogo() {
|
|
55
79
|
try {
|
|
56
80
|
return figlet.textSync('KGraph', {
|
package/dist/cli/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { registerDoctorCommand } from './commands/doctor.js';
|
|
|
8
8
|
import { registerHistoryCommand } from './commands/history.js';
|
|
9
9
|
import { registerInitCommand } from './commands/init.js';
|
|
10
10
|
import { registerIntegrateCommand } from './commands/integrate.js';
|
|
11
|
+
import { registerRepairCommand } from './commands/repair.js';
|
|
11
12
|
import { registerScanCommand } from './commands/scan.js';
|
|
12
13
|
import { registerUpdateCommand } from './commands/update.js';
|
|
13
14
|
import { registerVisualizeCommand } from './commands/visualize.js';
|
|
@@ -42,6 +43,7 @@ export function createProgram() {
|
|
|
42
43
|
registerVisualizeCommand(program);
|
|
43
44
|
registerHistoryCommand(program);
|
|
44
45
|
registerDoctorCommand(program);
|
|
46
|
+
registerRepairCommand(program);
|
|
45
47
|
return program;
|
|
46
48
|
}
|
|
47
49
|
if (isCliEntrypoint()) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { KGraphWorkspace } from '../types/config.js';
|
|
2
|
+
import type { ReferenceStatus } from '../types/cognition.js';
|
|
3
|
+
import type { FileMap, SymbolMap } from '../types/maps.js';
|
|
4
|
+
export interface CognitionRepairChange {
|
|
5
|
+
noteId: string;
|
|
6
|
+
title: string;
|
|
7
|
+
removedFileRefs: string[];
|
|
8
|
+
removedSymbolRefs: string[];
|
|
9
|
+
nextStatus: ReferenceStatus;
|
|
10
|
+
}
|
|
11
|
+
export interface CognitionQualityReport {
|
|
12
|
+
noteCount: number;
|
|
13
|
+
mixedOrStaleCount: number;
|
|
14
|
+
noisyFileRefCount: number;
|
|
15
|
+
noisySymbolRefCount: number;
|
|
16
|
+
changes: CognitionRepairChange[];
|
|
17
|
+
}
|
|
18
|
+
export declare function analyzeCognitionQuality(workspace: KGraphWorkspace, maps: {
|
|
19
|
+
fileMap: FileMap;
|
|
20
|
+
symbolMap: SymbolMap;
|
|
21
|
+
}): Promise<CognitionQualityReport>;
|
|
22
|
+
export declare function repairCognition(workspace: KGraphWorkspace, maps: {
|
|
23
|
+
fileMap: FileMap;
|
|
24
|
+
symbolMap: SymbolMap;
|
|
25
|
+
}, dryRun?: boolean): Promise<CognitionQualityReport>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { overwriteDomainRecord, readCognitionNotes, readDomainRecords, writeCognitionNote, } from '../storage/cognition-store.js';
|
|
2
|
+
export async function analyzeCognitionQuality(workspace, maps) {
|
|
3
|
+
const notes = await readCognitionNotes(workspace);
|
|
4
|
+
const changes = notes
|
|
5
|
+
.map((note) => analyzeNote(note, maps))
|
|
6
|
+
.filter((change) => change.removedFileRefs.length > 0 ||
|
|
7
|
+
change.removedSymbolRefs.length > 0);
|
|
8
|
+
return {
|
|
9
|
+
noteCount: notes.length,
|
|
10
|
+
mixedOrStaleCount: notes.filter((note) => ['mixed', 'stale', 'unresolved'].includes(note.referencesStatus)).length,
|
|
11
|
+
noisyFileRefCount: changes.reduce((total, change) => total + change.removedFileRefs.length, 0),
|
|
12
|
+
noisySymbolRefCount: changes.reduce((total, change) => total + change.removedSymbolRefs.length, 0),
|
|
13
|
+
changes,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export async function repairCognition(workspace, maps, dryRun = false) {
|
|
17
|
+
const notes = await readCognitionNotes(workspace);
|
|
18
|
+
const nextNotes = [];
|
|
19
|
+
const changes = [];
|
|
20
|
+
for (const note of notes) {
|
|
21
|
+
const change = analyzeNote(note, maps);
|
|
22
|
+
const nextNote = applyChange(note, change);
|
|
23
|
+
nextNotes.push(nextNote);
|
|
24
|
+
if (change.removedFileRefs.length > 0 ||
|
|
25
|
+
change.removedSymbolRefs.length > 0) {
|
|
26
|
+
changes.push(change);
|
|
27
|
+
if (!dryRun) {
|
|
28
|
+
await writeCognitionNote(workspace, nextNote);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!dryRun && changes.length > 0) {
|
|
33
|
+
await repairDomainRecords(workspace, nextNotes, maps);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
noteCount: notes.length,
|
|
37
|
+
mixedOrStaleCount: nextNotes.filter((note) => ['mixed', 'stale', 'unresolved'].includes(note.referencesStatus)).length,
|
|
38
|
+
noisyFileRefCount: changes.reduce((total, change) => total + change.removedFileRefs.length, 0),
|
|
39
|
+
noisySymbolRefCount: changes.reduce((total, change) => total + change.removedSymbolRefs.length, 0),
|
|
40
|
+
changes,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function analyzeNote(note, maps) {
|
|
44
|
+
const filePaths = new Set(maps.fileMap.files.map((file) => file.path));
|
|
45
|
+
const symbolNames = new Set(maps.symbolMap.symbols.map((symbol) => symbol.name));
|
|
46
|
+
const removedFileRefs = note.relatedFiles.filter((ref) => !filePaths.has(ref) && isNoisyFileRef(ref));
|
|
47
|
+
const removedSymbolRefs = note.relatedSymbols.filter((ref) => !symbolNames.has(ref) && isNoisySymbolRef(ref));
|
|
48
|
+
const nextFiles = note.relatedFiles.filter((ref) => !removedFileRefs.includes(ref));
|
|
49
|
+
const nextSymbols = note.relatedSymbols.filter((ref) => !removedSymbolRefs.includes(ref));
|
|
50
|
+
return {
|
|
51
|
+
noteId: note.id,
|
|
52
|
+
title: note.title,
|
|
53
|
+
removedFileRefs,
|
|
54
|
+
removedSymbolRefs,
|
|
55
|
+
nextStatus: evaluateReferenceStatus(nextFiles, nextSymbols, maps),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function applyChange(note, change) {
|
|
59
|
+
return {
|
|
60
|
+
...note,
|
|
61
|
+
relatedFiles: note.relatedFiles.filter((ref) => !change.removedFileRefs.includes(ref)),
|
|
62
|
+
relatedSymbols: note.relatedSymbols.filter((ref) => !change.removedSymbolRefs.includes(ref)),
|
|
63
|
+
referencesStatus: change.nextStatus,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async function repairDomainRecords(workspace, notes, maps) {
|
|
67
|
+
const domains = await readDomainRecords(workspace);
|
|
68
|
+
const filePaths = new Set(maps.fileMap.files.map((file) => file.path));
|
|
69
|
+
const symbolNames = new Set(maps.symbolMap.symbols.map((symbol) => symbol.name));
|
|
70
|
+
const notesById = new Map(notes.map((note) => [note.id, note]));
|
|
71
|
+
for (const domain of domains) {
|
|
72
|
+
const relatedNotes = domain.cognitionNotes
|
|
73
|
+
.map((id) => notesById.get(id))
|
|
74
|
+
.filter((note) => Boolean(note));
|
|
75
|
+
const next = {
|
|
76
|
+
...domain,
|
|
77
|
+
pathHints: unique(relatedNotes.flatMap((note) => note.relatedFiles)),
|
|
78
|
+
files: unique(relatedNotes
|
|
79
|
+
.flatMap((note) => note.relatedFiles)
|
|
80
|
+
.filter((file) => filePaths.has(file))),
|
|
81
|
+
symbols: unique(relatedNotes
|
|
82
|
+
.flatMap((note) => note.relatedSymbols)
|
|
83
|
+
.filter((symbol) => symbolNames.has(symbol))),
|
|
84
|
+
};
|
|
85
|
+
await overwriteDomainRecord(workspace, next);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function evaluateReferenceStatus(relatedFiles, relatedSymbols, maps) {
|
|
89
|
+
const filePaths = new Set(maps.fileMap.files.map((file) => file.path));
|
|
90
|
+
const symbolNames = new Set(maps.symbolMap.symbols.map((symbol) => symbol.name));
|
|
91
|
+
const references = [
|
|
92
|
+
...relatedFiles.map((file) => filePaths.has(file)),
|
|
93
|
+
...relatedSymbols.map((symbol) => symbolNames.has(symbol)),
|
|
94
|
+
];
|
|
95
|
+
if (references.length === 0)
|
|
96
|
+
return 'unresolved';
|
|
97
|
+
if (references.every(Boolean))
|
|
98
|
+
return 'current';
|
|
99
|
+
if (references.every((value) => !value))
|
|
100
|
+
return 'stale';
|
|
101
|
+
return 'mixed';
|
|
102
|
+
}
|
|
103
|
+
function isNoisyFileRef(ref) {
|
|
104
|
+
return !ref.includes('/') && /^[A-Z][A-Za-z0-9_-]*\.[A-Za-z0-9_-]+$/.test(ref);
|
|
105
|
+
}
|
|
106
|
+
function isNoisySymbolRef(ref) {
|
|
107
|
+
return /^[a-z][A-Za-z0-9_$]*$/.test(ref);
|
|
108
|
+
}
|
|
109
|
+
function unique(items) {
|
|
110
|
+
return [...new Set(items)];
|
|
111
|
+
}
|
|
@@ -14,33 +14,41 @@ Before exploring the repository, run \`kgraph "<topic>"\` to refresh repo intell
|
|
|
14
14
|
1. Infer the topic from the user's request.
|
|
15
15
|
2. Run \`kgraph "<topic>"\`. This refreshes maps, processes pending inbox notes, and returns focused context in one command.
|
|
16
16
|
3. Use the returned files, symbols, relationships, and cognition before broad exploration.
|
|
17
|
-
4. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong.
|
|
18
|
-
5.
|
|
19
|
-
6. If
|
|
20
|
-
7.
|
|
21
|
-
8. Run \`kgraph
|
|
17
|
+
4. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
|
|
18
|
+
5. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
|
|
19
|
+
6. If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
|
|
20
|
+
7. Skip capture only for read-only work, trivial formatting, typo-only docs, dependency-only churn, mechanical cleanup with no future value, or sessions where no repo files changed.
|
|
21
|
+
8. Do not run KGraph repeatedly. Run it once at the start with \`kgraph "<topic>"\`. If repo files changed, write any needed inbox note first, then run \`kgraph\` once at the end.
|
|
22
|
+
9. Run \`kgraph repair --dry-run\` before cleanup when stale/noisy cognition needs fixing. Run \`kgraph repair\` only when the user asks to apply that cleanup.
|
|
23
|
+
10. Run \`kgraph visualize\` when the user wants to inspect the dependency graph — opens an interactive graph at http://localhost:4242 with PNG export.
|
|
24
|
+
11. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|
|
22
25
|
|
|
23
26
|
The inbox note must use this structure:
|
|
24
27
|
\`\`\`markdown
|
|
25
28
|
# <Short Title>
|
|
26
29
|
|
|
27
30
|
## Summary
|
|
28
|
-
One or two sentences describing
|
|
31
|
+
One or two sentences describing the durable change or finding.
|
|
29
32
|
|
|
30
33
|
## Key Files
|
|
31
|
-
- \`path/to/file.ts\` — what it
|
|
34
|
+
- \`path/to/file.ts\` — what changed or why it matters
|
|
32
35
|
|
|
33
36
|
## Key Symbols
|
|
34
|
-
- \`FunctionName\` — what it
|
|
37
|
+
- \`FunctionName\` — what changed or why it matters
|
|
35
38
|
|
|
36
39
|
## Decisions
|
|
37
|
-
Any
|
|
40
|
+
Any implementation or product decision future sessions should know.
|
|
38
41
|
\`\`\`
|
|
39
42
|
`,
|
|
40
43
|
},
|
|
41
44
|
{
|
|
42
45
|
path: '.claude/commands/kgraph-doctor.md',
|
|
43
|
-
content: `Run \`kgraph doctor\` to check whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files. Summarize any failed checks and the next command to run.
|
|
46
|
+
content: `Run \`kgraph doctor\` to check whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files. Use \`kgraph doctor --quality\` when the user asks about stale or noisy cognition references. Summarize any failed checks and the next command to run.
|
|
47
|
+
`,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
path: '.claude/commands/kgraph-repair.md',
|
|
51
|
+
content: `Run \`kgraph repair --dry-run\` first and summarize the proposed cognition cleanup. Run \`kgraph repair\` only when the user asks to apply the cleanup.
|
|
44
52
|
`,
|
|
45
53
|
},
|
|
46
54
|
{
|
|
@@ -21,27 +21,30 @@ Workflow:
|
|
|
21
21
|
1. Infer the current topic from the user request.
|
|
22
22
|
2. Run \`kgraph "<topic>"\` before broad repo exploration. This refreshes maps, processes pending inbox notes, and returns focused context in one command.
|
|
23
23
|
3. Use KGraph's returned files, symbols, relationships, and cognition as navigation hints.
|
|
24
|
-
4. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong.
|
|
25
|
-
5.
|
|
26
|
-
6. If
|
|
27
|
-
7.
|
|
28
|
-
8. Run \`kgraph
|
|
24
|
+
4. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
|
|
25
|
+
5. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
|
|
26
|
+
6. If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
|
|
27
|
+
7. Skip capture only for read-only work, trivial formatting, typo-only docs, dependency-only churn, mechanical cleanup with no future value, or sessions where no repo files changed.
|
|
28
|
+
8. Do not run KGraph repeatedly. Run it once at the start with \`kgraph "<topic>"\`. If repo files changed, write any needed inbox note first, then run \`kgraph\` once at the end.
|
|
29
|
+
9. Run \`kgraph repair --dry-run\` before cleanup when stale/noisy cognition needs fixing. Run \`kgraph repair\` only when the user asks to apply that cleanup.
|
|
30
|
+
10. Run \`kgraph visualize\` when the user wants to inspect the dependency graph — opens an interactive graph at http://localhost:4242 with PNG export.
|
|
31
|
+
11. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|
|
29
32
|
|
|
30
33
|
The inbox note must use this structure:
|
|
31
34
|
\`\`\`markdown
|
|
32
35
|
# <Short Title>
|
|
33
36
|
|
|
34
37
|
## Summary
|
|
35
|
-
One or two sentences describing
|
|
38
|
+
One or two sentences describing the durable change or finding.
|
|
36
39
|
|
|
37
40
|
## Key Files
|
|
38
|
-
- \`path/to/file.ts\` — what it
|
|
41
|
+
- \`path/to/file.ts\` — what changed or why it matters
|
|
39
42
|
|
|
40
43
|
## Key Symbols
|
|
41
|
-
- \`FunctionName\` — what it
|
|
44
|
+
- \`FunctionName\` — what changed or why it matters
|
|
42
45
|
|
|
43
46
|
## Decisions
|
|
44
|
-
Any
|
|
47
|
+
Any implementation or product decision future sessions should know.
|
|
45
48
|
\`\`\`
|
|
46
49
|
`,
|
|
47
50
|
},
|
|
@@ -5,9 +5,12 @@ export const copilotAdapter = {
|
|
|
5
5
|
instructions: `## KGraph Workflow
|
|
6
6
|
|
|
7
7
|
1. **Before exploring the repository**, run \`kgraph "<topic>"\` to refresh maps, process pending inbox notes, and load focused repo intelligence. Use the returned files, symbols, relationships, and cognition before any broad exploration.
|
|
8
|
-
2. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong.
|
|
9
|
-
3.
|
|
10
|
-
4. If
|
|
8
|
+
2. Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
|
|
9
|
+
3. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
|
|
10
|
+
4. If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
|
|
11
|
+
5. Skip capture only for read-only work, trivial formatting, typo-only docs, dependency-only churn, mechanical cleanup with no future value, or sessions where no repo files changed.
|
|
12
|
+
6. Do not run KGraph repeatedly. Run it once at the start with \`kgraph "<topic>"\`. If repo files changed, write any needed inbox note first, then run \`kgraph\` once at the end.
|
|
13
|
+
7. Run \`kgraph repair --dry-run\` before cleanup when stale/noisy cognition needs fixing. Run \`kgraph repair\` only when the user asks to apply that cleanup.
|
|
11
14
|
|
|
12
15
|
The inbox note must use this structure:
|
|
13
16
|
\`\`\`markdown
|
|
@@ -34,7 +37,18 @@ description: Check KGraph workspace health and next actions
|
|
|
34
37
|
agent: agent
|
|
35
38
|
---
|
|
36
39
|
|
|
37
|
-
Run \`kgraph doctor\` to check whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files. Summarize any failed checks and the next command to run.
|
|
40
|
+
Run \`kgraph doctor\` to check whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files. Use \`kgraph doctor --quality\` when the user asks about stale or noisy cognition references. Summarize any failed checks and the next command to run.
|
|
41
|
+
`,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
path: '.github/prompts/kgraph-repair.prompt.md',
|
|
45
|
+
content: `---
|
|
46
|
+
description: Preview or clean stale/noisy KGraph cognition references
|
|
47
|
+
agent: agent
|
|
48
|
+
argument-hint: "--dry-run or apply"
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
Run \`kgraph repair --dry-run\` first and summarize the proposed cognition cleanup. Run \`kgraph repair\` only when the user asks to apply the cleanup.
|
|
38
52
|
`,
|
|
39
53
|
},
|
|
40
54
|
{
|
|
@@ -77,9 +91,10 @@ argument-hint: "Brief description of what was done"
|
|
|
77
91
|
|
|
78
92
|
Capture this session into KGraph cognition.
|
|
79
93
|
|
|
80
|
-
1.
|
|
81
|
-
2.
|
|
82
|
-
3.
|
|
94
|
+
1. For any completed code or repo-file change, check whether it has future value before finishing.
|
|
95
|
+
2. Skip capture only for read-only work, trivial formatting, typo-only docs, dependency-only churn, mechanical cleanup with no future value, or sessions where no repo files changed.
|
|
96
|
+
3. Write one Markdown note to \`.kgraph/inbox/<slug>.md\` using the structure below. Use the user's message as context, but keep the note factual and concise.
|
|
97
|
+
4. Run \`kgraph\` once to process the note and refresh maps. Use \`kgraph update\` only when you intentionally want inbox processing without a scan.
|
|
83
98
|
|
|
84
99
|
Note structure:
|
|
85
100
|
\`\`\`markdown
|
|
@@ -10,9 +10,12 @@ alwaysApply: true
|
|
|
10
10
|
## KGraph Workflow
|
|
11
11
|
|
|
12
12
|
- **Before exploring the repository**, run \`kgraph "<topic>"\` to refresh maps, process pending inbox notes, and load focused repo intelligence. Use the returned files, symbols, relationships, and cognition before any broad exploration.
|
|
13
|
-
- Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong.
|
|
14
|
-
-
|
|
15
|
-
- If
|
|
13
|
+
- Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
|
|
14
|
+
- At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
|
|
15
|
+
- If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
|
|
16
|
+
- Skip capture only for read-only work, trivial formatting, typo-only docs, dependency-only churn, mechanical cleanup with no future value, or sessions where no repo files changed.
|
|
17
|
+
- Do not run KGraph repeatedly. Run it once at the start with \`kgraph "<topic>"\`. If repo files changed, write any needed inbox note first, then run \`kgraph\` once at the end.
|
|
18
|
+
- Run \`kgraph repair --dry-run\` before cleanup when stale/noisy cognition needs fixing. Run \`kgraph repair\` only when the user asks to apply that cleanup.
|
|
16
19
|
- Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
|
|
17
20
|
- Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
|
|
18
21
|
`,
|
|
@@ -73,6 +73,12 @@ export function extractTsSymbols(sourceText, filePath) {
|
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
+
if (ts.isInterfaceDeclaration(node)) {
|
|
77
|
+
addSymbol(node.name.text, "interface", node, isExported(node), parentName);
|
|
78
|
+
}
|
|
79
|
+
if (ts.isTypeAliasDeclaration(node)) {
|
|
80
|
+
addSymbol(node.name.text, "type", node, isExported(node), parentName);
|
|
81
|
+
}
|
|
76
82
|
ts.forEachChild(node, (child) => visit(child, parentName));
|
|
77
83
|
};
|
|
78
84
|
try {
|
|
@@ -4,6 +4,7 @@ export declare function listInboxNotes(workspace: KGraphWorkspace): Promise<stri
|
|
|
4
4
|
export declare function archiveInboxNote(workspace: KGraphWorkspace, inboxPath: string, timestamp: string): Promise<string>;
|
|
5
5
|
export declare function writeCognitionNote(workspace: KGraphWorkspace, note: CognitionNote): Promise<string>;
|
|
6
6
|
export declare function writeDomainRecord(workspace: KGraphWorkspace, domain: DomainRecord): Promise<string>;
|
|
7
|
+
export declare function overwriteDomainRecord(workspace: KGraphWorkspace, domain: DomainRecord): Promise<string>;
|
|
7
8
|
export declare function readCognitionNotes(workspace: KGraphWorkspace): Promise<CognitionNote[]>;
|
|
8
9
|
export declare function readDomainRecords(workspace: KGraphWorkspace): Promise<DomainRecord[]>;
|
|
9
10
|
export declare function slugify(value: string): string;
|
|
@@ -33,6 +33,12 @@ export async function writeDomainRecord(workspace, domain) {
|
|
|
33
33
|
await writeFile(filePath, renderDomainRecord(merged), "utf8");
|
|
34
34
|
return filePath;
|
|
35
35
|
}
|
|
36
|
+
export async function overwriteDomainRecord(workspace, domain) {
|
|
37
|
+
await mkdir(workspace.domainsPath, { recursive: true });
|
|
38
|
+
const filePath = path.join(workspace.domainsPath, `${slugify(domain.name)}.md`);
|
|
39
|
+
await writeFile(filePath, renderDomainRecord(domain), "utf8");
|
|
40
|
+
return filePath;
|
|
41
|
+
}
|
|
36
42
|
export async function readCognitionNotes(workspace) {
|
|
37
43
|
if (!(await pathExists(workspace.cognitionPath))) {
|
|
38
44
|
return [];
|
package/dist/types/maps.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type ScanStatus = "mapped" | "generic" | "failed";
|
|
2
2
|
export type DependencyKind = "local" | "package" | "unknown";
|
|
3
|
-
export type SymbolKind = "function" | "class" | "method" | "export" | "import";
|
|
3
|
+
export type SymbolKind = "function" | "class" | "method" | "type" | "interface" | "export" | "import";
|
|
4
4
|
export type RelationshipType = "import" | "contains" | "mentions" | "belongs-to-domain" | "stale-reference" | "moved-from";
|
|
5
5
|
export interface RepositoryFile {
|
|
6
6
|
id: string;
|