88 lines
5.2 KiB
Markdown
88 lines
5.2 KiB
Markdown
# Direct state editing — bounded design, 2026-09-05
|
|
|
|
Read-only investigation; implementation and native verification remain pending.
|
|
Connection routing became the user's next priority after this design handoff.
|
|
|
|
## Decision and first task
|
|
|
|
Reuse Diagram/NodePlacement and existing atomic commands. Prefer a typed
|
|
`ProjectionKind::StateMachine { machine: Id }` over desktop-only coordinates or
|
|
a second persisted behavior-layout store. Existing projection strings remain
|
|
valid. Proposed source: `projection StateMachine { machine @operating_modes; };`.
|
|
The context references a same-layer machine and scopes placements to its machine,
|
|
regions and vertices. Explicit creation initializes existing contents in one
|
|
transaction; rendering must not dirty a model. Missing placements remain legal
|
|
and discoverable through an elements-not-shown action.
|
|
|
|
Retain active behavior diagram identity independently of semantic selection;
|
|
selecting a root Event must not switch machines. Diagram context/layout are model
|
|
content; active tool, pointer and zoom remain editor state. Context participates
|
|
in reference remapping/deletion, language reference controls and OpenAPI.
|
|
|
|
The first native task is: create a region and Initial/State; drag a child and a
|
|
composite; draw a transition; reconnect its endpoint; edit its guard; undo/redo;
|
|
save/reopen and inspect the equivalent source/API records. This is the minimum
|
|
vertical slice, not acceptance of all behavior editing.
|
|
|
|
## Existing seams and implementation contract
|
|
|
|
- `behavior.rs:56,118,494`: selection-derived context, selection-only canvas.
|
|
- `behavior/state_scene.rs:24,163`: computed vertical geometry; retain its state
|
|
symbols, internal-transition rows and typed routing, but consume persisted
|
|
shared node geometry. Generic projection drops equal-anchored/self edges and
|
|
includes relationships unsuitable for a state diagram.
|
|
- `behavior/states.rs:73,191`: reuse existing typed transition controls and
|
|
candidate validation. Reconnection edits a clone of the original relation.
|
|
- `model.rs:1235,1247`, `projection.rs:104,184`, `session.rs:562`: reuse placement
|
|
identity, semantic nesting/folding and grouped movement.
|
|
|
|
Events carry diagram identity explicitly: CreateAt(diagram, parent, kind,
|
|
position), Move(diagram, node, position), Connect(diagram, source, target),
|
|
Reconnect(diagram, relation, endpoint, vertex), EditTransition(diagram, relation).
|
|
They lower to existing CreateElement+CreateNode Batch, MoveNode,
|
|
CreateRelation/EditRelation commands. No alternate mutation API is required.
|
|
Gesture state is Idle/Move/Connect/Reconnect with transient preview and a captured
|
|
revision. Release commits once; Escape, stale revision or context change cancels.
|
|
Allocate creation IDs once per accepted plan. Drawing/hit testing/preview consume
|
|
one scene. Extend app.rs:864's draft guard to every mutation gesture.
|
|
|
|
## Required invariants
|
|
|
|
Creation targets the explicitly highlighted semantic Region. Region creation
|
|
targets a machine or stable State/Mode. Dragging never reparents. Moving a
|
|
container moves all descendant placements once, including folded descendants,
|
|
only in that diagram. Child movement preserves ownership and siblings. Resize
|
|
constraints preserve child/header space and movement cannot misleadingly suggest
|
|
ownership by another region. Entry/Exit remain region-owned boundary symbols.
|
|
|
|
Reconnect preserves relation UUID, alias, name, prose, triggers/effects and
|
|
artifact references; validate the full replacement so the old relation is not
|
|
double-counted for cardinality. Do not silently change transition kind or erase
|
|
incompatible data. Internal remains a row/self contract; External self-loops and
|
|
Local edges remain distinct. Cross-immediate-region transitions can be valid;
|
|
cross-machine endpoints reject. Existing history, boundary and orthogonal rules
|
|
in state_validation.rs remain authoritative.
|
|
|
|
Reject invalid drafts without losing them. New tools must not discard unfinished
|
|
behavior drafts. Preserve semantic selection after movement and same-card
|
|
reselection. Context references remap with UUID changes; machine deletion removes
|
|
its dedicated views without deleting cross-layer counterparts. Source-created
|
|
unplaced elements remain discoverable; cross-machine reparenting must also handle
|
|
incompatible placements atomically or reject with an actionable diagnostic.
|
|
|
|
## Partition and evidence gates
|
|
|
|
Core/context owns model.rs, projection.rs, references.rs, validation.rs and focused
|
|
tests. After type freeze, representation owns language.rs, source-project reference
|
|
handling, reST/OpenAPI and round-trip/API tests. Desktop gestures own new
|
|
behavior/state_canvas.rs and state_scene.rs. Lead integrates behavior.rs,
|
|
states.rs, app.rs and diagram context controls. Avoid a general graph framework.
|
|
|
|
Test pointer events at non-100% zoom, one history entry per gesture, exact
|
|
identities, grouped movement limited to one view, atomic rejection, context
|
|
lifecycle and source/JSON/REST equality. Native trial at 1440x900 and 1100x700 uses
|
|
two regions, a nested composite and guarded transitions. Try invalid edges into
|
|
Initial, invalid history reconnection, Escape mid-drag, a folded composite,
|
|
root-Event selection and save/reopen. Record task completion, discoverability,
|
|
ownership clarity and recoverability; no such native result is claimed here.
|