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.sourceTypeisfileorartifact).
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:
rawInterpreterOutputrawInterpreterError
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):
stdoutorstderrstreams (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
outputmap (preferred for structured data), or - emit a stable reference (file path or artifact identifier) and include that reference in the
outputmap so thatoutputFieldRulescan 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.