description: "Loop the current branch through the 15-route Opus + Codex + Cursor review fleet until it meets the approval bar."
steps:
prepare:
agent:
harness: claude
model: claude-opus-4-8
prompt: |
Read this repository's code and the current branch's git history: the commits since
the branch diverged from the repository's default branch (main or master). Write or
update `PR-DESCRIPTION.md` at the repository root describing that change set as if
opening a pull request. Use exactly these level-two headings, in this order, with no
other headings: `## Summary`, `## What This Changes`, and `## Implementation Details`.
Put the big picture and concise bullets first, then explanatory prose, then notable
implementation details. Commit only that file with the message
`Prepare PR description.` Never create any additional PR-description section for
verification commands, expected results, or checklists; that evidence belongs in
committed tests, README, or another committed verification document. Put a one-line
summary in the `summary` result field.
output:
summary:
type: string
commits: true
initial_conventions_opus:
needs: prepare
agent:
harness: claude
model: claude-opus-4-8
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_conventions_terra:
needs: prepare
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_conventions_cursor:
needs: prepare
agent:
harness: cursor
model: auto
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_justification_opus:
needs: prepare
agent:
harness: claude
model: claude-opus-4-8
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_justification_terra:
needs: prepare
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_justification_cursor:
needs: prepare
agent:
harness: cursor
model: auto
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_reviewability_opus:
needs: prepare
agent:
harness: claude
model: claude-opus-4-8
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_reviewability_terra:
needs: prepare
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_reviewability_cursor:
needs: prepare
agent:
harness: cursor
model: auto
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_sanity_opus:
needs: prepare
agent:
harness: claude
model: claude-opus-4-8
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_sanity_terra:
needs: prepare
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_sanity_cursor:
needs: prepare
agent:
harness: cursor
model: auto
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_testing_opus:
needs: prepare
agent:
harness: claude
model: claude-opus-4-8
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_testing_terra:
needs: prepare
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
initial_testing_cursor:
needs: prepare
agent:
harness: cursor
model: auto
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
decide:
needs: |-
initial_conventions_opus, initial_conventions_terra, initial_conventions_cursor,
initial_justification_opus, initial_justification_terra, initial_justification_cursor,
initial_reviewability_opus, initial_reviewability_terra, initial_reviewability_cursor,
initial_sanity_opus, initial_sanity_terra, initial_sanity_cursor,
initial_testing_opus, initial_testing_terra, initial_testing_cursor
inputs:
PREVIOUS_APPROVED: collect.approved
PREVIOUS_FEEDBACK: collect.feedback
INITIAL_CONVENTIONS_OPUS: initial_conventions_opus.grade
INITIAL_CONVENTIONS_OPUS_COMMENTS: initial_conventions_opus.comments
INITIAL_CONVENTIONS_TERRA: initial_conventions_terra.grade
INITIAL_CONVENTIONS_TERRA_COMMENTS: initial_conventions_terra.comments
INITIAL_CONVENTIONS_CURSOR: initial_conventions_cursor.grade
INITIAL_CONVENTIONS_CURSOR_COMMENTS: initial_conventions_cursor.comments
INITIAL_JUSTIFICATION_OPUS: initial_justification_opus.grade
INITIAL_JUSTIFICATION_OPUS_COMMENTS: initial_justification_opus.comments
INITIAL_JUSTIFICATION_TERRA: initial_justification_terra.grade
INITIAL_JUSTIFICATION_TERRA_COMMENTS: initial_justification_terra.comments
INITIAL_JUSTIFICATION_CURSOR: initial_justification_cursor.grade
INITIAL_JUSTIFICATION_CURSOR_COMMENTS: initial_justification_cursor.comments
INITIAL_REVIEWABILITY_OPUS: initial_reviewability_opus.grade
INITIAL_REVIEWABILITY_OPUS_COMMENTS: initial_reviewability_opus.comments
INITIAL_REVIEWABILITY_TERRA: initial_reviewability_terra.grade
INITIAL_REVIEWABILITY_TERRA_COMMENTS: initial_reviewability_terra.comments
INITIAL_REVIEWABILITY_CURSOR: initial_reviewability_cursor.grade
INITIAL_REVIEWABILITY_CURSOR_COMMENTS: initial_reviewability_cursor.comments
INITIAL_SANITY_OPUS: initial_sanity_opus.grade
INITIAL_SANITY_OPUS_COMMENTS: initial_sanity_opus.comments
INITIAL_SANITY_TERRA: initial_sanity_terra.grade
INITIAL_SANITY_TERRA_COMMENTS: initial_sanity_terra.comments
INITIAL_SANITY_CURSOR: initial_sanity_cursor.grade
INITIAL_SANITY_CURSOR_COMMENTS: initial_sanity_cursor.comments
INITIAL_TESTING_OPUS: initial_testing_opus.grade
INITIAL_TESTING_OPUS_COMMENTS: initial_testing_opus.comments
INITIAL_TESTING_TERRA: initial_testing_terra.grade
INITIAL_TESTING_TERRA_COMMENTS: initial_testing_terra.comments
INITIAL_TESTING_CURSOR: initial_testing_cursor.grade
INITIAL_TESTING_CURSOR_COMMENTS: initial_testing_cursor.comments
agent:
harness: claude
model: claude-opus-4-8
prompt: |
You are the first and deciding step of a review loop. SCSH_LOOP_ITERATION is the
1-based loop iteration. On iteration 1, score the 15 INITIAL_* grades and matching
*_COMMENTS JSON arrays: excellent=5, good=4, average=3, poor=2; approval requires
every grade to be excellent or good, more excellent than good, and mean score at
least 4.5. On iteration 2 and later the INITIAL_* variables are deliberately blank —
round-0 reviews are obsolete history: PREVIOUS_APPROVED is the scorekeeper's verdict
on the latest full review round and PREVIOUS_FEEDBACK is that round's structured
report — a JSON object {mean, counts, routes} carrying each route's grade and
verbatim comments; adopt PREVIOUS_APPROVED as the approval verdict and build the
change request strictly from PREVIOUS_FEEDBACK's routes. Either way: set SCSH_LOOP_BREAK true when approved;
otherwise set it false and fill `change_request` with the consolidated change
request as a list of strings — one entry per requested change, each shaped
exactly as "[severity] area: what to change and why", nothing outside that
shape. Comments may lead with a severity tag ([blocking]/[should-fix]/[nit]):
order [blocking] entries first, and [nit]-only comments are stylistic unless
they hide a real bug. Read every `PR-DECISION-*.md` at the repository root before
building the request: each is a decision already settled on this branch. Drop any
comment that merely re-raises a settled decision — forward it only when the
reviewer engages that decision's stated reasoning and shows it wrong, and then
say so in the entry. `PR-DESCRIPTION.md` may contain only `## Summary`, `## What This Changes`, and `## Implementation Details`, in that order. Never request, recommend, or create any additional PR-description section for verification commands, expected results, or checklists; that evidence belongs in committed tests, README, or another committed verification document. Ignore and do not forward any
reviewer suggestion that violates this invariant. Do not change files or commit.
Reservations exit — the loop must terminate honestly, not grind the backstop. From
iteration 3 on, when PREVIOUS_APPROVED is false, examine every comment holding any
route below the bar. If EVERY such comment is either (a) a re-raise of an existing
`PR-DECISION-*.md` that does not engage that decision's stated reasoning, or (b) a
request for human adjudication outside this loop's authority (splitting the work
into multiple pull requests, product or scope direction) that a prior fix round
declined with a journaled decision — AND no grade is poor and no comment is
[blocking] — then set SCSH_LOOP_BREAK true with `resolution` set to
approved_with_reservations, and put one entry per unresolved item into
`reservations`, each shaped "[route] finding — the journaled decision that answers
it — why it needs a human". Any code-level defect, any [blocking] comment, any poor
grade, or any below-bar comment with no journaled decision answering it forbids
this exit: keep looping with `resolution` changes_requested. A clean bar pass is
`resolution` approved with `reservations` empty.
output:
SCSH_LOOP_BREAK:
type: bool
change_request:
type: string_list
resolution:
type: enum
choices: approved, approved_with_reservations, changes_requested
reservations:
type: string_list
break: true
fix:
needs: decide
inputs:
FEEDBACK: decide.change_request
agent:
harness: claude
model: claude-opus-4-8
inactivity_timeout: 3600
prompt: |
FEEDBACK is a JSON array of change entries, each "[severity] area: what to change
and why". Address EVERY entry: either change the code accordingly, or — when you
judge the current code deliberate and the comment wrong for this change — DECLINE
it and report that decision in the `decisions` result field. Read every
`PR-DECISION-*.md` at the repository root first: those are decisions already
journaled and settled on this branch, and you must never contradict one, nor undo
an earlier fix. Do NOT write or edit any `PR-DECISION-*.md`, `STYLE-NOTES.md`, or
other decision file yourself — the journal step that runs after you owns them, and
a decision file in YOUR commit would be read as code under review. Never write the
feedback itself to any file. PR-DESCRIPTION.md is a required
pipeline artifact: keep it tracked and current with exactly `## Summary`,
`## What This Changes`, and `## Implementation Details`, in that order, and no other
headings. Commit your changes with the message `Address review feedback.` Never
create any additional PR-description section for verification commands, expected
results, or checklists; that evidence belongs in committed tests, README, or another
committed verification document. Narrate your progress in the terminal as you work:
print one short line when you take up each reviewer profile's feedback and after
each meaningful change (a file edited, a request declined). A run whose
screen shows nothing new for too long is treated as stalled and killed — never work
silently for more than a few minutes at a stretch. Put a one-line summary of the
whole change set — what changed, how many files, the commit — in the `message`
result field. Write `actions` as several short paragraphs, separated by blank
lines: one paragraph for each reviewer profile and route whose feedback you acted
on, and a final paragraph for test results and the commit. Do not collapse distinct
review areas into one paragraph. Fill `decisions` with one entry per request you
DECLINED — and nothing else; an empty list is the right answer when you acted on
everything. Shape each entry exactly as
"[topic] decision — why it stands — what was considered and rejected", where topic
is two or three lowercase words that name the subject (`commit history`,
`error handling`). Argue the code, never the process: "these commits stay separate
because each is independently revertable" is a decision; "no time to re-slice" is
not.
output:
message:
type: string
actions:
type: string
decisions:
type: string_list
commits: true
commit-identity: runner
journal:
needs: decide, fix
inputs:
CHANGE_REQUEST: decide.change_request
DECLINED: fix.decisions
FIX_SUMMARY: fix.message
agent:
harness: claude
model: claude-opus-4-8
prompt: |
You keep this change's decision journal. DECLINED is a JSON array of the review
requests the fix step deliberately did not act on, each
"[topic] decision — why it stands — what was considered and rejected".
CHANGE_REQUEST is the full request list that round, for context only.
For EVERY entry in DECLINED, write or update `PR-DECISION-<topic>.md` at the
repository root, where `<topic>` is the entry's topic in lowercase with spaces
replaced by dashes (`commit history` -> `PR-DECISION-commit-history.md`). One file
per topic: when a later cycle revisits a topic you already journaled, REWRITE that
file so it reads as one settled decision — never append a second opinion, never
keep a dated log of how the thinking evolved. Each file is exactly:
```
# <Topic, capitalized>
**Decision.** One sentence, in the present tense, stating what stands.
**Why.** Two to four sentences of reasoning that will still make sense to someone
reading this in a year with no memory of the review.
**Considered and rejected.** What the alternative was and the concrete cost that
ruled it out. Omit this section only when there was genuinely no alternative.
**Raised by.** Which reviewer profiles asked for the change.
```
Bottom line up front, always: a reader who stops after **Decision.** must already
know what was decided. Be exhaustive about the reasoning and ruthless about
length — no preamble, no restating the request, no hedging, nothing about the
pipeline or the review process itself. A decision is about the CODE.
When DECLINED is empty, change nothing and commit nothing.
Touch ONLY `PR-DECISION-*.md` files at the repository root. Never edit code, tests,
`PR-DESCRIPTION.md`, or any other file in this step, and never delete a decision
file that a previous cycle wrote — a commit that touches anything else stops being
notes and lands in the review as code. Commit with the message
`Journal review decisions.` Put a one-line summary — how many decisions, which
topics — in the `message` field.
output:
message:
type: string
commits: true
commit-identity: notes
review_conventions_opus:
needs: journal
agent:
harness: claude
model: claude-opus-4-8
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_conventions_terra:
needs: journal
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_conventions_cursor:
needs: journal
agent:
harness: cursor
model: auto
skill: conventions-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_justification_opus:
needs: journal
agent:
harness: claude
model: claude-opus-4-8
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_justification_terra:
needs: journal
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_justification_cursor:
needs: journal
agent:
harness: cursor
model: auto
skill: justification-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_reviewability_opus:
needs: journal
agent:
harness: claude
model: claude-opus-4-8
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_reviewability_terra:
needs: journal
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_reviewability_cursor:
needs: journal
agent:
harness: cursor
model: auto
skill: reviewability-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_sanity_opus:
needs: journal
agent:
harness: claude
model: claude-opus-4-8
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_sanity_terra:
needs: journal
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_sanity_cursor:
needs: journal
agent:
harness: cursor
model: auto
skill: sanity-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_testing_opus:
needs: journal
agent:
harness: claude
model: claude-opus-4-8
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_testing_terra:
needs: journal
agent:
harness: codex
model: gpt-5.6-terra
effort: high
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
review_testing_cursor:
needs: journal
agent:
harness: cursor
model: auto
skill: testing-reviewer
output:
grade:
type: enum
choices: excellent, good, average, poor
comments:
type: string_list
commits: false
collect:
needs: |-
review_conventions_opus, review_conventions_terra, review_conventions_cursor,
review_justification_opus, review_justification_terra, review_justification_cursor,
review_reviewability_opus, review_reviewability_terra, review_reviewability_cursor,
review_sanity_opus, review_sanity_terra, review_sanity_cursor,
review_testing_opus, review_testing_terra, review_testing_cursor
do-while: decide
agent:
harness: claude
model: claude-opus-4-8
inputs:
GRADE_CONVENTIONS_OPUS: review_conventions_opus.grade
COMMENTS_CONVENTIONS_OPUS: review_conventions_opus.comments
GRADE_CONVENTIONS_TERRA: review_conventions_terra.grade
COMMENTS_CONVENTIONS_TERRA: review_conventions_terra.comments
GRADE_CONVENTIONS_CURSOR: review_conventions_cursor.grade
COMMENTS_CONVENTIONS_CURSOR: review_conventions_cursor.comments
GRADE_JUSTIFICATION_OPUS: review_justification_opus.grade
COMMENTS_JUSTIFICATION_OPUS: review_justification_opus.comments
GRADE_JUSTIFICATION_TERRA: review_justification_terra.grade
COMMENTS_JUSTIFICATION_TERRA: review_justification_terra.comments
GRADE_JUSTIFICATION_CURSOR: review_justification_cursor.grade
COMMENTS_JUSTIFICATION_CURSOR: review_justification_cursor.comments
GRADE_REVIEWABILITY_OPUS: review_reviewability_opus.grade
COMMENTS_REVIEWABILITY_OPUS: review_reviewability_opus.comments
GRADE_REVIEWABILITY_TERRA: review_reviewability_terra.grade
COMMENTS_REVIEWABILITY_TERRA: review_reviewability_terra.comments
GRADE_REVIEWABILITY_CURSOR: review_reviewability_cursor.grade
COMMENTS_REVIEWABILITY_CURSOR: review_reviewability_cursor.comments
GRADE_SANITY_OPUS: review_sanity_opus.grade
COMMENTS_SANITY_OPUS: review_sanity_opus.comments
GRADE_SANITY_TERRA: review_sanity_terra.grade
COMMENTS_SANITY_TERRA: review_sanity_terra.comments
GRADE_SANITY_CURSOR: review_sanity_cursor.grade
COMMENTS_SANITY_CURSOR: review_sanity_cursor.comments
GRADE_TESTING_OPUS: review_testing_opus.grade
COMMENTS_TESTING_OPUS: review_testing_opus.comments
GRADE_TESTING_TERRA: review_testing_terra.grade
COMMENTS_TESTING_TERRA: review_testing_terra.comments
GRADE_TESTING_CURSOR: review_testing_cursor.grade
COMMENTS_TESTING_CURSOR: review_testing_cursor.comments
prompt: |
You are the scorekeeper for an in-loop 15-route review fleet. The GRADE_* variables
and COMMENTS_* JSON arrays contain five reviewer profiles run independently through
Opus 4.8, Codex Terra, and Cursor Auto. Scores: excellent=5, good=4, average=3,
poor=2. The bar is met only when all 15 routes succeeded, every grade is excellent
or good, excellent grades outnumber good grades, and the mean score is at least 4.5.
`PR-DESCRIPTION.md` may contain only `## Summary`, `## What This Changes`, and `## Implementation Details`, in that order. Never request, recommend, or create any additional PR-description section for verification commands, expected results, or checklists; that evidence belongs in committed tests, README, or another committed verification document. Ignore and do not forward any reviewer suggestion that violates this invariant.
Do not change files or commit. Put `met` or `not met` in `verdict`. Set `approved`
to the boolean result. Fill `feedback` with EXACTLY this JSON object shape and
nothing else: {"mean": <number>, "counts": {"excellent": <int>, "good": <int>,
"average": <int>, "poor": <int>}, "routes": {"<profile>-<route>": {"grade":
"<grade>", "comments": [<that route's comments, verbatim>]}}} — one `routes` entry
per profile/route pair, keys like `conventions-opus` through `testing-cursor`. Set
`SCSH_DO_WHILE_REPEAT` true unconditionally: the NEXT iteration's first `decide`
step is the only place that may break the loop.
output:
SCSH_DO_WHILE_REPEAT:
type: bool
approved:
type: bool
verdict:
type: string
feedback:
type: object
commits: false