Commit Graph

5 Commits

Author SHA1 Message Date
ruvnet e332689b8c fix(release): harden hooks, statusline, security, and plugin MCP integration 2026-07-16 23:06:29 -04:00
ruv 4d7515cd06 darwin-plugins iter 2 — ruflo-agent: document nested-subagents skill in README 2026-06-26 20:12:10 -04:00
rUv f5a180423d feat(agents): ADR-147 nested subagent (depth=5) infrastructure + P2 stage 1 (#2336)
* docs(adr): add ADR-147 — nested subagent capability integration (depth=5)

Captures the integration plan for the nested-subagent capability Boris
Cherny announced 2026-06-09 (depth=5 cap). Based on direct inspection
of CLI 2.1.169: the plumbing (parentAgentId propagation, hasTaskTool
per-spawn gate, Agent/Task tool aliasing, parent_agent_id OTel tag) is
in the shipped binary, but the depth=5 cap is not encoded as named
symbols and zero ruflo agent definitions declare a tools: field — so
spawned children currently inherit hasTaskTool=false.

Four-phase rollout: grant Task only to orchestrator-class agents
(P1), capture parent_agent_id into AgentDB on post-task (P2),
depth-aware pre-task guardrail with cap=4 default behind
CLAUDE_FLOW_STRICT_NESTING (P3), rewrite CLAUDE.md queen-coordinator
pattern + cross-reference ADR-099/143/144 (P4).

Refs ruvnet/ruflo#2335

Co-Authored-By: RuFlo <ruv@ruv.net>

* feat(ruflo-agent): add nested-subagent agents + skill (ADR-147 P1)

Adds four orchestrator/leaf agent definitions to the ruflo-agent
plugin, each with an explicit tools: frontmatter — the missing piece
that lets spawned children inherit Claude Code 2.1.169's hasTaskTool
gate and actually nest.

  nested-coordinator  — generic deep-delegation orchestrator (has Task)
  nested-researcher   — recursive research orchestrator (has Task)
  nested-reviewer     — find→adversarial-verify reviewer (has Task)
  nested-leaf         — leaf-worker template, deliberately no Task
                        (demonstrates the least-privilege boundary)

Plus a paired SKILL.md (skills/nested-subagents/) documenting when to
nest vs. flat fan-out, the depth budget (cap=4 default, 5 API), and the
required child-summary contract.

Implements P1 of ADR-147. Refs ruvnet/ruflo#2335.

Co-Authored-By: RuFlo <ruv@ruv.net>

* feat(ruflo-agent): add nested-queen — full-ruflo-stack nested orchestrator

Companion to nested-coordinator. Where nested-coordinator gives just
depth (Claude Code Task tool, depth=5 cap), nested-queen wires the
nested spawn tree into ruflo's existing machinery:

  - swarm_init + hive-mind_spawn (queen role, raft consensus)
  - hive-mind_consensus / coordination_consensus for branch decisions
    (replaces inline averaging in the diverse-lens reviewer pattern)
  - hooks_intelligence_* RETRIEVE -> JUDGE -> DISTILL -> CONSOLIDATE
    pipeline (full ADR-074..088 alignment), with trajectory tracking
    per spawn
  - memory_store / memory_search_unified for tree-shape patterns
    (HNSW-indexed lookup of prior similar trees before spawning)
  - claims_claim / claims_handoff / claims_load — ADR-144 AuthScope
    monotonic reduction enforced at every parent->child hop
  - aidefence_scan / aidefence_is_safe on outbound prompts and inbound
    child summaries — ADR-131 / ADR-146 P2 boundary
  - cost-budget pre-spawn check (refuse early when budget tight)
  - Five hard constraints made explicit: depth budget, scope monotonicity,
    AIDefence reject = no consume, pre-spawn budget, mandatory
    trajectory close

Selection guidance: default to nested-coordinator; use nested-queen
only when consensus, tree-shape learning, scope enforcement, content
gating, or hard cost budget is genuinely required. The overhead is
~10x for a reason.

Refs ADR-147, ADR-144, ADR-131, ADR-146, ADR-099, ADR-097.
Refs ruvnet/ruflo#2335.

Co-Authored-By: RuFlo <ruv@ruv.net>

* feat(ruflo-agent): tier-2 specialists — queen-researcher, queen-reviewer, queen-leaf

Mirrors the tier-1 specialist lineup (researcher / reviewer / leaf)
at tier 2 — each wires its role into ruflo's full machinery:

  nested-queen-researcher
    - HNSW pattern-search of prior research trees before spawning
    - hive-mind raft consensus on which followups to pursue (replaces
      silent inline ranking — the bias defence)
    - AIDefence on both outbound prompts (web content quoted in) and
      inbound child summaries (injected results)
    - Full trajectory record + EWC-consolidated pattern-store per tree

  nested-queen-reviewer
    - Phase 2 verifier vote becomes hive-mind byzantine consensus
      (tolerates f < N/3 lying verifiers); raft for the diverse-lens
      variant where verifiers aren't byzantine
    - AIDefence on diff content forwarded to verifiers + verifier
      reasoning returned
    - Pattern-store of review-tree shapes — what catches bugs vs FPs

  nested-queen-leaf
    - Still no Task tool (ADR-147 P1 least-privilege boundary)
    - AIDefence-scans its own inbound prompt; refuses on reject
    - claims_load confirms inherited AuthScope is still valid
    - Records hooks_intelligence_trajectory-step on completion (success
      or failure) — the leaf's contribution to the queen's learning
      pipeline

Together with nested-queen, the tier-2 set now mirrors tier-1
one-for-one. Selection rule remains: default to tier 1; reach for
tier 2 only when consensus, content gating, scope enforcement, or
tree-shape learning genuinely earns the overhead.

Refs ADR-147, ADR-144, ADR-131, ADR-146, ADR-099.
Refs ruvnet/ruflo#2335.

Co-Authored-By: RuFlo <ruv@ruv.net>

* test(adr-147): empirical depth probe + ADR P1 validation results

Adds scripts/probe-nested-spawn-depth.mjs — runs claude -p with
ruflo-agent:nested-coordinator, drives a self-replicating chain
L1->L2->... until refusal or test-limit (level 7), and reports
the observed cap. Writes results to docs/probes/.

Two runs against CLI 2.1.169 (one with default env, one with
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1). Both return:
  FINAL: level=1 status=NO_AGENT_TOOL

Empirical finding: declaring tools: [Task] in an agent's YAML
frontmatter is necessary but not sufficient in 2.1.169. The plugin
loader honors the field (claude plugin details lists the agent with
its declared tool set), but the runtime's parent->child spawn does
not propagate Task to the child based on the child's YAML allow-list.
No env-var or CLI flag found unlocks it.

ADR-147 Validation section updated with the full empirical block:
  - P1 infrastructure (agents + skill) is shipped and correct
  - End-to-end verification of the depth=5 cap is NOT possible in
    2.1.169 — runtime gate appears to be server-side or held behind
    a feature rollout not yet user-enableable
  - P2 + P3 explicitly deferred until the probe returns a positive
    verdict; both require a working nested spawn to exercise
  - P4 must NOT claim nested spawning is currently usable
  - The probe stays in-tree as the regression test — re-running it
    after future CLI upgrades is the first verification step

This is the honest "P1 actually complete" answer: infrastructure
landed, empirical limit captured, follow-on phases gated on the
runtime activation we cannot force from outside the binary.

Refs ruvnet/ruflo#2335

Co-Authored-By: RuFlo <ruv@ruv.net>

* docs(adr-147): add Path-2 sweep findings — denylist confirmed

Sharpens the empirical block in ADR-147 with results from the
four-variant CLI flag sweep:

  - Control (no flags):              L1 has Read,Grep,Glob,Bash
  - --allowedTools (incl Task,Agent): same
  - --permission-mode bypassPermissions: same
  - --agent nested-coordinator (lead is nc): same

All four return EXACTLY the same 4-tool list. Our YAML declares 6
tools (Task, Read, Grep, Glob, TodoWrite, Bash). 4 propagate, 2 are
stripped. The runtime applies a hardcoded denylist that drops Task
and TodoWrite at parent->child spawn time. The strip is consistent
across permission modes, lead agent identity, and explicit
--allowedTools grants -- so the gate is server-side or hardcoded
on specific tool names, not a user-facing toggle.

Favorable for P1: the YAML mechanism IS the right opt-in shape.
Our agents are declaratively correct. When the denylist for Task
lifts (whether by a future build, a server-side rollout, or a
discovered opt-out flag), nested spawning activates with zero
code changes to ruflo's agents.

Refs ruvnet/ruflo#2335

Co-Authored-By: RuFlo <ruv@ruv.net>

* feat(hooks): ADR-147 P2 stage 1 — thread parent_agent_id + depth through post-task

Wires the nested-subagent spawn-tree lineage through the post-task
hook chain so when Claude Code starts populating the
`x-claude-code-parent-agent-id` header (or its OTel span tag) on
spawned subagents, callers can pass it through and the data lands
in the existing feedback storage WITHOUT a schema migration.

Path: CLI flags -> MCP tool input schema -> bridgeRecordFeedback ->
LearningSystem.recordFeedback + memory entry (JSON.stringify(options)
on bridgeStoreEntry preserves the new fields automatically).

Changes:
  - commands/hooks.ts:     post-task gains --parent-agent-id and --depth flags
  - mcp-tools/hooks-tools.ts: hooks_post-task input schema gains parentAgentId
                              (string, validateIdentifier) and depth (integer,
                              0 <= d <= 32). Both optional; rejection returns
                              typed error and short-circuits before bridge call.
  - memory/memory-bridge.ts: bridgeRecordFeedback options extended; forwarded
                             to LearningSystem.recordFeedback. JSON.stringify
                             at the bridgeStoreEntry call picks them up for the
                             persisted memory entry automatically.

Tests (vitest, 7 cases, all green):
  - propagation when supplied
  - omission when not supplied (top-level lead path)
  - depth=0 boundary (must propagate as 0, not be coerced to undefined)
  - validation rejects invalid parentAgentId
  - validation rejects negative depth
  - validation rejects non-integer depth
  - validation rejects depth > 32 (defensive bound)

Why this is testable today despite the runtime denylist documented
in ADR-147 P1: the OTel parent_agent_id tag the binary emits already
exists for flat depth-1 spawns. The same code path captures it for
a depth-5 chain once the Task-tool denylist lifts upstream — no
further code changes needed.

DEFERRED to P2 stage 2 (separate PR):
  - Dedicated parent_agent_id + depth columns on the feedback /
    trajectories table (currently lands in the JSON metadata blob)
  - Automatic capture from the active OTel span context (currently
    caller must pass via CLI/MCP)
  - Query API to read the spawn tree by agent_id (downstream of the
    dedicated columns)

Refs ruvnet/ruflo#2335

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-06-09 12:15:03 -04:00
rUv 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>
2026-05-12 10:35:28 -04:00
rUv 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>
2026-05-12 10:24:03 -04:00