pi-gauntlet 8.1.5 → 8.1.6
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 +6 -0
- package/agents/loop-implementer.md +18 -18
- package/extensions/plan-tracker.test.ts +10 -0
- package/package.json +1 -1
- package/skills/gauntlet-resume/reference/reconstruction.md +3 -3
- package/skills/loop-implementation/SKILL.md +10 -8
- package/skills/loop-implementation/reference/coordinated-legs.md +30 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v8.1.6 - 2026-11-01
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Loop returns close related rows and seed incrementally** (#110) - an ordinary worker can close same-leg open rows alongside its target, with evidence and a decision line for each; extras consume no attempts. Seed can leave unreached rows without evidence, and one seed validation miss gets a repair-and-retry before the human stop. A validated partial seed continues without re-seeding.
|
|
8
|
+
|
|
3
9
|
## v8.1.5 - 2026-11-01
|
|
4
10
|
|
|
5
11
|
- `chase-bug` hotfix uses `loop-implementer` with a one-row ledger and a shared repair budget, escalating the last allowed attempt. Mandatory conformance and code review must pass on the final tested commit before landing; failed audits no longer continue to ship.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: loop-implementer
|
|
3
|
-
description: '
|
|
3
|
+
description: 'Dispatch for a loop-engine iteration on the target acceptance-criteria row plus proved same-leg extras, with evidence and one decision line each.'
|
|
4
4
|
tools: read, write, edit, bash
|
|
5
5
|
defaultContext: fresh
|
|
6
6
|
inheritProjectContext: true
|
|
@@ -13,11 +13,11 @@ You are the loop implementer. Complete one acceptance-criteria ledger iteration
|
|
|
13
13
|
|
|
14
14
|
## Output contract
|
|
15
15
|
|
|
16
|
-
Append
|
|
16
|
+
Append one decision line per changed row to the ledger's `## Decisions` section - the target (`done` or `failed`) and each extra closed `done` - target first. Reply with those lines only, with nothing before or after them:
|
|
17
17
|
|
|
18
|
-
`row <n> <done|failed> | <one sentence: what was done> | <one sentence:
|
|
18
|
+
`row <n> <done|failed> | <one sentence: what was done> | <one sentence: reusable artifacts for done, retry guidance for failed>`
|
|
19
19
|
|
|
20
|
-
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. Use the seed contract below for `target: seed`.
|
|
21
21
|
|
|
22
22
|
## Inputs
|
|
23
23
|
|
|
@@ -28,15 +28,15 @@ Read additive inputs `Leg:`, `Rules:`, mapped original AC and, for companions, e
|
|
|
28
28
|
## Procedure
|
|
29
29
|
|
|
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
|
-
2.
|
|
32
|
-
3. Run `git diff --stat <base>`. Open full diff hunks only for files the
|
|
33
|
-
4. Implement the target row using Three-scenario TDD and Test economy below. Run only its targeted check under Evidence command, never the
|
|
34
|
-
5. Update
|
|
35
|
-
6. Append the decision line defined in Output contract.
|
|
36
|
-
7. Remove the `pending:` line from the ledger in your commit. Stage your
|
|
37
|
-
8. Reply with the appended decision
|
|
31
|
+
2. Close the `target` row first. Use `previous decision` and `hint` to avoid repeating work and to try a different approach; keep the target unchanged.
|
|
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.
|
|
35
|
+
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
|
+
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
|
+
8. Reply with the appended decision lines only, target first.
|
|
38
38
|
|
|
39
|
-
For every home row or seed commit, put the saved `pending:` tuple and consumed `iteration:` on separate body lines immediately after the subject's blank separator, matching the companion attribution prefix below. Read that count from the ledger's bumped `iterations:` header, not the task's pre-bump `iteration`. Keep result rows and
|
|
39
|
+
For every home row or seed commit, put the saved `pending:` tuple and consumed `iteration:` on separate body lines immediately after the subject's blank separator, matching the companion attribution prefix below. Read that count from the ledger's bumped `iterations:` header, not the task's pre-bump `iteration`. Keep result rows and decisions in the ledger; write no sidecar or extra commit.
|
|
40
40
|
|
|
41
41
|
## Three-scenario TDD
|
|
42
42
|
|
|
@@ -64,22 +64,22 @@ Require the recorded command to exit nonzero when it selects no test. Before rec
|
|
|
64
64
|
|
|
65
65
|
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
66
|
|
|
67
|
-
Replace steps 2-6 with evidence seeding
|
|
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.
|
|
68
68
|
|
|
69
|
-
For
|
|
69
|
+
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
70
|
|
|
71
|
-
Append exactly one decision line: `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>`.
|
|
71
|
+
Append exactly one decision line: `row 0 done | seeded <k> rows, closed <m> on baseline | <first row to take>`. Count only rows given evidence in this return in k and their proven baseline closures in m, not unreached rows.
|
|
72
72
|
|
|
73
73
|
Stage the seeded evidence changes and ledger, remove `pending:` in that same commit, commit exactly once with subject `loop: seed evidence`, check for a clean tree, and reply with the appended seed decision only.
|
|
74
74
|
|
|
75
75
|
## Companion result commit
|
|
76
76
|
|
|
77
|
-
For a companion `pending:` input, replace ledger mutation/staging and decision appending in the procedure and output contract with the commit-body path below; leave the home ledger untouched. Limit work and seed checks to mapped entries for this leg. Apply the same one-commit and bounded evidence contracts. Prepare the resulting four-column `row | status | attempts | evidence`
|
|
77
|
+
For a companion `pending:` input, replace ledger mutation/staging and decision appending in the procedure and output contract with the commit-body path below; leave the home ledger untouched. Limit work and seed checks to mapped entries for this leg. Apply the same one-commit and bounded evidence contracts. Prepare the resulting four-column `row | status | attempts | evidence` rows in memory, not a sidecar. Serialize them in the companion commit body instead of editing the home ledger; for seed serialize all and only this leg's non-cut rows, including unreached open rows with empty evidence, preserving zero attempts and proven baseline closures. For ordinary work serialize the target, attempts +1 and status done/failed, plus each same-leg `open` -> `done` extra with attempts unchanged under step 6.
|
|
78
78
|
|
|
79
|
-
Use the existing subject `loop: row <n> <status>` or `loop: seed evidence`. Put the exact dispatched `pending:` tuple and consumed `iteration:` on separate body lines, then a blank line, then the resulting pipe-delimited table rows without a header, then a blank line and
|
|
79
|
+
Use the existing subject `loop: row <n> <status>` or `loop: seed evidence`. Put the exact dispatched `pending:` tuple and consumed `iteration:` on separate body lines, then a blank line, then the resulting pipe-delimited table rows without a header, then a blank line and one bounded decision line per changed row, target first (one seed decision for seed). Include the evidence command from Evidence command plus at most three semicolon-separated result lines and escaped pipes in each evidence cell. Compute seed decision counts from this leg only. Stage code/tests explicitly and commit exactly once in the companion; check clean status. Reply with those decision lines only. Let the parent validate the commit and write the home ledger.
|
|
80
80
|
|
|
81
81
|
For coordinated home work, edit only mapped home entries and its seeded state under the ordinary ledger contract; preserve foreign entries, mappings, bases and all other headers except removal of `pending:`.
|
|
82
82
|
|
|
83
83
|
## Boundaries
|
|
84
84
|
|
|
85
|
-
Edit code and tests only for the target row, or the open rows during seed.
|
|
85
|
+
Edit code and tests only for the target row and same-leg `open` extras under step 6, or the open rows during seed. Preserve every other row, including foreign-leg, `cut` and already `done` rows. Preserve row identifiers, row text, ledger headers (except removal of `pending:`), and existing decisions. Never edit the spec or the plan directory outside the supplied ledger. Never touch `main`. Leave whole-project verification and reviews to the parent.
|
|
@@ -411,6 +411,15 @@ test("refresh projects ledger states, numeric pending targets and live leg mappi
|
|
|
411
411
|
text: ledger(["1 | cut | 0 | deferred: #1", "2 | done | 0 | baseline", "3 | done | 1 | check \\| passed", "4 | failed | 1 | check failed", "5 | open | 0 |", "6 | open | 0 |"], "row 3 done | passed | row 4\n## Notes\nrow 2 done | not a decision | none", "pending: 5 | home | abc1234"),
|
|
412
412
|
expected: [["row 1", "skipped"], ["row 2", "skipped"], ["row 3", "complete"], ["row 4", "failed"], ["row 5", "in_progress"], ["row 6", "pending"]],
|
|
413
413
|
},
|
|
414
|
+
{
|
|
415
|
+
name: "child-closed extra is complete without a budget prefix while baseline stays skipped",
|
|
416
|
+
text: ledger([
|
|
417
|
+
"1 | done | 1 | node --test primary.test.mjs; 1 passed", "2 | open | 0 |",
|
|
418
|
+
"3 | done | 0 | node --test extra.test.mjs; 1 passed", "4 | done | 0 | baseline",
|
|
419
|
+
], "row 1 done | Added parser | lib/parser.mjs supplies the parser\nrow 3 done | Reused parser | extra.test.mjs covers the shared path", "allowance: 4"),
|
|
420
|
+
expected: [["row 1", "complete"], ["row 3", "complete"], ["row 4", "skipped"], ["row 2", "pending"]],
|
|
421
|
+
labels: [`1/4: ${descriptions[0]}`, descriptions[2], descriptions[3], `0/4: ${descriptions[1]}`],
|
|
422
|
+
},
|
|
414
423
|
{ name: "retry overrides failed", text: ledger(["1 | failed | 1 | failed"], "", "pending: 1 | home | abc1234"), expected: [["row 1", "in_progress"]] },
|
|
415
424
|
{ name: "leading-zero target names its numeric row", text: ledger(["1 | open | 0 |"], "", "pending: 01 | home | abc1234"), expected: [["row 1", "in_progress"]] },
|
|
416
425
|
{ name: "done beats stale pending", text: ledger(["1 | done | 1 | passed"], "row 1 done | passed | none", "pending: 1 | home | abc1234"), expected: [["row 1", "complete"]] },
|
|
@@ -429,6 +438,7 @@ test("refresh projects ledger states, numeric pending targets and live leg mappi
|
|
|
429
438
|
assert.equal(result.details.error, undefined, row.name);
|
|
430
439
|
assert.equal(result.details.action, "refresh", row.name);
|
|
431
440
|
assert.deepEqual(result.details.tasks.map(t => [t.name, t.status]), row.expected, row.name);
|
|
441
|
+
if (row.labels) assert.deepEqual(result.details.tasks.map(t => t.label), row.labels, row.name);
|
|
432
442
|
assert.deepEqual(validateSnapshot(result.details.tasks as any), [], row.name);
|
|
433
443
|
assert.deepEqual((await h.call({ action: "status" })).details.tasks, result.details.tasks, row.name);
|
|
434
444
|
const done = result.details.tasks.filter(t => ["complete", "skipped"].includes(t.status)).length;
|
package/package.json
CHANGED
|
@@ -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. Render the interrupted/ambiguous-history answer in one sentence: validate the full `<HEAD_BEFORE>..HEAD` range (using the recovered pre-dispatch SHA, including later commits), restore row
|
|
119
|
+
| Confirmed interrupted | Validate the entire `<pre-dispatch HEAD>..HEAD` range, never just `HEAD^..HEAD`, through the home row below. Render the interrupted/ambiguous-history answer in one sentence: validate the full `<HEAD_BEFORE>..HEAD` range (using the recovered pre-dispatch SHA, including later commits), restore every row the child changed (target and extras) and remove their unadmitted decisions from the pre-dispatch copy with the tuple before refresh on boundary rejection, state that iterations stay at the recovered count and child commits/changes are kept; use the saved cells for any other pre-dispatch status/attempts, or all dispatched non-cut rows for seed. Use the recovered tuple/count without another bump or a new commit. |
|
|
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. With zero new commits, keep the tuple and consumed iteration and take the interrupted-dispatch stop. Unrelated movement or multiple commits stop without redispatch or double counting. For a rejected terminal child result, restore the target
|
|
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
|
|
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. With zero new commits, keep the tuple and consumed iteration and take the interrupted-dispatch stop. Unrelated movement or multiple commits stop without redispatch or double counting. For a rejected terminal child result, restore every row the child changed (target and extras) and remove their unadmitted decisions in the working-tree ledger from the pre-dispatch copy with the tuple before refresh (all dispatched non-cut rows for seed); preserve other child changes, child commits and consumed iterations for the human's discard/reset decision. |
|
|
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. Stop preserving state on boundary/attribution failures (zero, unrelated or multiple commits or attribution mismatch); 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
|
|
|
@@ -71,7 +71,7 @@ When a refresh leaves implement active at rule 1, take the matching human stop;
|
|
|
71
71
|
|
|
72
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 hard boundaries and rule 3 before escalation: stagnation stops without dispatch. Preserve `STAGNANT`, `REJECT`, closureReview and grant_fix_rounds boundaries; this is implement permission, not verify credit.
|
|
73
73
|
|
|
74
|
-
Select `seed` until a validated `loop: seed evidence` commit with its `row 0 done` decision
|
|
74
|
+
Select `seed` until a validated `loop: seed evidence` commit with its `row 0 done` decision survives on the branch, independently of `iterations`; 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
75
|
|
|
76
76
|
For a numbered target at attempts == effective allowance - 1 with no existing durable `row <n> escalated` decision, 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 at effective allowance - 1. Never substitute a default-model last attempt for that stop.
|
|
77
77
|
|
|
@@ -96,24 +96,26 @@ Omit the model override except on an escalated round (`model: <implModel>`); let
|
|
|
96
96
|
## Validate the return
|
|
97
97
|
|
|
98
98
|
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`. On dirty/zero/multiple commits restore the
|
|
99
|
+
1. Require empty `git -C "<worktree>" status --porcelain` and exactly 1 from `git -C "<worktree>" rev-list HEAD_BEFORE..HEAD --count`. On dirty/zero/multiple commits restore every row the child changed (target and extras) from the saved copy and use the separately recorded dispatch identity to restore the `pending:` tuple in the working ledger; for seed restore all dispatched non-cut rows. Preserve consumed iterations and all other child changes and commits. Refresh before the discard/reset stop. Use `Stopped: iteration <i> left the tree dirty` or `Stopped: iteration <i> added <k> commits`. Read the ledger from HEAD only after this boundary passes.
|
|
100
100
|
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
101
|
|
|
102
102
|
| Target | Required changes | Miss |
|
|
103
103
|
|---|---|---|
|
|
104
|
-
| Seed | All attempts stay 0; only `open` -> `done` status transitions;
|
|
105
|
-
| Ordinary |
|
|
106
|
-
| Seed or ordinary | No committed tuple remains. | A retained committed tuple is
|
|
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; retry seed once with the miss in `hint:`. A second consecutive miss stops for a human. |
|
|
105
|
+
| 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
|
+
| 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
107
|
|
|
108
|
-
Require ordinary decision
|
|
108
|
+
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
109
|
|
|
110
|
-
On
|
|
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`, then refresh. Count the miss in the existing consecutive-validation-miss window; after the first miss re-dispatch `seed` once with the existing seed-contract instruction followed by `seed miss: <concrete miss>` in `hint:` and `previous decision: none`. After the second consecutive miss, repair and take the existing human stop without another dispatch. A validated seed resets the window, so ordinary dispatch starts clean. Exclude `loop: repair seed` from child-only stagnation. Recover the miss window from branch history on resume; between repair and retry select seed from the restored ledger with the seed-contract instruction only, since the miss hint is transient. Keep dirty/zero/multiple-commit seed returns at the human-gated boundary stop, outside this repair.
|
|
111
|
+
|
|
112
|
+
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 stop because the child is not following the contract. A conforming return resets the consecutive-miss count; parent repair commits do not count toward child-only empty stagnation.
|
|
111
113
|
|
|
112
114
|
## Human stop
|
|
113
115
|
|
|
114
116
|
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.
|
|
115
117
|
|
|
116
|
-
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, stagnation, 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
|
|
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, stagnation, 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.
|
|
117
119
|
|
|
118
120
|
Offer retry and `rows +N` only at row stops (allowance, stagnation or missing-model), alongside Amend and Stop. Dirty-tree and commit-boundary stops keep discard authorization only; interrupted-dispatch stops keep their recovery authorization, never budget offers; the verify-step-1 verification-failure stop keeps amend/stop only. A budget increase never bypasses those gates.
|
|
119
121
|
|
|
@@ -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
|
|
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. Stop preserving state on boundary/attribution failures (zero commits, unrelated movement, multiple commits or attribution mismatch); 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
|
|
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 and two-miss window: commit `loop: repair seed` in home to record the rejection, 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; retry this leg's seed once with the seed-contract instruction plus `seed miss: <concrete miss>` in `hint:`, then stop on a second consecutive miss. A validated seed resets the 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
|
|
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 returns apply the post-boundary repair above; preserve the pending tuple and every row only on boundary rejection. Recover interrupted returns by this same validation, 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. On failure preserve pending and stop. On success use the emitted object for the single parent ledger commit described above; never treat it as permission for another dispatch.
|
|
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. On boundary failure preserve pending and stop; 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
|
|
@@ -66,26 +66,38 @@ const oldRows = table(ledger);
|
|
|
66
66
|
requireThat(new Set(map.map(r => r[0])).size === map.length && map.length === oldRows.length && oldRows.every(r => map.some(m => m[0] === r[0])), 'invalid mapping');
|
|
67
67
|
const expected = oldRows.filter(r => map.some(m => m[0] === r[0] && m[2] === leg) && (target === 'seed' ? r[1] !== 'cut' : r[0] === target));
|
|
68
68
|
requireThat(expected.length && expected.every(r => r[1] !== 'cut'), 'foreign or cut target');
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
const decisionStart = resultLines.findIndex(line => /^row \d+ /.test(line));
|
|
70
|
+
requireThat(decisionStart > 0, 'missing rows or decisions');
|
|
71
|
+
const rowLines = resultLines.slice(0, decisionStart);
|
|
72
|
+
const decisions = resultLines.slice(decisionStart);
|
|
73
|
+
const decision = decisions[0];
|
|
74
|
+
const rows = rowLines.map(cells);
|
|
75
|
+
requireThat(rowLines.every(l => l.startsWith('|') && l.endsWith('|')) && rows.every(r => r.length === 4), 'malformed row');
|
|
76
|
+
requireThat(new Set(rows.map(r => r[0])).size === rows.length, 'duplicate row');
|
|
77
|
+
requireThat(target === 'seed' ? rows.length === expected.length : rows.some(r => r[0] === target), 'missing target or seed row');
|
|
78
|
+
for (const row of rows) {
|
|
79
|
+
const old = (target === 'seed' ? expected : oldRows).find(r => r[0] === row[0]);
|
|
80
|
+
requireThat(old && row[0] === old[0] && map.some(m => m[0] === row[0] && m[2] === leg), 'foreign row');
|
|
81
|
+
const isTarget = row[0] === target;
|
|
82
|
+
requireThat((target === 'seed' ? /^(open|done)$/ : isTarget ? /^(done|failed)$/ : /^done$/).test(row[1]), 'invalid status');
|
|
83
|
+
requireThat(target === 'seed' ? /^(open|done)$/.test(old[1]) : (isTarget ? /^(open|failed)$/.test(old[1]) : old[1] === 'open'), 'changed cut or closed row');
|
|
84
|
+
requireThat(/^\d+$/.test(row[2]) && Number(row[2]) === Number(old[2]) + (isTarget ? 1 : 0) && (target !== 'seed' || Number(row[2]) === 0), 'attempt mismatch');
|
|
85
|
+
requireThat((row[3].length > 0 || (target === 'seed' && row[1] === 'open' && row[3] === old[3])) && row[3].split(';').length <= 4 && !/[<>]/.test(row[3]), 'unbounded evidence');
|
|
78
86
|
requireThat(target !== 'seed' || old[1] !== 'done' || row[1] === 'done', 'lost baseline closure');
|
|
79
87
|
}
|
|
80
88
|
if (target === 'seed') {
|
|
81
|
-
requireThat(subject === 'loop: seed evidence', 'seed subject mismatch');
|
|
89
|
+
requireThat(subject === 'loop: seed evidence' && decisions.length === 1, 'seed subject or decision mismatch');
|
|
82
90
|
const d = /^row 0 done \| seeded (\d+) rows, closed (\d+) on baseline \| .{1,200}$/.exec(decision);
|
|
83
|
-
requireThat(d && Number(d[1]) ===
|
|
91
|
+
requireThat(d && Number(d[1]) >= 1 && Number(d[1]) === rows.filter(r => r[3].length > 0).length && Number(d[2]) === rows.filter(r => r[1] === 'done').length, 'seed counts mismatch');
|
|
84
92
|
} else {
|
|
85
|
-
|
|
86
|
-
requireThat(
|
|
93
|
+
const targetRow = rows.find(r => r[0] === target);
|
|
94
|
+
requireThat(subject === `loop: row ${target} ${targetRow[1]}`, 'row subject mismatch');
|
|
95
|
+
const parsed = decisions.map(line => /^row (\d+) (done|failed) \| .{1,200} \| .{1,200}$/.exec(line));
|
|
96
|
+
requireThat(parsed.length === rows.length && parsed.every(Boolean), 'invalid decision set');
|
|
97
|
+
requireThat(parsed[0][1] === target && new Set(parsed.map(d => d[1])).size === rows.length, 'decision order or duplicate');
|
|
98
|
+
requireThat(parsed.every(d => rows.some(r => r[0] === d[1] && r[1] === d[2])), 'unmatched decision');
|
|
87
99
|
}
|
|
88
|
-
console.log(JSON.stringify({ sha: commit, rows:
|
|
100
|
+
console.log(JSON.stringify({ sha: commit, rows: rowLines, decisions, decision }));
|
|
89
101
|
NODE
|
|
90
102
|
```
|
|
91
103
|
|