mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-25 22:16:19 +00:00
* fix(runtime): share one change position across an atomic thread operation MemoryRunStore.create_thread_operation_atomic marked each row it touched separately, so one interrupt-and-replace consumed two positions in the (change_seq, run_id) cursor that list_changed consumers page with. The SQL store allocates a single position for the whole set, and runtime/AGENTS.md documents that as the contract for an atomic thread operation. The memory store is the backend an install runs whenever no durable database is configured, so a cursor reader could observe the interrupted row and its replacement under two positions instead of one, ordered by run_id. Allocate one position after the raise-only scan -- so a rejected operation still consumes nothing -- and reuse it for the claimed rows and the new row. * test(runtime): pin that a rejected thread operation consumes no position create_thread_operation_atomic allocates its change position only after the raise-only candidate scan, so a ConflictError consumes nothing -- the memory store's counterpart of the SQL store rolling back and leaving its clock untouched. Nothing asserted that ordering. A consumed-but-unused position leaves no trace in the rows themselves, so a test comparing list_changed output passes even with the allocation hoisted above the scan. Assert instead on the position the next accepted operation lands on: that surfaces a hoist as a gap.