v1.5.0 to v1.6.0

116 added, 103 removed. Audit A to A.

---
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:*)"
+ Read-only release dashboard showing the release states a project can prove: unpushed work,
+ normalized CI, deployment progress, deploy-order blockers, and optional feature-toggle gates.
+ Passive: never prompts, pushes, or mutates state. Use for a quick release snapshot.
+ allowed-tools: "Read,Bash(./scripts/release-digest:*),Bash(./scripts/release-order:*),Bash(./scripts/contract-check:*)"
model-tier: standard
model: sonnet
effort: medium
- version: "1.5.0"
+ version: "1.6.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.
+ A read-only snapshot of release state across a project's services. It is the passive sibling of
+ `/release-manager`: show only states supported by available project evidence, take no action, and
+ ask no questions.
## 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
+ - Before starting `/watch-release`, to see the baseline
+ - To inspect what `/release-manager` could evaluate 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>`.
+ For the interactive gatekeeper, use `/release-manager`. For a deep gate on one service, use
+ `/ready-to-release <service>`.
## Usage
- ```
+ ```text
/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):
+ 1. **Gather the project digest.** Run the shared mechanical digest and pass through any service
+ argument:
```bash
- ./scripts/release-digest # git + ci + deploy + toggles, one parsed result
+ ./scripts/release-digest
```
- 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`.
+ The digest is the required project adapter. If it is missing, exits nonzero, omits the service
+ header, or is malformed, print one bounded `_Release status unavailable: <reason>_` line and
+ stop. Do not guess from project files or invoke a provider directly.
- 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.
+ Parse its ANSI-free sections:
- 2b. **Scan dependencies + contract coverage** (both read-only, no tokens/network):
+ - `---META---`: `context=<name>`, `ciProvider=<circleci|github-actions|cloud-build|none>`, and
+ `ci=<available|partial|unavailable>`. Provider identity is diagnostic only; decision and
+ rendering logic use normalized fields below and never branch by provider.
+ - `---SERVICES---`: one pipe-delimited row per service after this exact header:
+ `service|unpushed|uncommitted|ci|ciBranch|gitBranch|head|deploy|tag|age|ciRevision|ciExpectedRevision`.
+ - `unpushed` is commits ahead of upstream; `uncommitted` is `true|false`; `head` is local HEAD.
+ - `ci` is `success|failed|running|error|unknown`. Treat it as `unknown` for display when
+ `ciBranch != gitBranch`, either revision is `-`, or `ciRevision != ciExpectedRevision`.
+ A provider's branch-only or stale green is not exact evidence.
+ - `deploy`, `tag`, and `age` are optional deployment observations. An `N/M` value and
+ `cron`/`cron:rollout` are observable; `unknown`, `notfound`, `not-applicable`, and `-` are
+ not evidence of deployment state.
+ - `---TOGGLES---`: optional `FLAG=value` lines. Use them only when the optional manifest context
+ in step 2 declares toggle policy.
+ 2. **Read optional manifest context.** If `docs/release-manifest.yaml` is absent or unreadable,
+ use empty defaults for `toggles`, `parked`, `ignore`, and `non_deploying`. Otherwise read only
+ those sections. Ordering never depends on parsing the manifest here.
+
+ 2b. **Read optional ordering and contract coverage.** When the executable exists, run each command
+ read-only:
+
```bash
- ./scripts/release-order # effective dependency ordering authority
- ./scripts/contract-check coverage # CI verification coverage
+ ./scripts/release-order
+ ./scripts/contract-check coverage
```
- Both are project symlinks installed by their owning skills — `release-order` by
- /release-manager (see its Setup), `contract-check` by /contract-check.
+ - From a successful, well-formed `release-order`, parse `---GRAPH---` as the effective
+ `consumer: [providers]` map and `---DRIFT---` as informational drift evidence. If the command
+ is missing, exits nonzero, or is malformed, use an empty dependency map and mark dependency-order evidence unavailable.
+ Omit dependency drift; the dashboard still renders.
+ - From a successful `contract-check coverage`, parse `GAP`/`OK` lines. If the command is missing,
+ exits nonzero, or is malformed, omit contract-coverage observations; the dashboard still
+ renders.
- 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.
+ 2c. **Read optional in-flight state.** Read `.release-state.json` at the project root only when it
+ exists and is valid. Never create, repair, or rewrite it. `rolloutWatch` entries have the shape
+ `<service>: { sha, fromTag }` and describe pushes whose new deployment has not been confirmed.
+ Keep an entry only as potential context until step 3 establishes that deployment is observable
+ for that service.
- 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.
+ 3. **Classify available capabilities before rendering.** Capabilities come from evidence, not
+ project or provider names:
- 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.
+ - **CI exactness:** available per row only when normalized ref and revision fields match as
+ described in step 1. Otherwise display `unknown` even if native status says success.
+ - **Deployment observation:** a service is deployment-observable only when its `deploy` value is
+ `N/M`, `cron`, or `cron:rollout`. Include the `deployed (ready/tag/age)` column when at least
+ one displayed service is deployment-observable. If none is, omit the `deployed` column and
+ omit rollout-derived observations; do not infer a rollout state from Git history, CI, a saved
+ `rolloutWatch`, or naming conventions.
+ - **Toggle policy:** available only when the manifest has a non-empty `toggles` or `parked` map.
+ When both `toggles` and `parked` are empty, skip toggle evaluation entirely and omit toggle
+ observations. Never infer a toggle system from source names or a non-empty digest section.
+ - **Dependency order:** available only from a successful, well-formed `release-order` result;
+ `provider=none` with an empty graph is valid evidence. When unavailable, omit `READY`,
+ `WAITING`, and dependency-drift observations because prerequisite safety is not computable.
+ - **Contract coverage:** available only from a successful, well-formed coverage result. Its
+ absence removes coverage observations, not the service rows.
- 3. **Render a single table**, one row per service (skip `ignore`d services), columns:
- `service | unpushed | uncommitted | CI | deployed (ready/tag/age)`.
+ 4. **Render one table**, skipping `ignore`d services:
- 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.
+ - Always show `service | unpushed | uncommitted | CI`.
+ - Add `deployed (ready/tag/age)` only when deployment observation is available globally. Use `—`
+ in that column for an individual service without observable deployment evidence.
+ - Keep provider names out of column names and gate labels.
- 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").
+ 5. **Render observations only when computable.** This skill must never ask a question. It must
+ never write state.
+ - `⤴️ PUSHED — rolling out <service>` requires both a valid `rolloutWatch` entry and current
+ observable deployment evidence for that service. When the live tag still equals `fromTag`,
+ show `was <fromTag>, awaiting a new deployed tag`. When the tag moved but deployment remains
+ `N/M` with N<M or `cron:rollout`, show `new tag <tag>, rollout still unsettled`. Only when the
+ tag moved and deployment is settled may you note `✅ rolled out <service> <tag>`. Without
+ observable deployment evidence, omit the observation rather than guessing.
+ - `READY` requires valid dependency-order evidence. It means the service has unpushed commits,
+ exact CI success, and no co-changing prerequisite in the effective map. A valid empty map can
+ therefore yield `READY`; unavailable order evidence cannot.
+ - `WAITING ON <prereq>` requires valid dependency-order evidence, a service with unpushed
+ commits, and a prerequisite from the effective map that is co-changing. Unpushed work is
+ always observable. Count a prerequisite as mid-rollout only when its current deployment is
+ observable (`N/M` with N<M or
+ `cron:rollout`) or when its valid `rolloutWatch` entry can be compared with observable current
+ deployment evidence. A stable already-live prerequisite does not block.
+ - `📊 DEPENDENCY DRIFT` appears only when valid order evidence contains concrete `new:` or
+ `removed:` edges. `unmanaged`, `not-applicable`, absent, and malformed evidence are not drift.
+ - `🔗 CONTRACT COVERAGE GAP` appears only for valid `GAP` evidence, formatted as
+ `<provider>: <not-verified=…>`.
+ - `CI RED` appears for exact `failed` or `error` evidence. `running` stays visibly in progress;
+ stale or mismatched evidence displays as `unknown`.
+ - `TOGGLE READY` requires declared toggle policy, a false manifest-referenced flag, and settled
+ observable deployment evidence for its gating service. A `status: dark-release` toggle is
+ shown as `🌓 DARK RELEASE <flag> — flip is a manual call once validated`. A `parked` flag is
+ never ready; list it at most once in a quiet parked footnote. If deployment or toggle evidence
+ is unavailable, omit this state instead of reporting a failure.
+
+ 6. **Summarize in one line.** Count only rendered states, for example:
+ `3 ready, 1 waiting, 1 CI red, 2 coverage gaps`. Omit zero-count capability categories that were
+ not available. Keep the full result to roughly one screen.
+
## 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`.
+ - This skill is strictly read-only: never prompt, push, file work, reconcile drift, trigger CI,
+ mutate deployment, or update `.release-state.json`.
+ - `release-digest` is the one required project adapter. Deployment and toggle implementations are
+ deliberately opaque to this skill; normalized evidence decides what can be shown.
+ - `release-order` and `contract-check coverage` enrich the dashboard when installed. Their absence
+ must not hide basic Git and CI status.