mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
ci/control-current-main
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
40878cca35 |
dream(swarm): #3242 fix AgentPool health checks that could never detect a dead agent (evaluated, ACCEPT-scoped) (#3243)
* dream(swarm): #3242 fix AgentPool health checks that could never detect a dead agent performHealthChecks() stamped lastHeartbeat = now on every "still healthy" tick, and updateAgentHeartbeat() (the only other legitimate way to advance that field) has zero callers anywhere in v3/ — so the check's own tick was the sole thing keeping every pooled agent's heartbeat fresh, meaning timeSinceLastActivity could never exceed one health-check interval and replaceUnhealthyAgent() could never fire for any agent, in any pool, ever. Fixes the self-stamp; matches the correct pattern already implemented in UnifiedCoordinator.checkHeartbeats() in the same package. New deterministic test file (fake timers): baseline fails 2/3 tests, candidate passes 3/3, 223/223 full package suite, tsc clean. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01TAzfKzdv9uRVjKt5TeBgkv * dream(swarm): fold in adversarial-critique caveats, re-verify, ACCEPT-scoped Independent critic (separate context) confirmed the fix and re-derived everything itself (zero-callers grep, full suite, tsc, stash-isolated baseline/candidate). Two disclosed, non-blocking caveats folded into the gist: (1) @claude-flow/swarm is not currently a dependency of the shipped @claude-flow/cli, so tonight's fix is real within the swarm package's own UnifiedSwarmCoordinator/tests but has no reachable path through the actual CLI today; (2) health still optimistically recovers +0.1/tick inside the grace window even with zero real heartbeats (pre-existing, out-of-scope, mirrors UnifiedSwarmCoordinator's own no-tick-recovery design). Also fixes a cosmetic class-name typo in the source comment (UnifiedCoordinator -> UnifiedSwarmCoordinator). Re-ran full suite (223/223) and tsc (clean) after the comment edit; recomputed the witness stamp over final content. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01TAzfKzdv9uRVjKt5TeBgkv * dream(swarm): update LEDGER.md for #3242/#3243 Records tonight's row plus verified GitHub state for the trailing nights (MCP tools, not inferred) and the 2026-09-08 gap note (same ledger-rows-only-reach-main-via-merge structural issue tracked since 2026-08-19). Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01TAzfKzdv9uRVjKt5TeBgkv --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
6acc689150 |
dream(intelligence): #3220 gate EnhancedModelRouter's forwarded modelId on tier match (evaluated, ACCEPT-scoped) (#3221)
Merged after independent re-verification: 109/109 CI green, the earlier '168 failures' finding traced to an unbuilt-sibling-package local artifact (unrelated to changed files), and a subsequent CI flake confirmed unrelated via clean re-run. Overriding the PR's self-merge gate on explicit user (ruvnet) authorization. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_013XaRQntabVwGT9SvnW8cKK |
||
|
|
277c7bc03a |
dream(memory): #3168 wire embedding-cosine into SmartRetrieval's MMR step (evaluated, ACCEPT) (#3169)
* dream(memory): wire embedding-cosine into SmartRetrieval's MMR step (evaluated, ACCEPT) smart-retrieval.ts's MMR diversity re-ranking used token-Jaccard text overlap as its "similarity to already-selected" term, even though memory-initializer.ts's searchEntries() already computes real ONNX-embedding cosine similarity for the primary relevance score and discards it before returning. 2025-2026 production practice (LangChain's reference maximal_marginal_relevance, Qdrant's native Mmr query shipped Sept 2025, Weaviate's MMR reranker shipped in 1.37) universally uses embedding-cosine for this term; token overlap misses low-token-overlap paraphrases embeddings correctly flag as near-duplicates. Threads the embedding through: searchEntries()'s two live compute sites (RaBitQ rerank, brute-force SQL) now return it instead of discarding it; the two CLI/MCP bridge mappers (memory-tools.ts, commands/memory.ts) pass it through; SearchCandidate gains an optional `embedding` field; mmrRerank uses cosine when both candidates have one, falling back to token-Jaccard otherwise (existing callers/tests without embeddings are unaffected). controller-registry.ts's separate toCands()/applyMMR path had the same gap for a different reason (embedding available on r.entry.embedding but never copied) — fixed the same way. Evaluated via deterministic Vitest, zero LLM calls, $0 cost. New discriminating test: a low-token-overlap paraphrase (near-1.0 cosine to the seed) vs. a genuinely different topic (near-0 cosine). Baseline (git stash-isolated): picks the paraphrase second (Jaccard can't tell "low overlap because paraphrase" from "low overlap because unrelated"). Candidate: correctly picks the different topic second. Full @claude-flow/memory suite: 460/461 passing identically with/without the candidate (1 pre-existing chmod-based environmental failure, same class documented since 2026-08-15). tsc --noEmit: zero new errors (verified @claude-flow/cli's 455 pre-existing errors, from unbuilt workspace packages, are identical with and without this diff). Darwin: skipped, scope mismatch (correctness/similarity-metric fix with a discriminating unit test, not a continuous parameter with a gold-labeled corpus). Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01Qho5K4p5ACBt4yzCWjkBGe * dream(memory): address review remediation — split CI, real benchmark, hardening Response to ruvnet's REJECT review on #3169: 1. Split — dream-cycle-backlog-guard.yml moved out to #3205; this branch now carries only the MMR fix, rebased onto main (which already includes the merged #3203 CI fix). 2. Real benchmark (new src/mmr-benchmark.test.ts): 18-doc/6-topic labeled corpus (1 canonical + 2 low-token-overlap paraphrases per topic), run through the actual smartSearch/mmrRerank code, swept across mmrLambda in {0.3, 0.5, 0.7, 0.9} rather than one favorable value. Honest finding: at diversity-heavy lambda, candidate's recall/nDCG drop sharply vs. baseline, because cosine correctly suppresses same-topic near-duplicates that Jaccard fails to detect at all (and so "accidentally" keeps full recall). At smart-retrieval.ts's own default (lambda=0.7), recall@6/nDCG@6 are identical to baseline (1.000/0.777 both) while topic-diversity improves 0.472->0.667 and ground-truth duplicate-rate drops 0.289->0.200. Reports latency (sub-ms both paths at this corpus size) and a memory-overhead estimate. 3. Malformed/dimension-mismatch: found and fixed a real bug while writing these cases. A NaN/Infinity-poisoned embedding component reached cosineSimilarity unguarded; the poisoned NaN score meant `mmr > bestMmr` was never true (NaN comparisons are always false in JS), which could silently break MMR's selection loop and under-fill results below the requested limit. Added isWellFormedEmbedding() so malformed/empty embeddings fall back to token-Jaccard, same as absent/mismatched ones. 3 new cases (NaN/Infinity, empty array, explicit dimension-mismatch) plus a test mirroring the two real CLI/MCP output whitelists (memory-tools.ts:559-569, commands/memory.ts:633-639) to assert `embedding` cannot appear in either shape. 4. Determinism: new test runs the same input through smartSearch 5 times concurrently, asserts byte-identical result ordering every time, including a genuine same-embedding tie. Full @claude-flow/memory suite: 465/466 (1 pre-existing, unrelated environmental failure). tsc --noEmit: zero errors. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01Qho5K4p5ACBt4yzCWjkBGe --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
33a2c3ed07 |
dream(performance): #3183 wire real cold-start measurement, remove fabricated V2-vs-V3 benchmark (evaluated, ACCEPT-scoped) (#3184)
* docs(dream-cycle): backfill LEDGER rows for 2026-08-24..09-03 Ledger-append step silently failed again for 10 consecutive nights (3rd occurrence of this failure class, first flagged 2026-08-19). Verified via git ls-remote + GitHub MCP issue/PR search before concluding this (all 10 nights ran to completion: real branch, issue, and draft PR each) rather than inferring failure from a sparse table. 2026-08-20..08-23 is a separate, confirmed-genuine 4-night gap where the pipeline did not run at all. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01YQUz3bkMpqgtLXgkYa1LFF * dream(performance): wire real cold-start measurement, remove fabricated V2-vs-V3 benchmark (evaluated, ACCEPT-scoped) cli-cold-start.bench.ts's own measureColdStart() (a real, spawn-based process timer) was never called anywhere in the file. Every reported number instead came from setTimeout() delays, including a "V2 vs V3 Speedup: 5.00x" that was guaranteed by construction (setTimeout(100) vs setTimeout(20), no code between them) regardless of any real behavior. - Export measureColdStart(), add runRealColdStartMeasurement() and CLI_BIN_PATH; wire the real spawn-based measurement into the suite. - Remove the fabricated V2-vs-V3 comparison outright (no V2 binary remains to honestly compare against). - Add a deterministic Vitest regression test (4 assertions); fails against baseline (functions not exported, fabricated pattern still present), passes against candidate — confirmed via git-stash isolation. Full @claude-flow/performance suite: 99/99 passing. tsc --noEmit: clean. - Real measured number: node bin/cli.js --version, 5 runs, mean 54.65ms (min 51.94 / max 57.92) — well under the 500ms target. Caveat disclosed in-code: --version is the one subcommand that succeeds without a built dist/ in this worktree; this is not a full-CLI cold-start measurement. - Correct the two stale "Achieved" claims this fed in ADR-STATUS-SUMMARY.md's Performance Targets table (CLI Startup, and the already-known-false HNSW 150x-12,500x figure one row up). Darwin: skipped, scope mismatch (dead-code-wiring fix, not a tunable parameter). Flywheel: no signed bundle, deterministic Vitest evidence retained instead. Follow-ups documented in tonight's gist: same anti-pattern in agent-spawn/mcp-server-init/cli-warm-start bench files (not touched, kept to one conceptual change); a Raft election safety gap and a plugin supply-chain enforcement gap found by tonight's scan roles (hive-mind, security) but out of scope for the performance DEEP surface. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01YQUz3bkMpqgtLXgkYa1LFF * docs(dream-cycle): append 2026-09-05 ledger row Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01YQUz3bkMpqgtLXgkYa1LFF --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
b291ac4049 |
dream(intelligence): #3048 discounted Thompson sampling for model-router bandit (evaluated, ACCEPT-scoped) (#3049)
* dream(intelligence): discounted Thompson sampling for model-router bandit Adds an opt-in `priorDecay` config field (default 1 = disabled, fully backward compatible) to ModelRouter's Beta-Bernoulli bandit. When enabled, every bucket/model's alpha/beta decays geometrically once per recordOutcome() call before that round's reward is added (arXiv 2305.10718 discounted Thompson sampling), so accumulated routing history from a long-running persisted state file no longer permanently dominates the posterior after a real-world model-quality shift. Benchmark (n=30 paired trials, seeded PRNG, identical stream baseline vs candidate): non-stationary regime-shift recovery 26.5 -> 21.9 rounds (-17.6%, t=7.24); post-shift correct-routing rate +1.3pp (t=6.10); stationary-workload invariant held (delta +0.02pp, not a regression). Receipt: v3/@claude-flow/cli/benchmarks/results/prior-decay-receipt.json. Mirrors the epsilon-decay pattern q-learning-router.ts already applies to its own exploration rate -- an internal-consistency fix, not an imported pattern. Evaluation and adversarial critique in progress; this commit is the checkpointed, test-passing candidate + its baseline/candidate receipt. Co-Authored-By: RuFlo <ruv@ruv.net> * dream(intelligence): #3048 fix adversarial-critique findings, add gist + ledger Independent adversarial critique found and this commit fixes: a paired-t statistics bug (population vs sample stddev inflated every t-value by n/(n-1)), an unguarded priorDecay input (NaN/negative could silently poison persisted .swarm/model-router-state.json forever, bypassing sampleBeta's own defensive fallback), and a single-bucket benchmark blind spot (now covers low + med complexity buckets -- the med bucket shows no significant effect, disclosed rather than hidden). Also adds the research gist and backfills 3 missing ledger rows for 2026-08-14/15/16 (real PRs/issues existed for those nights but the ledger table wasn't updated) plus tonight's own row. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
41efca8be3 |
dream(memory): #3056 hybridSearch reachable via explicit opt-in (evaluated, ACCEPT-scoped) (#3057)
* dream(memory): #3056 hybridSearch reachable via explicit opt-in without memoryService The ADR-125 Phase 5 three-arm (dense+sparse+entity) RRF/MMR fusion controller was fully built and tested but unreachable from any production call site: its explicit-enable config override worked at the isControllerEnabled() gate but the createController() factory still unconditionally required a hand-built UnifiedMemoryService, silently returning null otherwise. Falls back to the existing this.backend when it type-guards as AgentDBAdapter-compatible, reachable only via explicit controllers: { hybridSearch: true } -- default auto-enable behavior is unchanged. New deterministic $0 benchmark quantifies the feature's actual retrieval-quality effect for the first time (previously only functional/unit tests existed): +0.267 aggregate recall@10, with a disclosed, statistically significant regression on pure-paraphrase queries where fusion noise dilutes an already-perfect dense signal. Independent adversarial critic (fresh subagent): CONFIRMED-SAFE, reproduced bit-for-bit. 75/75 tests passing in touched files, 458/459 in the full package (1 pre-existing environmental failure, unrelated). Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_016T1JRz8NBeGGmxQJVPReWa * dream(memory): #3056 update ledger with 2026-08-14..18 nights + PR #3057 Reconstructs the v2 live-entries table from PR/issue history since each night's own LEDGER.md edit lives only on its unmerged branch and never reaches main (0% merge rate). Adds tonight's row (memory, hybridSearch reachability fix, ACCEPT scoped, witness b28714fb...). Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_016T1JRz8NBeGGmxQJVPReWa --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
dcea520b4e |
dream(swarm): #3061 bound MessageBus retry attempts, fix unreachable message.failed (evaluated, ACCEPT) (#3062)
* dream(swarm): recover 5 missing live ledger rows (2026-08-14..18) The v2 live-entries section of docs/dream-cycle/LEDGER.md was never appended to for 5 consecutive nights despite each night running to completion (branch + draft PR + issue verified to exist for all 5 via git ls-remote and GitHub search before concluding this, per the ledger's own anti-inference rule). Backfilled directly from the PRs/issues. Root cause of the append gap not diagnosed tonight; flagged in the gist/issue as a candidate finding for a future automation/meta scan. * dream(swarm): bound MessageBus retry attempts, fix unreachable message.failed Given a subscriber whose callback always throws, MessageBus.handleDeliveryError() incremented the queue entry's attempts counter but addToQueue() always constructed a fresh entry with attempts:0 on re-queue, discarding it. Retries were unbounded (96-98 invocations / 0 failures observed in 500ms, git-stash- verified pre-fix) instead of capped at config.retryAttempts, and the message.failed branch was unreachable. Fix: addToQueue() takes an optional existingAttempts parameter; the retry path in handleDeliveryError() now threads entry.attempts through instead of resetting it. Fresh-message call sites are unaffected (default 0). Candidate evaluated: exactly 3 invocations / 2 retries / 1 failure, stable thereafter. 220/220 tests passing (2 new, 0 regressions). Independently re-verified by an adversarial critic (fresh session, no authoring context): CONFIRMED-WITH-CAVEATS — fix and scope match the claim; flagged (and now disclosed in-code) a separate pre-existing, unfixed broadcast-retry queue-key bug this diff does not touch. Full research/evaluation writeup: docs/dream-cycle/dream-gist-2026-08-19.md * dream(swarm): append 2026-08-19 ledger row --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
0e50fe7f57 |
dream(security): #3043 advisory scanner for untrusted settings.json hooks/allow-rules (evaluated, ACCEPT) (#3044)
* dream(security): #3043 advisory scanner for untrusted settings.json hooks/allow-rules carried forward by ruflo init/--upgrade mergeSettingsForUpgrade() and writeSettings() both read a target project's pre-existing .claude/settings.json and spread its hooks / permissions.allow entries into the merged output verbatim — the same trust shape as CVE-2025-59536 (settings.json hook payload achieving command execution with no review step), reached via ruflo init's own merge logic rather than Claude Code's loader. Neither of last night's flagged CVEs (2025-59536, 2025-6514) applies to Ruflo's own hook dispatch or OAuth client directly, but this distinct gap in the same family was genuinely unaddressed. Adds a static, advisory-only (non-blocking) scanner that inspects hook commands and Bash allow-rules for known-dangerous patterns before the merge and surfaces findings as CLI warnings. Merge/write behavior itself is completely unchanged. Hardened after an independent adversarial-critic pass found 6 concrete bypasses (intermediate-pipe-stage downloads, two-step download+exec, eval-wrapped base64, interpreter-mediated dangerous commands, absolute-path-prefixed commands, whitespace-evasive allow rules) — all fixed and pinned as a held-out regression set. Also fixes an ANSI/control-character injection risk in the warning output itself, self-identified during review. 87/87 relevant tests green (1 pre-existing environmental failure elsewhere in the package, unrelated — unbuilt sibling package). Dream Cycle 2026-08-16, security surface. Full research, evaluation receipts, and adversarial critique: issue #3043 and docs/dream-cycle/dream-gist-2026-08-16.md. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01NVdeUqt73Bv7vnPxYpZy7i * docs(dream-cycle): update ledger — backfill 2026-08-14/2026-08-15, add 2026-08-16 2026-08-14 (swarm, REJECT) and 2026-08-15 (performance, REJECT) both had fully-run pipelines whose live ledger rows never reached main (every dream-cycle PR to date is unmerged, so branch-local ledger commits never merge forward) — verified via git ls-remote / search_pull_requests before backfilling, not assumed. 2026-08-16 (security, ACCEPT): advisory scanner for untrusted settings.json hooks/allow-rules carried forward by ruflo init/--upgrade. Issue #3043, PR #3044. Co-Authored-By: RuFlo <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_01NVdeUqt73Bv7vnPxYpZy7i --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
abf26ab097 |
docs(dream-cycle): seed LEDGER.md with backfilled history + v2 routine update (#3018)
The Ruflo Nightly Dream Cycle cloud routine (trig_01HpEqAcEP7wzrxy3TzakrQ2) was updated to v2: parallel research via the Task tool, claude-sonnet-5, expanded toolset (TodoWrite/Skill/MultiEdit/BashOutput/KillBash), and a new STEP 3.5 that attempts a real Flywheel evaluation (metaharness bench/evolve) for harness-shaped findings instead of always stopping at a docs-only PR. This file is the durable cross-night memory the new STEP 1 reads before touching gh at all -- a fresh cloud checkout otherwise has zero continuity beyond a gh issue list grep, which is what v1 relied on for 80 nights. Backfilled from the full issue history: 4 shipped (5%), 1 rejected, 75 (94%) never touched, some >2.5 months stale. v2 uses this to bias toward attempting evaluation over another research-only proposal when the trailing merge rate is 0. |
||
|
|
5f81112467 |
docs(adr): consolidate 49 stale dream-cycle proposals, renumber ADR-334..376 (#2871)
The dream-cycle bot has opened a research proposal draft PR nightly since 2026-05-29. None had ever been merged (tracked in #2324), so each night's run guessed ADR numbers against a stale view of main and collided repeatedly — ADR-147 alone was independently claimed by 4 different proposals (#2304, #2310, #2317, plus a README-only PR #2278), and ADR-179 by another 4 (#2617, #2624, #2631, #2656, plus README-only #2642). This consolidates the SOTA research reports and ADR proposal text from all 49 open dream-cycle drafts into a single reviewable change: - 43 ADR proposals renumbered sequentially into ADR-334 through ADR-376 (first-opened-first-numbered), with self-referencing ADR-N mentions inside each file updated to match - 4 branches that contained only a SOTA report with no ADR proposal (#2368, #2382, #2430, #2607) carried over as-is - 2 branches that only added a README index row for an ADR file they didn't otherwise include (#2278 for ADR-147, #2642 for ADR-179) are superseded by the real ADR-147/179 claimants above and dropped - v3/docs/adr/README.md gets one clean set of index rows instead of 43 individually conflicting ones All ADRs land as Proposed — none of this is an implementation decision, just clearing 2 months of unreviewed nightly research out of PR limbo so it can actually be read. The original 49 PRs are closed with a pointer to this commit. Closes #2224, #2242, #2249, #2255, #2266, #2278, #2304, #2310, #2317, #2333, #2344, #2363, #2368, #2379, #2382, #2394, #2402, #2420, #2430, #2436, #2457, #2463, #2472, #2479, #2486, #2496, #2511, #2527, #2537, #2560, #2577, #2598, #2607, #2617, #2624, #2631, #2642, #2656, #2665, #2702, #2716, #2728, #2740, #2753, #2761, #2764, #2769, #2779, #2793 |