AGPL-3.0-or-later · forever.

showcase · tier 4 · research

Release train

Tests, lint and audit run in parallel. Only if all three are green does a human sign the GO; then it holds for the window, ships, and verifies prod reports the new version.

No green gates, no departure. No human GO, no departure. It ships on time or not at all, and the journal records which. · conformance-gated in nika-spec ↗ · re-proven at every push

The whole file

13 tasks · 10 waves · the plan falls out of the bindings, nothing is scheduled by hand.

t4-release-train.nika.yamlsource
nika: v1workflow:  id: release-train  description: "parallel gates → human GO → hold until the window → ship · verify · record"vars:  version:    type: string    required: true    description: "The version to ship (e.g. 1.4.0)"  window: "2026-07-28T09:00:00Z"secrets:  team_webhook:    source: env    key: TEAM_WEBHOOK_URL    egress:                       # sanction the on_finally ping · the secret IS the URL      - to: "nika:notify"        host_from_self: truetasks:  t0:    invoke:      tool: "nika:date"      args: { op: now }  # ── the gate wave · all three run in parallel ──  tests:    exec:      command: ["cargo", "test", "--workspace", "--quiet"]      capture: structured    timeout: "15m"  lint:    exec:      command: ["cargo", "clippy", "--workspace", "--all-targets", "--", "-D", "warnings"]      capture: structured    timeout: "10m"  audit:    exec:      command: ["cargo", "audit"]      capture: structured    timeout: "5m"    retry:      max_attempts: 2                  # advisory DB fetch can flake  gates_green:    with:      all_green: ${{ tasks.tests.output.exit_code == 0 && tasks.lint.output.exit_code == 0 && tasks.audit.output.exit_code == 0 }}   # three value edges · one boundary expression    invoke:      tool: "nika:assert"      args:        condition: "${{ with.all_green }}"        message: "A release gate is RED: the train does not depart"  gate_time:    with:      t0: ${{ tasks.t0.output }}    after:      gates_green: succeeded           # state, no data · the timing is only worth taking on a green board    invoke:      tool: "nika:date"      args:        op: diff        start: "${{ with.t0 }}"        end: "now"        unit: minutes  # ── the human signs the departure ──  conductor:    with:      gate_time: ${{ tasks.gate_time.output }}    invoke:      tool: "nika:prompt"      args:        message: "Gates GREEN in ${{ with.gate_time }} min. Ship ${{ vars.version }} in the ${{ vars.window }} window?"        default: false  approved:    with:      signed: ${{ tasks.conductor.output == true }}   # the signature check crosses as ONE boundary expression    invoke:      tool: "nika:assert"      args:        condition: "${{ with.signed }}"        message: "Departure not signed: train cancelled"  # ── hold until the window · absolute time, not a sleep ──  hold:    after:      approved: succeeded    invoke:      tool: "nika:wait"      args:        until: "${{ vars.window }}"        timeout: "48h"  ship:    after:      hold: succeeded    exec:      command: ["./scripts/release.sh", "${{ vars.version }}"]   # argv: the interpolation cannot break out      capture: structured    timeout: "30m"  verify:    after:      ship: succeeded    invoke:      tool: "nika:fetch"      args:        url: "https://api.example.com/v1/version"        mode: jq        jq: ".version"    retry:      max_attempts: 5      backoff_strategy: exponential      backoff_ms: 5000  live:    with:      version_live: ${{ tasks.verify.output == vars.version }}   # the whole check crosses as ONE boundary expression    invoke:      tool: "nika:assert"      args:        condition: "${{ with.version_live }}"        message: "Prod does not report the shipped version: investigate before announcing"  # the always-pattern · `after: {live: terminal}` admits every settled  # state · this task runs whether `live` succeeded, failed, or was  # cancelled by an upstream abort · a record that must land on EVERY  # outcome is a terminal task, not a cleanup hook (03 §on_finally).  record:    after:      live: terminal    with:      outcome: ${{ tasks.live.status }}   # observe the departure verdict · same pass-set as the after edge    invoke:      tool: "nika:emit"      args:        event_type: "release.train.departed"        payload:          version: "${{ vars.version }}"          status: "${{ with.outcome }}"    on_finally:      - invoke:          tool: "nika:notify"          args:            channel: webhook            target: "${{ secrets.team_webhook }}"            message: "Release train ${{ vars.version }} · ${{ with.outcome }}"            severity: infooutputs:  shipped: ${{ tasks.verify.output }}

nika inspect · engine 0.105.0 · vendored graph, never re-derived

13 declared edges · 10 waves · the plan falls out of the bindings