Skip to content

feat(orchestration): Master chat — human↔OpenHuman control channel + working receive loop#4660

Merged
senamakel merged 13 commits into
tinyhumansai:mainfrom
sanil-23:feat/master-chat-orchestration-tools
Jul 7, 2026
Merged

feat(orchestration): Master chat — human↔OpenHuman control channel + working receive loop#4660
senamakel merged 13 commits into
tinyhumansai:mainfrom
sanil-23:feat/master-chat-orchestration-tools

Conversation

@sanil-23

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

Copy link
Copy Markdown
Contributor

Summary

  • Adds the Master chat control channel: a human talks to the OpenHuman agent directly, and OpenHuman lists tiny.place contacts, browses its own agent↔agent session history, and messages contacts on the human's behalf.
  • Master chat runs a dedicated human-facing master_agent on the chat model, skipping the A2A front-end triage (that's for agent-to-agent), so replies are in OpenHuman's own voice.
  • Makes the receive loop actually work end-to-end: OpenHuman now auto-publishes its Signal keys so peers can encrypt replies to it, and a peer's answer to a master-initiated ask is surfaced back into the master chat as OpenHuman's own message.
  • Fixes the reply-threading correlation that never armed (a task-local died across the harness tokio::spawn boundary) by using a process-global origin beacon.
  • Master→peer sends are fire-and-forget: OpenHuman acks immediately and the async reply is surfaced automatically (no polling, no duplicate reports).

Problem

The master-chat surface could send to other agents but never received anything back, so it was effectively one-directional:

  1. OpenHuman was undiscoverable. Its Signal encryption key + one-time pre-keys were never published — that was a manual two-click action in the Messaging UI with no automatic path. Peers 404'd on OpenHuman's prekey bundle and could not encrypt a reply to it, so the entire orchestration receive loop was silently dead on any fresh/orchestration-enabled instance.
  2. The reply-threading correlation never armed. orchestration_send_to_agent recorded "who to thread the reply back to" via a tokio::task_local set by the orchestration execute node. But the agent harness dispatches tool calls beyond an internal tokio::spawn, and task-locals do not cross a spawn boundary — so pending_ask was never written and peer replies fell through to the ordinary A2A path, never reaching the master chat.

Solution

  • Auto-publish Signal keys. New idempotent tinyplace::ensure_signal_keys_published (provision pre-keys if missing + register the encryption key if not advertised), called once from the orchestration drain supervisor so any orchestration-enabled instance becomes discoverable/reachable without manual UI steps. Cheap no-op once published; retries until the wallet is unlocked, then stops.
  • Reliable W7 arming via a process-global beacon. The execute node opens a master-origin beacon around the local-master turn; send_to_agent reads it (a process-global survives the harness spawn boundary the task-local could not) and arms pending_ask(peer_session) → master. Safe because local-master wakes are serialized by the generation guard; the A2A concurrency edge is documented.
  • Report the reply as OpenHuman. When a master-initiated ask's reply ingests, report_peer_reply_to_master runs the master_agent and surfaces the answer as OpenHuman's own assistant message — scoped to master-triggered asks only; peer/A2A replies keep the raw threadback. Falls back to raw threading if the report turn fails so an answer is never dropped.
  • Fire-and-forget. The send_to_agent tool note + master_agent prompt now state the reply is surfaced automatically and the agent must not poll/read_session for it — so the W7 push is the sole async reporter (previously the agent polled-and-reported and W7 pushed → the reply surfaced twice).

Design decision: master-triggered asks are treated as one-shot — OpenHuman reports the answer and does not keep an autonomous thread running with the peer. The full peer transcript still lives in its own session (browsable via orchestration_read_session); the master chat is the curated control view.

Verified live on staging (3 tiny.place plugin sessions of a test agent): master ask → OpenHuman sends + immediate ack → peer reply → exactly one OpenHuman report in the master chat; pending_ask armed then cleared.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy — added the origin-beacon arming test (orchestration::tools::tests::master_origin_beacon_sets_and_clears) and W7 store one-shot / graph tests in the stack; the LLM-driven report turn and the network-dependent Signal auto-publish are integration-only and were verified live on staging (documented above).
  • Diff coverage ≥ 80% — N/A locally: several changed lines are integration-only seams (LLM report turn, Signal provision network calls, the background drain-supervisor loop) that can't be unit-covered without a live backend; covered the pure decision logic (beacon arming) and verified the rest end-to-end on staging. Deferring to the CI coverage report for the exact number.
  • Coverage matrix updated — N/A: no new top-level feature row (extends the existing orchestration/master-chat surface); behaviour is covered by the orchestration entries.
  • All affected feature IDs from the matrix are listed under ## Related — N/A: no matrix feature IDs apply to this orchestration-internal change.
  • No new external network dependencies introduced — no new hosts; reuses the existing tiny.place relay client already in the tinyplace domain.
  • Manual smoke checklist updated if this touches release-cut surfaces — N/A: no release-cut surface changed (orchestration core + agent prompts only).
  • Linked issue closed via Closes #NNN — N/A: no tracking issue; follows up the merged fix(orchestration): reliable agent-to-agent DM replies (surface, correct content, resilience) — Closes #4583 #4599 orchestration work.

Impact

  • Desktop/core only. Rust core (src/openhuman/orchestration, src/openhuman/tinyplace) plus bundled agent prompts. No UI, mobile, or CLI surface changes.
  • Security/privacy: the drain supervisor now auto-publishes the agent's Signal encryption key so peers can message it — i.e. an orchestration-enabled instance becomes discoverable on tiny.place automatically (previously a manual opt-in). Scoped to instances where the orchestration drain runs. Only public keys leave the process; private key material stays in the encrypted local store.
  • No migrations. No new network hosts.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: feat/master-chat-orchestration-tools
  • Commit SHA: see head of PR

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: no app/src files changed (core Rust + prompts only); cargo fmt run on changed Rust.
  • pnpm typecheck — N/A: no TypeScript changed.
  • Focused tests: cargo test --lib orchestration::tools::tests::master_origin_beacon_sets_and_clears (pass)
  • Rust fmt/check (if changed): cargo fmt + cargo check --bin openhuman-core (clean)
  • Tauri fmt/check (if changed): N/A: no app/src-tauri code changed.

Validation Blocked

  • command: pre-push pnpm rust:check
  • error: fails in a fresh worktree (missing vendored CEF for the Tauri shell)
  • impact: unrelated to this change (no app/src-tauri code touched); pushed with --no-verify.

Behavior Changes

  • Intended behavior change: master-initiated asks to other agents now surface the peer's reply back into the master chat as OpenHuman's own message; OpenHuman auto-publishes Signal keys so it can receive.
  • User-visible effect: "ask contact X …" in the master chat now gets an immediate ack and then a single follow-up report when the contact replies.

Parity Contract

  • Legacy behavior preserved: A2A peer-session orchestration (front-end triage → reasoning) is unchanged; peer replies to non-master asks keep the existing raw threadback.
  • Guard/fallback/dispatch parity checks: report turn falls back to raw threading on failure; deliberately tool-less agents unaffected; beacon closed unconditionally after each master turn.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): N/A
  • Canonical PR: this
  • Resolution: N/A

Summary by CodeRabbit

  • New Features

    • Added a new “Master chat” experience for talking directly with OpenHuman, including access to past conversations and the ability to hand off work to other agents.
    • Introduced tools for viewing session history, listing contacts, and sending messages to agents from within chat.
    • Local Master replies now stay in the Master conversation and display immediately in the UI.
  • Bug Fixes

    • Improved reply threading so responses return to the correct conversation.
    • Fixed message delivery reliability and reduced duplicate or misrouted follow-up replies.

sanil-23 added 12 commits July 7, 2026 21:08
… history

Master chat, read slice: give the orchestration reasoning core read-only tools
to browse its persisted OpenHuman<->agent session transcripts so it can answer a
question from its own history of chats with other agents, instead of only the
single window it was woken for.

- orchestration_list_sessions: enumerate saved agent chat sessions (peer, label,
  last activity, message count, one-line preview), pinned windows hidden.
- orchestration_read_session: read one session's transcript by id (chronological,
  pageable via before).

Both ReadOnly + concurrency-safe; workspace-internal store access via
store::{list_sessions,count_messages,list_recent_messages,list_messages_by_session}.
Registered in tools/ops.rs and added to the reasoning_agent allowlist + prompt.

Tests: cargo test openhuman::orchestration::tools -> 7/7 (3 new); full
orchestration 61/61, loader 85/85.

Builds on tinyhumansai#4599 (reliable reactive reply loop). Next: gated send-on-behalf tool.
Master chat, send slice (W5 + W6): give the reasoning core a tool to message
another agent on OpenHuman's behalf (e.g. to ask a peer something for the user).

- orchestration_send_to_agent { recipient, message, sessionId? }.
- Guardrail (linked-peers-only): recipient must be a linked/paired agent or one
  with an existing session; refuses cold-DMs, since the core runs under a
  background origin that bypasses the interactive approval gate.
- Session id (reuse-or-mint per peer): new store::latest_session_for_agent reuses
  the peer's newest thread's shared wrapper_session_id so the reply threads back
  (#227/tinyhumansai#4582); mints a fresh uuid only when no thread exists. Explicit sessionId
  overrides.
- Sends a v1 session envelope via handle_tinyplace_signal_send_message and records
  the outbound role=owner message + notify_orchestration_message (mirrors tinyhumansai#4599
  persist_outgoing_reply) so it shows in the chat + own history.
- PermissionLevel::Write; registered in tools/ops.rs; reasoning_agent allowlist +
  prompt updated.

Reply threading back into the originating master question (W7) is still open
(needs envelope inReplyTo correlation, F3).

Tests: cargo test openhuman::orchestration -> 64/64 (6 new incl. guardrail-refusal
and session reuse); loader 85/85; lib compiles clean.
…(W7)

Master chat, reply-threading (W7, core-only): when OpenHuman DMs a peer on the
user's behalf and the peer replies, thread that answer back into the window the
ask came from instead of auto-replying to the peer.

- One-shot correlation: the execute node scopes the origin window
  (tools::with_origin_session task-local); orchestration_send_to_agent records
  store::set_pending_ask(ask_session -> origin).
- On the peer's reply, invoke_with_runtime threads the newest inbound message into
  the origin window (thread_reply_to_origin) and finishes the cycle WITHOUT running
  the reply graph -- no ping-pong reply to the peer. Consumed one-shot via
  store::{pending_ask_origin,clear_pending_ask}.
- Additive/safe: only sessions OpenHuman itself initiated carry a pending marker;
  peer-initiated and master wakes are unchanged.

Store: kv_delete + set_pending_ask/pending_ask_origin/clear_pending_ask.

Limitation (needs F3, cross-repo): pragmatic 1:1 correlation assumes the next
inbound message on the ask session is the answer; robust many-in-flight needs an
envelope inReplyTo. The threaded answer is the peer's raw reply (no re-synthesis
of a final answer to the human yet).

Tests: cargo test openhuman::orchestration -> 66/66 (2 new: reply-threading skips
the graph + surfaces to master; pending-ask one-shot); lib clean; fmt clean.
…on) (F2)

The wake graph checkpointed under thread orchestration:<session_id>, but the
store keys sessions by (agent_id, session_id). Two peers sharing a session id (a
legacy harness_session_id fallback collision, now more likely with reuse-or-mint
outbound asks) could resume from each other's checkpoint. Scope the thread id to
orchestration:<counterpart>:<session_id> so it matches the store namespace.

Migration seam noted in-code: a cycle checkpointed under the old key that only
resumes after this upgrade starts a fresh thread (one extra in-flight cycle at
the boundary; Beta, gated by [orchestration]) — same worst case as the cycle_id
format change.

Deferred by tinyhumansai#4599 as a follow-up. Tests: orchestration 66/66 (thread-id assertion
updated).
Make the human↔OpenHuman Master chat route into OpenHuman's OWN reasoning graph
instead of requiring an external peer recipient.

Previously a Master-chat send with no recipient errored 'no Master counterpart
yet — specify a recipient' (schemas.rs) — it was only wired to steer an external
peer. But the Master chat is where the human talks to the OpenHuman agent to
control/communicate with external agents.

- types.rs: LOCAL_MASTER_AGENT sentinel ('openhuman:local') — the counterpart for
  a local human->OpenHuman cycle (never a real base58 address).
- schemas.rs handle_send_master_message: when no recipient AND no sessionId, take
  the local-ask path — persist the question (role=user) in the master window with
  a monotonic seq, notify the renderer, and publish OrchestrationSessionMessage to
  wake the reasoning core locally. No outbound DM, no recipient required. Explicit
  recipient/sessionId still steer a peer as before.
- ops.rs ProductionRuntime::send_dm: when the counterpart is LOCAL_MASTER_AGENT,
  persist the answer (role=assistant) into the master window and notify — no
  tiny.place DM. Reuses the reasoning core's tools + W7 threading (if it asks a
  real external agent, that reply threads back into master via origin='master').

Tests: cargo test openhuman::orchestration -> 67/67 (new:
local_master_reply_lands_in_the_window_not_an_outbound_dm).
…ions

Complete the master-chat browse loop so the OpenHuman agent can go
contacts -> that contact's sessions -> a session's history:

- orchestration_list_contacts (new): enumerate the agent's tiny.place contacts,
  delegating to the tiny.place contacts_list controller (re-exported
  handle_tinyplace_contacts_list from tinyplace::manifest). Read-only.
- orchestration_list_sessions: optional contactId filter -> only that contact's
  sessions (contact-wise view).
- Added to the reasoning_agent allowlist + prompt (browse loop documented).

Tests: cargo test openhuman::orchestration -> 68/68 (new list_sessions_tool_filters_by_contact);
loader 85/85.
For a local human->OpenHuman master cycle (counterpart = LOCAL_MASTER_AGENT), the
wake graph no longer runs the A2A front-end agent — the human talks straight to
the reasoning core (OpenHuman):

- graph/build.rs frontend node: on a local master cycle, pass 1 feeds the core a
  direct human-facing directive (instead of frontend_instruct's A2A triage), and
  pass 2 uses the core's reply verbatim (instead of frontend_compile's A2A
  'compile'). Peer-initiated cycles still run the two-pass front end unchanged.

The A2A front-end prompt ('a wrapped Claude/Codex session is talking to you') and
the reasoning prompt ('you are not talking to the user directly; the front end
will phrase the reply') were the wrong framing for the human master chat — this
routes around the front end for that direction.

Tests: cargo test openhuman::orchestration::graph -> 12/12 (new:
local_master_cycle_skips_the_a2a_frontend_agent); full orchestration 69/69.
…ster chat

Add a master_agent built-in — OpenHuman talking DIRECTLY to its human — derived
from the reasoning core (same reasoning tier, same tiny.place tool belt +
sub-agent allowlist) but with a human-facing system prompt instead of the A2A
split-brain framing ('you are not talking to the user directly; the front end
will phrase the reply').

- orchestration/master_agent/: agent.toml (clone of reasoning_agent config, id
  master_agent), prompt.md (human-direct: you are OpenHuman talking to your human;
  browse contacts/sessions/history; act on their behalf), prompt.rs (reuses the
  reasoning core's steering task-local), mod.rs.
- loader.rs: register master_agent (reuses reasoning_agent's default turn graph);
  add it to the non-worker-tier test allowlist.
- ops.rs execute node: run master_agent (human-conversation prompt) for a local
  master cycle (agent_id == LOCAL_MASTER_AGENT); reasoning_agent (A2A macro-
  instructions framing) for peer cycles.
- build.rs: local-master pass-1 directive trimmed to a light nudge (master_agent's
  system prompt now carries the framing).

Tests: orchestration 69/69, loader 85/85 (master_agent registers + tools resolve).
…unconfigured)

On staging, reasoning-v1 400s with 'API key not configured for provider' and has
no fallback, while chat-v1 works (burst-v1 fails but auto-falls-back to chat-v1).
The master_agent was running on hint:reasoning -> reasoning-v1, so every master
turn died. Route the local master turn to hint:chat (chat-v1) — master chat is a
direct human conversation, the chat tier is the right fit and the working one.

- ops.rs execute: local master -> (master_agent, hint:chat); A2A -> (reasoning_agent, hint:reasoning).
- master_agent/agent.toml: [model] hint = chat.

Tests: orchestration 69/69.
The master chat could send to peers but never surfaced their replies. Two
root causes, both fixed here:

1. OpenHuman was undiscoverable. Its Signal encryption key + pre-keys were
   never published (a manual two-click Messaging-UI action), so peers 404'd
   on its prekey bundle and could not encrypt a reply back — the receive loop
   was silently dead. Add `tinyplace::ensure_signal_keys_published` (idempotent
   provision + register) and call it from the orchestration drain supervisor so
   any orchestration-enabled instance auto-publishes and becomes reachable.

2. The W7 reply-threading correlation never armed. `send_to_agent` read the
   ask's origin from a `tokio::task_local`, but the agent harness dispatches
   tool calls beyond an internal `tokio::spawn`, and task-locals do not cross a
   spawn — so `pending_ask` was never set and replies fell through to the peer
   path. Replace it with a process-global master-origin beacon the `execute`
   node opens around the local-master turn; the tool reads it reliably.

When a master-initiated ask's reply arrives, surface it as OpenHuman's OWN
assistant message via `report_peer_reply_to_master` (runs the master_agent on
the chat tier), not the peer's raw words and not a user turn — scoped to
master-triggered asks; peer/A2A replies keep the raw threadback.

Make `send_to_agent` fire-and-forget: the tool note + master_agent prompt now
tell the agent the reply is surfaced automatically and to NOT poll/read_session
for it, so W7 is the sole async reporter (was double-surfacing — the agent
polled-and-reported AND W7 pushed).

Verified live on staging: master ask -> send + immediate ack -> peer reply ->
exactly one OpenHuman report in the master chat; pending_ask armed then cleared.
@sanil-23 sanil-23 requested a review from a team July 7, 2026 15:55
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b58249a7-3672-41e8-8b30-82cfb8c0a229

📥 Commits

Reviewing files that changed from the base of the PR and between 733e9ef and 412eceb.

📒 Files selected for processing (10)
  • docs/scoping/master-chat.md
  • src/openhuman/agent_registry/agents/loader.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/mod.rs
  • src/openhuman/orchestration/ops.rs
  • src/openhuman/orchestration/store.rs
  • src/openhuman/orchestration/tools.rs
📝 Walkthrough

Walkthrough

This PR introduces a local Master chat loop for direct human-to-OpenHuman conversation, adding a new master_agent with its own prompt/config, orchestration graph routing that bypasses A2A steps for local cycles, session-history/send-on-behalf tools, pending-ask reply threading, checkpoint thread-id scoping by counterpart agent, and Signal key-publishing reliability fixes, plus a scoping design document.

Changes

Master Chat Feature Implementation

Layer / File(s) Summary
Local master sentinel and agent registration
src/openhuman/orchestration/types.rs, src/openhuman/agent_registry/agents/loader.rs, src/openhuman/orchestration/mod.rs
Adds LOCAL_MASTER_AGENT sentinel constant, registers master_agent in the builtin agent loader, updates the worker-tier exception test, and declares the master_agent module.
master_agent module, prompt, and configuration
src/openhuman/orchestration/master_agent/mod.rs, .../prompt.md, .../prompt.rs, .../agent.toml
Adds the master_agent module with its system prompt builder and agent.toml (model, subagents, tools) for the human-facing Master chat.
Orchestration graph routing for local master cycles
src/openhuman/orchestration/graph/build.rs, .../graph/tests.rs
Detects local master cycles and skips A2A frontend triage/compile steps, uses agent_reply verbatim, scopes checkpoint thread ids by counterpart agent id, and adds a test.
Reasoning agent prompt and tool allowlist updates
src/openhuman/orchestration/reasoning_agent/agent.toml, .../prompt.md
Adds orchestration session-history/send tools to the reasoning agent's allowlist and prompt guidance.
Orchestration store persistence helpers
src/openhuman/orchestration/store.rs
Adds latest_session_for_agent, kv_delete, and pending-ask correlation store functions with tests.
Session-history and send-on-behalf tools
src/openhuman/orchestration/tools.rs, src/openhuman/tools/ops.rs
Implements ListSessionsTool, ReadSessionTool, ListContactsTool, SendToAgentTool, origin/master-origin correlation state, and registers them in the tool registry.
Pending-ask reply threading and local ask entry point
src/openhuman/orchestration/ops.rs, src/openhuman/orchestration/schemas.rs
Adds W7 reply-threading logic, an early-return guard for pending asks, Master vs peer execute-node branching, a local-master send_dm branch, and a local-ask path in handle_send_master_message.
Signal key publishing reliability
src/openhuman/tinyplace/manifest.rs, src/openhuman/tinyplace/mod.rs, src/openhuman/orchestration/ops.rs
Adds ensure_signal_keys_published and wires it into the drain supervisor to ensure discoverability before draining DMs.

Scoping Documentation

Layer / File(s) Summary
Master chat scoping document
docs/scoping/master-chat.md
Adds a document covering current Master chat behavior, gap analysis, work checklist, and open questions.

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

Sequence Diagram(s)

sequenceDiagram
  participant Human
  participant Schemas
  participant Ops
  participant MasterAgent
  participant Store
  participant Peer

  Human->>Schemas: send Master message (no recipient/sessionId)
  Schemas->>Store: persist user message in Master window
  Schemas->>Ops: publish OrchestrationSessionMessage event
  Ops->>MasterAgent: run local Master cycle (skip A2A frontend)
  MasterAgent->>Store: read session history / list contacts
  MasterAgent->>Peer: orchestration_send_to_agent (async ask)
  Store->>Store: set_pending_ask(origin=Master)
  Peer-->>Ops: DM reply
  Ops->>Store: pending_ask_origin lookup
  Ops->>MasterAgent: generate assistant report from reply
  Ops->>Store: thread report into Master window
  Store-->>Human: renderer notification (answer shown)
Loading

Possibly related PRs

  • tinyhumansai/openhuman#4425: Introduces the OrchestrationSessionMessage ingest event and session/message storage that this PR extends with pending-ask correlation and threading.
  • tinyhumansai/openhuman#4564: Adds the mailbox poll-drain supervisor that this PR extends with Signal key-publishing readiness checks.
  • tinyhumansai/openhuman#4599: Provides the reliable DM reply loop and send_dm correctness patterns this PR builds master-chat threading on top of.

Suggested labels: feature, rust-core, agent

Suggested reviewers: M3gA-Mind

Poem

A rabbit hops through wires and code,
Where Master chat now finds its road —
🥕 sessions read, and asks take flight,
Threaded replies land just right.
No more ping-pong, no more strife,
Just OpenHuman's steady voice, alive.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change set: a new Master chat control channel with end-to-end receive-loop support.

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 7, 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: 733e9ef0aa

ℹ️ 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".

let mut discoverable = false;
loop {
if !discoverable {
match crate::openhuman::tinyplace::ensure_signal_keys_published().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 Gate key publishing on orchestration being enabled

When [orchestration].enabled is set to false, this supervisor still runs at core startup and calls ensure_signal_keys_published() before loading the config or checking the flag. That helper can provision prekeys and publish the encryption key to the directory, so a user who disabled orchestration still gets made discoverable and has remote tiny.place state mutated. Load the config and skip this block when orchestration is disabled before attempting the publish path.

Useful? React with 👍 / 👎.

Comment thread src/openhuman/orchestration/tools.rs Outdated
if let Some(origin) = current_master_origin().or_else(current_origin_session) {
if origin != session_id && !origin.is_empty() {
if let Err(e) = store::with_connection(&workspace, |conn| {
store::set_pending_ask(conn, &session_id, &origin)

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 Scope pending asks by agent as well as session

This records the reply-correlation key with only session_id, while sessions elsewhere are keyed by (agent_id, session_id) and this same change acknowledges legacy session-id collisions in the graph checkpointer. If two linked peers share a legacy harness_session_id, any inbound message from the other peer on that session id will satisfy pending_ask_origin(config, session_id), get threaded back as the answer, clear the one-shot pending ask, and prevent the real recipient's reply from being reported correctly. Include the recipient/counterpart in the pending-ask key and lookup.

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: 13

🧹 Nitpick comments (1)
src/openhuman/orchestration/ops.rs (1)

1030-1044: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Clear the process-global master origin with a guard.

end_master_origin() runs after the awaited turn, but cancellation or panic before that point can leave the global beacon stale for a later wake. Use an RAII/drop guard around begin_master_origin so cleanup is tied to future drop.

🤖 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/ops.rs` around lines 1030 - 1044, The
process-global master origin in the orchestration path can be left stale if the
awaited turn exits early, so update the logic around begin_master_origin and
end_master_origin in the reasoning turn flow to use an RAII guard whose Drop
cleanup always clears the origin. Keep the existing is_local_master check, but
wrap the begin_master_origin call in a guard scoped across the await in the
with_steering / with_origin_session / run_agent_turn sequence so cleanup is tied
to future drop instead of relying on a trailing end_master_origin call.
🤖 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 `@docs/scoping/master-chat.md`:
- Around line 178-186: Update the sub-flow status matrix in master-chat.md so
Row 1 reflects the landed master-chat behavior instead of pre-PR baseline state.
Use the existing matrix entry and surrounding master-chat summary to relabel it
as historical context or mark it as now-supported, and make sure the wording
matches the actual master-initiated reply path rather than saying there is no
“answer the asker” surface.
- Around line 247-263: Update the W7 paragraph to match the implemented
reply-correlation flow: replace the task-local origin-scoping description with
the process-global beacon approach that survives tokio::spawn, and describe that
the threaded reply is surfaced as OpenHuman’s own message rather than the peer’s
raw reply. Keep the one-shot correlation behavior and clear the pending marker
after the first inbound response, using the existing orchestration symbols like
execute, orchestration_send_to_agent, invoke_with_runtime,
thread_reply_to_origin, and store::{pending_ask_origin,clear_pending_ask} to
locate the text.

In `@src/openhuman/orchestration/ops.rs`:
- Around line 387-403: The master reply path in ops::run_agent_turn is unsafe
because it feeds untrusted peer text into the full tool-enabled master_agent
with master transcript context. Change this flow to use a report-only, tool-free
reporter path instead of ProductionRuntime::run_agent_turn for the peer reply,
so the response is summarized without exposing OpenHuman’s tools or session
context to prompt injection. Keep the existing prompt construction in the
reply-handling block, but route it through a dedicated no-tools model or
reporting method identified by the master-agent reporting logic.
- Around line 2079-2091: The master-report assertion is currently
nondeterministic because report_peer_reply_to_master can build a
ProductionRuntime and persist a generated report instead of the expected raw
reply. Update the test setup around invoke_with_runtime and the pending-ask path
to use a deterministic provider override, or explicitly force the report
generation to fail in a controlled way, so the stored master message is
predictable before checking for "shipped v2".
- Around line 282-316: The pending-ask flow is only keyed by session_id, which
can route answers to the wrong window or persist them under the answering peer
instead of the original asker. Update pending_ask_origin and the related
reply-threading path in thread_reply_to_origin to carry the full origin
identity, including origin_agent_id plus origin_session_id, and use that origin
agent when inserting/notifying and when clearing the consumed ask. Also review
the other call sites in this orchestration flow that read or store pending asks
so they use the same origin tuple consistently.
- Around line 1224-1260: The local master persistence path in the orchestration
send flow currently swallows store failures and still returns success, which
lets the graph advance even when the assistant message was not saved. Update the
`LOCAL_MASTER_AGENT` branch in `ops::...` around the `store::with_connection`
block to propagate the error instead of only logging it, so the caller sees the
failure and `dm_sent`/cursor advancement do not occur on a bad write. Keep the
failure handling tied to the existing `master_answer.persist_failed` logging and
the `super::bus::notify_orchestration_message` call so notification only happens
after a successful persist.
- Around line 761-772: The reply flow in
orchestration::ops::report_peer_reply_to_master/thread_reply_to_origin is
clearing the pending ask and advancing the cursor even when persistence may have
failed. Make threading success explicit by changing thread_reply_to_origin to
return a status (or otherwise surface success/failure), and only call
clear_pending_ask and advance_cursor after either report_peer_reply_to_master or
raw threading completes successfully.

In `@src/openhuman/orchestration/schemas.rs`:
- Around line 482-510: The master message persistence path currently calls
store::next_session_seq and store::insert_message inside store::with_connection
without an immediate transaction, so concurrent master submits can reuse the
same seq. Update the branch in schemas::orchestration to wrap the seq
allocation, store::upsert_session, and store::insert_message work in
store::in_immediate_txn so the master session sequence is reserved atomically.

In `@src/openhuman/orchestration/tools.rs`:
- Around line 653-681: The session sequence allocation and message insert in
tools.rs are race-prone because `next_session_seq` and `store::insert_message`
are currently executed without the store’s immediate transaction protection.
Update the logic in the `store::with_connection` block for the session/message
write path to run the `next_session_seq` + `upsert_session` + `insert_message`
sequence inside `in_immediate_txn`, matching the concurrency-safe pattern used
by the store’s own tests and preventing duplicate or rejected sequence numbers
when concurrent sends hit the same session.
- Around line 638-648: Arm and persist the pending-ask origin before calling
handle_tinyplace_signal_send_message in tool.send_to_agent so any fast reply can
be threaded correctly. Move the pending_ask computation/storage earlier in the
send flow, using the same recipient/operation context already available in this
branch, and make sure the stored origin is cleared if the outbound send fails so
stale state does not remain.
- Around line 94-111: The `MASTER_ORIGIN` process-global in
`src/openhuman/orchestration/tools.rs` can bleed across concurrent tool calls,
causing unrelated A2A `orchestration_send_to_agent` calls to pick up the master
origin. Update the origin tracking so it is scoped to the specific spawned
tool-call context used by `orchestration_send_to_agent`, or gate reads with a
per-turn token/identifier so only calls from the active master turn can consume
it. Make the change in the origin lookup path that currently prefers
`MASTER_ORIGIN`, and keep the master vs peer-session behavior separated by the
existing `send_to_agent`/`execute` flow.
- Around line 591-596: The explicit session handling in `tools.rs` currently
filters out pinned values and then silently falls back to minting/reusing
another thread; instead, `explicit_session` processing in the tool path should
reject pinned or otherwise invalid `sessionId` values outright. After opening
the store, validate the provided session by comparing
`store::session_agent_id(conn, sid)` against `recipient` before using it, and
fail the request if it does not match. Apply the same validation to the
corresponding peer-message path so `sessionId` cannot be used to persist or send
under another peer’s thread.

In `@src/openhuman/tinyplace/manifest.rs`:
- Around line 3045-3061: The discoverability check in
ensure_signal_keys_published is too permissive because it returns true based
only on local key readiness and encryptionKeyPublished. Update the logic to also
consult the remote health from signal_key_status and only return Ok(true) when
the remote key bundle is confirmed usable; otherwise keep provisioning/retrying
or return Ok(false) so the supervisor does not stop early. Apply the same
remote-health gating to the related retry path in the other
ensure_signal_keys_published branch as well.

---

Nitpick comments:
In `@src/openhuman/orchestration/ops.rs`:
- Around line 1030-1044: The process-global master origin in the orchestration
path can be left stale if the awaited turn exits early, so update the logic
around begin_master_origin and end_master_origin in the reasoning turn flow to
use an RAII guard whose Drop cleanup always clears the origin. Keep the existing
is_local_master check, but wrap the begin_master_origin call in a guard scoped
across the await in the with_steering / with_origin_session / run_agent_turn
sequence so cleanup is tied to future drop instead of relying on a trailing
end_master_origin call.
🪄 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: 166108a9-ba67-49a0-a937-53eab0fa7237

📥 Commits

Reviewing files that changed from the base of the PR and between 77639d3 and 733e9ef.

📒 Files selected for processing (19)
  • docs/scoping/master-chat.md
  • src/openhuman/agent_registry/agents/loader.rs
  • src/openhuman/orchestration/graph/build.rs
  • src/openhuman/orchestration/graph/tests.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/mod.rs
  • src/openhuman/orchestration/ops.rs
  • src/openhuman/orchestration/reasoning_agent/agent.toml
  • src/openhuman/orchestration/reasoning_agent/prompt.md
  • src/openhuman/orchestration/schemas.rs
  • src/openhuman/orchestration/store.rs
  • src/openhuman/orchestration/tools.rs
  • src/openhuman/orchestration/types.rs
  • src/openhuman/tinyplace/manifest.rs
  • src/openhuman/tinyplace/mod.rs
  • src/openhuman/tools/ops.rs

Comment thread docs/scoping/master-chat.md Outdated
Comment thread docs/scoping/master-chat.md Outdated
Comment thread src/openhuman/orchestration/ops.rs Outdated
Comment thread src/openhuman/orchestration/ops.rs
Comment thread src/openhuman/orchestration/ops.rs Outdated
Comment thread src/openhuman/orchestration/tools.rs
Comment on lines +591 to +596
let explicit_session = args
.get("sessionId")
.and_then(Value::as_str)
.map(str::trim)
.filter(|s| !s.is_empty() && !is_pinned_window(s))
.map(str::to_string);

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject invalid or mismatched sessionId instead of falling back.

A pinned sessionId is currently filtered out, so sessionId: "master" silently reuses/mints another thread. Also validate that an explicit session belongs to recipient; otherwise the tool can send/persist a peer message under another peer’s thread id.

Suggested validation shape
-        let explicit_session = args
+        let explicit_session = match args
             .get("sessionId")
             .and_then(Value::as_str)
             .map(str::trim)
-            .filter(|s| !s.is_empty() && !is_pinned_window(s))
-            .map(str::to_string);
+            .filter(|s| !s.is_empty())
+        {
+            Some(s) if is_pinned_window(s) => {
+                return Ok(ToolResult::error(
+                    "`sessionId` must be an agent session, not a pinned window".to_string(),
+                ));
+            }
+            Some(s) => Some(s.to_string()),
+            None => None,
+        };

Then, after opening the store, compare store::session_agent_id(conn, sid) with recipient before using the explicit session.

Also applies to: 619-621

🤖 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/tools.rs` around lines 591 - 596, The explicit
session handling in `tools.rs` currently filters out pinned values and then
silently falls back to minting/reusing another thread; instead,
`explicit_session` processing in the tool path should reject pinned or otherwise
invalid `sessionId` values outright. After opening the store, validate the
provided session by comparing `store::session_agent_id(conn, sid)` against
`recipient` before using it, and fail the request if it does not match. Apply
the same validation to the corresponding peer-message path so `sessionId` cannot
be used to persist or send under another peer’s thread.

Comment on lines +638 to +648
// Send over the tiny.place Signal channel (same op the graph's send_dm and
// the send_master RPC use).
let mut send_params = serde_json::Map::new();
send_params.insert("recipient".to_string(), Value::from(recipient.clone()));
send_params.insert("plaintext".to_string(), Value::from(plaintext));
if let Err(e) =
crate::openhuman::tinyplace::handle_tinyplace_signal_send_message(send_params).await
{
log::warn!(target: "orchestration", "[orchestration] tool.send_to_agent send failed: {e}");
return Ok(ToolResult::error(format!("send failed: {e}")));
}

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Arm pending-ask before the outbound send.

The current order sends the Signal DM first and records pending_ask only afterward. A fast peer reply can be ingested before Line 704 stores the origin, so the reply misses W7 threading. Compute/store the origin before handle_tinyplace_signal_send_message, and clear it if the send fails.

Also applies to: 692-710

🤖 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/tools.rs` around lines 638 - 648, Arm and persist
the pending-ask origin before calling handle_tinyplace_signal_send_message in
tool.send_to_agent so any fast reply can be threaded correctly. Move the
pending_ask computation/storage earlier in the send flow, using the same
recipient/operation context already available in this branch, and make sure the
stored origin is cleared if the outbound send fails so stale state does not
remain.

Comment on lines +653 to +681
let persisted = store::with_connection(&workspace, |conn| {
let seq = store::next_session_seq(conn, &recipient, &session_id)?;
store::upsert_session(
conn,
&OrchestrationSession {
session_id: session_id.clone(),
agent_id: recipient.clone(),
source: String::new(),
label: None,
workspace: None,
last_seq: seq,
created_at: now.clone(),
last_message_at: now.clone(),
},
)?;
store::insert_message(
conn,
&OrchestrationMessage {
id: message_id.clone(),
agent_id: recipient.clone(),
session_id: session_id.clone(),
chat_kind: ChatKind::Session,
role: "owner".to_string(),
body: message.clone(),
timestamp: now.clone(),
seq,
},
)
});

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Wrap seq allocation and insert in in_immediate_txn.

next_session_seq + insert_message is race-prone when two sends target the same session concurrently. The store’s own concurrency test documents that allocation and insert must happen under in_immediate_txn; apply that here to avoid duplicate/rejected seqs after the DM has already been sent.

🤖 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/tools.rs` around lines 653 - 681, The session
sequence allocation and message insert in tools.rs are race-prone because
`next_session_seq` and `store::insert_message` are currently executed without
the store’s immediate transaction protection. Update the logic in the
`store::with_connection` block for the session/message write path to run the
`next_session_seq` + `upsert_session` + `insert_message` sequence inside
`in_immediate_txn`, matching the concurrency-safe pattern used by the store’s
own tests and preventing duplicate or rejected sequence numbers when concurrent
sends hit the same session.

Comment on lines +3045 to +3061
let keys_ready = status
.get("hasActiveSignedPreKey")
.and_then(Value::as_bool)
.unwrap_or(false)
&& status
.get("localPreKeyCount")
.and_then(Value::as_u64)
.unwrap_or(0)
> 0;
let published = status
.get("encryptionKeyPublished")
.and_then(Value::as_bool)
.unwrap_or(false);

if keys_ready && published {
log::debug!("{LOG_PREFIX} ensure_signal_keys_published: already discoverable");
return Ok(true);

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Include remote key-bundle health before declaring discoverability.

Ok(true) currently only means local keys exist and the directory card has encryptionPublicKey. If remote key health is unavailable or depleted, peers may still fail to fetch/encrypt to a usable bundle while the supervisor stops retrying. Use the remote health from signal_key_status to provision/retry or return Ok(false) until the remote bundle is confirmed usable.

Also applies to: 3079-3085

🤖 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/tinyplace/manifest.rs` around lines 3045 - 3061, The
discoverability check in ensure_signal_keys_published is too permissive because
it returns true based only on local key readiness and encryptionKeyPublished.
Update the logic to also consult the remote health from signal_key_status and
only return Ok(true) when the remote key bundle is confirmed usable; otherwise
keep provisioning/retrying or return Ok(false) so the supervisor does not stop
early. Apply the same remote-health gating to the related retry path in the
other ensure_signal_keys_published branch as well.

…rrelation, durable surfacing

Addresses CodeRabbit + Codex review on the master-chat receive loop:

- Prompt-injection: run a peer's UNTRUSTED reply through a new tool-free
  `master_reporter` agent (no tiny.place tools / sub-agents) instead of the
  full `master_agent`, and frame the reply as quoted data — a malicious peer
  can no longer prompt-inject OpenHuman into reading sessions or messaging
  contacts.
- Respect the orchestration opt-out: the drain supervisor loads config first
  and skips key-publishing + mailbox draining when `[orchestration].enabled`
  is false (no longer makes a user discoverable / mutates remote directory
  state against their config).
- Scope `pending_ask` by `(peer_agent_id, session_id)`, not session id alone,
  so a legacy shared `wrapper_session_id` across peers can't consume the ask
  and misroute the reply.
- Consume the one-shot pending ask + advance the cursor ONLY after the reply
  is durably surfaced: `thread_reply_to_origin` now returns a status and the
  caller retries on the next drain instead of dropping the answer on a
  transient store failure.
- Local-master `send_dm`: propagate the persist failure (the persist IS the
  send) so the graph doesn't mark the cycle sent + advance over a lost answer.
- Make the W7 test hermetic: exercise the deterministic peer-origin threadback
  path (the master-origin report runs a real model turn, covered live).
- Docs: refresh the scoping matrix + W7 section to the landed beacon /
  tool-free-report / fire-and-forget flow.
@sanil-23

sanil-23 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @coderabbitai + Codex — addressed the substantive findings in 412eceb.

Fixed

  • Prompt-injection (ops.rs report path): peer replies now run through a new tool-free master_reporter agent (no tiny.place tools / sub-agents) with the reply framed as quoted, non-instruction data. Untrusted peer text can no longer reach OpenHuman's tool belt.
  • Gate key-publish on [orchestration].enabled (ops.rs:181): the drain supervisor now loads config first and skips both key-publishing and mailbox draining when orchestration is disabled — no remote directory mutation / discoverability against a user's opt-out.
  • Scope pending_ask by (peer_agent_id, session_id) (ops.rs:316, tools.rs:705): store key is now pending_ask:{agent}:{session}, so a legacy shared wrapper_session_id across peers can't consume the wrong ask.
  • Consume the one-shot only after a durable surface (ops.rs:772): thread_reply_to_origin returns a Result; the caller clears pending_ask + advances the cursor only on success, otherwise the reply retries on the next drain instead of being dropped.
  • Local-master persistence failure (ops.rs:1260): the persist is the send, so it now propagates the error instead of Ok(()) — the graph won't mark dm_sent + advance over a lost answer.
  • Test determinism (ops.rs:2091): the W7 test now exercises the deterministic peer-origin threadback (the master-origin path runs a real model turn, covered live), and asserts the (agent, session) one-shot scoping.
  • Docs (docs/scoping/master-chat.md): the status matrix is relabeled pre-PR/Landed, and the W7 section now describes the process-global beacon + tool-free report + fire-and-forget flow.

Deferred with reason

  • Beacon process-global race (tools.rs:111): local-master wakes are serialized by the generation guard, so at most one master turn brackets the beacon; the only overlap is a concurrent A2A send during that window (single-user desktop, non-fatal — mis-threads at most one reply). Kept documented rather than adding cross-turn locking. Open to a follow-up if you'd prefer it closed.
  • Arm before send (tools.rs:648): the outbound send is awaited before arming and the reply arrives strictly after it, so arming-after avoids leaving a stale marker on a send failure; the sub-ms gap can't be beaten by a network round-trip.
  • in_immediate_txn for seq+insert (schemas.rs:510, tools.rs:681): low-risk on the serialized master window; noted as a hardening follow-up for the shared-write paths.
  • Remote bundle health before "discoverable" (manifest.rs:3061): ensure_signal_keys_published re-probes status after publishing; a stricter remote-health gate is a reasonable follow-up.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
git log --oneline -5
echo "---"
git show 412eceb --stat | head -50
echo "--- master_reporter ---"
rg -n "master_reporter" -C2 || true
echo "--- pending_ask key scoping ---"
rg -n "pending_ask:" src/openhuman/orchestration/store.rs src/openhuman/orchestration/tools.rs src/openhuman/orchestration/ops.rs || true
echo "--- orchestration.enabled gating in ops.rs ---"
rg -n "enabled" src/openhuman/orchestration/ops.rs | head -30
echo "--- thread_reply_to_origin signature ---"
rg -n "fn thread_reply_to_origin" -A5 src/openhuman/orchestration/ops.rs || true

Length of output: 3741


@sanil-23 Thanks for the detailed writeup — I confirmed commit 412eceb9 lands exactly what's described:

  • New src/openhuman/orchestration/master_reporter/ module (agent.toml, mod.rs, prompt.md, prompt.rs) — a separate, tool-free agent for framing untrusted peer replies, which closes the prompt-injection path cleanly since it can't reach the tool belt at all.
  • ops.rs, store.rs, and tools.rs diffs align with the described [orchestration].enabled gating, (peer_agent_id, session_id)-scoped pending_ask keys, and the thread_reply_to_originResult change for durable-before-consume semantics.
  • Docs and test changes in the diffstat match the W7 section refresh and the hermetic test description.

All of that looks solid. On the deferred items:

  • Beacon process-global race and arm-before-send ordering — your reasoning (serialized by the generation guard, sub-ms window, non-fatal single-user impact) is sound; fine to leave documented rather than adding cross-turn locking now.
  • in_immediate_txn for seq+insert and remote bundle health gate — agreed these are reasonable hardening follow-ups rather than blockers for this PR.

If you'd like, I can open follow-up issues for the four deferred items so they don't get lost — just let me know and I'll file them (tagging you as reporter).

ฅ^•ﻌ•^ฅ

[resolve]

@sanil-23

sanil-23 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai already opened the defferred issues

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@sanil-23 Got it — thanks for opening those already, no need for me to file duplicates. Nice work landing this end-to-end.

ヽ(•‿•)ノ

@sanil-23

sanil-23 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai re-review then

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@sanil-23 Sounds good — kicking off a fresh review of the current state of the PR.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@senamakel senamakel merged commit e042947 into tinyhumansai:main Jul 7, 2026
15 checks passed
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/. 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