Calendar Day
Monday, June 22, 2026 (PR 1 of 2)
Planned Effort
5 story points — sprint item #3 (High)
Continues: cppa-cursor-browser #42 (closed via PR #61, May 2026) — this PR finishes the remaining consolidation and adds CLI summary-cache wiring.
Companion PR: Monday PR 2 (os.environ fix #4) — same scripts/export.py; land this consolidation first so the explicit-override plumbing slots into the shared engine.
Prior work (#42 / PR #61)
Issue #42 flagged scripts/export.py as a ~700-line parallel implementation of the web pipeline. PR #61 (Brad, merged 2026-05-21) closed #42 by:
- Delegating workspace scanning to
services/workspace_db._collect_workspace_entries()
- Replacing private utility copies with imports from
utils/workspace_path, utils/text_extract, services/workspace_resolver
- Extracting Markdown generation to
utils/cursor_md_exporter.cursor_ide_chat_to_markdown()
- Deduplicating bubble/layout/diff loaders into
services/workspace_db._load_*_map() (also consumed by workspace_listing, workspace_tabs, api/export_api)
- Guarding
sys.path.insert under if __name__ == "__main__" (inert when installed via entry point)
Still open after #61 (this PR's scope):
scripts/export.py is still ~540 lines with its own orchestration loop — no shared export_engine.py and no use of services/workspace_listing.py
- Summary cache (
services/summary_cache.py) benefits the web path only; CLI re-scans on every run
[[tool.mypy.overrides]] for scripts.export with ignore_errors = true remains in pyproject.toml
sys.path.insert guard still present for direct python scripts/export.py invocation (not fully eliminated)
Problem
scripts/export.py (542 lines) duplicates substantial business logic from the services/ and utils/ layers rather than calling them through a shared interface. The script directly performs workspace scanning, database reading, workspace resolution, exclusion filtering, and markdown export. services/workspace_listing.py implements the same orchestration with caching (via services/summary_cache.py) — none of which benefits the CLI path. This duplication is explicitly exempted from mypy strict checking via [[tool.mypy.overrides]] in pyproject.toml (ignore_errors = true), so type-safety regressions in the CLI export path are invisible.
Goal
One merged PR that extracts a shared export-orchestration engine, reduces scripts/export.py to a thin CLI wrapper, routes both the web and CLI paths through it (so the summary cache benefits the CLI), and removes the mypy-strict exemption — with no behavioral change to CLI export output.
Scope
Touch points
services/export_engine.py (new or extend) — shared orchestration function
scripts/export.py — reduce to arg-parsing + calling the engine + output writing
services/workspace_listing.py — refactor to use the shared engine
services/summary_cache.py — consumed by the engine (read-only; no change)
pyproject.toml — remove the [[tool.mypy.overrides]] ignore_errors = true block for scripts.export
Out of scope
Acceptance Criteria
Verification
cd C:\Users\Jasen\CppAliance\cppa-cursor-browser
.\.venv\Scripts\Activate.ps1
mypy --strict scripts/export.py
pytest -k export
python scripts/export.py --help
Calendar Day
Monday, June 22, 2026 (PR 1 of 2)
Planned Effort
5 story points — sprint item #3 (High)
Continues: cppa-cursor-browser #42 (closed via PR #61, May 2026) — this PR finishes the remaining consolidation and adds CLI summary-cache wiring.
Companion PR: Monday PR 2 (os.environ fix #4) — same
scripts/export.py; land this consolidation first so the explicit-override plumbing slots into the shared engine.Prior work (#42 / PR #61)
Issue #42 flagged
scripts/export.pyas a ~700-line parallel implementation of the web pipeline. PR #61 (Brad, merged 2026-05-21) closed #42 by:services/workspace_db._collect_workspace_entries()utils/workspace_path,utils/text_extract,services/workspace_resolverutils/cursor_md_exporter.cursor_ide_chat_to_markdown()services/workspace_db._load_*_map()(also consumed byworkspace_listing,workspace_tabs,api/export_api)sys.path.insertunderif __name__ == "__main__"(inert when installed via entry point)Still open after #61 (this PR's scope):
scripts/export.pyis still ~540 lines with its own orchestration loop — no sharedexport_engine.pyand no use ofservices/workspace_listing.pyservices/summary_cache.py) benefits the web path only; CLI re-scans on every run[[tool.mypy.overrides]]forscripts.exportwithignore_errors = trueremains inpyproject.tomlsys.path.insertguard still present for directpython scripts/export.pyinvocation (not fully eliminated)Problem
scripts/export.py(542 lines) duplicates substantial business logic from theservices/andutils/layers rather than calling them through a shared interface. The script directly performs workspace scanning, database reading, workspace resolution, exclusion filtering, and markdown export.services/workspace_listing.pyimplements the same orchestration with caching (viaservices/summary_cache.py) — none of which benefits the CLI path. This duplication is explicitly exempted from mypy strict checking via[[tool.mypy.overrides]]inpyproject.toml(ignore_errors = true), so type-safety regressions in the CLI export path are invisible.Goal
One merged PR that extracts a shared export-orchestration engine, reduces
scripts/export.pyto a thin CLI wrapper, routes both the web and CLI paths through it (so the summary cache benefits the CLI), and removes the mypy-strict exemption — with no behavioral change to CLI export output.Scope
Touch points
services/export_engine.py(new or extend) — shared orchestration functionscripts/export.py— reduce to arg-parsing + calling the engine + output writingservices/workspace_listing.py— refactor to use the shared engineservices/summary_cache.py— consumed by the engine (read-only; no change)pyproject.toml— remove the[[tool.mypy.overrides]]ignore_errors = trueblock forscripts.exportOut of scope
os.environworkspace-path bypass (Monday PR 2 — Fix app.py and scripts/export.py CLI: switch to argparse, add --port/--host/--base-dir, fix default host, validate --since #4)Acceptance Criteria
scripts/export.pycalls a shared export-orchestration function instead of reimplementing workspace scanning, database reading, and composer processing[[tool.mypy.overrides]]block forscripts.exportwithignore_errors = trueis removedscripts/export.pypassesmypy --strictVerification