Zum Inhalt

JDL — InitialInvocation und kontextbezogene Multi-Entrypoints

Status: Nicht normativ. Architekturreserve für eine spätere Erweiterung. Abhängigkeiten: spec-context-model, spec-resource-model, spec-context-bridge. Zweck: Diese Notiz ändert insbesondere X-13 nicht. Sie hält fest, welche spätere Richtung mit dem bestehenden Context-/Bridge-Modell vereinbar erscheint und welche frühen Implementierungsentscheidungen Jade vermeiden sollte, damit diese Richtung nicht unnötig verbaut wird. Leitgedanke: Ein Prozesseinstieg ist Host-Mechanik. Ein Jade-Entrypoint wäre dagegen ein geprüfter Startvertrag für eine konkrete Root-Ausführungsdomäne.

Diese Notiz ist bewusst ausführlicher als eine gewöhnliche offene Frage. Der Grund ist nicht, dass die Funktion für Jade 0.1 nötig wäre. Im Gegenteil: Ein einzelner Einstiegspunkt ist für die erste Implementierung wesentlich einfacher. Der Punkt ist, dass eine zu enge Repräsentation des ersten Falls später einen Architekturwechsel erzwingen könnte, obwohl das bestehende Context-/Bridge-Modell die allgemeinere Form bereits nahelegt.

Die Reserve lautet deshalb nicht: Multi-Entrypoints jetzt implementieren. Sie lautet:

Den einfachen Fall so implementieren, dass „genau ein Entrypoint“ eine Kardinalitätsbeschränkung bleibt und nicht zur tiefen Annahme des gesamten Artefakt-, Loader- und Runtime-Modells wird.


Inhaltsverzeichnis

D.1 Ausgangspunkt

Die gegenwärtige Fassung legt mit X-13 fest:

Ein Artefakt hat genau einen Einstiegspunkt.

Für Jade 0.1 ist das eine vernünftige Regel. Sie hält Discovery, Loader, Diagnose und Startpfad klein. Gleichzeitig kennt das Context-Modell bereits mehrere Eigenschaften, aus denen sich später eine allgemeinere Form ergeben könnte:

Context       = geprüfte Umgebungsgrenze einer Ausführungsdomäne
Bridge        = typisierte, policy-geprüfte Kommunikation über eine Grenze
Transport     = Mechanik der Bewegung; local, thread, process, node, mock
ContextDesc.  = materialisierter Vertrag über Services, Resource-Bindings,
                Scheduler, Storage, Bridges und Limits

Heute wird der Root-Context als der Einstiegspunkt eines Artefakts behandelt. Langfristig könnte die präzisere Aussage stattdessen lauten:

Ein konkreter Start aktiviert genau einen Entrypoint.
Ein Artefakt kann mehrere zulässige Entrypoints beschreiben.
Jeder Entrypoint bestimmt genau eine Root-Ausführungsdomäne.

Der Unterschied klingt klein und ist strukturell erheblich. Die Eindeutigkeit wandert vom Artefakt zur konkreten Invocation.


D.2 Warum argc und argv nicht die Sprachgrenze sein sollten

Auf POSIX beginnt ein gewöhnlicher Prozess mit Hostdaten wie:

argc
argv
envp
working directory
stdin / stdout / stderr
weitere geerbte Prozessressourcen

Diese Form ist Betriebssystem- und ABI-Mechanik. Sie ist kein guter semantischer Vertrag für JDL. Insbesondere sind argc und argv nur eine historische C-Repräsentation derselben Information, die JDL bereits typisiert ausdrücken kann.

Eine mögliche spätere Trennung wäre:

POSIX process entry
        ↓
Host Adapter
        ↓
InitialInvocation        Root-Bindings
  args                    Console
  environment             FileSystem
  workingDirectory        Signals
        ↓                    ↓
        └────── Root-Context ──────┘

Der Host Adapter ist dabei keine neue Sprachabstraktion. Er ist Ring-0-/Host-Mechanik, die fremde Startrepräsentationen in Jade-kompatible Daten und Bindungen überführt.

Der wichtige Schnitt ist:

InitialInvocation  = Startdaten
Root-Bindings      = lebende Ressourcen und Services

stdin, ein Socket, ein File-Handle oder ein Scheduler gehören daher nicht einfach als Felder in eine InitialInvocation. Sie besitzen Laufzeitidentität, Lebensdauer und Autorität. Genau dafür existiert der Context.

InitialInvocation sollte demgegenüber nach Möglichkeit ein gewöhnlicher, kodierbarer und unveränderlich behandelbarer Wert sein.

Eine mögliche Form, ausdrücklich nur als Skizze:

// spekulativ

type InitialInvocation : record {
    args:             [str]
    environment:      EnvironmentSnapshot
    workingDirectory: Path
}

Ob alle drei Felder zum Kern gehören, ist offen. Wichtig ist nur die Kategoriengrenze: Startdaten ja, lebende Hostressourcen nein.


D.3 Was InitialInvocation bedeutet

Der Begriff soll nicht „Argumentliste in hübscher“ bedeuten.

InitialInvocation wäre der typisierte Startwert, mit dem eine neue Root-Ausführungsdomäne betreten wird.

Daraus folgen drei nützliche Eigenschaften.

D.3.1 Host-Unabhängigkeit

Ein lokaler POSIX-Start kann eine InitialInvocation erzeugen, ohne dass JDL selbst argc, argv oder envp kennen muss.

argc / argv / envp
        ↓
Host Adapter
        ↓
InitialInvocation

Eine spätere andere Hosting-Form könnte denselben Startwert erzeugen, ohne die Sprache zu ändern.

D.3.2 Transport-Unabhängigkeit

Die Herkunft der Invocation muss nicht Teil ihrer Bedeutung sein.

Shell                  Jade Context             Jade Node
  │                         │                       │
  └── Host Transport        └── local/process      └── node
             \                 |                  /
              \                |                 /
               └──── InitialInvocation ─────────┘
                              ↓
                         Entrypoint
                              ↓
                         Root Context

Das heißt nicht, dass jeder Transport jede Invocation zulassen muss. Admission-, Codec-, Resource-/Authority- und Trust-Regeln dürfen eine konkrete Bindung ablehnen. Es heißt lediglich: Die Anwendungssemantik des Ziel-Entrypoints muss nicht davon abhängen, ob der Start aus einer Shell, einem Supervisor, einem Test oder einem anderen Node kam.

D.3.3 Testbarkeit

Ein Test müsste keinen POSIX-Prozessstart simulieren, nur um das Verhalten eines Entrypoints zu prüfen. Er könnte eine InitialInvocation über einen mock- oder lokalen Transport an dieselbe Startgrenze liefern.

Damit wäre „unter Test starten“ keine zweite Initialisierungslogik.


D.4 Kontextbezogene Multi-Entrypoints

Der historische Begriff kontextbezogene Multi-Entrypoints lässt sich mit dem heutigen Modell präziser fassen.

Gemeint wären nicht mehrere Funktionen namens main und auch kein versteckter Dispatcher über argv[0] oder das erste Kommandozeilenargument.

Gemeint wäre:

Ein Artefakt darf mehrere explizit deklarierte Startziele besitzen. Jedes Startziel ist an einen bestimmten Root-Context-Vertrag gebunden. Eine konkrete Invocation wählt genau eines davon.

Beispielhaft:

Application Artifact
│
├── web
│   └── WebContext
│
├── worker
│   └── WorkerContext
│
├── cli
│   └── CliContext
│
└── maintenance
    └── MaintenanceContext

Alle vier können denselben Anwendungscode, dieselben Domänentypen und dieselben Bibliotheksmodule teilen. Sie müssen aber nicht dieselbe Ausführungsautorität teilen.

Beispiel:

WebContext
  Services:     Http, Db, Cache
  Resource authority: NetworkEndpoint(...)
  Scheduler:    latency-oriented

WorkerContext
  Services:     Queue, Db
  Resource authority: NetworkEndpoint(...)
  Scheduler:    throughput-oriented

CliContext
  Services:     Args, Console, Config
  Resource authority: Directory(..., read-only)
  Scheduler:    simple

MaintenanceContext
  Services:     Db, Audit, MaintenanceApi
  Resource authority: Directory(..., read-only), NetworkEndpoint(...)
  Limits:       enger administrativer Rahmen

Das ist der eigentliche Gewinn gegenüber einem klassischen Subcommand-Dispatcher. Bei einem einzigen großzügigen MainContext müsste die Anwendung häufig die Vereinigungsmenge aller benötigten Autorität tragen:

ResourceAuthority(Application)
    = Web ∪ Worker ∪ Cli ∪ Maintenance

Bei kontextbezogenen Entrypoints kann dagegen jede operative Rolle ihren eigenen geprüften Root-Vertrag besitzen.

ResourceAuthority(entrypoint)
    = nur das, was diese Rolle tatsächlich benötigt

Damit wird die Trennung nicht bloß organisatorisch, sondern Teil der materialisierten Laufzeitsemantik.


D.5 Entrypoint ist nicht gleich Funktion

Eine spätere Erweiterung sollte den Begriff Entrypoint nicht auf eine Funktionsadresse reduzieren.

Eine Funktion beantwortet:

Welcher Code wird aufgerufen?

Ein Entrypoint müsste mehr beantworten:

Welche Root-Ausführungsdomäne darf entstehen?
Welcher ContextDescriptor gilt dafür?
Welche Form der InitialInvocation wird akzeptiert?
Welche Bindungen müssen beim Start vorhanden sein?
Welche Admission-/Trust-Regeln gelten?
Welcher initiale Code wird innerhalb dieser Domäne ausgeführt?

Eine mögliche materialisierte Form könnte deshalb später ungefähr so aussehen:

EntryPointDescriptor
├── stableName / FQN
├── rootContextRef
├── invocationSchema
├── admissionPolicy
└── initialAction

Die konkreten Felder sind ausdrücklich nicht entschieden. Der wichtige Architekturpunkt ist nur: Ein Entrypoint wäre ein Startvertrag, nicht bloß ein Symbolzeiger.

Damit ließe sich auch die heutige Zweiteilung besser einordnen:

def main() ->{} i32

und

type Main : blueprint {
    ...
}

müssten langfristig nicht zwei konkurrierende Startmodelle sein.

Eine mögliche spätere Lesart wäre:

def main()
→ kompakte Form für einen Default-Entrypoint mit Default-Root-Context

type Main : blueprint
→ explizite deklarative Form des Root-Context-Vertrags

Ob diese Lesart tatsächlich übernommen wird, ist offen. Wichtig ist lediglich, die erste Implementierung nicht so hart mit „Prozesseinstieg = Funktion main“ zu verschweißen, dass jede spätere Trennung einen Bruch durch Ring 0, Loader, Artefaktformat und Tooling verlangt.


D.6 InitialInvocation und Zielwahl sind zwei verschiedene Dinge

Eine InitialInvocation beschreibt die Startdaten. Sie muss nicht zugleich festlegen, welcher Entrypoint gewählt wird.

Die Zielwahl kann außerhalb liegen:

Launch Request
├── target: myapp::worker
└── invocation: InitialInvocation

oder bereits durch den aufgerufenen Loader-/Bridge-Endpunkt feststehen:

Bridge-Bindung → myapp::worker
Payload        → InitialInvocation

Diese Trennung ist nützlich, weil dieselbe InitialInvocation nicht zwangsläufig wissen muss, wie ein Artefakt seine Startziele benennt oder adressiert.

Die genaue Form eines möglichen LaunchRequest ist nicht Gegenstand dieser Notiz. Festzuhalten ist nur:

Adressierung des Startziels und Startdaten sollten nicht unnötig zu einem einzigen Typ verschmolzen werden.


D.7 Verhältnis zur Bridge

Die Bridge sollte dabei Transport und Grenzprüfung bleiben. Sie ist nicht Besitzerin des Entrypoints und nicht automatisch ein Prozess-Launcher.

Quelle
  ↓
InitialInvocation
  ↓
Bridge / Host-Transport
  ↓
Entrypoint-Grenze
  ↓
Root Context

Die Bridge beantwortet weiterhin Fragen wie:

Darf diese Nachricht diese Grenze überqueren?
Ist ihr Typ kodierbar?
Welche Richtung gilt?
Welche Trust-Policy gilt?
Welche Distanz wird gebunden?
Welche Backpressure-/Timeout-Regeln gelten?

Der Entrypoint beantwortet dagegen:

Was darf durch eine gültige Startanforderung entstehen?

Die Begriffe dürfen nicht zusammenfallen. Sonst würde jede Bridge implizit zur Startmechanik, obwohl die meisten Bridges ausschließlich zwischen bereits laufenden Contexts kommunizieren.

D.7.1 Die Hostgrenze als Sonderquelle, nicht als Sondersemantik

Der POSIX-Host ist zunächst kein Jade-Context. Er kann deshalb nicht wörtlich dieselbe ContextBridge benutzen, bevor irgendeine Jade-Domäne existiert.

Das muss aber keinen zweiten semantischen Startweg erzeugen.

Eine mögliche Schichtung wäre:

POSIX Host
   ↓ Ring-0 Host Adapter
Jade-kompatible Invocation
   ↓ gemeinsames Admission-/Descriptor-Modell
Root Context

Sobald Jade selbst der Absender ist, kann dieselbe Startsemantik über eine reguläre Bridge transportiert werden.

Damit bleibt die notwendige Host-Sondermechanik ganz unten, während die Bedeutung oberhalb derselben Grenze vereinheitlicht wird.


D.8 Lokaler Prozess, eingebettete Domäne und Node

Wenn der Startvertrag vom Prozessstart getrennt ist, folgt eine weitere nützliche Möglichkeit:

Ein Root Context ist semantisch die Wurzel einer Invocation, nicht zwingend die Wurzel eines Betriebssystemprozesses.

Ein Entrypoint könnte später prinzipiell in unterschiedlichen Hosting-Formen aktiviert werden:

1. eigener POSIX-Prozess

Host
  ↓
Entrypoint
  ↓
Root Context


2. eingebettet in eine bestehende Jade-Runtime

bestehender Context
  ↓ Bridge
Entrypoint
  ↓
neuer Root Context der Invocation


3. entfernter Jade Node

Node A
  ↓ node-Transport
Node B / Entrypoint
  ↓
Root Context

„Root“ bezeichnet dabei die Root-Grenze dieser Invocation-Domäne, nicht notwendigerweise die äußerste technische Entität des gesamten Prozesses oder Nodes.

Das ist insbesondere für eine spätere Jade-Node-/JadeOS-Richtung interessant, sollte Jade 0.1 aber nicht mit verteilter Ausführung belasten. Der Wert der Notiz besteht gerade darin, die spätere Möglichkeit offen zu halten, ohne sie jetzt implementieren zu müssen.


D.9 Lebenszyklus

Mehrere deklarierte Entrypoints bedeuten nicht automatisch mehrere gleichzeitig aktive Root-Contexts.

Die saubere Grundregel wäre eher:

Artefakt
  enthält 1..n deklarierte Entrypoints

konkrete Invocation
  wählt genau 1 Entrypoint

Aktivierung
  erzeugt genau 1 Root-Ausführungsdomäne für diese Invocation

Ein Prozess oder Node kann später durchaus mehrere solche Domänen gleichzeitig hosten. Das wäre dann aber eine Eigenschaft des Hosts beziehungsweise der Runtime und keine Mehrdeutigkeit einer einzelnen Invocation.

Damit bleibt die wichtige Eindeutigkeit von X-13 erhalten, nur möglicherweise an einer präziseren Stelle.


D.10 Was aus X-13 später werden könnte

Heute bleibt X-13 unverändert. Sollte das Modell später übernommen werden, wäre eine mögliche Ersatzregel:

X-13-neu. Eine konkrete InitialInvocation aktiviert genau einen Entrypoint. Ein Artefakt darf mehrere deklarierte Entrypoints besitzen. Jeder Entrypoint bestimmt genau einen Root-Context-Vertrag.

Oder noch strenger getrennt:

X-13a  Ein Artefakt darf einen oder mehrere deklarierte Entrypoints besitzen.
X-13b  Eine konkrete Invocation adressiert genau einen davon.
X-13c  Ein Entrypoint aktiviert genau eine Root-Ausführungsdomäne.

Diese Form ist lediglich die dokumentierte Zielrichtung. Sie darf nicht in Implementierung oder Tests als bereits beschlossene Semantik eingehen.


D.11 Was Jade 0.1 nicht verbauen sollte

Dieser Abschnitt ist der praktische Kern der Notiz. Die spätere Erweiterung bleibt billig, wenn der erste Loader den Einzelfall als Einzelfall behandelt. Sie wird teuer, wenn „genau einer“ in Repräsentationen, IDs und APIs eingebrannt wird.

D.11.1 Artefaktformat nicht um eine rohe main-Adresse bauen

Ungünstig:

ArtifactHeader.mainFunctionOffset

Das macht aus dem Funktionszeiger die Identität des Startmodells.

Zukunftsoffener wäre konzeptionell:

ArtifactHeader.entryPointTableRef

wobei Jade 0.1 schlicht genau einen Eintrag fordert.

Das bedeutet nicht, dass bereits eine komplexe Tabelle implementiert werden muss. Auch eine intern ein-elementige Struktur genügt. Entscheidend ist die semantische API: Der Loader fragt nach einem Entrypoint, nicht nach „der Main-Funktion an Offset X“.

D.11.2 Loader-API im Singular darf eine Kardinalitätsregel sein

Eine API wie:

artifact.entryPoint()

ist für 0.1 völlig ausreichend, solange intern nicht daraus folgt, dass ein Artefakt prinzipiell nur einen tragen kann.

Später kann daraus werden:

artifact.entryPoints()
artifact.defaultEntryPoint()
artifact.resolveEntryPoint(name)

ohne das Binärmodell neu zu erfinden.

D.11.3 Root-Context-Discovery nicht ausschließlich an main.jdl festnageln

C-15 ist ohnehin offen. Diese Offenheit sollte erhalten bleiben.

Wenn Discovery später mehrere Startziele tragen soll, wäre ein ausschließlich über „es existiert genau eine Datei main.jdl und darin genau Main“ definiertes Artefaktmodell unnötig eng.

Für 0.1 darf diese Konvention trotzdem die einzige zulässige Schreibweise sein. Wichtig ist die Richtung:

Syntax-/Discovery-Regel
    ↓
materialisierter Entrypoint

nicht:

main.jdl ist selbst die Runtime-Identität des Entrypoints

D.11.4 argc/argv unterhalb der JDL-Semantik halten

Ring 0 darf beim POSIX-Start selbstverständlich argc, argv und envp erhalten. Sie sollten nur nicht zum dauerhaften Vertrag zwischen Runtime und JDL werden.

Schon 0.1 kann sie in einen normalen Jade-Wert beziehungsweise in klar getrennte Root-Bindings überführen.

Dann muss eine spätere InitialInvocation keine alte öffentliche ABI zurückbauen.

D.11.5 Startdaten von Services trennen

Wenn Args, EnvironmentSnapshot und WorkingDirectory als Werte behandelt werden, während Console, FileSystem, Network und ähnliche Dinge Context-Bindings bleiben, ist die spätere Trennung praktisch schon vorbereitet.

Wer stattdessen alle Startressourcen in ein gigantisches ProcessContext-Objekt steckt, baut genau den globalen Service-Locator, den spec-context-model §1 ausschließt.

D.11.6 Stable Identity nicht aus lokaler Loader-Reihenfolge ableiten

Sollten Entrypoints später im Artefakt referenziert werden, darf ihre persistente Identität nicht an lauf-lokalen Indizes hängen. Wie bei anderen Artefaktreferenzen braucht es eine stabile nominale oder inhaltliche Form.

Naheliegend wären FQN, stabiler Name, contentHash oder eine Kombination daraus. Die Entscheidung ist offen; die Negativregel ist wichtiger:

kein CompilerDB-lokaler Arena-Index
kein Runtime-Handle
keine zufällige Tabellenposition als externe Identität

D.11.7 Tooling nicht auf „es gibt nur main“ semantisch festlegen

REPL, Debugger, Mission Control, Packaging und Deployment dürfen 0.1 bequem einen einzigen Entrypoint anzeigen. Ihre internen Abfragen sollten aber idealerweise lauten:

Welche Entrypoints besitzt dieses Artefakt?

und für 0.1 genau einen zurückbekommen.

Das ist ein kleiner Unterschied in der API und ein großer Unterschied, wenn später mehr als einer existiert.


D.12 Warum das mehr ist als Framework-Komfort

Frameworks können mehrere operative Rollen bereits heute nachbauen:

app web
app worker
app migrate
app admin

Typischerweise läuft das jedoch über dieselbe Prozess- und Dependency-Container-Struktur. Der Unterschied zwischen den Rollen ist Konfiguration und Dispatch.

Kontextgebundene Entrypoints könnten stärker sein:

Entrypoint
   ↓
anderer ContextDescriptor
   ↓
andere Services
andere Resource-Bindings beziehungsweise Autorität
andere Scheduler-Policy
andere Storage-/Resource-Limits
andere Bridge-Bindungen

Damit kann der Compiler beziehungsweise Loader Aussagen prüfen, die ein Framework erst zur Laufzeit entdeckt oder nur durch Konvention ausdrückt.

Beispiel:

worker-Code verlangt Console
→ WorkerContext bindet Console nicht
→ Fehler an der Contextgrenze

CLI-Code verlangt plötzlich Network
→ Änderung der benötigten Autorität wird sichtbar

Maintenance-Entrypoint greift auf PluginContext ohne Bridge zu
→ kein Pfad, daher Fehler

Der operative Modus wird damit Bestandteil des geprüften Programmvertrags und nicht nur ein String in argv.


D.13 Mögliche Anwendungsszenarien

Diese Liste ist motivierend, nicht normativ.

D.13.1 Backend-Anwendung mit mehreren Rollen

same artifact
├── web
├── worker
├── scheduler
├── migration
└── maintenance

Gemeinsame Domänenlogik, getrennte Root-Verträge.

D.13.2 Tests

Der Test-Runner adressiert denselben Entrypoint über einen mock-Transport und liefert eine künstliche InitialInvocation. Keine zweite Bootstrap-API nötig.

D.13.3 Plugin- oder Supervisor-Start

Ein bereits laufender Jade-Context startet eine andere Domäne ausschließlich über einen freigegebenen Startendpunkt statt über direkten Zugriff auf deren Interna.

D.13.4 Jade Node

Ein Node könnte einen Entrypoint eines Artefakts adressieren und eine Invocation über Node-Transport zustellen. Deployment entscheidet über den Ort; der Entrypoint-Vertrag bleibt derselbe.

D.13.5 Lokaler Entwicklungsassistent

Ein Tool könnte denselben Entrypoint in einem eingeschränkten TestContext starten, ohne einen vollständigen externen Prozess hochzufahren. Das ist besonders interessant für reproduzierbare Diagnose- und Agentenläufe, aber kein Grund, die Kernsemantik darauf zuzuschneiden.


D.14 Grenzen und Risiken

Die Idee ist nur dann sauber, wenn einige Versuchungen ausdrücklich vermieden werden.

D.14.1 Kein universelles „alles ist Entrypoint“

Nicht jeder Context ist automatisch startbar.

Ein Context beschreibt eine Ausführungsdomäne. Ein Entrypoint ist eine ausdrückliche Freigabe, eine solche Domäne initial zu aktivieren. Werden beide Begriffe gleichgesetzt, ist plötzlich jede interne Context-Struktur von außen adressierbar — exakt die Art von versehentlicher Oberfläche, die Jade an anderen Stellen vermeiden will.

D.14.2 Keine implizite Resource-Autorität beim Start

Eine InitialInvocation darf keine Maschinenautorität einschleusen.

Daten in der Invocation sind gewöhnliche Werte. Lebende Resources — insbesondere autoritätstragende Handles — werden über Root-Bindings beziehungsweise den Host Adapter bereitgestellt und gegen den Root-Context-Vertrag geprüft. Ein Resource-Handle darf nicht als vermeintlich gewöhnliches Invocation-Feld die Context-Grenze umgehen.

D.14.3 Kein versteckter Service-Locator in InitialInvocation

Ein Feld wie:

services: Map[str, Any]

würde das gesamte Context-Modell durch eine Hintertür wieder abschaffen.

Die Invocation ist ein Wert, kein Container für Ambient Authority.

D.14.4 Keine Transportsemantik in Anwendungscode

Ein Entrypoint sollte nicht anders geschrieben werden müssen, nur weil er lokal, in einem Prozess oder auf einem Node aktiviert wird. Wenn die Distanz eine Operation nicht tragen kann, muss die Bindung abgelehnt werden — nicht der Anwendungscode mit if remote beginnen.

D.14.5 Kein Zwang, mehrere Entrypoints zu benutzen

Der Einzelfall muss der einfache Fall bleiben.

Für kleine Programme soll weiterhin sinngemäß gelten:

def main() ->{} ExitCode {
    ...
}

und Jade erledigt den Rest.

Eine Architektur ist nicht besser, wenn sie jeden „hello world“-Autor zwingt, erst einen Deploymentvertrag zu promovieren.


D.15 Verhältnis zum Artefaktbegriff

Für diese Notiz bedeutet Artefakt:

Eine unveränderliche, serialisierbare und transportierbare Repräsentation von geprüften Compilerergebnissen beziehungsweise ausdrücklich deferred Compilerarbeit, die eine konkrete CompilerDB- oder Runtime-Instanz überleben kann.

Ein ausführbares Application-Artefakt ist also nicht die laufende Anwendung. Es ist die transportierbare Programmeinheit, aus der Loader und Runtime die notwendige Ausführungsstruktur herstellen.

Für Multi-Entrypoints wäre die relevante gedachte Form:

ApplicationArtifact
├── Module / Proto / Code
├── projizierte Descriptor-Semantik
├── stabile Referenzen
└── EntryPointDescriptor[1..n]

Jade 0.1 kann n == 1 erzwingen, ohne dass das Format prinzipiell auf einen rohen main-Zeiger reduziert werden muss.

Die Unterscheidung ist wichtig:

Descriptor
= kanonische Semantik innerhalb einer CompilerDB

Artefakt
= transportierbare Projektion beziehungsweise Distributionseinheit

Runtime-Zustand
= lebende, aus Deskriptor-/Artefaktinformationen aufgebaute Ausführung

Ein EntrypointDescriptor wäre damit Compiler-/Artefaktsemantik. Der tatsächlich laufende Root Context wäre Runtime-Zustand unter diesem Vertrag.


D.16 Verständliches Glossar

Artefakt — Eine transportierbare Programmeinheit, die aus Compilerergebnissen entsteht. Ein Artefakt ist kein laufender Prozess und keine CompilerDB. Es enthält stabile Informationen, die später geladen oder weiterverarbeitet werden können.

Application-Artefakt — Ein Artefakt, das eine ausführbare Jade-Anwendung beschreibt. In der hier diskutierten Zukunftsform könnte es mehrere deklarierte Entrypoints enthalten.

Entrypoint — Ein ausdrücklich freigegebenes Startziel eines Artefakts. Nicht bloß eine Funktion, sondern der Vertrag dafür, welche Root-Ausführungsdomäne bei einem Start entstehen darf.

EntryPointDescriptor — Die gedachte materialisierte Beschreibung eines Entrypoints. Er würde stabile Informationen wie Root-Context-Verweis, akzeptierte Invocation-Form und Startaktion tragen. Die konkrete Struktur ist nicht festgelegt.

Root Context — Die äußerste Context-Grenze einer konkreten Ausführungsdomäne. „Root“ ist relativ zu dieser Domäne; er muss langfristig nicht mit „ein Betriebssystemprozess“ identisch sein.

InitialInvocation — Der typisierte Startwert einer neuen Root-Ausführungsdomäne. Er enthält Startdaten, aber keine beliebige lebende Maschinenautorität.

Invocation — Allgemein ein konkreter Startvorgang beziehungsweise dessen Eingabe. Ob Jade später einen allgemeinen Typ dieses Namens braucht, ist ausdrücklich offen; aus InitialInvocation soll nicht vorschnell eine neue Abstraktionsfamilie wachsen.

Launch Request — Ein möglicher äußerer Umschlag aus Zieladresse plus InitialInvocation. Nur ein Erklärungsbegriff dieser Notiz, kein beschlossenes JDL-Konstrukt.

Host Adapter — Ring-0-/Host-Mechanik, die eine fremde Startrepräsentation wie POSIX argc/argv/envp in Jade-kompatible Startdaten und Root-Bindings überführt.

Root-Binding — Ein Service oder eine Laufzeitressource, die beim Aufbau der Root-Domäne über den Context verfügbar gemacht wird, etwa Console oder FileSystem. Sie ist nicht einfach Teil der InitialInvocation.

Bridge — Eine typisierte, policy-geprüfte Kommunikationsoberfläche zwischen isolierten Context-Domänen. In dieser Notiz kann sie eine InitialInvocation transportieren, bleibt aber eine allgemeine Kommunikationsgrenze und wird nicht selbst zum Entrypoint.

Transport — Die mechanische Art, wie eine Bridge-Bindung eine Grenze überwindet, etwa local, thread, process, node oder mock. Transport ist nicht die Semantik der Nachricht.

Context-bound Entrypoint / kontextbezogener Entrypoint — Ein Entrypoint, dessen Startvertrag an einen bestimmten Root-Context-Vertrag gebunden ist. Verschiedene Entrypoints desselben Artefakts können dadurch unterschiedliche Services, Resource-Bindings, Scheduler-Policies und Limits besitzen.

Multi-Entrypoint-Artefakt — Ein Artefakt mit mehr als einem deklarierbaren Startziel. Eine konkrete Invocation wählt trotzdem genau eines.

Admission — Die Prüfung, ob eine konkrete Startanforderung für einen Entrypoint überhaupt zulässig ist. Dazu können Trust-, Resource-/Authority-, Codec- oder Deploymentbedingungen gehören. Die genaue Jade-Form ist offen.


D.17 Vorläufige Architekturregel dieser Notiz

Diese Notiz trifft keine normative Entscheidung. Sie hält nur folgende Reserve fest:

Jade 0.1 darf genau einen Entrypoint verlangen. Die Implementierung sollte diesen Einzelfall jedoch möglichst als „ein Element aus einer potenziell allgemeineren Menge“ behandeln. POSIX-Startdaten sollten früh in eine Jade-eigene Repräsentation überführt werden, lebende Ressourcen bleiben Context-Bindings, und der Loader sollte einen materialisierten Startvertrag konsumieren statt dauerhaft main mit dem Betriebssystem-Prozesseinstieg gleichzusetzen.

Wenn Multi-Entrypoints niemals kommen, kostet diese Reserve wenig: Der Satz bleibt immer einelementig.

Wenn sie später kommen, ist der Unterschied erheblich: Aus einer Kardinalitätsregel wird eine erweiterte Kardinalität, statt dass Artefaktformat, Loader, Context-Modell, Host-ABI und Tooling gleichzeitig aufgebrochen werden müssen.

D.18 Versionierbare Entrypoints

Wenn ein Entrypoint als eigener Startvertrag materialisiert wird, liegt eine eigene Versionsachse nahe.

ApplicationArtifact 7.4.1
├── cli@2
├── monitoring@3
└── worker@1

Artefaktversion und Entrypoint-Version sind nicht dasselbe. Eine neue Anwendungsversion muss nicht jeden Aktivierungsvertrag brechen; umgekehrt kann ein einzelner Entrypoint eine neue Vertragsversion bekommen.

Konzeptionell kann die Identität eines Entrypoints mindestens enthalten:

EntryPointKey
├── FQN / Name
└── Version

Die konkrete Versionsauflösung ist offen. Für eine erste Fassung sind exakte Versionen wesentlich leichter reproduzierbar als freie SemVer-Ranges.

Reserve: Das Artefaktformat sollte Entrypoint-Identität nicht so kodieren, dass später keine eigene Vertragsversion ergänzt werden kann.

D.19 Ingress und Egress getrennt halten

Eine CLI kann später beispielsweise so aussehen:

jade --invoke=cli --format[out]=json main.jdl -- getActiveUsers
jade --invoke=monitoring --format[out]=prometheus main.jdl -- collectTimings

Dabei sind drei Dinge verschieden:

--invoke=monitoring     wählt den Entrypoint / Root-Vertrag
--format[out]=...       wählt eine Egress-Projektion
-- ...                  liefert Invocation-Payload

Die Ausgabeprojektion gehört nicht in die Geschäftssemantik des Entrypoints. Ein Resultat kann je nach zulässiger Projektion als json, pretty, prometheus oder über einen anderen Transport ausgegeben werden.

Entrypoint Result
      ↓
Egress Projection
      ↓
Host / Bridge / Tooling

Ob eine Projektion zulässig ist, kann descriptor-semantisch geprüft werden. Das verhindert, dass CLI-Formatierung zum heimlichen Teil des Anwendungsprotokolls wird.

D.20 Operative Varianten, Rollouts und Benchmarking

Mehrere Entrypoints beziehungsweise unterschiedliche Root-Verträge desselben Artefakts können operative Rollen ausdrücken, ohne einen einzigen überprivilegierten main-Bootstrap zu erzwingen.

Beispiele:

app@stable        → StableContext
app@beta          → BetaContext
app@experimental  → ExperimentalContext
benchmark@1       → BenchmarkContext
monitoring@2      → MonitoringContext

Das ist kein Ersatz für gewöhnliche Feature-Flags. Ein eigener Context ist nur gerechtfertigt, wenn sich tatsächlich Ausführungsgrenzen, Bindings, Storage, Scheduler, Resources, Trust oder Kommunikation unterscheiden.

Ein BenchmarkContext ist ein besonders plausibler Fall: Er kann eigene Scheduler-/Storage-/Accounting-Bindings und Mess-Resources erhalten, ohne diese Autorität dem normalen ApplicationContext zu verleihen. Benutzerhardware kann dadurch unter einer expliziten Benchmark-Invocation vermessen werden, ohne den normalen Startvertrag aufzublähen.