Calendar Day
Backlog follow-up (discovered July 16, 2026 during refactor/trim-model-exports review)
Planned Effort
3–5 story points (Medium) — not on Week 29 sprint; file separately from Thursday PR 2
Problem
Code cleanup review of refactor/trim-model-exports found 12 pre-existing issues in unchanged portions of services/workspace_tabs.py, utils/cursor_md_exporter.py, and utils/display_bubble.py. None were introduced by the export trim (removing BubbleRole / BubbleMetadata from models/__all__). They are valid repair targets but out of scope for PR 2.
Goal
One follow-up PR reducing duplication, narrowing exception handling, and fixing small performance/hygiene issues in the tabs and markdown-export paths. No behavior change unless a bug is found while refactoring.
Scope
Medium priority
services/workspace_tabs.py — _assemble_tab_from_composer_data (~241 lines): extract sequential phases (bubble build, sort/annotate, metadata aggregation, tab dict construction).
services/workspace_tabs.py — duplicate composer-row loop in _build_workspace_tab_summaries_uncached and assemble_workspace_tabs; extract shared iteration/guard/exception skeleton with a callback or generator.
services/workspace_tabs.py — except Exception at L517 and L774; narrow to KeyError, TypeError, ValueError, json.JSONDecodeError (and similar realistic parse failures).
utils/cursor_md_exporter.py — cursor_ide_chat_to_markdown (~273 lines): extract phases (bubbles, aggregates, activity scan, frontmatter, body).
utils/cursor_md_exporter.py — duplicate tool-call markdown rendering in cursor_cli_session_to_markdown and cursor_ide_chat_to_markdown; extract _render_tool_call_md(tc) -> str.
Low priority
services/workspace_tabs.py — repeated error literals ("Conversation not found" ×4, "Global storage not found" ×3); extract named constants.
services/workspace_tabs.py — context_text += in nested loops (L170–209); accumulate list and join once.
services/workspace_tabs.py — restating comments at L683 and L782; delete.
utils/cursor_md_exporter.py — body += in per-bubble loops (CLI and IDE paths); use list + join (match fm_lines pattern).
utils/cursor_md_exporter.py — except Exception at L93 when reading CLI session metadata; narrow to sqlite3.Error, json.JSONDecodeError, IndexError, TypeError.
utils/display_bubble.py — cast(BubbleMetadata, …) at L129 and L160; type build_storage_bubble_metadata as BubbleMetadata | None to drop casts (also affects workspace_tabs.py).
Out of scope
- Further
models/__init__.py export trimming (Thursday PR 2 scope).
- RuleTokens threading, release tag, or other Week 29 items.
Acceptance Criteria
Verification
cd C:\Users\Jasen\CppAliance\cppa-cursor-browser
.\.venv\Scripts\Activate.ps1
mypy --strict services/workspace_tabs.py utils/cursor_md_exporter.py utils/display_bubble.py
pytest -q tests/test_workspace_tabs.py tests/test_export_engine.py
pytest -q -k "export or tab"
pytest -q
Calendar Day
Backlog follow-up (discovered July 16, 2026 during
refactor/trim-model-exportsreview)Planned Effort
3–5 story points (Medium) — not on Week 29 sprint; file separately from Thursday PR 2
Problem
Code cleanup review of
refactor/trim-model-exportsfound 12 pre-existing issues in unchanged portions ofservices/workspace_tabs.py,utils/cursor_md_exporter.py, andutils/display_bubble.py. None were introduced by the export trim (removingBubbleRole/BubbleMetadatafrommodels/__all__). They are valid repair targets but out of scope for PR 2.Goal
One follow-up PR reducing duplication, narrowing exception handling, and fixing small performance/hygiene issues in the tabs and markdown-export paths. No behavior change unless a bug is found while refactoring.
Scope
Medium priority
services/workspace_tabs.py—_assemble_tab_from_composer_data(~241 lines): extract sequential phases (bubble build, sort/annotate, metadata aggregation, tab dict construction).services/workspace_tabs.py— duplicate composer-row loop in_build_workspace_tab_summaries_uncachedandassemble_workspace_tabs; extract shared iteration/guard/exception skeleton with a callback or generator.services/workspace_tabs.py—except Exceptionat L517 and L774; narrow toKeyError,TypeError,ValueError,json.JSONDecodeError(and similar realistic parse failures).utils/cursor_md_exporter.py—cursor_ide_chat_to_markdown(~273 lines): extract phases (bubbles, aggregates, activity scan, frontmatter, body).utils/cursor_md_exporter.py— duplicate tool-call markdown rendering incursor_cli_session_to_markdownandcursor_ide_chat_to_markdown; extract_render_tool_call_md(tc) -> str.Low priority
services/workspace_tabs.py— repeated error literals ("Conversation not found"×4,"Global storage not found"×3); extract named constants.services/workspace_tabs.py—context_text +=in nested loops (L170–209); accumulate list andjoinonce.services/workspace_tabs.py— restating comments at L683 and L782; delete.utils/cursor_md_exporter.py—body +=in per-bubble loops (CLI and IDE paths); use list +join(matchfm_linespattern).utils/cursor_md_exporter.py—except Exceptionat L93 when reading CLI session metadata; narrow tosqlite3.Error,json.JSONDecodeError,IndexError,TypeError.utils/display_bubble.py—cast(BubbleMetadata, …)at L129 and L160; typebuild_storage_bubble_metadataasBubbleMetadata | Noneto drop casts (also affectsworkspace_tabs.py).Out of scope
models/__init__.pyexport trimming (Thursday PR 2 scope).Acceptance Criteria
_assemble_tab_from_composer_datasplit into named phase helpers (or equivalent structure with no 200+ line body).except Exceptionnarrowed in scoped locations (or documented if intentionally broad).mypy --strict+ fullpytest -qgreen; no user-visible export/tab behavior change.Verification