diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 3bd31e1..7e37e99 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -1,7 +1,7 @@ # PanoPainter Modernization Roadmap Status: live -Last updated: 2026-06-13 +Last updated: 2026-06-14 This is the living roadmap for modernizing PanoPainter into independently testable C++23 components while retaining all existing functionality. Keep this @@ -62,6 +62,13 @@ 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. +The 2026-06-14 planning audit added measurable blockers for roadmap +finalization: component boundary self-tests (`ARCH-001`), renderer backend +contract freeze and conformance (`RND-007`, `RND-008`), opt-in Vulkan/Metal lab +targets (`RND-009`, `RND-010`), UI thread-affinity and checked-handle migration +(`UI-001`, `UI-002`), render/UI queue race coverage (`APP-001`), package gates +for backend/UI work (`PLT-010`), and historical task cleanup (`AUD-001`). + Recent 2026-06-13 retained preview reductions continue to narrow DEBT-0036: `NodeStrokePreview::draw_stroke_immediate()` now also routes feedback/material/composite planning and stroke-shader uniform assembly through @@ -1829,6 +1836,11 @@ Gate: Goal: prepare Vulkan and Metal without destabilizing the OpenGL parity path. +Status: not started. Do not start production Vulkan or Metal work until +`RND-007` and `RND-008` freeze and validate the renderer API backend contract. +`RND-009` and `RND-010` are opt-in lab targets only and must stay outside the +production app path. + Implementation tasks: - Create non-default targets only after OpenGL backend parity: diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index f69b15c..aa6a8e4 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -52,6 +52,30 @@ task id, points moved, validation command, and commit hash. | `Blocked` | Needs a user decision, missing toolchain, or a prior task. | | `Done` | Validated, documented, committed, and pushed. | +## Planning Audit - 2026-06-14 + +Current progress covers many retained stroke, draw-merge, export, platform, +and app-core planner seams, but it is not sufficient to declare the +modernization roadmap final. Missing coverage before Vulkan, Metal, and broad +UI rewrites: + +- Renderer contract freeze: `pp_renderer_api` needs an explicit backend + conformance contract before any Vulkan or Metal lab can be useful. +- Backend conformance automation: OpenGL and recording backends need the same + command/resource/readback/transition fixtures that future Vulkan/Metal + targets must pass. +- Backend lab scaffolds: Vulkan and Metal must be opt-in, non-production + targets with validation-layer or command-encoding smoke tests only. +- UI safety: retained `Node` migration needs thread-affinity, checked handles, + scoped callbacks, and mutation-safe dispatch gates, not only one popup family. +- Threading safety: render/UI queue behavior needs race/regression tests around + cancellation, shutdown, nested dispatch, and cross-thread misuse. +- Platform gates: Apple/Linux/WebGL/AppX package readiness must be part of the + backend/UI gate because renderer and UI boundaries are platform-sensitive. +- Task hygiene: duplicate historical IDs and stale pending closeouts remain in + this tracker; new agents must treat `AUD-001` as documentation cleanup before + using historical score rows for accounting. + ## Ready Queue ### MT-001 - Adopt Measurable Task Tracking @@ -2441,6 +2465,334 @@ Validation: ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_stroke_execution|pp_paint_renderer_compositor" --output-on-failure ``` +### AUD-001 - Normalize Historical Task Tracker Duplicates + +Status: Ready +Score: no score movement +Debt: none +Scope: `docs/modernization/tasks.md` + +Goal: + +Clean the historical tracker rows that make current progress hard to audit +without changing code: duplicate `STR-010`, duplicate/ambiguous `STR-016`, +duplicate `STR-030`, malformed `RND-006` completed-task table shape, and stale +`pending` closeout rows. + +Done Checks: + +- Each historical task id has one active section or one clearly marked + historical alias note. +- No completed-task row has `pending` as a commit. +- Completed-task tables use a consistent Date/Task/Score/Validation/Commit + shape. +- The scorecard total is not changed unless backed by already committed rows. + +Validation: + +```powershell +rg -n "pending|### STR-010|### STR-016|### STR-030|RND-006" docs\modernization\tasks.md +git diff -- docs\modernization\tasks.md +``` + +### ARCH-001 - Add Component Boundary Dependency Self-Test + +Status: Ready +Score: +2 pure component behavior ownership +Debt: `DEBT-0003`, `DEBT-0008` +Scope: `scripts/dev/`, `tests/CMakeLists.txt`, root `CMakeLists.txt`, +`docs/modernization/build-inventory.md` + +Goal: + +Add an automated boundary check that fails when pure component headers or +targets include platform SDK headers, OpenGL headers, retained `App::I`/ +`Canvas::I` singletons, or backend-specific types outside allowed +`pp_renderer_gl` and `pp_platform_*` targets. + +Done Checks: + +- The check encodes allowed dependency direction for `pp_foundation`, + `pp_assets`, `pp_paint`, `pp_document`, `pp_renderer_api`, + `pp_paint_renderer`, `pp_ui_core`, `pp_app_core`, and platform/backend + targets. +- The check reports exact offending file, include, or target edge. +- Existing known legacy exceptions are explicit allowlist entries with debt ids. +- CTest registers the check under `desktop-fast`. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "panopainter_component_boundary" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### RND-007 - Freeze Renderer API Backend Contract + +Status: Ready +Score: +2 renderer boundary and OpenGL parity +Debt: `DEBT-0036`, `DEBT-0064` +Scope: `src/renderer_api/*`, `src/renderer_gl/*`, +`src/paint_renderer/*`, `tests/renderer_api/*`, +`tests/renderer_gl/*`, `tests/paint_renderer/*` + +Goal: + +Define the minimum renderer contract that OpenGL, Vulkan, and Metal must share: +resource descriptors, lifetime rules, texture upload/readback, render-target +attachment, copy/blit semantics, viewport/scissor state, shader/program +binding, feature flags, frame capture, debug labels, and error/status returns. + +Done Checks: + +- `pp_renderer_api` documents and tests the backend-neutral contract without GL, + Vulkan, Metal, platform SDK, or window headers. +- `pp_renderer_gl` passes the same contract expectations through focused + backend tests or command-plan tests. +- `pp_paint_renderer` chooses only renderer-api feature/path data; it does not + branch on OpenGL-specific symbols. +- `DEBT-0064` has a removal path tied to a callback-only or renderer-owned + texture seam. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_renderer_api|pp_renderer_gl|pp_paint_renderer" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### RND-008 - Add Backend Conformance Test Matrix + +Status: Ready +Score: +2 hardening and future backend readiness +Debt: `DEBT-0036` +Depends: `RND-007` +Scope: `tests/renderer_api/`, `tests/renderer_gl/`, `tests/CMakeLists.txt`, +`CMakePresets.json`, `docs/modernization/build-inventory.md` + +Goal: + +Create reusable backend conformance fixtures that every renderer backend must +pass before it can be considered for production: command recording order, +resource creation failures, texture state transitions, copy/blit bounds, +readback byte size, framebuffer feedback path selection, and deterministic +golden/readback samples. + +Done Checks: + +- Recording backend and OpenGL backend run equivalent conformance cases where + possible. +- Backend-specific skips are explicit and tied to feature flags, not target + names. +- `desktop-fast` covers headless contract cases; `desktop-gpu` covers real GL + readback/golden cases. +- Future Vulkan/Metal lab targets can register the same fixture family without + changing paint-renderer tests. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_renderer_api|pp_renderer_gl|pp_paint_renderer" --output-on-failure +ctest --preset desktop-gpu --build-config Debug --output-on-failure +``` + +### RND-009 - Scaffold Opt-In Vulkan Lab Backend + +Status: Blocked +Score: +2 hardening and future backend readiness +Debt: none +Depends: `RND-007`, `RND-008` +Blocked By: Vulkan SDK/package decision, validation-layer availability, and +OpenGL conformance baseline stability. +Scope: `src/renderer_vulkan_lab/*`, root `CMakeLists.txt`, +`tests/renderer_vulkan_lab/*`, `docs/modernization/build-inventory.md` + +Goal: + +Add a non-default `pp_renderer_vulkan_lab` target that proves the renderer-api +contract can map to Vulkan command buffers, resource lifetimes, layout +transitions, and ping-pong compositing without entering the production app path. + +Done Checks: + +- Target is opt-in and never linked by `PanoPainter`. +- Smoke tests create/destroy a device, allocate a tiny render target, execute a + clear/copy/readback path where local Vulkan support exists, and skip cleanly + when unavailable. +- Validation-layer failures fail the lab test. +- No production OpenGL behavior changes. + +Validation: + +```powershell +cmake --build --preset windows-msvc-default --config Debug --target pp_renderer_vulkan_lab_tests +ctest --preset desktop-gpu --build-config Debug -R "pp_renderer_vulkan_lab" --output-on-failure +``` + +### RND-010 - Scaffold Opt-In Metal Lab Backend + +Status: Blocked +Score: +2 hardening and future backend readiness +Debt: `DEBT-0059` +Depends: `RND-007`, `RND-008` +Blocked By: Apple root package/app gate, signed bundle policy, and Mac mini +toolchain validation. +Scope: `src/renderer_metal_lab/*`, root `CMakeLists.txt`, +`tests/renderer_metal_lab/*`, `scripts/automation/apple-remote-build.ps1`, +`docs/modernization/build-inventory.md` + +Goal: + +Add a non-default `pp_renderer_metal_lab` target that proves the renderer-api +contract can map to Metal command encoders, textures, render passes, and +readback without entering the production app path. + +Done Checks: + +- Target is opt-in and excluded from production app/package builds. +- Apple remote validation can build the target on macOS and skip iOS device + execution unless a signed runner exists. +- Smoke tests cover tiny texture/render-pass/copy-readback behavior where a + headless Metal device is available. +- No OpenGL or Apple production package behavior changes. + +Validation: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos -Targets pp_renderer_metal_lab_tests +``` + +### UI-001 - Define UI Thread-Affinity And Mutation Contract + +Status: Ready +Score: +2 hardening and future backend readiness +Debt: `DEBT-0003`, `DEBT-0063` +Scope: `src/ui_core/*`, `src/app_core/app_thread.*`, +`tests/ui_core/*`, `tests/app_core/app_thread_tests.cpp`, +`tools/pano_cli/*` + +Goal: + +Make UI safety explicit before broad retained UI migration: define which +operations are UI-thread-only, which may be posted from render/worker threads, +how checked node handles invalidate, how callbacks disconnect, and how layout +reload/destroy-during-callback mutations are sequenced. + +Done Checks: + +- `pp_ui_core` exposes a documented thread-affinity/mutation contract. +- Tests cover checked-handle invalidation, scoped callback disconnect, + destroy-during-callback, add/remove-during-dispatch, capture release, and + layout reload clear. +- `pp_app_core` app-thread plans reject or route unsafe cross-thread UI + mutations. +- `pano_cli plan-app-thread` exposes at least one unsafe-dispatch rejection + smoke. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_ui_core_(node_lifetime|overlay_lifetime)|pp_app_core_app_thread|pano_cli_plan_app_thread" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter pano_cli +``` + +### UI-002 - Migrate Next Retained Panel Family To Checked UI Handles + +Status: Ready +Score: +2 legacy adapter retirement +Debt: `DEBT-0063` +Depends: `UI-001` +Scope: choose one family from `src/node_panel_layer.cpp`, +`src/node_panel_brush.cpp`, `src/node_panel_stroke.cpp`, +`src/node_dialog_open.cpp`, or `src/node_dialog_browse.cpp`, plus +`src/legacy_ui_overlay_services.*` and focused tests. + +Goal: + +Move one more retained UI family from raw `Node*`/manual destroy/callback +ownership to the checked-handle and scoped-callback model, preserving current +behavior while proving the migration pattern is repeatable. + +Done Checks: + +- Chosen family no longer uses open-coded root insertion, close callback + lifetime, outside-click release, or stale raw child pointers where a checked + handle/service exists. +- Mutation-during-callback and close/release tests cover the chosen family. +- `DEBT-0063` names the migrated family and the remaining families. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_ui_core_(node_lifetime|overlay_lifetime)" --output-on-failure +cmake --build --preset windows-msvc-default --config Debug --target PanoPainter +``` + +### APP-001 - Add Render/UI Queue Race Regression Gate + +Status: Ready +Score: +2 test and automation coverage +Debt: `DEBT-0003`, `DEBT-0017` +Depends: `UI-001` +Scope: `src/foundation/*`, `src/app_core/app_thread.*`, +`tests/foundation/*`, `tests/app_core/app_thread_tests.cpp`, +`tools/pano_cli/*` + +Goal: + +Add deterministic stress/regression coverage for render/UI task queues before +threading behavior is relied on by backend labs or safer UI adapters. + +Done Checks: + +- Tests cover nested dispatch, unique task replacement, shutdown drain, + cancellation/no-op after stop, exception-free error reporting, and worker to + UI/render handoff ordering. +- `stress` preset includes the longer queue scenario while `desktop-fast` + keeps a small deterministic subset. +- `pano_cli plan-app-thread` exposes queue scenarios as JSON smoke commands. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_foundation_task_queue|pp_app_core_app_thread|pano_cli_plan_app_thread" --output-on-failure +ctest --preset stress --build-config Debug -R "app_thread|task_queue" --output-on-failure +``` + +### PLT-010 - Gate Backend And UI Work On Platform Package Readiness + +Status: Ready +Score: +2 platform and package parity +Debt: `DEBT-0004`, `DEBT-0011`, `DEBT-0059` +Scope: `scripts/automation/package-smoke.*`, +`scripts/automation/platform-build.*`, root `CMakeLists.txt`, +`docs/modernization/build-inventory.md` + +Goal: + +Make backend/UI modernization platform-sensitive by requiring named package or +package-readiness gates for Windows AppX, Apple bundles, Android standard, +Quest, Focus/Wave, Linux, and WebGL before backend lab or retained UI migration +work can claim broad readiness. + +Done Checks: + +- Package-readiness output identifies which backend/UI-sensitive platforms are + validated, blocked, or compile-only. +- Root CMake exposes a named target or documented command for each required + platform gate. +- Apple/iOS signed-bundle gaps and Windows AppX gaps remain debt-tracked until + real package builds exist. +- `docs/modernization/build-inventory.md` lists the commands as the current + gate for backend/UI roadmap work. + +Validation: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly +ctest --preset desktop-fast --build-config Debug -R "panopainter_package_smoke_readiness_self_test|panopainter_platform_build_target_matrix_self_test" --output-on-failure +``` + ### STR-010 - Extract Remaining Draw Merge Composite Orchestration ### STR-016 - Extract Draw Merge Layer Composite Execution