Always Shipping

Why PRs are not green, not merged, or not worked on at all while nobody is at the keyboard — and what rules replace the ones that cause that.

Decided 2026-09-17 — Fede adopted all of it except the settings registry (section 5, "Hygiene without a flag platform", first bullet), which is deferred: "too much for now".

Contents

  1. What the 30 days show
  2. Why last night specifically
  3. The thirteen holds, and what to do with each
  4. The rules that replace "end of night"
  5. Risk without flags: the three-switch system
  6. Options for Fede
  7. What was done today

TL;DR

1. What the 30 days show

The machine ships. The problem is the night and the morning baseline, not throughput.

Fede-authored PRs, 2026-08-18 → 09-17
Opened / merged / closed unmerged / open now1,607 / 1,439 / 161 / 7
Median time to merge37 minutes
90th percentile4.4 hours
Merged within 24 hours98.5%
Merged outside 7am–7pm Denver44%

So "always shipping" is already mostly true. Three numbers explain the mornings that feel bad:

SymptomNumber
PRs ever held by the auto-merge guard512 of 1,607 (32%)
Top hold reasonsdangerous-diff path 179 · 🟡 changes suggested 132 · changes-requested standing 50
PRs needing more than 3 review rounds33.5%
PRs over 600 lines613 (38%), median 4 review rounds
Nights with a ≥3-hour dead stretch, last 147
Finished-subagent notifications unanswered for 5+ minutes22,581 of 66,931 (34%)

Read together: a third of PRs get held, a third need four or more rounds, and half the nights the fleet stops before those are cleared. Whatever is unfinished at the dead stretch is what Fede finds at 7 am. Seven open PRs this morning was a normal night, not a bad one.

2. Why last night specifically

Timeline (Denver time):

Root cause A, mechanical. Each session is woken by a small waiter process that watches the GitHub event file. Waiters did not die when their turn ended. They lived up to 24 hours holding the session's "I already have a waiter" lock, so the next real waiter could not arm, and the stale one consumed each verdict and woke nobody. Found on the machine: 11 waiters whose Claude process had exited days earlier, some since September 10; the machine-wide duty lock held by a waiter from a turn that ended at 8:57 pm. Fixed today in the waiter script: a waiter exits within five minutes of its session ending, and a lock held by an orphan is taken over.

Root cause B, behavioral. Seven of the last fourteen nights have a three-hour-or-longer dead stretch, always after midnight. In 30 days, one in three "subagent finished" notifications (22,581 of 66,931) went unanswered for more than five minutes. The 25 longest silences were sessions that wrote a done-or-parked summary, or asked Fede a yes-or-hold question and stopped for a day. None were errors or limits.

Root cause C, structural. Thirteen distinct mechanisms can stop a green PR from merging without a person. Each is reasonable alone. Together they mean a PR needs a live session to clear it several times, and a sleeping session clears nothing.

3. The thirteen holds, and what to do with each

HoldKeep?Change
Changes-requested review standingkeepThe session that pushes the fix dismisses the stale review in the same turn. Never left for morning.
No verdict on current headkeepAutomatic. Nothing to do.
🟡 changes suggestedchangeNo longer holds. 🟡 = merge, then open one follow-up issue per finding. Only 🔴 blocking holds.
Stacked basekeepAutomatic.
Dangerous-diff pathkeep, narrowOnly auth, IAM, middleware, secrets, the guard itself. Admin routes under /api/admin behind admin auth are not dangerous.
Merge-evidence (green with zero tests run)keepThis is the one hold that catches real risk.
DraftkeepDrafts are not work in progress. A draft older than 24h is closed by its owner.
hold-for-review labelkeep, Fede-onlyUnchanged. Sessions never apply it.
Stale approval after pushkeepAutomatic.
Hand-armed auto-merge disarmed by eventchangeThe guard re-arms itself on a clean verdict; sessions must not treat "not armed" as a hold.
Red main freezekeepDriver rule already exists.
CI redkeepFix.
Review workflow self-modifykeepRare.

4. The rules that replace "end of night"

  1. A session that owns an open PR does not end its turn until the PR is armed for auto-merge or merged. Blocking waits happen inside one long command, not by ending the turn.
  2. A finished subagent is consumed by its parent within the same turn. A parent that has nothing to do with the result still says so and continues.
  3. A yes-or-hold question to Fede never stops the session. It posts the one-line ask and keeps working everything that does not depend on it.
  4. A sweep session wakes owners; it never takes over or splits a PR. A PR already under review merges as-is.
  5. Morning baseline: zero open fede-authored PRs older than 12 hours that are not armed. Anything else is a defect the owning session explains in one line.

5. Risk without flags: the three-switch system

Fede's constraint: ship aggressively, keep customers stable, no proliferation of forgotten flags.

Rule: there are exactly three places a behavior can be switched, and they are all product configuration, not engineering flags.

Switch kindWhere it livesWho flips itLifetime
Company live switch (claraLive)customer pageFedeforever; it is the go-live
Company setting (e.g. reminders opt-in, vendor calendar capture, lead source)customer page, settings cardops or the customerforever; it is a product feature
Property setting (e.g. per-property reminder recipient)property pageops or the customerforever

What is banned: environment flags for behavior (*_ENABLED), code-level release toggles, allowlists in code, "temporary" gates. Today there are 5 env flags and 6 org/property settings. The 5 env flags get a removal PR each or become a company setting.

How a risky change ships:

  1. It ships merged and deployed the same day, dark, meaning: off for every company by default because it is a company setting whose default is off.
  2. It is turned on at a test company (Fairhaven, Willows) by the session, with a proof on the tracker.
  3. Fede turns it on per customer from the customer page. That is the only "flag" anyone ever manages, and it is visible on the page the team already reads.

Hygiene without a flag platform:

6. Options for Fede

Decision: A, minus the settings registry.

  1. A. Adopt sections 3–5 as written (recommended). Dangerous-diff floor narrowed, 🟡 no longer holds, three-switch system, settings registry.
  2. B. Adopt 3–4 only; keep flags as they are. Fixes the overnight stalls, leaves the flag question for later.
  3. C. Keep holds as they are; only fix the waiter defect and the end-of-night rule. Least change, most mornings like today.

7. What was done today

PropFlow Docs