Files
ARCADIA-Studio/harness/experiments/behavior-navigation-review-20260912/diagram-navigation-remaining-coverage-20260912.md
T

16 KiB

Remaining diagram navigation coverage: verified correction seams

Read-only review, 2026-09-12. Scope: #14/#17 in .local/diagram-usages-ytr83r-20260912; current frozen, uncommitted working sources, not a release acceptance claim. No production changes, compilation, tests, UI interaction, or Gitea writes were performed by this review. Root owns integration and verification. Paths below are relative to that worktree.

Decision

Both gaps are actual representations omitted by the current query. Preserve the current render/projection rules, and add explicit target identities plus presentation highlighting. A caller-preview arrow is not identified by the underlying relation ID alone. An allocation grouping's selected semantic object must remain the Allocation relation, independently of the work placement used for focus/highlight.

Issue requirements: #14 requests textual-symbol diagram references and jumps to the corresponding element; #17 requests equivalent tree navigation. Peer boundaries were read directly in #3 comment 616 and comment 627. Peer confirms the direct-relation/visible-ancestor predicate below, requires separate semantic versus placement identity for Delete, and requires retiring gesture/context lifetimes even for equal-valued navigation. Peer test evidence is not evidence for this worktree.

Verified representation

  • crates/oa-desktop/src/behavior/topology.rs:904: sequence_links returns actual SequenceLink relations whose two contributions belong to the requested process/chain.
  • topology.rs:914 (GraphNode), especially :922: preview_links stores only (OccurrenceEndpoint, OccurrenceEndpoint). The relation ID is lost, unlike GraphEdge.id at :942.
  • topology.rs:1094 and :1128: each SequenceReference obtains the same bounded qualified preview tiles used by painting, then includes the reused definition's links only when both exact endpoints with references = [caller_reference_id] occur in the visible preview set. The normal bound is four tiles; expanded references allow 512. It does not add arrows for every deeper nested definition merely because nested tiles have been expanded.
  • crates/oa-desktop/src/behavior/topology/contextual.rs:253: preview traversal resolves qualified endpoints through TopologyIndex; it preserves each caller path and applies the visibility limit.
  • topology.rs:1568: the painter draws every retained preview link from the source tile's right center to the target tile's left center. Tile rectangles are then painted opaquely at :1581. Therefore the arrow's visible portion can be smaller than its raw line segment. These are real painted arrows, distinct from Graph.ordered_paths, whose explicit contract says they are projected adjacency without persisted relation IDs.
  • topology.rs:926: endpoint_rect has a whole-reference proxy fallback. A usages query must continue rejecting that fallback, as existing usages.rs:81 does for qualified tiles.
  • crates/oa-desktop/src/behavior/topology/usages.rs:89 and :123: current relation lookup considers graph.edges; it never scans node.preview_links. Thus a real caller arrow is absent even when the same relation has a normal link usage on its definition surface.
  • crates/oa-desktop/src/behavior/topology/direct.rs:540: edge hit testing is also restricted to Graph.edges. :105 and :111 implement occurrence context, not qualified relation selection. topology/view.rs:179 copies that occurrence context into graph.selected_preview; topology.rs:1583 highlights tiles with it. Reusing that context to mean an edge would conflate authoring semantics.
  • crates/oa-core/src/validation.rs:2437 forbids SequenceLink self endpoints; :2453 requires contributions directly owned by the same process/chain. Navigation should nevertheless reject missing/degenerate geometry, rather than using an enclosing box fallback.

Minimal correction

  1. Replace the preview endpoint pair with a small record retaining actual relation ID and the same two qualified endpoints. Populate it from the existing filtered relation loop. Do not add traversal, widen preview limits, or change which arrows are painted.
  2. Add a target such as ProcessPreviewLink { relation, source: OccurrenceEndpoint, target: OccurrenceEndpoint }. The enclosing Surface::Process(owner) plus these fields distinguishes repeated caller instances, parallel relations, and retargeting. The existing unqualified ProcessLink(Id) remains appropriate for normal graph edges.
  3. Share the record's exact arrow geometry between painting and usages. A midpoint of the raw segment may fall under an opaque tile; use a visible segment/gap for focus. A small helper can subtract the preview tile rectangles from the straight segment and choose a remaining segment. Require some visible nondegenerate geometry; never manufacture a row from endpoint membership alone when no arrow is emitted. This helper may be tested without changing routing or the visual layout.
  4. Query the actual retained records, with subject == record.relation. The chooser label must include the caller path, and its role should distinguish a preview sequence link. Do not emit links for ordered-path adjacency, arbitrary nested source links, or referenced work merely because it is an endpoint.
  5. Add dedicated transient preview-link presentation selection, then paint exactly that record with a selected stroke. Keep App.selected = relation, and clear occurrence selection for this target. Do not put an edge into selected_context, which is validated as an occurrence and feeds contribution operations. New canvas authoring/hit-test behavior is not necessary for the navigation fix.
  6. Revalidation uses the existing one-surface query and exact target equality. Both endpoints must still resolve and the same record must still be emitted under the current expansion snapshot. Reopening after a changed accepted revision may refresh; the stale Choose event must not jump. Existing asynchronous snapshot behavior remains sufficient: no draft, camera, or selection state needs to cross the worker boundary.

Independent expectations

  • A definition's link rendered in two caller invocations yields two distinct caller targets plus its normal definition target. Choosing either keeps semantic selection equal to the relation ID while highlighting and centering the correct qualified arrow.
  • A link touching the fifth hidden tile has no default caller row. Expanding only the first invocation adds that invocation's arrow, not its sibling's. Collapsing or retargeting invalidates the old target.
  • Deeper expanded tiles alone do not cause usages for deeper links that the existing painter never emits. Ordered adjacency without an actual SequenceLink remains absent.
  • Parallel relations retain distinct relation identities even if current preview geometry overlaps. Reverse/cross-row links focus a visible line segment, not an opaque tile interior.
  • Update topology/usages/tests.rs's current process_contextual_purpose_is_a_visible_reference_but_preview_arrows_are_not_links expectation specifically for retained preview records; preserve its exclusion of other unrepresented links.
  • Exercise actual App update with open/completion/choose, old token/revision/document, reference retargeting, modal/draft protection, repeat choice, and preserved Project/SourceBundle/revision/dirty/history. Assert exact qualified selection and bounds, not merely that the destination page opened.

B. Allocation relations represented by grouping

Verified representation

  • crates/oa-core/src/projection.rs:81, parents: Allocation projection computes actual placement parents using the effective allocation summary and nearest placed coherent work ancestors, with performer fallback. This is visual containment, separate from semantic ownership.
  • projection.rs:274 projects compatible placed nodes. Around :300, a collapsed ancestor or cycle prevents a descendant from entering visible view.nodes. Around :331, the resulting node records visual_parent; :350 encloses containers with projected header geometry.
  • projection.rs:393: Allocation relations are intentionally suppressed as arrows in Allocation projection. Looking only at projected edges cannot find their grouping representation.
  • projection.rs:331 and crates/oa-core/src/validation.rs:2812: allocation summary is explicitly aggregate display information, never an inherited Allocation relation. A summary node without a direct incoming Allocation is marked for dashed presentation. This does not authorize generating a relation usage.
  • crates/oa-desktop/src/diagram.rs:1015 derives visible containers from visual_parent; :1021 paints containers before edges/children. :1129 repaints container headers above traversing relationships. :1452 paints nodes; selection is based on element.id == selected. Summary styling is separate, including node_header at :1509.
  • crates/oa-desktop/src/app.rs:718 (selected_architecture_placement) derives a placement from App.selected; refresh_draft immediately recomputes selected_node from it. app/diagram_usages.rs:380 currently writes selected_node, but calls refresh_draft at :395. Setting relation semantic selection plus selected_node = work_placement alone therefore does not preserve focus, and the current renderer would not highlight that work. The same architecture seam applies to ports: Target::Port sets semantic selection to the port and owner placement separately, then draft refresh cannot find a node whose element is the port and clears selected_node. Root identified the existing port_navigation_selects_port_and_exact_visible_owner_without_editing_geometry expectation as affected while the frozen gate runs; this review did not execute it. State rows initially set behavior.diagram.placement (app/diagram_usages.rs:330), but the rest of refresh_draft (app.rs:734) recomputes that field using the same selected-node/element comparison when state_context resolves. Thus relation selection can clear that exact placement too. The renderer can still paint a row from selected relation identity; placement reset alone does not prove a visible row-highlight failure. Preserve and verify both semantic selection and the intended exact presentation identity.

Confirmed predicate and minimal correction

For an actual direct RelationKind::Allocation r, in a saved Allocation projection only:

  1. Obtain actual visible projected nodes whose element IDs are r.source (performer) and r.target (work).
  2. Walk the target work placement's visual_parent chain through visible projected placements with a visited set.
  3. Emit a grouping usage only if that chain contains the source performer placement. Retain the actual relation ID and the exact work and performer placement IDs.

This is precisely the peer-approved comment 616/627 predicate. It is not inferred from allocation_summary, two visible endpoints, a decomposition parent, or arbitrary semantic containment. Do not change core allocation validation, parents, drag/reparent commands, persistence, or peer Delete behavior.

Use an explicit target such as AllocationGrouping { relation, work_placement, performer_placement }, with role allocation grouping and the projected work's bounded labelled-header rectangle. Reuse the existing bounded node-header camera policy. This target makes the distinction reviewable; neither Placement(work) nor an unrelated StateRow target expresses it correctly.

Keep selected semantic identity equal to the queried relation. Add a separately validated presentation focus/highlight for the exact work placement, surviving refresh_draft; pass it to the architecture renderer independently of the semantic selection. Prefer a typed focus carrying document, revision, diagram, relation, placement, and navigation epoch, so normal selection/document changes cannot reuse stale focus. An alternative is deriving highlight from selected relation and projected grouping each paint; that avoids stored focus but needs proof it preserves exact placement when multiple representations exist. Do not silently change selection to work to reuse the current stroke logic. Use the same separation for architecture ports, while preserving state-view placement semantics. Do not blindly restore selected_node after refresh: coordinate its edit/Delete meaning first. Independent App tests should assert the exact validated visual marker (port owner, grouping work, or state row) and unchanged semantic target, rather than requiring an overloaded global edit-selection field.

Coordinate this presentation focus with the peer's Delete capture: removal continues to capture the selected relation as semantic target; focus placement is separate context, never a replacement semantic target. Explicit later user selection of work can of course change the target. Preserve app/diagram_usages.rs:382's unconditional canvas epoch increment, menu closure, bend/connection reset, and every pending-draft guard, including navigation returning to equal values. Extend deferred reveal to validate the same grouping target; its temporary pending tuple is consumed after layout and should not double as persistent highlight state.

Independent expectations

  • A visible direct allocation with the performer's placement on the actual work ancestor chain produces one grouping row and focuses that exact work header, even when the performer is not its immediate visual parent.
  • Hidden/folded work, hidden performer, wrong projection, endpoints that are merely both visible, a mismatching visual-parent chain, and aggregate-only summary produce no direct Allocation usage.
  • A direct child allocation underneath a summary container remains discoverable if its target is visible and its performer occurs in the chain. No extra relation is invented for the summary container.
  • Choosing preserves the complete model/source/history and leaves App.selected == relation; highlighting work does not make a subsequent Delete capture target work. Test this against peer's integrated removal contract, not by assuming current adapter state alone proves it.
  • Fold/delete/retarget/diagram replacement invalidates an old grouping target. Repeat navigation retires old canvas/context tickets even when destination/selection values compare equal. Both initial and deferred camera reveal reject stale document/revision/epoch.

Integration boundary and source identity

Suggested bounded production seams: diagram_usage.rs target/query/label; behavior/topology.rs preview record/geometry/paint; topology usages.rs query/reveal and view.rs selection wiring; minimal topology presentation-state field; App adapter and architecture canvas presentation-focus wiring. Root coordinates shared App/view changes and peer Delete compatibility. No model/schema/dependency or allocation-authoring changes are required.

Verified SHA-256 snapshots (raw file bytes):

File SHA-256
behavior/topology.rs dff564d2dca68af02874878cabdabdcb7f717bff67b221d376ccb6734a2e16ae
behavior/topology/usages.rs d1ff2f16695d560bd2676825eb6c11d82b0c259cc84d6804dc2dbd1a8dadc42c
diagram_usage.rs 11ed6c844148eba6a122c675168561e9e9dc4e88399ae4fc0facfb82d79bdd89
app/diagram_usages.rs 2374a9323bf422c8cb1af7832aa2c3ce3294a894f1fc710ba165c557b26d8c8b
oa-core/src/projection.rs 69ed12bace2cc5024e151752a174ab14034ac2d05eb741fcf13e9a27521c059b
oa-core/src/validation.rs 7c1b4ae5e4ebba13e99af9158ccde138dfc5e9a7afb580e76fba72d0b64ba74e

Line references describe these inspected working files. Root's in-progress checks cover the frozen implementation before these proposed corrections, not the proposal. Root should implement after the freeze, run focused query/App tests plus required project checks, and inspect actual repeated-call arrow and allocation-grouping navigation with semantic selection/Delete capture before accepting coverage.