fix(orchestrator): Keep Home and settle honest when work ends - #5459
fix(orchestrator): Keep Home and settle honest when work ends#5459mwolson wants to merge 2 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
One convention issue found in the new provider-ingest settlement code: a statically known tagged failure is recovered with Effect.catchTag instead of Effect.catchTags.
Posted via Macroscope — Effect Service Conventions
ApprovabilityVerdict: Needs human review This PR introduces significant runtime behavior changes to thread settlement lifecycle across server orchestration, projection stores, provider event ingestor, and client runtime. The changes control when threads settle/unsettle based on provider activity and background tasks, affecting user-visible thread state. The cross-cutting scope and behavioral nature warrant human review. You can customize Macroscope's approvability policy. Learn more. |
5229063 to
6c322c7
Compare
Port pingdotgg#5459 settled-thread lifecycle follow-ups: pin clear on settle, preserve newer updatedAt on activity unsettle, fresher archive membership, settle runs filter, and typed activity-unsettle prep errors.
25de21d to
0af2a6e
Compare
pingdotgg#5459's ProjectionSnapshotQuery.settled test must provide the same ThreadBackgroundLiveness and ThreadPlanProgress layers the live snapshot query now requires on CTM.
Stop retrying definitive missing thread snapshots, normalize V2 shell archive membership, preserve provider retry metadata, and harden settled projection ordering, activity unsettle, ingest timestamps, snapshot reads, and Waiting lifecycle invariants.
Settlement-only merge now applies pinnedAt on explicit settle so pins still clear, and activity unsettles no longer rewind updatedAt behind a newer metadata bump.
0a6ccc1 to
5908b04
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 5908b04. Configure here.
| const overrideMs = settledOverrideTimestampMs(state); | ||
| if (overrideMs === null) return true; | ||
| return activityAtMs >= overrideMs; | ||
| } |
There was a problem hiding this comment.
Keep-active pin clock drifts on metadata
Medium Severity
settledOverrideTimestampMs treats updatedAt as the keep-active pin time, but later renames and other metadata writes advance that same field. Provider activity that lands after the pin can then lose the ordering check and leave settledOverride: "active" in place, so auto-settle stays suppressed even though the server intended to clear the pin on real activity.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 5908b04. Configure here.


Summary
Keeps the home list and thread cards honest when work finishes, archives, or
wakes back up. Users should not see archived threads reappear on Home, settle
a thread that is still Waiting on background work, or lose an explicit settle
when a delayed provider event races the pin.
Also stops the client from spinning forever on a thread that is already gone
(HTTP 404), so deleted or never-created threads do not keep the UI in a loading
retry loop.
Why this matters
Without these lifecycle fixes, day-to-day product failures look like:
or a dropped archive delta, so the inbox feels "sticky" and hard to clean up.
queued turn or background Waiting work, or can leave a pin in place so the
card never looks truly put away.
settle or rewind thread ordering after a rename, so the list jumps and settle
state flickers.
retrying on the socket path, leaving empty detail views that never settle.
Problem and Fix
archivedAt, and on dual-list conflicts prefer the fresherupdatedAtcopy so a stale archive cannot beat a newer unarchive.pinnedAton settle); do not rewindupdatedAtbehind a newer metadata bump.canSettle/effectiveSettledwith pending background work and the same lifecycle signals the server uses.Defensive Fixes
revokeMcpCredential: trueon terminal provider-session detaches.ProviderEventPublishErrorso callers can retry.Validation
vp checkandvp run typecheckclean on the published head.updatedAtrewind,runsfilter, and typed unsettle prep errors fixed on the branch.Out of scope
Note
Medium Risk
Touches orchestration settle/unsettle, projection persistence, and provider ingest ordering—user-visible inbox and thread state—with broad test coverage but non-trivial concurrency edge cases.
Overview
Keeps the home list and settle/unsettle behavior aligned with real thread work, and stops dead threads from retrying forever.
Settlement and provider activity: New shared
reduceThreadSettlementEventmerges only settlement fields (and clearspinnedAton explicit settle) on server projection, client projection, and durable SQL writes—so stale full-thread unsettle payloads cannot rewind title, archive, or other metadata.ProviderEventIngestorV2prepends syntheticthread.unsettledbefore qualifying provider activity (pending approvals/user input, live session states), orders clears with provider payload time so delayed events cannot beat a newer pin, and stamps ordinary provider events at ingestion time.Settle guards:
thread.settlerejects archived threads, queued runs (isSettleBlockingRun), pending runtime requests, and pending provider background tasks (viaderivePendingBackgroundWork), with specific error messages.Client shell and threads:
canSettle/effectiveSettledblock onpendingBackgroundTasks; shell snapshots usenormalizeShellThreadMembershipand trustarchivedAtover streamlocationso archived threads do not stick on Home. HTTP thread snapshot loads returnpresent/missing/unavailable; a definitive 404 marks the thread deleted and skips socket subscribe/retry.Tests cover settle invariants, ingest races, projection merge, shell membership, legacy null settlement columns, and thread sync paths.
Reviewed by Cursor Bugbot for commit 5908b04. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix settlement state to reject stale overrides and block on active work in the orchestrator
thread.settledandthread.unsettledevents now merge only settlement fields (settledOverride,settledAt,pinnedAt,updatedAt) with activity-ordering guards, preventing stale payloads from overwriting unrelated thread metadata on both client (orchestrationV2Projection.ts) and server (ProjectionStore.ts).thread.settleis now rejected when a run is queued, a runtime request is pending, the thread is archived, or the active provider thread has pending background tasks.ProviderEventIngestorprepends a syntheticthread.unsettledevent before qualifying provider activity batches, using the activity timestamp for ordering so delayed events cannot clear a newer pin.normalizeShellThreadMembershipto place threads in the correct active/archived list, resolving duplicates by preferring the fresher copy.Macroscope summarized 5908b04.