@kentwynn/kgraph 0.2.24 → 0.2.27

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 (35) hide show
  1. package/README.md +6 -5
  2. package/dist/cli/commands/pack.js +25 -1
  3. package/dist/cli/commands/session.js +31 -15
  4. package/dist/cli/commands/workflow.d.ts +1 -0
  5. package/dist/cli/commands/workflow.js +11 -0
  6. package/dist/cli/help.js +2 -0
  7. package/dist/cli/index.js +2 -0
  8. package/dist/grammars/tree-sitter-bash.wasm +0 -0
  9. package/dist/grammars/tree-sitter-c.wasm +0 -0
  10. package/dist/grammars/tree-sitter-c_sharp.wasm +0 -0
  11. package/dist/grammars/tree-sitter-cpp.wasm +0 -0
  12. package/dist/grammars/tree-sitter-css.wasm +0 -0
  13. package/dist/grammars/tree-sitter-dart.wasm +0 -0
  14. package/dist/grammars/tree-sitter-elixir.wasm +0 -0
  15. package/dist/grammars/tree-sitter-go.wasm +0 -0
  16. package/dist/grammars/tree-sitter-html.wasm +0 -0
  17. package/dist/grammars/tree-sitter-java.wasm +0 -0
  18. package/dist/grammars/tree-sitter-json.wasm +0 -0
  19. package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
  20. package/dist/grammars/tree-sitter-lua.wasm +0 -0
  21. package/dist/grammars/tree-sitter-php.wasm +0 -0
  22. package/dist/grammars/tree-sitter-python.wasm +0 -0
  23. package/dist/grammars/tree-sitter-ruby.wasm +0 -0
  24. package/dist/grammars/tree-sitter-rust.wasm +0 -0
  25. package/dist/grammars/tree-sitter-scala.wasm +0 -0
  26. package/dist/grammars/tree-sitter-yaml.wasm +0 -0
  27. package/dist/integrations/adapters/claude-code.js +4 -4
  28. package/dist/integrations/agent-skills.js +5 -2
  29. package/dist/integrations/instruction-blocks.d.ts +3 -3
  30. package/dist/integrations/instruction-blocks.js +19 -10
  31. package/dist/integrations/integration-store.js +2 -2
  32. package/dist/integrations/workflow-steps.js +10 -6
  33. package/dist/scanner/tree-sitter-parser.js +28 -2
  34. package/dist/types/session.d.ts +1 -1
  35. package/package.json +13 -12
package/README.md CHANGED
@@ -168,12 +168,12 @@ Normal agent flow is intentionally small:
168
168
  ```bash
169
169
  kgraph "topic"
170
170
  # work normally
171
- kgraph "topic" --final
171
+ kgraph "topic" --final --agent codex
172
172
  # if final check requires capture:
173
- kgraph "topic" --capture "durable conclusion" --capture-file path/to/file.ts --capture-symbol SymbolName
173
+ kgraph "topic" --capture "durable conclusion" --capture-file path/to/file.ts --capture-symbol SymbolName --agent codex
174
174
  ```
175
175
 
176
- `kgraph "<topic>"` is the smart root workflow: it refreshes maps, processes capture notes, reports memory health, and returns focused context. Agents can still use `kgraph pack "<topic>" --budget 8000 --json` when they need the stable machine-readable `ContextPack` contract with atoms, source ranges, git changes, omitted items, token estimates, and inclusion reasons.
176
+ `kgraph "<topic>"` is the smart root workflow: it refreshes maps, processes capture notes, reports memory health, and returns focused context. Agents can pass `--agent <name>` to record a lightweight session context event. Agents can still use `kgraph pack "<topic>" --budget 8000 --json --agent <name>` when they need the stable machine-readable `ContextPack` contract with atoms, source ranges, git changes, omitted items, token estimates, and inclusion reasons.
177
177
 
178
178
  Use `kgraph doctor` after setup and before trusting a repo's saved intelligence. It checks initialization, maps, pending inbox notes, integration targets, and actionable quality problems. Use `kgraph doctor --quality` and `kgraph repair --dry-run` when stale or noisy atom references start making context harder to trust.
179
179
 
@@ -187,7 +187,7 @@ kgraph session end --agent codex --conclude --topic "auth session work"
187
187
  kgraph session
188
188
  ```
189
189
 
190
- This is optional. Claude Code can use generated hook scripts for automatic capture; other agents use the same commands through their managed instructions, rules, or prompts.
190
+ This is optional for manual read/write tracking. Generated `always` and `smart` workflows use `--agent <name>` on `kgraph pack` and root/final commands to record lightweight session context automatically; Claude Code can also use generated hook scripts for file read/write capture.
191
191
 
192
192
  ## Main Commands
193
193
 
@@ -307,9 +307,10 @@ Refresh atom lifecycle status against the current scan and inspect atom provenan
307
307
  ```bash
308
308
  kgraph pack "auth token refresh" --budget 8000
309
309
  kgraph pack "auth token refresh" --budget 8000 --json
310
+ kgraph pack "auth token refresh" --budget 8000 --json --agent codex
310
311
  ```
311
312
 
312
- Build a budget-aware context pack from files, source ranges, symbols, relationships, git changes, session history, and knowledge atoms. JSON output is the stable machine-readable contract for agents; text output is an Atom Core briefing for humans.
313
+ Build a budget-aware context pack from files, source ranges, symbols, relationships, git changes, session history, and knowledge atoms. Add `--agent <name>` to record a lightweight automatic session context event. JSON output is the stable machine-readable contract for agents; text output is an Atom Core briefing for humans.
313
314
 
314
315
  ```bash
315
316
  kgraph compact --dry-run
@@ -1,6 +1,7 @@
1
1
  import { buildContextPack } from '../../context/context-pack.js';
2
2
  import { queryContext } from '../../context/context-query.js';
3
3
  import { loadConfig } from '../../config/config.js';
4
+ import { assertSessionAgent, recordSessionEvent, } from '../../session/session-store.js';
4
5
  import { assertWorkspace } from '../../storage/kgraph-paths.js';
5
6
  import { mapsExist, readMaps } from '../../storage/map-store.js';
6
7
  import { KGraphError, runCommand } from '../errors.js';
@@ -10,7 +11,8 @@ export function registerPackCommand(program) {
10
11
  .description('Build a budget-aware KGraph context pack for a task')
11
12
  .option('--budget <tokens>', 'Maximum estimated tokens to include', '8000')
12
13
  .option('--json', 'Print JSON output')
13
- .action((task, options) => runCommand(async () => {
14
+ .option('--agent <name>', 'Record an automatic KGraph session context event for this integration agent')
15
+ .action((task, options, command) => runCommand(async () => {
14
16
  if (!task.trim())
15
17
  throw new KGraphError('Task cannot be empty.');
16
18
  const budget = Number.parseInt(options.budget ?? '8000', 10);
@@ -21,6 +23,16 @@ export function registerPackCommand(program) {
21
23
  if (!(await mapsExist(workspace))) {
22
24
  throw new KGraphError('KGraph maps are missing. Run `kgraph scan` first.');
23
25
  }
26
+ const agent = options.agent ??
27
+ command.getOptionValue('agent') ??
28
+ findCommandOption(command, 'agent');
29
+ if (agent) {
30
+ await recordSessionEvent(workspace, {
31
+ agent: assertSessionAgent(agent),
32
+ type: 'context',
33
+ captureSource: 'automatic',
34
+ });
35
+ }
24
36
  const [config, maps] = await Promise.all([
25
37
  loadConfig(workspace),
26
38
  readMaps(workspace),
@@ -34,6 +46,18 @@ export function registerPackCommand(program) {
34
46
  console.log(renderPackText(pack));
35
47
  }));
36
48
  }
49
+ function findCommandOption(command, name) {
50
+ let current = command?.parent;
51
+ while (current) {
52
+ const value = current.getOptionValue(name) ??
53
+ current.opts()[name];
54
+ if (value) {
55
+ return value;
56
+ }
57
+ current = current.parent;
58
+ }
59
+ return undefined;
60
+ }
37
61
  export function renderPackText(pack) {
38
62
  const lines = [
39
63
  `KGraph Pack · ${pack.task}`,
@@ -17,12 +17,12 @@ export function registerSessionCommand(program) {
17
17
  }));
18
18
  session
19
19
  .command('start')
20
- .requiredOption('--agent <name>', 'KGraph integration agent name')
20
+ .option('--agent <name>', 'KGraph integration agent name')
21
21
  .option('--source <source>', 'automatic, agent-reported, or manual', 'manual')
22
- .action((options) => runCommand(async () => {
22
+ .action((options, command) => runCommand(async () => {
23
23
  const workspace = await assertWorkspace(process.cwd());
24
24
  const event = await recordSessionEvent(workspace, {
25
- agent: requireAgent(options.agent),
25
+ agent: requireAgent(options, command),
26
26
  type: 'start',
27
27
  captureSource: normalizeSource(options.source),
28
28
  });
@@ -30,13 +30,13 @@ export function registerSessionCommand(program) {
30
30
  }));
31
31
  session
32
32
  .command('read <path>')
33
- .requiredOption('--agent <name>', 'KGraph integration agent name')
33
+ .option('--agent <name>', 'KGraph integration agent name')
34
34
  .option('--source <source>', 'automatic, agent-reported, or manual', 'manual')
35
- .action((filePath, options) => runCommand(async () => {
35
+ .action((filePath, options, command) => runCommand(async () => {
36
36
  const workspace = await assertWorkspace(process.cwd());
37
37
  const maps = await readMaps(workspace);
38
38
  const event = await recordSessionEvent(workspace, {
39
- agent: requireAgent(options.agent),
39
+ agent: requireAgent(options, command),
40
40
  type: 'read',
41
41
  path: filePath,
42
42
  captureSource: normalizeSource(options.source),
@@ -46,13 +46,13 @@ export function registerSessionCommand(program) {
46
46
  }));
47
47
  session
48
48
  .command('write <path>')
49
- .requiredOption('--agent <name>', 'KGraph integration agent name')
49
+ .option('--agent <name>', 'KGraph integration agent name')
50
50
  .option('--source <source>', 'automatic, agent-reported, or manual', 'manual')
51
- .action((filePath, options) => runCommand(async () => {
51
+ .action((filePath, options, command) => runCommand(async () => {
52
52
  const workspace = await assertWorkspace(process.cwd());
53
53
  const maps = await readMaps(workspace);
54
54
  const event = await recordSessionEvent(workspace, {
55
- agent: requireAgent(options.agent),
55
+ agent: requireAgent(options, command),
56
56
  type: 'write',
57
57
  path: filePath,
58
58
  captureSource: normalizeSource(options.source),
@@ -62,26 +62,27 @@ export function registerSessionCommand(program) {
62
62
  }));
63
63
  session
64
64
  .command('end')
65
- .requiredOption('--agent <name>', 'KGraph integration agent name')
65
+ .option('--agent <name>', 'KGraph integration agent name')
66
66
  .option('--source <source>', 'automatic, agent-reported, or manual', 'manual')
67
67
  .option('--conclude', 'Store a durable typed summary for this session')
68
68
  .option('--topic <topic>', 'Conclusion topic when using --conclude')
69
69
  .option('--type <type>', 'finding, decision, gotcha, summary, or relationship', 'summary')
70
70
  .option('--confidence <level>', 'high, medium, or low', 'medium')
71
71
  .option('--note <text>', 'Concise durable conclusion text')
72
- .action((options) => runCommand(async () => {
72
+ .action((options, command) => runCommand(async () => {
73
73
  const workspace = await assertWorkspace(process.cwd());
74
+ const agent = requireAgent(options, command);
74
75
  let pendingConclusion;
75
76
  if (options.conclude) {
76
- pendingConclusion = await buildActiveSessionConclusion(workspace, requireAgent(options.agent), {
77
- topic: options.topic ?? `${options.agent} session summary`,
77
+ pendingConclusion = await buildActiveSessionConclusion(workspace, agent, {
78
+ topic: options.topic ?? `${agent} session summary`,
78
79
  body: options.note,
79
80
  kind: normalizeKind(options.type),
80
81
  confidence: normalizeConfidence(options.confidence),
81
82
  });
82
83
  }
83
84
  const event = await recordSessionEvent(workspace, {
84
- agent: requireAgent(options.agent),
85
+ agent,
85
86
  type: 'end',
86
87
  captureSource: normalizeSource(options.source),
87
88
  });
@@ -121,12 +122,27 @@ export function renderSessionReport(report) {
121
122
  lines.push(...sessionNextActions(report));
122
123
  return lines.join('\n');
123
124
  }
124
- function requireAgent(value) {
125
+ function requireAgent(options, command) {
126
+ const value = options.agent ??
127
+ command?.getOptionValue('agent') ??
128
+ findCommandOption(command, 'agent');
125
129
  if (!value) {
126
130
  throw new KGraphError('--agent is required.');
127
131
  }
128
132
  return assertSessionAgent(value);
129
133
  }
134
+ function findCommandOption(command, name) {
135
+ let current = command?.parent;
136
+ while (current) {
137
+ const value = current.getOptionValue(name) ??
138
+ current.opts()[name];
139
+ if (value) {
140
+ return value;
141
+ }
142
+ current = current.parent;
143
+ }
144
+ return undefined;
145
+ }
130
146
  function normalizeSource(value) {
131
147
  if (value === 'automatic' || value === 'agent-reported' || value === 'manual') {
132
148
  return value;
@@ -7,5 +7,6 @@ export interface DefaultWorkflowOptions {
7
7
  tags?: string[];
8
8
  files?: string[];
9
9
  symbols?: string[];
10
+ agent?: string;
10
11
  }
11
12
  export declare function runDefaultWorkflow(query?: string, options?: DefaultWorkflowOptions): Promise<void>;
@@ -6,6 +6,7 @@ import { refreshKnowledgeAtomStatuses } from '../../knowledge/atom-store.js';
6
6
  import { getWorkingTreeChanges } from '../../scanner/git-utils.js';
7
7
  import { shouldExclude } from '../../scanner/file-classifier.js';
8
8
  import { scanRepository } from '../../scanner/repo-scanner.js';
9
+ import { assertSessionAgent, recordSessionEvent, } from '../../session/session-store.js';
9
10
  import { listInboxNotes } from '../../storage/cognition-store.js';
10
11
  import { assertWorkspace, pathExists, resolveWorkspace, } from '../../storage/kgraph-paths.js';
11
12
  import { readMaps, writeMaps } from '../../storage/map-store.js';
@@ -23,6 +24,16 @@ export async function runDefaultWorkflow(query, options = {}) {
23
24
  }
24
25
  const workspace = await assertWorkspace(process.cwd());
25
26
  const config = await loadConfig(workspace);
27
+ const sessionAgent = options.agent
28
+ ? assertSessionAgent(options.agent)
29
+ : undefined;
30
+ if (sessionAgent) {
31
+ await recordSessionEvent(workspace, {
32
+ agent: sessionAgent,
33
+ type: 'context',
34
+ captureSource: 'automatic',
35
+ });
36
+ }
26
37
  const previousMaps = await readMaps(workspace);
27
38
  const scan = await scanRepository(workspace.rootPath, config, {
28
39
  files: previousMaps.fileMap.files,
package/dist/cli/help.js CHANGED
@@ -37,6 +37,7 @@ export function renderRootHelp(useColor = supportsColor()) {
37
37
  command('compact', 'Merge duplicate atoms and archive stale noise'),
38
38
  command('knowledge list', 'Inspect canonical knowledge atoms'),
39
39
  command('pack "auth task" --budget 8000', 'Build a budget-aware context pack'),
40
+ command('pack "auth task" --agent codex', 'Record lightweight agent session context while building a pack'),
40
41
  command('stale', 'Show atoms invalidated by changed or missing refs'),
41
42
  command('blame <atom-id>', 'Show atom provenance and evidence'),
42
43
  command('context "auth token refresh"', 'Optional: return context without scanning or updating'),
@@ -66,6 +67,7 @@ export function renderRootHelp(useColor = supportsColor()) {
66
67
  command('--capture <text>', 'Store a durable conclusion in the root workflow'),
67
68
  command('--capture-file <path>', 'Attach file evidence to root capture'),
68
69
  command('--capture-symbol <name>', 'Attach symbol evidence to root capture'),
70
+ command('--agent <name>', 'Record lightweight agent session context'),
69
71
  '',
70
72
  sectionTitle(theme, `${accent} Examples`),
71
73
  ' kgraph init',
package/dist/cli/index.js CHANGED
@@ -39,6 +39,7 @@ export function createProgram() {
39
39
  .option('--capture-tag <tag>', 'Capture tag; repeatable', collect, [])
40
40
  .option('--capture-file <path>', 'Capture related repo file; repeatable', collect, [])
41
41
  .option('--capture-symbol <name>', 'Capture related symbol; repeatable', collect, [])
42
+ .option('--agent <name>', 'Record an automatic KGraph session context event for this integration agent')
42
43
  .version(version)
43
44
  .helpOption(false)
44
45
  .action(async (topicParts = [], options) => {
@@ -51,6 +52,7 @@ export function createProgram() {
51
52
  tags: options.captureTag,
52
53
  files: options.captureFile,
53
54
  symbols: options.captureSymbol,
55
+ agent: options.agent,
54
56
  });
55
57
  });
56
58
  program.option('-h, --help', 'Show this help');
Binary file
@@ -12,16 +12,16 @@ ${numberedWorkflow('claude-code', {
12
12
  commandFiles: [
13
13
  {
14
14
  path: '.claude/commands/kgraph.md',
15
- content: `Use KGraph persistent repo intelligence through the single normal \`kgraph "<topic>"\` entry point.
15
+ content: `Use KGraph persistent repo intelligence through the single normal \`kgraph "<topic>" --agent claude-code\` entry point.
16
16
 
17
17
  1. Infer a concise topic from the user's request.
18
- 2. Run exactly one command from the repository root: \`kgraph "<topic>"\`.
18
+ 2. Run exactly one command from the repository root: \`kgraph "<topic>" --agent claude-code\`.
19
19
  3. Treat the returned files, symbols, relationships, atoms, and warnings as the first-pass source of truth.
20
20
  4. If the user asked for an edit, inspect only the returned candidate file or the smallest necessary range, then make the edit.
21
21
  5. Verify the change actually landed before claiming completion. Prefer a narrow read of the changed range or \`git diff -- <path>\`; if there is no diff or the expected text is missing, say the edit did not apply and fix it before summarizing.
22
22
  6. Do not run \`kgraph\` again, \`kgraph context\`, \`kgraph pack\`, \`kgraph knowledge\`, \`kgraph stale\`, \`kgraph blame\`, \`kgraph scan\`, \`kgraph update\`, \`kgraph compact\`, or \`kgraph repair\` unless the user explicitly asks for that lower-level command.
23
23
  7. Do not continue broad repository search after the target file is identified. If a path must be located, prefer \`rg --files\` and quote paths containing spaces or parentheses.
24
- 8. At the end of repository-file changes, run \`kgraph "<topic>" --final\`. If KGraph reports capture-required, run \`kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name>\`, or explicitly say "No durable knowledge created" only when there is genuinely no reusable knowledge.
24
+ 8. At the end of repository-file changes, run \`kgraph "<topic>" --final --agent claude-code\`. If KGraph reports capture-required, run \`kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name> --agent claude-code\`, or explicitly say "No durable knowledge created" only when there is genuinely no reusable knowledge.
25
25
  `,
26
26
  },
27
27
  {
@@ -41,7 +41,7 @@ ${numberedWorkflow('claude-code', {
41
41
  },
42
42
  {
43
43
  path: '.claude/commands/kgraph-pack.md',
44
- content: `Run \`kgraph pack "$ARGUMENTS" --budget 8000 --json\` to build a machine-readable context pack. Summarize token use, included files, symbols, relationships, git changes, session history, atoms, and omitted items with the inclusion reasons.
44
+ content: `Run \`kgraph pack "$ARGUMENTS" --budget 8000 --json --agent claude-code\` to build a machine-readable context pack and record lightweight session context. Summarize token use, included files, symbols, relationships, git changes, session history, atoms, and omitted items with the inclusion reasons.
45
45
  `,
46
46
  },
47
47
  {
@@ -45,7 +45,7 @@ name: kgraph-pack
45
45
  description: Build a budget-aware KGraph context pack
46
46
  ---
47
47
 
48
- Run \`kgraph pack "$ARGUMENTS" --budget 8000 --json\` to build a machine-readable context pack. Summarize token use, included files, symbols, relationships, git changes, session history, atoms, and omitted items with the inclusion reasons.
48
+ Run \`kgraph pack "$ARGUMENTS" --budget 8000 --json --agent $AGENT\` to build a machine-readable context pack and record lightweight session context. Summarize token use, included files, symbols, relationships, git changes, session history, atoms, and omitted items with the inclusion reasons.
49
49
  `,
50
50
  },
51
51
  {
@@ -181,6 +181,9 @@ Workflow:
181
181
  ${numberedWorkflow(agentName)}
182
182
  `,
183
183
  },
184
- ...SHARED_AGENT_SKILLS,
184
+ ...SHARED_AGENT_SKILLS.map((file) => ({
185
+ ...file,
186
+ content: file.content.replaceAll('$AGENT', agentName),
187
+ })),
185
188
  ];
186
189
  }
@@ -3,6 +3,6 @@ export declare const KGRAPH_CONTEXT_POLICY_PLACEHOLDER = "{{KGRAPH_CONTEXT_POLIC
3
3
  export declare const KGRAPH_CAPTURE_POLICY_PLACEHOLDER = "{{KGRAPH_CAPTURE_POLICY}}";
4
4
  export declare function upsertManagedBlock(content: string, integrationName: string, instructions: string): string;
5
5
  export declare function removeManagedBlock(content: string, integrationName: string): string;
6
- export declare function applyContextPolicy(content: string, mode: IntegrationMode): string;
7
- export declare function renderContextPolicy(mode: IntegrationMode): string;
8
- export declare function renderCapturePolicy(): string;
6
+ export declare function applyContextPolicy(content: string, mode: IntegrationMode, agentName?: string): string;
7
+ export declare function renderContextPolicy(mode: IntegrationMode, agentName?: string): string;
8
+ export declare function renderCapturePolicy(agentName?: string): string;
@@ -30,36 +30,45 @@ function managedBlockPattern(integrationName) {
30
30
  function escapeRegExp(value) {
31
31
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
32
32
  }
33
- export function applyContextPolicy(content, mode) {
33
+ export function applyContextPolicy(content, mode, agentName) {
34
34
  return content
35
- .replaceAll(KGRAPH_CONTEXT_POLICY_PLACEHOLDER, renderContextPolicy(mode))
36
- .replaceAll(KGRAPH_CAPTURE_POLICY_PLACEHOLDER, renderCapturePolicy());
35
+ .replaceAll(KGRAPH_CONTEXT_POLICY_PLACEHOLDER, renderContextPolicy(mode, agentName))
36
+ .replaceAll(KGRAPH_CAPTURE_POLICY_PLACEHOLDER, renderCapturePolicy(agentName));
37
37
  }
38
- export function renderContextPolicy(mode) {
38
+ export function renderContextPolicy(mode, agentName) {
39
39
  const useResultBoundary = 'Use the returned KGraph ContextPack items as the first-pass source of truth. Prefer source ranges, atoms, git changes, and inclusion reasons from the pack before broad repository search. Do not rerun the same KGraph query just to tail or reformat output, do not continue broad repository search after the target file or range is identified, do not retry malformed shell commands with broader variants, and do not run broad `find`, recursive `grep`, or repeated full-file dumps after KGraph has narrowed the target.';
40
+ const packCommand = agentName
41
+ ? `kgraph pack "<topic>" --budget 8000 --json --agent ${agentName}`
42
+ : 'kgraph pack "<topic>" --budget 8000 --json';
40
43
  switch (mode) {
41
44
  case 'always':
42
- return `Every chat in this repository must start by running \`kgraph pack "<topic>" --budget 8000 --json\` before answering or exploring files. Infer the topic from the user's message; no exceptions, including simple or conversational requests. Use \`kgraph "<topic>"\` only when a human-readable briefing is explicitly needed. ${useResultBoundary}`;
45
+ return `Every chat in this repository must start by running \`${packCommand}\` before answering or exploring files. Infer the topic from the user's message; no exceptions, including simple or conversational requests. This records a lightweight KGraph session context event for the agent. Use \`kgraph "<topic>"\` only when a human-readable briefing is explicitly needed. ${useResultBoundary}`;
43
46
  case 'manual':
44
47
  return 'Do not run KGraph automatically. Run `kgraph pack "<topic>" --budget 8000 --json` only when the user explicitly asks for KGraph context, invokes KGraph, or needs a machine-readable repo-memory pack.';
45
48
  case 'off':
46
49
  return 'KGraph is disabled for this integration.';
47
50
  case 'smart':
48
51
  default:
49
- return `For repo-specific coding, debugging, architecture, refactor, review, or file-exploration requests, run \`kgraph pack "<topic>" --budget 8000 --json\` before broad repository exploration. Infer the topic from the user's message. Skip KGraph for simple conversational requests that do not depend on repo knowledge. Use \`kgraph "<topic>"\` only when a human-readable briefing is explicitly needed. ${useResultBoundary}`;
52
+ return `For repo-specific coding, debugging, architecture, refactor, review, or file-exploration requests, run \`${packCommand}\` before broad repository exploration. Infer the topic from the user's message. This records a lightweight KGraph session context event only when KGraph is actually used. Skip KGraph for simple conversational requests that do not depend on repo knowledge. Use \`kgraph "<topic>"\` only when a human-readable briefing is explicitly needed. ${useResultBoundary}`;
50
53
  }
51
54
  }
52
- export function renderCapturePolicy() {
55
+ export function renderCapturePolicy(agentName) {
56
+ const finalCommand = agentName
57
+ ? `kgraph "<topic>" --final --agent ${agentName}`
58
+ : 'kgraph "<topic>" --final';
59
+ const captureCommand = agentName
60
+ ? `kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name> --agent ${agentName}`
61
+ : 'kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name>';
53
62
  return `Capture policy:
54
- - At the end of any session that changed repository files, run \`kgraph "<topic>" --final\` before the final response so KGraph can enforce whether capture is required.
55
- - If final check reports capture-required, run \`kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name>\` to store durable engineering memory, or explicitly say "No durable knowledge created" only when there is genuinely no reusable knowledge.
63
+ - At the end of any session that changed repository files, run \`${finalCommand}\` before the final response so KGraph can enforce whether capture is required.
64
+ - If final check reports capture-required, run \`${captureCommand}\` to store durable engineering memory, or explicitly say "No durable knowledge created" only when there is genuinely no reusable knowledge.
56
65
  - Low-level alternatives remain available: \`kgraph conclude "<topic>" --type <finding|decision|gotcha|summary|relationship> --confidence <high|medium|low>\` or \`kgraph session end --agent <agent> --conclude --topic "<topic>"\`.
57
66
  - Add evidence when storing cognition. High-confidence conclusions must include at least one \`--file <path>\` or \`--symbol <name>\`; medium-confidence conclusions should include evidence when possible.
58
67
  - Preserve only expensive-to-rediscover findings, decisions, gotchas, summaries, and relationships. Do not store raw chain-of-thought, temporary reasoning, speculative exploration, or low-value observations.
59
68
  - Use \`.kgraph/inbox/<slug>.md\` only when a longer structured note is clearer than a single \`kgraph conclude\` command.
60
69
  - A \`.kgraph/inbox/*.md\` note is KGraph runtime capture, not project documentation. It is allowed by this workflow unless the user explicitly says not to capture to KGraph.
61
70
  - Do not skip capture for meaningful UI text, button, link, route, styling, or small file edits. Skip capture only when no reusable repository knowledge was created.
62
- - Do not run KGraph repeatedly. Run it once at the start with \`kgraph "<topic>"\` or \`kgraph pack "<topic>" --budget 8000 --json\` for agent-readable context. If repo files changed, run \`kgraph "<topic>" --final\` once before the final answer.
71
+ - Do not run KGraph repeatedly. Run it once at the start with \`kgraph pack "<topic>" --budget 8000 --json${agentName ? ` --agent ${agentName}` : ''}\` for agent-readable context. If repo files changed, run \`${finalCommand}\` once before the final answer.
63
72
  - After the final \`kgraph\` run, mention whether durable cognition was stored or processed.
64
73
 
65
74
  When using an inbox note, use this structure:
@@ -34,11 +34,11 @@ export async function addIntegrations(workspace, names, mode = 'always') {
34
34
  await removeIntegrationCommandFiles(workspace.rootPath, adapter.commandFiles ?? []);
35
35
  }
36
36
  else {
37
- await writeIntegrationInstructions(workspace.rootPath, adapter.targetPath, adapter.name, applyContextPolicy(adapter.instructions, mode));
37
+ await writeIntegrationInstructions(workspace.rootPath, adapter.targetPath, adapter.name, applyContextPolicy(adapter.instructions, mode, adapter.name));
38
38
  const deduped = (adapter.commandFiles ?? []).filter((file) => !writtenCommandFiles.has(file.path));
39
39
  await writeIntegrationCommandFiles(workspace.rootPath, deduped.map((file) => ({
40
40
  ...file,
41
- content: applyContextPolicy(file.content, mode),
41
+ content: applyContextPolicy(file.content, mode, adapter.name),
42
42
  })));
43
43
  for (const file of adapter.commandFiles ?? []) {
44
44
  writtenCommandFiles.add(file.path);
@@ -8,8 +8,12 @@ const REPAIR_STEP = `Run \`kgraph repair --dry-run\` before cleanup when stale/n
8
8
  const COMPACT_STEP = `Run \`kgraph compact --dry-run\` when cognition looks duplicated, noisy, or stale. Run \`kgraph compact\` only when the user asks to merge/archive cognition.`;
9
9
  const HISTORY_STEP = `Run \`kgraph history\` or \`kgraph history "<topic>"\` to review past cognition sessions with git author attribution.`;
10
10
  const KNOWLEDGE_STEP = `Run \`kgraph knowledge list --topic "<topic>"\` or \`kgraph knowledge get <atom-id>\` when the user asks what KGraph remembers or atom provenance/lifecycle matters.`;
11
- const PACK_STEP = `Treat \`kgraph pack "<task>" --budget 8000 --json\` as the primary agent contract: use atoms, source ranges, git changes, omitted items, and inclusion reasons from the ContextPack before reading files. Use human \`kgraph "<topic>"\` output only when the user explicitly wants a briefing.`;
12
- const SMART_ROOT_STEP = `Prefer the root workflow for normal agent work: run \`kgraph "<topic>"\` to refresh maps, process cognition, report memory health, and return context; run \`kgraph "<topic>" --final\` before the final answer when repository files changed; run \`kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name>\` when the final check requires durable knowledge.`;
11
+ function packStep(agentName) {
12
+ return `Treat \`kgraph pack "<task>" --budget 8000 --json --agent ${agentName}\` as the primary agent contract: use atoms, source ranges, git changes, omitted items, and inclusion reasons from the ContextPack before reading files. Use human \`kgraph "<topic>" --agent ${agentName}\` output only when the user explicitly wants a briefing.`;
13
+ }
14
+ function smartRootStep(agentName) {
15
+ return `Prefer the root workflow for normal agent work: run \`kgraph "<topic>" --agent ${agentName}\` when a human-readable refresh/context briefing is needed; run \`kgraph "<topic>" --final --agent ${agentName}\` before the final answer when repository files changed; run \`kgraph "<topic>" --capture "<durable conclusion>" --capture-file <path> --capture-symbol <name> --agent ${agentName}\` when the final check requires durable knowledge.`;
16
+ }
13
17
  const STALE_STEP = `Run \`kgraph stale\` when changed or deleted code may have invalidated durable knowledge. Run \`kgraph blame <atom-id>\` when provenance or evidence for a memory matters.`;
14
18
  const EXPLORATION_BOUNDARY_STEP = `Keep exploration bounded by the task. For simple edits, use KGraph to identify the likely file, then read only that file or a narrow range and make the edit. Do not keep searching after the target file is found, do not retry malformed shell commands with broader variants, and do not run broad \`find\`, recursive \`grep\`, or repeated full-file dumps after KGraph already returned candidate files. Use \`rg --files\` and quoted paths when a path must be located.`;
15
19
  const VERIFY_EDIT_STEP = `After editing, verify the change actually landed before claiming completion. Prefer a narrow read of the changed range or \`git diff -- <path>\`; if there is no diff or the expected text is missing, say the edit did not apply and fix it before summarizing.`;
@@ -27,8 +31,8 @@ export function numberedWorkflow(agentName, options = {}) {
27
31
  3. Use the returned files, symbols, relationships, and cognition before broad exploration.
28
32
  4. ${EXPLORATION_BOUNDARY_STEP}
29
33
  5. ${VERIFY_EDIT_STEP}
30
- 6. ${SMART_ROOT_STEP}
31
- 7. ${PACK_STEP}
34
+ 6. ${smartRootStep(agentName)}
35
+ 7. ${packStep(agentName)}
32
36
  8. ${KNOWLEDGE_STEP}
33
37
  9. ${DOCTOR_STEP}
34
38
  10. ${STALE_STEP}
@@ -50,8 +54,8 @@ export function bulletWorkflow(agentName, options = {}) {
50
54
  return `- {{KGRAPH_CONTEXT_POLICY}}
51
55
  - ${EXPLORATION_BOUNDARY_STEP}
52
56
  - ${VERIFY_EDIT_STEP}
53
- - ${SMART_ROOT_STEP}
54
- - ${PACK_STEP}
57
+ - ${smartRootStep(agentName)}
58
+ - ${packStep(agentName)}
55
59
  - ${KNOWLEDGE_STEP}
56
60
  - ${DOCTOR_STEP}
57
61
  - ${STALE_STEP}
@@ -1,6 +1,9 @@
1
+ import fs from 'node:fs';
1
2
  import { createRequire } from 'node:module';
2
3
  import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
3
5
  import { Language, Parser } from 'web-tree-sitter';
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
4
7
  const require = createRequire(import.meta.url);
5
8
  let initPromise = null;
6
9
  const languageCache = new Map();
@@ -42,8 +45,31 @@ async function ensureInit() {
42
45
  }
43
46
  function resolveWasmPath(grammarKey) {
44
47
  const { pkg, wasm } = GRAMMAR_PACKAGES[grammarKey];
45
- const pkgDir = path.dirname(require.resolve(`${pkg}/package.json`));
46
- return path.join(pkgDir, wasm);
48
+ // Production: bundled in dist/grammars/
49
+ const bundled = path.join(__dirname, '..', 'grammars', wasm);
50
+ if (fs.existsSync(bundled))
51
+ return bundled;
52
+ // Development: resolve from node_modules
53
+ try {
54
+ const pkgDir = path.dirname(require.resolve(`${pkg}/package.json`));
55
+ const fromPkg = path.join(pkgDir, wasm);
56
+ if (fs.existsSync(fromPkg))
57
+ return fromPkg;
58
+ }
59
+ catch {
60
+ // package not installed
61
+ }
62
+ // Fallback: tree-sitter-wasms package
63
+ try {
64
+ const wasmsDir = path.join(path.dirname(require.resolve('tree-sitter-wasms/package.json')), 'out');
65
+ const fromWasms = path.join(wasmsDir, wasm);
66
+ if (fs.existsSync(fromWasms))
67
+ return fromWasms;
68
+ }
69
+ catch {
70
+ // tree-sitter-wasms not installed
71
+ }
72
+ throw new Error(`Cannot find ${wasm} for grammar "${grammarKey}". Run "npm run build" or install dev dependencies.`);
47
73
  }
48
74
  export async function loadLanguage(grammarKey) {
49
75
  const cached = languageCache.get(grammarKey);
@@ -1,6 +1,6 @@
1
1
  import type { IntegrationName } from './config.js';
2
2
  export type SessionAgent = IntegrationName;
3
- export type SessionEventType = 'start' | 'read' | 'write' | 'end';
3
+ export type SessionEventType = 'start' | 'context' | 'read' | 'write' | 'end';
4
4
  export type SessionCaptureSource = 'automatic' | 'agent-reported' | 'manual';
5
5
  export interface SessionEvent {
6
6
  id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kentwynn/kgraph",
3
- "version": "0.2.24",
3
+ "version": "0.2.27",
4
4
  "description": "Persistent repo intelligence for AI coding assistants.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "clean": "node scripts/clean-dist.mjs",
17
- "build": "npm run clean && tsc -p tsconfig.json",
17
+ "build": "npm run clean && tsc -p tsconfig.json && node scripts/bundle-grammars.mjs",
18
18
  "postbuild": "node -e \"try{require('child_process').execSync('chmod +x dist/cli/index.js')}catch{}\"",
19
19
  "test": "vitest run",
20
20
  "kgraph": "tsx src/cli/index.ts",
@@ -44,11 +44,19 @@
44
44
  "homepage": "https://github.com/kentwynn/KGraph#readme",
45
45
  "dependencies": {
46
46
  "@clack/prompts": "^1.3.0",
47
- "@tree-sitter-grammars/tree-sitter-kotlin": "^1.1.0",
48
- "@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
49
47
  "chalk": "^5.6.2",
50
48
  "commander": "^12.1.0",
51
49
  "fast-glob": "^3.3.2",
50
+ "typescript": "^5.9.3",
51
+ "web-tree-sitter": "^0.26.8",
52
+ "yaml": "^2.5.1"
53
+ },
54
+ "devDependencies": {
55
+ "@release-it/conventional-changelog": "^11.0.0",
56
+ "@tree-sitter-grammars/tree-sitter-kotlin": "^1.1.0",
57
+ "@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
58
+ "@types/node": "^20.17.10",
59
+ "release-it": "^20.0.1",
52
60
  "tree-sitter-bash": "^0.25.1",
53
61
  "tree-sitter-c": "^0.24.1",
54
62
  "tree-sitter-c-sharp": "^0.23.5",
@@ -66,14 +74,7 @@
66
74
  "tree-sitter-ruby": "^0.23.1",
67
75
  "tree-sitter-rust": "^0.24.0",
68
76
  "tree-sitter-scala": "^0.24.0",
69
- "typescript": "^5.9.3",
70
- "web-tree-sitter": "^0.26.8",
71
- "yaml": "^2.5.1"
72
- },
73
- "devDependencies": {
74
- "@release-it/conventional-changelog": "^11.0.0",
75
- "@types/node": "^20.17.10",
76
- "release-it": "^20.0.1",
77
+ "tree-sitter-wasms": "^0.1.13",
77
78
  "tsx": "^4.19.2",
78
79
  "vitest": "^3.2.4"
79
80
  },