Skip to main content

Output and artifact model

Standard streams

Interpreters MAY write arbitrary text to standard output and standard error. The Runner captures both streams separately. They’re treated as unstructured by default. Output encoding MUST be UTF‑8. Interpreters SHOULD avoid emitting binary data directly; binary artifacts SHOULD be written to files and referenced as artifacts instead.

Artifacts

An artifact is any piece of data produced by an interpreter that’s attached to the job context. The Runner persists artifacts and makes them available for subsequent steps. This specification defines four well-known/standard artifact types:

  • Logs - Verbose, human‑readable messages (beyond raw stdout/stderr) intended for auditing or debugging.
  • Metrics - Quantitative measurements such as counts, durations, rates, or success percentages.
  • Reports - Structured or semi‑structured documents (for example, JSON, XML, or HTML) intended for downstream analysis or presentation.
  • State - Serialized objects representing the result of an action (for example, a list of created resources). Typically inserted into the job context. Subsequent steps may consume state values through expected inputs.

Interpreters MAY define additional artifact types. When introducing a new type, the interpreter MUST document its semantics and specify how the Runner should handle it.

Artifact emission

Interpreters MUST emit step results, including any artifact identifiers, paths, summaries, metrics, logs, and extracted values, through the Interpreter Output Contract returned as a single JSON object through standard output (stdout) (refer to the Interpreter output contract section for further details).

The Courier Runner MUST treat the output object in the Interpreter Output Contract as the authoritative carrier for interpreter-defined structured results. Interpreters MAY include any JSON-serializable keys in output, subject to interpreter-specific contract discovery (refer to the Interpreter discovery section for further details).

Artifact representation

For the purposes of this specification, an artifact is any interpreter-emitted result intended to be consumed by:

  • output field extraction rules (outputFieldRules), or
  • subsequent steps through job context variable propagation, or
  • downstream reporting and audit.

Interpreters SHOULD represent artifacts in the output map using one of the following forms:

  • Inline artifact content, encoded as JSON scalar or object values when small and safe to return in-band.
  • Artifact references, expressed as stable identifiers or file paths that the Runner can use as extraction sources (for example, if outputFieldRules.sourceType is file or artifact).

If an interpreter emits binary data as inline artifact content, it MUST encode the content into a string-safe representation (for example, Base64) and SHOULD clearly label the encoding in the corresponding key name or a companion field.

Raw output and error capture

Interpreters SHOULD include raw underlying tool output in the output map to support debugging and audit trails. At a minimum, interpreters SHOULD provide keys equivalent to:

  • rawInterpreterOutput
  • rawInterpreterError

Interpreters MAY also write unstructured diagnostic text to stderr. The Runner MAY capture and store stderr independently, but stderr MUST NOT be relied upon as the sole carrier for structured artifacts or required outputs.

Relationship to output field rules

When a job step defines outputFieldRules, the Courier Runner MAY derive job context variables from the following (as specified in the step definition):

  • stdout or stderr streams (sourceType: output),
  • process exit code (sourceType: exitCode),
  • files on disk (sourceType: file), or
  • interpreter-emitted artifact references (sourceType: artifact),

Interpreters that intend for a value to be consumed by later steps SHOULD either:

  • include it directly in the Interpreter Output Contract output map (preferred for structured data), or
  • emit a stable reference (file path or artifact identifier) and include that reference in the output map so that outputFieldRules can extract it deterministically.

Output extraction rules

The Runner uses output field rules to extract values from interpreter outputs for reuse in later steps. Output rules can extract data from artifacts, exit codes, files, or standard streams. Chef documentation lists the source types (artifact, exitCode, file, and output), matching methods (regex, jsonPath, and content), and optional sensitivity and required flags. A simplified outputFieldRules object in a step definition looks like this:

"outputFieldRules": {
  "<FIELD_NAME>": {
    "sourceType": "artifact" | "exitCode" | "file" | "output",
    "source": "<STRING>",           // path or stream name
    "extractMethod": "regex" | "jsonPath" | "content",
    "expression": "<STRING>",       // regex or JSONPath expression
    "required": false,
    "sensitive": false
  }
}

When sourceType is output, source must be stdout or stderr. When the method is content, the full content of the source is returned. Sensitivity and required flags control redaction and failure behavior.

This RFC doesn’t dictate the extraction rules; it specifies that interpreters SHOULDN’T embed extraction logic. Extraction is the responsibility of the Runner. Interpreters simply emit outputs and artifacts.

Thank you for your feedback!

×