Skip to content

fix(client): preserve live moves across metadata reads - #46954

Closed
kitlangton wants to merge 3 commits into
v2from
preserve-move-state
Closed

fix(client): preserve live moves across metadata reads#46954
kitlangton wants to merge 3 commits into
v2from
preserve-move-state

Conversation

@kitlangton

@kitlangton kitlangton commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Why

A session or family GET can serialize /repo, then arrive after session.moved has already updated the client to /worktree. The late response currently restores the old placement in the shared Solid cache, which clients use to follow the active session's directory.

Independent review found two gaps in earlier revisions: a saved move could overwrite a later repository adoption (3223615646), and unresolved adoption could prevent a subsequent complete move from being applied (181283c0fd). The latter caused an unnecessary GET whose failure rejected an otherwise successful sync. Both counterexamples are now maintained regressions.

Latest correction: 3f2aef16a1 handles complete same-session moves before the unresolved-placement guard, restoring their non-placement fields from the original fetched row without adding state or another synchronization mechanism.

What Changes

Each pending metadata read records only the move and repository-resolution events it observes. Before publishing the HTTP response, it folds those facts in order, applying repository identity changes through the same Worktree.adopt logic used by live events.

Situation Result
Session or family GET overlaps a move Keep the observed destination, workspace, project ID, and subpath
Move → repository adoption Keep the resolved repository ID and derived subpath
Adoption → later move The later move wins
Unresolved adoption → complete move for the same session Restore placement from that move plus the fetched non-placement fields; no additional read is needed for that uncertainty
Unresolved adoption → another session's move Keep revalidation necessary for the unresolved session
Another adoption follows the final move Apply it normally; revalidate if its canonical path is still unknown
Parent or child is not cached yet Apply observed placement facts when its metadata arrives
Explicit adoption uses a canonical path rather than a location alias Reuse the canonical project path and existing workspace exclusion rules
Placement remains unresolved because a canonical path was never loaded Re-read after the observed facts instead of guessing a subpath; moves during that read remain protected
Destination omits workspace or subpath Clear the old values
Response has refreshed title, cost, or timestamps Still accept those unrelated fields
A later read starts after these facts Accept its response normally; no permanent override

Placement observations are released when the read settles, including failures. Existing sync deduplication, serial invalidation/revalidation, and reconnect invalidation remain intact. Publication does not expose an intermediate stale directory or add another move-history row.

Scope

Client cache correctness only, with deterministic transport-seam tests using real createData and the Promise client. No protocol or durable-event changes. This does not address the separately diagnosed missing-shell/new-session startup incident, and no live-service or visual end-to-end verification is claimed. The revised head requires independent verification before approval; all earlier commits and reviewer scratch evidence remain intact.

Verification

# Dependencies installed with the original change; lockfile unchanged.
bun install --frozen-lockfile

cd packages/client
bun run test --conditions=browser test/solid-data-move.test.ts --test-name-pattern 'a later complete move avoids|unknown placement is superseded'
bun run test
bun run test --conditions=browser test/solid-data-move.test.ts --rerun-each 25
bun typecheck
bunx prettier --check src/solid/data.ts test/solid-data-move.test.ts

cd ../tui
bun run test test/new-session-location.test.ts test/context/session-retention.test.ts test/context/session-tabs.test.tsx test/session-home.test.tsx
bun typecheck
  • Original red: all four cached/uncached session/family move regressions failed before the first implementation. Old responses are serialized before their release gates, avoiding shared-fixture false passes.
  • First review correction: both cached/uncached move → adoption → already-resolved GET cases failed on 3223615646 and now pass.
  • Second review correction: on 181283c0fd, both cold session/family move → unknown adoption → complete move cases and the subsequent-known-adoption variant failed when unnecessary follow-up requests returned 503. The other-session and final-unresolved-adoption controls already passed. After the narrow reducer correction, all five pass, with exact request-count assertions.
  • Full client suite: 176 passed, 1 skipped, 0 failed. The skip is the reactive reconnect test under Solid's server build; the browser-conditioned run exercises it.
  • Browser-conditioned maintained regressions: 800 passed, 0 failed across 25 repeats of 32 cases. Includes the original move protections, ordered adoption, canonical aliases, workspace exclusions, necessary revalidation, subsequent moves, failure/retry, and removal of the unnecessary refresh.
  • Both unchanged independent-review scratch suites pass against the revised code: 13 + 8 = 21 passed, 0 failed. This is an implementation-side rerun, not independent approval of the new head.
  • Relevant TUI suite: 61 passed, 0 failed. Client and TUI typechecks and formatting passed; existing rename coverage remains green.
  • The normal pre-push hook passed all 33 repository typecheck tasks for 3f2aef16a1; hooks were not bypassed. New-head CI and independent verification are still required before approval.
  • Earlier exploratory browser-conditioned execution of the broader solid-data.test.ts exposed two existing proxy-sensitive assertions (assistant content replacement and background shell metadata), also reproduced with unchanged base d9c85d8d95. Those unrelated assertions remain outside this change.

@kitlangton kitlangton closed this Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant