Skip to content

fix(app): stabilize todo dock visibility#381

Merged
Astro-Han merged 1 commit into
devfrom
pawwork/todo-dock-completed-session-fix
May 2, 2026
Merged

fix(app): stabilize todo dock visibility#381
Astro-Han merged 1 commit into
devfrom
pawwork/todo-dock-completed-session-fix

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a shared session todo selector used by both the status panel and composer todo dock.
  • Keep active todo docks visible from real todowrite tool parts while preventing historical completed todo lists from flashing on session switch.
  • Add focused unit and e2e coverage for backend todos, message-derived todos, route fallback, completion auto-hide, and cleared todo history.

Why

The status panel and bottom todo dock were reading different todo sources. In real sessions, the status panel could show todowrite progress while the composer dock stayed hidden. Completed historical sessions could also briefly show the dock for several seconds after navigation.

Related Issue

No linked issue; found during local todo dock testing.

Human Review Status

Pending. A human should make the final merge decision after reviewing the final diff and verification evidence.

Review Focus

Please focus on the todo source priority in selectSessionTodos and the composer dock visibility rules around active vs. terminal todo lists.

Risk Notes

Low-to-medium UI behavior risk: this changes which todo source drives the status panel and composer dock. No data, permission, dependency, migration, updater, or packaging changes.

How To Verify

Related unit tests: 25 passed
Command: bun test src/pages/session/session-todos.test.ts src/pages/session/composer/session-composer-state.test.ts src/pages/session/session-status-extractors.test.ts

Todo dock e2e: 11 passed
Command: bun test:e2e -- session/session-composer-dock.spec.ts -g "todo dock"

Crosscheck review: PASS WITH NITS; P2 finding fixed with a regression test.

Screenshots or Recordings

Not attached. The visible behavior is covered by focused todo dock e2e tests; final manual visual confirmation should be done during human review if needed.

Checklist

  • Human review status is stated above as pending, approved, or not required
  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I described the review focus and any meaningful risks
  • I listed the relevant verification steps and the key result for each
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant
  • I reviewed the final diff for unrelated changes and suspicious dependency changes
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • New Features

    • Session todo dock now appears when real todo data arrives and remains hidden when navigating to sessions with only completed todos.
  • Improvements

    • Enhanced session navigation with fallback session ID handling for improved reliability.
  • Tests

    • Added comprehensive end-to-end coverage for session todo dock behavior and state transitions.
    • Expanded test suite for session todo selection logic with fallback scenarios.

@Astro-Han Astro-Han added bug Something isn't working P2 Medium priority app Application behavior and product flows labels May 2, 2026
@coderabbitai

coderabbitai Bot commented May 2, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces fallback session todo selection and improves session-transition handling in the todo dock. A new selectSessionTodos function cascades through backend and message-part sources with optional fallback, while session composer state tracks active-todo sessions to prevent dock hiding during transitions. Components and state management updated to use this new selection mechanism.

Changes

Session Todo Selection with Fallback

Layer / File(s) Summary
Type and Selection Logic
packages/app/src/pages/session/session-todos.ts
Introduces SessionTodoSource type with optional backend and required parts, and selectSessionTodos function that cascades: prefers backend if non-empty, else extractTodos(parts), else fallback backend, else extractTodos(fallback.parts ?? []).
State Management Integration
packages/app/src/pages/session/composer/session-composer-state.ts
createSessionComposerState accepts optional fallbackSessionID, derives todos() via selectSessionTodos with active and fallback session sources, and tracks sessionsWithActiveTodos set to gate dock hiding/completion state during session transitions.
Component Integration
packages/app/src/components/session/session-status-summary.tsx
Swaps extractTodos(props.parts()) to selectSessionTodos({ parts: props.parts() }) for todo item sourcing.
Page Wiring
packages/app/src/pages/session.tsx
Consolidates SolidJS imports and passes fallbackSessionID: () => params.id alongside sessionID to composer state initialization.
Unit Tests
packages/app/src/pages/session/session-todos.test.ts
Bun test suite for selectSessionTodos validates backend-precedence, message-part fallback, and secondary-session fallback behaviors via mock ToolState and Part structures.
E2E Tests
packages/app/e2e/session/session-composer-dock.spec.ts
Adds tests for dock appearing from real tool output and remaining hidden after same-count terminal session switch; updates existing tests with revised todo lifecycle sequences (initial status in_progresscompleted vs prior completed start) and adjusted state transition expectations (completing, count) across clock advances and session switches; fixes scroll-dock metrics guard formatting.

Sequence Diagram

sequenceDiagram
    participant User
    participant SessionPage as Session Page
    participant ComposerState as Composer State
    participant SelectTodos as selectSessionTodos
    participant StatusSummary as Status Summary
    participant Backend as Backend/Messages

    User->>SessionPage: Navigate to session
    SessionPage->>ComposerState: Init with sessionID + fallbackSessionID
    
    Note over ComposerState: Check active session
    ComposerState->>SelectTodos: selectSessionTodos(active session)
    SelectTodos->>Backend: Fetch active backend todos
    alt Active has backend todos
        SelectTodos-->>ComposerState: Return backend todos
    else Active backend empty
        SelectTodos->>Backend: Extract from active message parts
        alt Message parts have todos
            SelectTodos-->>ComposerState: Return message-derived todos
        else Active parts empty
            SelectTodos->>Backend: Fetch fallback session parts
            SelectTodos-->>ComposerState: Return fallback-derived todos
        end
    end
    
    ComposerState->>StatusSummary: Pass todos()
    StatusSummary->>User: Render todo progress
    
    Note over ComposerState: Track sessionsWithActiveTodos
    ComposerState->>ComposerState: Gate dock hide when<br/>session changed + todos exist
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 A hop through sessions, todos now relay
With fallback paths to light the way
The dock persists through switching scenes,
No premature goodbye between.
Cascading sources, wisdom flows!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(app): stabilize todo dock visibility' accurately describes the main objective of the PR, which is to fix todo dock visibility flashing issues.
Description check ✅ Passed The PR description follows the repository template with all major sections completed: Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify, and a checked Checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pawwork/todo-dock-completed-session-fix

Review rate limit: 7/10 reviews remaining, refill in 15 minutes and 33 seconds.

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

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
packages/app/src/pages/session/session-todos.test.ts (1)

53-61: ⚡ Quick win

Add a fallback-backend precedence test case.

You validate fallback parts, but not the branch where fallback.backend is non-empty. Adding that assertion locks down the full selection order and protects this bugfix path from regressions.

Proposed test addition
 describe("selectSessionTodos", () => {
+  test("prefers fallback backend todos over fallback parts todos", () => {
+    const fallbackParts = [
+      toolPart("todowrite", completedState({ input: { todos: [todo("from fallback parts", "in_progress")] } })),
+    ]
+
+    expect(
+      selectSessionTodos({
+        backend: [],
+        parts: [],
+        fallback: {
+          backend: [todo("from fallback backend", "pending")],
+          parts: fallbackParts,
+        },
+      }),
+    ).toEqual([todo("from fallback backend", "pending")])
+  })
+
   test("falls back to a secondary session source when the primary source is empty", () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/pages/session/session-todos.test.ts` around lines 53 - 61,
Add a test variant to cover the fallback.backend precedence: the current test
only exercises fallback.parts, so create an additional assertion calling
selectSessionTodos with backend: [], parts: [], and fallback: { backend: [ /* a
backend todo source */ ], parts: [...] } and assert the returned todos come from
fallback.backend instead of fallback.parts; reference the existing helpers and
symbols (selectSessionTodos, toolPart, completedState, todo) to construct the
fallback.backend item so the test pins the correct selection order.
packages/app/src/pages/session/session-todos.ts (1)

13-16: ⚡ Quick win

Drop the as Todo[] casts to keep type drift visible.

These assertions hide future schema mismatches. Returning extractTodos(...) directly keeps compile-time checks honest without changing runtime behavior.

Type-safety cleanup
   const fromParts = extractTodos(input.parts)
-  if (fromParts.length > 0) return fromParts as Todo[]
+  if (fromParts.length > 0) return fromParts

   if (input.fallback?.backend && input.fallback.backend.length > 0) return input.fallback.backend
-  return extractTodos(input.fallback?.parts ?? []) as Todo[]
+  return extractTodos(input.fallback?.parts ?? [])
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/src/pages/session/session-todos.ts` around lines 13 - 16, The
code currently forces types with casts like "fromParts as Todo[]" and
"extractTodos(...) as Todo[]", which masks schema mismatches; remove the "as
Todo[]" assertions so functions/variables (fromParts, input.fallback.backend,
extractTodos, Todo) retain their inferred types and let the compiler surface
mismatches; update the return lines in session-todos.ts to return fromParts,
input.fallback.backend, and extractTodos(...) directly (no casts) and run
typecheck to fix any resulting type errors by adjusting upstream types or
signatures instead of reintroducing assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/app/src/pages/session/session-todos.test.ts`:
- Around line 53-61: Add a test variant to cover the fallback.backend
precedence: the current test only exercises fallback.parts, so create an
additional assertion calling selectSessionTodos with backend: [], parts: [], and
fallback: { backend: [ /* a backend todo source */ ], parts: [...] } and assert
the returned todos come from fallback.backend instead of fallback.parts;
reference the existing helpers and symbols (selectSessionTodos, toolPart,
completedState, todo) to construct the fallback.backend item so the test pins
the correct selection order.

In `@packages/app/src/pages/session/session-todos.ts`:
- Around line 13-16: The code currently forces types with casts like "fromParts
as Todo[]" and "extractTodos(...) as Todo[]", which masks schema mismatches;
remove the "as Todo[]" assertions so functions/variables (fromParts,
input.fallback.backend, extractTodos, Todo) retain their inferred types and let
the compiler surface mismatches; update the return lines in session-todos.ts to
return fromParts, input.fallback.backend, and extractTodos(...) directly (no
casts) and run typecheck to fix any resulting type errors by adjusting upstream
types or signatures instead of reintroducing assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d356e4a-7609-4c84-96a6-8c04b47cf223

📥 Commits

Reviewing files that changed from the base of the PR and between 0d8cae9 and 8f659fe.

📒 Files selected for processing (6)
  • packages/app/e2e/session/session-composer-dock.spec.ts
  • packages/app/src/components/session/session-status-summary.tsx
  • packages/app/src/pages/session.tsx
  • packages/app/src/pages/session/composer/session-composer-state.ts
  • packages/app/src/pages/session/session-todos.test.ts
  • packages/app/src/pages/session/session-todos.ts

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the session todo selection logic by introducing a prioritized selection mechanism that falls back to message-derived parts and secondary session IDs when primary backend data is unavailable. It also refines the behavior of the todo dock to ensure it remains hidden when landing on completed sessions and correctly manages state during session transitions. New E2E and unit tests have been added to verify these improvements. I have no feedback to provide as no review comments were present.

@Astro-Han Astro-Han merged commit d3d5758 into dev May 2, 2026
38 of 39 checks passed
@Astro-Han Astro-Han deleted the pawwork/todo-dock-completed-session-fix branch May 2, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app Application behavior and product flows bug Something isn't working P2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant