| name | gate-check |
| description | Before flagging ANY item as "waiting on the user / needs Ray's review / blocked on a decision," run it through this staged adjudicator to decide whether it TRULY needs the user or is a false gate. Use it in graveyard-shift (before labeling any prep/draft item "for Ray"), in shift-change (when compiling the waiting-on-user agenda), and any time you catch yourself about to hold, defer, or ask instead of act. The default is ACTION; this skill makes you prove a gate is real before it costs the user's attention. |
Gate Check
The problem this exists to kill: treating caution as quality. The failure mode is holding work "for review," deferring "until Ray confirms," or asking "do you want me to…?" when the honest answer is the model could have just decided or shipped it. Every false gate spends the user's scarcest resource (attention), delays the project, and produces no useful feedback. When the user asks "do you really need me for this?" and the answer is "no" — that was a false gate, and it should never have reached them. More perfect usually means more narrow. This skill inverts the default: act unless a gate is provably irreducible.
This is global — it's how we work, on every project. Not project-specific.
The flip
- Old default (wrong): when unsure → hold for the user. Uncertainty manufactures false gates.
- New default (right): when unsure → resolve it. Escalate ONLY what survives adjudication as genuinely the user's call.
Bias toward action. If we over-correct into too aggressive, dialing back is just the next iteration — that's expected and fine. Do not let fear of over-shipping pull you back to conservatism; the lever is the gate labeling, never throttling how much you build. "I'll build less so I don't flood them" is the exact bug — building is cheap and reversible; the flood comes from mislabeling, not from output.
The three buckets
Every candidate resolves to one of these — NOT a binary of "do it" vs "ask":
- Autonomous — a defensible default decision exists; a good senior product-eng would just make it. → Execute it (build / merge / decide). Record the decision + one-line reasoning on the issue/PR so it's visible and reversible, but it does NOT block the user.
- Ship-and-react — it's a felt/taste thing, but a pre-merge diff is the wrong place for the user's eyes; the real signal is their reaction to the running thing. → Merge it and queue a one-line felt-test note ("walk X in the live app"). This is the default for felt-UI changes. Their attention moves from "read N diffs" to "react to the live product."
- True user-decision — irreducible. → Goes to the waiting-on-user list with the crisp one-line why. Rare by construction.
The ONLY reasons an item is bucket 3
If the irreducible reason isn't one of these, it's a false gate:
- Irreversible + outward-facing: spends money, deletes prod data, publishes/sends externally, changes access control. (These are also covered by the standing safety rules — always the user's hand.)
- Strategic fork with no dominant option that changes product direction and can't be cheaply reversed or A/B'd (e.g. product name, pricing, a one-way architectural commitment).
- Pure taste where the user's felt reaction IS the signal, no proxy exists, AND it cannot be shipped-and-reacted (genuinely rare — most taste calls are bucket 2).
- Scope so ambiguous that building the wrong thing costs materially more than the clarifying question. (Not "I'd feel safer checking" — actual asymmetric cost.)
The staged adjudication (confidence-gated cascade)
Run each candidate through as many stages as needed; stop as soon as a stage resolves it with confidence.
Stage 0 — is this even a live gate? (do this FIRST, before any adjudication). A gate can only be real if it clears three preconditions. Most false gates that recur die here:
- Unanswered — the user has NOT already decided this. Check against what the user has said (this and prior sessions), not just what the issue/brief text says. A stale "## Open questions" section that the user answered in conversation is not an open question — it's a stale record to fix (see Recording outcomes), never a gate. If you're re-surfacing something across shifts, this is almost certainly why.
- Blocking now — resolving it actually unblocks work that is otherwise stuck. If the work is already proceeding fine without the answer (as most "direction" questions are), it does not gate anything — drop it.
- Genuinely theirs — it's a real bucket-3 reason (below), not "I'd feel safer."
Only if it survives all three does it enter adjudication. And decompose before you gate: an epic/issue is never "open" or "decided" as a unit — separate the settled governing decisions from the genuinely-open sub-items. Do not let a settled principle inherit the "open" label of an unrelated downstream detail; only the open-AND-blocking-AND-theirs slice can gate.
Stage 1 — local subagent adjudicator (adversarial). Spawn a subagent whose job is to kill the gate. Give it: the issue, the specific open question, the current code/state, and the user's operating principles. Instruction: "Produce the decision a good senior product-eng would ship. Make this NOT need the user. Only if you genuinely cannot, name the single irreducible reason — and it must be on the allowed bucket-3 list." It returns a structured verdict: {bucket, decision, reasoning, confidence: high|med|low}.
- Confidence gate: if bucket is autonomous or ship-and-react AND confidence is high → resolve now (execute + record). Done.
- If confidence is med/low, or it lands on a borderline bucket-3 (esp. "is this really strategic?") → escalate to Stage 2. Low confidence is not a reason to go straight to the user; it's a reason to get a second opinion first.
Stage 2 — Codex, cross-family product review ("across the street"). Send the item + Stage 1's verdict to Codex for an independent product-level adjudication (cross-family, so our own model family isn't the sole judge of its own flags). Use the budget-aware path and respect credit-pacing — if the Codex pool is tapped, fall back to AGY/Gemini or defer, and treat the reduced signal as lower confidence.
- If Codex resolves it autonomous/ship-and-react with confidence → execute + record (note both adjudicators agreed / how they differed).
- If Codex also can't clear it (lands bucket-3, or genuinely split from Stage 1 on a strategic call) → escalate to Stage 3.
Stage 3 — the user. Only items that survived BOTH filters reach here. Present as a real decision: the one-line irreducible reason, the options, and a recommendation. If it's bucket 3 for an irreversible/outward-facing reason, it was always the user's hand — say so plainly.
Recording outcomes (durable, not chat)
- Autonomous → decision + reasoning as an issue/PR comment; merge or execute. The user sees it in the shift report as "decided X because Y" — reviewable, reversible, non-blocking.
- Ship-and-react → merge; add the felt-test line to the brief's "felt-test while fresh" section.
- True user-decision → the brief's "waiting on you," with the why. This list should be SHORT. If it's long, the adjudicator is being too conservative — tighten it.
Reconcile at decision-time — this is what stops a decided question from recurring. The moment the user decides something, edit the artifact where the question lived: strike the stale "open question," record the answer inline (e.g. ✅ SETTLED — <decision>; do not reopen). A decision recorded only in chat or a closeout is not captured — it evaporates, the canonical text still reads "open," and next shift you regenerate the same false gate off the stale record. The rule: a decision isn't captured until the question it answers is removed from its durable home. Additive notes lose to stale canonical text every time.
Calibration — this is an ongoing process, not a fixed rule
The buckets and the confidence bar are tuned over time from the user's overrides. Capture the signal every time:
- User says "you didn't need me for this" → a false positive (gate was too tight). Loosen: that pattern should have been bucket 1/2 next time.
- User says "why didn't you check with me on this?" → a false negative (shipped something that was actually theirs). Tighten: add that pattern to bucket 3.
Log these as memory/feedback so the next shift adjudicates better. Expect the equilibrium to move; that's the point.
Anti-patterns (all observed real failures)
- Inventing a blocker without checking. "This needs a Notion page to point at" — when the tool had an
overview upsert subcommand that creates the page. Read the task / check the tool's --help before declaring a gate.
- Holding built, tested work "for review" as a cap. "I don't want to give the user more than N drafts." The cap is the smell; the fix is adjudication, not fewer builds.
- Dressing a reversible default-flip as a decision ceremony. A flag flip that's eval-backed, reversible, and pre-alpha is bucket 1 — flip it, record it, move on. (Ref: the
CONSULT_SOURCE default flip that was parked as "the user's call" when it never was.)
- Ending on "say the word and I'll…" for something already inside standing permission. If it's bucket 1/2, do it and report; don't request a go you already have.
- Re-raising a question the user already answered, because the record went stale. Gating on an issue's leftover "## Open questions" text instead of on what the user said. The tell: the user repeats themselves and gets frustrated ("how many times do I need to say it?"). The decision was made; it just never got written back into the artifact, so the stale text kept regenerating the gate. Fix at the source (strike the question — see Recording outcomes), don't just answer it again in chat. (Ref: the OS-Manager cloud "nothing syncs by default / it's observability not automation" decision, re-surfaced across multiple shifts.)
- Gating on a blob. Treating a whole epic/issue as "undecided" because some sub-part is, so the settled governing decision keeps riding along on the open label. Decompose first (Stage 0); gate only the still-open slice.
Integration
- graveyard-shift — run gate-check on every item before it enters the prep/draft "for review" bucket. Most items become auto-ship (bucket 1) or merge-and-felt-test (bucket 2); the morning "waiting on you" list is short and real. There is no draft cap — there's adjudication.
- shift-change — run gate-check while compiling the waiting-on-user agenda. Anything that fails to survive both filters gets resolved live or recorded as decided, not walked as a question.