Skip to content

Let TurnState answer which idle publication settles a held turn - #3076

Merged
trissim merged 1 commit into
mainfrom
fix/turn-state-settles
Oct 24, 2026
Merged

trissim merged 1 commit into
mainfrom
fix/turn-state-settles

Conversation

@trissim

@trissim trissim commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Defect

Toad toast on core-49156b4bb (Tristan, 2026-10-24 ~15:42):

agent_comms/transcripts.py:358 publish_turn
toad/acp/comms_updates.py:256 publish_thread_turn
toad/acp/comms_updates.py:109 turn_changed  ->  binding.receive(update.state)
toad/conversation_turn.py:271 receive
AttributeError: 'TurnState' object has no attribute 'matches'

#2943 (merged 2026-10-23 22:42) deleted TurnState.matches / observed_id when it replaced finished_turn_id with finished: TurnRecord. Toad still calls state.matches(...) at conversation_turn.py:271 (and dead matches_settlement at :173), so every idle (non-busy) turn publication raises into Toad's UI. Reproduced in the installed runtime: ManagedTurnBinding.receive(TurnState()) -> AttributeError at conversation_turn.py:271.

Fix at the owner

Which turn a declaration holds is the declaration's fact; which turn a record finished is the record's fact. So:

  • TurnState.settles(held): a busy publication always replaces the held turn; an idle one settles it only via held.settled_by(self).
  • TurnDeclaration.settled_by (abstract): NoTurn -> True; ActiveTurn -> state.active.matches(self.id) or state.finished.names(self.id).
  • TurnRecord.names (concrete False); FinishedTurn overrides with its turn_id.

No string id comparison in the client, no None-means-anything branch. Toad PR (OpenHCSDev/toad) switches receive to state.settles(self.owner.state.active) and deletes the three dead matches_settlement methods; it needs this merged first.

Proof

  • tests/test_turn_lease_release.py::test_idle_publication_settles_only_the_turn_it_finished: real begin/finish/begin on a wire bus; the finished state settles its own held turn and an idle owner, refuses a replacement turn, and a busy state settles anything. 4 passed.
  • Toad tests/textual/test_compaction_turn_events.py against this branch: see the Toad PR.

Assumed: no other Core consumer needs the deleted matches(None) "anything goes" spelling; git grep "\.matches(" src shows only declaration/generation members.

🤖 Generated with Claude Code

PR #2943 deleted TurnState.matches while Toad's ManagedTurnBinding.receive
(conversation_turn.py:271) still called it, so every idle turn publication
raised AttributeError inside Toad. The turn declaration owns which turn it
holds and the finished record owns which turn it finished, so the answer is
TurnState.settles(held) delegating to TurnDeclaration.settled_by and
TurnRecord.names instead of a string id comparison in the client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trissim
trissim marked this pull request as ready for review October 24, 2026 19:50
@trissim
trissim enabled auto-merge October 24, 2026 19:50
Copilot AI balanced review requested due to automatic review settings October 24, 2026 19:50

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@github-actions

Copy link
Copy Markdown

debt-src at e23a313, every finding:

grew TypeErrors:src/agent_comms/turn_lease.py +2

@trissim
trissim merged commit 208a5b2 into main Oct 24, 2026
13 of 14 checks passed
trissim added a commit to OpenHCSDev/toad that referenced this pull request Oct 24, 2026
Pins agent-comms to 208a5b2ee, the merge of OpenHCSDev/agent-comms#3076,
so this branch never ships calling state.settles against a Core that lacks it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants