ADR-098 documents the durable behavioural decisions from the ruflo adoption pass (#510): domain-score de-dilution (#2), EWC++ importance-weighted forgetting (#6), contradiction suppression (#7), the two pre-existing bug fixes (consecutive_failures, MCP -32601), and the explicit NEGLECTED decisions — ruflo's Beta-priors (#2) and RaBitQ speedup (#8) did not transfer, and multi-bundle packaging is deferred. AQE WH(Y) format, Accepted. Marks the consecutive_failures (ae7c8b71) and MCP error-code (9b189115) side-findings FIXED in the plan. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
17 KiB
Ruflo Adoption Plan — Self-Learning, Routing, MCP & Benchmark Improvements
Source: Analysis of ruvnet/ruflo changes (307 commits, 2026-05-02 → 2026-06-01, ADR-120 → ADR-143).
Goal: Port the highest-value mechanisms and disciplines from Ruflo's last month into the AQE platform.
Branch: working-april · Tracking issue: proffesor-for-testing/agentic-qe#510
Working rule: implement → integrate → verify from a user's perspective → commit each item separately. Do not push until requested.
Theme of Ruv's month: "proof, not theater." An audit (#2245) found the self-learning system "reports success but persists nothing queryable." ~20 ADRs went into wiring engines to their advertised surfaces and benchmarking against public baselines. That measurement discipline — not any single algorithm — is the core thing AQE adopts here.
Status legend
TODO · IN-PROGRESS · VERIFIED (user-perspective check passed) · COMMITTED (sha recorded) · BLOCKED
Progress table
| # | Item | Tier | Risk | Status | Commit |
|---|---|---|---|---|---|
| 1 | Self-learning verification harness | 1 | Low (new script) | VERIFIED | 9cb44d32 |
| 2 | Routing-confidence fix (domain-score de-dilution; ruflo per-bucket priors N/A) | 1 | Med (router) | VERIFIED (PARTIAL: +5.6pp on broad tasks; structural Q-maturity/perf-term ceiling remains — see side-findings) | 1bb91b40 |
| 3 | Router bug audit: stale cache + state-encoder truncation | 1 | Low (audit) | VERIFIED | 28fa643e |
| 4 | MCP protocol-compliance smoke + tool-parity audit | 1 | Low (new tests) | VERIFIED | b1a462fb |
| 5 | Resilient hook shim (local→exit 0→swallow stderr→JSON-only stdout) | 1 | Low | VERIFIED | 1a695f56 |
| 6 | EWC++ catastrophic-forgetting protection | 2 | Med (learning) | VERIFIED | ef4738de |
| 7 | Contradiction detection in consolidation | 2 | Med (learning) | VERIFIED | 43918b3b |
| 8 | RaBitQ 1-bit signatures (utility + benchmark; 32× mem, ~1.3× speed, UNWIRED) | 2 | Med (perf) | VERIFIED | 0d80eb56 |
| 9 | Pretrain-from-history bootstrap | 2 | Low (new script) | VERIFIED | 3196c05e |
| 10 | Plugin smoke contract ONLY (marketplace+lean bundle pre-existed; multi-bundle packaging DEFERRED) | 2 | Low | PARTIAL — smoke contract verified; original "subset bundles" scope not delivered | 98a6b19c |
| 11 | Committed-baseline benchmark convention | 3 | Low | TODO | — |
| 12 | Honest-CI ethos (bootstrap CIs for mincut on/off) | 3 | Low | TODO | — |
| 13 | Supply-chain hardening (expiring accepted-findings) | 3 | Low | TODO | — |
| 14 | Init-bundle invariants smoke | 3 | Low | TODO | — |
Execution order (compounding clusters)
- #3 (router audit — near-free, reveals correctness bugs) → #1 (verification harness — exposes whether 338/73%/40% are real).
- #2 + #6 + #7 (routing-confidence + forgetting + contradiction — they compound on the learning store).
- #4 + #5 (MCP smoke + hook shim — CI/runtime hygiene).
- #8 + #9 (perf + bootstrap).
- #10–#14 opportunistic packaging/benchmark work.
Each item below has: What Ruflo does, AQE target, Acceptance (user-perspective verification), Ruflo reference.
#1 — Self-learning verification harness [Tier 1]
- Ruflo: Runs each learning entry-point N× in an isolated temp store, asserts the store actually moved; includes a negative control (record-only → 0 delta) and a unified-stats consistency check across aggregators. Built after #2245 found counters that never incremented and
pretrainclaiming patterns thatlistreturned empty. - AQE target: A script that runs AQE's learning entry-points against a temp copy of
patterns.rvf/ a throwaway namespace, asserts pattern/trajectory count deltas, a record-only negative control, and that the reported338 patterns / 73% success / 40% confidenceround-trip through a query and survive a restart. - Acceptance: Run the harness; it prints measured before/after deltas, exits non-zero if any store fails to persist. Independently confirm (or refute) the session-banner numbers.
- Ref:
v3/@claude-flow/cli/scripts/benchmark-self-learning.mjs
#2 — Per-bucket bandit priors (the 40% routing-confidence fix) [Tier 1] — RECLASSIFIED
- Ruflo (ADR-142): Beta(α,β) routing priors keyed by complexity bucket (low/med/high) instead of one global prior — fixes "8 failures on one hard task suppress a model for all tasks." Lossless forward-migration of flat priors into 3 buckets.
- Investigation (2026-06-02, verified with real routes): AQE's routing confidence is NOT a Beta-bandit prior, so ruflo's ADR-142 fix does not apply. Confidence (
QERoutingResult.confidence) is the top agent's combined static score fromcalculateAgentScores(src/learning/agent-routing.ts:338), blended with an immature Q-table (qWeightramps 0→0.4 only after 20 visits/state; live telemetry showsqWeight: 0). The one Beta sampler in the codebase (src/integrations/ruvector/thompson-sampler.ts, ADR-084) is for cross-domain transfer, keyed per domain-pair (already bucketed), and never feeds the 40% number. - Real root cause: domain-score dilution.
agent-routing.ts:363computesdomainScore = (domainMatch / detectedDomains.length) * 0.4. AQE's domain detector returns 7–12 domains per task, so a perfect single-domain match yields(1/11)*0.4 ≈ 0.04. Confidence is therefore dominated by the fixed performance term (profile.performanceScore * 0.3 ≈ 0.27) + a default capability term (0.15), which is why a clean easy task lands at 37.3% and a hard task at 20.5% (measured viaaqe hooks pre-task). The byzantine-consensus task also mis-routed toqe-performance-tester. - Proposed scoped fix (needs sign-off — published hot path): de-dilute the domain term — divide by matched-or-
min(detectedDomains.length, K)rather than the full breadth of detected domains, so relevance isn't washed out when the detector is broad. Keep it behind the existingroutingWeightsso it's tunable/reversible. Affects every routing decision + all confidence telemetry → requires explicit confirmation per CLAUDE.md production-safety. - Acceptance (unchanged): reproduce low confidence (done: 37.3%/20.5%), apply fix, show easy-task confidence recovers and good matches rank correctly, verified via real
aqe hooks pre-taskcalls. - Ref: AQE
src/learning/agent-routing.ts:338-405; rufloADR-142-per-task-bandit-priors.md(not a structural match).
#3 — Router bug audit [Tier 1]
- Ruflo (2026-05-29): (#2229) learned Q-update hidden behind a stale route cache until 50 updates accrued → invalidate the state's cache entry on every update. (#2239) task→state hash shifted the keyword feature block past a 31-bit mask, collapsing all tasks into one state → full-width FNV-1a +
encoderVersionmigration guard. - AQE target: Grep AQE routing/caching/state-encoding for both patterns; fix if present, document if absent.
- Acceptance: A test demonstrating a learned update is visible immediately (no stale cache) and two distinct tasks map to distinct states.
- Ref:
v3/@claude-flow/cli/src/ruvector/q-learning-router.tsL274-281, L449-491
#4 — MCP protocol-compliance smoke + CLI↔MCP parity audit [Tier 1]
- Ruflo (#1874): Boots the real MCP server (
spawn), sends a realinitializeJSON-RPC request, validates wire format against the spec (protocolVersionmatchesYYYY-MM-DD). Plusaudit-cli-mcp-tools.mjs(monotone baseline) caught ~20 dangling CLI→MCP references. - AQE target: A smoke test that boots AQE's MCP server and validates the
initializehandshake; an audit asserting every CLIcallMCPTool('x')resolves to a registered tool. Enforces CLAUDE.md's existing (currently unenforced) "MCP-CLI Parity" + "Integration Tests Required for MCP" mandates. - Acceptance: Smoke connects to the live server and passes; parity audit reports 0 new dangling refs against a baseline.
- Ref:
plugins/ruflo-core/scripts/test-mcp-protocol.mjs,scripts/audit-cli-mcp-tools.mjs
#5 — Resilient hook shim [Tier 1]
- Ruflo:
ruflo-hook.{sh,cjs}— prefer local binary → npx offline fallback → swallow stderr → alwaysexit 0; Windows.cjsparity. Prevents a hook failure (ornpx @alphare-resolve crash) from blocking a Claude Code turn. - AQE target: Harden AQE's
.claude/hooksto never block a turn and never dump init noise into the transcript. - Acceptance: Force a hook-internal error; confirm the turn proceeds and stderr is suppressed.
- Ref:
.claude-plugin/scripts/ruflo-hook.{sh,cjs},hooks/hooks.json
#6 — EWC++ catastrophic-forgetting protection [Tier 2]
- Ruflo: Blends high-importance patterns instead of letting new low-value ones clobber them, weighted by per-dimension importance × recency. Honest framing:
F_iis an embedding-importance proxy, not true Fisher. - AQE target: Add importance-weighted blending to AQE's consolidation/dream cycle so success rate doesn't erode as patterns accumulate.
- Acceptance: Simulate an influx of low-value patterns; show high-value patterns survive and recall@k for known-good patterns is preserved.
- Ref:
v3/@claude-flow/cli/src/memory/ewc-consolidation.ts
#7 — Contradiction detection in consolidation [Tier 2]
- Ruflo: Flags pairs with cosine > 0.8 but quality delta > 0.4 ("similar context, opposite outcome") and excludes the loser from retrieval.
- AQE target: Extend AQE's dedup (which merges agreeing near-duplicates) to also detect conflicting ones and suppress the loser.
- Acceptance: Inject a contradictory pattern pair; show the lower-quality one stops being recalled.
- Ref:
v3/@claude-flow/neural/src/reasoning-bank.ts:1202
#8 — RaBitQ 1-bit signatures for HNSW retrieval [Tier 2]
- Ruflo (perf M4): Sign-random-projection + Hamming popcount, gated at N≥100: 10.9× per-pair, 2.7× end-to-end at N=1000, 32× index-memory reduction.
- AQE target: Apply to
qe-embeddings/patterns.rvfsimilarity used in defect-prediction and coverage-gap search. - Acceptance: Benchmark before/after on a fixed corpus; show speedup and memory reduction with recall@10 preserved.
- Ref:
v3/@claude-flow/guidance/src/retriever.ts
#9 — Pretrain-from-history bootstrap [Tier 2]
- Ruflo (ADR-077): Seeds the store from git history (commits = success trajectories) + closed issues at ~3 ms/trajectory through the same live-learning code path.
- AQE target: A bootstrap script so a fresh repo starts with a non-empty, project-specific pattern store.
- Acceptance: Run on a clean fixture repo; show the store goes from 0 to N patterns, queryable.
- Ref:
scripts/pretrain-from-github.mjs
#10 — marketplace.json + lean skill packaging [Tier 2]
- Ruflo: Flat marketplace index of plugins (
{name, source, description}); versions per-plugin; skills auto-discovered (no skill/command/agent arrays in the manifest); per-bundlesmoke.shas a machine-checkable contract. - AQE target: Package AQE's ~84 skills into installable bundles (
aqe-core,aqe-security,aqe-browser, …) so users/plugin install aqe-security@agentic-qe. - Acceptance: A generated
marketplace.json+ at least one bundle that passes its smoke contract. - Ref:
.claude-plugin/marketplace.json,plugins/ruflo-plugin-creator/skills/create-plugin/SKILL.md
#11 — Committed-baseline benchmark convention [Tier 3]
- Ruflo: Every benchmark writes
runs/<name>-latest.json+ a timestamped run; regressions show as a git diff. CI: soft-gate + artifact upload + one hard "history summary" gate on newly-regressed metrics;process.exit(0)guards against native-handle hangs. - AQE target: Adopt the convention for qe-* benchmarks on the
benchmarksbranch. - Acceptance: One AQE benchmark emits the run-JSON pair and a CI step diffs it.
- Ref:
docs/benchmarks/runs/,.github/workflows/v3-ci.yml
#12 — Honest-CI ethos for mincut on/off [Tier 3]
- Ruflo (BEIR): Reports retrieval quality with bootstrap 95% CIs and labels non-significant wins as such.
- AQE target: Re-report the existing
mincut on/offbenchmark (branchbenchmarks, commit914dc934) with point estimate + CI; benchqe_mincut_*like Ruflo benchesdynamic-mincutvspersonalized-pagerank(p50/p99 at fixed graph size, baseline JSON). - Acceptance: Mincut benchmark output includes CIs and a significance label.
- Ref:
docs/benchmarks/BEIR-MATRIX.md,scripts/benchmark-graph.mjs
#13 — Supply-chain hardening [Tier 3]
- Ruflo:
accepted-findings.jsonwithexpiresAt(auto re-fail after the window); lesson #2112 — CVE overrides must be duplicated into every published package, not just root. - AQE target: Add an expiring accepted-findings file; verify overrides in every published package (reinforces the documented consumer-audit rule).
- Acceptance: Audit step fails on an expired finding; tarball-install audit confirms overrides apply in the published package.
- Ref:
.github/supply-chain/{allowed-deps,accepted-findings}.json,scripts/audit-supply-chain.mjs
#14 — Init-bundle invariants smoke [Tier 3]
- Ruflo (ADR-128): Init silently shipped 0 skills because a dir-walk only resolved on the maintainer's machine; a static smoke ("every SKILLS_MAP entry resolves, no orphans") guards it.
- AQE target: A smoke asserting every shipped skill/agent resolves in the packed npm tarball.
- Acceptance: Pack the tarball, run the smoke; it fails if a declared skill is missing.
- Ref:
scripts/smoke-init-bundle-invariants.mjs
Discovered side-findings (from running the new harnesses)
- Multiple lean subset bundles (follow-up from #10): AQE ships ONE bundle (
agentic-qe-fleet). Splitting the 93 QE skills intoaqe-security/aqe-browser/aqe-core/… subset bundles (so users/plugin installa subset) is a larger restructure of shipped artifacts needing a distribution decision.skills-manifest.jsonalready has category data (specialized-testing16,analysis-review6,infrastructure6, …) to drive it. Deferred. - Embedding latency ~2.3s/item (found by #9, 2026-06-02): the real ONNX embedding (
RealEmbeddings) costs ~2.3s per text here, vs ruflo's ~3ms/trajectory. So pretrain-from-history on 500 commits takes minutes, and any live path that embeds synchronously is slow. Candidate follow-up: batch embedding / faster backend / cache. Tracked in issue #510. - Hook cold-start latency (found by #5, 2026-06-02): the
route/session-startbundle hooks cold-start the full system (CoherenceService, RVF, fleet, daemons) on each fire — observed ~30–60s. They run on every UserPromptSubmit/SessionStart. The shim doesn't change this; candidate perf follow-up (warm daemon / lighter route path / cache). Tracked in issue #510. - Windows
.cjshook parity (follow-up from #5): AQE's hook config is entirely POSIXsh -c, so a Windows.cjsshim twin (as ruflo ships) also needs a settings rewrite — deferred. - [FIXED
9b189115] MCP unknown-tool error loses its JSON-RPC code (found by #4, 2026-06-02):handleToolsCallthrows a plain object{ code: -32601, message: 'Unknown tool: …' }for unknown tools; it escapes the request-handler safety net whereerr instanceof Erroris false, surfacing ascontent{"success":false,"error":"Internal error: [object Object]"}instead of a proper JSON-RPC-32601error. Tool is still correctly NOT executed. Candidate fix: throw a realError/McpError. Tracked in issue #510. - [FIXED
ae7c8b71]consecutive_failuresdeprecation branch never fires (found by #6, 2026-06-02):PatternLifecycleManager.checkDeprecationreads(pattern as PatternWithDeprecation).consecutive_failures, butrowToPattern(used bygetPattern) does not surface that column, so the value is alwaysundefined→0and the'failures'deprecation reason is dead via this path. Pre-existing (not introduced by #6). Candidate dedicated fix: includeconsecutive_failures/deprecated_atinrowToPattern. Tracked in issue #510. - RVF↔SQLite pattern drift (found by #1 audit-real, 2026-06-02): live store shows RVF vector count 338 vs SQLite
qe_patternsrows 345 (−7). Banner numbers (72.5% success / 39.7% confidence / 2131 routings) corroborate the session banner, but ~7 patterns exist in the table with no vector in the index. Non-gating note today; candidate for a dedicated reconciliation fix (aqe_patternsrow without an RVF vector is invisible to semantic recall). Tracked in issue #510.
Skip list (analyzed, not adopting)
- Legacy
install.sh/uninstall.sh(cp -rinto~/.claude) — superseded by native/plugin install. - The neural-trader plugin itself — domain-specific; only its substrate-consumption pattern is reusable.
Reference clone
/tmp/ruflo-analysis (depth-200 clone of ruvnet/ruflo).