Reserved capability fields#
The sidecar schema reserves an optional launch object for future
launch-configuration metadata:
"launch": {
"block": 256,
"shmem_bytes": 0,
"grid": {}
}
block— int (reserved: thread-block size hint)shmem_bytes— int (reserved: dynamic shared-memory bytes hint)grid— object (reserved: freeform grid-configuration hint)
These fields are reserved in v1: unpopulated, and the current loaders ignore
them. They may be populated in a future minor revision without a
``schema_version`` bump. The schema keeps additionalProperties permissive on
both the launch object and the top-level object so unknown/future keys do not
fail validation of the reserved surface.
This ignore-unknown guarantee — for launch specifically, and for any
unrecognized top-level sidecar/manifest key generally — is exercised by an
executable test on both loaders, not just asserted in prose:
eagle/python/tests/test_schema_hardening.py and
eagle/tests/test_SchemaHardening.cpp. No launch hint is populated by the
producer today; adding one is a deliberate design decision, not a casual
addition.
Note
Do not confuse this reserved launch sidecar field with eagle’s own,
unrelated idealBlockSize concept in the native CUDA-graph machinery
(eagle/cuda/{Graph.h, CapturedGraph.h, Launcher.h, ComputeBlocks.h}) — a
per-captured-kernel blockDim-reconciliation cap used when composing native
eagle graph nodes. The two share a naming convention, not a design link.
The schema files#
manifest-v1.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/amasat01/eagle/raw/main/docs/schemas/manifest-v1.schema.json",
"title": "EAGLE plugin deployment manifest (schema v1)",
"description": "Frozen schema v1 for the EAGLE deployment manifest emitted by the code generator's deploy pipeline (deploy/bundle.py). A manifest describes one deployment set: an ordered list of plugin artifacts (+ their sidecars) that the C++ PluginRegistry (or the Python loaders) consume as a self-contained unit. The list order is the injection order. Validators are backward-lenient (an absent schema_version is treated as v1) and forward-strict (a schema_version newer than the loader is rejected). Unknown/future top-level keys are tolerated so a future minor revision may add keys without a schema_version bump; additionalProperties is therefore true.",
"type": "object",
"required": ["aether_abi", "plugins"],
"additionalProperties": true,
"properties": {
"schema_version": {
"const": 1,
"description": "Plugin-schema version this manifest conforms to. Single-sourced from eagle.roles.SCHEMA_VERSION / plugin/roles.h::kPluginSchemaVersion. Absent ⇒ treated as v1 (backward-lenient); a value greater than the loader supports ⇒ rejected (forward-strict). Orthogonal to aether_abi."
},
"version": {
"type": "integer",
"description": "Legacy manifest-version alias (always 1). Retained for pre-freeze readers; superseded by schema_version, which the loaders read. A loader falls back to this key when schema_version is absent."
},
"pattern": {
"type": "string",
"description": "Tag naming the plugin family of the bundle. The code generator's Bundle builder emits one of the canonical values \"vector\" | \"pure\" (a Bundle is pattern-homogeneous). The Python load_manifest / C++ PluginRegistry are STRICT: an unknown OR absent pattern is rejected. It is typed as a string (not enum-constrained) so a future family can be added without a schema bump, but the current loaders accept only \"vector\" | \"pure\"."
},
"aether_abi": {
"const": "aether-abi/1",
"description": "Binary-ABI tag of the by-value GRef / HandleT POD mirrors this set was built against. Separate from and orthogonal to schema_version: it is the ABI-stable binary-layout contract. A loader rejects a mismatch before binding any by-value struct."
},
"plugins": {
"type": "array",
"description": "The set's plugin artifacts in declared (injection) order.",
"items": { "$ref": "#/$defs/pluginEntry" }
}
},
"$defs": {
"pluginEntry": {
"type": "object",
"description": "One artifact in the set: its stable id, injection order, enabled flag, artifact + sidecar filenames (relative to the manifest directory), and the artifact format.",
"required": ["id", "order", "enabled", "artifact", "sidecar", "format"],
"additionalProperties": true,
"properties": {
"id": {
"type": "string",
"description": "Stable, unique plugin id (from the kernel function name; duplicates get a numeric suffix)."
},
"order": {
"type": "integer",
"minimum": 0,
"description": "Injection order == list index (the deterministic sequence in which a vector set accumulates into outVec)."
},
"enabled": {
"type": "boolean",
"description": "Whether the registry loads this plugin."
},
"artifact": {
"type": "string",
"description": "Artifact filename (<id>.<ext>), relative to the manifest directory."
},
"sidecar": {
"type": "string",
"description": "Sidecar filename (<id>.json), relative to the manifest directory."
},
"format": {
"enum": ["ptx", "cubin", "fatbin"],
"description": "Artifact format: arch-portable PTX, single-arch cubin, or multi-arch fatbin."
}
}
}
}
}
sidecar-v1.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/amasat01/eagle/raw/main/docs/schemas/sidecar-v1.schema.json",
"title": "EAGLE plugin sidecar (schema v1)",
"description": "Frozen schema v1 for the per-artifact JSON sidecar emitted by the code generator's deploy pipeline (deploy/compile.py). A sidecar describes one plugin's launch signature: a shared base plus one of two pattern-specific variants (vector | pure). arg_spec is the ordered list of [role, name] pairs a loader binds; every role must be one of the 9 canonical schema-v1 roles enumerated inline (plugin/roles.h::kPluginArgRoles ≡ eagle.roles.ROLES). Validators are backward-lenient (absent schema_version ⇒ v1) and forward-strict (an unknown role, or a schema_version newer than the loader, ⇒ rejected). Unknown/future top-level keys are tolerated (additionalProperties true) so a future minor revision may add keys — including populating the reserved launch surface — without a schema_version bump.",
"type": "object",
"additionalProperties": true,
"required": [
"format",
"pattern",
"aether_abi",
"scalar_type",
"kernel",
"vector_inputs",
"params",
"per_sample",
"arg_spec"
],
"properties": {
"schema_version": {
"const": 1,
"description": "Plugin-schema version this sidecar conforms to. Single-sourced from eagle.roles.SCHEMA_VERSION. Absent ⇒ treated as v1 (backward-lenient); newer than the loader ⇒ rejected (forward-strict). Orthogonal to aether_abi."
},
"format": {
"enum": ["ptx", "cubin", "fatbin"],
"description": "Artifact format the sidecar accompanies: arch-portable PTX, single-arch cubin, or multi-arch fatbin."
},
"pattern": {
"enum": ["vector", "pure"],
"description": "Plugin family — selects the variant-specific required fields (see the conditional blocks). A loader refuses the wrong artifact family; an unknown OR absent pattern is a hard error (strict)."
},
"aether_abi": {
"const": "aether-abi/1",
"description": "Binary-ABI tag of the by-value GRef / HandleT POD mirrors the artifact was built against. Separate from and orthogonal to schema_version: the ABI-stable binary-layout contract. A loader rejects a mismatch before binding any by-value struct."
},
"scalar_type": {
"enum": ["float64", "float32", "softdouble"],
"description": "Real scalar type the kernel was compiled for."
},
"kernel": {
"type": "string",
"description": "The extern-\"C\" entry-point symbol the loader resolves in the artifact: always \"raptor_kernel\", the name raptor's schema fixes for every producer, hand-written kernels included."
},
"vector_inputs": {
"type": "array",
"items": { "type": "string" },
"description": "Named vector inputs, in binding order (mirrors the vec_in arg_spec roles)."
},
"params": {
"type": "array",
"items": { "type": "string" },
"description": "Named uniform scalar parameters (bound via the uniform role)."
},
"per_sample": {
"type": "array",
"items": { "type": "string" },
"description": "Named per-sample scalar inputs (bound via the per_sample role)."
},
"arg_spec": {
"$ref": "#/$defs/argSpec"
},
"vec_widths": {
"$ref": "#/$defs/vecWidths"
},
"launch": {
"$ref": "#/$defs/launch"
},
"accumulate": {
"type": "boolean",
"description": "Vector only: whether the sink (out) uses the outVec `+=` accumulate idiom."
},
"sink": {
"type": "string",
"description": "Vector only: the accumulate sink contract name (e.g. \"outVec-scratch\") — a per-kernel deterministic-reduce scratch slot, not the final total."
},
"buffers": {
"$ref": "#/$defs/buffers"
},
"mutables": {
"$ref": "#/$defs/mutables"
},
"matrix_inputs": {
"type": "array",
"items": { "type": "string" },
"description": "Pure only, and only when the kernel has matrix inputs: the mat_in binding order (mirrors vector_inputs)."
},
"mat_shapes": {
"$ref": "#/$defs/matShapes"
},
"derivative": {
"type": "object",
"description": "Optional, additive schema-v1 field (no version bump): present only for a VJP/JVP derivative artifact (autodiff, generated or custom — structurally indistinguishable). Metadata only; the artifact still launches as an ordinary pure kernel. Recompute-only in v1, so residual_policy is 'recompute' and residuals is []; a populated residuals list is a future revision that bumps schema_version and is rejected by a v1 loader.",
"properties": {
"kind": { "enum": ["vjp", "jvp"] },
"primal": { "type": "string", "description": "the primal kernel's logical id" },
"wrt": { "type": "array", "items": { "type": "string" }, "description": "the differentiated input names" },
"residual_policy": { "const": "recompute" },
"residuals": { "type": "array", "maxItems": 0, "description": "always empty (recompute-only)" }
},
"required": ["kind", "wrt", "residual_policy", "residuals"],
"additionalProperties": true
}
},
"allOf": [
{
"if": {
"required": ["pattern"],
"properties": { "pattern": { "const": "vector" } }
},
"then": {
"required": ["accumulate", "sink", "vec_widths", "buffers"]
}
},
{
"if": {
"required": ["pattern"],
"properties": { "pattern": { "const": "pure" } }
},
"then": {
"required": ["mutables", "vec_widths", "buffers"]
}
}
],
"$defs": {
"role": {
"description": "The 9 canonical schema-v1 arg-spec roles. Single source of truth: plugin/roles.h::kPluginArgRoles ≡ eagle.roles.ROLES (cross-checked by python/tests/test_roles_vocab.py). A loader rejects any role outside this set at LOAD time (forward-strict). Note: mat_in is a valid role recognized by every loader, but the reference C++ host inject() does not pack matrix arguments (a CUDA-backend capability).",
"enum": [
"out",
"vec_in",
"mat_in",
"per_sample",
"lookup",
"mutable",
"terminated",
"uniform",
"nsamples"
]
},
"argSpec": {
"type": "array",
"description": "Ordered list of [role, name] pairs (role FIRST) the loader binds in sequence.",
"items": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"prefixItems": [
{ "$ref": "#/$defs/role" },
{ "type": "string", "description": "The argument name (a vector_input / param / per_sample / mutable / buffer name, or a fixed slot name such as \"out\"/\"terminated\"/\"nsamples\")." }
],
"items": false
}
},
"vecWidths": {
"type": "object",
"description": "Per-name vector width (component count) so a host can allocate (W, N) buffers; the GRef struct itself is width-independent. Present on both variants.",
"additionalProperties": { "type": "integer" }
},
"buffers": {
"type": "array",
"description": "Declared read-only lookup buffers (the consolidation contract). Present on both variants. May be empty.",
"items": { "$ref": "#/$defs/buffer" }
},
"buffer": {
"type": "object",
"description": "One read-only lookup buffer the registry uploads once at consolidation and binds by value as a flat handle.",
"required": ["name", "kind", "dtype", "shape", "count"],
"additionalProperties": true,
"properties": {
"name": { "type": "string" },
"kind": { "const": "lookup" },
"dtype": { "const": "float" },
"shape": {
"type": "array",
"items": { "type": "integer" },
"description": "Buffer dimensions."
},
"count": {
"type": "integer",
"description": "Flat element count == prod(shape)."
}
}
},
"mutables": {
"type": "array",
"description": "Pure only: the writable per-sample state that IS the pure output.",
"items": { "$ref": "#/$defs/mutable" }
},
"mutable": {
"type": "object",
"description": "One writable per-sample slot. dtype/width let a loader rebuild which Mutables ride the (W, N) GRef ABI vs a flat scalar handle; the optional default fills an omitted Mutable. A matrix slot additionally carries its (R, C) shape.",
"required": ["name", "dtype", "width"],
"additionalProperties": true,
"properties": {
"name": { "type": "string" },
"dtype": {
"enum": ["float", "int", "vector", "matrix"],
"description": "Element kind of the mutable."
},
"width": {
"type": "integer",
"description": "Flat component count (1 for a scalar)."
},
"default": {
"type": ["number", "null"],
"description": "Scalar fill value for an omitted mutable (null when none)."
},
"shape": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": { "type": "integer" },
"description": "The (R, C) shape — present ONLY when dtype == \"matrix\" (the flat width alone cannot be un-flattened)."
}
},
"if": {
"properties": { "dtype": { "const": "matrix" } },
"required": ["dtype"]
},
"then": {
"required": ["shape"]
}
},
"matShapes": {
"type": "object",
"description": "Pure only, and only when the kernel has matrix inputs: the (R, C) shape per matrix-input name.",
"additionalProperties": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": { "type": "integer" }
}
},
"launch": {
"type": "object",
"description": "RESERVED in v1 (unpopulated; loaders ignore). Populated in a future minor revision without a schema_version bump. additionalProperties is true so unknown/future launch keys do not fail validation of the reserved surface.",
"additionalProperties": true,
"properties": {
"block": {
"type": "integer",
"description": "Reserved: thread-block size hint."
},
"shmem_bytes": {
"type": "integer",
"description": "Reserved: dynamic shared-memory bytes hint."
},
"grid": {
"type": "object",
"additionalProperties": true,
"description": "Reserved: freeform grid-configuration hint (shape TBD)."
}
}
}
}
}