milens 0.6.7 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -13
- package/adapters/claude-code/.claude/mcp.json +2 -2
- package/adapters/claude-code/CLAUDE.md +1 -1
- package/adapters/gemini/.gemini/context.md +2 -2
- package/adapters/opencode/.opencode/config.json +2 -3
- package/adapters/zed/.zed/settings.json +1 -1
- package/dist/agents-md.d.ts +1 -0
- package/dist/agents-md.d.ts.map +1 -1
- package/dist/agents-md.js +50 -1
- package/dist/agents-md.js.map +1 -1
- package/dist/analyzer/engine.d.ts +2 -0
- package/dist/analyzer/engine.d.ts.map +1 -1
- package/dist/analyzer/engine.js +56 -24
- package/dist/analyzer/engine.js.map +1 -1
- package/dist/analyzer/resolver.js +5 -2
- package/dist/analyzer/resolver.js.map +1 -1
- package/dist/analyzer/review.d.ts.map +1 -1
- package/dist/analyzer/review.js +5 -1
- package/dist/analyzer/review.js.map +1 -1
- package/dist/analyzer/scope-resolver.d.ts.map +1 -1
- package/dist/analyzer/scope-resolver.js +45 -4
- package/dist/analyzer/scope-resolver.js.map +1 -1
- package/dist/cli.js +33 -15
- package/dist/cli.js.map +1 -1
- package/dist/security/rules.d.ts +2 -1
- package/dist/security/rules.d.ts.map +1 -1
- package/dist/security/rules.js +276 -61
- package/dist/security/rules.js.map +1 -1
- package/dist/server/mcp.d.ts.map +1 -1
- package/dist/server/mcp.js +84 -19
- package/dist/server/mcp.js.map +1 -1
- package/dist/server/test-plan.d.ts +1 -1
- package/dist/server/test-plan.d.ts.map +1 -1
- package/dist/server/test-plan.js +48 -4
- package/dist/server/test-plan.js.map +1 -1
- package/dist/store/db.d.ts.map +1 -1
- package/dist/store/db.js +18 -16
- package/dist/store/db.js.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/progress.d.ts +6 -18
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +40 -94
- package/dist/ui/progress.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
<a href="https://github.com/fuze210699/milens/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="license"></a>
|
|
10
10
|
<img src="https://img.shields.io/badge/tools-43-purple" alt="43 tools">
|
|
11
11
|
<img src="https://img.shields.io/badge/languages-12-blue" alt="12 languages">
|
|
12
|
-
<img src="https://img.shields.io/badge/prompts-
|
|
13
|
-
<img src="https://img.shields.io/badge/security-
|
|
12
|
+
<img src="https://img.shields.io/badge/prompts-6-orange" alt="6 prompts">
|
|
13
|
+
<img src="https://img.shields.io/badge/security-190%2B-red" alt="190+ rules">
|
|
14
14
|
<img src="https://img.shields.io/badge/harnesses-7-lightgrey" alt="7 harnesses">
|
|
15
15
|
</p>
|
|
16
16
|
|
|
@@ -88,14 +88,19 @@ That single command analyzes your codebase, builds a knowledge graph, generates
|
|
|
88
88
|
|
|
89
89
|
Then connect your editor:
|
|
90
90
|
|
|
91
|
+
**Prerequisite:** Install milens globally on your machine:
|
|
92
|
+
```bash
|
|
93
|
+
npm install -g milens # one-time setup
|
|
94
|
+
```
|
|
95
|
+
|
|
91
96
|
```json
|
|
92
97
|
// .vscode/mcp.json — VS Code / Copilot
|
|
93
98
|
{
|
|
94
99
|
"servers": {
|
|
95
100
|
"milens": {
|
|
96
101
|
"type": "stdio",
|
|
97
|
-
"command": "
|
|
98
|
-
"args": ["
|
|
102
|
+
"command": "milens",
|
|
103
|
+
"args": ["serve", "-p", "${workspaceFolder}"]
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
}
|
|
@@ -103,7 +108,7 @@ Then connect your editor:
|
|
|
103
108
|
|
|
104
109
|
```bash
|
|
105
110
|
# Claude Code
|
|
106
|
-
claude mcp add milens --
|
|
111
|
+
claude mcp add milens -- milens serve -p .
|
|
107
112
|
```
|
|
108
113
|
|
|
109
114
|
<details>
|
|
@@ -111,21 +116,21 @@ claude mcp add milens -- npx -y milens serve -p .
|
|
|
111
116
|
|
|
112
117
|
```bash
|
|
113
118
|
# Cursor — .cursor/mcp.json
|
|
114
|
-
{ "mcpServers": { "milens": { "command": "
|
|
119
|
+
{ "mcpServers": { "milens": { "command": "milens", "args": ["serve", "-p", "${workspaceFolder}"] } } }
|
|
115
120
|
|
|
116
|
-
# OpenCode —
|
|
117
|
-
{ "mcp": { "milens": { "
|
|
121
|
+
# OpenCode — opencode.json
|
|
122
|
+
{ "mcp": { "milens": { "type": "local", "command": ["milens", "serve", "-p", "."] } } }
|
|
118
123
|
|
|
119
124
|
# Codex — .codex/config.toml
|
|
120
125
|
[mcp_servers.milens]
|
|
121
|
-
command = "
|
|
122
|
-
args = ["
|
|
126
|
+
command = "milens"
|
|
127
|
+
args = ["serve", "-p", "."]
|
|
123
128
|
|
|
124
129
|
# Gemini — .gemini/settings.json
|
|
125
|
-
{ "mcpServers": { "milens": { "command": "
|
|
130
|
+
{ "mcpServers": { "milens": { "command": "milens", "args": ["serve", "-p", "${workspaceFolder}"] } } }
|
|
126
131
|
|
|
127
132
|
# Zed — .zed/settings.json
|
|
128
|
-
{ "
|
|
133
|
+
{ "context_servers": { "milens": { "command": "milens serve -p ." } } }
|
|
129
134
|
```
|
|
130
135
|
|
|
131
136
|
</details>
|
|
@@ -159,7 +164,7 @@ Open your AI agent. It auto-loads `AGENTS.md` with codebase context. You're read
|
|
|
159
164
|
|---|---|
|
|
160
165
|
| **Code Intelligence** | 43 MCP tools — search, impact, context, trace, routes |
|
|
161
166
|
| **Security Scanner** | 50+ rules across 9 categories + dependency audit |
|
|
162
|
-
| **Sub-Agent Prompts** |
|
|
167
|
+
| **Sub-Agent Prompts** | 6 prompts — plan, review, tdd, security, architect, debugger |
|
|
163
168
|
| **CLI Workflows** | 7 commands — tdd, review, plan, onboard, security-scan, refactor, handoff |
|
|
164
169
|
| **Uninstall** | Full cleanup — 11 trace categories, interactive or auto |
|
|
165
170
|
| **Metrics** | 7 metrics — TER, LR, CQI, BRR, TCGR, DCER, CTR |
|
|
@@ -45,7 +45,7 @@ All tool calls must include `repo` set to the absolute workspace root.
|
|
|
45
45
|
|
|
46
46
|
## Session Workflow
|
|
47
47
|
|
|
48
|
-
1. **Start** — The milens MCP server connects via `
|
|
48
|
+
1. **Start** — The milens MCP server connects via `milens serve -p .`. Verify with `mcp_milens_status`.
|
|
49
49
|
2. **Recall** — When asked to work on a symbol, use `mcp_milens_overview` for a combined view of context, impact, and text references.
|
|
50
50
|
3. **Code** — Make changes following the edit-safety rules below.
|
|
51
51
|
4. **Verify** — Before committing, run `mcp_milens_detect_changes` to confirm only expected files changed.
|
|
@@ -22,8 +22,8 @@ This project is indexed by **milens**. You have MCP tools that are faster and mo
|
|
|
22
22
|
{
|
|
23
23
|
"mcpServers": {
|
|
24
24
|
"milens": {
|
|
25
|
-
"command": "
|
|
26
|
-
"args": ["
|
|
25
|
+
"command": "milens",
|
|
26
|
+
"args": ["serve", "-p", "${workspaceFolder}"],
|
|
27
27
|
"env": { "MILENS_PROFILE": "standard" }
|
|
28
28
|
}
|
|
29
29
|
}
|
package/dist/agents-md.d.ts
CHANGED
package/dist/agents-md.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-md.d.ts","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"agents-md.d.ts","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAoDzC,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsChE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAsIvE"}
|
package/dist/agents-md.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join, relative, basename, dirname } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -35,6 +35,51 @@ function findRouteSymbols(db) {
|
|
|
35
35
|
const routePatterns = /[\/\\]route\.[jt]sx?$|[\/\\]router[\/\\]|[\/\\]routes[\/\\]|[\/\\]api[\/\\]/;
|
|
36
36
|
return all.filter(s => routePatterns.test(s.filePath) && s.exported && (s.kind === 'function' || s.kind === 'method' || s.kind === 'class'));
|
|
37
37
|
}
|
|
38
|
+
function loadCrossRefConfig(rootPath) {
|
|
39
|
+
const configPath = join(rootPath, '.milens-cross-ref.json');
|
|
40
|
+
try {
|
|
41
|
+
if (existsSync(configPath)) {
|
|
42
|
+
return JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
export function generateCrossRefSection(rootPath) {
|
|
49
|
+
const config = loadCrossRefConfig(rootPath);
|
|
50
|
+
if (!config || !config.repos || config.repos.length === 0)
|
|
51
|
+
return '';
|
|
52
|
+
const lines = [];
|
|
53
|
+
lines.push('<!-- AUTO-GENERATED by milens cross-ref hook — do not edit manually -->');
|
|
54
|
+
lines.push(`<!-- Last updated: ${new Date().toISOString()} -->`);
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('## Cross-Repository Context');
|
|
57
|
+
lines.push('');
|
|
58
|
+
lines.push('### Connected Repos');
|
|
59
|
+
lines.push('| Repo | Role | Visibility |');
|
|
60
|
+
lines.push('|------|------|------------|');
|
|
61
|
+
for (const repo of config.repos) {
|
|
62
|
+
const upstream = repo.isUpstream ? ' (upstream)' : '';
|
|
63
|
+
const license = repo.license ? ` ${repo.license}` : '';
|
|
64
|
+
lines.push(`| **${repo.name}**${upstream} | ${repo.role} | ${repo.visibility}${license} |`);
|
|
65
|
+
}
|
|
66
|
+
lines.push('');
|
|
67
|
+
if (config.contract) {
|
|
68
|
+
lines.push('### Contract');
|
|
69
|
+
lines.push(`- **Package:** ${config.contract.package} v${config.contract.version}`);
|
|
70
|
+
lines.push('');
|
|
71
|
+
}
|
|
72
|
+
if (config.dependencies && config.dependencies.length > 0) {
|
|
73
|
+
lines.push('### Key Dependencies');
|
|
74
|
+
lines.push('| Symbol | Source | Used By |');
|
|
75
|
+
lines.push('|--------|--------|---------|');
|
|
76
|
+
for (const d of config.dependencies) {
|
|
77
|
+
lines.push(`| \`${d.symbol}\` | ${d.source} | ${d.usedBy} |`);
|
|
78
|
+
}
|
|
79
|
+
lines.push('');
|
|
80
|
+
}
|
|
81
|
+
return lines.join('\n');
|
|
82
|
+
}
|
|
38
83
|
export function generateAgentsMd(db, rootPath) {
|
|
39
84
|
const version = readMilensVersion();
|
|
40
85
|
const date = new Date().toISOString().split('T')[0];
|
|
@@ -158,6 +203,10 @@ export function generateAgentsMd(db, rootPath) {
|
|
|
158
203
|
lines.push('3. mcp_milens_annotate({symbol: "X", key: "note", value: "..."}) — save discoveries');
|
|
159
204
|
lines.push('4. mcp_milens_session_end({session_id: "..."}) — record stats');
|
|
160
205
|
lines.push('');
|
|
206
|
+
const crossRef = generateCrossRefSection(rootPath);
|
|
207
|
+
if (crossRef) {
|
|
208
|
+
lines.push(crossRef);
|
|
209
|
+
}
|
|
161
210
|
return lines.join('\n');
|
|
162
211
|
}
|
|
163
212
|
//# sourceMappingURL=agents-md.js.map
|
package/dist/agents-md.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../src/agents-md.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ProgressReporter } from '../ui/progress.js';
|
|
1
2
|
import type { AnalysisStats } from '../types.js';
|
|
2
3
|
import type Parser from 'web-tree-sitter';
|
|
3
4
|
export declare function getCachedTree(filePath: string): Parser.Tree | undefined;
|
|
@@ -10,6 +11,7 @@ interface EngineOptions {
|
|
|
10
11
|
aliases?: Record<string, string>;
|
|
11
12
|
embeddings?: boolean;
|
|
12
13
|
files?: string[];
|
|
14
|
+
onProgress?: ProgressReporter;
|
|
13
15
|
}
|
|
14
16
|
export declare function analyze(opts: EngineOptions): Promise<AnalysisStats>;
|
|
15
17
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/analyzer/engine.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAyJ,aAAa,EAAE,MAAM,aAAa,CAAC;AACxM,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAO1C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,IAAI,GAAG,SAAS,CAEvE;AACD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AA8DD,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/analyzer/engine.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAyJ,aAAa,EAAE,MAAM,aAAa,CAAC;AACxM,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAC;AAO1C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,IAAI,GAAG,SAAS,CAEvE;AACD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AA8DD,UAAU,aAAa;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAqCD,wBAAsB,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CA8XzE"}
|
package/dist/analyzer/engine.js
CHANGED
|
@@ -14,6 +14,7 @@ import { enrichMetadata } from './enrich.js';
|
|
|
14
14
|
import { isTestFile } from '../utils.js';
|
|
15
15
|
import { Database } from '../store/db.js';
|
|
16
16
|
import { TfIdfProvider, EmbeddingStore, buildEmbeddingText } from '../store/vectors.js';
|
|
17
|
+
import { ProgressPhase } from '../ui/progress.js';
|
|
17
18
|
// ── Cross-phase Tree Cache ──
|
|
18
19
|
// Caches parsed syntax trees between parse and resolution phases
|
|
19
20
|
// so scope-based resolvers can re-use trees without re-parsing.
|
|
@@ -108,20 +109,13 @@ export async function analyze(opts) {
|
|
|
108
109
|
const rootPath = resolve(opts.rootPath);
|
|
109
110
|
const db = new Database(opts.dbPath);
|
|
110
111
|
const aliases = opts.aliases ?? {};
|
|
111
|
-
|
|
112
|
-
if (opts.files && opts.files.length > 0) {
|
|
113
|
-
db.clearFiles(opts.files);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
db.clear();
|
|
117
|
-
}
|
|
118
|
-
}
|
|
112
|
+
const reporter = opts.onProgress;
|
|
119
113
|
// Phase 1: Scan files (or use explicit file list for incremental)
|
|
120
114
|
const files = opts.files && opts.files.length > 0
|
|
121
115
|
? scanFilesWithFilter(rootPath, opts.files, opts.verbose)
|
|
122
116
|
: scanFiles(rootPath, opts.verbose);
|
|
123
117
|
if (opts.verbose)
|
|
124
|
-
console.
|
|
118
|
+
console.error(`[scan] Found ${files.length} source files`);
|
|
125
119
|
// Phase 2: Group files by language for cache-friendly processing
|
|
126
120
|
const langGroups = new Map();
|
|
127
121
|
for (const file of files) {
|
|
@@ -152,6 +146,13 @@ export async function analyze(opts) {
|
|
|
152
146
|
const parsedFiles = new Set();
|
|
153
147
|
const importCache = new ImportResolveCache();
|
|
154
148
|
let filesParsed = 0;
|
|
149
|
+
// Count total files for progress
|
|
150
|
+
let totalToParse = 0;
|
|
151
|
+
if (docGroup)
|
|
152
|
+
totalToParse += docGroup.length;
|
|
153
|
+
for (const [, group] of langGroups)
|
|
154
|
+
totalToParse += group.length;
|
|
155
|
+
reporter?.startPhase(ProgressPhase.PARSE, totalToParse);
|
|
155
156
|
// Process document files (no tree-sitter needed) — batch read
|
|
156
157
|
if (docGroup) {
|
|
157
158
|
const docContents = await readFilesAsync(docGroup.map(f => f.absolutePath));
|
|
@@ -161,7 +162,7 @@ export async function analyze(opts) {
|
|
|
161
162
|
continue;
|
|
162
163
|
if (!opts.force && db.isFileUpToDate(file.relativePath, source)) {
|
|
163
164
|
if (opts.verbose)
|
|
164
|
-
console.
|
|
165
|
+
console.error(`[skip] ${file.relativePath} (unchanged)`);
|
|
165
166
|
continue;
|
|
166
167
|
}
|
|
167
168
|
try {
|
|
@@ -180,8 +181,9 @@ export async function analyze(opts) {
|
|
|
180
181
|
db.upsertFileHash(file.relativePath, source);
|
|
181
182
|
parsedFiles.add(file.relativePath);
|
|
182
183
|
filesParsed++;
|
|
184
|
+
reporter?.tick(file.relativePath);
|
|
183
185
|
if (opts.verbose)
|
|
184
|
-
console.
|
|
186
|
+
console.error(`[parse] ${file.relativePath}: ${result.symbols.length} symbols`);
|
|
185
187
|
}
|
|
186
188
|
catch (err) {
|
|
187
189
|
if (opts.verbose)
|
|
@@ -215,7 +217,8 @@ export async function analyze(opts) {
|
|
|
215
217
|
// Skip unchanged files (incremental)
|
|
216
218
|
if (!opts.force && db.isFileUpToDate(file.relativePath, source)) {
|
|
217
219
|
if (opts.verbose)
|
|
218
|
-
console.
|
|
220
|
+
console.error(`[skip] ${file.relativePath} (unchanged)`);
|
|
221
|
+
reporter?.tick();
|
|
219
222
|
continue;
|
|
220
223
|
}
|
|
221
224
|
try {
|
|
@@ -236,7 +239,7 @@ export async function analyze(opts) {
|
|
|
236
239
|
for (const imp of result.imports) {
|
|
237
240
|
const resolved = importCache.resolve(file.spec, imp.modulePath, imp.filePath, rootPath, aliases);
|
|
238
241
|
if (opts.verbose)
|
|
239
|
-
console.
|
|
242
|
+
console.error(`[resolve] ${imp.filePath}::${imp.modulePath} => ${resolved ?? 'NULL'}`);
|
|
240
243
|
if (resolved) {
|
|
241
244
|
resolvedImportPaths.set(`${imp.filePath}::${imp.modulePath}`, resolved);
|
|
242
245
|
}
|
|
@@ -251,8 +254,9 @@ export async function analyze(opts) {
|
|
|
251
254
|
db.upsertFileHash(file.relativePath, source);
|
|
252
255
|
parsedFiles.add(file.relativePath);
|
|
253
256
|
filesParsed++;
|
|
257
|
+
reporter?.tick(file.relativePath);
|
|
254
258
|
if (opts.verbose)
|
|
255
|
-
console.
|
|
259
|
+
console.error(`[parse] ${file.relativePath}: ${result.symbols.length} symbols`);
|
|
256
260
|
}
|
|
257
261
|
catch (err) {
|
|
258
262
|
if (opts.verbose)
|
|
@@ -262,6 +266,7 @@ export async function analyze(opts) {
|
|
|
262
266
|
// chunkContents goes out of scope → GC can reclaim source strings
|
|
263
267
|
}
|
|
264
268
|
}
|
|
269
|
+
reporter?.endPhase();
|
|
265
270
|
// Phase 4: Load unchanged files' symbols for cross-file resolution
|
|
266
271
|
if (!opts.force) {
|
|
267
272
|
for (const [, group] of langGroups) {
|
|
@@ -277,6 +282,7 @@ export async function analyze(opts) {
|
|
|
277
282
|
}
|
|
278
283
|
}
|
|
279
284
|
// Phase 5: Resolve cross-file links
|
|
285
|
+
reporter?.startPhase(ProgressPhase.RESOLVE, 1);
|
|
280
286
|
const perFileImportSemantics = new Map();
|
|
281
287
|
const perFileMroStrategy = new Map();
|
|
282
288
|
for (const [, group] of langGroups) {
|
|
@@ -306,16 +312,20 @@ export async function analyze(opts) {
|
|
|
306
312
|
});
|
|
307
313
|
const links = resolution.links;
|
|
308
314
|
if (opts.verbose) {
|
|
309
|
-
console.
|
|
315
|
+
console.error(`[link] Resolved ${links.length} relationships`);
|
|
310
316
|
if (resolution.unresolvedImports > 0 || resolution.unresolvedCalls > 0) {
|
|
311
|
-
console.
|
|
317
|
+
console.error(`[link] ⚠ ${resolution.unresolvedImports} unresolved imports, ${resolution.unresolvedCalls} unresolved calls (internal)`);
|
|
312
318
|
}
|
|
313
319
|
if (resolution.externalImports > 0 || resolution.externalCalls > 0) {
|
|
314
|
-
console.
|
|
320
|
+
console.error(`[link] ✓ ${resolution.externalImports} external imports, ${resolution.externalCalls} external calls (expected)`);
|
|
315
321
|
}
|
|
316
322
|
}
|
|
323
|
+
reporter?.endPhase();
|
|
317
324
|
// Phase 5.5: Dual-path resolution — compare legacy vs scope-based
|
|
318
|
-
{
|
|
325
|
+
try {
|
|
326
|
+
const scopeT0 = Date.now();
|
|
327
|
+
if (opts.verbose)
|
|
328
|
+
console.error(`[dual] Starting scope-based resolution (${allSymbols.length} symbols, ${allCalls.length} calls, ${allImports.length} imports)...`);
|
|
319
329
|
const scopeResolution = resolveWithScopes({
|
|
320
330
|
symbolsByFile,
|
|
321
331
|
allSymbols,
|
|
@@ -332,14 +342,20 @@ export async function analyze(opts) {
|
|
|
332
342
|
perFileMroStrategy,
|
|
333
343
|
treeCache,
|
|
334
344
|
});
|
|
345
|
+
if (opts.verbose)
|
|
346
|
+
console.error(`[dual] Scope resolution completed in ${Date.now() - scopeT0}ms (${scopeResolution.links.length} links)`);
|
|
335
347
|
const diffs = diffResolutions(resolution, scopeResolution);
|
|
336
348
|
if (opts.verbose) {
|
|
337
349
|
const matchPct = resolution.links.length > 0
|
|
338
350
|
? ((resolution.links.length - diffs.length) / resolution.links.length * 100).toFixed(1)
|
|
339
351
|
: '0.0';
|
|
340
|
-
console.
|
|
352
|
+
console.error(`[dual] Legacy: ${resolution.links.length} links, Scope: ${scopeResolution.links.length} links, Diff: ${diffs.length} (${matchPct}% match)`);
|
|
341
353
|
}
|
|
342
354
|
}
|
|
355
|
+
catch (err) {
|
|
356
|
+
if (opts.verbose)
|
|
357
|
+
console.error(`[dual] Scope resolution failed (non-fatal): ${err}`);
|
|
358
|
+
}
|
|
343
359
|
// Release raw extraction data — no longer needed after resolution
|
|
344
360
|
allImports.length = 0;
|
|
345
361
|
allCalls.length = 0;
|
|
@@ -352,9 +368,11 @@ export async function analyze(opts) {
|
|
|
352
368
|
resolvedImportPaths.clear();
|
|
353
369
|
importCache.clear();
|
|
354
370
|
// Phase 6: Enrich — compute roles, heat, zones from resolved graph
|
|
371
|
+
reporter?.startPhase(ProgressPhase.ENRICH, 1);
|
|
355
372
|
const enriched = enrichMetadata({ symbols: allSymbols, links });
|
|
356
373
|
if (opts.verbose)
|
|
357
|
-
console.
|
|
374
|
+
console.error(`[enrich] Computed metadata for ${allSymbols.length} symbols, ${enriched.zones.size} zones`);
|
|
375
|
+
reporter?.endPhase();
|
|
358
376
|
// Phase 6.5: Test coverage — count symbols referenced from test files
|
|
359
377
|
const testFileSymbolIds = new Set();
|
|
360
378
|
const testFiles = new Set();
|
|
@@ -377,9 +395,15 @@ export async function analyze(opts) {
|
|
|
377
395
|
}
|
|
378
396
|
const exportedProduction = allSymbols.filter(s => s.exported && !isTestFile(s.filePath));
|
|
379
397
|
// Phase 7: Persist to database in single transaction
|
|
398
|
+
reporter?.startPhase(ProgressPhase.PERSIST, 1);
|
|
380
399
|
db.transaction(() => {
|
|
381
400
|
if (opts.force) {
|
|
382
|
-
|
|
401
|
+
if (opts.files && opts.files.length > 0) {
|
|
402
|
+
db.clearFiles(opts.files);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
db.clear();
|
|
406
|
+
}
|
|
383
407
|
}
|
|
384
408
|
else {
|
|
385
409
|
for (const fp of parsedFiles)
|
|
@@ -410,6 +434,7 @@ export async function analyze(opts) {
|
|
|
410
434
|
db.setMeta('exported_production_symbols', String(exportedProduction.length));
|
|
411
435
|
db.rebuildSearch();
|
|
412
436
|
});
|
|
437
|
+
reporter?.endPhase();
|
|
413
438
|
// Phase 8: Generate embeddings (optional)
|
|
414
439
|
if (opts.embeddings) {
|
|
415
440
|
const provider = new TfIdfProvider();
|
|
@@ -433,7 +458,7 @@ export async function analyze(opts) {
|
|
|
433
458
|
embedded += batch.length;
|
|
434
459
|
}
|
|
435
460
|
if (opts.verbose)
|
|
436
|
-
console.
|
|
461
|
+
console.error(`[embed] Generated ${embedded} embeddings (${provider.name})`);
|
|
437
462
|
}
|
|
438
463
|
const stats = {
|
|
439
464
|
filesScanned: files.length,
|
|
@@ -447,11 +472,18 @@ export async function analyze(opts) {
|
|
|
447
472
|
externalCalls: resolution.externalCalls,
|
|
448
473
|
};
|
|
449
474
|
if (opts.verbose) {
|
|
450
|
-
console.
|
|
475
|
+
console.error(`[done] ${stats.symbolCount} symbols, ${stats.linkCount} links in ${stats.durationMs}ms`);
|
|
451
476
|
}
|
|
477
|
+
reporter?.done(stats);
|
|
478
|
+
reporter?.finalize();
|
|
452
479
|
clearQueryCache();
|
|
453
480
|
clearTreeCache();
|
|
454
|
-
|
|
481
|
+
try {
|
|
482
|
+
db.close();
|
|
483
|
+
}
|
|
484
|
+
finally {
|
|
485
|
+
// ensure close even on error
|
|
486
|
+
}
|
|
455
487
|
return stats;
|
|
456
488
|
}
|
|
457
489
|
async function parseFile(source, filePath, spec, parser, lang) {
|