State machine: gelöschter Zustand hinterlässt hängende Kanten #60

Closed
opened 2026-09-12 18:02:40 +02:00 by meleki · 1 comment
Owner

Entscheidung in #51 (Punkt 2): Port-Keys sind die State-Ids; ein gelöschter Zustand lässt die Exec-Kante an State branch/Set state hängen „wie jeder weggefallene Port“ – der Port ist weg, die Kante bleibt im edges-Array und wird nicht gezeichnet.

Zu bauen:

  • Sichtbar machen: Der Inspector des Nodes (oder ein Warn-Marker am Node) listet Kanten zu Ports, die es nicht mehr gibt, mit „Kante entfernen“.
  • Oder beim Löschen eines Zustands im State-machine-Tab die Nutzung anzeigen (usages kennt Assets, nicht Ports): „Zustand wird in 2 Behaviors verwendet“ – mit Undo bleibt es gefahrlos.
  • Prüfen, ob dasselbe schon für andere abgeleitete Ports gilt (Struct-Felder an Pack/Expand, Variablen-Ports) – dann gehört die Lösung in den generischen Kanten-Code, nicht in die State machine.

Folge-Issue zu #51 (State machine, Commit e7d82bd, 2026-09-12).

Entscheidung in #51 (Punkt 2): Port-Keys sind die State-Ids; ein **gelöschter Zustand** lässt die Exec-Kante an `State branch`/`Set state` hängen „wie jeder weggefallene Port“ – der Port ist weg, die Kante bleibt im `edges`-Array und wird nicht gezeichnet. **Zu bauen:** - Sichtbar machen: Der Inspector des Nodes (oder ein Warn-Marker am Node) listet Kanten zu Ports, die es nicht mehr gibt, mit „Kante entfernen“. - Oder beim Löschen eines Zustands im State-machine-Tab die Nutzung anzeigen (`usages` kennt Assets, nicht Ports): „Zustand wird in 2 Behaviors verwendet“ – mit Undo bleibt es gefahrlos. - Prüfen, ob dasselbe schon für andere abgeleitete Ports gilt (Struct-Felder an `Pack`/`Expand`, Variablen-Ports) – dann gehört die Lösung in den generischen Kanten-Code, nicht in die State machine. --- Folge-Issue zu #51 (State machine, Commit `e7d82bd`, 2026-09-12).
meleki added the state-machine label 2026-09-12 18:02:40 +02:00
admin added this to the Development project 2026-09-13 13:29:59 +02:00
admin moved this to Next in Development on 2026-09-13 18:02:37 +02:00
admin moved this to Queue in Development on 2026-09-14 06:39:09 +02:00
admin moved this to Next in Development on 2026-09-14 11:08:47 +02:00
Author
Owner

Gebaut als Geister-Port: die Kante verschwindet nicht, sie wird als nicht wirklich verbunden lesbar — rote gestrichelte Kurve, hohler roter Pin, Zeile N edge(s) on a port that is gone, roter Rahmen am Node.

Punkt 3 des Issues trifft zu, aber weiter als vermutet. Es ist nicht ein Weg, sondern vier — und die State machine ist nur einer davon:

Was man tut Was verschwindet
Zustand im Machine-Tab löschen ein Exec-Port je State branch/Set state
das State machine-Literal löschen / Kante kappen alle State-Ports auf einmal (machineOf folgt der Kante)
Behavior start/end löschen alle abgeleiteten Ports jedes Run behavior-Aufrufers
Behavior-/Machine-Asset löschen dito, projektweit

Gemeinsame Ursache ist RemoveNodeCommand: es räumt per edgesOfNode nur den eigenen Graph. Deshalb sitzt die Lösung im generischen Kanten-Code — drawnDef in graph/nested.ts deckt alle vier, ohne eine einzige Löschstelle anzufassen.

Zur Einordnung: nur abgeleitete Ports (derivePorts) verschwinden spurlos. Feste (def.inputs/outputs) verschwinden nie, deklarierte (node.ports) nur über RemovePortCommand, das seine Kanten mitnimmt — auch über Assets hinweg. Fällt die Grundlage eines deklarierten Ports weg, bleibt der Port stehen und portSection schreibt "x" is not a variable of … daneben.

Warum der Geist und nicht bloß ein Warn-Marker: der Rechtsklick auf eine Kante geht im ganzen Editor ausschließlich über view.portAt — einen Kurven-Hit-Test gibt es nicht. Ohne Portzeile ist so eine Kante nicht bloß unsichtbar, sie ist unerreichbar. Der Geist ist also der einzige Griff, an dem Disconnect hängen kann.

resolveDef bleibt unberührt. Es ist die Wahrheit für Interpreter, Compiler, ConnectCommand, dropTarget und openPaletteForDrop — dadurch kann durch einen Geist nichts laufen und nichts verbunden werden, ganz ohne zweite Sperre. Beim Gegenprüfen bestätigt: openPaletteForDrop gibt bei fromType === undefined von selbst auf. Ein Linksklick am Geist-Pin tut nichts (die erste Fassung verschob sonst den Node).

Geprüft: ./check.sh → CHECK EXIT 0, 943 Tests (935 + 8 neue, tests/core/ghost-ports.test.ts). e2e Modul 26 → ALL PASSED – 33 Checks (26 + 7 neue), E2E EXIT 0. Screenshot angesehen: gestrichelte rote Kante zum zweiten Log, während State 1 weiß und durchgezogen bleibt.

Acht Verbiegungen — sieben beißen: drawnDef ohne Geister (5 Unit-Tests) · nur Input-Seite (1) · Singular/Plural (1) · Geister vorne statt hinten (1) · Canvas ohne drawnDef (3 FAILED, ghosted: ["State 1"] — wörtlich der Issue-Zustand) · Warn-Marker weg (1 FAILED, null) · Drag-Sperre weg (1 FAILED, dangling: true). Die achte biss nicht und fand damit toten Code: die Dedup über edge.id bräuchte eine Selbstkante, und ConnectCommand verbietet die — ersatzlos vereinfacht.

Nicht gebaut: kein Inspector-Eintrag, kein automatisches Aufräumen, keine Nutzungswarnung beim Löschen eines Zustands.

Commit a041322, Wiki 6e524c2 (State-machines, Behaviors, Development).

Gebaut als **Geister-Port**: die Kante verschwindet nicht, sie wird als *nicht wirklich verbunden* lesbar — rote gestrichelte Kurve, hohler roter Pin, Zeile `N edge(s) on a port that is gone`, roter Rahmen am Node. **Punkt 3 des Issues trifft zu, aber weiter als vermutet.** Es ist nicht ein Weg, sondern vier — und die State machine ist nur einer davon: | Was man tut | Was verschwindet | |---|---| | Zustand im Machine-Tab löschen | ein Exec-Port je `State branch`/`Set state` | | das `State machine`-Literal löschen / Kante kappen | **alle** State-Ports auf einmal (`machineOf` folgt der Kante) | | `Behavior start`/`end` löschen | alle abgeleiteten Ports jedes `Run behavior`-Aufrufers | | Behavior-/Machine-Asset löschen | dito, projektweit | Gemeinsame Ursache ist **`RemoveNodeCommand`**: es räumt per `edgesOfNode` nur den eigenen Graph. Deshalb sitzt die Lösung im generischen Kanten-Code — `drawnDef` in `graph/nested.ts` deckt alle vier, **ohne eine einzige Löschstelle anzufassen**. Zur Einordnung: nur *abgeleitete* Ports (`derivePorts`) verschwinden spurlos. Feste (`def.inputs/outputs`) verschwinden nie, deklarierte (`node.ports`) nur über `RemovePortCommand`, das seine Kanten mitnimmt — auch über Assets hinweg. Fällt die *Grundlage* eines deklarierten Ports weg, bleibt der Port stehen und `portSection` schreibt `"x" is not a variable of …` daneben. **Warum der Geist und nicht bloß ein Warn-Marker:** der Rechtsklick auf eine Kante geht im ganzen Editor ausschließlich über `view.portAt` — einen Kurven-Hit-Test gibt es nicht. Ohne Portzeile ist so eine Kante nicht bloß unsichtbar, sie ist **unerreichbar**. Der Geist ist also der einzige Griff, an dem *Disconnect* hängen kann. **`resolveDef` bleibt unberührt.** Es ist die Wahrheit für Interpreter, Compiler, `ConnectCommand`, `dropTarget` und `openPaletteForDrop` — dadurch kann durch einen Geist nichts laufen und nichts verbunden werden, ganz ohne zweite Sperre. Beim Gegenprüfen bestätigt: `openPaletteForDrop` gibt bei `fromType === undefined` von selbst auf. Ein Linksklick am Geist-Pin tut nichts (die erste Fassung verschob sonst den Node). **Geprüft:** `./check.sh` → `CHECK EXIT 0`, **943 Tests** (935 + 8 neue, `tests/core/ghost-ports.test.ts`). e2e Modul 26 → **ALL PASSED – 33 Checks** (26 + 7 neue), `E2E EXIT 0`. Screenshot angesehen: gestrichelte rote Kante zum zweiten `Log`, während `State 1` weiß und durchgezogen bleibt. **Acht Verbiegungen — sieben beißen:** `drawnDef` ohne Geister (5 Unit-Tests) · nur Input-Seite (1) · Singular/Plural (1) · Geister vorne statt hinten (1) · Canvas ohne `drawnDef` (**3 FAILED**, `ghosted: ["State 1"]` — wörtlich der Issue-Zustand) · Warn-Marker weg (**1 FAILED**, `null`) · Drag-Sperre weg (**1 FAILED**, `dangling: true`). Die achte biss *nicht* und fand damit toten Code: die Dedup über `edge.id` bräuchte eine Selbstkante, und `ConnectCommand` verbietet die — ersatzlos vereinfacht. **Nicht gebaut:** kein Inspector-Eintrag, kein automatisches Aufräumen, keine Nutzungswarnung beim Löschen eines Zustands. Commit `a041322`, Wiki `6e524c2` (*State-machines*, *Behaviors*, *Development*).
admin moved this to Done in Development on 2026-09-14 11:57:04 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#60