Project Quality Loop - Review-and-Fix Folder Pipeline (Autonomous)
You drive a pipeline of review-fix loops from a folder. You run each prompt file in the folder, in numeric order, looping it on the target until its bar is met, then advance to the next file. After the run-start mode ask, run fully autonomously - the ONLY pause points are that mode ask, each stage-close fresh-session ask, and the final report's tear-down-vs-keep ask when the run started infrastructure (OUTPUT); every other decision, including DELEGATED mode's fix-inline-vs-dispatch economy calls, you make yourself, apply, and log (measured: one run asked the user a mid-stage FIX-mode question this line already forbade). When context genuinely forces a MID-STAGE pause (a pass done, FIX not started, the chat too heavy to continue well), the pause runs the same mechanics as a stage close - write RUN-STATE.md FIRST, then one AskUserQuestion (continue here vs fresh session) - never a prose 'which do you want?' that ends the turn with the handoff artifact unwritten (measured: one mid-pass stop narrated two options and left RUN-STATE unwritten until the user asked what to paste into a new session). Gate-stamp files (flow/APPROVAL) are written with the Write tool at the ABSOLUTE path $CLAUDE_PROJECT_DIR/<docs-path>/flow/APPROVAL - .claude/ is a protected path so the first write prompts (take the prompt's 'allow Claude to edit its own settings for this session' option and the rest of the run is free), and a relative Bash write follows whatever cwd the shell drifted to (measured: two sessions landed the stamp in a phantom nested docs tree and lost dispatches to the guard). If the harness refuses BOTH that write and an absolute-path Bash fallback, stop and put the choice through AskUserQuestion (retry, or run this stage inline) - never retry blind: five sessions in one project silently degraded every FIX to inline for a whole 12-stage run because the stamp could not be written and nothing said so. The stamp belongs to the session that dispatches - written when its own decision lands, deleted at its own close; an earlier session's leftover stamp is not consent (measured: a 2h52m-old stamp from another session authorized five implementer dispatches). A user 'don't ask me' instruction waives FIX-step judgment calls only - never the structural asks above. The protocol binds whatever dispatch primitive is available: an orchestration or fan-out tool never replaces DISCOVERY, the numbered stages, or the anti-gaming sweep (measured: two runs re-implemented the loop as ad hoc fan-out scripts and lost the sweep entirely).
Best run in Claude Code, where you can edit files and re-read them across passes. On a large codebase the context can fill - if so, run it per module (point TARGET at one module at a time). Each stage boundary is a fresh-session resume point - the loops folder plus each file's logged outcome is the handoff (measured, carried-forward conversation, not tool output, dominates session cost). A step, not advice (the advice form was ignored in 4 of 4 audited long sessions), and the one exception to the no-input rule above: when a stage reaches its STOP and another stage remains, ask via AskUserQuestion - continue in a fresh session from the loops folder (recommended) vs continue here; on 'fresh', first write the run's carryover to an un-numbered <LOOP_DIR>/RUN-STATE.md as a LEAN digest - the run parameters, the GREEN BASELINE sha recorded at DISCOVERY, ONE outcome line per finished file, only still-open items, and a Next section naming the next stage file - while the full per-decision rationale appends to <LOOP_DIR>/DECISIONS.md, a side file no resume reads whole (measured: the all-in-one carryover grew to ~1,447 lines and its whole-file resume read alone was 39% of one session's tool-result volume, recurring in 8 of 11 sessions). Then end the turn with a RESUME BLOCK the new session can start from alone: the exact invocation naming RUN-STATE.md and the next stage number, and one line on what that stage will do. The resumed session reads the RUN-STATE digest (offset-scoped to the run parameters plus the latest stage when the file is long), re-confirms the green baseline BEFORE its first dispatch (a sha-identity diff against the recorded baseline plus the build, at minimum), and diffs its final anti-gaming sweep against the recorded sha.
INPUTS (fill these in)
- LOOP_DIR - the folder of prompt files. When not given, check
<docs-path>/loops/ - that folder IS the loop set; missing or empty means BOOTSTRAP below. Each file is named {number}.{name}.md (e.g. 1.structure.md, 2.code-quality.md, 3.naming.md) - five stages, plus an optional 0.-numbered standing-guidance file (see DISCOVERY). There is no architecture stage (structure and code-quality both read the architecture map - structure to spare a layout it records as deliberate, code-quality to audit conformance to it; architecture-level restructuring is the separate project-architecture-quality-loop skill) and no tests stage (the GREEN BASELINE gate keeps the suite green; coverage work is the project-test-coverage-analyzer/-loop pair).
- TARGET - the one scope every file runs against, in order, each pass re-reading its current on-disk state so earlier fixes persist. Name a path or glob - preferred, since the loop re-reads between passes. Paste code inline only for a throwaway snippet with no file to edit; the fence below just delimits a pasted block, so omit it when you name a path.
<<<TARGET
{{PASTE CODE, OR NAME A PATH/GLOB}}
TARGET>>>
- BAR - default: zero findings at every severity - BLOCKER, MAJOR, AND MINOR all fixed. Nothing is left as acceptable or debatable; a minor finding is still a finding and must be resolved. REAL findings only: a candidate that fails the findings gate (RULES) is not a finding - it is not recorded, not counted against this bar, and its absence is not a gap; the bar is zero real findings. A file may set its own bar inside it - that wins for that file.
- MAX_PASSES - per file, default 5.
EXECUTION MODES
DELEGATED vs INLINE keys on dispatch capability, not file presence - agent files on disk with no Agent tool to dispatch them is still INLINE. When dispatch is available, ask ONE question before DISCOVERY, via AskUserQuestion - run the pipeline in the current session, or dispatch the audit and fix seats? - then hold the answer for the run; no dispatch capability (or a TARGET with nothing to hand off, below) is INLINE without asking:
- DELEGATED (the user chose agents) - recommend it in the ask whenever the Task/Agent tool is present: it keeps the main session's context clean across passes and hands the audit and fix work to a specialist built for it. The main session keeps ALL bookkeeping; INNER LOOP step RUN dispatches the domain verifier as a read-only auditor, and step FIX dispatches the domain implementer with a findings-plan (a red gate routes to the matching resolver instead). Seats are always the NAMED domain seats - never a generic seat (
general-purpose/claude); a surface with no matching installed seat runs INLINE for that stage (measured: one run put all 10 dispatches on generic seats, losing every seat pin, preload, and trap-list). On choosing DELEGATED - and on every resume that carries it - write the dispatch-approval stamp BEFORE the first FIX dispatch: <docs-path>/flow/APPROVAL, first line AUTO - "<the mode-ask answer, verbatim>" (the mode answer IS the standing consent the dispatch hook checks; a leftover stamp from another flow is not, and the hook expires old stamps), and delete the file when the run or stage-close ends. The full who-does-what - dispatch-prompt construction, the finding contract, gate stages, economy guidance, the opus first-find experiment - is references/delegated-mode.md; read it before the first dispatch.
- INLINE (the user chose the current session - or forced, no question asked: no dispatch, TARGET is pasted code with no file to hand off, or a single small file) - the mode this skill originally shipped as; its behavior is unchanged: the whole INNER LOOP (RUN, SCORE, CHECK, STOP?, FIX) runs in the current session exactly as written in that section. For a .NET or Angular TARGET, load the domain's convention skills before the loop starts editing - conventions are the source of truth, not recall; the per-stack load list, and the caveat that the Angular Material/CDK skill is the one a project can lack (skip it when nothing in your list covers it), are the DOMAIN CONVENTIONS section of
references/delegated-mode.md.
BOOTSTRAP - no usable <docs-path>/loops/ folder yet?
This skill ships a starter set under its own references/ folder - a standing fix-discipline preamble plus five stage prompts: structure, code quality, naming, logging and comments, all audits. The structure stage moves files and folders only; the code-quality stage reads <docs-path>/architecture/ARCHITECTURE.md and audits TARGET for both quality and conformance to the recorded structure; the logging stage audits whether a failure can be detected and reconstructed from the log points - silent failures, missing join keys, wrong levels, duplicate log-and-rethrow chains - and fixes through the repo's own logging seam. When LOOP_DIR (the resolved <docs-path>/loops/ from INPUTS) does not exist or holds no .md files, create it yourself and seed it: make the folder (mkdir -p "<LOOP_DIR>"), then copy the six references/ prompts into it, prefixing each with its order number - 0.fix-discipline.md, 1.structure.md, 2.code-quality.md, 3.naming.md, 4.logging.md, 5.comments.md - and edit to taste. Number them by blast radius - see NOTE ON CONVERGENCE - so later stages do not undo earlier ones. Do this silently as part of the run, then proceed to DISCOVERY; a missing or empty folder is never a reason to pause. A folder that HAS .md files but no numbered stage file is neither missing nor yours to fill - the files are user-authored, so never seed the starter set around them: proceed to DISCOVERY, list them as skipped, and end with a report naming the fix (number the custom prompts to make them stages, or empty the folder to re-bootstrap from the starter set).
DISCOVERY (do this first, before any work)
- Resolve the run order in one shot: list
LOOP_DIR/*.md and sort ascending by the leading integer before the first dot in each filename - numerically, not lexically (ls "<LOOP_DIR>" | sort -t. -k1,1n - bare filenames, so the leading integer is field 1; 2.x runs before 10.x). Print the resolved order before starting; skip files with no numeric prefix (list them as skipped), and run same-numbered files in filename order (note it).
STANDING GUIDANCE - a 0.-numbered file is fix discipline, not a stage: read it now, hold its rules for every stage's FIX step (in DELEGATED mode fold them into each FIX dispatch brief), record it SATISFIED with zero findings in the run order, and advance. Never run an audit or a gate against it; re-read it after a compaction or when splitting the run per module.
- ORDER WARNING - sanity-check that numeric order against the blast-radius order in NOTE ON CONVERGENCE. If a wider-blast stage is numbered after a narrower one (a code-quality file after a comments file, say), print the warning - later stages invalidating earlier ones is the main cause of non-convergence - but do not reorder; the numeric sort stays authoritative.
- GREEN BASELINE - confirm it before any stage runs (command-first): run the project's build and test gate commands in-session. A red baseline is a pre-existing failure - fix it first (route to the matching resolver) or record it explicitly, so each stage's changes are measured against a green start rather than blamed for a prior break. Record the sweep baseline in the same step: the HEAD sha, or on a dirty tree the sha
git stash create prints (a commit object of the uncommitted state, tree untouched) - the final ANTI-GAMING SWEEP diffs against it. You re-gate at the end (see OUTER LOOP).
OUTER LOOP - strictly one file at a time, in order
Process the files strictly in ascending numeric order, beginning with the lowest-numbered file. Fully finish the current file - its inner loop must reach a STOP - before you open the next one. Never run files out of order, never skip ahead, and never work on more than one file at a time. When a file's inner loop reaches its STOP and another file remains, run the stage-close fresh-session ask (top of this skill) before opening the next.
For each file F, lowest number first:
- Load F as the active review prompt for this stage. Validate any skill names F instructs auditors to load against the installed inventory - a stage file naming a nonexistent skill silently re-derives that content in every dispatch prompt; substitute the real home or drop the load, and note it.
- Run the INNER LOOP below on TARGET until it STOPs.
- Record F's outcome (SATISFIED / PLATEAU / OSCILLATION / DIVERGED / CAPPED, on which pass) and advance to the next file. Do NOT abort the pipeline because a file plateaued, oscillated, diverged, or capped - log it and continue. A plateau on a judgment audit is expected, not a failure. When another stage remains, the outcome line is not complete without the stage-close answer: fire the fresh-session-vs-here ask (the intro's one exception) IN the same message that records the outcome, end the turn, and append
continue: <fresh|here> - "<answer>" to the outcome line before the next stage's first audit or dispatch runs - a next stage started with that field absent is a protocol violation, headless runs included (measured: one headless run recorded three stage outcomes and fired zero of the three mandated asks; the same model honored the identically-shaped run-start ask, so the binding lives on the outcome line, not in prose reminders).
After the last file: re-run the GREEN BASELINE (build + tests) as a final gate. A red here means a stage regressed the build - route it to the matching resolver and re-verify before reporting done. Then the ANTI-GAMING SWEEP: diff the target against the GREEN BASELINE sha recorded at DISCOVERY - plus every file untracked at that sha (git ls-files --others --exclude-standard; a plain diff is blind to brand-new files, so a gamed bar added in one would never surface) - and check the cumulative diff for gamed bars - a disabled or skipped test, a new warning suppression, a swallowed exception, a weakened or deleted assertion, a lowered threshold introduced by any FIX. Review the FULL diff - never cap it (head, first-N lines); a long diff is paged deterministically until exhausted, because a gamed bar past the cap is exactly the one that survives (measured: one sweep piped the diff through head -400 - harmless that run only because the diff was 177 lines). A structure stage makes that diff rename-heavy: run it with rename detection (git diff -M --stat) and a pure rename (R100, no content change) is verified by name alone - every remaining content hunk is still paged in full, no cap. An autonomous fix loop can make a bar 'pass' by exactly these shortcuts, so this sweep is the mechanism behind the never-weaken rule (RULES), not a second opinion. Any hit is a BLOCKER: revert the shortcut, fix the real problem it dodged, re-run the gate, and name the stage that gamed it in the Final report. Then emit the Final report.
INNER LOOP - run the current file F to a stop
Repeat until you STOP (in DELEGATED mode, RUN and FIX are the two dispatched steps - references/delegated-mode.md; everything else stays in the main session):
Pass N:
- RUN - apply F to TARGET in its current state. Produce its full result (findings, or gate result - see CHECK). A pass-2+ audit RUN may scope to the files changed since the recorded pass sha (
git diff --name-only) plus the files carrying open findings - an unchanged file's prior verdict stands; log the scope in the SCORE line. When a DELEGATED stage partitions TARGET into slices, one auditor ALWAYS takes the cumulative diff against the green-baseline sha as its slice (the diff-lens seat) - stated here, not only in the reference, because a resumed session re-reads this file and not necessarily references/delegated-mode.md (measured: one resume dropped the diff-lens seat with the rule sitting unread).
- SCORE - print one line:
F | Pass N - BLOCKER: x, MAJOR: y, MINOR: z, DECIDED: d, then the open-finding set on the next line: open: [...], one entry per unresolved finding keyed by (severity, file:line-or-symbol, 3-6 word description), sorted. Identity is the (severity, file:line-or-symbol) pair; the description is a human label, so re-wording it alone does not make a finding new. That printed set is the single identity of this pass's findings - the STOP conditions are read off it across passes, never off an eyeball judgment. For a gate-based file (see CHECK), print the gate result instead: F | Pass N - gate: <command> -> pass/fail, with the command output standing in for the open set.
- CHECK - decide if F's bar is met (BAR is defined once, in INPUTS - do not restate or soften it here):
- Findings-based file (an audit) -> met only when BAR is met; with the default bar, you may not declare it met while any finding of any severity remains open.
- Gate-based file (a transform that names a verifiable command - e.g. the test suite, or build + comment-only diff) -> the bar is that command exiting 0. Run it; do not judge it by eye. If it still fails and no new fix is available, re-running the identical command is a PLATEAU - stop and report the failure, do not burn passes on the same invocation.
- STOP? - compare this pass's open set to the prior passes and check the STOP conditions below; if any holds, end F's inner loop. If the open-set count rose versus the previous pass, the last FIX over-reached - make the next FIX as minimal as possible.
- FIX - for every open finding (every severity counts against BAR):
- Clear fix -> apply the smallest correct change.
- Judgment call or ambiguity -> decide it yourself. Pick the option most consistent with the codebase's existing patterns and conventions, apply it, and add a line to the DECISIONS log (
<LOOP_DIR>/DECISIONS.md): the choice, and the concrete precedent it follows (a file:symbol or named rule); when no precedent exists, say so explicitly and still decide. Do not ask, pause, or wait.
- Out of scope for F (owned by a different file in the pipeline) -> note under OUT OF SCOPE, leave it, do not count it against the bar.
- Mechanically impossible here (depends on a file, service, or value that does not exist in this context) -> make the most reasonable assumption and proceed; if you truly cannot, record it under COULD-NOT-APPLY with the reason and continue.
- Go to Pass N+1.
STOP CONDITIONS (per file; stop at the first that holds)
Read these off the printed open set (SCORE) across passes, not by eye - PLATEAU and OSCILLATION compare set identity; DIVERGED also tracks whether you already minimized the last FIX.
- SATISFIED - the bar is met; the printed score proves it. SATISFIED means every MEASURED finding was fixed, decided, or scoped out - never that the codebase is clean: any report or capture-doc line derived from it states the qualified form ('all measured findings resolved'), and the unqualified 'no open weaknesses' is banned.
- PLATEAU - this pass's open set equals the previous pass's (ignore re-wording) and the count did not drop. The same items remain and none are now resolvable; do not re-run identically hoping for a different outcome. An equal count with a changed set is churn, not a plateau - keep going.
- OSCILLATION - this pass's open set differs from the immediately previous pass but matches an earlier one (a 2-cycle, or any longer cycle repeating) - so it is never also a PLATEAU. A fix and its reversal are ping-ponging; re-running will not converge. Log both competing states under DECISIONS, pick the one most consistent with the codebase's conventions, apply it, and leave it.
- DIVERGED - the open-set count rose again even after you minimized the last FIX (see INNER LOOP step 4). The stage is making the target worse, not better; stop and report it rather than burn the remaining passes.
- CAPPED - you reached MAX_PASSES.
Example - one file's inner loop
DELEGATED, 3.naming.md over src/Orders/:
3.naming.md | Pass 1 - BLOCKER: 0, MAJOR: 1, MINOR: 2, DECIDED: 0
open: [(MAJOR, OrderSvc.cs:14, abbreviation in public type), (MINOR, OrderQueries.cs:22, vague 'data' param), (MINOR, OrderQueries.cs:41, vague 'tmp' local)]
- RUN dispatched aspnet-verifier as a read-only auditor; the open set above is its result.
- FIX: OrderSvc -> OrderService (clear); the two vague names renamed to follow the OrderQueries naming precedent, logged to DECISIONS. Dispatch aspnet-implementer with that findings-plan.
- Pass 2 re-runs the auditor ->
open: [] -> SATISFIED; advance to the next file.
RULES (these keep autonomous self-judgment honest)
- Decide, do not ask. Every decision the work needs, you make - using the codebase's existing conventions as the tiebreaker - and record it.
- The findings gate - a candidate is a finding only when all four are answered explicitly: what breaks (the concrete wrong outcome - 'it differs from a preference, another codebase, or a reference doc' is not an answer); who notices, and when (named, with the trigger); is it actually new (behavior already recorded as a known limit or a prior decision is a re-measurement, not a discovery); has the project already decided it (a choice recorded in CLAUDE.md or the architecture docs is a Deliberate tradeoff - never re-raise it). A gate-passing defect is Must fix: it enters the open set. A true-but-not-actionable observation is Worth knowing: note it in the pass output, never in the open set - and never 'fix' it.
- Do not invent a finding to demonstrate diligence, and do not omit one to keep a pass short.
open: [] on pass 1 is a valid, expected result on healthy code - a stage that finds nothing is SATISFIED on pass 1, and reporting it is a success, not a weak audit. Equally, twenty real findings means the open set lists all twenty: PLATEAU and OSCILLATION are read off set identity across passes, so a truncated set silently breaks the stop conditions.
- 'Satisfied' means the explicit bar is met - not 'this looks fine' or 'good enough'. Show the score; it is the proof.
- List every remaining item before you stop a file. Never declare a file done with hidden open items.
- Every finding is resolved one way: fixed, decided-and-applied, marked out of scope, or could-not-apply with a reason. Nothing is silently dropped.
- Never weaken, skip, or delete a check, test, or assertion to make a bar appear met. If a fix would break a test, that is a finding, not a fix. The final gate's anti-gaming sweep checks the cumulative diff for exactly this.
- Make the smallest change that resolves each item. Avoid rewrites that introduce new findings - they make the loop diverge instead of converge.
- For gate-based files, the command is the bar - a passing command beats your opinion. Self-judgment is only the fallback for things no command can check, like naming or design quality.
- An enumerable finding class - one a grep or glob can list exhaustively (a banned API, a naming pattern, a suppression marker) - pairs the model audit with the deterministic scan and reconciles the two lists; a model-only sweep misses members (measured: five auditors together missed 6 of a class's 81 instances that a one-line grep listed).
- The main session is the only orchestrator - never instruct a subagent to dispatch another; the auditors and implementers this loop dispatches (domain verifiers, implementers, resolvers) carry no Agent tool. A stage needing a verdict and a fix is two dispatches from here, not one nested one.
OUTPUT
Per pass: the one-line score and open set, plus a short note of what you fixed and decided.
Per file: the outcome line.
Final report (whole pipeline):
- The run order, and each file's outcome.
- The final gate: build + tests result, and the anti-gaming sweep over the cumulative diff (clean, or what was reverted and which stage gamed it).
- Remaining findings per file, if any.
- DECISIONS log:
<LOOP_DIR>/DECISIONS.md - every judgment call across all files, each with the precedent it followed (or an explicit note that none existed), appended as it lands in either mode and reviewable after the fact; the report names the file and its entry count, never re-pastes it (the close is an answer like any other - the answer-length hook blocks a wall of prose).
- OUT OF SCOPE / COULD-NOT-APPLY: anything deliberately left, with reasons.
- Leftovers - what the pipeline's gate and audit runs started and still have up (containers, seeded test data, background processes), or
none; anything listed gets tear-down-vs-keep through AskUserQuestion batched with the close, teardown recommended - never touching what the run did not start.
memories purged: <names|none> - DELEGATED runs purge the serena hand-off notes fold-first at close (the rule and receipt shape: references/delegated-mode.md).
- Overall summary of changes.
NOTE ON CONVERGENCE
This is a single forward pass through the files. A later file's edits are not re-checked against earlier files. If you want a full fixpoint, run the whole pipeline again - a clean second run (every file SATISFIED, or a stable PLATEAU) means it has converged. Order the files by blast radius so later stages do not invalidate earlier ones: structure (widest - a move changes a symbol's public path, so every later finding would have to be re-keyed), then code-quality (it carries architecture-conformance), then naming, then logging (its messages are written against the settled names, and its edits - a log line added, a duplicate removed - move nothing a later stage keys on), then comments.
1---2name: project-quality-loop3description: Autonomous review-and-fix pipeline driven from a folder of numbered prompt files (the `<docs-path>/loops/` folder of fix-discipline / structure / code-quality / naming / logging / comments). Runs each prompt in numeric order, looping it on a target until its bar is met, then advances - making and logging judgment calls itself, pausing only at the run-start mode ask and each stage-close fresh-session ask. Triggers on 'run the project quality loop' or 'run the loops pipeline'. Code-quality only - architecture restructuring is project-architecture-quality-loop; measuring or raising test coverage is the project-test-coverage-analyzer/-loop pair; a single diff sweep is project-verify-code or /security-review, not this. Do NOT fire for a one-off review pass or when findings should be reported without auto-fixing (a missing or empty loops folder is no blocker - the skill seeds it from a bundled starter set to bootstrap; a folder of custom prompts is the user's, never overwritten).4---56# Project Quality Loop - Review-and-Fix Folder Pipeline (Autonomous)78You drive a pipeline of review-fix loops from a folder. You run each prompt file in the folder, in numeric order, looping it on the target until its bar is met, then advance to the next file. After the run-start mode ask, run fully autonomously - the ONLY pause points are that mode ask, each stage-close fresh-session ask, and the final report's tear-down-vs-keep ask when the run started infrastructure (OUTPUT); every other decision, including DELEGATED mode's fix-inline-vs-dispatch economy calls, you make yourself, apply, and log (measured: one run asked the user a mid-stage FIX-mode question this line already forbade). When context genuinely forces a MID-STAGE pause (a pass done, FIX not started, the chat too heavy to continue well), the pause runs the same mechanics as a stage close - write RUN-STATE.md FIRST, then one AskUserQuestion (continue here vs fresh session) - never a prose 'which do you want?' that ends the turn with the handoff artifact unwritten (measured: one mid-pass stop narrated two options and left RUN-STATE unwritten until the user asked what to paste into a new session). Gate-stamp files (`flow/APPROVAL`) are written with the Write tool at the ABSOLUTE path `$CLAUDE_PROJECT_DIR/<docs-path>/flow/APPROVAL` - `.claude/` is a protected path so the first write prompts (take the prompt's 'allow Claude to edit its own settings for this session' option and the rest of the run is free), and a relative Bash write follows whatever cwd the shell drifted to (measured: two sessions landed the stamp in a phantom nested docs tree and lost dispatches to the guard). If the harness refuses BOTH that write and an absolute-path Bash fallback, stop and put the choice through AskUserQuestion (retry, or run this stage inline) - never retry blind: five sessions in one project silently degraded every FIX to inline for a whole 12-stage run because the stamp could not be written and nothing said so. The stamp belongs to the session that dispatches - written when its own decision lands, deleted at its own close; an earlier session's leftover stamp is not consent (measured: a 2h52m-old stamp from another session authorized five implementer dispatches). A user 'don't ask me' instruction waives FIX-step judgment calls only - never the structural asks above. The protocol binds whatever dispatch primitive is available: an orchestration or fan-out tool never replaces DISCOVERY, the numbered stages, or the anti-gaming sweep (measured: two runs re-implemented the loop as ad hoc fan-out scripts and lost the sweep entirely).910Best run in Claude Code, where you can edit files and re-read them across passes. On a large codebase the context can fill - if so, run it per module (point TARGET at one module at a time). Each stage boundary is a fresh-session resume point - the loops folder plus each file's logged outcome is the handoff (measured, carried-forward conversation, not tool output, dominates session cost). A step, not advice (the advice form was ignored in 4 of 4 audited long sessions), and the one exception to the no-input rule above: when a stage reaches its STOP and another stage remains, ask via AskUserQuestion - continue in a fresh session from the loops folder (recommended) vs continue here; on 'fresh', first write the run's carryover to an un-numbered `<LOOP_DIR>/RUN-STATE.md` as a LEAN digest - the run parameters, the GREEN BASELINE sha recorded at DISCOVERY, ONE outcome line per finished file, only still-open items, and a Next section naming the next stage file - while the full per-decision rationale appends to `<LOOP_DIR>/DECISIONS.md`, a side file no resume reads whole (measured: the all-in-one carryover grew to ~1,447 lines and its whole-file resume read alone was 39% of one session's tool-result volume, recurring in 8 of 11 sessions). Then end the turn with a RESUME BLOCK the new session can start from alone: the exact invocation naming RUN-STATE.md and the next stage number, and one line on what that stage will do. The resumed session reads the RUN-STATE digest (offset-scoped to the run parameters plus the latest stage when the file is long), re-confirms the green baseline BEFORE its first dispatch (a sha-identity diff against the recorded baseline plus the build, at minimum), and diffs its final anti-gaming sweep against the recorded sha.1112## INPUTS (fill these in)13- LOOP_DIR - the folder of prompt files. When not given, check `<docs-path>/loops/` - that folder IS the loop set; missing or empty means BOOTSTRAP below. Each file is named `{number}.{name}.md` (e.g. `1.structure.md`, `2.code-quality.md`, `3.naming.md`) - five stages, plus an optional `0.`-numbered standing-guidance file (see DISCOVERY). There is no architecture stage (structure and code-quality both read the architecture map - structure to spare a layout it records as deliberate, code-quality to audit conformance to it; architecture-level restructuring is the separate `project-architecture-quality-loop` skill) and no tests stage (the GREEN BASELINE gate keeps the suite green; coverage work is the `project-test-coverage-analyzer`/`-loop` pair).14- TARGET - the one scope every file runs against, in order, each pass re-reading its current on-disk state so earlier fixes persist. Name a path or glob - preferred, since the loop re-reads between passes. Paste code inline only for a throwaway snippet with no file to edit; the fence below just delimits a pasted block, so omit it when you name a path.15 <<<TARGET16 {{PASTE CODE, OR NAME A PATH/GLOB}}17 TARGET>>>18- BAR - default: zero findings at every severity - BLOCKER, MAJOR, AND MINOR all fixed. Nothing is left as acceptable or debatable; a minor finding is still a finding and must be resolved. REAL findings only: a candidate that fails the findings gate (RULES) is not a finding - it is not recorded, not counted against this bar, and its absence is not a gap; the bar is zero real findings. A file may set its own bar inside it - that wins for that file.19- MAX_PASSES - per file, default 5.2021## EXECUTION MODES22DELEGATED vs INLINE keys on dispatch capability, not file presence - agent files on disk with no Agent tool to dispatch them is still INLINE. When dispatch is available, ask ONE question before DISCOVERY, via AskUserQuestion - run the pipeline in the current session, or dispatch the audit and fix seats? - then hold the answer for the run; no dispatch capability (or a TARGET with nothing to hand off, below) is INLINE without asking:2324- **DELEGATED** (the user chose agents) - recommend it in the ask whenever the Task/Agent tool is present: it keeps the main session's context clean across passes and hands the audit and fix work to a specialist built for it. The main session keeps ALL bookkeeping; INNER LOOP step RUN dispatches the domain verifier as a read-only auditor, and step FIX dispatches the domain implementer with a findings-plan (a red gate routes to the matching resolver instead). Seats are always the NAMED domain seats - never a generic seat (`general-purpose`/`claude`); a surface with no matching installed seat runs INLINE for that stage (measured: one run put all 10 dispatches on generic seats, losing every seat pin, preload, and trap-list). On choosing DELEGATED - and on every resume that carries it - write the dispatch-approval stamp BEFORE the first FIX dispatch: `<docs-path>/flow/APPROVAL`, first line `AUTO - "<the mode-ask answer, verbatim>"` (the mode answer IS the standing consent the dispatch hook checks; a leftover stamp from another flow is not, and the hook expires old stamps), and delete the file when the run or stage-close ends. The full who-does-what - dispatch-prompt construction, the finding contract, gate stages, economy guidance, the opus first-find experiment - is `references/delegated-mode.md`; read it before the first dispatch.25- **INLINE** (the user chose the current session - or forced, no question asked: no dispatch, TARGET is pasted code with no file to hand off, or a single small file) - the mode this skill originally shipped as; its behavior is unchanged: the whole INNER LOOP (RUN, SCORE, CHECK, STOP?, FIX) runs in the current session exactly as written in that section. For a .NET or Angular TARGET, load the domain's convention skills before the loop starts editing - conventions are the source of truth, not recall; the per-stack load list, and the caveat that the Angular Material/CDK skill is the one a project can lack (skip it when nothing in your list covers it), are the DOMAIN CONVENTIONS section of `references/delegated-mode.md`.2627## BOOTSTRAP - no usable `<docs-path>/loops/` folder yet?28This skill ships a starter set under its own `references/` folder - a standing fix-discipline preamble plus five stage prompts: structure, code quality, naming, logging and comments, all audits. The structure stage moves files and folders only; the code-quality stage reads `<docs-path>/architecture/ARCHITECTURE.md` and audits TARGET for both quality and conformance to the recorded structure; the logging stage audits whether a failure can be detected and reconstructed from the log points - silent failures, missing join keys, wrong levels, duplicate log-and-rethrow chains - and fixes through the repo's own logging seam. When LOOP_DIR (the resolved `<docs-path>/loops/` from INPUTS) does not exist or holds no `.md` files, create it yourself and seed it: make the folder (`mkdir -p "<LOOP_DIR>"`), then copy the six `references/` prompts into it, prefixing each with its order number - `0.fix-discipline.md`, `1.structure.md`, `2.code-quality.md`, `3.naming.md`, `4.logging.md`, `5.comments.md` - and edit to taste. Number them by blast radius - see NOTE ON CONVERGENCE - so later stages do not undo earlier ones. Do this silently as part of the run, then proceed to DISCOVERY; a missing or empty folder is never a reason to pause. A folder that HAS `.md` files but no numbered stage file is neither missing nor yours to fill - the files are user-authored, so never seed the starter set around them: proceed to DISCOVERY, list them as skipped, and end with a report naming the fix (number the custom prompts to make them stages, or empty the folder to re-bootstrap from the starter set).2930## DISCOVERY (do this first, before any work)311. Resolve the run order in one shot: list `LOOP_DIR/*.md` and sort ascending by the leading integer before the first dot in each filename - numerically, not lexically (`ls "<LOOP_DIR>" | sort -t. -k1,1n` - bare filenames, so the leading integer is field 1; `2.x` runs before `10.x`). Print the resolved order before starting; skip files with no numeric prefix (list them as skipped), and run same-numbered files in filename order (note it).32 STANDING GUIDANCE - a `0.`-numbered file is fix discipline, not a stage: read it now, hold its rules for every stage's FIX step (in DELEGATED mode fold them into each FIX dispatch brief), record it SATISFIED with zero findings in the run order, and advance. Never run an audit or a gate against it; re-read it after a compaction or when splitting the run per module.332. ORDER WARNING - sanity-check that numeric order against the blast-radius order in NOTE ON CONVERGENCE. If a wider-blast stage is numbered after a narrower one (a code-quality file after a comments file, say), print the warning - later stages invalidating earlier ones is the main cause of non-convergence - but do not reorder; the numeric sort stays authoritative.343. GREEN BASELINE - confirm it before any stage runs (command-first): run the project's build and test gate commands in-session. A red baseline is a pre-existing failure - fix it first (route to the matching resolver) or record it explicitly, so each stage's changes are measured against a green start rather than blamed for a prior break. Record the sweep baseline in the same step: the HEAD sha, or on a dirty tree the sha `git stash create` prints (a commit object of the uncommitted state, tree untouched) - the final ANTI-GAMING SWEEP diffs against it. You re-gate at the end (see OUTER LOOP).3536## OUTER LOOP - strictly one file at a time, in order37Process the files strictly in ascending numeric order, beginning with the lowest-numbered file. Fully finish the current file - its inner loop must reach a STOP - before you open the next one. Never run files out of order, never skip ahead, and never work on more than one file at a time. When a file's inner loop reaches its STOP and another file remains, run the stage-close fresh-session ask (top of this skill) before opening the next.3839For each file F, lowest number first:401. Load F as the active review prompt for this stage. Validate any skill names F instructs auditors to load against the installed inventory - a stage file naming a nonexistent skill silently re-derives that content in every dispatch prompt; substitute the real home or drop the load, and note it.412. Run the INNER LOOP below on TARGET until it STOPs.423. Record F's outcome (SATISFIED / PLATEAU / OSCILLATION / DIVERGED / CAPPED, on which pass) and advance to the next file. Do NOT abort the pipeline because a file plateaued, oscillated, diverged, or capped - log it and continue. A plateau on a judgment audit is expected, not a failure. When another stage remains, the outcome line is not complete without the stage-close answer: fire the fresh-session-vs-here ask (the intro's one exception) IN the same message that records the outcome, end the turn, and append `continue: <fresh|here> - "<answer>"` to the outcome line before the next stage's first audit or dispatch runs - a next stage started with that field absent is a protocol violation, headless runs included (measured: one headless run recorded three stage outcomes and fired zero of the three mandated asks; the same model honored the identically-shaped run-start ask, so the binding lives on the outcome line, not in prose reminders).43After the last file: re-run the GREEN BASELINE (build + tests) as a final gate. A red here means a stage regressed the build - route it to the matching resolver and re-verify before reporting done. Then the ANTI-GAMING SWEEP: diff the target against the GREEN BASELINE sha recorded at DISCOVERY - plus every file untracked at that sha (`git ls-files --others --exclude-standard`; a plain diff is blind to brand-new files, so a gamed bar added in one would never surface) - and check the cumulative diff for gamed bars - a disabled or skipped test, a new warning suppression, a swallowed exception, a weakened or deleted assertion, a lowered threshold introduced by any FIX. Review the FULL diff - never cap it (`head`, first-N lines); a long diff is paged deterministically until exhausted, because a gamed bar past the cap is exactly the one that survives (measured: one sweep piped the diff through `head -400` - harmless that run only because the diff was 177 lines). A structure stage makes that diff rename-heavy: run it with rename detection (`git diff -M --stat`) and a pure rename (R100, no content change) is verified by name alone - every remaining content hunk is still paged in full, no cap. An autonomous fix loop can make a bar 'pass' by exactly these shortcuts, so this sweep is the mechanism behind the never-weaken rule (RULES), not a second opinion. Any hit is a BLOCKER: revert the shortcut, fix the real problem it dodged, re-run the gate, and name the stage that gamed it in the Final report. Then emit the Final report.4445## INNER LOOP - run the current file F to a stop46Repeat until you STOP (in DELEGATED mode, RUN and FIX are the two dispatched steps - `references/delegated-mode.md`; everything else stays in the main session):4748Pass N:491. RUN - apply F to TARGET in its current state. Produce its full result (findings, or gate result - see CHECK). A pass-2+ audit RUN may scope to the files changed since the recorded pass sha (`git diff --name-only`) plus the files carrying open findings - an unchanged file's prior verdict stands; log the scope in the SCORE line. When a DELEGATED stage partitions TARGET into slices, one auditor ALWAYS takes the cumulative diff against the green-baseline sha as its slice (the diff-lens seat) - stated here, not only in the reference, because a resumed session re-reads this file and not necessarily `references/delegated-mode.md` (measured: one resume dropped the diff-lens seat with the rule sitting unread).502. SCORE - print one line: `F | Pass N - BLOCKER: x, MAJOR: y, MINOR: z, DECIDED: d`, then the open-finding set on the next line: `open: [...]`, one entry per unresolved finding keyed by (severity, file:line-or-symbol, 3-6 word description), sorted. Identity is the (severity, file:line-or-symbol) pair; the description is a human label, so re-wording it alone does not make a finding new. That printed set is the single identity of this pass's findings - the STOP conditions are read off it across passes, never off an eyeball judgment. For a gate-based file (see CHECK), print the gate result instead: `F | Pass N - gate: <command> -> pass/fail`, with the command output standing in for the open set.513. CHECK - decide if F's bar is met (BAR is defined once, in INPUTS - do not restate or soften it here):52 - Findings-based file (an audit) -> met only when BAR is met; with the default bar, you may not declare it met while any finding of any severity remains open.53 - Gate-based file (a transform that names a verifiable command - e.g. the test suite, or build + comment-only diff) -> the bar is that command exiting 0. Run it; do not judge it by eye. If it still fails and no new fix is available, re-running the identical command is a PLATEAU - stop and report the failure, do not burn passes on the same invocation.544. STOP? - compare this pass's open set to the prior passes and check the STOP conditions below; if any holds, end F's inner loop. If the open-set count rose versus the previous pass, the last FIX over-reached - make the next FIX as minimal as possible.555. FIX - for every open finding (every severity counts against BAR):56 - Clear fix -> apply the smallest correct change.57 - Judgment call or ambiguity -> decide it yourself. Pick the option most consistent with the codebase's existing patterns and conventions, apply it, and add a line to the DECISIONS log (`<LOOP_DIR>/DECISIONS.md`): the choice, and the concrete precedent it follows (a file:symbol or named rule); when no precedent exists, say so explicitly and still decide. Do not ask, pause, or wait.58 - Out of scope for F (owned by a different file in the pipeline) -> note under OUT OF SCOPE, leave it, do not count it against the bar.59 - Mechanically impossible here (depends on a file, service, or value that does not exist in this context) -> make the most reasonable assumption and proceed; if you truly cannot, record it under COULD-NOT-APPLY with the reason and continue.606. Go to Pass N+1.6162## STOP CONDITIONS (per file; stop at the first that holds)63Read these off the printed open set (SCORE) across passes, not by eye - PLATEAU and OSCILLATION compare set identity; DIVERGED also tracks whether you already minimized the last FIX.64- SATISFIED - the bar is met; the printed score proves it. SATISFIED means every MEASURED finding was fixed, decided, or scoped out - never that the codebase is clean: any report or capture-doc line derived from it states the qualified form ('all measured findings resolved'), and the unqualified 'no open weaknesses' is banned.65- PLATEAU - this pass's open set equals the previous pass's (ignore re-wording) and the count did not drop. The same items remain and none are now resolvable; do not re-run identically hoping for a different outcome. An equal count with a changed set is churn, not a plateau - keep going.66- OSCILLATION - this pass's open set differs from the immediately previous pass but matches an earlier one (a 2-cycle, or any longer cycle repeating) - so it is never also a PLATEAU. A fix and its reversal are ping-ponging; re-running will not converge. Log both competing states under DECISIONS, pick the one most consistent with the codebase's conventions, apply it, and leave it.67- DIVERGED - the open-set count rose again even after you minimized the last FIX (see INNER LOOP step 4). The stage is making the target worse, not better; stop and report it rather than burn the remaining passes.68- CAPPED - you reached MAX_PASSES.6970## Example - one file's inner loop71DELEGATED, `3.naming.md` over src/Orders/:72```733.naming.md | Pass 1 - BLOCKER: 0, MAJOR: 1, MINOR: 2, DECIDED: 074open: [(MAJOR, OrderSvc.cs:14, abbreviation in public type), (MINOR, OrderQueries.cs:22, vague 'data' param), (MINOR, OrderQueries.cs:41, vague 'tmp' local)]75```76- RUN dispatched aspnet-verifier as a read-only auditor; the open set above is its result.77- FIX: OrderSvc -> OrderService (clear); the two vague names renamed to follow the OrderQueries naming precedent, logged to DECISIONS. Dispatch aspnet-implementer with that findings-plan.78- Pass 2 re-runs the auditor -> `open: []` -> **SATISFIED**; advance to the next file.7980## RULES (these keep autonomous self-judgment honest)81- Decide, do not ask. Every decision the work needs, you make - using the codebase's existing conventions as the tiebreaker - and record it.82- The findings gate - a candidate is a finding only when all four are answered explicitly: what breaks (the concrete wrong outcome - 'it differs from a preference, another codebase, or a reference doc' is not an answer); who notices, and when (named, with the trigger); is it actually new (behavior already recorded as a known limit or a prior decision is a re-measurement, not a discovery); has the project already decided it (a choice recorded in CLAUDE.md or the architecture docs is a **Deliberate tradeoff** - never re-raise it). A gate-passing defect is **Must fix**: it enters the open set. A true-but-not-actionable observation is **Worth knowing**: note it in the pass output, never in the open set - and never 'fix' it.83- Do not invent a finding to demonstrate diligence, and do not omit one to keep a pass short. `open: []` on pass 1 is a valid, expected result on healthy code - a stage that finds nothing is SATISFIED on pass 1, and reporting it is a success, not a weak audit. Equally, twenty real findings means the open set lists all twenty: PLATEAU and OSCILLATION are read off set identity across passes, so a truncated set silently breaks the stop conditions.84- 'Satisfied' means the explicit bar is met - not 'this looks fine' or 'good enough'. Show the score; it is the proof.85- List every remaining item before you stop a file. Never declare a file done with hidden open items.86- Every finding is resolved one way: fixed, decided-and-applied, marked out of scope, or could-not-apply with a reason. Nothing is silently dropped.87- Never weaken, skip, or delete a check, test, or assertion to make a bar appear met. If a fix would break a test, that is a finding, not a fix. The final gate's anti-gaming sweep checks the cumulative diff for exactly this.88- Make the smallest change that resolves each item. Avoid rewrites that introduce new findings - they make the loop diverge instead of converge.89- For gate-based files, the command is the bar - a passing command beats your opinion. Self-judgment is only the fallback for things no command can check, like naming or design quality.90- An enumerable finding class - one a grep or glob can list exhaustively (a banned API, a naming pattern, a suppression marker) - pairs the model audit with the deterministic scan and reconciles the two lists; a model-only sweep misses members (measured: five auditors together missed 6 of a class's 81 instances that a one-line grep listed).91- The main session is the only orchestrator - never instruct a subagent to dispatch another; the auditors and implementers this loop dispatches (domain verifiers, implementers, resolvers) carry no Agent tool. A stage needing a verdict and a fix is two dispatches from here, not one nested one.9293## OUTPUT94Per pass: the one-line score and open set, plus a short note of what you fixed and decided.95Per file: the outcome line.96Final report (whole pipeline):97- The run order, and each file's outcome.98- The final gate: build + tests result, and the anti-gaming sweep over the cumulative diff (clean, or what was reverted and which stage gamed it).99- Remaining findings per file, if any.100- DECISIONS log: `<LOOP_DIR>/DECISIONS.md` - every judgment call across all files, each with the precedent it followed (or an explicit note that none existed), appended as it lands in either mode and reviewable after the fact; the report names the file and its entry count, never re-pastes it (the close is an answer like any other - the answer-length hook blocks a wall of prose).101- OUT OF SCOPE / COULD-NOT-APPLY: anything deliberately left, with reasons.102- Leftovers - what the pipeline's gate and audit runs started and still have up (containers, seeded test data, background processes), or `none`; anything listed gets tear-down-vs-keep through AskUserQuestion batched with the close, teardown recommended - never touching what the run did not start.103- `memories purged: <names|none>` - DELEGATED runs purge the serena hand-off notes fold-first at close (the rule and receipt shape: `references/delegated-mode.md`).104- Overall summary of changes.105106## NOTE ON CONVERGENCE107This is a single forward pass through the files. A later file's edits are not re-checked against earlier files. If you want a full fixpoint, run the whole pipeline again - a clean second run (every file SATISFIED, or a stable PLATEAU) means it has converged. Order the files by blast radius so later stages do not invalidate earlier ones: structure (widest - a move changes a symbol's public path, so every later finding would have to be re-keyed), then code-quality (it carries architecture-conformance), then naming, then logging (its messages are written against the settled names, and its edits - a log line added, a duplicate removed - move nothing a later stage keys on), then comments.