@kentwynn/kgraph 0.1.18 → 0.1.20

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Persistent repository intelligence for AI coding tools.
4
4
 
5
- KGraph gives Codex, GitHub Copilot, Cursor, and Claude Code a local knowledge layer for your repo: file maps, symbols, imports, relationships, and durable notes from previous AI sessions. The goal is simple: your assistant should not spend every session re-learning the same codebase.
5
+ KGraph gives Codex, GitHub Copilot, Cursor, Claude Code, Gemini CLI, Windsurf, and Cline a local knowledge layer for your repo: file maps, symbols, imports, relationships, and durable notes from previous AI sessions. The goal is simple: your assistant should not spend every session re-learning the same codebase.
6
6
 
7
7
  ## The Workflow
8
8
 
@@ -10,7 +10,7 @@ Use KGraph in two steps:
10
10
 
11
11
  ```bash
12
12
  # Required once per repository
13
- kgraph init --integrations codex,copilot,cursor,claude-code
13
+ kgraph init --integrations codex,copilot,cursor,claude-code,gemini,windsurf,cline
14
14
 
15
15
  # Normal daily command
16
16
  kgraph "auth token refresh"
@@ -89,7 +89,7 @@ From the root of a repository:
89
89
  kgraph init
90
90
 
91
91
  # 2. Optional: connect AI tools so they know the KGraph workflow
92
- kgraph integrate add codex copilot cursor claude-code
92
+ kgraph integrate add codex copilot cursor claude-code gemini windsurf cline
93
93
 
94
94
  # 3. Run the normal workflow for a topic
95
95
  kgraph "auth token refresh"
@@ -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
@@ -109,7 +120,7 @@ kgraph init
109
120
  Required once per repo. Creates `.kgraph/` and the local config.
110
121
 
111
122
  ```bash
112
- kgraph init --integrations codex,copilot,cursor,claude-code
123
+ kgraph init --integrations codex,copilot,cursor,claude-code,gemini,windsurf,cline
113
124
  ```
114
125
 
115
126
  Initializes KGraph and writes local instruction files for supported AI tools.
@@ -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
131
143
  ```
132
144
 
133
- Checks whether the workspace is initialized, maps exist, inbox notes are pending, and configured integrations point to real files.
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
150
+ ```
151
+
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
 
@@ -177,7 +196,7 @@ Show processed cognition sessions.
177
196
  KGraph integrations are local files. They do not start background agents, call AI providers, or send data anywhere.
178
197
 
179
198
  ```bash
180
- kgraph integrate add codex copilot cursor claude-code
199
+ kgraph integrate add codex copilot cursor claude-code gemini windsurf cline
181
200
  kgraph integrate list
182
201
  kgraph integrate remove cursor
183
202
  ```
@@ -188,6 +207,11 @@ kgraph integrate remove cursor
188
207
  | GitHub Copilot | `.github/copilot-instructions.md`, `.github/prompts/*` |
189
208
  | Cursor | `.cursor/rules/kgraph.mdc` |
190
209
  | Claude Code | `CLAUDE.md`, `.claude/commands/*` |
210
+ | Gemini CLI | `GEMINI.md` |
211
+ | Windsurf | `.windsurf/rules/kgraph.md` |
212
+ | Cline | `.clinerules/kgraph.md` |
213
+
214
+ Antigravity is supported through the existing agent instruction surfaces it can read, especially `AGENTS.md` and `GEMINI.md`; it does not need a separate KGraph adapter yet.
191
215
 
192
216
  KGraph preserves existing user-authored content and updates only its marked instruction blocks or generated command files.
193
217
 
@@ -255,6 +279,8 @@ Run the local TypeScript CLI without installing globally:
255
279
  npm run kgraph -- init
256
280
  npm run kgraph -- "auth token refresh"
257
281
  npm run kgraph -- doctor
282
+ npm run kgraph -- doctor --quality
283
+ npm run kgraph -- repair --dry-run
258
284
  ```
259
285
 
260
286
  Test the built package as a global local install:
@@ -265,6 +291,7 @@ npm install -g .
265
291
  kgraph --version
266
292
  kgraph doctor
267
293
  kgraph "auth token refresh"
294
+ kgraph repair --dry-run
268
295
  ```
269
296
 
270
297
  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
- .action(() => runCommand(async () => {
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
- if (mapStatus) {
41
- const maps = await readMaps(workspace);
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,2 @@
1
+ import type { Command } from 'commander';
2
+ export declare function registerRepairCommand(program: Command): void;
@@ -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(`KGraph refreshed ${scan.files.length} files, ${scan.symbols.length} symbols, and ${update.processed.length} cognition notes.`);
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);
@@ -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
@@ -2,7 +2,7 @@ import { Chalk } from 'chalk';
2
2
  import figlet from 'figlet';
3
3
  export function renderRootHelp(useColor = supportsColor()) {
4
4
  const theme = new Chalk({ level: useColor ? 3 : 0 });
5
- const command = (name, description) => ` ${theme.green(name.padEnd(30))} ${description}`;
5
+ const command = (name, description) => ` ${theme.green(name.padEnd(42))} ${description}`;
6
6
  const logo = renderLogo();
7
7
  return [
8
8
  '',
@@ -11,7 +11,7 @@ export function renderRootHelp(useColor = supportsColor()) {
11
11
  ` ${theme.bold('KGraph')} ${theme.dim('Persistent repo intelligence for AI coding tools')}`,
12
12
  '',
13
13
  ` ${theme.hex('#c084fc')('Build a local knowledge layer that helps Codex, Copilot, Cursor,')}`,
14
- ` ${theme.hex('#c084fc')('and Claude Code reuse repo structure, decisions, and debugging history.')}`,
14
+ ` ${theme.hex('#c084fc')('Claude Code, Gemini, Windsurf, and Cline reuse repo intelligence.')}`,
15
15
  '',
16
16
  theme.bold('Usage'),
17
17
  ' kgraph [topic]',
@@ -19,7 +19,7 @@ export function renderRootHelp(useColor = supportsColor()) {
19
19
  '',
20
20
  theme.bold('Start'),
21
21
  command('init', 'Required once: create .kgraph/ workspace'),
22
- command('init --integrations codex,cursor', 'Initialize and connect AI tools'),
22
+ command('init --integrations codex,gemini', 'Initialize and connect AI tools'),
23
23
  '',
24
24
  theme.bold('Daily workflow'),
25
25
  command('kgraph', 'Refresh scan maps and process pending cognition notes'),
@@ -30,12 +30,15 @@ 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
  '',
36
39
  theme.bold('Integrations'),
37
40
  command('integrate list', 'Show configured AI tool integrations'),
38
- command('integrate add codex copilot', 'Write KGraph instructions for AI tools'),
41
+ command('integrate add gemini windsurf cline', 'Write KGraph instructions for AI tools'),
39
42
  command('integrate remove cursor', 'Remove KGraph-managed instruction blocks'),
40
43
  '',
41
44
  theme.bold('Options'),
@@ -43,7 +46,7 @@ export function renderRootHelp(useColor = supportsColor()) {
43
46
  command('-h, --help', 'Show this help'),
44
47
  '',
45
48
  `${theme.yellow('Examples')}`,
46
- ' kgraph init --integrations codex,copilot,cursor',
49
+ ' kgraph init --integrations codex,copilot,cursor,claude-code,gemini,windsurf,cline',
47
50
  ' kgraph "blog admin token usage"',
48
51
  ' kgraph doctor',
49
52
  '',
@@ -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(42))} ${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
+ }
@@ -25,10 +25,13 @@ export const DEFAULT_CONFIG = {
25
25
  'specs',
26
26
  '.cursor',
27
27
  '.claude',
28
+ '.windsurf',
29
+ '.clinerules',
28
30
  '.github/copilot-instructions.md',
29
31
  '.github/prompts',
30
32
  'AGENTS.md',
31
33
  'CLAUDE.md',
34
+ 'GEMINI.md',
32
35
  'REQUIREMENTS.md',
33
36
  '*.log',
34
37
  '*.tgz',
@@ -132,7 +135,15 @@ function normalizeIntegrations(value) {
132
135
  seen.has(candidate.name)) {
133
136
  continue;
134
137
  }
135
- if (!['claude-code', 'codex', 'copilot', 'cursor'].includes(candidate.name)) {
138
+ if (![
139
+ 'claude-code',
140
+ 'cline',
141
+ 'codex',
142
+ 'copilot',
143
+ 'cursor',
144
+ 'gemini',
145
+ 'windsurf',
146
+ ].includes(candidate.name)) {
136
147
  continue;
137
148
  }
138
149
  seen.add(candidate.name);
@@ -14,13 +14,14 @@ 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.
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
18
  5. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
19
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
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
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 visualize\` when the user wants to inspect the dependency graph opens an interactive graph at http://localhost:4242 with PNG export.
23
- 10. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
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.
24
25
 
25
26
  The inbox note must use this structure:
26
27
  \`\`\`markdown
@@ -42,7 +43,12 @@ Any implementation or product decision future sessions should know.
42
43
  },
43
44
  {
44
45
  path: '.claude/commands/kgraph-doctor.md',
45
- 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.
46
52
  `,
47
53
  },
48
54
  {
@@ -0,0 +1,2 @@
1
+ import type { IntegrationAdapter } from '../integration-registry.js';
2
+ export declare const clineAdapter: IntegrationAdapter;
@@ -0,0 +1,17 @@
1
+ export const clineAdapter = {
2
+ name: 'cline',
3
+ label: 'Cline',
4
+ targetPath: '.clinerules/kgraph.md',
5
+ instructions: `# KGraph Workflow
6
+
7
+ - **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
+ - Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
9
+ - At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
10
+ - If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
11
+ - 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
+ - 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
+ - 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.
14
+ - Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
15
+ - Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
16
+ `,
17
+ };
@@ -21,13 +21,14 @@ 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.
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
25
  5. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
26
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
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
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 visualize\` when the user wants to inspect the dependency graph opens an interactive graph at http://localhost:4242 with PNG export.
30
- 10. Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
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.
31
32
 
32
33
  The inbox note must use this structure:
33
34
  \`\`\`markdown
@@ -5,11 +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.
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
9
  3. At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
10
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
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
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.
13
14
 
14
15
  The inbox note must use this structure:
15
16
  \`\`\`markdown
@@ -36,7 +37,18 @@ description: Check KGraph workspace health and next actions
36
37
  agent: agent
37
38
  ---
38
39
 
39
- 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.
40
52
  `,
41
53
  },
42
54
  {
@@ -10,11 +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.
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
14
  - At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
15
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
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
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.
18
19
  - Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
19
20
  - Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
20
21
  `,
@@ -0,0 +1,2 @@
1
+ import type { IntegrationAdapter } from '../integration-registry.js';
2
+ export declare const geminiAdapter: IntegrationAdapter;
@@ -0,0 +1,17 @@
1
+ export const geminiAdapter = {
2
+ name: 'gemini',
3
+ label: 'Gemini CLI',
4
+ targetPath: 'GEMINI.md',
5
+ instructions: `## KGraph Workflow
6
+
7
+ - **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
+ - Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
9
+ - At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
10
+ - If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
11
+ - 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
+ - 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
+ - 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.
14
+ - Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
15
+ - Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
16
+ `,
17
+ };
@@ -0,0 +1,2 @@
1
+ import type { IntegrationAdapter } from '../integration-registry.js';
2
+ export declare const windsurfAdapter: IntegrationAdapter;
@@ -0,0 +1,17 @@
1
+ export const windsurfAdapter = {
2
+ name: 'windsurf',
3
+ label: 'Windsurf',
4
+ targetPath: '.windsurf/rules/kgraph.md',
5
+ instructions: `# KGraph Workflow
6
+
7
+ - **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
+ - Run \`kgraph doctor\` when setup, maps, inbox processing, or integrations look wrong. Run \`kgraph doctor --quality\` when context shows stale/noisy cognition references.
9
+ - At the end of any session that changed repository files, check the KGraph capture workflow before finishing.
10
+ - If the file change has future value, write one concise Markdown note to \`.kgraph/inbox/<slug>.md\`; otherwise explicitly skip capture as trivial.
11
+ - 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
+ - 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
+ - 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.
14
+ - Run \`kgraph visualize\` to open the interactive dependency graph at http://localhost:4242 with PNG export.
15
+ - Run \`kgraph history\` to review the timeline of past cognition sessions with git author attribution.
16
+ `,
17
+ };
@@ -1,12 +1,18 @@
1
1
  import { claudeCodeAdapter } from "./adapters/claude-code.js";
2
+ import { clineAdapter } from "./adapters/cline.js";
2
3
  import { codexAdapter } from "./adapters/codex.js";
3
4
  import { copilotAdapter } from "./adapters/copilot.js";
4
5
  import { cursorAdapter } from "./adapters/cursor.js";
6
+ import { geminiAdapter } from "./adapters/gemini.js";
7
+ import { windsurfAdapter } from "./adapters/windsurf.js";
5
8
  const ADAPTERS = [
6
9
  claudeCodeAdapter,
10
+ clineAdapter,
7
11
  codexAdapter,
8
12
  copilotAdapter,
9
- cursorAdapter
13
+ cursorAdapter,
14
+ geminiAdapter,
15
+ windsurfAdapter
10
16
  ].sort((left, right) => left.name.localeCompare(right.name));
11
17
  export function listIntegrationAdapters() {
12
18
  return ADAPTERS;
@@ -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 [];
@@ -12,7 +12,7 @@ export interface DomainHint {
12
12
  paths?: string[];
13
13
  tags?: string[];
14
14
  }
15
- export type IntegrationName = "claude-code" | "codex" | "copilot" | "cursor";
15
+ export type IntegrationName = "claude-code" | "cline" | "codex" | "copilot" | "cursor" | "gemini" | "windsurf";
16
16
  export interface IntegrationConfig {
17
17
  name: IntegrationName;
18
18
  enabled: boolean;
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kentwynn/kgraph",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Persistent repo intelligence for AI coding assistants.",
5
5
  "type": "module",
6
6
  "bin": {