# Blueprint Standard (/docs/blueprint-standard)



# Blueprint Standard [#blueprint-standard]

This document defines the shared contract every MirrorNeuron and OtterDesk blueprint should follow. It is intended to make blueprints interchangeable across product cataloging, local execution, UI launch, observability, and future deployment targets.

The current standard version is `1.0`.

## Architecture Model [#architecture-model]

Agents are the working units of a MirrorNeuron workflow. A blueprint should describe how agents work together: what starts the graph, which messages move between agents, what each agent produces, and which runtime boundaries apply. Shared `mn-agents` entries are generic agent templates. A blueprint actualizes those templates into concrete workflow agents with `uses`, `with`, and `config`, then assembles them like reusable blocks.

Actualized agents may be deterministic workers, routers, reducers, stream processors, services, output adapters, or LLM-backed decision makers. Control templates coordinate workflow behavior such as lifecycle, retry, joins, filters, checkpoints, approval, and fanout. Data templates are the workhorse units that blueprints customize for Python execution, native modules, LLM decisions/tools, observation, sandboxed code work, edge model inference, and data services.

MirrorNeuron is the runtime system that executes the workflow in an orchestrated way. It owns scheduling, routing, run state, event capture, artifact capture, resource limits, retries, and isolation. Blueprints own the workflow shape and domain intent. This split should make workflows reliable, inspectable, and efficient across local, cloud, and edge deployments.

Not every agent should call an LLM. When an agent does call an LLM, it must reference named LLM config. Agents that generate, review, browse, shell into, or execute code should declare a sandbox boundary, because model output and untrusted inputs must not share the same trust level as ordinary deterministic workers.

## Normative Language [#normative-language]

This standard uses:

* `MUST` for requirements that validators may enforce for every applicable blueprint.
* `SHOULD` for recommended behavior that improves interoperability but may have justified exceptions.
* `MAY` for optional behavior.

Validator-enforced universal requirements appear in the Required For All Blueprints checklist. Conditional requirements apply only when the blueprint uses the related feature, such as LLMs, live streams, output skills, TCP outputs, OpenShell custom images, or multi-agent handoffs.

## Goals [#goals]

Every blueprint should be:

* Discoverable from the root catalog files.
* Configurable through the same config shape.
* Runnable in mock mode without external services.
* Runnable with real inputs through declared adapters.
* Observable through the same run store artifacts and event format.
* Explainable to a product user through consistent metadata.
* Safe to customize without editing runtime code.
* Clear about which agents communicate, which agents call LLMs, and which agents require sandboxing or external capabilities.
* Efficient enough to run in constrained edge environments when the blueprint is marked or adapted for edge use.

## Required Files [#required-files]

Each blueprint directory must contain:

* `manifest.json`: graph, metadata, node, adapter, and product contract.
* `README.md`: user-facing summary and quick-start instructions.
* `SPEC.md`: implementation and behavior specification.
* `LICENSE.md`: license terms for the blueprint code, docs, configuration, scripts, and payloads.
* `TERM.md`: user-facing terms of use, responsibility, warranty disclaimer, third-party service notice, and liability limitation.
* `config/default.json`: default configuration following this standard.
* `payloads/`: executable code, scripts, workers, support modules, sample data, or policies.

Blueprints may also contain:

* `scenario.json`: canonical scenario input for simulation or demos.
* `config/overwrite.json`: local or user-specific override values. This file should not be required for correctness.
* `knowledge/`: optional LLM-agent knowledge content, such as RAG material, prompt context, domain references, embeddings metadata, or other agent knowledge sources.
* `payloads/.../samples`: bundled demo data.
* `payloads/.../policies`: runtime or sandbox policy files.

The root `index.json` must include a catalog row for each blueprint. The root `category.json` should include category grouping for browsing and filtering.

## Identity [#identity]

Every blueprint must declare stable identity in both `manifest.json` and `config/default.json`.

Required identity fields:

* `blueprint_id`: snake\_case directory-aligned id.
* `name`: human-readable display name.
* `graph_id`: versioned workflow id, usually `<blueprint_id>_v1`.
* `job_name`: kebab-case job name.
* `manifest_version`: manifest schema version.
* `standard_version`: blueprint standard version, currently `1.0`.

Required manifest legal reference fields:

* `license`: relative path to the blueprint license file, usually `LICENSE.md`.
* `term`: relative path to the blueprint terms file, usually `TERM.md`.

At runtime, the system must also assign:

* `run_id`: unique run id, either supplied by config/env or generated by the run store.

## Metadata [#metadata]

Each blueprint must include product metadata under `manifest.json.metadata`.

Required metadata:

* `blueprint_id`
* `name`
* `category`
* `description`
* `problem_solved`
* `target_user`
* `customizable_for`
* `simulation_type`
* `runtime_features`
* `output`
* `output_contract`
* `quick_test`
* `standard`
* `interfaces`

Conditional metadata:

* `llm_agent_role` is required when the blueprint uses an LLM agent.

The root `index.json` should mirror the product-facing subset:

* `id`
* `name`
* `path`
* `category`
* `description`
* `graph_id`
* `job_name`
* `product.problem`
* `product.input`
* `product.output`
* `product.how_it_works`
* `product.benefit`
* `product.target_users`
* `product.runtime_features`

## Config Contract [#config-contract]

The canonical config file is `config/default.json`.

Required top-level config sections:

* `standard_version`
* `identity`
* `mode`
* `metadata`
* `inputs`
* `simulation`
* `llm`
* `outputs`
* `logging`
* `resources`
* `human_control`
* `real_adapters`
* `interfaces`
* `execution_model`

The `llm` section remains a top-level config section for compatibility. Model-free blueprints should declare `llm.enabled: false`.

Blueprint-specific sections are allowed when they describe real runtime concepts. Examples:

* `streams`
* `memory`
* `benchmark`
* `optimization`
* `error_handling`
* `state`
* `capabilities`
* `privacy`
* `triggers`
* `backpressure`
* `schemas`
* `budgets`
* `agent_handoffs`
* `web_ui`

Blueprint-specific sections should be referenced from `interfaces.config` in `manifest.json.metadata` and from `interfaces.config_sections` in `config/default.json`.

Config resolution order should be:

1. Shared default config generated for the blueprint id.
2. Blueprint `config/default.json`.
3. Optional config file from `MN_BLUEPRINT_CONFIG_PATH`.
4. Optional inline JSON from `MN_BLUEPRINT_CONFIG_JSON`.
5. Direct runtime overrides, including CLI flags and UI fields.
6. Environment values such as `MN_RUN_ID`, `MN_RUNS_ROOT`, and `MN_BLUEPRINT_REVISION`.

Later layers override earlier layers by deep merge.

## Input Contract [#input-contract]

Every blueprint must support these input adapters:

* `mock`: bundled synthetic or demo inputs; required for demos and tests.
* `json`: inline JSON object supplied in config.
* `file`: JSON object loaded from `inputs.path`.
* `env_json`: JSON object loaded from an environment variable, defaulting to `MN_BLUEPRINT_INPUT_JSON`.

Resolved inputs must be a JSON object. Arrays, strings, and scalar values are not valid top-level input payloads.

The resolved input source should include:

* `adapter`
* `path`, when applicable
* `description`, when available
* `real_ready`, where `false` means mock inputs and `true` means user or real-world supplied inputs

Input fields should be domain concepts, not internal implementation toggles. Examples:

* Facility safety: monitored stream, cooldown policy, alert destination.
* Portfolio stress: holdings, cash constraints, hedge constraints, shock assumptions.
* Property alpha: target ZIP, price ceiling, history months, broker notes, financing constraints.
* Drug discovery: disease or target profile, screening criteria, candidate seeds.

### Product Input Contract [#product-input-contract]

Each blueprint should declare `manifest.json.metadata.input_contract` so launchers and users can understand what the blueprint actually needs before a run starts. This product-facing contract complements, but does not replace, the executable `inputs` config.

Recommended shape:

```json
{
  "input_contract": {
    "schema_version": "mn.blueprint.input_contract.v1",
    "required_inputs": [
      {
        "name": "portfolio",
        "type": "object",
        "description": "Holdings, cash constraints, and exposure assumptions.",
        "example": {}
      }
    ],
    "optional_inputs": [
      {
        "name": "seed",
        "type": "integer",
        "description": "Deterministic replay seed.",
        "example": 42
      }
    ],
    "supported_adapters": ["mock", "json", "file", "env_json"],
    "profiles": {
      "mock": {"adapter": "mock", "description": "Bundled synthetic inputs."},
      "sample_file": {"adapter": "file", "path": "inputs/sample.json"},
      "live_stream": {"adapter": "mock", "streams": ["primary_stream"]},
      "connector": {"adapter": "mock", "input_skills": ["source_folder"]}
    },
    "privacy_classification": "internal",
    "validation_rules": [],
    "resolved_artifact": "inputs.json"
  }
}
```

Launchers should use this contract and `metadata.init_config_review.fields` to ask only about meaningful runtime values such as data source, stream endpoint, model endpoint, output destination, or human-control mode.

### Stream Inputs [#stream-inputs]

Blueprints that consume live or replayed streams should declare those inputs under `streams` or `inputs.streams`.

Supported stream kinds:

* `audio`
* `video`
* `data`
* `multimodal`

Supported stream transports:

* `file`
* `http`
* `https`
* `rtsp`
* `rtmp`
* `webrtc`
* `websocket`
* `socketio`
* `tcp`
* `udp`
* `sse`
* `kafka`
* `mqtt`
* `custom`

Recommended stream shape:

```json
{
  "streams": {
    "primary_video": {
      "kind": "video",
      "transport": "rtsp",
      "uri": "rtsp://127.0.0.1:8554/local-camera",
      "codec": "h264",
      "sample_interval_seconds": 5,
      "enabled": true
    },
    "agent_audio": {
      "kind": "audio",
      "transport": "websocket",
      "url": "wss://example.test/audio",
      "codec": "pcm16",
      "sample_rate_hz": 16000,
      "enabled": true
    },
    "events": {
      "kind": "data",
      "transport": "socketio",
      "url": "https://example.test/events",
      "namespace": "/blueprint",
      "event": "observation",
      "enabled": true
    }
  }
}
```

Each stream entry should include:

* `kind`
* `transport`
* `uri` or `url`
* `enabled`
* media details when applicable, such as `codec`, `sample_rate_hz`, `frame_rate`, or `resolution`
* protocol details when applicable, such as `namespace`, `event`, `topic`, `headers_env`, or `auth_env`

Stream credentials and headers should be referenced by environment variable names, not embedded as literal secrets.

### Input Skill Definitions [#input-skill-definitions]

Blueprint inputs may also be declared as skill-backed sources. Use an input skill when the blueprint needs a reusable integration capability rather than a one-time JSON payload or raw stream.

Input skills are useful for sources such as:

* Google Drive folders
* Slack channels
* email inboxes
* calendars
* issue trackers
* databases
* object storage buckets
* webhook endpoints

Input skills should be declared under `input_skills` or `inputs.skills`.

Recommended input skill shape:

```json
{
  "input_skills": {
    "deal_room": {
      "skill": "google_drive.folder",
      "connector": "google_drive",
      "folder_id": "drive-folder-id",
      "live": true,
      "events": {
        "on_change": "folder_content_changed"
      },
      "sync": {
        "mode": "incremental",
        "include_mime_types": [
          "application/pdf",
          "application/vnd.google-apps.document",
          "text/csv"
        ]
      }
    },
    "ops_channel": {
      "skill": "slack.channel",
      "connector": "slack",
      "channel_id": "slack-channel-id",
      "live": true,
      "events": {
        "on_message": "slack_message_received",
        "on_file": "slack_file_shared"
      }
    }
  }
}
```

Each input skill should include:

* `skill`: stable skill type, such as `google_drive.folder` or `slack.channel`.
* `connector`: connector or integration family.
* source identity fields, such as `folder_id`, `channel_id`, `database_id`, `bucket`, or `path`.
* `live`: whether the source should emit runtime events when content changes.
* `events`: blueprint event types emitted by live updates.
* `sync`: optional backfill, polling, filtering, or incremental sync settings.

When `live` is `false`, the input skill is read once during `load_inputs` and the resolved content is recorded in `inputs.json` or referenced from the run artifact.

When `live` is `true`, the blueprint should:

* record the initial source state during `load_inputs`
* subscribe, poll, or receive webhooks through the connector
* emit typed events when source content changes
* include enough source metadata in event payloads to correlate updates without storing secrets

Live input skill events must follow the normal event contract in `events.jsonl`. Example event types:

* `folder_content_changed`
* `drive_file_added`
* `drive_file_updated`
* `slack_message_received`
* `slack_file_shared`

Input skill credentials must be managed by the connector or referenced by environment variable names. Blueprint config must not contain literal OAuth tokens, bot tokens, refresh tokens, cookies, or private keys.

## Knowledge Contract [#knowledge-contract]

Blueprints may include a `knowledge/` directory beside `config/` and `payloads/` for LLM-agent knowledge content such as RAG material, prompt context, domain references, embeddings metadata, or other agent knowledge sources.

The `knowledge/` directory is optional. If present, it must contain exactly these standard subdirectories:

* `init/`: bundled or base knowledge shipped with the blueprint.
* `custom/`: user- or customer-provided knowledge.
* `learned/`: runtime-, feedback-, or experience-derived knowledge.

The standard does not prescribe file formats, indexing behavior, retrieval precedence, embedding strategy, or how agents use these folders. Blueprints and runtime integrations may decide those details.

## Output Contract [#output-contract]

Every blueprint must always write local logs, events, and run artifacts through the `local_run_store` output adapter. This local observability output is mandatory even when the blueprint also writes to external destinations.

Default run root:

```text
~/.mn/runs/<run_id>/
```

Required run artifacts:

* `run.json`: run id, blueprint id, status, timestamps, paths, and failure details when relevant.
* `config.json`: resolved runtime config.
* `inputs.json`: resolved input payload.
* `events.jsonl`: append-only typed runtime events.
* `errors.jsonl`: error-only stream containing `mn.error.v1` envelopes plus run context.
* `timeline.jsonl`: append-only normalized execution timeline using `mn.timeline.v1`.
* `observability_summary.json`: compact closeout summary for trace, duration, counts, retries, resources, and links.
* `result.json`: complete machine-readable result.
* `final_artifact.json`: user-facing final result or compact artifact.

Optional run artifacts:

* `job.json`: scheduler, host, or orchestration metadata.
* `web_ui.json`: UI launch metadata.
* `web/index.html`: static report or output page.
* `ui.json`: UI state or richer dashboard metadata.
* `logs.jsonl`: structured runtime logs when logs are persisted separately from `events.jsonl`.
* `events.log`: optional human-readable lifecycle event mirror.
* `errors.log`: optional human-readable error mirror.
* `events.index.json`: index metadata for rotated lifecycle events.
* `logs.index.json`: index metadata for rotated or segmented structured logs.
* `errors.index.json`: index metadata for rotated error records.
* `timeline.json`: compact ordered mirror regenerated when the run closes.
* `human.jsonl`: sparse human collaboration notices, input requests, and responses, mirrored to `events.jsonl`.
* `resources.jsonl`: CPU, GPU, memory, and LLM token usage samples captured for the run.

`result.json` should contain enough context to audit the run without reading stdout. `final_artifact.json` should contain the durable product answer, not internal logs.

### Shared Failure Contract [#shared-failure-contract]

Runtime, SDK/API, and UI must normalize failures into the shared `mn.error.v1` envelope. Blueprints should emit ordinary failure events through the shared run store and workflow helpers; they should not invent blueprint-specific error schemas.

```json
{
  "schema_version": "mn.error.v1",
  "code": "workflow.step.timeout",
  "desc": "Workflow step timed out",
  "details": {
    "message": "Step missed its heartbeat deadline.",
    "category": "timeout",
    "retryable": false,
    "step_id": "prepare_income_workpapers",
    "agent_id": "income_preparer",
    "attempt": 2,
    "max_attempts": 2
  },
  "severity": "ERROR",
  "occurred_at": "2026-06-04T12:34:56.000Z",
  "event_id": "evt_...",
  "trace_id": "trc_...",
  "span_id": "spn_...",
  "remediation": "Check agent heartbeat, runtime node health, and step timeout settings.",
  "links": [
    {"rel": "errors", "artifact_id": "errors_jsonl"},
    {"rel": "events", "artifact_id": "events_jsonl"},
    {"rel": "logs", "artifact_id": "logs_jsonl"}
  ]
}
```

Limits are platform-level and apply after redaction:

* `code`: 128 chars.
* `desc`: 160 chars.
* `details.message`: 2 KiB.
* `remediation`: 1 KiB.
* Full event/API `error` envelope: 16 KiB.
* Single JSONL event, log, or error record: 64 KiB.

Oversized values are replaced with a bounded object such as `{"truncated": true, "chars": 12000, "preview": "..."}` and should link to the relevant artifacts. `job_failed`, `workflow_step_failed`, `sandbox_job_failed`, retry exhaustion, scheduler failures, and recovery failures must include `error: mn.error.v1`. Existing `reason` and `status_reason` fields remain compatibility fields derived from `error.desc` when available.

`events.jsonl`, `logs.jsonl`, and `errors.jsonl` rotate at 10 MiB by default and keep five rotated segments per run. Current files keep their existing names; rotated files use numbered suffixes such as `events.001.jsonl`, `logs.001.jsonl`, and `errors.001.jsonl`. Artifact indexes and API responses must expose stable artifact IDs such as `events_jsonl`, `events_jsonl_001`, `logs_jsonl_001`, and `errors_jsonl_001` with size, hash, content type, and download URL.

### Trace, Timeline, And Summary Contract [#trace-timeline-and-summary-contract]

Every run must have one stable run-level `trace_id` in `run.json`. Records written through shared observability helpers must carry `trace_id` and a per-record `span_id`; callers may provide `trace_id`, `span_id`, and `parent_span_id`, and the runtime must preserve those values. Generated ids use `trc_<urlsafe-random>` and `spn_<urlsafe-random>`.

`timeline.jsonl` contains normalized execution records using `mn.timeline.v1`:

```json
{
  "schema_version": "mn.timeline.v1",
  "ts": "2026-06-04T12:34:56.000Z",
  "run_id": "run_...",
  "blueprint_id": "finance_example",
  "trace_id": "trc_...",
  "span_id": "spn_...",
  "parent_span_id": "spn_...",
  "type": "workflow_step_failed",
  "phase": "running_worker",
  "step_id": "prepare_income_workpapers",
  "agent_id": "income_preparer",
  "status": "failed",
  "duration_ms": 120000,
  "summary": "Workflow step timed out",
  "links": [{"rel": "errors", "artifact_id": "errors_jsonl"}],
  "details": {}
}
```

`observability_summary.json` is written before observability closes on success and failure. It includes status, duration, trace id, event/log/error/warning/timeline/artifact counts, retry count, failed step or agent when known, slowest phases or steps when durations are available, resource peaks, token totals, and artifact links for `events_jsonl`, `logs_jsonl`, `errors_jsonl`, `timeline_jsonl`, and `timeline_json`.

The same redaction and truncation rules used for `mn.error.v1` apply to timeline details and summary fields. `timeline.jsonl` is append-only; `timeline.json` is a compact ordered mirror and may be truncated for very large runs while retaining the full JSONL stream.

### Product Output Contract [#product-output-contract]

Every blueprint should declare `metadata.output_contract.final_artifact` and `metadata.output_contract.artifacts`.

The final artifact should include these user-facing fields when the blueprint can produce them:

* `type`
* `executive_summary`
* `recommended_action`
* `confidence`
* `evidence`
* `next_steps`
* `source_refs`

The artifact list should include durable records for `run.json`, `config.json`, `inputs.json`, `events.jsonl`, `result.json`, `final_artifact.json`, logs, resources, human events when enabled, web UI metadata when enabled, and output-skill delivery attempts when configured. Each record should include `artifact_id`, `type`, `schema_version`, `path`, `mime_type`, and `producer`.

Blueprints may also declare skill-backed output destinations. Output skills are optional fan-out destinations, not replacements for local logs and events.

Output skills are useful for destinations such as:

* Google Drive files or folders
* Slack channels or direct messages
* email messages
* issue tracker comments
* databases
* object storage buckets
* webhook endpoints

Output skills should be declared under `output_skills` or `outputs.skills`.

Recommended output skill shape:

```json
{
  "output_skills": {
    "archive_report": {
      "skill": "google_drive.write_file",
      "connector": "google_drive",
      "folder_id": "drive-folder-id",
      "filename_template": "{blueprint_id}-{run_id}-report.json",
      "content": "final_artifact",
      "enabled": true
    },
    "notify_ops": {
      "skill": "slack.send_message",
      "connector": "slack",
      "channel_id": "slack-channel-id",
      "content": "summary",
      "include_run_link": true,
      "enabled": true
    }
  }
}
```

Each output skill should include:

* `skill`: stable skill type, such as `google_drive.write_file` or `slack.send_message`.
* `connector`: connector or integration family.
* destination identity fields, such as `folder_id`, `channel_id`, `database_id`, `bucket`, `path`, or `webhook_url_env`.
* `content`: what to send, such as `final_artifact`, `result`, `summary`, `events`, `logs`, or a named artifact.
* `enabled`
* optional formatting fields, such as `filename_template`, `message_template`, `mime_type`, or `include_run_link`

Multiple output skills may be enabled at the same time. The blueprint should treat them as a fan-out list: write the local run store first, then attempt each enabled output skill.

Each output skill attempt should emit an event, for example:

* `output_skill_started`
* `output_skill_completed`
* `output_skill_failed`
* `drive_file_written`
* `slack_message_sent`

Failures in optional output skills should be recorded in `events.jsonl` and `result.json`. They should fail the whole run only when the output skill is marked as required.

Output skill credentials must be managed by the connector or referenced by environment variable names. Blueprint config must not contain literal OAuth tokens, bot tokens, refresh tokens, cookies, or private keys.

### TCP Output Port Convention [#tcp-output-port-convention]

Some outputs expose a TCP service instead of only writing files or connector messages. Examples include web UIs, report preview servers, callback receivers, local dashboards, stream preview pages, and connector bridge endpoints.

TCP output services should use fixed externally reachable ports so users, launchers, tunnels, and downstream tools know where to connect. These are external, host, or tunnel ports, not necessarily the internal container or process bind ports.

Port assignment rules:

* Use `8080` for the first or primary TCP output.
* If `8080` is already taken, use `8081` as the fallback.
* If the blueprint needs two TCP output ports, use `8080` and `8081` in that order.
* If both `8080` and `8081` are unavailable, or more than two TCP output ports are required, the blueprint should require an explicit config override instead of choosing a random port.

Recommended TCP output config shape:

```json
{
  "outputs": {
    "tcp": {
      "enabled": true,
      "ports": [
        {
          "name": "web_ui",
          "external_port": 8080,
          "protocol": "http",
          "url_path": "/",
          "required": true
        },
        {
          "name": "secondary_output",
          "external_port": 8081,
          "protocol": "http",
          "url_path": "/",
          "required": false
        }
      ]
    }
  }
}
```

When a TCP output is launched, the blueprint should write the resolved external port and external URL to the relevant artifact, usually `web_ui.json`, `ui.json`, or `result.json`. It should also emit events such as `tcp_output_started`, `tcp_output_available`, and `tcp_output_failed`.

TCP output port failures should follow `error_handling`: use `retry` for temporary bind failures, use `skip` only for optional secondary outputs, and use `stop` when a required TCP output such as a primary web UI cannot bind to `8080` or the declared fallback.

## Artifact Contract [#artifact-contract]

Artifacts are durable files or objects produced by a blueprint. Every user-facing report, extracted file, model-generated result, static page, image, table, or structured summary should be represented as a named artifact when it may be consumed by users, output skills, replay, tests, or later blueprint steps.

Recommended artifact record shape:

```json
{
  "artifact_id": "final_report",
  "type": "report",
  "schema_version": "mn.artifact.report.v1",
  "path": "final_artifact.json",
  "mime_type": "application/json",
  "created_at": "2026-05-13T12:00:00Z",
  "producer": "ranking_reporting",
  "source_refs": [
    "inputs:portfolio",
    "event:llm_decision:3"
  ]
}
```

Each artifact record should include:

* `artifact_id`: stable name within the run.
* `type`: domain-readable type, such as `report`, `summary`, `dataset`, `image`, `video_clip`, `html`, `model_output`, or `debug_bundle`.
* `schema_version`: schema id for structured artifacts.
* `path`: run-store relative path or external destination reference.
* `mime_type`
* `created_at`: UTC ISO timestamp.
* `producer`: worker, stage, agent, or output skill that produced it.
* `source_refs`: optional references to input records, events, files, messages, streams, or prior artifacts.

`final_artifact.json` should identify its schema or schema version when possible. If it wraps multiple artifacts, it should include an `artifacts` list with artifact records.

Named artifacts may be routed through output skills by setting `content` to the artifact id. Output skills should record the artifact id and destination reference in their completion event payload.

## Event And Observability Contract [#event-and-observability-contract]

Every event in `events.jsonl` must be one JSON object per line with:

* `ts`: UTC ISO timestamp.
* `run_id`
* `blueprint_id`
* `type`: stable snake\_case event type.
* `payload`: JSON object.

Required lifecycle events:

* `run_started`
* `inputs_loaded`
* `run_completed` or `run_failed`

Recommended lifecycle events:

* `simulation_step_started`
* `simulation_state_observed`
* `llm_decision`
* `simulation_state_updated`
* `artifact_written`
* `web_ui_available`

Blueprint-specific events are encouraged when they expose useful product behavior. Event names should be stable and domain-readable, for example:

* `door_camera_frame_analyzed`
* `door_camera_face_detected`
* `benchmark_step_scored`
* `targets_ready`
* `pipeline_complete`

Status logging may also write JSONL to stderr, but stderr is not the durable observability surface. The run store is the system of record.

Secrets and sensitive environment values must be redacted from config summaries, logs, and events.

## Logging Contract [#logging-contract]

Logs are diagnostic narrative. Events are durable state, product, and lifecycle facts. Errors are always recorded as events and may also be written to logs.

Canonical log levels:

* `TRACE`: very detailed execution flow, usually disabled by default.
* `DEBUG`: developer-oriented diagnostic details.
* `INFO`: normal progress and high-level runtime milestones.
* `WARN`: unexpected but recoverable conditions.
* `ERROR`: operation failed, but the process may continue depending on `error_handling`.
* `CRITICAL`: execution cannot continue safely.

The default log level is `INFO`. `WARN` is canonical. `WARNING` may be accepted as a compatibility alias, but persisted logs should normalize it to `WARN`.

When logs are persisted to `logs.jsonl` or stderr JSONL, each log line should include:

* `ts`: UTC ISO timestamp.
* `run_id`
* `blueprint_id`
* `level`
* `component`: worker, stage, adapter, connector, or module name.
* `message`: human-readable diagnostic text.
* `event_id`, when the log explains a durable event.
* `trace_id`, when correlating work across stages.
* `span_id`, when correlating a nested operation.
* `source_ref`, when the log relates to a stream item, input file, connector record, output skill, or artifact.
* `error`, when applicable, with `type`, `message`, and optionally a redacted stack or code.

Recommended logging config shape:

```json
{
  "logging": {
    "level": "INFO",
    "events_jsonl": true,
    "logs_jsonl": true,
    "stderr_jsonl": true,
    "redact_env_secrets": true,
    "redact_fields": [
      "api_key",
      "token",
      "authorization",
      "cookie",
      "password",
      "private_key"
    ]
  }
}
```

Blueprints should not rely on logs for product state. If a fact is needed for audit, UI, replay, downstream skills, or final artifacts, it should be emitted as an event or artifact record.

Secret redaction must happen before a log line is written. Raw prompts, connector payloads, headers, OAuth tokens, cookies, private keys, and full environment dumps must not be logged unless explicitly redacted.

## Resource Observability Contract [#resource-observability-contract]

Every blueprint should declare `resources` even if resource sampling is only best-effort in the local runner. The resource channel records operational signals that help compare runs, debug regressions, and decide whether a blueprint is ready for hosted or edge execution.

Recommended resource config shape:

```json
{
  "resources": {
    "enabled": true,
    "sample_interval_seconds": 10,
    "gpu_enabled": "auto",
    "gpu_sample_interval_seconds": 60,
    "history_window_hours": 24,
    "raw_retention_hours": 48,
    "rollup_bucket_seconds": 3600
  }
}
```

When enabled, resource samples should be written to `resources.jsonl`. Samples may include CPU, memory, disk, GPU, queue depth, and LLM token usage. Resource sampling failures should be recorded as events or logs, but they should not fail the blueprint unless the blueprint explicitly marks resource enforcement as required.

## Human-Control Contract [#human-control-contract]

Every blueprint must declare `human_control` in config, even when no human approval is needed.

Supported modes:

* `disabled`: the blueprint only writes local decision-support artifacts and has no high-impact action to approve. It must include `reason`.
* `notice_only`: the blueprint may emit `human_notice` events for review, but it does not block artifact writing on approval.
* `approval_required`: the blueprint must request approval before applying or recommending high-impact actions. It must declare `allowed_decisions`, `timeout_seconds`, `default_action`, and `blocked_actions`.

Human-control events use the existing human channel and are mirrored to `events.jsonl`:

* `human_notice`
* `human_input_requested`
* `human_input_received`
* `human_input_timeout`
* `human_decision_applied`

The manifest should mirror the policy under `metadata.human_control` so catalog and launch UI code can explain the review behavior before a run starts.

## Status Transparency Contract [#status-transparency-contract]

Every blueprint should declare `metadata.status_contract` and emit status events from the run store. Standard phases are:

* `loading_inputs`
* `running_worker`
* `waiting_for_human`
* `writing_artifacts`
* `completed`

Each phase should define `start_event`, `progress_event`, `completion_event`, and `failure_event`. The shared events are `blueprint_phase_started`, `blueprint_status`, `blueprint_phase_completed`, and `blueprint_phase_failed`.

Long-running, stream, service, or multi-stage blueprints should emit progress or heartbeat `blueprint_status` events so users can tell whether work is still active. Web UI surfaces must read status from run-store events rather than private worker state.

## Runtime Workflow Control Contract [#runtime-workflow-control-contract]

Blueprints that use `flow.steps` for multi-step execution should declare runtime workflow control so MirrorNeuron can keep progress durable, bounded, and recoverable. The source of truth is the step ledger stored on the job as `workflow_state`; nodes and agents are workers, not the durable progress authority.

Required runtime shape:

```json
{
  "runtime": {
    "workflow_control": {
      "schema_version": "mn.workflow.runtime_control.v1",
      "enabled": true,
      "source_of_truth": "flow.steps",
      "state_ledger": {
        "enabled": true,
        "persisted_field": "workflow_state",
        "step_statuses": [
          "pending",
          "ready",
          "queued",
          "running",
          "retry_wait",
          "blocked",
          "completed",
          "partial",
          "skipped",
          "failed"
        ],
        "message_ledger": true,
        "delivery_semantics": "at_least_once_with_idempotency"
      },
      "attempts": {
        "dispatch_metadata": [
          "workflow_run_id",
          "step_id",
          "attempt_id",
          "attempt",
          "deadline_at",
          "heartbeat_deadline_at",
          "idempotency_key"
        ],
        "stale_attempt_outputs": "ignore",
        "retry_policy_source": "flow.steps[].control.retry",
        "timeout_source": "flow.steps[].control.timeout_seconds"
      },
      "liveness": {
        "event": "agent_beacon",
        "interval_ms": 15000,
        "timeout_ms": 45000,
        "required": true,
        "missed_action": "fail_attempt"
      },
      "reconciliation": {
        "interval_ms": 2000,
        "on_timeout": "fail_attempt_then_retry",
        "on_missed_beacon": "fail_attempt_then_retry",
        "on_retry_exhausted": "apply_step_failure_policy"
      },
      "pause_cancel": {
        "pause_mode": "stop_active_attempts",
        "resume_mode": "reconcile_from_workflow_state",
        "cancel_mode": "terminate_active_attempts"
      },
      "events": [
        "workflow_step_attempt_started",
        "workflow_step_beacon",
        "workflow_step_attempt_completed",
        "workflow_step_attempt_timed_out",
        "workflow_step_attempt_retry_scheduled",
        "workflow_step_blocked",
        "workflow_step_completed",
        "workflow_step_failed",
        "workflow_message_dead_lettered"
      ]
    }
  }
}
```

Every `flow.steps[]` entry should declare bounded control policy:

* `control.timeout_seconds`: positive integer for the current attempt deadline
* `control.retry.max_attempts`: positive integer
* `control.retry.backoff_seconds`: non-negative number
* `control.failure_policy`: the result after retry exhaustion, such as fail, partial, skip, or fail-closed behavior

Executor node rendering should project the same step policy into the runtime node config:

* `timeout_seconds`
* `max_attempts`
* `retry_backoff_ms`
* `beacon_enabled: true`
* `beacon_interval_ms: 15000`
* `beacon_timeout_ms: 45000`
* `beacon_missed_action: "fail_attempt"`
* `agent_beacon_required: true` for Python executor steps

Plain-code stages must still use an executor agent. For Python scripts, prefer
the shared `mn_blueprint_support.python_executor_template_node(...)` or
`python_executor_runtime_binding(...)` helpers, which declare the stage through
`mn-agents.data_python_executor@1.0.0`. Do not launch stage code through an
untracked helper process or a blueprint-specific wrapper just to run ordinary
Python.

The status contract should connect UI surfaces to the workflow ledger:

```json
{
  "metadata": {
    "status_contract": {
      "heartbeat_required": true,
      "heartbeat_event": "agent_beacon",
      "beacon_event": "agent_beacon",
      "beacon_interval": "15s",
      "beacon_timeout": "45s",
      "beacon_missed_action": "fail_attempt",
      "runtime_state_source": "workflow_state",
      "attempt_event": "workflow_step_attempt_started",
      "retry_event": "workflow_step_attempt_retry_scheduled",
      "blocked_event": "workflow_step_blocked",
      "terminal_step_events": [
        "workflow_step_completed",
        "workflow_step_partial",
        "workflow_step_skipped",
        "workflow_step_failed"
      ]
    }
  }
}
```

The UI should prefer `workflow_state` for job details. A step that is alive should show recent beacon timing, a step in backoff should show retry timing, and a dependency problem should show blocked reason rather than an indefinite running state.

## Observability Dashboard Contract [#observability-dashboard-contract]

Blueprint dashboards should be declared in metadata and config, then rendered by the shared web UI from run-store files.

Standard panels:

* `current_status`
* `recent_events`
* `pending_human_requests`
* `output_artifacts`
* `resource_usage`
* `errors`

Conditional panels:

* Stream blueprints: `input_lag`, `backpressure`
* LLM blueprints: `llm_calls`, `token_budget`, `llm_retries`
* Output-skill blueprints: `output_skill_attempts`, `output_skill_failures`

## Error Handling Contract [#error-handling-contract]

Every blueprint must record errors, even when the runtime chooses to continue.

Supported error handling modes:

* `retry`: attempt the operation again according to a bounded retry policy.
* `skip`: record the error and continue with the next item, event, stream frame, message, file, or optional output.
* `stop`: record the error, mark the run or worker as failed, and stop the current execution path.

Blueprints may configure error handling globally and override it per stage, stream, input skill, output skill, or worker.

Recommended error policy shape:

```json
{
  "error_handling": {
    "default_mode": "stop",
    "policies": {
      "stream_frame": {
        "mode": "skip",
        "max_consecutive_errors": 10
      },
      "llm_call": {
        "mode": "retry",
        "max_attempts": 3,
        "backoff_seconds": 2
      },
      "required_output": {
        "mode": "stop"
      }
    }
  }
}
```

Each recorded error event should include:

* `error_type`
* `message`
* `mode`
* `stage` or `component`
* `attempt`, when retrying
* `source_ref`, when the error relates to a stream item, file, message, input skill, or output skill
* `recoverable`: boolean

Recommended error event types:

* `error_recorded`
* `retry_scheduled`
* `item_skipped`
* `run_failed`

`retry` should always be bounded by max attempts, elapsed time, or another explicit limit.

`skip` is appropriate for stream processing, batch item processing, optional connector reads, and optional output fan-out where one bad item should not invalidate the whole run.

`stop` is appropriate when required inputs cannot load, config is invalid, required output delivery fails, or the blueprint can no longer produce a trustworthy final artifact.

The selected error mode changes control flow only. It must not suppress logs, events, or final error summaries.

## State And Checkpoint Contract [#state-and-checkpoint-contract]

Long-running service, live-input, stream, or multi-stage blueprints should declare how runtime state is stored and resumed.

Recommended state config shape:

```json
{
  "state": {
    "enabled": true,
    "checkpoint_interval": {
      "events": 100,
      "seconds": 60
    },
    "resume_mode": "latest_checkpoint",
    "idempotency_key_fields": [
      "source_ref",
      "event_id"
    ]
  }
}
```

Supported `resume_mode` values:

* `none`: do not resume; each launch starts fresh.
* `latest_checkpoint`: resume from the newest checkpoint.
* `replay_events`: rebuild state by replaying `events.jsonl`.
* `manual`: require the user or orchestration layer to choose a checkpoint.

Checkpoints should be written under the run store or a declared state path. They should include the checkpoint timestamp, producer component, source position, and any idempotency keys needed to avoid duplicate processing.

Live input events, stream frames, connector records, and external messages should have stable `source_ref` values. After restart, the blueprint should use those references to skip already processed items or replay them deterministically.

## Capability And Permission Contract [#capability-and-permission-contract]

Blueprints should declare external capabilities before runtime so users and launch UIs can review what the blueprint is allowed to do.

Recommended capabilities shape:

```json
{
  "capabilities": {
    "required": [
      "llm.call",
      "filesystem.write",
      "stream.subscribe"
    ],
    "optional": [
      "google_drive.read",
      "google_drive.write",
      "slack.read",
      "slack.send",
      "network.egress"
    ]
  }
}
```

Common capability names:

* `llm.call`
* `google_drive.read`
* `google_drive.write`
* `slack.read`
* `slack.send`
* `network.egress`
* `stream.subscribe`
* `filesystem.read`
* `filesystem.write`

Required external capabilities should be shown during UI or init config review before launch. Optional capabilities may be disabled by config, but if enabled they should still be visible in review.

Capability declarations are not credential storage. Credentials must be managed by connectors, environment references, or the runtime.

## Privacy And Redaction Contract [#privacy-and-redaction-contract]

Blueprints that process user, business, operational, financial, health, media, or connector data should declare data classification and handling rules.

Supported data classes:

* `public`
* `internal`
* `confidential`
* `regulated`

Recommended privacy config shape:

```json
{
  "privacy": {
    "default_classification": "internal",
    "rules": {
      "public": {
        "log": true,
        "send_to_llm": true,
        "send_to_output_skills": true
      },
      "internal": {
        "log": "metadata_only",
        "send_to_llm": true,
        "send_to_output_skills": true
      },
      "confidential": {
        "log": "redacted",
        "send_to_llm": "allowed_configs_only",
        "send_to_output_skills": "approved_destinations_only"
      },
      "regulated": {
        "log": "redacted",
        "send_to_llm": false,
        "send_to_output_skills": "approved_destinations_only"
      }
    }
  }
}
```

Privacy rules should define whether each class may be:

* logged
* included in durable events
* sent to named `LLM_CONFIG` entries
* sent through output skills
* stored in artifacts

The blueprint must redact or omit environment tokens, OAuth credentials, cookies, private keys, passwords, authorization headers, and connector secrets from logs, events, artifacts, and output skills unless the value is explicitly a safe reference such as an environment variable name.

When content is transformed for privacy, the blueprint should emit a redaction or filtering event with metadata about what class of data was changed, without recording the sensitive content itself.

## Trigger And Scheduling Contract [#trigger-and-scheduling-contract]

Blueprints should declare how runs start and what keeps them active.

Supported trigger types:

* `manual`
* `scheduled`
* `live_input`
* `webhook`
* `stream`
* `service`
* `batch`

Recommended trigger config shape:

```json
{
  "triggers": {
    "type": "service",
    "sources": [
      "input_skills.deal_room",
      "input_skills.ops_channel"
    ],
    "schedule": null
  }
}
```

If an input skill has `live: true`, the blueprint should declare a `live_input` trigger or another trigger that explains how live updates are received. Scheduled triggers should use a stable schedule representation owned by the orchestration layer rather than ad hoc worker sleep loops.

Top-level manifest `type: "service"` means the blueprint expects to remain active after initialization. Omitted top-level `type` means the blueprint defaults to a finite batch run.

## Backpressure And Rate Limit Contract [#backpressure-and-rate-limit-contract]

Blueprints that consume live inputs, streams, connector events, or high-volume batches should declare backpressure behavior and rate limits.

Recommended backpressure config shape:

```json
{
  "backpressure": {
    "max_events_per_second": 10,
    "queue_size": 1000,
    "drop_policy": "skip_with_error",
    "max_concurrency": 4,
    "connectors": {
      "google_drive": {
        "max_reads_per_minute": 60,
        "max_writes_per_minute": 10
      }
    },
    "llm": {
      "max_calls_per_minute": 30,
      "max_concurrent_calls": 2
    }
  }
}
```

Supported `drop_policy` values:

* `block`: stop accepting new work until capacity is available.
* `sample`: process a representative subset.
* `drop_oldest`: discard oldest queued work first.
* `drop_newest`: discard newest incoming work first.
* `skip_with_error`: skip the item, record an error event, and continue.

Dropped, sampled, skipped, or rate-limited items should be recorded as events. Budget or rate-limit violations should follow the configured `error_handling` mode.

## Determinism And Replay Contract [#determinism-and-replay-contract]

Blueprints should make mock, test, and replay runs reproducible when the domain allows it.

Recommended determinism config shape:

```json
{
  "determinism": {
    "enabled": true,
    "seed_field": "seed",
    "frozen_clock": null,
    "replay": {
      "from_inputs": "inputs.json",
      "from_events": "events.jsonl",
      "llm_mode": "mock"
    }
  }
}
```

Deterministic blueprints should declare:

* `seed_field`: input or config field used for deterministic randomness.
* `frozen_clock`: optional timestamp used to stabilize time-dependent output.
* replay inputs: usually `inputs.json`.
* replay events: usually `events.jsonl` for live or multi-stage runs.
* mock LLM behavior: fake, fixture, or recorded response mode.

When deterministic mode is enabled, replay runs should produce comparable final artifacts and event sequences, allowing expected differences such as timestamps, run ids, and explicitly nondeterministic external service responses.

## Schema Validation Contract [#schema-validation-contract]

Blueprints should declare schemas or schema ids for the surfaces other tools consume.

Recommended schema config shape:

```json
{
  "schemas": {
    "config": "mn.blueprint.config.v1",
    "inputs": "mn.blueprint.inputs.v1",
    "events": "mn.blueprint.events.v1",
    "final_artifact": "mn.blueprint.final_artifact.v1",
    "input_skills": "mn.blueprint.input_skills.v1",
    "output_skills": "mn.blueprint.output_skills.v1"
  }
}
```

Schemas may begin as inline ids before concrete schema files exist. When schema files are present, the schema id should resolve to a local file, package resource, or documented registry entry.

Schema validation should cover:

* config
* inputs
* events
* final artifacts
* input skills
* output skills
* agent handoff messages

Validation failures should be recorded as errors and follow `error_handling`.

## Resource Budget Contract [#resource-budget-contract]

Blueprints may declare resource budgets to keep local and hosted runs predictable.

Recommended budget config shape:

```json
{
  "budgets": {
    "max_runtime_seconds": 600,
    "max_llm_calls": 20,
    "max_llm_tokens": 20000,
    "max_connector_reads": 500,
    "max_connector_writes": 20,
    "max_disk_mb": 250,
    "max_stream_duration_seconds": 3600
  }
}
```

Budget checks may apply globally or per component. When a budget is exceeded, the blueprint should emit a budget event and then follow the configured `error_handling` mode.

Recommended budget event types:

* `budget_warning`
* `budget_exceeded`
* `rate_limited`

## Agent Handoff Contract [#agent-handoff-contract]

Multi-agent and multi-worker blueprints should declare how messages move between stages.

Recommended handoff shape:

```json
{
  "agent_handoffs": {
    "targets_ready": {
      "producer": "target_discovery",
      "consumer": "structure_generation",
      "message_type": "targets_ready",
      "payload_schema": "mn.science.targets_ready.v1",
      "error_policy": "retry",
      "artifact_owner": "structure_generation"
    }
  }
}
```

Each handoff should define:

* `message_type`
* `payload_schema`
* `producer`
* `consumer`
* `error_policy`: `retry`, `skip`, or `stop`
* `artifact_owner`: worker or stage responsible for durable artifacts derived from the message

Handoff messages should be replayable when they affect durable state or final artifacts. If a message cannot be replayed, the blueprint should state why in the handoff definition.

## Execution Model [#execution-model]

Every blueprint should follow this shared lifecycle:

1. `load_metadata`
2. `resolve_config`
3. `load_inputs`
4. `start_run_store`
5. `observe_simulation_state`
6. `call_llm_agent`
7. `apply_decision_to_simulation`
8. `emit_events`
9. `write_final_artifact`

Blueprints may insert domain-specific steps, such as:

* `seed_large_context`
* `retrieve_working_memory`
* `score_all_context_vs_optimized_memory`
* `sample_video_frame`
* `evaluate_binding`
* `rank_candidates`

Domain-specific steps should preserve the shared lifecycle ordering around config, inputs, run store, events, and final artifacts.

## Pre-Launch Hook [#pre-launch-hook]

Blueprints may include `scripts/pre-launch.sh` when a run needs host-side services before validation or worker submission, such as a local RTSP mapper, tunnel, or filesystem watcher. The hook is optional; blueprints without it launch normally.

Launchers start `scripts/pre-launch.sh` before launch-time input validation. The hook may be long-lived and must write the file named by `MN_PRE_LAUNCH_READY_FILE` once the required service is usable. Launchers wait for that file and fail the run cleanly if it is not written before the timeout.

Launchers provide these environment variables:

* `MN_RUN_ID`
* `MN_RUN_DIR`
* `MN_RUNS_ROOT`
* `MN_BLUEPRINT_BUNDLE_DIR`
* `MN_BLUEPRINT_CONFIG_JSON`
* `MN_PRE_LAUNCH_READY_FILE`

`MN_PRE_LAUNCH_TIMEOUT_SECONDS` may override the launcher wait timeout.

The hook should log to stdout/stderr, avoid mutating tracked blueprint files, and terminate cleanly on `SIGTERM`. Launchers record `pre_launch.log` and `pre_launch_process.json` in the run directory and stop the process on failed validation, failed submission, cancellation, or run-resource cleanup.

## Manifest Graph Contract [#manifest-graph-contract]

`manifest.json` must declare:

* `entrypoints`
* `nodes`
* `edges`
* `initial_inputs`
* `requirements` with minimum `cpu`, `gpu`, `memory`, and `disk`
* `input_validation` with a `rules` list, even when no custom rules are needed yet
* `license`
* `term`

The manifest graph is the actualized-agent communication contract. It should make the workflow inspectable without reading every payload script. A reader should be able to identify the templates used, the concrete agents produced from those templates, their responsibilities, their message handoffs, and the runtime concerns that matter for reliability or edge execution.

Each node should include:

* `node_id`
* `alias`, when the node is rendered from a shared template and needs a job-specific user-facing name
* `display_name`, when a title-cased or spaced variant is useful for UI surfaces
* `type`
* `role`, when useful
* `agent_type`
* `config.command`, for executable nodes
* `config.workdir`
* `config.upload_path` or `config.upload_paths`, when payload files must be staged
* `config.output_message_type`, when the node emits graph messages
* `uses`, when the node is rendered from a shared `mn-agents` template
* `config.llm_config`, when the agent calls an LLM
* sandbox or service config, when the agent runs untrusted code, generated code, browser automation, shell commands, custom images, or network-facing services

Edges must include:

* `edge_id`
* `from_node`
* `to_node`
* `message_type`

Multi-agent workflows should keep message types stable and explicit. Avoid implicit handoffs through shared files unless the artifact is also declared in metadata or output contracts.

Long-running blueprints should set top-level manifest `type: "service"`. Finite batch blueprints should omit top-level `type`.

### Shared Agent Aliases [#shared-agent-aliases]

Shared `mn-agents` templates often use generic implementation names such as `ingress`, `runtime`, `router`, `worker`, or `visual_detector`. A blueprint may customize those shared/template agents with `alias` and optional `display_name` so Job Details, progress views, graph views, logs, and dashboards can show domain-specific names.

`alias` is the canonical field for blueprint-level renaming. It is display-only. It must not change scheduling, event routing, persisted IDs, service registration, `node_id`, `uses`, or message contracts.

Display name precedence is:

1. `alias`
2. `display_name`
3. `label`
4. `role`
5. stable id (`id`, `agent_id`, or `node_id`)

Use aliases when a shared agent becomes a job-specific noun. Prefer concise snake\_case aliases for stable product surfaces, and use `display_name` only when a human-readable title is useful.

Example:

```json
{
  "metadata": {
    "agent_templates": {
      "nodes": [
        {
          "node_id": "ingress",
          "alias": "video_monitor",
          "display_name": "Video Monitor",
          "uses": "mn-agents.control_router@1.0.0"
        },
        {
          "node_id": "video_frame_tick_source",
          "alias": "frame_sampler",
          "display_name": "Frame Sampler",
          "uses": "mn-agents.data_module@1.0.0"
        }
      ]
    }
  }
}
```

Workflow workers under `runtime.bindings.*.workers[]` may also declare aliases:

```json
{
  "runtime": {
    "bindings": {
      "detect_visual_targets": {
        "workers": [
          {
            "id": "visual_target_detector",
            "alias": "visual_target_detector",
            "display_name": "Visual Target Detector",
            "role": "Run visual detection"
          },
          {
            "id": "quality_controller",
            "alias": "quality_controller",
            "display_name": "Quality Controller",
            "role": "Review alert quality"
          }
        ]
      }
    }
  }
}
```

When a blueprint uses shared template nodes, preserve both identities:

* Stable runtime identity: `node_id`, worker `id`, `uses`, edge endpoints, and event worker IDs.
* User-facing identity: `alias`, then `display_name`, then existing labels and roles.

Do not rename a stable runtime id just to improve UI text. If the runtime id is part of edges, persisted events, or service registration, keep it stable and add `alias`. If a workflow worker id is newly introduced and not yet part of a compatibility contract, it should already be a job-specific noun such as `video_monitor`, `frame_sampler`, `quality_controller`, or `watch_summary_writer`.

Runtime infrastructure agents are not blueprint workers. If transport or wrapper agents appear in graph data, UI surfaces should label them as system/runtime infrastructure rather than showing raw names such as `runtime` as if they were domain agents.

### Custom OpenShell Image Port Note [#custom-openshell-image-port-note]

Agents that run with a customized OpenShell image should declare any input or output ports that must be reachable from outside the sandbox. This applies to custom images declared with fields such as `custom_openshell_image` and runners such as `MirrorNeuron.Sandbox.OpenShell`.

If an OpenShell agent consumes or exposes a network service, the blueprint should use SSH port tunneling to verify and preserve connectivity for those ports. This includes:

* input stream ports, such as RTSP, WebRTC, WebSocket, Socket.IO, TCP, UDP, HTTP, or webhook listener ports
* output service ports, such as local dashboards, preview servers, callback URLs, report servers, or connector bridge endpoints
* model, tool, or helper service ports that must be reached from inside the OpenShell sandbox

Recommended OpenShell port declaration shape:

```json
{
  "openshell": {
    "custom_image": "person_detector/openshell_sandbox",
    "ports": [
      {
        "name": "video_input",
        "direction": "input",
        "protocol": "rtsp",
        "container_port": 8554,
        "external_port": 8554,
        "tunnel": "ssh",
        "required": true
      },
      {
        "name": "dashboard_output",
        "direction": "output",
        "protocol": "http",
        "container_port": 7860,
        "external_port": 8080,
        "tunnel": "ssh",
        "required": false
      }
    ]
  }
}
```

Each declared port should include:

* `name`
* `direction`: `input`, `output`, or `bidirectional`
* `protocol`
* `container_port`: internal container or process port, when applicable
* `external_port`: host or tunnel port exposed outside the sandbox
* `host_port`, when separately fixed by the runtime
* `tunnel`: usually `ssh` for OpenShell network bridging
* `required`: whether failure to establish the tunnel should stop the run

Before the agent starts processing live input or publishing output, the runtime should verify that required SSH tunnels are established and that the declared ports are reachable from the side that needs them. Tunnel setup, verification, and failures should be recorded as events, such as `openshell_tunnel_started`, `openshell_tunnel_verified`, and `openshell_tunnel_failed`.

OpenShell tunnel failures should follow `error_handling`: use `retry` for temporary tunnel setup issues, `skip` only for optional output ports, and `stop` when a required input or output port cannot be reached.

## LLM Config Contract [#llm-config-contract]

LLM usage is part of the shared blueprint standard. Any blueprint that calls a language, vision-language, embedding, reranking, or multimodal model must declare those model settings in `llm`.

One blueprint may have one or many named `LLM_CONFIG` entries. The `llm` section is the registry for those entries.

LLM use is an agent capability, not a workflow default. Prefer deterministic agents when rules, simulation, routing, validation, aggregation, or formatting can be handled without model inference. Reserve LLM agents for judgment, language, multimodal interpretation, planning, code generation, or other tasks that need model behavior.

Recommended shape:

```json
{
  "llm": {
    "enabled": true,
    "default_config": "primary",
    "configs": {
      "primary": {
        "provider": "docker_model_runner",
        "mode": "openai_compatible",
        "runtime_model": "gemma4:e2b",
        "model": "gemma4:e2b",
        "api_base": "auto",
        "backend": "llama.cpp",
        "context_size": 4096,
        "mock_mode": "fake",
        "timeout_seconds": 60,
        "num_retries": 1,
        "max_tokens": 700
      },
      "vision": {
        "provider": "ollama",
        "mode": "ollama",
        "model": "nemotron3:33b",
        "api_base": "http://192.168.4.173:11434",
        "mock_mode": "fake"
      }
    },
    "agents": {
      "analyst": {
        "llm_config": "primary",
        "role": "Portfolio stress-test analyst"
      },
      "frame_observer": {
        "llm_config": "vision",
        "role": "Safety observation agent"
      }
    }
  }
}
```

Model-free blueprints should keep the `llm` section but set:

```json
{
  "llm": {
    "enabled": false
  }
}
```

Each `LLM_CONFIG` entry should include:

* `provider`
* `mode`
* `model`
* `api_base`
* `mock_mode`
* timeout, retry, and token fields when supported
* credential reference fields when needed, such as `api_key_env`
* for runtime-managed local models, `provider: "docker_model_runner"` plus `runtime_model`, `backend`, and optional `context_size`

For local Docker Model Runner models, `api_base: "auto"` lets MirrorNeuron inject `http://localhost:12434/engines/v1` for HostLocal workers and `http://model-runner.docker.internal/engines/v1` for container or sandbox workers. The default runtime model alias is `gemma4:e2b`, resolved to Docker's `ai/gemma4:E2B`.

Each agent that uses an LLM must reference a named config with `llm_config`. Agents must not repeat model values that already live in `llm.configs`.

Allowed agent-level fields:

* `llm_config`: required named reference to `llm.configs.<name>`.
* `role`
* `responsibilities`
* prompt or instruction text
* tool and output schema declarations

Agent prompts, worker manifests, manifest environment blocks, and script defaults should quote the config reference only, for example `LLM_CONFIG.primary` or `llm.configs.primary`. They must not restate the concrete `model`, `api_base`, credential, timeout, retry, or max-token values. Manifest node environments should reference resolved config-derived environment names rather than literal model settings.

Domain-specific model sections such as `vl_model` should be folded into `llm.configs` unless they contain non-LLM stream or device settings. For example, a video blueprint should keep stream source fields in `streams`, but place the vision-language model endpoint in `llm.configs.vision`.

LLM agents that generate, modify, review, browse, shell into, install dependencies for, or execute code should run in a declared sandbox, such as OpenShell or another runtime-supported isolation boundary. The blueprint should declare relevant sandbox image, file access, network access, service ports, and output artifacts so MirrorNeuron can enforce the boundary and record what happened.

Mock mode must be available for quick tests and offline demos.

Model endpoints, credentials, and provider-specific values should be configurable through config and environment, not hard-coded inside worker logic.

`mn blueprint validate` and `mn blueprint run` check runtime-managed local models after service preflight and before input validation. Missing models fail with a fix such as `mn model install gemma4:e2b`; incompatible hardware fails unless the operator explicitly uses `--force`.

## UI Contract [#ui-contract]

Blueprints may expose:

* no UI
* static HTML output
* Gradio dashboard
* custom UI adapter

Supported web UI adapters:

* `none`
* `static_html`
* `gradio`
* `custom`

UI configuration belongs under `web_ui`. If a UI is enabled, the blueprint should write `web_ui.json` with at least:

* `enabled`
* `adapter`
* `url`, when a server is launched
* `port`, when a TCP server is launched
* `run_id`
* `run_dir`

Input UIs should collect config/input values and pass them through the normal config and input adapters. Output UIs should read from the run store instead of private worker state.

## Quick Test Contract [#quick-test-contract]

Every blueprint should define `metadata.quick_test`.

Quick tests should:

* Use mock inputs by default.
* Avoid external services unless explicitly enabled.
* Be deterministic where possible.
* Complete quickly enough for local validation.
* Emit the same required run artifacts as normal runs.

When a quick test is disabled, the metadata must explain why and provide the safest available validation path.

## Configuration Review Contract [#configuration-review-contract]

Blueprints with operationally sensitive or environment-specific defaults should declare `metadata.init_config_review`.

Use init config review for fields such as:

* stream URI or URL
* `llm.configs.<name>.api_base`
* `llm.configs.<name>.model`
* Slack or notification destination
* credentials reference
* data source path

Each review field should include:

* `path`
* `label`
* `default`
* `description`

The review step should let the user keep defaults or provide overrides before launch.

## Validation Checklist [#validation-checklist]

Use this checklist to separate universal requirements from feature-specific requirements.

### Required For All Blueprints [#required-for-all-blueprints]

* It appears in `index.json`.
* It has `manifest.json`, `README.md`, `SPEC.md`, `LICENSE.md`, `TERM.md`, and `config/default.json`.
* `manifest.json.metadata.blueprint_id` matches the directory name.
* `manifest.json.license` points to `LICENSE.md`.
* `manifest.json.term` points to `TERM.md`.
* `config/default.json.identity.blueprint_id` matches the directory name.
* It declares standard version `1.0`.
* It supports `mock`, `json`, `file`, and `env_json` input adapters.
* It always writes local logs, events, and required run artifacts through `local_run_store`.
* It emits `run_started`, `inputs_loaded`, and completion or failure events.
* It records every error and declares whether recoverable errors use `retry`, `skip`, or `stop`.
* It has a deterministic mock path or explains why quick test is disabled.
* Its product metadata explains input, output, user, problem, benefit, and runtime features.
* Blueprint-specific config sections are declared in `interfaces`.
* Sensitive values are not written into durable logs or artifacts.

### Required When Applicable [#required-when-applicable]

* Connector-backed inputs are declared as input skills with source identity, `live` behavior, and event types.
* External output destinations are declared as output skills and combined as fan-out after local run-store writes.
* TCP outputs use fixed external ports: `8080` for primary output and `8081` for fallback or secondary output.
* Persisted logs use structured records and canonical levels: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, and `CRITICAL`.
* Long-running service, live, or stream blueprints declare state, checkpoint, resume, and idempotency behavior.
* Blueprints that require external systems declare required and optional capabilities before launch.
* Blueprints that need host-side setup before validation or submission use the standard `scripts/pre-launch.sh` hook and signal readiness through `MN_PRE_LAUNCH_READY_FILE`.
* Blueprints that process sensitive, business, operational, financial, health, media, or connector data classify handled data and define logging, LLM, output-skill, and artifact behavior.
* Blueprints with scheduled, live, webhook, stream, service, or batch execution declare trigger type.
* Live, stream, or high-volume blueprints declare backpressure and rate-limit behavior.
* Deterministic or replayable blueprints declare seed, replay inputs/events, and mock LLM behavior.
* Blueprints with validator-consumed schemas declare schema ids for config, inputs, events, final artifacts, input skills, output skills, and handoffs.
* Blueprints with runtime, LLM, connector, disk, or stream limits declare resource budgets.
* Blueprints with `flow.steps` declare `runtime.workflow_control`, use `workflow_state` as the runtime state source, and expose workflow attempt, retry, blocked, and terminal step events in `metadata.status_contract`.
* Every `flow.steps[]` entry has positive `control.timeout_seconds`, bounded retry attempts, and a declared failure policy.
* Multi-agent graphs declare handoff message type, payload schema, producer, consumer, error policy, and artifact ownership.
* Shared/template agents and workflow workers declare `alias` when their stable runtime IDs are generic or implementation-oriented.
* Python executor workflow workers require `agent_beacon` liveness and render step timeout, retry, and beacon policy into the runtime node config.
* Agents using customized OpenShell images declare required input/output ports and verify SSH tunnels before processing.
* External endpoints and model settings are configurable when used.
* LLM-using blueprints declare model usage under `llm.configs`.
* Agents reference named `LLM_CONFIG` entries instead of repeating concrete model settings.

### Recommended [#recommended]

* Durable artifacts include artifact metadata such as `artifact_id`, `type`, `schema_version`, `path`, `mime_type`, `created_at`, and `producer`.
* Blueprints declare schemas before validators enforce them.
* Blueprints declare resource budgets before they are needed for hosted execution.
* Blueprints declare privacy rules even when data is expected to be only `public` or `internal`.

## Versioning [#versioning]

The standard should change only when the cross-blueprint contract changes.

Patch-level changes can clarify wording without changing `standard_version`.

Increment the standard version when adding, removing, or renaming:

* required config sections
* required adapters
* required run artifacts
* required event fields
* lifecycle steps that validators enforce

Blueprints may support a newer standard while keeping compatibility fields for `1.0` during migration.
