Zum Inhalt

JDL/Jade — Runtime-TypeDescriptor, reified, dyn und Function Unions

Status: Konsolidierungsnotiz / Architekturentwurf
Zweck: Sammlung und Präzisierung der Erkenntnisse aus der Diskussion zu reifizierten Typinformationen, dyn-Werten, Function Unions, TypeFns, Blueprints, Contexts, Engines, ContextBridge, Syntax-Erweiterungen und runtime-konsumierbaren Descriptoren.
Normativität: Nicht normativ. Diese Notiz ist Vorarbeit für spätere Anpassungen an TypeFn-, Dispatch-, CompilerDB-, Blueprint-, Runtime-, API-Contract- und Web-/Wire-Specs.
Leitsatz: Runtime-Dynamik in Jade entsteht nicht durch eine laufende TypeEngine, sondern durch zur Compile-Time geprüfte und in Artefakte exportierte Descriptor-Projektionen. Contexts begrenzen Ausführung; Engines betreiben dynamische Abläufe innerhalb dieser Grenzen.


1. Kernthese

JDL unterscheidet drei Ebenen:

Compile-Time-Typwissen
  vollständig, beweisend, erklärend
  TypeDescriptor, MetaRecord, TruthProfile, ProofTrace, Source-Spans, Constitution-Kontext

Runtime-Descriptor-Projektion
  kompakt, freigegeben, ausführungsnah
  RuntimeTypeDescriptor, RuntimeTypeInfo, CodecDescriptor, DispatchDescriptor, RouteDescriptor

Runtime-Wert
  VM-Wert, Handle, DynValue, ActorMessage, Request, Response

Ein Typ wird nicht dadurch dynamisch, dass er reified ist. Ein reified Typ ist weiterhin statisch bekannt. Der Unterschied ist: Ein Teil seines zur Compile-Time materialisierten TypeDescriptors wird als runtime-lesbare Projektion ins Artefakt übernommen.

Ein dyn P-Wert ist dagegen ein existentieller Wert: Der konkrete Typ ist an der statischen Aufrufstelle verborgen, aber die Grenze ist durch ein Protocol P beschränkt. dyn P ist keine allgemeine Any-Form.

Function Unions bilden eine dritte Kategorie: eine geschlossene Menge typisierter Operationen, deren konkrete Variante zur Runtime gewählt wird, deren Gesamtform aber zur Compile-Time bekannt und prüfbar ist.


2. Begriffe

2.1 TypeDescriptor

Ein TypeDescriptor ist das vollständige, zur Compile-Time materialisierte Typartefakt. Er enthält oder referenziert unter anderem:

  • Typidentität,
  • TypeKind,
  • generische Bindungen,
  • MetaRecord,
  • Ring-0-Facts,
  • TruthProfile / LabelProfile,
  • LayoutDescriptor,
  • ProvideDescriptoren,
  • DispatchDescriptoren,
  • ProofTrace,
  • Diagnostics- und Source-Kontext.

Der vollständige TypeDescriptor gehört primär der Compile-Time-Welt. Er ist Material für TypeEngine, Materializer, IRBuilder, Verifier, Generator und Tooling.

2.2 RuntimeTypeDescriptor / RuntimeTypeInfo

Ein RuntimeTypeDescriptor ist eine kontrollierte Projektion eines TypeDescriptors für die Runtime.

Er enthält nur, was zur Runtime benötigt und freigegeben wurde, zum Beispiel:

RuntimeTypeDescriptor {
    typeId
    qualifiedName?        // optional, stripbar
    kind                  // Struct | Enum | Union | Primitive | Function | Dyn | Blueprint
    fieldTable?           // nur bei Schema/Reflection/Serde-Bedarf
    variantTable?         // nur bei Enum/Union-Serde/Inspection
    layoutRef?            // LayoutDescriptor-Referenz, wenn nötig
    dropRef?              // DropDescriptor-Referenz, wenn nötig
    dispatchRefs?         // für dyn/Protocol-Dispatch
    codecRefs?            // für Wire/Serde
    flags                 // kompakte Runtime-Policies
}

Er enthält normalerweise nicht:

  • TypeFn-Bodies,
  • vollständige MetaRecords,
  • ProofTraces,
  • Constitution-Regeln,
  • AST,
  • Source-Spans,
  • CompilerDB-Queries,
  • Provider-Interna.

Ausnahme: Debug-/REPL-/Tooling-Bundles können zusätzliche Informationen laden. Das ist kein Normalfall der Production-Runtime.

2.3 Reified Type

Ein reified Typ ist ein statisch bekannter Typ, dessen runtime-relevante TypeDescriptor-Projektion absichtlich ins Artefakt exportiert wird.

// Beispielhaft
fn describe[reified T](value: T) -> str =
    TypeInfo.of[T]().name

reified ist ein Bindungsmodus, kein normales Refinement. Eine TypeFn darf den Reification-Modus lesen und voraussetzen, aber nicht nachträglich an bestehenden Bindungen verändern.

2.4 Dyn Protocol Value

Ein dyn P-Wert ist ein existentialer Wert mit expliziter Protocol-Grenze.

Er bedeutet:

Der konkrete Typ ist an dieser Stelle statisch verborgen.
Bekannt ist nur: Der Wert erfüllt Protocol P.

Die Runtime-Repräsentation braucht daher eine Typidentität und Dispatch-Information.

Konzeptionell:

DynValue[P] {
    payload: JadeValue | Handle
    typeId: RuntimeTypeId
    dispatchRef: DispatchDescriptorRef[P]
}

dyn P ist kein Any. Es trägt eine Grenze, keine Kapitulation.

2.5 Function Union

Eine Function Union ist eine geschlossene Union typisierter Operationen.

Korrekte Syntax:

type UserCommand : union =
    | getUser(id: UserId) -> Result[User, ApiError]
    | createUser(req: CreateUserRequest) -> Result[User, ApiError]
    | deleteUser(id: UserId) -> Result[(), ApiError]

Sie ist „statisch-dynamisch“:

  • statisch, weil die Menge der Varianten und ihre Signaturen bekannt sind,
  • dynamisch, weil zur Runtime eine konkrete Variante ausgewählt und verarbeitet wird.

Function Unions eignen sich als Operations-Interface für Actors, RPC, Routing, Message-Busse und transport-agnostische API-Contracts.


3. Architekturfluss

Der Grundfluss lautet:

Blueprint / TypeSubject / Function Union / Contract
TypeEngine / TypeFnEvaluator / Provider
MaterializationPatch
CompilerDB Materializer
Descriptoren
Generator / ArtifactBuilder
Runtime-Descriptor-Projektionen im Artefakt
RuntimeBus / JME / RoutingEngine / DispatchEngine / CodecEngine konsumieren Tabellen

Die Runtime bekommt keine TypeEngine. Sie bekommt vorbereitete Verträge.

Das ist der zentrale Sicherheits- und Ressourcenpunkt: Der teure und beweisende Teil geschieht zur Compile-Time. Die Runtime liest kompakte Tabellen und führt definierte Commands aus.


4. reified T

4.1 Bedeutung

reified T bedeutet:

Der konkrete Typ T ist statisch bekannt.
Ein runtime-lesbarer Descriptor-Anteil von T muss im Artefakt verfügbar sein.

Nicht gemeint ist:

Der Typ T wird zur Runtime neu erzeugt.
T wird dynamisch.
Die Runtime bekommt den vollständigen Compile-Time-TypeDescriptor.

4.2 TypeFn-Verhalten

Eine TypeFn darf:

  • prüfen, ob ein Typparameter reified gebunden ist,
  • daraus Descriptor-Patches erzeugen,
  • RuntimeTypeInfo-Anforderungen anmelden,
  • Diagnostics erzeugen, wenn Reification fehlt.

Eine TypeFn darf nicht:

  • einen bestehenden Typparameter nachträglich reified machen,
  • die Calling Convention rückwirkend ändern,
  • Runtime-TypeInfo ohne explizite Reification erzwingen.

Zulässig:

typefn NeedsTypeInfo[reified T]() -> Type =
    RuntimeView[T]

Nicht zulässig:

typefn MakeReified[T]() =
    db.setQualifier(T, reified)   // verbotenes Modell

4.3 Runtime-Kosten

reified ist nicht automatisch teuer. Der Preis ist abhängig von der exportierten Projektion.

Stufenmodell:

Minimal:
  typeId, kind, optional name

Schema:
  fieldTable, variantTable, field types

Layout:
  size, align, offsets, layoutRef

Dispatch:
  protocol bindings, dispatchRefs

Debug:
  lesbare Namen, Source-Spans, pretty inspection

Proof:
  normalerweise nicht Runtime

Production-Builds sollten Projektionen strippen können. Debug- und REPL-Builds können mehr tragen.


5. dyn P

5.1 Bedeutung

dyn P ist ein dynamischer Protocol-Wert. Der konkrete Typ ist verborgen, aber die operationale Grenze ist explizit.

dyn Serializable
  = irgendein konkreter Typ, der Serializable erfüllt

Das ist keine offene Universalform. Es gibt kein Any.

5.2 Abgrenzung zu reified

Mechanismus Bedeutung
reified T T ist bekannt; Typinfo von T soll runtime-sichtbar sein
dyn P konkreter Typ ist verborgen; Protocol-Grenze P ist bekannt
dyn P -> T Runtime-Pipeline materialisiert einen konkreten Zieltyp
Function Union geschlossene Menge typisierter Operationen

5.3 Dyn als Boundary-Form

dyn ist besonders sinnvoll an Grenzen:

  • Plugin-Grenzen,
  • REPL/Inspection,
  • Routing,
  • heterogene Collections,
  • Message-Bus,
  • Service-Registries,
  • WebSocket/RPC,
  • Hostobjekte.

Nicht sinnvoll ist dyn als Ersatz für Generics oder normale Protocol-Constraints.

5.4 Dyn-Pipeline in konkreten Typ

Der bevorzugte Umgang mit dyn ist:

dyn P
  → descriptor-geprüfte Pipeline
  → konkreter Typ T
  → danach wieder statische Semantik

Beispielhaft:

dyn Message
  → typeId/schema route
  → decoder/validator
  → UserCreated | PaymentFailed | HttpRequest[CreateUser]
  → konkreter Handler

Die Bindings können statisch vorbereitet werden:

DynDispatchDescriptor
TypeId → ConcreteBinding
ProtocolId + TypeId → Handler
SchemaId → Decoder
RouteId → HandlerProto

Damit bleibt dyn kontrollierte Dynamik, kein architektonischer Nebel.


6. Function Unions als statisch-dynamische Interfaces

Function Unions sind ein tragendes Konzept, weil sie Operationen als Typen ausdrücken.

Sie sind kein OO-Interface und kein dyn-Wert. Sie sind eine geschlossene Operationssumme.

6.1 Beispiel

type UserCommand : union =
    | getUser(id: UserId) -> Result[User, ApiError]
    | createUser(req: CreateUserRequest) -> Result[User, ApiError]
    | listUsers(filter: UserFilter) -> Result[[User], ApiError]
    | deleteUser(id: UserId) -> Result[(), ApiError]

6.2 Actor-Verwendung

type UserActor : blueprint {
    state: UserState
    message: UserCommand
}

Die Actor-Engine kann daraus einen ActorMessageDescriptor ableiten.

Ein match über UserCommand ist exhaustiv prüfbar. Jeder Arm hat seinen eigenen Rückgabetyp. Damit wird dynamische Operationauswahl möglich, ohne Any oder offene Reflection zu verwenden.

6.3 Generische Function Unions

Function Unions können generisch sein:

type RepositoryCommand[T, E] : union =
    | get(id: Id) -> Result[T, E]
    | list() -> Result[[T], E]
    | delete(id: Id) -> Result[(), E]

Das erlaubt generische API-, Repository-, Actor- und RPC-Modelle, ohne die Operationsmenge zu öffnen.

6.4 Beziehung zu Contracts

Ein API-Contract-Blueprint kann eine Function Union ableiten oder enthalten.

type UserService : blueprint {
    commands: UserCommand
}

Oder struktureller:

type ServiceBinding[C] : blueprint {
    contract: C
    handlers: HandlerMap[C]
}

HandlerMap[C] ist konzeptionell eine TypeFn/Type-Materialisierung, die aus Contract-Operationen passende Handler-Signaturen ableitet.

Offen bleibt, ob Function Unions manuell geschrieben, aus Contract-Blueprints abgeleitet oder beides unterstützt werden.


7. Blueprints als ideale Steuerform

Blueprints sind die natürliche Oberfläche für diese Mechanik.

Beispiele:

RouteBlueprint
ServiceBlueprint
SchemaBlueprint
CodecBlueprint
DynProtocolBlueprint
FfiBindingBlueprint
ActorBlueprint
ContractBlueprint

Blueprints beschreiben Absicht. Engines werten diese Beschreibungen aus. Descriptoren sind das materialisierte Ergebnis.

Für Web/Routing bedeutet das:

RouteBlueprint
  + Handler-Signatur
  + Body[T]
  + Returns[U]
  + Effect-/Service-Information
  + reified TypeDescriptor-Projektionen
RouteDescriptor
CodecDescriptor
SchemaDescriptor
DispatchDescriptor
Runtime-Routing-Tabelle

Zur Runtime liest die RoutingEngine nur:

method
path
bodyCodec
responseCodec
handlerRef
requiredServices
middlewareRefs

Sie liest keine CompilerDB und führt keine TypeFns aus.


8. Web-Backend-Anwendung

Ein Web-Backend profitiert stark von reified, dyn und Function Unions, aber nur an Grenzen.

8.1 Reified im Web

Sinnvoll für:

  • Request Body Parsing,
  • Response Serialization,
  • Schema/OpenAPI-Generierung,
  • Config- und Form-Validation,
  • Debug/Inspection,
  • Plugin-Routes.

Beispiel:

route POST "/users"
    :> Body[CreateUserRequest]
    :> Returns[UserResponse]
    :> Uses[UserDb]
{
    createUser
}

Compile-Time:

Body[CreateUserRequest]
Returns[UserResponse]
  → verlangt CodecDescriptor / SchemaDescriptor
  → nutzt RuntimeTypeDescriptor-Projektion der beteiligten Typen

Runtime:

HTTP request
  → RouteDescriptor match
  → bodyCodec.decode(bytes)
  → CreateUserRequest
  → HandlerProto
  → responseCodec.encode(UserResponse)

8.2 Dyn im Web

Sinnvoll für:

  • WebSocket-Nachrichten,
  • polymorphe Event Streams,
  • Plugin-Requests,
  • Middleware-Objekte mit bewusst verborgener Implementierung,
  • Routing über Message-Typen.

Empfohlenes Muster:

dyn HttpMessage
  → route/schema/typeId pipeline
  → concrete Request[T]
  → statischer Handler

Nicht empfohlen:

Handler nimmt überall dyn und castet innen herum.

Das wäre ein Any-Ersatz mit besserer Frisur.

8.3 Function Unions im Web

Function Unions eignen sich als transport-agnostische Operationsebene:

type UserApi : union =
    | getUser(id: UserId) -> Result[UserResponse, ApiError]
    | createUser(req: CreateUserRequest) -> Result[UserResponse, ApiError]

HTTP, gRPC, WebSocket oder IPC können dieselbe Operationsmenge unterschiedlich abbilden.

UserApi
  → HttpRouteDescriptoren
  → GrpcMethodDescriptoren
  → WsMessageDescriptoren
  → ActorCommandDescriptoren

Die Operationen bleiben gleich. Nur die TransportEngine ändert sich.


9. TypeFns, Generics und TypeEngine-Schichtung

9.1 Generics vor TypeFn-Evaluation

Generische Bindungen müssen vor der TypeFn-Auswertung zumindest gebunden und als TypeSubject sichtbar sein.

Ablauf:

Parse
  → Name Resolution
  → Generic Binding
  → Constraint Environment
  → TypeSubject
  → TypeFn Evaluation
  → PatchSet
  → Materializer

Eine TypeFn soll keine rohe Generic-Syntax auflösen. Sie arbeitet auf bereits gebundenen TypeSubjects.

9.2 TypeFn-Evaluation

TypeFns laufen während der Meta-/Type-Resolution, nachdem TypeSubjects und Namen ausreichend aufgelöst sind, aber bevor Layout, IRBuilder und Generator harte Annahmen treffen.

TypeFns erzeugen keine direkten CompilerDB-Mutationen, sondern Patches.

9.3 Tags statt Types für Phantom-State

Compile-Time-Zustände in Phantom-Parametern sind Tags, keine Types.

tag SyntaxKnown
tag NamesBound
tag GenericsBound
tag MetaApplied
tag TruthClosed
tag LayoutKnown
tag RuntimeDescribed

Ein State-Blueprint könnte so aussehen:

type TypeMaterialization[phantom S] : blueprint {
    // beschreibt Zustand und erlaubte Übergänge der Typmaterialisierung
}

Übergänge:

def bindNames(t: TypeMaterialization[SyntaxKnown])
    -> TypeMaterialization[NamesBound]

def bindGenerics(t: TypeMaterialization[NamesBound])
    -> TypeMaterialization[GenericsBound]

def applyRefinements(t: TypeMaterialization[GenericsBound])
    -> TypeMaterialization[MetaApplied]

Das ist eine typisierte State-Machine der Materialisierung. Die ausführende Engine ist davon zu trennen.


10. Kein Any

JDL sollte keinen universellen Any-Typ besitzen.

Any ist ein Escape Hatch, der Architekturfehler verschleiert. Wer Any will, meint meistens eines der folgenden Konzepte:

Gemeinter Zweck JDL-Mechanismus
mehrere bekannte Varianten union / enum
irgendein Wert mit Verhalten dyn P
bekannter Typ mit Runtime-TypeInfo reified T
transportierte Operation Function Union
fremde Ressource opaque Handle
deklarative Beschreibung Blueprint
runtime-lesbares Schema RuntimeTypeDescriptor / SchemaDescriptor

Regel:

Dynamik muss in JDL immer über eine explizite Grenze formuliert werden.


11. Ressourcenprofil

reified und dyn sind nicht automatisch teuer.

Kosten entstehen durch:

  • exportierte Descriptor-Daten,
  • dynamischen Dispatch,
  • Runtime-Introspektion,
  • Codec-/Schema-Tabellen,
  • Debug-/REPL-Daten.

Der Hot Path kann statisch bleiben, wenn dynamische Werte früh in konkrete Typen materialisiert werden.

Empfohlene Strategie:

Boundary:
  dyn / reified / descriptors erlaubt

Core Logic:
  konkrete Typen, Generics, statische Provides

Debug/REPL:
  optionale zusätzliche Descriptor-Projektionen

Production:
  stripbare RuntimeTypeInfo-Stufen

12. Gegenargumente und Grenzen

12.1 Runtime-Fehler statt Compile-Time-Fehler

dyn verschiebt bestimmte Fehler an die Runtime. Das ist akzeptabel an Grenzen, aber schlecht als inneres Programmiermodell.

Lösung: dyn möglichst früh materialisieren.

12.2 Descriptor-Disziplin wird kritisch

Wenn RouteDescriptor, CodecDescriptor oder DispatchDescriptor falsch materialisiert sind, wird die Runtime zur Lotterie.

Lösung: Materializer, Verifier und Artifact-Validator müssen Descriptor-Kohärenz hart prüfen.

12.3 Hot-Path-Verführung

dyn ist bequem und kann missbraucht werden.

Lösung: Lints, Performance-Warnings und Idiomatik: dyn nur an Boundaries.

12.4 Security-Grenzen

dyn über Plugin-, Web- oder Message-Grenzen darf nicht unkontrolliert akzeptiert werden.

Lösung: Herkunft, Schema-Version, Plugin-Trust, allowed Protocols und Capability-Kontext prüfen.

12.5 Reification-Bloat

Zu breite RuntimeTypeInfo-Projektionen vergrößern Artefakte.

Lösung: Reification-Profile und stripbare Descriptor-Stufen.


13. Offene Entscheidungen

  1. Syntax für dyn: dyn P, Dyn[P] oder andere finale Form.
  2. Reification-Profile: Minimal, Schema, Layout, Debug, Full? Welche Namen?
  3. Function-Union-Variantensyntax: finale Signaturform ohne def bestätigen.
  4. Ableitung aus Contract-Blueprints: automatisch, per TypeFn, per explizitem :> DeriveCommands()?
  5. RuntimeTypeDescriptor-Format: welche Felder sind stabil, welche optional?
  6. Debug-Bundles: getrenntes Artefakt oder Build-Profil im VmModuleArtifact?
  7. Web-RouteDescriptor: in jdl::http oder allgemeiner in jdl::api?
  8. Dyn-Pipeline-API: Standard-Protocol für tryMaterialize[T]?
  9. No-Any-Regel: wo normativ verankern?
  10. TypeMaterialization-State-Machine: eigene Spec oder TypeFn-/CompilerDB-Erweiterung?

14. Empfohlene spätere Spec-Patches

14.1 dispatch-modes.md

Ergänzen:

  • dyn P ist Boundary-Mechanismus, kein Generics-Ersatz.
  • dyn P ist kein Any.
  • dyn → concrete Pipeline als empfohlenes Muster.
  • DynValue referenziert RuntimeTypeId und DispatchDescriptor.

14.2 jdl-typefn-spec.md

Ergänzen:

  • TypeFns dürfen Reification-Modus lesen, nicht mutieren.
  • TypeFns können RuntimeDescriptor-Anforderungen als Patches anmelden.
  • Generics müssen vor TypeFn-Evaluation gebunden sein.
  • Structural TypeFns für HandlerMap / TypedClient / Function Union Derivation als Ausbaustufe.

14.3 jade-compiler-db-spec.md

Ergänzen:

  • RuntimeDescriptorProjection als Artifact/Descriptor-Klasse.
  • Materializer-Regeln für reified/dyn-Projektionen.
  • Descriptor-Stripping/Profile im ArtifactDomain.

14.4 12-design-constitution.md

Ergänzen:

  • Keine Runtime-TypeEngine.
  • Runtime konsumiert Descriptor-Projektionen.
  • Any als Nicht-Ziel.
  • Reification/Dyn als kontrollierte Descriptor-Dynamik.

14.5 jdl-api-contract-design-note.md

Ergänzen:

  • Function Unions als statisch-dynamisches Interface-Modell.
  • korrekte Syntax type X : union = ....
  • generische Function Unions.
  • Ableitung aus Contract-Blueprints.

14.6 Web-/HTTP-Spec

Neu oder später:

  • RouteBlueprint,
  • RouteDescriptor,
  • CodecDescriptor,
  • SchemaDescriptor,
  • reified Body/Return-Typen,
  • dyn Message Pipelines,
  • transport-agnostische Function Unions.

15. Kurzfassung

reified T
  = bekannter Typ T, dessen TypeDescriptor-Projektion zur Runtime verfügbar ist

dyn P
  = unbekannter konkreter Typ mit bekannter Protocol-Grenze P

Function Union
  = geschlossene Menge typisierter Operationen; statisch bekannt, runtime auswählbar

Blueprint
  = deklarierte Absicht

Descriptor
  = geprüfter, materialisierter Vertrag

Runtime
  = konsumiert Tabellen, führt keine TypeEngine aus

Der entscheidende Satz:

Jade erlaubt kontrollierte Dynamik, indem dynamische Runtime-Grenzen zur Compile-Time descriptor-basiert vorbereitet werden. reified, dyn und Function Unions sind keine Escape Hatches, sondern drei unterschiedliche Arten, Typwissen sicher und begrenzt über Phasengrenzen zu tragen.


Teil II - Context, Engines, Bridges und Surface-Syntax

Status dieses Teils: Ergaenzung aus der Folgediskussion. Nicht normativ.
Zweck: Die bisherigen Descriptor-/Dyn-/Reification-Erkenntnisse werden um Contexts, Engines, ContextBridge, Syntax-Erweiterungen, Parser-Kombinatoren, Property Testing und Artefakt-Store-Gedanken ergaenzt.

Der zentrale Zusatz lautet:

Context     = static env einer Ausfuehrungsdomaene
Engine      = dynamic env / Mechanik innerhalb eines Contexts
Bridge      = expliziter Gatekeeper zwischen Contexts
Descriptor  = gepruefter Vertrag zwischen Semantik und Maschine

Damit wird Runtime-Dynamik nicht global, sondern lokal und gegrenzt. Engines duerfen dynamisch sein. Aber sie sind dynamisch innerhalb eines statisch materialisierten Contexts.


16. Context als static env

Ein Context ist keine neue Runtime und kein globaler Service-Locator. Ein Context ist eine descriptor-materialisierte Environment-Grenze.

Er beschreibt, was innerhalb einer Ausfuehrungsdomaene erlaubt, verfuegbar und gebunden ist.

ContextDescriptor
  profile
  services
  capabilities
  engines
  storage
  scheduler
  messaging
  bridges
  reification
  limits
  parentExpose

Ein Context beantwortet statisch:

Welche Services sind sichtbar?
Welche Capabilities sind erlaubt?
Welche Engines duerfen laufen?
Welche Scheduler-Strategie gilt?
Welche Storage-Policy gilt?
Welche Runtime-TypeDescriptor-Projektionen werden exportiert?
Welche Kommunikationswege sind erlaubt?
Welche Parent-Services werden exposed?

Ein Context fuehrt diese Dinge nicht selbst aus. Die eigentliche Maschinenarbeit bleibt bei Ring 0 / VM / JME / RuntimeBus / Scheduler-Kern. Der Context liefert die gepruefte Verdrahtung.

Der praezise Satz:

Ein Context ist die statisch materialisierte Environment-Grenze einer Ausfuehrungsdomaene. Er verdrahtet seine Inhabitants kontrolliert mit erlaubten Maschinen- und Service-Faehigkeiten, waehrend die tatsaechliche Ausfuehrung von Engines und Ring-0-Domaenen getragen wird.

16.1 Context und Runtime trennen

Jade Runtime
  VM, JME, RuntimeBus, Scheduler-Kern, Intrinsics, FFI-Bridge

JDL Context
  Services, Engines, Policies, Capabilities, Storage-/Scheduler-Konfiguration,
  Middleware, Messaging, Reification-Profile, Parent-Exposes

Runtime ist die operative Maschine. Context ist die gepruefte Umgebung, in der Anwendungsmechanik laufen darf.

16.2 Context-Profile

Context-Profile sind keine eigenen Sprachprimitive. Sie sind vordefinierte Profile desselben Context-Schemas.

ApplicationContext  allgemeiner App-Rahmen
WebContext          HTTP, Routing, Middleware, Request-Scopes, Serde
CliContext          Args, StdIO, ExitCode, Config, Logging
ReplContext         live CompilerDB, Debug, Inspection, Hot-Load
PluginContext       isolierte Plugin-Ausfuehrung
FfiContext          ABI, Marshal-Descriptoren, Host-Grenze
TestContext         deterministischer Scheduler, Property Testing, Seeds
ActorContext        Mailbox, Scheduler, Isolation, Message Passing
LibraryContext      keine Host-Caps, exportierbare APIs, kein Runtime-Start
EffectContext       Service-Bindings, Retry/Timeout/Transaction-Policies

Mehr Context-Profile sollten nur entstehen, wenn eine echte Grenze vorliegt:

- eigene Capability-Grenze
- eigene Scheduler-Strategie
- eigene Storage-/Resource-Policy
- eigene Trust-/Plugin-Grenze
- eigene Runtime-Kommunikationsform
- eigener Debug-/CompilerDB-Zugriff

Kein neuer Context fuer Logging, JSON, Auth, Metrics oder einzelne Middleware. Das sind Services, Engines, Refinements oder Policies. Sonst entsteht Context-Flut. Und Context-Flut ist nur globale Unordnung mit besseren Substantiven.


17. Engines als dynamic env

Eine Engine ist Mechanik. Sie validiert, materialisiert, dispatcht, scheduled, serialisiert, transportiert oder interpretiert Descriptoren. Eine Engine besitzt dynamischen Zustand nur in ihrer laufenden Instanz, nicht in ihrer deklarativen Definition.

Der bessere Schnitt:

Blueprint / Refinements / Provides
        |
        v
Descriptor
        |
        v
ContextDescriptor
        |
        v
EngineInstance
        |
        v
dynamic env: Queues, Tasks, Mailboxes, Requests, Effects, Handles, Scopes

Der Context sagt:

Was darf hier existieren und verwendet werden?

Die Engine sagt:

Was passiert gerade innerhalb dieser erlaubten Umgebung?

17.1 Fundamentale Engines

Fundamentale Engines sind identitaetsstiftende Ausfuehrungsdimensionen von Jade. Sie sind nicht dumm. Sie definieren mechanische Invarianten, auf denen spezialisierte Engines aufbauen.

SchedulerEngine     Tasks, Yield, Join, Cancellation, Fairness, Backpressure
ConcurrencyEngine   Task-Grenzen, Share/Send/Sync, Channels, Mailboxes
ResourceEngine      with, Cleanup, Drop-Garantien, Scope-Ende
StorageEngine       Arenas, Pools, Rc, Allocation Policies
DispatchEngine      static/generic/dyn Dispatch, Function Unions, Protocol Dispatch
CodecEngine         Wire/Serde, Schema, Reification Profiles
EffectEngine        Effect-Werte, Service-Bindings, Handler-Kontext
CapabilityEngine    Services, Hostrechte, Runtime-Caps, Plugin-Grenzen
TransportEngine     Nachrichtenbewegung zwischen Contexts/Nodes

Spezialisierte Engines komponieren fundamentale Engines:

HttpEngine =
  RouteBlueprint
  + SchedulerEngine
  + CodecEngine
  + ResourceEngine
  + CapabilityEngine
  + MiddlewareBlueprints

ActorEngine =
  FunctionUnion
  + SchedulerEngine
  + ConcurrencyEngine
  + DispatchEngine
  + MailboxPolicy

RpcEngine =
  FunctionUnion
  + CodecEngine
  + TransportEngine
  + DispatchEngine
  + CapabilityEngine

Der wichtige Satz:

Spezialisierte Engines besitzen nicht die ganze Welt selbst. Sie orchestrieren fundamentale Engines innerhalb eines Contexts.

17.2 Engine-Spezialisierung ueber Protocols und Provides

Eine Engine wird nicht durch Vererbung erweitert, sondern ueber Protocol-Faehigkeiten und provide-Implementierungen spezialisiert.

Beispielhaft:

protocol RoutableEngine[E] {
    def describeRoutes(self: E) -> RouteTableDescriptor
}

protocol MiddlewareEngine[E, M] {
    def applyMiddleware(self: E, middleware: M) -> MiddlewareDescriptor
}

provide RoutableEngine[HttpEngine] for HttpEngine {
    def describeRoutes(self) -> RouteTableDescriptor = ...
}

provide MiddlewareEngine[HttpEngine, AuthMiddleware] for HttpEngine {
    def applyMiddleware(self, middleware: AuthMiddleware) -> MiddlewareDescriptor = ...
}

Provides duerfen eine Engine nur innerhalb erlaubter Protocol-Grenzen erweitern. Sie duerfen keine fremden Descriptoren direkt schreiben, keine Ring-0-Facts aendern und keine Runtime-Capabilities heimlich einschleusen.


18. ContextApi und ContextBridge

18.1 ContextApi: Gatekeeper innerhalb eines Contexts

Die ContextApi ist die lokale API innerhalb eines Contexts. Engines verwenden sie, um Services, Storage, Scheduler, Messaging oder Ressourcen anzufordern.

Engine -> ContextApi.require(Service)
Engine -> ContextApi.schedule(task)
Engine -> ContextApi.openArena(RequestArena)
Engine -> ContextApi.send(message)
Engine -> ContextApi.resolveCodec(typeId)

Die ContextApi prueft gegen den ContextDescriptor:

allowed?
local binding?
parent exposed it?
capability satisfied?
lifetime/resource policy ok?

Wenn statisch bekannt: Compile-Time-/Load-Time-Fehler. Wenn erst zur Runtime sichtbar: Trap am Context-Gate.

18.2 ContextBridge: Gatekeeper zwischen Contexts

Eine ContextBridge ist eine explizit deklarierte, typisierte und policy-gepruefte Kommunikationsoberflaeche zwischen zwei ansonsten isolierten Contexts.

Wichtig:

ContextApi     = Gatekeeper innerhalb eines Contexts
ContextBridge  = Gatekeeper zwischen zwei Contexts

Ohne Bridge gibt es keinen Kommunikationspfad. Nicht "verboten, aber technisch moeglich", sondern schlicht: nicht adressierbar.

+-------------------+          +-------------------+
| PluginContext     |          | ApplicationContext |
|                   |          |                   |
| Engine A          |          | Engine B          |
|   |               |          |   ^               |
|   v               |          |   |               |
| ContextBridge ----+----------+---+               |
+-------------------+          +-------------------+

Eine Bridge exponiert nur die deklarierte Oberflaeche:

allowed messages
allowed queries
allowed commands
codec / wire format
capability requirements
direction
lifetime
backpressure policy
error model
trust policy

Beispielhaft ueber eine Function Union:

type UserPluginBridge : union =
    | getUser(id: UserId) -> Result[UserView, UserError]
    | emitAudit(event: AuditEvent) -> Result[(), AuditError]

Daraus kann entstehen:

ContextBridgeDescriptor {
  from: PluginContext
  to: ApplicationContext
  interface: UserPluginBridge
  allowedQueries: [getUser]
  allowedCommands: [emitAudit]
  codec: JadeWire
  capabilities: [ReadUser, EmitAudit]
  policy: LocalOnly
}

Damit bekommt der PluginContext nicht direkt UserDb, nicht den WebContext und nicht den Scheduler des Parent. Er bekommt nur die im BridgeDescriptor erlaubten Operationen.

18.3 Bridge-Formen

Die Bridge-Semantik bleibt gleich, auch wenn die Mechanik variiert:

local bridge     gleiche VM, billige Message/Call-Grenze
thread bridge    Scheduler/Mailbox-Grenze
process bridge   Transport/Codec-Grenze
node bridge      Jade Node / Netzwerk
mock bridge      TestContext / deterministic replay

Die Form ist Mechanik. Die erlaubte Oberflaeche ist Descriptor-Semantik.


19. Context-Hierarchie und Parent-Expose

Contexts koennen hierarchisch angelegt werden, aber Kommunikation bleibt explizit.

ApplicationContext
  |
  +-- WebContext
  |     |
  |     +-- RequestContext
  |
  +-- ActorContext[WorkerPool]
  |
  +-- PluginContext[ImageCodec]
  |
  +-- ReplContext

Ein ChildContext sieht nicht automatisch den Parent. Der Parent muss gezielt Services oder Bridges exposen.

ParentContext
  exposes: [Logger, Config]

PluginContext
  imports: [Logger]
  cannot see: Db, Network, SchedulerInternals

Der Context ist damit eine kontrollierte Env. Er gruppiert sinnvoll. Er enthaelt alles, was seine Aufgabe gesichert abarbeiten muss, aber nicht mehr.


20. Storage im Context

Storage kann ueber normale Blueprints im Context verdrahtet werden. Es gibt aber kein eigenes Keyword service blueprint oder context blueprint. Es gibt nur blueprint; Rollen ergeben sich aus Struktur, Refinements und Provides.

Wichtig:

Nicht:
  Context bekommt die JME.

Sondern:
  Context bekommt Storage-Policies, Arena-/Pool-Specs und Limits.
  Die JME bleibt Ring-0-Mechanik.

Beispielhaft:

type RequestStorage : blueprint {
    requestArena: ArenaSpec
    bodyPool: PoolSpec
    limits: StorageLimits
}

type WebContext : blueprint {
    storage: RequestStorage
    scheduler: SchedulerConfig
    services: ServiceSet
    engines: EngineSet
}

Compile-Time / Load-Time:

RequestStorage
  -> StorageDescriptor
  -> ArenaDescriptor
  -> PoolDescriptor
  -> StorageLimitDescriptor
  -> ContextDescriptor

Runtime:

ContextDescriptor
  -> StorageDescriptor
  -> JME creates/enforces arenas, pools, rc policies, limits

Der Satz:

Storage ist im Context als deklarierte Policy verdrahtet; operative Speicherhoheit bleibt bei der JME.


21. Context-Flut vermeiden

Context ist stark, solange er selten und begruendet bleibt. Ohne Regeln wird Context zur neuen Gottklasse.

21.1 Ein Schema, viele Profile

Es gibt ein gemeinsames ContextDescriptor-Schema. Profile sind vordefinierte Belegungen dieses Schemas.

Nicht:

WebContextDescriptor
ActorContextDescriptor
FfiContextDescriptor

als inkompatible Welten.

Sondern:

ContextDescriptor(profile = Web)
ContextDescriptor(profile = Actor)
ContextDescriptor(profile = Ffi)

21.2 Keine Feature-Contexts

Kein eigener Context fuer:

JsonContext
AuthContext
LoggingContext
MetricsContext
ValidationContext

Das sind Services, Middleware, Engines, Refinements oder Policies.

21.3 Lint-Regeln

Spaeter sollte Tooling Context-Missbrauch melden:

CONTEXT-001: Context unterscheidet sich nur durch Service-Binding.
CONTEXT-002: Context hat keine eigene Capability-Grenze.
CONTEXT-003: Context dupliziert Scheduler/Storage-Profil.
CONTEXT-004: Engine-spezifische Policy wurde als Context modelliert.

22. Syntax-Sugar und User-Erweiterungen

JDL-Syntax sollte nicht magisch sein. Eingebauter Sugar und User-Sugar sollten dieselbe Mechanik verwenden.

Grundfluss:

Surface Syntax
  -> SyntaxDescriptor
  -> ParserCombinator
  -> SyntaxNode / SugarNode
  -> LoweringProvider
  -> normales AST / Descriptor / Extended IR
  -> Core IR

Eingebauter Sugar:

:=        -> val-Binding mit Type Inference
|>        -> verschachtelte Calls / Pipeline-IR
=?        -> Result-Propagation
with      -> Scope-/Resource-Desugaring

User-Sugar:

do Effect { ... }
  -> EffectDoNode
  -> EffectDescriptor oder Effect-Kombinatoren
  -> normales IR

Der Unterschied ist Autoritaet, nicht Mechanik.

Built-in JDL Sugar
  privilegierter, versionierter Standard-Provider

User Syntax Extension
  scoped, context-/package-/namespace-gebunden,
  Constitution-/Materializer-geprueft

22.1 SyntaxExtensionDescriptor

Eine Syntax-Erweiterung sollte materialisiert werden als:

SyntaxExtensionDescriptor {
  scope
  entryPoint
  precedence
  associativity
  parserCombinator
  outputNodeKind
  loweringProvider
  conflicts
  requiredCapabilities
}

Die ParserEngine kann dadurch pruefen:

Ist diese Syntax in diesem Context aktiv?
Kollidiert sie mit bestehender Syntax?
Welche Prioritaet hat sie?
Welche Fehlermeldungen liefert sie?
Welcher Lowerer ist zustaendig?

22.2 Harte Regeln fuer Syntax-Erweiterungen

1. Core-Syntax bleibt klein und stabil.
2. Sugar lowered immer zu normaler Semantik.
3. User-Sugar ist scoped, nie global.
4. Bestehende Syntax darf nicht ueberschrieben werden.
5. Lowering darf keine Ring-0-Facts aendern.
6. Parser erzeugt Syntax, aber committed keine Descriptoren.
7. Der Verifier sieht nur gelowerten IR/Core.

Der Satz:

JDL-Syntax ist privilegierter, standardisierter Sugar ueber dieselben Syntax-/Lowering-Schnittstellen, die auch kontrollierte User-Erweiterungen verwenden duerfen.

Das erlaubt lokale DSLs, ohne die VM-Semantik zu veraendern.


23. Constitution-Enforcement als Blueprint-System

Eine Constitution ist kein Text, der streng schaut. Sie wird selbst materialisiert.

ConstitutionSpec
  -> ConstitutionEngine
  -> ConstitutionDescriptor
  -> RuleIndex / EnforcementHooks
  -> Compilerphasen / Runtime-Gates

Regeln laufen nicht frei als beliebiges Programm, sondern werden in eine endliche Regel-Algebra normalisiert.

Minimalstruktur:

type ConstitutionRule : struct {
    trigger:   RuleTrigger
    selector:  RuleSelector
    predicate: RulePredicate
    action:    RuleAction
}

Typische Trigger:

OnNamespaceLoad
OnImport
OnTypeSubject
OnApplyRefinement
OnProvide
OnEffectDescriptor
OnDescriptorCommit
OnIrVerify
OnArtifactEmit

Wichtigster Gate: OnDescriptorCommit. Dort wird verhindert, dass illegale Semantik zur CompilerDB-Wahrheit wird.

Der Satz:

Eine Blueprint-Constitution wird enforced, indem sie in einen ConstitutionDescriptor mit endlicher Regel-Algebra materialisiert wird. Enforcement passiert an festen Gates der Compiler- und Runtime-Pipeline, nicht durch freie Programmausfuehrung.


24. Compile-Time Inlining und Lazy

24.1 Comptime Inlining

Comptime Inlining ist kein VM-Feature. Es ist ein IR-/Pass-Thema.

Function / expression
  -> typed IR
  -> Inline-Pass
  -> optimierter IR
  -> Lowering
  -> Core IR

Gute Kandidaten:

kleine pure Funktionen
Operator-Wrapper
CastTo lossless
kleine Provide-Methoden
Getter/Setter
kleine Generator-Combinators
kleine Function-Union-Dispatcher

Schlechte Kandidaten:

grosse Funktionen
rekursive Funktionen
FFI-Grenzen
RuntimeBus-Commands
Scheduler-/JME-Operationen
Debug-Hooks

Inline sollte ein Hint oder Refinement sein, kein semantischer Zwang.

24.2 Lazy

Jade hat bereits zwei saubere Lazy-Formen:

Generator[T]
  lazy Sequenz, next() liefert Option[T]

Effect[R, E, D]
  Beschreibung einer Berechnung, Ausfuehrung erst durch Dependency-Kontext

VM-Lazy sollte nicht allgemeiner Auswertungsmodus sein. Falls spaeter noetig, dann als expliziter Typ:

Lazy[T]
  Unevaluated(thunk)
  Evaluating
  Evaluated(value)
  Failed(error/trap)

Empfehlung:

Lazy als Oberflaeche
Fusion/Inlining im IR
keine versteckte VM-weite Lazy-Semantik

Pipeline-Fusion ist wichtiger als VM-Lazy:

users |> filter(active) |> map(email) |> collect

naiv:
  Generator wrapper + closures + next calls

optimiert:
  eine Schleife mit if und push

25. Property Testing und Arbitrary

Property Testing passt sehr gut zu Jade, weil Jade Descriptoren besitzt.

Normales Muster:

TypeDescriptor[T]
  -> Derive(Arbitrary)
  -> ProvideDescriptor Arbitrary[T]
  -> TestArtifact

Arbitrary sollte nicht nur Zufallswerte erzeugen, sondern auch shrinken.

type GenSeed : struct {
    value: u64
}

type GenContext : struct {
    seed:  GenSeed
    size:  u32
    depth: u32
}

type GenResult[T] : struct {
    value: T
    seed:  GenSeed
}

protocol Arbitrary[T] {
    def arbitrary(ctx: GenContext) -> GenResult[T]
    def shrink(value: T) -> Generator[T]
}

Rng oder besser GenRng ist ein deterministischer Seed-Transformer:

type RngStep : struct {
    random: u64
    seed:   GenSeed
}

def nextRandom(seed: GenSeed) -> RngStep

Eigenschaft:

gleicher Seed rein
  -> gleicher Wert raus
  -> gleicher naechster Seed raus

Damit sind Testfehler reproduzierbar.

Beispiel:

property failed:
  seed = 0x91af33c2
  case = User { name: "", age: -1 }

Ein TestContext kann dafuer bereitstellen:

PropertyEngine
GeneratorEngine
ShrinkerEngine
SeedControl
FailureDatabase
DeterministicScheduler
MockBridge

Property Testing prueft nicht nur Usercode, sondern auch Jade selbst:

parse(prettyPrint(ast)) ~= ast
lower(extendedIR) enthaelt keine ExtendedOps
serialize(deserialize(x)) == x
copy(x) erhaelt Struktur und Sharing-Regeln
dyn -> concrete Pipeline akzeptiert nur erlaubte Typen
ContextDescriptor erlaubt keine nicht deklarierten Capabilities

26. Content-addressable Jade Store

Nix adressiert immutable Store-Objekte und ihre Closure. Jade kann ein aehnliches Prinzip fuer Jade-native Artefakte sauberer anwenden, weil Jade-Artefakte selbst descriptor-basiert sind und nicht aus fremden Buildsystemen domestiziert werden muessen.

Jade sollte keinen Git-Tree nachbauen. Git adressiert Source-Historie. Jade sollte gepruefte Artefakte und Descriptor-Closures adressieren.

Git:
  Was ist der Dateibaum?

Nix:
  Was ist das gebaute Store-Objekt und seine Closure?

Jade:
  Was ist das gepruefte Artefakt, seine Descriptoren,
  sein Context und seine Closure?

Moegliche ArtifactId:

ArtifactId = hash(
  normalized JBC,
  descriptorSet,
  contextDescriptor,
  runtimeTypeProjections,
  dependencyArtifactIds,
  targetDescriptor,
  abiProfile,
  capabilityDescriptor
)

Unterscheidung:

Pure Jade Artifact
  JBC, Descriptoren, Context-Anforderungen
  stark reproduzierbar
  gut content-addressable

Host-bound Jade Artifact
  FFI, ABI, OS-Caps, native Bindings
  braucht TargetDescriptor
  reproduzierbar relativ zu Host-/ABI-Profil

External Artifact
  fremde Software, C-Lib, Systempaket
  braucht eigene Integritaets- und Provenance-Regeln

Der Satz:

Jade muss nicht jedes fremde Buildsystem nachtraeglich disziplinieren. Jade kann Artefaktsemantik selbst definieren. Fremdheit kommt nur an den Raendern zurueck und muss dort explizit descriptorisiert werden.


27. := als lokale immutable Type-Inference-Bindung

Aus der Odin-Diskussion wurde ein moegliches Sugar-Modell fuer JDL abgeleitet.

x := 123

Sollte bedeuten:

neue lokale immutable Bindung
Typ wird aus Initializer inferiert

Aequivalent zu:

val x = 123

Nicht erlaubt:

x := 456        // wenn x bereits existiert
var x := 123    // Unsinn
pub x := 123    // API sollte expliziter sein

Harte Regel:

:= darf niemals mutable erzeugen.
var bleibt fuer Mutation immer explizit.

Damit bleibt die Grundwahrheit sichtbar:

Immutability ist Default.
Mutation ist explizit.

28. Architektur-Story von Jade

Die bisherige Diskussion laesst sich in einen zentralen Satz verdichten:

Jade trennt deklarierte Absicht, gepruefte Bedeutung und laufende Ausfuehrung.

Oder technischer:

Blueprints beschreiben Absicht.
Refinements praezisieren Absicht.
Provides binden Faehigkeiten.
Descriptoren materialisieren Bedeutung.
Contexts begrenzen Ausfuehrung.
Bridges kontrollieren Context-Grenzen.
Engines betreiben dynamische Ablaeufe.
VM/JME/RuntimeBus fuehren kontrolliert aus.

Jade loest damit reale Probleme:

- globale Runtime-Umgebungen werden explizit und gegrenzt
- Dynamik wird descriptor-basiert statt Any-basiert
- Compile-Time-Wissen verdampft nicht, sondern wird selektiv exportiert
- Plugins werden in eigene Contexts isoliert
- Web/RPC/Actor/REPL koennen auf denselben Descriptor-Grundlagen bauen
- Artefakte koennen in Jade Node / JadeOS reproduzierbar aktiviert werden

Der Pitch ohne Vergleichsfolklore:

Jade macht die Ausfuehrungsumgebung eines Programms zum Teil der Sprache.

Oder:

Jade ist eine VM-first Sprache fuer descriptor-getriebene Anwendungen. Sie verbindet statische Typsemantik mit kontrollierter Runtime-Dynamik: Blueprints beschreiben Absicht, Descriptoren materialisieren Bedeutung, Contexts begrenzen Ausfuehrung, Engines betreiben die Anwendung.

Wichtige Warnung:

Die Maschine darf tief sein.
Die Oberflaeche muss ruhig bleiben.

Nutzer sollten zuerst einfache Formen sehen:

route POST "/users"
    :> Body[CreateUser]
    :> Returns[User]
    :> Uses[UserDb]

Nicht zuerst:

RouteBlueprint -> ContextDescriptor -> EngineBindingDescriptor -> ...

Die innere Jade-Regel lautet:

Ergonomie oben.
Strenge unten.

29. Erweiterte offene Entscheidungen

Zu den bisherigen offenen Entscheidungen kommen hinzu:

  1. ContextDescriptor-Schema: Welche Felder sind Kernschema, welche Profile?
  2. ContextApi: minimale API fuer require, schedule, openResource, send, resolve.
  3. ContextBridgeDescriptor: genaue Form fuer Queries, Commands, Messages, Policies.
  4. Parent-Expose-Modell: wie Services/Capabilities vom Parent an Child-Contexts gegeben werden.
  5. Fundamentale Engines: finale Liste und Grenze zwischen Ring 1/Ring 2.
  6. Storage im Context: Syntax und Descriptoren fuer Arena-/Pool-/Rc-Policies.
  7. SyntaxExtensionDescriptor: ParserCombinator-, Precedence-, Scope- und Lowering-Modell.
  8. JDL-eigener Sugar: welche Sprachformen werden selbst ueber diese Pipeline definiert?
  9. Arbitrary/Property Testing: Stdlib-Protocol, derive-Mechanik, TestContext.
  10. Artifact Store: Content-addressed Store fuer Jade-native Artefakte.
  11. Context-Flut-Lints: wann ist ein Context-Profil gerechtfertigt?
  12. Inline/Fusion/Lazy: welche Optimierungen sind IR-Pass, welche Stdlib-Typen, welche VM-Mechanik?

30. Ergaenzte Spec-Patch-Empfehlungen

30.1 Neue Context-Spec

Anlegen einer eigenen Spec, z.B.:

jdl-context-model.md

Inhalte:

Context als static env
ContextDescriptor-Schema
ContextApi
Context-Profile
Parent-Expose
ContextBridge
Context-Flut-Regeln
PluginContext-Isolation

30.2 Engine-/Descriptor-Spec aktualisieren

Ergaenzen:

fundamentale Engines
spezialisierte Engines als Komposition
Engine dynamic env vs Context static env
Engine-Spezialisierung ueber Protocols/Provides
Scheduler/Storage nicht als Engine-Eigentum, sondern Context-Policy + Ring-0-Mechanik

30.3 Parser-/Syntax-Spec ergaenzen

Ergaenzen:

SyntaxExtensionDescriptor
ParserCombinator-Registry
scoped Syntax Activation
LoweringProvider
JDL-Sugar nutzt dieselbe Pipeline wie User-Sugar
Konflikt-/Precedence-Regeln

30.4 Test-/Property-Spec anlegen

Ergaenzen:

Arbitrary[T]
GenSeed / GenContext / GenResult
Shrink-Protokoll
TestContext
FailureDatabase
deterministische Reproduktion
Descriptor-basiertes derive Arbitrary

30.5 Artifact-/Store-Spec spaeter anlegen

Ergaenzen:

JadeArtifactId
DescriptorClosure
ContextDescriptor im Artefakt
RuntimeTypeProjection
TargetDescriptor
Host-bound vs Pure Jade Artifacts
Content-addressed Store