memtrace-skills 1.2.9 → 1.2.11

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 (48) hide show
  1. package/dist/managed-skills.d.ts +4 -0
  2. package/dist/managed-skills.js +95 -0
  3. package/dist/rail-hook.d.ts +7 -1
  4. package/dist/rail-hook.js +177 -57
  5. package/dist/rail-install.js +3 -6
  6. package/dist/rail-lifecycle.js +6 -3
  7. package/dist/rail-runtime.d.ts +38 -3
  8. package/dist/rail-runtime.js +88 -7
  9. package/dist/tool-names.js +6 -0
  10. package/dist/transformers/claude.d.ts +16 -4
  11. package/dist/transformers/claude.js +69 -82
  12. package/dist/transformers/codex.js +5 -20
  13. package/dist/transformers/cursor.js +5 -20
  14. package/dist/transformers/kiro.js +5 -14
  15. package/dist/transformers/opencode.js +6 -6
  16. package/dist/transformers/pi.js +5 -5
  17. package/dist/transformers/rail-hooks.d.ts +6 -1
  18. package/dist/transformers/rail-hooks.js +72 -13
  19. package/dist/transformers/shared.d.ts +2 -1
  20. package/dist/transformers/shared.js +28 -23
  21. package/dist/transformers/vscode.js +3 -1
  22. package/package.json +2 -2
  23. package/plugins/memtrace-skills/references/mcp-parameters.md +14 -3
  24. package/plugins/memtrace-skills/skills/memtrace-codebase-exploration/SKILL.md +4 -0
  25. package/plugins/memtrace-skills/skills/memtrace-daily/SKILL.md +4 -0
  26. package/plugins/memtrace-skills/skills/memtrace-first/SKILL.md +55 -24
  27. package/plugins/memtrace-skills/skills/memtrace-graph/SKILL.md +4 -0
  28. package/plugins/memtrace-skills/skills/memtrace-guided-refactor/SKILL.md +88 -0
  29. package/plugins/memtrace-skills/skills/memtrace-impact/SKILL.md +4 -0
  30. package/plugins/memtrace-skills/skills/memtrace-index/SKILL.md +21 -0
  31. package/plugins/memtrace-skills/skills/memtrace-preflight/SKILL.md +4 -0
  32. package/plugins/memtrace-skills/skills/memtrace-quality/SKILL.md +16 -2
  33. package/plugins/memtrace-skills/skills/memtrace-refactoring-guide/SKILL.md +4 -0
  34. package/plugins/memtrace-skills/skills/memtrace-search/SKILL.md +1 -0
  35. package/plugins/memtrace-skills/skills/memtrace-session-continuity/SKILL.md +4 -0
  36. package/skills/commands/memtrace-daily.md +4 -0
  37. package/skills/commands/memtrace-graph.md +4 -0
  38. package/skills/commands/memtrace-impact.md +4 -0
  39. package/skills/commands/memtrace-index.md +22 -0
  40. package/skills/commands/memtrace-preflight.md +4 -0
  41. package/skills/commands/memtrace-quality.md +19 -2
  42. package/skills/commands/memtrace-search.md +1 -0
  43. package/skills/managed-stock-sha256.txt +364 -0
  44. package/skills/workflows/memtrace-codebase-exploration.md +4 -0
  45. package/skills/workflows/memtrace-first.md +55 -24
  46. package/skills/workflows/memtrace-guided-refactor.md +89 -0
  47. package/skills/workflows/memtrace-refactoring-guide.md +4 -0
  48. package/skills/workflows/memtrace-session-continuity.md +4 -0
@@ -3,8 +3,8 @@
3
3
  * hook. Each supported agent intercepts tool calls differently, so each gets a
4
4
  * thin host-specific registration that points at the SAME router
5
5
  * (`memtrace route --hook --host <h>`). All entries are idempotent and remove
6
- * cleanly. Hooks default to observe mode (zero behavior change); the user opts
7
- * into more via `MEMTRACE_RAIL=nudge|rail|strict`.
6
+ * cleanly. Hooks default to nudge mode (context without suppressing ordinary
7
+ * tools); explicit `MEMTRACE_RAIL` and rail.json modes remain authoritative.
8
8
  *
9
9
  * Host families:
10
10
  * - Claude Code → `.claude/settings.json` hooks.PreToolUse (in claude.ts)
@@ -19,7 +19,7 @@ import fs from 'fs';
19
19
  import os from 'os';
20
20
  import path from 'path';
21
21
  import { safeReadJson, writeJsonAtomic } from '../fs-safe.js';
22
- import { railIsActive, railHookCommand, railHookInvocation, isRailCommand } from '../rail-runtime.js';
22
+ import { railIsActive, railHookCommand, railHookInvocation, isRailCommand, enrichEnabled } from '../rail-runtime.js';
23
23
  /** Substring identifying a memtrace-owned Rail hook entry. */
24
24
  export const RAIL_HOOK_MARKER = 'route --hook';
25
25
  /** The discovery tools each host surfaces. */
@@ -68,10 +68,8 @@ export function openCodeConfigDir(ctx, options = {}) {
68
68
  ? openCodeGlobalConfigDir(options)
69
69
  : path.join(ctx.cwd, '.opencode');
70
70
  }
71
- // OpenCode's plugin directory name changed across versions: current official
72
- // docs use `plugins/` (plural) while older/community builds load `plugin/`
73
- // (singular). We write the plugin to BOTH so it loads regardless of version;
74
- // uninstall removes both. (Identical content — whichever the runtime reads.)
71
+ // Enumerate both locations for upgrade/uninstall cleanup. OpenCode loads both,
72
+ // so installation must write only the current plural directory (public #82).
75
73
  export function openCodeRailPluginPaths(ctx, options = {}) {
76
74
  const base = openCodeConfigDir(ctx, options);
77
75
  return [
@@ -79,6 +77,13 @@ export function openCodeRailPluginPaths(ctx, options = {}) {
79
77
  path.join(base, 'plugins', 'memtrace-rail.js'),
80
78
  ];
81
79
  }
80
+ export function writeOpenCodeRailPlugin(ctx, source) {
81
+ const [legacy, current] = openCodeRailPluginPaths(ctx);
82
+ fs.mkdirSync(path.dirname(current), { recursive: true });
83
+ fs.writeFileSync(current, source);
84
+ fs.rmSync(legacy, { force: true });
85
+ return current;
86
+ }
82
87
  function isRecord(v) {
83
88
  return typeof v === 'object' && v !== null && !Array.isArray(v);
84
89
  }
@@ -154,7 +159,7 @@ export function removeSettingsHook(settingsPath, eventName) {
154
159
  * schema: `{version, hooks: {beforeShellExecution: [{command}]}}`. We intercept
155
160
  * both shell execution (where rg/grep/find run) and file reads.
156
161
  */
157
- export function registerCursorRailHook(hooksPath, binary) {
162
+ export function registerCursorRailHook(hooksPath, binary, options = {}) {
158
163
  if (!railIsActive()) {
159
164
  removeCursorRailHook(hooksPath);
160
165
  return { registered: false };
@@ -176,9 +181,27 @@ export function registerCursorRailHook(hooksPath, binary) {
176
181
  const preserved = existing.filter((e) => !(isRecord(e) && typeof e.command === 'string' && isRailCommand(e.command)));
177
182
  preserved.push({ command: cmd });
178
183
  cfg.hooks[event] = preserved;
184
+ // Grep enrichment: Cursor `postToolUse` on its Shell and Grep tools answers
185
+ // with `additional_context` (design section 9). Fresh Nudge enables it;
186
+ // explicit mode/enrichment settings keep their existing meaning.
187
+ const post = Array.isArray(cfg.hooks[CURSOR_ENRICH_EVENT]) ? cfg.hooks[CURSOR_ENRICH_EVENT] : [];
188
+ const postPreserved = post.filter((e) => !(isRecord(e) && typeof e.command === 'string' && isRailCommand(e.command)));
189
+ if (options.enrich ?? enrichEnabled()) {
190
+ postPreserved.push({
191
+ matcher: CURSOR_ENRICH_MATCHER,
192
+ command: railHookCommand('cursor', process.platform, ['--phase', 'post']),
193
+ timeout: 2,
194
+ });
195
+ }
196
+ if (postPreserved.length)
197
+ cfg.hooks[CURSOR_ENRICH_EVENT] = postPreserved;
198
+ else
199
+ delete cfg.hooks[CURSOR_ENRICH_EVENT];
179
200
  writeJsonAtomic(hooksPath, cfg);
180
201
  return { registered: true };
181
202
  }
203
+ export const CURSOR_ENRICH_EVENT = 'postToolUse';
204
+ export const CURSOR_ENRICH_MATCHER = 'Shell|Grep';
182
205
  /** Remove the Cursor Rail hook entries. */
183
206
  /** Windsurf Cascade hooks path (user-level). */
184
207
  export function windsurfHooksPath() {
@@ -305,7 +328,7 @@ export function removeCursorRailHook(hooksPath) {
305
328
  if (!isRecord(cfg.hooks))
306
329
  return { changed: false };
307
330
  let changed = false;
308
- for (const event of ['beforeShellExecution', 'beforeReadFile']) {
331
+ for (const event of ['beforeShellExecution', 'beforeReadFile', CURSOR_ENRICH_EVENT]) {
309
332
  if (!Array.isArray(cfg.hooks[event]))
310
333
  continue;
311
334
  const before = cfg.hooks[event];
@@ -334,22 +357,31 @@ export function removeCursorRailHook(hooksPath) {
334
357
  */
335
358
  export function openCodePluginSource(binary) {
336
359
  const hook = railHookInvocation('open-code');
360
+ const runtimeModule = new URL('../rail-runtime.js', import.meta.url).href;
337
361
  return `// AUTO-GENERATED by memtrace install — Memtrace Rail discovery hook.
338
- // Routes OpenCode tool calls through \`${binary} route\`. Defaults to observe
339
- // (no-op) unless MEMTRACE_RAIL=nudge|rail|strict. Remove via 'memtrace uninstall'.
362
+ // Routes OpenCode tool calls through \`${binary} route\`.
363
+ // Defaults to non-blocking context; explicit Rail mode overrides are retained.
364
+ // Remove via 'memtrace uninstall'.
340
365
  import { execFileSync } from 'node:child_process';
366
+ import { enrichEnabled, railConfig, railMode } from ${JSON.stringify(runtimeModule)};
341
367
 
342
368
  const BIN = ${JSON.stringify(hook.command)};
343
369
  const ARGS = ${JSON.stringify([...hook.args, '--json'])};
370
+ const POST_ARGS = ${JSON.stringify([...hook.args, '--phase', 'post'])};
344
371
 
345
- export const MemtraceRail = async ({ project, client, $ }) => ({
372
+ export const MemtraceRail = async ({ directory }) => ({
346
373
  'tool.execute.before': async (input, output) => {
347
374
  try {
348
375
  const tool = input?.tool;
349
376
  if (tool !== 'bash' && tool !== 'grep' && tool !== 'glob') return;
377
+ const config = railConfig();
378
+ const mode = railMode(process.env, config);
379
+ // The post hook supplies Nudge context once, after the ordinary search.
380
+ // Rail and Strict retain their existing pre-execution enforcement.
381
+ if (enrichEnabled(process.env, config) && mode !== 'rail' && mode !== 'strict') return;
350
382
  const attempt = {
351
383
  host: 'open-code',
352
- cwd: output?.args?.cwd || process.cwd(),
384
+ cwd: output?.args?.cwd || directory || process.cwd(),
353
385
  tool: tool === 'bash' ? 'Bash' : tool === 'grep' ? 'Grep' : 'Glob',
354
386
  input: output?.args || {},
355
387
  session_id: input?.sessionID || 'opencode',
@@ -367,6 +399,33 @@ export const MemtraceRail = async ({ project, client, $ }) => ({
367
399
  if (e && String(e.message || '').startsWith('[Memtrace Rail]')) throw e;
368
400
  }
369
401
  },
402
+ // OpenCode @opencode-ai/plugin 1.19.4: native registry tools expose the
403
+ // mutable {title, output, metadata} tool.execute.after contract.
404
+ 'tool.execute.after': async (input, output) => {
405
+ try {
406
+ const tool = input?.tool;
407
+ if ((tool !== 'bash' && tool !== 'grep') || typeof output?.output !== 'string'
408
+ || !enrichEnabled() || typeof input?.sessionID !== 'string') return;
409
+ const payload = {
410
+ cwd: input?.args?.cwd || directory || process.cwd(),
411
+ session_id: input.sessionID,
412
+ tool_use_id: input.callID,
413
+ tool_name: tool === 'bash' ? 'Bash' : 'Grep',
414
+ tool_input: input.args || {},
415
+ tool_response: { ...(output.metadata || {}), stdout: output.output },
416
+ };
417
+ const raw = execFileSync(BIN, POST_ARGS, {
418
+ input: JSON.stringify(payload), timeout: 2000, encoding: 'utf8', windowsHide: true,
419
+ });
420
+ const text = JSON.parse(raw)?.hookSpecificOutput?.additionalContext;
421
+ if (typeof text === 'string' && text.trim() && Buffer.byteLength(text, 'utf8') <= 4000) {
422
+ output.output += '\\n\\n' + text;
423
+ }
424
+ } catch {
425
+ // Missing owner, invalid query, timeout or malformed output leaves the
426
+ // original ordinary-tool response byte-for-byte unchanged.
427
+ }
428
+ },
370
429
  });
371
430
  `;
372
431
  }
@@ -14,7 +14,8 @@ export interface JsonMcpResult {
14
14
  }
15
15
  export declare function registerMcpServersJsonAt(filePath: string, binary: string): JsonMcpResult;
16
16
  export declare function removeMcpServersJsonAt(filePath: string): void;
17
- export declare function registerVsCodeMcpAt(filePath: string, binary: string): JsonMcpResult;
17
+ export type VsCodeMcpScope = 'user' | 'workspace';
18
+ export declare function registerVsCodeMcpAt(filePath: string, binary: string, scope?: VsCodeMcpScope): JsonMcpResult;
18
19
  export declare function removeVsCodeMcpAt(filePath: string): void;
19
20
  export declare function registerOpenCodeMcpAt(filePath: string, binary: string): JsonMcpResult;
20
21
  export declare function removeOpenCodeMcpAt(filePath: string): void;
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { safeReadJson, writeJsonAtomic } from '../fs-safe.js';
4
+ import { writeManagedSkill, removeManagedSkills } from '../managed-skills.js';
4
5
  export const MCP_SERVER_NAME = 'memtrace';
5
6
  // MemFleet coordination now lives on the Memtrace MCP server. Replace this
6
7
  // retired registration during install so clients do not load the same graph
@@ -27,23 +28,15 @@ export function skillMarkdown(skill, extraFrontmatter = {}) {
27
28
  return `---\nname: ${name}\ndescription: "${safeDesc}"${extra ? `\n${extra}` : ''}\n---\n\n${skill.body}`;
28
29
  }
29
30
  export function writeSkills(skills, rootDir, extraFrontmatter = {}) {
30
- removeMemtraceSkills(rootDir);
31
+ let written = 0;
31
32
  for (const skill of skills) {
32
- const name = skillName(skill);
33
- const outDir = path.join(rootDir, name);
34
- fs.mkdirSync(outDir, { recursive: true });
35
- fs.writeFileSync(path.join(outDir, 'SKILL.md'), skillMarkdown(skill, extraFrontmatter));
33
+ if (writeManagedSkill(rootDir, skillName(skill), skillMarkdown(skill, extraFrontmatter)))
34
+ written++;
36
35
  }
37
- return skills.length;
36
+ return written;
38
37
  }
39
38
  export function removeMemtraceSkills(rootDir) {
40
- if (!fs.existsSync(rootDir))
41
- return;
42
- for (const entry of fs.readdirSync(rootDir)) {
43
- if (entry.startsWith('memtrace-')) {
44
- fs.rmSync(path.join(rootDir, entry), { recursive: true, force: true });
45
- }
46
- }
39
+ removeManagedSkills(rootDir);
47
40
  }
48
41
  export function writeTextAtomic(filePath, content) {
49
42
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
@@ -78,27 +71,39 @@ export function removeMcpServersJsonAt(filePath) {
78
71
  else
79
72
  writeJsonAtomic(filePath, value);
80
73
  }
81
- export function registerVsCodeMcpAt(filePath, binary) {
74
+ export function registerVsCodeMcpAt(filePath, binary, scope = 'workspace') {
82
75
  const { value, corrupted, backupPath } = safeReadJson(filePath);
83
76
  if (corrupted)
84
77
  return { registered: false, backupPath };
85
78
  const cfg = (value ?? {});
86
79
  cfg.servers = cfg.servers ?? {};
87
80
  removeLegacyMcpServer(cfg.servers);
88
- cfg.servers[MCP_SERVER_NAME] = {
81
+ // MEMBIZ-50 D2: `cwd` is the ONE anchor that drives both store resolution
82
+ // and repository discovery in `memtrace mcp`. Without it the server spawns
83
+ // in the editor's own working directory (often the user profile), where it
84
+ // can resolve a stale user-level `.memdb` instead of the project's.
85
+ //
86
+ // MEMBIZ-95: but VS Code only resolves `${workspaceFolder}` in a
87
+ // WORKSPACE-scoped file. In the user-level `Code/User/mcp.json` it refuses
88
+ // outright —
89
+ //
90
+ // Error starting memtrace: CodeExpectedError:
91
+ // Variable workspaceFolder can not be resolved. Please open a folder.
92
+ //
93
+ // — and Memtrace never launches at all, in any window. A server that cannot
94
+ // start anchors nothing, so keeping the variable there trades a narrow
95
+ // wrong-store risk for a total outage. Omitted at user scope: a server
96
+ // spawned without an anchor joins the unique live `memtrace start` instead
97
+ // (see `mcp_from_home_cwd_lists_the_unique_live_estate`), which is the
98
+ // normal case and what the field workaround relied on.
99
+ const entry = {
89
100
  type: 'stdio',
90
101
  command: binary,
91
102
  args: ['mcp'],
92
- // MEMBIZ-50 D2: `cwd` is the ONE anchor that drives both store
93
- // resolution and repository discovery in `memtrace mcp`. Without it a
94
- // user-scope entry spawns the server in the editor's own working
95
- // directory (often the user profile), where it resolves a stale
96
- // user-level `.memdb` instead of the project's — every project then
97
- // shares one wrong, empty store. VS Code substitutes the variable per
98
- // window, so one global entry serves every project correctly.
99
- cwd: '${workspaceFolder}',
103
+ ...(scope === 'workspace' ? { cwd: '${workspaceFolder}' } : {}),
100
104
  env: MEMTRACE_MCP_ENV,
101
105
  };
106
+ cfg.servers[MCP_SERVER_NAME] = entry;
102
107
  writeJsonAtomic(filePath, cfg);
103
108
  return { registered: true };
104
109
  }
@@ -31,7 +31,9 @@ export const vscodeTransformer = {
31
31
  const warnings = [];
32
32
  const mcpConfigPath = mcpPath(ctx);
33
33
  if (!ctx.skipMcp) {
34
- const result = registerVsCodeMcpAt(mcpConfigPath, ctx.memtraceBinary);
34
+ // MEMBIZ-95: the user-level file cannot carry `${workspaceFolder}` —
35
+ // VS Code refuses to resolve it there and never starts the server.
36
+ const result = registerVsCodeMcpAt(mcpConfigPath, ctx.memtraceBinary, ctx.scope === 'global' ? 'user' : 'workspace');
35
37
  mcpRegistered = result.registered;
36
38
  if (!mcpRegistered && result.backupPath) {
37
39
  warnings.push(`VS Code MCP config was malformed; backed up to ${result.backupPath}.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memtrace-skills",
3
- "version": "1.2.9",
3
+ "version": "1.2.11",
4
4
  "description": "Memtrace skills for AI coding agents — codebase exploration, temporal evolution, impact analysis, and more.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "prebuild": "node scripts/copy-skills.js",
18
18
  "build": "tsc",
19
19
  "prepublishOnly": "npm run build",
20
- "test": "vitest run && tsc && node --test tests/runtime/rail-lifecycle.test.mjs",
20
+ "test": "vitest run && tsc && node --test tests/runtime/rail-lifecycle.test.mjs tests/runtime/rail-enrich-hook.test.mjs tests/runtime/opencode-rail-plugin.test.mjs",
21
21
  "test:watch": "vitest"
22
22
  },
23
23
  "dependencies": {
@@ -91,6 +91,9 @@ the repository.
91
91
  | `include_diagnostics` | boolean | no | `false` | Include `id`, `score` in results |
92
92
  | `include_dependency_checks` | boolean | no | `true` | With diagnostics, set false for scores without pre-edit risk checks |
93
93
  | `include_context` | boolean | no | auto | Bounded processes, communities and selected callers/callees; default on for concepts, off for identifiers |
94
+ | `verbose` | boolean | no | `false` | Full uncompacted answer (row provenance, ranking constants); `context.next_calls` is kept either way |
95
+
96
+ Rows are `name`, `kind`, `file_path`, `start_line`, `end_line` (`symbol_start_line`/`symbol_end_line` when a long symbol was narrowed). `context.processes[].id` is the `process` argument for `get_process_flow`.
94
97
 
95
98
  No `kind` param — use `find_symbol(kind=...)` instead.
96
99
 
@@ -131,10 +134,13 @@ No parameters. Call once at session start to get `repo_id` values.
131
134
  | `as_of` | string | no | now |
132
135
  | `view` | string | no | `"live"` |
133
136
  | `include_content` | boolean | no | `false` |
134
- | `limit` | integer | no | `20` (max `200`) |
137
+ | `limit` | integer | no | `5` (max `200`; `20` with `verbose`) |
135
138
  | `offset` | integer | no | `0` |
139
+ | `include_references` | boolean | no | `false` |
140
+ | `include_details` | boolean | no | `false` |
141
+ | `verbose` | boolean | no | `false` |
136
142
 
137
- Returns compact symbol locations, relationship sections, community and process context. Source bodies require `include_content: true`, or use `get_source_window`. Each section has `pagination` metadata with `available`, `returned`, `offset`, and `next_offset`. The offset applies independently to each section; repeat with that section's `next_offset` to continue it. These pages cover the bounded graph result: `graph_truncated` and `available_is_lower_bound` remain true when an internal graph cap was reached.
143
+ Returns the subject (location, signature, doc, `node_id`), callers and callees with edge evidence (`via`: `rel`, `reason`, `confidence`, call-site `lines`), process memberships and community. Source bodies require `include_content: true`, or use `get_source_window`. `pagination` lists only sections with more rows: `available`, `next_offset`, and `lower_bound` when an internal graph cap was reached; the offset applies to every section. References are counted in `omitted.references` and returned with `include_references: true`. `verbose: true` returns the full uncompacted answer. An answer over the response budget drops whole rows, sets `truncated: true` and names each shortened list in `omitted` with how to fetch it.
138
144
 
139
145
  ### `analyze_relationships`
140
146
  | Field | Type | Required | Default | Notes |
@@ -276,8 +282,13 @@ Returns `cochanged_files[]` with `file_path`, `cochange_count`, `last_cochanged_
276
282
  | `branch` | string | no | `"main"` |
277
283
  | `limit` | integer | no | `20` (max `200`) |
278
284
  | `offset` | integer | no | `0` |
285
+ | `focus_symbol` | string | no | — |
286
+ | `query` | string | no | — |
287
+ | `from_symbol` | boolean | no | `false` |
288
+ | `path_nodes` | array of string | no | — |
289
+ | `verbose` | boolean | no | `false` |
279
290
 
280
- Returns ordered steps, `total_steps`, `returned_steps`, `next_offset`, and `scan_truncated`. Follow `next_offset` to continue. The existing internal scan cap still applies; `scan_truncated` signals when pagination cannot expose the entire process.
291
+ Returns ordered steps, `total_steps`, `returned_steps`, `next_offset`, and `scan_truncated`. Follow `next_offset` to continue. `focus_symbol` (a member `node_id`) returns its call neighborhood; `query` searches the members and returns matches with short previews. Without a catalog process pass `from_symbol: true` and a callable `node_id` as `process`. To search one `flow_paths.choices` path pass `from_symbol: true`, `process` = `flow_paths.anchor_symbol`, `path_nodes` = the choice's `nodes`, and `query`. `connections` name their endpoints with `rel`, `reason`, `confidence` and call-site `lines`. `verbose: true` returns the full uncompacted answer.
281
292
 
282
293
  ### `find_dependency_path`
283
294
  | Field | Type | Required | Default | Notes |
@@ -5,6 +5,10 @@ description: "Map an indexed source-code repo into a structured overview — sca
5
5
 
6
6
  ## Overview
7
7
 
8
+ ### Choose the scope
9
+
10
+ Use this entry for a narrative overview and onboarding. For a specific algorithm such as PageRank, bridge detection, communities, or dependency paths, use `memtrace-graph`. A broad overview and an algorithm query remain distinct entry points.
11
+
8
12
  Full codebase exploration workflow — from indexing through architectural understanding. Chains indexing, graph algorithms, community detection, and temporal analysis into a structured onboarding experience. Use this when someone is new to a codebase and needs to build a mental model.
9
13
 
10
14
  ## Steps
@@ -5,6 +5,10 @@ description: "Orient at the start of a coding session, review what recently chan
5
5
 
6
6
  ## Overview
7
7
 
8
+ ### Choose the scope
9
+
10
+ Use this entry for the fixed last-24-hour briefing, hotspots, and session self-audit. To resume from your own saved anchor, use `memtrace-session-continuity`; do not substitute a 24-hour window for time since the user's last session.
11
+
8
12
  Session bookends: orient before you start, audit before you finish. All
9
13
  three tools read the bi-temporal version history — every save is a change
10
14
  event with complexity deltas, so "what happened" includes "did it make the
@@ -1,17 +1,31 @@
1
1
  ---
2
2
  name: memtrace-first
3
- description: "Route code discovery, debugging, flow tracing, how-code-works questions, and pre-edit rationale checks in indexed source-code repos to Memtrace graph plus Cortex decision tools. Use first before searching/reading code, and before editing, refactoring, deleting, or re-picking an approach that may have a recorded decision, ban, convention, or contract. Do not use Grep, Glob, rg, find, or manual file browsing for code discovery when Memtrace is indexed. Zero results are not permission to grep: diagnose the miss first, then allow one targeted reformulation and bounded source verification or fallback, and reindex only on evidence of stale or incomplete coverage — never in a loop. A `repo_not_in_store` refusal means a different store holds the repository: route to that store, never grep and never re-index here."
3
+ description: "Use indexed graph and decision context for nontrivial code discovery, debugging, caller or consumer analysis, cross-file changes, impact, history, and recorded contracts. Follow useful retrieval with relevant relationships and current-source verification. Ordinary tools remain available; explicit user and project workflows take precedence."
4
4
  ---
5
5
  # Memtrace First
6
6
 
7
- Use Memtrace first for code discovery in indexed repositories. Use its graph to
8
- understand relationships, processes and impact; verify source when exact behavior
9
- matters. Retrieval is evidence, not a guarantee of complete coverage.
7
+ Use Memtrace when indexed context helps resolve a concrete question about code,
8
+ relationships, processes, change impact or recorded decisions. Retrieval is
9
+ evidence, not a guarantee of complete coverage or correct behavior.
10
+
11
+ ## Respect the chosen workflow
12
+
13
+ This is the managed contextual default. Explicit user and project instructions,
14
+ including custom strict workflows and opt-outs, take precedence. Keep the existing
15
+ Rail setting: `off`, `observe`, `nudge`, `rail` or `strict`. Do not change a user's
16
+ mode or treat this default as authorization for indexing or other external actions.
17
+
18
+ Ordinary source search, reads, edits and tests remain available. Use them directly
19
+ for small, known local changes, exact text searches, or questions the graph cannot
20
+ answer. There is no mandatory first call, query quota or minimum tool count. For
21
+ nontrivial discovery or shared behavior, prefer Memtrace's indexed context and
22
+ follow useful hits with the relationships that answer the open question.
10
23
 
11
24
  ## Establish scope
12
25
 
13
- Call `list_indexed_repositories` once per session. Select the actual repository
14
- and branch; pass `repo_id` explicitly when possible. It lists this session's
26
+ Select the actual repository and branch; pass `repo_id` explicitly when
27
+ possible. When the task already names the repository, use it directly; call
28
+ `list_indexed_repositories` only when the repository or branch is unknown. It lists this session's
15
29
  store only, so a repository missing from it may still be indexed and live in
16
30
  another store. Do not index a parent containing unrelated repositories. For a
17
31
  deliberately shared workspace, verify its workspace marker and scope before
@@ -52,7 +66,7 @@ answer from stale repos.
52
66
  ## Search, then investigate
53
67
 
54
68
  - Exact symbol: `find_symbol(name=..., repo_id=...)`.
55
- - Behavior or concept: `find_code(query=..., repo_id=...)`.
69
+ - Behavior or concept: `find_code(query=..., repo_id=..., limit=10)` (default 20 rows).
56
70
  - Relationships: `get_symbol_context` or `analyze_relationships` on the useful hit.
57
71
  - Change impact: `get_impact`; confirm relevant callers against source.
58
72
  - Execution path: `get_process_flow`; follow its `next_offset` for further steps.
@@ -68,7 +82,8 @@ Treat partial context, truncation and unavailable overlay context as incomplete
68
82
  evidence; selected static flows are not complete runtime traces.
69
83
 
70
84
  `context.next_calls` provides scoped follow-up arguments for the useful symbol
71
- and process. Before changing shared behavior, inspect relevant callers and
85
+ and process; copy them rather than rebuilding arguments. A `context.processes[].id`
86
+ is the `process` for `get_process_flow`. Before changing shared behavior, inspect relevant callers and
72
87
  callees to identify contracts the patch must preserve. Use process IDs for
73
88
  flow navigation. No sampled flow is not proof that no call path exists.
74
89
 
@@ -79,8 +94,11 @@ Run related existing tests to detect regressions before claiming completion.
79
94
 
80
95
  Read the bounded source span when verifying behavior, editing or quoting. Do not
81
96
  fetch whole files or entire process traces when a local span answers the question.
82
- `get_symbol_context` omits source bodies by default; use `include_content: true`
83
- for explicit expansion, and `limit`/`offset` for relationship pages. An omitted
97
+ `get_symbol_context` returns 5 rows per relationship section and omits source
98
+ bodies and references by default: `pagination` names sections with more
99
+ (`limit`/`offset`), `omitted` names what was left out (`include_references: true`,
100
+ `include_details: true`), and `include_content: true` returns the symbol's body whole
101
+ with short neighbour previews. An omitted
84
102
  risk diagnostic means unknown, not zero callers or low risk. Check truncation and
85
103
  pagination metadata before describing a neighborhood as complete.
86
104
 
@@ -124,9 +142,11 @@ searched nothing. The `diagnostic` block names the store that answered, its
124
142
  problem: the id matches more than one repository in *this* store, and the
125
143
  message says to pass the exact id. Do that and stop here. Everything below
126
144
  applies to the `not_in_store` reason.
127
- 2. Do not fall back to file search. The refusal says so itself, in `_note`:
128
- "Wrong store for this repo_id; do not fall back to filesystem search, ask
129
- the session attached to the store named in diagnostic.repo_lives_in."
145
+ 2. Route graph questions to the owning store. A filesystem match cannot turn
146
+ this refusal into successful graph retrieval or prove that graph edges are
147
+ absent. Ordinary source work may continue when the actual checkout, path and
148
+ branch have been verified; keep that evidence separate from the unavailable
149
+ graph answer. Do not freeze the user's workflow while waiting for a store.
130
150
  3. Do not call `index_directory`. The repository is already indexed in the
131
151
  store `repo_lives_in` names. Indexing it here would build a second copy in
132
152
  the wrong store — writes are never routed to another store, so the call
@@ -138,7 +158,9 @@ searched nothing. The `diagnostic` block names the store that answered, its
138
158
  or `--workspace <name>` when a manifest or a Named Workspace owns its
139
159
  scope.
140
160
  5. If `repo_lives_in` is absent, no live Memtrace runtime declares the
141
- repository. Running `memtrace start` in its own workspace is the fix.
161
+ repository. If graph access is needed and setup is authorized, start Memtrace
162
+ in that repository's own workspace. Ordinary verified source work need not
163
+ wait; a retrieval refusal is not authorization to create another index.
142
164
 
143
165
  A refusal is not the only outcome. When the runtime whose store declares the
144
166
  repository is live and publishes a reachable control port, the same read is
@@ -167,8 +189,9 @@ that sets no `repo_in_store` key, is handled in the section above, not here.
167
189
  tool that sets no `repo_in_store` key, missing scope, wrong branch, pending
168
190
  index/embedding job, stale index and a valid empty result. Do not treat an
169
191
  error as a clean miss, and do not treat a refusal or a keyless zero as one
170
- either — re-ask through `find_code` or `find_symbol` before reading
171
- anything into a keyless zero.
192
+ either. Use a membership-checking tool when a membership or absence claim
193
+ matters; a keyless zero alone cannot establish it. Ordinary source
194
+ verification remains available without an extra graph-call prerequisite.
172
195
  2. For an ambiguous query, make at most one targeted reformulation, using an
173
196
  identifier or path hint where available, and a `file_path` filter such as
174
197
  `ui/`, `memtrace-ui/`, `src/` or the framework directory when one applies.
@@ -195,8 +218,9 @@ are also appropriate uses of file tools.
195
218
 
196
219
  ## Check rationale before changing code
197
220
 
198
- BEFORE you edit/refactor/delete existing code or choose another pattern, call
199
- Cortex `recall_decision("<symbol/subsystem/approach>")` when available. If a symbol
221
+ When changing shared behavior, deleting code, or revisiting an approach that may
222
+ have a recorded contract, use Cortex `recall_decision("<symbol/subsystem/approach>")`
223
+ when available and relevant. If a symbol
200
224
  ID is available, consult `why_is_this_here(symbol_id)` and
201
225
  `governing_contracts(symbol_id)`. Verify a
202
226
  matching decision with `verify_intent` before relying on it. Unknown rationale
@@ -208,8 +232,10 @@ when choosing among competing local idioms.
208
232
 
209
233
  Use JSON numbers for limits/depths and booleans for switches. Use symbol names
210
234
  for `get_symbol_context.symbol`, `get_impact.target` and relationship targets;
211
- use IDs only where the specific schema asks for one. Prefer the live schema over
212
- remembered parameters. `find_code` has no `kind` filter; use `find_symbol` for it.
235
+ use a returned exact UUID when that tool supports identity-based recovery. Check
236
+ the actual schema rather than guessing an argument name. When a call is rejected,
237
+ check that tool's schema rather than retrying from memory; do not pre-read schemas.
238
+ `find_code` has no `kind` filter; use `find_symbol` for it.
213
239
  Search without an explicit repository uses safe scope inference, not an implicit
214
240
  search of every repository. `get_evolution` uses `from`, not `days`.
215
241
 
@@ -222,12 +248,17 @@ receipts; preserve evidence internally and report meaningful findings and limits
222
248
  - The right repository and branch were used.
223
249
  - Graph claims are supported by retrieved edges, with missing/truncated data
224
250
  made explicit, and exact behavioral claims are checked against source.
225
- - A `repo_not_in_store` refusal was routed on `diagnostic.repo_lives_in`, not
226
- answered by grep and not answered by indexing the repository into this store.
251
+ - A `repo_not_in_store` graph question was routed on `diagnostic.repo_lives_in`,
252
+ not answered by indexing another copy into this store. Any ordinary source
253
+ fallback verified the actual checkout and was not reported as graph evidence.
227
254
  - A zero from a tool that sets no `repo_in_store` key was re-checked through a
228
255
  membership-checking tool before it was called an absence.
229
256
  - Failed retrieval on a genuine zero (`repo_in_store: true`) is diagnosed and
230
257
  bounded; it does not trigger query or reindex loops, and fallbacks remain
231
258
  distinguishable from retrieval successes.
232
- - Any source read was bounded to the span Memtrace returned.
233
- - Existing rationale and contracts were checked when the tools were available.
259
+ - Source inspection was scoped to the question; exact claims and edits were
260
+ verified against the current source rather than inferred from graph edges.
261
+ - Relevant recorded rationale and contracts were checked when available.
262
+ - Before finishing, compare the requested requirements with the implementation
263
+ and verification: state any remaining unverified behavior. This checklist is
264
+ a review aid, not machine-verified correctness or an extra approval gate.
@@ -5,6 +5,10 @@ description: "Map source-code architecture with graph algorithms — PageRank ce
5
5
 
6
6
  ## Overview
7
7
 
8
+ ### Choose the scope
9
+
10
+ Use this entry for a specific graph algorithm or structural question: centrality, bridges, communities, or dependency paths. For a narrative introduction spanning scale, architecture, APIs, and recent activity, use `memtrace-codebase-exploration`.
11
+
8
12
  Graph algorithms over the knowledge graph — communities (Louvain), PageRank centrality, bridge symbols (articulation points), shortest paths, and execution flows.
9
13
 
10
14
  ## Quick Reference
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: memtrace-guided-refactor
3
+ description: "Run a saved, staged refactor shared with Memtrace's Quality page. Use for splitting tangled functions, extracting helpers, or continuing a guided refactor run with fixed file scope and checks between edits."
4
+ ---
5
+
6
+ Use the `guided_refactor` MCP tool to track the same run shown in Quality. This
7
+ skill coordinates the agent's edits and language tools; Memtrace does not execute
8
+ shell commands or rewrite source on behalf of the browser. Never invent check
9
+ results. Recorded checks are agent-reported evidence, not proof of equivalence.
10
+
11
+ ## Diagnose
12
+
13
+ 1. Resolve the repository and exact symbol/file with `find_symbol` and
14
+ `get_symbol_context`. Use the runtime attached to that repository.
15
+ 2. If a run ID was supplied, call `guided_refactor` with `action: "get"`,
16
+ `repo_id`, and `run_id`. Otherwise call `action: "list"` and reuse a relevant
17
+ unfinished run; create one with `file_path` and `symbol` only when needed.
18
+ 3. Inspect function complexity, affected callers, evolution/churn, module
19
+ boundaries, existing tests, and decision-memory constraints. Use
20
+ `get_function_quality_metrics`, `get_impact`, `get_evolution`, and
21
+ `get_symbol_context` as available; read the selected source. Record missing
22
+ evidence explicitly. LOC alone is never a reason to split code.
23
+ 4. Respect the returned classification. `Manual` runs permit diagnosis and
24
+ blueprint only. In this first version, staged source work is available for
25
+ Rust, TypeScript, JavaScript, Python, and Go in Git checkouts. Other indexed
26
+ languages and configuration files still get a saved manual plan. Nothing is
27
+ classified Automatic.
28
+
29
+ ## Blueprint
30
+
31
+ Call `get` before running baseline checks and retain its `snapshot`. Run the
32
+ project's compiler/type checker and relevant behavior tests. Compare the exported
33
+ API and affected callers. If a check fails or is unavailable, record that fact;
34
+ do not label it passed or begin source work.
35
+
36
+ Submit `action: "blueprint"` with the returned `revision`, retained `snapshot`,
37
+ diagnostic evidence in `note`, baseline `checks`, and 1–12 ordered `steps`:
38
+
39
+ ```json
40
+ {
41
+ "title": "Capture diagnostic behavior",
42
+ "operation": "capture_tests",
43
+ "files": ["src/parser.rs", "tests/parser.rs"],
44
+ "boundary": "Add cases for existing diagnostics; preserve parsing behavior"
45
+ }
46
+ ```
47
+
48
+ The only staged operations are `capture_tests` and `extract_helper`. Name every
49
+ file a step can change, including planned new files, with repository-relative
50
+ paths. Keep each step small enough to review. Do not change generated code,
51
+ ownership or lifetime contracts, macros, import side effects, public APIs, or
52
+ configuration semantics as an incidental extraction. If those boundaries cannot
53
+ be justified, pause and explain the manual decision needed.
54
+
55
+ Every check has `kind` (`compiler`, `tests`, or `api`), `command`, `passed`, and
56
+ `evidence`. All three kinds are required. Evidence should include exact commands,
57
+ results/counts, and uncertainty. API evidence can be a documented source/caller
58
+ comparison when the project has no API-check command.
59
+
60
+ ## Execute one step
61
+
62
+ 1. Call `get`, inspect saved state, and send `action: "begin"` with `revision`,
63
+ `snapshot`, and one stable `agent_id`. The coordinator refuses overlapping
64
+ active runs and source changes between steps. Do not delegate overlapping edits.
65
+ 2. Make only the active step's bounded change. Preserve existing unrelated edits.
66
+ Do not commit during a run: a changed Git HEAD requires a fresh diagnosis.
67
+ 3. Call `get` after editing and **before** running the checks. Retain that snapshot,
68
+ run the compiler, tests, and API comparison, then send `action: "checkpoint"`
69
+ with that same `snapshot`, current `revision`, `agent_id`, `checks`, and `note`.
70
+ Never refresh the snapshot after tests merely to get past a stale-source gate.
71
+ 4. Inspect the response. A paused run is not a passed checkpoint. Stop editing
72
+ until the failure is understood. Keep failed evidence visible. To resume after
73
+ fixing the active step, obtain a fresh snapshot, rerun all checks, and send
74
+ `action: "resume"` with checks and an explanation, then checkpoint the step.
75
+ Restore an accidental scope escape without discarding someone else's work;
76
+ otherwise create a new diagnosis with an explicitly reviewed scope.
77
+ 5. Begin the next step only after the preceding checkpoint is accepted.
78
+
79
+ ## Verify
80
+
81
+ After every step is checked, the run enters Verify. Compare before/after
82
+ complexity, callers, public API, test results, and the actual diff. Get a snapshot,
83
+ run final checks, then submit `action: "complete"` with `revision`, `snapshot`,
84
+ `agent_id`, `checks`, and the comparison in `note`. State what remains unproven.
85
+
86
+ The Quality page shows saved stages, agent, scope, current tracked-file diff,
87
+ failed checks, and the final comparison. Closing the browser does not discard the
88
+ run. Use `pause` with a reason whenever the next safe step needs a decision.
@@ -5,6 +5,10 @@ description: "Compute the blast radius of modifying a symbol through transitive
5
5
 
6
6
  ## Overview
7
7
 
8
+ ### Choose the scope
9
+
10
+ Use this entry for a quick upstream/downstream blast radius. For the bundled pre-edit gate, including co-change, complexity, churn, and a verification checklist, use `memtrace-preflight`. Keep the narrower impact query available when a full preflight is unnecessary.
11
+
8
12
  Compute the blast radius of changing a specific symbol. Traces upstream (what depends on this) and downstream (what this depends on) through the knowledge graph to quantify risk before making modifications.
9
13
 
10
14
  ## Quick Reference