@softerist/heuristic-mcp 3.0.3 → 3.0.6
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/.agent/workflows/code-review.md +14 -3
- package/LICENSE +1 -1
- package/config.jsonc +4 -4
- package/debug-pids.js +26 -23
- package/features/find-similar-code.js +20 -16
- package/features/hybrid-search.js +197 -187
- package/features/index-codebase.js +2610 -2554
- package/features/lifecycle.js +74 -58
- package/features/register.js +3 -1
- package/index.js +531 -516
- package/lib/cache-utils.js +1 -3
- package/lib/cache.js +1474 -1456
- package/lib/call-graph.js +1 -1
- package/lib/config.js +789 -797
- package/lib/embedding-process.js +35 -24
- package/lib/embedding-worker.js +734 -684
- package/lib/json-writer.js +14 -21
- package/lib/logging.js +4 -2
- package/lib/onnx-backend.js +14 -8
- package/lib/settings-editor.js +2 -9
- package/lib/tokenizer.js +87 -85
- package/lib/utils.js +7 -6
- package/lib/vector-store-binary.js +615 -612
- package/mcp_config.json +9 -0
- package/package.json +1 -1
- package/scripts/mcp-launcher.js +35 -0
- package/search-configs.js +6 -6
- package/test/ann-config.test.js +0 -1
- package/test/ann-fallback.test.js +0 -1
- package/test/binary-store.test.js +0 -1
- package/test/cache-branches.test.js +0 -1
- package/test/cache-errors.test.js +7 -4
- package/test/cache-extra.test.js +6 -5
- package/test/cache-helpers.test.js +0 -1
- package/test/cache-hnsw-failure.test.js +0 -1
- package/test/cache-json-worker.test.js +1 -2
- package/test/cache-worker.test.js +104 -103
- package/test/cache.test.js +15 -16
- package/test/call-graph.test.js +0 -1
- package/test/clear-cache.test.js +0 -1
- package/test/code-review-workflow.test.js +0 -1
- package/test/config.test.js +0 -1
- package/test/coverage-gap.test.js +0 -1
- package/test/coverage-maximizer.test.js +3 -2
- package/test/debug-analysis.js +106 -108
- package/test/embedding-model.test.js +27 -16
- package/test/embedding-worker-extra.test.js +42 -39
- package/test/embedding-worker.test.js +3 -4
- package/test/features.test.js +3 -2
- package/test/final-boost.test.js +281 -272
- package/test/final-polish.test.js +9 -4
- package/test/final.test.js +0 -1
- package/test/find-similar-code.test.js +3 -2
- package/test/fixtures/mcp-workspace/config.jsonc +12 -0
- package/test/fixtures/mcp-workspace/example.js +8 -0
- package/test/helpers.js +0 -1
- package/test/helpers.test.js +0 -1
- package/test/hybrid-search-basic.test.js +9 -10
- package/test/hybrid-search-branch.test.js +176 -178
- package/test/hybrid-search-callgraph.test.js +27 -27
- package/test/hybrid-search-extra.test.js +0 -1
- package/test/hybrid-search.test.js +0 -1
- package/test/index-cli.test.js +13 -6
- package/test/index-codebase-batch.test.js +1 -4
- package/test/index-codebase-branches.test.js +575 -582
- package/test/index-codebase-core.test.js +1039 -1033
- package/test/index-codebase-edge-cases.test.js +250 -254
- package/test/index-codebase-errors.test.js +0 -1
- package/test/index-codebase-gap.test.js +244 -233
- package/test/index-codebase-lines.test.js +0 -1
- package/test/index-codebase-watcher.test.js +369 -368
- package/test/index-codebase-zone.test.js +154 -153
- package/test/index-codebase.test.js +0 -1
- package/test/index-memory.test.js +195 -185
- package/test/indexer-detailed.test.js +0 -1
- package/test/integration.test.js +0 -1
- package/test/json-worker.test.js +0 -1
- package/test/lifecycle.test.js +7 -6
- package/test/master.test.js +0 -1
- package/test/mcp-search.test.js +78 -0
- package/test/perfection.test.js +0 -1
- package/test/project-detector.test.js +0 -1
- package/test/register.test.js +0 -1
- package/test/stress.js +19530 -18955
- package/test/tokenizer.test.js +0 -1
- package/test/ultra-maximizer.test.js +0 -1
- package/test/utils-branches.test.js +160 -162
- package/test/utils-extra.test.js +51 -52
- package/test/utils.test.js +0 -1
- package/test/verify_fixes.js +78 -77
- package/test/worker-errors.test.js +3 -2
- package/test/worker-init.test.js +0 -1
- package/test/worker_throttling.test.js +91 -94
- package/tools/scripts/cache-stats.js +1 -1
- package/tools/scripts/manual-search.js +70 -34
- package/mcp_config.example.json +0 -13
|
@@ -7,6 +7,7 @@ last_updated: 2026-01-29
|
|
|
7
7
|
You are a senior software engineer and code reviewer. Review the code provided according to the following strict guidelines.
|
|
8
8
|
|
|
9
9
|
## 1. Review Scope & Context
|
|
10
|
+
|
|
10
11
|
- **For code <100 lines**: Quick review focusing on correctness and obvious bugs.
|
|
11
12
|
- **For code 100-500 lines**: Standard review following all sections below.
|
|
12
13
|
- **For code >500 lines or critical systems**: Deep review with extra emphasis on architecture, security, and edge cases.
|
|
@@ -14,46 +15,56 @@ You are a senior software engineer and code reviewer. Review the code provided a
|
|
|
14
15
|
- **Domain-Specific Checks**: If the code domain is identifiable (e.g., web, mobile, embedded, ML, healthcare), apply relevant domain-specific standards (e.g., WCAG for web, PII handling for healthcare, real-time constraints for embedded).
|
|
15
16
|
|
|
16
17
|
## 2. Line-by-Line Review
|
|
18
|
+
|
|
17
19
|
- Review every function and critical code path. For files >200 lines, focus on functions with issues rather than every line.
|
|
18
20
|
- Group line-by-line findings by severity (**Critical** first), then by file/function within each severity tier.
|
|
19
21
|
- For each issue, quote the relevant line(s).
|
|
20
22
|
- **Confidence Ratings**: For ambiguous issues where context is missing, explicitly note `[Confidence: Low/Medium/High]` and explain what additional information would clarify the finding.
|
|
21
23
|
|
|
22
24
|
## 3. High-Level Review
|
|
25
|
+
|
|
23
26
|
- Focus on system-level patterns not visible at function scope: module organization, layer violations, missing abstraction layers, deployment concerns.
|
|
24
27
|
- Do not check for issues already covered in line-by-line (avoid redundancy).
|
|
25
28
|
|
|
26
29
|
## 4. Follow-up Reviews
|
|
30
|
+
|
|
27
31
|
- For follow-up reviews, focus on: regression verification, new code introduced by fixes, and cross-cutting impact of changes.
|
|
28
32
|
|
|
29
33
|
## 5. Stalled/Incomplete Logic
|
|
34
|
+
|
|
30
35
|
- Check for "forgotten error paths": places where exceptions/errors could occur but aren't caught, or catch blocks that are empty/only log without recovery strategy.
|
|
31
36
|
- Verify TODOs or placeholders.
|
|
32
37
|
|
|
33
38
|
## 6. Consistency
|
|
39
|
+
|
|
34
40
|
- Identify the dominant pattern in the codebase and flag deviations. If no clear majority, note the inconsistency itself as an issue.
|
|
35
41
|
- Check naming conventions, coding style, and file structure.
|
|
36
42
|
|
|
37
43
|
## 7. Fix Plan
|
|
44
|
+
|
|
38
45
|
Provide a prioritized checklist (most critical first):
|
|
46
|
+
|
|
39
47
|
- **Estimated effort per item** using this scale:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
- **S (Small)**: <2 hours, isolated change, no breaking changes.
|
|
49
|
+
- **M (Medium)**: 2-8 hours, may affect multiple files, local refactoring.
|
|
50
|
+
- **L (Large)**: >8 hours, architectural changes, breaking changes, or requires team coordination.
|
|
43
51
|
- For each item, note any dependencies: "Requires #N" if another fix must be completed first.
|
|
44
52
|
- Group independent fixes together to enable parallel work.
|
|
45
53
|
|
|
46
54
|
## 8. Patch
|
|
55
|
+
|
|
47
56
|
- Propose concrete code edits in **unified diff format** for **ALL critical severity issues**.
|
|
48
57
|
- For **high severity** issues, provide patches for the top 5 most impactful.
|
|
49
58
|
- For new files or large refactors (>50 lines changed), provide complete code blocks with clear before/after markers.
|
|
50
59
|
|
|
51
60
|
## 9. Tests
|
|
61
|
+
|
|
52
62
|
- Separate **unit tests** (isolated, mocked dependencies) from **integration tests** (real dependencies). Specify which category each test belongs to.
|
|
53
63
|
- List the exact tests you'd add (test names + what each asserts).
|
|
54
64
|
- For performance issues, include benchmark or load tests with acceptable thresholds.
|
|
55
65
|
|
|
56
66
|
## Output Format Constraints
|
|
67
|
+
|
|
57
68
|
- **Do not skip sections.** If a section has no findings, state "No issues found" and briefly explain why (e.g., "No concurrency issues: code is single-threaded").
|
|
58
69
|
- **Assume production context**: Treat as a professional audit. If context is unclear, state assumptions (e.g., "assuming user-facing web application with moderate traffic").
|
|
59
70
|
- **Be exhaustive and specific.** Do not be polite; be direct.
|
package/LICENSE
CHANGED
package/config.jsonc
CHANGED
|
@@ -563,7 +563,7 @@
|
|
|
563
563
|
"gitattributes",
|
|
564
564
|
"editorconfig",
|
|
565
565
|
"npmrc",
|
|
566
|
-
"yarnrc"
|
|
566
|
+
"yarnrc",
|
|
567
567
|
],
|
|
568
568
|
// Specific filenames to include regardless of extension.
|
|
569
569
|
"fileNames": [
|
|
@@ -612,7 +612,7 @@
|
|
|
612
612
|
"docker-compose.yml",
|
|
613
613
|
"docker-compose.yaml",
|
|
614
614
|
"makefile.am",
|
|
615
|
-
"makefile.in"
|
|
615
|
+
"makefile.in",
|
|
616
616
|
],
|
|
617
617
|
// Glob patterns to exclude from indexing.
|
|
618
618
|
"excludePatterns": [
|
|
@@ -624,7 +624,7 @@
|
|
|
624
624
|
"**/.next/**",
|
|
625
625
|
"**/target/**",
|
|
626
626
|
"**/vendor/**",
|
|
627
|
-
"**/.smart-coding-cache/**"
|
|
627
|
+
"**/.smart-coding-cache/**",
|
|
628
628
|
],
|
|
629
629
|
// Enable project-type detection + smart ignore patterns.
|
|
630
630
|
"smartIndexing": true,
|
|
@@ -719,5 +719,5 @@
|
|
|
719
719
|
// Persist ANN index to disk.
|
|
720
720
|
"annIndexCache": true,
|
|
721
721
|
// ANN distance metric.
|
|
722
|
-
"annMetric": "cosine"
|
|
722
|
+
"annMetric": "cosine",
|
|
723
723
|
}
|
package/debug-pids.js
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import { exec } from 'child_process';
|
|
2
|
-
import util from 'util';
|
|
3
|
-
|
|
4
|
-
const execPromise = util.promisify(exec);
|
|
5
|
-
|
|
6
|
-
async function check() {
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import util from 'util';
|
|
3
|
+
|
|
4
|
+
const execPromise = util.promisify(exec);
|
|
5
|
+
|
|
6
|
+
async function check() {
|
|
7
7
|
console.info('Checking processes...');
|
|
8
|
-
try {
|
|
9
|
-
const { stdout } = await execPromise(
|
|
10
|
-
`powershell -NoProfile -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'node.exe' } | Select-Object ProcessId, CommandLine, ParentProcessId | ConvertTo-Json"`
|
|
11
|
-
);
|
|
12
|
-
const processes = JSON.parse(stdout);
|
|
13
|
-
const list = Array.isArray(processes) ? processes : [processes];
|
|
14
|
-
|
|
15
|
-
for (const p of list) {
|
|
16
|
-
if (
|
|
8
|
+
try {
|
|
9
|
+
const { stdout } = await execPromise(
|
|
10
|
+
`powershell -NoProfile -Command "Get-CimInstance Win32_Process | Where-Object { $_.Name -eq 'node.exe' } | Select-Object ProcessId, CommandLine, ParentProcessId | ConvertTo-Json"`
|
|
11
|
+
);
|
|
12
|
+
const processes = JSON.parse(stdout);
|
|
13
|
+
const list = Array.isArray(processes) ? processes : [processes];
|
|
14
|
+
|
|
15
|
+
for (const p of list) {
|
|
16
|
+
if (
|
|
17
|
+
p.CommandLine &&
|
|
18
|
+
(p.CommandLine.includes('heuristic-mcp') || p.CommandLine.includes('index.js'))
|
|
19
|
+
) {
|
|
17
20
|
console.info(`PID: ${p.ProcessId}, Parent: ${p.ParentProcessId}`);
|
|
18
21
|
console.info(`CMD: ${p.CommandLine}`);
|
|
19
22
|
console.info('---');
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
} catch (err) {
|
|
23
|
-
console.error('Error:', err.message);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
check();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error('Error:', err.message);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
check();
|
|
@@ -48,7 +48,7 @@ export class FindSimilarCode {
|
|
|
48
48
|
// Check if input is too large and truncate intelligently
|
|
49
49
|
const estimatedTokens = estimateTokens(code);
|
|
50
50
|
const limit = getModelTokenLimit(this.config.embeddingModel);
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// If input is significantly larger than the model limit, we should chunk it
|
|
53
53
|
if (estimatedTokens > limit) {
|
|
54
54
|
// Use smartChunk to get a semantically valid first block
|
|
@@ -66,14 +66,16 @@ export class FindSimilarCode {
|
|
|
66
66
|
pooling: 'mean',
|
|
67
67
|
normalize: true,
|
|
68
68
|
});
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
|
|
70
|
+
// CRITICAL: Deep copy Float32Array to avoid detachment issues with WASM/Workers
|
|
71
|
+
// accessing a detached buffer from a reusable ONNX tensor can crash the process.
|
|
72
|
+
const codeVector = new Float32Array(codeEmbed.data);
|
|
71
73
|
|
|
72
74
|
let candidates = vectorStore;
|
|
73
75
|
let usedAnn = false;
|
|
74
76
|
if (this.config.annEnabled) {
|
|
75
77
|
const candidateCount = this.getAnnCandidateCount(maxResults, vectorStore.length);
|
|
76
|
-
const annLabels = await this.cache.queryAnn(
|
|
78
|
+
const annLabels = await this.cache.queryAnn(codeVector, candidateCount);
|
|
77
79
|
if (annLabels && annLabels.length >= maxResults) {
|
|
78
80
|
usedAnn = true;
|
|
79
81
|
const seen = new Set();
|
|
@@ -88,27 +90,27 @@ export class FindSimilarCode {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
const normalizedInput = codeToEmbed.trim().replace(/\s+/g, ' ');
|
|
91
|
-
|
|
93
|
+
|
|
92
94
|
/**
|
|
93
95
|
* Batch scoring function to prevent blocking the event loop
|
|
94
96
|
*/
|
|
95
97
|
const scoreAndFilter = async (chunks) => {
|
|
96
98
|
const BATCH_SIZE = 500;
|
|
97
99
|
const scored = [];
|
|
98
|
-
|
|
100
|
+
|
|
99
101
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
100
102
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
101
|
-
|
|
103
|
+
|
|
102
104
|
// Yield to event loop between batches
|
|
103
105
|
if (i > 0) {
|
|
104
106
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
105
107
|
}
|
|
106
|
-
|
|
108
|
+
|
|
107
109
|
for (const chunk of batch) {
|
|
108
110
|
const vector = this.getChunkVector(chunk);
|
|
109
111
|
if (!vector) continue;
|
|
110
112
|
const similarity = dotSimilarity(codeVector, vector);
|
|
111
|
-
|
|
113
|
+
|
|
112
114
|
if (similarity >= minSimilarity) {
|
|
113
115
|
// Deduplicate against input
|
|
114
116
|
if (normalizedInput) {
|
|
@@ -116,17 +118,17 @@ export class FindSimilarCode {
|
|
|
116
118
|
const normalizedChunk = content.trim().replace(/\s+/g, ' ');
|
|
117
119
|
if (normalizedChunk === normalizedInput) continue;
|
|
118
120
|
}
|
|
119
|
-
|
|
121
|
+
|
|
120
122
|
scored.push({ ...chunk, similarity });
|
|
121
123
|
}
|
|
122
124
|
}
|
|
123
125
|
}
|
|
124
|
-
|
|
126
|
+
|
|
125
127
|
return scored.sort((a, b) => b.similarity - a.similarity);
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
let filteredResults = await scoreAndFilter(candidates);
|
|
129
|
-
|
|
131
|
+
|
|
130
132
|
// Fallback to full scan if ANN didn't provide enough results
|
|
131
133
|
// Optimization: Skip full scan on large codebases to avoid long pauses
|
|
132
134
|
const MAX_FULL_SCAN_SIZE = 5000;
|
|
@@ -143,12 +145,14 @@ export class FindSimilarCode {
|
|
|
143
145
|
return { ...chunk, content: await this.getChunkContent(chunk) };
|
|
144
146
|
}
|
|
145
147
|
return chunk;
|
|
146
|
-
})
|
|
148
|
+
})
|
|
147
149
|
);
|
|
148
150
|
|
|
149
151
|
return {
|
|
150
152
|
results,
|
|
151
|
-
message:
|
|
153
|
+
message:
|
|
154
|
+
warningMessage ||
|
|
155
|
+
(results.length === 0 ? 'No similar code found above the similarity threshold.' : null),
|
|
152
156
|
};
|
|
153
157
|
}
|
|
154
158
|
|
|
@@ -160,7 +164,7 @@ export class FindSimilarCode {
|
|
|
160
164
|
const formatted = await Promise.all(
|
|
161
165
|
results.map(async (r, idx) => {
|
|
162
166
|
const relPath = path.relative(this.config.searchDirectory, r.file);
|
|
163
|
-
const content = r.content ?? await this.getChunkContent(r);
|
|
167
|
+
const content = r.content ?? (await this.getChunkContent(r));
|
|
164
168
|
return (
|
|
165
169
|
`## Similar Code ${idx + 1} (Similarity: ${(r.similarity * 100).toFixed(1)}%)\n` +
|
|
166
170
|
`**File:** \`${relPath}\`\n` +
|
|
@@ -172,7 +176,7 @@ export class FindSimilarCode {
|
|
|
172
176
|
'\n' +
|
|
173
177
|
'```\n'
|
|
174
178
|
);
|
|
175
|
-
})
|
|
179
|
+
})
|
|
176
180
|
);
|
|
177
181
|
|
|
178
182
|
return formatted.join('\n');
|