mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-07-09 17:28:42 +00:00
fix(ruvector-npm): accurate MCP tool count + reconcile tool lists (0.2.33) (#624)
* fix(ruvector-npm): accurate MCP tool count + reconcile tool lists (0.2.33) The package advertised 103 MCP tools but the server registers 97, and the README listed 12 tools (brain_agi_*, midstream_*) that don't exist. Three independent sources had also drifted: server TOOLS array (97), the cli 'mcp tools' display list (91, missing the 6 decompile_* tools), and the README count (103). - README: 103 → 97; drop the 12 phantom tool bullets; point to 'npx ruvector mcp tools' as the authoritative list - cli.js 'mcp tools': add the missing 'decompile' group (6 tools) → now lists 97, matching the server - mcp-server.js: report version from package.json instead of the hardcoded (and stale) '0.2.30' - bump 0.2.32 → 0.2.33 All three sources now reconcile to 97. Full test suite passes (73 + 7 + 2 + 8 + 2 across the publish-gate files). Co-Authored-By: claude-flow <ruv@ruv.net> * fix(ci): commit optimizer module, ignore RUSTSEC-2026-0190, ship src/optimizer Root-causes three pre-existing CI failures on the ruvector npm package: 1. Optimizer test (Cannot find module src/optimizer/index.js): the module was never committed because .gitignore's bare 'index.js' rule (for napi artifacts) silently ignored this hand-written module. Add a negation exception (as already done for @ruvector/sona) and commit index.js — 8 profiles, detectTaskType, applyProfile. Test: 135/135 pass. 2. cargo deny (advisories FAILED): RUSTSEC-2026-0190 (unsoundness in anyhow's Error::downcast_mut, anyhow 1.0.102, single version in tree). Added to deny.toml ignore list with justification + re-review date, consistent with the existing unsoundness exceptions — we never downcast anyhow::Error to a mismatched mutable type. 3. src/optimizer/ now ships (added to package.json files), so the published package's 'optimize' command works instead of graceful-degrading. Pre-existing failures NOT addressed here (separate infra work; main is also red): Functional smoke / Recall quality / Learning check fail because the npm CI installs with --no-optional, so @ruvector/rvf + the native HNSW addon are absent and the engine runs degraded. dependency-review is already continue-on-error (awaiting a repo Dependency-Graph settings flip). Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
parent
ee620d600f
commit
227bb3f876
7 changed files with 207 additions and 8 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -41,6 +41,10 @@ index.d.ts
|
||||||
# (v3 emits no v2-style loader), which published an empty 0.1.6 (#516)
|
# (v3 emits no v2-style loader), which published an empty 0.1.6 (#516)
|
||||||
!npm/packages/sona/index.js
|
!npm/packages/sona/index.js
|
||||||
!npm/packages/sona/index.d.ts
|
!npm/packages/sona/index.d.ts
|
||||||
|
# ruvector optimizer is a hand-written module (not a napi artifact); the bare
|
||||||
|
# `index.js` rule above wrongly ignored it, so it was never committed and CI's
|
||||||
|
# optimizer test could not resolve it.
|
||||||
|
!npm/packages/ruvector/src/optimizer/index.js
|
||||||
|
|
||||||
# Environment variables and secrets
|
# Environment variables and secrets
|
||||||
.env
|
.env
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,14 @@ ignore = [
|
||||||
# mmap loading and other crates; no fixed release on the 0.9 line yet.
|
# mmap loading and other crates; no fixed release on the 0.9 line yet.
|
||||||
# We don't pass attacker-controlled offsets to memmap2. Re-review 2026-08-01.
|
# We don't pass attacker-controlled offsets to memmap2. Re-review 2026-08-01.
|
||||||
"RUSTSEC-2026-0186",
|
"RUSTSEC-2026-0186",
|
||||||
|
|
||||||
|
# anyhow 1.0.102 — unsoundness in `Error::downcast_mut()` (RUSTSEC-2026-0190,
|
||||||
|
# "unsound", not an exploitable vuln). Triggering it requires downcasting an
|
||||||
|
# `anyhow::Error` to a mismatched mutable type — a pattern we never use; our
|
||||||
|
# usage is construct/propagate/`Display`/read-only `downcast_ref`. Single
|
||||||
|
# version (1.0.102) in the tree. Bump to the patched anyhow once it ships and
|
||||||
|
# remove this entry. Re-review 2026-08-01.
|
||||||
|
"RUSTSEC-2026-0190",
|
||||||
]
|
]
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ npx ruvector hooks init --pretrain --build-agents quality
|
||||||
|
|
||||||
### MCP Server Integration
|
### MCP Server Integration
|
||||||
|
|
||||||
RuVector includes an MCP server for Claude Code with 103 tools:
|
RuVector includes an MCP server for Claude Code with 97 tools:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Add to Claude Code
|
# Add to Claude Code
|
||||||
|
|
@ -86,10 +86,11 @@ claude mcp add ruvector -- npx ruvector mcp start
|
||||||
- `hooks_rag_context` — Semantic context retrieval
|
- `hooks_rag_context` — Semantic context retrieval
|
||||||
- `hooks_attention_info`, `hooks_gnn_info` — Neural capabilities
|
- `hooks_attention_info`, `hooks_gnn_info` — Neural capabilities
|
||||||
- `brain_search`, `brain_share`, `brain_status` — Shared brain knowledge
|
- `brain_search`, `brain_share`, `brain_status` — Shared brain knowledge
|
||||||
- `brain_agi_status`, `brain_sona_stats`, `brain_temporal`, `brain_explore` — AGI diagnostics
|
- `decompile_package`, `decompile_file`, `decompile_url` — Package/file decompilation + witness
|
||||||
- `brain_midstream`, `brain_flags` — Midstream platform + feature flags
|
- `edge_status`, `edge_join`, `edge_balance` — Edge cluster coordination
|
||||||
- `midstream_status`, `midstream_attractor`, `midstream_scheduler` — Streaming analysis
|
- `identity_generate`, `identity_show` — Agent identity
|
||||||
- `midstream_benchmark`, `midstream_search`, `midstream_health` — Latency benchmarks + health
|
|
||||||
|
See `npx ruvector mcp tools` for the full, authoritative tool list.
|
||||||
|
|
||||||
**MCP tool-access policy (default-deny, ADR-256):** restrict the exposed/callable
|
**MCP tool-access policy (default-deny, ADR-256):** restrict the exposed/callable
|
||||||
tool surface with environment variables — useful for least-privilege deployments.
|
tool surface with environment variables — useful for least-privilege deployments.
|
||||||
|
|
|
||||||
|
|
@ -8200,7 +8200,7 @@ mcpCmd.command('info')
|
||||||
|
|
||||||
mcpCmd.command('tools')
|
mcpCmd.command('tools')
|
||||||
.description('List all MCP tools with descriptions (JSON output)')
|
.description('List all MCP tools with descriptions (JSON output)')
|
||||||
.option('--group <group>', 'Filter by group (hooks, workers, rvf, rvlite, brain, edge, identity)')
|
.option('--group <group>', 'Filter by group (hooks, workers, rvf, rvlite, brain, edge, identity, decompile)')
|
||||||
.option('--json', 'JSON output')
|
.option('--json', 'JSON output')
|
||||||
.action((opts) => {
|
.action((opts) => {
|
||||||
const tools = {
|
const tools = {
|
||||||
|
|
@ -8323,6 +8323,14 @@ mcpCmd.command('tools')
|
||||||
{ name: 'identity_generate', desc: 'Generate new pi key' },
|
{ name: 'identity_generate', desc: 'Generate new pi key' },
|
||||||
{ name: 'identity_show', desc: 'Show current identity' },
|
{ name: 'identity_show', desc: 'Show current identity' },
|
||||||
],
|
],
|
||||||
|
'decompile': [
|
||||||
|
{ name: 'decompile_package', desc: 'Decompile an npm package + witness' },
|
||||||
|
{ name: 'decompile_file', desc: 'Decompile a single file' },
|
||||||
|
{ name: 'decompile_url', desc: 'Decompile from a URL' },
|
||||||
|
{ name: 'decompile_diff', desc: 'Diff two decompiled artifacts' },
|
||||||
|
{ name: 'decompile_search', desc: 'Search decompiled artifacts' },
|
||||||
|
{ name: 'decompile_witness', desc: 'Verify decompile witness' },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Filter by group if specified
|
// Filter by group if specified
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ class Intelligence {
|
||||||
const server = new Server(
|
const server = new Server(
|
||||||
{
|
{
|
||||||
name: 'ruvector',
|
name: 'ruvector',
|
||||||
version: '0.2.30',
|
version: require('../package.json').version,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
capabilities: {
|
capabilities: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ruvector",
|
"name": "ruvector",
|
||||||
"version": "0.2.32",
|
"version": "0.2.33",
|
||||||
"description": "Self-learning vector database for Node.js \u2014 hybrid search, Graph RAG, FlashAttention-3, HNSW, 50+ attention mechanisms",
|
"description": "Self-learning vector database for Node.js \u2014 hybrid search, Graph RAG, FlashAttention-3, HNSW, 50+ attention mechanisms",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
@ -93,6 +93,7 @@
|
||||||
"bin/",
|
"bin/",
|
||||||
"dist/",
|
"dist/",
|
||||||
"src/decompiler/",
|
"src/decompiler/",
|
||||||
|
"src/optimizer/",
|
||||||
"wasm/",
|
"wasm/",
|
||||||
"README.md",
|
"README.md",
|
||||||
"LICENSE"
|
"LICENSE"
|
||||||
|
|
|
||||||
177
npm/packages/ruvector/src/optimizer/index.js
Normal file
177
npm/packages/ruvector/src/optimizer/index.js
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
/**
|
||||||
|
* RVAgent Optimizer — Claude Code configuration profiles (ADR-139).
|
||||||
|
*
|
||||||
|
* Maps a task type (coding, research, quickfix, …) to an optimal set of
|
||||||
|
* `CLAUDE_CODE_*` environment variables and a permission mode. Profiles are
|
||||||
|
* derived from the decompiled Claude Code intelligence (see ADR-139) and are
|
||||||
|
* consumed by `npx ruvector optimize` and the settings generator.
|
||||||
|
*
|
||||||
|
* Public API:
|
||||||
|
* - PERMISSION_MODES — valid permission-mode strings
|
||||||
|
* - listProfiles() — array of profile names
|
||||||
|
* - getProfile(name) — { description, permissionMode, env } | null
|
||||||
|
* - applyProfile(name) — sets process.env, returns { applied, permissionMode } | null
|
||||||
|
* - detectTaskType(prompt) — infer a profile name from a free-text prompt
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** Permission modes understood by Claude Code's harness. */
|
||||||
|
const PERMISSION_MODES = [
|
||||||
|
'default',
|
||||||
|
'acceptEdits',
|
||||||
|
'bypassPermissions',
|
||||||
|
'plan',
|
||||||
|
'dontAsk',
|
||||||
|
'auto',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task profiles. Every env key MUST start with `CLAUDE_CODE_` and every
|
||||||
|
* `permissionMode` MUST be a member of {@link PERMISSION_MODES}.
|
||||||
|
*/
|
||||||
|
const PROFILES = {
|
||||||
|
coding: {
|
||||||
|
description: 'Implementation work — edits with checkpointing and thinking enabled',
|
||||||
|
permissionMode: 'acceptEdits',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'high',
|
||||||
|
CLAUDE_CODE_THINKING: '1',
|
||||||
|
CLAUDE_CODE_AUTO_COMPACT: '1',
|
||||||
|
CLAUDE_CODE_FILE_CHECKPOINTING: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
research: {
|
||||||
|
description: 'Investigation and analysis — read-heavy, no edits, deep reasoning',
|
||||||
|
permissionMode: 'default',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'high',
|
||||||
|
CLAUDE_CODE_THINKING: '1',
|
||||||
|
CLAUDE_CODE_AUTO_COMPACT: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
quickfix: {
|
||||||
|
description: 'Small, fast fixes — brief output, low effort, quick turnaround',
|
||||||
|
permissionMode: 'acceptEdits',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_BRIEF: '1',
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'low',
|
||||||
|
CLAUDE_CODE_THINKING: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
planning: {
|
||||||
|
description: 'Architecture and design — plan mode, no edits until approved',
|
||||||
|
permissionMode: 'plan',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'high',
|
||||||
|
CLAUDE_CODE_THINKING: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
description: 'Long-running background/daemon work — autonomous, minimal prompts',
|
||||||
|
permissionMode: 'bypassPermissions',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'medium',
|
||||||
|
CLAUDE_CODE_AUTO_COMPACT: '1',
|
||||||
|
CLAUDE_CODE_PROMPT_SUGGESTION: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
swarm: {
|
||||||
|
description: 'Multi-agent swarm coordination — autonomous, hooks-driven',
|
||||||
|
permissionMode: 'bypassPermissions',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'medium',
|
||||||
|
CLAUDE_CODE_AUTO_COMPACT: '1',
|
||||||
|
CLAUDE_CODE_THINKING: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
review: {
|
||||||
|
description: 'Code review — read-only, no edits, thorough reasoning',
|
||||||
|
permissionMode: 'default',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'high',
|
||||||
|
CLAUDE_CODE_THINKING: '1',
|
||||||
|
CLAUDE_CODE_BRIEF: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ci: {
|
||||||
|
description: 'CI / automation pipelines — fast, non-interactive, no suggestions',
|
||||||
|
permissionMode: 'dontAsk',
|
||||||
|
env: {
|
||||||
|
CLAUDE_CODE_FAST_MODE: '1',
|
||||||
|
CLAUDE_CODE_EFFORT_LEVEL: 'low',
|
||||||
|
CLAUDE_CODE_PROMPT_SUGGESTION: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keyword → profile rules, evaluated in order. The first rule whose regex
|
||||||
|
* matches the prompt wins, so more specific task types are listed first.
|
||||||
|
*/
|
||||||
|
const DETECTION_RULES = [
|
||||||
|
{ type: 'quickfix', re: /\b(typo|quick\s?-?fix|one-?liner|small fix|rename)\b/i },
|
||||||
|
{ type: 'ci', re: /\b(ci|cd|pipeline|github actions|workflow|deploy)\b/i },
|
||||||
|
{ type: 'swarm', re: /\b(swarm|multi-?agent|coordinate|orchestrat\w*|hive)\b/i },
|
||||||
|
{ type: 'background', re: /\b(background|daemon|monitor\w*|watch\b|long-?running)\b/i },
|
||||||
|
{ type: 'review', re: /\b(review|pull request|\bpr\b|audit|critique)\b/i },
|
||||||
|
{ type: 'planning', re: /\b(plan\w*|architect\w*|design|roadmap|strategy)\b/i },
|
||||||
|
{ type: 'research', re: /\b(research|investigat\w*|explore|compare|survey)\b/i },
|
||||||
|
{ type: 'coding', re: /\b(implement|code|build|add|write|refactor|create|fix|function|feature)\b/i },
|
||||||
|
];
|
||||||
|
|
||||||
|
/** List all available profile names. */
|
||||||
|
function listProfiles() {
|
||||||
|
return Object.keys(PROFILES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return a profile by name, or `null` if it does not exist. */
|
||||||
|
function getProfile(name) {
|
||||||
|
if (!name || !Object.prototype.hasOwnProperty.call(PROFILES, name)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return PROFILES[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a profile's env vars to `process.env`. Returns `{ applied, permissionMode }`
|
||||||
|
* where `applied` is the map of env vars that were set, or `null` if the profile
|
||||||
|
* is unknown.
|
||||||
|
*/
|
||||||
|
function applyProfile(name) {
|
||||||
|
const profile = getProfile(name);
|
||||||
|
if (!profile) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const applied = {};
|
||||||
|
for (const [key, val] of Object.entries(profile.env)) {
|
||||||
|
process.env[key] = val;
|
||||||
|
applied[key] = val;
|
||||||
|
}
|
||||||
|
return { applied, permissionMode: profile.permissionMode };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infer the most likely task type from a free-text prompt. Defaults to
|
||||||
|
* `'coding'` for empty/unrecognised input.
|
||||||
|
*/
|
||||||
|
function detectTaskType(prompt) {
|
||||||
|
if (!prompt || typeof prompt !== 'string') {
|
||||||
|
return 'coding';
|
||||||
|
}
|
||||||
|
for (const rule of DETECTION_RULES) {
|
||||||
|
if (rule.re.test(prompt)) {
|
||||||
|
return rule.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'coding';
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
PERMISSION_MODES,
|
||||||
|
PROFILES,
|
||||||
|
listProfiles,
|
||||||
|
getProfile,
|
||||||
|
applyProfile,
|
||||||
|
detectTaskType,
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue