mandrel 2.41.0 → 2.42.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/.agents/agents/story-worker.md +24 -14
- package/.agents/docs/agentrc-reference.json +7 -2
- package/.agents/docs/configuration.md +5 -2
- package/.agents/schemas/agentrc.schema.json +17 -2
- package/.agents/schemas/validation-evidence.schema.json +3 -1
- package/.agents/scripts/acceptance-eval.js +68 -3
- package/.agents/scripts/coverage-capture.js +25 -8
- package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -2
- package/.agents/scripts/lib/baselines/git-base.js +74 -38
- package/.agents/scripts/lib/close-validation/gates.js +153 -25
- package/.agents/scripts/lib/close-validation/process.js +30 -1
- package/.agents/scripts/lib/close-validation/runner.js +5 -0
- package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +33 -12
- package/.agents/scripts/lib/config/quality.js +36 -21
- package/.agents/scripts/lib/config-settings-schema-delivery.js +6 -0
- package/.agents/scripts/lib/coverage-capture-incremental.js +12 -6
- package/.agents/scripts/lib/crap-baseline-join.js +11 -7
- package/.agents/scripts/lib/full-suite-lock.js +311 -0
- package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -104
- package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +320 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +8 -1
- package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +83 -4
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +39 -7
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +70 -18
- package/.agents/scripts/lib/orchestration/verify-credit.js +207 -0
- package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +24 -0
- package/.agents/workflows/helpers/acceptance-self-eval.md +12 -0
- package/.agents/workflows/helpers/deliver-digest.md +31 -10
- package/.agents/workflows/helpers/deliver-story-reference.md +50 -30
- package/.agents/workflows/helpers/deliver-story.md +23 -21
- package/docs/CHANGELOG.md +18 -0
- package/package.json +1 -1
|
@@ -233,17 +233,19 @@ runs maker-blind at Story-scope review inside the close subprocess. The
|
|
|
233
233
|
dispatch step produces `checklistPath` from the Story's predicted footprint
|
|
234
234
|
before it spawns the worker — see [`/mandrel-deliver`](../mandrel-deliver.md).
|
|
235
235
|
|
|
236
|
-
**
|
|
236
|
+
**Full-suite discipline (spine Step 2.5).** Repo-invariant guards —
|
|
237
237
|
drift-guard and schema tests living outside the Story's scoped greps — are
|
|
238
238
|
the failure class that actually bounces deliveries: close-validation
|
|
239
239
|
discovers them only after the whole close pipeline has run, at several times
|
|
240
|
-
the cost of one
|
|
240
|
+
the cost of one full-suite run in the worktree.
|
|
241
241
|
|
|
242
|
-
**Run it so close can credit it.**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
242
|
+
**Run it once, last, so close can credit it.** The run belongs **after** the
|
|
243
|
+
self-eval loop's last fix commit and immediately **before** the hand-off push,
|
|
244
|
+
so its stamp describes the tree that is pushed; redraft rounds run scoped
|
|
245
|
+
tests. Close skips a gate that already passed at the current HEAD, but a bare
|
|
246
|
+
`npm test` deposits no such record — the suite then runs twice per delivery,
|
|
247
|
+
once here and once in the close gate chain. Pick the invocation by the same
|
|
248
|
+
predicate `close-validation/gates.js` uses to choose its test gate:
|
|
247
249
|
|
|
248
250
|
```bash
|
|
249
251
|
# CRAP gate enabled (default) + a `test:coverage` script — writes the stamp
|
|
@@ -259,7 +261,15 @@ node <main-repo>/.agents/scripts/evidence-gate.js --standalone \
|
|
|
259
261
|
The credit expires the moment it stops describing the tree: evidence is keyed
|
|
260
262
|
on HEAD, the capture stamp on a content digest of `crap.targetDirs`. A
|
|
261
263
|
self-eval fix — or any commit — invalidates it and close re-runs the suite for
|
|
262
|
-
real, so this never trades away the gate.
|
|
264
|
+
real, so this never trades away the gate. That keying is exactly why the run
|
|
265
|
+
comes last.
|
|
266
|
+
|
|
267
|
+
**`verify[]` reuses the same stamp.** A `verify[]` entry that is itself a
|
|
268
|
+
full-suite command is reported **credited** against that stamp rather than
|
|
269
|
+
respawned (`resolveVerifyCredit` in
|
|
270
|
+
[`verify-credit.js`](../../scripts/lib/orchestration/verify-credit.js)), and the
|
|
271
|
+
self-eval gate warns when it sees one: the intended shape is scoped `verify[]`
|
|
272
|
+
entries **plus** the single credited run.
|
|
263
273
|
|
|
264
274
|
**Conflict with `main` mid-implementation** → resolve as you would any branch
|
|
265
275
|
rebase. There is no `epic/<id>` intermediate, so the rebase base is `main`
|
|
@@ -500,22 +510,16 @@ judgment that help text cannot carry.
|
|
|
500
510
|
|
|
501
511
|
The `single-story-close.js` script, in order:
|
|
502
512
|
|
|
503
|
-
1.
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
goes to `temp/orchestration/close-gates-<storyId>.log`; a clean run reports
|
|
507
|
-
one digest line naming that artifact, and a **failed** gate replays its
|
|
508
|
-
captured tail inline so the evidence is in front of you without opening a
|
|
509
|
-
file. Read the artifact when you need the full text — or re-run under
|
|
510
|
-
`AGENT_LOG_LEVEL=verbose` for live streaming.
|
|
511
|
-
1a. **Syncs the Story branch from `origin/<baseBranch>`** before push.
|
|
512
|
-
Runs `git fetch origin <baseBranch>` followed by
|
|
513
|
-
`git merge --no-edit origin/<baseBranch>` inside the worktree. This
|
|
513
|
+
1. **Syncs the Story branch from `origin/<baseBranch>`** — before the gates,
|
|
514
|
+
not after them. Runs `git fetch origin <baseBranch>` followed
|
|
515
|
+
by `git merge --no-edit origin/<baseBranch>` inside the worktree. This
|
|
514
516
|
defends against the parallel-`/deliver-story` race: when
|
|
515
517
|
multiple sessions run in parallel, the Story that auto-merges first
|
|
516
518
|
bumps `baseBranch`, and without this sync the lagging Stories open
|
|
517
519
|
PRs that are "behind base" and stall against branch-protection's
|
|
518
|
-
`up-to-date branch` rule.
|
|
520
|
+
`up-to-date branch` rule. Running it first also means a conflict costs
|
|
521
|
+
no gate run at all, and — the load-bearing half — the tree the gates
|
|
522
|
+
validate is the tree the push sends. Outcomes:
|
|
519
523
|
- **No-op / fast-forward / clean merge-commit** → close proceeds to
|
|
520
524
|
push.
|
|
521
525
|
- **Merge conflict** → the merge is aborted, a `friction` structured
|
|
@@ -533,12 +537,26 @@ The `single-story-close.js` script, in order:
|
|
|
533
537
|
closes the PR-open-time race but a residual race remains between PR
|
|
534
538
|
open and auto-merge fire.
|
|
535
539
|
|
|
536
|
-
2.
|
|
537
|
-
|
|
540
|
+
2. Runs the close-validation gates against `baseBranch` as the baseline.
|
|
541
|
+
On any gate failure it throws — the operator fixes and re-runs close.
|
|
542
|
+
The chain fails cheapest-first: `typecheck`, `lint`, `format` and the
|
|
543
|
+
coverage-independent half of the baselines gate
|
|
544
|
+
(`check-baselines-independent`) run in parallel, and only once they are
|
|
545
|
+
green does the serial walk pay for `coverage-capture` and the
|
|
546
|
+
coverage-consuming half (`check-baselines-coverage`).
|
|
547
|
+
**Gate output is captured, not streamed.** Every gate line
|
|
548
|
+
goes to `temp/orchestration/close-gates-<storyId>.log`; a clean run reports
|
|
549
|
+
one digest line naming that artifact, and a **failed** gate replays its
|
|
550
|
+
captured tail inline so the evidence is in front of you without opening a
|
|
551
|
+
file. Read the artifact when you need the full text — or re-run under
|
|
552
|
+
`AGENT_LOG_LEVEL=verbose` for live streaming.
|
|
553
|
+
|
|
554
|
+
3. Pushes `story-<id>` to `origin`.
|
|
555
|
+
4. Probes for an existing open PR with `head = story-<id>`. If none
|
|
538
556
|
exists, opens one via `gh pr create --base <baseBranch>`. The PR
|
|
539
557
|
body carries `Closes #<storyId>` so the GitHub merge auto-closes the
|
|
540
558
|
issue.
|
|
541
|
-
|
|
559
|
+
4a. **Enables GitHub native auto-merge by default** via
|
|
542
560
|
`gh pr merge <prNumber> --auto --squash --delete-branch`. Once CI's
|
|
543
561
|
required checks turn green, GitHub squash-merges the PR and deletes
|
|
544
562
|
the source branch — the operator does not need to babysit the merge
|
|
@@ -546,7 +564,7 @@ The `single-story-close.js` script, in order:
|
|
|
546
564
|
non-fatal: the operator retains the manual merge surface in the
|
|
547
565
|
GitHub UI. Pass `--no-auto-merge` to opt out when the PR needs a
|
|
548
566
|
pre-merge eyeball.
|
|
549
|
-
|
|
567
|
+
5. Flips the Story to **`agent::closing`** (NOT `agent::done`) and leaves
|
|
550
568
|
the GitHub issue **OPEN**. Auto-merge completes
|
|
551
569
|
asynchronously _after_ this script exits, so closing the issue here
|
|
552
570
|
would strand a CLOSED issue with no merged work if the PR later failed
|
|
@@ -557,9 +575,9 @@ The `single-story-close.js` script, in order:
|
|
|
557
575
|
`--no-wait-merge` run, or the in-close confirm phase on the
|
|
558
576
|
close-and-land default. (Step 5.5 is the Status-column resync.) A Story
|
|
559
577
|
only reaches `agent::done` once its PR to `main` is confirmed merged.
|
|
560
|
-
|
|
578
|
+
6. Reaps the worktree when `delivery.worktreeIsolation.reapOnSuccess`
|
|
561
579
|
is enabled.
|
|
562
|
-
|
|
580
|
+
7. **Releases the Story lease.** Clears the Story assignment
|
|
563
581
|
that init claimed so the next `/deliver-story` run sees an
|
|
564
582
|
unclaimed ticket. The release is a no-op when the operator no longer
|
|
565
583
|
holds the claim (a later run took over via reclaim/steal), so a late
|
|
@@ -572,13 +590,15 @@ The `single-story-close.js` script, in order:
|
|
|
572
590
|
de-assigning the ticket. The close result carries
|
|
573
591
|
`leaseReleased: <boolean>`.
|
|
574
592
|
|
|
575
|
-
`--skip-validation` bypasses
|
|
593
|
+
`--skip-validation` bypasses the gate step. Use only when re-running
|
|
576
594
|
close after a fixed gate failure that's already known to pass.
|
|
577
595
|
|
|
578
|
-
`--skip-sync` bypasses
|
|
579
|
-
close after a hand-resolved sync, or in tests.
|
|
596
|
+
`--skip-sync` bypasses the base-sync step. Use only when re-running
|
|
597
|
+
close after a hand-resolved sync, or in tests. The two flags are
|
|
598
|
+
independent: either, both or neither may be set, and each elides exactly
|
|
599
|
+
its own phase.
|
|
580
600
|
|
|
581
|
-
`--no-auto-merge` disables
|
|
601
|
+
`--no-auto-merge` disables the auto-merge arm (step 4a). Use when the PR materially changes
|
|
582
602
|
behaviour and warrants pre-merge review.
|
|
583
603
|
|
|
584
604
|
---
|
|
@@ -40,7 +40,7 @@ that dispatched the work**, never to a spawned worker.
|
|
|
40
40
|
|
|
41
41
|
**A worker returning no terminal envelope is expected, not a failure** — only
|
|
42
42
|
Step 3 mints one. Never re-dispatch the Story on it; resume per § Recovery
|
|
43
|
-
(reference § Idempotence
|
|
43
|
+
(reference § Idempotence).
|
|
44
44
|
|
|
45
45
|
## Step 0 — Initialize (`single-story-init.js`)
|
|
46
46
|
|
|
@@ -73,12 +73,8 @@ One branch, one PR to `main`, commits against the inline `acceptance[]` /
|
|
|
73
73
|
digest-first; read a caller-provided `checklistPath` first, and walk any
|
|
74
74
|
`## Slicing` rows as **intra-session checkpoints** (reference § Step 1).
|
|
75
75
|
2. Implement and commit on the Story branch, iterating with quick advisory
|
|
76
|
-
gates (`typecheck`, `lint`, scoped tests) — the full chain runs in Step 3
|
|
77
|
-
|
|
78
|
-
guards outside the Story's scoped greps are the failure class that bounces
|
|
79
|
-
deliveries. Fix and commit first, then run the self-eval loop. Run it **so
|
|
80
|
-
Step 3 credits it** — a bare `npm test` records nothing, so close re-runs
|
|
81
|
-
the identical suite (reference § Step 1, "Pre-eval full-suite discipline").
|
|
76
|
+
gates (`typecheck`, `lint`, scoped tests) — the full chain runs in Step 3,
|
|
77
|
+
and the **one** creditable full-suite run at Step 2.5.
|
|
82
78
|
|
|
83
79
|
### Step 1a — Bounded acceptance self-eval loop (**required**)
|
|
84
80
|
|
|
@@ -94,14 +90,21 @@ Ceremony is `delivery.routing.ceremonyProfile` × the **derived change level**,
|
|
|
94
90
|
never a planner-authored verdict. **Digest § 3** is the incantation (change set
|
|
95
91
|
once, derive the level, resolve critics with `ceremony-routing.js`); edge cases
|
|
96
92
|
are reference § Step 2. Hard gates always run in Step 3 — the derived level
|
|
97
|
-
never disables them; do **not** pre-run the chain here.
|
|
93
|
+
never disables them; do **not** pre-run the chain here — Step 2.5's credited
|
|
94
|
+
suite run is the sole exception.
|
|
98
95
|
|
|
99
|
-
### Step 2.5 —
|
|
96
|
+
### Step 2.5 — The creditable full-suite run, then push and hand off
|
|
100
97
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
Run the full suite **once**, after the self-eval loop's last fix commit and
|
|
99
|
+
immediately **before** the push, in the shape close credits (**digest § 5**):
|
|
100
|
+
the credit is keyed on the tree, so any later commit invalidates it, and a bare
|
|
101
|
+
`npm test` deposits none. Red → fix, commit, re-run. An inline run makes the
|
|
102
|
+
same run before Step 3.
|
|
103
|
+
|
|
104
|
+
Then (sub-agent dispatch only) push `story-<storyId>` to `origin`, confirm the
|
|
105
|
+
remote ref moved, and return the hand-off — Story id, `workCwd`, branch, pushed
|
|
106
|
+
head SHA, self-eval verdict, `verify[]` evidence — then stop. Do not open the
|
|
107
|
+
PR; do not compose a terminal envelope.
|
|
105
108
|
|
|
106
109
|
## Step 3 — Close and land (`single-story-close.js`)
|
|
107
110
|
|
|
@@ -115,7 +118,7 @@ node <main-repo>/.agents/scripts/single-story-close.js --story <storyId> --cwd <
|
|
|
115
118
|
**The whole delivery tail** — gates, PR, merge wait, `agent::done` flip,
|
|
116
119
|
post-land tail in one process. Never background it, never delegate it to a
|
|
117
120
|
child, and never end your turn while it is still running: "close is running"
|
|
118
|
-
is not a return value. Branch on the envelope's `status` per **digest §
|
|
121
|
+
is not a return value. Branch on the envelope's `status` per **digest § 6**
|
|
119
122
|
(`landed` → Step 7; `pending` → run `nextCommand`; `blocked`/`checks-failed`
|
|
120
123
|
→ Step 4; `failed` → diagnose, re-run). Gate output is captured.
|
|
121
124
|
|
|
@@ -126,7 +129,7 @@ Internals, merge-wait budgets, the slow-CI **async** confirm mode, the
|
|
|
126
129
|
|
|
127
130
|
Relay the validated envelope close emits between its
|
|
128
131
|
`--- STORY DELIVER TERMINAL ---` markers — never free-form prose, never a
|
|
129
|
-
hand-composed object. Statuses, exits and fields: **digest §
|
|
132
|
+
hand-composed object. Statuses, exits and fields: **digest § 6** (SSOT: the
|
|
130
133
|
shipped [schema](../../schemas/story-deliver-terminal.schema.json)).
|
|
131
134
|
`pending` is the only sanctioned no-merge ending.
|
|
132
135
|
|
|
@@ -139,15 +142,14 @@ so only a green on a NEW head SHA re-arms it — a re-run is refused; fix at sou
|
|
|
139
142
|
and push ([`rules/ci-remediation.md`](../../rules/ci-remediation.md)). And a
|
|
140
143
|
`tail.*: false` degrades the report, never the land.
|
|
141
144
|
|
|
142
|
-
**Watch exit codes** — `pr-watch-with-update.js` exits 0 green, 1
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
and no digest exists to read.
|
|
145
|
+
**Watch exit codes** — `pr-watch-with-update.js` exits 0 green, 1 on a genuine
|
|
146
|
+
red, 2 slow-but-not-red (still-running, unresolved, or `notYetStarted`). Never
|
|
147
|
+
route a 2 onto the red path: nothing is broken and no digest exists to read.
|
|
148
|
+
Which slow condition, and what to do: reference § Step 4.
|
|
147
149
|
|
|
148
150
|
**Lost envelope first: read it off disk.** Close persists each to
|
|
149
151
|
`temp/orchestration/story-deliver-terminal-<storyId>.json`; branch on it per
|
|
150
|
-
digest §
|
|
152
|
+
digest § 6. Otherwise do not guess — probe **read-only** with
|
|
151
153
|
`node .agents/scripts/deliver-recover.js --story <storyId>`; it prints the
|
|
152
154
|
**one** next command with its evidence, never a menu. A live close answers
|
|
153
155
|
`close-in-flight`: wait, never re-init underneath it.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,24 @@ All notable changes to this project will be documented in this file.
|
|
|
15
15
|
-->
|
|
16
16
|
<!-- markdownlint-disable-file MD004 MD012 MD037 -->
|
|
17
17
|
|
|
18
|
+
## [2.42.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.41.0...mandrel-v2.42.0) (2026-09-06)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
* full-suite capture economy: default the coverage-independent skip on, and serialize concurrent captures behind a host lock ([#5173](https://github.com/dsj1984/mandrel/issues/5173)) ([#5178](https://github.com/dsj1984/mandrel/issues/5178)) ([ed79751](https://github.com/dsj1984/mandrel/commit/ed7975199b6e2a3279a5d0d02b50e3068509987f))
|
|
24
|
+
* story-worker digest carries the creditable full-suite invocation, runs it after self-eval, and the critic reuses its stamp ([#5174](https://github.com/dsj1984/mandrel/issues/5174)) ([#5175](https://github.com/dsj1984/mandrel/issues/5175)) ([1e46457](https://github.com/dsj1984/mandrel/commit/1e464574aa6305dcc8f1ff8522015ae0f9a5301a))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
* scope the baseline refresh acknowledgment to the rows the refresh commit actually refreshed ([#5179](https://github.com/dsj1984/mandrel/issues/5179)) ([#5180](https://github.com/dsj1984/mandrel/issues/5180)) ([e8758b9](https://github.com/dsj1984/mandrel/commit/e8758b909ec19ed55c0678c05f481d515937f978))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
* close fails fast: base-sync before validation, and coverage-independent baseline kinds in the parallel gate phase ([#5172](https://github.com/dsj1984/mandrel/issues/5172)) ([#5177](https://github.com/dsj1984/mandrel/issues/5177)) ([dff33d5](https://github.com/dsj1984/mandrel/commit/dff33d530965ef7da8ee3dd4f1f218d11805273f))
|
|
35
|
+
|
|
18
36
|
## [2.41.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.40.0...mandrel-v2.41.0) (2026-09-06)
|
|
19
37
|
|
|
20
38
|
|
package/package.json
CHANGED