Skip to content

fix(desktop): drop client ordinal when a durable row id is bound - #90661

Open
NorethSea wants to merge 1 commit into
NousResearch:mainfrom
NorethSea:fix/desktop-drop-ordinal-when-rowid-bound
Open

NorethSea wants to merge 1 commit into
NousResearch:mainfrom
NorethSea:fix/desktop-drop-ordinal-when-rowid-bound

Conversation

@NorethSea

Copy link
Copy Markdown

Summary

Motivation

Restore-to-checkpoint fails with Restore failed / truncate_before_user_ordinal (N) does not match truncate_before_row_id target turn (M) on sessions whose client ordinal space diverged from the gateway's durable ordinal space — e.g. after queued/re-sent turns following a 429: failed turns are skipped client-side (isFailedUserTurn) while durable repair merges adjacent user rows, so the same target resolves to different ordinals on each side. The gateway's fail-closed 4030 cross-check (#82756) then refuses the pair, and the client had no path to send the row id alone.

Implementation

In runRewindSubmit, the ordinal-only branch already resolved a durable row id by content and dropped the client ordinal (#87059). This extends the same discipline to the already-bound-rowId branch: keep the durable row id as the sole address, set resolvedOrdinal = undefined. The cut is always aimed by the resolved durable target, so dropping the ordinal cannot re-aim a truncation.

Validation

  • npx vitest run src/app/session/hooks/use-prompt-actions/ — 214 passed (updated the bound-rowId case to assert ordinal is dropped)
  • npx tsc -p . --noEmit — exit 0
  • Manual repro on the affected session: 4030 REFUSED before (ordinal=11 vs row_id=13), submits with row_id only after

Impact

None identified beyond the behavior above. Backend (tui_gateway) unchanged; gateway 4030 protection remains in force for genuinely stale ordinals.

Refs: #82756, #87059, #82462

The gateway refuses ordinal+row_id truncation with 4030 whenever the two
ordinal spaces disagree (NousResearch#82756): failed turns are skipped client-side while
durable repair merges adjacent user rows, so restore-to-checkpoint on a
session with queued/re-sent turns (e.g. after a 429) sent a stale ordinal
alongside the row id and was refused. Keep the bound durable row id as the
sole address and drop the ordinal the same way the ordinal-only path already
does; messageId-only restores keep their ordinal (stale rendered ids fall
back to it, NousResearch#82462).
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state duplicate This issue or pull request already exists labels Aug 20, 2026
@alt-glitch

Copy link
Copy Markdown

This was generated by AI during triage.

Duplicate of #90091. Both patches remove the stale client ordinal when a durable row ID is available, preventing the same false 4030 rewind refusal; #90091 covers the fuller durable-address contract.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants