Repository navigation
Refuse a second ask to a seat already being waited on - #76
Conversation
|
Warning Review limit reachedNext included review available in 27 minutes. View limit detailsLimit details: You’ve used the included review currently available. This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (3)
Comment |
Tiny Sweeper reviewTiny Sweeper reviewed this change across 6 lane(s) and found 1 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below. State: Ready for maintainer review Review snapshot
Completeness: Complete What changedThe review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below. FeaturesNone identified with supported citations. TestsNo supported feature-to-test mapping was produced. Test execution is not inferred. Findings
Before mergeNone. How this fits togetherflowchart LR
n0["EpisodeTools<br/>changed<br/>1 finding"]:::flagged
n1["...ad_returns_the_window_and_records_nothing<br/>changed"]:::changed
n2["register"]:::impacted
n3["dispatch"]:::impacted
n4["Dispatch"]:::impacted
n5["stand_up"]:::impacted
n6["Journal"]:::impacted
n7["drive"]:::impacted
n0 -->|uses| n4
n1 -->|calls| n2
n1 -->|tests| n2
n1 -->|calls| n3
n1 -->|tests| n3
n2 -->|uses| n4
n3 -->|uses| n4
n5 -->|uses| n0
n7 -->|uses| n6
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
Agent review detailscritique
security
tests
commits
description
e2e
Evidence and run details
|
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0062 · 133,241 in / 9,853 out · 7,606 cached (6%) · ladder/vectors, gpt-5.6-luna, deepseek-v4-flash · 446 embedded
critique: $0.0028 · 56,246 in / 2,255 out · 2,133 cached (4%) · gpt-5.6-luna, deepseek-v4-flash
security: $0.0027 · 46,664 in / 1,821 out · 1,889 cached (4%) · gpt-5.6-luna
tests: $0.0003 · 17,752 in / 1,032 out · 2,048 cached (12%) · deepseek-v4-flash
description: $0.0002 · 8,762 in / 2,553 out · 1,536 cached (18%) · deepseek-v4-flash
| // | ||
| // Refusing is the same rule the thread turn already applies | ||
| // one line up, at the other end of the same wait. | ||
| if self.awaits(seat, to) { |
There was a problem hiding this comment.
Reject duplicate asks made in the same turn
awaits only checks the snapshot supplied before the turn began. If a seat calls ask for the same recipient twice during one turn, the first call is recorded but does not update awaiting, so the second call passes this check and opens a second conversation. Enforce the outstanding pair against calls already accepted in the current turn as well as the snapshot.
[RULE] duplicate-request-race ·
A seat waiting on an answer is still turned on the desk. That turn is deliberate -- it is what keeps the episode live while the seat it asked is parked -- but look at what it is given. Its brief is its own unanswered question, echoed back under "New desk messages" and again under "Conversations still in progress"; `complete_episode` is refused until the conversation concludes; `broadcast` has nothing to carry; and the standing contract closes with "a reply that calls no tool records nothing". Every door is shut except `ask`, and the model is told that silence counts for nothing. So it asks again -- and each repeat opens a *second* conversation with the same seat, which the conductor must then track and conclude separately. Observed on a hosted desk: one question re-issued verbatim, one root, three conversations, three conclusions. The record already refuses an `ask` inside a conversation, one line above this, for the same reason at the other end of the same wait. This extends it to the asker's side: a seat may not ask a seat it is already waiting on. Asking someone *else* is untouched, and the pair is reachable again once the answer lands. The ledger that knows who a seat awaits is the driver's, and the record cannot read it, so `EpisodeTools::awaiting` takes it per turn exactly as `window` takes the rows `read` may return. `open_turn` hands over what the brief already computed.
471897e to
ddaf106
Compare
There was a problem hiding this comment.
tinysweeper found nothing blocking. Approving.
$0.0074 · 161,916 in / 17,836 out · 21,953 cached (14%) · ladder/vectors, gpt-5.6-luna, deepseek-v4-flash · 446 embedded
critique: $0.0041 · 88,580 in / 2,979 out · 14,591 cached (16%) · gpt-5.6-luna, deepseek-v4-flash
security: $0.0023 · 44,789 in / 1,251 out · 3,778 cached (8%) · gpt-5.6-luna
tests: $0.0004 · 16,723 in / 4,283 out · 2,048 cached (12%) · deepseek-v4-flash
description: $0.0004 · 7,717 in / 6,558 out · 1,536 cached (20%) · deepseek-v4-flash
| // | ||
| // Refusing is the same rule the thread turn already applies | ||
| // one line up, at the other end of the same wait. | ||
| if self.awaits(seat, to) { |
There was a problem hiding this comment.
Reject duplicate asks made in the same turn
awaiting is only refreshed from the driver's snapshot before the turn begins. After the first ask is accepted, this snapshot is not updated, so a second ask to the same recipient during the same turn still passes self.awaits and opens another conversation. Check accepted asks already recorded in the current turn as well as the snapshot, or update the outstanding set atomically when accepting an ask.
[RULE] duplicate-request-race ·
Summary
A seat waiting on an answer is still turned on the desk. That turn is deliberate — it is what keeps the episode live while the seat it asked is parked — but look at what the turn is given. This is a real brief, in full, from a hosted desk:
Its own unanswered question, twice.
complete_episoderefused until the conversation concludes.broadcastwith nothing to carry. And the contract closing with "a reply that calls no tool records nothing."Every door is shut except
ask, and the model is told that silence counts for nothing. So it asks again — verbatim. Sequence 104 is character-for-character sequence 97.Each repeat opens a second conversation with the same seat, which the conductor must then track and conclude separately. In that episode one question became three conversations under one root, each with its own
concluded our conversation (thread 97/104/113)row.The record already refuses an
askinside a conversation — one line above this change, for the same reason at the other end of the same wait. This extends it to the asker's side.Related issue
None — found while running the hosted runner under OpenCompany and reading back what each seat had actually been prompted with.
API or behavior changes
Additive, non-breaking:
EpisodeTools::awaiting(seat, seats)— a per-turn snapshot, exactly likewindow. The ledger that knows who a seat awaits is the driver's and the record cannot read it, so the host hands it over;open_turnpasses whatEpisodeBrief::awaitingalready computed.asknaming a seat this one is already waiting on. Asking a different seat is untouched, and the pair is reachable again once the answer lands.Dispatchis deliberately unchanged — adding a field to it would have broken every construction site in the repo and every consumer, for state that is per-turn rather than per-dispatch.Validation
cargo fmt --all -- --check— exit 0cargo clippy --all-targets --all-features -- -D warnings— exit 101, pre-existing onmain:missing documentation for a methodatcrates/tinyhivemind-openhuman/src/hosted/mod.rs:103(tool_prefix). Verified by running the same command on unmodified8cc4dc9c, which fails identically.cargo clippy -p tinyhivemind-tools --all-targets -- -D warningsis exit 0.cargo build --all-targets --all-features— exit 0cargo test --all-features— exit 0, 36 targets ok, 0 failuresThe driver suite passing is the part worth noting: the waiting seat's desk turn is still proposed, still nudged, still the liveness mechanism. This refuses one duplicate call, not the turn.
Tests
a_second_ask_to_a_seat_already_being_waited_on_is_refusedincrates/tinyhivemind-tools/src/tools/tests, covering four states in sequence: the first ask is taken; a second to the same seat is refused and records nothing, so no second conversation opens; a different seat is still reachable; and once the host clears the list the pair is reachable again.Documentation
EpisodeTools::awaitingdocuments why the state arrives from the host rather than being read. The refusal site carries the observed failure — one question, three conversations — so the next reader knows what the branch is defending against rather than only what it does.🤖 Generated with Claude Code