Review an open change thoroughly and against something outside the change itself: assess what work categories the diff contains, resolve each category''s review treatment from the review-knowledge memory shelf, review each through its layers (objective linters, then design-grounding from committed sources for design-bearing categories), consolidate findings that each cite their basis, and stop at one decision gate resolved per gate-config — the reviewer owns the approve/reject verdict when th...
Scanned 9/10/2026
Install to Claude Code
npx -y skills add kapilvirenahuja/garura --skill review-change --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Review Change?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/kapilvirenahuja-review-change)More formats (shields.io, HTML) on the badges page.
---
name: review-change
position: end
description: 'Review an open change thoroughly and against something outside the change itself: assess what work categories the diff contains, resolve each category''s review treatment from the review-knowledge memory shelf, review each through its layers (objective linters, then design-grounding from committed sources for design-bearing categories), consolidate findings that each cite their basis, and stop at one decision gate resolved per gate-config — the reviewer owns the approve/reject verdict when the gate is on; when off the computed recommendation is recorded and posted as a clearly marked harness verdict. The gate (third step) of the end sequence in the ProductOS command model. Use when a PR is ready to be reviewed and a verdict is needed.'
user-invocable: true
---
# review-change
Review an open change so the merge decision rests on something **outside** the change. Assess
the work categories the diff contains, resolve each category's treatment from the
review-knowledge memory shelf, review each through up to two layers (objective linters, then
design-grounding for design-bearing categories), consolidate findings that each cite a basis,
and stop at one decision gate resolved per gate-config: the reviewer owns the verdict when
the gate is on; when off, the computed recommendation becomes the decision, marked as a
harness verdict — either way it is posted to the PR.
**Pipeline position: end** (third step of the end sequence: commit-change →
propose-change → review-change → merge-change). The D2 pipeline-position rule injects this
sequence into any play declared `position: end`. Independent, invokable play; ordering is
enforced by pre-flight (an open PR must exist).
## Compiled From
This play was compiled from the review-change ICE (`reference/ice.md`) by play-editor
(#443 redesign; #467 Batch C gate ruling; #484 scripted chain; #496 grounding fan-out). Intent defines constraints (C1–C11) and failure
conditions (F1–F12); the expectation defines success scenarios (S1–S6), a Done means
(D1–D3, baked to `stop-condition.yaml`), and one recovery entry per failure condition.
To modify this play, update `reference/ice.md` and recompile with play-editor.
Do NOT edit this file manually — it is a compiled artifact.
## Role
You are the orchestrator. You own the workflow, the step order, and the one decision gate.
You delegate the agentic assessment and the design-grounding to `change-reviewer` and the
standards linter to `quality-auditor` — genuine judgment, via JSON contracts over files on
disk. The mechanical PR/host I/O (context bind, verdict post) runs in bundled scripts, not
an agent (C10, #484). You presume **no** work categories and **no** review
treatment: the categories are assessed every run, and each category's treatment is resolved
from the `knowledge/review/` shelf. You run only the layers and steps that apply to the
categories present. You never invent the verdict — you compute a *recommendation*; the gate
resolution (C8) decides who owns the decision: the human when the gate is on, the
recommendation itself (recorded as a harness verdict) when it is off.
**The guiding rule: the change under review is never its own standard.**
**Forbidden:** presuming or hardcoding a category list or a review treatment; grounding a
design principle in the branch's own new content; running a full-repo scan (reads outside the
diff are allowed *only* to reconstruct committed grounding, and are read-only);
auto-deciding the verdict while the gate resolves on; recording an off-gate decision that
differs from the computed recommendation, or posting any decision that does not name its
decider (harness vs human); leaving a verdict silent or unposted; reporting a finding with
no cited basis.
**Agent boundaries:**
| Agent | Domain | Skill/script it invokes | Phases | Role type |
|-------|--------|-------------------------|--------|-----------|
| `change-reviewer` | (Assessment) assess work categories from the diff; (Review) design-ground **one** design-bearing category from committed sources — dispatched once per design-bearing category as a concurrent read-only fan-out (C11) | reads `knowledge/review/` shelf; `git show <base>:<path>` | Assessment, Review | Domain |
| `quality-auditor` | Run the standards linter (`quality-check-scoped`) against the diff for the standards-driven categories | `quality-check-scoped` | Review | Domain |
The mechanical PR/host I/O has **no agent** (C10): `fetch_pr_context.py` binds the PR context
(Step 1) and `post_verdict.py` posts the decision + commits the run artifacts (Step 6), both
via `platform_adapter.py`.
Domain agents: 2 (`change-reviewer`, `quality-auditor`) — `change-reviewer` is dispatched
once for assessment and then **once per design-bearing category** for grounding, in one
concurrent batch (C11, `standards/rules/concurrent-fanout.md`). The verdict **recommendation**
is a deterministic script; the verdict **decision** follows the gate resolution — the human's
when the gate is on, the recommendation recorded as a harness verdict when it is off (C8).
## Pre-flight
| Check | Constraint | Action on Failure |
|-------|-----------|-------------------|
| Resolve working base + config (`.garura/core/config.yaml`) | — | Hard halt |
| An open PR exists for the branch | — | Hard halt |
| Platform CLI available (`gh`) | C8 | Hard halt |
| Resolve standards set + review-knowledge shelf path via `standards_order` / `ltm` | C2 | Hard halt |
| Fetch PR diff + `changed_paths` + base ref (the only files in scope) | C5 | Hard halt |
Resolve the deterministic pre-flight facts with the bundled resolver — config tokens,
`branch`, `issue`, `evidence_record`:
```
python3 scripts/preflight.py --play review-change \
--config .garura/core/config.yaml --branch "$(git branch --show-current)"
```
Right after the resolver, record the session identity stamp's start marker (#463 — soft-fail, never a halt):
```
python3 scripts/session_stamp.py --phase start \
--marker "{stm_base}{issue}/status/session-stamp-review-change.json" \
--cwd "$(pwd)" --branch "$(git branch --show-current)"
```
The open-PR check and `gh` availability are live host reads; the standards set, the
review-knowledge shelf path, and the PR diff/`changed_paths`/base ref are resolved by the
bundled `fetch_pr_context.py` (Step 1, via `platform_adapter.py`) — no agent (C10). Record
the resolved shelf path, the standards set, the PR's `changed_paths`, and the base ref;
everything downstream is bounded to those paths.
## Task DAG
Create ALL tasks immediately after resolving the working base — before any domain work.
The play owns this DAG; agents must not edit its top-level tasks.
```
[T1] Bind PR Context blockedBy: []
[T2] Assess Categories blockedBy: [T1]
[T3] Review Per Category (layers) blockedBy: [T2]
[T4] Consolidate + Recommend Verdict blockedBy: [T3]
[T5] Decision Gate (config-resolved) blockedBy: [T4]
[T6] Post Decision to PR blockedBy: [T5]
[T7] Scenario Validation blockedBy: [T6]
[T8] Close blockedBy: [T7]
```
Mark each task in-progress before its step and completed right after its eval passes. No
runtime reordering. On resume, skip completed and reset in-progress to pending.
## Workflow
### Phase: Assessment
**Step 1 — Bind PR Context** · Owner: play (script) · Depends on: pre-flight
Run the bundled `fetch_pr_context.py` — it fetches the PR diff/changed-paths/base-ref (via
`platform_adapter.py`) and binds `standards_order` + the resolved `knowledge/review/` shelf
path from config into `context.yaml`. No agent (C10). Standards *resolution per finding* is
owned downstream by `quality-check-scoped`; this step binds the diff, the changed paths, the
base ref, the standards_order, and the review-shelf path:
```
python3 scripts/fetch_pr_context.py --config .garura/core/config.yaml \
--out-context "<working>/context.yaml" --out-diff "<working>/pr.diff"
```
`context.yaml` records `standards_order`, the `review_shelf` path, `changed_paths`, and
`base`.
**Step 2 — Assess Categories** · Owner: `change-reviewer` · Depends on: Step 1
The agent reads the diff and derives the work categories actually present — judging each
changed file by its content, consulting the `knowledge/review/` shelf to recognise seeded
categories but never limited to them. It writes `categories.yaml`: each present category, the
changed paths that evidence it, and the governing playbook id (or `null` + "playbook missing"
for a new category).
{
"task": "assess the work categories present in the diff; cite changed-path evidence and the governing playbook",
"inputs": { "context": "<working>/context.yaml", "diff": "<working>/pr.diff",
"review_shelf": "<resolved>/knowledge/review/" },
"outputs": { "categories": "<working>/categories.yaml" }
}
**SE-1 (F1/C1):** every category in `categories.yaml` cites the changed paths that put it
there, and the set was derived from the diff — no presumed/hardcoded category list was used
(an absent category is simply not listed).
### Phase: Review
**Step 3 — Review Per Category** · Owner: play (dispatch) · Depends on: Step 2
For each category in `categories.yaml`, resolve its treatment from its `knowledge/review/`
playbook, then run **only the layers that apply**:
- **Layer 1 — linters.** For the standards-driven categories (code, config, tests, docs-prose)
the play dispatches `quality-auditor` to run `quality-check-scoped` against the diff →
`quality-findings.yaml`. For harness/memory the play runs the bundled structural linters the
playbook names (`lint_play.py`, `lint-components`) and folds their output into findings. For
categories whose linter is a known gap (ADRs, config-map path-existence), the play performs
the playbook's objective checks and records the basis. Where a category has a **runnable**
check (a test suite, a language linter), the play executes it — it is not merely read.
- **Layer 2 — design-grounding (concurrent read-only fan-out, C11).** Take the design-bearing
categories from `categories.yaml` (harness, memory, any new design-bearing category) and
dispatch **one `change-reviewer` per design-bearing category in a single concurrent batch**
(one message, N dispatches — concurrent read-only fan-out: each grounds only its own category
from committed sources, writes only its own `design-findings-<category>.yaml`, no grounding
agent depends on another; the safety conditions hold and the batch is **joined** before Step 4
reads any output — see `standards/rules/concurrent-fanout.md`). Each agent reconstructs its
category's principles from committed sources (base ref, `docs/philosophy/**`, `docs/adr/**`,
`memory/standards/rules/**`) and checks conformance; grounding reads are read-only and never
from diff-added content. The batch is bounded (the design-bearing set fixed by Step 2) and its
outputs are collected in a stable category order, so the result is identical to a serial run.
A single design-bearing category is a fan-out of width one.
A category whose categories.yaml entry is absent has its layers skipped — that is the expected
path, not a failure.
One grounding dispatch per design-bearing category `<cat>`, all sent as one concurrent batch:
{
"task": "design-ground ONLY the '<cat>' category from committed sources; emit conformance findings",
"inputs": { "context": "<working>/context.yaml", "categories": "<working>/categories.yaml",
"category": "<cat>", "diff": "<working>/pr.diff" },
"outputs": { "design_findings": "<working>/design-findings-<cat>.yaml" }
}
The standards linter (a single dispatch across all standards-driven categories):
{
"task": "run the standards linter against the diff for the standards-driven categories",
"inputs": { "context": "<working>/context.yaml", "categories": "<working>/categories.yaml" },
"outputs": { "quality_findings": "<working>/quality-findings.yaml" }
}
**SE-2 (F2/C2):** each reviewed category's treatment is sourced from its `knowledge/review/`
playbook (the record cites the playbook id) — no treatment is carried in the play body.
**SE-3 (F3/C3):** the layers executed equal the union of the applicable layers for the
categories present — no layer ran for an absent category, and no applicable layer was skipped.
**SE-4 (F4/C4):** every grounded principle across the `design-findings-<category>.yaml` set
cites a committed/external source; none cites a diff-added file (the branch is not its own standard).
**SE-5 (F5/C5):** every path read for review is within `changed_paths`, except grounding reads
which are read-only and committed — no full-repo scan ran.
**SE-7 (F7/C7):** for each in-scope category with a runnable check, the check was executed and
its result recorded; none was merely read.
**SE-12 (F12/C11):** design-grounding ran as a concurrent read-only fan-out — the count of
grounding dispatches equals the count of design-bearing categories in `categories.yaml`; each
wrote only its own `design-findings-<category>.yaml` (distinct paths, no overlap); the batch was
joined before Step 4 read any of them; and the collected result is order-stable (a serial re-run
would produce the same consolidated findings).
### Phase: Decision
**Step 4 — Consolidate + Recommend Verdict** · Owner: play (script) · Depends on: Step 3
The play assembles its agents' outputs — `quality-findings.yaml`, the joined
`design-findings-<category>.yaml` set (read in stable category order after the fan-out barrier),
and any bundled-linter findings — into one `findings.yaml` grouped by category and severity — every
finding already classified P1–P4 (by `quality-check-scoped` for standards findings, by the
`pr.md` taxonomy for design findings) and carrying a cited basis. It then computes the
**recommended** verdict — a fixed rule, no agent:
```
python3 scripts/compute_verdict.py --findings <working>/findings.yaml --threshold <conf>
```
It emits `recommended_verdict.yaml` (recommendation + reason + cited blocking findings +
counts): **reject** if any P1 finding (or a runnable suite is red), otherwise **approve**.
This is an input to the human gate, not the decision.
**SE-6 (F6/C6):** every finding in `findings.yaml` carries a P1–P4 class **and** a cited basis
— a linter rule id or a grounded principle with its committed source.
**Step 5 — Decision Gate (class: standard)** · Owner: play · Depends on: Step 4
This checkpoint is a config switch per `standards/rules/gate-config.md` (C8, #466/#467):
resolve `gates.plays.review-change` → `gates.classes.standard` → `gates.default`
(absent ⇒ on). Per the #467 ruling `gates.plays.review-change` is `off`; flipping the
config back to `on` restores the human wait unchanged. `review-pr.bypass` remains a
SEPARATE, pre-existing config (whether a reject blocks the downstream merge), untouched
by this switch.
- **On — the human decides.** Present, in plain language: the categories assessed; for
each design-bearing category, the principles grounded and their committed sources; the
consolidated findings grouped by category and severity, each with its basis; and the
recommended verdict with its reason. Then output the summary and **wait for the
reviewer's typed approve or reject** (do NOT use AskUserQuestion; do NOT proceed on the
recommendation alone). Record the reviewer's decision verbatim to `decision.yaml`
(`decided_by: human`).
- **Off — the recommendation becomes the decision.** Do not wait. Record
`gate skipped by config (gates.plays.review-change)` as a Checkpoint Decisions row in
the evidence. Write `decision.yaml` directly from `recommended_verdict.yaml`:
`decided_by: harness`, the recommendation **verbatim**, and the citing (blocking)
findings. A `reject` outcome stands exactly as a human reject would — fix the cited
findings and re-raise. The verdict is still never silent and never unposted (C9).
**Step 6 — Post Decision to PR** · Owner: play (script) · Depends on: Step 5
Assemble the decision comment (decision + the cited findings + routing) into a file — the
comment ALWAYS names its decider: a human decision is posted as the reviewer's verdict; an
off-gate decision leads with `Harness verdict (gate off per gates.plays.review-change):
<decision>` so no reader mistakes it for a human review (C8, F10). Then run the bundled
`post_verdict.py` — it posts the comment (via `platform_adapter.py`), writes
`review/posted.json` `{posted: true, comment_url}`, and commits+pushes the review run
artifacts, so the PR updates with its own review record. No agent (C10):
```
python3 scripts/post_verdict.py --config .garura/core/config.yaml \
--pr-number "<pr number>" --comment-file "<working>/decision-comment.md" \
--issue <issue> --artifacts-dir "{stm_base}{issue}/review/" \
--out "<working>/posted.json"
```
Whether a `reject` hard-blocks the downstream merge is governed by config
(`review-pr.bypass`), unchanged from prior behavior. A verdict rendered AND posted counts as
done regardless of approve/reject (C9).
**SE-8 (F8/C8):** the recommended verdict was computed; when the gate resolved on, the
recorded decision equals the reviewer's typed input; a verdict comment authored by this
run exists on the PR after the step.
**SE-9 (F9/C9):** `posted.json` reads `posted: true` with a comment URL; the run artifacts
are on the remote branch; the stop-condition verdict reads held before the close may read
COMPLETED.
**SE-10 (F10/C8):** when the gate resolved off, `decision.yaml` reads `decided_by: harness`
and equals the computed recommendation verbatim with its citing findings, and the posted
comment identifies its decider (harness vs human).
**SE-11 (F11/C10):** the PR context bind (Step 1) and the verdict post + artifact
commit/push (Step 6) ran as the bundled `fetch_pr_context.py` / `post_verdict.py` (via
`platform_adapter.py`), not an agent dispatch — no `repo-orchestrator` was invoked for the
mechanical PR/host work.
### Phase: Scenario Validation
**Step 7 — Scenario Evals** · Owner: play · Depends on: Step 6
- **SCE-1 (S1 — mixed PR):** the assessed category set reflects the diff's content; every
present category ran its applicable layers; no absent-category layer ran; posted.json
records the comment URL; the run artifacts are committed and pushed to the branch; the
stop-condition verdict reads held.
- **SCE-2 (S2 — single-kind PR):** only the applicable layers ran; design-grounding and test
execution were skipped — not failed — when their categories were absent; posted.json
records the comment URL; the run artifacts are committed and pushed to the branch; the
stop-condition verdict reads held.
- **SCE-3 (S3 — external grounding):** every grounding source recorded is committed/external;
none is a diff-added file.
- **SCE-4 (S4 — blocking finding):** with a P1 finding, the recommended verdict is reject
citing it; the decision followed the gate resolution (human's input when on; the harness
reject, marked as such, when off); the posted decision equals the recorded decision and
names its decider.
- **SCE-5 (S5 — cited basis):** every finding in the consolidated report names a linter rule
or a grounded principle as its basis.
- **SCE-6 (S6 — multi-category grounding):** when the diff holds more than one design-bearing
category, the number of grounding dispatches equals the number of design-bearing categories,
each wrote only its own `design-findings-<category>.yaml`, the batch was joined before
consolidation read any of them, and the consolidated result is order-stable.
### Phase: Evidence & Close
**Step 8 — Close** · Owner: play · Depends on: Step 7
Run the Standard Play Close. Evidence recording is play-only and config-gated per the D1
evidence rule (`standards/rules/evidence-recording.md`).
```bash
# --- Standard Play Close (canonical; see standards/rules/play-close.md) ---
# Path tokens resolved at pre-flight (resolve here if not already):
# ltm_project_target = yq '.ltm.project-target' .garura/core/config.yaml
# evidence_base, slug (project-scoped play):
# evidence_base="${stm_base}${issue}/evidence/review-change/" ; slug="#${issue}"
evidence_template=$(cat "${ltm_project_target}standards/templates/evidence-file.md")
delivery_template=$(cat "${ltm_project_target}standards/templates/delivery-report.md")
ts=$(date -u +%Y%m%d-%H%M%S)
evidence_dest="${evidence_base}${ts}.md"
mkdir -p "$(dirname "$evidence_dest")"
# Session identity stamp (#463) — close phase; start phase ran at pre-flight
session_stamp=$(python3 scripts/session_stamp.py --phase close \
--marker "${stm_base}${issue}/status/session-stamp-review-change.json")
# Stop-condition gate (#464) — Step C0: this play carries a baked manifest, so the
# gate is LIVE. Evaluate the Done means against the run's STM as the close's
# authoritative input.
python3 scripts/check_stop_condition.py \
--manifest "<play-dir>/stop-condition.yaml" \
--base "${stm_base}${issue}/" \
--out "${stm_base}${issue}/status/stop-condition-review-change.yaml"
sc_exit=$? # 0 held · 1 unmet · 2 error
```
**Step C0 — bind the verdict.** `sc_exit == 0` (held) permits `status: COMPLETED`.
Anything else closes `HALTED` with `exit_reason: stop_condition_unmet` and the evidence's
Stop Condition section names every unmet clause. An unevaluable verdict is never a pass.
**Step C1 — Write evidence file.** Gated by the resolved `evidence.record` flag (global +
per-play `evidence.plays.review-change`; first match wins, absent ⇒ record). When false,
skip the write and record `evidence skipped (record=false)` in the report's pointer line.
Otherwise fill the `evidence-file.md` slots (play `review-change`, run_id
`review-change-${ts}`, issue, started_at/completed_at, status per C0, exit_reason; artifacts
produced: `context.yaml`, `categories.yaml`, `quality-findings.yaml`, `design-findings.yaml`,
`findings.yaml`, `recommended_verdict.yaml`, `decision.yaml`, `posted.json` (with the PR
comment URL), the stop-condition verdict; step/scenario eval results; the recorded decision
(with its `decided_by`) as the terminal status; checkpoint decisions (incl. any
`gate skipped by config` row);
commit reference = the run-artifacts commit SHA; the session identity stamp fields from
$session_stamp (#463): session_id, ledger_file, ledger_start_offset, ledger_end_offset (null
when unresolved — never blocks the close); and stop_condition per C0 with the Stop Condition
section filled) and write to `$evidence_dest`. Do NOT hand-author the body.
**Step C2 — Render delivery report.** Also render the **Next** line: resolve this play in `standards/rules/pipeline-next.md` and emit `**Next:** /<command> — <why>. Or run /next to see all recommended actions.` (only /next pointer, or omit, when the mapped command is null), per `play-close.md`. Fill the `delivery-report.md` slots and output the
report: `## review-change Delivered — #${issue}` (lead with the human's decision), the Run
Summary table, the Pipeline Steps table from the task DAG, the Artifacts Produced table, Next
Steps (on approve: run merge-change; on reject: fix the cited findings and re-raise), and a
pointer to `$evidence_dest`. Always emitted; never gated.
```bash
# --- end Standard Play Close ---
```
## Scenario Validation
| Scenario | Persona | Eval |
|----------|---------|------|
| S1 — mixed PR | reviewer | SCE-1 |
| S2 — single-kind PR | reviewer | SCE-2 |
| S3 — external grounding | reviewer | SCE-3 |
| S4 — blocking finding | reviewer | SCE-4 |
| S5 — cited basis | reviewer | SCE-5 |
| S6 — multi-category grounding | reviewer | SCE-6 |
## Recovery
| For | Trigger | Direction | Handoff |
|-----|---------|-----------|---------|
| F1 | categories presumed or hardcoded | re-run the category assessment from the diff and discard any presumed list | autonomous |
| F2 | treatment taken from the play body | re-resolve the category's treatment from the `knowledge/review/` shelf | autonomous |
| F3 | a layer ran for an absent category, or an applicable layer was skipped | recompute applicability from the assessed categories — skip absent-category layers, run every applicable one | autonomous |
| F4 | grounding drawn from the branch's own new content | re-ground the design from committed/external sources only and re-check conformance | autonomous |
| F5 | the review expanded beyond the diff | re-scope to the diff; keep any outside reads read-only and grounding-only | autonomous |
| F6 | a finding has no cited basis | attach the finding's basis (linter rule or grounded principle) or drop the finding | autonomous |
| F7 | a runnable check was read but not executed | execute the check and fold its result into the findings | autonomous |
| F8 | the verdict was auto-decided while the gate was on, or the decision was not posted | hold at the human gate, record the reviewer's decision verbatim, and post it to the PR | human |
| F9 | the run is about to close COMPLETED with the Done means unmet (verdict never posted, posted.json or run artifacts missing) | post the verdict / fix the run state (write posted.json, commit+push the run artifacts), then re-evaluate the stop condition; the close stays HALTED until the verdict reads held | autonomous |
| F10 | with the gate off, `decision.yaml` differs from the computed recommendation, or the posted comment does not identify its decider | rewrite `decision.yaml` from `recommended_verdict.yaml` (`decided_by: harness`, recommendation verbatim, citing findings) and re-post the comment with the decider named | autonomous |
| F11 | a mechanical PR/host op (context bind, or verdict post + artifact commit/push) ran through an agent instead of its bundled script | route it through `fetch_pr_context.py` / `post_verdict.py` (via `platform_adapter.py`) and remove the agent dispatch | autonomous |
| F12 | design-grounding ran as a serial monolithic pass, or a grounding agent crossed category scope / wrote a shared output, or the batch wasn't joined before consolidation | re-dispatch grounding as a concurrent read-only fan-out — one read-only `change-reviewer` per design-bearing category, each scoped to its category and its own `design-findings-<category>.yaml`, joined before consolidation | autonomous |
## Pause and Resume
Steps run top to bottom. On entry, resolve the PR from the branch, check the status
marker, skip completed steps, reset any in-progress step to pending, and continue. When the
gate resolves on, the decision gate (Step 5) is never auto-resolved on resume — if it has
not been answered, re-present and wait; when it resolves off, resume re-derives the
decision from the recommendation exactly as a first pass would. A re-run re-posts the
current decision rather than adding a conflicting second one.
## Compilation Metadata
| Field | Value |
|-------|-------|
| fingerprint | sha256:b4adce1338cabd935698234cf8157be971f9e8c589d48e2f5865733c99167cdd (of `reference/ice.md`) |
| compiled_by | play-editor (#466 Batch A; #467 Batch C; #484 scripted chain; #496 grounding fan-out) |
| pipeline_position | end |
| workflow_structure | A (multi-agent; agentic assessment → concurrent read-only design-grounding fan-out (one agent per design-bearing category) → consolidation; config-resolved verdict gate; gated close) |
| stop_condition | stop-condition.yaml (D1–D3), gate live at Step C0 |
| domain_agents | 2 (change-reviewer — assessment ×1, grounding ×N design-bearing categories in a concurrent batch; quality-auditor) |
| utility_agents | 0 (#484 — mechanical PR/host I/O moved to bundled scripts) |
| skills_reused | quality-check-scoped, lint_play.py, lint-components |
| knowledge_consumed | knowledge/review/ (category playbooks); standards/rules/pr.md (severity taxonomy); standards/rules/concurrent-fanout.md (Layer-2 fan-out); standards_order set |
| scripts | 7 (preflight.py — pre-flight facts; compute_verdict.py — recommended verdict over classified findings; check_stop_condition.py — Done-means gate; session_stamp.py — #463 identity stamp; platform_adapter.py — code-host adapter; fetch_pr_context.py — bind PR context; post_verdict.py — post decision + commit artifacts) |
| step_evals | 12 (SE-1…SE-12) |
| scenario_evals | 6 (SCE-1…SCE-6) |
| recovery_entries | 12 (one per failure condition; F8 hands to the human gate, the rest autonomous) |
## Recompile note (#496, grounding fan-out)
Intent change via `reference/ice.md` → recompile. Added C11 (design-grounding runs as a
concurrent read-only fan-out per `standards/rules/concurrent-fanout.md`: one read-only
`change-reviewer` per design-bearing category, dispatched as one batch after assessment fixes
the category set, joined before consolidation), F12, REC12, SE-12, and S6/SCE-6. Step 3 Layer 2
changed from a single monolithic grounding dispatch (`design-findings.yaml`) to a per-category
fan-out (`design-findings-<category>.yaml`, distinct output paths); Step 4 now joins and reads
that set in stable category order. The assess-first barrier (Step 2) and the consolidate-last
barrier (Step 4) are unchanged, so the outcome is identical to a serial run — concurrency changes
only wall-clock, and a single design-bearing category is a fan-out of width one. No new agent
(same `change-reviewer`, dispatched N times), no new script. domain_agents stays 2; step_evals
11 → 12; scenario_evals 5 → 6; recovery_entries 11 → 12. The fold of assessment into grounding
was considered and dropped (Occam: it saves only the ~30s assessment round-trip on single-category
PRs, cannot coexist with the fan-out, and would add a permanent branch — see #496). Fingerprint
recomputed over the edited ICE.
## Recompile note (#484, scripted chain)
Intent change via `reference/ice.md` → recompile. Added C10 (mechanical PR/host I/O runs in
bundled scripts, never agent dispatch), F11, REC10, SE-11. Step 1 (bind PR context) and Step
6 (post verdict + commit/push artifacts) no longer dispatch `repo-orchestrator`; they run
`fetch_pr_context.py` and `post_verdict.py` via `platform_adapter.py` (canonical copies in
`play-creator/references/`, stamped here). The category assessment + design-grounding
(`change-reviewer`) and the standards linter (`quality-auditor`) STAY agent-run — genuine
judgment. Utility agents 1 → 0; scripts 4 → 7. Guarantees (categories assessed from the diff,
treatment from the shelf, grounding from committed sources, cited findings, human/harness
decision per gate, verdict posted) unchanged. Fingerprint recomputed over the edited ICE.
## Direct-edit deviation note (#434, harness-led sweep)
Superseded by the #443 redesign below. The prior note recorded moving the verdict from an LLM
agent into `compute_verdict.py`; that script is retained, now as the *recommendation* engine
feeding the human gate.
## Direct-edit deviation note (#443, review-change redesign)
Intent change (via `reference/ice.md` → play-editor, not a hand-edit): review-change moved from
a single-pass autonomous scripted gate to a thorough, category-aware, externally-grounded
review. The play now assesses work categories agentically (`change-reviewer` → `categories.yaml`),
resolves each category's treatment from the new `knowledge/review/` memory shelf, reviews each
through up to two layers (objective linters; design-grounding from committed sources for
design-bearing categories), runs only the applicable layers, consolidates findings that each
cite a basis, and ends at one mandatory human gate that owns the approve/reject verdict.
`compute_verdict.py` is retained as the recommendation input (no longer the decision);
`preflight.py` is unchanged. New domain agent `change-reviewer` added (categorization +
design-grounding); `quality-auditor` reused for the standards linter. The fingerprint reflects
the rewritten `reference/ice.md`.
## Direct-edit deviation note (#463, session identity stamp)
Non-intent change: the Standard Play Close gained the session identity stamp — `scripts/session_stamp.py` (canonical copy: `play-creator/references/session_stamp.py`) runs `--phase start` at pre-flight and `--phase close` in the close block; the evidence frontmatter carries session_id / ledger_file / ledger_start_offset / ledger_end_offset. Source of truth: `standards/rules/play-close.md`; play-creator emits the same lines so a rebuild converges. No constraint, failure, scenario, or eval changed; the fingerprint stands.
## Recompile note (#467 Batch C, chain gates off)
Intent change via `reference/ice.md` → play-editor: the Step 5 gate constraint (C8) now
resolves per gate-config (per-play `gates.plays.review-change` off per the #467 ruling).
When off, the recommendation from `compute_verdict.py` BECOMES the recorded decision —
`decision.yaml` carries `decided_by: harness`, the recommendation verbatim, and the citing
findings; the comment posted to the PR is clearly marked as a harness verdict; a REJECT
stands exactly as a human reject would (fix the cited findings, re-raise;
`review-pr.bypass` untouched). The verdict is still never silent and never unposted (C9
unchanged). New F10 + REC10 + SE-10 guard the off path (decision ≡ recommendation; the
posted comment names its decider). Checkpoint machinery is kept: flipping the config back
to `on` restores the human wait unchanged. No new scripts. The fingerprint reflects the
updated ICE.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!