fix: fifth review round (durable mount failures, {#key} hydration slots)

cursor[bot]:
- variant_mount_failed now sets the session's pendingEvent (without
  clobbering a still-pending generate), so a helper restart replays it
  onto /poll and a repair --reply resolves instead of returning
  unknown_poll_reply_id. live-resume's next action names the real event
  id instead of a literal EVENT_ID placeholder.
- Contract v2 text hydration strips {#key} DELIMITERS from the zip
  source (content stays; it always renders), so key blocks can no longer
  shift expression slots against the live DOM.

This work was produced with AI assistance (Claude Code).

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-27 16:33:34 -07:00
co-authored by Claude Code
parent 39df25ee5a
commit e5f6d27a9c
5 changed files with 74 additions and 3 deletions
+7
View File
@@ -410,6 +410,13 @@ function applyEvent(snapshot, entry) {
},
].slice(-MOUNT_FAILURE_HISTORY);
next.renderState = deriveRenderState(next);
// The failure needs an agent reply, so it must survive a helper
// restart the same way a generate does. Never clobber a still-pending
// generate: a progressive publish can fail an early mount while the
// generate event itself is still leased.
if (!next.pendingEvent) {
next.pendingEvent = toPendingEvent(event);
}
break;
}
case 'checkpoint':