Implements all 3 phases of ADR-377 (ruvnet/ruflo#2516, tracked in #2873):
AgentDB's retrieval and write paths had zero certified defenses against
memory poisoning — SMSR (arXiv:2606.12703) shows 93-100% undefended attack
success. All three phases are off by default; enabling each is opt-in via
env flag until independently benchmarked, per the ADR's own gate criteria.
Phase 1 — AgentDbRetrievalGuard (@claude-flow/memory)
- New `agentdb-retrieval-guard.ts`, wired into `AgentDBBackend.search()`
(covers `query()`'s semantic path too, since it calls `search()`
internally). Reuses `@claude-flow/security`'s `ToolOutputGuardrail`
(ADR-131) for the actual OWASP LLM01/LLM08 pattern scan rather than
duplicating it — `@claude-flow/memory` now depends on
`@claude-flow/security` (no cycle: security has zero workspace deps).
- Size gate + guardrail scan per retrieved chunk. Flag-only by default;
`CLAUDE_FLOW_RETRIEVAL_GUARD_STRICT=true` drops unsafe/oversized chunks
instead of just annotating them. Both flags off by default
(`CLAUDE_FLOW_RETRIEVAL_GUARD=true` to enable scanning at all).
Phase 2 — MemoryPoisonForensics (@claude-flow/hooks)
- New `workers/memory-poison-forensics.ts`: rolling-window z-score anomaly
detection on write-interval and content-length features per
(agentId, namespace), reproducing the Forensic Trajectory Signatures
(arXiv:2606.30566) shape (behavioral features on write *sequences*, not
content). Opt-in `HookEvent.PostToolUse` handler for memory-write tools;
`CLAUDE_FLOW_POISON_FORENSICS=0` disables recording.
- NOT wired into any of this repo's three separate "worker" dispatch
systems (hooks' own workers/index.ts codebase-analyzers,
@claude-flow/swarm's worker-dispatch.ts 12-trigger table, or the CLI's
scheduled daemon) — @claude-flow/swarm is a deliberately
zero-workspace-dependency package and adding hooks there would break
that property; picking the wrong one of three ambiguous dispatch tables
seemed worse than leaving that integration as an explicit follow-up.
See the file header for detail.
Phase 3 — McpCallerIdentity (@claude-flow/security)
- New `mcp-caller-identity.ts`: per-invocation Ed25519-signed capability
tokens (callerId + toolName + nonce + 30s TTL by default), native
node:crypto sign/verify following the same pattern already used by
`@claude-flow/browser`'s witness-signer.ts (reimplemented rather than
cross-imported — a security-primitives module depending on the browser
package would be a backwards layering dependency).
- Standalone issue/verify API; deliberately NOT wired into
`AgentAuthorizationPropagator.checkToolCall` (ADR-144) or any tool
dispatcher — this repo has at least 3 distinct `ToolRegistry`
implementations and guessing which is authoritative risked silently
wiring the wrong path. `CLAUDE_FLOW_MCP_CALLER_AUTH` defaults to
disabled, matching the ADR's own text: key distribution needs a
follow-on ADR before this ships enabled.
Deviations from the ADR's guessed file paths/class names (documented
inline where relevant): the ADR was written against aspirational paths
(`agentdb/retrieval-guard.ts`, a `BackgroundWorker` interface,
`SafeExecutor`) that don't match the real repo layout — implementation
targets the actual `AgentDBBackend`, the actual worker systems, and the
actual `AgentAuthorizationPropagator`/tool-registries respectively.
Tests: 31 new tests across the three packages (9 + 11 + 11), all passing;
full existing suites re-run clean (memory 451, hooks 145, security 570 —
zero regressions).
Follow-up from dream-cycle issue #2783 / PR #2784. Implements the v2 that the already-shipped v1 (commits 381b7ebcc/581cd2bf3) explicitly deferred: SimHash-based cross-tool fragment detection for MCP composition, and a ChannelGuard reusing the real InputValidator instead of a reinvented catalog. 29 new tests, 134/134 existing hooks tests passing, 0 regressions, clippy clean.
getSecurityStatus() hardcoded totalCves=3 and counted scan *files* as
'CVEs fixed', fabricating '⚠ 3 CVEs' for every project. Now reads the
NEWEST scan in .claude/security-scans/ and surfaces its real findings
count (summary.total ?? totalFindings ?? findings.length). cvesFixed
stays 0 until a real fix-tracking mechanism exists.
Fixed in all 5 copies:
- v3/@claude-flow/cli/src/funnel/local-signals.ts (TS source of truth)
- v3/@claude-flow/cli/.claude/helpers/statusline.js (cli helper)
- v3/@claude-flow/mcp/.claude/helpers/statusline.cjs (mcp helper)
- v3/@claude-flow/mcp/.claude/helpers/statusline.js (mcp helper)
- v3/@claude-flow/hooks/src/statusline/index.ts (hooks statusline)
Also: executor.ts init defaults totalCves 3->0 (2 sites);
statusline/index.ts audit fallback defaults 3->0.
Added regression test issue-2694-cve-counter.test.ts (pure unit, no CLI).
Updated security-scan-persistence.test.ts to assert CLEAN/0/0 for the
empty fixture (was asserting cvesFixed>=1, the fabricated behavior).
The 'block stopping when too many unconsolidated patterns' test stores
12 patterns, each triggering HuggingFace embedding model inference. On
cold-cache CI the model download alone can take 30-60s, then 3-5s per
pattern × 12. 60s wasn't enough; 180s gives headroom for slow runners.
Local warm-cache runs still finish in <2s.
Co-Authored-By: RuFlo <ruv@ruv.net>
Down to 2 unique failing tests after the previous batch landed (each
appearing 4× through workspace mirror paths). Both fixed:
1. tool-honesty 'should not generate fake speedup claims'
The assertion required `/speedup:.*implementation\.startsWith\('real-'\)/`
but the current handler doesn't emit a 'speedup' field at all
(which equally honors 'don't fake a speedup'). Rewrote as a
conditional check: if a speedup field IS present, gate it on
implementation.startsWith('real-'); always reject unconditional
numeric literals. Either implementation passes; only a fabricated
one fails.
2. guidance-provider 'should block stopping when too many unconsolidated'
Had inline { timeout: 15000 } overriding the global 30s bump. CI
cold-loads HuggingFace embeddings on first storePattern call and
12 of those exceed 15s. Bumped the inline override to 60000.
Plus, macOS Node 24 drop:
Smoke (no better-sqlite3) / macos-latest / Node 24 fails because
GitHub's macos-latest image ships Python 3.12 which removed
distutils, breaking node-gyp for hnswlib-node + better-sqlite3
during install. Linux × Node 22+24 + macOS × Node 22 still covers
the OS×Node cross-product meaningfully.
Co-Authored-By: RuFlo <ruv@ruv.net>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T03:43:49Z
- Changes: 1 file(s)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Claude Code writes its internal status (e.g., "7s • 1p") at absolute terminal
coordinates (columns 15-25 on second-to-last line), causing character bleeding
when our statusline has content there.
Changes:
- Add generateSingleLine() for single-line output (complete avoidance)
- Add generateSafeStatusline() with 24-space padding after emoji (2+24=26)
- Make safe mode the default, add --single/--unsafe/--legacy options
- Add comprehensive tests for collision zone avoidance
The collision zone is cols 15-25 on the second-to-last line of output.
By padding with 24 spaces after the emoji (2 cols), content starts at
column 26, safely past the collision zone.
Fixes#985
Automatic checkpoint created by Claude Code
- Branch: v3
- Timestamp: 2026-01-07T15:37: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: v3
- Timestamp: 2026-01-07T15:37:32Z
- 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: v3
- Timestamp: 2026-01-07T15:37: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: v3
- Timestamp: 2026-01-07T15:34: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: v3
- Timestamp: 2026-01-07T15:33: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: v3
- Timestamp: 2026-01-07T15:33:29Z
- Changes: 6 file(s)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated standard-checkpoint-hooks.sh to accept both JSON and plain paths
- Fixed pre-edit and post-edit functions to detect input format
- Fixed v3 CLI hook flags (-f -> --file, -c -> --command, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>