pi-gauntlet 8.2.1 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +2 -2
- package/agents/loop-implementer.md +19 -4
- package/extensions/lib/plan-check.test.ts +10 -0
- package/extensions/lib/plan-check.ts +2 -2
- package/package.json +1 -1
- package/skills/brainstorming/SKILL.md +2 -0
- package/skills/gauntlet-resume/reference/reconstruction.md +6 -6
- package/skills/loop-implementation/SKILL.md +40 -21
- package/skills/loop-implementation/reference/action-spend.md +10 -0
- package/skills/loop-implementation/reference/coordinated-legs.md +5 -5
- package/skills/loop-implementation/reference/interrupted-recovery.md +10 -0
- package/skills/loop-implementation/reference/unreachable-returns.md +13 -0
- package/skills/verification-before-completion/reference/conformance-check.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v8.3.0 - 2026-11-06
|
|
4
|
+
|
|
5
|
+
- Loop execution uses the ledger allowance for interrupted child and seed recovery, exit-verification repairs and grant-funded conformance rounds. Recovery requires checkout ownership and confirmed job exit; stagnation supplies a row-local hint rather than stopping early. Unreachable target failures become audited scope cuts under amend permission, while exhausted named-action bounds still stop. Loop workers bound blocking calls and track longer jobs in isolated POSIX sessions; design approval authorizes named paid or external actions only within their flow-wide bounds.
|
|
6
|
+
|
|
3
7
|
## v8.2.1 - 2026-11-06
|
|
4
8
|
|
|
5
9
|
- Shape-ticket's AC integrity gate drops workflow-stage proof after splitting bundled observations, retains retired proof in the Reporter note, and routes an emptied AC list to recovery or park.
|
package/README.md
CHANGED
|
@@ -37,9 +37,9 @@ Concretely, one change through the gauntlet:
|
|
|
37
37
|
|
|
38
38
|
0. *(Optional)* Before there's even a spec, `/skill:shape-ticket` can create one tracker issue or repair a comma/whitespace list of issue refs - shaping each into a Context/Problem/Idea/Acceptance Criteria ticket, grounded by a repository audit, an AC integrity check, and a cheap council roast. Repair finishes preparation for all tickets before presenting exact-diff confirmations sequentially in ref order; each approval writes that ticket before the next gate, and may include one optional gated comment for a Reporter note or overlap evidence. The audit checks factual claims, Idea fit, AC mechanisms against cited repo guidance, and already-stated observable legs in configured sibling checkouts. It reports in-motion work and attempts a best-effort scenario through authorized current-system reads, without promising reproduction or a fix; missing access or nothing to observe is reported, not a new approval gate. Implementer detail moves into the gated Reporter note; brainstorming reads that note with the ticket so the spec retains the detail. A failed roast is retried once, then surfaced inline at the gate if it fails again. It's a tool, not a phase: no worktree, no plan/phase tracker, runs from any repo state. The agent may start it on its own when the ask is "file a ticket" or another skill routes there; the write still waits for your yes on the presented diff. Similarly, `/skill:chase-bug` triages a raw bug report into an evidenced verdict - and can hand off to shape-ticket, brainstorming, or a bounded hotfix - before any spec exists.
|
|
39
39
|
1. Opt in with `/skill:brainstorming` and describe the change. The command is the reliable discovery-and-entry path; explicit prose requesting brainstorming/the gauntlet also supplies consent when the skill is already loaded or an available instruction or route identifies it. An ordinary implementation request or an agent recommendation is not consent. A leading run of GitHub references (`#N`, `owner/repo#N`, or a `/pull/N` or `/issues/N` URL), separated by whitespace or commas, resolves each reference as a PR first: related open, same-repository, non-fork PRs on one base form one rework subject, including drafts. Admission runs in listed order and relatedness is checked before provisioning; the first retained PR is home, whose existing branch rebases onto the fetched PR base by default, then member commits replay onto it in listed order. The first intent word `merge-forward` opts out and keeps the merge path. An unresolved conflict after its scoped helper aborts that step and continues to the spec with the repair as Task 1. A single non-PR reference follows the ticket path. The first non-reference token starts intent text; mid-sentence references and other ticket/free-text subjects keep their existing paths. The combined code, PR-carried specs, claims, and review threads are the brainstorm input, with each PR's provenance retained; only home's bound ticket supplies acceptance criteria, while member tickets supply context. A single PR retains the same rework path without member replays or a close offer. The combined state is judged against constraints from the fetched current base HEAD, not the fork point or the PRs' proposed policy edits; see the [PR-subject contract](skills/brainstorming/reference/pr-subject.md) and [PR-head worktree owner](skills/using-git-worktrees/reference/pr-head.md). **`brainstorming`** sets up an isolated worktree (on the existing branch for PR rework), explores the codebase, and turns the subject into a written spec - when its recon finds a cited case that the ask is the wrong change (misdiagnosed, wrong-sized, already solved, a band-aid, or cutting across a sound pattern - including a repo convention that is itself debt) and can name the alternative, question one is a framing question (`as framed`, `pivot: <alternative>`, or `smaller or none`); otherwise it opens with one sentence naming what it checked, and every approach it proposes ends with a `Pattern:` line naming what it follows or cuts across; when the run starts from a ticket, the spec carries the ticket's acceptance criteria verbatim, each with a disposition (`in-scope`, `deviates:`, `deferred:`, `venue:`, `elsewhere:` for a row another repo's part delivers), scope cuts come only from your answer to a cut question and are listed at the gate, the conformance gate checks the in-scope ones, and `/skill:check-delivery` verifies `venue:` rows before the prod deploy. A multi-model critique runs on it automatically. If the spec replaces a known prior spec, brainstorming marks the predecessor with a `> **Superseded by:**` banner under its title (default format, syntax overridable via `.pi/gauntlet-overrides.md`; candidates come from brainstorming's scout recon, never a mechanical sweep). **You read and approve the spec - human gate 1.** Options 1/2/4/5 approve and pick an engine; option 6 approves the content only: it writes `**Engine:** deferred` under `**Amend-grant:** none`, pushes the branch, opens a draft PR carrying just the spec, prints the URL, and ends the flow - no plan, no loop, no handoff brief. For a coordinated spec, it first pushes every companion branch to origin, then opens one home draft PR; it creates no companion PRs. A later `brainstorming #N` reconstructs the recorded companions from their origin branches before re-presenting the implementation gate; the [publication and re-gate owner](skills/brainstorming/reference/spec-pr.md) defines all-member preflight, recovery, and cleanup. The branch stays; a gauntlet-owned worktree is removed, a host-owned checkout is reported and left. Option 6 is withheld on a PR subject (`Withheld: draft PR - #N already exists`) and when the branch's diff against the default branch is not spec-only. A later `brainstorming #N` on that PR classifies it from the diff alone: one added spec carrying the marker plus banner-only predecessor edits re-presents the gate with 1/2/4/5 (3 only when the spec commit carries a council audit) and skips gather, questionary, council, and scout; a spec-only diff without the marker prints `spec-only PR without the gate marker - running lint and council` and takes the normal brainstorm path with the carried spec as the draft; any other diff takes the rework path. Approval at that re-gate writes `**Engine:**`, `**Amend-grant:**`, and `**PR:** <owner/repo#N>` as a new commit on the PR branch and chains into planning or the loop as usual. Before approval, PR rework's sole write/run exception outside the spec directories permits only the base sync (rebase or merge), each member replay or merge, their conflict helpers' edits to the conflicted files, and their scoped conflict tests; other subjects have no implementation code yet.
|
|
40
|
-
2. By default, **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files. Experimental approval options 4/5 instead select **`loop-implementation`**: the plan phase is skipped and a stamped acceptance-criteria ledger replaces the task plan. Option 4 retains amendment review; option 5
|
|
40
|
+
2. By default, **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files. Experimental approval options 4/5 instead select **`loop-implementation`**: the plan phase is skipped and a stamped acceptance-criteria ledger replaces the task plan. Option 4 retains amendment review; option 5 auto-applies amends, including unreachable-row cuts, and funds conformance rounds up to the allowance when the cap blocks. Redraws, exhausted bounds and unproven recovery still stop. See [Loop engine operations](doc/configuration.md#loop-engine-operations).
|
|
41
41
|
3. **`subagent-driven-development`** executes the plan in waves, with task implementers followed by one integrated `wave-reviewer` after the scoped test gate passes. The reviewer checks anchored spec clauses and code quality together; repairs stay on the current tree and pass the same gate before re-review. TDD-locked: red, green, refactor. Independent implementation, review, and council batches remain parallel, but their dispatches are foreground: the orchestrator waits for terminal results before accepting work or advancing a phase.
|
|
42
|
-
The loop alternative to step 3 runs one fresh `loop-implementer` per seed or row iteration, without implement-phase reviewers. Each row starts with the shared allowance (default 4); approval replies such as `4; allowance 6` override it for one run. Under either loop approval option, attempt `escalateAfter + 1` (default 4), clamped to the last allowed attempt, escalates once per row on `escalationLoop.implModel` (the main-loop model when unset); later attempts use the ordinary worker model
|
|
42
|
+
The loop alternative to step 3 runs one fresh `loop-implementer` per seed or row iteration, without implement-phase reviewers. Each row starts with the shared allowance (default 4); approval replies such as `4; allowance 6` override it for one run. Under either loop approval option, attempt `escalateAfter + 1` (default 4), clamped to the last allowed attempt, escalates once per row on `escalationLoop.implModel` (the main-loop model when unset); later attempts use the ordinary worker model. The allowance also bounds seed and exit-verification repair counts; verification repairs use the same escalation model and count home repair commits plus an unmatched `pending: verify` reservation. Stagnation supplies a row-local hint, not an early stop. Interrupted returns spend attempts after ownership-fenced recovery: the driver confirms owned jobs exited before resetting the checkout; unknown ownership or failed cleanup requires a human decision. An admitted `unreachable:` target failure becomes an audited scope cut under amend permission, never a passing row. At a row stop, `retry <n> | <hint>` adds one attempt to that row, while `rows +N` raises every row's allowance. Attempts never reset and there is no total iteration cap. Ledger refresh completes implement when every row is closed; verify step 1 runs the gate set: deduplicated (owning checkout, command) pairs from done rows' recorded checks, with ownership from the ledger. Gate output goes to logs; the driver keeps exit codes and paths, not test output. CI on push owns the full run.
|
|
43
43
|
|
|
44
44
|
4. **verify**: the parent first runs the plan's full verification command set for waves, or the ledger gate set for loop; only a passing result permits whole-diff code review, then the **conformance gate**. A review fix invalidates that result, so the parent reruns the same set before the next review or conformance gate. Loop conformance repairs and finish also use the gate set, never the ledger's full `verification:` command. When the overrides file declares a happy path for the touched paths (see [Project-specific overrides](#project-specific-overrides)), the parent runs it once here, between code review and the conformance gate, and the reviewer reads its transcript as runtime evidence - a hang or a failed request shows up in the audit with the transcript quoted - as a gap when an origin clause ties to it, otherwise as a `happy-path: failed - unattributable` line - never as a silent green. The conformance subagent reads the finished code and docs against your *original words* from step 1, not the plan, and reports per-requirement: delivered, partial, missing, drifted, or unauthorized. Unauthorized rows - shipped surface no human input asked for, whether it crept in or was laundered through the spec - follow their recommendation like every other row: a contained removal auto-runs, anything another requirement leans on is deferred with a plain-language "I'd cut it / I'd keep it" recommendation. Inside a brainstorming-entered flow this gate is machine-blocked from being skipped. Compatible executable recommendations auto-run through an isolated fix-and-re-audit loop with no prompt; anything still open surfaces as a numbered decision brief - one item per decision, the problem in plain words first, lettered options each with a one-line consequence, and `Recommended: <letter> - <reason>` or `No recommendation - pick one`. Reply with one line per item (`1. B`), or bare `1` to take every recommendation (no-recommendation items are re-asked by number); a current `CONFORMS` / no-concerns result goes straight to the branch options with no extra conformance sign-off.
|
|
45
45
|
5. **`finishing-a-development-branch`**: PR, draft PR, squash, keep, or discard; PR rework's row 1 offers a lease push of the rebased home branch to the existing PR (`Base:` records in `merge:` form push non-force). A spec whose header carries `**PR:**` (approved at a spec-PR re-gate) and no `## Rework record` replaces the two create rows with `Push to PR #N and mark it ready for review` and `Push to PR #N, keep it a draft` (`Push to PR #N (already ready for review)` when the PR is already ready): both push without force after strip-and-seal, the first then runs `gh pr ready`, neither rewrites the PR body, and both are withheld when origin's branch head is no longer an ancestor of local HEAD. For coordinated specs, these [header-linked rows 1/2](skills/finishing-a-development-branch/reference/spec-pr.md#push-rows-12) deliver companions in recorded order before one home seal carrying every companion PR URL, then push home and apply its readiness choice. Row 1 makes companion drafts ready too; row 2 creates drafts but never converts an already-ready PR back to draft. Companion URLs appear in the shipped summary, companions first and home last, not in the unchanged home PR body; keep that summary for cross-repo review because successful home delivery removes receipts. A spec still carrying `**Engine:** deferred` stops finishing (and `gauntlet-resume`) with `spec approved for handoff only - run brainstorming #N` before any phase change, verification, or push. The PR-rework push appends a `## Rework` block naming absorbed PRs while retaining the original description bytes; the header-linked `**PR:**` push leaves the body untouched. Only after a successful rework push and home-description edit does one gated confirmation show the exact close comments and eligible member targets, linking home; declining or any other finish option leaves members open. Closing never deletes member branches, and finish posts no review-thread replies. Its `Before:` handle includes the full portable pre-rework SHA and the local `refs/gauntlet/pre-rework/pr-<N>` ref in the rework checkout. The [finishing owner](skills/finishing-a-development-branch/SKILL.md#pr-subject-row-1-push-to-the-pr-branch) defines the landing and body-update contract. Once a PR exists, run `/skill:gatekeep-pr <pr>` to verify it before merging - it judges the diff against the spec at the PR's head (the acceptance-criteria dispositions and Design you approved; the PR description when no spec applies) - rows the spec defers or deviates are settled, every other row needs its mechanism (code, tests, docs) - and against the rubric; whatever can be seen only after merge is left to step 6. **Human gate 2** - the only other decision you make.
|
|
@@ -17,7 +17,7 @@ Append one decision line per changed row to the ledger's `## Decisions` section
|
|
|
17
17
|
|
|
18
18
|
`row <n> <done|failed> | <one sentence: what was done> | <one sentence: reusable artifacts for done, retry guidance for failed>`
|
|
19
19
|
|
|
20
|
-
For `done`, name what later rows can build on (a file, helper, interface or fixture) and how to reuse it; write `nothing new to build on` when the row added no reusable artifact, including an extra closed by a check without further edits. For `failed`, state what the next iteration should not redo or should try differently. Limit each sentence to 200 characters. Use the seed contract below for `target: seed`.
|
|
20
|
+
For `done`, name what later rows can build on (a file, helper, interface or fixture) and how to reuse it; write `nothing new to build on` when the row added no reusable artifact, including an extra closed by a check without further edits. For `failed`, state what the next iteration should not redo or should try differently. Limit each sentence to 200 characters. Put action accounting inside the first sentence, not in a third slot. Use the seed contract below for `target: seed`.
|
|
21
21
|
|
|
22
22
|
## Inputs
|
|
23
23
|
|
|
@@ -30,8 +30,15 @@ Read additive inputs `Leg:`, `Rules:`, mapped original AC and, for companions, e
|
|
|
30
30
|
1. Read the given spec in full before reading the ledger or code. Read the given ledger next. Save the exact `pending:` tuple and bumped `iterations:` count before editing.
|
|
31
31
|
2. Close the `target` row first. Read every `row <n> ...` line for the target row from `## Decisions`, oldest first, before choosing an approach. Treat them as ordered guidance: avoid what a `failed` line's third slot says not to redo, follow what it says to try differently, and never repeat an approach a prior line of this row rules out. Exclude other rows' lines from guidance for this target. Read `retry` and `escalated` lines in the same pass: use the retry hint as guidance; treat the escalation marker as historical evidence that escalation is spent, and never infer the current attempt's model from it. Keep `previous decision` as the latest admitted target line and the tie-break for most recent. Use `previous decision` and `hint` to avoid repeating work and to try a different approach; keep the target unchanged.
|
|
32
32
|
3. Run `git diff --stat <base>`. Open full diff hunks only for files the row being worked on touches, using `git diff <base> -- <row files>`; read the relevant code before editing it.
|
|
33
|
-
4. Implement the target row using Three-scenario TDD and Test economy below. Treat empty evidence on an unreached row as a normal state after partial seeding, not a seed failure; create its first check before implementing it, then close or fail the row with command-first evidence under step 5. Run only its targeted check under Evidence command, never the owning checkout's full verification command or the full suite.
|
|
34
|
-
5. Update the target row's mutable cells: set `status` to `done` on a passing check or `failed` on a failing check, increment `attempts` by 1, and set `evidence` to one physical Markdown table cell opening with the command you ran under Evidence command, up to the first unescaped semicolon, plus at most three result lines separated by semicolons. Escape pipes as `\|` and use plain text without angle-bracket markup. On failure, record the concrete cause in plain words: the spec-vs-code contradiction, failing assertion, or missing credential, tool, or fixture. Keep reasoning and transcripts out of evidence.
|
|
33
|
+
4. Implement the target row using Three-scenario TDD and Test economy below. Apply step 5's action authorization before running a check. Treat empty evidence on an unreached row as a normal state after partial seeding, not a seed failure; create its first check before implementing it, then close or fail the row with command-first evidence under step 5. Run only its targeted check under Evidence command, never the owning checkout's full verification command or the full suite.
|
|
34
|
+
5. Before replacing an evidence cell, repeat each carried `ran <action> (<k> of <bound>)` and `bound spent: <action> ...` record verbatim in that row's own decision sentence before any new spend, including records from a successful seed; retain their ordinals and count copies only once. Treat a dropped record as a validation miss even when the replacement check passes. Update the target row's mutable cells: set `status` to `done` on a passing check or `failed` on a failing check, increment `attempts` by 1, and set `evidence` to one physical Markdown table cell opening with the command you ran under Evidence command, up to the first unescaped semicolon, plus at most three result lines separated by semicolons. Escape pipes as `\|` and use plain text without angle-bracket markup. On failure, record the concrete cause in plain words: the spec-vs-code contradiction, failing assertion, or missing credential, tool, or fixture. Keep reasoning and transcripts out of evidence. Run ordinary local checks as today. Apply the action rules below before any paid or external action; an approved spec clause in an acceptance row or Design must name its bound (runner, inputs, count per flow). Read all earlier decision lines, evidence cells, `loop: repair` commit bodies since base and caller-supplied home repair records in `hint` for `ran <action> (<k> of <bound>)` and `bound spent: <action> (<k> of <bound>)`, including other rows, across seed, rows, repairs and finish. Use the highest recorded k for each action, counting duplicate records of one spend once; use these records only for accounting, not target retry guidance. Before launching an action, append `bound spent: <action> (<k> of <bound>)` to the jobs file named under Evidence command and retain it through return; append `ran <action> (<k> of <bound>)` after confirmed execution. Preserve action records when removing exited process lines. Treat a reservation without confirmation as spent, not permission to rerun. With uncertain prior execution and neither a reservation nor affirmative no-action provenance, stop for parent recovery rather than infer zero spend.
|
|
35
|
+
|
|
36
|
+
| Observed action state | Result |
|
|
37
|
+
|---|---|
|
|
38
|
+
| Named, prerequisites present, count below bound | Run inside that bound without asking; append `ran <action> (<k> of <bound>)` within the row's decision sentence, with k one more than the highest recorded k (zero with no spend history). Put the same record in the evidence result line. Reuse its output for local rechecks rather than spending it again. |
|
|
39
|
+
| Concrete prerequisite no permitted attempt in this checkout can supply: credential, environment or data not present, or action the spec does not name | Record `unreachable: <what is missing> - <where it can run>` as the first result line after the check name; set the target `failed` and make no further attempt in this session. Name the missing prerequisite and runnable venue; do not ask the driver for permission. |
|
|
40
|
+
| Named action's count exhausted | Record `bound spent: <action> <k> of <k>` as the first result line and set the target `failed`; do not run the action or mark it unreachable. |
|
|
41
|
+
|
|
35
42
|
6. Append the target's decision line defined in Output contract. Only after the target is `done`, consider further open rows of your leg whose work sits in the files or helper just changed: a check already passing, or a small step on the same code. Take extras one at a time; write or name each row's selective check before implementing it, apply Three-scenario TDD, make it pass, record command-first evidence bounded as in step 5, and append its decision line. Set each extra `done` with attempts unchanged. Do not look elsewhere to pad the return or start a row you cannot finish in this session. Revert all code, test, cell and decision changes for an unfinished extra before committing; preserve the completed rows' changes.
|
|
36
43
|
7. Remove the `pending:` line from the ledger in your commit. Stage your row changes and the ledger explicitly. Commit exactly once with subject `loop: row <n> <status>`, naming the target only. Check `git status --porcelain` and leave the working tree clean.
|
|
37
44
|
8. Reply with the appended decision lines only, target first.
|
|
@@ -56,15 +63,23 @@ Keep and extend the test from earlier attempts on a retry; never start it over.
|
|
|
56
63
|
|
|
57
64
|
## Evidence command
|
|
58
65
|
|
|
66
|
+
Bound every blocking tool call with `timeout -k 30 <n>`, n at most 600 seconds: a foreground command, a poll, a wait. Include bookkeeping commands such as git reads, staging, commits and status, not just checks. Wrap shell builtins through `timeout -k 30 <n> bash -c '...'`. Keep the tool's own deadline above n + 30 and retain the executed timeout wrapper in evidence. Record a timeout as a failed attempt with `timed out after <n> s` in evidence; do not retry the timed-out check in this iteration.
|
|
67
|
+
|
|
68
|
+
Preflight python3 and timeout before launching longer work; missing facilities stop before spawning, without dependency installs, with the executed preflight as the evidence command. Start the scratch Python controller from a bounded launcher that returns immediately: use `subprocess.Popen(["python3", controller_path], start_new_session=True, stdout=controller_log, stderr=controller_log)`. Let the controller outlive the launcher's short timeout rather than wrapping the controller's lifetime in that timeout. Inside the controller use `subprocess.Popen(["timeout", "-k", "30", "3600", ...command], start_new_session=True)` and redirect stdout and stderr to a log under `${TMPDIR:-/tmp}`. Keep the controller alive to wait, reap and record the exit code. Immediately append `<pid> <process-start-identity> <command>` to `${TMPDIR:-/tmp}/loop-<base SHA>-<iteration>.jobs`, using the leg's base and the pre-bump task iteration, not the consumed ledger count. Capture the OS-observed process start identity and full command at launch; retain launch provenance, including the controller identity, for the parent. Preserve existing jobs lines. Run each poll in a separate tool call bounded as above, never a long polling loop inside one call.
|
|
69
|
+
|
|
70
|
+
Wait for affirmative exit evidence from the controller before removing a jobs line. For cancellation, require the live start identity and command to match the launch record and PGID to equal the recorded pid. Recheck identity and command immediately before signaling the owned group with `kill -TERM -- -<pid>`; wait at most 10 s, then recheck ownership before `kill -KILL -- -<pid>` on a surviving group. Require the controller to reap the job, `kill -0 <pid>` to fail and the group to be absent; remove only that job's line and confirm the controller exited with a bounded process check before ordinary completion. A 3600-second timeout records `timed out after 3600 s`. Missing launch provenance, unavailable identity or a mismatch means cleanup incomplete: signal nothing, preserve records and changes, and stop safely for parent recovery rather than claim completion. Never treat a missing identity as proof of exit or reply as completed with a job running.
|
|
71
|
+
|
|
59
72
|
Record one selective invocation: a test file, test id or filter, or an asserting command. Use no `;`, `|` or `&&` in that command; use the runner's filter flags rather than a shell pipeline. Never record the owning checkout's full verification command (the home ledger's `verification:` header or a leg's recorded command), or a runner with no file or filter. Keep the command first and results bounded as in step 5: `node --test extensions/x.test.ts; 3 passed; 0 failed`.
|
|
60
73
|
|
|
74
|
+
Never record a paid or external action as the evidence's first segment: verify, fix rounds, conformance and finish rerun it. Record the local replay or fixture check as the command and the action in a result line.
|
|
75
|
+
|
|
61
76
|
Require the recorded command to exit nonzero when it selects no test. Before recording a filter, verify its runner's behavior once: run it with a name that matches nothing and require a nonzero exit; otherwise record the file. For Node, record the test file: `node --test` with a missing file exits nonzero, but `--test-name-pattern` with no matching name exits 0 and reports `tests 0`.
|
|
62
77
|
|
|
63
78
|
## Target seed
|
|
64
79
|
|
|
65
80
|
Use this contract for `target: seed`, normally iteration 0. After a human-authorized recovery discards an interrupted seed, repeat seeding at the consumed iteration count; keep the ledger's `iterations` unchanged.
|
|
66
81
|
|
|
67
|
-
Replace steps 2-6 with evidence seeding for at least one non-cut row; seed a subset or all open rows. Keep the spec-first read order and scope diff hunks to the seeded rows' files. Leave unreached rows unchanged.
|
|
82
|
+
Replace steps 2-6 with evidence seeding for at least one non-cut row; seed a subset or all open rows. Apply step 5's action authorization and durable accounting before every seed check or action; record action spends in the seeded evidence, preserving the fixed seed decision below. Keep the spec-first read order and scope diff hunks to the seeded rows' files. Leave unreached rows unchanged.
|
|
68
83
|
|
|
69
84
|
For each selected `open` row, write or identify its failing test (use an asserting command for a trivial or assertion-only row) and record the command you ran in `evidence` under Evidence command. Close a row already satisfied by the codebase as `done` only with passing baseline evidence; record the command of the passing check for every baseline closure. Keep other open rows `open`. Keep every row's `attempts` at 0; never set `failed`. Preserve `cut` rows and their disposition evidence. Bound evidence as in step 5.
|
|
70
85
|
|
|
@@ -1369,6 +1369,16 @@ for (const [name, change] of Object.entries({
|
|
|
1369
1369
|
})) test(`coordinated metadata rejects ${name}`, () => {
|
|
1370
1370
|
assert.ok(checkPlan(change(coordinatedLedger()), coordinatedSpec, emptyPort).findings.length);
|
|
1371
1371
|
});
|
|
1372
|
+
test("closed coordinated ledgers admit member verification reservations only", () => {
|
|
1373
|
+
const closed = coordinatedLedger().replaceAll("| open | 0 | |", "| done | 1 | test -f result; pass |");
|
|
1374
|
+
for (const [repo, accepted] of [["repo-b", true], ["stranger", false]] as const) {
|
|
1375
|
+
const source = closed.replace("iterations: 0", `iterations: 1\npending: verify | ${repo} | abc1234`);
|
|
1376
|
+
const findings = checkPlan(source, coordinatedSpec, emptyPort).findings;
|
|
1377
|
+
if (accepted) assert.deepEqual(findings, []);
|
|
1378
|
+
else assert.ok(findings.some((f) => f.reason === "invalid pending tuple or target leg"));
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
|
|
1372
1382
|
test("scope textual order does not change original AC or member order, and design claims no ownership", () => {
|
|
1373
1383
|
const spec = coordinatedSpec.replace("scope: AC 1, AC 2", "scope: AC 2, AC 1\ndesign: AC 3 touches lib/other.ts");
|
|
1374
1384
|
assert.deepEqual(checkPlan(coordinatedLedger().replace("| 4 | open | 0 | |", "| 4 | done | 1 | checked a\\|b |"), spec, emptyPort).findings, []);
|
|
@@ -1226,9 +1226,9 @@ function coordinatedMetadata(lines: string[], legs: ReturnType<typeof parseLegs>
|
|
|
1226
1226
|
const pending = header("pending");
|
|
1227
1227
|
if (pending.length > 1) add(pending[1].i, "duplicate pending tuple");
|
|
1228
1228
|
for (const row of pending) {
|
|
1229
|
-
const m = /^(seed|[1-9]\d*) \| (\S+) \| ([a-f0-9]{7,40})$/.exec(row.value);
|
|
1229
|
+
const m = /^(seed|verify|[1-9]\d*) \| (\S+) \| ([a-f0-9]{7,40})$/.exec(row.value);
|
|
1230
1230
|
const repo = m?.[2].toLowerCase();
|
|
1231
|
-
if (!m || !legs.some(l => l.repo === repo) || (m[1] !== "seed" && pairs[Number(m[1]) - 1]?.leg !== repo)) add(row.i, "invalid pending tuple or target leg");
|
|
1231
|
+
if (!m || !legs.some(l => l.repo === repo) || (m[1] !== "seed" && m[1] !== "verify" && pairs[Number(m[1]) - 1]?.leg !== repo)) add(row.i, "invalid pending tuple or target leg");
|
|
1232
1232
|
}
|
|
1233
1233
|
const mapping = lines.findIndex(l => l === "## Leg mapping");
|
|
1234
1234
|
if (lines.filter(l => l === "## Leg mapping").length > 1) add(mapping, "duplicate leg mapping section");
|
package/package.json
CHANGED
|
@@ -155,6 +155,8 @@ Start the message with `gauntlet: question` alone at column zero on the first ph
|
|
|
155
155
|
|
|
156
156
|
Use two rounds, targeting 300-500 words each, with one approval each; revisions remain within that approval point. Ask once per round; round-1 approval without correction confirms the predecessor. Round 1 covers architecture, responsibilities, data flow, and `supersedes <path>, <scope>` when applicable. Round 2 covers errors, edges, tests, and `## Documentation impact`. In round 2, read and apply [Documentation impact](reference/documentation-impact.md), including its verbatim template; cite that portable relative path in the spec; do not restate its categories. Ask the user when doc impact is unclear. Unreadable -> stop the step with a blocking error. Cite the draft's `Docs touched:` entries as candidates for "Materially amended existing docs"; admit or drop each by that owner's materiality bar, never list them automatically. In round 1, carry chosen `Removes:`/`Adds:` into Design as exhaustive `Remove:`/`Add:` imperatives naming every moving part; route unlisted parts through `reference/amendment-surface.md`. In round 2, write `## Tests`: one `<observable> - <test name or file>` per acceptance row and Design edge/error clause; `<observable> - none: <why>` for untestable.
|
|
157
157
|
|
|
158
|
+
In round 2, name every paid or external action needed for implementation or verification in Design with its runner, inputs and count for the whole flow across seed, rows, repairs and finish. Treat design approval as authorization within those bounds without per-step permission prompts; state that the loop treats an action without such a clause as unreachable, and require separate explicit authorization to add an unnamed action to Design.
|
|
159
|
+
|
|
158
160
|
## Ticket Handling
|
|
159
161
|
|
|
160
162
|
Read [Ticket Handling](reference/ticket-acceptance.md) at first use - before gathering context, even with no ticket. Steps 4 and 8 carry the same read behind an in-context check so a restored session (`gauntlet-resume` routes there) loads it once; a same-session redraw or a second brainstorm in one session reuses the content already in context. Unreadable -> stop with a blocking error, never reconstruct from memory.
|
|
@@ -94,16 +94,16 @@ After confirmation:
|
|
|
94
94
|
2. Call `phase_tracker({ action: "start", phase: "brainstorm" })`, then `phase_tracker({ action: "skip", phase: "brainstorm", reason: "resume: <spec path>" })`, then `phase_tracker({ action: "start", phase: "plan" })`.
|
|
95
95
|
3. Admit exactly one positive safe-integer `cap:` or `allowance:` header; both or neither is `ledger header malformed: <observed header lines>`, requiring human repair by hand. Call `plan_check({ planPath: <absolute ledger path> })` with legacy-compatible admission. On FAIL, stop with findings, retaining plan in_progress. Start the message with `gauntlet: stuck` followed by the findings reason on that line; never enter `## Plan repair` or writing-plans. On PASS, call `phase_tracker({ action: "skip", phase: "plan", reason: "resume: <spec> (loop engine)" })`, then `phase_tracker({ action: "start", phase: "implement" })`. Use the resolved absolute spec path as `<spec>` in the reason. Restore implement through refresh, not `init`.
|
|
96
96
|
4. **Shared allowance boundary (every ledger restore, before phase continuation).** Read `/skill:loop-implementation`. Skip Entry step 1's allowance seeding; restore base, verification, iterations, row attempts and decisions from the ledger without reseeding. Resolve `gauntlet_setting({ key: "loopEngine" })` exactly once at the driver's authorized-restore grant boundary and retain `escalateAfter` in driver memory for this run; share this read with step 4.2, never refresh it inside the loop. On an unavailable tool, stop before any dispatch or write with `cannot resolve escalation threshold: settings tool unavailable (loopEngine.escalateAfter)`. Apply the following order on bare-worktree and brief routes alike:
|
|
97
|
-
1. Apply pending recovery below against the unmigrated ledger, including home returns whose child commit removed the tuple. Validate the original one-commit `<pre-dispatch HEAD>..HEAD` range against its unchanged before-image. For companions, retain unchanged home HEAD and admit the expected iterations-bump-plus-tuple dirt. On unrecoverable attribution or before-image, stop before refresh. Resolve ambiguous-history admission before tracker calls as required below.
|
|
97
|
+
1. Apply pending recovery below against the unmigrated ledger, including home returns whose child commit removed the tuple. Validate the original one-commit `<pre-dispatch HEAD>..HEAD` range against its unchanged before-image. For companions, retain unchanged home HEAD and admit the expected iterations-bump-plus-tuple dirt. On unrecoverable attribution or before-image, stop before refresh. Resolve ambiguous-history admission before tracker calls as required below. Apply the driver's ownership-fenced interrupted recovery before migration; migration changes neither admission ranges nor the home HEAD used for recovery.
|
|
98
98
|
2. Migrate only an admitted, clean, tuple-free ledger with no retained recovery stop. With `cap:` and no `allowance:`, reuse the single restore-boundary settings read and replace the cap line with `allowance: <maxIterationsPerRow>`. Commit only that header replacement as parent `loop: migrate allowance`; preserve iterations, every attempts cell and all decisions. With an existing allowance, use it without allowance resolution or a migration commit; the restore read supplies `escalateAfter` only. Defer migration through any retained recovery stop or dirty tree; after authorized recovery reaches a clean tuple-free tree, migrate before the next dispatch or verification.
|
|
99
99
|
3. Require `allowance:` and no `cap:` before continuation, including for all-closed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`. For a retained recovery stop or unresolved dirty tree, defer this final validation with migration and project the unmigrated ledger solely to report the stop.
|
|
100
100
|
4. Call `plan_tracker({ action: "refresh", path: <absolute ledger path> })` exactly once after phase restoration, recovery and eligible migration/final validation, before any unresolved dirty-tree stop or dispatch. On verify/ship, restore the saved mixed task list first as `brief-contract.md` specifies; on implement, use no `init`. On refresh failure, stop with its findings and leave the existing task list untouched. Read `plan_tracker status` and report its exact observed state, never an inferred list.
|
|
101
|
-
Render the allowance header, rows, iterations, attempts, effective allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. Compute each effective allowance as the header plus one per matching retry decision; ignore the retry's audit ceiling. Keep `cap +N` history as inert text and restore no funded rounds.
|
|
101
|
+
Render the allowance header, rows, iterations, attempts, effective allowances and all decisions; distinguish the latest operational `row <n> ...` decision from the last physical history line. Compute each effective allowance as the header plus one per matching retry decision; ignore the retry's audit ceiling. Keep `cap +N` history as inert text and restore no funded rounds. For a recovered pending tuple with a recoverable before-image, apply the driver's ## Interrupted recovery below allowance before continuation; require exclusive checkout provenance and confirmed owned-job exits before any reset. Report unresolved cleanup or ownership with the driver's recovery-incomplete header, saved unresolved-row counts and discard-authorization menu, preserving changes and making no redispatch. Keep unrecoverable before-image and ambiguous-history stops. Resume the original phase only after this boundary: implement at `Before each dispatch`; verify/ship at `After the loop` step 1.
|
|
102
102
|
5. Continue at loop step 5, the delivered driver's `Before each dispatch`, with durable iterations and retry data; an all-closed ledger completes implement through refresh and takes `After the loop` step 0. A migrated unresolved row at or above its effective allowance stops under rule 2 without an attempt; keep an allowance-stopped row `failed`. Render a row whose `pending:` tuple is restored or retained as `row <n> in_progress (pending tuple restored)`. Never reset counters or reseed a validated seed.
|
|
103
103
|
|
|
104
104
|
### Pending recovery
|
|
105
105
|
|
|
106
|
-
Recover before dispatch or verification on every ledger restore. Run the read-only admission-evidence check below before phase/task restoration on every ledger route, including briefs; resolve its human question before any tracker call. Apply recovery writes only at the ordered pending-recovery step. Read the durable `pending:` tuple (target row or
|
|
106
|
+
Recover before dispatch or verification on every ledger restore. Run the read-only admission-evidence check below before phase/task restoration on every ledger route, including briefs; resolve its human question before any tracker call. Apply recovery writes only at the ordered pending-recovery step. Read the durable `pending:` tuple (target row, seed or verify, repo, pre-dispatch HEAD); the parent's uncommitted iterations bump plus tuple is expected dispatch dirt, not a reason to skip recovery. Route `pending: verify` through the loop driver's After the loop step 1 repair admission/recovery before the row/seed paths below; preserve its reserved count and consumed iteration without a second marker or bump.
|
|
107
107
|
|
|
108
108
|
With no `pending:` on disk, inspect home commit history before any refresh. Find the latest home child row/seed commit that changed this ledger, even when unrelated commits follow it; read its subject and body with `git -C <worktree> log --format=%H -- <ledger path>` and `git -C <worktree> show -s --format=%B <sha>`. Exclude returns superseded by a parent admission/repair or approved ledger mutation proven by the evidence below; never replay those over the parent's current ledger.
|
|
109
109
|
|
|
@@ -116,13 +116,13 @@ Revalidate a clean, exactly-one-commit return through the home row below. For la
|
|
|
116
116
|
| Confirmed admission state | Action |
|
|
117
117
|
|---|---|
|
|
118
118
|
| Confirmed settled | Preserve the current ledger and continue normal restore; require fresh verification/conformance, not historical gate credit. |
|
|
119
|
-
| Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below.
|
|
119
|
+
| Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below. Use the recovered tuple and before-image without another bump. Confirmation that admission was interrupted proves no ownership of later writes: apply the driver's ## Interrupted recovery only with retained exclusive checkout/write provenance and owned-job exit evidence. Missing evidence preserves child and unrelated changes at recovery incomplete; project saved row cells without overwriting the ledger. A completed recovery writes the parent repair with iterations at the recovered consumed count. |
|
|
120
120
|
| Still unknown | Stop without mutation; ask for the missing admission evidence, never turn uncertainty into a discard/reset decision. |
|
|
121
121
|
|
|
122
122
|
| Tuple target | Recovery |
|
|
123
123
|
|---|---|
|
|
124
|
-
| Home leg or single-member `home` | Reconstruct the pre-dispatch ledger from `HEAD:<ledger path>` when HEAD is the tuple SHA, otherwise from `<pre-dispatch HEAD>:<ledger path>`. Compare live HEAD with that SHA. Admit exactly one new home commit with subject `loop: row <n> <status>` or `loop: seed evidence` only through the driver's `## Validate the return`: require a clean tree and the bounded row/decision result, allowing only the consumed iteration and pending removal header deltas. Clear the tuple through the admitted close or ordinary-miss repair.
|
|
125
|
-
| Actual multi-member companion | Apply `/skill:loop-implementation` `reference/coordinated-legs.md` `## Resume`: require unchanged home HEAD and exactly one new companion commit with tuple attribution, then validate its result. Record that leg's admitted rows, decisions or seeded state and SHA, removing the tuple in the home-ledger commit; never rerun the recovered row or its admitted extras.
|
|
124
|
+
| Home leg or single-member `home` | Reconstruct the pre-dispatch ledger from `HEAD:<ledger path>` when HEAD is the tuple SHA, otherwise from `<pre-dispatch HEAD>:<ledger path>`. Compare live HEAD with that SHA. Admit exactly one new home commit with subject `loop: row <n> <status>` or `loop: seed evidence` only through the driver's `## Validate the return`: require a clean tree and the bounded row/decision result, allowing only the consumed iteration and pending removal header deltas. Clear the tuple through the admitted close or ordinary-miss repair. Route zero new commits, multiple commits, dirty or non-DONE returns through the driver's ## Interrupted recovery against the tuple HEAD and its ledger before-image. Require exclusive checkout provenance and verified process identity/exit before reset; after clean/zero-commit observations write the repair with the already-consumed iteration, clear pending and continue at Before each dispatch. Preserve every change at recovery incomplete when ownership or cleanup is unresolved. Unrelated movement, attribution mismatch or an unrecoverable before-image stops without redispatch or double counting. |
|
|
125
|
+
| Actual multi-member companion | Apply `/skill:loop-implementation` `reference/coordinated-legs.md` `## Resume`: require unchanged home HEAD and exactly one new companion commit with tuple attribution, then validate its result. Record that leg's admitted rows, decisions or seeded state and SHA, removing the tuple in the home-ledger commit; never rerun the recovered row or its admitted extras. Route dirty, zero/multiple-commit or non-DONE boundaries through that reference's ownership-fenced interrupted recovery, using the companion tuple HEAD and saved home ledger; preserve state on unrelated movement, attribution mismatch, unrecoverable before-image or unresolved ownership/cleanup; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair in that protocol, clear `pending:` and preserve the consumed iteration. |
|
|
126
126
|
|
|
127
127
|
## Spec with plan
|
|
128
128
|
|
|
@@ -18,7 +18,7 @@ Run this driver in the main session. Carry the absolute implementation worktree
|
|
|
18
18
|
| Otherwise overrides has `## verification-before-completion` | Use its exactly one backticked command; zero or several is a configuration error. |
|
|
19
19
|
| Neither section supplies a command | Discover the project's test entrypoint from its actual manifest/build instructions; print discovery as source. Stop on an unresolved or ambiguous entrypoint. |
|
|
20
20
|
|
|
21
|
-
At seed and at an authorized restore, before entering the dispatch loop, read the spec in full. Decode `**Amend-grant:**` through [amendment-surface Value decoding](../brainstorming/reference/amendment-surface.md). Capture the decoded grant, ordered leg membership, each leg's absolute checkout paths and combined spec/task Rules for dispatch and handoff; use home for zero or one leg. At an authorized fresh-session restore, resolve `gauntlet_setting({ key: "loopEngine" })` exactly once at this boundary and hold `escalateAfter` for the run; share that read with reconstruction's Shared allowance boundary, including legacy allowance migration. With an unavailable tool, stop before dispatch with `cannot resolve escalation threshold: settings tool unavailable (loopEngine.escalateAfter)`; never supply an in-loop default.
|
|
21
|
+
At seed and at an authorized restore, before entering the dispatch loop, read the spec in full. Decode `**Amend-grant:**` through [amendment-surface Value decoding](../brainstorming/reference/amendment-surface.md). Capture the decoded grant, row dispositions, ordered leg membership, each leg's absolute checkout paths and combined spec/task Rules for dispatch and handoff; use home for zero or one leg. At an authorized fresh-session restore, resolve `gauntlet_setting({ key: "loopEngine" })` exactly once at this boundary and hold `escalateAfter` for the run; share that read with reconstruction's Shared allowance boundary, including legacy allowance migration. With an unavailable tool, stop before dispatch with `cannot resolve escalation threshold: settings tool unavailable (loopEngine.escalateAfter)`; never supply an in-loop default.
|
|
22
22
|
|
|
23
23
|
At seed and at an authorized restore, when the held membership has more than one leg, read `reference/coordinated-legs.md` IN FULL now with read at its absolute path; stop on an unreadable reference naming its path, never reconstruct it. On fresh entry apply its `## Entry` section at step 4 instead of the home-only skeleton below, using step 4's resolved allowance seed value. On a restore apply its `## Resume` section before the dirty-tree stop and before any pending recovery. Keep legacy and single-member ledger bytes unchanged, with no coordinated metadata.
|
|
24
24
|
|
|
@@ -44,34 +44,38 @@ allowance: <n>
|
|
|
44
44
|
Use the actual repo-relative spec path alone in the Spec header. Read base with `git -C "<worktree>" rev-parse HEAD`. Index every spec AC in order, including nested disposition lines without treating them as extra ACs; keep row text only in the spec. Initialize explicit/absent `in-scope` and `venue:` rows `open`, attempts 0, evidence empty. Initialize only `deviates:`, `deferred:`, `elsewhere:` rows `cut`, attempts 0, disposition text as evidence. Write `allowance:` immediately after `iterations: 0` using step 4's seed value; never scale it by row count or seed dispatches: 24 non-cut rows at default 4 yield allowance 4. All-cut ledgers keep the same allowance and exit through rule 1 without a seed dispatch. Later cuts, reopens and requirement-preserving amendments leave allowance unchanged; redraw deletes the ledger and reseeds it. Serialize evidence in one physical table cell, result lines separated by semicolons, pipes escaped, plain text without angle markup.
|
|
45
45
|
5. Call `plan_check({ planPath: <ledger path> })`. Stop with findings as a configuration error. Commit the stamped skeleton as `loop: seed ledger`; call `phase_tracker({ action: "start", phase: "implement" })`, then `plan_tracker({ action: "refresh", path: <absolute ledger path> })`, including all-cut ledgers with no seed dispatch.
|
|
46
46
|
|
|
47
|
-
For resume, use the admitted ledger, its base and verification command, and durable iterations and allowance instead of overwriting it. Skip Entry step 1's allowance seeding for an admitted ledger; the allowance setting applies only to fresh seeding, and the restore boundary resolves `escalateAfter` once. Apply `/skill:gauntlet-resume` pending recovery and its `loop: migrate allowance` step before refresh and any unresolved dirty-tree stop. Render rows, allowance and decision history;
|
|
47
|
+
For resume, use the admitted ledger, its base and verification command, and durable iterations and allowance instead of overwriting it. Skip Entry step 1's allowance seeding for an admitted ledger; the allowance setting applies only to fresh seeding, and the restore boundary resolves `escalateAfter` once. Apply `/skill:gauntlet-resume` pending recovery and its `loop: migrate allowance` step before refresh and any unresolved dirty-tree stop. Render rows, allowance and decision history; route a recovered pending tuple through reconstruction's pending recovery and ## Interrupted recovery before any unresolved dirty-tree stop.
|
|
48
48
|
|
|
49
49
|
## Driver holds
|
|
50
50
|
|
|
51
|
-
After seeding, restrict driver reads during implement to the ledger (including saved or committed ledger snapshots), the child's return file (one file reference), git boundary commands (`status --porcelain`, `rev-list --count`, `rev-parse`, `show -s --format=%b` for commit bodies), skill resources at their absolute paths and the overrides file. Keep rows by status, iterations, allowance, the last decision, the decoded amendment grant and each leg's checkout path for dispatch, handoff and stops. Use Entry's captured grant and membership throughout the loop.
|
|
51
|
+
After seeding, restrict driver reads during implement to the ledger (including saved or committed ledger snapshots), the child's return file (one file reference), git boundary commands (`status --porcelain`, `rev-list --count`, `rev-parse`, `show -s --format=%b` for commit bodies, `log --format=%s <base>..HEAD` for repair counts), retained dispatch/write provenance, the child's jobs file, OS process start identity and command, `ps -o pgid= -p <pid>`, `kill`, skill resources at their absolute paths and the overrides file. Keep rows by status, iterations, allowance, the last decision, the decoded amendment grant and each leg's checkout path for dispatch, handoff and stops. Use Entry's captured grant, row dispositions and membership throughout the loop.
|
|
52
52
|
|
|
53
|
-
Never read the spec, source files, test output or logs inside the implement loop. Never diagnose a failure's cause; carry the child's evidence into the next dispatch or human stop. The only log-read exception is the last 20 lines at the human stop in After the loop step 1. Leave spec reads for seed, authorized restore and the amendment action below, outside the loop.
|
|
53
|
+
Never read the spec, source files, test output or logs inside the implement loop. Never diagnose a failure's cause; carry the child's evidence into the next dispatch or human stop. Inside the implement loop, end a turn only with a stop header from ## Human stop; follow every intermediate report with the next ordered-table action in the same turn. The only log-read exception is the last 20 lines at the human stop in After the loop step 1. Leave spec reads for seed, authorized restore and the amendment action below, outside the loop.
|
|
54
54
|
|
|
55
55
|
## Before each dispatch
|
|
56
56
|
|
|
57
57
|
When the held membership has more than one leg, read `reference/coordinated-legs.md` IN FULL now with read at its absolute path; stop on an unreadable reference naming its path, never reconstruct it. Apply its `## Resume`, `## Targeting and dispatch`, `## Companion return validation`, `### Companion commit admission` and `## Amendments` sections together with this driver; never apply `## Entry` here.
|
|
58
58
|
|
|
59
|
+
Read [action-spend durability](reference/action-spend.md) in full now; carry retained repair accounting into this dispatch, including seed and companions.
|
|
60
|
+
|
|
59
61
|
Read the ledger and require its `checks:` line per ## Gate set.
|
|
60
62
|
|
|
61
|
-
Read the ledger and require `allowance:` and no `cap:` before the ordered table, including for seed and completed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`. Keep `iterations:` as a dispatch counter only; it bounds nothing. Count empty child commits and validation misses only after the latest `loop: retry row <n>`
|
|
63
|
+
Read the ledger and require `allowance:` and no `cap:` before the ordered table, including for seed and completed ledgers; otherwise stop with `ledger has no allowance: line - resume through /skill:gauntlet-resume`. Keep `iterations:` as a dispatch counter only; it bounds nothing. Count each row's empty child commits and validation misses only after the latest of `loop: retry row <n>` for that row, `loop: amend`, or any `loop: cut row <n>`; an admitted amendment starts new windows for every row because it changed what rows are measured against. Raising allowance resets neither window. Recover both windows from branch history on resume. Preserve every row's attempts and spent escalation. Before the ordered table, route each admitted failed target through ## Unreachable returns once at admission (including companions), or on resume when admitted but not yet routed; follow that reference's answered-stop rule after human decisions. Apply this ordered table, starting here after each return or human decision:
|
|
62
64
|
|
|
63
65
|
| Order | Observed state | Action |
|
|
64
66
|
|---|---|---|
|
|
65
67
|
| 1 | No `open` or `failed` row | Refresh; require implement complete; continue at ## After the loop step 0. All-cut and baseline-complete ledgers exit here. |
|
|
66
68
|
| 2 | Unresolved row attempts >= effective allowance | Human stop under approval option 4 and option 5 alike. Exempt `done` and `cut`. |
|
|
67
|
-
| 3 | Last two child row commits
|
|
69
|
+
| 3 | Last two child row commits for the same row changed no file outside the ledger and no row status, or two consecutive validation misses on that row | Set the hint for that row: `the last two attempts changed nothing outside the ledger` for empty-child stagnation, or `two returns broke the contract: <concrete miss from the last repair evidence>` for validation misses; continue to rule 4. |
|
|
68
70
|
| 4 | Dispatch allowed | Select target by the priority below, then apply the escalation threshold check. |
|
|
69
71
|
|
|
72
|
+
Count two consecutive child `loop: row <n> ...` commits for the same row for empty-child stagnation; commits for different rows never pair. Exclude seed and parent commits from this count. A decision alone is not progress. A pending human `retry <n> | <hint>` for that row wins over the fixed hint. Attach a rule-3 hint only to its row; a cut row or a different selected target carries none. Pass the selected row's hint in the existing `hint:` task field.
|
|
73
|
+
|
|
70
74
|
When a refresh leaves implement active at rule 1, take the matching human stop; never start verify. Before evaluating rule 2, compute each row's effective allowance as the ledger's `allowance:` plus the count of that row's `row <n> retry | ... | allowed attempts <m>` lines in `## Decisions`. Count each retry once; the stored `<m>` is historical, not an absolute override. Ignore every other decision and grant in this arithmetic. Use the same rule for every coordinated entry, regardless of leg. With allowance 4 and two retries, a row has effective allowance 6 even if the historical `<m>` values are 5 and 99; raising the shared header to 7 makes it 9, while an unretried row gets 7. After migration, a row already at or above its effective allowance is exhausted. Never reset or reduce attempts.
|
|
71
75
|
|
|
72
|
-
Use the held decoded amendment grant for amendment choices only; ignore its waves-only budget token, retaining no amend permission for a budget-only value. Never consult this value for row escalation. Apply
|
|
76
|
+
Use the held decoded amendment grant for amendment choices only; ignore its waves-only budget token, retaining no amend permission for a budget-only value. Never consult this value for row escalation. Apply rule 2 before rule 3; a rule-3 hint dispatches through rule 4. Preserve `STAGNANT`, `REJECT` and closureReview boundaries; After the loop step 3 funds conformance rounds from the allowance.
|
|
73
77
|
|
|
74
|
-
Select `seed` until a validated `loop: seed evidence` commit with its `row 0 done` decision survives on the branch, independently of `iterations`;
|
|
78
|
+
Select `seed` until a validated `loop: seed evidence` commit with its `row 0 done` decision survives on the branch, independently of `iterations`; before any seed dispatch apply ## Validate the return's seed count instead of rule 3's row windows. Otherwise select the still-unresolved human retry target, then the still-failed row named by the previous decision, then first failed row, then first open row. Read seed survival from the ledger at HEAD and the matching validated commit, not from evidence completeness. Never re-seed a validated partial seed to fill empty evidence cells. Use the latest admitted return's target decision for targeting and the child's `previous decision:` input, never an extra's line; skip allowance-grant and legacy grant history while retaining the entire Decisions section. Durable status beats a decision's suggestion. Keep the retry hint only for its target.
|
|
75
79
|
|
|
76
80
|
For a numbered target with no durable `row <n> escalated` decision, compute `threshold = min(escalateAfter, effective allowance - 1)` from the held `escalateAfter` and the row's effective allowance. When the row's pre-dispatch attempts >= threshold, make this dispatch the escalated round: resolve `gauntlet_setting({ key: "escalationLoop" })` under approval option 4 and option 5 alike. Use the returned non-empty `implModel` string, including the resolver's main-loop model fallback when the setting is unset or malformed. With the settings tool unavailable or `implModel` undefined (neither a configured model nor a main-loop model), stop before dispatch with `Problem: escalationLoop.implModel unavailable`; write no escalation decision and leave attempts unchanged. Never substitute a default-model attempt for that stop.
|
|
77
81
|
|
|
@@ -79,7 +83,7 @@ With the resolved model, append `row <n> escalated | implModel round | allowed a
|
|
|
79
83
|
|
|
80
84
|
## Dispatch
|
|
81
85
|
|
|
82
|
-
For home dispatch, record `HEAD_BEFORE`, save the ledger before the iterations bump and tuple write, and retain the current `iterations:` count as i. Send `iteration: i` using the current pre-bump `iterations:` count and write `iterations: i + 1` before dispatch; admission requires the child commit body to carry `i + 1`, read from the bumped ledger header. State that difference when rendering a dispatch or admission: the task line carries the pre-bump count by design, the body line and `ITERATION` carry the consumed count `i + 1`, and the two never compare to each other. Record the dispatch identity separately and write `pending: <row or seed> | <repo> | <HEAD sha>` using `home` for zero or one spec leg, the actual member identifier for coordinated runs, and the selected checkout's HEAD. Persist the consumed count and tuple before every home or companion dispatch; then refresh. Commit nothing extra. Create a unique absolute output path with `mktemp` outside the repository. Dispatch exactly one foreground child in the main implementation worktree, not a nested worktree:
|
|
86
|
+
For home dispatch, record `HEAD_BEFORE`, save the ledger before the iterations bump and tuple write, and retain the current `iterations:` count as i. Retain dispatch/write provenance and background-launch records for ## Interrupted recovery; a clean boundary and one child alone never establish exclusive ownership. Send `iteration: i` using the current pre-bump `iterations:` count and write `iterations: i + 1` before dispatch; admission requires the child commit body to carry `i + 1`, read from the bumped ledger header. State that difference when rendering a dispatch or admission: the task line carries the pre-bump count by design, the body line and `ITERATION` carry the consumed count `i + 1`, and the two never compare to each other. Record the dispatch identity separately and write `pending: <row or seed> | <repo> | <HEAD sha>` using `home` for zero or one spec leg, the actual member identifier for coordinated runs, and the selected checkout's HEAD. Persist the consumed count and tuple before every home or companion dispatch; then refresh. Commit nothing extra. Create a unique absolute output path with `mktemp` outside the repository. Dispatch exactly one foreground child in the main implementation worktree, not a nested worktree:
|
|
83
87
|
|
|
84
88
|
```text
|
|
85
89
|
subagent({ agent: "loop-implementer", context: "fresh", async: false,
|
|
@@ -91,33 +95,45 @@ subagent({ agent: "loop-implementer", context: "fresh", async: false,
|
|
|
91
95
|
|
|
92
96
|
For `target: seed`, explicitly instruct the child to apply its seed contract even when iteration is greater than 0; carry that instruction in the existing `hint` field. Keep the actual consumed pre-bump count in `iteration`.
|
|
93
97
|
|
|
94
|
-
Omit the model override except on an escalated round (`model: <implModel>`); let the persona override or parent inheritance resolve it. Carry effects only: one file-reference return, one ledger read, git boundary checks. Never read a child transcript or carry reasoning history.
|
|
98
|
+
Omit the model override except on an escalated round (`model: <implModel>`); let the persona override or parent inheritance resolve it. Carry effects only: one file-reference return, one ledger read, git boundary checks. Never read a child transcript or carry reasoning history. Route a dispatch error or non-DONE return, including a silence kill, through ## Interrupted recovery. An async handle still stops; never poll or join it. Redispatch only through the ordered table after completed recovery.
|
|
95
99
|
|
|
96
100
|
## Validate the return
|
|
97
101
|
|
|
102
|
+
Read [action-spend durability](reference/action-spend.md) in full now; preserve action records through admission and every validation-miss repair below.
|
|
103
|
+
|
|
98
104
|
For home returns, apply the following boundary and table. Never project terminal child results before clean/exactly-one-commit admission.
|
|
99
|
-
1. Require empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`.
|
|
105
|
+
1. Require a DONE return, empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. Route dispatch errors, non-DONE, killed, dirty and zero/multiple-commit returns through ## Interrupted recovery, not result admission. Read the ledger from HEAD only after this boundary passes.
|
|
100
106
|
2. Validate by dispatched `target`, not iteration number, against the saved copy using this table. Require the commit body's first two lines to match the exact dispatched `pending:` tuple and consumed `iteration:` (saved iterations +1), using the persona's home attribution contract for row and seed alike. Admit only `iterations` +1 and removal of the dispatched `pending:` line; reject every other header change, including allowance. Preserve row identifiers and prior decisions.
|
|
101
107
|
|
|
102
108
|
| Target | Required changes | Miss |
|
|
103
109
|
|---|---|---|
|
|
104
|
-
| Seed | Require bounded nonempty evidence on at least one non-cut row; admit a subset or all rows. All attempts stay 0; only `open` -> `done` status transitions; keep unreached rows unchanged, including open rows with empty evidence, and preserve cut rows. Require exactly one new `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>` decision, counting only rows given evidence in this return and their proven baseline closures. Partial and complete baseline closure both pass. Never `failed`. | Seed repair below;
|
|
110
|
+
| Seed | Require bounded nonempty evidence on at least one non-cut row; admit a subset or all rows. All attempts stay 0; only `open` -> `done` status transitions; keep unreached rows unchanged, including open rows with empty evidence, and preserve cut rows. Require exactly one new `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>` decision, counting only rows given evidence in this return and their proven baseline closures. Partial and complete baseline closure both pass. Never `failed`. | Seed repair below; redispatch seed while its repair count is below allowance. |
|
|
105
111
|
| Ordinary | Require the target row's mutable cells to change: status `done` or `failed`, attempts +1, nonempty bounded evidence. Admit zero or more other rows in the same leg changing `open` -> `done`, each with nonempty bounded evidence and attempts unchanged. Require set equality between changed rows and rows with exactly one new decision line, target first, each matching its row and status. Keep every other row, header and prior decision unchanged apart from the dispatch header changes in step 2. | Parent repair below. |
|
|
106
112
|
| Seed or ordinary | No committed tuple remains. | A retained committed tuple is a validation miss for the dispatched target after boundary admission, not a boundary rejection. |
|
|
107
113
|
|
|
108
114
|
Require each ordinary decision to match `^row <that row> <that status> \| .{1,200} \| .{1,200}$`; an old conforming line is not a new line. Require check name plus at most three result lines in evidence, serialized with semicolons and escaped pipes as in the persona; add no command-format check. Reject a `failed` extra, a foreign-leg extra, a changed `cut` or `done` row, extra attempts changes, empty evidence on a changed row, or a missing, duplicate, malformed or unmatched decision. Admit an evidenced `done` extra beside a `failed` target. Never police worker ordering or execute a check after a return; leave regressions to verify step 1's gate set. Keep the child subject `loop: row <target n> <status>`; declare extras only in the ledger diff and their decision lines.
|
|
109
115
|
|
|
110
|
-
On a seed miss after clean/exactly-one-commit admission, restore every non-cut row, headers (including the saved allowance) and decisions from the saved copy; preserve cut rows and retain the incremented iterations. Clear `pending:`, commit parent `loop: repair seed
|
|
116
|
+
On a seed miss after clean/exactly-one-commit admission, restore every non-cut row, headers (including the saved allowance) and decisions from the saved copy; preserve cut rows and retain the incremented iterations. Clear `pending:`, commit parent `loop: repair seed` with `seed miss: <concrete miss>` in the body, then refresh and apply the seed count below. A validated seed resets the validation-miss window, so ordinary dispatch starts clean. Exclude seed repairs from rule 3's row windows.
|
|
117
|
+
|
|
118
|
+
Count seed attempts as `loop: repair seed` commits since ledger base, including interrupted and validation-miss repairs; for coordinated runs count home repair markers only. Dispatch seed while this count is below the ledger allowance, with the seed-contract instruction and `seed miss: <concrete miss>` or `seed interrupted: <reason>` in `hint:`, and `previous decision: none`. Recover the count and reason from branch history on resume. At allowance render `Stopped on seed` with `seed: <k> of <allowance>` and the retry/`rows +N` menu; only a raised allowance permits more seed repairs, and a numbered retry never erases this count. Keep row attempts at 0.
|
|
119
|
+
|
|
120
|
+
On an ordinary miss restore every non-target row, headers (including the saved allowance) and prior decisions from the saved copy, retaining the incremented iterations. Set the target `failed`, attempts = saved attempts +1, evidence = `iteration <i>: <concrete miss>`. Clear `pending:`, remove malformed appended decisions and commit `loop: repair row <n>`, then refresh. Set previous decision to `none`; on an admitted ordinary return use the target's new conforming line, never the last extra's. Two consecutive validation misses on a row set its rule-3 hint. A conforming return resets the consecutive-miss count; parent repair commits do not count toward child-only empty stagnation.
|
|
121
|
+
|
|
122
|
+
## Unreachable returns
|
|
123
|
+
|
|
124
|
+
Read [unreachable-returns](reference/unreachable-returns.md) in full now with read at its absolute path; apply its evidence routing before returning to the ordered table.
|
|
125
|
+
|
|
126
|
+
## Interrupted recovery
|
|
111
127
|
|
|
112
|
-
|
|
128
|
+
Read [interrupted recovery](reference/interrupted-recovery.md) in full now; apply its numbered procedure before redispatch.
|
|
113
129
|
|
|
114
130
|
## Human stop
|
|
115
131
|
|
|
116
132
|
Read and apply [menu-layout](../brainstorming/reference/menu-layout.md). Start the message with `gauntlet: question` at every human stop, including the discard/reset authorization ask for a dirty or commit-boundary return. Put it alone on the first output line, followed by a newline before the stop text, without a driver-state preamble, wrapper or code fence. These decisions are neither done nor stuck outcomes.
|
|
117
133
|
|
|
118
|
-
Implement-phase stops only: leave implement active and use the row offers below. For verify stops use the menus in After the loop, retaining verify active. Use one screen of plain words: `Stopped on row <n>` for row failures, or the concrete boundary/verification header. `Problem:` quotes the evidence cell and last decision line verbatim; attribute any spec/code contradiction, failing assertion/output or missing capability to that evidence, without investigating it. At every human stop, including allowance,
|
|
134
|
+
Implement-phase stops only: leave implement active and use the row offers below. For verify stops use the menus in After the loop, retaining verify active. Use one screen of plain words: `Stopped on row <n>` for row failures, or the concrete boundary/verification header. `Problem:` quotes the evidence cell and last decision line verbatim; attribute any spec/code contradiction, failing assertion/output or missing capability to that evidence, without investigating it. At every human stop, including allowance, missing-model, dirty-tree, commit-boundary, interrupted-dispatch and exit-verification stops, list every `open` or `failed` row after the header as `row <n>: <attempts> of <effective allowance>`, then print `Preserve every row's attempts.` Compute each denominator from the ledger using Before each dispatch; keep retry increments in `## Decisions`, never a new table column. Use restored pre-dispatch row cells at rejected-return stops, not unadmitted child results. With no open or failed rows, omit row lines but retain the preservation sentence. Name `escalated round spent` when applicable; omit round history and reasoning traces.
|
|
119
135
|
|
|
120
|
-
Offer retry and `rows +N` only at row stops (allowance
|
|
136
|
+
For stops not handled by ## Unreachable returns: Offer retry and `rows +N` only at row stops (allowance or missing-model) or seed exhaustion, alongside Amend and Stop. The recovery-incomplete stop keeps discard authorization only, never budget offers; the verify-step-1 verification-failure stop keeps amend/stop only. A budget increase never bypasses those gates.
|
|
121
137
|
|
|
122
138
|
| Human choice | Durable action |
|
|
123
139
|
|---|---|
|
|
@@ -126,11 +142,11 @@ Offer retry and `rows +N` only at row stops (allowance, stagnation or missing-mo
|
|
|
126
142
|
| Amend | Follow `/skill:brainstorming` amendment surface; cut only through an approved disposition amendment. Reconcile ledger and spec in one commit. |
|
|
127
143
|
| Stop | Keep phase implement and preserve branch state. |
|
|
128
144
|
|
|
129
|
-
Serialize the bare decision as `rows +50 |` with an empty words cell. Raising allowance resets neither window (empty-child or validation-miss); exclude `loop: raise allowance` from child-commit counting.
|
|
145
|
+
Serialize the bare decision as `rows +50 |` with an empty words cell. Raising allowance resets neither window (empty-child or validation-miss); exclude `loop: raise allowance` from child-commit counting. Use Before each dispatch's window rule for retry and admitted amendments.
|
|
130
146
|
|
|
131
|
-
|
|
147
|
+
Recover interrupted returns through ## Interrupted recovery before dispatch. At recovery incomplete, ask for explicit discard authorization naming the unresolved ownership or cleanup; a budget reply authorizes no discard. Preserve spent escalation and the consumed dispatch count through recovery: iterations = restored HEAD's value +1, before the next normal bump. Recover from disk/branch, never repeat iteration 0.
|
|
132
148
|
|
|
133
|
-
Outside the dispatch loop, perform authorized amendment actions under the amendment surface's own reads. After the amendment commit, re-decode the grant and refresh the held membership, checkout paths and Rules from the updated spec before returning to the loop; apply this to funding and standing-grant amendments too. Leave the `**Amend-grant:**` header grammar unchanged.
|
|
149
|
+
Outside the dispatch loop, perform authorized amendment actions under the amendment surface's own reads. After the amendment commit, re-decode the grant and refresh the held row dispositions, membership, checkout paths and Rules from the updated spec before returning to the loop; apply this to funding and standing-grant amendments too. Leave the `**Amend-grant:**` header grammar unchanged.
|
|
134
150
|
|
|
135
151
|
Retry, cut, amend, raise-allowance and escalate commits never clear the tuple. For ledger amendments use its line-1 discriminant: no plan writer or plan_check; refresh after the amendment commit. Approved deviates/deferred/elsewhere becomes `cut` with disposition evidence; requirement-preserving amendments leave rows unchanged; a re-bounded done row becomes `open` with `reopened by amendment`. Preserve attempts, iterations and allowance. Commit spec + ledger as `loop: cut row <n>` or `loop: amend`. Option 4 stops for amendments, option 5 auto-applies amends, redraw always stops and deletes the ledger with the plan. Cut only through the amendment surface, including its standing-grant section 5.
|
|
136
152
|
|
|
@@ -154,10 +170,13 @@ For coordinated runs, route each verification and review below to every leg with
|
|
|
154
170
|
|
|
155
171
|
0. Call `phase_tracker({ action: "start", phase: "verify" })`. Mint `LOG_DIR=$(mktemp -d)` once for this verify session; a resumed session mints a new one at its first gate-set site.
|
|
156
172
|
1. Run the gate set per ## Gate set. Require every pair to pass. Commit verification-produced tracked changes, including gate-produced changes. Any repair invalidates that run: apply the rerun scope below before the next gate. No task reopen/update is awaited.
|
|
157
|
-
|
|
158
|
-
|
|
173
|
+
Count `repairs` as home `loop: repair verification` commits since ledger base, plus one for a `pending: verify` tuple with no admitted repair commit. Use the shared ledger allowance, with no per-row retry increments. Recover this count from branch history and disk on every resume; match marker bodies to pending tuples to avoid counting one dispatch twice. Recover an outstanding tuple before any new gate run or dispatch, including the last reserved repair at allowance.
|
|
174
|
+
On failure automatically repair while `repairs < allowance` under approval option 4 and option 5 alike; never consult amend permission or gate on iterations. Keep verify active and implement complete. Resolve `gauntlet_setting({ key: "escalationLoop" })`; require its non-empty `implModel`, including the resolver's main-loop fallback. Missing settings/model stops with `Problem: escalationLoop.implModel unavailable`, without a bump or marker. Save the home ledger and home/failing-leg HEADs, retain dispatch/write and background-launch provenance, then bump iterations once and write `pending: verify | <repo> | <HEAD>` on disk before dispatch, using the failing leg's identity (single-leg `home`) and HEAD. Treat only that bump/tuple as expected home dirt. Dispatch exactly one `implementer` with `model: <implModel>`, `context: "fresh"`, `async: false`, failing checkout cwd and Rules, absolute spec path, failing command, checkout, exit code and log path, never pasted output. Pass the exact pending tuple and consumed `iteration:` for the first two commit-body lines, plus the failing leg's base and pre-bump iteration for jobs-file identity. Require retained launch/no-launch evidence and the jobs records in ## Interrupted recovery. Apply [action-spend durability](reference/action-spend.md) to this repair and inject the persona's step-5 action authorization/accounting contract, including pre-launch reservations, without its row mutation protocol; require action-spend records after tuple/iteration in the repair commit body. Include this blocking-call contract in the repair task: bound every blocking command with `timeout -k 30 <n>`, n <= 600; background and poll longer work. Read [loop-implementer's Evidence command](../../agents/loop-implementer.md#evidence-command) and copy its first three paragraphs verbatim into that task, omitting its row/seed ledger protocol. The repair child reads the log to derive the files to touch; for a stale selector restore the test or its name, never ledger evidence.
|
|
175
|
+
Require DONE, a clean failing checkout and exactly one commit after HEAD_BEFORE, matching the task's tuple/iteration attribution. Require all ledger rows unchanged, preserving attempts, mapping, allowance and prior decisions. The home child's sole commit includes the already-bumped ledger with pending retained; a companion child commits its leg only, leaving home HEAD and expected dirt unchanged. Remove `pending:` only in the parent repair marker: commit `loop: repair verification` in home with the consumed iteration and exact tuple in its body, recording the admitted child SHA. Refresh after admission. On killed, error, non-DONE, dirty, zero/multiple-commit or invalid repair returns, apply ## Interrupted recovery steps 1-3 to the failing checkout, not its numbered-row/seed budget or step 4. Preserve the saved row cells and already-consumed iteration; after owned jobs exit and the boundary is clean, clear pending in an empty `loop: repair verification` marker (no repair code), with tuple, iteration and interruption reason in its body. For companions require unchanged home HEAD and expected-only dirt, and write the marker only in home. On missing provenance, ambiguous attribution/before-image or failed cleanup, retain state at the recovery-incomplete stop; the pending reservation remains consumed. On resume, admit a matching clean single repair commit or recover the interrupted return by this same path without another bump; an already admitted matching marker needs no second marker.
|
|
176
|
+
Rerun the failing checkout's gate pairs once using ## Gate set's log redirection and fail-fast rule after each admitted or recovered repair. After that rerun passes, run the original fail-fast run's still-unexecuted pairs from other checkouts in ledger order before recording verified HEAD. On resume run the complete gate set in a fresh session LOG_DIR. A new failure in any leg returns to the repair-count check; do not reopen rows or reset the count. Never spend verify-phase credits. On failure at `repairs >= allowance`, render `Stopped: verification failed with every row closed` with `repairs: <k> of <allowance>` and `Problem:` naming `gate <i> exit <code> <log path>` and quoting at most the last 20 lines with `tail -n 20`; this human-stop excerpt is the driver's only log read. Keep verify active and implement complete; offer amend or stop only, no `Retry with hint` or `rows +N`. Use the same restricted menu for missing capabilities. On success record verified HEAD and clean status for every leg.
|
|
159
177
|
2. Dispatch foreground whole-diff `wave-reviewer` per `/skill:requesting-code-review`, from ledger base through committed HEAD, with `SCOPED_TEST_COMMANDS: none`. Apply its fix rounds. Rerun the complete gate set after every fix round before re-review/next gate. Carry final SHIP Minor lines verbatim as `whole-diff minors:`, or `whole-diff minors: none`.
|
|
160
178
|
3. Run happy path per the fully read reference when overrides has `## Happy path` or the diff selects a row; use the diff-derived row, not a plan header. Pass summary and outcome to the separate fresh `conformance-reviewer`, along with spec path, verbatim original prompt and full diff. Use spec AC rows against the ledger as the checklist. Follow the reference's partition, concern decomposition, fix rounds and Convergence with the gate set replacing plan Verification at every test site per the reference's ledger-subject override. Use normal conformance Gn tasks on the same tracker and keep durable Gn identities in reports. Rerun the complete gate set after repairs. Resolve closureReview settings and reviewer dispatch per the reference. Reviews happen only after complete implement; none inside the iteration loop.
|
|
179
|
+
When the conformance fix-round cap blocks (`<used> fix round(s) used against a cap of <cap>`) or the reference's step 6 asks at its cap, read `<used>` from that text. Under amend permission with `<used>` below the ledger allowance: when the block is live, call `phase_tracker({ action: "grant_fix_rounds", rounds: <allowance - used>, reason: "<Amend-grant sentence verbatim>" })`, print `funded <allowance - used> conformance rounds under the grant`, and continue the fix loop; when `closureReview.enforce` is false, continue without a call. With `<used>` at or above the allowance, an error reply, or no amend permission, take the reference's step-6 stop. Never call the tool as a probe or store a grant counter; never count rounds yourself. The next block's `<used>` includes granted rounds, so a second block at the allowance stops; a resumed run with unspent credits continues without a block or another grant. Leave the cap and settings unchanged.
|
|
161
180
|
On an approved re-bound (`reopened by amendment`), refresh and stop with `Stopped: row <n> reopened by amendment during verify`; offer authorize the row's return to ledger implementation or stop. On approval apply the normal Before each dispatch boundaries, then Dispatch, Validate the return and refresh with verify still active and no phase reset; close on disk and rerun step 1 before continuing verify. Keep completion blocked until closure; never substitute a tracker write for the ledger return.
|
|
162
181
|
4. Complete verify only on current CONFORMS or valid carried-open deferred inventory per the reference. A started positive-cap fix loop blocking/failing/exhausting with an open fix gap stops, never completes verify. Summarize rows closed, iterations consumed, files changed, test counts and review verdict. Emit exact `## Closure / conformance` schema from the reference: `status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA>`, happy-path exactly when run, Deferred/deviates per spec exactly when applicable, all gap/concern fields unchanged, auto-applied fix commits index and whole-diff minors. Read its whole-diff-minors companion when directed. Never rename fields.
|
|
163
182
|
5. Immediately invoke `/skill:finishing-a-development-branch <abs worktree path>`. Its menu is the human gate; do not add a ready-to-finish prompt.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Action-spend durability
|
|
2
|
+
|
|
3
|
+
Read this contract before admitting a return or restoring any saved ledger, including seed, row, companion and verification repairs. Keep action accounting separate from row attempts and repair allowances.
|
|
4
|
+
|
|
5
|
+
1. Before deleting a jobs file, resetting a checkout or restoring ledger decisions, retain every `ran <action> (<k> of <bound>)` and `bound spent: <action> (<k> of <bound>)` record from the child's jobs file, returned evidence/decisions and attributable ledger or commit body. Read only those permitted boundary artifacts, never a transcript or log. Treat action-record lines in the jobs file as accounting, not process entries; apply process ownership checks only to pid records. Require a pre-launch spend reservation, confirmed execution record or affirmative retained evidence that no paid/external action launched. With uncertain execution and no attributable reservation, stop at recovery incomplete with `action execution uncertain`; preserve state rather than infer an unspent bound from missing decision text.
|
|
6
|
+
2. Before admitting a successful row or seed return, require every reserved spend to survive in its ledger evidence/decisions (or companion result cells). Before replacing an evidence cell, require the child to repeat each carried `ran <action> (<k> of <bound>)` and `bound spent: <action> (<k> of <bound>)` record verbatim in its own decision sentence before any new spend, including records from a successful seed. Treat a dropped record as a validation miss even when the replacement check passes. For verification repairs, require the records after tuple/iteration in the attributed child commit body instead, leaving row cells unchanged; copy them into the home repair marker. A reservation without a confirmed `ran` record stays conservatively spent. A missing spend record is a validation miss, not permission to erase it. Retain the action records until admission or a durable repair marker; only then delete the jobs file after process cleanup.
|
|
7
|
+
3. For every interrupted or validation-miss repair, copy all retained action records into the parent repair commit body before clearing the pending tuple or discarding child output. Include them in a numbered target's evidence cell after the interruption/miss reason, within the existing result-line bound; the commit body retains the complete accounting. For seed preserve the saved row cells and fixed seed decision contract; keep action accounting in the `loop: repair seed` commit body. For verification retain it in the `loop: repair verification` marker. Keep prior decisions intact and add no decision kind or ledger header.
|
|
8
|
+
4. Carry these repair commit bodies as spend history on every later dispatch and authorized restore, including companion dispatches: inject home repair action records in the existing hint when the child cannot read home history. Count the highest recorded k for each action across decisions, evidence and repair bodies; identical copies are one spend. Preserve this history through retry, amendment and finish.
|
|
9
|
+
|
|
10
|
+
For a capture that succeeds before an interrupted seed, preserve `ran capture (1 of 1)` in the seed repair commit body even when reset removes its fixture and ledger changes. The next child counts that spend and records `bound spent: capture 1 of 1`, never another capture. Preserve a lone pre-launch reservation conservatively in the same way.
|
|
@@ -6,7 +6,7 @@ At seed, read `## Legs` with [the scope grammar](../../brainstorming/reference/l
|
|
|
6
6
|
|
|
7
7
|
Retain the home skeleton's `**Spec:**`, `verification:`, `checks: commands`, `iterations:`, `allowance:` and `## Decisions` fields and its `plan_check`/commit admission. Use the driver's gate set grouped by `## Leg mapping` for verification; keep the home verification header as the CI command.
|
|
8
8
|
|
|
9
|
-
For coordinated exit, apply the driver's `## Gate set` and `## After the loop` step 1 in verify, routing each pair through its mapped checkout.
|
|
9
|
+
For coordinated exit, apply the driver's `## Gate set` and `## After the loop` step 1 in verify, routing each pair through its mapped checkout. Count home `loop: repair verification` markers against the driver's shared allowance across failing legs. Success only after every leg passes; retain each verified HEAD and clean status.
|
|
10
10
|
|
|
11
11
|
Assign numeric entries in original AC order, then membership order for shared ACs, independent of scope-list order. Leave spec rows untouched and copy each cut disposition to every expanded entry. Keep the four-column table and add `## Leg mapping` with `row | ac | leg`, one mapping per entry exactly once. Reject duplicate/missing mappings. Keep `base:` as home base; record one actual `base repo-a: <sha>` / `seeded repo-a: no` pair per member, including home. Resolve bases with each member's `git -C`, not home HEAD.
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ Use the same allowance seed value and source echo as the home driver's Entry ste
|
|
|
14
14
|
|
|
15
15
|
## Resume
|
|
16
16
|
|
|
17
|
-
Use the held membership and checkout paths captured by the driver's Entry at seed or authorized restore. Recover pending companion work before generic dirty checks and before any new dispatch. Read the durable home ledger's `pending:` tuple and consumed iteration, selected companion HEAD and saved pre-dispatch state. Reconstruct the pre-dispatch ledger from home `HEAD:<ledger path>` on resume and admit only the expected on-disk iterations bump and tuple against it. Admit only the known iterations bump and exact pending tuple as pre-dispatch dirt; stop on other dirt. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions.
|
|
17
|
+
Use the held membership and checkout paths captured by the driver's Entry at seed or authorized restore. Route `pending: verify` through the driver's After the loop step 1 before the row/seed admission below. Recover pending companion work before generic dirty checks and before any new dispatch. Read the durable home ledger's `pending:` tuple and consumed iteration, selected companion HEAD and saved pre-dispatch state. Reconstruct the pre-dispatch ledger from home `HEAD:<ledger path>` on resume and admit only the expected on-disk iterations bump and tuple against it. Admit only the known iterations bump and exact pending tuple as pre-dispatch dirt; stop on other dirt. Reapply companion return validation below only when exactly one new commit after the recorded HEAD matches attribution. Apply the home-ledger commit without another attempt or iteration bump, clear pending and retain prior decisions. Route interrupted boundaries (dirty, zero/multiple commits, dispatch error or non-DONE) through ## Companion return validation's ownership-fenced recovery; keep unrelated movement and attribution mismatch as state-preserving stops; route post-boundary result-validation misses through ordinary `loop: repair row <n>` or seed `loop: repair seed` repair below, clear `pending:` and preserve the consumed iteration. After a successful parent commit no pending tuple remains, so a subsequent resume cannot duplicate the update.
|
|
18
18
|
|
|
19
19
|
## Targeting and dispatch
|
|
20
20
|
|
|
@@ -24,15 +24,15 @@ For coordinated dispatch, capture home and selected leg heads and save a pre-dis
|
|
|
24
24
|
|
|
25
25
|
## Companion return validation
|
|
26
26
|
|
|
27
|
-
For a companion, validate from its commit, not the reply. Require a clean companion and exactly one commit after pending HEAD; require unchanged home HEAD and no home edits except the expected persisted bump/tuple. Match subject `loop: row <n> <status>` or `loop: seed evidence`, exact pending tuple and consumed `iteration:` in the body. Parse four-column row lines followed by decision lines. For ordinary returns require the target (`done` or `failed`, attempts +1) plus zero or more same-leg `open` -> `done` extras with attempts unchanged. Require nonempty bounded evidence and exactly one matching bounded decision for each changed row, target decision first, under the driver's `## Validate the return` table; admit extras beside a failed target without policing worker order or adding a command-format check. For seed require all and only that leg's non-cut rows, at least one with evidence, and one bounded seed decision; admit unchanged open rows with empty evidence. Reject a wrong target, foreign entry, changed cut/done extra, header changes, fabricated counts, malformed evidence or unmatched/duplicate rows or decisions. Validate seed counts against nonempty evidence cells and baseline closures; require zero attempts and set only this leg's seeded value to `yes` after the complete row set validates. Route seed validation misses after boundary admission through the driver's seed repair
|
|
27
|
+
For a companion, validate from its commit, not the reply. Require a clean companion and exactly one commit after pending HEAD; require unchanged home HEAD and no home edits except the expected persisted bump/tuple. Match subject `loop: row <n> <status>` or `loop: seed evidence`, exact pending tuple and consumed `iteration:` in the body. Parse four-column row lines followed by decision lines. For ordinary returns require the target (`done` or `failed`, attempts +1) plus zero or more same-leg `open` -> `done` extras with attempts unchanged. Require nonempty bounded evidence and exactly one matching bounded decision for each changed row, target decision first, under the driver's `## Validate the return` table; admit extras beside a failed target without policing worker order or adding a command-format check. For seed require all and only that leg's non-cut rows, at least one with evidence, and one bounded seed decision; admit unchanged open rows with empty evidence. Reject a wrong target, foreign entry, changed cut/done extra, header changes, fabricated counts, malformed evidence or unmatched/duplicate rows or decisions. Validate seed counts against nonempty evidence cells and baseline closures; require zero attempts and set only this leg's seeded value to `yes` after the complete row set validates. Route seed validation misses after boundary admission through the driver's seed repair count: commit `loop: repair seed` in home with the concrete miss in the body, write no returned rows or decisions, clear `pending:`, leave this leg's seeded value `no` and preserve foreign state. Retain consumed iterations and saved allowance; apply the driver's seed count and hint rule to retry this leg below allowance or stop at allowance. A validated seed resets the validation-miss window. Route ordinary validation misses after boundary admission through the driver's ordinary repair: set only the target `failed` with attempts +1 and `iteration <i>: <miss>` evidence, append its repair decision, clear `pending:` and commit `loop: repair row <n>` in home. Preserve every non-target row and prior decision from the saved copy, consumed iterations and saved allowance; count the miss in the existing two-miss window.
|
|
28
28
|
|
|
29
|
-
After validation write every admitted row and append every validated decision to the home ledger, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Use the target's decision as the next dispatch's `previous decision:`, never an extra's. Preserve every other row, header and prior decision. That home-ledger commit (`loop: record <repo> row <n>`) is a parent commit, not a child `loop: row ...` commit: it never counts toward child-only empty-commit stagnation; only the companion's own commits are counted at the boundary. For rejected
|
|
29
|
+
After validation write every admitted row and append every validated decision to the home ledger, record companion SHA in evidence, and remove `pending:` in one home-ledger commit. Use the target's decision as the next dispatch's `previous decision:`, never an extra's. Preserve every other row, header and prior decision. That home-ledger commit (`loop: record <repo> row <n>`) is a parent commit, not a child `loop: row ...` commit: it never counts toward child-only empty-commit stagnation; only the companion's own commits are counted at the boundary. For rejected results apply the post-boundary repair above. For interrupted boundaries, apply the driver's ## Interrupted recovery immediately and on resume: require unchanged home HEAD and expected-only bump/tuple dirt, exclusive companion checkout/write provenance, accounted-for writers and matching jobs-file process identity before signaling or reset. Reset only the selected companion to its `HEAD_BEFORE`, using its base/iteration jobs file; require confirmed job exits and clean/zero-commit observations. Restore the saved home ledger with consumed iterations, preserve foreign rows, mappings, bases and seeded flags, clear pending and commit `loop: repair row <n>` or `loop: repair seed` only in home. Increment only the numbered target's attempts once; seed leaves rows unchanged. Refresh and return to the driver's ordered table or seed count without double counting. Missing provenance, missing before-image, unexpected home changes, unresolved cleanup or ambiguous attribution stops with state preserved, not a reset based on commit timing. Recover from boundary evidence, never trusted reply text.
|
|
30
30
|
|
|
31
31
|
For coordinated home returns apply it only to home entries/seeded state, preserving foreign entries, mappings and bases.
|
|
32
32
|
|
|
33
33
|
### Companion commit admission
|
|
34
34
|
|
|
35
|
-
Require the unchanged home HEAD and expected-only home dirt boundary above, then run this read-only admission recipe on both immediate returns and pending recovery. Set `CHECKOUT` to the companion root, `PENDING` to the exact persisted tuple including `pending:`, `ITERATION` to the consumed count and `SAVED_LEDGER` to the durable home ledger after the iterations bump and pending write, including on recovery. Use the pre-dispatch snapshot only for the expected-dirt comparison.
|
|
35
|
+
Require the unchanged home HEAD and expected-only home dirt boundary above, then run this read-only admission recipe on both immediate returns and pending recovery. Set `CHECKOUT` to the companion root, `PENDING` to the exact persisted tuple including `pending:`, `ITERATION` to the consumed count and `SAVED_LEDGER` to the durable home ledger after the iterations bump and pending write, including on recovery. Use the pre-dispatch snapshot only for the expected-dirt comparison. Classify boundary failures before running this recipe: route dirty/zero/multiple-commit interrupted returns through the ownership-fenced recovery above; preserve pending and stop on unrelated movement or attribution mismatch. On a seed validation miss after the boundary passes apply the seed repair above. On an ordinary validation miss after the boundary passes apply ordinary repair above, not the boundary stop. On success use the emitted object for the single parent ledger commit described above; never treat it as permission for another dispatch.
|
|
36
36
|
|
|
37
37
|
<!-- companion-return-shell -->
|
|
38
38
|
```bash
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Interrupted recovery
|
|
2
|
+
|
|
3
|
+
Treat dispatch error, non-DONE, silence kill, dirty tree and zero/multiple commits as interrupted returns. Use the saved pre-dispatch ledger and checkout `HEAD_BEFORE`; on resume use the tuple's HEAD and its ledger before-image (the saved home HEAD for a companion). Keep an unrecoverable before-image or ambiguous attribution at the recovery stop with state preserved. Apply this procedure under options 4 and 5 alike, only below the numbered target's effective allowance or the seed repair-count allowance; at exhaustion take rule 2 or the seed stop without another dispatch.
|
|
4
|
+
|
|
5
|
+
1. Establish exclusive checkout provenance before destructive recovery. Require retained dispatch and write provenance identifying every changed path and commit as this child's output, with every writer accounted for and quiescent except owned jobs to terminate below. A clean `HEAD_BEFORE`, one dispatched child, path substrings and commit timing prove no ownership. Missing provenance, concurrent or unattributed writes take the recovery-incomplete stop with all changes preserved; do not reset or clean. Read and apply [action-spend durability](action-spend.md) before any restoration or deletion; retain confirmed executions and conservative reservations for the repair body, including seed.
|
|
6
|
+
2. Read `${TMPDIR:-/tmp}/loop-<base SHA>-<iteration i>.jobs`: process lines are `<pid> <process-start-identity> <command>`, with OS-observed start identity captured at launch, not record-write time; preserve action-record lines under action-spend durability. Treat an absent or empty file as no jobs only with retained evidence that the child launched no background work. For each live pid require matching start identity and command plus `ps -o pgid= -p <pid>` equal to pid; a replacement group leader is not owned. Recheck all three immediately before signaling. Unavailable identity or mismatch stops without signaling. For a confirmed owned group send `kill -TERM -- -<pid>`, wait at most 10 s, use `kill -KILL -- -<pid>` for a surviving group after another identity recheck, then require `kill -0 <pid>` to fail. An already exited job needs affirmative exit evidence, not an unavailable identity mistaken for exit. Signal neither the driver's shells nor unrecorded processes. Print `terminated <k> child jobs` when k > 0; delete the jobs file only after every listed job is confirmed exited and action accounting is durable in the admitted result or repair commit body.
|
|
7
|
+
3. After exclusive provenance and job exit are both established and action accounting is retained, use the driver's shell: `git -C "<worktree>" reset --hard HEAD_BEFORE`, then `git -C "<worktree>" clean -fd` (leave ignored files alone). Require empty `git -C "<worktree>" status --porcelain` and 0 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`.
|
|
8
|
+
4. Write the ledger from the saved copy with `iterations:` = saved +1 and no `pending:`. For a numbered target set only that row `failed`, attempts = saved attempts +1, evidence `iteration <i>: interrupted - <reason>` plus retained action records; preserve every other row and all prior decisions, including spent escalation. Use `killed after silence`, `dispatch error: <text>`, `dirty tree`, `<k> commits` or `non-DONE` as the concrete reason. Commit `loop: repair row <n>` with retained action records in its body, refresh and return to the ordered table; rule 2 stops a repaired row at allowance. For seed leave every row cell and decision unchanged, commit `loop: repair seed` with `seed interrupted: <reason>` and retained action records in the body, refresh and apply the seed count in ## Validate the return. Never append a fabricated child decision.
|
|
9
|
+
|
|
10
|
+
On unresolved provenance, action accounting or cleanup render `Stopped: iteration <i> recovery incomplete - <what>` with the discard-authorization menu below. Name the observed failure, such as `checkout ownership unproven`, `action execution uncertain`, `background launch history unavailable`, `job <pid> not owned`, `job <pid> still running` or `tree dirty after reset`. Preserve remaining changes, pending identity and consumed iteration; consume no attempt and make no repair commit. Project saved pre-dispatch row cells at this stop without overwriting unadmitted work. For a companion apply [coordinated recovery](coordinated-legs.md#companion-return-validation) to its checkout and write the repair only in home.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Unreachable returns
|
|
2
|
+
|
|
3
|
+
Key routing to the admitted return, not unchanged evidence. Keep an unanswered stop pending, including on resume. Treat a human retry, `rows +N`, an applied amendment answering the stop, or an applied cut as answering that return. Recover answered state on resume from the existing retry, raise-allowance and amendment decisions/commits after that admission; add no routing marker. Continue at the ordered table without re-firing its marker, even while the failed row's evidence is unchanged. Route a newly admitted failed return independently, even with identical evidence. Keep action counts and authorization bounds unchanged by retry or `rows +N`; only an approved amendment can raise an action's bound.
|
|
4
|
+
|
|
5
|
+
Inspect only the target's first result segment after the check name in its admitted evidence cell; split on unescaped semicolons and trim whitespace. Never inspect later result segments, other rows or a rejected return. Leave malformed markers on the ordinary failed-attempt path.
|
|
6
|
+
|
|
7
|
+
| First result segment | Action |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Matches `^bound spent: .+$` | Render `Stopped on row <n>` per the driver's Human stop under options 4 and 5 alike, with the ordinary row menu (retry, `rows +N`, Amend, Stop) and `Recommendation: none - named action bound spent`; never cut or redispatch automatically, including for a `venue:` row. |
|
|
10
|
+
| Matches `^unreachable: .+ - .+$` | Keep `venue:` rows on the ordinary failed-attempt path with their held disposition unchanged. For other rows, take the amendment action below before another dispatch. |
|
|
11
|
+
| Neither | Return to the ordered table. |
|
|
12
|
+
|
|
13
|
+
Leave diagnosis to the child. Form one amend item outside the dispatch loop through [amendment-surface](../../brainstorming/reference/amendment-surface.md), using the captured `<what>` and `<where>` from `unreachable: <what> - <where>` as evidence. Recommend disposition `deviates: unreachable in this checkout - <what>; proof at <where>` and an `## Out of scope` entry `<row text, first 60 chars> - unreachable in this checkout - <what>`; never convert the disposition to `venue:`, even for a production proof location. Reuse the surface's batch preparation, grant decoding and section 5 audit/ledger aftermath, including its redraw and repeated-evidence stops. Without amend permission take its human batch before any write or dispatch. Under amend permission apply the item: set the ledger row `cut` with the disposition as evidence in the surface's single `loop: cut row <n>` commit, and print `amended the spec: row <n> - unreachable in this checkout - <what>`. Preserve attempts, iterations, allowance and spent escalation. Refresh held state through the driver's Human stop amendment return and continue the ordered table in the same turn. Carry the cut on After the loop's `Deferred/deviates per spec:` line. For companions use the held mapping and coordinated amendment rules; the home spec/ledger own the cut.
|
|
@@ -182,7 +182,7 @@ Per round:
|
|
|
182
182
|
that omits `model:` when `closureReview.model` is set, and warns (non-blocking)
|
|
183
183
|
on one whose model differs. Mark every `Gn` the re-audit reports `DELIVERED`
|
|
184
184
|
`complete`; open ones stay `in_progress`.
|
|
185
|
-
6. **Converge or continue**: verdict `CONFORMS`
|
|
185
|
+
6. **Converge or continue**: verdict `CONFORMS` -> Convergence below. Under the loop engine with amend permission, apply the loop driver's After the loop step 3 funding up to the ledger allowance before this ask; ask the human only when it declines. Start the message with `gauntlet: gate=verification-before-completion/step-6` alone on the first output line, followed by a newline before the human escalation text, including Convergence cap exhaustion. Read and apply [menu-layout](../../brainstorming/reference/menu-layout.md); ask for explicit funding of additional rounds. Emit this proactively, independent of any runtime guard error. Keep verification incomplete; emit no done or stuck line here or at intermediate closure. Open gaps
|
|
186
186
|
within the cap → re-partition (per the rule above) and start the next
|
|
187
187
|
round. Cap (`gauntlet_setting({ key: "closureReview" }).maxFixRounds`,
|
|
188
188
|
default `5`, floors negatives at `0`, normalizes missing or non-integer values to `5`) reached
|