Schema And Contract Reference#
Noema separates what is being evaluated from how it is executed. A recipe is the compiled experiment instance; a template is only a reusable way to create that instance.
Recipe Field Ownership#
Concern |
Canonical owner |
Purpose |
|---|---|---|
Schema generation |
|
Selects the recipe contract. It is an integer, not a task or template version. |
Research purpose |
|
Tags reconstruction, classification, VQA, retrieval, and other scored outcomes for validation and result presentation. It does not select blocks. |
Execution topology |
|
Declares a versioned executable spine such as |
Executable graph |
|
Orders operation instances and connects typed outputs to inputs. |
Block configuration |
|
Configures one operation instance and is validated by that operation’s parameter schema. |
Experiment-wide protocol |
|
Holds seeds, measurement policy, provenance, and other values that apply across steps. |
Dataset-capture policy |
training plan |
Configures capture taps, partitions, and sampling without changing the scenario recipe. An embedded recipe field is accepted only for legacy files and transient capture jobs. |
Research-area discovery |
research-catalog |
Groups canonical scenarios for exploration without changing recipe semantics. |
Benchmark ownership |
|
Associates a recipe with a protocol family; it is not the template-browser taxonomy. |
Parameter sweep |
|
Defines dimensions and binds selected values into |
Training campaign |
Workbench |
Selects replaceable blocks, capture, and support framework after an ordinary recipe is chosen. Workbench derives reachable evaluation sinks automatically. An external objective may be recorded as provenance, but Workbench does not select it. |
Cross-recipe comparison |
benchmark pack |
Selects recipes, fixed overrides, roles, datasets, tasks, and metrics for a comparison. |
metadata.task_id remains a v1 compatibility alias. When it is present, it is resolved through the
research catalog and must agree with metadata.research.task.id. New recipes should use
metadata.research.task when an explicit declaration is needed. If the task can be inferred from a
specific source/metric graph, the declared and inferred task must also agree.
The training-plan fields are intentionally orthogonal: selected_steps chooses portable replacement
boundaries; optional loss_steps lets advanced CLI workflows narrow recipe route analysis, while
Workbench analyzes all reachable evaluation sinks automatically;
dataset_capture defines offline records/splits; and objective names an external or optional-demo
loss. An objective such as image.mse is never treated as a recipe step ID.
Purpose, Profile, And Steps Are Orthogonal#
These fields answer different questions:
metadata.research.task: What purpose/outcome is scored?execution_profile: What stable execution spine does this graph claim?steps: Which concrete operations execute, in what order?steps[].params: How is each concrete operation configured?
For example, image reconstruction can use either a layered_digital JPEG graph or a
joint_source_channel_symbols DeepJSCC graph. Conversely, a layered_digital profile can carry
image, text, or another payload. Combining purpose and profile into one discriminator would duplicate
the graph and make those valid combinations hard to represent.
Standard execution profiles are mandatory topology contracts during planning. custom is an
explicit opt-out for graphs that do not claim a standard spine; it may retain based_on provenance
after a standard graph is edited. See Recipe Execution Profiles.
Configurator Presentation#
The browser presents every open recipe through one stable hierarchy without adding another recipe schema:
Overview resolves the read-only purpose tag, working-copy origin, execution profile, graph size, and validation state from the ordinary recipe and its UI-only tab wrapper.
Blocks is the consistent primary editor. It exposes exact operation IDs, typed inputs, operation-schema parameters, wiring, sweeps, and artifact bindings for the current graph.
Recipe Settings owns recipe-wide identity and execution defaults plus explicit atomic controls that must update linked blocks together. Whole-pipeline presets are labeled as replacements and require confirmation.
Graph selection is transient browser state and is not written to recipe JSON. A template may retain an editor hint for compatibility, but opening the same compiled recipe through a formal template, the project recipe catalog, or a working copy produces the same Overview, Blocks, and Recipe Settings structure.
Graph nodes permanently display only the canonical block role, a compact configuration summary, and
the input-to-output flow. Technical step IDs remain available in delayed hover details and block
settings. The Workbench Operation Training Capabilities table follows the same convention: its
Block column uses the graph’s canonical role name, while the exact operation has its own column
and the technical step ID is available on delayed hover and in exported contracts. Built-in
fine-tuning is an explicit implementation capability (Operation.fine_tuning_supported plus a
callable operation-owned fine_tuning_provider, exposed as
training_capabilities.built_in_fine_tuning). No bundled operation currently advertises that action;
Portable replacement instead requires a complete
validated trained_artifact_abi. The older differentiability.trainable_params field is retained for
contract compatibility but is not a replacement or fine-tuning permission switch. Gradient and Differentiable
support describe the current operation when retained in a live graph; they are not selection gates
for replacing it.
Presentation routing is a versioned, code-only adapter registry. Adapter matching depends only on
canonical recipe content, with metadata.ui_configured: false retained as a compatibility opt-out
to the generic Blocks view. Template IDs, file paths, and tab editor preferences never select an
adapter. The registry contract and facet contract are currently version 1; their versions and
adapter IDs are UI implementation details and are never serialized into recipe JSON.
The header’s raw JSON editor is also a working-copy view. Apply sends the authored object to the strict validation-only endpoint, adopts the normalized response only after successful validation, and never writes the originating template or recipe file. Copy and paste operate on the editor draft, so invalid text remains recoverable until the user fixes or cancels it.
Templates#
A template is not a second runtime schema. It is a stored starter recipe or a deterministic builder that emits an ordinary recipe. After instantiation, validation and execution do not depend on which template produced it.
Template rules:
A public template defines a research scenario or genuinely distinct protocol topology, not a particular method, training mode, maturity label, smoke test, or saved workspace file.
Classical methods, learned fallbacks, and returned artifacts that share a topology belong behind a stable typed block selector. They are compared as benchmark-pack methods, not duplicated as separate templates.
Choosing a different template replaces the pipeline graph. It must not retain blocks from the previous pipeline, while user-authored recipe-wide identity and global protocol fields are preserved when replacing the current working copy.
Purpose is a declared or inferred semantic tag used for catalog grouping, metric validation, and result visualization. Editing purpose never inserts, removes, or rewires blocks.
An ordinary parameter edit preserves the current graph and changes only the selected values.
Template/source provenance may be kept for the UI, but it must not override recipe semantics.
Every generated recipe declares an
execution_profile; task builders do not infer topology from a UI label at execution time.Shared defaults belong in operation parameter schemas. Templates should specify deliberate experiment choices, not copy every operation default.
The resulting object model is deliberately small:
Scenario template discovers a canonical topology.
Recipe working copy records one configured method and protocol coordinate.
Training plan separately selects replacement blocks, capture taps/splits, and any external objective for one study.
Workbench training-interface bundle derives typed tensor and artifact-return contracts from the recipe plus that plan.
Benchmark pack stores the multi-method comparison used by a paper or documentation demo.
Run/benchmark result bundles preserve hashes, manifests, metrics, and artifacts as evidence.
There is no training template or workspace template layer. A training campaign must be derived
from any compatible ordinary recipe. A scenario is not advertised as closed-loop trainable until
its selected block has an operation-owned data contract and executable artifact-return ABI.
The recipe and training plan have independent SHA-256 identities. The recipe SHA answers “was the same runnable scientific scenario used?”; the training-plan SHA answers “were the same replacement targets, capture policy, route boundary, and framework used?” Export materializes the overlay only temporarily and writes both identities. Consequently, changing a training choice does not silently create a different scenario, while changing a recipe block or parameter does.
The backend template catalog in src/noema_lab/recipe_templates.yaml owns discovery and default
selection. Each entry declares id, label, task_id, editor, recipe_path, order, default,
status, the expected execution_profile, and optionally a packaged starter_resource. Every task
represented in the catalog has exactly one supported default; the catalog does not need to
represent every research-catalog task. Here task_id is the catalog’s purpose classification, not
a graph-building command. The Template Recipes browser is populated only by
GET /api/recipe-templates and presents those curated rows under research area and purpose.
GET /api/recipes remains available for explicit file loading, benchmark packs, tests, and saved
research assets, but it does not create a catch-all Workspace Recipes section. The browser must not
rediscover defaults from filename substrings or maintain a second purpose-to-template table.
Instantiation is by stable catalog ID. A file at <project_root>/<recipe_path> is an explicit
project override and takes precedence over starter_resource; an invalid override is reported and
never silently replaced by the built-in. If the override is absent, the packaged starter makes the
same template usable from an installed wheel without a repository checkout. Resolution, one-time
source reading, strict compilation, operation-registry validation, and task/profile contract checks
are performed together for every call, so prior inspection is not stale authorization to use a
changed file.
An instantiation may apply a typed step_params mapping, plus optional name and description,
before its final strict compilation. Step IDs and parameter names must exist in the starter or its
operation contract; parameter values retain their JSON types and still pass operation-owned schema
validation. The standalone recipe records only canonical provenance, not UI working-copy state:
metadata:
template_provenance:
schema_version: 1
kind: noema.recipe_template_provenance
template_id: ai_phy.pilot_channel_estimation.adapter
catalog_schema_version: 1
template_digest: sha256:<digest-of-template-catalog-entry>
source_kind: packaged_builtin # or project_override
source_reference: noema_lab:recipe_starters/channel_estimation_adapter_awgn.yaml
source_digest: sha256:<digest-of-exact-source-bytes>
overrides_digest: sha256:<digest-of-canonical-typed-overrides>
Use noema template instantiate <template-id> from the CLI or
POST /api/recipe-templates/instantiate from the dashboard. The browser keeps the active
configurator view, graph selection, working-copy state, and topology-preservation flags in its tab
wrapper; those UI concerns are not
written into the instantiated executable recipe. Template-time editor overrides use explicit
catalog editor_bindings (step_id, op, and param), which are checked against the selected
project override or packaged starter before the template is advertised as valid. A local editor
may merge parameter updates into existing step IDs, but cannot replace the catalog-owned operation
IDs, inputs, graph shape, or unrelated catalog-defined parameters.
The inspection response has catalog-level schema_version, status (valid, degraded, or
invalid), and templates. The server re-inspects the referenced project recipes when the endpoint
is requested, so a saved or externally edited template cannot leave process-lifetime validation
evidence stale. Each template row includes available, row validation (valid,
unavailable, or invalid), the selected source kind/digest, and a compact resolved-recipe summary.
A missing project override uses the packaged starter; discovery degrades only if neither source is
available. A task, profile, or recipe-contract mismatch is invalid. Multiple
templates may implement the same task only when they represent genuinely different protocols or
topologies—for example layered-digital text transport and continuous-symbol text JSCC. A baseline
operation and a learned replacement inside the same graph are method choices, not two templates.
The editor selects a compatible editing surface; it does not change recipe semantics.
Matrices And Concrete Coordinates#
metadata.matrix is the canonical authored parameter-space definition. Dimension values are
explicit lists. step_params binds dimensions to operation parameters by step ID; a
{matrix: <dimension>} reference may appear at any depth in the parameter value.
metadata:
matrix:
dimensions:
seed: [1, 2]
payload.bit_count: [1024, 4096]
step_params:
data:
seed: {matrix: seed}
bit_count: {matrix: payload.bit_count}
steps:
- id: data
op: source.random_bits
params:
seed: 0
bit_count: 1024
Expansion computes the Cartesian product of the dimensions, up to 256 concrete points. Unknown
steps or dimensions, unused dimensions, and malformed references are errors. Each concrete recipe
has the selected values applied to steps[].params, removes all matrix-definition aliases, and
records metadata.matrix_selection, its deterministic metadata.matrix_index, and a type-sensitive
stable metadata.matrix_variant_id of the form mxv1-<sha256>. The ID hashes canonical typed
coordinates, so booleans, integers, and floats remain distinct and harmless recipe renames or
dimension reordering do not change identity. The selection is provenance for one concrete point,
not another sweep definition.
Matrix planning strictly compiles the authored recipe and every concrete point through the same
operation registry. Single-run entry points reject an unresolved matrix before run-directory side
effects; use noema recipe run-matrix or the backend matrix-expansion API to execute its concrete
recipes. The dashboard uses those returned recipes verbatim rather than reapplying coordinates in
JavaScript.
The old flat authoring fields metadata.sweeps and metadata.ui_sweeps are compatibility-only
inputs. Readers normalize them when possible, but new recipes and UI edits write metadata.matrix.
When forms coexist, canonical matrix wins with a compatibility warning; without it, sweeps wins
over ui_sweeps. Strict legacy checking rejects either alias, which is useful for enforcing new
authored contracts without breaking v1 reads.
Benchmark recipe entries use the same coordinate name for already-materialized points:
recipes:
- id: jpeg_snr_8
path: recipes/jpeg_q75_kodak_repetition_awgn.yaml
params:
matrix_selection:
channel.snr_db: 8
step_params:
wireless_channel:
snr_db: 8
params.matrix_selection is canonical. When the source recipe declares matching matrix dimensions,
the benchmark loader requires a complete in-range selection, applies those bindings to
steps[].params, and rejects any conflicting explicit step_params override. The instantiated
benchmark recipe then contains the concrete selection and index, but no remaining matrix definition.
It also carries the same stable matrix_variant_id used by direct matrix and capture execution.
Additional coordinates that are not dimensions of the source recipe remain typed provenance; their
executable effects must still be declared through step_params.
The deprecated benchmark field params.sweep_values is accepted when it appears alone and is
normalized to metadata.matrix_selection in the concrete recipe. If both names appear, their
mappings must be identical. Concrete recipes never gain a new metadata.sweep_values alias.
Runtime Controls And Evidence#
Execution controls are invocation parameters, not recipe fields. parallel_workers selects the
local scheduler bound and use_plan_cache selects a planning optimization; neither belongs under
recipe metadata, execution_profile, or steps[].params. The CLI, HTTP API, and dashboard pass
them separately when starting a run.
The resulting summary.json and manifest.json both record execution.mode and
execution.parallel_workers. Their execution_plan.cache records the cache outcome and links it to
the immutable execution plan and authored/effective recipe hashes. Verification accepts older
bundles without these optional P3 fields, but if either copy is present its schema and cross-file
links must be consistent. See Execution Runtime.
Compilation Modes#
compile_recipe(..., mode="compat") supports existing v1 inputs. Unknown root or step fields and
implicit step IDs produce diagnostics, and unknown fields are retained so round-trips are lossless.
compile_recipe(..., mode="strict") turns those conditions into errors. The CLI recipe validate
command and the UI save endpoint use strict compilation. UI saves validate the default-expanded
recipe against the operation registry before atomically replacing a file, so invalid edits do not
damage the previous recipe.
Both modes require an exact supported integer schema_version when the field is supplied. Values
such as 0, 2, false, "1", or 1.0 are rejected.
Validation Boundaries#
Validation is layered deliberately:
The recipe compiler checks recipe shape, schema version, field ownership, IDs, and references.
Operation schemas validate each step’s local parameters, including nested objects and arrays.
The planner validates operation availability, required inputs, artifact kinds, research metadata, and declared execution-profile conformance.
Recipe lint adds cross-step research and communication invariants and can return a complete issue report without bypassing the planner used for execution.
Benchmark validation checks comparison-level dataset, task, metric, and override consistency.
Source-Of-Truth Locations#
Contract |
Source of truth |
Reflected in docs |
|---|---|---|
Recipe parsing and compilation |
|
This page and Python API reference |
Recipe-template discovery and instantiation |
|
This page, |
Recipe matrices, concrete identities, and legacy sweep reads |
|
This page, |
Task/dataset/metric identities |
|
Architecture and research CLI |
Execution profiles |
|
Execution-profile architecture page |
Operation inputs, outputs, params, and defaults |
operation |
Generated operation reference |
Benchmark packs |
|
Benchmark docs and validation commands |
Run/result verification |
|
Verification docs and API reference |
Runtime scheduling, cancellation, and plan caching |
|
Execution-runtime architecture page |
External adapters |
|
External adapter SDK |
Capture bundles |
|
Capture docs and API reference |
If a field is part of a public recipe, operation, adapter, benchmark, capture, run, result, or submission contract, document it in the closest implementation source first. Public documentation should then generate it or link to the generated reference.