@claude-flow/cli 3.72.0 → 3.72.1
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/.claude/helpers/helpers.manifest.json +2 -2
- package/.claude/skills/fast-code-edits/SKILL.md +45 -0
- package/.claude/skills/graph-mincut/SKILL.md +32 -0
- package/.claude/skills/injection-defense/SKILL.md +36 -0
- package/.claude/skills/lora-learning/SKILL.md +30 -0
- package/.claude/skills/sublinear-solver/SKILL.md +34 -0
- package/.claude/skills/vector-quantization/SKILL.md +36 -0
- package/catalog-manifest.json +4 -4
- package/dist/src/appliance/ruvllm-bridge.d.ts +6 -2
- package/dist/src/appliance/ruvllm-bridge.js +13 -8
- package/dist/src/commands/init.js +2 -0
- package/dist/src/commands/neural.js +79 -71
- package/dist/src/init/executor.js +13 -0
- package/dist/src/init/types.d.ts +6 -0
- package/dist/src/init/types.js +3 -0
- package/dist/src/mcp-client.js +2 -0
- package/dist/src/mcp-tools/agentdb-tools.js +34 -2
- package/dist/src/mcp-tools/fast-apply-tools.d.ts +4 -0
- package/dist/src/mcp-tools/fast-apply-tools.js +85 -0
- package/dist/src/mcp-tools/hooks-tools.js +2 -33
- package/dist/src/mcp-tools/metaharness-tools.js +1 -1
- package/dist/src/mcp-tools/realpath-containment.d.ts +3 -0
- package/dist/src/mcp-tools/realpath-containment.js +39 -0
- package/dist/src/mods/command-registry/schema.d.ts +12 -12
- package/dist/src/ruvector/ast-analyzer.d.ts +1 -2
- package/dist/src/ruvector/ast-analyzer.js +4 -12
- package/dist/src/ruvector/coverage-router.d.ts +1 -2
- package/dist/src/ruvector/coverage-router.js +4 -12
- package/dist/src/ruvector/diff-classifier.d.ts +1 -2
- package/dist/src/ruvector/diff-classifier.js +3 -12
- package/dist/src/ruvector/fast-apply.d.ts +46 -0
- package/dist/src/ruvector/fast-apply.js +73 -0
- package/dist/src/ruvector/graph-analyzer.d.ts +11 -1
- package/dist/src/ruvector/graph-analyzer.js +22 -36
- package/dist/src/ruvector/mincut-bridge.d.ts +70 -0
- package/dist/src/ruvector/mincut-bridge.js +172 -0
- package/dist/src/services/distill-oracle.d.ts +1 -1
- package/dist/src/services/distill-oracle.js +2 -2
- package/node_modules/@claude-flow/codex/.agents/skills/fast-code-edits/SKILL.md +42 -0
- package/node_modules/@claude-flow/codex/.agents/skills/graph-mincut/SKILL.md +42 -0
- package/node_modules/@claude-flow/codex/.agents/skills/injection-defense/SKILL.md +45 -0
- package/node_modules/@claude-flow/codex/.agents/skills/lora-learning/SKILL.md +39 -0
- package/node_modules/@claude-flow/codex/.agents/skills/sublinear-solver/SKILL.md +38 -0
- package/node_modules/@claude-flow/codex/.agents/skills/vector-quantization/SKILL.md +49 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js +6 -0
- package/node_modules/@claude-flow/codex/dist/generators/skill-md.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/index.d.ts +3 -3
- package/node_modules/@claude-flow/codex/dist/index.js +1 -1
- package/node_modules/@claude-flow/codex/dist/templates/index.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/dist/templates/index.js +37 -0
- package/node_modules/@claude-flow/codex/dist/templates/index.js.map +1 -1
- package/node_modules/@claude-flow/codex/dist/types.d.ts +1 -1
- package/node_modules/@claude-flow/codex/dist/types.d.ts.map +1 -1
- package/node_modules/@claude-flow/codex/package.json +1 -1
- package/package.json +11 -9
- package/plugins/ruflo-metaharness/.claude-plugin/plugin.json +1 -1
- package/plugins/ruflo-metaharness/scripts/_darwin.mjs +4 -4
- package/plugins/ruflo-metaharness/scripts/_harness.mjs +1 -1
- package/plugins/ruflo-metaharness/scripts/smoke.sh +4 -4
|
@@ -1502,6 +1502,8 @@ export const agentdbGraphPathfinder = {
|
|
|
1502
1502
|
}
|
|
1503
1503
|
const edges = rawEdges;
|
|
1504
1504
|
let paths = [];
|
|
1505
|
+
let mincutInfo;
|
|
1506
|
+
let approximation;
|
|
1505
1507
|
// Check millisecond budget before heavy computation
|
|
1506
1508
|
if (Date.now() - t0 > budget.maxMillis) {
|
|
1507
1509
|
return { success: true, paths: [], count: 0, message: `complexityBudget.maxMillis (${budget.maxMillis}ms) exceeded before solver dispatch`, seedNodeId, algorithm, elapsedMs: Date.now() - t0 };
|
|
@@ -1557,10 +1559,38 @@ export const agentdbGraphPathfinder = {
|
|
|
1557
1559
|
paths = witnessChain.slice(0, topK);
|
|
1558
1560
|
break;
|
|
1559
1561
|
}
|
|
1562
|
+
case 'dynamic-mincut': {
|
|
1563
|
+
// Exact minimum cut of the seed's depth-hop neighbourhood: the
|
|
1564
|
+
// weakest boundary around the seed, and the nodes on its side of it.
|
|
1565
|
+
// Wasm solver via ruvector (@ruvector/mincut-wasm), JS Stoer-Wagner
|
|
1566
|
+
// fallback for small neighbourhoods.
|
|
1567
|
+
const edgeTuples = edges.map(r => [String(r[0]), String(r[1]), Number(r[2]) || 1.0]);
|
|
1568
|
+
const { seedLocalMinCut } = await import('../ruvector/mincut-bridge.js');
|
|
1569
|
+
const { fallbackMinCut } = await import('../ruvector/graph-analyzer.js');
|
|
1570
|
+
const cut = await seedLocalMinCut(seedNodeId, edgeTuples, depth, budget.maxNodesVisited, fallbackMinCut);
|
|
1571
|
+
if (!cut) {
|
|
1572
|
+
mincutInfo = { backend: 'none', message: 'seed neighbourhood too large for the JS fallback and the wasm solver is unavailable (install ruvector)' };
|
|
1573
|
+
break;
|
|
1574
|
+
}
|
|
1575
|
+
paths = cut.seedSide
|
|
1576
|
+
.map(r => ({ nodeId: r.nodeId, score: 1 / (1 + r.depth), depth: r.depth }))
|
|
1577
|
+
.filter(r => r.score >= threshold)
|
|
1578
|
+
.slice(0, topK);
|
|
1579
|
+
mincutInfo = {
|
|
1580
|
+
backend: cut.backend,
|
|
1581
|
+
cutValue: cut.cutValue,
|
|
1582
|
+
seedSideSize: cut.seedSide.length + 1,
|
|
1583
|
+
otherSideSize: cut.otherSide.length,
|
|
1584
|
+
subgraphNodes: cut.subgraphNodes,
|
|
1585
|
+
cutEdges: cut.cutEdges.slice(0, 50),
|
|
1586
|
+
};
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1560
1589
|
case 'connected-component-churn':
|
|
1561
|
-
case 'dynamic-mincut':
|
|
1562
1590
|
case 'spectral-sparsify': {
|
|
1563
|
-
//
|
|
1591
|
+
// Not implemented natively yet: approximated by k-hop neighbours with
|
|
1592
|
+
// a rank-decay score. The response says so via `implementation`.
|
|
1593
|
+
approximation = 'k-hop';
|
|
1564
1594
|
const edgeTuples = edges.map(r => [r[0], r[1], Number(r[2]) || 1.0]);
|
|
1565
1595
|
const khopResult = await agentdbGraphQuery.handler({
|
|
1566
1596
|
nodeId: seedNodeId, mode: 'k-hop', depth, complexityBudget: budget,
|
|
@@ -1582,6 +1612,8 @@ export const agentdbGraphPathfinder = {
|
|
|
1582
1612
|
count: paths.length,
|
|
1583
1613
|
elapsedMs,
|
|
1584
1614
|
budgetUsed: { millis: elapsedMs, nodes: rawEdges.length },
|
|
1615
|
+
...(mincutInfo && { mincut: mincutInfo }),
|
|
1616
|
+
...(approximation && { implementation: `${approximation} approximation` }),
|
|
1585
1617
|
...(depthWarning && { warning: depthWarning }),
|
|
1586
1618
|
};
|
|
1587
1619
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hooks_fast-apply — merge a code snippet into a file or string with
|
|
3
|
+
* agent-booster (~ms, no LLM). The caller supplies the target code; for
|
|
4
|
+
* deterministic intents with no snippet use hooks_codemod instead.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
7
|
+
import { resolve, sep } from 'path';
|
|
8
|
+
import { getProjectCwd } from './types.js';
|
|
9
|
+
import { validatePath } from './validate-input.js';
|
|
10
|
+
import { realpathNearest, isInsideRealRoot } from './realpath-containment.js';
|
|
11
|
+
const MAX_INPUT_BYTES = 1_000_000;
|
|
12
|
+
function langForPath(p) {
|
|
13
|
+
const ext = p.slice(p.lastIndexOf('.') + 1).toLowerCase();
|
|
14
|
+
const map = {
|
|
15
|
+
ts: 'typescript', tsx: 'typescript', mts: 'typescript', cts: 'typescript',
|
|
16
|
+
js: 'javascript', jsx: 'javascript', mjs: 'javascript', cjs: 'javascript',
|
|
17
|
+
py: 'python', rs: 'rust', go: 'go', java: 'java', c: 'c', cpp: 'cpp', h: 'c',
|
|
18
|
+
};
|
|
19
|
+
return map[ext];
|
|
20
|
+
}
|
|
21
|
+
export const hooksFastApply = {
|
|
22
|
+
name: 'hooks_fast-apply',
|
|
23
|
+
description: 'Merge an edit SNIPPET (the rewritten code, e.g. a whole new version of one function) into a file or raw code using agent-booster — a local fast-apply engine (~1-10 ms, no LLM, $0). `edit` must be code, not an instruction: "make add typed" fails, "function add(a: number, b: number): number { return a + b; }" works. Use when you already have the replacement code and the surrounding file is large, instead of re-sending the whole file. Deterministic intents (var-to-const, remove-console, add-logging) belong to hooks_codemod. Returns confidence + strategy; below minConfidence nothing is written.',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
edit: { type: 'string', description: 'Target code snippet to merge (code, not an instruction)' },
|
|
28
|
+
file: { type: 'string', description: 'Existing file inside the project to patch in place' },
|
|
29
|
+
code: { type: 'string', description: 'Raw source to patch instead of a file (returns output, writes nothing)' },
|
|
30
|
+
language: { type: 'string', description: 'Language hint (inferred from the file extension when omitted)' },
|
|
31
|
+
minConfidence: { type: 'number', description: 'Minimum merge confidence 0-1 required to apply (default 0.5)' },
|
|
32
|
+
dryRun: { type: 'boolean', description: 'Report the merge result without writing the file' },
|
|
33
|
+
},
|
|
34
|
+
required: ['edit'],
|
|
35
|
+
},
|
|
36
|
+
handler: async (params) => {
|
|
37
|
+
const edit = params.edit;
|
|
38
|
+
if (typeof edit !== 'string' || edit.trim() === '')
|
|
39
|
+
return { success: false, error: 'edit (non-empty code snippet) is required' };
|
|
40
|
+
if (edit.length > MAX_INPUT_BYTES)
|
|
41
|
+
return { success: false, error: 'edit too large' };
|
|
42
|
+
const minConfidence = typeof params.minConfidence === 'number'
|
|
43
|
+
? Math.min(Math.max(params.minConfidence, 0), 1) : 0.5;
|
|
44
|
+
const dryRun = params.dryRun === true;
|
|
45
|
+
const { fastApply } = await import('../ruvector/fast-apply.js');
|
|
46
|
+
if (typeof params.code === 'string') {
|
|
47
|
+
if (params.code.length > MAX_INPUT_BYTES)
|
|
48
|
+
return { success: false, error: 'code too large' };
|
|
49
|
+
const r = await fastApply({ code: params.code, edit, language: params.language, minConfidence });
|
|
50
|
+
return { ...r, mode: 'code', cost: 0 };
|
|
51
|
+
}
|
|
52
|
+
if (typeof params.file !== 'string')
|
|
53
|
+
return { success: false, error: 'Provide `file` or `code`.' };
|
|
54
|
+
const v = validatePath(params.file, 'file');
|
|
55
|
+
if (!v.valid)
|
|
56
|
+
return { success: false, error: v.error };
|
|
57
|
+
const cwd = getProjectCwd();
|
|
58
|
+
const abs = resolve(cwd, v.sanitized);
|
|
59
|
+
if (abs !== cwd && !abs.startsWith(cwd + sep))
|
|
60
|
+
return { success: false, error: `path escapes project root: ${params.file}` };
|
|
61
|
+
let realRoot;
|
|
62
|
+
try {
|
|
63
|
+
realRoot = realpathNearest(cwd);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return { success: false, error: `cannot resolve project root: ${err.message}` };
|
|
67
|
+
}
|
|
68
|
+
if (!isInsideRealRoot(realRoot, abs))
|
|
69
|
+
return { success: false, error: `path escapes project root via symlink: ${params.file}` };
|
|
70
|
+
if (!existsSync(abs))
|
|
71
|
+
return { success: false, error: `file not found: ${params.file}` };
|
|
72
|
+
const before = readFileSync(abs, 'utf-8');
|
|
73
|
+
if (before.length > MAX_INPUT_BYTES)
|
|
74
|
+
return { success: false, error: 'file too large' };
|
|
75
|
+
const language = params.language ?? langForPath(abs);
|
|
76
|
+
const r = await fastApply({ code: before, edit, language, minConfidence });
|
|
77
|
+
const written = r.success && !dryRun;
|
|
78
|
+
if (written)
|
|
79
|
+
writeFileSync(abs, r.output, 'utf-8');
|
|
80
|
+
const { output, ...meta } = r;
|
|
81
|
+
return { ...meta, mode: dryRun ? 'dry-run' : 'file', file: params.file, written, ...(dryRun && { output }), cost: 0 };
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export const fastApplyTools = [hooksFastApply];
|
|
85
|
+
//# sourceMappingURL=fast-apply-tools.js.map
|
|
@@ -5,9 +5,10 @@ import { feedbackPatternsSchema, validateFeedbackPatterns } from '../memory/feed
|
|
|
5
5
|
*/
|
|
6
6
|
import { mkdirSync, writeFileSync, existsSync, readFileSync, statSync, unlinkSync, readdirSync } from 'fs';
|
|
7
7
|
import * as nodeFs from 'fs';
|
|
8
|
-
import {
|
|
8
|
+
import { dirname, join, resolve, sep } from 'path';
|
|
9
9
|
import { getProjectCwd } from './types.js';
|
|
10
10
|
import { validateIdentifier, validateText, validatePath } from './validate-input.js';
|
|
11
|
+
import { realpathNearest, isInsideRealRoot } from './realpath-containment.js';
|
|
11
12
|
import { commandRecordingDisabled, redactCommandForStorage } from '../services/command-recording.js';
|
|
12
13
|
import { checkCommandLoop, recordCommandOutcome } from './tool-loop-guardrail.js';
|
|
13
14
|
import { buildLearnedRoutingPatterns, } from '../services/learned-routing.js';
|
|
@@ -5126,38 +5127,6 @@ function codemodLangForExt(abs) {
|
|
|
5126
5127
|
return 'javascript';
|
|
5127
5128
|
return 'typescript';
|
|
5128
5129
|
}
|
|
5129
|
-
// Canonicalize a path that may not exist yet: realpath the nearest existing
|
|
5130
|
-
// ancestor and re-attach the missing tail, so a symlinked parent still
|
|
5131
|
-
// resolves to its real location (mirrors @claude-flow/security's
|
|
5132
|
-
// canonicalizeSync, which is not exported).
|
|
5133
|
-
function realpathNearest(p) {
|
|
5134
|
-
try {
|
|
5135
|
-
return nodeFs.realpathSync(p);
|
|
5136
|
-
}
|
|
5137
|
-
catch (err) {
|
|
5138
|
-
if (err?.code !== 'ENOENT')
|
|
5139
|
-
throw err;
|
|
5140
|
-
}
|
|
5141
|
-
const parent = dirname(p);
|
|
5142
|
-
if (parent === p)
|
|
5143
|
-
return p;
|
|
5144
|
-
return join(realpathNearest(parent), basename(p));
|
|
5145
|
-
}
|
|
5146
|
-
// CWE-59 (#4346): containment must compare real paths on BOTH sides — a
|
|
5147
|
-
// symlink inside the project pointing outside it must not pass, and a
|
|
5148
|
-
// symlinked project root (e.g. macOS /var -> /private/var) must not make
|
|
5149
|
-
// every path fail. Fails closed if canonicalization throws (ELOOP, EACCES).
|
|
5150
|
-
function isInsideRealRoot(realRoot, abs) {
|
|
5151
|
-
let real;
|
|
5152
|
-
try {
|
|
5153
|
-
real = realpathNearest(abs);
|
|
5154
|
-
}
|
|
5155
|
-
catch {
|
|
5156
|
-
return false;
|
|
5157
|
-
}
|
|
5158
|
-
const rel = relative(realRoot, real);
|
|
5159
|
-
return rel === '' || (rel !== '..' && !rel.startsWith('..' + sep) && !isAbsolute(rel));
|
|
5160
|
-
}
|
|
5161
5130
|
// Deterministic codemod execution — the real Tier-1 path (ADR-143)
|
|
5162
5131
|
export const hooksCodemod = {
|
|
5163
5132
|
name: 'hooks_codemod',
|
|
@@ -399,7 +399,7 @@ export const metaharnessTools = [
|
|
|
399
399
|
},
|
|
400
400
|
// ───────────────────────────────────────────────────────────────────────
|
|
401
401
|
// ADR-153 — @metaharness/darwin integration (3 tools).
|
|
402
|
-
// Backed by the separate `@metaharness/darwin@~0.
|
|
402
|
+
// Backed by the separate `@metaharness/darwin@~0.13.0` npm package, NOT
|
|
403
403
|
// the umbrella `metaharness`. Plugin scripts shell out via _darwin.mjs.
|
|
404
404
|
// Same {success, data, degraded, exitCode} contract.
|
|
405
405
|
// ───────────────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-root containment for MCP tools that read or write files.
|
|
3
|
+
* Shared by hooks_codemod and hooks_fast-apply (moved out of hooks-tools.ts).
|
|
4
|
+
*/
|
|
5
|
+
import * as nodeFs from 'fs';
|
|
6
|
+
import { basename, dirname, isAbsolute, join, relative, sep } from 'path';
|
|
7
|
+
// Canonicalize a path that may not exist yet: realpath the nearest existing
|
|
8
|
+
// ancestor and re-attach the missing tail, so a symlinked parent still
|
|
9
|
+
// resolves to its real location (mirrors @claude-flow/security's
|
|
10
|
+
// canonicalizeSync, which is not exported).
|
|
11
|
+
export function realpathNearest(p) {
|
|
12
|
+
try {
|
|
13
|
+
return nodeFs.realpathSync(p);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err?.code !== 'ENOENT')
|
|
17
|
+
throw err;
|
|
18
|
+
}
|
|
19
|
+
const parent = dirname(p);
|
|
20
|
+
if (parent === p)
|
|
21
|
+
return p;
|
|
22
|
+
return join(realpathNearest(parent), basename(p));
|
|
23
|
+
}
|
|
24
|
+
// CWE-59 (#4346): containment must compare real paths on BOTH sides — a
|
|
25
|
+
// symlink inside the project pointing outside it must not pass, and a
|
|
26
|
+
// symlinked project root (e.g. macOS /var -> /private/var) must not make
|
|
27
|
+
// every path fail. Fails closed if canonicalization throws (ELOOP, EACCES).
|
|
28
|
+
export function isInsideRealRoot(realRoot, abs) {
|
|
29
|
+
let real;
|
|
30
|
+
try {
|
|
31
|
+
real = realpathNearest(abs);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const rel = relative(realRoot, real);
|
|
37
|
+
return rel === '' || (rel !== '..' && !rel.startsWith('..' + sep) && !isAbsolute(rel));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=realpath-containment.js.map
|
|
@@ -192,8 +192,8 @@ export declare const inventorySourceSchema: z.ZodObject<{
|
|
|
192
192
|
}, "strict", z.ZodTypeAny, {
|
|
193
193
|
digest: string;
|
|
194
194
|
sourcePath: string;
|
|
195
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
196
195
|
package: string;
|
|
196
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
197
197
|
observedInvocation: string;
|
|
198
198
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
199
199
|
shippedIn: string[];
|
|
@@ -201,8 +201,8 @@ export declare const inventorySourceSchema: z.ZodObject<{
|
|
|
201
201
|
}, {
|
|
202
202
|
digest: string;
|
|
203
203
|
sourcePath: string;
|
|
204
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
205
204
|
package: string;
|
|
205
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
206
206
|
observedInvocation: string;
|
|
207
207
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
208
208
|
shippedIn: string[];
|
|
@@ -370,8 +370,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
|
|
|
370
370
|
}, "strict", z.ZodTypeAny, {
|
|
371
371
|
digest: string;
|
|
372
372
|
sourcePath: string;
|
|
373
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
374
373
|
package: string;
|
|
374
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
375
375
|
observedInvocation: string;
|
|
376
376
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
377
377
|
shippedIn: string[];
|
|
@@ -379,8 +379,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
|
|
|
379
379
|
}, {
|
|
380
380
|
digest: string;
|
|
381
381
|
sourcePath: string;
|
|
382
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
383
382
|
package: string;
|
|
383
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
384
384
|
observedInvocation: string;
|
|
385
385
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
386
386
|
shippedIn: string[];
|
|
@@ -391,8 +391,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
|
|
|
391
391
|
sources: {
|
|
392
392
|
digest: string;
|
|
393
393
|
sourcePath: string;
|
|
394
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
395
394
|
package: string;
|
|
395
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
396
396
|
observedInvocation: string;
|
|
397
397
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
398
398
|
shippedIn: string[];
|
|
@@ -432,8 +432,8 @@ export declare const catalogEntrySchema: z.ZodObject<{
|
|
|
432
432
|
sources: {
|
|
433
433
|
digest: string;
|
|
434
434
|
sourcePath: string;
|
|
435
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
436
435
|
package: string;
|
|
436
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
437
437
|
observedInvocation: string;
|
|
438
438
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
439
439
|
shippedIn: string[];
|
|
@@ -636,8 +636,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
636
636
|
}, "strict", z.ZodTypeAny, {
|
|
637
637
|
digest: string;
|
|
638
638
|
sourcePath: string;
|
|
639
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
640
639
|
package: string;
|
|
640
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
641
641
|
observedInvocation: string;
|
|
642
642
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
643
643
|
shippedIn: string[];
|
|
@@ -645,8 +645,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
645
645
|
}, {
|
|
646
646
|
digest: string;
|
|
647
647
|
sourcePath: string;
|
|
648
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
649
648
|
package: string;
|
|
649
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
650
650
|
observedInvocation: string;
|
|
651
651
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
652
652
|
shippedIn: string[];
|
|
@@ -657,8 +657,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
657
657
|
sources: {
|
|
658
658
|
digest: string;
|
|
659
659
|
sourcePath: string;
|
|
660
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
661
660
|
package: string;
|
|
661
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
662
662
|
observedInvocation: string;
|
|
663
663
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
664
664
|
shippedIn: string[];
|
|
@@ -698,8 +698,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
698
698
|
sources: {
|
|
699
699
|
digest: string;
|
|
700
700
|
sourcePath: string;
|
|
701
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
702
701
|
package: string;
|
|
702
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
703
703
|
observedInvocation: string;
|
|
704
704
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
705
705
|
shippedIn: string[];
|
|
@@ -741,8 +741,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
741
741
|
sources: {
|
|
742
742
|
digest: string;
|
|
743
743
|
sourcePath: string;
|
|
744
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
745
744
|
package: string;
|
|
745
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
746
746
|
observedInvocation: string;
|
|
747
747
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
748
748
|
shippedIn: string[];
|
|
@@ -787,8 +787,8 @@ export declare const commandCatalogSchema: z.ZodObject<{
|
|
|
787
787
|
sources: {
|
|
788
788
|
digest: string;
|
|
789
789
|
sourcePath: string;
|
|
790
|
-
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
791
790
|
package: string;
|
|
791
|
+
channel: "repo-project-commands" | "cli-init-template" | "marketplace-plugin" | "source-plugin" | "mod-registration";
|
|
792
792
|
observedInvocation: string;
|
|
793
793
|
binding: "markdown-loader" | "mod-register" | "mod-middleware-on-markdown";
|
|
794
794
|
shippedIn: string[];
|
|
@@ -40,8 +40,7 @@ export interface ASTAnalysis {
|
|
|
40
40
|
}
|
|
41
41
|
export declare class ASTAnalyzer {
|
|
42
42
|
private config;
|
|
43
|
-
private
|
|
44
|
-
private useNative;
|
|
43
|
+
private readonly useNative;
|
|
45
44
|
private analysisCache;
|
|
46
45
|
constructor(config?: Partial<ASTAnalyzerConfig>);
|
|
47
46
|
initialize(): Promise<void>;
|
|
@@ -22,24 +22,16 @@ const LANGUAGE_PATTERNS = {
|
|
|
22
22
|
};
|
|
23
23
|
export class ASTAnalyzer {
|
|
24
24
|
config;
|
|
25
|
-
ruvectorEngine = null;
|
|
26
25
|
useNative = false;
|
|
27
26
|
analysisCache = new Map();
|
|
28
27
|
constructor(config = {}) {
|
|
29
28
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
30
29
|
}
|
|
31
30
|
async initialize() {
|
|
32
|
-
try
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.ruvectorEngine = ruvector.createASTAnalyzer?.(this.config);
|
|
37
|
-
this.useNative = !!this.ruvectorEngine;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
this.useNative = false;
|
|
42
|
-
}
|
|
31
|
+
// Pure-JS analysis. This used to try `import('@ruvector/ast')`, a package that has
|
|
32
|
+
// never been published (npm 404), so it always fell through to here. ruvector@0.3's
|
|
33
|
+
// ASTParser needs the native tree-sitter grammars and is async-only, so it cannot
|
|
34
|
+
// back this synchronous analyzer.
|
|
43
35
|
}
|
|
44
36
|
analyze(code, filePath = 'unknown') {
|
|
45
37
|
const startTime = performance.now();
|
|
@@ -63,8 +63,7 @@ export interface CoverageRouteResult {
|
|
|
63
63
|
}
|
|
64
64
|
export declare class CoverageRouter {
|
|
65
65
|
private config;
|
|
66
|
-
private
|
|
67
|
-
private useNative;
|
|
66
|
+
private readonly useNative;
|
|
68
67
|
private coverageHistory;
|
|
69
68
|
constructor(config?: Partial<CoverageRouterConfig>);
|
|
70
69
|
initialize(): Promise<void>;
|
|
@@ -37,24 +37,16 @@ const DEFAULT_CONFIG = {
|
|
|
37
37
|
};
|
|
38
38
|
export class CoverageRouter {
|
|
39
39
|
config;
|
|
40
|
-
ruvectorEngine = null;
|
|
41
40
|
useNative = false;
|
|
42
41
|
coverageHistory = [];
|
|
43
42
|
constructor(config = {}) {
|
|
44
43
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
45
44
|
}
|
|
46
45
|
async initialize() {
|
|
47
|
-
try
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.ruvectorEngine = ruvector.createCoverageRouter?.(this.config);
|
|
52
|
-
this.useNative = !!this.ruvectorEngine;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
this.useNative = false;
|
|
57
|
-
}
|
|
46
|
+
// Pure-JS analysis. This used to try `import('@ruvector/coverage')`, a package that
|
|
47
|
+
// has never been published (npm 404), so it always fell through to here.
|
|
48
|
+
// ruvector@0.3's parseIstanbulCoverage is a plain-JS parser equivalent to the parsers
|
|
49
|
+
// below.
|
|
58
50
|
}
|
|
59
51
|
parseCoverage(data, format = 'json') {
|
|
60
52
|
switch (format) {
|
|
@@ -49,8 +49,7 @@ export interface DiffAnalysis {
|
|
|
49
49
|
}
|
|
50
50
|
export declare class DiffClassifier {
|
|
51
51
|
private config;
|
|
52
|
-
private
|
|
53
|
-
private useNative;
|
|
52
|
+
private readonly useNative;
|
|
54
53
|
private classificationCache;
|
|
55
54
|
constructor(config?: Partial<DiffClassifierConfig>);
|
|
56
55
|
initialize(): Promise<void>;
|
|
@@ -60,24 +60,15 @@ function isSecuritySensitivePath(path) {
|
|
|
60
60
|
}
|
|
61
61
|
export class DiffClassifier {
|
|
62
62
|
config;
|
|
63
|
-
ruvectorEngine = null;
|
|
64
63
|
useNative = false;
|
|
65
64
|
classificationCache = new Map();
|
|
66
65
|
constructor(config = {}) {
|
|
67
66
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
68
67
|
}
|
|
69
68
|
async initialize() {
|
|
70
|
-
try
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (ruvector) {
|
|
74
|
-
this.ruvectorEngine = ruvector.createDiffClassifier?.(this.config);
|
|
75
|
-
this.useNative = !!this.ruvectorEngine;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
this.useNative = false;
|
|
80
|
-
}
|
|
69
|
+
// Pure-JS analysis. This used to try `import('@ruvector/diff')`, a package that has
|
|
70
|
+
// never been published (npm 404), so it always fell through to here. ruvector@0.3's
|
|
71
|
+
// parseDiff is a plain-JS parser equivalent to parseDiff() below.
|
|
81
72
|
}
|
|
82
73
|
parseDiff(diffContent) {
|
|
83
74
|
const files = [];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast-apply: merge an edit snippet into existing code with agent-booster.
|
|
3
|
+
*
|
|
4
|
+
* agent-booster is a Morph/Cursor-style *applier*: `apply({ code, edit })`
|
|
5
|
+
* expects `edit` to be the target code (e.g. the rewritten function), and it
|
|
6
|
+
* locates and splices it into `code` in a few milliseconds with no LLM call.
|
|
7
|
+
* It cannot turn a natural-language instruction into an edit — given one it
|
|
8
|
+
* returns `success: false, strategy: "failed"` (see ADR-143). So this is the
|
|
9
|
+
* path for callers that already hold a snippet (an agent's proposed rewrite),
|
|
10
|
+
* not a Tier-1 intent engine; deterministic intents stay in hooks_codemod.
|
|
11
|
+
*/
|
|
12
|
+
export interface FastApplyRequest {
|
|
13
|
+
code: string;
|
|
14
|
+
edit: string;
|
|
15
|
+
language?: string;
|
|
16
|
+
/** Results below this confidence are reported as not applied. Default 0.5. */
|
|
17
|
+
minConfidence?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface FastApplyResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
output: string;
|
|
22
|
+
confidence: number;
|
|
23
|
+
strategy: string;
|
|
24
|
+
latencyMs: number;
|
|
25
|
+
backend: 'agent-booster' | 'unavailable';
|
|
26
|
+
reason?: string;
|
|
27
|
+
}
|
|
28
|
+
interface BoosterLike {
|
|
29
|
+
apply(req: {
|
|
30
|
+
code: string;
|
|
31
|
+
edit: string;
|
|
32
|
+
language?: string;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
output: string;
|
|
35
|
+
success: boolean;
|
|
36
|
+
confidence: number;
|
|
37
|
+
strategy: string;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
/** Lazily construct one AgentBooster. Resolves null when it is not installed. */
|
|
41
|
+
export declare function loadAgentBooster(): Promise<BoosterLike | null>;
|
|
42
|
+
/** Test hook: forget the memoised AgentBooster. */
|
|
43
|
+
export declare function resetAgentBoosterLoader(): void;
|
|
44
|
+
export declare function fastApply(req: FastApplyRequest): Promise<FastApplyResult>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=fast-apply.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast-apply: merge an edit snippet into existing code with agent-booster.
|
|
3
|
+
*
|
|
4
|
+
* agent-booster is a Morph/Cursor-style *applier*: `apply({ code, edit })`
|
|
5
|
+
* expects `edit` to be the target code (e.g. the rewritten function), and it
|
|
6
|
+
* locates and splices it into `code` in a few milliseconds with no LLM call.
|
|
7
|
+
* It cannot turn a natural-language instruction into an edit — given one it
|
|
8
|
+
* returns `success: false, strategy: "failed"` (see ADR-143). So this is the
|
|
9
|
+
* path for callers that already hold a snippet (an agent's proposed rewrite),
|
|
10
|
+
* not a Tier-1 intent engine; deterministic intents stay in hooks_codemod.
|
|
11
|
+
*/
|
|
12
|
+
let boosterPromise = null;
|
|
13
|
+
/** Lazily construct one AgentBooster. Resolves null when it is not installed. */
|
|
14
|
+
export function loadAgentBooster() {
|
|
15
|
+
if (!boosterPromise) {
|
|
16
|
+
boosterPromise = (async () => {
|
|
17
|
+
try {
|
|
18
|
+
const specifier = 'agent-booster';
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- optional dep
|
|
20
|
+
const mod = await import(specifier);
|
|
21
|
+
const Ctor = mod?.AgentBooster ?? mod?.default?.AgentBooster ?? mod?.default;
|
|
22
|
+
if (typeof Ctor !== 'function')
|
|
23
|
+
return null;
|
|
24
|
+
// Our own threshold is applied below; let the engine report everything.
|
|
25
|
+
return new Ctor({ confidenceThreshold: 0 });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
})();
|
|
31
|
+
}
|
|
32
|
+
return boosterPromise;
|
|
33
|
+
}
|
|
34
|
+
/** Test hook: forget the memoised AgentBooster. */
|
|
35
|
+
export function resetAgentBoosterLoader() {
|
|
36
|
+
boosterPromise = null;
|
|
37
|
+
}
|
|
38
|
+
export async function fastApply(req) {
|
|
39
|
+
const start = performance.now();
|
|
40
|
+
const minConfidence = req.minConfidence ?? 0.5;
|
|
41
|
+
const booster = await loadAgentBooster();
|
|
42
|
+
if (!booster) {
|
|
43
|
+
return {
|
|
44
|
+
success: false, output: req.code, confidence: 0, strategy: 'none',
|
|
45
|
+
latencyMs: performance.now() - start, backend: 'unavailable',
|
|
46
|
+
reason: 'agent-booster is not installed (npm i agent-booster); apply the edit with the Edit tool instead',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const r = await booster.apply({ code: req.code, edit: req.edit, language: req.language });
|
|
51
|
+
const applied = r.success && r.confidence >= minConfidence && r.output !== req.code;
|
|
52
|
+
return {
|
|
53
|
+
success: applied,
|
|
54
|
+
output: applied ? r.output : req.code,
|
|
55
|
+
confidence: r.confidence,
|
|
56
|
+
strategy: r.strategy,
|
|
57
|
+
latencyMs: performance.now() - start,
|
|
58
|
+
backend: 'agent-booster',
|
|
59
|
+
reason: applied ? undefined
|
|
60
|
+
: !r.success ? 'agent-booster could not place the snippet (it must be code, not an instruction)'
|
|
61
|
+
: r.output === req.code ? 'snippet is already present; nothing to change'
|
|
62
|
+
: `confidence ${r.confidence.toFixed(2)} below minConfidence ${minConfidence}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
return {
|
|
67
|
+
success: false, output: req.code, confidence: 0, strategy: 'error',
|
|
68
|
+
latencyMs: performance.now() - start, backend: 'agent-booster',
|
|
69
|
+
reason: `agent-booster threw: ${err.message}`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=fast-apply.js.map
|
|
@@ -121,9 +121,19 @@ interface IRuVectorGraph {
|
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
124
|
+
* Load the accelerated graph backend.
|
|
125
|
+
*
|
|
126
|
+
* MinCut runs on ruvector's `DynamicMinCut` (the `@ruvector/mincut-wasm`
|
|
127
|
+
* solver ruvector ships as an optional dependency), see mincut-bridge.ts.
|
|
128
|
+
* Inputs the wasm solver cannot describe (isolated nodes, no edges) and
|
|
129
|
+
* Louvain go to the built-in JS implementations — ruvector's own
|
|
130
|
+
* `louvainCommunities` is plain JS too, so there is nothing to gain there.
|
|
131
|
+
* Returns null when the wasm solver is unavailable; callers then use the
|
|
132
|
+
* built-in Stoer-Wagner `fallbackMinCut`.
|
|
125
133
|
*/
|
|
126
134
|
declare function loadRuVector(): Promise<IRuVectorGraph | null>;
|
|
135
|
+
/** Which MinCut backend `analyzeMinCutBoundaries` will use. */
|
|
136
|
+
export declare function getMinCutBackend(): Promise<'mincut-wasm' | 'stoer-wagner'>;
|
|
127
137
|
/**
|
|
128
138
|
* Build dependency graph from source directory (with caching)
|
|
129
139
|
*/
|