DataRipple
Dev War Room · Gate 1 concepts

Release Pipeline

Reimagining the DWR PRs & GH Integration tab so a merged-but-not-shipped PR is impossible to miss. Three directions on one idea - pick one, then we build it. Illustrative sample data throughout (Gate 1); the real build wires the GitHub feed from line one.
The 2-day pain this fixes

Draft PRs went up for review. Matt reviewed and said “done.” Everyone moved on. Two days later we found the release to RippleCore main was broken - a PR had merged but never actually shipped. The current tab shows merge state but not release state, so “merged” read as “shipped” when it wasn't. The redesign makes the gap between merged and live on main a first-class, loud state.

1 · What's out there

Best-in-class tools, and the gap none of them close

Everyone shows the road up to the merge. Almost no one, for a small team, keeps showing it after the merge - all the way to live on production.

GitHub PRs & Projects

Great at review + merge status. But the story ends at “merged” - there's no built-in “did this actually reach production” state next to the PR.

Gap: stops at merged.

Release trains (GitLab, Shopify, Google)

Batch changes and ship them on a set cadence - exactly Jon's ask. But they're heavy CI machinery, divorced from a simple team PR list.

Gap: not PR-list-native.

Deploy dashboards (Vercel, CD tools)

Show deploy success/fail clearly. But they live in a separate tool from the PRs, so a failed deploy isn't sitting next to the PR that caused it.

Gap: separated from the PR.

Linear / Jira

Strong issue workflow and cycles. Release/ship state is bolted on with custom fields, and it tracks issues, not the PRs themselves.

Gap: issue-first, not release-first.
2 · The slice that makes ours better

“Merged” is not “shipped”

We treat release as a real state after merge, and a scheduled batch (the Monday train) as the unit - so both the gap and the on-purpose exclusions are always visible.
  • Four plain-English release states - Pending merge · Merged, not released · Released · Held for changes. No jargon in the headline.
  • The Monday release train - what's going out, what's in it, and what got pulled and why. Nothing silently drops from a release.
  • A merged-but-not-live PR runs loud - the exact state that cost 2 days becomes the hardest thing on the page to ignore.
  • Every number drills down; every PR opens its full timeline - opened → reviewed → merged → released. That trail is also the release evidence for SOC 2.
3 · Three directions - open them

Same reframe, three layouts

All three share the four states, the Monday train, the loud failed-release, the drill-downs, and the same sample data - so you're comparing layout and emphasis, not content. Click any card to open the live concept.
4 · What ships clean, and what's gated

Good / better / best - with the real blockers named

TierCapabilityWave 1?The real blocker
MustFour release states from PR dataOK Wave 1The webhook already delivers opened / review / merge events, and ship.html already renders PR rows. Merge-side states are free.
Must“Merged, not released” surfaced loudPartialNeeds a release signal - did the merge actually reach RC main? The GitHub webhook gives merge, not deploy-to-main. Source it from GitHub Deployment status events, the RC-main CI result, or a manual “released” mark.
ShouldGrouped release train (batch by ship day)PartialNeeds a “which train” grouping: a PR milestone / label / target-date convention, or a small DWR-side batch table (one row per train). Not in the webhook by default.
ShouldHeld / excluded, with the reasonOK Wave 1“Changes requested” already comes over the webhook; the reason is the review comments. Just needs to be shown as a first-class state instead of buried.
DifferentiatorPer-PR release timeline (opened→released)PartialThe merge-side timeline is free from webhook events; the “released” step needs the release signal above. Assembled timeline can be derived live or cached in a small D1 table.
DifferentiatorRelease-FAILED health & alertingGatedHighest value, highest dependency: needs a real RC-main deploy / CI status feed (the DWR doesn't observe that today) plus a “merged but not released after N hours” rule. Once the release signal exists, the alert itself is small.
5 · What this means for Wave 1

The honest recommendation

Build Concept C (State Ledger) as the Wave-1 base - it's the daily triage tab, closest to replacing today's page, and it pins the failed-release group at the top where it can't be scrolled past. Graft in B's readiness verdict as the Overview tile (the weekly “are we clear to ship Monday” glance) and keep A's flow board as an optional secondary view. Pick one and we lock it.

Ships in Wave 1 (reuses today's webhook + ship.html)

  • The full reframe UI - four states, the Monday train grouping, held/excluded with reasons, and the per-PR merge timeline.
  • A minimal release signal - even a manual “released” mark on the batch closes the 2-day gap on day one and lights up the loud state.

The real work (name it, don't hand-wave)

  • The RC-main release/deploy feed is the one genuine new data source. Wiring GitHub Deployment status (or the CI result) turns the manual mark automatic and unlocks the Release-FAILED alerting - the piece that actually prevents a repeat. Medium effort; it's a new source, not just UI.
  • Train grouping needs a convention decision (label vs milestone vs a small D1 batch table). Small once decided.
Gate 1 boundary: this is a design-review prototype. No live-app changes, no D1, no backend routes - it stops here until you pick a direction.
Sample vs real: every PR, state, and timeline here is illustrative sample data so all three concepts tell the same story. The real build wires the GitHub webhook feed from the first line.
Run locally: node mockups/release-pipeline/_serve.mjs (serves on http://localhost:4310).