sverklo 0.2.7 → 0.2.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 -0
- package/dist/src/doctor.js +57 -0
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/init.js +36 -0
- package/dist/src/init.js.map +1 -1
- package/dist/src/server/hints.d.ts +21 -0
- package/dist/src/server/hints.js +175 -0
- package/dist/src/server/hints.js.map +1 -0
- package/dist/src/server/mcp-server.js +46 -1
- package/dist/src/server/mcp-server.js.map +1 -1
- package/dist/src/server/prompts.d.ts +17 -0
- package/dist/src/server/prompts.js +148 -0
- package/dist/src/server/prompts.js.map +1 -0
- package/dist/src/server/tools/context.d.ts +25 -0
- package/dist/src/server/tools/context.js +162 -0
- package/dist/src/server/tools/context.js.map +1 -0
- package/dist/src/server/tools/review-diff.js +92 -1
- package/dist/src/server/tools/review-diff.js.map +1 -1
- package/dist/src/server/tools/risk-score.d.ts +26 -0
- package/dist/src/server/tools/risk-score.js +138 -0
- package/dist/src/server/tools/risk-score.js.map +1 -0
- package/dist/src/server/tools/test-map.js +36 -68
- package/dist/src/server/tools/test-map.js.map +1 -1
- package/dist/src/server/tools/test-paths.d.ts +8 -0
- package/dist/src/server/tools/test-paths.js +62 -0
- package/dist/src/server/tools/test-paths.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Weighted risk score for changed files in a diff.
|
|
2
|
+
//
|
|
3
|
+
// Inspired by code-review-graph's compute_risk_score, adapted for sverklo's
|
|
4
|
+
// data model. Score is in [0, 1] — higher means "review more carefully".
|
|
5
|
+
// The formula is intentionally simple, deterministic, and explainable so a
|
|
6
|
+
// reviewer can see why a file got flagged.
|
|
7
|
+
//
|
|
8
|
+
// untested +0.30 no test file matches by name or import
|
|
9
|
+
// security keywords +0.20 path or symbol matches sensitive surface
|
|
10
|
+
// high fan-in up to +0.15 importer count / 20, capped
|
|
11
|
+
// many callers up to +0.10 total caller count of changed symbols / 100
|
|
12
|
+
// dangling removes up to +0.20 removed symbols still referenced
|
|
13
|
+
// churn up to +0.05 ln(added+removed) / 20, capped
|
|
14
|
+
//
|
|
15
|
+
// Total is clamped to 1.0. The breakdown is returned alongside the score so
|
|
16
|
+
// the reviewer can see the contributing reasons.
|
|
17
|
+
// Path/symbol substrings that indicate security-sensitive surface area.
|
|
18
|
+
// Lowercased before matching. Kept short on purpose — false positives here
|
|
19
|
+
// just nudge a reviewer to look more carefully, which is the right default.
|
|
20
|
+
const SECURITY_KEYWORDS = [
|
|
21
|
+
"auth",
|
|
22
|
+
"login",
|
|
23
|
+
"logout",
|
|
24
|
+
"session",
|
|
25
|
+
"token",
|
|
26
|
+
"jwt",
|
|
27
|
+
"oauth",
|
|
28
|
+
"password",
|
|
29
|
+
"passwd",
|
|
30
|
+
"secret",
|
|
31
|
+
"credential",
|
|
32
|
+
"crypto",
|
|
33
|
+
"encrypt",
|
|
34
|
+
"decrypt",
|
|
35
|
+
"signature",
|
|
36
|
+
"permission",
|
|
37
|
+
"authorize",
|
|
38
|
+
"authoriz",
|
|
39
|
+
"access",
|
|
40
|
+
"admin",
|
|
41
|
+
"csrf",
|
|
42
|
+
"xss",
|
|
43
|
+
"sanitize",
|
|
44
|
+
"sql",
|
|
45
|
+
"query",
|
|
46
|
+
"exec",
|
|
47
|
+
"shell",
|
|
48
|
+
"subprocess",
|
|
49
|
+
"eval",
|
|
50
|
+
"deserialize",
|
|
51
|
+
"unmarshal",
|
|
52
|
+
"pii",
|
|
53
|
+
"billing",
|
|
54
|
+
"payment",
|
|
55
|
+
"stripe",
|
|
56
|
+
"webhook",
|
|
57
|
+
];
|
|
58
|
+
function hasSecurityKeyword(haystack) {
|
|
59
|
+
const lower = haystack.toLowerCase();
|
|
60
|
+
return SECURITY_KEYWORDS.some((kw) => lower.includes(kw));
|
|
61
|
+
}
|
|
62
|
+
export function computeRiskScore(inputs) {
|
|
63
|
+
const breakdown = {
|
|
64
|
+
untested: 0,
|
|
65
|
+
security: 0,
|
|
66
|
+
fanIn: 0,
|
|
67
|
+
callers: 0,
|
|
68
|
+
dangling: 0,
|
|
69
|
+
churn: 0,
|
|
70
|
+
};
|
|
71
|
+
const reasons = [];
|
|
72
|
+
if (!inputs.isTested) {
|
|
73
|
+
breakdown.untested = 0.3;
|
|
74
|
+
reasons.push("no matching tests");
|
|
75
|
+
}
|
|
76
|
+
// Security: check path + symbol names
|
|
77
|
+
const securityHaystack = [inputs.path, ...inputs.changedSymbolNames].join(" ");
|
|
78
|
+
if (hasSecurityKeyword(securityHaystack)) {
|
|
79
|
+
breakdown.security = 0.2;
|
|
80
|
+
reasons.push("touches security-sensitive surface");
|
|
81
|
+
}
|
|
82
|
+
// File fan-in (importers): each importer worth 0.0075, capped 0.15
|
|
83
|
+
if (inputs.importerCount > 0) {
|
|
84
|
+
breakdown.fanIn = Math.min(0.15, inputs.importerCount * 0.0075);
|
|
85
|
+
if (inputs.importerCount >= 5) {
|
|
86
|
+
reasons.push(`${inputs.importerCount} importers depend on this file`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Caller count of changed symbols: 0.001 per caller, capped 0.10
|
|
90
|
+
if (inputs.totalCallerCount > 0) {
|
|
91
|
+
breakdown.callers = Math.min(0.1, inputs.totalCallerCount * 0.001);
|
|
92
|
+
if (inputs.totalCallerCount >= 20) {
|
|
93
|
+
reasons.push(`${inputs.totalCallerCount} callers reference changed symbols`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Dangling references on removed symbols are the most dangerous signal:
|
|
97
|
+
// each removed symbol that still has callers is a near-certain breakage.
|
|
98
|
+
if (inputs.danglingSymbolCount > 0) {
|
|
99
|
+
breakdown.dangling = Math.min(0.2, inputs.danglingSymbolCount * 0.1);
|
|
100
|
+
reasons.push(`${inputs.danglingSymbolCount} removed symbol${inputs.danglingSymbolCount === 1 ? "" : "s"} still referenced`);
|
|
101
|
+
}
|
|
102
|
+
// Churn: log-scaled so a 5-line edit isn't penalised but a 500-line one is
|
|
103
|
+
const churnLines = inputs.added + inputs.removed;
|
|
104
|
+
if (churnLines > 0) {
|
|
105
|
+
breakdown.churn = Math.min(0.05, Math.log(1 + churnLines) / 100);
|
|
106
|
+
if (churnLines >= 200) {
|
|
107
|
+
reasons.push(`${churnLines} lines churned`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const total = Math.min(1, breakdown.untested +
|
|
111
|
+
breakdown.security +
|
|
112
|
+
breakdown.fanIn +
|
|
113
|
+
breakdown.callers +
|
|
114
|
+
breakdown.dangling +
|
|
115
|
+
breakdown.churn);
|
|
116
|
+
let level;
|
|
117
|
+
if (total >= 0.7)
|
|
118
|
+
level = "critical";
|
|
119
|
+
else if (total >= 0.45)
|
|
120
|
+
level = "high";
|
|
121
|
+
else if (total >= 0.2)
|
|
122
|
+
level = "medium";
|
|
123
|
+
else
|
|
124
|
+
level = "low";
|
|
125
|
+
return { total, level, breakdown, reasons };
|
|
126
|
+
}
|
|
127
|
+
export function formatRiskBadge(score) {
|
|
128
|
+
const pct = Math.round(score.total * 100);
|
|
129
|
+
const icon = score.level === "critical"
|
|
130
|
+
? "🔴"
|
|
131
|
+
: score.level === "high"
|
|
132
|
+
? "🟠"
|
|
133
|
+
: score.level === "medium"
|
|
134
|
+
? "🟡"
|
|
135
|
+
: "🟢";
|
|
136
|
+
return `${icon} risk ${pct} (${score.level})`;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=risk-score.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-score.js","sourceRoot":"","sources":["../../../../src/server/tools/risk-score.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
2
|
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { isTestPath, candidateTestNames } from "./test-paths.js";
|
|
4
|
+
import { computeRiskScore, formatRiskBadge } from "./risk-score.js";
|
|
3
5
|
export const testMapTool = {
|
|
4
6
|
name: "sverklo_test_map",
|
|
5
7
|
description: "Map a git diff to its test coverage. Given a ref/range, lists which tests likely cover " +
|
|
@@ -22,72 +24,6 @@ export const testMapTool = {
|
|
|
22
24
|
},
|
|
23
25
|
},
|
|
24
26
|
};
|
|
25
|
-
// Filename patterns that indicate a test file across common ecosystems.
|
|
26
|
-
// Kept regex-light so additions are easy.
|
|
27
|
-
const TEST_FILE_PATTERNS = [
|
|
28
|
-
/\.test\.[jt]sx?$/,
|
|
29
|
-
/\.spec\.[jt]sx?$/,
|
|
30
|
-
/(^|\/)__tests__\//,
|
|
31
|
-
/(^|\/)tests?\//,
|
|
32
|
-
/_test\.go$/,
|
|
33
|
-
/_test\.py$/,
|
|
34
|
-
/(^|\/)test_[^/]+\.py$/,
|
|
35
|
-
/Test\.java$/,
|
|
36
|
-
/Tests\.java$/,
|
|
37
|
-
/Spec\.scala$/,
|
|
38
|
-
/_spec\.rb$/,
|
|
39
|
-
/(^|\/)spec\//,
|
|
40
|
-
/\.test\.exs$/,
|
|
41
|
-
/(^|\/)test\/.*\.exs$/,
|
|
42
|
-
];
|
|
43
|
-
function isTestPath(path) {
|
|
44
|
-
return TEST_FILE_PATTERNS.some((re) => re.test(path));
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Generate the candidate test filenames that conventionally cover a source file.
|
|
48
|
-
* Examples:
|
|
49
|
-
* src/foo/bar.ts → bar.test.ts, bar.spec.ts, __tests__/bar.test.ts
|
|
50
|
-
* src/foo/bar.py → test_bar.py, bar_test.py
|
|
51
|
-
* com/Foo.java → FooTest.java, FooTests.java
|
|
52
|
-
*/
|
|
53
|
-
function candidateTestNames(sourcePath) {
|
|
54
|
-
const file = basename(sourcePath);
|
|
55
|
-
const dot = file.lastIndexOf(".");
|
|
56
|
-
if (dot <= 0)
|
|
57
|
-
return [];
|
|
58
|
-
const stem = file.slice(0, dot);
|
|
59
|
-
const ext = file.slice(dot); // includes leading dot
|
|
60
|
-
const names = [];
|
|
61
|
-
// JS/TS family
|
|
62
|
-
if (/\.[jt]sx?$/.test(ext)) {
|
|
63
|
-
names.push(`${stem}.test${ext}`, `${stem}.spec${ext}`);
|
|
64
|
-
}
|
|
65
|
-
// Python
|
|
66
|
-
if (ext === ".py") {
|
|
67
|
-
names.push(`test_${stem}.py`, `${stem}_test.py`);
|
|
68
|
-
}
|
|
69
|
-
// Go
|
|
70
|
-
if (ext === ".go") {
|
|
71
|
-
names.push(`${stem}_test.go`);
|
|
72
|
-
}
|
|
73
|
-
// Java/Kotlin/Scala
|
|
74
|
-
if (ext === ".java" || ext === ".kt" || ext === ".scala") {
|
|
75
|
-
names.push(`${stem}Test${ext}`, `${stem}Tests${ext}`, `${stem}Spec${ext}`);
|
|
76
|
-
}
|
|
77
|
-
// Ruby
|
|
78
|
-
if (ext === ".rb") {
|
|
79
|
-
names.push(`${stem}_spec.rb`, `${stem}_test.rb`);
|
|
80
|
-
}
|
|
81
|
-
// Rust — convention is inline #[cfg(test)] modules; sibling file uncommon
|
|
82
|
-
if (ext === ".rs") {
|
|
83
|
-
names.push(`${stem}_test.rs`);
|
|
84
|
-
}
|
|
85
|
-
// Elixir
|
|
86
|
-
if (ext === ".ex") {
|
|
87
|
-
names.push(`${stem}_test.exs`);
|
|
88
|
-
}
|
|
89
|
-
return names;
|
|
90
|
-
}
|
|
91
27
|
export function handleTestMap(indexer, args) {
|
|
92
28
|
const ref = args.ref || "main..HEAD";
|
|
93
29
|
const includeImporters = args.include_importers !== false;
|
|
@@ -203,8 +139,40 @@ export function handleTestMap(indexer, args) {
|
|
|
203
139
|
lines.push(`## ⚠️ No matching tests found (${uncovered.length})`);
|
|
204
140
|
lines.push(`These changed files have no test file matching by name or import. They may be untested, ` +
|
|
205
141
|
`tested via integration/e2e suites sverklo can't see, or covered by tests outside the indexed paths.`);
|
|
206
|
-
for
|
|
207
|
-
|
|
142
|
+
// Compute a risk score for each uncovered file so the reviewer sees
|
|
143
|
+
// *which* untested files are actually dangerous (e.g. auth code with
|
|
144
|
+
// many importers) vs benign (e.g. a typo in a doc snippet).
|
|
145
|
+
const uncoveredScored = uncovered.map((u) => {
|
|
146
|
+
const id = pathToId.get(u);
|
|
147
|
+
const importerCount = id !== undefined
|
|
148
|
+
? indexer.graphStore.getImporters(id).length
|
|
149
|
+
: 0;
|
|
150
|
+
const symbols = id !== undefined
|
|
151
|
+
? indexer.chunkStore.getByFile(id).filter((c) => c.name).map((c) => c.name)
|
|
152
|
+
: [];
|
|
153
|
+
let totalCallers = 0;
|
|
154
|
+
for (const name of symbols) {
|
|
155
|
+
totalCallers += Math.min(indexer.symbolRefStore.getCallerCount(name), 50);
|
|
156
|
+
}
|
|
157
|
+
const score = computeRiskScore({
|
|
158
|
+
path: u,
|
|
159
|
+
added: 0,
|
|
160
|
+
removed: 0,
|
|
161
|
+
isTested: false,
|
|
162
|
+
importerCount,
|
|
163
|
+
changedSymbolNames: symbols,
|
|
164
|
+
totalCallerCount: totalCallers,
|
|
165
|
+
danglingSymbolCount: 0,
|
|
166
|
+
});
|
|
167
|
+
return { path: u, score };
|
|
168
|
+
});
|
|
169
|
+
uncoveredScored.sort((a, b) => b.score.total - a.score.total);
|
|
170
|
+
for (const { path: u, score } of uncoveredScored) {
|
|
171
|
+
lines.push(`- ${formatRiskBadge(score)} ${u}`);
|
|
172
|
+
if (score.reasons.length > 0) {
|
|
173
|
+
lines.push(` _${score.reasons.filter((r) => r !== "no matching tests").join("; ") || "no matching tests"}_`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
208
176
|
lines.push("");
|
|
209
177
|
}
|
|
210
178
|
// Suggested next-step commands the reviewer can paste
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-map.js","sourceRoot":"","sources":["../../../../src/server/tools/test-map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"test-map.js","sourceRoot":"","sources":["../../../../src/server/tools/test-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function isTestPath(path: string): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Generate the candidate test filenames that conventionally cover a source file.
|
|
4
|
+
* src/foo/bar.ts → bar.test.ts, bar.spec.ts
|
|
5
|
+
* src/foo/bar.py → test_bar.py, bar_test.py
|
|
6
|
+
* com/Foo.java → FooTest.java, FooTests.java
|
|
7
|
+
*/
|
|
8
|
+
export declare function candidateTestNames(sourcePath: string): string[];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Shared helpers for identifying test files and the test files that
|
|
2
|
+
// conventionally cover a given source file. Extracted so both test-map and
|
|
3
|
+
// review-diff (risk scoring) can ask "is this file tested?" without
|
|
4
|
+
// duplicating the patterns.
|
|
5
|
+
import { basename } from "node:path";
|
|
6
|
+
const TEST_FILE_PATTERNS = [
|
|
7
|
+
/\.test\.[jt]sx?$/,
|
|
8
|
+
/\.spec\.[jt]sx?$/,
|
|
9
|
+
/(^|\/)__tests__\//,
|
|
10
|
+
/(^|\/)tests?\//,
|
|
11
|
+
/_test\.go$/,
|
|
12
|
+
/_test\.py$/,
|
|
13
|
+
/(^|\/)test_[^/]+\.py$/,
|
|
14
|
+
/Test\.java$/,
|
|
15
|
+
/Tests\.java$/,
|
|
16
|
+
/Spec\.scala$/,
|
|
17
|
+
/_spec\.rb$/,
|
|
18
|
+
/(^|\/)spec\//,
|
|
19
|
+
/\.test\.exs$/,
|
|
20
|
+
/(^|\/)test\/.*\.exs$/,
|
|
21
|
+
];
|
|
22
|
+
export function isTestPath(path) {
|
|
23
|
+
return TEST_FILE_PATTERNS.some((re) => re.test(path));
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate the candidate test filenames that conventionally cover a source file.
|
|
27
|
+
* src/foo/bar.ts → bar.test.ts, bar.spec.ts
|
|
28
|
+
* src/foo/bar.py → test_bar.py, bar_test.py
|
|
29
|
+
* com/Foo.java → FooTest.java, FooTests.java
|
|
30
|
+
*/
|
|
31
|
+
export function candidateTestNames(sourcePath) {
|
|
32
|
+
const file = basename(sourcePath);
|
|
33
|
+
const dot = file.lastIndexOf(".");
|
|
34
|
+
if (dot <= 0)
|
|
35
|
+
return [];
|
|
36
|
+
const stem = file.slice(0, dot);
|
|
37
|
+
const ext = file.slice(dot);
|
|
38
|
+
const names = [];
|
|
39
|
+
if (/\.[jt]sx?$/.test(ext)) {
|
|
40
|
+
names.push(`${stem}.test${ext}`, `${stem}.spec${ext}`);
|
|
41
|
+
}
|
|
42
|
+
if (ext === ".py") {
|
|
43
|
+
names.push(`test_${stem}.py`, `${stem}_test.py`);
|
|
44
|
+
}
|
|
45
|
+
if (ext === ".go") {
|
|
46
|
+
names.push(`${stem}_test.go`);
|
|
47
|
+
}
|
|
48
|
+
if (ext === ".java" || ext === ".kt" || ext === ".scala") {
|
|
49
|
+
names.push(`${stem}Test${ext}`, `${stem}Tests${ext}`, `${stem}Spec${ext}`);
|
|
50
|
+
}
|
|
51
|
+
if (ext === ".rb") {
|
|
52
|
+
names.push(`${stem}_spec.rb`, `${stem}_test.rb`);
|
|
53
|
+
}
|
|
54
|
+
if (ext === ".rs") {
|
|
55
|
+
names.push(`${stem}_test.rs`);
|
|
56
|
+
}
|
|
57
|
+
if (ext === ".ex") {
|
|
58
|
+
names.push(`${stem}_test.exs`);
|
|
59
|
+
}
|
|
60
|
+
return names;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=test-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-paths.js","sourceRoot":"","sources":["../../../../src/server/tools/test-paths.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,2EAA2E;AAC3E,oEAAoE;AACpE,4BAA4B;AAE5B,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,kBAAkB,GAAG;IACzB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;IAChB,YAAY;IACZ,YAAY;IACZ,uBAAuB;IACvB,aAAa;IACb,cAAc;IACd,cAAc;IACd,YAAY;IACZ,cAAc;IACd,cAAc;IACd,sBAAsB;CACvB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE5B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,QAAQ,GAAG,EAAE,EAAE,GAAG,IAAI,QAAQ,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,GAAG,IAAI,UAAU,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,EAAE,EAAE,GAAG,IAAI,QAAQ,GAAG,EAAE,EAAE,GAAG,IAAI,OAAO,GAAG,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,EAAE,GAAG,IAAI,UAAU,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sverklo",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Sverklo — local-first code intelligence MCP server.
|
|
3
|
+
"version": "0.2.9",
|
|
4
|
+
"description": "Sverklo — local-first code intelligence MCP server. Diff-aware MR review, risk scoring, hybrid semantic search, PageRank ranking, persistent memory. Zero config.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sverklo": "dist/bin/sverklo.js"
|