Skip to content

Park a seat on the host, and brief it on its other conversations - #72

Merged
sanil-23 merged 3 commits into
tinyhumansai:mainfrom
sanil-23:parked-elsewhere
Sep 22, 2026
Merged

sanil-23 merged 3 commits into
tinyhumansai:mainfrom
sanil-23:parked-elsewhere

Conversation

@sanil-23

Copy link
Copy Markdown
Collaborator

Summary

Two things a host needs before it can run its own agents in a completion episode, and which OpenCompany blocks on.

A turn can park. A seat whose turn stops on something only the host can settle — an approval it has queued — used to read as a silent one: nudged, nudged again, then Error::Stalled, while the approval sat unanswered. Conductor::record_parked records whatever the turn called and then holds the seat where it stopped: not nudged for silence, not counted toward a stall, not proposed again, and a parked askee's conversation waits with it rather than concluding for want of a turn. resume_seat puts it back in the next wave. Nothing due with a seat parked is a wait, not an end.

A seat can be shown its other conversations. A host that briefs a seat on its other channels writes that read itself, and a read written in the host is how a seat ends up shown a row it was never addressed on. gather_elsewhere does it over the same log port and the same projection as every other read: narrowed to the seat, every conversation bounded by one before so a turn's context is a snapshot rather than reads drifting while the log grows, and a conversation the seat may read nothing of listed with no rows rather than dropped. EpisodeBrief::elsewhere carries the result, rendered under a heading that says it is context, not work.

The loop ties both to the host: Journal::released is where a host blocks on its approval queue, and Journal::channels names the conversations to gather. Both have defaults, so a host that does neither is unaffected.

Related issue

None; groundwork for the OpenCompany integration.

API or behavior changes

  • Breaking: TurnResult is an enum — Replied, Failed, Parked — rather than Option<Result<String, String>>. The None case meant "timed out" and no runner ever produced it; the embed runner's timeout is now a Failed naming the seat. reply() and parked() read it.
  • Breaking: EpisodeHost::after_turn returns Result<Disposition> instead of Result<()>. Disposition::Done is the default and the old behavior.
  • New in tinyhivemind: the elsewhere module — gather_elsewhere, ElsewhereQuery, Elsewhere, render_row.
  • New in tinyhivemind-driver: Conductor::record_parked, Conductor::resume_seat, Conductor::parked, Event::Parked, Event::Resumed, Error::Parked, EpisodeBrief::elsewhere, ElsewhereView.
  • New in tinyhivemind-openhuman: Disposition, Released, Journal::channels, Journal::released, MemoryLog::append_to, Row::desk.
  • Behavior: Conductor::record_parked records the turn's calls before holding the seat, so a seat that broadcast and then parked keeps its broadcast.

Validation

Run from the repository root, all passing:

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-features (36 suites)
  • RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
  • .github/scripts/assert-pure.sh, .github/scripts/assert-openhuman-pin.sh
  • cargo llvm-cov --workspace --all-targets --all-features: no file under the 90% gate
  • cargo test --locked --manifest-path examples/openhuman/Cargo.toml

Tests

  • conduct/test/parked.rs: a parked desk seat held and released; a parked askee holding its conversation open and answering once released; releasing a seat that was never parked changing nothing, with the ordinary stall still a stall; and what a seat said before it parked being recorded.
  • driver/brief/test.rs: elsewhere rendered after the turn's own rows, on the desk and in a thread, and absent when the host gives none.
  • elsewhere/test.rs: the turn's own conversation skipped, the narrowing to the seat, the bound holding every conversation to one moment, a thread as its own conversation, and a failed read reported.
  • episode/test/parking.rs: a parked seat waited for and run again through run_episode; a host that releases nobody ending the episode parked; a seat's other desk reaching its brief.

Documentation

conduct/README.md gains the parking rule; episode/README.md, hosted/README.md, runner/README.md and journal/README.md follow the new hooks; elsewhere/README.md is new and indexed from src/README.md.

Checklist

  • Public API changes called out
  • Tests included
  • Docs updated

sanil-23 and others added 3 commits September 23, 2026 02:26
A turn that stops on something only the host can settle -- an approval
-- read as a silent one: nudged, then a stall. `record_parked` holds the
seat where it stopped, not nudged, not stalled, not proposed, with a
parked askee's conversation waiting rather than concluding; `resume_seat`
owes it a turn there. Nothing due with a seat parked is a wait, and
`Error::Parked` is the host giving up on one. `EpisodeBrief::elsewhere`
carries the newest rows of the seat's other conversations, rendered as
context after the turn's own rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A host that briefs a seat on its other channels writes that read itself,
and a read written in the host is how a seat ends up shown a row it was
never addressed on. `gather_elsewhere` does it over the same log port and
the same projection as every other read: narrowed to the seat, every
conversation bounded by one `before` so a turn's context is a snapshot,
and a conversation the seat may read nothing of listed with no rows
rather than dropped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`TurnResult` becomes an enum -- replied, failed, parked -- which drops a
`None` case no runner ever produced and gives a turn that stopped on the
host somewhere to say so. `EpisodeHost::after_turn` returns a
`Disposition`, so a host that queues an approval parks the seat; the loop
records what the turn called and holds it. With nothing to run and seats
parked, the loop asks `Journal::released`, where a host blocks on its own
queue, and a host that releases nobody ends the episode parked rather than
spinning. `Journal::channels` names the seat's other conversations, whose
newest rows are gathered through the same wave watermark and carried in
the brief as context.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tinysweeper

tinysweeper Bot commented Sep 22, 2026

Copy link
Copy Markdown

Tiny Sweeper review

⚠️ Review failed for ab7234137d8c. the review of #72 did not finish within 900s

@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 39 billable files and costs up to $9.75.

Or wait 15 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: b472e1bd-ca1a-45b6-b870-2b9ea1366290

📥 Commits

Reviewing files that changed from the base of the PR and between b96b61c and ab72341.

📒 Files selected for processing (39)
  • crates/tinyhivemind-driver/src/conduct/README.md
  • crates/tinyhivemind-driver/src/conduct/mod.rs
  • crates/tinyhivemind-driver/src/conduct/steps.rs
  • crates/tinyhivemind-driver/src/conduct/test/mod.rs
  • crates/tinyhivemind-driver/src/conduct/test/parked.rs
  • crates/tinyhivemind-driver/src/conduct/test/support.rs
  • crates/tinyhivemind-driver/src/conduct/test/wire.rs
  • crates/tinyhivemind-driver/src/conduct/wave.rs
  • crates/tinyhivemind-driver/src/driver/brief.rs
  • crates/tinyhivemind-driver/src/driver/brief/test.rs
  • crates/tinyhivemind-driver/src/driver/mod.rs
  • crates/tinyhivemind-driver/src/error/mod.rs
  • crates/tinyhivemind-driver/src/lib.rs
  • crates/tinyhivemind-openhuman/src/embed/mod.rs
  • crates/tinyhivemind-openhuman/src/episode/README.md
  • crates/tinyhivemind-openhuman/src/episode/mod.rs
  • crates/tinyhivemind-openhuman/src/episode/test/flow.rs
  • crates/tinyhivemind-openhuman/src/episode/test/mod.rs
  • crates/tinyhivemind-openhuman/src/episode/test/parking.rs
  • crates/tinyhivemind-openhuman/src/episode/test/support.rs
  • crates/tinyhivemind-openhuman/src/hosted/README.md
  • crates/tinyhivemind-openhuman/src/hosted/mod.rs
  • crates/tinyhivemind-openhuman/src/journal/README.md
  • crates/tinyhivemind-openhuman/src/journal/mod.rs
  • crates/tinyhivemind-openhuman/src/lib.rs
  • crates/tinyhivemind-openhuman/src/raw/mod.rs
  • crates/tinyhivemind-openhuman/src/runner/README.md
  • crates/tinyhivemind-openhuman/src/runner/mod.rs
  • crates/tinyhivemind-openhuman/src/runner/test.rs
  • crates/tinyhivemind/src/README.md
  • crates/tinyhivemind/src/elsewhere/README.md
  • crates/tinyhivemind/src/elsewhere/mod.rs
  • crates/tinyhivemind/src/elsewhere/test.rs
  • crates/tinyhivemind/src/elsewhere/types.rs
  • crates/tinyhivemind/src/lib.rs
  • examples/openhuman/src/bin/conducted/hosted.rs
  • examples/openhuman/src/bin/deepswe_hive.rs
  • examples/openhuman/src/bin/pe1006_hive.rs
  • examples/openhuman/src/main.rs

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

@sanil-23
sanil-23 merged commit e60d4ca into tinyhumansai:main Sep 22, 2026
4 of 6 checks passed
@sanil-23 sanil-23 mentioned this pull request Sep 23, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant