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).
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*).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Entscheidung in #51 (Punkt 2): Port-Keys sind die State-Ids; ein gelöschter Zustand lässt die Exec-Kante an
State branch/Set statehängen „wie jeder weggefallene Port“ – der Port ist weg, die Kante bleibt imedges-Array und wird nicht gezeichnet.Zu bauen:
usageskennt Assets, nicht Ports): „Zustand wird in 2 Behaviors verwendet“ – mit Undo bleibt es gefahrlos.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).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:
State branch/Set stateState machine-Literal löschen / Kante kappenmachineOffolgt der Kante)Behavior start/endlöschenRun behavior-AufrufersGemeinsame Ursache ist
RemoveNodeCommand: es räumt peredgesOfNodenur den eigenen Graph. Deshalb sitzt die Lösung im generischen Kanten-Code —drawnDefingraph/nested.tsdeckt 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 überRemovePortCommand, das seine Kanten mitnimmt — auch über Assets hinweg. Fällt die Grundlage eines deklarierten Ports weg, bleibt der Port stehen undportSectionschreibt"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.resolveDefbleibt unberührt. Es ist die Wahrheit für Interpreter, Compiler,ConnectCommand,dropTargetundopenPaletteForDrop— dadurch kann durch einen Geist nichts laufen und nichts verbunden werden, ganz ohne zweite Sperre. Beim Gegenprüfen bestätigt:openPaletteForDropgibt beifromType === undefinedvon 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 zweitenLog, währendState 1weiß und durchgezogen bleibt.Acht Verbiegungen — sieben beißen:
drawnDefohne Geister (5 Unit-Tests) · nur Input-Seite (1) · Singular/Plural (1) · Geister vorne statt hinten (1) · Canvas ohnedrawnDef(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 überedge.idbräuchte eine Selbstkante, undConnectCommandverbietet die — ersatzlos vereinfacht.Nicht gebaut: kein Inspector-Eintrag, kein automatisches Aufräumen, keine Nutzungswarnung beim Löschen eines Zustands.
Commit
a041322, Wiki6e524c2(State-machines, Behaviors, Development).