Found by the pre-merge correctness and hermes-specific review of this stack:
- A fold after a row whose one response repeated a provider id (one shared uid) appended the
absorbed turn's uid in the wrong slot. The shared uid now fills each of the row's own
occurrences before the fold appends (per_occurrence_tool_call_uids). A single response keeps one
shared uid for a repeated id: every result carries it, so no call looks unanswered.
- A digest-less re-flush of a restored fold (replay heal, adopt after a digest mismatch) let the
stored pre-fold map overwrite the longer live list, so the later occurrence's results paired
with nothing. A live list that starts with every stored occurrence is kept (stored uid or list).
- A dict that lost its uid map (a clone) rewrote tool_call_uids to NULL. The row-addressed
rewrite now fills stored uids for the calls the dict still names; a call it dropped keeps none.
- append_messages_batch(chunk_rows=...) reset the pairing index per chunk, so a result in the chunk
after its call was stored without tool_call_uid (branch/seed copies). The whole batch is paired
before it is chunked.
- _merge_assistant_into keeps its dict guard on the absorbed turn's map (a plugin-built dict with a
non-dict map no longer raises).