Experiment with guarded cached label association cues

This commit is contained in:
2026-10-01 18:46:59 -07:00
parent 6ea7518e7b
commit 3e5e094bb1
6 changed files with 590 additions and 0 deletions
@@ -0,0 +1,79 @@
# Label association cue candidate B: source handoff
Implemented only in the isolated `codex/label-cue-experiment-01a0d717-20261001`
worktree from `6ea7518e`. No compilation, GUI operation, Gitea mutation, commit,
or production acceptance is claimed. Intent was recorded before source edits in
`label-cue-experiment-intent.md`.
## Changes
- New private `diagram/label_cues.rs` derives an edge-ID-to-cue map. For nonempty
ordinary labels, it clamps the anchor to the label rectangle to obtain the
nearest boundary point. Gap must be strictly greater than 12 world units.
Anchor inside/on the box and normal six-unit gaps produce no cue.
- A cue is omitted if its anchor is within 7 world units of any distinct edge's
segment, if its closed segment intersects any distinct route, any visible card
rectangle, or another ordinary/association-end label rectangle. Touching is
rejected. This includes container rectangles: conservative omission is intended.
- Two production Scene constructors cache cues with their already-routed scene,
using the preview Project where appropriate. Existing cache reuse handles
ordinary selection, hover, zoom and pan without recomputation. Route/placement
previews and revisions that build new scenes recompute the map.
- Canvas draws one-world-unit neutral dotted lines (2 on / 3 off) behind the owning
label's backing. SVG computes the same geometry once per export and uses matching
color, width and dash spacing, with `pointer-events="none"`. There is no marker,
arrowhead, endpoint dot, semantic hit region or stored metadata. Existing SVG
content is retained; the cue is the only intended export addition.
- One existing attachment-test Scene literal received an empty cue map; that test
exercises attachment handles, not label decoration. No unrelated refactor.
Four focused tests are prepared (not run by this agent):
1. Complete representative model admits without errors, retains twelve edges,
derives conversation boundary (1180,274.5) to anchor (1162,274.5), emits an
arrowless SVG cue, and preserves Project and complete routed geometry.
2. A long normal-offset label with only six units of boundary clearance is skipped;
exact 12-unit gap is skipped and 12.25 admitted; a genuinely authored label
centered on its anchor is skipped and stays exact.
3. Shared and six-unit-near landings, intersecting foreign route, card and label
controls suppress the cue. Additional nonintersecting segments six and exactly
seven units LEFT of the anchor are rejected; eight units left is admitted,
isolating the clearance guard from the crossing guard.
4. Actual Scene cache identity and cue map remain identical after selection,
pointer, zoom and pan changes. A changed Project with an authored label centered
on its anchor plus incremented context revision creates a new Scene and removes
the obsolete cue, independently checking invalidation as well as cache reuse.
Parent reproduction selector:
```powershell
cargo test --locked -p oa-desktop diagram::label_cues -- --test-threads=1
```
Parent should format, compile, run appropriate affected diagram/SVG gates and
independently review before native comparison. All changes remain uncommitted.
## Limits and explicit tradeoffs
The cue does not fix the foreign Allocation stroke already running through the
conversation label. It may be too weak at Fit; this is the central native falsifier.
No claim of improved unselected reading follows from source/geometry tests.
Closed rectangle and segment guards use projected geometry, not exact text glyph
or port-symbol contours. Authored label locations are never moved; a blocked cue
is simply omitted. The tests use the established representative scene, not the
user's exact source. There are no camera-dependent admission thresholds, so zoom
does not introduce cue admission flicker; physical dot size still scales normally.
Rebuild cost scans scene routes/cards/labels for each eligible label. No global
optimizer, new index, arbitrary cutoff, or per-hover scan was introduced. Dense
rebuild and route-preview latency remain parent performance gates. Individual
cue guards do not perform cue-to-cue avoidance; multiple eligible leaders can
intersect each other in other scenes. This is an explicit experimental limitation
to inspect before widening scope or making a general rendering claim.
The intended native comparison preserves the complete model, paths, labels and
camera: baseline versus B, plus the saved manual-label control. Fresh reading must
precede Inspector answers, and distinguish correct first association from mere
selectability. Revisit or reject B if wrong association persists, added marks are
mistaken for relationships, other reading worsens, or rendering/preview cost
regresses. Selection disambiguation and automatic-placement A remain separate.
@@ -0,0 +1,37 @@
# Isolated label association cue experiment
Base: 6ea7518e; branch codex/label-cue-experiment-01a0d717-20261001. This is
candidate B for issue 38, not production acceptance. The eight-card view is a
representative reconstruction, not recovered user source. Existing-candidate
automatic-placement feasibility is being investigated separately in Rust.
Before implementation, the intended policy is a private derived straight cue from
the nearest point on a nonempty label's rectangular boundary to its existing
route anchor. Require the anchor outside the box and a gap strictly greater than
12 world units. Reject a landing within 7 world units of any distinct edge's
segment, or a cue intersecting any other route, visible card, or other label
(including association-end labels). Exact thresholds are experimental geometry
controls, not measured perceptual limits. No arrows, junction dots, semantic hit
regions, project fields, route changes, label movement, or hiding/grouping.
Cache derived cues with the existing Scene and render a restrained dotted line
in both canvas and SVG. Camera and selection changes must not change admission or
rescan the scene. Scene rebuilds and actual route previews may recompute cues.
Conservative guards may omit potentially useful cues; omission is not a claim
that association is already clear. Container interception may suppress a cue.
Tests will cover the representative conversation's 18-unit boundary gap, normal
6-unit gap, an authored anchor inside its box, shared/near landing and route/card/
label obstruction. SVG must expose a cue without a semantic arrow/edge marker;
Project and routed geometry must remain unchanged. Parent owns formatting,
compilation, native reading, performance, and independent review.
Native evaluator: compare identical complete baseline and candidate scenes with
fresh reading (no Inspector), first association/selected stroke and confidence,
Fit and working zoom, Request/Report controls, and cue mistaken for a relationship.
Reject if the misplaced conversation still attaches perceptually to the foreign
Allocation, if other reading worsens, or if the cue needs prior explanation. The
existing foreign stroke through the label remains a known risk. Count added cues
and intersections; measure rebuild/preview cost against baseline. Preserve every
semantic identity, port, placement, authored field, path and label; Undo/Redo and
save/reopen remain separate native gates. No compiler or GUI run by this agent.
@@ -0,0 +1,43 @@
# Independent source review: isolated label cue candidate B
No blocker or high-severity source defect found in this frozen experimental diff. It is suitable for the parent's compilation and bounded native/performance experiment, not accepted as a fix or production behavior. No compiler, GUI, Gitea operation or production edit was performed. This report is the only new file.
## Reviewed identity
Base `6ea7518e`; uncommitted changes limited to `crates/oa-desktop/src/diagram.rs`, private `diagram/label_cues.rs`, and the added field in one `diagram/attachment_tests.rs` Scene literal. Read the predeclared experiment intent, source handoff, and the independent design critic from the diagram worktree.
Reviewed file SHA256:
- diagram.rs: `f9f7ff0ffa2f9cc41a2eb95651072a6200b67df1c28f427bd921b92724eaee3e`
- label_cues.rs: `82a819e2d7a1bd03a326a4e1c4bf318a6f6d4e87ebfcf22922253ab78a594055`
- attachment_tests.rs: `1cbfa3d926e8c6d7dcbab2d393ce248dd7e190583886f75165c7d2f5c9e7e127`
## Correctness assessment
The helper consumes immutable Project, ProjectedView and RoutedView inputs and returns only a private cue map. No core model field, semantic endpoint, route point, authored label, projected placement/port, selection policy, hitbox or command changes. Picking still uses original path/label geometry; cue strokes introduce no semantic target.
`label_cues.rs:16-46` implements the stated conservative geometry contract: clamp the route anchor to the label rectangle; omit gaps at or below 12 world units, including anchors inside/on the rectangle; reject closed intersection with every distinct edge's segments; reject landing distance at or below 7; and reject visible card/other ordinary label/association-end label intersections. Distinct edge IDs are retained, so a coincident foreign segment cannot be mistaken for a uniquely owned landing. Node/container suppression is intentional. The closed segment intersection and box tests are consistent for straight finite geometry, including collinear overlap and touching. No measured perceptual clearance is established by these constants.
Caching is attached to the existing Scene, not camera state. Both constructors derive from the geometry actually stored in that Scene. Allocation/work preview uses its own preview Project; ordinary route/node/port previews use the current semantic Project with their derived preview geometry, which is appropriate because these previews alter presentation. Existing context/revision, route, preview and port keys control rebuild; the work cache uses preview Arc identity. No new stale-cache path was found by inspection. Existing caller obligations to update context for model changes remain unchanged.
Canvas and SVG use the same derivation and boundary/anchor endpoints. Both paint the dotted cue after its owning path and before its label backing. The backing hides only the boundary's inward stroke half; the admitted open gap stays outside the box. Guards exclude later unrelated route/label/card centerline/rectangle intersections, addressing the ordinary interleaved rendering-order risk. Color matches MUTED (75,89,104); width and dash values match (1; 2/3). SVG has no arrow marker and uses pointer-events none. Cue endpoints are already within the routed path/label bounds, so no export bounds enlargement is required.
## Meaningful tests and specific coverage limits
The four tests are relevant: representative geometry/SVG and model preservation, boundary gap versus center-distance distinction, obstruction guards, and actual Scene Arc reuse across selection/pointer/camera changes. They do not establish compilation or behavior until run.
Nonblocking evaluator weakness at `label_cues.rs:160-165`: all three foreign vertical segments intersect the cue. In particular x=1168 tests both the six-unit clearance condition and crossing rejection. Removing the landing-clearance predicate would still pass that alleged near-landing control. A future focused control should place a short parallel segment six units from the anchor, outside the cue segment, with a corresponding safely distant positive control. Current production predicate itself is correct by inspection.
Further untested boundaries: exactly 12 versus greater-than-12 gap; exactly 7 versus greater-than-7 landing clearance; collinear/touching rectangles; association-end label obstruction; a safe positive control adjacent to each obstruction; scene invalidation for changed route/revision/work preview. The reuse test does not verify invalidation. These are coverage limitations, not reproduced stale state or geometric defects. The representative test does not assert the complete cue set/count, which the native experiment should record.
## Risks and release boundaries
The known central falsifier is unchanged: target cue length is 18 world units, approximately 9.3 pixels at representative Fit, while the foreign Allocation stroke still passes through the label. Four or so tiny dash elements may be missed or read as a relationship branch. Source correctness cannot show improved first association; require the fresh reading experiment before calling B a fix. This review does not endorse explaining the cue to the reader first.
Admission scans routes/cards/labels per eligible label: approximately O(eligible_labels * (total_route_segments + edges + nodes + association_labels)) per scene build, plus association-label geometry construction. The existing scene cache prevents ordinary hover/selection/camera rescans, but route drag previews can rebuild every changed gesture. Dense rebuild/preview latency remains an actual measurement gate. No demonstrated performance regression is claimed here.
Known limited geometry remains: no cue-to-cue avoidance; no port-symbol, arrowhead, glyph or stroke-width contour avoidance; own-route segments other than the anchor are not tested; no width-scaled guard. These may produce visual interference in other scenes, but no such failure was reproduced in this read-only scope. Do not generalize the straight-centerline/rectangle checks into an all-rendered-marks guarantee. Conservative omission is not proof that a label is already understandable.
The private module is proportionate for an isolated experiment. SVG duplicates width/dash/color literals that canvas receives via constants/style; values agree now, but sharing those values would reduce future drift if the candidate survives. No refactor is required before the bounded experiment.
Retain baseline and B with identical complete model, paths, labels and camera; measure first chosen association, controls, cue count/intersections and preview cost. Publication, native usability, save/reopen and broad accessibility acceptance remain outside this review.