---
name: release-status
description: >
  Read-only release dashboard for letterbox — one view of what's built-but-unpushed,
  pushed-but-not-rolled-out, deployed-but-toggle-still-off, and what's blocked by deploy
  order. Passive: never prompts, never pushes. Use for a quick "where is everything" glance.
allowed-tools: "Read,Bash(./scripts/release-digest:*),Bash(make feature-toggles-disabled:*),Bash(./scripts/release-order:*),Bash(./scripts/contract-check:*)"
model-tier: standard
model: sonnet
effort: medium
version: "1.5.0"
author: "flurdy"
---

# Release Status

A read-only snapshot of release state across all letterbox services. This is the passive
sibling of `/release-manager` — it shows the same picture but **takes no action and asks no
questions**. Safe to run anytime.

## When to Use

- A quick "what's the release situation right now" glance
- Before starting a `/watch-release` loop, to see the baseline
- To sanity-check what `/release-manager` would act on, without being prompted

For the interactive version that prompts to push / defer / cancel and auto-files CI-failure
beads, use `/release-manager`. For a deep gate on one service, use `/ready-to-release <service>`.

## Usage

```
/release-status                 # all services
/release-status dispatch        # one service
```

## Instructions

1. **Gather.** Run the shared mechanical digest (pass through any service arg to scope it):

   ```bash
   ./scripts/release-digest        # git + ci + deploy + toggles, one parsed result
   ```

   Parse the delimited sections (already ANSI-free):
   - `---META---`: `context=<kubectl ctx>`, `ci=<available|unavailable>` — when `ci=unavailable`
     (no CircleCI key from `secret-api-key`, `CIRCLECI_TOKEN`, or `.env.circleci`) every `ci` field is `unknown`; show it as such.
   - `---SERVICES---`: one pipe-delimited line per service after the header line:
     `service|unpushed|uncommitted|ci|ciBranch|gitBranch|head|deploy|tag|age`.
     - `unpushed` (int, commits ahead of origin), `uncommitted` (`true|false`), `head` = short
       sha of the current local HEAD (`-` if no checkout).
     - `ci` ∈ `success|failed|running|error|unknown`; `ciBranch`/`gitBranch` are the pipeline branch
       and the repo's current branch.
     - `deploy` = a Deployment's `<ready>/<desired>` (`1/1` = rolled out; `N/M`, N<M = rolling out;
       `0/1` = failing); for **CronJob-backed services** (digest, patrol, reconciler) it's a marker:
       `cron` = settled / rolled out, `cron:rollout` = images differ (Flux mid-bump). Also
       `notfound`/`unknown` (e.g. no kubectl). `tag`/`age` = live image tag + pod-or-run age.
   - `---TOGGLES---`: `FLAG=value` lines — **compact by default**: only false-valued and
     manifest-referenced (`toggles:`/`parked:`) flags, with a trailing `# compact: …` summary of
     what was hidden. This covers the TOGGLE READY cross-reference (manifest flags show at any
     value; everything still-`false` is present). For the full map run
     `./scripts/release-digest --full-toggles`; for disabled-only, `make feature-toggles-disabled`.

2. **Read optional manifest context.** If `docs/release-manifest.yaml` is absent, use empty
   defaults for `toggles`, `parked`, and `ignore`. Otherwise read those sections. Ordering never
   depends on the skill parsing this file.

2b. **Scan dependencies + contract coverage** (both read-only, no tokens/network):

   ```bash
   ./scripts/release-order           # effective dependency ordering authority
   ./scripts/contract-check coverage # CI verification coverage
   ```

   Both are project symlinks installed by their owning skills — `release-order` by
   /release-manager (see its Setup), `contract-check` by /contract-check.

   From `release-order` parse:
   - `---SOURCE---` — `provider=pact|manifest|none`, `graph=generated|live|manual|none`, and
     manifest presence.
   - `---GRAPH---` — the accepted effective `consumer: [providers]` map after manual edges and
     suppressions. Generated edges remain effective until explicit reconciliation. Use this graph
     directly; do not merge order sections in the skill.
   - `---DRIFT---` — `status: in-sync`, `new:`/`removed:` provider drift, or an
     `unmanaged`/`not-applicable` status when reconciliation does not apply.

   From `contract-check coverage` parse the `GAP`/`OK` lines: a `GAP <provider> … not-verified=…`
   means that provider's CI doesn't verify all its synced consumer contracts. Contract *health*
   lives in `/contract-check`; the dependency graph is purely the rate limiter.

2c. **Read in-flight pushes** from `.release-state.json` at the repo root, **read-only** — if the
   file is absent or unreadable, skip this (do NOT create it; that's `/release-manager`'s job).
   Parse `rolloutWatch`: each entry `<service>: { sha, fromTag }` is a service `/release-manager`
   pushed in a prior tick whose new image hasn't been confirmed live yet. This is the only source
   for the *pushed-but-not-rolled-out* state — once a service is pushed, its `unpushed` count
   drops to 0, so nothing in the `release-digest` output reveals that a rollout is still in flight. Keep
   these for step 4.

3. **Render a single table**, one row per service (skip `ignore`d services), columns:
   `service | unpushed | uncommitted | CI | deployed (ready/tag/age)`.

4. **Below the table, observations only** (no prompts):
   - `⤴️ PUSHED — rolling out <service>` — for each `rolloutWatch` entry from step 2c: compare the
     live deploy `tag` against the recorded `fromTag`. If the live tag still equals `fromTag` (or
     deploy is `unknown`), the rollout is **in flight** — Flux hasn't applied the new image yet;
     show `was <fromTag>, awaiting new tag`. If the live tag has moved off `fromTag` (Deployment
     `ready`, or CronJob marker `cron`), it has effectively rolled out — `/release-manager` will
     clear it from `rolloutWatch` on its next tick; you may note `✅ rolled out <service> <tag>`.
     (Read-only: this skill never edits `rolloutWatch`.)
   - `READY` — has unpushed commits, CI green, and no **co-changing** prereq (see WAITING below).
   - `WAITING ON <prereq>` — has unpushed commits AND a provider it depends on (effective
     map) is *co-changing*: that provider also has unpushed commits, is mid-rollout (a Deployment
     `N/M`, N<M, or a CronJob service showing `cron:rollout`), or was pushed-but-not-confirmed
     (it's in step 2c's `rolloutWatch` with its live tag still at `fromTag`).
     A stable, already-live provider does **not**
     trigger this — only a provider that is itself changing right now. (This is the deploy
     rate limiter: a consumer waits a tick for its provider's rollout to confirm.)
   - `📊 DEPENDENCY DRIFT` — only when `---DRIFT---` contains `new`/`removed` edges, list them
     and note `/release-manager` can reconcile the provider block. An `unmanaged` or
     `not-applicable` status is informational, not drift.
   - `🔗 CONTRACT COVERAGE GAP` — for each `contract-check coverage` `GAP` line, show
     `provider: <not-verified=…>` (e.g. `contactform: not-verified=digest,patrol,…`). This is a
     prod-safety signal — a provider whose CI doesn't verify all its consumer contracts can
     break them silently. (For full contract health — staleness, sync-gaps — run `/contract-check`.)
   - `CI RED` — CI failed/errored (note: `/release-manager` would auto-file a bead here).
   - `TOGGLE READY` — a `toggles` entry whose gating service is rolled out (a Deployment showing
     `deploy ready`, or a CronJob service showing the settled `cron` marker) but whose flag is
     still `false` in prod (cross-reference the `---TOGGLES---` map from step 1). Exceptions:
     - A toggle with `status: dark-release` is **not** "ready" — show it as `🌓 DARK RELEASE
       <flag> — flip is a manual call once validated`, never as TOGGLE READY.
     - **Never** treat a `parked` flag as ready — those are intentionally off; list them once
       under a quiet "parked" footnote (flag, `superseded_by`, `reconsider_if`) and do not nudge.

5. Keep it to one screen. End with a one-line summary (e.g. "3 ready, 1 waiting, 1 CI red, 1
   toggle ready, 2 coverage gaps").

## Notes

- Strictly read-only. If you find yourself wanting to push, file a bead, or reconcile drift,
  that's `/release-manager`.
- A CircleCI key available through `secret-api-key` (or `CIRCLECI_TOKEN`) and kubectl context `paperboy` are needed for full data; degrade gracefully to
  `unknown` for any section that isn't available rather than failing the whole dashboard.
- `./scripts/release-order` (ordering) and `./scripts/contract-check coverage` (contract health)
  are pure-filesystem, need no network/tokens, and always run. A `provider=none` result is a valid
  empty dependency map, not an error. The graph is the deploy rate limiter; coverage gaps are a
  standing prod-safety signal independent of the current release. Full contract health
  (staleness, sync-gaps) is `/contract-check`.
