Support per-view connection boundary attachments in ordinary and state diagrams

This commit is contained in:
2026-09-22 17:51:13 -07:00
parent 3f9e6a18af
commit 79cc9d5551
49 changed files with 3534 additions and 52 deletions
@@ -0,0 +1,53 @@
// Immutable acceptance baseline: copy before editing. Stable IDs are deliberate.
arcadia 7;
project endpoint_acceptance "Harbor dispatch — attachment acceptance" id "ea202922-0033-4000-8000-000000000001" {
description "Small native fixture for presentation-only endpoint editing. Names describe stored source-to-target direction.";
oa_activity receive_report "Receive distress report" id "ea202922-0033-4000-8000-000000000010" { }
oa_activity dispatch_crew "Dispatch rescue crew" id "ea202922-0033-4000-8000-000000000011" { }
interaction dispatch_request "Dispatch request: Receive → Dispatch" id "ea202922-0033-4000-8000-000000000020" { source @receive_report; target @dispatch_crew; description "Semantic sentinel: retain this description and direction."; }
sa_system controller "Rescue readiness controller" id "ea202922-0033-4000-8000-000000000030" { }
sa_state_machine readiness "Rescue readiness" id "ea202922-0033-4000-8000-000000000031" { parent @controller; }
sa_region main_region "Readiness region" id "ea202922-0033-4000-8000-000000000032" { parent @readiness; }
sa_initial start "Startup" id "ea202922-0033-4000-8000-000000000033" { parent @main_region; }
sa_state ready "Ready" id "ea202922-0033-4000-8000-000000000034" { parent @main_region; }
sa_state active "Active" id "ea202922-0033-4000-8000-000000000035" { parent @main_region; }
sa_choice decision "Dispatch decision" id "ea202922-0033-4000-8000-000000000036" { parent @main_region; }
sa_final finished "Shutdown complete" id "ea202922-0033-4000-8000-000000000037" { parent @main_region; }
state_transition initialize "Initialize: Startup → Ready" id "ea202922-0033-4000-8000-000000000040" { source @start; target @ready; transition_kind External; triggers []; trigger ""; guard ""; effects []; effect ""; }
state_transition activate "Activate: Ready → Active" id "ea202922-0033-4000-8000-000000000041" { source @ready; target @active; transition_kind External; triggers []; trigger ""; guard "crew_assigned"; effects []; effect ""; }
state_transition assess "Assess: Active → Decision" id "ea202922-0033-4000-8000-000000000042" { source @active; target @decision; transition_kind External; triggers []; trigger ""; guard ""; effects []; effect ""; }
state_transition retry "Retry: Decision → Ready" id "ea202922-0033-4000-8000-000000000043" { source @decision; target @ready; transition_kind External; triggers []; trigger ""; guard "retry_requested"; effects []; effect ""; }
state_transition finish "Finish: Decision → Shutdown" id "ea202922-0033-4000-8000-000000000044" { source @decision; target @finished; transition_kind External; triggers []; trigger ""; guard "else"; effects []; effect ""; }
state_transition refresh "Refresh: Active → Active" id "ea202922-0033-4000-8000-000000000045" { source @active; target @active; transition_kind External; triggers []; trigger ""; guard "refresh_requested"; effects []; effect ""; }
state_transition internal_check "Internal status check" id "ea202922-0033-4000-8000-000000000046" { source @active; target @active; transition_kind Internal; triggers []; trigger ""; guard ""; effects []; effect "Status unchanged"; }
sa_function emit_status "Emit readiness status" id "ea202922-0033-4000-8000-000000000050" { }
sa_function display_status "Display readiness status" id "ea202922-0033-4000-8000-000000000051" { }
sa_port status_out "Status output" id "ea202922-0033-4000-8000-000000000052" { parent @emit_status; contract { FunctionOutput { outgoing_items []; }; }; }
sa_port status_in "Status input" id "ea202922-0033-4000-8000-000000000053" { parent @display_status; contract { FunctionInput { incoming_items []; }; }; }
functional_exchange status_exchange "Readiness status: Emit → Display" id "ea202922-0033-4000-8000-000000000054" { source @emit_status; target @display_status; source_port @status_out; target_port @status_in; items []; }
diagram dispatch_view "01 Dispatch — edit attachments" id "ea202922-0033-4000-8000-000000000100" { layer Oa; projection FunctionalDataflow; routes [{ edge @dispatch_request; waypoints [{ x 440; y 340; }]; label { fraction 0.5; offset { x 12; y -18; }; }; source_attachment { side Right; offset 0.5; }; target_attachment { side Left; offset 0.6; }; }]; }
diagram dispatch_reference "02 Dispatch — untouched reference" id "ea202922-0033-4000-8000-000000000101" { layer Oa; projection FunctionalDataflow; routes [{ edge @dispatch_request; target_attachment { side Bottom; offset 0.25; }; }]; }
node dispatch_view_receive id "ea202922-0033-4000-8000-000000000110" { diagram @dispatch_view; element @receive_report; position { x 100; y 180; }; size { width 240; height 120; }; collapsed false; }
node dispatch_view_dispatch id "ea202922-0033-4000-8000-000000000111" { diagram @dispatch_view; element @dispatch_crew; position { x 600; y 180; }; size { width 240; height 120; }; collapsed false; }
node dispatch_reference_receive id "ea202922-0033-4000-8000-000000000120" { diagram @dispatch_reference; element @receive_report; position { x 100; y 180; }; size { width 240; height 120; }; collapsed false; }
node dispatch_reference_dispatch id "ea202922-0033-4000-8000-000000000121" { diagram @dispatch_reference; element @dispatch_crew; position { x 600; y 180; }; size { width 240; height 120; }; collapsed false; }
diagram readiness_view "03 Readiness — edit attachments" id "ea202922-0033-4000-8000-000000000200" { layer Sa; projection { StateMachine { machine @readiness; }; }; routes [{ edge @activate; waypoints [{ x 500; y 310; }]; label { fraction 0.5; offset { x 8; y -16; }; }; source_attachment { side Right; offset 0.5; }; target_attachment { side Left; offset 0.6; }; }, { edge @initialize; source_attachment { side Right; offset 0.5; }; }, { edge @finish; source_attachment { side Right; offset 0.5; }; }]; }
diagram readiness_reference "04 Readiness — untouched reference" id "ea202922-0033-4000-8000-000000000201" { layer Sa; projection { StateMachine { machine @readiness; }; }; routes []; }
node readiness_view_readiness id "ea202922-0033-4000-8000-000000000210" { diagram @readiness_view; element @readiness; position { x 40; y 40; }; size { width 980; height 590; }; collapsed false; }
node readiness_view_main_region id "ea202922-0033-4000-8000-000000000211" { diagram @readiness_view; element @main_region; position { x 64; y 104; }; size { width 932; height 500; }; collapsed false; }
node readiness_view_start id "ea202922-0033-4000-8000-000000000212" { diagram @readiness_view; element @start; position { x 110; y 212; }; size { width 20; height 20; }; collapsed false; }
node readiness_view_ready id "ea202922-0033-4000-8000-000000000213" { diagram @readiness_view; element @ready; position { x 190; y 170; }; size { width 240; height 120; }; collapsed false; }
node readiness_view_active id "ea202922-0033-4000-8000-000000000214" { diagram @readiness_view; element @active; position { x 570; y 170; }; size { width 240; height 140; }; collapsed false; }
node readiness_view_decision id "ea202922-0033-4000-8000-000000000215" { diagram @readiness_view; element @decision; position { x 670; y 430; }; size { width 40; height 40; }; collapsed false; }
node readiness_view_finished id "ea202922-0033-4000-8000-000000000216" { diagram @readiness_view; element @finished; position { x 880; y 440; }; size { width 24; height 24; }; collapsed false; }
node readiness_reference_readiness id "ea202922-0033-4000-8000-000000000230" { diagram @readiness_reference; element @readiness; position { x 40; y 40; }; size { width 980; height 590; }; collapsed false; }
node readiness_reference_main_region id "ea202922-0033-4000-8000-000000000231" { diagram @readiness_reference; element @main_region; position { x 64; y 104; }; size { width 932; height 500; }; collapsed false; }
node readiness_reference_start id "ea202922-0033-4000-8000-000000000232" { diagram @readiness_reference; element @start; position { x 110; y 212; }; size { width 20; height 20; }; collapsed false; }
node readiness_reference_ready id "ea202922-0033-4000-8000-000000000233" { diagram @readiness_reference; element @ready; position { x 190; y 170; }; size { width 240; height 120; }; collapsed false; }
node readiness_reference_active id "ea202922-0033-4000-8000-000000000234" { diagram @readiness_reference; element @active; position { x 570; y 170; }; size { width 240; height 140; }; collapsed false; }
node readiness_reference_decision id "ea202922-0033-4000-8000-000000000235" { diagram @readiness_reference; element @decision; position { x 670; y 430; }; size { width 40; height 40; }; collapsed false; }
node readiness_reference_finished id "ea202922-0033-4000-8000-000000000236" { diagram @readiness_reference; element @finished; position { x 880; y 440; }; size { width 24; height 24; }; collapsed false; }
diagram ports_view "05 Status — semantic ports regression" id "ea202922-0033-4000-8000-000000000300" { layer Sa; projection FunctionalDataflow; routes []; }
node ports_emit id "ea202922-0033-4000-8000-000000000310" { diagram @ports_view; element @emit_status; position { x 100; y 180; }; size { width 240; height 120; }; collapsed false; port_anchors [{ port @status_out; side Right; offset 0.5; }]; }
node ports_display id "ea202922-0033-4000-8000-000000000311" { diagram @ports_view; element @display_status; position { x 600; y 180; }; size { width 240; height 120; }; collapsed false; port_anchors [{ port @status_in; side Left; offset 0.5; }]; }
}
@@ -0,0 +1,66 @@
# Native endpoint attachment acceptance
This is a prepared plan, not a record of passed native checks. `native-fixture.arcadia` is a deliberately small schema-7 source fixture with 49 explicit stable UUIDs. The parent must parse and validate it with the candidate before staging a working copy. No GUI, compilation, or evaluator has been run for this preparation.
## Bind the run
Record the exact candidate commit, source/worktree cleanliness, GUI/runtime hashes, successful gate receipts, fixture hash and recipe hash. Keep an immutable baseline and a separate mutable working source; use an isolated profile. Record launch, normal close, stdout/stderr, saved checkpoints, and captures. Compile baseline and checkpoints to full typed Project values with the same pinned source evaluator. Use a baseline-derived expected Project with only the named field changes; compare the entire Project, not a JSON subset or screenshot. Source text formatting may differ after save; source must parse to the exact expected Project. Save/reopen comparisons must use the same expected Project. Preserve raw files and integer precision.
The fixture contains two OA activities and their one interaction, one small SA state machine, and a separate two-function semantic-port regression view. Its controller is semantic ownership, not a large canvas placement. The State view places the machine, region, and all five vertices. Two saved views per edited graph expose view-isolation failures. View 05 is separate to keep the main workflows uncluttered.
## Identities and geometry
Every ID has prefix `ea202922-0033-4000-8000-`; the twelve-digit suffix below is decimal-padded. The source file is authoritative for all fields.
| Object / alias | ID suffix | Purpose |
|---|---:|---|
| `dispatch_request` | 20 | Stored source `receive_report` (10), target `dispatch_crew` (11) |
| `dispatch_view` / `dispatch_reference` | 100 / 101 | Edited OA view / untouched OA view |
| `readiness` / `main_region` | 31 / 32 | Machine / region membership |
| `start`, `ready`, `active`, `decision`, `finished` | 33–37 | Initial, two stable states, choice, final |
| `activate` | 41 | Stored Ready source → Active target |
| `initialize` / `finish` | 40 / 44 | Circle-source / diamond-source contour checks |
| `refresh` / `internal_check` | 45 / 46 | External self-transition / internal row |
| `readiness_view` / `readiness_reference` | 200 / 201 | Edited State view / untouched State view |
| `status_exchange` / `ports_view` | 54 / 300 | Real semantic ports regression |
Coordinates below are **diagram coordinates**, not assumed native screen coordinates. After Fit, identify bounds and zoom/pan from actual UI; map `window = canvas origin + pan + zoom × diagram`. State canvas includes a guidance strip in its offset. Confirm painted handles before pressing; retain screenshots documenting the mapping. Source and target describe stored ends, regardless of arrow appearance.
| View / endpoint | Baseline attachment / contour point | Intended destination |
|---|---|---|
| OA `dispatch_request` source | Right 0.5 → (340,240) | Top 0.25 → (160,180) |
| OA `dispatch_request` target | Left 0.6 → (600,252) | Bottom 0.75 → (780,300) |
| State `activate` source | Right 0.5 → (430,230) | Top 0.25 → (250,170) |
| State `activate` target | Left 0.6 → (570,254) | Bottom 0.75 → (750,310) |
| State `initialize` initial source | Right 0.5 → (126,220) | Top 0.5 → (118,212) |
| State `finish` choice source | Right 0.5 → (698,444) | Top 0.5 → (684,430) |
| Real `status_out` / `status_in` | Right 0.5 → (340,240) / Left 0.5 → (600,240) | No attachment editing permitted |
For rounded corners, the quarter-width points are on the straight section. Circle and diamond checks intentionally use contour extrema with unambiguous 0.5 offsets. Native drag input may quantize to adjacent hundredths: if the intended fraction is not attained, do not change the expected oracle to match output. Repeat from the prior checkpoint using the painted geometry, or record the observed limitation and narrow the claim.
## OA workflow and exact expectations
1. Open view **01 Dispatch — edit attachments** and Fit. Select `Dispatch request` on its line. Confirm distinct endpoint handles and context actions. Save baseline checkpoint `00` before edits; full Project equals baseline B.
2. Drag source handle from (340,240) to (160,180), inspect live preview and release. Save `01`. Expected O1 = B with **only** `diagrams[100].routes[edge20].source_attachment = {Top,0.25}`. Target sentinel `{Left,0.6}`, waypoint `(440,340)`, label `{fraction:0.5,offset:(12,-18)}`, relation description/direction, nodes and all other views remain exact.
3. Undo and save `02`: B exactly. Redo and save `03`: O1 exactly. One Undo must remove the entire drag, not a partial movement.
4. Drag target to (780,300), save `04`: O2 = O1 with only target `{Bottom,0.75}`. Open source and target context actions to ensure end identity is clear. Use **Reset source attachment**, save `05`: O3 = O2 with source None; preserve target, waypoint and label. Undo returns O2, redo returns O3.
5. Start a drag, move away and return within three screen pixels of the press, then release: no source/history change. Repeat a drag canceled with Escape; repeat with right click, middle pan, wheel/camera change, focus loss, and release outside. Save a checkpoint after each meaningful cancellation; expect O3 exactly. Camera-only state is outside Project. After these checks, one Undo still reverses the last real reset (O2), showing no hidden history entry; Redo restores O3.
6. Open view **02 Dispatch — untouched reference**: its independent target `{Bottom,0.25}` and placements remain baseline. Return to 01, save, close normally, reopen the saved working file and save `06`: O3 exactly. Confirm the saved source contains the attachment and existing waypoint/label.
## State workflow and exact expectations
Continue from saved O3 so the State trial also proves preservation of the prior OA edits. The frozen expected catalog composes State changes on O3; B remains the unchanged comparison for view 201.
1. Open **Rescue readiness** in Behavior / State diagram and choose **03 Readiness — edit attachments**. Check source-defined membership is visible, with Ready and Active readable and no nested hierarchy. Select `Activate`; choose **Adjust source attachment** from its actions, then drag the highlighted source to (250,170). Save `S01`: S1 = O3 with only `diagrams[200].routes[edge41].source_attachment={Top,0.25}`. Preserve target `{Left,0.6}`, waypoint `(500,310)`, label `{fraction:0.5,offset:(8,-16)}`, all semantic transitions and view 201.
2. Undo → O3, redo → S1. Adjust target to (750,310), save `S02`: S2 adds only target `{Bottom,0.75}`. Reset target and save `S03`: S3 has target None, preserves source/bend/label. Cancel an attachment gesture with Escape and perform away-return and wheel interruption; checkpoints remain S3. View **04 Readiness — untouched reference** stays B exactly.
3. Choose `Initialize` → **Adjust source attachment**, drag the initial circle source to (118,212), save `S04`: S4 = S3 with only route edge40 source `{Top,0.5}`. Choose `Finish` → Adjust source, drag the choice source to (684,430), save `S05`: S5 = S4 with only route edge44 source `{Top,0.5}`. Capture both painted contours; the typed checkpoint is the persistence oracle. Undo/redo each as practical. Save/normal-close/reopen final checkpoint: S5 exactly.
4. Inspect external `Refresh: Active → Active`: both Adjust source and Adjust target must be discoverable and identify the corresponding end even on a self-transition. Inspect `Internal status check` row: it must not offer external attachment handles/actions. Do not infer every symbol was exercised from these checks.
5. **Separate reversible reconnect trial from S5:** with Select / move, drag the selected `Activate` target handle from Active to `Dispatch decision` (or use explicitly labelled Reconnect target). Expected R1 differs from S5 only in relation41's semantic target: 35 → 36. Route presentation fields and every other relation field remain unchanged. Undo must restore S5. This distinguishes semantic reconnect from Adjust; do not mix its checkpoint with S5. If cardinality/validity blocks the trial, record it and do not claim reconnect success without a valid alternative approved against source rules.
## Real semantic ports regression
Open **05 Status — semantic ports regression**. Select the `Readiness status` functional exchange. Both attachment Move/Reset actions must be disabled or absent because source_port52 and target_port53 remain authoritative. Drag Status output to its owner's Top/0.25 position through the established port-layout interaction, then Undo. That trial may change only the emitting node's port_anchor and must restore S5 exactly on Undo; relation/source_port/target_port identities must never change. No edge-attachment record should be created by port dragging. Record UI hit selection and full saved Project, then leave this trial out of the final OA/State checkpoint.
## Acceptance and limits
Require exact full-Project checks for every named checkpoint, normal-close/reopen retention, source/target discoverability, useful previews, and cancellation without hidden history. Inspect native fit/readability and any port/label/handle overlap; reduce claim or fix defects rather than interpreting screenshots as model proof. This fixture does not establish Process/Scenario authoring support, all state symbols, every projection, promoted/folded endpoints, continuous held-motion performance, or exact camera persistence. Those require separate evidence; targeted automated tests remain complementary. Runtime source parsing/validation and native execution are pending parent gates.