diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 4c29d97..4d6b804 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1,7 +1,7 @@ # PanoPainter Modernization Roadmap Status: live -Last updated: 2026-06-05 +Last updated: 2026-06-12 This is the living roadmap for modernizing PanoPainter into independently testable C++23 components while retaining all existing functionality. Keep this @@ -11,6 +11,9 @@ or temporary adapters live only in chat history. ## How To Keep This Roadmap Live - Update the phase status before and after each implementation pass. +- Use `docs/modernization/tasks.md` for measurable execution tasks and + percentage/progress claims. The phase prose explains direction; the task + tracker is the source of truth for score changes. - When a shortcut is introduced, add it to the debt log section in this file until `docs/modernization/debt.md` exists, then move debt entries there. - When a major architectural decision is made, add an ADR under `docs/adr/` @@ -51,6 +54,14 @@ or temporary adapters live only in chat history. | 7 | Hardening, Coverage, And Breaking-Point Tests | Not started | Each component has edge/failure tests | | 8 | Future Backend Readiness | Not started | Vulkan/Metal lab targets remain non-default | +## Measurable Task Tracking + +Use `docs/modernization/tasks.md` before starting implementation work. It +contains the current 100-point modernization scorecard, task states, ready +queue, blocked queue, validation commands, and completion rules. Do not move the +percentage for a narrowed adapter or added planner unless a task in that file is +marked `Done` with validation and a debt/roadmap update. + ## Target Component Architecture The refactor should move toward one-way dependencies: diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md new file mode 100644 index 0000000..4701730 --- /dev/null +++ b/docs/modernization/tasks.md @@ -0,0 +1,556 @@ +# Modernization Task Tracker + +Status: live +Last updated: 2026-06-12 + +This file turns the modernization roadmap into small, measurable work items. +The roadmap explains direction, the debt log explains why shortcuts remain, and +this tracker is the execution queue. Prefer closing one task here over adding a +new broad roadmap paragraph. + +## Operating Rules + +- Pick one `Ready` task at a time unless the user asks for planning only. +- Keep each slice small enough to validate and commit in one session. +- Do not claim percentage progress for "narrowed" debt. Points move only when a + task row is changed to `Done`. +- A task is `Done` only when its listed checks pass, the debt log is updated or + closed as applicable, and the roadmap/task score is updated. +- If a task proves too large, split it before editing code. The original task + stays `Ready` or becomes `Blocked` with the reason. +- After a verified task is committed and pushed, reset conversation context + before starting the next task when practical. + +## Progress Scorecard + +The current score is intentionally conservative. It should move in visible, +auditable steps rather than by subjective estimates. + +| Area | Weight | Current | Progress Rule | +| --- | ---: | ---: | --- | +| Build and CMake ownership | 15 | 11 | Root CMake owns active source lists, app/tool targets, and retained package entrypoints. | +| Test and automation coverage | 15 | 9 | Headless, platform, package, and focused validation commands exist and are current. | +| Pure component behavior ownership | 15 | 8 | Behavior lives in `pp_*` components and is consumed by live adapters. | +| Legacy adapter retirement | 20 | 2 | `legacy_*_services` and singleton bridges are deleted or reduced to trivial composition. | +| Renderer boundary and OpenGL parity | 15 | 3 | Live render/export/readback paths execute through renderer interfaces with parity checks. | +| Platform and package parity | 10 | 2 | Required platforms have root CMake/package validation and injected platform services. | +| Hardening and future backend readiness | 10 | 0 | Edge, fuzz, golden, stress, and backend-lab gates exist for high-risk paths. | +| **Total** | **100** | **35** | Only completed tasks below may change this number. | + +When updating `Current`, add a dated note under "Completed Task Log" with the +task id, points moved, validation command, and commit hash. + +## Task States + +| State | Meaning | +| --- | --- | +| `Ready` | Clear enough for an agent to execute. | +| `In progress` | Actively being changed in the current slice. | +| `Blocked` | Needs a user decision, missing toolchain, or a prior task. | +| `Done` | Validated, documented, committed, and pushed. | + +## Ready Queue + +### MT-001 - Adopt Measurable Task Tracking + +Status: Done +Score: no score movement +Debt: none +Scope: `docs/modernization/tasks.md`, `docs/modernization/roadmap.md` + +Steps: + +- Add this tracker. +- Link it from the roadmap. +- Make the scorecard the source for percentage claims. + +Done Checks: + +- `docs/modernization/roadmap.md` points agents to this file. +- The tracker has task states, scoring rules, and at least one ready queue. + +Validation: + +```powershell +git diff -- docs\modernization\roadmap.md docs\modernization\tasks.md +``` + +### ADP-001 - Remove History Bridge From Document Resize And Canvas Clear + +Status: Ready +Score: +1 legacy adapter retirement +Debt: `DEBT-0020`, `DEBT-0027` +Scope: `src/legacy_document_canvas_services.*`, +`src/app_core/document_resize.h`, `tests/app_core/document_resize_tests.cpp`, +related canvas-clear tests only + +Goal: + +Make document resize and canvas-clear execution consume app-core history +commands directly instead of routing through `legacy_history_services`. + +Done Checks: + +- `src/legacy_document_canvas_services.*` no longer includes + `legacy_history_services.h`. +- Resize still executes in order: resize, title update, history clear. +- Canvas clear still records undo and marks the document unsaved when a canvas + exists. +- `docs/modernization/debt.md` narrows or closes the affected removal condition. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_resize|pp_app_core_document_canvas|pano_cli_plan_document_resize|pano_cli_plan_canvas_clear" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### ADP-002 - Remove History Bridge From Layer Operations + +Status: Ready +Score: +1 legacy adapter retirement +Debt: `DEBT-0021` +Scope: `src/legacy_document_layer_services.*`, +`src/app_core/document_layer.h`, `tests/app_core/document_layer_tests.cpp` + +Goal: + +Move layer add/remove/merge/clear/rename history side effects into tested +app-core execution plans so the live layer bridge no longer calls +`legacy_history_services`. + +Done Checks: + +- `src/legacy_document_layer_services.*` no longer includes + `legacy_history_services.h`. +- Layer operations still preserve undo/history behavior covered by + `pp_app_core_document_layer_tests`. +- `pano_cli plan-layer-operation`, `plan-layer-menu`, and + `plan-layer-rename` JSON remains compatible. +- `docs/modernization/debt.md` records the narrowed or closed layer-history + adapter dependency. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_layer|pano_cli_plan_layer" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### ADP-003 - Remove History Bridge From Document Open And Session Save + +Status: Ready +Score: +1 legacy adapter retirement +Debt: `DEBT-0039`, `DEBT-0040`, `DEBT-0042` +Scope: `src/legacy_document_open_services.*`, +`src/legacy_document_session_services.*`, +`src/app_core/document_session.*`, `src/app_core/document_route.*`, +matching tests only + +Goal: + +Make document-open, close, save, save-before-workflow, Save As, and Save Version +history effects explicit app-core outputs instead of direct +`legacy_history_services` calls in the live bridges. + +Done Checks: + +- `src/legacy_document_open_services.*` and + `src/legacy_document_session_services.*` no longer include + `legacy_history_services.h`. +- Existing dirty-document, save-before, new-document, Save As, and Save Version + plans preserve their JSON contracts. +- The debt log is updated for every debt id listed above. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_route|pp_app_core_document_session|pano_cli_plan_open_route|pano_cli_simulate_app_session|pano_cli_plan_document_file|pano_cli_plan_document_version" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### ADP-004 - Make Dialog Creation A UI Factory Boundary + +Status: Ready +Score: +2 legacy adapter retirement +Debt: `DEBT-0058`, `DEBT-0063` +Scope: `src/legacy_app_dialog_services.*`, +`src/legacy_ui_overlay_services.*`, `src/app_dialogs.cpp`, +`src/app_core/app_dialog.h`, dialog tests only + +Goal: + +Keep app-core dialog metadata pure, but move retained +`NodeProgressBar`/`NodeMessageBox`/`NodeInputBox` construction behind one +`pp_panopainter_ui` or retained UI factory function. `App` should ask for a +dialog object through an interface instead of knowing individual node creation +details. + +Done Checks: + +- `App::show_progress`, `App::message_box`, and `App::input_box` still preserve + captions, cancel behavior, and keyboard behavior. +- New factory path has focused tests or existing `pp_app_core_app_dialog_tests` + plus a smoke command proving the live adapter still builds. +- The debt log states exactly which raw-node lifetime hazards remain. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_app_dialog|pano_cli_plan_app_dialog" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### ADP-005 - Convert One Popup/Dialog Family To Checked Overlay Lifetime + +Status: Ready +Score: +2 legacy adapter retirement +Debt: `DEBT-0063` +Scope: choose exactly one family from `src/node_dialog_open.cpp`, +`src/node_dialog_browse.cpp`, `src/node_panel_quick.cpp`, +`src/node_panel_stroke.cpp`, or `src/node_combobox.cpp`, plus +`src/legacy_ui_overlay_services.*` + +Goal: + +Adopt `pp_ui_core` overlay lifetime semantics for one retained popup/dialog +family before trying to rewrite all retained UI nodes. + +Done Checks: + +- The chosen family no longer owns open-coded root insertion, outside-click + release, close callback wiring, or destroy-during-callback behavior. +- Existing UI behavior is preserved. +- Tests cover missing root/template handling and close/release behavior for the + chosen family. +- The debt log names the completed family and the remaining families. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_ui_core_overlay_lifetime|pp_ui_core_node_lifetime" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter +``` + +### RND-001 - Make Pure Equirectangular Export The Primary Success Path + +Status: Ready +Score: +2 renderer boundary and OpenGL parity +Debt: `DEBT-0010`, `DEBT-0036`, `DEBT-0043` +Scope: `src/legacy_document_export_services.*`, +`src/app_core/document_export.*`, `src/paint_renderer/compositor.*`, +`tests/app_core/document_export_tests.cpp`, +`tests/paint_renderer/compositor_tests.cpp` + +Goal: + +For payload-complete snapshots, live PNG/JPEG equirectangular export should +complete through the pure document/paint-renderer writer. Retained +`Canvas::export_equirectangular*` should run only for unsupported Web, +incomplete-readback, or writer-failure fallbacks. + +Done Checks: + +- Export route reports whether the pure writer was used or why fallback was + required. +- Tests cover pure-writer success and each fallback reason. +- Live bridge does not call retained equirectangular export after pure-writer + success. +- The debt log narrows retained equirectangular export execution. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_export|pp_paint_renderer_compositor|pano_cli_plan_export_snapshot_route|pano_cli_simulate_document_export" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### RND-002 - Make Pure Layer And Animation Collection Export Primary + +Status: Ready +Score: +2 renderer boundary and OpenGL parity +Debt: `DEBT-0010`, `DEBT-0036`, `DEBT-0043` +Scope: `src/legacy_document_export_services.*`, +`src/app_core/document_export.*`, `src/paint_renderer/compositor.*`, +collection export tests only + +Goal: + +For payload-complete snapshots, live layer and animation-frame collection export +should complete through the pure collection writer. Retained +`Canvas::export_layers*` and `Canvas::export_anim_frames*` should run only for +unsupported Web, incomplete-readback, or writer-failure fallbacks. + +Done Checks: + +- Collection export route reports pure-writer success versus fallback reason. +- Tests cover layer collection, animation-frame collection, and fallback. +- The debt log narrows retained collection export execution. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_export|pp_paint_renderer_compositor|pano_cli_plan_export_snapshot_route" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### RND-003 - Replace Depth Export Readiness With Pure Depth Export Execution + +Status: Ready +Score: +3 renderer boundary and OpenGL parity +Debt: `DEBT-0010`, `DEBT-0036`, `DEBT-0043` +Scope: `src/paint_renderer/compositor.*`, +`src/app_core/document_export.*`, `src/legacy_document_export_services.*`, +depth tests only + +Goal: + +Turn the current pure depth export render plan into actual payload generation +for payload-complete snapshots, then write image/depth payloads through the +existing app-core two-payload writer before falling back to retained +`Canvas::export_depth*`. + +Done Checks: + +- Pure depth export produces deterministic image and depth payloads for a + payload-complete snapshot. +- Retained depth export runs only for unsupported targets, incomplete readback, + or writer failure. +- Tests cover malformed depth target inputs and byte-size validation. +- The debt log narrows depth export readback/execution. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_export|pp_paint_renderer_compositor|pano_cli_plan_export_snapshot_route" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### RND-004 - Add First Desktop GPU Golden Gate + +Status: Ready +Score: +2 hardening and future backend readiness +Debt: `DEBT-0036` +Scope: `tests/`, `CMakeLists.txt`, renderer test helpers only + +Goal: + +Create the first non-default `desktop-gpu` golden/readback test that validates +one OpenGL output against a deterministic fixture. Keep it opt-in so headless +agents are not blocked. + +Done Checks: + +- `ctest --preset desktop-gpu --build-config Debug` has at least one real test. +- The test is skipped with a clear message when no GPU/context is available. +- The roadmap and debt log describe what the golden covers and what remains. + +Validation: + +```powershell +ctest --preset desktop-gpu --build-config Debug --output-on-failure +ctest --preset desktop-fast --build-config Debug -R "pp_renderer_gl|pp_paint_renderer" --output-on-failure +``` + +### PLT-001 - Split Apple Picker/Browse Service From Legacy Platform Adapter + +Status: Ready +Score: +2 platform and package parity +Debt: `DEBT-0017`, `DEBT-0051`, `DEBT-0055` +Scope: `src/platform_legacy/legacy_platform_services.*`, new +`src/platform_apple/*` files if needed, `CMakeLists.txt`, platform API tests + +Goal: + +Move macOS/iOS document browse roots, file picking, directory picking, and +display-path formatting out of the catch-all legacy platform adapter and into a +named Apple platform service boundary. + +Done Checks: + +- `src/platform_legacy/legacy_platform_services.*` no longer owns Apple + browse/picker policy. +- Apple compile validation still passes through the remote build script. +- The debt log narrows Apple platform shell extraction. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device +``` + +### PLT-002 - Split Web Export/Storage Policy From Legacy Platform Adapter + +Status: Ready +Score: +2 platform and package parity +Debt: `DEBT-0050`, `DEBT-0053`, `DEBT-0057` +Scope: `src/platform_legacy/legacy_platform_services.*`, new +`src/platform_web/*` files if needed, `src/platform_api/*`, platform tests + +Goal: + +Move WebGL exported-image publishing, persistent-storage flushing, +prepared-file handoff, and default canvas resolution out of the catch-all +legacy platform adapter into a named Web platform service boundary. + +Done Checks: + +- Web policy is injectable through `pp_platform_api`. +- The legacy adapter no longer owns Web default canvas resolution or storage + flush policy. +- Package-smoke readiness still reports Web blockers explicitly. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure +powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly +``` + +### DEP-001 - Remove Generated fmt Overlay + +Status: Ready +Score: +1 build and CMake ownership +Debt: `DEBT-0062` +Scope: `CMakeLists.txt`, `cmake/`, `vcpkg.json`, `libs/fmt` or package wiring + +Goal: + +Use a supported fmt package or update the vendored fmt release so VS 2026 no +longer needs a generated `format.h` overlay. + +Done Checks: + +- No build-tree fmt header overlay is generated. +- `DEBT-0062` is closed. +- Windows app and at least one focused component test build pass. + +Validation: + +```powershell +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pp_platform_api_tests +ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure +``` + +### DEP-002 - Remove Generated nanort Overlay + +Status: Ready +Score: +1 build and CMake ownership +Debt: `DEBT-0060` +Scope: retained Android package CMake, `libs/nanort`, grid/lightmap dependency +wiring + +Goal: + +Update, replace, or isolate `nanort` so Android package builds do not generate +a patched vendor overlay. + +Done Checks: + +- Android retained package CMake no longer generates a patched `nanort.h`. +- `DEBT-0060` is closed. +- Standard Android retained package validation passes. + +Validation: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter +``` + +## Blocked Or Later Queue + +These are real goals, but they should not be picked until prerequisite tasks +above have reduced risk. + +### LATER-001 - Replace OpenVR With OpenXR + +Status: Blocked +Score: +3 platform and package parity +Debt: `DEBT-0061` +Blocked By: OpenXR package decision and runtime availability + +Done Checks: + +- OpenXR SDK/package target exists. +- Windows platform service can start/stop desktop XR without OpenVR. +- `libs/openvr` and `openvr_api.dll` deployment are removed. +- `DEBT-0061` is closed. + +### LATER-002 - Remove Catch2 Harness Debt + +Status: Blocked +Score: +2 test and automation coverage +Debt: `DEBT-0005` +Blocked By: vcpkg/toolchain reliability across Windows and headless presets + +Done Checks: + +- Existing local test harness is replaced or permanently justified. +- Catch2 tests run through `desktop-fast` and vcpkg headless presets. +- `DEBT-0005` is closed. + +### LATER-003 - Live Stroke Rasterization Through Renderer Services + +Status: Blocked +Score: +5 renderer boundary and OpenGL parity +Debt: `DEBT-0036` +Blocked By: `RND-001`, `RND-002`, `RND-003`, and at least one GPU golden gate + +Done Checks: + +- Live stroke rasterization, dual-brush compositing, and pattern feedback choose + paths through renderer services. +- OpenGL output parity is covered by golden/readback tests. +- Retained stroke OpenGL execution is deleted or isolated as an OpenGL backend + implementation. + +### LATER-004 - Remove Catch-All Platform Legacy Adapter + +Status: Blocked +Score: +5 platform and package parity +Debt: `DEBT-0017` +Blocked By: Apple/Web split tasks and per-platform package validation + +Done Checks: + +- `src/platform_legacy/legacy_platform_services.*` is deleted or contains only + compile-time unsupported stubs with debt entries. +- Windows, Apple, Android, Linux, and Web platform services are named targets. +- Platform-build and package-smoke report explicit pass/fail per platform. + +## Completed Task Log + +| Date | Task | Score Change | Validation | Commit | +| --- | --- | ---: | --- | --- | +| 2026-06-12 | MT-001 | 0 | `git diff -- docs\modernization\roadmap.md docs\modernization\tasks.md` | same docs slice | + +## Task Template + +Use this shape when adding a new task: + +````markdown +### AREA-000 - Imperative Task Name + +Status: Ready +Score: +N scorecard area +Debt: `DEBT-0000` +Scope: exact files or directories + +Goal: + +One paragraph describing the behavior or ownership change. + +Done Checks: + +- Binary, grep-able, or testable condition. +- Debt log update condition. +- Validation condition. + +Validation: + +```powershell +command +``` +````