11 KiB
Allocation toolbar correction source review — 2026-09-12
Reviewed 1b3c401a1948cb6f17209d3b2b336993d5e977bb, diff from d9b3f0d, relevant surrounding production paths, new tests and harness/release-allocation-feedback-decision-20260912.md. Reviewer: /root/allocation_checkpoint_review. No compiler, tests, native UI, Gitea, Git mutation or source edits; this report is the sole write. Root owns execution and integration. This is source-derived evidence, not native acceptance.
[P2] Full destination-name tooltip cannot be accessed during or after the drag
Primary location: crates/oa-desktop/src/views.rs:525 (tooltip over the truncated destination text). Related: diagram.rs:897 (held motion dispatch), app/allocation_drag.rs:189 (viewport rejection), :534 (outside feedback), :268 (identity fallback), and :602 (release retirement).
The visible destination is truncated to 28 characters, and its only new full-name access is a hover tooltip on the toolbar. However, moving the held pointer from the target into that toolbar sends a WorkDrag Preview with a position outside the frozen canvas. The resolver returns OutsideViewport; App sets refused feedback with an empty target vector. destination_identity() consequently becomes No eligible destination, and the rebuilt tooltip contains that text rather than the selected target's full name. Releasing before moving to the toolbar also cannot work: release retires feedback, so the slot/tooltip reverts to None · drag work to choose.
Exact user sequence: set the target name to Receiving subsystem WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW (the new full-tree fixture), begin the successful ordinary (40,35) grab and hover the target at (160,140), then, while still holding, move to the destination slot to read the suffix. The destination is replaced before it can be inspected. This does not require a small window, though truncation at 1100×700 makes the promised access particularly relevant. Two target names sharing the first 27 characters have indistinguishable slot text; the full tooltip was intended to resolve precisely this limitation.
The pinned Iced implementation confirms that tooltip activation requires the cursor over its own layout (.local/toolchain/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iced_widget-0.14.2/src/tooltip.rs:222); it neither captures mouse events nor suppresses the held canvas's motion dispatch (:269). Thus the tooltip is not an independent route around outside-canvas feedback. The destination text itself is not a focusable keyboard control.
Provide a full-name inspection path that survives normal pointer movement without making an invalid outside-canvas drop valid. For example, retain an explicitly labeled last-target identity for inspection while the separate validity/status still says the current drop is outside, including after gesture retirement; or display a full-identity detail outside the canvas without requiring the held pointer to leave its target. Preserve the distinction between current valid target and remembered target, stable canvas layout, and the existing outside-release cancellation.
Add an actual mounted hover/inspection sequence and assert full identity after leaving the canvas and after release/cancellation according to the chosen interaction. Current pixel comparisons never hover this tooltip: Mounted::pixels deliberately supplies Cursor::Unavailable (behavior/canvas_workspace/tests.rs:238).
Root's proposed minimal remedy is adequate: retain an immutable captured name/list as inspection context, explicitly labeled Last target or a completed-operation result, while current resolver/preview validity remains separate. During outside motion, the current destination must still be No eligible destination; a tooltip can identify the last target and state that no current drop is valid. After refusal/cancel, label the remembered context as unapplied; after success, a result label can identify the applied target. Clear/replace this context on document/diagram changes or a new gesture. Never feed remembered identity back into target planning or change gesture ownership to show it. Preserve Ambiguous for remembered incomparable targets. This is simpler than introducing a wrapping/scrolling name area, which creates another potential owner of held pointer/scroll input. Verify actual hover, outcome wording, outside-release atomicity, stable bounds and replacement of previous-gesture context.
Correction supported by source inspection
- Original and collapsed counterexamples are repaired. No opaque duplicate name/rectangle is painted by WorkFeedback (
diagram/work_drag.rs:137); the removed label-overlap and frozen-label viewport requirements can no longer exclude every collapsed-header point. The selected work's actual projected header still must fit the viewport (allocation_drag.rs:551). A target placement must still match the accepted visible performer (:518), and the frozen resolver/semantic precedence and ordinary pointer delta remain unchanged. - No geometric workaround was introduced. Target outlines remain tied to captured regions. The exact work snap, subtree translation, target unfold, semantic candidate and command/source equality machinery remain intact. The decision document accurately distinguishes hit-region stability from the incidental name-overlay location, and explicitly supersedes that part of v2 without changing user-owned requirements.
- Refusal and ambiguity identity are consistent for a moved gesture. A chosen target's accepted full name comes directly from the frozen resolver index, including when its semantic/placement candidate is refused. Blocked/outside-canvas feedback has no target and says
No eligible destination; multiple incomparable targets produce the explicitAmbiguous:prefix and all captured names in the underlying identity. Status prose cannot overwrite these names. No wrong-target commit path was established. - Stable layout is designed explicitly. The allocation destination row exists at idle and active states, has fixed height 26, width Fill, and clipping; the explanatory status occupies its separate existing height-30 row (
views.rs:513–540,:590). This is consistent with retaining canvas bounds across a gesture. Full-name tooltip reachability is the specific remaining problem above, not a finding that this row itself moves the canvas mid-drag.
Test fidelity and remaining limits
The new packet tests cover OA/SA Receiver and collapsed-name input through actual frozen target resolution at three transforms and the top-viewport case, exact (120,110) preview/commit, explicit target unfolding, unchanged Project/SourceBundle before release, and complete Undo/Redo. The former label-refusal test now evaluates actual selected-header clipping, preserving the atomicity/redo/cache assertions. Its corrected pointer expression keeps the pointer inside the viewport at zoom 0.75 while the grabbed header remains above the viewport.
The new full-tree test mounts the real App at 1100×700 and 2000×1400, includes the long collapsed name and pan.y=-100, measures destination/canvas rectangles, exercises preview/release, and compares source/history exactly. Pixel comparisons establish that the dedicated row changes from idle to active and that arbitrary status prose does not alter the destination row or canvas. The top-edge case also traverses a genuine clipping refusal and recovers within the held gesture.
These tests are suitable for the repaired geometry and layout composition, subject to execution by root. Pixel inequality is not an OCR/readability assertion; no tooltip activation is exercised, and the new identity helper test checks only empty-target outcomes, not real ambiguous-target UI. The source branching for ambiguity is straightforward and no separate actionable ambiguity defect was established. Do not describe these checks as native packaged acceptance.
No additional actionable outline/text collision was established from this review. The retained outline is still a 3-pixel stroke drawn above the scene, but a general possibility of crossing text is not sufficient evidence for another finding. Actual minimum-window typography, long-name detail access, native event/subscription ordering and packaged workflows remain root-owned acceptance gates.
Bounded recheck of 5ce798b — tooltip finding addressed in source
Reviewed 5ce798b7132f953926c93f93464a69653cd2bc93 against 1b3c401, including the new real-hover test and retained-tree renderer helper. The P2 above is addressed by the inspected source; no new actionable finding was established in this bounded recheck. No compiler, test or native UI was run by this reviewer.
Active::inspection_targets records only the most recent resolved target indices or ambiguous set, and copies them to Feedback for presentation (app/allocation_drag.rs:554–560, :627). inspection_identity() explicitly distinguishes remembered names from the current No eligible destination and says releasing outside cancels (:271). The indices refer to immutable names in this gesture's captured Press; they never enter semantic planning or target resolution. New press initializes an empty vector (:509), and retirement clears active/preview/feedback together (:330), so no postgesture stale identity survives. Keeping inspection gesture-local is sufficient: users can inspect the full name while holding, return to a valid target, then release. The guide now describes exactly that workflow.
The new OA/SA 1100×700 full-tree test (app/allocation_drag_full_tree_tests.rs:557) dispatches target motion followed by actual toolbar hover, checks the refused current destination plus remembered full name, renders with the real hover cursor, and measures the tooltip overlay. It then verifies outside release preserves source/history, a fresh gesture inherits no inspection name, and a subsequent valid drop commits once and undoes completely. This directly targets the prior missing interaction. Its renderer helper preserves the old unavailable-cursor default while adding pixels_at for explicit overlay evidence. Assertions do not by themselves establish every glyph's readability; root's optional captured-render inspection and native acceptance remain separate evidence.
Moving the full-tree success pointer from world y140 to y145 retains the standard (40,35) grab, the same selected snapped position (120,110), the original overlap region, and collapsed-header target. It avoids a floating-point half-grid tie caused by a fractional App origin; the original y140 inputs remain in planner and packet coverage. This does not weaken the corrected destination-readability or collapsed-reachability assertions. Root reports the prior focused run at 1b3c401 passed 60 of 61 with only that exact tie failing; this reviewer did not execute or independently certify either runtime result, and the new focused run remains root-owned.