Skip to content

fix(web): restore composer tasks after relaunch - #8097

Open
sethwebster wants to merge 20 commits into
pingdotgg:mainfrom
sethwebster:upstream/restore-composer-tasks-after-relaunch
Open

fix(web): restore composer tasks after relaunch#8097
sethwebster wants to merge 20 commits into
pingdotgg:mainfrom
sethwebster:upstream/restore-composer-tasks-after-relaunch

Conversation

@sethwebster

@sethwebster sethwebster commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

What Changed

This draft restores the composer Tasks tab from the persisted plan for the active turn after T3 Code relaunches. Bounded thread hydration retains that plan through an indexed single-row lookup.

Why

The task plan survives a server restart as thread activity, but the composer also requires process-local plan progress. That temporary state starts empty after relaunch, so the active Tasks tab disappears while the turn continues.

Closes #8091.

UI Changes

There is no visual redesign. Both captures use the same disposable database with 501 activities.

Before: upstream baseAfter: fixed branch
Before relaunch recovery: no composer Tasks tab After relaunch recovery: restored composer Tasks drawer

The upstream base shows 500 retained tool activities and no composer Tasks tab. The fixed branch restores the sequence-1 plan and expands all three steps.

Scope and non-goals

  • Restore only the composer Tasks tab from the active turn's persisted plan.
  • Preserve the existing completed-plan, superseded-turn, and dismissal behavior.
  • Do not persist sidebar plan progress or add wire fields or database columns.

Decisions

  • The persisted active-turn plan is the source for composer task progress.
  • Dismissal remains local to the current app session.
  • All providers keep using their existing normalized plan activities.

Implementation checklist

  • Add a regression test for an active persisted plan without process-local shell progress.
  • Derive composer task progress and steps from the exact active turn.
  • Keep completed and superseded plans hidden.
  • Preserve the latest active-turn plan outside the bounded activity window.
  • Use an indexed, single-row latest-plan lookup.
  • Cover persisted-activity wiring and the production query plan.
  • Document task progress and reconnect behavior for users.
  • Settle active provider-aborted turns so Tasks cannot linger.
  • Prefer the session active turn when latest-turn projection diverges.
  • Ignore untargeted aborts without clearing active progress.
  • Finalize buffered assistant text and proposed plans on an accepted abort.
  • Key task dismissal to the resolved active turn.

Verification checklist

  • Run the focused web tests.
  • Run targeted web type checking, lint, and formatting checks.
  • Verify relaunch recovery with isolated T3 state.
  • Verify recovery when more than 500 later activities follow the plan.
  • Add before and after UI evidence.
  • Complete fresh adversarial and security reviews.
  • Verify active turn abort lifecycle and rerun fresh reviews.

Security and compatibility

The change adds no input, stored user data, network, authentication, or authorization behavior. It keeps the existing optional wire field for compatibility. Migration 42 adds only a partial SQLite index for the parameterized latest-plan lookup.

Deviations

  • Cursor Bugbot found accepted aborts settled lifecycle state without flushing buffered assistant text or proposed-plan deltas; the plan now includes a terminal-finalization regression.
  • Fresh abort-fix review found active-session/latest-turn divergence and untargeted abort cleanup gaps; both now have focused regressions.
  • Cursor Bugbot found that a provider turn.aborted event cleared only process-local progress and could leave the persisted turn running; the plan now includes a lifecycle regression and fix.
  • Fresh Standards review found the first pinning query ranked every plan update without a supporting index; the plan now includes a partial index and query-plan regression.
  • Fresh Spec review found that the 500-activity detail limit could omit an older active-turn plan; the plan now includes a bounded-hydration regression and fix.
  • The collaborative preview capture failed, so the user approved Chrome as the fallback for the final GitHub-uploaded image pair.
  • The two temporary asset-only commits bypassed the pre-commit hook because vp fmt had no supported target. Both code commits ran the hook normally.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • This change has no animation

Built with GPT-5.6-sol in the Codex harness.

Note

Fix composer Tasks tab to restore active turn plan after relaunch

  • Adds resolveActivePlanTurnId and deriveActiveComposerTasks in session-logic.ts to compute Tasks drawer progress and steps from the latest turn.plan.updated activity, scoped to the active or running turn; hides the drawer once the turn settles or all steps complete.
  • Extends listPinnedThreadActivityRowsByThread in ProjectionSnapshotQuery.ts to always pin the latest turn.plan.updated for the active or unsettled turn, even when it falls outside the recent-activity window.
  • Hardens turn.aborted handling in ProviderRuntimeIngestion.ts: ignores untargeted or wrong-turn aborts, sets session status to interrupted, clears activeTurnId, finalizes assistant messages, and only clears plan progress when the lifecycle actually settles the active turn.
  • Adds migration 42 in 042_ProjectionThreadPlanActivityIndex.ts, a partial index on projection_thread_activities for kind = 'turn.plan.updated' to speed up the plan activity lookup.
  • Risk: ProviderRuntimeIngestion.acceptEventForThread now rejects turn.aborted events with a null activeTurnId or a turn mismatch; callers relying on untargeted aborts being applied will see them dropped.

Macroscope summarized 1e8276a.


Note

Medium Risk
Changes turn lifecycle handling for turn.aborted (ignore untargeted aborts; interrupt and finalize the active turn) and the thread-detail activity pin query. Wrong matching would leave a turn running or drop the restored Tasks tab.

Overview
Restores the composer Tasks tab after relaunch from the persisted active-turn plan, instead of relying on empty process-local shell progress.

Thread detail now pins the latest turn.plan.updated activity for the unsettled turn (preferring a running session’s activeTurnId when it diverges from latest_turn_id) so the plan survives the 500-activity hydration cap. Migration 042 adds a partial index for that lookup.

turn.aborted now settles only the matching active turn: session becomes interrupted, buffered assistant text and proposed plans finalize, and plan progress clears. Untargeted or other-turn aborts are ignored.

The UI derives composer tasks from that pinned plan via deriveActiveComposerTasks / resolveActivePlanTurnId, hiding the tab when the turn settles or every step is complete.

Reviewed by Cursor Bugbot for commit 1e8276a. Bugbot is set up for automated code reviews on this repo. Configure here.

Kick off the approved pingdotgg#8091 plan with the regression-test slice first.
@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a19edca3-ec80-4b73-aa30-f7885d406d93

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Aug 24, 2026
Add the approved active-plan seam and a failing regression case for pingdotgg#8091. The test proves persisted unfinished tasks are currently hidden after process-local progress resets.
@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:XS 0-9 changed lines (additions + deletions). labels Aug 24, 2026
Derive the composer Tasks tab from persisted active-turn plan activities instead of process-local shell progress. Keep completed, settled, and superseded plans hidden.
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 24, 2026
Capture the restored task drawer from the isolated pingdotgg#8091 restart fixture. The asset-only pre-commit formatter has no supported target, so this commit bypasses that hook.
Remove the verification image from the branch tip because CI requires PR evidence to be hosted on GitHub rather than tracked. The PR references the immutable image commit.
Reproduce pingdotgg#8091 when 500 later activities push the active turn plan outside bounded thread-detail hydration.
Pin the latest unsettled-turn plan beside unresolved request activities so restart hydration still restores composer tasks after 500 later activities.
Assert that SQLite uses a plan-specific index for the single latest plan row needed by restart hydration.
Replace unbounded plan ranking with a single-row lookup backed by a partial thread-turn plan index.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding: the new migration test targets a migration (042) that this PR never adds or registers, so the test and the index it asserts cannot exist.

Posted via Macroscope — Effect Service Conventions

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Aug 24, 2026
Use one active-plan result for both the composer Tasks tab and in-chat Working label so their current-step rules stay aligned.
Drive composer task derivation from persisted activities at the ChatView seam and explain the production CTE so wiring and index regressions fail focused tests.
Document the Tasks tab, reconnect restoration, settlement behavior, and session-local dismissal.
@sethwebster
sethwebster marked this pull request as ready for review August 24, 2026 14:07
Comment thread apps/web/src/session-logic.ts
@macroscopeapp

macroscopeapp Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This change crosses server lifecycle handling, bounded database hydration, a production index migration, and client task-state derivation. It alters how aborted turns are settled and how persisted plans are restored, so the runtime and state-management impact warrants human review.

You can add or adjust custom eligibility rules. Learn more.

Reproduce stale persisted task progress when turn.aborted clears only the in-memory plan registry and leaves the active session running.
Project an active turn.aborted event as an interrupted session with no active turn, while ignoring aborts for other turns. This prevents persisted task plans from lingering after abort or relaunch.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 52a3944. Configure here.

Comment thread apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts
Reproduce wrong-plan hydration when session.activeTurnId differs from latestTurnId, and prove an untargeted abort must not clear active plan progress.
Keep plan progress when an untargeted or foreign turn.aborted event is rejected, while matched aborts settle and clear the active turn. Cover late duplicates without polling.
Prefer session.activeTurnId while a session runs in both hydration and web derivation, falling back to latestTurnId only outside a running session.
Reproduce lost buffered assistant text and proposed-plan deltas when turn.aborted is the only accepted terminal event.
Treat an accepted turn.aborted as a terminal event for buffered assistant messages and proposed plans before clearing turn state.
Pass the resolved session-active Tasks turn into ChatComposer so session-local dismissal cannot target a stale latestTurnId.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Active turn Tasks list disappears after an update-triggered relaunch

1 participant