33a529538d
When a high-risk side effect (e.g. host restart via shutdown.exe) runs, the user's plain-text confirmation phrase is persisted in the conversation transcript. If the host restart killed the gateway process before the assistant's tool result was written, the transcript tail ends on the assistant's text response - and the dangerous confirmation text remains in the user role. On the next inbound message - possibly a casual 'are you there?' from the user minutes later - the LLM sees the stale confirmation and may interpret the new turn as a fresh re-confirmation, re-executing the destructive action. This is the failure mode reported in #59607. Fix: - Add strip_stale_dangerous_confirmations() in agent/replay_cleanup.py that removes user messages whose content matches a known dangerous confirmation pattern AND whose timestamp is older than 60 seconds. - Add is_dangerous_confirmation() helper with the matched patterns (i18n-aware: covers 確認強制重開機 from the original incident). - Wire the stripper into _build_gateway_agent_history() right after the existing75ed07acestrippers, so the strip chain is: strip_interrupted_tool_tails -> strip_dangling_tool_call_tail -> strip_stale_dangerous_confirmations. - Update _build_replay_entry() to preserve the timestamp on user messages (it was previously dropped), since the new stripper needs it. Complements75ed07ace(which strips the assistant side of the broken tail) by handling the user side: a stale plain-text confirmation that the assistant has not yet responded to in a way the resume logic recognises. Failing-test-first discipline: the bug-detection test test_stale_confirmation_text_is_stripped_on_resume fails on unfixed code (proves the test catches the bug) and passes after the fix. Five additional safety tests confirm no regression on: - fresh confirmations (within expiry) are preserved - non-confirmation text is preserved - non-matching histories are untouched - dangerous-pattern detection works in all cases (case, i18n, None) - direct unit test of the strip helper Refs: #59607