Imported from gmcoolsr/VpnFakeService (
.cursor/skills/surgical-change-reviewer/SKILL.md). Install upstream withnpx skills add gmcoolsr/VpnFakeService --skill surgical-change-reviewer. Copyright stays with the author.
Surgical Change Reviewer
Token discipline: apply ../../_shared/token-discipline.md and its project overlay at every step; it never outranks evidence, gate, test, or stage rules.
Purpose
Drive one change target to a reviewed-clean state. You are the loop host: you resolve the target, run every review and fix attempt in a fresh independent context, enforce convergence, and own the final verdict. You never review and never fix in your own context.
Every reviewer, fixer, verifier, and triple-pass handoff must carry this safety clause verbatim:
ГЛАВНОЕ НЕ СЛОМАТЬ ДРУГОЙ ФУНКЦИОНАЛ.
СДЕЛАТЬ ХИРУРГИЧЕСКУЮ ДОРАБОТКУ.
Run only in an interactive human session. This skill is outside the autonomous
Stage pipeline: it never advances a tracker workflow and never merges.
agent-doc-debt: the Execution Topology ladder is duplicated here instead of extracted into a shared fragment used by both this skill and surgical-ticket-refiner; revisit when surgical-ticket-refiner migrates to a shared independent-attempt topology fragment
Mandatory Reads
Before resolving the target, read:
../../_shared/grounded-output.md../../_shared/delegation-first.md../../_shared/chatgpt-subagent-discipline.md../../_shared/complexity-reuse-ladder.md../../_shared/final-review-blocking-contract.md../../_shared/review-wave-discipline.md../../_shared/anti-false-green.md../../_shared/restrictive-change-blast-radius.md../../_shared/tool-output-normalization.md../review-orchestrator/SKILL.md../reviewer-test/SKILL.md
If any mandatory source cannot be read, return BLOCKED before touching any
file.
Invocation Contract
Repository status. This repository has no commits yet: git rev-parse HEAD
fails and no branch ref exists. Three of the four target kinds below therefore
cannot resolve today — only worktree can, and only over untracked files. That
is a state, not a defect: say so and stop, rather than reporting an empty review
as a clean one.
Resolve exactly one target. Four target kinds cover the supported requests:
| Kind | Human phrasing | Resolution |
|---|---|---|
worktree |
review local changes | git diff HEAD plus untracked files from git ls-files --others --exclude-standard |
local-commits |
review local commits | git log '@{u}..HEAD'; if no upstream, git log 'main..HEAD' |
commit |
review commit <sha> |
git diff '<sha>^..<sha>', or the named range; see the merge and root-commit forms below |
ticket |
review the commits of <KEY> |
the anchored git log --grep below, then the union of those commits |
Always write git revisions inside single quotes. The rule covers PowerShell and
POSIX shells: @{u} is a hashtable literal in PowerShell, so unquoted
revisions break the local-commits target there.
'<sha>^..<sha>' is the single-parent form only. A merge commit has more than
one parent and that form silently drops every parent but the first, so resolve
a merge against all of its parents — with git show -m, or with a range the
human explicitly confirmed:
git show --name-only --format= -m '<sha>'
A root commit has no ^ at all and that form fails outright, so resolve it
against the empty tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904.
The ticket pattern is anchored on purpose. An unanchored --grep=<KEY> is a
substring match, so a shorter valid key silently pulls in the commits of every
longer key that contains it. Anchor it:
git log --all --oneline -E --grep='(^|[^A-Z0-9-])<KEY>([^0-9]|$)'
A commit or issue key that resolves through none of these forms is ambiguity, not a default: take it to the rule below.
Echo the resolved target back to the human before starting any lane: kind,
base sha, head sha, commit count, changed-file list, and the target anchor.
The changed-file list enumerates individual files, never a collapsed
directory, so it counts the same units as the untracked anchor.
Never guess between candidate resolutions. Ambiguity — several branches
carrying the same issue key, a dirty tree under a commit or ticket target,
an upstream that resolves through neither @{u} nor main — is a question,
not a default.
Accept an optional fix-attempt limit as max-fixes: <positive integer>.
Default to 20. Reject values over the hard cap of 50. Use an explicit value
exactly as written; do not clamp it back to the default or to the cap. Reject
an invalid value before touching any file. One fix attempt is one candidate
change that reaches the write fence.
This skill always fixes what it may safely fix. Do not ask for permission to
fix, and do not stop at a findings report. The narrow exception is an explicit
review-only in the current human request, which suppresses the fix lane and
returns findings.
Examples:
Use $surgical-change-reviewer on the working tree.
Use $surgical-change-reviewer on local commits, max-fixes: 15.
Use $surgical-change-reviewer on the commits of VPN-1234.
Absolute Boundaries
The loop host is the only writer of run artifacts, with the manual tier as the
single exception: the fresh window writes its own verdict file to the absolute
path the host printed. The review lane's read-only permission mode must
therefore still permit writing exactly that verdict file under
.artifacts/change-review/**, and nothing else. The fix lane is the only
writer of repository files.
Never run git commit, git push, git commit --amend, git rebase,
git reset --hard, git checkout <branch>, git stash pop, or any tag,
branch, or remote mutation. Every change this skill makes stays in the working
tree so the human can inspect it with git diff and revert it with one command.
Never write to the tracker. For a ticket target the tracker is read-only
evidence, routed through docs/agents/mcp-youtrack.md and the active runtime
schema; resolve the commits from git, not from ticket prose.
Never run migrations, deployments, publishes, or destructive data commands.
Five guardrails replace the missing review-only gate:
- Working tree only. No commit, no push, no history rewrite.
- Clean-tree precondition for
commit,local-commits, andtickettargets. If the tree is dirty, stop and ask; otherwise the human's unsaved work and the skill's fixes become indistinguishable.worktreehas no such precondition, because the dirt is the target. Snapshot it before the fix lane's first write.git stash createcovers modifications to tracked files only; it captures none of the target's untracked paths, with or without--include-untracked. So the run must additionally copy every untracked target path into its own run workspace under.artifacts/change-review/...before that first write. Without that copy a fixer that damages an untracked file leaves the human no way back. The commitgit stash createprints is dangling — no ref, no reflog entry — so record its sha insnapshot/tracked-stash.txt; unrecorded, it survives only until the nextgit gcand is recoverable only throughgit fsck --unreachable. - Fixes land on top. For
commitandtickettargets, corrections are new working-tree changes. History is never rewritten. - Target files only. The fix lane may edit only files in the resolved
target file list: the tracked diff plus the untracked target paths. A new
file never appears in
git diff HEAD, so the untracked half of that list is what keeps it in scope. Any file outside the list requires ascope_expansionentry naming the file and the blocking finding that forces it; without one, stop. - No silent product decisions. A finding that requires choosing intended behaviour never enters the fix lane. It goes to the Human Clarification Contract below.
Apply ../../_shared/complexity-reuse-ladder.md
to every fix: understand the touched flow first, then take the smallest durable
rung that closes the finding. A review loop must not become a refactor.
Execution Topology
The required property is fresh independent review, fix, and verification attempts. The mechanism is negotiable; the property is not.
Never-Break Ladder
A tier failure never stops the run. Each lane starts at the best tier its runtime allows and degrades automatically.
| Runtime | Order | Floor |
|---|---|---|
| Claude | probe, then a child session (claude -p) for the review lane; on any failure, a native subagent |
manual window |
| Codex / ChatGPT | the runtime-native delegation call only | manual window |
| zcode / GLM / unknown | native delegation if exposed; otherwise a Claude-compatible child CLI when the probe passes | manual window |
For Codex the shell tier does not exist. A shell-launched nested codex exec
is not delegation and never substitutes for the native call; see
../../_shared/chatgpt-subagent-discipline.md.
Never hardcode a binary name. Keep a runtime-to-command table and let an environment override win; an unknown runtime goes to native delegation, never to a guessed shell command.
Probe
Probe once per run before pinning tiers. The probe is a small end-to-end task, not an existence check: in the repository working directory, with an explicit permission mode and an explicit timeout, the child session must read one file and write a one-word result to a file. Anything else is a failure.
These are failures, and each one degrades the lane one tier: binary missing, probe timeout, authentication failure, sandbox denial, non-zero exit, empty or unparseable verdict, and a hang past the timeout.
Tier Rules
- Degradation goes down only. Pin the tier per lane after the probe. If the pinned tier fails mid-run, it degrades for the rest of the run and never recovers upward; otherwise half the loop runs at a different rigor than the other half.
- The review lane runs read-only. When it runs as a child session, give it a permission mode that cannot write repository files.
- The fix lane always runs as a native subagent, never as a child session. Its edits then surface in the human's own session under the normal permission flow instead of appearing silently in the working tree.
- The one forbidden recovery is reviewing in the host context. It looks like
success and quietly destroys independence. When every tier is exhausted, stop
BLOCKED; never substitute yourself. - Every attempt records
tier_requested,tier_used, anddegradation_reason.
Manual Tier
The manual tier is the floor for any runtime without native delegation. Print the exact prompt, including the absolute path the fresh window must write its verdict to, ask the human to run it in a new window, and wait for that file. The manual tier is full-strength independence, not a degraded result.
Independence Invariant
Every review and verification attempt runs in a context that has never seen prior verdicts, finding history, fixer rationale, expected answers, or an explanation of what was fixed. Beyond the lane's own role definition, three things are the maximum input set: the target specification, the repository state, and the safety clause. An attempt may receive less. The triple pass is the stricter case — see the Triple-Pass Exit Invariant, where the target specification shrinks to a minimal locator or disappears entirely.
Independence is a property of the context, not of the tier. It holds identically on a child session, a subagent, and a manual window: the subagent handoff packet carries no history, and the printed manual prompt carries no history.
Do not summarize previous findings to help a fresh reviewer. That well-meant
hint is the exact failure this invariant exists to prevent. A seeded attempt is
BLOCKED, never CLEAN_PASS.
Review Lanes
The generalist lane is mandatory and always runs first, in every wave, for every target. Its prompt is deliberately unconstrained — the target, the safety clause, and nothing else. No checklist, no lane list, no domain hints. It decides for itself what matters.
Specialist lanes are additive only. They never narrow, replace, or override the generalist lane. Add them by domain of the changed files:
| Domain | Added lane |
|---|---|
control-api/, portal/ product code |
review-orchestrator, which selects its own profile and auditors |
core/, gateway/ Go code |
Generalist only. There is no Go specialist lane in this repository, and the .NET and Angular auditors do not apply to Go: adding one produces wrong findings, not extra coverage. This is where the product's highest-severity properties live, so say in the report that no specialist lane judged the diff. |
apps/windows, apps/apple, apps/android native clients |
Generalist only. There is no WinUI, SwiftUI, or Compose specialist lane, and the .NET and Angular auditors do not apply — the C# planned for apps/windows is a WinUI client, not an ASP.NET Core service. |
infra/ Terraform and Ansible |
Generalist only. devops is a build-and-rollout role, not a review lane, and has no review checklist to contribute. |
docs/agents/** and its projections |
documentation-reviewer, plus the documentation graph gate |
docs/** other documentation |
documentation-reviewer |
| repository tooling and scripts | generalist plus the tooling's own invariant tests |
tests/**, including tests/network/ |
reviewer-test for the affected specs |
A fix under docs/agents/source/** is finished only after
pwsh ./docs/tooling/agent-docs-sync.ps1 -Mode sync (or
sh ./docs/tooling/agent-docs-sync.sh -Mode sync) and
pwsh ./docs/tooling/agent-consistency-check.ps1 (or
sh ./docs/tooling/agent-consistency-check.sh) have been rerun. The
consistency check is the executable gate for registry coverage, layer labels,
core purity, overlay pairing, _shared link integrity, stage literals, and MCP
aliases — the invariants an agent-doc edit breaks. The sync rebuilds
docs/agents/docs-graph.json itself, so run
sh docs/tooling/docs-graph/docs-graph.sh build only when the sync reports
that it could not. The regenerated projections and
docs/agents/docs-graph.json are in-scope consequences of that fix, not a
scope_expansion: the fix lane owes them, and the step 7 readback counts them
as part of the recorded scope.
A domain with no matching specialist is not a gap: the generalist has already covered it. Never skip the generalist because a specialist ran.
Normalize every lane result through
../../_shared/tool-output-normalization.md.
Keep raw lane output out of the host result.
Convergence Contract
../../_shared/review-wave-discipline.md
bounds the autonomous pipeline to one full wave plus at most four verification
waves and forbids re-running the full auditor set as a recheck. This skill
deliberately deviates: every iteration runs a full independent wave from
scratch, because a verification wave seeded with what to check cannot satisfy
the Independence Invariant, and because a human is present to stop the run.
The deviation is bounded by three compensating rules, not by trust:
- Origin test. Apply
../../_shared/final-review-blocking-contract.mdto every finding. Only a defect introduced by the target diff enters the fix loop. Pre-existing and improvement findings are advisory and are recorded, never fixed. Without this rule a fresh wave keeps discovering legacy debt and the loop never converges. A mandatory gate that is red at the base and provenbase_redunder the same contract is one such finding: record it as advisory and keep it out of the fix loop. It ends that finding, not the run. - Budget.
max-fixes, default20, hard cap50. - Fingerprints. Every finding carries a stable fingerprint built from
category, file path, and the normalized claim. Line numbers are excluded on
purpose: a landed fix shifts them, so a
path:lineidentity would give an unfixed defect a new fingerprint in the next wave and silently disarm the oscillation detector.path:linestays as evidence, never as identity. Fingerprints are how repetition, oscillation, and closure are detected across waves.
Loop Procedure
1. Resolve and snapshot
Resolve the target, echo it to the human, and compute the anchor.
The worktree anchor has two parts, because that target includes untracked
paths and git diff HEAD does not show untracked files at all. The tracked
part is the diff hash; the untracked part folds the content of every untracked
target path:
git diff HEAD | git hash-object --stdin
git -c core.quotePath=false ls-files --others --exclude-standard |
LC_ALL=C sort > "$run/untracked-list"
while IFS= read -r p; do
h=$(git hash-object -- "$p") || exit 1
printf '%s %s\n' "$h" "$p"
done < "$run/untracked-list" > "$run/untracked-pairs" || exit 1
git hash-object --stdin < "$run/untracked-pairs"
The loop reads from a file in the run workspace instead of from a pipeline on
purpose. Inside a pipeline the loop is a subshell, so its exit cannot stop
the run; a failed command substitution is swallowed; and the pipeline status is
the status of the trailing git hash-object --stdin, which succeeds on a
truncated list. A shell that supports set -o pipefail may keep the pipeline
form instead, provided a per-file failure still aborts the run.
Every element of that form is load-bearing: core.quotePath=false stops
ls-files from C-quoting non-ASCII paths, which git hash-object cannot then
open — this repository has none today, and the flag is what keeps that from
becoming a silent failure the first time one is added; LC_ALL=C sort makes the order
locale-independent; IFS= read -r preserves leading and trailing spaces in a
path; -- keeps a leading-dash path from being read as an option. Without
them git hash-object cannot open the path and the anchor stops tracking that
file's content. If any git hash-object call fails, stop the run instead of
continuing with a silently corrupted anchor.
The anchor of a commit, local-commits, or ticket target has two parts
too. The range part is git diff '<base>..<head>' | git hash-object --stdin;
the working-tree part folds both halves of the working tree exactly as the
worktree anchor does — the tracked git diff HEAD hash and the untracked
hash from the loop above, piped together into git hash-object --stdin to
give one value — because guardrail 4 lets a fix create a file and a new file
never appears in git diff HEAD. Their clean-tree precondition pins both
halves at snapshot time, the tracked one at the empty-diff constant
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 and the untracked path list empty,
and that part is the one that moves: fixes land on top as working-tree changes
and never rewrite the range, so a range-only anchor could never show that a fix
landed.
This is pure git plumbing and behaves identically on macOS, Windows, and Linux; no external hashing tool is involved. If a shell cannot run the loop above, compute the same values by any available means — the values are what matters, not the shell syntax.
The anchor of an empty diff is the constant
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391. Stop NO_CHANGES only when both
parts are empty: the tracked part equals that constant and the untracked path
list is empty. A target made only of new files is not NO_CHANGES.
Record both anchor parts, git rev-parse HEAD, the porcelain status, and the
changed file list. The anchor identifies the target within this run on this
machine; it is not a cross-machine identity.
2. Run a full wave
Launch the generalist lane plus every additive specialist, each in its own fresh context at its pinned tier. Wait for every lane before deciding anything.
3. Normalize findings
Fingerprint every finding, apply the origin test, and split the result into blocking findings, advisory findings, and items needing a human decision.
With review-only, stop here and report. The terminal status is
REVIEW_FINDINGS, including when no finding survives the origin test.
4. Resolve human-needed items
If any finding requires a product decision, follow the Human Clarification Contract before continuing.
5. Fix
Give a fresh fixer subagent the blocking fingerprints, the target file list,
and the safety clause. Route by ownership: backend code to the backend
implementation role, frontend to the frontend role, documentation to the
documentation writer, tests to the tester. The fixer proposes a candidate; it
never widens scope and never touches a file outside the resolved target file
list without a scope_expansion entry.
6. Fence the write
Immediately before applying a candidate, re-read git rev-parse HEAD, the
porcelain status, and every anchor part. On any difference from the snapshot,
discard the candidate and restart once from the new state. On a second
concurrent change, stop CONFLICT without writing.
7. Read back
After the fix lands, recompute every anchor part and confirm the applied change is exactly the candidate and touches no file outside the recorded scope. An edit to an untracked file moves only the untracked part, so a readback that looks at the tracked part alone would miss it. A missing or mismatched readback is not success.
Once the readback is confirmed, replace the recorded snapshot — git rev-parse HEAD, the porcelain status, and every anchor part — with the post-fix state.
The snapshot is rebaselined after every landed fix, so the step 6 fence of the
next attempt catches only external changes and never this run's own fixes.
8. Verify
Run only the affected suites, under the project C0/C1 test policy, through
reviewer-test. Apply
../../_shared/anti-false-green.md: a
suite that was never red does not prove the fix, and a skipped or filtered
suite is not a pass.
9. Re-review
Launch a new full wave in fresh contexts against the new anchor, seeded with nothing from the previous iteration. Return to step 3 until the wave is clean or a stop condition fires.
Child Output Schemas
Require every review lane to return only:
verdict: PASS | BLOCKING | ADVISORY_ONLY | NEEDS_HUMAN | BLOCKED
findings:
- fingerprint: stable-category-path-and-claim
category: correctness | regression | security | quality | ux | docs | tests
origin: introduced | pre_existing | improvement
evidence: path:line plus a concise retrievable reference
required_change: the smallest change that closes the finding
human_needs: []
lane: generalist | <specialist name>
Require the fixer to return only:
status: CANDIDATE | NEEDS_HUMAN | BLOCKED
addressed_fingerprints: []
files_touched: []
scope_expansion:
- file: path
forced_by: fingerprint
changes_summary:
- concise correction
scope_check: unchanged | widened
Findings must be grounded in the diff, repository source, canonical documentation, or a command result. A plausible failure narrative without evidence tied to the diff cannot block.
Human Clarification Contract
When an item needs a product decision, the consolidated question is the whole user-facing response for that turn. Do not send a status line, a progress note, a verdict, or the completion envelope before or after it.
Ask once, in Russian, numbered, and for each item give:
question— the exact decision needed;why_needed— why the loop cannot safely continue without it;evidence— concise non-secret evidence that created the need;options— at least two concrete choices, each withlabel,descriptionof what would change in the code, andconsequence;recommendation— one option markedrecommended: true, with a short rationale.
If only one safe option exists, still present it with the consequence of rejecting it. Never collapse independent decisions into one vague question. Treat the answer as authoritative evidence, feed it to a fresh fixer, and continue the loop.
Triple-Pass Exit Invariant
CLEAN_PASS requires all three:
- the last full wave is clean;
- a separate fresh verifier is clean against the same anchor;
- three independent context-free passes each return
PASS, orADVISORY_ONLYwith nointroducedfinding after the origin test.
Context-free means a pass carries no verdicts, no finding history, no fixer rationale, and no candidate text. It does not mean the pass is denied a target locator.
For a worktree target a pass receives no locator at all: the kind resolves
itself from git, and the working tree is the whole target. The prompt is
equivalent to:
сделай ревью локальных изменений
проверь что ничего не сломано
ГЛАВНОЕ НЕ СЛОМАТЬ ДРУГОЙ ФУНКЦИОНАЛ.
СДЕЛАТЬ ХИРУРГИЧЕСКУЮ ДОРАБОТКУ.
For local-commits, commit, and ticket targets a pass receives the minimal
target locator — the resolved range recorded as target.spec, or the issue key
— and nothing else, and must review that locator together with the current
working tree. A branch without an upstream is why the locator is the resolved
range and never the literal @{u}..HEAD: that revision does not resolve there,
and an unresolvable locator sends the run to BLOCKED.
Their clean-tree precondition means a locator-free pass would see only
this run's own fixes, or an empty tree, and would return a PASS without ever
looking at the reviewed commits;
../../_shared/anti-false-green.md
forbids that false green.
Substitute the phrasing that matches the target kind, adding the locator for
local-commits, commit, and ticket; keep it a plain review request with no
checklist. All three passes receive the byte-identical prompt, so a divergence
between their verdicts is a divergence of context and never of instruction.
Three contexts, not three questions
Independence across the passes is what raises recall, so make it checkable:
- distinct
attempt_idand distinctchild_idper pass. A repeatedchild_idis a reused context and stops the runBLOCKED; child_id: unavailableis acceptable only on the manual tier, and only when each pass has its own window and its own verdict file undertriple-pass/;- one prompt, one context, one verdict. A second question asked in a context that already answered is not a pass;
context_free: trueandseeded_with_prior_review: falseon every pass, and never relay one pass's findings to another;- when more than one tier or runtime is available, spread the three passes
across distinct ones and record
tier_usedper pass. That diversity is expected, not required: a single-tier runtime still satisfies the invariant when the three contexts are genuinely distinct.
Anchor freeze
All three passes run against the same anchor, and the anchor is re-read after the last one returns. Any drift across the triple pass invalidates it, and it reruns in full against the new anchor.
Collect, then fix
Run all three passes even when the first returns a blocking finding, then fold
every introduced finding from all three into one fix input. Stopping at the
first blocker discards exactly the recall the other two passes exist to add.
A triple pass that finds a blocking defect is the next loop input. After the
fix, a new triple pass runs from scratch; an earlier PASS is never
reused. Three answers from one context are not a triple pass. If the triple
pass cannot run as three independent contexts on any tier, the terminal status
is BLOCKED or NEEDS_HUMAN — never CLEAN_PASS.
The triple pass spends no max-fixes budget: a pass is a review attempt, not a
fix attempt.
Stop Conditions
Stop immediately when:
- the same fingerprint reappears after an attempted fix;
- the anchor is unchanged after a fix attempt, judged across every anchor part, so an untracked-only fix is not mistaken for no change;
- anchors oscillate
A -> B -> A; - the configured
max-fixeslimit is reached; - the fixer widens scope, or a required change falls outside the resolved
target file list without a justified
scope_expansion; - a product decision remains unresolved after the clarification step;
- a second concurrent external change hits the working tree;
- every tier is exhausted for a required lane.
Every stop condition other than a second concurrent external change
(CONFLICT) and an unresolved product decision (NEEDS_HUMAN) terminates as
BLOCKED, with the condition named in stop_reason.
Run Workspace
.artifacts/change-review/<target-kind>-<short-anchor>/<YYYYMMDD-HHMMSS>/
iter-1/review/<lane>.yaml
iter-1/fix/candidate.yaml
iter-1/verify/test-result.txt
iter-1/rereview/<lane>.yaml
triple-pass/pass-1.yaml
triple-pass/pass-2.yaml
triple-pass/pass-3.yaml
snapshot/tracked-stash.txt <stash-create sha, written before the first write>
snapshot/untracked/<untracked target paths, copied before the first write>
loop-state.md
final-report.md
The timestamp segment is literally YYYYMMDD-HHMMSS: no colons, so the path is
legal on Windows as well as macOS and Linux. An ISO-8601 timestamp is not
allowed, because its colons make the folder uncreatable on Windows.
The workspace is gitignored and never committed. Manual-tier prompts and their verdict files live in the same iteration folder.
Completion Contract
Return the final response as a short Russian result line of at most three lines, then exactly one fenced YAML block, and nothing after it except one short Russian sentence when a limitation must be disclosed.
The YAML block is the authoritative result. attempts is mandatory; use an
empty array only when the run stopped before any attempt started. CLEAN_PASS
is invalid unless attempts contains receipts for the final wave, the
final_verifier, and all three passes. In attempts.role, test_verify is the
step 8 test gate and final_verifier is the independent verifier required by
item 2 of the Triple-Pass Exit Invariant. Every triple_pass attempt carries
its own pass_index. REVIEW_FINDINGS is the terminal
status of every review-only run and reports the review outcome whether or not
the findings list is empty. The second anchor fields carry the untracked
part for a worktree target and the working-tree part for commit,
local-commits, and ticket targets; they are none only for a worktree
target with no untracked paths. At CLEAN_PASS, advisory_findings must list
every advisory finding the run recorded, each with its fingerprint and origin.
A clean run does not mean an independent review will find nothing: the origin
test deliberately leaves pre_existing and improvement findings unfixed, and
a later review outside this skill applies no such test. The advisory list is
what makes those findings recognizable as already known instead of missed.
Never include raw diffs, raw lane output, credentials, or long logs.
status: CLEAN_PASS | REVIEW_FINDINGS | NEEDS_HUMAN | CONFLICT | NO_CHANGES | BLOCKED
target:
kind: worktree | local-commits | commit | ticket
spec: as resolved
base_sha: sha
head_sha: sha
files: 0
initial_anchor: sha1
final_anchor: sha1
initial_second_anchor: sha1 | none
final_second_anchor: sha1 | none
budget:
max_fixes: 20
fix_attempts_used: 0
topology:
runtime: claude | codex | other
probe: passed | failed | skipped
review_lane_tier: child-session | subagent | manual
fix_lane_tier: subagent | manual
iterations:
- index: 1
anchor_in: sha1
anchor_out: sha1
blocking_fingerprints: []
advisory_fingerprints: []
fixed_fingerprints: []
attempts:
- role: review | fixer | test_verify | final_verifier | triple_pass
attempt_id: id
pass_index: null | 1 | 2 | 3
lane: generalist | <specialist name>
tier_requested: child-session | subagent | manual
tier_used: child-session | subagent | manual
degradation_reason: null | concise reason
child_id: id | unavailable
seeded_with_prior_review: false
anchor: sha1
verdict: PASS | BLOCKING | ADVISORY_ONLY | CANDIDATE | NEEDS_HUMAN | BLOCKED
finding_fingerprints: []
triple_pass:
distinct_contexts: true | false
anchor_stable: true | false
anchor: sha1 | not-run
passes:
- index: 1
child_id: id | unavailable
tier_used: child-session | subagent | manual
context_free: true
resolved_target_itself: true | false
verdict: PASS | ADVISORY_ONLY | BLOCKING | NEEDS_HUMAN | BLOCKED
verdict: PASS | ADVISORY_ONLY | BLOCKING | NEEDS_HUMAN | BLOCKED | not-run
advisory_findings:
- fingerprint: id
origin: pre_existing | improvement
summary: concise
no_touch_audit:
commits: 0
pushes: 0
branch: unchanged | changed | not-checked
history_rewrites: 0
tracker_writes: 0
files_outside_target: 0
migrations_run: 0
surgical_scope:
no_break_clause_in_handoffs: true
scope_expansion: []
stop_reason: null | concise reason
Any changed or not-checked value in no_touch_audit, or a non-zero count
in its numeric fields, blocks CLEAN_PASS.