milens 0.6.5 → 0.6.7
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/.agents/skills/adapters/SKILL.md +14 -14
- package/.agents/skills/analyzer/SKILL.md +26 -24
- package/.agents/skills/apps/SKILL.md +10 -8
- package/.agents/skills/docs/SKILL.md +14 -8
- package/.agents/skills/milens/SKILL.md +164 -43
- package/.agents/skills/milens-security-review/SKILL.md +224 -224
- package/.agents/skills/orchestrator/SKILL.md +3 -1
- package/.agents/skills/parser/SKILL.md +16 -15
- package/.agents/skills/root/SKILL.md +20 -20
- package/.agents/skills/security/SKILL.md +1 -0
- package/.agents/skills/server/SKILL.md +13 -12
- package/.agents/skills/store/SKILL.md +12 -12
- package/.agents/skills/test/SKILL.md +57 -26
- package/README.md +170 -171
- package/adapters/claude-code/CLAUDE.md +36 -15
- package/adapters/codex/.codex/codex.md +38 -23
- package/adapters/copilot/.github/copilot-instructions.md +29 -22
- package/adapters/gemini/.gemini/context.md +33 -10
- package/adapters/opencode/AGENTS.md +36 -15
- package/dist/agents-md.d.ts.map +1 -1
- package/dist/agents-md.js +51 -2
- package/dist/agents-md.js.map +1 -1
- package/dist/analyzer/engine.d.ts +3 -0
- package/dist/analyzer/engine.d.ts.map +1 -1
- package/dist/analyzer/engine.js +342 -8
- package/dist/analyzer/engine.js.map +1 -1
- package/dist/analyzer/resolver.d.ts +2 -0
- package/dist/analyzer/resolver.d.ts.map +1 -1
- package/dist/analyzer/resolver.js +187 -9
- package/dist/analyzer/resolver.js.map +1 -1
- package/dist/analyzer/review.d.ts.map +1 -1
- package/dist/analyzer/review.js +254 -32
- package/dist/analyzer/review.js.map +1 -1
- package/dist/analyzer/scope-resolver.d.ts +42 -0
- package/dist/analyzer/scope-resolver.d.ts.map +1 -0
- package/dist/analyzer/scope-resolver.js +687 -0
- package/dist/analyzer/scope-resolver.js.map +1 -0
- package/dist/cli.js +294 -1
- package/dist/cli.js.map +1 -1
- package/dist/parser/extract.d.ts +6 -1
- package/dist/parser/extract.d.ts.map +1 -1
- package/dist/parser/extract.js +14 -2
- package/dist/parser/extract.js.map +1 -1
- package/dist/parser/lang-css.d.ts.map +1 -1
- package/dist/parser/lang-css.js +7 -1
- package/dist/parser/lang-css.js.map +1 -1
- package/dist/parser/lang-go.d.ts.map +1 -1
- package/dist/parser/lang-go.js +16 -0
- package/dist/parser/lang-go.js.map +1 -1
- package/dist/parser/lang-html.d.ts +4 -0
- package/dist/parser/lang-html.d.ts.map +1 -1
- package/dist/parser/lang-html.js +40 -1
- package/dist/parser/lang-html.js.map +1 -1
- package/dist/parser/lang-java.d.ts.map +1 -1
- package/dist/parser/lang-java.js +12 -0
- package/dist/parser/lang-java.js.map +1 -1
- package/dist/parser/lang-js.d.ts.map +1 -1
- package/dist/parser/lang-js.js +3 -0
- package/dist/parser/lang-js.js.map +1 -1
- package/dist/parser/lang-php.d.ts.map +1 -1
- package/dist/parser/lang-php.js +11 -0
- package/dist/parser/lang-php.js.map +1 -1
- package/dist/parser/lang-py.d.ts.map +1 -1
- package/dist/parser/lang-py.js +14 -0
- package/dist/parser/lang-py.js.map +1 -1
- package/dist/parser/lang-ruby.d.ts.map +1 -1
- package/dist/parser/lang-ruby.js +20 -0
- package/dist/parser/lang-ruby.js.map +1 -1
- package/dist/parser/lang-rust.d.ts.map +1 -1
- package/dist/parser/lang-rust.js +27 -4
- package/dist/parser/lang-rust.js.map +1 -1
- package/dist/parser/lang-ts.d.ts.map +1 -1
- package/dist/parser/lang-ts.js +3 -0
- package/dist/parser/lang-ts.js.map +1 -1
- package/dist/parser/lang-vue.d.ts +17 -1
- package/dist/parser/lang-vue.d.ts.map +1 -1
- package/dist/parser/lang-vue.js +177 -0
- package/dist/parser/lang-vue.js.map +1 -1
- package/dist/parser/language-provider.d.ts +27 -0
- package/dist/parser/language-provider.d.ts.map +1 -0
- package/dist/parser/language-provider.js +2 -0
- package/dist/parser/language-provider.js.map +1 -0
- package/dist/server/mcp.d.ts.map +1 -1
- package/dist/server/mcp.js +224 -50
- package/dist/server/mcp.js.map +1 -1
- package/dist/server/watcher.d.ts +8 -0
- package/dist/server/watcher.d.ts.map +1 -1
- package/dist/server/watcher.js +10 -8
- package/dist/server/watcher.js.map +1 -1
- package/dist/skills.js +163 -42
- package/dist/skills.js.map +1 -1
- package/dist/store/schema.sql +1 -1
- package/dist/ui/progress.d.ts +28 -0
- package/dist/ui/progress.d.ts.map +1 -0
- package/dist/ui/progress.js +100 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/uninstall.d.ts +54 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +795 -0
- package/dist/uninstall.js.map +1 -0
- package/docs/README.md +4 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lang-vue.js","sourceRoot":"","sources":["../../src/parser/lang-vue.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lang-vue.js","sourceRoot":"","sources":["../../src/parser/lang-vue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CodeSymbol, RawCall } from '../types.js';
|
|
2
|
+
export interface ParseContext {
|
|
3
|
+
filePath: string;
|
|
4
|
+
sourceDir: string;
|
|
5
|
+
rootPath: string;
|
|
6
|
+
}
|
|
7
|
+
export interface LanguageProvider {
|
|
8
|
+
/** Unique identifier (e.g. 'typescript', 'python') */
|
|
9
|
+
id: string;
|
|
10
|
+
/** File extensions this language handles (e.g. ['.ts', '.tsx']) */
|
|
11
|
+
extensions: string[];
|
|
12
|
+
/** Tree-sitter WASM module name */
|
|
13
|
+
wasmName: string;
|
|
14
|
+
/** All tree-sitter queries keyed by capture type */
|
|
15
|
+
treeSitterQueries: Record<string, string>;
|
|
16
|
+
/** How imports expose symbols to the importing file */
|
|
17
|
+
importSemantics: 'named' | 'wildcard-leaf' | 'wildcard-transitive' | 'namespace';
|
|
18
|
+
/** Method resolution order strategy for inheritance */
|
|
19
|
+
mroStrategy: 'first-wins' | 'c3' | 'ruby-mixin' | 'none';
|
|
20
|
+
/** Determine whether a symbol is exported in this language */
|
|
21
|
+
isExported(symbol: CodeSymbol, context: ParseContext): boolean;
|
|
22
|
+
/** Resolve a raw import string to a relative file path, or null if external */
|
|
23
|
+
resolveImport(raw: string, fromFile: string, root: string, aliases: Record<string, string>): string | null;
|
|
24
|
+
/** Optional: infer an implicit receiver for a call (e.g. `this` in JS) */
|
|
25
|
+
inferImplicitReceiver?(call: RawCall, context: ParseContext): string | null;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=language-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-provider.d.ts","sourceRoot":"","sources":["../../src/parser/language-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAC;IAEX,mEAAmE;IACnE,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IAEjB,oDAAoD;IACpD,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1C,uDAAuD;IACvD,eAAe,EAAE,OAAO,GAAG,eAAe,GAAG,qBAAqB,GAAG,WAAW,CAAC;IAEjF,uDAAuD;IACvD,WAAW,EAAE,YAAY,GAAG,IAAI,GAAG,YAAY,GAAG,MAAM,CAAC;IAEzD,8DAA8D;IAC9D,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC;IAE/D,+EAA+E;IAC/E,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IAE3G,0EAA0E;IAC1E,qBAAqB,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAAC;CAC7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-provider.js","sourceRoot":"","sources":["../../src/parser/language-provider.ts"],"names":[],"mappings":""}
|
package/dist/server/mcp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/server/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/server/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAmatF,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CA+0E5D;AAwGD,wBAAsB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCjE;AAID,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6G9E"}
|
package/dist/server/mcp.js
CHANGED
|
@@ -21,6 +21,7 @@ import { loadRules } from '../security/rules.js';
|
|
|
21
21
|
import { HookManager, defaultOnSessionStart, defaultOnSessionEnd, defaultOnPreCommit, defaultOnFileChange, defaultOnPreCompact, defaultOnPostCompact } from './hooks.js';
|
|
22
22
|
import { Orchestrator } from '../orchestrator/orchestrator.js';
|
|
23
23
|
import { FileWatcher } from './watcher.js';
|
|
24
|
+
import { reviewPr } from '../analyzer/review.js';
|
|
24
25
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
25
26
|
const PKG_VERSION = process.env.MILENS_VERSION ?? JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf-8')).version;
|
|
26
27
|
// ── Lazy DB connection with idle eviction ──
|
|
@@ -89,6 +90,30 @@ class LazyDb {
|
|
|
89
90
|
this.instance = null;
|
|
90
91
|
}
|
|
91
92
|
}
|
|
93
|
+
// ── Session-level edit safety guard ──
|
|
94
|
+
class SessionGuard {
|
|
95
|
+
/** sessionId → Set of symbol names that had safety checks performed */
|
|
96
|
+
checks = new Map();
|
|
97
|
+
/** sessionId → total edit operations attempted (reported by agent) */
|
|
98
|
+
editOps = new Map();
|
|
99
|
+
recordCheck(sessionId, symbolName) {
|
|
100
|
+
if (!this.checks.has(sessionId))
|
|
101
|
+
this.checks.set(sessionId, new Set());
|
|
102
|
+
this.checks.get(sessionId).add(symbolName);
|
|
103
|
+
}
|
|
104
|
+
recordEditOp(sessionId) {
|
|
105
|
+
this.editOps.set(sessionId, (this.editOps.get(sessionId) ?? 0) + 1);
|
|
106
|
+
}
|
|
107
|
+
getAudit(sessionId) {
|
|
108
|
+
const checked = [...(this.checks.get(sessionId) ?? [])];
|
|
109
|
+
const ops = this.editOps.get(sessionId) ?? 0;
|
|
110
|
+
return { checked, editOps: ops };
|
|
111
|
+
}
|
|
112
|
+
clear(sessionId) {
|
|
113
|
+
this.checks.delete(sessionId);
|
|
114
|
+
this.editOps.delete(sessionId);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
92
117
|
// ── Tool usage tracking ──
|
|
93
118
|
// Estimated tokens an agent would spend WITHOUT milens (manual exploration cost per tool)
|
|
94
119
|
const TOKEN_SAVINGS_MULTIPLIER = {
|
|
@@ -317,7 +342,24 @@ function loadGrepIgnoreRules(rootPath) {
|
|
|
317
342
|
return ig;
|
|
318
343
|
}
|
|
319
344
|
// ── Server instructions (sent to client via MCP protocol on initialize) ──
|
|
320
|
-
const MILENS_INSTRUCTIONS =
|
|
345
|
+
const MILENS_INSTRUCTIONS = `⚠️ CRITICAL: This project is indexed by milens (knowledge graph). Use milens MCP tools BEFORE reading files directly.
|
|
346
|
+
|
|
347
|
+
WHY: The knowledge graph already knows every symbol, dependency, and reference. Reading files manually = slower, more expensive, and misses hidden connections.
|
|
348
|
+
|
|
349
|
+
RULE: Before opening ANY file to understand code, call the appropriate milens tool:
|
|
350
|
+
- overview({name: "X"}) — understand a symbol (context + impact + grep). Replaces 3-5 file reads.
|
|
351
|
+
- impact({target: "X", mode: "strict"}) — check blast radius BEFORE editing. strict mode BLOCKS if >5 deps.
|
|
352
|
+
- guard_edit_check({name: "X", session_id}) — HARD safety gate. Call BEFORE every edit. Returns BLOCKED if high risk.
|
|
353
|
+
- grep({pattern: "X"}) — find ALL text references (code, templates, docs, configs, styles).
|
|
354
|
+
- codebase_summary() — 500-token project overview. Use INSTEAD of reading README or exploring directories.
|
|
355
|
+
- detect_changes() — verify changes before committing. Shows changed symbols + risk scores.
|
|
356
|
+
- query({query: "X"}) — find symbol definitions by name. FTS5 instant search.
|
|
357
|
+
|
|
358
|
+
AUDIT: session_end reports which symbols were safety-checked. Editing without checks = audit gap.
|
|
359
|
+
|
|
360
|
+
TOKEN SAVINGS: Using milens first = 70% fewer tokens, zero missed dependencies.
|
|
361
|
+
|
|
362
|
+
milens — code intelligence engine. Indexes codebases into symbol graphs.
|
|
321
363
|
|
|
322
364
|
## Tool selection
|
|
323
365
|
- \`query\` — find symbol definitions (code identifiers only)
|
|
@@ -325,6 +367,7 @@ const MILENS_INSTRUCTIONS = `milens — code intelligence engine. Indexes codeba
|
|
|
325
367
|
- \`context\` — 360° view: incoming + outgoing for a symbol
|
|
326
368
|
- \`impact\` — blast radius: what breaks if symbol changes
|
|
327
369
|
- \`overview\` — combined context + impact + grep in one call (preferred for editing workflows)
|
|
370
|
+
- \`guard_edit_check\` — HARD pre-edit gate: blocks if dependents > 5, tracks checks for session audit
|
|
328
371
|
- \`edit_check\` — pre-edit safety: callers + export status + re-export chains + test coverage + ⚠ warnings (fastest for edits)
|
|
329
372
|
- \`trace\` — execution flow: call chains from entrypoints to a symbol (or downstream from it)
|
|
330
373
|
- \`routes\` — detect framework routes/endpoints (Express, FastAPI, NestJS, Flask, Go, PHP, Rails)
|
|
@@ -338,7 +381,9 @@ const MILENS_INSTRUCTIONS = `milens — code intelligence engine. Indexes codeba
|
|
|
338
381
|
- \`get_type_hierarchy\` — inheritance tree
|
|
339
382
|
|
|
340
383
|
## Rules
|
|
341
|
-
- Before editing a symbol: run \`edit_check\` or \`smart_context\` with intent=edit
|
|
384
|
+
- Before editing a symbol: run \`guard_edit_check\` or \`edit_check\` or \`smart_context\` with intent=edit
|
|
385
|
+
- \`guard_edit_check({name, session_id})\` — HARD gate: records check for audit, blocks if dependents > 5
|
|
386
|
+
- \`impact({mode: "strict"})\` — strict mode returns BLOCKED when depth-1 deps > 5
|
|
342
387
|
- For debugging: run \`smart_context\` with intent=debug or \`trace\` to=symbol
|
|
343
388
|
- For writing tests: run \`smart_context\` with intent=test — shows deps to mock + callers to cover
|
|
344
389
|
- \`impact\` only tracks code deps — always pair with \`grep\` for templates/configs
|
|
@@ -359,6 +404,7 @@ export function createMcpServer(rootPath) {
|
|
|
359
404
|
const registry = new RepoRegistry();
|
|
360
405
|
const pools = new Map();
|
|
361
406
|
const trackDb = getTrackingDb();
|
|
407
|
+
const guard = new SessionGuard();
|
|
362
408
|
function normalizePath(p) {
|
|
363
409
|
const abs = resolve(p);
|
|
364
410
|
if (process.platform === 'win32') {
|
|
@@ -458,7 +504,7 @@ export function createMcpServer(rootPath) {
|
|
|
458
504
|
});
|
|
459
505
|
}
|
|
460
506
|
// ── Tool: query ──
|
|
461
|
-
server.tool('query', '
|
|
507
|
+
server.tool('query', 'Find symbol definitions by name (FTS5 instant search). Use instead of reading files to find where a function/class is defined. For text in templates/configs/docs, use `grep`.', {
|
|
462
508
|
query: z.string().describe('Symbol name, kind, or keyword to search'),
|
|
463
509
|
repo: z.string().optional().describe('Repository root path (optional if only one indexed)'),
|
|
464
510
|
limit: z.number().optional().default(15).describe('Max results'),
|
|
@@ -472,10 +518,10 @@ export function createMcpServer(rootPath) {
|
|
|
472
518
|
return { content: [{ type: 'text', text }] };
|
|
473
519
|
});
|
|
474
520
|
// ── Tool: grep ──
|
|
475
|
-
server.tool('grep', '
|
|
476
|
-
pattern: z.string().describe('Text
|
|
521
|
+
server.tool('grep', 'Find EVERY text occurrence across ALL project files. Searches code, templates, styles, configs, docs — not just symbol definitions. Use INSTEAD of built-in search tools which may miss non-code files. ⚠️ IMPORTANT: Default is LITERAL mode (isRegex: false). Characters like | . * + ? are treated as literal text, NOT regex. To use regex alternation or wildcards, set isRegex: true.', {
|
|
522
|
+
pattern: z.string().describe('Text OR regex pattern to search for. ⚠️ Default is LITERAL: characters | . * + ? ( ) are escaped as plain text. To use regex, set isRegex: true.'),
|
|
477
523
|
repo: z.string().optional().describe('Repository root path (optional)'),
|
|
478
|
-
isRegex: z.boolean().optional().default(false).describe('
|
|
524
|
+
isRegex: z.boolean().optional().default(false).describe('Set to true for regex patterns. Default false: special chars like | . * are treated as literal text.'),
|
|
479
525
|
caseSensitive: z.boolean().optional().default(false),
|
|
480
526
|
include: z.string().optional().describe('Glob filter for file paths (e.g. "**/*.vue", "*.scss")'),
|
|
481
527
|
scope: z.enum(['all', 'code', 'imports', 'definitions']).optional().default('all')
|
|
@@ -493,8 +539,14 @@ export function createMcpServer(rootPath) {
|
|
|
493
539
|
const filtered = scope === 'all' || scope === 'code'
|
|
494
540
|
? matches
|
|
495
541
|
: matches.filter(m => matchesScope(m.text, scope));
|
|
542
|
+
// Detect regex-like patterns used in literal mode (hint BEFORE result output)
|
|
543
|
+
const regexChars = /[|.*+?(){}\[\]]/;
|
|
544
|
+
const regexHint = (!isRegex && regexChars.test(pattern))
|
|
545
|
+
? `⚠️ HINT: Pattern "${pattern}" contains special regex characters (${pattern.match(regexChars).join(' ')}). Default is LITERAL mode — these are escaped as plain text. To use as regex, add isRegex: true.\n\n`
|
|
546
|
+
: '';
|
|
496
547
|
if (filtered.length === 0) {
|
|
497
|
-
|
|
548
|
+
const hintBlock = regexHint + `No matches for "${pattern}"${scope !== 'all' ? ` (scope: ${scope})` : ''}`;
|
|
549
|
+
return { content: [{ type: 'text', text: hintBlock }] };
|
|
498
550
|
}
|
|
499
551
|
// Group by file for compact output
|
|
500
552
|
const grouped = new Map();
|
|
@@ -503,7 +555,10 @@ export function createMcpServer(rootPath) {
|
|
|
503
555
|
arr.push({ line: m.line, text: m.text });
|
|
504
556
|
grouped.set(m.file, arr);
|
|
505
557
|
}
|
|
506
|
-
const lines = [
|
|
558
|
+
const lines = [];
|
|
559
|
+
if (regexHint)
|
|
560
|
+
lines.push(regexHint);
|
|
561
|
+
lines.push(`${filtered.length} matches in ${grouped.size} files${scope !== 'all' ? ` (scope: ${scope})` : ''}:\n`);
|
|
507
562
|
for (const [file, hits] of grouped) {
|
|
508
563
|
lines.push(file);
|
|
509
564
|
for (const h of hits) {
|
|
@@ -516,7 +571,7 @@ export function createMcpServer(rootPath) {
|
|
|
516
571
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
517
572
|
});
|
|
518
573
|
// ── Tool: context ──
|
|
519
|
-
server.tool('context', '
|
|
574
|
+
server.tool('context', '360° view of a symbol: who calls it + what it depends on. Instant dependency graph. Use INSTEAD of reading multiple files to trace call chains manually — catches cross-file imports you would miss.', {
|
|
520
575
|
name: z.string().describe('Symbol name to inspect'),
|
|
521
576
|
repo: z.string().optional(),
|
|
522
577
|
detail: z.enum(['L0', 'L1', 'L2']).optional().default('L1').describe('Output detail: L0=names only, L1=default, L2=full metadata'),
|
|
@@ -554,13 +609,14 @@ export function createMcpServer(rootPath) {
|
|
|
554
609
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
555
610
|
});
|
|
556
611
|
// ── Tool: impact ──
|
|
557
|
-
server.tool('impact', '
|
|
612
|
+
server.tool('impact', 'Exact blast radius BEFORE you edit. Shows which symbols WILL BREAK if you change a target. Use instead of guessing or manually tracing dependencies. Code deps only — pair with `grep` for templates/configs.', {
|
|
558
613
|
target: z.string().describe('Symbol name to analyze'),
|
|
559
614
|
direction: z.enum(['upstream', 'downstream']).default('upstream'),
|
|
560
615
|
depth: z.number().optional().default(3),
|
|
561
616
|
repo: z.string().optional(),
|
|
562
617
|
detail: z.enum(['L0', 'L1', 'L2']).optional().default('L1').describe('Output detail: L0=names only, L1=default, L2=full metadata'),
|
|
563
|
-
|
|
618
|
+
mode: z.enum(['normal', 'strict']).optional().default('normal').describe('strict=BLOCKED if depth-1 dependents > 5, normal=report only'),
|
|
619
|
+
}, async ({ target, direction, depth, repo, detail, mode }) => {
|
|
564
620
|
const { db } = getDb(repo);
|
|
565
621
|
const symbols = db.findSymbolByName(target);
|
|
566
622
|
if (symbols.length === 0) {
|
|
@@ -576,8 +632,18 @@ export function createMcpServer(rootPath) {
|
|
|
576
632
|
lines.push(`No ${direction} deps found.`);
|
|
577
633
|
}
|
|
578
634
|
else {
|
|
579
|
-
|
|
635
|
+
const depth1Count = refs.filter(r => r.depth === 1).length;
|
|
636
|
+
lines.push(`${direction} (${refs.length} symbols, depth-1: ${depth1Count}):`);
|
|
580
637
|
lines.push(fmtImpact(refs, detail));
|
|
638
|
+
// Strict mode: hard stop if depth-1 dependents > 5
|
|
639
|
+
if (mode === 'strict' && direction === 'upstream' && depth1Count > 5) {
|
|
640
|
+
lines.push('');
|
|
641
|
+
lines.push('---');
|
|
642
|
+
lines.push(`⚠️ BLOCKED: ${depth1Count} direct dependents (>5 threshold).`);
|
|
643
|
+
lines.push('Editing this symbol may cause cascading breakage.');
|
|
644
|
+
lines.push('To proceed: re-run with mode="normal" or explicitly acknowledge the risk.');
|
|
645
|
+
lines.push('---');
|
|
646
|
+
}
|
|
581
647
|
}
|
|
582
648
|
lines.push('');
|
|
583
649
|
}
|
|
@@ -648,7 +714,7 @@ export function createMcpServer(rootPath) {
|
|
|
648
714
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
649
715
|
});
|
|
650
716
|
// ── Tool: overview ──
|
|
651
|
-
server.tool('overview', 'Combined context + impact + grep
|
|
717
|
+
server.tool('overview', 'ONE call replaces 3-5 file reads. Combined context + impact + grep. Use BEFORE reading any source file. Saves 70% tokens vs reading files individually. Preferred before editing/deleting/renaming a symbol.', {
|
|
652
718
|
name: z.string().describe('Symbol name'),
|
|
653
719
|
repo: z.string().optional(),
|
|
654
720
|
depth: z.number().optional().default(2).describe('Impact traversal depth (default: 2)'),
|
|
@@ -762,7 +828,7 @@ export function createMcpServer(rootPath) {
|
|
|
762
828
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
763
829
|
});
|
|
764
830
|
// ── Tool: detect_changes ──
|
|
765
|
-
server.tool('detect_changes', '
|
|
831
|
+
server.tool('detect_changes', 'Pre-commit safety check. Uses git diff to show which symbols changed + their direct dependents + risk. Use INSTEAD of manually running `git diff` before every commit.', {
|
|
766
832
|
ref: z.string().optional().default('HEAD').describe('Git ref to diff against (default: HEAD)'),
|
|
767
833
|
repo: z.string().optional(),
|
|
768
834
|
}, async ({ ref, repo }) => {
|
|
@@ -919,6 +985,20 @@ export function createMcpServer(rootPath) {
|
|
|
919
985
|
lines.push(`${sym.name} [${sym.kind}] L${sym.startLine}-${sym.endLine}${exp} ← ${incoming.length} refs, → ${outgoing.length} deps`);
|
|
920
986
|
}
|
|
921
987
|
}
|
|
988
|
+
// File-path auto-suggest: domain hint
|
|
989
|
+
const parts = file.replace(/\\/g, '/').split('/');
|
|
990
|
+
let areaName = 'root';
|
|
991
|
+
if (parts.length > 1) {
|
|
992
|
+
if (parts[0] === 'src') {
|
|
993
|
+
areaName = parts.length > 2 ? parts[1] : 'root';
|
|
994
|
+
}
|
|
995
|
+
else {
|
|
996
|
+
areaName = parts[0];
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (areaName !== 'root') {
|
|
1000
|
+
lines.push(`\n💡 This file is in the '${areaName}' domain. Load skill 'milens-${areaName}' for key symbols and dependencies.`);
|
|
1001
|
+
}
|
|
922
1002
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
923
1003
|
});
|
|
924
1004
|
// ── Tool: get_type_hierarchy ──
|
|
@@ -955,7 +1035,7 @@ export function createMcpServer(rootPath) {
|
|
|
955
1035
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
956
1036
|
});
|
|
957
1037
|
// ── Tool: edit_check ──
|
|
958
|
-
server.tool('edit_check', '
|
|
1038
|
+
server.tool('edit_check', 'Fast pre-edit safety. Shows callers, export status, re-export chains, test coverage, and ⚠ warnings. Use BEFORE modifying any function/class/method — catches hidden risks you would miss.', {
|
|
959
1039
|
name: z.string().describe('Symbol name to check before editing'),
|
|
960
1040
|
repo: z.string().optional(),
|
|
961
1041
|
}, async ({ name, repo }) => {
|
|
@@ -1024,6 +1104,95 @@ export function createMcpServer(rootPath) {
|
|
|
1024
1104
|
}
|
|
1025
1105
|
return { content: [{ type: 'text', text: sections.join('\n') }] };
|
|
1026
1106
|
});
|
|
1107
|
+
// ── Tool: guard_edit_check ──
|
|
1108
|
+
server.tool('guard_edit_check', 'HARD pre-edit safety gate. Call BEFORE every edit operation — tracks checks for session audit. If dependents > 5, returns BLOCKED status requiring explicit confirmation. Combines edit_check with enforcement tracking.', {
|
|
1109
|
+
name: z.string().describe('Symbol name to check before editing'),
|
|
1110
|
+
repo: z.string().optional(),
|
|
1111
|
+
session_id: z.string().optional().describe('Session ID for audit tracking'),
|
|
1112
|
+
confirm: z.string().optional().describe('Type "I understand the risk" to bypass a BLOCKED result'),
|
|
1113
|
+
}, async ({ name, repo, session_id, confirm }) => {
|
|
1114
|
+
const { db, root } = getDb(repo);
|
|
1115
|
+
const symbols = db.findSymbolByName(name);
|
|
1116
|
+
const sections = [];
|
|
1117
|
+
if (symbols.length === 0) {
|
|
1118
|
+
return { content: [{ type: 'text', text: `"${name}" not found in index. Try \`grep\` to find it in templates/docs first.` }] };
|
|
1119
|
+
}
|
|
1120
|
+
for (const sym of symbols) {
|
|
1121
|
+
sections.push(`${fmtSymbol(sym)}${sym.exported ? ' (exported)' : ''}`);
|
|
1122
|
+
const incoming = db.getIncomingLinks(sym.id).filter(l => l.type !== 'contains');
|
|
1123
|
+
const depsCount = incoming.filter(l => {
|
|
1124
|
+
const from = db.findSymbolById(l.fromId);
|
|
1125
|
+
return from && !isTestFilePath(from.filePath);
|
|
1126
|
+
}).length;
|
|
1127
|
+
if (session_id)
|
|
1128
|
+
guard.recordCheck(session_id, name);
|
|
1129
|
+
// Hard stop: if > 5 non-test dependents and no confirmation
|
|
1130
|
+
if (depsCount > 5 && confirm !== 'I understand the risk') {
|
|
1131
|
+
sections.push(`⚠️ BLOCKED: ${name} has ${depsCount} non-test dependents (>5 threshold).`);
|
|
1132
|
+
sections.push(`Direct callers (${incoming.length} total):`);
|
|
1133
|
+
for (const l of incoming) {
|
|
1134
|
+
const from = db.findSymbolById(l.fromId);
|
|
1135
|
+
sections.push(` ${l.type}: ${from ? fmtSymbol(from) : l.fromId}`);
|
|
1136
|
+
}
|
|
1137
|
+
sections.push('');
|
|
1138
|
+
sections.push(`To proceed, re-call with confirm: "I understand the risk"`);
|
|
1139
|
+
sections.push(`Or: run \`impact({target: "${name}", depth: 2})\` to see full blast radius.`);
|
|
1140
|
+
}
|
|
1141
|
+
else {
|
|
1142
|
+
// Safe to edit or explicitly confirmed
|
|
1143
|
+
const status = depsCount > 5 ? '⚠️ CONFIRMED (high risk)' : '✅ Safe to edit';
|
|
1144
|
+
sections.push(`${status} — ${depsCount} non-test dependents`);
|
|
1145
|
+
if (incoming.length > 0) {
|
|
1146
|
+
sections.push(`callers (${incoming.length}):`);
|
|
1147
|
+
for (const l of incoming) {
|
|
1148
|
+
const from = db.findSymbolById(l.fromId);
|
|
1149
|
+
sections.push(` ${l.type}: ${from ? fmtSymbol(from) : l.fromId}`);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
sections.push(`callers: none`);
|
|
1154
|
+
}
|
|
1155
|
+
// Export chain
|
|
1156
|
+
const grepMatches = grepFiles(root, name, { maxResults: 5, includePattern: '**/index.{ts,js,mjs}' });
|
|
1157
|
+
const reExportMatches = grepMatches.filter(m => /export\s*\{[^}]*/.test(m.text) && m.text.includes('from'));
|
|
1158
|
+
if (reExportMatches.length > 0) {
|
|
1159
|
+
sections.push(`re-exported via:`);
|
|
1160
|
+
for (const m of reExportMatches) {
|
|
1161
|
+
sections.push(` ${m.file}:${m.line}`);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
// Heritage
|
|
1165
|
+
const descendants = db.getTypeHierarchy(sym.id).descendants;
|
|
1166
|
+
if (descendants.length > 0) {
|
|
1167
|
+
sections.push(`⚠ inherited by ${descendants.length} types:`);
|
|
1168
|
+
for (const { symbol: d } of descendants) {
|
|
1169
|
+
sections.push(` ${fmtSymbol(d)}`);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
// Test coverage
|
|
1173
|
+
const testRefs = incoming.filter(l => {
|
|
1174
|
+
const from = db.findSymbolById(l.fromId);
|
|
1175
|
+
return from && isTestFilePath(from.filePath);
|
|
1176
|
+
});
|
|
1177
|
+
if (testRefs.length > 0) {
|
|
1178
|
+
const testFiles = [...new Set(testRefs.map(l => {
|
|
1179
|
+
const from = db.findSymbolById(l.fromId);
|
|
1180
|
+
return from?.filePath;
|
|
1181
|
+
}).filter(Boolean))];
|
|
1182
|
+
sections.push(`✓ tested from: ${testFiles.join(', ')}`);
|
|
1183
|
+
}
|
|
1184
|
+
else if (sym.exported) {
|
|
1185
|
+
sections.push(`⚠ no test coverage for this exported symbol`);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
// Unresolved warning
|
|
1190
|
+
const unresolved = db.getUnresolvedStats();
|
|
1191
|
+
if (unresolved.imports > 0 || unresolved.calls > 0) {
|
|
1192
|
+
sections.push(`⚠ index has ${unresolved.imports} unresolved internal imports, ${unresolved.calls} unresolved internal calls — callers list may be incomplete`);
|
|
1193
|
+
}
|
|
1194
|
+
return { content: [{ type: 'text', text: sections.join('\n') }] };
|
|
1195
|
+
});
|
|
1027
1196
|
// ── Tool: trace ──
|
|
1028
1197
|
server.tool('trace', 'Trace execution flow: find call chains from entrypoints to a target symbol, or from a symbol downstream. Shows HOW code gets executed.', {
|
|
1029
1198
|
name: z.string().describe('Symbol name to trace'),
|
|
@@ -1401,7 +1570,7 @@ export function createMcpServer(rootPath) {
|
|
|
1401
1570
|
}
|
|
1402
1571
|
});
|
|
1403
1572
|
// ═══ codebase_summary ═══
|
|
1404
|
-
server.tool('codebase_summary', '
|
|
1573
|
+
server.tool('codebase_summary', '500-token project overview. Use at session start INSTEAD of reading README, exploring directory structure, or reading multiple files to understand the codebase. Returns domains, key symbols, coverage %.', { repo: z.string().optional() }, async ({ repo }) => {
|
|
1405
1574
|
const { db } = getDb(repo);
|
|
1406
1575
|
const summary = db.getCodebaseSummary();
|
|
1407
1576
|
const lines = [
|
|
@@ -1431,43 +1600,23 @@ export function createMcpServer(rootPath) {
|
|
|
1431
1600
|
// ═══ review_pr ═══
|
|
1432
1601
|
server.tool('review_pr', 'PR risk assessment: git diff -> affected symbols with risk scores (LOW/MEDIUM/HIGH/CRITICAL).', { ref: z.string().optional().default('HEAD'), repo: z.string().optional() }, async ({ ref, repo }) => {
|
|
1433
1602
|
const { db, root } = getDb(repo);
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
const { execSync } = await import('node:child_process');
|
|
1437
|
-
const diff = execSync(`git diff --name-only ${ref}`, { cwd: root, encoding: 'utf-8' }).trim();
|
|
1438
|
-
changedFiles = diff ? diff.split('\n').filter(Boolean) : [];
|
|
1439
|
-
}
|
|
1440
|
-
catch { }
|
|
1441
|
-
if (changedFiles.length === 0) {
|
|
1603
|
+
const result = reviewPr(db, root, ref);
|
|
1604
|
+
if (result.changedFiles.length === 0) {
|
|
1442
1605
|
return { content: [{ type: 'text', text: 'No changed files detected.' }] };
|
|
1443
1606
|
}
|
|
1444
1607
|
const allAffected = [];
|
|
1445
|
-
for (const
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
const heat = sym.heat ?? 0;
|
|
1453
|
-
const hasTest = db.getSymbolTestCoverage(sym.id);
|
|
1454
|
-
const score = Math.round((heat / 100) * 40 + Math.min(depsCount / 10, 1) * 35 + (hasTest ? 0 : 25));
|
|
1455
|
-
let level = 'LOW';
|
|
1456
|
-
if (score > 75)
|
|
1457
|
-
level = 'CRITICAL';
|
|
1458
|
-
else if (score > 50)
|
|
1459
|
-
level = 'HIGH';
|
|
1460
|
-
else if (score > 25)
|
|
1461
|
-
level = 'MEDIUM';
|
|
1462
|
-
allAffected.push({ symbol: sym.name, kind: sym.kind, file: sym.filePath, heat, dependents: depsCount, hasTest, riskScore: score, riskLevel: level });
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
allAffected.sort((a, b) => b.riskScore - a.riskScore);
|
|
1608
|
+
for (const s of result.symbols) {
|
|
1609
|
+
allAffected.push({
|
|
1610
|
+
symbol: s.symbol.name, kind: s.symbol.kind, file: s.symbol.filePath,
|
|
1611
|
+
heat: s.symbol.heat ?? 0, dependents: s.dependents,
|
|
1612
|
+
hasTest: s.tested, riskScore: s.riskScore, riskLevel: s.riskLevel,
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1466
1615
|
const summary = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
|
|
1467
1616
|
for (const a of allAffected)
|
|
1468
1617
|
summary[a.riskLevel]++;
|
|
1469
1618
|
const lines = [`PR Risk Assessment (vs ${ref}):\n`];
|
|
1470
|
-
lines.push(`${changedFiles.length} changed files, ${allAffected.length} affected symbols\n`);
|
|
1619
|
+
lines.push(`${result.changedFiles.length} changed files, ${allAffected.length} affected symbols\n`);
|
|
1471
1620
|
for (const a of allAffected.slice(0, 30)) {
|
|
1472
1621
|
lines.push(` ${a.symbol} [${a.kind}] ${a.file} — heat:${a.heat} deps:${a.dependents} test:${a.hasTest ? 'yes' : 'no'} → ${a.riskLevel}(${a.riskScore})`);
|
|
1473
1622
|
}
|
|
@@ -1644,10 +1793,13 @@ export function createMcpServer(rootPath) {
|
|
|
1644
1793
|
return { content: [{ type: 'text', text: lines.join('\n') }] };
|
|
1645
1794
|
});
|
|
1646
1795
|
// ═══ session_end ═══
|
|
1647
|
-
server.tool('session_end', 'End a session and record its stats. Use at the end of every session.', { session_id: z.string(), status: z.enum(['completed', 'failed']).optional().default('completed') }, async ({ session_id, status }) => {
|
|
1796
|
+
server.tool('session_end', 'End a session and record its stats. Shows audit trail: which symbols were safety-checked vs total edit operations. Use at the end of every session.', { session_id: z.string(), status: z.enum(['completed', 'failed']).optional().default('completed') }, async ({ session_id, status }) => {
|
|
1648
1797
|
const { db, root, dbPath } = getDb();
|
|
1649
1798
|
const store = new AnnotationStore(db.connection);
|
|
1650
1799
|
const summary = store.sessionEnd(session_id, status);
|
|
1800
|
+
// Audit trail from SessionGuard
|
|
1801
|
+
const audit = guard.getAudit(session_id);
|
|
1802
|
+
guard.clear(session_id);
|
|
1651
1803
|
let hookOutput = '';
|
|
1652
1804
|
try {
|
|
1653
1805
|
const ctx = store.sessionContext(session_id);
|
|
@@ -1658,7 +1810,17 @@ export function createMcpServer(rootPath) {
|
|
|
1658
1810
|
}
|
|
1659
1811
|
}
|
|
1660
1812
|
catch { /* hooks are best-effort */ }
|
|
1661
|
-
const
|
|
1813
|
+
const lines = [
|
|
1814
|
+
`Session ended: ${session_id}`,
|
|
1815
|
+
`Status: ${status}`,
|
|
1816
|
+
`Annotations: ${summary.annotationCount}`,
|
|
1817
|
+
`───`,
|
|
1818
|
+
`Audit Trail:`,
|
|
1819
|
+
` safety checks performed: ${audit.checked.length}`,
|
|
1820
|
+
audit.checked.length > 0 ? ` symbols checked: ${audit.checked.join(', ')}` : ' ⚠ no symbols were checked via guard_edit_check',
|
|
1821
|
+
audit.editOps > 0 ? ` edit operations reported: ${audit.editOps}` : null,
|
|
1822
|
+
].filter(Boolean);
|
|
1823
|
+
const text = lines.join('\n');
|
|
1662
1824
|
return { content: [{ type: 'text', text: hookOutput ? `${text}\n\n${hookOutput}` : text }] };
|
|
1663
1825
|
});
|
|
1664
1826
|
// ═══ handoff ═══
|
|
@@ -2320,7 +2482,13 @@ export async function startStdio(rootPath) {
|
|
|
2320
2482
|
const hookMgr = new HookManager();
|
|
2321
2483
|
const hookConfig = hookMgr.loadConfig(rootPath);
|
|
2322
2484
|
if (hookConfig.enabled && hookConfig.onFileChange) {
|
|
2323
|
-
watcher = new FileWatcher({
|
|
2485
|
+
watcher = new FileWatcher({
|
|
2486
|
+
rootPath,
|
|
2487
|
+
dbPath: entry.dbPath,
|
|
2488
|
+
logger: (_level, msg) => {
|
|
2489
|
+
server.server.sendLoggingMessage({ level: 'info', data: msg });
|
|
2490
|
+
},
|
|
2491
|
+
});
|
|
2324
2492
|
watcher.start();
|
|
2325
2493
|
}
|
|
2326
2494
|
}
|
|
@@ -2349,7 +2517,13 @@ export async function startHttp(port, rootPath) {
|
|
|
2349
2517
|
const hookMgr = new HookManager();
|
|
2350
2518
|
const hookConfig = hookMgr.loadConfig(rootPath);
|
|
2351
2519
|
if (hookConfig.enabled && hookConfig.onFileChange) {
|
|
2352
|
-
watcher = new FileWatcher({
|
|
2520
|
+
watcher = new FileWatcher({
|
|
2521
|
+
rootPath,
|
|
2522
|
+
dbPath: entry.dbPath,
|
|
2523
|
+
logger: (_level, msg) => {
|
|
2524
|
+
server.server.sendLoggingMessage({ level: 'info', data: msg });
|
|
2525
|
+
},
|
|
2526
|
+
});
|
|
2353
2527
|
watcher.start();
|
|
2354
2528
|
}
|
|
2355
2529
|
}
|