Skip to content

fix: add missing items for MCP array schemas#1296

Closed
that-lucas wants to merge 5944 commits intoruvnet:mainfrom
that-lucas:fix/mcp-array-items-schema-1294
Closed

fix: add missing items for MCP array schemas#1296
that-lucas wants to merge 5944 commits intoruvnet:mainfrom
that-lucas:fix/mcp-array-items-schema-1294

Conversation

@that-lucas
Copy link

Summary

  • Fix MCP tool schemas that defined type: 'array' without items, which breaks strict JSON Schema validation.
  • This was reproduced in OpenCode: start a session with opus, then switch to codex; tool schema validation fails with array schema missing items.
  • Add a regression test to scan src/mcp-tools/*.ts and fail if any array schema omits items.

Validation

  • npx vitest run __tests__/mcp-schema-array-items.test.ts

Context

ruvnet and others added 30 commits February 8, 2026 21:20
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:27Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:35Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:45Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:58Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:06Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:10Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:15Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:20Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:02Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:33Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:41Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:27:23Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:31:26Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:31:38Z
- Changes: 2 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:31:43Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:31:54Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:38:59Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:39:23Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:40:13Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:40:18Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:41:35Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:41:52Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:42:24Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:44:59Z
- Changes: 5 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:15:04Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:15:24Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:15:49Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:17:41Z
- Changes: 2 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:18:53Z
- Changes: 3 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T22:22:54Z
- Changes: 6 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ruvnet and others added 25 commits February 17, 2026 21:30
Co-Authored-By: claude-flow <ruv@ruv.net>
…#1163)

ruflo.js now imports CLI class directly and passes ruflo branding
(name, description) instead of re-importing cli.js with defaults.
Also fixed two hardcoded 'claude-flow' strings in index.ts help text
to use this.name for proper branding in both packages.

Fixes ruvnet#1162
Co-Authored-By: claude-flow <ruv@ruv.net>
On Windows, import() requires file:// URLs, not bare C:\ paths.
Added pathToFileURL() wrapper for all dynamic imports in ruflo.js.

Fixes ruvnet#1164
…uvnet#1233)

* feat(ADR-053): AgentDB v3 controller activation + statusline fixes

Implement ADR-053 phases 1-6 for AgentDB v3 controller activation:
- ControllerRegistry with 12 active controllers (CRUD, search, graph, scope, lifecycle, stats, export, import, consolidation, learning, health, migration)
- Memory bridge connecting CLI -> ControllerRegistry -> HybridBackend -> AgentDB
- 9 agentdb_* MCP tools for direct AgentDB access
- Fix statusline to read Claude Code stdin JSON protocol (model, context%, cost)
- Fix settings-generator to emit only valid statusLine fields (type, command, padding)
- Fix upgrade path (init --update --settings) to clean invalid statusLine config
- Update README statusline documentation
- Skip 39 pre-existing test failures requiring live MCP context
- Bump to 3.1.0-alpha.52

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): sync lock files with updated package.json dependencies

Regenerate package-lock.json and pnpm-lock.yaml to match current
package.json specs (agentdb, agentic-flow, @ruvector/gnn,
@ruvector/tiny-dancer, @claude-flow/plugin-gastown-bridge).

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): skip optional deps (sharp) in V3 CI to prevent timeout failures

Add --no-optional to all pnpm install steps. sharp and @xenova/transformers
are optional deps in agentdb that often timeout during CI binary downloads.
They are not needed for testing, type checking, or building.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): skip sharp postinstall via pnpm.neverBuiltDependencies

sharp is an optional dep of agentdb that often times out downloading
native binaries in CI. Adding it to neverBuiltDependencies prevents
its postinstall from running while still keeping all other optional
deps (like @rollup/*) functional.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): cast agentdb dynamic import to any for TS compatibility

The agentdb@3.0.0-alpha.7 type declarations use export default which
causes TS to reject .default property access on the typeof import.
Cast to any since these are runtime-checked fallback chains.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): add agentdb as optional dep to @claude-flow/neural

The reasoning-bank.ts uses dynamic import('agentdb') but agentdb
was not listed as a dependency, causing TS2307 in strict pnpm CI.
Added as optionalDependency and cast import to any.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): cast pg dynamic import to any in ruvector-bridge

pg is a user-installed runtime dependency, not bundled. Cast the
dynamic import to any to prevent TS2307 in strict pnpm CI builds.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): resolve all V3 build TS errors for @ruvector/attention and pg

- Cast @ruvector/attention dynamic imports to any (API changed from
  PascalCase classes to camelCase functions across versions)
- Replace broken type imports with local any aliases
- Remove stale @ts-expect-error directive
- Fix null return in benchmarkTraining
- Cast pg dynamic import to any in ruvector-bridge (user-installed dep)

Resolves 21 pre-existing TS errors that blocked Build V3 on main.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): add pg type declaration for plugins build

TS2307 cannot be fixed with : any cast — the module must be
resolvable. Add a minimal ambient declaration since pg is a
user-installed optional dependency, not bundled.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ci): add ambient declarations for all optional runtime modules

Add type declarations for pg, sql.js, agentic-flow, ruvector,
@ruvector/core, and @xenova/transformers. These are dynamically
imported at runtime but not bundled — users install as needed.
Prevents TS2307 in strict pnpm CI where hoisted modules are absent.

All 25 V3 packages now build with 0 TS errors.

Co-Authored-By: claude-flow <ruv@ruv.net>
…tools

Upgrade agentdb dependency to 3.0.0-alpha.9 (zero deprecation warnings,
pure JS SQLite, updated ruvector). Wire 8 new controllers into
ControllerRegistry (HierarchicalMemory, MemoryConsolidation,
BatchOperations, ContextSynthesizer, GNNService, RVFOptimizer,
MMRDiversityRanker, GuardedVectorBackend) with level-based init.
Add 6 new MCP tools (hierarchical-store/recall, consolidate, batch,
context-synthesize, semantic-route) and bridge functions. Update README
with AgentDB v3 Controllers documentation section.

Co-Authored-By: claude-flow <ruv@ruv.net>
…t#216)

Add pnpm overrides to force @ruvector/gnn@0.1.25 across all v3 packages.
The 0.1.25 release replaces panic!() with Result-based error handling,
converting the fatal process abort into a catchable JS exception. GNNService
now gracefully falls back to JS heuristics when hiddenDim % heads != 0.

Co-Authored-By: claude-flow <ruv@ruv.net>
…w integration

Rebranding from Claude Flow to Ruflo. Includes:
- agentic-flow v3.0.0-alpha.1 deep integration (10 subpath exports)
- AgentDB v3.0.0-alpha.9 with 8 controllers + 6 MCP tools
- Unified agentic-flow bridge with tiered embedding resolution
- Security hardening (command injection fix, TOCTOU race fix)
- Doctor health check for agentic-flow
- 22 agent/skill files updated to v3.0.0-alpha.1
- ADR-054, ADR-055, ADR-056
- Comprehensive CHANGELOG from 5,800+ commits
- All 3 packages bumped to 3.5.0

Co-Authored-By: claude-flow <ruv@ruv.net>
Co-Authored-By: claude-flow <ruv@ruv.net>
Ruflo v3.5.0 — First Major Stable Release
Co-Authored-By: claude-flow <ruv@ruv.net>
…ls (v3.5.1)

aidefence, guidance, and agentic-flow all transitively require
agentdb → hnswlib-node (native C++ compilation). On minimal
containers without Python/gcc, npm install fails entirely.

Moving these to optionalDependencies lets npm skip them gracefully.
The CLI already handles their absence with import().catch() fallbacks.

Co-Authored-By: claude-flow <ruv@ruv.net>
Lockfile updates reflecting optionalDependencies move for slim container support.

Co-Authored-By: claude-flow <ruv@ruv.net>
chore: sync v3.5.1 lockfiles and finalize release
* docs: add ADR-057 — RVF native storage backend to replace sql.js

Proposes replacing the 18MB sql.js WASM SQLite dependency with
RuVector Format (RVF) across @claude-flow/shared, memory, and
embeddings packages. Includes automatic and manual migration paths
for existing .db and .json files with full backward compatibility.

Key benefits: -18MB install size, 150x-12,500x faster vector search
via native HNSW, quantization support, crash-safe append-only format.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs: extend ADR-057 with RVF embedding provider, ruvLLM persistence, and progressive download

Add three major sections to ADR-057:

- Section 3A: RVF as 5th EmbeddingProvider (52KB WASM replaces 540MB
  agentic-flow for basic use cases). Updated auto-select hierarchy:
  rvf > agentic-flow > transformers > mock.

- Section 3B: ruvLLM learning persistence via RVF segments. SONA
  patterns (ReasoningBank), LoRA adapters, and EWC++ weights now
  survive process restarts. RuVectorProvider.searchMemory works
  offline via RVF without HTTP server.

- Section 10: Progressive download architecture. Replaces npm
  optionalDependencies (all-or-nothing 1.3GB) with on-demand
  capability downloads stored as .rvf files. 5 phases from 22MB
  core CLI to full LLM/CNN/GNN/kernel capabilities.

Implementation plan expanded from 5 to 8 phases. Testing strategy
updated with 11 new test cases covering the additions.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat: add optimized Docker images for Ruflo lite/full/workers

- Dockerfile: Multi-stage Alpine build with aggressive dependency pruning.
  Result: 324MB image, 0.6s startup (vs 1.3GB/35s baseline).
  Uses --omit=optional + explicit rm -rf of heavy transitive deps.

- Dockerfile.full: Full image variant with all optional dependencies
  including native compilation (onnxruntime-node, better-sqlite3).

- Dockerfile.headless: Updated from node:20 to node:22, claude-flow
  branding to ruflo, same prune strategy as lite.

- docker-compose.yml: Three profiles (lite, full, workers) with
  appropriate resource limits and health checks.

- .dockerignore: Excludes node_modules, tests, source maps, IDE
  configs, and secrets from build context.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(ADR-057): implement RVF native storage backend across all packages

Replace sql.js (18MB WASM) with zero-dependency RVF format across
memory, events, embeddings, and learning subsystems. Pure TypeScript
fallback with optional native @ruvector/rvf acceleration.

New files:
- memory/rvf-backend.ts: IMemoryBackend impl with HNSW + binary persistence
- memory/hnsw-lite.ts: Lightweight HNSW graph for vector search
- memory/rvf-learning-store.ts: SONA pattern/LoRA/EWC/trajectory persistence
- memory/persistent-sona.ts: PersistentSonaCoordinator wrapping learning store
- shared/events/rvf-event-log.ts: Append-only event log (replaces EventStore)
- embeddings/rvf-embedding-cache.ts: Binary file embedding cache (FNV-1a keys)
- embeddings/rvf-embedding-service.ts: Hash-based embedding provider (<0.1ms)

Integrations:
- DatabaseProvider: 'rvf' added, auto-selected first (always available)
- EmbeddingProvider: 'rvf' added, auto-selected first in async factory
- All packages export new RVF types and classes

Tests: 163 passing (5 suites), validated in Docker (node:22-alpine)
- rvf-backend: 50 tests (CRUD, query, search, persistence, HNSW)
- rvf-event-log: 33 tests (append, replay, snapshots, crash recovery)
- rvf-embeddings: 30 tests (cache, service, determinism, normalization)
- rvf-learning-store: 31 tests (patterns, LoRA, EWC, trajectories)
- rvf-integration: 19 tests (provider selection, migration, concurrency)

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(ADR-057): harden RVF storage with security, performance, and migration

Security: atomic writes (tmp+rename) across all backends, path validation,
input validation at boundaries. Performance: persist lock prevents concurrent
flushes, stack overflow fix for large datasets, timer.unref() prevents hangs,
O(1) eviction lookup in embedding cache. New: bidirectional RVF migration
utility (JSON/SQLite/RVF), format v2 with backward compat, auto-persist
patterns and trajectories before eviction. Added HnswLite and RvfMigrator
exports. 193 tests passing, 0 TS errors.

Refs ruvnet#1242

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix: doctor version detection and init settings warnings (ruvnet#1235, ruvnet#1230)

doctor: Replace unreliable path-walking heuristic with import.meta.url
traversal to find the correct package.json. Removes stale npx cache
scanning that could report wrong versions. Fixes ruvnet#1235.

init: Remove invalid TeammateIdle and TaskCompleted keys from generated
.claude/settings.json hooks section. These are not recognized by Claude
Code and caused warnings. Config remains available under the claudeFlow
namespace. Fixes ruvnet#1230.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(doctor): remove Windows-incompatible shell redirects, simplify root detection

- Remove fragile Windows root calculation (split on backslash); use
  dirname(dir) === dir instead which works on all platforms
- Remove 2>/dev/null from npm view command (fails on Windows cmd.exe);
  the catch block handles errors gracefully already

Co-Authored-By: claude-flow <ruv@ruv.net>

* security: harden RVF against crafted files and race conditions

- rvf-backend: validate dimensions (1-10000), validate RVF header
  structure and size before JSON.parse, guard persist interval
  against concurrent flushes
- rvf-embedding-cache: use random suffix for tmp files to prevent
  predictable-path attacks on multi-user systems
- rvf-event-log: add 100MB max payload size limit to prevent DoS
  from crafted event log files
- rvf-migration: add null byte and type validation on all paths

Co-Authored-By: claude-flow <ruv@ruv.net>
Published: @claude-flow/cli@3.5.2, claude-flow@3.5.2, ruflo@3.5.2
- ADR-057: RVF native storage backend with bidirectional migration
- Security: atomic writes, header validation, payload limits, path validation
- Fix ruvnet#1235: doctor version detection via import.meta.url
- Fix ruvnet#1230: remove invalid TeammateIdle/TaskCompleted from settings.json

Co-Authored-By: claude-flow <ruv@ruv.net>
Documents the RVF binary format, HnswLite vector search, RvfMigrator,
DatabaseProvider auto-selection, crash safety, SONA persistence, and
security hardening. Updates Architecture module table.

Co-Authored-By: claude-flow <ruv@ruv.net>
Replace all claude-flow references in install.sh with ruflo branding
and change ruflo@alpha to ruflo@latest throughout README.md to match
current package naming and recommended install path.

Co-Authored-By: claude-flow <ruv@ruv.net>
…ication suite

ADR-058 defines the RVFA (RuVector Format Appliance) — a single .rvf
file containing Linux kernel, Node.js, Claude Code, Ruflo, ruvLLM
(from RuVector), and a 35-category verification suite (127 checks).

Three profiles: offline (4GB, air-gapped), hybrid (2GB), cloud (60MB).
ruvLLM extends @ruvector/core with on-device GGUF inference.

scripts/verify-appliance.sh runs all 35 categories (113 critical
checks, 10 non-critical warnings, 4 skipped) — verified in Docker.

Co-Authored-By: claude-flow <ruv@ruv.net>
Full implementation of self-contained Ruflo RVF Appliance (ADR-058):

Core modules (v3/@claude-flow/cli/src/appliance/):
- rvfa-format.ts: Binary format reader/writer with RVFA magic bytes,
  section management, SHA256 integrity, gzip compression (500 lines)
- rvfa-builder.ts: Multi-stage build pipeline for cloud/hybrid/offline
  profiles with AES-256-GCM API key vault encryption (394 lines)
- rvfa-runner.ts: Boot sequence with native and container isolation,
  verify section extraction, vault decryption (282 lines)
- ruvllm-bridge.ts: Local LLM inference bridge from @ruvector ecosystem
  with 3-tier routing (Agent Booster → local GGUF → cloud API) (307 lines)

CLI command (commands/appliance.ts):
- `ruflo appliance build` — build .rvf with profile selection
- `ruflo appliance inspect` — show header + section manifest
- `ruflo appliance verify` — integrity + capability checks
- `ruflo appliance extract` — unpack sections to directory
- `ruflo appliance run` — boot in cli/mcp/verify mode

Tests: 59/59 passing (44 format + 15 builder)
Docker: Dockerfile.appliance for production Alpine image

Co-Authored-By: claude-flow <ruv@ruv.net>
…ution, hot-patch

Phase 3: ruvLLM GGUF inference engine
- gguf-engine.ts: Binary GGUF header parser (v2/v3), model metadata extraction,
  optional node-llama-cpp integration for local inference, RVKV KV-cache
  persistence format, async token streaming
- ruvllm-bridge.ts: Integrated GGUF engine as preferred Tier 2 backend,
  automatic model metadata enrichment on load

Phase 4: Ed25519 code signing + IPFS distribution + hot-patch updates
- rvfa-signing.ts: Ed25519 key generation/storage (PEM), two-pass appliance
  signing (canonical JSON for deterministic digests), signature verification,
  detached patch/section signing
- rvfa-distribution.ts: RVFP binary patch format (magic "RVFP", section-level
  replacement), Pinata IPFS publishing (multipart upload, no external deps),
  11-step atomic patch application with backup + rollback
- appliance-advanced.ts: CLI subcommands (sign, publish, update) extracted
  to keep files under 500 lines

Tests: 75 new tests (26 GGUF + 21 signing + 28 distribution), 134 total passing

Co-Authored-By: claude-flow <ruv@ruv.net>
- Pass --signer flag through to signAppliance() in CLI command
- Auto-detect PEM vs DER key format for cross-module signing interop
- mkdir key directory before saving key pair (prevents ENOENT)
- Add redirect depth limit (max 5) and 30s timeout on HTTP requests
- Use canonical JSON for deterministic patch signature verification
- Make RVKV footer hash mandatory (reject truncated cache files)
- Use llama.cpp token count when available, else chars/4 heuristic
- Remove unused GgufMetadata type import from ruvllm-bridge

Co-Authored-By: claude-flow <ruv@ruv.net>
feat(ADR-058): Phase 3-4 — GGUF engine, Ed25519 signing, IPFS distribution, hot-patch
Copilot AI review requested due to automatic review settings March 5, 2026 14:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes MCP JSON Schemas that define type: 'array' without items (which fails strict validation), and adds a regression test to prevent reintroducing the issue.

Changes:

  • Added missing items definitions to several MCP tool input schemas that use type: 'array'.
  • Added a Vitest regression test that scans MCP tool source files for array schemas missing items.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
v3/@claude-flow/cli/src/mcp-tools/system-tools.ts Adds items to array-typed schema properties in system tools.
v3/@claude-flow/cli/src/mcp-tools/performance-tools.ts Adds items to components array schema.
v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts Adds items to trajectoryIds array schema.
v3/@claude-flow/cli/src/mcp-tools/github-tools.ts Adds items to labels / assignees array schemas.
v3/@claude-flow/cli/src/mcp-tools/daa-tools.ts Adds items to multiple array schemas and defines steps.items with anyOf.
v3/@claude-flow/cli/src/mcp-tools/coordination-tools.ts Adds items to agents array schema.
v3/@claude-flow/cli/tests/mcp-schema-array-items.test.ts Adds regression test to detect array schemas missing items.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +47 to +48
const mcpToolsDir = join(process.cwd(), 'src', 'mcp-tools');
const files = readdirSync(mcpToolsDir).filter(file => file.endsWith('.ts'));
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process.cwd() is not guaranteed to be v3/@claude-flow/cli when running Vitest in a monorepo/workspace, so this can fail with ENOENT depending on how tests are invoked. Prefer resolving the path relative to the test file (e.g., via import.meta.url + fileURLToPath and dirname) or via a known package root to make the test location-independent.

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +42

function findArraySchemasMissingItems(source: string): number[] {
const matches: number[] = [];
const pattern = /type:\s*['\"]array['\"]/g;
let match: RegExpExecArray | null;

while ((match = pattern.exec(source)) !== null) {
const typeIndex = match.index;

const objectStart = source.lastIndexOf('{', typeIndex);
if (objectStart === -1) {
continue;
}

let depth = 0;
let objectEnd = -1;
for (let i = objectStart; i < source.length; i += 1) {
const char = source[i];
if (char === '{') {
depth += 1;
} else if (char === '}') {
depth -= 1;
if (depth === 0) {
objectEnd = i;
break;
}
}
}

if (objectEnd !== -1) {
const objectText = source.slice(objectStart, objectEnd + 1);
if (!/\bitems\s*:/.test(objectText)) {
const line = source.slice(0, typeIndex).split('\n').length;
matches.push(line);
}
}
}

return matches;
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The brace-matching approach can be thrown off by { / } that appear inside strings, template literals, or comments in the source (likely in large files like hooks-tools.ts), leading to false positives/negatives. Consider switching this check to a TypeScript AST-based approach (e.g., typescript parser) that specifically finds object literals where type is 'array' and verifies a sibling items property; this will be more robust and easier to evolve.

Suggested change
function findArraySchemasMissingItems(source: string): number[] {
const matches: number[] = [];
const pattern = /type:\s*['\"]array['\"]/g;
let match: RegExpExecArray | null;
while ((match = pattern.exec(source)) !== null) {
const typeIndex = match.index;
const objectStart = source.lastIndexOf('{', typeIndex);
if (objectStart === -1) {
continue;
}
let depth = 0;
let objectEnd = -1;
for (let i = objectStart; i < source.length; i += 1) {
const char = source[i];
if (char === '{') {
depth += 1;
} else if (char === '}') {
depth -= 1;
if (depth === 0) {
objectEnd = i;
break;
}
}
}
if (objectEnd !== -1) {
const objectText = source.slice(objectStart, objectEnd + 1);
if (!/\bitems\s*:/.test(objectText)) {
const line = source.slice(0, typeIndex).split('\n').length;
matches.push(line);
}
}
}
return matches;
import * as ts from 'typescript';
function findArraySchemasMissingItems(source: string): number[] {
const sourceFile = ts.createSourceFile(
'file.ts',
source,
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TS
);
const lines: number[] = [];
function checkObjectLiteral(node: ts.ObjectLiteralExpression) {
let hasArrayType = false;
let hasItems = false;
let typePropNode: ts.PropertyAssignment | undefined;
for (const prop of node.properties) {
if (!ts.isPropertyAssignment(prop)) continue;
const name = prop.name;
const propName =
ts.isIdentifier(name) || ts.isStringLiteralLike(name)
? name.text
: undefined;
if (!propName) continue;
if (propName === 'type') {
if (
ts.isStringLiteralLike(prop.initializer) &&
prop.initializer.text === 'array'
) {
hasArrayType = true;
typePropNode = prop;
}
} else if (propName === 'items') {
hasItems = true;
}
}
if (hasArrayType && !hasItems && typePropNode) {
const { line } = sourceFile.getLineAndCharacterOfPosition(
typePropNode.getStart(sourceFile)
);
lines.push(line + 1);
}
}
function visit(node: ts.Node) {
if (ts.isObjectLiteralExpression(node)) {
checkObjectLiteral(node as ts.ObjectLiteralExpression);
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
return lines;

Copilot uses AI. Check for mistakes.
if (objectEnd !== -1) {
const objectText = source.slice(objectStart, objectEnd + 1);
if (!/\bitems\s*:/.test(objectText)) {
const line = source.slice(0, typeIndex).split('\n').length;
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Computing the line number by re-splitting the entire prefix on every match is O(n²) in the number of matches and file size (notable for large tool files). If this starts to slow the test suite, consider precomputing newline offsets once per file or counting newlines incrementally as the regex advances.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: MCP schema invalid for strict clients (array missing items)

3 participants