cto-review

Reviews code changes like a chief technology officer would, checking quality and readiness to release.

Installation
Run `npx skills add "https://github.com/fellowship-dev/dogfooded-skills" --skill "cto-review"` to install this skill, then follow its SKILL.md instructions for my next request.

Paste this into Claude Code, Cursor, or any agent that can run commands.

SKILL.mdShow the author's original SKILL.md
---
name: cto-review
description: Use when performing a CTO-level PR review — cohesive review, owner gate, CI and merge-authority checks, and a non-blocking visual evidence notice for UI PRs. No staging-evidence gate (staging is a release-train step, pylot#3389).
user-invocable: true
allowed-tools: Read, Bash, Glob, Grep, Task
---

## Purpose

Strategic CTO-level review of a single PR, partitioned into isolated stages so the critical
judgement (the whole-diff review) runs in a clean context window. Stage 01 gathers PR metadata,
the full diff, repo context, and merge state. Stage 02 reviews the WHOLE diff cohesively across
all dimensions (docs gaps, external deps, downstream/template impact, correctness, security, merge
strategy, action items) in isolated context. Stage 03 runs inline: posts the GH review comment,
applies the verdict label, merges-or-labels honoring merge state, writes the report file, and
emits the outcome marker.

This proc is **PR review ONLY**. There is no heartbeat mode.

## Arguments

| Param | Required | Default | Notes |
|-------|----------|---------|-------|
| `PR_NUMBER` | yes | — | PR number to review |
| `org/repo` | yes | — | Target repository, e.g. `fellowship-dev/booster-pack` |

Parse positionally from `$ARGUMENTS`: first token = PR number, second token = `org/repo`.
Example: `/cto-review 742 fellowship-dev/booster-pack`.

## What it does

3-stage ICM procedure (sequential):

| Stage | Mode | Description |
|-------|------|-------------|
| 01-setup | subagent | Fetch repo context, PR metadata, full diff, merge state, **all PR comments + label snapshot** (#2918), **resolve the pipeline lane** (#2996, step 5.3), and resolve merge authority from the DB-authoritative team `deploy.release_mode`. Only explicit `ship` permits automated merge; every other state is label-only. Short-circuit only if CLOSED-not-merged. There is no staging-evidence gate (pylot#3389). Visual evidence (5.6) is a **notice, not a short-circuit**: it searches the PR body first, then comments (newest-first), and accepts `N/A` within 3 lines of its heading as the waiver. |
| 02-review | subagent | **Judgement layer first** (#2918): read all labels + all comments, identify and classify every blocker (resolved/unresolved). Then ONE cohesive review of the whole diff across all dimensions → verdict + checklist + action items + **receipts block**. Review depth is identical in both lanes. |
| 03-synthesize-act | inline | Post GH comment (always includes `## Checked / Found` receipts), apply label. **Step 3.0: owner gate** (#2918, #3240) — human `waiting-on-owner` present (fresh label read) OR stage 02's `owner_authority_class != none`: post park comment (one decision line + named answerer), apply `waiting-on-owner`, emit `status=blocked`, STOP. `security` is never a trigger. **Step 3.1: lane merge bar** (#2996) — from the same fresh read: `lane:fast` requires `reviewed` only; everything else requires `reviewed` + `double-checked`. Otherwise: merge-or-label honoring merge state, write report file, emit outcome marker. |

Stage 02 is the isolated critical-judgement step — it receives only the setup handoff and its own
CONTEXT.md, never orchestrator history.

## Handoff locations

All handoffs live in the repo working directory:
```
.procedure-output/cto-review/{stage}/handoff.md
```

Stage 01 writes setup. Stage 02 reads only the setup handoff. Stage 03 reads both.

## Execution

### Stage 01 (subagent)

Spawn one Task. Pass only the arguments (PR number, org/repo) and the stage CONTEXT.md path.

Task prompt template:
```
You are running stage 01-setup of the cto-review procedure.

Arguments:
  PR_NUMBER = {PR}
  REPO = {org/repo}

Read your stage instructions:
  skills/cto-review/stages/01-setup/CONTEXT.md

Write your output to:
  .procedure-output/cto-review/01-setup/handoff.md

Execute all steps in CONTEXT.md. Write handoff.md before exiting.
```

After stage 01 completes, read `.procedure-output/cto-review/01-setup/handoff.md` and check
`short_circuit`:

- If `short_circuit: closed-no-merge` → skip stage 02, go straight to stage 03 (which posts
  nothing and emits the blocked/closed outcome).
- Otherwise → continue to stage 02.

Missing visual evidence is **not** a short_circuit and never appears here. It is carried in the
handoff as `## Visual Evidence → notice: yes` and surfaced by stage 03 as an advisory line
appended to the review comment. It does not gate the merge bar, does not apply `needs-work`, and
does not suppress any stage. See stage 01 CONTEXT.md, "Why this is a notice, not a gate".

### Stage 02 (subagent)

Spawn one Task. Pass only the stage 01 handoff path and the stage CONTEXT.md path. Do NOT pass
orchestrator history or any prior reasoning — the review must run in clean isolated context.

Task prompt template:
```
You are running stage 02-review of the cto-review procedure.

Read your stage instructions:
  skills/cto-review/stages/02-review/CONTEXT.md

Your inputs:
  .procedure-output/cto-review/01-setup/handoff.md

Write your output to:
  .procedure-output/cto-review/02-review/handoff.md

Review the WHOLE diff cohesively across all dimensions. Write handoff.md before exiting.
```

Await stage 02 before proceeding to stage 03.

### Stage 03 (inline)

Run stage 03 yourself (orchestrator context). Read CONTEXT.md:
```
skills/cto-review/stages/03-synthesize-act/CONTEXT.md
```
Post the comment, apply the label, merge-or-label, write the report file, and emit the
`[pylot] outcome=...` marker from the orchestrator (not from a subagent).

## Stage handoff chain

```
01-setup ──► 02-review ──► 03-synthesize-act (inline, reads 01 + 02)
   │   (labels+comments│    (judgement layer: labels/comments/blockers → receipts)
   │   +lane captured) │         │
   │                   ▼         ▼
   │                        Step 3.0: Owner Gate (human label fresh + stage-02 class) — LANE-INDEPENDENT
   │                              │
   │                              ├── waiting-on-owner OR owner_authority_class≠none ──► park + status=blocked
   │                              └── clear ──► Step 3.1: lane merge bar
   │                                              ├── lane:fast ──► require `reviewed`
   │                                              └── else      ──► require `reviewed` + `double-checked`
   │
   └── short_circuit: closed-no-merge ──────────────────────► 03 (no-op)

   (visual evidence: notice only — flows through 02/03 as an advisory line, never blocks)
```

## Exit paths

- **Success**: stage 03 emits `[pylot:$PYLOT_OUTCOME_NONCE] outcome="cto-review PR #{N} complete — verdict={verdict}, action={merged|labeled}" status=success`
- **Failure**: failing stage emits `[pylot:$PYLOT_OUTCOME_NONCE] outcome="cto-review failed at stage NN: {reason}" status=failed`
- **Blocked (closed)**: `[pylot:$PYLOT_OUTCOME_NONCE] outcome="cto-review skipped: PR #{N} closed without merge" status=blocked`
- **Blocked (owner gate)**: `[pylot:$PYLOT_OUTCOME_NONCE] outcome="cto-review parked: PR #{N} — owner decision required" status=blocked` (#2918, #3240 — fires when a human has applied `waiting-on-owner` OR stage 02's owner-authority classifier matched one of five closed classes; `security` is never a trigger; park comment + `waiting-on-owner` label applied)

## Hard Rules

1. **Sequential only** — one subagent at a time, never parallel Task launches.
2. **Stage 02 is the isolated judgement step** — it receives ONLY the setup handoff + its CONTEXT.md.
3. **Never pass full orchestrator context** into subagent Task prompts — inputs only.
4. **The whole diff is reviewed in ONE cohesive stage** — never split per-file or per-dimension.
5. **Stage 03 runs inline** — GH side effects and the `[pylot] outcome=...` marker MUST come from the orchestrator.
6. **Each stage writes handoff.md before the next stage reads it.**
7. **Do not skip stages** — every stage executes, except stage 02 is skipped only on the CLOSED-no-merge short-circuit.
8. **Honor merge state** — never merge a CLOSED PR; for an already-merged PR, post the review as a post-merge note and never attempt merge.
9. **Never merge on a CI block** — Stage 01 classifies CI once as `pass`, `block`, or
   `na-no-configured-checks`. Only pass or N/A may satisfy the CI prerequisite; N/A still requires
   the normal review, lane, owner-gate, and merge-authority requirements.
10. **No Quest** — reporting is the local report file only.
11. **No evidence check short-circuits.** There is no staging-evidence gate (rule 16).
    **Visual evidence (step 5.6) is a notice, never a blocker** — it is
    recorded in the handoff, and appended by stage 03 as an advisory line. It never short-circuits,
    never applies a label, and never gates the merge bar. Its notice MUST still name the self-serve
    path; a bare "add screenshots" message is the defect it exists to fix.
12. **Scope by the earlier reviews' comments, don't assume** — setup captures all PR comments;
    the review trusts what the review-pr/double-check comments cover, spot-checks what they
    don't, and treats their still-open findings as verdict inputs. No earlier review found →
    assume nothing was covered and review at full depth.
13. **Owner gate is unconditional (#2918, #3240)** — stage 03 step 3.0 fires on either of two
    independent triggers: a human-applied `waiting-on-owner` (fresh GitHub label read), or stage
    02's `owner_authority_class != none` (a closed five-class taxonomy match, read verbatim, never
    re-judged in stage 03). `security` is never a trigger by itself — it is classification
    metadata only. Either trigger fires regardless of verdict, CI status, or any prose in the PR.
    LGTM verdict cannot override the gate. `waiting-on-owner` comes off only by human action. Two
    consecutive live bypasses (#2912, #2935) are why this rule exists; the model talked itself into
    merging both times, so the check is code, not prompt.
14. **Every verdict comment includes receipts (#2918)** — the `## Checked / Found` section (labels
    seen, comment count + last author, blockers → status) is mandatory in every comment stage 03
    posts. No silent LGTM without an enumeration of what was checked. On a fast-lane PR the
    receipts must also name the lane and the compensating controls (Step 3.1 list) — the whole
    point of the trade is that it is stated, not assumed.
15. **Lanes are LEGACY (owner ruling 2026-09-06)** — `lane:fast`/`lane:staging` labels no longer
    are informational only. The merge bar
    default is `reviewed double-checked`; the historical fast-lane exception (a `lane:fast` PR
    where double-check was deliberately never dispatched) still merges on `reviewed` alone —
    never `needs-work` such a PR for a missing `double-checked`. No new lane labels are emitted.
16. **No staging-evidence requirement (pylot#3389)** — cto-review never asks for, checks, or
    blocks on staging evidence, on any PR. Staging is a release-train step owned by the release
    process, and `scripts/ci-release-gate.sh` still runs the unscoped full corpus before anything
    reaches production. Never write "no staging evidence" as a blocker or a `needs-work` item.
17. **Merge authority is explicit and DB-authoritative** — stage 01 MUST use
    `resolve-merge-strategy.sh`, which reads live team configuration through the Pylot CLI. Only
    `deploy.release_mode=ship` grants automated merge authority. `propose`, missing configuration,
    lookup failure, malformed output, or an ambiguous repo-to-team mapping all resolve to
    `label-only`. Never read a legacy `crew.yml`, and never default to auto-merge.

## Reference files

- `CONTEXT.md` — architecture overview
- `shared/review-comment-format.md` — exact GH review-comment template (verbatim from the original skill)
- `shared/report-format.md` — local report-file template
- `stages/NN-name/CONTEXT.md` — per-stage inputs, task, output contract

Ships with 16 supporting files:

  • CONTEXT.md
  • resolve-merge-strategy.sh
  • shared/report-format.md
  • shared/review-comment-format.md
  • stages/01-setup/ci_gate.py
  • stages/01-setup/collect_ci_evidence.sh
  • stages/01-setup/CONTEXT.md
  • stages/01-setup/test_ci_gate.py
  • stages/01-setup/test_collect_ci_evidence.py
  • stages/01-setup/test_visual_gate.py
  • stages/02-review/CONTEXT.md
  • stages/03-synthesize-act/CONTEXT.md
  • test_resolve_merge_strategy.sh
  • tests/owner-gate-fixtures.json
  • tests/patch-id-merge-pin.test.sh
  • tests/test_owner_gate_contract.py

Mirrored from the author's public source. Install counts from the open skills registry.

The systems behind these skills get built for partners every week.

Partner with us