Skip to content

embed: steer a running turn and hand back unapplied steers - #7853

Merged
senamakel merged 12 commits into
tinyhumansai:mainfrom
senamakel:embed-turn-steering
Oct 15, 2026
Merged

senamakel merged 12 commits into
tinyhumansai:mainfrom
senamakel:embed-turn-steering

Conversation

@senamakel

@senamakel senamakel commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Adds Turn::steering_handle() to openhuman-embed. It returns a TurnSteering handle (Clone + Send + Sync) that adds user messages to a turn while the turn runs.
  • AgentChatEnv gains run_queue. agent_chat_reply_for attaches it with OpenHumanSessionHost::set_run_queue, so the existing steering forwarder delivers queued steers into the running loop. Both embed turn targets get this: runtime-owned agents and the orchestrator of a caller-built runtime.
  • Steers the turn did not apply are handed back, never dropped. On success they come back in TurnOutcome::unapplied_steers. After a failure or cancellation they come from TurnSteering::take_unapplied(). A steer sent after the turn ended is refused with SteerRefused, which carries the text.
  • Bumps vendor/tinyagents to Requeue unapplied steers synchronously when a forwarder guard drops tinyagents#462.

Problem

Embedders could cancel a turn but could not add to one. A message that arrived while a turn was running had to wait for it to finish and then run as a separate turn, often against a reply the model wrote without that message. Web chat already steers turns through the session run queue. The embed dispatch path (agent_chat_for) never attached a queue.

Solution

  • TurnSteering owns a RunQueue<QueuedTurn>. steer() pushes onto the Steer lane. The core's forwarder injects each steer as [User steering message]: <text>, and the agent loop applies it at its next safe checkpoint:
    • before the first model call, for a steer queued before send();
    • after a tool batch has settled;
    • when the model has written what would be its final answer. TinyAgents' settle_natural_finish keeps the draft as an assistant message, appends the steer and calls the model again, bounded by the iteration cap. So a steer sent during a plain chat turn's only model call still shapes that turn's reply.
  • Nothing interrupts a model call or a tool that is already running.
  • Leftovers are collected deterministically. tinyagents#462 makes the forwarder guard requeue delivered-but-unapplied steers synchronously when it drops, so once the turn future finishes every unapplied steer is back in the queue. A SteeringScope declared first in Turn::send_inner drops after the dispatch future. Closing it and pushing a new steer take the same lock, so a steer is either refused or reported, never lost.
  • The API describes the capability only. Hosts decide whether to run leftovers as a new turn.

Public API

impl Turn { pub fn steering_handle(&mut self) -> TurnSteering; }

#[derive(Clone)] pub struct TurnSteering;            // Send + Sync, Debug
impl TurnSteering {
    pub fn steer(&self, text: impl Into<String>) -> Result<(), SteerRefused>;
    pub fn take_unapplied(&self) -> Vec<String>;
}

#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub struct SteerRefused;
impl SteerRefused { pub fn text(&self) -> &str; pub fn into_text(self) -> String; }

pub struct TurnOutcome { /* ... */ pub unapplied_steers: Vec<String> }   // new field
pub struct AgentChatEnv { /* ... */ pub run_queue: Option<Arc<RunQueue<QueuedTurn>>> } // openhuman-core, new field

Adding a field to TurnOutcome breaks struct literals outside the crate. No in-tree crate builds one outside openhuman-embed's own tests.

Submission Checklist

  • Tests added or updated:
    • crates/openhuman-embed/tests/turn_steering.rs (end to end against a wiremock provider): a steer sent during a plain chat turn's only model call follows the draft and earns a second call in the same turn; a steer queued before send reaches the first call; a steer after the end is refused with its text; a cancelled turn hands its delivered steer back.
    • src/turn_steering_tests.rs covers ordering, closing, the failure path, a late requeue, and that Debug leaves out message text.
    • With the core wiring removed, the end-to-end test fails: the reply is the un-steered draft.
  • Diff coverage ≥ 80%: not measured locally. The new module and the core wiring are exercised by the tests above.
  • Coverage matrix updated: row 16.1.30 "Steering a running turn".
  • Affected feature IDs: 16.1.30, plus 16.1.13 (per-turn cancellation, which shares the turn control path).
  • No new external network dependencies.
  • Manual smoke checklist: N/A. This is a library API, not a release-cut surface.
  • Linked issue: N/A. No tracking issue.

Validation run locally

  • cargo test -p openhuman-embed --test turn_steering: pass.
  • cargo test -p openhuman-embed --lib turn: 34 passed.
  • cargo clippy -p openhuman -p openhuman-embed --all-targets -- -D warnings: no findings in the changed files. The lint run itself fails on pre-existing unused imports in untouched files (for example agent/artifacts/schemas.rs).
  • cargo fmt -p openhuman-embed -- --check: clean. Workspace cargo fmt --check flags about 50 untouched core files that are already unformatted on main.
  • node scripts/ci/check-openhuman-rust-layout.mjs: pass.
  • cargo test -p openhuman-embed --no-fail-fast: three suites fail locally, completion_routing (finish reason length vs MAX_TOKENS), tool_hook_context (shell HOME in the sandbox) and cron_host_delivery (job did not fire). None of them takes a steering handle, and without one the turn runs with run_queue: None, which matches main. I treat them as environmental or pre-existing.

Impact

  • Library and in-process embedders only. Turns without a steering handle behave as before.
  • No migration needed.

Related

Summary by CodeRabbit

  • New Features
    • Added turn-scoped steering, allowing messages to be queued before or during a turn and handled at safe checkpoints.
    • Turn outcomes now report steering messages that were not applied. Attempts to steer after a turn ends are refused, with the message retained.
  • Documentation
    • Added guidance on steering behavior, including how it interacts with active model calls, tools, and turn completion.

senamakel and others added 12 commits October 15, 2026 10:40
Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds the agent chat operations to the host runtime, wiring up the
inference entry points needed to run chat requests through the host
runtime.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Move the turn steering logic out of the embed crate's main file into a dedicated module so the steering behaviour is easier to find and maintain. No functional change is intended.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Move the turn steering logic out of the embed crate's main module into a
dedicated file so the steering behaviour can be tested and evolved
independently. No behaviour change.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds coverage for turn steering behaviour in the embed crate, exercising the
steering paths that previously had no direct tests.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce turn control and turn type modules to the embed crate, giving
callers a structured way to manage and describe turns. The lib module is
updated to expose the new pieces.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The turn outcome test fixture now initializes the new unapplied_steers field so it matches the updated struct.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add integration tests covering turn steering in the embed crate, exercising
the steering flow end to end to guard against regressions.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reduce the slow provider delay in the cancelled-turn scenario from 30s to 4s so the test no longer stalls for half a minute while still exercising the same cancellation path.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a README for the embed crate and its tests directory, and introduce a public API test that exercises the crate's exported surface. The docs explain how to run the tests and what the public API test covers.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the steering handle call and the unapplied-steers assertion so each fits on one line, matching rustfmt output. No test behaviour changed.

Auto-committed-on: macbook
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-15T06:13:13.093302Z 62f892b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 13917f70-f98b-4ff8-ad6c-c6596188c4b2
📥 Commits

Reviewing files that changed from the base of the PR and between 13dc83d and 62f892b.

📒 Files selected for processing: 14
  • crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs
  • crates/openhuman-embed/README.md
  • crates/openhuman-embed/src/lib.rs
  • crates/openhuman-embed/src/turn.rs
  • crates/openhuman-embed/src/turn_control.rs
  • crates/openhuman-embed/src/turn_steering.rs
  • crates/openhuman-embed/src/turn_steering_tests.rs
  • crates/openhuman-embed/src/turn_tests.rs
  • crates/openhuman-embed/src/turn_types.rs
  • crates/openhuman-embed/tests/README.md
  • crates/openhuman-embed/tests/public_api.rs
  • crates/openhuman-embed/tests/turn_steering.rs
  • docs/TEST-COVERAGE-MATRIX.md
  • vendor/tinyagents

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📝 Walkthrough

The embedding API adds turn-scoped steering. It queues messages for agent chat, refuses steering after a turn ends, and reports messages that were not applied. Tests and documentation cover steering during execution, before the first model call, after completion, and during cancellation.

Changes: Turn Steering

Layer / File(s) Summary
Steering API and state
crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_types.rs
Adds the TurnSteering and SteerRefused APIs, shared queue state, and TurnOutcome::unapplied_steers. Turn stores an optional steering handle. Unit tests cover queue ordering, scope completion, and refused messages.
Queue delivery and turn dispatch
crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/turn_control.rs, vendor/tinyagents
Passes the steering queue through AgentChatEnv during dispatch. send_inner closes the steering scope and includes unapplied messages in TurnOutcome. The vendored tinyagents reference changes.
Steering tests and documentation
crates/openhuman-embed/tests/*, crates/openhuman-embed/README.md, crates/openhuman-embed/tests/README.md, crates/openhuman-embed/src/turn_tests.rs, docs/TEST-COVERAGE-MATRIX.md
Tests cover steering before and during execution, refusal after completion, and cancellation. Documentation describes steering checkpoints and unapplied messages. The TurnOutcome test fixture initializes the new field.

Priority: ⬇️ Low

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

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant Turn
  participant TurnSteering
  participant SendInner as Turn::send_inner
  participant AgentChatEnv
  participant TurnOutcome
  Caller->>Turn: request steering_handle()
  Turn-->>Caller: return TurnSteering
  Caller->>TurnSteering: steer(text)
  SendInner->>AgentChatEnv: pass run_queue
  AgentChatEnv-->>SendInner: dispatch completes
  SendInner->>TurnOutcome: include unapplied steers
Loading

Suggested reviewers: sanil-23, oxoxdev

Merge Risk: 🔵 Low · up to 62f89

The steering feature looks sound as described. Before merging, confirm that the vendored tinyagents pointer references the commit merged upstream and not only a branch head.

Security architecture risk: 🟡 Moderate · up to 62f89

The new live-message path does not visibly apply the same input checks as the initial message. Existing permissions remain in place, limiting exposure, but input-policy parity and recovery of messages during cancellation are not fully established.

Retained concerns

  • Medium · security · inferred: The newly reachable embed steering path accepts additional user text under the active turn's authority without visible application of the prompt policy enforced on the initial message. A handle holder could submit a benign initial request and subsequently steer with content that the initial-input guard would reject. Existing turn permissions and approvals constrain the outcome; the missing upstream consumer and unspecified embedder trust model make the end-to-end bypass inferred rather than fully verified.
Security review details

Security Blast Radius

  • inferred — Possession of a steering handle delegates influence over one selected turn, including model decisions using that turn's existing tools and accessible data. The inspected path does not let message text select another target or mint new permissions. Wider tenant, service, or environment exposure depends on the host's existing authority and how it distributes handles; production deployment policy was not supplied.

Security Findings and Attack Paths

  • inferred — The material attack hypothesis is a handle holder introducing policy-rejected instructions after an acceptable initial message has passed admission. The initial guards inspect only their message argument, while the new queue reaches a separate feed. This is newly reachable through embed dispatch, although steering infrastructure predates the PR. No successful unsafe tool action or disclosure was established, and the unavailable consumer limits verification.

Trust Boundaries and Controls

  • observed — The handle is a bearer capability: clones share the same queue, and submissions carry no separate client or thread identity. Core attaches the queue to the already selected session and retains its host authority and approval context. Empty submission metadata alone does not establish cross-session access or an authentication bypass.

Resilience and Maintainability Implications

  • inferred — Safe recovery requires the consumer to distinguish applied instructions from delivered-but-unapplied instructions and finish requeueing before leftovers are collected. The local implementation anticipates late cancellation requeues, but the missing dependency prevents verifying ordering, idempotency, and whether a single recovery read is complete. No message-loss or replay defect is established.

Hardening Proposals

  • proposed — Apply a consistent input-policy decision at the shared steering ingress, preserving the explicit host-only exception and returning rejected text to the caller. Document that sharing a handle delegates the active turn's input authority, with caller authentication and tenant routing remaining host responsibilities.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 55.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 38 functions across 10 files. (4 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
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 clearly and concisely summarizes the main changes: steering a running turn and returning unapplied steers.
Full details: Docstring Coverage

Explanation

Docstring coverage is 55.26% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 38 functions across 10 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit queues a thought to share
It waits until the turn can hear
If some words stay unapplied,
They’re gathered safely at the side
Then off the rabbit hops, ears high.

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

@tinysweeper

tinysweeper Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Tiny Sweeper reviewed this change across 5 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below.

State: Incomplete
Priority: none
Reviewed head: 62f892b74774
Updated: 2026-10-15T06:16:02Z

Review snapshot

Change surface Files Review signal Count
Production 6 Active findings 0
Tests 4 Noted findings 0
Documentation 3 Resolved findings 0
Configuration 0 Pending checks/questions 20

Completeness: Incomplete
Test assessment: No supported feature-to-test mapping was available; this does not mean tests are absent or passed.

Features

None identified with supported citations.

Tests

No supported feature-to-test mapping was produced. Test execution is not inferred.

Findings

No active actionable findings.

Could not review: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/README.md, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_control.rs, crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/turn_steering_tests.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/tests/README.md, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs, docs/TEST-COVERAGE-MATRIX.md

Before merge

  • Complete the critique review for crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_control.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/README.md, crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/turn_steering_tests.rs, crates/openhuman-embed/tests/README.md, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs, docs/TEST-COVERAGE-MATRIX.md.
  • Complete the security review for crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs.

How this fits together

flowchart LR
  n0["AgentChatEnv<br/>changed"]:::changed
  n1["agent_chat_reply_for<br/>changed"]:::changed
  n2["a_turn_outcome_carries_what_the_turn_spent<br/>changed"]:::changed
  n3["send_inner"]:::impacted
  n4["Result"]:::impacted
  n5["agent_chat_for"]:::impacted
  n6["dispatch"]:::impacted
  n7["agent_chat_for_inner"]:::impacted
  n8["as_ref"]:::impacted
  n1 -->|uses| n0
  n1 -->|uses| n4
  n1 -->|calls| n8
  n2 -->|calls| n8
  n2 -->|tests| n8
  n3 -->|uses| n0
  n3 -->|uses| n4
  n3 -->|calls| n8
  n5 -->|uses| n0
  n5 -->|uses| n4
  n5 -->|calls| n7
  n6 -->|calls| n1
  n6 -->|uses| n4
  n6 -->|calls| n5
  n6 -->|calls| n8
  n7 -->|uses| n0
  n7 -->|calls| n1
  n7 -->|uses| n4
  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
Agent review details

critique

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_control.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/README.md, crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/turn_steering_tests.rs, crates/openhuman-embed/tests/README.md, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs, docs/TEST-COVERAGE-MATRIX.md
  • Lane summary: Reviewed 0 files; 0 findings. 13 files could not be reviewed: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_control.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/README.md, crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/turn_steering_tests.rs, crates/openhuman-embed/tests/README.md, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs, docs/TEST-COVERAGE-MATRIX.md.

security

  • Conclusion: Success
  • Scope reviewed: incomplete; unanswered: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs
  • Lane summary: Reviewed 3 files; 0 findings. 7 files could not be reviewed: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_tests.rs, crates/openhuman-embed/src/turn_types.rs, crates/openhuman-embed/tests/public_api.rs, crates/openhuman-embed/tests/turn_steering.rs. 3 files were not security-reviewed: crates/openhuman-embed/README.md (prose or tabular data), crates/openhuman-embed/tests/README.md (prose or tabular data), docs/TEST-COVERAGE-MATRIX.md (prose or tabular data). _The code index is behind this pull request (indexed at `7afe6f9e25dc`), so retrieved context may be out of date._

tests

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: I have most of what I need: the steering module, its unit tests, the end-to-end test, and the attach path all check out against the `set_run_queue` accessor and the steering forwarding already in core. Two things remain unsettled: whether `RunQueue::push_now` can be exercised from a `#[cfg(test)]` module given how `tinyagents_harness` is re-exported (its visibility rules are in the vendored crate, which I could not see), and whether `Turn::send` re-enters `send_inner` via another caller path that would call `SteeringScope::new` twice on the same steering handle (the retry/dispatch plumbing in `turn_control.rs` lines 330–460 was cut off). One more read settles both; until then the change looks sound and its test coverage matches its stated invariants, with the end-to-end test pinning the draft-then-steer ordering the docs claim. _The code index is behind this pull request (indexed at `7afe6f9e25dc`), so retrieved context may be out of date._

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The description accurately matches the diff: `Turn::steering_handle`/`TurnSteering`/`SteerRefused` and the `TurnOutcome::unapplied_steers` field are exactly as documented, `AgentChatEnv.run_queue` is attached via `set_run_queue` in `agent_chat.rs`, the lock-checked `steer()`/`finish()` handoff matches the 'refused or reported, never lost' claim, and the `SteeringScope` drop ordering (declared first, dropped last) is implemented as described. The new tests follow the repository's sibling `_tests.rs` rule with `#[cfg(test)]`, `#[path]` and `use super::*`, and the README, coverage-matrix and public-API test changes are all reflected. The vendored tinyagents code at the reviewed commit contains the steering machinery the description depends on. Nothing in the description describes behaviour the diff lacks, and no significant diff change goes unmentioned; the change looks sound to merge from a description-accuracy standpoint. _The code index is behind this pull request (indexed at `7afe6f9e25dc`), so retrieved context may be out of date._
Evidence and run details
  • Models: ladder/vectors-oai3, glm-5.3-flash,
  • Spend: $0.005152
  • Tokens: 163282 input · 14733 output · 0 cached · 726 embedding
Head State Pass summary
62f892b74774 incomplete 0 active finding(s), 0 resolved finding(s) (at 2026-10-15T06:16:02Z)

tinysweeper 0.1.2

@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: 62f892b747

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +98 to +102
self.0.queue.push_now(
QueueLane::Steer,
QueuedTurn {
id: uuid::Uuid::new_v4().to_string(),
text,

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 Enforce prompt policy on steering messages

When steering a normal (non-untrusted_input) embed turn with end-user text, this direct RunQueue push bypasses the prompt-injection enforcement that ordinary embed turns execute in agent_chat_reply_for (agent_chat.rs:392-405); the web queue path likewise calls enforce_prompt_input before enqueueing (start_chat.rs:223-232). A string that Turn::send rejects (as exercised by structured_turns.rs:27-29,293-299) is therefore accepted by steer() and reaches a tool-capable running agent. Apply the same core policy before queuing, while retaining the explicit host-only untrusted_input exception.

AGENTS.md reference: AGENTS.md:L53-L54

Useful? React with 👍 / 👎.

async fn send_inner(mut self, usage: &UsageSink) -> Result<TurnOutcome, CoreError> {
// Declared first so it drops last, after the dispatch future: by then
// every steer the turn did not apply is back in the queue.
let steering = crate::turn_steering::SteeringScope::new(self.steering.take());

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 Close steering when pre-start cancellation wins

When turn.stream() is dropped before its spawned task first polls (or any already-cancelled token enters send_controlled), the biased cancellation branch completes without polling send_inner, so this SteeringScope is never constructed. Dropping the unpolled send_inner future then merely drops the Turn's Option<TurnSteering>: the external handle remains finished == false, later steer() calls incorrectly return Ok, and take_unapplied() can never return the stranded text. Install an owner/drop guard before the cancellable select so pre-start cancellation closes and hands back the queue.

Useful? React with 👍 / 👎.

Comment thread vendor/tinyagents
@@ -1 +1 @@
Subproject commit aa5476fa48092d9bf051fbd2d1bf07f14cc9f331
Subproject commit b6b7f994a54f43a7b7bac106dec082d56c05fbef

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 Pin the merged tinyagents commit

The commit's Related section identifies b6b7f994a as PR #462's branch head and explicitly says it must be replaced after merge. Pinning this gitlink as-is makes OpenHuman depend on an unmerged branch object rather than an independently reviewable canonical upstream commit; merge #462 first and update the gitlink to the resulting upstream commit before landing this change.

AGENTS.md reference: AGENTS.md:L537-L545

Useful? React with 👍 / 👎.

pub use session_store::{InMemorySessionStores, SessionStoreProvider};
pub use turn::{absolute, Route, Turn, TurnOutcome, TurnRequest};
pub use turn_cancellation::TurnCancellation;
pub use turn_steering::{SteerRefused, TurnSteering};

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 Regenerate the embed API index

This new public export changes the host-facing contract, but the generated api-index.md/api-index.json still omit SteerRefused and TurnSteering, and llms-full.txt still contains the old README. Checking the candidate tree with node scripts/generate-embed-docs.mjs --check while supplying the existing capability payload reports all three files as drift, so pnpm docs:check will reject the change and the published embed index hides the new API. Run the documentation generator and commit its outputs.

AGENTS.md reference: AGENTS.md:L771-L773

Useful? React with 👍 / 👎.

@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, but could not review everything, so this is not an approval: crates/openhuman-core/src/inference/host_runtime/ops/agent_chat.rs, crates/openhuman-embed/README.md, crates/openhuman-embed/src/lib.rs, crates/openhuman-embed/src/turn.rs, crates/openhuman-embed/src/turn_control.rs, crates/openhuman-embed/src/turn_steering.rs, crates/openhuman-embed/src/turn_steering_tests.rs, crates/openhuman-embed/src/turn_tests.rs and 5 more.

             $0.0052 · 163,282 in / 14,733 out · 0 cached (0%) · ladder/vectors-oai3, glm-5.3-flash,  · 726 embedded
security:    $0.0005 · 56,384 in  / 748 out    · 0 cached (0%) · glm-5.3-flash,
tests:       $0.0005 · 49,900 in  / 510 out    · 0 cached (0%) · glm-5.3-flash
description: $0.0041 · 56,998 in  / 13,475 out · 0 cached (0%) · glm-5.3-flash

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Oct 15, 2026
@senamakel
senamakel merged commit 748c349 into tinyhumansai:main Oct 15, 2026
22 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant