Add renderer and package readiness validation gates
This commit is contained in:
@@ -203,18 +203,42 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.p
|
||||
target before reporting the same readiness matrix. `package-smoke.ps1
|
||||
-AndroidNativeChecks` also runs the retained Android standard `native-lib`
|
||||
build and Quest/Focus configure helper for selected Android package kinds,
|
||||
then reports those native results beside the APK blocker matrix.
|
||||
then reports those native results beside the APK readiness matrix. Both
|
||||
wrappers now classify each platform gate as `validated`, `compile-only`, or
|
||||
`blocked` based on local prerequisites and whether a real root CMake package
|
||||
target exists.
|
||||
`scripts/dev/check_package_smoke_readiness.py`, registered as
|
||||
`panopainter_package_smoke_readiness_self_test`, verifies both wrappers keep
|
||||
the same seven package kinds, blocked DEBT-0011 status, readiness-only mode,
|
||||
the same seven package kinds, readiness status modes, readiness-only mode,
|
||||
retained Android native-check prerequisite metadata, retained Linux/WebGL
|
||||
CMake baseline metadata, and root CMake package validation target names.
|
||||
- `scripts/dev/check_component_boundaries.py`, registered as
|
||||
`panopainter_component_boundary_self_test`, checks pure component source files in
|
||||
`pp_foundation`, `pp_assets`, `pp_paint`, `pp_document`, `pp_renderer_api`,
|
||||
`pp_paint_renderer`, `pp_ui_core`, and `pp_app_core` for forbidden platform
|
||||
SDK/backend includes, `App::I`/`Canvas::I` leakage, and disallowed `pp_*`
|
||||
target dependencies before desktop-fast validation. Temporary allowed-platform
|
||||
edges remain explicitly tracked by DEBT-0003 and DEBT-0008.
|
||||
- `scripts/dev/check_renderer_conformance_matrix.py`, registered as
|
||||
`panopainter_renderer_conformance_matrix_self_test`, verifies renderer conformance
|
||||
tests are labeled with the shared `renderer-conformance` matrix profile.
|
||||
- `scripts/dev/check_renderer_api_contract.py`, registered as
|
||||
`panopainter_renderer_api_contract_self_test`, enforces backend-neutral boundary
|
||||
rules for `pp_renderer_api` and `pp_paint_renderer`, including forbidden
|
||||
backend symbols/includes in these components before renderer contract milestones.
|
||||
- Root CMake exposes non-default package validation targets:
|
||||
`panopainter_package_readiness`,
|
||||
`panopainter_windows_app_package_smoke`,
|
||||
`panopainter_windows_appx_package_readiness`,
|
||||
`panopainter_apple_bundle_package_readiness`,
|
||||
`panopainter_android_standard_native_package`,
|
||||
`panopainter_android_standard_apk_package_readiness`,
|
||||
`panopainter_android_quest_apk_package_readiness`,
|
||||
`panopainter_android_focus_apk_package_readiness`,
|
||||
`panopainter_android_vr_native_package_configure`, and
|
||||
`panopainter_android_native_package_smoke`, and
|
||||
`panopainter_linux_app_package_readiness`,
|
||||
`panopainter_webgl_package_readiness`, and
|
||||
`panopainter_linux_webgl_package_readiness`. These targets call the
|
||||
automation scripts from CMake but do not convert APK/AppX/Linux/Apple/WebGL
|
||||
package outputs to root CMake package targets yet.
|
||||
|
||||
@@ -22,12 +22,51 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
routes the retained pre-dispatch state capture through local commit helpers;
|
||||
the live path still owns concrete layer/action mutation until the retained
|
||||
commit adapter is fully split from `Canvas`.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. Open/Browse
|
||||
delete-confirmation now uses handle-based open/close in
|
||||
`src/node_dialog_open.cpp` and `src/node_dialog_browse.cpp`, with
|
||||
`attach_legacy_overlay_node_to_root` fallback removed; migration still pending in
|
||||
remaining panel families.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_combobox.cpp` now uses
|
||||
overlay handle open/close (`open_legacy_overlay_node_with_handle` and
|
||||
`close_legacy_overlay_node`) for popup lifecycle, with the older attach/close
|
||||
overlay path removed in this file.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_panel_stroke.cpp` now
|
||||
routes the stroke preset/brush/dual-brush/pattern popup open-close flow through
|
||||
checked overlay handles and explicit partial-open cleanup; migration is still
|
||||
pending in remaining panel families.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_panel_brush.cpp` now
|
||||
routes brush popup-menu open-close flow through checked overlay handles and
|
||||
handle-based close on selection.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/legacy_quick_ui_services.cpp`
|
||||
now converts quick brush/color popup lifecycle from raw attach+bind-destroy to
|
||||
checked-overlay open/close (`open_legacy_overlay_node_with_handle` and
|
||||
`close_legacy_overlay_node`) with explicit handle invalidation on closure.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_popup_menu.h/.cpp`
|
||||
now routes popup-menu close through checked overlay handles and removes direct
|
||||
`close_legacy_popup_overlay(*this)` usage.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_panel_layer.h/.cpp` now
|
||||
uses shared ownership for current-layer/m_layers tracking, guards stale-layer
|
||||
callback/mutation paths, and routes popup outside-click close through
|
||||
`close_legacy_popup_panel`; migration remains open in other panel/dialog
|
||||
families.
|
||||
- 2026-06-14: `DEBT-0063` was narrowed again. `src/node_dialog_picker.cpp` now
|
||||
inlines outside-click/autohide popup close through capture release, parent
|
||||
detach, and guarded `on_popup_close` dispatch instead of routing that path
|
||||
through `close_legacy_popup_panel(*this, on_popup_close)`.
|
||||
- 2026-06-14: `DEBT-0036` was narrowed again. `Canvas::stroke_draw()` now
|
||||
routes the retained main-pass request assembly through helper APIs and keeps
|
||||
the live callsite focused on branch selection and pass dispatch.
|
||||
- 2026-06-14: `DEBT-0064` was opened for the compositor test-local
|
||||
`Texture2D::bind()` shim needed while planner tests exercise retained inline
|
||||
preview helpers before tests can link a non-app legacy texture boundary.
|
||||
- 2026-06-14: `DEBT-0036` was narrowed again. `Canvas::stroke_draw()` now
|
||||
routes the main-pass destination texture binding declaration through
|
||||
`Canvas::make_stroke_draw_main_pass_request`; `Canvas::stroke_draw()` now only
|
||||
assembles execution inputs and dispatches the retained main-pass callback chain.
|
||||
- 2026-06-14: `DEBT-0064` was narrowed again. Stroke-preview result copy now
|
||||
routes through `pp::paint_renderer::copy_stroke_preview_result_to_texture(...)`
|
||||
in `src/paint_renderer/compositor.h`, and the node-level copy wrapper,
|
||||
final-composite wrapper, and pass-sequence wrapper are gone. The compositor
|
||||
test-local `Texture2D::bind()` shim is also gone, while live preview still
|
||||
owns concrete texture binding and remaining OpenGL copy execution.
|
||||
- 2026-06-14: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()` now
|
||||
routes the retained request-dispatch invocation through
|
||||
`execute_canvas_stroke_commit_dispatch(...)`; the wrapper still owns the
|
||||
@@ -1216,6 +1255,12 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
`panopainter_windows_app_package_smoke`, which calls the full Windows
|
||||
`package-smoke` command from CMake so the app executable/runtime payload check
|
||||
and Windows AppX blocker matrix are available from the CMake target graph.
|
||||
- 2026-06-14: DEBT-0011 was narrowed again. `package-smoke.ps1` and
|
||||
`package-smoke.sh` now classify package readiness as `validated`,
|
||||
`compile-only`, or `blocked` instead of reporting every platform gate as
|
||||
blocked, and root CMake now exposes per-platform readiness targets for
|
||||
Windows AppX, Apple bundles, Android standard/Quest/Focus APKs, Linux app,
|
||||
and WebGL while real package outputs remain debt-tracked.
|
||||
- 2026-06-05: DEBT-0007 was narrowed. `platform-build.ps1` now resolves
|
||||
`VCPKG_ROOT` for vcpkg presets from the environment or bundled Visual Studio
|
||||
installs, reports the selected vcpkg root in JSON, and root CMake exposes
|
||||
@@ -1726,7 +1771,7 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
| DEBT-0008 | Open | Modernization | `windows-msvc-default` and `windows-msvc-vcpkg-headless` explicitly select Visual Studio 18 2026 for local validation, but non-VS2026 CMake executables on PATH may not know that generator | The local machine has VS 2026, but using an older CMake can still default to Ninja or reject the VS 2026 generator | `cmake --preset windows-msvc-default`; `cmake --build --preset windows-msvc-default --config Debug --target PanoPainter`; `ctest --preset desktop-fast --build-config Debug` | The repo automation invokes or locates a CMake executable that supports `Visual Studio 18 2026`, and VS 2026 generator validation is the normal Windows path without manual tool selection |
|
||||
| DEBT-0009 | Open | Modernization | Android root CMake validation currently builds headless targets only, while retained standard/Quest/Focus package CMake paths now have a refreshed CMake 3.10/C++23 baseline outside root CMake; automation queries `sdkmanager`, installs newer or missing SDK Manager NDK/CMake packages, selects the resulting pair before configure, and reports update decisions; root CMake exposes non-default platform-build and retained native package validation targets | Platform app entrypoints still live in legacy Gradle/CMake projects and need Phase 6 alignment | `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64`; `cmake --build --preset android-x64`; `cmake --build --preset android-quest-arm64`; `cmake --build --preset android-focus-arm64`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_platform_build_android_assets`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages quest,focus -ConfigureOnly`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke` | Android standard, Quest, and Focus/Wave package targets consume shared component targets and have package smoke commands |
|
||||
| DEBT-0010 | Open | Modernization | `pp_document` is a pure layer/frame/document/undo-history model with alpha-lock metadata, snapshot construction, per-layer frame metadata, renderer-free RGBA8 face payload storage, snapshot-embedded face-payload validation, renderer-free alpha8 selection-mask storage, PPI import/export helpers, stroke-script-to-face-payload CLI automation, `pp_paint_renderer` document face/frame compositors, renderer-neutral six-face texture upload, pure six-face PNG export, pure equirectangular PNG export, pure equirectangular JPEG+XMP export, pure layer/animation-frame PNG collection export, pure depth image/depth PNG export for payload-complete snapshots, shared document-frame export readiness reporting, depth export render-plan reporting, OpenGL command-planner validation through CLI render automation, live Canvas snapshot projection through `pp_app_core`/`legacy_document_canvas_services`, captured RGBA8 payload attachment to `pp_document`, live Save/Save As/Save Version/save-before-workflow snapshot-readiness reporting before retained save execution, pure app-core PPI export for payload-complete canvas snapshots, payload-complete canvas-snapshot renderer-upload plus face-PNG export automation, live cube-face face-PNG writer execution using app-core face target planning and write/publish service dispatch with retained fallback, live PNG/JPEG equirectangular writer execution using the paint-renderer equirectangular exports plus app-core file write/publish dispatch with retained fallback, live payload-complete layer/animation-frame collection writer execution using paint-renderer PNG sequences and app-core collection write/publish dispatch with retained fallback, live payload-complete depth export execution using pure paint-renderer PNG payloads plus app-core two-payload writing with retained fallback, tested app-core document-snapshot export route policy for writer versus retained fallback including current-platform support, and live equirectangular/layer/animation-frame/depth/cube-face export snapshot/render/export-readiness reporting through the shared readiness helper plus the depth render plan, but action-command adoption, live save-writer replacement, Web and incomplete-readback collection handoff, progress/threading parity, broader renderer-owned export execution, exact GPU/golden parity, live-camera depth parity, and renderer-owned cube-face readback ownership are not yet wired | Keep extraction incremental while preserving app behavior | `ctest --preset desktop-fast --build-config Debug`; `pano_cli create-document --width 64 --height 32 --layers 2`; `pano_cli load-project --path tests\data\projects\minimal-project.ppi`; `pano_cli simulate-document-render --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --width 64 --height 32`; `pano_cli plan-canvas-document-snapshot --captured-face-payloads-per-layer 1`; `pano_cli plan-export-snapshot-route --kind layers-collection --captured-face-payloads 3 --pending-face-payloads 6`; `pp_document_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pp_paint_renderer_compositor_tests`; `pp_app_core_document_canvas_tests`; `pp_app_core_document_export_tests`; `pano_cli_simulate_document_edits_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_simulate_document_render_smoke`; `pano_cli_plan_canvas_document_snapshot_smoke`; `pano_cli_plan_canvas_document_snapshot_payload_smoke`; `pano_cli_plan_export_snapshot_route_pending_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Legacy document behavior is represented by `pp_document`/`pp_paint_renderer` tests and the app consumes it through a boundary/facade |
|
||||
| DEBT-0011 | Open | Modernization | `package-smoke` validates the Windows CMake app artifact and launch-folder DLL payload, and reports a structured package readiness matrix for Windows AppX, Android standard/Quest/Focus APKs, Apple bundles, Linux app output, and WebGL output; the Windows app smoke passes the configure-time CMake executable so VS 2026 generator validation does not depend on `cmake` from PATH, retained Android package native CMake paths, and retained Linux/WebGL CMake baseline metadata are reachable from package validation and root CMake package-readiness targets, but Windows AppX/APK/Linux/Apple/WebGL package outputs are still `blocked` because root CMake package targets do not exist yet | Platform package targets are not migrated to root CMake yet | `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_app_package_smoke`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_linux_webgl_package_readiness`; `python scripts/dev/check_package_smoke_readiness.py`; `bash -n scripts/automation/package-smoke.sh` | Package-smoke builds and validates Windows AppX, Android APK variants, Linux app, Apple bundles, and WebGL output where local toolchains are present |
|
||||
| DEBT-0011 | Open | Modernization | `package-smoke` validates the Windows CMake app artifact and launch-folder DLL payload, reports a structured package readiness matrix for Windows AppX, Android standard/Quest/Focus APKs, Apple bundles, Linux app output, and WebGL output, and now classifies each package gate as `validated`, `compile-only`, or `blocked` based on local prerequisites plus root CMake package-target ownership; the Windows app smoke passes the configure-time CMake executable so VS 2026 generator validation does not depend on `cmake` from PATH, retained Android package native CMake paths, retained Linux/WebGL CMake baseline metadata, and per-platform readiness targets are reachable from package validation and root CMake package-readiness targets, but Windows AppX and Apple/WebGL outputs remain blocked where local toolchains or root package targets are missing and Android/Linux package readiness remains compile-only until root CMake owns real package targets | Platform package targets are not migrated to root CMake yet | `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_app_package_smoke`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_windows_appx_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_apple_bundle_package_readiness`; `powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly -AndroidNativeChecks -PackageKinds android-standard-apk,android-quest-apk,android-focus-apk`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_standard_apk_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_quest_apk_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_focus_apk_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_android_native_package_smoke`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_linux_app_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_webgl_package_readiness`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_linux_webgl_package_readiness`; `python scripts/dev/check_package_smoke_readiness.py`; `bash -n scripts/automation/package-smoke.sh` | Package-smoke builds and validates Windows AppX, Android APK variants, Linux app, Apple bundles, and WebGL output where local toolchains are present |
|
||||
| DEBT-0012 | Open | Modernization | `pp_ui_core` uses vcpkg tinyxml2 on `windows-msvc-vcpkg-headless`, but retains `pp_vendor_tinyxml2` for default and unproven platform presets | Mobile/AppX/Apple triplets and app packaging still need validation before removing the vendored fallback | `ctest --preset desktop-fast-vcpkg --build-config Debug`; `ctest --preset desktop-fast --build-config Debug`; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64` | All supported presets consume vcpkg tinyxml2 or document a permanent vendored exception |
|
||||
| DEBT-0013 | Open | Modernization | `pp_assets`, `pp_document`, `pano_cli inspect-project`, `pano_cli load-project`, and `pano_cli save-project` validate the fixed PPI header, thumbnail/body byte layout, generated multi-layer/multi-frame PPI writing with explicit layer opacity/blend/alpha-lock/visibility metadata, per-layer frame durations, metadata-only and targeted dirty-face-payload save/load round-trips, layer/frame index, dirty-face descriptors, dirty-face PNG payload metadata, asset-level RGBA PNG payload decoding, pure document-to-PPI export, CLI document export automation, file-writing document export automation, stroke-script-generated document payload export, decoded pixel attachment to `pp_document`, live save-path snapshot-readiness reporting, and app-core canvas-snapshot-to-PPI export automation, but full legacy PPI round-trip parity and pure live save writer replacement are not yet extracted | Full PPI save parity requires staged extraction of legacy `Canvas` serialization and image/layer payload handling | `ctest --preset desktop-fast --build-config Debug`; `pp_assets_image_pixels_tests`; `pp_assets_ppi_header_tests`; `pp_document_ppi_import_tests`; `pp_document_ppi_export_tests`; `pano_cli_inspect_project_layout_smoke`; `pano_cli_load_project_metadata_smoke`; `pano_cli_save_project_roundtrip_smoke`; `pano_cli_save_project_payload_roundtrip_smoke`; `pano_cli_simulate_document_export_smoke`; `pano_cli_save_document_project_roundtrip_smoke`; `pano_cli_apply_stroke_script_roundtrip_smoke`; `pano_cli_apply_stroke_script_rejects_tiny_canvas` | Full PPI load/save fixtures cover thumbnails, decoded layer face payloads attached to documents, frames, corrupt payloads, dirty-face payload saving, arbitrary legacy canvas payload/layout combinations, and legacy app round-trip compatibility |
|
||||
| DEBT-0014 | Open | Modernization | `windows-clangcl-asan` now configures as a headless Ninja/clang-cl preset and uses the release MSVC runtime required by ASan, but local builds still fail because installed clang-cl 18.1.8 is paired with VS 2026-preview STL headers that require Clang 20 or newer | Sanitizer validation should be local and repeatable, but this machine's compiler/header pairing is incompatible | `cmake --fresh --preset windows-clangcl-asan`; `cmake --build --preset windows-clangcl-asan --target pp_foundation` | Install/use Clang 20+ with the VS 2026 STL, or point the preset at a compatible VS 2022 toolchain, then make `platform-build.ps1 -Presets windows-clangcl-asan` pass for the headless matrix |
|
||||
@@ -1772,11 +1817,11 @@ agent or engineer to remove them without reconstructing context from chat.
|
||||
| DEBT-0055 | Open | Modernization | `src/app.h` now forward-declares retained iOS/macOS/Android/Linux/Web platform handles instead of including platform SDK headers, and full SDK includes are isolated in `src/platform_legacy/legacy_platform_services.cpp`, but the `App` singleton still stores those platform handles directly | Reduce central header platform coupling incrementally without rewriting non-Windows platform entrypoints before Phase 6 | Windows app build; Apple/Android/Linux/Web package smoke once platform root builds are active | Platform handles are owned by injected `pp_platform_*` shell state or services, and `App` has no platform SDK handle fields or platform conditional members |
|
||||
| DEBT-0056 | Open | Modernization | `src/asset.h` is now Android-SDK-free and uses opaque Android asset handles behind `Asset::set_android_asset_manager`, but retained `Asset` still owns a static Android asset-manager bridge and `src/asset.cpp` still performs Android `AAssetManager` reads directly; the current `android-arm64` root preset is headless and does not expose `pp_legacy_assets_io`, though the retained Android standard package `native-lib` now builds through its refreshed C++23 CMake path | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64 -Targets pp_assets`; `powershell -ExecutionPolicy Bypass -File scripts\automation\android-legacy-package-build.ps1 -Packages standard` | Android asset loading is owned by injected asset storage/platform services or `pp_assets` file providers, with no static Android asset manager on `Asset` |
|
||||
| DEBT-0061 | Open | Modernization | Desktop XR runtime selection now lives in tested `pp_platform_api` policy and prefers OpenXR, but `WindowsPlatformServices` still reports OpenXR unavailable and reaches the retained OpenVR SDK bridge as a legacy fallback; Windows runtime deployment copies `openvr_api.dll` beside `PanoPainter.exe` until that fallback is removed | Preserve current desktop VR behavior while replacing OpenVR with OpenXR behind the platform/renderer boundary | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests --output-on-failure`; `cmake --build --preset windows-msvc-default --config Debug --target PanoPainter` | Add an OpenXR SDK/package target, implement desktop OpenXR startup/shutdown/pose/controller submission behind `pp_platform_vr` or `PlatformServices`, validate parity with mocked/runtime smoke coverage, and remove `libs/openvr` plus the OpenVR link/include paths from root CMake |
|
||||
| DEBT-0063 | Open | Modernization | The retained UI tree still exposes `Node* m_parent`, public `std::vector<std::shared_ptr<Node>> m_children`, raw `find<T>()` lookup results, `add_child<T>()` allocation through `new`, callbacks/observers that take or capture raw `Node*`, and manual `destroy()`/`m_destroyed` semantics. `pp_ui_core` now owns a tested `NodeLifetimeTree` target model with checked node handles, scoped callback connections, subtree destruction, pointer/keyboard capture release, whole-tree clear for layout reload, and mutation-safe dispatch, plus a tested `UiOverlayLifetime` popup/dialog stack model. Retained app-dialog root insertion, app-menu popup template cloning/root attachment, quick/stroke/brush panel popup root attachment, combo-box popup insertion, Open/Browse delete-confirmation dialog insertion, popup tick decoration insertion, top-toolbar panel popup insertion, repeated retained popup activation flag setup, repeated retained popup close/release execution, popup tick-decoration close callback wiring, and popup-panel outside-click release/remove/callback dispatch are now centralized in `src/legacy_ui_overlay_services.*`, but retained `Node`/`NodePopupMenu`/`NodeDialog*` still have not adopted checked handles or scoped callback ownership | Preserve current UI behavior while making panel/dialog extraction safe instead of spreading lifetime hazards into the new architecture | `pp_ui_core_layout_xml_tests`; `pp_ui_core_node_lifetime_tests`; `pp_ui_core_overlay_lifetime_tests`; future `pp_panopainter_ui_dialog_lifetime_tests`; `ctest --preset desktop-fast --build-config Debug`; `cmake --build --preset windows-msvc-default --config Debug --target PanoPainter` | Retained `Node` and `pp_panopainter_ui` adopt checked node handles or equivalent non-owning references, scoped callback connection/disconnect semantics, mutation-safe event dispatch, parent/child invariants hidden behind APIs, and destroy-during-callback/capture-release/popup-close/layout-reload tests; retained `Node*` APIs are removed or isolated behind compatibility adapters |
|
||||
| DEBT-0063 | Open | Modernization | `pp_ui_core` now owns tested `NodeLifetimeTree` and `UiOverlayLifetime` models for checked handles, scoped callback connections, subtree destruction, capture release, and mutation-safe dispatch. `src/node_panel_layer.h/.cpp`, `src/node_combobox.cpp`, `src/node_dialog_open.cpp`, `src/node_dialog_browse.cpp`, `src/node_panel_stroke.cpp`, `src/node_panel_brush.cpp`, `src/node_dialog_picker.cpp`, `src/legacy_quick_ui_services.cpp`, and `src/node_popup_menu.h/.cpp` now route popup/dialog/menu lifetime through checked overlay handles and handle-based close; migration remains open in other legacy panel/dialog families | Preserve current UI behavior while completing safe panel/dialog lifetime migration incrementally | `pp_ui_core_layout_xml_tests`; `pp_ui_core_node_lifetime_tests`; `pp_ui_core_overlay_lifetime_tests`; `tests/ui_core/node_lifetime_tests.cpp:destroy_subtree_clears_child_connections`; `tests/ui_core/overlay_lifetime_tests.cpp:double_close_overlay_returns_invalid_argument`; `ctest --preset desktop-fast --build-config Debug`; `cmake --build --preset windows-msvc-default --config Debug --target panopainter_app pp_ui_core_node_lifetime_tests pp_ui_core_overlay_lifetime_tests` | Remaining legacy popup/dialog families still use non-handle ownership and open lifetimes; migration stays open until their surfaces are converted, including lifecycle safety parity checks |
|
||||
| DEBT-0057 | Open | Modernization | Default canvas allocation size now dispatches through `PlatformServices::default_canvas_resolution`, removing the `CANVAS_RES` platform macro from `src/canvas.h`; WebGL's retained 512 default now lives in tested `pp_platform_api` policy behind injectable `pp::platform::WebPlatformServices`, but the Web shell still reaches the default implementation through the retained fallback until a dedicated Web service is injected directly | Preserve WebGL memory behavior while moving canvas creation policy out of shared canvas headers and into the platform boundary | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build; WebGL package smoke once root Web build exists | Default canvas resolution is owned by injected `pp_platform_*` services for every supported platform, with no WebGL branch in the legacy fallback |
|
||||
| DEBT-0058 | Open | Modernization | App-level progress/message/input dialog metadata, including message-dialog OK/cancel captions, now consumes pure `pp_app_core` through `App::show_progress`, `App::message_box`, `App::input_box`, `pano_cli plan-app-dialog`, and `pp_app_core_app_dialog_tests`; live execution is centralized in `src/legacy_app_dialog_services.*`, retained root insertion now routes through `src/legacy_ui_overlay_services.*`, and whats-new dialog state persistence routes through `src/legacy_preference_storage.*`, but the bridge still creates retained `NodeProgressBar`, `NodeMessageBox`, and `NodeInputBox` instances with raw callback/lifetime ownership | Preserve current app-shell dialog behavior while moving shared dialog policy toward UI/app services | `pp_app_core_app_dialog_tests`; `pano_cli plan-app-dialog --kind progress --total -4`; `pano_cli plan-app-dialog --kind message --cancel`; `pano_cli plan-app-dialog --kind input --ok-caption Save`; `ctest --preset desktop-fast --build-config Debug`; Windows app build | Progress/message/input dialog creation, callback wiring, layout insertion, lifetime ownership, and headless automation are owned by injected app/UI services with `App` methods acting only as adapters |
|
||||
| DEBT-0059 | Open | Modernization | iOS root CMake headless builds assign generated bundle identifiers and disable code signing for executable test/tool targets | The current Apple gate is compile validation for shared component targets; signed iOS app/package validation is not migrated to root CMake yet | `powershell -ExecutionPolicy Bypass -File scripts\automation\apple-remote-build.ps1 -Presets macos,ios-simulator,ios-device`; `sh scripts/automation/platform-build.sh "ios-device"` on `panopainter-mac` | Root CMake owns the signed Apple app/package targets, package-smoke validates Apple bundles where signing material is available, and headless iOS test/tool targets are either excluded from signed package builds or use explicit test-runner signing policy |
|
||||
| DEBT-0064 | Open | Modernization | `pp_paint_renderer_compositor_tests` has a test-local no-op `Texture2D::bind()` definition so retained inline stroke-preview copy helpers can be covered without linking the full app-only legacy texture implementation | `tests` are configured before `pp_legacy_engine`, and linking the app legacy texture object into this planner test would couple the renderer-neutral test target back to the app target graph | `cmake --build --preset windows-msvc-default --config Debug --target pp_paint_renderer_compositor_tests`; `ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor" --output-on-failure` | Move retained preview copy behavior behind a pure callback-only test seam or split legacy texture binding into a linkable non-app test support target, then delete the test-local `Texture2D::bind()` shim |
|
||||
| DEBT-0064 | Open | Modernization | Stroke-preview result copy now routes through the renderer-facing `pp::paint_renderer::copy_stroke_preview_result_to_texture(...)` callback-only contract in `src/paint_renderer/compositor.h`; the node-level copy wrapper, final-composite wrapper, and pass-sequence wrapper are removed, and `pp_paint_renderer_compositor_tests` no longer needs either a test-local `Texture2D::bind()` definition. Live preview still owns concrete texture binding and OpenGL execution around the remaining preview flow | `tests` are configured before `pp_legacy_engine`, and linking the app legacy texture object into this planner test would still couple the renderer-neutral test target back to the app target graph | `cmake --build --preset windows-msvc-default --config Debug --target pp_paint_renderer_compositor_tests`; `ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor" --output-on-failure` | Keep preview-copy behavior on renderer-facing callback-only seams and move the remaining live preview copy execution behind renderer-owned services so the remaining preview flow can become fully app-texture-free |
|
||||
|
||||
## Closed Debt
|
||||
|
||||
|
||||
115
docs/modernization/renderer_api_contract.md
Normal file
115
docs/modernization/renderer_api_contract.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# Renderer API Backend-Neutral Contract
|
||||
|
||||
## Purpose
|
||||
|
||||
`pp_renderer_api` defines the backend-neutral rendering contract used by `pp_paint_renderer`
|
||||
and the higher-level app core. This document captures the minimum behavior that any
|
||||
concrete backend (`pp_renderer_gl` today, Vulkan/Metal later) must preserve.
|
||||
|
||||
## Contract Scope
|
||||
|
||||
- Public interfaces:
|
||||
- `pp::renderer::IRenderDevice`
|
||||
- `pp::renderer::ICommandContext`
|
||||
- `pp::renderer::ITexture2D`
|
||||
- `pp::renderer::IRenderTarget`
|
||||
- `pp::renderer::IShaderProgram`
|
||||
- `pp::renderer::IMesh`
|
||||
- `pp::renderer::IReadbackBuffer`
|
||||
- `pp::renderer::IRenderTrace`
|
||||
- `pp::renderer::Recording*` helpers in `renderer_api/recording_renderer.*`
|
||||
- Validation helpers in `renderer_api.h` and shader catalog helpers in
|
||||
`renderer_api/shader_catalog.*`
|
||||
|
||||
## Behavioral Invariants
|
||||
|
||||
- No exceptions are part of API control flow; failures are reported through
|
||||
`pp::foundation::Status` / `pp::foundation::Result`.
|
||||
- Object lifetimes remain backend-owned; API consumers pass references/handles only.
|
||||
- Resource descriptors and command/state descriptors must be validated and constrained by the
|
||||
helper functions.
|
||||
- Backends may reject unsupported operations via explicit non-OK status but must not mutate
|
||||
visible program state before reporting failure.
|
||||
- Error codes and debug names are deterministic and backend-neutral (human-readable and
|
||||
test-stable where feasible).
|
||||
|
||||
## Surface Contracts
|
||||
|
||||
1. `IRenderDevice`
|
||||
|
||||
- `backend_name()` identifies backend family.
|
||||
- `features()` returns capability bits used for planner decisions.
|
||||
- Resource creation methods return `Result` and report allocation/validation failures.
|
||||
- `immediate_context()` is stable for the lifetime of the device object.
|
||||
- `trace()` may return `nullptr`; callers must tolerate no trace provider.
|
||||
|
||||
2. `ICommandContext`
|
||||
|
||||
- State mutation (`set_viewport`, `set_scissor`, blend/depth/shader/sampler/mesh/program binds) is
|
||||
explicit and backend-agnostic.
|
||||
- Command methods that can fail must return status.
|
||||
- `end_render_pass()` is always side-effect safe and non-throwing.
|
||||
- `read_texture` / `capture_frame` readback contracts are byte-sized and descriptor-driven.
|
||||
- Texture upload/copy/readback/transition methods must respect descriptor bounds and ordering rules.
|
||||
|
||||
3. Resource descriptors and helpers
|
||||
|
||||
- `TextureDesc`, `Extent2D`, `Viewport`, `ScissorRect`, `RenderPassDesc`,
|
||||
`TextureUsage`, `TextureState`, `BlendState`, `DepthState`, sampler/topology enums
|
||||
are shared semantic vocabulary across backends.
|
||||
- Validation helpers (`validate_*`) are the compatibility fence for contract behavior.
|
||||
- `PaintFeedbackPlan` and `plan_paint_feedback(...)` are the feature/algorithm decision seam
|
||||
for framebuffer feedback vs ping-pong workflows.
|
||||
|
||||
4. Trace and recording
|
||||
|
||||
- `IRenderTrace` is optional and may be elided, but implementations should support scoped markers
|
||||
and markers where used.
|
||||
- Recording backend (`RecordingRenderDevice`, `RecordingCommandContext`) must preserve command
|
||||
order and reject invalid sequences through status/command visibility.
|
||||
|
||||
## Feature semantics
|
||||
|
||||
Backends are expected to honor all feature bits consistently:
|
||||
|
||||
- `framebuffer_fetch`
|
||||
- `explicit_texture_transitions`
|
||||
- `texture_copy`
|
||||
- `render_target_blit`
|
||||
- `frame_capture`
|
||||
- `float16_render_targets`
|
||||
- `float32_render_targets`
|
||||
- `float32_linear_filtering`
|
||||
|
||||
Feature gates must be enforced by planners before issuing backend commands.
|
||||
|
||||
## Existing conformance coverage
|
||||
|
||||
Current renderer-api conformance tests (non-backend):
|
||||
|
||||
- `pp_renderer_api_tests`
|
||||
- `pp_renderer_api` test cases:
|
||||
- `validates_texture_usage_contract`
|
||||
- `validates_texture_transition_contract`
|
||||
- `validates_mipmap_generation_contract`
|
||||
- `validates_texture_copy_contract`
|
||||
- `validates_blit_contract`
|
||||
- `plans_paint_feedback_paths`
|
||||
- `renderer_interfaces_support_backend_neutral_dispatch`
|
||||
- `recording_renderer_*` command-sequence and validation tests
|
||||
|
||||
OpenGL-specific conformance remains in `pp_renderer_gl` suites:
|
||||
|
||||
- `pp_renderer_gl_capabilities_tests`
|
||||
- `pp_renderer_gl_command_plan_tests`
|
||||
- `pp_renderer_gl_gpu_readback_tests` (where GPU context is available)
|
||||
- `panopainter_renderer_conformance_matrix_self_test`
|
||||
- `ctest --preset renderer-conformance`
|
||||
- `panopainter_renderer_api_contract_self_test` (tooling guard for renderer API and paint renderer
|
||||
backend-neutral contract source purity).
|
||||
|
||||
## Open items for RND-007
|
||||
|
||||
- Ensure Vulkan/Metal planning/lifecycle tests run the same contract surfaces without backend leakage.
|
||||
- Keep `pp_renderer_api` implementation/usage free from backend-only headers and raw platform state.
|
||||
- Keep new backend labs opt-in until this contract and conformance matrix are complete.
|
||||
@@ -1836,7 +1836,7 @@ Gate:
|
||||
|
||||
Goal: prepare Vulkan and Metal without destabilizing the OpenGL parity path.
|
||||
|
||||
Status: not started. Do not start production Vulkan or Metal work until
|
||||
Status: in progress. 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.
|
||||
@@ -1848,6 +1848,14 @@ Implementation tasks:
|
||||
- `pp_renderer_metal_lab`
|
||||
- Use `D:\Dev\vkpaint` as reference material for Vulkan painting experiments,
|
||||
not as direct production code.
|
||||
- Record and enforce the renderer API contract surface in
|
||||
`docs/modernization/renderer_api_contract.md` and keep
|
||||
`panopainter_renderer_api_contract_self_test` as a precondition for
|
||||
`RND-007` closeout.
|
||||
- Add and keep a renderer-conformance matrix fixture profile using
|
||||
`renderer-conformance` labels plus `ctest --preset renderer-conformance` and
|
||||
`ctest --preset desktop-gpu`, enforced by
|
||||
`panopainter_renderer_conformance_matrix_self_test` before `RND-008` closeout.
|
||||
- Before integration, prove:
|
||||
- ping-pong compositing path
|
||||
- input-attachment/subpass path where applicable
|
||||
|
||||
Reference in New Issue
Block a user