Key points
- The
outputblock runs after execution finishes, so it can describe what happened, including failures. output.items[].typeacceptsmarkdown,pdf,excel,json,html, ordashboard.whenacceptsalways,success, orfailureand defaults toalways.- The whole
outputblock is rejected whenllm_enabled: false, because deliverables are generated. - A
dashboarditem needs adashboardblock;modeacceptsreplace,append,snapshot, orseries, and defaults toreplace. - Deliverables are stored separately from raw task logs, and run list surfaces expose only an aggregate
final_output_status.
Examples
output:
model: reasoning-large
items:
- name: Release summary
type: markdown
when: always
prompt: Summarize the release, its approvals, and anything that failed.
model: reasoning-large
- name: Release health
type: dashboard
when: success
prompt: Publish the release health entry for this service.
dashboard:
ref: platform/service-health
section: releases
entry_key: payments
mode: series
preset: metrics
ttl: 30dname: release-service
description: Build, verify, and publish the payments service.
container_image: alpine:3.20
working_directory: /workspace
timeout: 45m
display_option: list
llm_enabled: true
model: reasoning-large
agent_role: senior-release-engineer
governance_level: strict
mcp_profiles:
- jira-readonly
knowledge_context:
- kind: guardrail
ref: security/repo-check
required: true
llm_content_preload: false
llm_content_include:
- "src/**/*.go"
llm_content_ignore:
- "**/testdata/**"
variables:
- RELEASE_CHANNEL
- platform/shared:ARTIFACT_BUCKET
steps:
- name: checkout
include: step:platform/shared/checkout
- name: build
depends_on: [checkout]
script: |
make build
echo "1.0.$(date +%s)" > /nopsai/outputs/BUILD_TAG
outputs:
- name: BUILD_TAG
- name: verify
image: golang:1.24
depends_on: [build]
runtime_pool: ci
volumes:
- build-cache:/root/.cache
script: |
go vet ./...
go test ./...
- name: checks
depends_on: [verify]
tasks:
- name: licenses
ignore_failure: true
script: |
./scripts/license-check.sh
- name: sbom
script: |
./scripts/sbom.sh > /workspace/sbom.json
sha256sum /workspace/sbom.json | cut -d' ' -f1 > /nopsai/outputs/SBOM_DIGEST
outputs:
- name: SBOM_DIGEST
- name: risk-review
depends_on: [checks.sbom]
goal: Review the changed files and list the risks this release carries.
model: reasoning-large
governance_level: advisory
mcp_profiles:
- jira-readonly
knowledge_context:
- kind: example
path: .nopsai/docs/risk-review-example.md
- name: report
depends_on: [checks.licenses, checks.sbom]
variables:
SBOM_DIGEST: $steps.checks.sbom.outputs.SBOM_DIGEST
script: |
echo "checks complete"
echo "sbom $SBOM_DIGEST"
- name: package
depends_on: [checks]
secrets:
- REGISTRY_TOKEN
- platform/shared:SIGNING_KEY
variables:
BUILD_TAG: $steps.build.outputs.BUILD_TAG
script: |
./scripts/package.sh "$BUILD_TAG"
echo "channel $RELEASE_CHANNEL, bucket $ARTIFACT_BUCKET"
./scripts/mint-token.sh > /nopsai/outputs/PUBLISH_TOKEN
./scripts/sign.sh --key "$SIGNING_KEY" --token "$REGISTRY_TOKEN"
outputs:
- name: PUBLISH_TOKEN
sensitive: true
- name: announce
depends_on: [package]
condition: Only run when the release channel is stable.
ignore_failure: true
script: |
./scripts/announce.sh
- name: production-gate
depends_on: [package]
approval:
type: production-release
teams:
- platform/sre
allow_self_approval: false
timeout: 24h
- name: publish
depends_on: [production-gate]
script: |
./scripts/promote.sh
- name: release-notes
depends_on: [publish]
goal: Read the commits since the last tag and write release notes to /workspace/NOTES.md.
model: reasoning-large
agent_role: release-writer
governance_level: advisory
mcp_profiles:
- github-readonly
knowledge_context:
- kind: policy
ref: platform/release-notes
required: true
- name: deploy
depends_on: [publish]
include: pipeline:platform/deploy-service
sync: true
outputs:
- name: DEPLOY_ID
output:
model: reasoning-large
items:
- name: Release summary
type: markdown
when: always
prompt: Summarize the release, its approvals, and anything that failed.
model: reasoning-large
- name: Release health
type: dashboard
when: success
prompt: Publish the release health entry for this service.
dashboard:
ref: platform/service-health
section: releases
entry_key: payments
mode: series
preset: metrics
ttl: 30dllm_enabled: false
output:
items:
- name: Summary
type: markdown
prompt: Summarize the run.Field reference
outputpipelineobjectOptionalNone
Final deliverables and dashboard publications generated after the run finishes.
output:
items:
- name: Summary
type: markdown
prompt: Summarize the run.- Rejected when
llm_enabled: false.
services/nopsai/pkg/validation/pipeline.go
output.modeloutputstringOptionalPipeline `model`, otherwise configured default
Model profile used to generate every output item that does not set its own.
output:
model: report-writer- Setting this without at least one output item is a validation error.
output.items[].model
services/nopsai/pkg/validation/pipeline.go
output.items[].nameoutput itemstringRequiredNone
Display name of the deliverable and the default dashboard entry key.
name: Executive summary- Duplicate names are rejected (case-insensitive).
services/nopsai/pkg/validation/pipeline.go
output.items[].typeoutput itemstringRequiredNone
Deliverable format produced after the run finishes.
type: pdfmarkdown, pdf, excel, json, html, dashboard
pdfrendering requires a reachable Gotenberg service.
services/nopsai/pkg/validation/pipeline.go
output.items[].whenoutput itemstringOptionalalways
Run outcome that triggers generation of this item.
when: failurealways, success, failure
- An omitted or empty value is treated as
always.
services/nopsai/pkg/validation/pipeline.go
output.items[].promptoutput itemstringRequiredNone
Instruction used to generate the deliverable content from run evidence.
prompt: Summarize the release, its approvals, and any ignored failures.- An empty prompt is a validation error.
services/nopsai/pkg/validation/pipeline.go
output.items[].modeloutput itemstringOptional`output.model`, then pipeline, then configured default
Most specific model profile override for this deliverable.
model: reasoning-largeoutput.items[].dashboard.refdashboard outputstringRequiredNone
Target dashboard in team/dashboard-slug form.
ref: platform/release-health- Requires
type: dashboard. - Must be a relative path with at least two segments.
- Segments may not be empty,
., or...
services/nopsai/pkg/validation/pipeline.go
output.items[].dashboard.sectiondashboard outputstringRequiredNone
Dashboard section key the publication is written into.
section: deployments- Requires
type: dashboard. - Must match ^[a-zA-Z0-9_.-]+$.
services/nopsai/pkg/validation/pipeline.go
output.items[].dashboard.entry_keydashboard outputstringOptionalThe output item name
Stable key that identifies the entry across runs so replace and series can find it.
entry_key: payments/prod- Requires
type: dashboard. - Must match ^[a-zA-Z0-9_.:/-]+$.
services/nopsai/pkg/validation/pipeline.go
output.items[].dashboard.modedashboard outputstringOptionalreplace
How the publication interacts with existing entries under the same key.
mode: seriesreplace, append, snapshot, series
- Requires
type: dashboard. - An empty value is accepted and means
replace.
services/nopsai/pkg/validation/pipeline.go
output.items[].dashboard.presetdashboard outputstringOptionalNone
Prompt preset hint for the generated layout: narrative report, primary table, current-state status, chronological timeline, side-by-side comparison, numbers-first metrics, or cohesive mixed.
preset: metricsauto, report, table, status, timeline, comparison, metrics, mixed
- Requires
type: dashboard. - An empty value is accepted.
services/nopsai/pkg/validation/pipeline.go
output.items[].dashboard.ttldashboard outputdurationOptionalNone
How long the published entry is treated as current before it is shown as stale.
ttl: 7d- Requires
type: dashboard.
How it works
Think of deliverables as the audience-facing half of a run. The logs are for whoever is debugging; the deliverable is for whoever needs to know what shipped, and it is the artefact that survives into a review.
A failed run can still produce a deliverable. when: failure is how a pipeline explains itself to the person who did not watch it run.
Dashboard publication turns a run into a data point rather than a document: series accumulates entries over time under an entry key, while replace keeps only the current state.
Generation can be retried and cancelled per item without re-running the pipeline, which matters when a renderer, not the work, is what failed.
Implementation evidence
services/nopsai/pipeline_final_output_specs.goItem specification, types, and generation contract.
doc/final-output-rendering.mdRenderers, retry and audit behavior.

