Skip to content

feat(orchestration): local-exec device tool + trust gate + async completion forward (stacked on #4738)#4753

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:feat/1074-r3-local-exec-device-tool
Jul 10, 2026
Merged

feat(orchestration): local-exec device tool + trust gate + async completion forward (stacked on #4738)#4753
senamakel merged 1 commit into
tinyhumansai:mainfrom
sanil-23:feat/1074-r3-local-exec-device-tool

Conversation

@sanil-23

@sanil-23 sanil-23 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Give the hosted orchestration brain back local execution (retired in the hosted-only migration, #4738) as a gated device tool, restricted to Master-chat cycles, with an async completion-forward so the result re-enters the brain via a fresh wake cycle.

Builds on #4738 (now merged into main). Rebased onto merged main — this is a clean single-commit PR with only the R3 diff. No backend change is required.

Problem

#4738 moved the brain to the cloud and deleted the client's local code_executor / spawn_async_subagent from the orchestration path — so the hosted brain lost the ability to run code / touch files on the user's machine. We want that back, but only when the human is driving their own agent (Master chat), never when an external agent's DM (A2A) triggered the cycle — otherwise a prompt-injected reasoning turn could induce local code execution / file exfiltration (confused-deputy).

Solution (scope: core)

  1. run_local_agent device tool (orchestration/effect_executor.rs) — declared in the device manifest; spawns a local sub-agent (code_executor, researcher, tools_agent, …) via SpawnSubagentTool and forwards its result.
  2. Device-authoritative trust gate (orchestration/exec_gate.rs) — records cycleId -> (counterpart, session) at forward time (from what the device itself forwarded, not what the backend asserts) and authorizes local-execution tools only when the cycle's counterpart is LOCAL_MASTER_AGENT. Unknown / A2A cycles fail closed. Enforced in effect_executor — on the device that holds the capability — so an injected or compromised cloud brain cannot induce local execution for an A2A cycle.
  3. Async completion modelrun_local_agent returns an immediate accepted ack (well inside the device-tool timeout, so the wake cycle never blocks) and runs the sub-agent in the background; on completion the result is forwarded up as a tool_completion event, which wakes a fresh cycle that reasons over it.
  4. Origin capturecloud::push_event now returns the backend cycleId (from the 202), recorded at both forward sites (ingest.rs, schemas.rs).

No backend change: executeLoop already surfaces device-declared tools to the model, the /v1/events route already fires runWakeForCycle on any non-duplicate event, and the event kind field is unconstrained — so the tool_completion forward rides the existing ingest→wake path.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) — tests/orchestration_exec_gate.rs (master authorized, A2A denied, unknown fail-closed, cycle_target routing) + inline exec_gate unit tests.
  • Diff coverage ≥ 80%N/A: the Rust Core Coverage gate can't run — cargo test --lib is broken repo-wide on main (the refactor(orchestration): hosted-only brain — retire the client local orchestration engine (Phase 4) #4738 merge commit e5c6507c is also red on this check; ~30 unrelated modules fail to compile in the cfg(test) build, the known breakage orchestration/cloud.rs documents). The R3 gate logic is covered via the integration test (which links the compiled lib, bypassing cfg(test)); the run_local_agent spawn/forward path needs a runtime (e2e follow-up).
  • Coverage matrix updated — N/A: Coverage Matrix Sync passes; device-tool wiring has no matrix feature id.
  • All affected feature IDs listed under ## Related.
  • No new external network dependencies — reuses the existing backend client + orchestration socket.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: behind the hosted path, no release-cut UI surface.
  • Linked issue referenced in ## Related.

Impact

  • Runtime/platform: desktop only. No mobile/web change.
  • Security: restores local execution but fenced to the Master-chat surface via a deterministic, device-authoritative gate (fail-closed); A2A / injected cycles cannot reach local code or files. See the trust-split rationale in the commit.
  • Behavior: the brain can delegate local work (e.g. code_executor) on the user's machine when the human asks; the result arrives asynchronously as a follow-up cycle, so long tasks never time out the original cycle.

Known follow-ups (not in this PR)

  • Structured toolCallId correlation for the completion (today it re-enters as flattened rawInput text — works with the current backend prompt).
  • Optional agent_id allowlist inside run_local_agent (today any registered sub-agent is spawnable on a Master cycle).
  • A loop-depth guard on completion-triggered cycles.

Related

Summary by CodeRabbit

  • New Features

    • Added support for running a local agent from the app and returning results asynchronously.
    • Added new read-only access to hosted orchestration data, including sessions, messages, and steering info.
    • Improved hosted service startup and shutdown handling for a smoother connected experience.
  • Bug Fixes

    • Improved event forwarding so successful requests now preserve returned cycle information.
    • Tightened access controls for local execution tools to reduce unauthorized runs.
    • Fixed background processing so completed tool runs are properly recorded and delivered.

@sanil-23 sanil-23 requested a review from a team July 9, 2026 16:54
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fecf7820-25ed-4540-8a7c-6e526976bd65

📥 Commits

Reviewing files that changed from the base of the PR and between 5a2ecf2 and 47cc95a.

📒 Files selected for processing (9)
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/socket/event_handlers.rs
  • tests/orchestration_exec_gate.rs
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/orchestration/schemas.rs
  • tests/orchestration_exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/cloud.rs

📝 Walkthrough

Walkthrough

This PR adds cycleId-aware hosted cloud pushes, a hosted GET read surface (sessions/messages/steering), a device-authoritative exec gate tracking cycle origins, a gated run_local_agent tool with background execution and tool_completion forwarding, and hosted-client lifecycle start/stop control.

Changes

Hosted orchestration flow and execution gate

Layer / File(s) Summary
Cloud push/read surface
src/openhuman/orchestration/cloud.rs
post_with_retry returns JSON; push_event/push_event_with extract an optional cycleId; push_world_diff(_with) discard the JSON body; a new ReadPass type provides authenticated fetch_sessions, fetch_messages, and fetch_steering.
Execution gate and cycle origin tracking
src/openhuman/orchestration/exec_gate.rs, mod.rs, ingest.rs, schemas.rs, migrate_history.rs, tests/orchestration_exec_gate.rs
Adds a bounded in-memory cycle-origin store with record_cycle_origin, cycle_is_master, cycle_target, and is_local_execution_tool; call sites in ingest, schemas, and migrate_history record cycle origins after successful push_event calls; unit and integration tests cover authorization behavior.
Hosted-client service lifecycle
src/openhuman/orchestration/mod.rs
Adds HOSTED_CLIENT_TASKS, start_hosted_client_services, and stop_hosted_client_services to manage sync, flush, and migration background tasks based on orchestration enablement.
Local-agent tool dispatch
src/openhuman/orchestration/effect_executor.rs, src/openhuman/socket/event_handlers.rs
Adds run_local_agent to the tool manifest, makes dispatch_device_tool/handle_tool_call async with a master-cycle capability gate, runs local sub-agent execution in a background task that persists a completion message and pushes a tool_completion event, and moves socket tool-call handling into a spawned task.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Socket
  participant EffectExecutor
  participant ExecGate
  participant LocalAgentTask
  participant Cloud
  Socket->>EffectExecutor: orch:tool_call (run_local_agent)
  EffectExecutor->>ExecGate: cycle_is_master(cycle_id)
  ExecGate-->>EffectExecutor: allow / deny
  alt allowed
    EffectExecutor->>LocalAgentTask: spawn run_local_agent
    EffectExecutor-->>Socket: accepted/running result
    LocalAgentTask->>LocalAgentTask: execute SpawnSubagentTool
    LocalAgentTask->>Cloud: push_event(tool_completion)
    Cloud-->>LocalAgentTask: cycleId
    LocalAgentTask->>ExecGate: record_cycle_origin
  else denied
    EffectExecutor-->>Socket: error result
  end
Loading

Possibly related PRs

  • tinyhumansai/openhuman#4660: Prior changes to cloud::push_event/exec_gate cycle-origin recording in ingest.rs and schemas.rs connect to this PR's same forwarding path.
  • tinyhumansai/openhuman#4738: Both PRs modify the hosted cloud.rs client layer, including the /orchestration/v1/* read/write helpers.

Suggested labels: rust-core, agent, feature

Poem

A rabbit hops the cycle's trail,
Checking gates before local mail. 🐰
run_local_agent waits its turn,
Only masters get to earn.
Push, record, and forward on—
Burrows synced till dawn. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: gated local-exec tooling with async completion forwarding.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. labels Jul 9, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ae1f80c21

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

/// hosted brain ships every terminal reply as a `send_dm`; the device decides
/// whether that reply is for a peer or for the user's own window.
fn is_self_session(session_id: &str) -> bool {
session_id.is_empty() || session_id == "master" || session_id == "subconscious"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Don't treat peer Master replies as self replies

In the peer-DM path, ingest::classify_message assigns plain external DMs to session_id master while counterpart_agent_id remains the peer. With this predicate, handle_send_dm takes the self-session return path for those hosted replies and never calls execute_send_dm, so responses to external Master-window DMs are only cached locally and are not sent over Signal. Please key self replies on the local counterpart, e.g. LOCAL_MASTER_AGENT, instead of the session id alone.

Useful? React with 👍 / 👎.

use crate::openhuman::tools::traits::Tool;
// 1. Run the local sub-agent synchronously to completion (real output).
let tool = crate::openhuman::agent_orchestration::tools::SpawnSubagentTool::new();
let result = tool.execute(run_args).await.map_err(|e| e.to_string())?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Force local agent spawns to run synchronously

For manifest-compliant run_local_agent calls, the args contain only agent_id/prompt/context. SpawnSubagentTool defaults blocking to false, so from this socket background task with no current_parent it routes into SpawnAsyncSubagentTool and returns spawn_async_subagent called outside of an agent turn; with a parent it would still forward only an async reference. As a result the device tool accepts the request but forwards a failed/placeholder completion instead of the local sub-agent's output. Force blocking: true or call a blocking runner before forwarding.

Useful? React with 👍 / 👎.

ts,
"tool_completion",
);
super::cloud::push_event(&config, &envelope).await?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record the cycle created by tool completions

This new forward site ignores the cycleId returned by push_event, unlike the master ask and ingest forwarders. The tool_completion event wakes a fresh Master cycle; if that follow-up cycle needs another local-execution tool, exec_gate has no origin recorded for it and fails closed, so multi-step local work stalls after the first completion. Record the returned cycle id for the same counterpart/session before returning.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
scripts/ci/orch-ip-gate.sh (1)

38-41: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Model-metadata check only covers .toml files.

If agent-tier/model routing metadata were reintroduced in a different format (Rust source, JSON, YAML config), this check wouldn't catch it. Consider whether the metadata format is guaranteed to stay TOML-only, or broaden the scan.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/orch-ip-gate.sh` around lines 38 - 41, The model-metadata gate in
orch-ip-gate.sh only scans orchestration TOML files, so reintroduced agent_tier
or [model] routing metadata in other formats could slip through. Update the
check around the grep in the metadata validation block to either explicitly
document that TOML is the only supported source of this metadata or broaden the
scan in the relevant orchestration area to include the additional config/source
formats you want covered.
src/openhuman/orchestration/mod.rs (1)

41-111: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

mod.rs should be export-only; move hosted-client lifecycle logic into a sibling module.

This block adds a static (HOSTED_CLIENT_TASKS) plus business logic (abort_hosted_client_tasks, start_hosted_client_services, stop_hosted_client_services) directly in mod.rs. Per repo convention, mod.rs files must contain only mod/pub mod, pub use, and controller-schema wiring. Consider relocating this into a domain sibling (e.g. hosted_client.rs) and re-exporting the two public entrypoints from here.

As per coding guidelines: "mod.rs files must be export-only: mod/pub mod, pub use, and controller schema wiring only; no business logic."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/orchestration/mod.rs` around lines 41 - 111, The hosted-client
lifecycle logic is incorrectly implemented inside mod.rs instead of being
export-only. Move HOSTED_CLIENT_TASKS, abort_hosted_client_tasks,
start_hosted_client_services, and stop_hosted_client_services into a sibling
module such as hosted_client.rs, then re-export the public entrypoints from
mod.rs. Keep mod.rs limited to module declarations, pub use, and
controller-schema wiring, and preserve the existing behavior around task
abort/restart and orchestration.enabled.

Source: Coding guidelines

app/src/components/intelligence/pixiGraphRenderer.test.ts (1)

65-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stub removeChildren() diverges slightly from real PIXI API.

Real Container.removeChildren() accepts beginIndex/endIndex and returns the removed children array; this stub always clears everything and returns undefined. Fine as long as the code under test doesn't consume the return value or a partial range.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/components/intelligence/pixiGraphRenderer.test.ts` around lines 65 -
67, The `removeChildren()` stub in `pixiGraphRenderer.test.ts` does not match
the real PIXI `Container.removeChildren()` API, which can take
`beginIndex`/`endIndex` and returns the removed children array. Update the stub
on the test container mock to accept those parameters and return the removed
items so any code using partial removal or the return value behaves consistently
with PIXI.
src/openhuman/orchestration/effect_executor.rs (1)

196-222: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Structured ok/is_error/tool_name fields left unset on the completion message.

ok is computed but only embedded in free text; the message's own structured columns (used elsewhere for filtering/rendering) stay at their defaults.

♻️ Proposed fix
         super::store::insert_message(
             conn,
             &super::types::OrchestrationMessage {
                 id: format!("tool-completion:{task_id}:{seq}"),
                 agent_id: counterpart.to_string(),
                 session_id: session_id.to_string(),
                 chat_kind: super::types::ChatKind::Master,
                 role: "system".to_string(),
                 body: body.clone(),
                 timestamp: now.clone(),
                 seq,
+                tool_name: Some(agent_id.to_string()),
+                ok: Some(ok),
+                is_error: Some(!ok),
                 ..Default::default()
             },
         )?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/orchestration/effect_executor.rs` around lines 196 - 222, The
completion message built in `effect_executor.rs` computes `ok` but never writes
it into the structured fields on `super::types::OrchestrationMessage`, so
downstream filtering/rendering can’t use it. Update the `OrchestrationMessage`
created in the `insert_message` path to set the appropriate completion metadata
fields (`ok`, `is_error`, and `tool_name`) alongside the existing `body`, and
keep the free-text body as a human-readable summary only. Use the existing
`body` construction and the `tool-completion:{task_id}:{seq}` message creation
block as the place to set these fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/orchestration/effect_executor.rs`:
- Around line 578-610: The evict handler in handle_evict is treating a callId as
successfully completed as soon as it is seen, so retries after a real
execute_evict failure get re-acked as success. Update the dedupe flow so
is_duplicate_call/effect tracking reflects the actual outcome: only mark the
call as completed after execute_evict succeeds, or store and replay the prior
(ok, error) result for duplicates. Keep the duplicate protection in
effect_executor::handle_evict, but make sure failed attempts are not recorded as
successful; apply the same pattern to handle_send_dm if it uses the same dedupe
cache.
- Around line 161-199: The background sub-agent flow in
run_local_agent_and_forward can exit early on tool.execute() errors, which
prevents any completion from being forwarded to the originating session. Change
the error handling in run_local_agent_and_forward so invocation failures are
converted into a failure completion payload and still persisted/forwarded as a
tool_completion event, instead of using ? to return immediately; keep the
tokio::spawn caller’s logging, but ensure it never leaves the brain waiting
forever for a completion. If forwarding/persistence still fails after retries,
add a last-resort local failure record using the existing status/world_obs-style
path so the failure is visible on the next poll.

In `@src/openhuman/orchestration/migrate_history.rs`:
- Around line 74-88: The replay path in migrate_history::replay_session is not
preserving the backend cycle origin returned by push_event, so Master-session
turns can’t be recognized later by exec_gate::cycle_is_master. Update the replay
flow around super::cloud::push_event to capture the returned cycleId and record
it the same way the live master/ingest paths do for run_local_agent
authorization. Use the existing replay_session and push_event symbols to wire
the origin through the resumed event handling instead of discarding it.

In `@src/openhuman/orchestration/store.rs`:
- Around line 741-751: Wrap append_world_obs in in_immediate_txn so the
MAX(seq)+1 calculation and INSERT run atomically under a write lock; this
prevents concurrent writers from racing on world_obs and producing duplicate seq
values that later get deduped away. Update the append_world_obs function to
perform both the query_row and execute inside the immediate transaction path,
keeping the existing session_id, seq, note, ts insert logic unchanged.

---

Nitpick comments:
In `@app/src/components/intelligence/pixiGraphRenderer.test.ts`:
- Around line 65-67: The `removeChildren()` stub in `pixiGraphRenderer.test.ts`
does not match the real PIXI `Container.removeChildren()` API, which can take
`beginIndex`/`endIndex` and returns the removed children array. Update the stub
on the test container mock to accept those parameters and return the removed
items so any code using partial removal or the return value behaves consistently
with PIXI.

In `@scripts/ci/orch-ip-gate.sh`:
- Around line 38-41: The model-metadata gate in orch-ip-gate.sh only scans
orchestration TOML files, so reintroduced agent_tier or [model] routing metadata
in other formats could slip through. Update the check around the grep in the
metadata validation block to either explicitly document that TOML is the only
supported source of this metadata or broaden the scan in the relevant
orchestration area to include the additional config/source formats you want
covered.

In `@src/openhuman/orchestration/effect_executor.rs`:
- Around line 196-222: The completion message built in `effect_executor.rs`
computes `ok` but never writes it into the structured fields on
`super::types::OrchestrationMessage`, so downstream filtering/rendering can’t
use it. Update the `OrchestrationMessage` created in the `insert_message` path
to set the appropriate completion metadata fields (`ok`, `is_error`, and
`tool_name`) alongside the existing `body`, and keep the free-text body as a
human-readable summary only. Use the existing `body` construction and the
`tool-completion:{task_id}:{seq}` message creation block as the place to set
these fields.

In `@src/openhuman/orchestration/mod.rs`:
- Around line 41-111: The hosted-client lifecycle logic is incorrectly
implemented inside mod.rs instead of being export-only. Move
HOSTED_CLIENT_TASKS, abort_hosted_client_tasks, start_hosted_client_services,
and stop_hosted_client_services into a sibling module such as hosted_client.rs,
then re-export the public entrypoints from mod.rs. Keep mod.rs limited to module
declarations, pub use, and controller-schema wiring, and preserve the existing
behavior around task abort/restart and orchestration.enabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31274cef-d5c5-48b5-b30e-a6d88898fa77

📥 Commits

Reviewing files that changed from the base of the PR and between e5c6507 and 4ae1f80.

📒 Files selected for processing (89)
  • .env.example
  • .github/workflows/ci-lite.yml
  • app/src/components/intelligence/IntelligenceSubconsciousTab.tsx
  • app/src/components/intelligence/TinyPlaceOrchestrationTab.test.tsx
  • app/src/components/intelligence/TinyPlaceOrchestrationTab.tsx
  • app/src/components/intelligence/__tests__/IntelligenceSubconsciousTab.test.tsx
  • app/src/components/intelligence/pixiGraphRenderer.test.ts
  • app/src/components/orchestration/AgentChatPanel.tsx
  • app/src/components/orchestration/__tests__/AgentChatPanel.test.tsx
  • app/src/hooks/__tests__/useSubconscious.test.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
  • app/src/lib/orchestration/orchestrationClient.ts
  • app/src/pages/__tests__/OrchestrationPage.test.tsx
  • app/src/utils/tauriCommands/__tests__/subconscious.test.ts
  • app/src/utils/tauriCommands/subconscious.ts
  • docs/TEST-COVERAGE-MATRIX.md
  • scripts/ci/orch-ip-gate.sh
  • src/core/event_bus/events.rs
  • src/core/jsonrpc.rs
  • src/openhuman/about_app/catalog_data.rs
  • src/openhuman/agent_registry/agents/loader.rs
  • src/openhuman/config/schema/load/env_overlay.rs
  • src/openhuman/config/schema/orchestration.rs
  • src/openhuman/credentials/ops.rs
  • src/openhuman/mcp_server/resources.rs
  • src/openhuman/orchestration/bus.rs
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/frontend_agent/agent.toml
  • src/openhuman/orchestration/frontend_agent/graph.rs
  • src/openhuman/orchestration/frontend_agent/mod.rs
  • src/openhuman/orchestration/frontend_agent/prompt.md
  • src/openhuman/orchestration/frontend_agent/prompt.rs
  • src/openhuman/orchestration/graph/build.rs
  • src/openhuman/orchestration/graph/compress.rs
  • src/openhuman/orchestration/graph/mod.rs
  • src/openhuman/orchestration/graph/state.rs
  • src/openhuman/orchestration/graph/tests.rs
  • src/openhuman/orchestration/graph/world_diff.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/master_agent/agent.toml
  • src/openhuman/orchestration/master_agent/mod.rs
  • src/openhuman/orchestration/master_agent/prompt.md
  • src/openhuman/orchestration/master_agent/prompt.rs
  • src/openhuman/orchestration/master_reporter/agent.toml
  • src/openhuman/orchestration/master_reporter/mod.rs
  • src/openhuman/orchestration/master_reporter/prompt.md
  • src/openhuman/orchestration/master_reporter/prompt.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/ops.rs
  • src/openhuman/orchestration/reasoning_agent/agent.toml
  • src/openhuman/orchestration/reasoning_agent/graph.rs
  • src/openhuman/orchestration/reasoning_agent/mod.rs
  • src/openhuman/orchestration/reasoning_agent/prompt.md
  • src/openhuman/orchestration/reasoning_agent/prompt.rs
  • src/openhuman/orchestration/reasoning_agent/steering.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/orchestration/steering.rs
  • src/openhuman/orchestration/store.rs
  • src/openhuman/orchestration/sync.rs
  • src/openhuman/orchestration/tools.rs
  • src/openhuman/orchestration/world_diff_uploader.rs
  • src/openhuman/orchestration/world_model.rs
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/subconscious/factory.rs
  • src/openhuman/subconscious/mod.rs
  • src/openhuman/subconscious/profiles/mod.rs
  • src/openhuman/subconscious/profiles/tinyplace.rs
  • src/openhuman/subconscious/profiles/tinyplace_tests.rs
  • src/openhuman/tinyagents/topology.rs
  • src/openhuman/tools/ops.rs
  • src/openhuman/voice/dictation_listener.rs
  • tests/orchestration_exec_gate.rs
  • tests/orchestration_hosted_client.rs
💤 Files with no reviewable changes (36)
  • src/openhuman/orchestration/frontend_agent/prompt.md
  • src/openhuman/orchestration/reasoning_agent/prompt.md
  • src/openhuman/subconscious/profiles/mod.rs
  • src/openhuman/orchestration/master_reporter/prompt.md
  • src/openhuman/orchestration/master_reporter/agent.toml
  • src/openhuman/orchestration/master_reporter/prompt.rs
  • src/openhuman/orchestration/master_agent/prompt.md
  • src/openhuman/orchestration/graph/world_diff.rs
  • src/openhuman/orchestration/frontend_agent/prompt.rs
  • src/openhuman/orchestration/steering.rs
  • src/openhuman/orchestration/frontend_agent/mod.rs
  • src/openhuman/orchestration/master_agent/agent.toml
  • src/openhuman/orchestration/master_agent/prompt.rs
  • src/openhuman/orchestration/reasoning_agent/mod.rs
  • src/openhuman/orchestration/reasoning_agent/prompt.rs
  • src/openhuman/orchestration/frontend_agent/agent.toml
  • src/openhuman/subconscious/mod.rs
  • src/openhuman/orchestration/reasoning_agent/graph.rs
  • src/openhuman/tinyagents/topology.rs
  • src/openhuman/orchestration/reasoning_agent/agent.toml
  • src/openhuman/orchestration/reasoning_agent/steering.rs
  • src/openhuman/orchestration/graph/tests.rs
  • src/openhuman/mcp_server/resources.rs
  • src/openhuman/orchestration/graph/state.rs
  • src/openhuman/orchestration/frontend_agent/graph.rs
  • .env.example
  • src/openhuman/orchestration/graph/compress.rs
  • app/src/components/intelligence/IntelligenceSubconsciousTab.tsx
  • src/openhuman/orchestration/master_reporter/mod.rs
  • src/openhuman/orchestration/graph/mod.rs
  • src/openhuman/subconscious/profiles/tinyplace.rs
  • src/openhuman/subconscious/profiles/tinyplace_tests.rs
  • src/openhuman/config/schema/load/env_overlay.rs
  • src/core/event_bus/events.rs
  • src/openhuman/orchestration/graph/build.rs
  • src/openhuman/orchestration/master_agent/mod.rs

Comment thread src/openhuman/orchestration/effect_executor.rs
Comment thread src/openhuman/orchestration/effect_executor.rs
Comment thread src/openhuman/orchestration/migrate_history.rs
Comment thread src/openhuman/orchestration/store.rs
@sanil-23 sanil-23 force-pushed the feat/1074-r3-local-exec-device-tool branch 2 times, most recently from d4f0813 to 7081117 Compare July 9, 2026 17:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/orchestration/cloud.rs`:
- Around line 85-105: Record the `cycleId` returned by `push_event` inside
`resume_pending` so replayed sessions keep their device-authoritative origin.
Update the `resume_pending` flow in `migrate_history` to capture the
`Option<String>` from `push_event` and persist/pass it through to whatever
session state `exec_gate` reads, instead of discarding it. Use the existing
`push_event` and `exec_gate` symbols to trace where the origin must be stored
and restored.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 56d80bdb-8721-4b76-9e6d-660c17b25073

📥 Commits

Reviewing files that changed from the base of the PR and between 4ae1f80 and d4f0813.

📒 Files selected for processing (14)
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/orchestration/store.rs
  • src/openhuman/orchestration/sync.rs
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/subconscious/factory_tests.rs
  • src/openhuman/voice/dictation_listener.rs
  • tests/orchestration_exec_gate.rs
  • tests/orchestration_hosted_client.rs
✅ Files skipped from review due to trivial changes (1)
  • src/openhuman/voice/dictation_listener.rs
🚧 Files skipped from review as they are similar to previous changes (10)
  • tests/orchestration_exec_gate.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/sync.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/store.rs

Comment thread src/openhuman/orchestration/cloud.rs
@sanil-23 sanil-23 force-pushed the feat/1074-r3-local-exec-device-tool branch from 7081117 to a43e06c Compare July 9, 2026 17:25

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/orchestration/mod.rs`:
- Around line 43-111: Move the hosted-client lifecycle state and logic out of
`mod.rs` into `ops.rs`: relocate `HOSTED_CLIENT_TASKS`,
`abort_hosted_client_tasks`, `start_hosted_client_services`, and
`stop_hosted_client_services` so `mod.rs` stays export-only and re-export the
public functions from there, following the existing
`start_message_drain_supervisor` pattern. While moving
`start_hosted_client_services`, avoid duplicating the drain-and-abort behavior
by reusing the same helper used by
`stop_hosted_client_services`/`abort_hosted_client_tasks`, or extract a shared
helper around the task mutex to handle replacement and cleanup consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 840c4fdd-95e9-4bd0-9bf4-ea57f48a3c6e

📥 Commits

Reviewing files that changed from the base of the PR and between d4f0813 and 7081117.

📒 Files selected for processing (8)
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/socket/event_handlers.rs
  • tests/orchestration_exec_gate.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/orchestration_exec_gate.rs
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/effect_executor.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/orchestration/mod.rs`:
- Around line 43-111: Move the hosted-client lifecycle state and logic out of
`mod.rs` into `ops.rs`: relocate `HOSTED_CLIENT_TASKS`,
`abort_hosted_client_tasks`, `start_hosted_client_services`, and
`stop_hosted_client_services` so `mod.rs` stays export-only and re-export the
public functions from there, following the existing
`start_message_drain_supervisor` pattern. While moving
`start_hosted_client_services`, avoid duplicating the drain-and-abort behavior
by reusing the same helper used by
`stop_hosted_client_services`/`abort_hosted_client_tasks`, or extract a shared
helper around the task mutex to handle replacement and cleanup consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 840c4fdd-95e9-4bd0-9bf4-ea57f48a3c6e

📥 Commits

Reviewing files that changed from the base of the PR and between d4f0813 and 7081117.

📒 Files selected for processing (8)
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/socket/event_handlers.rs
  • tests/orchestration_exec_gate.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/orchestration_exec_gate.rs
  • src/openhuman/socket/event_handlers.rs
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/effect_executor.rs
🛑 Comments failed to post (1)
src/openhuman/orchestration/mod.rs (1)

43-111: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Move hosted-client lifecycle logic out of mod.rs into ops.rs.

This adds a global Mutex state and three non-trivial functions (task spawn/abort lifecycle) directly in mod.rs. Per the repo's mod.rs convention, this file should stay export-only (mod/pub use/schema wiring), and business logic belongs in ops.rs — which this same file already re-exports from (pub use ops::start_message_drain_supervisor;), so there's existing precedent for where this logic should live.

♻️ Proposed fix: relocate to `ops.rs`, re-export from `mod.rs`
-// ── Hosted-client background services (login-gated) ──────────────────────────
-
-use std::sync::Mutex;
-
-use tokio::task::JoinHandle;
-
-use crate::openhuman::config::Config;
-
-/// Join handles for the per-login hosted-client loops (read-sync + world-diff
-/// uploader), so a logout→login aborts the old session's loops before starting
-/// fresh ones — no duplicates, and never a loop bound to a previous session's
-/// config/workspace.
-static HOSTED_CLIENT_TASKS: Mutex<Vec<JoinHandle<()>>> = Mutex::new(Vec::new());
-
-fn abort_hosted_client_tasks() { /* ... */ }
-
-pub async fn start_hosted_client_services(config: &Config) { /* ... */ }
-
-pub fn stop_hosted_client_services() { /* ... */ }
+pub use ops::{start_hosted_client_services, stop_hosted_client_services};

Then add the moved static + functions to ops.rs (same bodies), where they sit alongside start_message_drain_supervisor.

While relocating, consider having start_hosted_client_services call the same drain-and-abort helper used by stop_hosted_client_services/abort_hosted_client_tasks (it currently reimplements the drain+abort loop inline at lines 78-83) to remove the duplication, e.g. by extracting a fn replace_tasks(new: Vec<JoinHandle<()>>) helper that both call under one lock.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/orchestration/mod.rs` around lines 43 - 111, Move the
hosted-client lifecycle state and logic out of `mod.rs` into `ops.rs`: relocate
`HOSTED_CLIENT_TASKS`, `abort_hosted_client_tasks`,
`start_hosted_client_services`, and `stop_hosted_client_services` so `mod.rs`
stays export-only and re-export the public functions from there, following the
existing `start_message_drain_supervisor` pattern. While moving
`start_hosted_client_services`, avoid duplicating the drain-and-abort behavior
by reusing the same helper used by
`stop_hosted_client_services`/`abort_hosted_client_tasks`, or extract a shared
helper around the task mutex to handle replacement and cleanup consistently.

Source: Coding guidelines

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/openhuman/config/schemas/mod.rs (1)

32-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove duplicate #[cfg(test)] attribute.

Lines 32 and 33 both apply #[cfg(test)] to the same use statement. Harmless but redundant.

🧹 Proposed fix
-#[cfg(test)]
 #[cfg(test)]
 pub(crate) use schema_defs::schemas;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/openhuman/config/schemas/mod.rs` around lines 32 - 35, Remove the
duplicated conditional attribute on the re-export in mod.rs: the `pub(crate) use
schema_defs::schemas;` statement is preceded by two identical `#[cfg(test)]`
attributes. Keep only one `#[cfg(test)]` on that item and leave the `schemas`
re-export unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/openhuman/orchestration/effect_executor.rs`:
- Line 242: The forwarded completion path in effect_executor::run_local_agent is
discarding the backend cycle origin returned by super::cloud::push_event, which
later breaks cycle_is_master checks for the new cycle. Update this forwarding
branch to capture the returned cycleId/origin the same way the other forward
sites do, and persist it alongside the envelope so subsequent run_local_agent
calls recognize the origin correctly.

---

Nitpick comments:
In `@src/openhuman/config/schemas/mod.rs`:
- Around line 32-35: Remove the duplicated conditional attribute on the
re-export in mod.rs: the `pub(crate) use schema_defs::schemas;` statement is
preceded by two identical `#[cfg(test)]` attributes. Keep only one
`#[cfg(test)]` on that item and leave the `schemas` re-export unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b261247d-dae0-4e16-96e6-ed9c7e2d498f

📥 Commits

Reviewing files that changed from the base of the PR and between 7081117 and 5a2ecf2.

📒 Files selected for processing (19)
  • src/openhuman/channels/providers/web/mod.rs
  • src/openhuman/config/schema/load/mod.rs
  • src/openhuman/config/schemas/mod.rs
  • src/openhuman/inference/local/service/ollama_admin/mod.rs
  • src/openhuman/inference/provider/reliable.rs
  • src/openhuman/mcp_server/tools/mod.rs
  • src/openhuman/memory/chat.rs
  • src/openhuman/memory/schema/mod.rs
  • src/openhuman/memory/tree_source/file.rs
  • src/openhuman/orchestration/cloud.rs
  • src/openhuman/orchestration/effect_executor.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/migrate_history.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/sandbox/docker.rs
  • src/openhuman/socket/event_handlers.rs
  • tests/orchestration_exec_gate.rs
✅ Files skipped from review due to trivial changes (5)
  • src/openhuman/memory/schema/mod.rs
  • src/openhuman/memory/tree_source/file.rs
  • src/openhuman/sandbox/docker.rs
  • src/openhuman/inference/provider/reliable.rs
  • src/openhuman/memory/chat.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • tests/orchestration_exec_gate.rs
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/orchestration/exec_gate.rs
  • src/openhuman/orchestration/ingest.rs
  • src/openhuman/orchestration/mod.rs
  • src/openhuman/orchestration/cloud.rs

Comment thread src/openhuman/orchestration/effect_executor.rs
…letion forward

Give the hosted brain back local execution (retired in the hosted-only
migration) as a gated device tool, restricted to Master-chat cycles.

- `run_local_agent` device tool: spawns a local sub-agent (code_executor,
  researcher, tools_agent, …) on the device and forwards its result.
- `exec_gate`: device-authoritative trust gate. Records cycleId -> (counterpart,
  session) at forward time; authorizes local execution only when the cycle's
  counterpart is LOCAL_MASTER_AGENT. Unknown/A2A cycles fail closed. Enforced in
  effect_executor (the capability holder), so an injected/compromised cloud brain
  cannot induce local execution for an agent-to-agent cycle.
- Async completion model: run_local_agent returns an immediate `accepted` ack
  (inside the device-tool timeout, so the cycle never blocks) and runs the
  sub-agent in the background; on completion the result is forwarded up as a
  `tool_completion` event, which wakes a fresh cycle that reasons over it.
- cloud.push_event now returns the backend cycleId (origin capture).
- Integration tests for the gate (master allowed, A2A/unknown denied).

No backend change: executeLoop already surfaces device-declared tools to the
model, the /v1/events route already wakes a cycle on any event, and the event
`kind` field is unconstrained.

Stacked on tinyhumansai#4738.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sanil-23 sanil-23 force-pushed the feat/1074-r3-local-exec-device-tool branch from 5a2ecf2 to 47cc95a Compare July 9, 2026 20:52
@senamakel senamakel merged commit f5b77ed into tinyhumansai:main Jul 10, 2026
20 checks passed
senamakel added a commit to senamakel/openhuman that referenced this pull request Jul 10, 2026
…ck CI)

tests/orchestration_effect_executor_e2e.rs (added by tinyhumansai#4738) still called
dispatch_device_tool/handle_tool_call with the old sync 2-arg signatures after
tinyhumansai#4753 made them async/3-arg — broken identically on upstream/main. It only
surfaced in this PR because the Motion A test-debt fix touched agent_orchestration
files, pulling the orchestration domain into CI rust-core-coverage's scope.

Convert the two affected tests to #[tokio::test] + .await, and pass the cycle_id
arg (the exec gate is bypassed for non-local-exec tools like device_status).

Claude-Session: https://claude.ai/code/session_01U8NDGbt9tKj443VquzycLB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Built-in agents, prompts, orchestration, and agent runtime in src/openhuman/agent/. enhancement feature Net-new user-facing capability or product behavior. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants