v0.9.35 — Explicit turn_id for conversation boundary detection
Changed
- Conversation boundary detection now uses explicit turn IDs. `Message` gains a `turn_id: Option` field. At the start of each turn the agent generates a per-session turn id and stashes it on `Agent::current_turn_ids`. Every message persisted during the turn (assistant replies, tool results, synthetic injections) is auto-stamped by `append_message_canonical` reading from that map. `message_build_phase` then finds the current-task boundary by turn id match instead of inferring from message content.
This removes a known race condition: when the same text was sent twice in a session, the old content-match logic could anchor on the previous instance and keep an unrelated tool chain as "current interaction." Content match is retained as a fallback for messages from before this field existed.
Fixed
- `test_compaction_fires_on_window_overflow` flake under coverage instrumentation. The assertion took `call_log.last()` with a 200ms post-turn sleep; under slow runners `last()` could be an async compaction call rather than the main Turn 8 call. The check now scans the last 4 calls so order doesn't matter, and the sleep matches the 1000ms pattern used earlier in the same test.
All 2189 library tests pass (+1 new `test_turn_id_groups_messages_within_a_turn`).
Full Changelog: v0.9.34...v0.9.35