Aus #207, Antwort 2: „lassen wir es einfach vorerst - über mehrere nodes => extra issue anlegen“.
Befund
Seit #207 kann ein NodeDef eine Gruppe mit gemeinsamem Typ tragen (sharedType). Der Ausgang erbt den Typ, auf den sich die verbundenen Eingänge einigen (agreedType, src/core/graph/portTypes.ts).
Bewusst nicht gebaut: Ketten. Hängt vor einem solchen Node ein weiterer Node derselben Art, meldet der Vorgänger das any, mit dem er registriert ist (shapedDef(…, inherit: false), src/core/graph/nested.ts:124 ff.). Zwei First not empty hintereinander typisieren sich deshalb nicht durch, obwohl vorn eine Animation hineingeht.
Der Grund war der Schutz vor Rückkopplung: Ein Datenzyklus aus solchen Nodes würde sich beim Auflösen endlos im Kreis fragen.
Zu bauen (Vorschlag)
Die Frage „was speist diesen Eingang“ darf durch Nodes mit sharedType hindurch weiterfragen, mit einer Menge der schon besuchten Nodes. Wird ein Node zum zweiten Mal erreicht, zählt er als any. Damit endet jeder Zyklus, und eine Kette ohne Zyklus typisiert sich durch.
Weiter gilt Variante A aus #207: Nur Ausgänge erben, Eingänge bleiben any.
Eine Kante, die dadurch weiter hinten ungültig wird, wird rot wie heute (#207, Antwort 3).
Tests: Kette aus zwei und aus drei Nodes typisiert durch. Ein Zyklus aus zwei Nodes endet mit any, ohne Stack-Überlauf. Ein gemischter Eingang irgendwo in der Kette macht alles dahinter any. Undo einer Kante vorne bringt die Kette zurück auf any.
Offen (mit Vorschlag)
Kosten: Das Auflösen läuft bei jedem Redraw. Vorschlag: messen mit 50 Nodes in einer Kette, erst bei Bedarf cachen.
Farbige Eingangs-Pins (paintType, Nachtrag in #207): Folgen sie dem durchgereichten Typ mit? Vorschlag: ja, sie nehmen schon heute den aufgelösten Ausgangstyp des Nachbarn, das fällt automatisch ab.
Aus #207, Antwort 2: „lassen wir es einfach vorerst - über mehrere nodes => extra issue anlegen“.
## Befund
- Seit #207 kann ein `NodeDef` eine Gruppe mit gemeinsamem Typ tragen (`sharedType`). Der Ausgang erbt den Typ, auf den sich die verbundenen Eingänge einigen (`agreedType`, `src/core/graph/portTypes.ts`).
- **Bewusst nicht gebaut: Ketten.** Hängt vor einem solchen Node ein weiterer Node derselben Art, meldet der Vorgänger das `any`, mit dem er registriert ist (`shapedDef(…, inherit: false)`, `src/core/graph/nested.ts:124` ff.). Zwei `First not empty` hintereinander typisieren sich deshalb nicht durch, obwohl vorn eine Animation hineingeht.
- Der Grund war der Schutz vor Rückkopplung: Ein Datenzyklus aus solchen Nodes würde sich beim Auflösen endlos im Kreis fragen.
## Zu bauen (Vorschlag)
- Die Frage „was speist diesen Eingang“ darf durch Nodes mit `sharedType` hindurch weiterfragen, mit einer Menge der schon besuchten Nodes. Wird ein Node zum zweiten Mal erreicht, zählt er als `any`. Damit endet jeder Zyklus, und eine Kette ohne Zyklus typisiert sich durch.
- Weiter gilt Variante A aus #207: Nur Ausgänge erben, Eingänge bleiben `any`.
- Eine Kante, die dadurch weiter hinten ungültig wird, wird rot wie heute (#207, Antwort 3).
- Tests: Kette aus zwei und aus drei Nodes typisiert durch. Ein Zyklus aus zwei Nodes endet mit `any`, ohne Stack-Überlauf. Ein gemischter Eingang irgendwo in der Kette macht alles dahinter `any`. Undo einer Kante vorne bringt die Kette zurück auf `any`.
## Offen (mit Vorschlag)
1. **Kosten:** Das Auflösen läuft bei jedem Redraw. Vorschlag: messen mit 50 Nodes in einer Kette, erst bei Bedarf cachen.
2. **Farbige Eingangs-Pins** (`paintType`, Nachtrag in #207): Folgen sie dem durchgereichten Typ mit? Vorschlag: ja, sie nehmen schon heute den aufgelösten Ausgangstyp des Nachbarn, das fällt automatisch ab.
meleki
added the new label 2026-09-23 07:05:34 +02:00
Der gemeinsame Typ wandert durch Ketten. Hängt hinter einem First not empty oder Select ein weiterer solcher Node, übernimmt er den Typ, auf den sich der vordere geeinigt hat. Das gilt auch gemischt, etwa Select hinter zwei First not empty.
Ein gemischter oder offener Eingang irgendwo in der Kette macht alles dahinter wieder any. Davor bleibt der Typ stehen.
Ein Kreis aus solchen Nodes endet mit any, statt endlos zu fragen. Das gilt auch für einen Node, der sich selbst speist.
Eingänge bleiben any, nur Ausgänge erben (Variante A aus #207). Eine Kante, die weiter hinten ungültig wird, bleibt liegen und wird rot.
Die farbigen Eingangs-Pins folgen mit (Antwort 2).
Kosten (Antwort 1)
Kein Cache, wie entschieden.
Eine Kette aus 50 Nodes löst sich in rund 10 ms auf, vorher waren es 2 ms. Die Zahl stammt aus einer Messung früher in dieser Runde, für den Endstand habe ich sie nicht neu gemessen. Ein Unit-Test hält fest, dass die 50er-Kette innerhalb eines Frames bleibt.
Speist ein Node beide Eingänge des nächsten, wird er je Frage nur einmal gefragt. Ohne das würde sich der Aufwand mit jedem Glied verdoppeln. Das ist kein Cache zwischen zwei Änderungen, die Antworten gelten nur für die eine Frage.
Under the hood
shapedDef in src/core/graph/nested.ts bekommt statt des Schalters inherit einen Trail mit zwei Teilen:
open: die Nodes, die gerade gefragt werden. Wird einer zum zweiten Mal erreicht, meldet er das any, mit dem er registriert ist.
done: die Antworten dieser einen Frage.
ownShape ist der abgespaltene Teil von shapedDef, der die Ports baut, bevor die Gruppe mitredet. Inhaltlich ist er unverändert.
paintedInputs benutzt einen Trail für alle Pins eines Nodes.
Tests (auf melektaus-atx)
Gate → 211 Files, 3240 Tests, CHECK EXIT 0 (3227 + 13)
e2e 1-6 → ALL PASSED – 298 checks (6: +2 für die Kette)
e2e 4,6,18,19,20,23,24,26,28,31,36,43,53 → ALL PASSED – 558 checks
14 neue Unit-Tests in tests/core/shared-port-type.test.ts: Kette aus zwei und drei, gemischte Arten, gemischter und offener Eingang, Undo vorne, Kreis aus zwei, Selbstspeisung, hinter einem Kreis, ungültige Kante weiter hinten, die 40er-Kette (jeder Node einmal gefragt), die 50er-Kette, zwei für die Pins. Der alte Test „reicht den Typ nicht durch einen zweiten Node“ ist gestrichen, daher netto 13.
Zwei neue e2e-Checks in Modul 06: Der zweite Node übernimmt number, und ein Text vorne öffnet die ganze Kette wieder.
Alle vier Unit-Gegenproben greifen.
Die Browser-Gegenprobe greift: Mit dem alten Verhalten fällt genau der Ketten-Check, die übrigen 297 bleiben grün.
Die e2e-Summe 1673 ist gerechnet (1671 + 2). 1671 hat CI für c88f57c gemessen. Volle Suite und Smokes liefen für diesen Stand nicht, das macht der CI-Lauf zu diesem Commit.
Nicht im Browser geprüft: der Kreis und die Kette aus drei Nodes, dafür gibt es nur Unit-Tests. Nach dem Build habe ich nichts mehr angesehen.
Wiki: Behaviors (Absatz zum gemeinsamen Typ) und Development (Summe).
Umgesetzt und live (Build auf stein2).
## Was sich ändert
- **Der gemeinsame Typ wandert durch Ketten.** Hängt hinter einem `First not empty` oder `Select` ein weiterer solcher Node, übernimmt er den Typ, auf den sich der vordere geeinigt hat. Das gilt auch gemischt, etwa `Select` hinter zwei `First not empty`.
- **Ein gemischter oder offener Eingang** irgendwo in der Kette macht alles dahinter wieder `any`. Davor bleibt der Typ stehen.
- **Ein Kreis aus solchen Nodes** endet mit `any`, statt endlos zu fragen. Das gilt auch für einen Node, der sich selbst speist.
- **Eingänge bleiben `any`**, nur Ausgänge erben (Variante A aus #207). Eine Kante, die weiter hinten ungültig wird, bleibt liegen und wird rot.
- **Die farbigen Eingangs-Pins folgen mit** (Antwort 2).
## Kosten (Antwort 1)
- **Kein Cache**, wie entschieden.
- **Eine Kette aus 50 Nodes** löst sich in rund 10 ms auf, vorher waren es 2 ms. Die Zahl stammt aus einer Messung früher in dieser Runde, für den Endstand habe ich sie nicht neu gemessen. Ein Unit-Test hält fest, dass die 50er-Kette innerhalb eines Frames bleibt.
- **Speist ein Node beide Eingänge des nächsten**, wird er je Frage nur einmal gefragt. Ohne das würde sich der Aufwand mit jedem Glied verdoppeln. Das ist kein Cache zwischen zwei Änderungen, die Antworten gelten nur für die eine Frage.
## Under the hood
- `shapedDef` in `src/core/graph/nested.ts` bekommt statt des Schalters `inherit` einen `Trail` mit zwei Teilen:
- `open`: die Nodes, die gerade gefragt werden. Wird einer zum zweiten Mal erreicht, meldet er das `any`, mit dem er registriert ist.
- `done`: die Antworten dieser einen Frage.
- `ownShape` ist der abgespaltene Teil von `shapedDef`, der die Ports baut, bevor die Gruppe mitredet. Inhaltlich ist er unverändert.
- `paintedInputs` benutzt einen `Trail` für alle Pins eines Nodes.
## Tests (auf `melektaus-atx`)
```
Gate → 211 Files, 3240 Tests, CHECK EXIT 0 (3227 + 13)
e2e 1-6 → ALL PASSED – 298 checks (6: +2 für die Kette)
e2e 4,6,18,19,20,23,24,26,28,31,36,43,53 → ALL PASSED – 558 checks
```
- **14 neue Unit-Tests** in `tests/core/shared-port-type.test.ts`: Kette aus zwei und drei, gemischte Arten, gemischter und offener Eingang, Undo vorne, Kreis aus zwei, Selbstspeisung, hinter einem Kreis, ungültige Kante weiter hinten, die 40er-Kette (jeder Node einmal gefragt), die 50er-Kette, zwei für die Pins. Der alte Test „reicht den Typ nicht durch einen zweiten Node“ ist gestrichen, daher netto 13.
- **Zwei neue e2e-Checks** in Modul 06: Der zweite Node übernimmt `number`, und ein Text vorne öffnet die ganze Kette wieder.
- **Alle vier Unit-Gegenproben greifen.**
- **Die Browser-Gegenprobe greift:** Mit dem alten Verhalten fällt genau der Ketten-Check, die übrigen 297 bleiben grün.
- Die e2e-Summe **1673** ist gerechnet (1671 + 2). 1671 hat CI für `c88f57c` gemessen. Volle Suite und Smokes liefen für diesen Stand nicht, das macht der CI-Lauf zu diesem Commit.
- **Nicht im Browser geprüft:** der Kreis und die Kette aus drei Nodes, dafür gibt es nur Unit-Tests. Nach dem Build habe ich nichts mehr angesehen.
Wiki: *Behaviors* (Absatz zum gemeinsamen Typ) und *Development* (Summe).
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.
Aus #207, Antwort 2: „lassen wir es einfach vorerst - über mehrere nodes => extra issue anlegen“.
Befund
NodeDefeine Gruppe mit gemeinsamem Typ tragen (sharedType). Der Ausgang erbt den Typ, auf den sich die verbundenen Eingänge einigen (agreedType,src/core/graph/portTypes.ts).any, mit dem er registriert ist (shapedDef(…, inherit: false),src/core/graph/nested.ts:124ff.). ZweiFirst not emptyhintereinander typisieren sich deshalb nicht durch, obwohl vorn eine Animation hineingeht.Zu bauen (Vorschlag)
sharedTypehindurch weiterfragen, mit einer Menge der schon besuchten Nodes. Wird ein Node zum zweiten Mal erreicht, zählt er alsany. Damit endet jeder Zyklus, und eine Kette ohne Zyklus typisiert sich durch.any.any, ohne Stack-Überlauf. Ein gemischter Eingang irgendwo in der Kette macht alles dahinterany. Undo einer Kante vorne bringt die Kette zurück aufany.Offen (mit Vorschlag)
paintType, Nachtrag in #207): Folgen sie dem durchgereichten Typ mit? Vorschlag: ja, sie nehmen schon heute den aufgelösten Ausgangstyp des Nachbarn, das fällt automatisch ab.Umgesetzt und live (Build auf stein2).
Was sich ändert
First not emptyoderSelectein weiterer solcher Node, übernimmt er den Typ, auf den sich der vordere geeinigt hat. Das gilt auch gemischt, etwaSelecthinter zweiFirst not empty.any. Davor bleibt der Typ stehen.any, statt endlos zu fragen. Das gilt auch für einen Node, der sich selbst speist.any, nur Ausgänge erben (Variante A aus #207). Eine Kante, die weiter hinten ungültig wird, bleibt liegen und wird rot.Kosten (Antwort 1)
Under the hood
shapedDefinsrc/core/graph/nested.tsbekommt statt des SchaltersinheriteinenTrailmit zwei Teilen:open: die Nodes, die gerade gefragt werden. Wird einer zum zweiten Mal erreicht, meldet er dasany, mit dem er registriert ist.done: die Antworten dieser einen Frage.ownShapeist der abgespaltene Teil vonshapedDef, der die Ports baut, bevor die Gruppe mitredet. Inhaltlich ist er unverändert.paintedInputsbenutzt einenTrailfür alle Pins eines Nodes.Tests (auf
melektaus-atx)tests/core/shared-port-type.test.ts: Kette aus zwei und drei, gemischte Arten, gemischter und offener Eingang, Undo vorne, Kreis aus zwei, Selbstspeisung, hinter einem Kreis, ungültige Kante weiter hinten, die 40er-Kette (jeder Node einmal gefragt), die 50er-Kette, zwei für die Pins. Der alte Test „reicht den Typ nicht durch einen zweiten Node“ ist gestrichen, daher netto 13.number, und ein Text vorne öffnet die ganze Kette wieder.c88f57cgemessen. Volle Suite und Smokes liefen für diesen Stand nicht, das macht der CI-Lauf zu diesem Commit.Wiki: Behaviors (Absatz zum gemeinsamen Typ) und Development (Summe).