Files
ruflo/v3/@claude-flow/cli/__tests__
rUvandClaude 82595ec557 dream(security): #3151 sliding-window reset for maxToolCallsPerTurn (evaluated, ACCEPT) (#3152)
* dream(security): #3151 sliding-window reset for maxToolCallsPerTurn (evaluated, ACCEPT)

Follow-up to PR #3139 (2026-08-31, unmerged): the opt-in MCP policy
enforcer's maxToolCallsPerTurn was a permanent session-lifetime cumulative
counter that never reset, explicitly disclosed as unsafe to enable by
default. Tonight's research (5 parallel roles) converged on a wall-clock
sliding window as the correct fix, corroborated by the MCP spec's own
silence on rate-limit mechanism, SEP-2567's removal of the session
concept, Cloudflare's production sliding-window-counter data, and how
FastMCP/PolicyLayer solve the same problem in the MCP ecosystem.

- checkAndRecordCall/evaluateToolCall now take an injectable `now`
  (defaults to Date.now(), zero production behavior change at the one
  real call site in mcp-server.ts).
- New McpPolicy.turnWindowMs field (default 60000ms); shipped in
  .harness/mcp-policy.json alongside the existing maxToolCallsPerTurn.
- 30/30 tests passing (24 pre-existing unmodified + 6 new). Broader
  MCP-suite sweep: 52/56 (4 failures are pre-existing unbuilt-sibling-
  package environmental gaps, unrelated to this diff).
- Independent adversarial critique: CONFIRMED-WITH-CAVEATS. Two minor
  findings (untested exact window boundary; audit-log timestamp cosmetic
  desync from the injected clock) fixed before this commit.

Full report: docs/dream-cycle/dream-gist-2026-09-01.md

* dream(security): #3151 update LEDGER.md for 2026-09-01

Ledger row for tonight's dream-cycle: sliding-window reset for
maxToolCallsPerTurn (PR #3152, stacked on #3139).

* dream(security): #3151 address ruvnet's PR #3152 review (round 1)

Retargeted PR #3152's base to main: dream/2026-08-31-security is not
main/develop, so every required CI workflow (ci.yml, integration-tests.yml,
cve-audit.yml, v3-ci.yml, verification-pipeline.yml) is configured to
trigger only on PRs targeting main/develop and structurally never ran on
either #3139 or this stacked PR's head, regardless of what was pushed.
This is a repo-wide trigger-configuration fact, not fixable by a commit.

Also addresses the review's other concrete asks:
- Built the two sibling packages disclosed as unbuilt (@claude-flow/cli-core,
  @claude-flow/neural) via tsc. Broader MCP-suite sweep improves from 52/56
  to 201/204 -- remaining 3 failures confirmed (independently, by testing a
  raw ::1 bind outside any test) to be EAFNOSUPPORT: IPv6 loopback binding
  unsupported at the container/OS level in this sandbox, unrelated to this
  diff and not fixable by any code change here.
- Added an integration test exercising the real stdio dispatcher
  (MCPServerManager.handleMCPMessage) through a full deny -> expiry -> allow
  cycle with fake timers, proving the fix holds without bypassing audit
  logging or the opt-in flag -- the review's specific ask, previously only
  covered at the direct evaluateToolCall() call level.
- Strengthened documentation (McpPolicy.maxToolCallsPerTurn JSDoc and
  .harness/mcp-policy.json's own field comment): explicit that despite the
  field name this is wall-clock rate limiting, not a literal
  per-conversational-turn counter -- MCP has no protocol-level turn concept.

31/31 policy-enforcer tests passing (was 30/30; +1 dispatcher-level test).

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-14 22:20:33 +00:00
..
2026-01-04 20:41:12 +00:00
2026-01-04 20:37:19 +00:00
2026-01-04 20:37:19 +00:00

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 inputs
  • getToolMetadata() - Metadata retrieval
  • listMCPTools() - Tool listing and filtering by category
  • hasTool() - Tool existence checks
  • getToolCategories() - Category enumeration
  • validateToolInput() - Input validation against schemas
  • MCPClientError - 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 operations
  • swarm-tools.js - Mocked swarm coordination
  • memory-tools.js - Mocked memory operations
  • config-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