# 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. - When the user asks for subagents or delegation, follow `docs/modernization/director-workflow.md` and keep each delegated task mapped to a row in this tracker. ## 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 | 13 | 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 | 7 | `legacy_*_services` and singleton bridges are deleted or reduced to trivial composition. | | Renderer boundary and OpenGL parity | 15 | 10 | Live render/export/readback paths execute through renderer interfaces with parity checks. | | Platform and package parity | 10 | 6 | 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** | **53** | 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: Done 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: Done 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: Done 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: Done 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: Done 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: Done 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: Done 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: Done 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: Blocked 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: Done 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: Done 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: Done 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: Done 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 | DEP-002 | +1 build and CMake ownership | `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard` | 648404ee | | 2026-06-12 | RND-002 | +2 renderer boundary and OpenGL parity | `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` | 46fb8ef | | 2026-06-12 | RND-001 | +2 renderer boundary and OpenGL parity | `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` | 46fb8ef | | 2026-06-12 | ADP-004 | +2 legacy adapter retirement | VS-bundled CMake build of `pp_app_core_app_dialog_tests` and `pano_cli`; `ctest --preset desktop-fast --build-config Debug -R "pp_app_core_app_dialog\|pano_cli_plan_app_dialog" --output-on-failure` | 46fb8ef | | 2026-06-12 | PLT-001 | +2 platform and package parity | VS-bundled CMake build of `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure`; Apple remote build blocked by unpublished fmt submodule pointer before DEP-001 correction | 46fb8ef | | 2026-06-12 | RND-003 | +3 renderer boundary and OpenGL parity | VS-bundled CMake build of `pp_paint_renderer_compositor_tests`, `pp_app_core_document_export_tests`, and `pano_cli`; `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` | 46fb8ef | | 2026-06-12 | DEP-001 | +1 build and CMake ownership | VS-bundled CMake build of `PanoPainter` and `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure` | 46fb8ef | | 2026-06-12 | ADP-003 | +1 legacy adapter retirement | `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` | 34a9e910 | | 2026-06-12 | PLT-002 | +2 platform and package parity | `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`; `ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_layer\|pano_cli_plan_layer\|pp_platform_api_tests" --output-on-failure` | 8cd38401 | | 2026-06-12 | ADP-002 | +1 legacy adapter retirement | `ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_layer\|pano_cli_plan_layer" --output-on-failure`; `ctest --preset desktop-fast --build-config Debug -R "pp_app_core_document_layer\|pano_cli_plan_layer\|pp_platform_api_tests" --output-on-failure` | ae242852 | | 2026-06-12 | ADP-001 | +1 legacy adapter retirement | `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`; `powershell -ExecutionPolicy Bypass -File scripts\automation\quiet-validate.ps1 -BuildTargets PanoPainter,pano_cli -TestRegex "pp_app_core\|pano_cli_plan"` | e489b1e2 | | 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 ``` ````