Three optimizations to the ruflo-side AgentBBS federation integration
(ADR-164), all in v3/@claude-flow/cli/src/mcp-tools/agentbbs-tools.ts.
1. PeerHello dedup (register). `federation_bbs_register` appended a fresh
PeerHello envelope on EVERY call even though the registry entry and nodeId
were already idempotent — so a node retrying register N times emitted N
near-identical hellos (observed live: one node published 8). Now a hello is
emitted only for a genuinely new registration, or as a heartbeat refresh once
FEDERATION_BBS_HELLO_WINDOW_SECS (default 60) has elapsed. Returns
`helloEmitted` so the caller can see whether one was written (a silent
suppression would otherwise be unverifiable).
2. Watch dedup. `federation_bbs_watch` now collapses duplicate envelopeIds
before applying the limit, so a relay replay or a double-append cannot
surface the same envelope twice to a watcher. Order preserved.
3. O(1) seq append. `nextSeq` re-parsed the whole room log on every
publish/register (O(n) as the log grows). It now scans only the last 64 KiB
to find the last seq, with a full-read fallback for the rare huge-line case.
Monotonic seq (ADR-164 §3.2.2) is preserved and tested past the tail window.
Decision helpers (`shouldEmitHello`, `dedupEnvelopes`, `nextSeq`,
`lastPeerHelloMs`) are exported and unit-tested deterministically — the tool
handlers early-return `{degraded:true}` when the optional `agentbbs` package is
absent, so the pure logic is tested directly rather than through the wrapper.
Tests: 7 new cases; full file 15 passed / 4 skipped (the 4 are agentbbs-present
happy-path, skipped when the optional dep is absent). tsc --noEmit clean on the
changed file. Structural + degraded contract unchanged.
Scope: this is the ruflo-side integration only. Claim leases, signed result
receipts, and node reputation are agentbbs/relay-authority concerns (external
pkg + x.ruv.io gateway) — a separate track.
Co-Authored-By: RuFlo <ruv@ruv.net>
CLI Module Tests
This directory contains comprehensive tests for the V3 CLI module using Vitest.
Test Files
1. cli.test.ts (~15+ tests)
Tests for the main CLI class covering:
- Version command (
--version,-V) - Help output (
--help,-h) - Command parsing (long flags, short flags, equals syntax)
- Positional arguments
- Boolean flags and negation
- Global flags (
--quiet,--format,--config,--no-color) - Error handling (unknown commands, missing options)
- Subcommand execution and aliases
- Exit codes
2. mcp-client.test.ts (~10+ tests)
Tests for MCP tool invocation:
callMCPTool()- Tool execution with various inputsgetToolMetadata()- Metadata retrievallistMCPTools()- Tool listing and filtering by categoryhasTool()- Tool existence checksgetToolCategories()- Category enumerationvalidateToolInput()- Input validation against schemasMCPClientError- Custom error handling
3. commands.test.ts (~48+ tests)
Tests for all CLI commands:
Agent Commands (spawn, list, status, stop, metrics):
- Spawning agents with various configurations
- Listing agents with filters
- Getting agent status and metrics
- Stopping agents (graceful/force)
- Agent performance metrics
Swarm Commands (init, start, status, stop, scale, coordinate):
- Initializing swarms with different topologies
- Starting swarm execution with objectives
- Checking swarm status
- Stopping and scaling swarms
- V3 15-agent coordination structure
Memory Commands (store, retrieve, search, list, delete, stats, configure):
- Storing data in memory (with/without vectors)
- Retrieving data by key
- Semantic/vector search
- Listing memory entries
- Deleting entries
- Viewing statistics
- Backend configuration
Config Commands (init, get, set, providers, reset, export, import):
- Initializing configuration
- Getting/setting config values
- Managing AI providers
- Resetting to defaults
- Exporting/importing configuration
Mocking Strategy
MCP Tools
All MCP tools are mocked at the module level to prevent actual tool execution:
agent-tools.js- Mocked agent operationsswarm-tools.js- Mocked swarm coordinationmemory-tools.js- Mocked memory operationsconfig-tools.js- Mocked configuration
Output
The output module is fully mocked to capture formatted output without console pollution.
Prompts
Interactive prompts (select, confirm, input, multiSelect) are mocked to return default values for non-interactive testing.
Process
process.exit() is mocked to throw errors instead of terminating the test process.
Running Tests
# Run all CLI tests
npm test -- v3/@claude-flow/cli/__tests__/
# Run specific test file
npm test -- v3/@claude-flow/cli/__tests__/cli.test.ts
# Run with coverage
npm test -- v3/@claude-flow/cli/__tests__/ --coverage
# Run in watch mode
npm test -- v3/@claude-flow/cli/__tests__/ --watch
Test Coverage Goals
- Statements: >80%
- Branches: >75%
- Functions: >80%
- Lines: >80%
Key Testing Patterns
1. Command Execution
const result = await command.action!(ctx);
expect(result.success).toBe(true);
expect(result.data).toHaveProperty('expectedField');
2. Flag Parsing
ctx.flags = { myFlag: 'value', _: [] };
await command.action!(ctx);
// Assertions in action callback
3. Error Handling
try {
await cli.run(['invalid-command']);
} catch (e) {
expect((e as Error).message).toContain('process.exit');
}
4. Output Validation
const output = consoleOutput.join('');
expect(output).toContain('Expected text');
Notes
- All tests are non-interactive (
interactive: false) - Console output is captured for verification
- Process exits are converted to exceptions
- MCP client is fully isolated from actual MCP server
- Tests use unique command names to avoid conflicts