Tasks: Fix Thinking Panel Re-Expand on Conversation Switch
Input: Design documents from docs/docs/specs/095-fix-thinking-panel-expand/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
Tests: Tests are included per Constitution gate VII (test-first quality gates).
Organization: Tasks are grouped by user story to enable independent implementation and testing of each story.
Format: [ID] [P?] [Story] Description​
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (e.g., US1, US2)
- Include exact file paths in descriptions
Phase 1: Setup​
Purpose: Verify the existing code state and ensure we're on the right branch
- T001 Verify branch is
095-fix-thinking-panel-expandand rebased on latestorigin/main - T002 Verify existing
showRawStreaminitializer inui/src/components/chat/ChatPanel.tsxuses lazyuseState(() => ...)withmessage.isFinalcheck
Phase 2: User Story 1 - Completed Message Thinking Panel Stays Collapsed on Return (Priority: P1) 🎯 MVP​
Goal: When a message has finished streaming (isFinal === true), the thinking/plan panel defaults to collapsed on mount, including when the user navigates back to the conversation.
Independent Test: Switch away from a conversation with a completed response, switch back — the thinking panel must remain collapsed.
Tests for User Story 1​
NOTE: Write these tests FIRST, ensure they FAIL before implementation (if code fix not yet applied)
- T003 [US1] Add test in
ui/src/components/chat/__tests__/ChatPanel.test.tsx: for a message withisFinal: trueandrawStreamContent, assert thinking section defaults to collapsed (not expanded) - T004 [US1] Add test in
ui/src/components/chat/__tests__/ChatPanel.test.tsx: for a message withisFinal: truerendered after remount (simulating conversation switch), assert thinking section remains collapsed
Implementation for User Story 1​
- T005 [US1] In
ChatMessageinui/src/components/chat/ChatPanel.tsx, ensureshowRawStreamuseStateinitializer returnsfalsewhenmessage.isFinal === true
Checkpoint: At this point, User Story 1 should be fully functional — final messages default to collapsed on (re)mount
Phase 3: User Story 2 - Streaming Messages Honor User Preference (Priority: P2)​
Goal: When a message is still streaming (isFinal !== true), the thinking panel defaults to the user's preference from showThinkingDefault. No regression from existing behavior.
Independent Test: Start a new conversation, confirm the thinking panel follows the feature flag default during streaming.
Tests for User Story 2​
- T006 [P] [US2] Add test in
ui/src/components/chat/__tests__/ChatPanel.test.tsx: for a message withisFinal: falseandrawStreamContent, assert thinking section defaults to expanded (whenshowThinkingflag istrue) - T007 [P] [US2] Add test in
ui/src/components/chat/__tests__/ChatPanel.test.tsx: verify the thinking panel toggle button works (user can expand/collapse regardless of initial state)
Implementation for User Story 2​
- T008 [US2] In
ChatMessageinui/src/components/chat/ChatPanel.tsx, ensureshowRawStreamuseStateinitializer returnsshowThinkingDefaultwhenmessage.isFinal !== true(verify no regression)
Checkpoint: Both User Story 1 and 2 pass — final messages collapsed, streaming messages honor user preference
Phase 4: Polish & Cross-Cutting Concerns​
Purpose: Quality gates, docs, and commit
- T009 Run
make caipe-ui-testsand confirm all ChatPanel tests pass (zero failures) - T010 Run manual smoke test per
quickstart.md: switch conversations with completed responses, verify collapsed state - T011 [P] Update spec status from
DrafttoCompleteindocs/docs/specs/095-fix-thinking-panel-expand/spec.md - T012 Commit all changes with conventional commit:
fix(ui): default thinking panel to collapsed for completed messages
Dependencies & Execution Order​
Phase Dependencies​
- Setup (Phase 1): No dependencies — verify state immediately
- User Story 1 (Phase 2): Depends on Setup — core bug fix
- User Story 2 (Phase 3): Can start in parallel with US1 (tests are in a different describe block, implementation is the same
useStateline) - Polish (Phase 4): Depends on US1 and US2 completion
User Story Dependencies​
- User Story 1 (P1): Independent — no dependencies on other stories
- User Story 2 (P2): Independent — validates existing behavior is preserved (no regression)
Within Each User Story​
- Tests MUST be written and FAIL before implementation (if fix not yet applied)
- Implementation is a single
useStateinitializer change - Story complete when tests pass
Parallel Opportunities​
- T003 and T004 (US1 tests) must be sequential (same test file section)
- T006 and T007 (US2 tests) are marked [P] — they test different behaviors and can be written independently
- T009 and T011 (Polish) are independent
Parallel Example: User Story 1 + User Story 2​
# Since both stories touch the same useState line, implement sequentially:
# 1. Write US1 tests (T003, T004) → verify fix (T005) → checkpoint
# 2. Write US2 tests (T006, T007) → verify no regression (T008) → checkpoint
# 3. Run full test suite (T009) → smoke test (T010) → commit (T012)
Implementation Strategy​
MVP First (User Story 1 Only)​
- Complete Phase 1: Verify setup
- Complete Phase 2: Add US1 tests + verify fix
- STOP and VALIDATE: Run
make caipe-ui-tests - If passing → this is the MVP
Full Delivery​
- Complete MVP (US1)
- Add US2 regression tests → verify
- Run full quality gates → commit → PR
Notes​
- The code fix (T005/T008) is already applied in the working tree — the
useStateinitializer already checksmessage.isFinal. The primary remaining work is adding tests (T003, T004, T006, T007) and running quality gates. - [P] tasks = different files or independent test cases, no dependencies
- [Story] label maps task to specific user story for traceability
- Commit after all tests pass with
git commit -sfor DCO sign-off