diff --git a/docs/en/phase-0-reactflow-parity-audit.md b/docs/en/phase-0-reactflow-parity-audit.md index 2234e49e..d0f34d9f 100644 --- a/docs/en/phase-0-reactflow-parity-audit.md +++ b/docs/en/phase-0-reactflow-parity-audit.md @@ -202,6 +202,10 @@ Phase 538 is GitHub #199 / `avalonia-node-map-a3w`, the eraser behavior/API feas Phase 539 is GitHub #201 / `avalonia-node-map-rwr`, the rectangle/freehand drawing primitive model gate. This docs/tests-only slice records that the current `GraphDocument` / `GraphNode` / `GraphConnection` model surface and `GraphEditorSelectionRectangleSnapshot` / `GraphEditorSelectionLassoSnapshot` evidence are graph-scene and selection contracts, not rectangle/freehand drawing primitives. It defines the minimum future contract needed before drawing behavior can be implemented or claimed: model identity, geometry, style/brush state, hit-testing/edit lifecycle, renderer projection, persistence, and Cookbook/screenshot evidence. It authorizes no runtime behavior changes, no public API changes, no Avalonia pointer coordinator edits, no renderer-layer changes, no persistence/schema changes, no screenshot manifest expansion, no UI redesign, no eraser behavior, no toolbar work, no retained API removal, and no full React Flow whiteboard parity. +## Phase 540 Update + +Phase 540 is GitHub #203 / `avalonia-node-map-91b`, the whiteboard persistence and render-layer readiness gate. This docs/tests-only slice records that current persistence and rendering evidence is graph-scene evidence: `GraphDocumentSerializer`, `GraphDocumentCompatibility`, `CurrentSchemaVersion`, and `GraphWorkspaceService` persist graph documents and workspaces, while `GraphEditorSceneSnapshot`, `NodeCanvasConnectionSceneRenderer`, `CookbookScreenshotGateRoutes.json`, and `CookbookShellVisualGateStates.json` prove graph-scene projection and screenshot fixtures. They do not implement whiteboard annotation persistence or whiteboard annotation rendering. Before any future rectangle/freehand drawing state can be persisted or rendered as first-class whiteboard primitives, a later issue must define a persistence/schema contract, renderer projection contract, hit-testing/edit lifecycle, screenshot/Cookbook evidence, migration policy, and explicit non-goals. Phase 540 authorizes no runtime behavior changes, no public API changes, no persistence/schema changes, no renderer-layer changes, no screenshot manifest expansion, no Avalonia pointer coordinator edits, no UI redesign, no drawing tool implementation, no eraser behavior, no toolbar work, no retained API removal, and no full React Flow whiteboard parity. + ## Phase 489 Update Phase 489 closed GitHub #101 / `avalonia-node-map-6sc` through PR #102 as a renderer virtualization design spike on branch `perf/renderer-virtualization-spike`. This slice was docs/tests only: it defined the proof contract required before any future ItemsRepeater/Skia-style renderer virtualization, background graph index, or graph-size claim expansion. It made no public API change and no runtime change. The current evidence remains viewport-budgeted scene projection/rendering, not a true renderer virtualization contract; `xlarge` stays telemetry-only. @@ -378,7 +382,7 @@ Phase 529 records the whiteboard/lasso/eraser feasibility audit through GitHub # | Lasso/freehand selection | Public Avalonia lasso selection mode with hosted toolbar activation and transient visual feedback / whiteboard gap retained | `GetSelectionLassoSnapshot`, `GraphEditorSelectionLassoSnapshot`, `Queries_GetSelectionLassoSnapshot_ReturnsCenterContainedNodesAndConnections`, `Queries_GetSelectionLassoSnapshot_UsesNodeCenterInsteadOfBoundsIntersection`, `Queries_GetSelectionLassoSnapshot_WithOpenOrDegeneratePath_ReturnsDeterministicResults`, `UpdateLassoSelection_WithFinalizeTrue_UsesBackendSelectionLassoQuery`, `LassoSelection_RoutesThroughCanvasBridge_AndSelectsContainedNodes`, `NodeCanvasSelectionGestureKind.Lasso`, `TryBeginLassoSelection_WithLassoGestureKind_RecordsStartAndMoveAfterThreshold`, `HandleMoved_WhenCanvasSelectionUsesLassoGesture_RecordsLassoPointAndSkipsMarqueeUpdate`, `HandleReleased_AfterLassoSelection_FinalizesLassoSelectionAndResetsSession`, `NodeCanvasSelectionMode.Lasso`, `LassoSelectionMode_RoutesThroughCanvasPointerHandlers_AndSelectsContainedNodes`, `UpdateLassoFeedback`, `ClearLassoFeedback`, `LassoSelectionMode_RendersTransientFeedbackPathOnlyDuringDrag`, `CreatePointerSelectionModeActions`, `pointer-mode.lasso-selection`, `PART_PointerModeLassoButton`, `HostedActions_PointerModeActionsSwitchNodeCanvasSelectionModeWithoutRuntimeCommandRoute`, and `AuthoringToolsChrome_ProjectsPointerModeActionsThroughNodeCanvasSelectionMode` prove the active-scope backend query, internal Avalonia bridge, internal gesture capture route, public pointer-mode activation route, hosted toolbar route, and transient visual feedback route. The query treats freeform points as a closed polygon, selects nodes by center-point containment, and selects connections when both endpoint nodes are selected. | No eraser behavior, drawing primitives, persistence, renderer layer, strict pixel baselines, retained API removal, or full React Flow whiteboard parity is implemented. This remains not full React Flow whiteboard parity. | | Eraser tool | Feasibility gate recorded / gap retained | `selection.delete`, the `Delete Selection` descriptor, and the stock `selection-delete` placement prove graph-selection deletion evidence only. | Phase 538 records that graph-selection deletion is not an eraser cursor, collision trail, or eraser-specific hit-testing path. No eraser cursor, no collision trail, no eraser-specific hit-testing, no drawing primitives, no persistence, no renderer rewrite, no strict pixel baseline enforcement, no retained API removal, and no full whiteboard parity are implemented. | | Rectangle/freehand drawing | Model gate recorded / gap retained | Phase 539 / GitHub #201 / `avalonia-node-map-rwr` ties current reusable evidence to `GraphDocument`, `GraphNode`, `GraphConnection`, `GraphEditorSelectionRectangleSnapshot`, `GraphEditorSelectionLassoSnapshot`, `GetSelectionRectangleSnapshot`, `GetSelectionLassoSnapshot`, `interaction-selection-marquee-route`, `selection-marquee-workbench`, and `cookbook-interaction-lasso-screenshot-proof`. These prove graph-scene, selection, and visual-proof seams only. | Before rectangle/freehand drawing behavior can be implemented or claimed, a later API/model issue must define model identity, geometry, style/brush state, hit-testing/edit lifecycle, renderer projection, persistence/drawing persistence, and Cookbook/screenshot evidence. Phase 539 adds no runtime behavior changes, no public API changes, no Avalonia pointer coordinator edits, no renderer-layer changes, no persistence/schema changes, no screenshot manifest expansion, and no full React Flow whiteboard parity. | -| Whiteboard persistence/render layer | Gap retained | Current Cookbook and screenshot rows cover graph scenes and built-in components, not whiteboard annotations or drawing state. | Future work would need persistence, renderer layer, hit-testing, React Flow-like examples, and screenshot manifest expansion; Phase 529 adds none of those. | +| Whiteboard persistence/render layer | Readiness gate recorded / gap retained | Phase 540 / GitHub #203 / `avalonia-node-map-91b` ties current reusable evidence to `GraphDocumentSerializer`, `GraphDocumentCompatibility`, `CurrentSchemaVersion`, `GraphWorkspaceService`, `GraphEditorSceneSnapshot`, `NodeCanvasConnectionSceneRenderer`, `CookbookScreenshotGateRoutes.json`, and `CookbookShellVisualGateStates.json`. These prove graph document/workspace persistence, graph-scene projection, committed connection rendering, and screenshot fixture coverage only. | Future whiteboard annotation persistence and whiteboard annotation rendering need a later implementation issue with a persistence/schema contract, renderer projection contract, hit-testing/edit lifecycle, screenshot/Cookbook evidence, migration policy, and explicit non-goals. Phase 540 adds no runtime behavior changes, no public API changes, no persistence/schema changes, no renderer-layer changes, no screenshot manifest expansion, and no full React Flow whiteboard parity. | ## Completed Phase 0 Issue Wave @@ -513,6 +517,8 @@ Phase 538 records the eraser behavior/API feasibility gate through GitHub #199 / Phase 539 records the rectangle/freehand drawing primitive model gate through GitHub #201 / `avalonia-node-map-rwr`. It keeps current `GraphDocument`, `GraphNode`, `GraphConnection`, `GraphEditorSelectionRectangleSnapshot`, and `GraphEditorSelectionLassoSnapshot` evidence scoped to graph-scene and selection contracts, then defines the future model identity, geometry, style/brush state, hit-testing/edit lifecycle, renderer projection, persistence, and Cookbook/screenshot evidence required before any rectangle/freehand drawing parity claim. +Phase 540 records the whiteboard persistence and render-layer readiness gate through GitHub #203 / `avalonia-node-map-91b`. It keeps current `GraphDocumentSerializer`, `GraphDocumentCompatibility`, `CurrentSchemaVersion`, `GraphWorkspaceService`, `GraphEditorSceneSnapshot`, `NodeCanvasConnectionSceneRenderer`, `CookbookScreenshotGateRoutes.json`, and `CookbookShellVisualGateStates.json` evidence scoped to graph documents, workspaces, graph-scene projection, committed connection rendering, and screenshot fixtures; it does not claim whiteboard annotation persistence or whiteboard annotation rendering. + | GitHub | Bead | Title | Priority | Likely write set | Parallelism | | --- | --- | --- | --- | --- | --- | | #193 | `avalonia-node-map-8l6` | Phase 535: refresh post-lasso visual feedback parity queue | P2 | parity roadmap docs and focused docs tests | Current docs/test queue refresh. Blocks the next implementation wave because it replaces the stale Phase 534 current row with tracker-backed follow-ups. | @@ -520,7 +526,7 @@ Phase 539 records the rectangle/freehand drawing primitive model gate through Gi | #197 | `avalonia-node-map-w9h` | Phase 537: lasso toolbar UX and public activation ergonomics boundary | P2 | hosted authoring tools, `NodeCanvas.SelectionMode` activation surface, Demo/Cookbook route, and editor/Avalonia tests | Merged toolbar ergonomics slice. It stays on hosted actions over the existing canvas selection mode and does not create whiteboard primitives. | | #199 | `avalonia-node-map-a3w` | Phase 538: eraser behavior/API feasibility gate | P3 | graph-selection deletion evidence, parity roadmap docs, and focused docs tests | Current eraser feasibility slice. It keeps `selection.delete` scoped to graph-selection deletion evidence and does not create an eraser cursor, collision trail, or eraser-specific hit-testing path. | | #201 | `avalonia-node-map-rwr` | Phase 539: rectangle/freehand drawing primitive model gate | P3 | Core/Editor model contract docs/tests and whiteboard primitive API inventory | Current stacked drawing model gate on top of Phase 538 / PR #200. It stays docs/model-only, does not touch Avalonia pointer coordinators, and preserves Phase 540 as future persistence/render-layer readiness work. | -| TBD | TBD | Phase 540: whiteboard persistence and render-layer readiness gate | P4 | persistence/schema planning docs, renderer-layer boundary docs, screenshot policy notes, and focused docs tests | Depends on Phase 539 model decisions; do not implement persistence or renderer behavior in the queue refresh. | +| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate | P4 | persistence/schema planning docs, renderer-layer boundary docs, screenshot policy notes, and focused docs tests | Stacked after Phase 539 / PR #202; do not merge before Phase 539. This slice records readiness criteria only and does not implement persistence or renderer behavior. | ## Recommended Parallel Worktree Plan @@ -561,7 +567,7 @@ Phase 539 records the rectangle/freehand drawing primitive model gate through Gi - `feature/phase-537-lasso-toolbar-ergonomics`: owned #197 / `avalonia-node-map-w9h`; merged worktree for lasso toolbar UX and public activation ergonomics. - `feature/phase-538-eraser-feasibility`: owns #199 / `avalonia-node-map-a3w`; current worktree for eraser behavior/API feasibility with graph-selection deletion evidence only. - `docs/phase-539-drawing-primitive-model-gate`: owns #201 / `avalonia-node-map-rwr`; current stacked docs/test gate for rectangle/freehand drawing primitive model decisions on top of Phase 538 / PR #200, with no runtime/API/UI/pointer coordinator/renderer/persistence changes. -- `docs/phase-540-whiteboard-render-persistence-gate`: future candidate for persistence/render-layer readiness after drawing model decisions. +- `docs/phase-540-whiteboard-render-persistence-gate`: owns #203 / `avalonia-node-map-91b`; current stacked docs/test gate for persistence/render-layer readiness after drawing model decisions, with no runtime/API/persistence/schema/renderer/screenshot-manifest/UI/pointer coordinator changes. ## UI Verification Policy @@ -617,4 +623,5 @@ Current coverage includes scene-level route captures plus ten manifest-driven fu - Phase 535 is GitHub #193 / `avalonia-node-map-8l6`; it refreshes the post-Phase-534 parity queue without runtime behavior changes, public API changes, UI redesign, screenshot manifest expansion, strict pixel baseline enforcement, retained API removal, or whiteboard implementation. - Phase 536 is GitHub #195 / `avalonia-node-map-uvd`; it adds `cookbook-interaction-lasso-screenshot-proof`, `interaction-lasso-screenshot-proof-route`, `shell-cookbook-lasso-screenshot-proof`, `full-window-shell-lasso-state`, and `LASSO_SCREENSHOT_PROOF_BOUNDARY_OK` without toolbar UX, eraser behavior, drawing primitives, persistence, renderer rewrite, strict pixel baseline enforcement, retained API removal, or full whiteboard parity. - Phase 539 is GitHub #201 / `avalonia-node-map-rwr`; it records the rectangle/freehand drawing primitive model gate without runtime behavior changes, public API changes, Avalonia pointer coordinator edits, renderer-layer changes, persistence/schema changes, screenshot manifest expansion, UI redesign, eraser behavior, toolbar work, retained API removal, or full React Flow whiteboard parity. -- Product code remains out of scope for Phase 478, Phase 484, Phase 490, Phase 491, Phase 492, Phase 493, Phase 494, Phase 495, Phase 497, Phase 498, Phase 499, Phase 500, Phase 501, Phase 502, Phase 503, Phase 504, Phase 505, Phase 506, Phase 507, Phase 508, Phase 509, Phase 510, Phase 511, Phase 512, Phase 513, Phase 520, Phase 521, Phase 522, Phase 523, Phase 524, Phase 525, Phase 526, Phase 527, Phase 528, Phase 529, Phase 535, and Phase 539 unless a focused test proves a specific missing contract. +- Phase 540 is GitHub #203 / `avalonia-node-map-91b`; it records the whiteboard persistence and render-layer readiness gate without runtime behavior changes, public API changes, persistence/schema changes, renderer-layer changes, screenshot manifest expansion, Avalonia pointer coordinator edits, UI redesign, drawing tool implementation, eraser behavior, toolbar work, retained API removal, or full React Flow whiteboard parity. +- Product code remains out of scope for Phase 478, Phase 484, Phase 490, Phase 491, Phase 492, Phase 493, Phase 494, Phase 495, Phase 497, Phase 498, Phase 499, Phase 500, Phase 501, Phase 502, Phase 503, Phase 504, Phase 505, Phase 506, Phase 507, Phase 508, Phase 509, Phase 510, Phase 511, Phase 512, Phase 513, Phase 520, Phase 521, Phase 522, Phase 523, Phase 524, Phase 525, Phase 526, Phase 527, Phase 528, Phase 529, Phase 535, Phase 539, and Phase 540 unless a focused test proves a specific missing contract. diff --git a/docs/zh-CN/phase-0-reactflow-parity-audit.md b/docs/zh-CN/phase-0-reactflow-parity-audit.md index 2b9eef05..3cbb3496 100644 --- a/docs/zh-CN/phase-0-reactflow-parity-audit.md +++ b/docs/zh-CN/phase-0-reactflow-parity-audit.md @@ -202,6 +202,10 @@ Phase 538 是 GitHub #199 / `avalonia-node-map-a3w`,承接 eraser behavior/API Phase 539 是 GitHub #201 / `avalonia-node-map-rwr`,记录 rectangle/freehand drawing primitive model gate。本 docs/tests-only slice 记录当前 `GraphDocument` / `GraphNode` / `GraphConnection` model surface 和 `GraphEditorSelectionRectangleSnapshot` / `GraphEditorSelectionLassoSnapshot` evidence 只属于 graph-scene 与 selection contracts,不是 rectangle/freehand drawing primitives。它定义未来实现或声明 drawing behavior 前必须先具备的 minimum contract:model identity、geometry、style/brush state、hit-testing/edit lifecycle、renderer projection、persistence 和 Cookbook/screenshot evidence。它不授权 no runtime behavior changes、no public API changes、no Avalonia pointer coordinator edits、no renderer-layer changes、no persistence/schema changes、no screenshot manifest expansion、no UI redesign、no eraser behavior、no toolbar work、no retained API removal 或 no full React Flow whiteboard parity。 +## Phase 540 更新 + +Phase 540 是 GitHub #203 / `avalonia-node-map-91b`,记录 whiteboard persistence and render-layer readiness gate。本 docs/tests-only slice 记录当前 persistence 与 rendering evidence 只属于 graph-scene evidence:`GraphDocumentSerializer`、`GraphDocumentCompatibility`、`CurrentSchemaVersion` 和 `GraphWorkspaceService` 持久化 graph documents 与 workspaces;`GraphEditorSceneSnapshot`、`NodeCanvasConnectionSceneRenderer`、`CookbookScreenshotGateRoutes.json` 和 `CookbookShellVisualGateStates.json` 证明 graph-scene projection 与 screenshot fixtures。它们不实现 whiteboard annotation persistence 或 whiteboard annotation rendering。后续若要把 rectangle/freehand drawing state 作为 first-class whiteboard primitives 持久化或渲染,必须由后续 issue 先定义 persistence/schema contract、renderer projection contract、hit-testing/edit lifecycle、screenshot/Cookbook evidence、migration policy 和 explicit non-goals。Phase 540 不授权 no runtime behavior changes、no public API changes、no persistence/schema changes、no renderer-layer changes、no screenshot manifest expansion、no Avalonia pointer coordinator edits、no UI redesign、no drawing tool implementation、no eraser behavior、no toolbar work、no retained API removal 或 no full React Flow whiteboard parity。 + ## Phase 489 更新 Phase 489 通过 PR #102 关闭 GitHub #101 / `avalonia-node-map-6sc`,完成 `perf/renderer-virtualization-spike` 分支上的 renderer virtualization design spike。本 slice 只做 docs/tests:先定义未来声明 ItemsRepeater/Skia-style renderer virtualization、background graph index 或扩大 graph-size claim 前必须满足的 proof contract。不做 public API change,也不做 runtime change。当前证据仍只支持 viewport-budgeted scene projection/rendering,不是真正的 renderer virtualization contract;`xlarge` 继续保持 telemetry-only。 @@ -378,7 +382,7 @@ Phase 529 记录 whiteboard/lasso/eraser feasibility audit,对应 GitHub #181 | Lasso/freehand selection | Public Avalonia lasso selection mode with hosted toolbar activation and transient visual feedback / whiteboard gap retained | `GetSelectionLassoSnapshot`、`GraphEditorSelectionLassoSnapshot`、`Queries_GetSelectionLassoSnapshot_ReturnsCenterContainedNodesAndConnections`、`Queries_GetSelectionLassoSnapshot_UsesNodeCenterInsteadOfBoundsIntersection`、`Queries_GetSelectionLassoSnapshot_WithOpenOrDegeneratePath_ReturnsDeterministicResults`、`UpdateLassoSelection_WithFinalizeTrue_UsesBackendSelectionLassoQuery`、`LassoSelection_RoutesThroughCanvasBridge_AndSelectsContainedNodes`、`NodeCanvasSelectionGestureKind.Lasso`、`TryBeginLassoSelection_WithLassoGestureKind_RecordsStartAndMoveAfterThreshold`、`HandleMoved_WhenCanvasSelectionUsesLassoGesture_RecordsLassoPointAndSkipsMarqueeUpdate`、`HandleReleased_AfterLassoSelection_FinalizesLassoSelectionAndResetsSession`、`NodeCanvasSelectionMode.Lasso`、`LassoSelectionMode_RoutesThroughCanvasPointerHandlers_AndSelectsContainedNodes`、`UpdateLassoFeedback`、`ClearLassoFeedback`、`LassoSelectionMode_RendersTransientFeedbackPathOnlyDuringDrag`、`CreatePointerSelectionModeActions`、`pointer-mode.lasso-selection`、`PART_PointerModeLassoButton`、`HostedActions_PointerModeActionsSwitchNodeCanvasSelectionModeWithoutRuntimeCommandRoute` 和 `AuthoringToolsChrome_ProjectsPointerModeActionsThroughNodeCanvasSelectionMode` 证明 active-scope backend query、internal Avalonia bridge、internal gesture capture route、public pointer-mode activation route、hosted toolbar route 和 transient visual feedback route。该 query 把 freeform points 当作 closed polygon,用 center-point containment 选择 node,并在两个 endpoint node 都选中时选择 connection。 | 尚未实现 eraser behavior、drawing primitives、persistence、renderer layer、strict pixel baselines、retained API removal 或 full React Flow whiteboard parity。该边界仍是 not full React Flow whiteboard parity。 | | Eraser tool | Feasibility gate recorded / gap retained | `selection.delete`、`Delete Selection` descriptor 和 stock `selection-delete` placement 只证明 graph-selection deletion evidence。 | Phase 538 记录 graph-selection deletion is not an eraser cursor、collision trail 或 eraser-specific hit-testing path。尚未实现 no eraser cursor、no collision trail、no eraser-specific hit-testing、no drawing primitives、no persistence、no renderer rewrite、no strict pixel baseline enforcement、no retained API removal 或 no full whiteboard parity。 | | Rectangle/freehand drawing | Model gate recorded / gap retained | Phase 539 / GitHub #201 / `avalonia-node-map-rwr` 将当前 reusable evidence 绑定到 `GraphDocument`、`GraphNode`、`GraphConnection`、`GraphEditorSelectionRectangleSnapshot`、`GraphEditorSelectionLassoSnapshot`、`GetSelectionRectangleSnapshot`、`GetSelectionLassoSnapshot`、`interaction-selection-marquee-route`、`selection-marquee-workbench` 和 `cookbook-interaction-lasso-screenshot-proof`。这些只证明 graph-scene、selection 和 visual-proof seams。 | 后续实现或声明 rectangle/freehand drawing behavior 前,必须由新的 API/model issue 定义 model identity、geometry、style/brush state、hit-testing/edit lifecycle、renderer projection、persistence/drawing persistence 和 Cookbook/screenshot evidence。Phase 539 不做 no runtime behavior changes、no public API changes、no Avalonia pointer coordinator edits、no renderer-layer changes、no persistence/schema changes、no screenshot manifest expansion,也不声明 no full React Flow whiteboard parity。 | -| Whiteboard persistence/render layer | Gap retained | 当前 Cookbook 和 screenshot rows 覆盖 graph scenes 与 built-in components,不覆盖 whiteboard annotations 或 drawing state。 | 后续若推进,需要 persistence、renderer layer、hit-testing、React Flow-like examples 和 screenshot manifest expansion;Phase 529 均不新增。 | +| Whiteboard persistence/render layer | Readiness gate recorded / gap retained | Phase 540 / GitHub #203 / `avalonia-node-map-91b` 将当前 reusable evidence 绑定到 `GraphDocumentSerializer`、`GraphDocumentCompatibility`、`CurrentSchemaVersion`、`GraphWorkspaceService`、`GraphEditorSceneSnapshot`、`NodeCanvasConnectionSceneRenderer`、`CookbookScreenshotGateRoutes.json` 和 `CookbookShellVisualGateStates.json`。这些只证明 graph document/workspace persistence、graph-scene projection、committed connection rendering 和 screenshot fixture coverage。 | 后续 whiteboard annotation persistence 与 whiteboard annotation rendering 需要新的 implementation issue 定义 persistence/schema contract、renderer projection contract、hit-testing/edit lifecycle、screenshot/Cookbook evidence、migration policy 和 explicit non-goals。Phase 540 不做 no runtime behavior changes、no public API changes、no persistence/schema changes、no renderer-layer changes、no screenshot manifest expansion,也不声明 no full React Flow whiteboard parity。 | ## 已完成的 Phase 0 Issue Wave @@ -513,6 +517,8 @@ Phase 538 通过 GitHub #199 / `avalonia-node-map-a3w` 记录 eraser behavior/AP Phase 539 记录 rectangle/freehand drawing primitive model gate,通过 GitHub #201 / `avalonia-node-map-rwr`。它把当前 `GraphDocument`、`GraphNode`、`GraphConnection`、`GraphEditorSelectionRectangleSnapshot` 和 `GraphEditorSelectionLassoSnapshot` evidence 继续限制在 graph-scene 与 selection contracts,然后定义后续声明 rectangle/freehand drawing parity 前需要的 model identity、geometry、style/brush state、hit-testing/edit lifecycle、renderer projection、persistence 和 Cookbook/screenshot evidence。 +Phase 540 记录 whiteboard persistence and render-layer readiness gate,通过 GitHub #203 / `avalonia-node-map-91b`。它把当前 `GraphDocumentSerializer`、`GraphDocumentCompatibility`、`CurrentSchemaVersion`、`GraphWorkspaceService`、`GraphEditorSceneSnapshot`、`NodeCanvasConnectionSceneRenderer`、`CookbookScreenshotGateRoutes.json` 和 `CookbookShellVisualGateStates.json` evidence 限制在 graph documents、workspaces、graph-scene projection、committed connection rendering 与 screenshot fixtures;它不声明 whiteboard annotation persistence 或 whiteboard annotation rendering。 + | GitHub | Bead | 标题 | 优先级 | 可能 write set | 并行边界 | | --- | --- | --- | --- | --- | --- | | #193 | `avalonia-node-map-8l6` | Phase 535: refresh post-lasso visual feedback parity queue | P2 | parity roadmap docs 和 focused docs tests | Current docs/test queue refresh。它用 tracker-backed follow-ups 替换 stale Phase 534 current row,因此会阻塞下一批 implementation wave。 | @@ -520,7 +526,7 @@ Phase 539 记录 rectangle/freehand drawing primitive model gate,通过 GitHub | #197 | `avalonia-node-map-w9h` | Phase 537: lasso toolbar UX and public activation ergonomics boundary | P2 | hosted authoring tools、`NodeCanvas.SelectionMode` activation surface、Demo/Cookbook route 和 editor/Avalonia tests | Merged toolbar ergonomics slice。它只在 existing canvas selection mode 上投影 hosted actions,不创建 whiteboard primitives。 | | #199 | `avalonia-node-map-a3w` | Phase 538: eraser behavior/API feasibility gate | P3 | graph-selection deletion evidence、parity roadmap docs 和 focused docs tests | Current eraser feasibility slice。它把 `selection.delete` 限定为 graph-selection deletion evidence,不创建 eraser cursor、collision trail 或 eraser-specific hit-testing path。 | | #201 | `avalonia-node-map-rwr` | Phase 539: rectangle/freehand drawing primitive model gate | P3 | Core/Editor model contract docs/tests 和 whiteboard primitive API inventory | Current stacked drawing model gate,位于 Phase 538 / PR #200 之上。它保持 docs/model-only,不触碰 Avalonia pointer coordinators,并保留 Phase 540 作为后续 persistence/render-layer readiness work。 | -| TBD | TBD | Phase 540: whiteboard persistence and render-layer readiness gate | P4 | persistence/schema planning docs、renderer-layer boundary docs、screenshot policy notes 和 focused docs tests | 依赖 Phase 539 model decisions;本 queue refresh 不实现 persistence 或 renderer behavior。 | +| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate | P4 | persistence/schema planning docs、renderer-layer boundary docs、screenshot policy notes 和 focused docs tests | Stacked after Phase 539 / PR #202;不要早于 Phase 539 合并。本 slice 只记录 readiness criteria,不实现 persistence 或 renderer behavior。 | ## 推荐并行 Worktree 计划 @@ -561,7 +567,7 @@ Phase 539 记录 rectangle/freehand drawing primitive model gate,通过 GitHub - `feature/phase-537-lasso-toolbar-ergonomics`:负责 #197 / `avalonia-node-map-w9h`;已合并的 worktree,用于 lasso toolbar UX 和 public activation ergonomics。 - `feature/phase-538-eraser-feasibility`:负责 #199 / `avalonia-node-map-a3w`;当前 worktree,用 graph-selection deletion evidence 记录 eraser behavior/API feasibility。 - `docs/phase-539-drawing-primitive-model-gate`:负责 #201 / `avalonia-node-map-rwr`;当前 stacked docs/test gate,位于 Phase 538 / PR #200 之上,用于 rectangle/freehand drawing primitive model decisions,不做 runtime/API/UI/pointer coordinator/renderer/persistence changes。 -- `docs/phase-540-whiteboard-render-persistence-gate`:future candidate,用于 drawing model decisions 后的 persistence/render-layer readiness。 +- `docs/phase-540-whiteboard-render-persistence-gate`:负责 #203 / `avalonia-node-map-91b`;当前 stacked docs/test gate,用于 drawing model decisions 后的 persistence/render-layer readiness,不做 runtime/API/persistence/schema/renderer/screenshot-manifest/UI/pointer coordinator changes。 ## UI 验证策略 @@ -617,4 +623,5 @@ Phase 539 记录 rectangle/freehand drawing primitive model gate,通过 GitHub - Phase 535 是 GitHub #193 / `avalonia-node-map-8l6`;它刷新 post-Phase-534 parity queue,不做 runtime behavior changes、public API changes、UI redesign、screenshot manifest expansion、strict pixel baseline enforcement、retained API removal 或 whiteboard implementation。 - Phase 536 是 GitHub #195 / `avalonia-node-map-uvd`;它新增 `cookbook-interaction-lasso-screenshot-proof`、`interaction-lasso-screenshot-proof-route`、`shell-cookbook-lasso-screenshot-proof`、`full-window-shell-lasso-state` 和 `LASSO_SCREENSHOT_PROOF_BOUNDARY_OK`,不做 toolbar UX、eraser behavior、drawing primitives、persistence、renderer rewrite、strict pixel baseline enforcement、retained API removal 或 full whiteboard parity。 - Phase 539 是 GitHub #201 / `avalonia-node-map-rwr`;它记录 rectangle/freehand drawing primitive model gate,不做 runtime behavior changes、public API changes、Avalonia pointer coordinator edits、renderer-layer changes、persistence/schema changes、screenshot manifest expansion、UI redesign、eraser behavior、toolbar work、retained API removal 或 full React Flow whiteboard parity。 -- Phase 478、Phase 484、Phase 490、Phase 491、Phase 492、Phase 493、Phase 494、Phase 495、Phase 497、Phase 498、Phase 499、Phase 500、Phase 501、Phase 502、Phase 503、Phase 504、Phase 505、Phase 506、Phase 507、Phase 508、Phase 509、Phase 510、Phase 511、Phase 512、Phase 513、Phase 520、Phase 521、Phase 522、Phase 523、Phase 524、Phase 525、Phase 526、Phase 527、Phase 528、Phase 529、Phase 535 和 Phase 539 都不修改产品代码;除非 focused test 证明存在具体 missing contract。 +- Phase 540 是 GitHub #203 / `avalonia-node-map-91b`;它记录 whiteboard persistence and render-layer readiness gate,不做 runtime behavior changes、public API changes、persistence/schema changes、renderer-layer changes、screenshot manifest expansion、Avalonia pointer coordinator edits、UI redesign、drawing tool implementation、eraser behavior、toolbar work、retained API removal 或 full React Flow whiteboard parity。 +- Phase 478、Phase 484、Phase 490、Phase 491、Phase 492、Phase 493、Phase 494、Phase 495、Phase 497、Phase 498、Phase 499、Phase 500、Phase 501、Phase 502、Phase 503、Phase 504、Phase 505、Phase 506、Phase 507、Phase 508、Phase 509、Phase 510、Phase 511、Phase 512、Phase 513、Phase 520、Phase 521、Phase 522、Phase 523、Phase 524、Phase 525、Phase 526、Phase 527、Phase 528、Phase 529、Phase 535、Phase 539 和 Phase 540 都不修改产品代码;除非 focused test 证明存在具体 missing contract。 diff --git a/tests/AsterGraph.Demo.Tests/ReactFlowParityRoadmapDocsTests.cs b/tests/AsterGraph.Demo.Tests/ReactFlowParityRoadmapDocsTests.cs index 82572d34..46e543ca 100644 --- a/tests/AsterGraph.Demo.Tests/ReactFlowParityRoadmapDocsTests.cs +++ b/tests/AsterGraph.Demo.Tests/ReactFlowParityRoadmapDocsTests.cs @@ -1127,6 +1127,52 @@ public void ParityRoadmapDocs_RecordPhase539DrawingPrimitiveModelGateInBothLocal Assert.Contains("Phase 539 记录 rectangle/freehand drawing primitive model gate", chineseParity, StringComparison.Ordinal); } + [Fact] + public void ParityRoadmapDocs_RecordPhase540WhiteboardPersistenceRenderGateInBothLocales() + { + var englishParity = ReadRepoFile("docs/en/phase-0-reactflow-parity-audit.md"); + var chineseParity = ReadRepoFile("docs/zh-CN/phase-0-reactflow-parity-audit.md"); + + foreach (var contents in new[] { englishParity, chineseParity }) + { + Assert.Contains("Phase 540", contents, StringComparison.Ordinal); + Assert.Contains("GitHub #203", contents, StringComparison.Ordinal); + Assert.Contains("avalonia-node-map-91b", contents, StringComparison.Ordinal); + Assert.Contains("whiteboard persistence and render-layer readiness gate", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("GraphDocumentSerializer", contents, StringComparison.Ordinal); + Assert.Contains("GraphDocumentCompatibility", contents, StringComparison.Ordinal); + Assert.Contains("CurrentSchemaVersion", contents, StringComparison.Ordinal); + Assert.Contains("GraphWorkspaceService", contents, StringComparison.Ordinal); + Assert.Contains("GraphEditorSceneSnapshot", contents, StringComparison.Ordinal); + Assert.Contains("NodeCanvasConnectionSceneRenderer", contents, StringComparison.Ordinal); + Assert.Contains("CookbookScreenshotGateRoutes.json", contents, StringComparison.Ordinal); + Assert.Contains("CookbookShellVisualGateStates.json", contents, StringComparison.Ordinal); + Assert.Contains("persistence/schema contract", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("renderer projection contract", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("hit-testing/edit lifecycle", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("screenshot/Cookbook evidence", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("migration policy", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("whiteboard annotation persistence", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("whiteboard annotation rendering", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no runtime behavior changes", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no public API changes", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no persistence/schema changes", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no renderer-layer changes", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no screenshot manifest expansion", contents, StringComparison.OrdinalIgnoreCase); + Assert.Contains("no full React Flow whiteboard parity", contents, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("whiteboard persistence parity is supported", contents, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("render-layer parity is supported", contents, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("whiteboard annotation persistence is implemented", contents, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("| TBD | TBD | Phase 540: whiteboard persistence and render-layer readiness gate", contents, StringComparison.Ordinal); + } + + AssertPostPhase540Queue(ExtractIssueWaveTable(englishParity)); + AssertPostPhase540Queue(ExtractIssueWaveTable(chineseParity)); + + Assert.Contains("Phase 540 records the whiteboard persistence and render-layer readiness gate", englishParity, StringComparison.Ordinal); + Assert.Contains("Phase 540 记录 whiteboard persistence and render-layer readiness gate", chineseParity, StringComparison.Ordinal); + } + [Fact] public void ParityRoadmapDocs_RecordPhase501PostPhase500QueueRefreshInBothLocales() { @@ -1223,7 +1269,9 @@ private static void AssertPostPhase534Queue(string table) Assert.Contains("Phase 538: eraser behavior/API feasibility gate", table, StringComparison.Ordinal); Assert.Contains("Phase 539: rectangle/freehand drawing primitive model gate", table, StringComparison.Ordinal); Assert.Contains("Phase 540: whiteboard persistence and render-layer readiness gate", table, StringComparison.Ordinal); - Assert.Contains("TBD", table, StringComparison.Ordinal); + Assert.True( + table.Contains("TBD", StringComparison.Ordinal) + || table.Contains("| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate", StringComparison.Ordinal)); Assert.Contains("Cookbook screenshot manifest", table, StringComparison.OrdinalIgnoreCase); Assert.Contains("hosted authoring tools", table, StringComparison.OrdinalIgnoreCase); Assert.True( @@ -1251,7 +1299,9 @@ private static void AssertPostPhase537Queue(string table) Assert.Contains("Phase 538: eraser behavior/API feasibility gate", table, StringComparison.Ordinal); Assert.Contains("Phase 539: rectangle/freehand drawing primitive model gate", table, StringComparison.Ordinal); Assert.Contains("Phase 540: whiteboard persistence and render-layer readiness gate", table, StringComparison.Ordinal); - Assert.Contains("TBD", table, StringComparison.Ordinal); + Assert.True( + table.Contains("TBD", StringComparison.Ordinal) + || table.Contains("| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate", StringComparison.Ordinal)); Assert.Contains("hosted authoring tools", table, StringComparison.OrdinalIgnoreCase); Assert.True( table.Contains("editor selection/delete commands", StringComparison.OrdinalIgnoreCase) @@ -1267,7 +1317,9 @@ private static void AssertPostPhase538Queue(string table) Assert.Contains("| #199 | `avalonia-node-map-a3w` | Phase 538: eraser behavior/API feasibility gate", table, StringComparison.Ordinal); Assert.Contains("| #201 | `avalonia-node-map-rwr` | Phase 539: rectangle/freehand drawing primitive model gate", table, StringComparison.Ordinal); Assert.Contains("Phase 540: whiteboard persistence and render-layer readiness gate", table, StringComparison.Ordinal); - Assert.Contains("TBD", table, StringComparison.Ordinal); + Assert.True( + table.Contains("TBD", StringComparison.Ordinal) + || table.Contains("| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate", StringComparison.Ordinal)); Assert.Contains("graph-selection deletion evidence", table, StringComparison.OrdinalIgnoreCase); Assert.Contains("Core/Editor model contract", table, StringComparison.OrdinalIgnoreCase); Assert.Contains("persistence/schema planning", table, StringComparison.OrdinalIgnoreCase); @@ -1292,6 +1344,15 @@ private static void AssertPostPhase539Queue(string table) Assert.DoesNotContain("| TBD | TBD | Phase 539: rectangle/freehand drawing primitive model gate", table, StringComparison.Ordinal); } + private static void AssertPostPhase540Queue(string table) + { + AssertPostPhase539Queue(table); + Assert.Contains("| #203 | `avalonia-node-map-91b` | Phase 540: whiteboard persistence and render-layer readiness gate", table, StringComparison.Ordinal); + Assert.Contains("Stacked after Phase 539", table, StringComparison.OrdinalIgnoreCase); + Assert.Contains("readiness criteria", table, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain("| TBD | TBD | Phase 540: whiteboard persistence and render-layer readiness gate", table, StringComparison.Ordinal); + } + private static void AssertPhase538WorktreePlan(string plan) { Assert.Contains("feature/phase-537-lasso-toolbar-ergonomics", plan, StringComparison.Ordinal); @@ -1442,7 +1503,7 @@ private static void AssertWhiteboardLassoEraserFeasibilityAudit(string table) Assert.Contains("| Lasso/freehand selection | Public Avalonia lasso selection mode with hosted toolbar activation and transient visual feedback / whiteboard gap retained |", table, StringComparison.Ordinal); Assert.Contains("| Eraser tool | Feasibility gate recorded / gap retained |", table, StringComparison.Ordinal); Assert.Contains("| Rectangle/freehand drawing | Model gate recorded / gap retained |", table, StringComparison.Ordinal); - Assert.Contains("| Whiteboard persistence/render layer | Gap retained |", table, StringComparison.Ordinal); + Assert.Contains("| Whiteboard persistence/render layer | Readiness gate recorded / gap retained |", table, StringComparison.Ordinal); Assert.Contains("https://reactflow.dev/learn/advanced-use/whiteboard", table, StringComparison.Ordinal); Assert.Contains("Freehand draw", table, StringComparison.Ordinal); Assert.Contains("Lasso selection", table, StringComparison.Ordinal);