Skip to content

fix(hosted/orchestration): scope turn origin for local-agent spawn so cron tools aren't denied - #5527

Merged
senamakel merged 2 commits into
tinyhumansai:mainfrom
YellowSnnowmann:fix/cron-origin-effect-executor-5508
Aug 13, 2026
Merged

fix(hosted/orchestration): scope turn origin for local-agent spawn so cron tools aren't denied#5527
senamakel merged 2 commits into
tinyhumansai:mainfrom
YellowSnnowmann:fix/cron-origin-effect-executor-5508

Conversation

@YellowSnnowmann

@YellowSnnowmann YellowSnnowmann commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fix agent cron_add/cron_update (and every external-effect tool) failing with "agent turn has no origin label" when the turn's work runs on a spawned task.
  • AGENT_TURN_ORIGIN is a tokio::task_local, which does not cross tokio::spawn; the hosted-orchestration local-agent path spawned without re-scoping it, so the approval gate saw AgentTurnOrigin::Unknown and fail-closed-denied.
  • Scope an explicit origin at that residual spawn site, and make the deny message actionable.

Problem

PR #5465 fixed the four canonical spawn sites (agent/orchestration/{ops, workflow_runs/engine, tools/spawn_async_subagent, agent_teams/runtime}) so the turn origin survives delegation. One site was missed: src/openhuman/hosted/orchestration/effect_executor.rs::run_local_agent fires run_local_agent_and_forward from a bare tokio::spawn with no origin scope. On that task turn_origin::current() is None → the gate treats it as AgentTurnOrigin::Unknown (security/approval/gate.rs) and refuses external-effect tools with the raw "no origin label" marker. This is the multi-core / intermittent cron_add failure reported in #5508 and #5499 (the Settings→Cron UI path is unaffected because it writes the store directly, never through the gate).

Solution

  • effect_executor.rs: wrap the spawned agent future in turn_origin::with_origin(AgentTurnOrigin::Cli, …). This path is post-approval device automation with no ambient turn (current() is None, so with_inherited_origin would stay Unknown); Cli matches the repo's existing turn-less internal-dispatch precedent (mcp/registry/ops.rs, agent/task_dispatcher/executor.rs). The gate is not weakened, cron is not granted at the gate, and no label is manufactured inside run_subagent.
  • gate.rs: rewrite the Unknown deny message to state, specifically and actionably, that the external-effect/scheduling tool was refused because the turn carried no origin label — not a generic permissions error.

Submission Checklist

  • Tests added or updated — gate.rs: cron_add on a bare tokio::spawn denies with "origin label", and under an explicit with_origin(Cli, …) scope resolves to a real origin and is allowed (across a real spawn boundary). turn_origin.rs: an explicit Cli origin survives a turn-less spawn. Updated the existing deny-message assertions to the new copy.
  • Diff coverage ≥ 80% — enforced by CI (ci-lite.yml); changed lines covered by the added gate/origin tests. cargo test green locally.
  • Coverage matrix updated — N/A: behaviour-only change (security-gate regression fix, no new feature surface).
  • Affected feature IDs under ## RelatedN/A: behaviour-only change.
  • No new external network dependencies — N/A.
  • Manual smoke checklist — N/A: no release-cut smoke surface.
  • Linked issues closed via Closes in ## Related.

Impact

  • Restores agent-initiated cron scheduling on cores/sessions that route agent work through the hosted-orchestration local-agent spawn. Security posture unchanged — the fail-closed gate still denies genuinely unlabelled turns; this only gives the legitimate device-automation path a correct label. Note: PR feat(agent): make an embedded turn observable, rooted, and able to finish #5465's four fixes are already on main but not yet in a release, so shipped builds need a release to carry the full fix.

Related


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

  • N/A — human-authored.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed approval handling for scheduled and other external-effect actions initiated through command-line workflows.
    • Added clearer denial messages when an action lacks the required origin information, including guidance to retry.
    • Ensured valid command-line-originated actions are recognized correctly when running in background tasks.
    • Improved regression coverage for origin-aware approval behavior.

`AGENT_TURN_ORIGIN` is a `tokio::task_local`, so it does not cross
`tokio::spawn`. `effect_executor::run_local_agent` fires the local
sub-agent from a bare `tokio::spawn` with no agent turn on the stack, so
`turn_origin::current()` was `None` on the spawned task, the approval
gate read `AgentTurnOrigin::Unknown`, and every external_effect tool the
sub-agent called (cron_add / cron_update / shell / …) was denied as
"agent turn has no origin label".

PR tinyhumansai#5465 fixed the four canonical spawn sites (orchestration spawn_agent,
spawn_async_subagent, workflow runs, agent teams) via
`capture`/`propagate`/`with_inherited_origin`. This closes the residual
`effect_executor` gap. There is no ambient turn to inherit here (the
device-tool bridge is not itself an agent turn), so an explicit
`AgentTurnOrigin::Cli` is scoped around the spawned work — this path only
runs after the device-authoritative Master-chat gate in
`dispatch_device_tool` has passed, matching the turn-less internal
dispatch label already used by `mcp::registry` and `task_dispatcher`.

Also makes the gate's `Unknown` deny message specific and actionable: it
names the missing origin label, the scheduling/external-effect tools it
blocks, and frames it as an internal wiring gap rather than user error,
without leaking internals.

Tests: gate unit test that a `cron_add` call on a turn-less/delegated
spawn resolves to a real origin (allowed) instead of `Unknown`-denied;
turn_origin propagation test covering the explicit-`Cli`-across-spawn
shape of the effect_executor site.

Closes tinyhumansai#5508, tinyhumansai#5499
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d73a197-1075-4bc9-a81b-527050dab17e

📥 Commits

Reviewing files that changed from the base of the PR and between b508b3c and 4b68c35.

📒 Files selected for processing (4)
  • src/openhuman/agent/turn_origin.rs
  • src/openhuman/hosted/orchestration/effect_executor.rs
  • src/openhuman/security/approval/gate.rs
  • tests/raw_coverage/tool_registry_approval_raw_coverage_e2e.rs

📝 Walkthrough

Walkthrough

The change establishes an explicit CLI origin for background local-agent tasks, preserves origin visibility across spawned tasks, improves unknown-origin denial guidance, and adds regression coverage for denied and allowed cron_add calls.

Changes

Origin propagation and approval

Layer / File(s) Summary
Turn origin scope behavior
src/openhuman/agent/turn_origin.rs
Tests that an explicitly scoped AgentTurnOrigin::Cli remains observable after a turnless spawn.
Unknown-origin approval behavior
src/openhuman/security/approval/gate.rs, tests/raw_coverage/tool_registry_approval_raw_coverage_e2e.rs
Improves unknown-origin denial guidance and tests fail-closed behavior for unscoped cron_add calls and allowed behavior for explicitly scoped CLI calls.
Local-agent origin wiring
src/openhuman/hosted/orchestration/effect_executor.rs
Wraps background local-agent execution in an explicit CLI origin scope and documents that run_local_agent establishes the origin.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Mergeability Score: 🔵 Low · up to 4b68c

The PR restores hosted background scheduling by assigning the work an existing broad command-line trust category, which also enables other eligible external-effect actions on that path. Local master-cycle checks limit reachability, but the remaining bounded security and audit risk is that hosted automation shares this broad authority and the provenance binding for the triggering cycle is not fully established; the change is mergeable with explicit owner awareness.

Possibly related issues

  • tinyhumansai/openhuman issue 5499 — Addresses explicit CLI origin propagation so cron_add passes the security gate.

Possibly related PRs

Suggested labels: rust-core, bug, test

Suggested reviewers: senamakel

Poem

A rabbit checks the origin tag,
No hidden hop escapes the bag.
cron_add waits, then passes through,
When Cli marks the task as true.
The gate explains what went astray—
And spawned turns find their way. 🐇

🚥 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 fix: preserving turn origin for local-agent tasks so cron tools are not denied.
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.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@YellowSnnowmann
YellowSnnowmann marked this pull request as ready for review August 13, 2026 08:38
@YellowSnnowmann
YellowSnnowmann requested a review from a team August 13, 2026 08:38
@coderabbitai coderabbitai Bot added bug rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. test Test additions, fixes, or harness work. labels Aug 13, 2026

@tinysweeper tinysweeper 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.

tinysweeper found nothing blocking. Approving.

             $0.0344 · 30,885 in / 11,466 out · 26,008 cached (84%) · z-ai/glm-5.2
critique:    $0.0159 · 10,587 in / 5,686 out  · 9,095 cached (86%)  · z-ai/glm-5.2
security:    $0.0107 · 9,827 in  / 3,484 out  · 8,098 cached (82%)  · z-ai/glm-5.2
tests:       $0.0058 · 4,790 in  / 1,952 out  · 4,010 cached (84%)  · z-ai/glm-5.2
description: $0.0021 · 5,681 in  / 344 out    · 4,805 cached (85%)  · z-ai/glm-5.2

@tinysweeper

tinysweeper Bot commented Aug 13, 2026

Copy link
Copy Markdown

What this change touches

4 files, +141 -16 across 4 components. The code graph knows nothing about these files yet — normal for newly added files, and a cold index otherwise.

flowchart LR
  n0["src/openhuman/security/approval<br/>1 file +68 -4"]:::changed
  n1["src/openhuman/hosted/orchestration<br/>1 file +44 -11"]:::changed
  n2["src/openhuman/agent<br/>1 file +28 -0"]:::changed
  n3["tests/raw_coverage<br/>1 file +1 -1"]:::changed
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading

Green: changed. Grey: untouched, reached through an import or a call. Orange: has findings. Red: has a finding that blocks the merge.

Component Files Lines Findings
src/openhuman/security/approval changed 1 +68 -4
src/openhuman/hosted/orchestration changed 1 +44 -11
src/openhuman/agent changed 1 +28 -0
tests/raw_coverage changed 1 +1 -1
Changed files

src/openhuman/security/approval

  • src/openhuman/security/approval/gate.rs

src/openhuman/hosted/orchestration

  • src/openhuman/hosted/orchestration/effect_executor.rs

src/openhuman/agent

  • src/openhuman/agent/turn_origin.rs

tests/raw_coverage

  • tests/raw_coverage/tool_registry_approval_raw_coverage_e2e.rs

tinysweeper 0.1.0

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Aug 13, 2026
@senamakel
senamakel merged commit 1b7f621 into tinyhumansai:main Aug 13, 2026
33 of 37 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Team Openhuman Aug 13, 2026
@YellowSnnowmann
YellowSnnowmann deleted the fix/cron-origin-effect-executor-5508 branch August 13, 2026 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. test Test additions, fixes, or harness work.

Projects

Archived in project

2 participants