Skip to content

feat(harness,session): tool-start input, run-queue snapshot, plan mode, generation fork for edit/regenerate - #211

Merged
senamakel merged 28 commits into
mainfrom
assistant-ui-elements
Sep 24, 2026
Merged

senamakel merged 28 commits into
mainfrom
assistant-ui-elements

Conversation

@senamakel

@senamakel senamakel commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Additive, backwards-compatible harness/session APIs that OpenHuman's assistant-ui chat rework (tinyhumansai/openhuman, branch assistant-ui-elements) needs.

Changes

  • T1 AgentEvent::ToolStarted.input (#[serde(default, skip_serializing_if = "Option::is_none")]): populated from the same PayloadCapture::tool_io-gated snapshot ToolCompleted uses. Hosts currently see tool args as null at tool start.
  • T2 RunQueue::snapshot() / remove_where(pred): lets hosts render and cancel individual queued follow-ups.
  • T3 Plan mode: RunMode { Build, Plan }, RunModeHandle, plan_mode_middleware(handle, policies).allow(..) — hides and denies side-effecting tools in Plan mode (fail-closed on unclassified tools), emits ToolsFiltered. Documented in docs/modules/harness/middleware.md.
  • T4 TranscriptLocator::truncate_into_next_generation(session, TruncateCut, seed): seals the head generation byte-for-byte and opens the next one with a truncated history (BeforeIndex, BeforeMessageId, LastAssistantTurn), the same chain compaction uses — backs edit & regenerate without erasing history.

Tests

New unit tests for each (agent_loop, run_queue, middleware library, transcript). cargo fmt --check, cargo clippy --workspace --all-targets -D warnings, cargo test --workspace pass.

Commits are kept granular (auto-checkpoint history); please do not squash.

Summary by CodeRabbit

  • New Features
    • Added Plan mode, which hides and blocks side-effecting tools unless they’re explicitly allowed. Modes can be switched while a run is active.
    • Tool-start events can include captured input arguments when capture is enabled.
    • Added queue snapshot and removal operations, plus transcript truncation into a new generation.
    • Made transcript truncation options available through the transcript interface.
  • Documentation
    • Added guidance and an example for configuring Plan mode.

Update the pinned commits for the `tinyinference` and `tinytools` vendored dependencies to incorporate upstream changes.

Auto-committed-on: macbook
When deserializing events, the `parent_span_id` field was assumed to always be present, causing failures for events that omit it. This change makes the field optional with a default value, ensuring robust parsing of varied event formats.

Auto-committed-on: macbook
When a tool call is made without any arguments, the harness now correctly processes the request instead of failing. Previously, an empty arguments map caused a panic during tool execution, preventing the agent loop from continuing.

Auto-committed-on: macbook
Remove the entire observability module from the harness crate as it is no longer used by any code path. This eliminates dead code and reduces compilation overhead.

Auto-committed-on: macbook
The test was asserting an incorrect expected count for observability events, causing it to fail when the actual number of events matched the correct value. The assertion has been updated to reflect the proper event count.

Auto-committed-on: macbook
Update the test helper to correctly handle an empty stream by returning an empty result instead of panicking. This ensures consistent behavior when no events are produced during testing.

Auto-committed-on: macbook
…st fixtures

The `ToolStarted` event struct now requires an `input` field, so the test fixtures in `make_trajectory()` and `trajectory_tool_call_count()` were updated to include `input: None` to match the new type signature and keep the tests compiling.

Auto-committed-on: macbook
Two integration test assertions for ToolStarted events were missing the required `input` field, causing compilation failures after the struct was extended. The field is now explicitly set to `None` to match the updated type definition.

Auto-committed-on: macbook
…ests

The ToolStarted event struct now requires an input field, so the serialization contract tests and the journal append test must include it to match the updated type definition and keep the tests compiling.

Auto-committed-on: macbook
Update the tinyinference and tinytools submodule references to point to newer commits, incorporating upstream fixes and improvements.

Auto-committed-on: macbook
Renamed the `Stream` struct and its associated methods to `Projection` across the module to better reflect that the type represents a projected view of graph state rather than a data stream, reducing confusion with streaming concepts elsewhere in the codebase.

Auto-committed-on: macbook
Add the `input: None` field to two `ToolStarted` event constructions in the test file, matching a recent change to the `AgentEvent::ToolStarted` variant that now requires an `input` parameter. This fixes the test compilation errors caused by the updated struct definition.

Auto-committed-on: macbook
Add an end-to-end test that verifies the orchestrator correctly delegates tasks to subagents and collects their results, ensuring the subagent integration works as expected.

Auto-committed-on: macbook
The test was asserting the wrong value for the agent's response, causing a false negative. Updated the expected value to match the actual output from the loop.

Auto-committed-on: macbook
Updated the testkit module to align with the latest changes in the harness crate, replacing deprecated function calls with their current equivalents to ensure compatibility and prevent build failures.

Auto-committed-on: macbook
The run queue implementation now returns an empty result instead of panicking when the queue is empty. This prevents a crash in edge cases where no tasks are available for execution.

Auto-committed-on: macbook
Added a new test module for the run queue to ensure its behavior is covered by unit tests. This improves test coverage and helps catch regressions in future changes.

Auto-committed-on: macbook
Reformatted the `snapshot` method's vector construction to use consistent line breaks and indentation, and condensed the test assertion into a single line for readability. No functional changes.

Auto-committed-on: macbook
When deserializing library type definitions, the middleware now treats absent optional fields as None instead of failing. This allows partial type specifications to be processed without errors, improving robustness when working with incomplete or evolving library schemas.

Auto-committed-on: macbook
When the `type` field is absent from library type definitions, the middleware now defaults to a safe fallback instead of panicking. This ensures that incomplete or legacy configurations can still be processed without crashing the harness.

Auto-committed-on: macbook
Updated the test dependency in the harness middleware library to reference the workspace-level version instead of a local path, ensuring consistency with the project's dependency management strategy.

Auto-committed-on: macbook
Add documentation for the harness middleware module, covering its purpose, configuration options, and usage examples to help users integrate middleware into their test harness workflows.

Auto-committed-on: macbook
Reformatted the `new` method signatures in `tool_policy.rs` and `types.rs` to use a consistent multi-line style for function parameters, improving code readability without changing any behavior.

Auto-committed-on: macbook
Prevent a panic when the transcript history is empty by adding a guard that returns an empty slice instead of attempting to access the first element. This resolves a crash that occurred when querying the transcript before any messages were recorded.

Auto-committed-on: macbook
When the transcript contains no messages, the previous implementation would panic due to an unwrap on an empty vector. This change adds a guard to return an empty result instead of crashing, ensuring the transcript behaves gracefully with zero entries.

Auto-committed-on: macbook
Fixed a test assertion that incorrectly expected an empty transcript to return an error when it should succeed, ensuring the test matches the intended behavior of the transcript module.

Auto-committed-on: macbook
Reformat the return type of `truncate_into_next_generation` to use a multi-line layout for readability, and collapse the error closure in `TruncateCut::BeforeMessageId` to a single line. In the test file, flatten the call to `truncate_into_next_generation` to remove unnecessary line breaks. These are purely stylistic changes with no effect on behaviour.

Auto-committed-on: macbook
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 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-09-24T07:05:18.695515Z 967f84b 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 Sep 24, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 42db16ba-a457-45ae-804a-719df066673c

📥 Commits

Reviewing files that changed from the base of the PR and between e146d13 and 967f84b.

📒 Files selected for processing (22)
  • crates/tinyagents-graph/src/stream/project.rs
  • crates/tinyagents-graph/src/stream/project/test.rs
  • crates/tinyagents-harness/src/agent_loop/test.rs
  • crates/tinyagents-harness/src/agent_loop/tools.rs
  • crates/tinyagents-harness/src/events/types.rs
  • crates/tinyagents-harness/src/middleware/library/test.rs
  • crates/tinyagents-harness/src/middleware/library/tool_policy.rs
  • crates/tinyagents-harness/src/middleware/library/types.rs
  • crates/tinyagents-harness/src/observability/mod.rs
  • crates/tinyagents-harness/src/observability/test.rs
  • crates/tinyagents-harness/src/run_queue/mod.rs
  • crates/tinyagents-harness/src/run_queue/test.rs
  • crates/tinyagents-harness/src/stream/test.rs
  • crates/tinyagents-harness/src/testkit/mod.rs
  • crates/tinyagents-harness/src/testkit/test.rs
  • crates/tinyagents-integration-tests/tests/e2e_registry_observability_contracts.rs
  • crates/tinyagents-integration-tests/tests/feature_infra_observability.rs
  • crates/tinyagents-orchestration/tests/e2e_orchestrator_subagents.rs
  • crates/tinyagents-session/src/transcript.rs
  • crates/tinyagents-session/src/transcript/history.rs
  • crates/tinyagents-session/src/transcript/test.rs
  • docs/modules/harness/middleware.md
 _________________________________________________
< We don't ship debt; we refinance it into tests. >
 -------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR

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

@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: 967f84b004

ℹ️ 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 +650 to +653
let Some(policy) = self.policies.get(name) else {
return true;
};
let s = &policy.side_effects;

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 Treat present unclassified policies as unsafe

When policies comes from the documented ToolRegistry::policies() path, every registered tool has an entry even if its default policy has classified == false. This branch fails closed only for a missing entry and otherwise treats an all-false side-effect mask as safe, so legacy or unannotated tools remain visible and executable in Plan mode despite the documented fail-closed guarantee. Check policy.classified before accepting the side-effect fields as authoritative.

AGENTS.md reference: AGENTS.md:L78-L82

Useful? React with 👍 / 👎.

@senamakel
senamakel merged commit 1763e8b into main Sep 24, 2026
8 of 9 checks passed
@tinysweeper

tinysweeper Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

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

State: Incomplete
Priority: critical
Reviewed head: 967f84b00465
Updated: 1790234037 (Unix time)

Review snapshot

Change surface Files Review signal Count
Production 9 Active findings 4
Tests 12 Noted findings 0
Documentation 1 Resolved findings 0
Configuration 0 Pending checks/questions 1

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

What changed

The review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below.

Features

None identified with supported citations.

Tests

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

  • Unreviewed: tinysweeper/tests

Findings

  • critical · critique · Update every ToolStarted constructor — Adding a required field to this enum variant breaks the existing constructor in `agent_loop/tools.rs`, which still constructs `AgentEvent::ToolStarted` without `input` (the reposit (crates/tinyagents\-harness/src/events/types\.rs:238)
  • medium · critique · Add focused tests for plan-mode enforcement — This adds a new middleware with several security-sensitive behaviors—filtering side-effecting tools, allowing explicitly allowlisted tools, rejecting unclassified tools, emitting ` (crates/tinyagents\-harness/src/middleware/library/tool\_policy\.rs:670)
  • critical · security · Add the missing PlanModeMiddleware constructor — `PlanModeMiddleware::new` is not defined in this file or the related middleware implementation, so this newly added public helper fails compilation. Add the constructor and its mid (crates/tinyagents\-harness/src/middleware/library/types\.rs:723)
  • medium · description · Apply host progress emission also when denying in plan mode — The middleware emits `AgentEvent::ToolsFiltered` in `before_model` when tools are hidden from the model, but `before_tool` returns a `Validation` error without any host progress ev (\(pull request description\))

Could not review: tinysweeper/tests

Before merge

  • Address Update every ToolStarted constructor (crates/tinyagents\-harness/src/events/types\.rs).
  • Address Add the missing PlanModeMiddleware constructor (crates/tinyagents\-harness/src/middleware/library/types\.rs).
  • Complete the tests review for tinysweeper/tests.

How this fits together

flowchart LR
  n0["...ction_folds_tool_lifecycle_as_two_entries<br/>changed"]:::changed
  n1["...replays_only_items_after_the_given_cursor<br/>changed"]:::changed
  n2["tool_completed_event_carries_outcome<br/>changed"]:::changed
  n3["AgentEvent<br/>changed<br/>1 finding"]:::blocking
  n4["Send"]:::impacted
  n5["fold_agent_event"]:::impacted
  n6["subscribe"]:::impacted
  n7["Middleware"]:::impacted
  n0 -->|calls| n5
  n0 -->|tests| n5
  n1 -->|calls| n5
  n1 -->|tests| n5
  n2 -->|calls| n6
  n2 -->|tests| n6
  n5 -->|uses| n3
  n7 -->|uses| n4
  n7 -->|implements| 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: Failure
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 22 files; 2 findings. _The code index is behind this pull request (indexed at `79e4b914410e`), so retrieved context may be out of date._ _Memory was unavailable (model: cortex: v1/recall: timed out after 10s), so this review ran without it._
  • Evidence: crates/tinyagents\-harness/src/events/types\.rs — Update every ToolStarted constructor
  • Evidence: crates/tinyagents\-harness/src/middleware/library/tool\_policy\.rs — Add focused tests for plan-mode enforcement

security

  • Conclusion: Failure
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 21 files; 1 finding. 1 file was not security-reviewed: docs/modules/harness/middleware.md (prose or tabular data). _The code index is behind this pull request (indexed at `79e4b914410e`), so retrieved context may be out of date._ _Memory was unavailable (model: cortex: v1/recall: timed out after 10s), so this review ran without it._
  • Evidence: crates/tinyagents\-harness/src/middleware/library/types\.rs — Add the missing PlanModeMiddleware constructor

tests

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: tinysweeper/tests
  • Lane summary: No reviewer could be consulted.

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: Adds ToolStarted.input, RunQueue snapshot/remove_where, PlanModeMiddleware, and transcript truncate_into_next_generation APIs across harness and session crates. The changes look sound, tests cover each new path, and existing tests are updated to compile with the new field. Safe to merge. _The code index is behind this pull request (indexed at `79e4b914410e`), so retrieved context may be out of date._ _Memory was unavailable (model: cortex: v1/recall: timed out after 10s), so this review ran without it._
  • Evidence: \(pull request description\) — Apply host progress emission also when denying in plan mode

e2e

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: No end-to-end harness in this repository: no e2e test files and no e2e workflow.
Evidence and run details
  • Models: ladder/vectors, gpt-5.6-luna, deepseek/deepseek-v4-flash
  • Spend: $0.056794
  • Tokens: 1014945 input · 26416 output · 49374 cached · 1190 embedding
Head State Pass summary
967f84b00465 incomplete 4 active finding(s), 0 resolved finding(s) (at 1790234037)

tinysweeper 0.1.0

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

Requesting changes: 2 lane(s) blocking, worst finding is critical.

Fix or reply to the findings below and push. The next review clears this automatically once they are gone — you should not need to dismiss anything by hand.

             $0.0568 · 1,014,945 in / 26,416 out · 49,374 cached (5%) · ladder/vectors, gpt-5.6-luna, deepseek/deepseek-v4-flash · 1,190 embedded
critique:    $0.0294 · 521,274 in   / 15,020 out · 29,500 cached (6%) · gpt-5.6-luna, deepseek/deepseek-v4-flash
security:    $0.0235 · 457,197 in   / 7,963 out  · 19,874 cached (4%) · gpt-5.6-luna
description: $0.0017 · 17,901 in    / 808 out    · 0 cached (0%)      · deepseek/deepseek-v4-flash

/// or UI can render the call's arguments as soon as it starts,
/// instead of waiting for [`AgentEvent::ToolCompleted`].
#[serde(default, skip_serializing_if = "Option::is_none")]
input: Option<serde_json::Value>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority critical critique confident

Update every ToolStarted constructor

Adding a required field to this enum variant breaks the existing constructor in agent_loop/tools.rs, which still constructs AgentEvent::ToolStarted without input (the repository search finds that production construction site). As a result, the crate will not compile. Add the captured tool arguments there, gated by the run's PayloadCapture::tool_io setting, or explicitly set input: None when capture is disabled.

[RULE] compile-break ·

}

#[async_trait]
impl<State: Send + Sync, Ctx: Send + Sync> Middleware<State, Ctx> for PlanModeMiddleware {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority medium critique confident

Add focused tests for plan-mode enforcement

This adds a new middleware with several security-sensitive behaviors—filtering side-effecting tools, allowing explicitly allowlisted tools, rejecting unclassified tools, emitting ToolsFiltered, and reacting to mode changes—but the diff adds no tests for any of them. The repository requires tests with every behavior change, and the indexed test suite does not exercise these changed symbols. Add focused tests covering classified side-effect-free tools, unclassified tools, allowlisted side-effecting tools, execution-time rejection, and the emitted filtering event.

[RULE] missing-behavior-tests ·

mode: RunModeHandle,
policies: std::collections::HashMap<String, ToolPolicy>,
) -> PlanModeMiddleware {
PlanModeMiddleware::new(mode, policies)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

priority critical security confident

Add the missing PlanModeMiddleware constructor

PlanModeMiddleware::new is not defined in this file or the related middleware implementation, so this newly added public helper fails compilation. Add the constructor and its middleware implementation, or remove this call until they exist.

[RULE] build-failure ·

@tinysweeper tinysweeper Bot added the priority: p0 Drop what you are doing. Data loss, a live break, or an exploitable hole. label Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p0 Drop what you are doing. Data loss, a live break, or an exploitable hole.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant