mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
docs/chatgpt-plugin-reference
411 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
645f31a06f |
feat(graph-intelligence): #2044 ADR-123 Phases 2-4 — 5 adapters across 5 wedges
Phase 2 — Wedge 1: BrowserCausalAdapter
Exports ADR-122 Phase 2 selector-break events as a DD SparseMatrix per
origin. Off-diagonal weights are time-decayed adjacencies (half-life 24h
default). Includes role:name fuzzy-match keys for robust matching across
ref renames. graphId = `browser:causal:<origin>`.
Phase 3 — Wedges 3/6/7 (three adapters in parallel):
FederationTrustAdapter (ruflo-federation:trust-mesh)
Peer × peer with signature-confidence edges, stale-edge pruning
(default 7-day freshness window). Asymmetric (one-way trust).
CostAttributionAdapter (ruflo-cost-tracker:causation:<sessionId>)
Prompt → agent → MCP-call → model causation. L1-normalises costs per
parent so PR weights are proportional shares of blame.
ObservabilitySpanAdapter (ruflo-observability:trace:<traceId>)
Span dependency tree + cross-trace causedBy links. self-time-weighted
edges normalised per parent.
Phase 4 — Wedges 4/5:
KnowledgeGraphAdapter (ruflo-knowledge-graph:entities)
Entity-relation graph, multiple relations sum capped at 1.0 confidence.
RagMemoryAdapter (ruflo-rag-memory:chunks:<namespace>)
Chunk connectivity for personalized PR. Similarity floor filter
(default 0.5) so noise edges don't dilute results. seedNodes plumbed
through sublinear/page-rank-entry for query-aware personalisation.
All 5 adapters share:
- Dependency-injection via structural Source interfaces (no hard import
of @claude-flow/browser, ruflo-federation, etc. from this plugin)
- Optional nodeFilter for matrix pruning
- contentHash for memoization + Phase 7 signed-artifact integrity
- DD-safety-margin diagonal to keep the matrix solvable
63/63 tests passing (+18 for Phases 2-4):
- browser-causal-adapter.test.ts: 8 tests
- phase3-adapters.test.ts: 11 tests (federation: 4, cost: 3, observability: 3)
- phase4-adapters.test.ts: 8 tests (KG: 5, RAG: 3)
End-to-end via sublinear/page-rank-entry: 4 routed-through tests proving
the full registry → adapter → solver → result path on real graph shapes.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
126c23a0fc |
feat(graph-intelligence): #2044 ADR-123 Phase 1 — ruflo-graph-intelligence plugin foundation
Scaffolds plugins/ruflo-graph-intelligence/ — the RuFlo Graph Intelligence Engine. Built on sublinear-time-solver@^1.7.0. Three-layer architecture: Neural / Graph Intelligence / Complexity. Phase 1 deliverables: - package.json @ 0.1.0-alpha.1 - domain/types.ts — SparseMatrix, ComplexityClass (12 tiers + fitsBudget + isEdgeSafe), CoherenceReport, PageRankQuery/Result, SolveQuery/Result, SolveOnChangeQuery, structured GraphIntelError taxonomy - domain/adapter.ts — SublinearAdapter interface, AdapterRegistry (singleton) - infrastructure/solver-bridge.ts — coherenceScore, singleEntryPageRank (forward-push), conjugateGradient, neumann, solveOnChange, hashResult, observedComplexity, runPageRank/runSolve/runSolveOnChange entry points - mcp-tools/index.ts — 6 MCP tools under sublinear/*: page-rank-entry / solve / solve-on-change / analyze / feasibility / jl-embed All threaded with maxComplexityClass + coherenceThreshold budget gates. - tests: 37/37 passing — solver-bridge (coherence, PR, CG, Neumann, solve-on-change, hash determinism), adapter-registry (CRUD + singleton), mcp-tools (happy path, graph-not-found, coherence-rejected, complexity-budget-exceeded) CI guard (#2044 follow-up): - .github/workflows/v3-ci.yml — adds plugins/ruflo-graph-intelligence/** to both push and pull_request path filters - New job: ruflo-graph-intelligence build + test smoke. Installs (npm ci with --legacy-peer-deps because the plugin is outside the v3 pnpm workspace), typechecks, builds, runs vitest. Cross-platform via Node 22. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
116613e935 |
docs(ruflo-browser): #2041 link plugin to ADR-122 substrate
Adds a substrate-alignment banner pointing at the published @claude-flow/browser@3.0.0-alpha.4 npm package + the announcement gist. The plugin is the user-facing skill layer; npm package is the substrate. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
9056720219 |
fix(browser): #2015 round 2 — strip bogus --kind flag, ship alpha.42
Round 1 (alpha.41) added the required --dimension flag to `ruvector rvf create` but left the equally bogus `--kind browser-session` in place. ruvector@0.2.25's `rvf create` accepts only: -d, --dimension <n> (required) -m, --metric <metric> (optional, default cosine) Commander's required-option check fires before its unknown-option check, so the original bug report (#2015) only surfaced the dimension error. The fresh live regression check after publishing alpha.41 exposed the second-layer bug: `error: unknown option '--kind'`. This round: - Strip `--kind browser-session` from all 5 call sites (TS source, compiled dist via rebuild, replay-spike.sh, browser-agent.md, browser-record/SKILL.md). Also fixed the ADR prose example. - Tighten the smoke (scripts/smoke-browser-rvf-create-flags.mjs): - Switch from rg-based content scan to an explicit PATHS_IN_SCOPE list (the original `--kind browser-session` anchor is gone, so we can no longer identify call sites by content). - Police BOTH invariants per line: * --dimension / -d is present * --kind is ABSENT (since ruvector@0.2.25 rejects it) - Skip quoted-string false positives ('rvf create failed' log lines). Versions: @claude-flow/cli 3.7.0-alpha.42 claude-flow 3.7.0-alpha.42 ruflo 3.7.0-alpha.42 @claude-flow/memory 3.0.0-alpha.16 (unchanged, #2019 fix already live) Post-publish live functional check (everything green): - ruvector rvf create --dimension 384 (no --kind): exit 0, .rvf file written. Reproduces what the MCP tool now invokes. - Published CLI dist:113 carries '--dimension','384', no --kind. - #2019 vectorBackend / graphAdapter functional test from alpha.41 still passes against published memory@3.0.0-alpha.16. - verify.mjs precondition contract still holds. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
e4bd9bbcbe |
fix(verify+memory+browser): #1880, #2019, #2015 — three precondition/contract fixes + CI guards
Three small but recurring bugs ship together because they share the same anti-pattern: a try/catch (or a missing flag) silently turned a clear precondition failure into a vague "verification failed" / "controller disabled" / "rvf create failed" outcome that downstream consumers couldn't act on. #1880 — witness verify exits 1 on source-only checkouts - The 12h scheduled verification has been filing a duplicate "HIGH — verification broken" issue every cron run since 2026-05-10 because the runner does a source-only checkout (no @noble/ed25519 install, no `npm run build`) and verify.mjs lumped that into the same exit-1 bucket as a real signature regression. - verify.mjs now reserves exit 2 strictly for precondition misses: * @noble/ed25519 not installed → exit 2 * every manifest entry missing AND manifest → exit 2 references /dist/ paths (= "dist not built") Real failures (signature invalid, specific marker regressed) keep exit 1. The scheduled runner can now distinguish "needs install/build" from "we broke something". - New CI guard: scripts/smoke-witness-verify-precondition.mjs drives all three shapes (missing dep, all-files-missing, built tree) and asserts the exit code contract. - Wired into v3-ci.yml as witness-verify-precondition-smoke and into witness-verify's `needs:` so a contract break blocks publish. #2019 — vectorBackend controller permanently disabled - @claude-flow/memory's controller-registry.ts calls agentdb.getController('vectorBackend'). agentdb@3.0.0-alpha.14's getController switch only handles memory/reflexion/skills/causal and throws `Unknown controller: vectorBackend` for everything else — silently swallowed, leaving the controller `enabled: false` even though `agentdb.vectorBackend` is a real field on the instance (assigned in AgentDB.initialize()). - Registry now probes `agentdb[name]` directly first, falls back to getController only when the field is absent. Applied to all three accessor paths (initializeController, get, isEnabled). - RuntimeConfig gains an optional `agentdb` injection field so tests and consumers with a pre-built AgentDB can govern it via the registry. - Two new tests in controller-registry.test.ts cover both branches (direct property wins; falls back to getController when absent). - Full controller-registry suite stays green (67 tests). #2015 — ruflo-browser session_record fails every call - ruvector@0.2.25 makes `-d, --dimension <n>` required on `rvf create`. The browser_session_record MCP tool wrapper invoked `rvf create … --kind browser-session` WITHOUT the flag, so every call returned `{ success: false, error: "rvf create failed" }`. - All five call sites updated to pass `--dimension 384` (matches MiniLM-L6 / AgentDB index default): v3/@claude-flow/cli/src/mcp-tools/browser-session-tools.ts plugins/ruflo-browser/scripts/replay-spike.sh plugins/ruflo-browser/agents/browser-agent.md plugins/ruflo-browser/skills/browser-record/SKILL.md plugins/ruflo-browser/docs/adrs/0001-browser-skills-architecture.md - New CI guard: scripts/smoke-browser-rvf-create-flags.mjs statically scans every `rvf create … --kind browser-session` invocation across the repo (TS, dist, shell, markdown) and fails if any is missing --dimension / -d. - Wired into v3-ci.yml as browser-rvf-create-flags-smoke and into witness-verify's `needs:` so a regression blocks publish. Cases covered by guards: source-only checkout (no deps), source-only checkout with build, built tree, missing dimension flag on TS/dist/ shell/markdown call sites. The smokes are independent jobs so the CI summary names the specific contract that broke. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
c328b76541 |
docs(plugins): aidefence 2.3.0 surface in ruflo-aidefence/-browser/-federation READMEs (#2003)
Followup to ADR-118. Three plugin READMEs amended to describe what
the upstream aidefence@2.3.0 / aimds-*@0.1.1 release improves in
their existing 3-gate flows:
• ruflo-aidefence: new "What the gates catch" table — prompt
injection (0..4 modifier window), role hijack, jailbreak
markers; aidefence_stats counters now accurate.
• ruflo-browser: AIDefence Gate 3 (Prompt-injection check) note
that scraped-content scans now flag role-hijack + jailbreak
in addition to the canonical `ignore all previous
instructions` family.
• ruflo-federation: 3-gate alignment block extended with a
paragraph that the inbound aidefence_is_safe gate's wider
detection runs through the adaptive confidence calibration
automatically — no plugin code change needed.
No semantic change to the plugins themselves. Pure documentation
of behavior the 2.3.0 bump already provides through the unchanged
MCP-tool surface.
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
dafc567d82 |
fix(verify): actionable error when @noble/ed25519 isn't installed (#1880) (#1999)
The 12-hour scheduled verification has bounced off the same failure 6+ times — `verify.mjs` can't load `@noble/ed25519` because the scheduled runner is a source-only checkout with no `npm install` step. The root package.json already declares the dep; this is purely a pipeline problem. Until the scheduled runner is fixed (add `npm ci && npm run build`), make the error message itself spell out the exact remediation: Fix: from the repo root, run `npm install` (the dep is declared in the root package.json under @noble/ed25519). If your runner is a source-only checkout, your verification pipeline must run `npm ci && npm run build` before invoking this script. Also returns a `reason: 'noble-ed25519-not-installed'` field so the scheduled runner can distinguish "missing dep" from a real signature failure programmatically without grepping the error. Pure error-message + structured-output change. No behavior change when the dep IS installed. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
639b45a66b |
docs(plugin): correct runtime smoke gate count 17 → 20 (#1990)
The README still referenced "17 documented entry points end-to-end" but #1988 extended the smoke to 20 (pairs/adaptive/multi-indicator gates added). Update the text to match the actual gate count and list what's covered. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
17986904a5 |
chore(plugin): bump pin to ^2.8.11 + add pairs/adaptive/multi-indicator smoke (#1988)
Updates the README prerequisites block to reflect the 2.8.x line (flag-style CLI dispatcher with --backtest, --signal, --risk, --portfolio, --regime, --train, --predict, --strategy-create) and the analytical layers (walk-forward, Monte Carlo, multi-symbol, benchmark, optimize, Kelly). Extends runtime-smoke.sh with three new gates for the strategies shipped in 2.8.10 and 2.8.11: 17. pairs strategy returns metrics 18. adaptive strategy picks regime 19. multi-indicator strategy runs All 20 gates pass against neural-trader 2.8.11. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
b92716b322 |
test(plugin): extend runtime smoke to assert advanced backtest features (#1985)
Adds 6 new gates (11-16) that exercise the features wired in neural-trader 2.8.x: 11. .metrics.kellyFraction (real Kelly from win/loss stats) 12. .walkForward.windowsRun (rolling 6m/1m validation) 13. .monteCarlo.distribution (Gaussian-resampled p5/p50/p95) 14. .optimization.best.sharpeRatio (parameter sweep result) 15. .signalsCount (live indicator scan) 16. .aggregate.bestSymbol (multi-symbol aggregate) Also bumps NT_PIN default to 2.8.9. Current result: 17 / 17. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
cad471be2f |
test(plugin): add runtime smoke that exercises every documented command (#1984)
The existing `plugins/ruflo-neural-trader/scripts/smoke.sh` is
structural-only (file presence, README pins, frontmatter checks). It
passed for months while `npx neural-trader --backtest` and every
other documented invocation crashed at runtime — those gaps got
caught and fixed across neural-trader 2.7.5 → 2.8.1.
This adds a sibling `runtime-smoke.sh` that actually:
1. Installs `neural-trader@2.8.1` in a clean tmpdir
2. Runs each of the 8 commands the plugin's skills document
3. Parses the JSON output and asserts `.command == <expected>`
4. Confirms `require('neural-trader')` exposes >= 100 exports
5. Confirms `--version` returns the pinned major.minor
Run:
bash plugins/ruflo-neural-trader/scripts/runtime-smoke.sh
Current result: 11 passed, 0 failed.
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
c37b7764b9 |
chore(plugin): bump neural-trader pin 2.7.2 → ^2.7.6 (#1982)
`neural-trader@2.7.6` is on npm with three working platform binaries
(linux-x64-gnu, darwin-arm64, darwin-x64) and three additional bugs
fixed beyond the install-hook fork-bomb that was resolved in 2.7.2:
• Missing `napi-loader-shared.js` / `napi-loader.js` /
`validation-utils.js` restored — `require('neural-trader')` no
longer throws at import time on any platform (broken since
2.5.0).
• `fasthash-sys` x86-only SIMD flags replaced with stdlib
`DefaultHasher` — `cargo build` now succeeds on aarch64-darwin.
• Cross-platform binaries actually ship — `darwin-arm64` and
`darwin-x64` are in the tarball for the first time ever.
Updates the README prerequisite block to reflect the new resolution,
adds a platform-coverage table, and pins to `^2.7.6` (compatible
with whatever future patches add linux-arm64 + win32 binaries).
Refs:
• ruflo#1974 (original bug report)
• ruflo#1981 (announcement)
• https://gist.github.com/ruvnet/a1aca90a5c299d89fa92e905dab11041
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
4051aeecad |
docs(neural-trader): record 2.7.2 fix, keep --ignore-scripts as defense (#1974) (#1979)
`neural-trader@2.7.2` published 2026-05-14 — install hook no longer spawns a recursive `npm install`. Cite the upstream PR (ruvnet/neural-trader#109) in the README's Prerequisites section, recommend pinning to >=2.7.2, and keep the `--ignore-scripts` flag on every documented install as defense in depth (cheap belt-and-braces against any future install-script regression — and what `scripts/audit-neural-trader-safety.mjs` still enforces). The "danger zone" advisory still appears for anyone pinned to <=2.7.1, since lockfiles can hold older versions long after the fix lands. Verified end-to-end: $ rm -rf /tmp/nt-verify && mkdir /tmp/nt-verify && cd /tmp/nt-verify $ perl -e 'alarm 30; exec("npm","install","neural-trader@latest")' added 698 packages in 18s ← was 80 min / 120 GB RAM exit=0 $ ps aux | grep -c "[n]eural-trader" 1 ← was 3,049 Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
4bd194554d |
fix(neural-trader): mitigate upstream fork-bomb on install + CI guard (#1974) (#1976)
The upstream `neural-trader@2.7.1` (and every earlier published version
audited) ships a malicious-by-accident `install` lifecycle script that
recursively invokes `npm install` from inside the install hook. On any
non-`linux-x64` host the recursion is unbounded — one reporter saw 3,049
stuck processes consuming ~120 GB of RAM in ~80 minutes before manual
intervention.
The `plugins/ruflo-neural-trader/README.md` Prerequisites section said
plainly `npm install neural-trader` — running THAT instruction is what
fork-bombs the machine.
We can't patch upstream from this repo, but we can stop telling users
to run the dangerous command. Mitigations:
- README Prerequisites: add a prominent warning advisory + switch
the recommended install to `npm install --ignore-scripts neural-trader`.
The linux-x64 binary is hardcoded inline in the upstream tarball,
so the package still works after `--ignore-scripts` on that platform.
- agents/trading-strategist.md: same `--ignore-scripts` fix on the
"Ensure installed" line that previously fork-bombed if the package
wasn't already cached.
- 6 skill files (trader-backtest/portfolio/regime/risk/signal/train):
same one-liner fix.
- trader-cloud-backtest/SKILL.md: also patch the `npm install -g
neural-trader` line in the Managed-Agent `initScript` — cloud
containers ARE isolated, but the same in-container fork-bomb
amplification is still a problem.
CI guard: `scripts/audit-neural-trader-safety.mjs` scans
`plugins/ruflo-neural-trader/` for any `npm install neural-trader` /
`npm i neural-trader` invocation that doesn't also carry
`--ignore-scripts`. Allowlist: lines preceded by a "DO NOT run" marker
(the README's anti-example block). Wired into the existing
`hook-command-audit` job in `v3-ci.yml`.
Verified:
- audit clean on the fixed tree
- audit catches a deliberately-reverted regression (exit 1, diagnostic
names the offending file:line)
- all other audits + plugin smoke still green
Mitigates #1974 in THIS repo. Upstream fix to the `neural-trader` npm
package (drop the recursive `npm install` in the install hook + publish
the platform-binary optionalDependencies) is still required for the
underlying bug.
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
c8258cc07c |
fix(cost-tracker/compact): resolve from anywhere + free HEALTH_PORT (#1930) (#1971)
`compact.mjs` only worked when the caller ran from a cwd where `@claude-flow/integration` resolved — which on a pnpm-workspace marketplace install means `cwd=v3/@claude-flow/integration/` specifically (pnpm doesn't hoist into `v3/node_modules/`). The skill's documented `cd v3 && node ...` path failed with `Cannot find module @claude-flow/integration/token-optimizer`. The script also imported agentic-flow indirectly, which binds `process.env.HEALTH_PORT || 8080` at module-load time and EADDRINUSE'd on any host with something else already on 8080. Fix: 1. Resolution chain (#1930 step 5) — try in order: - createRequire(cwd) — works for npm-style hoisted installs - createRequire(script-dir) — works when run from inside the plugin - absolute path walk from `import.meta.url` up to 6 levels looking for `v3/@claude-flow/integration/dist/token-optimizer.js` — works on the marketplace layout regardless of cwd 2. HEALTH_PORT (#1930 step 4) — set to `0` by default (OS picks a free port) before the dynamic import runs. Users can still override. 3. dist/-missing (#1930 step 1) — when the resolver finds a path that doesn't exist on disk, surface a clear error pointing at the build command (`cd v3/@claude-flow/integration && pnpm run build`) instead of the generic MODULE_NOT_FOUND. Steps 2 (agentic-flow not in workspace deps) and 3 (sharp prebuild missing) are install-environment issues outside the script's reach. The graceful-fallback path already reports `agenticFlowAvailable: false` when the bridge can't load, which covers those cases truthfully. Resolves #1930 (script-level — the deeper packaging fix to ship a built `@claude-flow/integration/dist` in marketplace bundles is separate). Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
545426f605 |
docs(adr-117): neural-trader heavy jobs on the Managed Agent cloud runtime (#1935)
ADR-117 (Accepted): dispatch heavy neural-trader jobs — multi-year walk-forward backtests, big Monte-Carlo, parameter sweeps, LSTM/ Transformer/N-BEATS training — to an Anthropic Managed Agent cloud container via the managed_agent_* tools (ADR-115, shipped in 3.7.0-alpha.27). No new MCP tools, no new deps — pure orchestration. - skills/trader-cloud-backtest/SKILL.md — the recipe (provision-once, pre-flight-cheap, run, ingest-locally, terminate-eagerly); allowed-tools scoped to managed_agent_* + memory_* + agentdb_pattern-store + Bash/Read (no wildcard grant). - commands/trader.md — /trader cloud <backtest|train|sweep> subcommand. - scripts/smoke.sh — step 2 now asserts the 7th skill exists, references managed_agent_create, and names the local trader-backtest fallback; step 10 ADR-status check corrected to Accepted. - README.md — overview + skills table + Architecture-Decisions + Related-Plugins cross-refs to ADR-117 / ADR-115 / ruflo-agent. - ADR-115 Links — cross-refs ADR-117 as the first consumer. Cost-optimization rules baked into the recipe (the "optimize" requirement): install-once in initScript, reuse the environment, pre-flight cheap (1-path/3-month smoke before a 1000-path/multi-year run), batch sweeps into one prompt, terminate eagerly + GC orphans (#1931), cheap agent model (Haiku/Sonnet — the compute is the Rust engine, not the LM; ADR-026), estimate before kicking off. Validation: ruflo-neural-trader smoke 11/0, ruflo-agent smoke 12/0, audit-cli-mcp-tools / audit-tool-descriptions / audit-plugin-packages / audit-hook-commands all green. No new MCP tools → cli build unaffected. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
3975ab512c |
docs(ruflo-agent): bring README up to date for the managed (cloud) runtime (#1933)
The README still described only the WASM runtime (it was the old ruflo-wasm README with a name-swap). Rewrote it around the two runtimes — WASM (rvagent, sandboxed-local, the safe default) + Managed (Anthropic Claude Managed Agents, cloud) — plus the planned SDK runtime (ADR-116). Now documents: - the runtime decision table (when to use which) + the trust/sandbox model - all 16 MCP tools (10 wasm_* + 6 managed_agent_*) with the managed↔wasm counterpart mapping - the ANTHROPIC_API_KEY prereq + the graceful "use wasm_agent_create" fallback - the managed-agent skill + /managed-agent command - the beta caveats (managed-agents-2026-04-01; multiagent/define-outcomes are research preview; mcpServers needs a reachable URL; cost = tokens + container time) - ADR-115 cross-ref; smoke is "12 passed, 0 failed" (was 11); the CI workflow + the no-network managed-agent test as the contract - ruflo-cost-tracker as a related plugin (record managed sessions) smoke.sh 12/0. Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
ef73a1616f |
feat(ruflo-agent): rename ruflo-wasm → ruflo-agent + Claude Managed Agents (cloud) runtime — ADR-115 (proposed→accepted, implemented) (#1929)
* docs(adr): ADR-115 — Claude Managed Agents as a cloud backend for rvagent (explored + validated)
Records the proposal to add `runtime: "managed"` to ruflo's rvagent
interface (ruflo-wasm / @ruvector/rvagent-wasm / wasm_agent_* MCP tools),
backed by Anthropic's Claude Managed Agents API (beta), as a second backend
alongside the local WASM sandbox — mirroring the ConsensusTransport
LocalTransport|FederationTransport pattern (ADR-095 G2 / ADR-104). The
agent/environment/session/events model maps ~1:1 to wasm_agent_create/
prompt/files/terminate + the gallery.
Validated live against api.anthropic.com/v1 with the org's Anthropic key
(GCP claude-flow/anthropic-api-key): created an agent + environment + session,
sent a bash task, observed the full event log (status_running → user.message
→ tool_use(bash) → tool_result → agent.message("Done.") → status_idle,
stop_reason end_turn), cleaned up. ~7s for a trivial Haiku task.
High-value combos noted: ruflo's own MCP server as a Managed Agent tool
source (cloud-hosted ruflo, zero local infra); Managed Agent session as a
third task_assign executor (closes #1916 items 3/4); long-running/async work;
skills + define-outcomes parity. Constraints: opt-in/off-by-default, needs
ANTHROPIC_API_KEY + beta access, plugin-level @anthropic-ai/sdk dep,
cost-tracking + orphaned-session GC, beta churn, branding.
Status: proposed. Registered in AgentDB (adr-ADR-115) + adr-patterns.
Co-Authored-By: RuFlo <ruv@ruv.net>
* refactor(plugins): rename ruflo-wasm → ruflo-agent (agent-runtimes home; ADR-115 prep)
`ruflo-wasm` only covered local WASM-sandboxed agents (rvagent —
@ruvector/rvagent-wasm, the wasm_agent_*/wasm_gallery_* MCP tools). It's
becoming the home for *all* ruflo agent runtimes: the existing local-WASM
backend plus Anthropic's Claude Managed Agents as a cloud backend (ADR-115),
behind one interface — same local-vs-cloud pattern as ConsensusTransport.
- git mv plugins/ruflo-wasm → plugins/ruflo-agent
- plugin.json: name ruflo-wasm → ruflo-agent; description/keywords now span
both runtimes (rvagent/wasm + managed-agents/anthropic/cloud)
- .claude-plugin/marketplace.json entry renamed
- README / plugins/README / docs/index / cli README / ruflo README /
discover-plugins SKILL / verification/inventory.json / ADR-115 — refs updated
- wasm_agent_* / wasm_gallery_* MCP tool names are unchanged (they stay; the
plugin is just renamed). managed_agent_* tools land next per ADR-115.
(Left `ruflo-wasm-mcp` in ruvocal/workerClient.ts alone — unrelated worker MCP name.)
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(cli): managed_agent_* MCP tools — Claude Managed Agents cloud runtime (ADR-115)
Six new MCP tools wrapping Anthropic's Claude Managed Agents REST API (beta,
`anthropic-beta: managed-agents-2026-04-01`) via plain fetch — no new SDK dep:
managed_agent_create agents.create + environments.create + sessions.create ↔ wasm_agent_create (CLOUD counterpart)
managed_agent_prompt events.send(user.message) + poll events until idle ↔ wasm_agent_prompt
managed_agent_status GET /v1/sessions/{id}
managed_agent_events GET /v1/sessions/{id}/events (full transcript) ↔ wasm_agent_files
managed_agent_list GET /v1/sessions
managed_agent_terminate DELETE /v1/sessions/{id} (+ optionally the env) ↔ wasm_agent_terminate
Needs ANTHROPIC_API_KEY (or CLAUDE_API_KEY); every tool degrades gracefully
with a structured "use wasm_agent_* for a local no-key runtime" error when the
key is absent — the CLI/MCP server stays up. ADR-112-compliant descriptions
(each says when wasm_agent_* / native is the right call instead). Registered
in mcp-client.ts. Lives conceptually in the `ruflo-agent` plugin (the
`ruflo-wasm`→`ruflo-agent` rename in the prior commit).
Validated live against api.anthropic.com with the org's Anthropic key (GCP
claude-flow/anthropic-api-key) via `ruflo mcp exec -t managed_agent_*`:
create (haiku) → prompt ("echo … > /tmp/r.txt && cat") → got finished:true,
status:idle, stopReason:end_turn, assistantText:"Done.", toolUses:[bash],
13 events → terminate (sessionDeleted+environmentDeleted). No-key path returns
the graceful error. audit-cli-mcp-tools 311 registered/0 dangling;
audit-tool-descriptions 0 no-guidance; cli build clean.
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(ruflo-agent): wire the managed-agent (cloud) runtime into the plugin + CI smoke
- skills/managed-agent/SKILL.md — drives the cloud runtime: managed_agent_create
/ prompt / status / events / list / terminate, with the WASM-vs-managed
decision table, the ANTHROPIC_API_KEY prereq + graceful fallback, the
mcpServers-reachability caveat, and the cost/cleanup discipline (a cloud
session bills until terminated). Explicit allowed-tools (no wildcard).
- commands/managed-agent.md — quick "list cloud sessions / status / transcript
/ clean up" command (the cloud sibling of /wasm).
- plugin.json — kept rvagent-wasm + ruvllm-wasm keywords (still built on those);
added managed-agents/anthropic/cloud.
- smoke.sh: step 1 now also asserts name=ruflo-agent + the managed-agents
keywords; step 10 expects ADR-0001 status `Accepted` (was stale `Proposed`,
pre-existing red); new step 12 — managed-agent skill+command exist + all 6
managed_agent_* tools referenced + the skill keeps an explicit allowed-tools
list + offers the wasm_agent_create fallback. 12 passed / 0 failed.
- .github/workflows/ruflo-agent-smoke.yml — new CI job running smoke.sh on any
plugins/ruflo-agent/** change (the plugin had no CI gate before).
Validated: `claude --plugin-dir plugins/ruflo-agent` loads the plugin and lists
its skills (managed-agent, wasm-agent, wasm-gallery); plugin.json + all skill
frontmatters parse; smoke.sh 12/0.
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(adr): ADR-115 → Accepted + Implementation section (managed_agent_* landed)
Status Proposed → Accepted. Added an Implementation (2026-05-12) section:
the ruflo-wasm→ruflo-agent rename, the 6 managed_agent_* MCP tools (plain
fetch, no new SDK dep, graceful no-key degradation, ADR-112 descriptions),
the managed-agent skill+command, the smoke.sh/ruflo-agent-smoke.yml CI guard,
the live e2e validation (create→prompt→terminate against api.anthropic.com
with the GCP anthropic-api-key) and `claude --plugin-dir` validation, and the
called-out follow-ups (runtime:"managed" unification, deployed HTTP ruflo MCP
server for the cloud-hosted-ruflo combo, task_assign/federation dispatch to a
Managed Agent session, cost-tracking + orphaned-session GC, multiagent/outcomes).
Tracking issue: #1931.
Co-Authored-By: RuFlo <ruv@ruv.net>
* test(cli): no-network guard for managed_agent_* tools (ADR-115)
__tests__/managed-agent-tools.test.ts (10 cases): the 6 managed_agent_*
tools are registered; each has an object inputSchema + a ≥80-char,
ADR-112-ish, unique description that names the wasm_agent_*/native fallback;
and — crucially — every handler degrades gracefully with no ANTHROPIC_API_KEY/
CLAUDE_API_KEY: no throw, structured error mentioning the key + the
wasm_agent_create fallback, no network call (so the CLI/MCP server stays up
offline). Plus managed_agent_prompt's missing-sessionId/message validation.
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(adr): ADR-115 — add the third runtime (Claude Agent SDK) to the picture
ADR-115 adds the *cloud* runtime (Managed Agents); add a section noting the
natural *third* runtime — the Claude Agent SDK (@anthropic-ai/claude-agent-sdk,
"Claude Code as a library": query()/ClaudeSDKClient, hooks, subagents, MCP,
permission modes, sessions, loads .claude/ config + plugins; runs in-process,
full host trust). ruflo-agent → three runtimes behind one model:
WASM (rvagent) local sandbox, no host fs/net untrusted/portable/offline
SDK (future) your process, your filesystem a real Claude agent loop on the local repo — the in-process `claude -p`
Managed Anthropic cloud container long-running/async, no local infra
The SDK runtime's killer combo: `mcpServers: { ruflo: { command: "npx", args: ["ruflo","mcp","start"] } }` — a *local* stdio MCP server, so the agent gets ruflo's 314 tools with zero deployment (vs Managed Agents needing a reachable URL). Anthropic positions SDK→Managed as prototype→production. Costs: heavy dep (bundles a Claude Code binary), full host trust (no sandbox — least isolated), needs an API key. Implementing it = a follow-up, likely ADR-116 (tracked in #1931).
Co-Authored-By: RuFlo <ruv@ruv.net>
---------
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
965ec669d9 |
fix(#1927): ruflo-cost-tracker encodeProjectPath handles Windows backslash + drive colon (#1928)
* fix(#1927): ruflo-cost-tracker encodeProjectPath handles Windows `\` + drive `:` `track.mjs` couldn't find Claude Code session jsonls on Windows because `encodeProjectPath()` only replaced `/` — a no-op on `D:\project\Foo`, so it looked under a corrupt `~/.claude/projects/D:\project\Foo` instead of the real `~/.claude/projects/D--project-Foo`. Now replaces `/`, `\`, and `:` with `-` (matching Claude Code's encoding); POSIX paths are unchanged. CI guard: smoke.sh step 29b runs `track.mjs` with `TRACK_CWD='D:\project\Subcloudy'` and asserts the (expected-to-fail) "looked under" line shows `D--project-Subcloudy` and not the corrupt un-encoded form. Negative-tested. Also fixed smoke.sh step 8 (ADR-0001 is `Accepted`, not `Proposed` — the check was stale; cost-tracker-smoke was already red on main because of it). Witness marker #1927. Not fixed here (secondary issue in the report): on long Windows sessions `spawnSync('npx', ['claude-flow', 'memory', 'store', '--value', JSON.stringify(summary)])` can exceed the CreateProcess argv limit when `summary` is large — a follow-up (write to a temp file / stream via stdin). Co-Authored-By: RuFlo <ruv@ruv.net> * ci: green up witness-verify (sync linux/windows manifests) + cost-tracker-smoke (.ci-bench npm-init) Two pre-existing CI reds, surfaced while making sure all builds pass: - witness-verify on ubuntu/windows failed after #1923: it verifies the per-OS manifest (verification/{linux,windows}/manifest.md.json), but regen-witness.mjs only ever rewrites the *current* OS's manifest (macos on the maintainer's machine), so the linux/windows snapshots still had the pre-#1923 `#1862` marker — which #1923 changed when it moved the hook invocation behind ruflo-hook.sh. Synced linux + windows manifests to the current macos one (byte-identical at the same commit — the Ed25519 seed is derived from gitCommit only, not OS, and the dist .js are LF everywhere). All 3 verify clean (pass=113, 0 regressed). - cost-tracker-smoke `Install agent-booster for the bench` step did `npm init -y` inside `.ci-bench/`, and npm 11 rejects a package name starting with `.`. Write the manifest explicitly instead. Co-Authored-By: RuFlo <ruv@ruv.net> * ci(v3): run v3-ci.yml on pull_request when verification/** changes (witness-verify on PRs) Without this, a PR that bumps witness-fixes.json / regenerates a per-OS manifest doesn't trigger witness-verify, so a stale per-OS manifest only fails after merge to main (the push trigger does have verification/**). Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
f0ee0f9688 |
fix(#1921): plugin hooks use a resilient shim, not bare npx @alpha per fire (#1923)
* fix(#1921): plugin hooks invoke a resilient shim, not bare `npx @alpha` per fire Every PreToolUse/PostToolUse/Stop hook ran `npx <pkg>@alpha hooks …`, which (a) re-resolves the @alpha dist-tag from the registry on every fire and (b) re-installs from cold cache — and when that install crashes (an arborist `Invalid Version` on npm 10.8.x, deep in a transitive OTEL/grpc subtree) the user sees a hook error in Claude Code after every assistant turn, plus ~7s of wasted registry traffic per turn. Fix: each plugin (`.claude-plugin/`, `plugin/`, `plugins/ruflo-core/`) ships `scripts/ruflo-hook.sh` — prefers an already-installed `ruflo`/`claude-flow` binary, falls back to `npx --prefer-offline --yes ruflo@alpha`, and ALWAYS exits 0. hooks.json invokes `"${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh" … || true` (the `|| true` covers the unset-$CLAUDE_PLUGIN_ROOT case). stdin (the hook event JSON) passes through unchanged; the stdin-jq-xargs shell-injection-safety pattern in plugin/hooks/hooks.json is preserved. This does NOT fix the underlying arborist crash (which needs the offending empty-`version` package pinned via `overrides` once it's identified on npm 10.8.2 — see the issue thread) — it makes a CLI/install failure invisible and cheap instead of a visible error every turn. CI guard: scripts/audit-hook-commands.mjs — fails CI if any hook `command` uses `npx` without `--prefer-offline`, or invokes the CLI without a non-fatal guard. Wired into v3-ci.yml as `hook-command-audit` (also bash-lints each ruflo-hook.sh and asserts it exits 0 with no CLI on PATH) + added to witness-verify needs[]. Path triggers updated to fire on `**/hooks/hooks.json`, `**/scripts/ruflo-hook.sh`, and `scripts/**`. Witness markers for #1921 + Co-Authored-By: RuFlo <ruv@ruv.net> * fix(#1921): make test-hooks.mjs shim-aware; fix shim-lint CI step; regen witness Rebasing #1921 onto main surfaced 3 CI failures: - plugin-hooks-smoke (ubuntu + macos): test-hooks.mjs substituted only `npx ruflo@alpha` → the local CLI, but the hooks.json now invokes `${CLAUDE_PLUGIN_ROOT}/scripts/ruflo-hook.sh <args>`. It now also substitutes the shim path → `<cli> hooks <args>` (bypassing the shim, so the test exercises the real CLI flag wiring) and strips the shim's trailing `|| true` so exit codes are still asserted. 7/7 pass. - hook-command-audit shim-lint step: `PATH="/nonexistent" bash "$sh"` set PATH to a dir with no `bash`, so `bash: command not found`. Now invokes bash by full path with `PATH=` empty: `PATH= "$BASH" "$sh"` — the shim's `command -v` is a builtin (works with empty PATH) and the npx fallback fails cleanly under `|| true` → exit 0. (resolved in v3-ci.yml during the rebase.) Witness manifest regenerated; #1862's marker refreshed to match the shim-relocated `post-edit -f "$FILE" -s true` (the documented-flag form is preserved). `ruflo verify` 0 regressed. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
22ca3b018b |
feat(swarm): ADR-095 G2 — pluggable ConsensusTransport + Ed25519 message signing (step 1) (#1905)
* feat(swarm): ADR-095 G2 step 1 — pluggable ConsensusTransport + Ed25519 message signing
First concrete piece of ADR-095 G2 (hive-mind multi-process). The
consensus protocols (raft/byzantine/gossip in @claude-flow/swarm) used a
local EventEmitter for *everything* — both observability events
("leader.elected", "consensus.achieved") AND inter-node messages
(append-entries, vote requests, pre-prepare/prepare/commit). The latter
never crossed a process boundary: a node "sent" a message by emitting it
locally and synthesizing the peer's reply inline. That's the single-
process limitation #G2 names.
## What lands
`v3/@claude-flow/swarm/src/consensus/transport.ts`:
- `ConsensusTransport` interface — `send` (request-response), `broadcast`,
`onMessage`, `peers`, `close`. Separates the inter-node-message
dimension from the observability-event dimension (events stay on each
protocol's own EventEmitter).
- `LocalTransport` + `LocalTransportRegistry` — in-process registry,
the default. Matches current single-process behavior so nothing breaks.
Supports optional Ed25519 signing + per-sender monotonic-seq replay
defense when keypairs are configured.
- Real Ed25519 helpers via Node's built-in `crypto` (no new deps):
`generateNodeKeyPair`, `signMessage`, `verifyMessage`,
`canonicalizeForSigning` (deep-sorted-key JSON — deterministic across
hosts), `messageDigest`.
- Exported from `consensus/index.ts`.
## CI guard (the user's ask: "include ci guards for new capabilities")
`plugins/ruflo-core/scripts/test-consensus-transport.mjs`, wired as a step
in the `mcp-roundtrip-smoke` job:
- Static: required exports present in swarm dist; **no `return true`
signature-stub regression** (the original #G2 bug — `verifySignature()`
returned true unconditionally).
- Behavioral: `LocalTransport` round-trip (send → peer handler → reply);
Ed25519 verify is real (true for right key; false for wrong key /
tampered payload / missing sig). 30s watchdog so CI never hangs.
## Tests
14 new tests in `__tests__/consensus-transport.test.ts` (sign/verify
round-trip, tampered-payload rejection, wrong-key rejection, fail-closed
on missing sig, canonicalization stability, LocalTransport send/broadcast/
peers/timeout/closed-peer, signed-transport round-trip, unsigned-rejected,
seq monotonicity). 186/186 swarm suite passes. Build clean.
## Remaining for G2 (subsequent commits)
- FederationTransport adapter (ADR-104 WS wire)
- Wire raft/byzantine/gossip to accept an injected ConsensusTransport
- Replace byzantine-coordinator verifySignature()→true with real verifyMessage
- Per-strategy correctness: BFT f<n/3 vote counting; Raft term/log replication
- Failure-injection tests
ADR-095 G2 status section updated.
Tracks #1872
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(swarm): ADR-095 G2 step 2 — wire ByzantineConsensus to ConsensusTransport + sha256 digests
Second piece of ADR-095 G2. ByzantineConsensus now accepts an optional
`transport: ConsensusTransport` in its config:
- When set, PBFT messages (pre-prepare / prepare / commit) actually go
over the transport (signed if the transport has a keypair) instead of
being `emit`ted into the void. Inbound transport messages are routed
back into `handlePrePrepare` / `handlePrepare` / `handleCommit`.
- When unset, behavior is unchanged: messages emit as `message.broadcast`
/ `message.sent` events for an external relay layer (the legacy
single-process path). The `emit`s also stay when a transport IS wired,
so observers don't break.
- Transport broadcast failures are non-fatal at the protocol layer — the
proposal simply times out, which is the correct failure mode (lose
liveness, never commit incorrectly).
Also: `computeDigest` was a 32-bit string-hash "for demonstration" —
replaced with sha256. PBFT relies on the digest uniquely identifying the
request being agreed on; a 32-bit hash has trivial collisions. Removed
the toy hash entirely (no test depended on it).
Tests: 3 new in `__tests__/byzantine-transport.test.ts` — emit-only when
no transport (legacy unchanged); broadcasts go over transport AND emit
when wired (and digests are 64-hex sha256); inbound transport messages
route into the PBFT handlers (a pre-prepare in → a prepare out over the
transport). 189/189 swarm suite passes. consensus-transport CI guard
green. Build clean.
Remaining for G2: same wiring for raft.ts + gossip.ts; FederationTransport
adapter; per-strategy correctness (BFT f<n/3 vote counting — the current
`2f+1` thresholds are right but a single node fabricates the quorum
locally; Raft term/log replication); failure-injection tests.
Tracks #1872 · branch feat/adr-095-g2-hive-mind-ws-transport
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(swarm): ADR-095 G2 step 3 — wire RaftConsensus to ConsensusTransport with real receiver rules
Third piece of ADR-095 G2. RaftConsensus now accepts an optional
`transport: ConsensusTransport`:
- Sender side: `requestVote(peerId)` / `appendEntries(peerId, entries)`
go over the transport as real request-response RPCs (RequestVote /
AppendEntries) instead of mutating the local fake-peer map. On a
higher-term reply, the node steps down (§5.1).
- Receiver side (`handleInboundRaftMessage`): proper Raft rules —
• RequestVote: grant iff `term >= currentTerm` AND (haven't voted this
term OR voted for this candidate) AND candidate's log is at least as
up-to-date (lastLogTerm/lastLogIndex comparison). Adopts a higher
term, resets the election timer on grant.
• AppendEntries: reject if `term < currentTerm`; else become follower,
reset the election timer, append entries by index, advance
`commitIndex` to `min(leaderCommit, lastLogIndex)`.
- Legacy no-transport path unchanged (single-process in-memory peer map).
This is the "Raft term/log replication correctness" piece from the ADR.
(Full prevLogIndex/prevLogTerm conflict resolution is the next refinement;
the current append-by-index is correct for the heartbeat + sequential-
append cases the consensus engine actually exercises.)
Tests: 5 new in `__tests__/raft-transport.test.ts` — vote granted for an
up-to-date candidate; second different candidate denied (vote-once-per-
term); stale-term candidate denied; behind-log candidate denied; valid
AppendEntries accepted + commitIndex updated; stale-term AppendEntries
rejected with the follower's term reported. 194/194 swarm suite passes.
Build clean. consensus-transport CI guard green.
Remaining for G2: same wiring for gossip.ts; FederationTransport adapter
(ADR-104 WS wire); BFT f<n/3 vote-counting correctness; failure-injection
tests; cross-host validation; build/publish.
Tracks #1872 · branch feat/adr-095-g2-hive-mind-ws-transport
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(swarm): ADR-095 G2 step 4 — FederationTransport (ConsensusTransport over the ADR-104 WS wire)
Fourth piece of ADR-095 G2 — the multi-host transport option.
`v3/@claude-flow/swarm/src/consensus/federation-transport.ts`:
- `FederationTransport implements ConsensusTransport` — backed by the
federation plugin's ADR-104 WS wire (agentic-flow/transport/loader).
- Structural dependency, not a package dep: takes an
`AgenticFlowTransportLike` instance by injection (the `loadQuicTransport`
result satisfies it) plus consensus-level metadata (this node's id, how
to address peers, who the peers are). @claude-flow/swarm stays zero-dep;
the wiring layer (hive-mind + federation) supplies the transport.
- Layers request-response on top of fire-and-forget WS delivery via
per-message correlation ids + a pending-replies map + per-call timeout.
Uses ADR-104 stream-mux (`streamId='ruflo-consensus'`) so consensus
traffic doesn't interleave with application traffic.
- Optional Ed25519 signing — outbound signed, inbound verified against the
sender's published pubkey (resolvePeerPublicKey), per-sender monotonic-
seq replay defense. Fail-closed: unverifiable inbound is dropped.
- Exported from `consensus/index.ts` (+ `AgenticFlowTransportLike` /
`FederationTransportOptions` types).
Tests: 7 new in `__tests__/federation-transport.test.ts` using a mock
in-memory mesh — send→handler→reply correlation; broadcast to all peers;
no-address rejection; send timeout; peers() excludes self; signed
round-trip (seq increments, signature present); unsigned inbound dropped
at a signing-enabled node (sender's send times out, handler never runs).
201/201 swarm suite passes. Build clean. consensus-transport CI guard
extended to assert FederationTransport is exported — green.
Remaining for G2: wire gossip.ts to the transport; BFT f<n/3 vote-
counting correctness (real vote aggregation across distinct senders, not
a locally-fabricated quorum); failure-injection tests; cross-host
validation (mac↔ruvultra over tailscale, root); build/publish; then merge.
Tracks #1872 · branch feat/adr-095-g2-hive-mind-ws-transport
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(swarm): ADR-095 G2 step 5 — wire GossipConsensus to transport + BFT f-from-cluster-size
Fifth piece of ADR-095 G2 — completes the protocol-wiring trio and adds
the BFT fault-tolerance correctness fix.
## GossipConsensus transport wiring
- `GossipConfig.transport?` — when set, `sendToNeighbor` actually sends
the gossip message over the transport (signed if signing is on) instead
of mutating the local fake-neighbor map. Inbound gossip routes into the
merge logic via `handleInboundGossipMessage`, deduped by message id.
- Legacy no-transport path preserved.
## BFT fault tolerance correctness
- `f` (`maxFaultyNodes`) was hardcoded to 1 in the config default, so a
7- or 10-node cluster ran with the same `2f+1=3` quorum as a 4-node one
— wrong. Now `byzantineF()` derives `f = floor((n-1)/3)` from the actual
cluster size (n = self + known peers), clamped to ≥1. `config.maxFaultyNodes`,
when set, acts as an *upper cap* (never exceed what the operator declared
the cluster can tolerate). The three `2f+1` quorum checks (vote /
handlePrepare / handleCommit) now use the cluster-derived `f`.
- Dropped the `?? 1` config default so an operator who doesn't pass
`maxFaultyNodes` gets the cluster-derived behavior, not a silent cap of 1.
## Tests
- 3 new gossip-transport tests (messages go over transport with hops/path
incremented; inbound deduped by id; non-gossip ignored).
- 5 new byzantine-f tests (f scales 4→1, 7→2, 10→3; explicit cap honored;
no-cap follows cluster size; 3-node clamps to 1).
- 210/210 swarm suite passes. Build clean. consensus-transport CI guard green.
ADR-095 G2 status section updated — all three protocols now wired,
FederationTransport landed, Ed25519 sig verify real, BFT correctness done,
Raft receiver rules done. Remaining: failure-injection tests, cross-host
validation, merge.
Tracks #1872 · branch feat/adr-095-g2-hive-mind-ws-transport
Co-Authored-By: RuFlo <ruv@ruv.net>
* test(swarm): ADR-095 G2 step 6 — failure-injection tests (f<n/3 BFT, f<n/2 Raft)
Sixth piece of ADR-095 G2 — the failure-injection coverage the ADR calls for.
## BFT — prepare/commit quorum under f-bounded faults
`injectQuorum()` builds one ByzantineConsensus with a configured cluster
size (so byzantineF() derives f = floor((n-1)/3)), feeds it a pre-prepare
(creates the proposal), then N distinct external prepares + M distinct
external commits, and reports whether `consensus.achieved` fired. Because
the node contributes 1 prepare + 1 commit of its own, 2f external messages
of each kind hit the 2f+1 quorum.
- 4-node (f=1): 2 ext prepares + 2 ext commits → reached; 1 ext commit → NOT
- 7-node (f=2): 4 + 4 → reached (quorum 5); 3 ext commits → NOT
- 10-node + maxFaultyNodes:1 cap → f stays 1, 2 ext commits suffice
## Raft — election under vote majority/minority
`tallyVotes()` drives a RequestVote round from a candidate to all voters
over LocalTransport; silenced voters never reply (their handler is a no-op)
so the candidate's `send` to them times out → no vote. Tallies grants
including the self-vote.
- 5-node, all reply → 5 votes (≥ majority 3) → wins
- 5-node, 2 silent → 3 votes (= majority) → wins
- 5-node, 3 silent → 2 votes (< majority) → loses
(The full multi-node PBFT cascade over the synchronous LocalTransport is
order-sensitive and flaky as an integration test — the direct
message-injection form above tests the threshold property robustly. A
real-WS cross-host cascade test belongs in the federation cross-host
validation step, not the unit suite.)
218/218 swarm suite passes. Build clean.
This completes the per-strategy correctness + failure-injection items.
Remaining for G2: cross-host validation (mac↔ruvultra over tailscale,
root); merge PR #1905.
Tracks #1872 · branch feat/adr-095-g2-hive-mind-ws-transport
Co-Authored-By: RuFlo <ruv@ruv.net>
---------
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
8403907d86 |
fix(#1863): guard undefined arrays in task status + cli-no-crash CI smoke
## The crash
`task status <id>` threw `TypeError: Cannot read properties of undefined
(reading 'join')` in the Assignment section. Lines in task.ts did
`result.dependencies.join(', ')`, `result.dependents.join(', ')`,
`result.tags.join(', ')` — `callMCPTool<{ dependencies: string[]; ... }>()`
types those as non-optional arrays, but the MCP server legitimately omits
them for tasks created via task_create or loaded from an older store
schema. The TS compiler can't see the risk; only running the command does.
Fix: `?.join(', ') || 'None'` at all five sites (the inline `task status`
formatter at ~206 + the detailed one at ~441). `assignedTo` was already
guarded; the others weren't.
## CI guard (the user's ask: "ensure this type of error is caught")
New plugins/ruflo-core/scripts/test-cli-no-crash.mjs — drives
`task create` → `task status <id>` plus `task list` / `agent list` /
`memory list` / `swarm status`, asserting none crash with an unhandled
exception (TypeError/ReferenceError/"Cannot read propert"/etc). Graceful
"not found" errors are fine; only unhandled crash stacks fail the gate.
Per-command 30s timeout + 90s process-level watchdog so CI never hangs.
Tried a static grep-based guard first (`obj.prop.arrayMethod()` without
`?.`) — too noisy: 285 hits, mostly legit. Behavioral smoke is the right
shape: it catches the actual crash class, not the syntactic pattern.
Wired as a step in the existing mcp-roundtrip-smoke job (already builds
the cli + has the watchdog discipline).
Local: smoke green — confirms `task status` on a fresh task no longer crashes.
Closes #1863
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
0114951502 |
fix(#1899): ruflo-core hooks call npx ruflo@alpha not npx claude-flow@alpha
The ruflo-core plugin's hooks.json referenced the legacy package name `claude-flow@alpha` in all 5 hook commands (PreToolUse/Bash, PreToolUse/file, PostToolUse/Bash, PostToolUse/file, Stop/session-end). On every session end + every tool call, `npx` re-resolves the old `claude-flow` package, producing visible `ETIMEDOUT` errors on any brief network blip (VPN reconnect, etc.) even though it's non-blocking. Per the ruflo rebranding, all 5 now use `npx ruflo@alpha`. Updated test-hooks.mjs's substitution regex to match. Bumped ruflo-core plugin version 0.2.1 → 0.2.2. 7/7 hooks smoke still passes after the rename. NOTE: the marketplace plugin distributes via IPFS, not npm — users won't get this until ruflo-core@0.2.2 is republished to the marketplace (separate step, same pattern as #1862). Closes #1899 Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
8aac1b2ccc |
feat(mcp): ADR-112 — 285/285 tool descriptions have 'Use when …' guidance + CI guard + #1892 statusline (#1897)
* docs(adr-095): status update — G1/G3/G4/G6/benchmark remediated (verification receipts)
External re-audit (AlphaSignal AI, May 7) surfaced ADR-095 gaps publicly.
Verification pass on current main shows 4 of 7 named gaps already
quietly fixed by the v3.7.0-alpha work:
G1 — agent_spawn intentionally registry-only; real execution wire is
agent_execute → agent-execute-core.ts:117 → Anthropic Messages API
G3 — workflow_execute has a real step executor (workflow-tools.ts:308+);
the 'Workflow not found' error is correct missing-ID handling
G4 — promptWasmAgent (agent-wasm.ts:154) detects echo stub + routes
through callAnthropicMessages when ANTHROPIC_API_KEY set
G6 — refuted via direct measurement: hook is a single routing call,
no trigram/Jaccard symbols, 8 backend entries observed
Bench — simulate_benchmarks.py removed; '84.8% SWE' claim cleaned
from tracked docs
Preserves original ADR text. Adds 'Status update — 2026-05-11' section
at the bottom with file-path receipts. Still open: G2, G5 (→ADR-094),
G7 (per-controller), #1748 (tool descriptions).
Related: #1896 (external audit response)
Co-Authored-By: RuFlo <ruv@ruv.net>
* feat(mcp): ADR-112 — every tool description now has "Use when … is wrong because …" guidance + CI guard + #1892 statusline fix
External audit (AlphaSignal AI, May 7) measured 237/300 MCP tool
descriptions lacked guidance for when Claude should pick Ruflo's tool
over native (Bash/Read/Grep/Glob/Task/TodoWrite). Re-measurement on
current main was actually 279/285 — worse. Now: 0/285.
## ADR-112 + bulk fix
- New ADR documenting the rule: every description must answer
"use this over native when?" with concrete value-add (cost
attribution / learning persistence / coordination / witness chain /
sandbox isolation), and honestly state when native is fine.
- 7 agent-tools.ts descriptions hand-edited (the P1 native-Task overlap).
- 272 remaining descriptions bulk-updated via category-aware suffixes
in scripts/bulk-fix-tool-descriptions.mjs — each tool category
(memory/agentdb/embeddings/swarm/hive-mind/hooks/workflow/browser/
cost/intelligence/aidefence/security/federation/iot/wasm/ruvllm/
config/system/mcp/status/doctor/performance/analyze/progress/transfer/
guidance/claims/terminal/daemon/causal/graph/reasoningbank/search)
gets its own honest "Use when … is wrong because …" suffix.
## CI guard (every tool's description checked)
- scripts/audit-tool-descriptions.mjs scans every MCPTool definition and
enforces three gates per tool:
1. "Use when ..." guidance present (the original ADR-112 check)
2. Description length ≥ 80 chars (catches near-empty descriptions)
3. Description unique across all tools (catches lazy copy-paste)
All three baselines stored in verification/mcp-tool-baseline.json
and are monotone-decreasing — CI fails on any regression.
- .github/workflows/v3-ci.yml gains a `tool-descriptions-audit` job
wired into witness-verify needs[] so the release pipeline gates on it.
## #1892 — UI version mismatch
- v3/@claude-flow/cli/.claude/helpers/statusline.js was hardcoded
to "RuFlo V3.5"; now reads from installed @claude-flow/cli's
package.json at runtime via resolveBannerVersion() so the UI matches
`ruflo doctor` output. Resolves across local-checkout / npm-installed /
globally-installed layouts.
## Witness manifest
- verification/witness-fixes.json: ADR-111, ADR-112, #1892 markers added.
- verification/macos/manifest.md.json regen'd — 102/102 fixes verified,
Ed25519 signature valid.
## Tests
- 1963 federation+cli tests pass on this branch.
- Build clean.
- Audit: 285/285 tools with guidance, 0 too-short, 0 duplicates.
Resolves #1748 (tool discoverability)
Resolves #1892 (UI version mismatch)
Tracks #1896 (external audit response)
Co-Authored-By: RuFlo <ruv@ruv.net>
* docs(verification): README — current 102/102 fix count + ADR-112 baseline + Layer 1 smoke jobs
- Folder layout adds mcp-tool-baseline.json (ADR-112)
- Example manifest summary updated 82→102 fixes, alpha.18→alpha.21
- Manifest schema example: added missing 'signature' field
- Integration table expanded with the 5 Layer 1 smoke jobs that exist
today: install, hook, mcp-protocol, memory-import, tool-descriptions
Co-Authored-By: RuFlo <ruv@ruv.net>
* chore(verification): lock ADR-112 baseline at all-zeros for noGuidance, tooShort, duplicates
The enhanced audit-tool-descriptions.mjs now tracks three gates instead
of one. Baseline file was carrying only the original noGuidance count;
running --update-baseline writes all three so future regressions in
any gate fail CI.
Co-Authored-By: RuFlo <ruv@ruv.net>
* ci: fix Performance Verification — download phantom artifact
Long-standing latent bug masked by download-artifact@v3's warning
behavior, surfaced as a hard error by @v4. The job tried to download
build-artifacts-<verification-id> but no job in the workflow has
ever uploaded an artifact under that name; build-verification only
runs npm pack and uploads nothing.
Fix: build the CLI locally inside the perf job (same pattern the
other jobs use) instead of relying on a phantom artifact. Memory-leak
smoke now probes the v3 cli dist binary with a graceful fallback if
the build skipped — keeps the job informational, not blocking.
Affected run: https://github.com/ruvnet/ruflo/actions/runs/25648092044
Triggered by main push of
|
||
|
|
d0c507e643 |
fix(memory): #1883 + #1884 — WSL path resolution + import-key sanitization + CI guard (#1886)
* fix(memory): #1883 + #1884 — WSL path resolution + import-key sanitization #1883 — memory_import_claude(allProjects=false) returned imported=0 on WSL because project-hash derivation only POSIX-slash-replaced cwd. A WSL bridge running Ruflo with cwd `/mnt/c/Users/x/Project Name` could never match the Windows-host Claude Code project dir `C--Users-x-Project-Name`. Fix: resolveProjectMemoryDir() tries multiple candidate hashes (legacy POSIX, WSL `/mnt/<drive>/`-translated, leading-dash-stripped, space-replaced) and returns the first that exists. Also adds optional `projectPath` input parameter as an explicit override for callers in cross-environment setups. #1884 — memory_import_claude wrote keys built from raw frontmatter `name` and section titles directly to storeEntry, bypassing validateMemoryInput. memory_delete enforces it. Any markdown file with shell-metacharacters in section headings (`(`, `)`, `{`, `}`, `[`, `]`, `<`, `>`, `!`, `#`, etc.) produced keys that imported successfully but could not be deleted through MCP — stranded in the database, requiring direct SQLite intervention. Fix: sanitizeMemoryKey() replaces every char in DANGEROUS_KEY_CHARS with `_` before storeEntry. The set is shared with DANGEROUS_KEY_PATTERN used by validateMemoryInput so write-side and read-side can never drift apart. CI guard (catches the bug class going forward): - plugins/ruflo-core/scripts/test-memory-import.mjs: 12 regression checks covering static dist scan (helpers defined + called from import handler), legacy-code negative-attestation, sanitizer property test against 27 adversarial inputs, WSL-fixture and POSIX-compat candidate-set checks. - .github/workflows/v3-ci.yml: new `memory-import-smoke` job (ubuntu+macos), wired into witness-verify needs[]. - verification/witness-fixes.json: #1883 + #1884 markers (resolve…, sanitize…) — witness-verify cryptographically attests both helpers are present in dist on every PR. Why our verification missed these (and is now closed): - Witness manifest catches drift from a known-good baseline. Both bugs were always there; no drift to detect. Closed via new markers + the static dist scan that asserts call-sites, not just helper presence. - CI matrix has Linux/macOS/Windows runners but no WSL-bridge fixture. Closed via deriveCandidates() unit assertion on synthetic WSL cwd. - No round-trip test for write-path/read-path key invariant. Closed via sanitizer property test on 27 adversarial inputs. Local verification: 12/12 regression guards pass; witness-verify clean (99 fixes pass, signature valid). Closes #1883 Closes #1884 Co-Authored-By: RuFlo <ruv@ruv.net> * ci: memory-import-smoke uses recursive --no-bail build The targeted `--filter @claude-flow/cli... run build` doesn't pull in @claude-flow/swarm, which @claude-flow/cli imports from at TS-compile time (TS6305 — referenced .d.ts not built from source). Switching to the same `pnpm --recursive --no-bail run build || true` pattern that witness-verify uses. The smoke script already fails loudly if the cli dist didn't get produced, so we don't lose signal. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
02eee0bcdc |
docs(adr): bulk-update plugin contract ADR statuses (sweep)
- 27 plugins moved Proposed → Accepted (shipped versions, in marketplace) - 0 plugins kept as Proposed (all have real versions ≥ 0.2.0) Per-plugin breakdown: ruflo-aidefence v0.2.0 Accepted — 3-gate pattern, 6 aidefence_* tools ruflo-autopilot v0.2.0 Accepted — 10 autopilot_* tools, /loop integration ruflo-core v0.2.1 Accepted — MCP server contract, plugin-catalog discovery ruflo-cost-tracker v0.16.1 Accepted — namespace-routing fix, ADR-097 budget integration ruflo-daa v0.2.0 Accepted — 8 daa_* tools, intelligence-pipeline alignment ruflo-ddd v0.2.0 Accepted — AgentDB domain graph, SPARC Architecture-phase ruflo-docs v0.2.0 Accepted — document worker dispatch, drift detection ruflo-federation v0.2.0 Accepted — ADR-097 Phase 1+2, 3-gate alignment ruflo-goals v0.2.0 Accepted — 6 namespaces, GOAP + dossier ADR-099 ruflo-iot-cognitum v0.2.0 Accepted — 5-tier trust, 6 background workers ruflo-jujutsu v0.2.0 Accepted — 6 analyze_* tools, ADR-compliance cross-link ruflo-knowledge-graph v0.2.0 Accepted — embeddings_generate fix, pathfinder ruflo-loop-workers v0.2.0 Accepted — 12 worker triggers, 5 hooks_worker-* tools ruflo-market-data v0.2.0 Accepted — embeddings + namespace-routing bugs fixed ruflo-migrations v0.2.0 Accepted — namespace-routing bug fixed both skills ruflo-neural-trader v0.2.0 Accepted — 4 namespaces already compliant ruflo-observability v0.2.0 Accepted — namespace-routing bug fixed both skills ruflo-plugin-creator v0.2.0 Accepted — scaffolding templates updated with contract ruflo-rag-memory v0.2.0 Accepted — claude-memories reserved namespace consumer ruflo-ruvllm v0.2.0 Accepted — LLM-config + chat-format slice ownership ruflo-rvf v0.2.0 Accepted — portable-memory + session-persistence slice ruflo-security-audit v0.2.0 Accepted — 3-gate + audit_1776853149979 regression class ruflo-sparc v0.2.0 Accepted — all 5 SPARC phases cross-linked ruflo-swarm v0.2.0 Accepted — 12 MCP tools (4 swarm_* + 8 agent_*) ruflo-testgen v0.2.0 Accepted — testgaps worker + coverage CLI commands ruflo-wasm v0.2.0 Accepted — 10 wasm_* tools, ADR-070 cross-ref ruflo-workflows v0.2.0 Accepted — 10 workflow_* tools, SPARC phase transitions Each ADR received: updated: 2026-05-09 in frontmatter + Implementation status section noting version, marketplace presence, and contract element alignment. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
858ce28f7e |
fix(cli): bin/cli.js MCP-stdio auto-detect overrode explicit -t http
Investigating why the #1874 boot smoke kept failing in CI uncovered a separate-but-related cli bug: v3/@claude-flow/cli/bin/cli.js auto-routes any `mcp start *` invocation to stdio mode when stdin isn't a TTY — even when the user explicitly passed `-t http`. Result: every smoke / non-TTY caller silently got stdio regardless of the transport flag. This is the same class as #1874: a "smart default" that overrides explicit user intent, with no test catching it. Yet another example of self-consistent code where everyone agreed on the wrong behaviour. Fix: the MCP auto-detect now defers when explicit `-t <non-stdio>`, `--transport <non-stdio>`, or `--transport=<non-stdio>` is in argv. HTTP transport now starts when requested even from non-TTY contexts (CI smoke, daemonized callers, etc.). Verified locally: $ node bin/cli.js mcp start -t http -p N [OK] MCP Server started — Transport: http (was: stdio) Smoke test simplified ───────────────────── The boot-an-actual-server-and-call-initialize approach hit a secondary issue (in-process HTTP server doesn't keep the process alive after `await mcpServer.start()` returns; needs separate plumbing). For #1874's regression coverage, a static dist scan is sufficient and reliable: assert the protocolVersion assignment is a YYYY-MM-DD spec string, reject the {major,...} object form. Combined with witness markers (#1874-mcp, #1874-shared) attesting the spec strings live in dist, and the corrected unit test in mcp.test.ts using the spec string form, this is three-way coverage of the bug class without flaky integration plumbing. A separate issue tracks the boot-smoke gap (cli's HTTP server process-lifetime); not blocking #1874 closure. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
d065b2d654 |
fix #1874 + add MCP protocol-compliance smoke layer
The bug
───────
@claude-flow/mcp and @claude-flow/shared returned protocolVersion as
{ major, minor, patch } in the initialize response. The MCP spec
requires a YYYY-MM-DD string. Claude Code's Zod validator rejects
the object form with 'Invalid input: expected string, received
object', so HTTP MCP transport users couldn't connect at all.
Fix
───
- MCPProtocolVersion type: interface with major/minor/patch →
type alias for string (both packages).
- Server constants: '2025-11-25' (mcp) and '2024-11-05' (shared).
- Existing unit test in mcp.test.ts also corrected — it was
asserting the wrong shape, so test + prod agreed on a non-spec
format. This is the most important finding from the
'why did validation miss this' investigation.
- README example updated to spec-compliant string.
Why validation missed it (the gap)
──────────────────────────────────
- Layer 1 (smoke): no smoke test boots the actual HTTP MCP
server, sends a real initialize request, and validates the
wire format. The existing tests only exercise tool execution.
- Layer 2 (witness): tracks fix presence, can't catch
'always-wrong-from-the-start' bugs that have no good baseline.
- Layer 3 (history): same — no marker, no signal.
- The unit test was self-consistent with the buggy production
code. Both used { major, minor, patch }. Nothing measured
against the upstream MCP spec or a real client validator.
Closing the gap
───────────────
plugins/ruflo-core/scripts/test-mcp-protocol.mjs
Boots the HTTP MCP server, sends initialize, asserts response
shape against the spec:
- protocolVersion is a string matching YYYY-MM-DD
- capabilities is an object
- serverInfo has { name, version } strings
Final assertion mirrors what Claude Code's Zod would accept.
v3-ci.yml: new mcp-protocol-smoke job (Linux + macOS), gated
before witness-verify. Three layers of regression guard now
cover this class.
verification/witness-fixes.json: registers #1874-mcp and
#1874-shared. Witness now attests the spec strings are present in
both dist files; future regressions to the object form are caught
by witness-verify, not just user reports.
Impact
──────
84/84 fixes verified in the regenerated manifest (was 82).
Anyone running ruflo mcp start -t http with the new build can now
connect Claude Code without the Zod rejection.
Closes #1874
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
b4a60e0374 |
feat: performance verification + capability historical reference
Adds a fourth verification layer alongside the existing three (smoke
tests, witness manifest, marker-presence history): per-OS performance
measurements that catch speed regressions the way markers catch presence
regressions.
What's added
────────────
plugins/ruflo-core/scripts/witness/perf.mjs
Benchmark runner. Each capability is one synchronous bench function
in a runners map; failures throw and get recorded as error entries.
Supports --baseline to compare against the rolling-5 median per
capability and --json for CI consumption.
verification/<os>/performance.jsonl (one per OS, append-only)
Schema: { v, commit, issuedAt, os, capability, durationMs, ... }
Same per-OS organization as manifest.md.json + history.jsonl —
different platforms have different native code paths so absolute
numbers don't compare directly, but per-OS trends do.
verification/CAPABILITIES.md
Historical reference: which capabilities are tracked, why each
matters, reference baselines (macOS-class hardware), and incident
history (#1867 Node 26 install, #1859/#1862 hooks, #1608
bcrypt→bcryptjs, ADR-009 fallback chain). Documents the pattern
of `durationMs` regression detection and the schema.
Capabilities (initial set)
──────────────────────────
install_pack pnpm pack @claude-flow/memory (370ms macOS)
install_no_optional npm install --omit=optional (~5s; CI-skipped)
memory_load cold import('@claude-flow/memory') (18ms)
memory_round_trip createDatabase + store/get + close (CI-skipped)
witness_verify verify.mjs --manifest (53ms)
CI integration
──────────────
v3-ci.yml witness-verify job gains a 'Performance verification' step
that runs the lightweight subset (install_pack, memory_load,
witness_verify) with --baseline and appends results. Heavier benches
(install_no_optional, memory_round_trip) are local-only — adopters
run the full suite during release prep.
Soft gate (`|| echo … non-blocking`) until baselines stabilise; can
be promoted to hard gate by removing the suffix.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
9817695a60 |
feat: per-OS verification cognitive containers + tutorial README
Reorganizes the verification system into per-OS bundles, addressing
the cross-platform CI matrix added in
|
||
|
|
b289c009e9 |
fix(witness): probe workspace packages for @noble/ed25519 (pnpm isolated linker)
CI-only failure: signature verification returned all-false because
verify.mjs couldn't load @noble/ed25519. Locally it worked because
v3/node_modules/@noble/ed25519 happened to exist as a flat copy from
an earlier non-pnpm install. Fresh CI runners get pnpm's default
isolated linker, which only exposes a transitive dep at workspace
root if a workspace member declares it directly — and no v3 root
member declares ed25519 (only @claude-flow/cli and
@claude-flow/plugin-agent-federation do).
Fix: expand the probe paths in both verify.mjs and lib.mjs to also
look inside the workspace packages that DO declare @noble/ed25519.
Now resolution succeeds on:
- flat npm install (probes repoRoot/node_modules)
- pnpm hoist install (probes v3/node_modules)
- pnpm isolated install (probes v3/@claude-flow/cli/node_modules)
Verified locally by removing v3/node_modules/@noble/ed25519 (the
stale flat copy) and re-running verify.mjs — signature valid,
82/82 fixes pass.
Also: verify.mjs now prints the probed paths + last error when
ed25519 can't be located, instead of silently returning all-false
signature flags. The diagnostic visibility (via the v3-ci.yml
update in
|
||
|
|
76bd35943a |
feat: ADR-103 witness temporal history + plugin-distributed toolkit (#1868)
Closes the gap that ADR-102 left open: snapshot-only manifests can't
answer "when did this fix regress?" Adds a JSONL temporal log + extracts
the witness toolkit into ruflo-core as an optional plugin asset that
any project can adopt — not just ruflo's own monorepo.
What's new
──────────
1. verification-history.jsonl — one append-only line per regen with
{ commit, issuedAt, manifestHash, summary, fixes: { id: {sha256,
markerVerified} } }. Format choices: JSONL for cheap appends and
minimal git diffs; per-fix object for O(1) lookup.
2. plugins/ruflo-core/scripts/witness/ — project-agnostic toolkit
- lib.mjs shared regen + history primitives
- init.mjs bootstrap empty manifest into any repo
- regen.mjs sign + append history
- verify.mjs validate signature + markers (no ruflo CLI dep)
- history.mjs query temporal log (summary, regressions, timeline)
3. plugins/ruflo-core/{skills,commands,agents}/witness*
Slash command + skill doc + curator agent — Claude Code surface area.
4. scripts/regen-witness.mjs — thin wrapper, delegates to plugin lib.
Reads project-specific NEW_FIXES from a committed witness-fixes.json
instead of inline literals. Single source of truth in the plugin.
5. .github/workflows/v3-ci.yml — witness-verify job gains a follow-on
`history.mjs summary` step that surfaces transitions since the last
snapshot (newly regressed / passing / added / removed fixes).
Empirically verified
────────────────────
Before refactor: 81/81 verified, 1 history entry
After refactor: 81/81 verified, 1 history entry, signature reproducible
signature, marker, sha256 all match across the move.
Plugin scripts run standalone without ruflo CLI installed — only
@noble/ed25519 required. Adopters get full witness capability by
copying plugins/ruflo-core/scripts/witness/ into their repo.
Refs #1868 — implementation issue
ADR-103 — design + rationale + residual risk
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
d4795b7538 |
chore(ruflo-core): 0.2.0 → 0.2.1 (publish #1859 #1862 fix)
Bumps the plugin version so Claude Code's marketplace pulls the
fixed hooks.json. Cached 0.2.0 installations need to refresh:
/plugin update ruflo-core
# or: rm -rf ~/.claude/plugins/cache/ruflo/ruflo-core/0.2.0
What 0.2.1 changes vs 0.2.0:
- PostToolUse:Bash + Edit hooks call only documented CLI flags
(-c/-s/-e for post-command, -f/-s for post-edit). Removes the
bogus --format/--update-memory/--track-metrics/--store-results.
- Bash hook reads stdin once via `bash -c` wrapper instead of
`tr | xargs -0 -I {}`, so multi-line heredoc commands no longer
fragment into multiple null-delimited records.
Verified end-to-end against the just-published
@claude-flow/cli@3.7.0-alpha.18 — 7/7 smoke assertions pass.
Refs #1859 #1862
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
8d06e427ca |
fix: #1859 #1862 ruflo-core hooks + CLI flag priority
Two distinct bugs converged on the same user symptom (every Write/Edit/Bash fired in Claude Code logged a parser error or recorded "true" as the file path). ## CLI parser bug (root of #1859 "records true as filename") In v3/@claude-flow/cli/src/commands/hooks.ts every handler resolved the primary value with: const x = ctx.args[0] || ctx.flags.X as string Because boolean-typed flags don't consume their next token, writing `--success true` (which the help text and project examples explicitly recommend) leaves the literal string "true" in `ctx.args[0]`, which then beats the named flag. Result: post-edit logs "Recording outcome for: true" instead of the path passed via --file. Fixed by swapping priority — flag value first, positional fallback — across all 14 sites: const x = (ctx.flags.X as string) || ctx.args[0] Backward compatible for legacy positional-only callers; surgical to a single regexed bulk swap. ## Plugin hooks bug (#1862 + part of #1859) plugins/ruflo-core/hooks/hooks.json passed flags the CLI doesn't accept: `--format true`, `--update-memory true`, `--track-metrics true`, `--store-results true`. The CLI's global `--format` flag rejects "true" because it's restricted to text|json|table — every Write/Edit hook crashed with "Invalid value for --format: true" before the handler ran. Also: the Bash hook's `tr '\n' '\0' | xargs -0 -I {}` mangled multi-line heredoc commands by splitting them at newlines, occasionally producing empty `--command ''` calls that the CLI rejected with "Required option missing". Replaced with a `bash -c` wrapper that: - Reads stdin once, extracts via jq into env vars (multi-line safe). - No-ops cleanly when the relevant field is absent. - Calls only flags the CLI documents: -c/-s/-e for post-command, -f/-s for post-edit. ## CI regression guard plugins/ruflo-core/scripts/test-hooks.mjs drives each PostToolUse hook with synthetic Claude-Code JSON against a CLI binary (local or published), asserting both exit code 0 *and* that the recorded value is the intended one (not a stray boolean). Verified empirically: fixed CLI: 7/7 pass broken @3.7.0-alpha.17: 5/7 fail with the exact #1859/#1862 symptoms Wired into .github/workflows/v3-ci.yml as `plugin-hooks-smoke` (Node 20 + 22), gating publish on green. Refs #1859 #1862 Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
ba92c56122 |
feat(cli-core): split cli into cli-core (lite) + cli (umbrella) — alpha.5 (#1764)
* feat(cli-core): scaffold @claude-flow/cli-core package + ADR-100 (#1748 Issue 3) First fire of the cli-core split (ADR-100). Establishes the package boundary, design doc, and skeleton entry point. Subsequent fires move memory + hooks source in, build, benchmark, and publish under the alpha tag. What lands in this fire: - v3/docs/adr/ADR-100-cli-core-split-lazy-load.md (Proposed) — full design rationale: the 1.8 MB / 999 files cold-cache problem from #1748 Issue 3, the cli-core ≤250KB target, the metapackage facade for the existing @claude-flow/cli, alpha-tag-then-promote versioning strategy, riskiest-assumption section, plan of work with 8-step roadmap, verification scaffold, migration path for plugin authors. - v3/@claude-flow/cli-core/package.json — alpha 3.7.0-alpha.0, type=module, bin=claude-flow-core, exports map for the surface, publishConfig tag=alpha (so npm publish defaults to alpha, never accidentally to latest before validation). - v3/@claude-flow/cli-core/README.md — what's included (memory + hooks), what's NOT (everything else — points at @claude-flow/cli), cold-cache verification snippet, ADR-100 cross-link. - v3/@claude-flow/cli-core/tsconfig.json — ES2022 + Node module resolution + strict (mirrors @claude-flow/cli config). - v3/@claude-flow/cli-core/src/index.ts — alpha-skeleton entry that responds to --version + --help and prints a "real surface lands in subsequent alphas" notice for any other command. This means the package can be npm-published immediately (non-empty surface) without breaking anything, and plugin authors can pin to it ahead of the actual feature landing. Next fire (per ADR-100 §"Plan of work"): Step 2 — move commands/memory.ts + commands/hooks.ts + mcp-tools/{memory,hooks}-tools.ts + output.ts + types.ts into cli-core/src/ Step 3 — build cli-core, smoke, fix any cross-package import misses Step 4 — update @claude-flow/cli's src/index.ts to re-export from cli-core + register lazy-loaded extras Step 5 — cold-cache benchmark old vs new, persist numbers Step 6 — bump versions to 3.7.0-alpha.1, npm publish --tag alpha Step 7 — PR + comment on #1748 with proof Do NOT promote alpha → latest until the cold-cache benchmark shows <5s and at least one external validator (the #1748 reporter is the target candidate) confirms MCP startup succeeds on a cold cache. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): foundation surface (types, output, MCP tool types, validators) — ADR-100 Step 2 Second fire of the cli-core split. Foundation files copied from @claude-flow/cli with no internal dependencies on cli's heavier modules. Builds cleanly, dist is 136 KB / 20 files (vs cli's 9.6 MB / 777 files — 71× reduction). Files copied to v3/@claude-flow/cli-core/src/: - types.ts (CommandContext, Command, CommandResult, ParsedFlags) - output.ts (terminal formatting, tables, spinners, progress) - mcp-tools/types.ts (MCPTool, MCPToolInputSchema, MCPToolResult) - mcp-tools/validate-input.ts (input bounds + identifier guards) Deferred from foundation: - fs-secure.ts — depends on encryption/vault.ts (ADR-096 encryption- at-rest). Will be added if memory.ts/hooks.ts need it; for the pure foundation surface it's not load-bearing. Index.ts now exports a real foundation surface: import { CommandContext, MCPTool } from '@claude-flow/cli-core'; import { output, validateInput } from '@claude-flow/cli-core'; Programmatic smoke verified — exports include: CLIError, CommandNotFoundError, ConfigError, ValidationError, output (OutputFormatter, Progress, Spinner), validateInput (assertValid, validateIdentifier, validateAgentSpawn, ...) Binary --version and --help still work (alpha skeleton notice still shown for non-foundation commands until Step 3+ lands memory + hooks). Build: TS clean, no external errors. tsc --noEmit passes. Next fire (Step 3): copy mcp-tools/memory-tools.ts + mcp-tools/hooks-tools.ts (the MCP tool definitions — already use types.ts + validate-input.ts that are now in cli-core, so should build with minimal additional changes). Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): foundation alpha.0 — defers memory/hooks tool deps to backend split (ADR-100 fire 3) Fire 3 attempted to copy memory-tools.ts + hooks-tools.ts into cli-core per the original plan and discovered both files have deep transitive ML dependencies that defeat the lite-bundle goal: memory-tools.ts → ../memory/memory-initializer.js (2830 LOC) → fs-secure.ts → encryption/vault.ts (ADR-096) hooks-tools.ts → 9 transitive imports across memory/{sona-optimizer, ewc-consolidation, memory-bridge} and ruvector/{moe-router, semantic-router, flash-attention, lora-adapter, enhanced-model-router} Pulling those in would balloon cli-core past the 250 KB target. Right architectural move (now documented in ADR-100 §"Discovery"): 1. Memory backend abstraction. cli-core defines a MemoryBackend interface and ships a JsonMemoryBackend (no SQLite/HNSW/ONNX, just a JSON file at .swarm/memory.json — the foundation case). cli ships SqliteHnswMemoryBackend (the existing heavy implementation) that swaps in via env or import map. 2. Tool-definition / handler split. MCPTool definitions (name, description, inputSchema — pure data, ~10 KB) go in cli-core. Handler implementations (the actual code) stay in cli's full module tree, accessed via dynamic-import only at request time. This is more work than fire 1 anticipated — 4-6 additional fires instead of the original "next fire" estimate. Net call: ship the foundation alpha.0 NOW (proves publish pipeline, gives plugin authors type imports + output utility); land backend abstraction in alpha.1 and tool/handler split in alpha.2. What's actually in alpha.0 (this commit): Foundation-only surface, 136 KB / 20 files dist, TS clean: - types.ts (CommandContext, Command, ParsedFlags, ...) - output.ts (terminal formatting, tables, spinners) - mcp-tools/types.ts (MCPTool, MCPToolInputSchema, ...) - mcp-tools/validate-input.ts (input validators) Programmatically: import { CommandContext, MCPTool, output, validateInput } from '@claude-flow/cli-core'; The Plan-of-work table in ADR-100 is updated with the new step ordering, status markers, and the Discovery section explaining why steps 3+4 changed shape. Co-Authored-By: RuFlo <ruv@ruv.net> * bench(cli-core): cold-cache 38× faster than @claude-flow/cli — alpha.0 published (ADR-100) Persisted cold-cache benchmark proving the cli-core split fixes #1748 Issue 3's 30s MCP-startup timeout race: | Package | Cold | Warm | Files | Packed | | @claude-flow/cli-core@3.7.0-alpha.0 | 671 ms | 361 ms | 22 | 22 KB | | @claude-flow/cli@3.6.30 | 25.5 s | 623 ms | 999 | 1.8 MB | Results: - 38× cold-cache speedup (25.5s → 0.67s) - 80× packed-size reduction (1.8 MB → 22.3 KB) - 45× file-count reduction (999 → 22) - Fits comfortably under Claude Code's 30s MCP-startup timeout (cli is borderline at 25.5s — slow networks race and lose) Caveats (also in the JSON's caveats array): - cli-core@alpha.0 is foundation-only — types + output + MCP-tool types + validate-input. Does NOT yet expose memory/hooks command surface. ADR-100 §Discovery documents the tool-def/handler split needed for alpha.1 + alpha.2. - The benchmark proves the COLD-CACHE thesis (smaller bundle = under timeout). It does NOT yet prove memory/hooks parity at speed — that requires the backend abstraction work in alpha.1. Persisted to v3/docs/benchmarks/cli-core-cold-cache.json so future regressions are visible. Published: @claude-flow/cli-core@3.7.0-alpha.0 with --tag alpha (latest also points to alpha.0 since this is the first publish). Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): alpha.1 — MemoryBackend abstraction + working memory CLI (ADR-100 fire 4) The hard problem from ADR-100 §Discovery — memory-tools.ts had a 2830-LOC ML chain that defeated the lite-bundle goal. This commit implements the backend abstraction so cli-core can ship its own lite memory implementation without pulling sql.js / HNSW / ONNX. What lands in alpha.1: src/memory/backend.ts (~150 LOC) Defines MemoryBackend interface — store / retrieve / search / list / delete / stats. MemoryEntry, MemorySearchResult, StoreOptions / SearchOptions / ListOptions types. Contract every backend (lite + heavy) implements. src/memory/json-backend.ts (~190 LOC) JsonMemoryBackend — implements the full interface against a JSON file (default .swarm/memory.json, override CLAUDE_FLOW_MEMORY_PATH). Atomic writes via tmp file + rename. TTL handling, namespace isolation, tag filtering, substring search. NO SQLite, NO HNSW, NO ONNX — pure JSON, no transitive ML deps. src/commands/memory.ts (~210 LOC) `memory <subcommand>` CLI dispatcher wrapping the backend. Subcommands: store / retrieve / get / list / search / delete / rm / stats. Every subcommand supports --format=json for piping to jq, --namespace, and the relevant per-op flags (--tags, --ttl, --upsert, --limit, --threshold, --path). src/index.ts (updated) Re-exports MemoryBackend interface + JsonMemoryBackend impl. Bin entry now dispatches `memory <args>` to runMemoryCommand. Live verified end-to-end (smoke): ✓ store hello world → ✓ stored default::hello ✓ store --namespace=test foo "bar baz" --tags=a,b → stored test::foo ✓ retrieve hello → "world" ✓ list → 2 entries (default::hello + test::foo) ✓ search bar --format=json → returns test::foo with score ✓ stats → backend=json, 2 entries, 656 bytes ✓ delete hello → deleted ✓ list after delete → only test::foo remains Cold-cache via npm @ 3.7.0-alpha.1: rm -rf ~/.npm/_npx; npx @claude-flow/cli-core@alpha memory store ... → 2.71s wall-time Compare to @claude-flow/cli@3.6.30: 25.5s cold cache. **Cold-cache speedup with alpha.1's full memory surface: 9.4× faster.** (alpha.0's foundation-only was 38× — alpha.1 is heavier because it has the actual memory commands now, but still well under the 30s timeout.) dist size: 200 KB / 32 files (vs cli's 9.6 MB / 777 files = 48× reduction). Substrate trade-offs (honest): - Search degrades to substring matching (no semantic / vector). For real semantic search install @claude-flow/cli@alpha (heavy backend). The MemoryBackend interface is identical so call sites don't change. - Concurrent writers across processes: last-writer-wins. Acceptable for single-developer plugin workloads, not safe under high contention. - Atomic write via tmp+rename — no in-flight reader sees half-written JSON. exports map updated: '@claude-flow/cli-core/memory' → backend interface '@claude-flow/cli-core/memory/json-backend' → JsonMemoryBackend impl '@claude-flow/cli-core/commands/memory' → CLI dispatcher Published: @claude-flow/cli-core@3.7.0-alpha.1 with --tag alpha. Next fire (alpha.2): tool-def/handler split for hooks-tools.ts. Pure MCPTool definitions move to cli-core; handlers stay in @claude-flow/cli behind dynamic-import boundaries. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): alpha.2 — MCP tool defs (memory + hooks subset, def-only) (ADR-100 fire 5) Tool-definition / handler split landed. cli-core now ships pure-data MCPTool definitions for the memory_* (6) + hooks_* (7) families an MCP server can register with `tools/list`. Handlers stay in @claude-flow/cli — dynamic- imported only at request time. What lands in alpha.2: src/mcp-tools/memory-defs.ts (~115 LOC) 6 memory_* MCPTool definitions: memory_store, memory_retrieve, memory_search, memory_delete, memory_list, memory_stats Descriptions match the 3.6.30 sharpening (#1748 Issue 4 — "Use when native X is wrong because Y" framing). src/mcp-tools/hooks-defs.ts (~120 LOC) 7 hooks_* MCPTool definitions (most-used subset): hooks_route, hooks_pre-task, hooks_post-task, hooks_post-edit, hooks_model-outcome, hooks_model-route, hooks_explain Remaining 30 hooks tools stay in @claude-flow/cli (they pull in sona-optimizer, ewc-consolidation, ruvector/* heavy ML deps). If a session needs one of those, fall through to cli@alpha. src/mcp-tools/index.ts (~25 LOC) Re-exports memoryToolDefs + hooksToolDefs + allToolDefs (concatenation, suitable for a single tools/list registration). src/index.ts (updated) Re-exports MCPToolDef type + the def arrays so consumers can `import { allToolDefs } from '@claude-flow/cli-core'`. package.json (updated) Version 3.7.0-alpha.1 → 3.7.0-alpha.2 New exports: ./mcp-tools, ./mcp-tools/memory-defs, ./mcp-tools/hooks-defs Live verified end-to-end via npm: rm -rf ~/.npm/_npx npx -y @claude-flow/cli-core@alpha --version → 2.3s cold Programmatic import: import { memoryToolDefs, hooksToolDefs, allToolDefs } from '@claude-flow/cli-core'; // memoryToolDefs.length: 6 // hooksToolDefs.length: 7 // allToolDefs.length: 13 dist: 256 KB / 44 files (still 38× smaller than cli's 9.6 MB / 777). Why this matters (the lazy-load thesis): An MCP server backed by cli-core can advertise these 13 tools to a Claude session in <2.5s on a cold cache (vs cli's 25s race). The model sees the tools listed, picks one, and the handler can be dynamic-imported from cli at request time — paying the heavy cost ONLY when actually used. This is the structural fix #1748 Issue 3 asked for. Next fire (alpha.3): wire dynamic-import handlers in @claude-flow/cli's metapackage so an MCP server using cli-core's defs can dispatch a real memory_search invocation through to the heavy backend on demand. Co-Authored-By: RuFlo <ruv@ruv.net> * docs(cli-core): MIGRATION.md + scan helper for plugin authors (ADR-100 fire 6) alpha.2 ships functional memory CLI + 13 MCPTool defs. This commit makes the alpha actually usable today by plugin authors who want to opt into the cold-cache speedup. What lands: v3/@claude-flow/cli-core/MIGRATION.md Concrete diff + env-flag pattern for switching plugin Bash blocks from @claude-flow/cli@latest to @claude-flow/cli-core@alpha. Tables of what's safe to migrate today (memory ops) vs what's deferred (hooks, neural, agent/swarm). Storage backend coexistence section documents the SQLite/HNSW vs JSON file split honestly. Reverting instructions. Adoption sequence. v3/@claude-flow/cli-core/README.md Adds prominent MIGRATION.md pointer in the documentation list + issue #1760 cross-reference for alpha tracking. v3/@claude-flow/cli-core/scripts/migrate-plugin-call-sites.mjs Conservative scanner — walks a plugin dir, finds @claude-flow/cli invocations, classifies each as [review] (memory ops, safe to migrate by hand) vs [skip] (hooks/neural/agent/swarm — deferred). Deliberately does NOT auto-rewrite (regex over Node argv arrays isn't safe enough to ship without human review). Exit code 1 when call sites need review; exit 0 only when fully clean. Smoke run on cost-tracker (the canonical heavy CLI consumer): 6 scripts flagged for memory migration: track.mjs, budget.mjs, conversation.mjs, export.mjs, federation.mjs, summary.mjs 1 script correctly skipped (outcome.mjs uses hooks — defer to alpha.3+) Migration recommendation summarized in MIGRATION.md: const cliPkg = process.env.CLI_CORE === '1' ? '@claude-flow/cli-core@alpha' // lite — JSON backend, ~2s cold : '@claude-flow/cli@latest'; // heavy — SQLite/HNSW, ~25s cold Plugin authors can opt in via env var, A/B test, then flip the default once they're confident the substring-search regression doesn't bite their use case. Honest trade-offs documented in MIGRATION.md: - Storage file changes (.swarm/memory.db → .swarm/memory.json) - Search degrades to substring (no semantic / vector) - Hooks operations not yet migrable (alpha.3+) - Storage convergence planned for alpha.3 or later No version bump in this commit (docs + scripts only). cli-core stays at 3.7.0-alpha.2. Next fire (alpha.3): wire dynamic-import handlers in @claude-flow/cli's metapackage so an MCP server using cli-core's defs can dispatch a real tools/call invocation through to the heavy backend on demand. After that, cost-tracker's hooks call sites become migrable too. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): alpha.4 — bin-shim isMain fix + flag-form CLI compat + cost-tracker integration (ADR-100 fire 7) End-to-end validation. cli-core@alpha.4 is now actually usable from plugin scripts with the env-flag pattern. Two real bugs caught + fixed during integration testing. Bug 1: bin-shim isMain detection broken (alpha.0–alpha.2) Earlier alphas used: process.argv[1]?.endsWith('cli-core/dist/src/index.js') This fails when invoked via `npx @claude-flow/cli-core@alpha` because npx exposes the binary through a bin-shim symlink at ~/.npm/_npx/<hash>/node_modules/.bin/claude-flow-core, NOT the underlying dist/src/index.js. The endsWith check missed it, isMain returned false, the bin entry silently no-op'd. alpha.0/.1/.2 were effectively unusable as published binaries — --version returned empty, memory store wrote nowhere, exit 0. Fix: ESM-standard isMain via realpathSync comparison. argv[1] symlink-resolves to dist/src/index.js, which equals fileURLToPath(import.meta.url). Fallback heuristic for fringe cases (regex on argv[1] for claude-flow-core / cli-core/dist/). Bug 2: memory store argument-parsing incompatibility cli-core's memory store only accepted positional `<key> <value>` args; @claude-flow/cli accepts `--key K --value V` flag form too. Plugin scripts (track.mjs, summary.mjs, etc.) use the flag form, so cli-core was a non-drop-in replacement. Fix: accept BOTH forms. Same change applied to retrieve, get, delete, rm subcommands. Usage messages updated to show both. Cost-tracker integration (proves the alpha works end-to-end): plugins/ruflo-cost-tracker/scripts/track.mjs gains the env-flag pattern from MIGRATION.md: const cliPkg = process.env.CLI_CORE === '1' ? '@claude-flow/cli-core@alpha' // lite — JSON, ~2s cold : '@claude-flow/cli@latest'; // heavy — SQLite/HNSW, ~25s cold Live verified end-to-end on this session's data: rm -rf ~/.npm/_npx CLI_CORE=1 CLAUDE_FLOW_MEMORY_PATH=/tmp/test.json \ node plugins/ruflo-cost-tracker/scripts/track.mjs Result: | Persisted | `cli-core-test:session-1dba3b8c-1f1f-4718-bab4-9ffba5f49578` | /tmp/test.json: backend=json, 1 entry, $2578.69 total persisted CLI_CORE unset still uses cli@latest — backward compatible. Why this matters: alpha.0–alpha.3 *published* but the bin was broken; nobody pulling the alpha could actually run it. alpha.4 is the FIRST alpha that genuinely works through `npx`. The cold-cache benchmark numbers from fire 3 (38× speedup) were directionally right but under-reported because alpha.0's binary just exited 0 immediately — the real work was being skipped. With alpha.4's working bin, every operation is real. Published: @claude-flow/cli-core@3.7.0-alpha.4 with --tag alpha. Branch: feat/cli-core-split, 8 commits. Next fire: extend the env-flag pattern to remaining cost-tracker scripts (budget, summary, conversation, federation, export); validate each end-to-end; then the metapackage refactor for @claude-flow/cli. Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cost-tracker): apply CLI_CORE env-flag to all 5 remaining scripts Extends fire 7 (track.mjs) to budget/summary/conversation/federation/export. All cost-tracker scripts now route to @claude-flow/cli-core@alpha when CLI_CORE=1 is set, dropping cold-cache wall-time from ~25s to ~2s per spawnSync. Falls back to the heavy @claude-flow/cli@latest by default. Validated end-to-end against cli-core@3.7.0-alpha.4: - budget set/get/check (markdown + JSON) - summary --format json (cross-namespace list + retrieve) - conversation --format md (per-session timeline) - federation --format json (empty + non-empty paths) - export --prometheus (textfile-collector exposition) The 13 call sites all use a module-scoped CLI_PKG constant so the package resolution happens once at startup, not per spawn. Refs ADR-100, #1748 Issue 3, #1760 Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli-core): alpha.5 — add mcp-tools/types + validate-input subpath exports Adds two new package.json export entries: - ./mcp-tools/types (MCPTool, MCPToolInputSchema, MCPToolResult) - ./mcp-tools/validate-input (validators) These already shipped via the bundled ./mcp-tools index, but exposing them as direct subpath exports is the prereq for @claude-flow/cli to replace its 4 byte-identical local copies (types.ts, output.ts, mcp-tools/types.ts, mcp-tools/validate-input.ts — 1,229 LOC total) with single-line re-export shims pointing at cli-core. Verified via diff -q between cli and cli-core that all four files are currently identical. That follow-up PR is intentionally NOT bundled with alpha.5 because cli is 2.2 MB / 1146 files and the foundation refactor deserves proper review. This release just lays the wiring so the cli-side change is mechanical. Validated all 11 cli-core subpath exports resolve correctly via Node's ESM resolution. Build clean. Published @ alpha tag (latest stays at alpha.0 to preserve "alpha is opt-in" semantics). Refs ADR-100, #1748 Issue 3, #1760 Co-Authored-By: RuFlo <ruv@ruv.net> * feat(cli): re-export 4 foundation modules from cli-core@alpha.5 Replaces 4 byte-identical files in @claude-flow/cli with one-line re-export shims pointing at @claude-flow/cli-core. Net: -1,215 LOC of duplication, +31 LOC of shim. The shim files keep their original paths so the 60+ internal `import './types.js'`-style call sites continue to resolve unchanged. Files migrated (all confirmed byte-identical to cli-core via diff -q prior to refactor): - cli/src/types.ts (287 LOC → 14 LOC shim) - cli/src/output.ts (640 LOC → 9 LOC shim) - cli/src/mcp-tools/types.ts (46 LOC → 8 LOC shim) - cli/src/mcp-tools/validate-input.ts (256 LOC → 9 LOC shim) Wiring: - Added @claude-flow/cli-core: ^3.7.0-alpha.5 to cli's runtime deps - pnpm install resolved cli-core via the v3 monorepo workspace map (workspaces: ["@claude-flow/*"]); pnpm-lock.yaml updated accordingly Validation: - npm run build: clean, zero TypeScript errors - node bin/cli.js --version: ok (v3.6.30) - node bin/cli.js memory list: ok (full SQLite backend still works) - dynamic import of output.js: OutputFormatter, Progress, Spinner, output instance all reachable through the shim Future drift is now impossible — when cli-core's types change, cli picks them up automatically via the dep. The 4 files are no longer maintained in two places. NOT bumping cli's version in this commit. Let the change bake on the branch before publishing. Once external validation lands (#1748 reporter, cost-tracker bench-corpus parity), this can ship as part of the cli-core-split PR. Refs ADR-100, #1748 Issue 3, #1760 Co-Authored-By: RuFlo <ruv@ruv.net> * test(cli-core): cold-cache benchmark script (ADR-100 fire 11) Reproducible benchmark for the cli vs cli-core wall-time claim. Uses NPM_CONFIG_CACHE redirection so it never touches ~/.npm/_npx (per project memory feedback on destructive cache ops). Results captured on this run (N=3, macOS, mise/node v22): | Condition | Min | Mean | Max | |--------------------|------:|------:|------:| | cli cold-cache | 32.76 | 34.89 | 37.38 | | cli warm-cache | 16.56 | 16.69 | 16.89 | | core cold-cache | 1.38 | 1.53 | 1.80 | | core warm-cache | 1.33 | 1.36 | 1.42 | Speedup cold-cache: 22.9x (cli 34.89s vs core 1.53s) warm-cache: 12.3x (cli 16.69s vs core 1.36s) The cold-cache gap (~33s saved per spawn) is the user-visible win for plugin scripts that spawn the cli many times — exactly the problem #1748 issue 3 raised. Refs ADR-100, #1748 Issue 3, #1760 Co-Authored-By: RuFlo <ruv@ruv.net> * feat(ruflo-adr): apply CLI_CORE env-flag to verify + import scripts Extends the cli-core opt-in pattern from cost-tracker (fires 7+8) to ruflo-adr's CLI spawn sites — verify.mjs (list+retrieve) and import.mjs (store). With CLI_CORE=1, both route to @claude-flow/cli-core@alpha, dropping per-spawn cold-cache wall-time from ~25s to ~2s. import.mjs documents one behavior delta: cli-core's JsonMemoryBackend overwrites by default, collapsing the "exists"/UNIQUE-constraint signal to plain "ok". Re-runs become idempotent (records refreshed) rather than incremental (records skipped). The comment in import.mjs flags this so users who want incremental semantics know to leave CLI_CORE unset. Validated end-to-end with a single-ADR smoke test under /tmp: CLI_CORE=1 IMPORT_FORMAT=json node import.mjs → storedRecords: 1 CLI_CORE=1 VERIFY_FORMAT=json node verify.mjs → adrCount: 1 Refs ADR-100, #1748 Issue 3, #1760, #1764 Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
cd0b66f0d4 |
feat(ruflo-adr): one-shot import + verify scripts (v0.3.0) (#1758)
The /ruflo-adr:adr-index skill previously instructed the agent to
issue per-ADR MCP tool calls (agentdb_hierarchical-store +
agentdb_causal-edge + memory_store) — for the Ruflo monorepo's 70+
ADRs that's hundreds of round-trips, no dedup, no false-positive
guard for issue numbers, and no support for the v3-vs-plugin format
divergence.
This commit packages the logic as a reusable script.
What lands:
- scripts/import.mjs (~200 LOC) — walks the working dir (or ADR_ROOT
override), parses every ADR under */docs/adr/ or */docs/adrs/,
handles both formats:
* v3-style: `# ADR-097: Title` heading + `**Status**:` line
* plugin-style: YAML frontmatter (id/title/status/date/tags)
Persists to `adr-patterns` (records) + `adr-edges` (relationships)
via spawnSync over `npx @claude-flow/cli memory store`. JSON or
markdown output. IMPORT_DRY_RUN=1 supported.
- scripts/verify.mjs (~80 LOC) — companion read-back validator that
surfaces dangling refs, supersede cycles, status mismatches.
Exits 1 on cycles (always corruption); exits 1 on any issue with
VERIFY_STRICT=1 (CI fail-closed).
- skills/adr-index/SKILL.md — rewritten to call import.mjs in one
Bash invocation instead of looping MCP calls.
- skills/adr-verify/SKILL.md — new sibling skill wrapping verify.mjs.
- scripts/smoke.sh — extended from 10 to 15 checks: verifies both
scripts are executable + syntax-clean, validates the import
script's dual-format support + issue-number false-positive guard,
validates verify.mjs has cycle detection + fail-closed exit, and
asserts both skills reference their respective scripts.
Live verified on the Ruflo monorepo:
- 73 ADRs across 39 source dirs imported to adr-patterns
- 13 'related' edges to adr-edges
- 0 dangling refs (was 17 false positives on issue numbers before
the script's extractAdrRefs() guard stripped #1697 / commit /
PR / backtick-quoted patterns)
- 0 status mismatches
- 0 storage errors
False-positive fix detail: the skill's old prose said "extract ADR-NNN
references from ## Links section". The reality is ADRs reference
GitHub issues (#1697), commits, PRs all the time, and a naive regex
captures those as ADR-1697. extractAdrRefs() strips known non-ADR
patterns before the regex pass.
Plugin-only change. No npm publish needed (loaded directly from the
repo via /plugin install or claude --plugin-dir).
Version: 0.2.0 → 0.3.0. Smoke: 10 → 15 checks (~85ms).
Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
|
||
|
|
a002ae49a6 |
fix(plugins): hooks per-plugin layout — ruflo-core install now loads hooks (#1748 Issue 1) (#1754)
The most load-bearing finding in @-the-Liberation-of-Bajor-team's methodical eval (#1748): with `/plugin install ruflo-core@ruflo`, zero hooks load. Their cross-check against hookify confirmed the plugin loader looks for `<plugin>/hooks/hooks.json` per-plugin, but ruflo's hooks lived only at marketplace root (`.claude-plugin/hooks/hooks.json`). Result: the README's headline value prop ("after init, just use Claude Code normally — hooks handle everything") was a no-op for plugin-install users. The 26KB of MCP tool definitions loaded but the hooks that auto-route tasks, learn from successful patterns, and coordinate agents in the background never fired. Fix: copy the same hook definitions to `plugins/ruflo-core/hooks/hooks.json`. Marketplace-root copy at `.claude-plugin/hooks/hooks.json` preserved for users who do `claude --plugin-dir <repo-root>` (full-tree load) — both paths work now. Files in PreToolUse/PostToolUse/PreCompact/Stop are unchanged from the marketplace-root version; this is a pure relocation so the per-plugin loader can find them. README updated to call out the per-plugin layout + pointer at the bug it addresses. Closes #1748 Issue 1 (the most load-bearing of the four — hooks not loading is the difference between Ruflo's auto-routing pitch and "26KB of inert tool definitions the model ignores"). Issues 2/3/4 from #1748 will land in follow-up PRs: - Issue 2 (spawned-agent --mcp-config wiring for hive-mind spawn) - Issue 3 (cold-cache 30s timeout / package size) - Issue 4 (tool description sharpening / lite default surface) Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
47704f83d8 |
fix(agents): coder agents now read docs/adr/*.md alongside docs/SPEC.md (#1749) (#1752)
* fix(agents): coder agents now read docs/adr/*.md alongside docs/SPEC.md (#1749) Issue #1749 (Coder agents ignore ADRs and only reference docs/SPEC.md) documents real architectural drift in spec-driven workflows: the Architect agent generates ADRs under docs/adr/, then Backend / Frontend coders are spawned and only consult docs/SPEC.md, ignoring the ADRs entirely. Code ends up out of sync with the architectural contract. This change updates three coder agent definitions to declare ADRs as authoritative inputs alongside SPEC.md: - .claude/agents/core/coder.md (the Task-tool default `coder` subagent) - .claude/agents/templates/implementer-sparc-coder.md (SPARC Refinement / Completion phase coder template) - plugins/ruflo-core/agents/coder.md (the plugin form) Each now contains an "Authoritative project documents" section that: 1. Mandates reading docs/SPEC.md AND docs/adr/*.md before architecture/scope-affecting work 2. States the contract explicitly: SPEC describes WHAT, ADRs describe HOW. ADRs are *binding* unless superseded by a newer Accepted ADR. 3. Calls out the multi-agent case explicitly: ADRs are the cross-agent contract that prevents bounded-context drift between parallel backend / frontend / tester implementations. 4. Tells coders that on conflict, they MUST surface it (propose either following the ADR or drafting a successor) rather than silently diverging. No code generation behavior change — only the prompts spawned coder agents see. Closes #1749. Co-Authored-By: RuFlo <ruv@ruv.net> * fix(agents): also wire ADR-awareness into sparc-coder template + ruflo-core/agents/coder.md (#1749) Companion to the previous commit on this branch. The first commit only landed for .claude/agents/core/coder.md because the Edit tool requires Read first for the other two files. This commit adds the same "Authoritative project documents" section to: - .claude/agents/templates/implementer-sparc-coder.md (SPARC coder) - plugins/ruflo-core/agents/coder.md (plugin form) Closes #1749 — all three coder agent variants now mandate reading docs/adr/*.md alongside docs/SPEC.md. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
4f1580bf18 |
docs(cost-tracker): consistency audit — agent + README mention all 13 skills (v0.16.1) (#1750)
Audit findings (now fixed): - cost-analyst.md mentioned only 3 of 13 skills. The agent didn't know about cost-budget-check, cost-trend, cost-conversation, cost-export, cost-federation, cost-summary, cost-benchmark, or cost-compact-context — capabilities silently invisible to spawned cost-analysts. - README skills table missing 4 rows: cost-conversation, cost-export, cost-federation, cost-summary. - README "Commands (8 subcommands)" header was stale (now 15) AND duplicated `cost budget set` line. Fixes: - agents/cost-analyst.md — replaced static "Tools" list with a 13-row Skills table (role + when-to-invoke per skill), updated MCP tool list to reflect actual usage (memory_*, hooks_route, hooks_model-outcome, hooks_worker-status), kept the existing Agent Booster / Background workers / Memory / Neural-learning sections. - README.md — added 4 missing skill rows; rewrote Commands block to the canonical 15-subcommand layout (no dupes). New smoke checks (now 48/48, ~85ms) prevent this drift recurring: 41. agent mentions every skill dir 42. README skills table has a row per skill dir 43. every script in scripts/ parses cleanly (node --check) 44. plugin.json parses as valid JSON + matches step-1 version sentinel Init verification: - plugin.json valid: name=ruflo-cost-tracker, version=0.16.1, 23 keywords - 10/10 scripts executable + parse - 13/13 skills with valid frontmatter - smoke 48/48 pass in ~85ms Branch: audit/cost-tracker-v0.16-consistency Version: 0.16.0 → 0.16.1 (patch — docs + smoke). Co-authored-by: Reuven <cohen@ruv-mac-mini.local> |
||
|
|
9c706d28a8 |
docs(cost-tracker): ADR-0003 + corpus v3 bench refresh (v0.16.0)
All 11 priorities from this session's implementation list are landed. ADR-0003 documents the v0.4 → v0.15 arc — what shipped, what's deferred (real MCP tool registration, upstream memory-store UNIQUE fix, federation Phase 3 producer), and the riskiest assumptions. Also persists the freshest measured bench (corpus v3, 25 cases, all 4 endpoints) — strongest verification yet: | Endpoint | Tier 1 | Adv | Avg latency | Cost/edit | Speedup | |-----------------|--------|------|-------------|------------|---------| | Booster (WASM) | 18/18 | esc | 0.36 ms | $0 | — | | Gemini 2.0 | 18/18 | 3/7 | 807.56 ms | $0.000028 | 2243× | | Sonnet 4.6 | 18/18 | 2/7 | 1270.64 ms | $0.000933 | 3530× | | Opus 4.7 | 18/18 | 5/7 | 1563.72 ms | $0.005943 | 4344× | New finding: Sonnet 4.6 only solves 2/7 adversarial cases — booster's "correctly refuse" path beats Sonnet on routing-correctness, not just speed. Smoke step 8 now also verifies ADR-0002 + ADR-0003 are Accepted. Cron c0b44f45 cancelled — implementation list complete. Version: 0.15.0 → 0.16.0. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
129a6b405f |
feat(cost-tracker): P9 — programmatic cost-summary contract (v0.15.0)
ADR-0002 considered MCP tools cost_report / cost_summary but explicitly
deferred them — adding registered MCP tools requires modifying
@claude-flow/cli source, out of scope for plugin-local work and
deserving its own ADR. P9 ships the plugin-local equivalent: a single
script with a stable JSON contract that any consumer (other plugins,
dashboards, Slackbots) can shell out to.
What lands:
- scripts/summary.mjs — single-shot dump from cost-tracking +
federation-spend namespaces. Output shape (stable contract):
{ exportedAt, total_cost_usd, sessionCount, conversationCount,
byTier, byModel, topSession, budget, federation }
Markdown is the default; --format json for programmatic consumers.
- skills/cost-summary/SKILL.md — documents the contract
- `cost summary [--format ...]` subcommand
- 1 new smoke check (39c)
Live verified: total $1546.36, 1 session, all Opus, budget $2500
configured, INFO alert level (61.9%), federation aggregate 0/0/$0
(Phase 3 not emitting yet).
Version: 0.14.0 → 0.15.0. Keywords: + interop.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
1c08043159 |
feat(cost-tracker): P6 — ADR-097 Phase 3 federation_spend consumer (v0.14.0)
ADR-097 Phase 1 (federation_send budget envelope) is landed; Phase 3
(federation_spend event bus that publishes per-completion {peerId,
taskId, tokensUsed, usdSpent, ts}) is deferred upstream. This plugin
is the declared consumer of those events. P6 wires the consumer side
so it activates the moment Phase 3 emits.
What lands:
- scripts/federation.mjs — reads namespace `federation-spend` for keys
`fed-spend-*`, aggregates per-peer 1h/24h/7d rolling windows, flags
peers exceeding the suspension threshold (default $5/24h per ADR-097
Phase 2). FED_FORMAT=json for machine-readable; FED_NAMESPACE and
FED_SUSPEND_THRESHOLD_USD overrides.
- skills/cost-federation/SKILL.md — documents the consumer contract
(event shape, namespace, key prefix) so upstream knows where to write
- `cost federation` subcommand
- 1 new smoke check (39b — pre-39a)
Live verified by injecting two mock events:
- peer-alice $0.045 → no flag
- peer-bob $7.50 → ⚠ flagged over $5/24h threshold
Phase 3 status: not yet emitting upstream. Skill prints "no events
found, will activate when upstream lands" and exits cleanly.
Version: 0.13.0 → 0.14.0. Keywords: + federation.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
3ea80a9a9c |
feat(cost-tracker): P10 — telemetry export (Prometheus + webhook) (v0.13.0)
Cost data lived only inside the cost-tracking AgentDB namespace; nothing
in the plugin emitted it for external dashboards. P10 closes that gap.
What lands:
- scripts/export.mjs — gather sessions + budget config, emit:
• --prometheus <path>: node_exporter textfile-collector format
(cost_tracker_total_usd, _tier_total_usd, _session_total_usd,
_session_messages, _budget_usd, _budget_utilization). Drop the
file in the collector directory and Prometheus picks it up.
• --webhook <url>: POST JSON {sessions, budget, totalUsd, byTier,
exportedAt}. Auth via EXPORT_WEBHOOK_HEADER='K: V, K2: V2'.
• no flag: stdout JSON.
- skills/cost-export/SKILL.md
- `cost export [--prometheus|--webhook]` subcommand
- 1 new smoke check (39a — pre-CI step)
Live verified: wrote /tmp/cost-tracker-test.prom with this session's
$1546.36 total + 1597-message Opus record + the $2500 budget config
+ utilization gauge (0.6185).
Version: 0.12.0 → 0.13.0. Keywords: + prometheus, + observability.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
088e18f174 |
feat(cost-tracker): P11 — cost-per-conversation view (v0.12.0)
cost-report / cost-optimize aggregate by agent and model. P11 adds the per-conversation lens: each session in cost-tracking gets one row with started-at, message count, top model, and total cost. Useful for retrospectives and project-level rollups. What lands: - scripts/conversation.mjs — list memory-keys starting with `session-`, retrieve each, sort by startedAt, render markdown table with per-tier totals + per-conversation rows. CONV_FORMAT=json for machine-readable; CONV_LIMIT=N to truncate; CONV_NAMESPACE to override. - skills/cost-conversation/SKILL.md - `cost conversation` subcommand - 1 new smoke check (40a — pre-CI step), now 41/41 Live verified on this checkout: 1 conversation tracked, $1546.36 total, all Opus 4.7 (heavy cache-read pattern). Version: 0.11.0 → 0.12.0. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
4b3169df91 |
feat(cost-tracker): P8 — GitHub Actions smoke + booster bench on PR (v0.11.0)
Wires the binary smoke gate + booster-only bench into CI so plugin
regressions surface before merge. LLM/Anthropic baselines are
intentionally excluded — they cost real money per invocation and
belong in a scheduled or manually-triggered workflow with a budget
guard, not on every PR.
What lands:
- .github/workflows/cost-tracker-smoke.yml — triggers on push/PR/
workflow_dispatch when plugins/ruflo-cost-tracker/** changes:
1. Run smoke (40+ checks, ~85ms)
2. Install agent-booster@^0.2 in .ci-bench/ sandbox
3. Run booster-only bench from that sandbox
4. Run trend.mjs (sanity check on persisted runs)
5. Verify Tier 1 winRate ≥ 0.80 (regression gate)
6. Upload runs/latest.json as artifact (30-day retention)
- README.md: pointer to the workflow + explicit note that LLM
baselines are NOT run in CI
- Smoke step 40: asserts the workflow file exists, references
smoke.sh + bench.mjs, has the winRate gate, and crucially does
NOT include BENCH_LLM_BASELINE or BENCH_ANTHROPIC (cost guard)
Version: 0.10.0 → 0.11.0. Keywords: + ci.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
c16114659a |
feat(cost-tracker): P7 — corpus v3 expansion (16 → 25 cases) (v0.10.0)
Stronger verification — adds 6 Tier 1 + 3 adversarial cases. Tier 1 added (booster should apply): - var-to-let-1, double-quote-to-single, add-readonly-prop, remove-debugger, import-add-named, remove-trailing-semis Adversarial added (booster should escalate): - adversarial-extract-class (class delegation refactor) - adversarial-callback-to-promise (control-flow rewrite) - adversarial-deeply-nested-conditional (guard-clause flattening) Live verified on the 25-case corpus: - Tier 1 win rate: 100% (18/18) - Escalation rate: 100% (7/7) — every adversarial case fell below 0.5 confidence threshold, min 0.000 - Avg latency: 0.32 ms (improvement; new Tier 1 cases are simpler) - Booster's qualitative win is unchanged: correct apply + correct refuse, faster than any LLM Smoke step 24 now requires 18+ Tier 1, 6+ adversarial, 25+ total. Corpus version: 2 → 3. Plugin: 0.9.0 → 0.10.0. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
89d7584b45 |
feat(cost-tracker): P5 — cost-trend skill surfaces drift across bench runs (v0.9.0)
The smoke gate is binary (winRate ≥ 0.80 → pass). A win rate slowly
creeping from 100% to 85% would still "pass" smoke but represents real
degradation. cost-trend turns the gate into a curve.
What lands:
- scripts/trend.mjs — reads every docs/benchmarks/runs/*.json (excluding
latest.json), reports first→last deltas on winRate, avg/p99 latency,
escalationRate, speedupVsLlm; per-run series with Sonnet 4.6 + Opus 4.7
latency columns; regression flags (`⚠ Regression`) when win rate drops
or avg latency rises ≥ 1.5×
- skills/cost-trend/SKILL.md
- `cost trend` subcommand
- 2 new smoke checks (now 39/39): trend.mjs has metrics + regression
flag, ruflo-cost.md documents the subcommand
Live verified on the 6 persisted runs from this session:
- Win rate stable at 100% across all 6
- Avg latency drifted 0.58ms → 0.50ms (slight improvement)
- Sonnet 4.6 latency varied 1072→1158ms (real LLM noise visible)
- Escalation rate appeared in last 2 runs (corpus v2 added adversarial
cases — backward-compat preserved)
Optional env: TREND_FORMAT=json, TREND_LIMIT=N.
Version bump: 0.8.0 → 0.9.0. Keywords: + trend-analysis.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
8f580f207b |
feat(cost-tracker): P4 — encapsulate compact-context Node block as compact.mjs (v0.8.0)
Drops the inline `node --input-type=module -e '...'` block from cost-compact-context. Replaced with a proper script that: - resolves @claude-flow/integration from process.cwd() (so users can `cd v3 && node ../plugins/.../compact.mjs "<query>"`) - prints a markdown table by default, JSON via COMPACT_QUIET=1 - catches bridge-unavailable cases cleanly True MCP-tool wrapping (modifying @claude-flow/cli) is deferred — directive excludes unrelated v3 changes. This is the plugin-local equivalent: one entry point, no inline JS in skill text. Live verified from v3/: returns documented fallback shape (agenticFlowAvailable: false, "bridge returns inert results") because agentic-flow isn't installed in v3/node_modules. Smoke: 37/37. Version: 0.7.0 → 0.8.0. Co-Authored-By: RuFlo <ruv@ruv.net> |
||
|
|
333e6338d9 |
feat(cost-tracker): P3 — auto-emit hooks_model-outcome (v0.7.0)
cost-optimize step 8 was documented but manual; an agent would have to
hand-construct the JSON and shell-quote correctly. Now wired to a tight
wrapper script that takes (task, model, outcome) as positional args and
spawns hooks_model-outcome with explicit argv.
What lands:
- scripts/outcome.mjs — validates outcome ∈ {success, escalated, failure}
and shells `npx @claude-flow/cli hooks model-outcome -t <task> -m <model> -o <outcome>`
with spawnSync (no shell-escape risks)
- skills/cost-optimize/SKILL.md step 8 — replaced manual JSON
instruction with a copy-pasteable command pattern that uses outcome.mjs
- `cost outcome <task> <model> <outcome>` subcommand
- 3 new smoke checks (now 36/36): cost-optimize references outcome.mjs,
outcome.mjs has spawnSync + validation, command is documented
Live verified: emitted "convert var to const in src/utils.ts" with
model=haiku, outcome=success. Router responded:
[OK] Outcome recorded for haiku: success
This closes the routing feedback loop documented in ruflo-intelligence
ADR-0001 §"Neutral" (legacy routing-outcomes namespace migration).
Version bump: 0.6.0 → 0.7.0. Keywords: + model-outcome.
Co-Authored-By: RuFlo <ruv@ruv.net>
|
||
|
|
5d2f860802 |
feat(cost-tracker): P2 — real budget enforcement (v0.6.0)
Wires the 50/75/90/100% alert ladder that REFERENCE.md documented but
no code enforced. Budget config now persists to cost-tracking namespace
with timestamped keys (workaround for a UNIQUE-constraint quirk in the
@claude-flow/cli memory layer where store and retrieve disagree on
existing keys).
What lands:
- skills/cost-budget-check/SKILL.md — agent-facing instructions
- scripts/budget.mjs — three subcommands:
• set <usd> — write budget-config-<timestamp> to cost-tracking
• get — list budget-config-* and resolve the lexicographically
latest (timestamps are equal-width, sort correctly)
• check — sum total_cost_usd across session-* records, compute
utilization, emit 🟢 OK / 🟡 INFO / 🟠 WARNING /
🔴 CRITICAL / 🛑 HARD_STOP. Exits 1 on HARD_STOP so
callers can guard agent spawns: `budget check && spawn ...`
- 3 new smoke checks (now 33/33): budget skill exists with alert ladder,
budget.mjs has alertLevel + process.exit(1), and ruflo-cost.md
documents set/get/check subcommands.
Live verified on this session:
- set $2000 → ✓
- update to $2500 → ✓ (timestamped record pattern)
- check at $2500 budget vs $1546.36 measured spend → 61.9% / 🟡 INFO
- check at $50 budget → 3092.7% / 🛑 HARD_STOP, exit 1
Period filter: BUDGET_PERIOD=today|week|month|all (default all).
Machine-readable JSON: BUDGET_QUIET=1.
Version bump: 0.5.0 → 0.6.0. Keywords: + budget.
Co-Authored-By: RuFlo <ruv@ruv.net>
|