mandrel 1.70.0 → 1.72.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/README.md +6 -6
- package/.agents/docs/SDLC.md +4 -5
- package/.agents/docs/configuration.md +9 -9
- package/.agents/docs/workflows.md +4 -6
- package/.agents/schemas/qa-finding.schema.json +1 -1
- package/.agents/scripts/apply-quality-bootstrap.js +2 -2
- package/.agents/scripts/lib/bootstrap/ci-workflow-template.js +1 -1
- package/.agents/scripts/lib/bootstrap/quality-bootstrap.js +1 -1
- package/.agents/scripts/lib/config/defaults.js +1 -1
- package/.agents/scripts/lib/config/sync-agentrc.js +1 -1
- package/.agents/scripts/lib/config-resolver.js +1 -1
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +35 -5
- package/.agents/scripts/lib/qa/qa-context-hydrator.js +1 -1
- package/.agents/scripts/lib/qa/resolve-qa-contract.js +1 -1
- package/.agents/scripts/{agents-update-preflight.js → mandrel-update-preflight.js} +11 -11
- package/.agents/scripts/sync-agentrc.js +2 -2
- package/.agents/skills/skills.index.json +2 -2
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +3 -3
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +4 -4
- package/.agents/workflows/git-deliver.md +298 -0
- package/.agents/workflows/helpers/epic-testing.md +6 -6
- package/.agents/workflows/helpers/{agents-sync-config.md → mandrel-sync-config.md} +5 -4
- package/.agents/workflows/helpers/plan-epic.md +51 -8
- package/.agents/workflows/helpers/plan-story.md +18 -2
- package/.agents/workflows/{agents-update.md → mandrel-update.md} +8 -8
- package/.agents/workflows/plan.md +71 -3
- package/.agents/workflows/qa-explore.md +1 -1
- package/.agents/workflows/{qa-run-harness.md → qa-run.md} +5 -5
- package/README.md +20 -0
- package/docs/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/.agents/workflows/git-commit-all.md +0 -15
- package/.agents/workflows/git-pr-all.md +0 -281
- package/.agents/workflows/git-push.md +0 -63
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: >-
|
|
3
|
+
Single ad-hoc delivery command for working-tree changes. Detects the git
|
|
4
|
+
setup and escalates to the right terminal step — commit only, commit + push,
|
|
5
|
+
or commit + push + open a PR with native auto-merge — picking the default
|
|
6
|
+
from observable state and letting flags pin any level explicitly. Replaces
|
|
7
|
+
the retired git-commit-all, git-push, and git-pr-all trio.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /git-deliver [Message] [--no-push] [--pr] [--draft] [--no-auto-merge] [--branch <name>] [--base <branch>]
|
|
11
|
+
|
|
12
|
+
This workflow is the **single source of truth** for getting outstanding
|
|
13
|
+
working-tree changes out the door when they do not belong to a planned Epic
|
|
14
|
+
(typo fixes, file deletions, doc tweaks, dependency bumps, operator
|
|
15
|
+
housekeeping). It is the ad-hoc counterpart to the heavyweight `/deliver`
|
|
16
|
+
pipeline.
|
|
17
|
+
|
|
18
|
+
It replaces the retired `/git-commit-all`, `/git-push`, and `/git-pr-all`
|
|
19
|
+
commands: instead of choosing a command by how far you want to go, you run
|
|
20
|
+
one command and it **detects the git setup** and escalates to the correct
|
|
21
|
+
terminal step. Flags pin any level explicitly; the interactive choice prompt
|
|
22
|
+
fires **only** when the detected state is genuinely ambiguous, so the common
|
|
23
|
+
path stays non-interactive and scriptable.
|
|
24
|
+
|
|
25
|
+
> **Persona**: `devops-engineer` · **Skills**:
|
|
26
|
+
> `core/git-workflow-and-versioning`
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Terminal levels
|
|
31
|
+
|
|
32
|
+
| Level | Terminal action | Default trigger |
|
|
33
|
+
| ----- | --------------- | --------------- |
|
|
34
|
+
| **commit** | stage + commit on the current branch | `--no-push`, **or** no git remote is configured |
|
|
35
|
+
| **push** | + push the current branch to its upstream | on a feature branch (current ≠ base branch) with a remote |
|
|
36
|
+
| **pr** | + cut/push a feature branch, open a PR, arm auto-merge | on the base branch (a direct push would bounce off branch protection), **or** `--pr` is set |
|
|
37
|
+
|
|
38
|
+
The detection only sets the **default**. Every level is reachable by an
|
|
39
|
+
explicit flag, and the command **announces what it detected and which level
|
|
40
|
+
it is about to run** before it acts.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Arguments
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
/git-deliver [Message] [--no-push] [--pr] [--draft] [--no-auto-merge] [--branch <name>] [--base <branch>]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- `Message` — the commit subject. First line becomes the commit subject (and,
|
|
51
|
+
at the **pr** level, the PR title); if the message contains a blank line,
|
|
52
|
+
everything after it becomes the commit/PR body. When omitted, a timestamped
|
|
53
|
+
fallback (`chore: ad-hoc changes <ISO 8601>`) is used so the commit is never
|
|
54
|
+
unmessageable.
|
|
55
|
+
- `--no-push` — force the **commit** level: stage and commit only, no push.
|
|
56
|
+
Useful when chaining several commits or deferring the push.
|
|
57
|
+
- `--pr` — force the **pr** level even from a feature branch where a plain
|
|
58
|
+
push would otherwise be the default.
|
|
59
|
+
- `--draft` — (pr level) open the PR in draft state and skip arming
|
|
60
|
+
auto-merge. Useful when you want CI to run before flipping to
|
|
61
|
+
ready-for-review.
|
|
62
|
+
- `--no-auto-merge` — (pr level) open a normal (non-draft) PR but do not enable
|
|
63
|
+
GitHub's native auto-merge queue. The operator merges through the UI.
|
|
64
|
+
Default at the pr level is `gh pr merge --auto --squash --delete-branch`.
|
|
65
|
+
- `--branch <name>` — (pr level) override the auto-generated feature branch
|
|
66
|
+
name. When omitted, the branch is slugged from the commit subject (Step 3).
|
|
67
|
+
- `--base <branch>` — override the base branch used for detection and as the PR
|
|
68
|
+
merge target. When omitted, reads `project.baseBranch` from `.agentrc.json`
|
|
69
|
+
(default `main`).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Step 0 — Detect Git Setup & Resolve Level
|
|
74
|
+
|
|
75
|
+
1. Resolve `[BASE_BRANCH]` from `--base` or `.agentrc.json` →
|
|
76
|
+
`project.baseBranch` (default `main`).
|
|
77
|
+
2. Read the current branch: `git rev-parse --abbrev-ref HEAD`.
|
|
78
|
+
3. Verify the working tree has outstanding changes with
|
|
79
|
+
`git status --porcelain`. If the output is empty: **STOP** and tell the
|
|
80
|
+
operator there is nothing to deliver.
|
|
81
|
+
4. Detect whether a remote is configured: `git remote`.
|
|
82
|
+
5. Resolve the **terminal level** from flags + state:
|
|
83
|
+
- `--no-push` set → **commit**.
|
|
84
|
+
- No remote configured → **commit** (warn there is nowhere to push).
|
|
85
|
+
- `--pr` set → **pr**.
|
|
86
|
+
- Current branch equals `[BASE_BRANCH]` → **pr** (a direct push to the
|
|
87
|
+
protected base would be rejected, so the PR flow is the only safe path).
|
|
88
|
+
- Otherwise (a feature branch with a remote) → **push**.
|
|
89
|
+
6. **Ambiguity gate.** Surface an interactive choice **only** when the state is
|
|
90
|
+
genuinely under-determined — for example a **detached HEAD**, or a feature
|
|
91
|
+
branch with a remote but no upstream tracking ref where pushing would need
|
|
92
|
+
`-u`. Present the operator the candidate levels (e.g. "push to a new
|
|
93
|
+
upstream" vs. "open a PR") and proceed with their pick. In every
|
|
94
|
+
non-ambiguous case, do **not** prompt — announce the detected level and
|
|
95
|
+
continue.
|
|
96
|
+
7. Echo a one-line plan to the operator before acting, e.g.
|
|
97
|
+
`detected: on feature branch 'fix/foo' with upstream → level: push`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Step 1 — Compose Commit Message
|
|
102
|
+
|
|
103
|
+
If the operator passed `[Message]`, use it verbatim. Otherwise fall back to
|
|
104
|
+
`chore: ad-hoc changes <ISO 8601 timestamp>`.
|
|
105
|
+
|
|
106
|
+
Split the message on the first blank line:
|
|
107
|
+
|
|
108
|
+
- **Subject** — the first line; commit subject and (pr level) PR title.
|
|
109
|
+
- **Body** — everything after the first blank line; commit body and (pr level)
|
|
110
|
+
PR body. May be empty.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Step 2 — Stage + Commit (all levels)
|
|
115
|
+
|
|
116
|
+
Stage all outstanding changes:
|
|
117
|
+
|
|
118
|
+
```powershell
|
|
119
|
+
git add -A
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Commit:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
git commit -m "<subject>" -m "<body>"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
If the body is empty, omit the second `-m`. If the pre-commit hook fails:
|
|
129
|
+
|
|
130
|
+
1. Read the failure output.
|
|
131
|
+
2. Fix the issue (run `npm run format`, fix lint errors, etc.).
|
|
132
|
+
3. `git add -A` again.
|
|
133
|
+
4. Re-run `git commit` — do **not** pass `--no-verify`.
|
|
134
|
+
|
|
135
|
+
**If the level is `commit`, stop here** and print the commit summary.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Step 3 — Cut Feature Branch (pr level, from-base only)
|
|
140
|
+
|
|
141
|
+
Only when the level is **pr** *and* the current branch equals `[BASE_BRANCH]`.
|
|
142
|
+
Skip when already on a feature branch.
|
|
143
|
+
|
|
144
|
+
When `--branch <name>` is set, use it verbatim. Otherwise generate a branch
|
|
145
|
+
slug from the commit subject:
|
|
146
|
+
|
|
147
|
+
1. Detect the Conventional Commit type prefix (`<type>(<scope>): …`). If
|
|
148
|
+
matched, use `<type>` as the branch namespace. Allowed types: `feat`,
|
|
149
|
+
`fix`, `chore`, `docs`, `refactor`, `test`, `build`, `ci`, `perf`,
|
|
150
|
+
`style`. Anything else (or no prefix) → `chore`.
|
|
151
|
+
2. Strip the type prefix and any leading punctuation from the subject.
|
|
152
|
+
3. Lowercase, replace non-alphanumeric runs with `-`, collapse repeated
|
|
153
|
+
hyphens, trim leading/trailing hyphens.
|
|
154
|
+
4. Truncate to 50 chars on a word boundary.
|
|
155
|
+
5. Combine: `<type>/<slug>`. Example: `"Delete unused files"` →
|
|
156
|
+
`chore/delete-unused-files`.
|
|
157
|
+
|
|
158
|
+
Cut and check out the branch **before committing** — that is, when this step
|
|
159
|
+
applies, run it ahead of Step 2's commit so the commit lands on the feature
|
|
160
|
+
branch, never on the base branch:
|
|
161
|
+
|
|
162
|
+
```powershell
|
|
163
|
+
git checkout -b <branch-name>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
If a local branch with that name already exists, append `-2` (then `-3`, …)
|
|
167
|
+
until `git rev-parse --verify` returns non-zero, and check that out instead.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Step 4 — Push (push and pr levels)
|
|
172
|
+
|
|
173
|
+
Push the current branch. At the **push** level, push to the existing upstream:
|
|
174
|
+
|
|
175
|
+
```powershell
|
|
176
|
+
git push
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
At the **pr** level (or any branch lacking an upstream), set the upstream:
|
|
180
|
+
|
|
181
|
+
```powershell
|
|
182
|
+
git push -u origin <branch-name>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
If the pre-push hook fails:
|
|
186
|
+
|
|
187
|
+
1. Read the failure output.
|
|
188
|
+
2. Fix the offending baseline / test / lint issue in the working tree.
|
|
189
|
+
3. `git add -A`, then create a **new follow-up commit** (do not amend a commit
|
|
190
|
+
that has already been pushed; amending an unpushed commit is fine).
|
|
191
|
+
4. Re-run the push. Never bypass the hook with `--no-verify`.
|
|
192
|
+
|
|
193
|
+
If the push is rejected because the remote has work you do not have locally,
|
|
194
|
+
`git pull --rebase`, resolve conflicts, and push again.
|
|
195
|
+
|
|
196
|
+
**If the level is `push`, stop here** and print the push summary.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Step 5 — Open PR (pr level)
|
|
201
|
+
|
|
202
|
+
```powershell
|
|
203
|
+
gh pr create --base <BASE_BRANCH> --head <branch-name> \
|
|
204
|
+
--title "<subject>" --body "<body-or-default>"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
When the body would otherwise be empty, fall back to a single line:
|
|
208
|
+
`Opened via /git-deliver`. Pass `--draft` to `gh pr create` when the operator
|
|
209
|
+
set `--draft`. Capture the PR URL from stdout for the summary.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Step 6 — Arm Auto-Merge (pr level, default)
|
|
214
|
+
|
|
215
|
+
Skip when `--draft` or `--no-auto-merge` is set.
|
|
216
|
+
|
|
217
|
+
```powershell
|
|
218
|
+
gh pr merge <PR_NUMBER> --auto --squash --delete-branch
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
This queues the PR to merge as soon as required checks turn green and schedules
|
|
222
|
+
head-branch deletion on merge. Auto-merge requires `allow_auto_merge: true` on
|
|
223
|
+
the repo. If `gh pr merge --auto` fails (missing repo feature, insufficient
|
|
224
|
+
token scope), log the failure and surface it — the PR stays open and mergeable
|
|
225
|
+
through the GitHub UI.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Step 7 — Summary
|
|
230
|
+
|
|
231
|
+
Print a single block matched to the level that ran:
|
|
232
|
+
|
|
233
|
+
```text
|
|
234
|
+
# commit level
|
|
235
|
+
✅ Committed on <branch>: <subject>
|
|
236
|
+
|
|
237
|
+
# push level
|
|
238
|
+
✅ Committed + pushed <branch> → origin: <subject>
|
|
239
|
+
|
|
240
|
+
# pr level
|
|
241
|
+
✅ Opened PR #<PR_NUMBER>: <subject>
|
|
242
|
+
<PR_URL>
|
|
243
|
+
branch: <branch-name> → <BASE_BRANCH>
|
|
244
|
+
auto-merge: <enabled | draft | disabled>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Do **not** poll CI. That is the `/deliver` Phase 7 job and is overkill for
|
|
248
|
+
ad-hoc changes. The operator (or GitHub's email notification) is the next
|
|
249
|
+
watcher.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Troubleshooting
|
|
254
|
+
|
|
255
|
+
- **Hook failures**: Read the output, fix the underlying issue, never
|
|
256
|
+
`--no-verify`. The pre-push hook (lint + format + maintainability + audit +
|
|
257
|
+
coverage + CRAP) is the same gate every PR has to pass eventually; failing
|
|
258
|
+
here lets you fix it before opening the PR rather than after CI fails.
|
|
259
|
+
- **Branch already exists locally**: appended `-2`/`-3` per Step 3; pass
|
|
260
|
+
`--branch <name>` for a specific name.
|
|
261
|
+
- **`gh pr create` fails with "no commits between branches"**: the push did not
|
|
262
|
+
move the branch (e.g. it was already at the same SHA as `[BASE_BRANCH]`).
|
|
263
|
+
Verify `git log <BASE_BRANCH>..HEAD` shows commits before re-running.
|
|
264
|
+
- **PR template wins over `--body`**: if `.github/pull_request_template.md`
|
|
265
|
+
exists, `gh pr create --body` overrides it. For ad-hoc PRs the explicit body
|
|
266
|
+
is the right default.
|
|
267
|
+
- **Auto-merge does not fire after CI green**: confirm the PR's required checks
|
|
268
|
+
match the auto-merge requirements. The framework's quality gate
|
|
269
|
+
(`Validate and Test`) is the canonical required check.
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Constraint
|
|
274
|
+
|
|
275
|
+
- **Never** push directly to `[BASE_BRANCH]`. At the pr level Step 3's branch
|
|
276
|
+
cut is mandatory in from-base mode; remove it and the workflow becomes a
|
|
277
|
+
silent bypass of the PR-required policy.
|
|
278
|
+
- **Never** pass `--no-verify` to `git commit` or `git push` to bypass the
|
|
279
|
+
quality gate. Fix the failure at the source.
|
|
280
|
+
- **Never** force-push from `/git-deliver`. This workflow opens new PRs, it
|
|
281
|
+
does not rewrite history. Force-pushes belong to `/git-merge-pr` (with
|
|
282
|
+
`--force-with-lease` after a rebase) and `/deliver` Phase 7.
|
|
283
|
+
- **Always** prefer `--auto --squash --delete-branch` at the pr level unless
|
|
284
|
+
the operator opts out, so `main`'s commit history stays uniform across the
|
|
285
|
+
`/git-deliver` and `/deliver` surfaces.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## ⚠️ Parallel Story Execution
|
|
290
|
+
|
|
291
|
+
Do **not** use this workflow from inside a parallel story-execution context
|
|
292
|
+
(`/deliver #<storyId>`, `/deliver` wave dispatch). `git add -A` sweeps any
|
|
293
|
+
untracked files in the working tree, which in a shared working directory may
|
|
294
|
+
belong to another agent. In those contexts stage explicit paths only and
|
|
295
|
+
confirm `git branch --show-current` reports the expected `story-<id>` branch
|
|
296
|
+
before committing — see
|
|
297
|
+
[`helpers/worktree-lifecycle.md`](helpers/worktree-lifecycle.md) for the
|
|
298
|
+
shared-tree hazard and the worktree-isolation model that contains it.
|
|
@@ -6,12 +6,12 @@ description: QA Epic-testing workflow — ingest the agent-driven QA harness swe
|
|
|
6
6
|
|
|
7
7
|
> **Helper module.** Not a slash command. Invoked from the QA gate during
|
|
8
8
|
> `/deliver` or directly by an operator when the Epic-testing ticket
|
|
9
|
-
> needs refreshed evidence. For ad-hoc acceptance runs use `/qa-run
|
|
9
|
+
> needs refreshed evidence. For ad-hoc acceptance runs use `/qa-run` —
|
|
10
10
|
> this helper owns the Epic-evidence ticket lifecycle on top of it.
|
|
11
11
|
|
|
12
12
|
Gather and attach the acceptance-suite evidence that gates Epic closure. The
|
|
13
13
|
evidence artifact is the **agent-driven QA harness sweep report** produced by
|
|
14
|
-
`/qa-run
|
|
14
|
+
`/qa-run` (scenario pass/fail/blocked totals plus structured
|
|
15
15
|
findings), **not** a hand-ticked markdown checklist.
|
|
16
16
|
|
|
17
17
|
> **When to run**: During the QA phase of an Epic, after all Story merges
|
|
@@ -38,13 +38,13 @@ findings), **not** a hand-ticked markdown checklist.
|
|
|
38
38
|
|
|
39
39
|
## Step 1 — Execute the QA Harness Sweep
|
|
40
40
|
|
|
41
|
-
Invoke `/qa-run
|
|
41
|
+
Invoke `/qa-run` with the chosen selector:
|
|
42
42
|
|
|
43
43
|
```text
|
|
44
|
-
/qa-run
|
|
44
|
+
/qa-run "tag:@smoke and @risk-high"
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
The `/qa-run
|
|
47
|
+
The `/qa-run` workflow (`.agents/workflows/qa-run.md`) owns the
|
|
48
48
|
execution mechanics — `qa` contract resolution, scenario selection, browser
|
|
49
49
|
navigation, and finding capture. This workflow consumes its output.
|
|
50
50
|
|
|
@@ -117,7 +117,7 @@ and deleting the checklist in the same change.
|
|
|
117
117
|
|
|
118
118
|
## Cross-References
|
|
119
119
|
|
|
120
|
-
- Execution mechanics: `.agents/workflows/qa-run
|
|
120
|
+
- Execution mechanics: `.agents/workflows/qa-run.md`.
|
|
121
121
|
- Scenario authoring rules: `.agents/rules/gherkin-standards.md`.
|
|
122
122
|
- Runner / fixture / trace conventions:
|
|
123
123
|
`.agents/skills/stack/qa/playwright-bdd/SKILL.md`.
|
|
@@ -5,15 +5,16 @@ description: >-
|
|
|
5
5
|
surfacing redundant keys (project values that already match framework
|
|
6
6
|
defaults). The runtime layers defaults at read time, so the helper never
|
|
7
7
|
auto-fills optional keys from the template. Invoked by reference from
|
|
8
|
-
/
|
|
8
|
+
/mandrel-update.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# mandrel-sync-config (helper)
|
|
12
12
|
|
|
13
13
|
> **Not a slash command.** Lives under `.agents/workflows/helpers/` so it is
|
|
14
14
|
> not projected into the mandrel plugin command tree. Invoked by reference from
|
|
15
|
-
> [`/
|
|
16
|
-
> shipped as `/agents-sync-config
|
|
15
|
+
> [`/mandrel-update`](../mandrel-update.md) after a framework update; previously
|
|
16
|
+
> shipped as the standalone `/agents-sync-config` command (later demoted to a
|
|
17
|
+
> helper, then renamed alongside `/mandrel-update`). The reconciliation runs as part of the
|
|
17
18
|
> `mandrel update` upgrade path (bump → sync → migrate → doctor).
|
|
18
19
|
>
|
|
19
20
|
> **Configuration reference.** The full set of configurable keys, defaults,
|
|
@@ -74,14 +74,22 @@ Phase 5 (Re-Plan Detection).
|
|
|
74
74
|
one-pager feeds the scope-triage gate below, whose verdict folds into
|
|
75
75
|
the **same** Phase 1 HITL confirmation. Do not stop twice.
|
|
76
76
|
|
|
77
|
-
3. **HITL stop — confirm the sharpened one-pager
|
|
78
|
-
to the operator and **STOP**. Do not proceed to Phase 2
|
|
79
|
-
user explicitly confirms the direction. This is the same gate
|
|
80
|
-
skill's own Phase 3 enforces; surfacing it here makes the wait
|
|
77
|
+
3. **HITL stop — confirm the sharpened one-pager** (**gate #1**): Display
|
|
78
|
+
the one-pager to the operator and **STOP**. Do not proceed to Phase 2
|
|
79
|
+
until the user explicitly confirms the direction. This is the same gate
|
|
80
|
+
the skill's own Phase 3 enforces; surfacing it here makes the wait
|
|
81
81
|
contract visible to `/plan` callers. When the Phase 1.5 verdict is
|
|
82
82
|
`story` or `borderline`, this stop carries the three-way choice the
|
|
83
83
|
triage gate defines (below) instead of a plain confirm.
|
|
84
84
|
|
|
85
|
+
> **`--yes` (headless) auto-proceed.** When `/plan` was invoked with
|
|
86
|
+
> `--yes`, this gate does **not** STOP: the one-pager confirm resolves as
|
|
87
|
+
> **approved** and the run continues to Phase 2. A `story` / `borderline`
|
|
88
|
+
> triage verdict resolves to its **Recommended** branch (below) rather
|
|
89
|
+
> than prompting the three-way choice. Display the one-pager and the
|
|
90
|
+
> verdict line for the record, then proceed without waiting. See
|
|
91
|
+
> [`plan.md` § Headless / non-interactive mode](../plan.md#headless--non-interactive-mode---yes).
|
|
92
|
+
|
|
85
93
|
## Phase 1.5: Scope Triage (ideation path only)
|
|
86
94
|
|
|
87
95
|
This phase runs **only** on the ideation path, immediately after Phase 1
|
|
@@ -124,6 +132,15 @@ skill states once).
|
|
|
124
132
|
avoid the ceremony tax of pushing a story-sized scope through the full Epic
|
|
125
133
|
pipeline.
|
|
126
134
|
|
|
135
|
+
> **`--yes` (headless) exception.** "Never auto-route" is the interactive
|
|
136
|
+
> contract. Under `--yes` the operator has *pre-authorized* the
|
|
137
|
+
> recommendation: the three-way choice resolves to its **Recommended**
|
|
138
|
+
> branch deterministically — `single Story` hands off to
|
|
139
|
+
> `/plan --from-notes <path>` (carrying `--yes` so the receiving story
|
|
140
|
+
> path also auto-proceeds), and an `epic` verdict simply continues to
|
|
141
|
+
> Phase 2. No operator wait. This is the only sanctioned auto-route, and it
|
|
142
|
+
> exists solely to make `/plan` driveable headlessly.
|
|
143
|
+
|
|
127
144
|
## Phase 2: Cross-Epic Duplicate Search
|
|
128
145
|
|
|
129
146
|
Runs immediately after Phase 1 (and only on the s-plan-ideation path).
|
|
@@ -396,6 +413,19 @@ for the scoring logic.
|
|
|
396
413
|
permission") is honored — no `gh issue edit` call until the
|
|
397
414
|
operator confirms.
|
|
398
415
|
|
|
416
|
+
> **`--yes` (headless) auto-proceed.** This refinement-diff confirm is the
|
|
417
|
+
> clarity-gate face of `/plan`'s **gate #1** on the existing-Epic
|
|
418
|
+
> (`/plan <epicId>`) path — it is an operator *wait*, not a deterministic
|
|
419
|
+
> validator (the deterministic half is the section-presence *scoring* in
|
|
420
|
+
> step 1, which always runs). When `/plan` was invoked with `--yes`, this
|
|
421
|
+
> confirm does **not** STOP: the sharpened body is auto-**approved** and the
|
|
422
|
+
> run proceeds to step 6 (persist). The blast-radius note is still displayed
|
|
423
|
+
> for the record; only the operator wait is suppressed. This keeps
|
|
424
|
+
> `/plan <epicId> --yes` driveable headlessly even when the Epic body needs
|
|
425
|
+
> refinement (`gh issue edit` still runs only via the step 6 persist call,
|
|
426
|
+
> which the auto-approval authorizes). See
|
|
427
|
+
> [`plan.md` § Headless / non-interactive mode](../plan.md#headless--non-interactive-mode---yes).
|
|
428
|
+
|
|
399
429
|
6. **Persist**: On approval, run the persist mode:
|
|
400
430
|
|
|
401
431
|
```bash
|
|
@@ -556,18 +586,31 @@ for the scoring logic.
|
|
|
556
586
|
`planningRisk.requiresReview` unless the operator passed
|
|
557
587
|
`--force-review`:
|
|
558
588
|
- **High risk** (`requiresReview === true`) or **operator override**
|
|
559
|
-
(`--force-review`)
|
|
560
|
-
PRD, Tech Spec, and Acceptance Spec on GitHub. Approval is
|
|
561
|
-
user's verbal OK in this session — the three context tickets stay
|
|
589
|
+
(`--force-review`) — **gate #2**: **STOP**. Ask the USER to review the
|
|
590
|
+
generated PRD, Tech Spec, and Acceptance Spec on GitHub. Approval is
|
|
591
|
+
the user's verbal OK in this session — the three context tickets stay
|
|
562
592
|
**open** through delivery and are closed automatically by
|
|
563
593
|
`/deliver` when the Epic PR opens. Do NOT proceed
|
|
564
594
|
to decomposition until the user confirms the plan is accurate.
|
|
595
|
+
|
|
596
|
+
> **`--yes` (headless) auto-proceed.** When `/plan` was invoked with
|
|
597
|
+
> `--yes`, this review gate does **not** STOP, even when
|
|
598
|
+
> `requiresReview === true` or `--force-review` was also passed: the
|
|
599
|
+
> review resolves as **approved** and the run **continues directly to
|
|
600
|
+
> Phase 8**, exactly as the low-risk auto-proceed branch below. The
|
|
601
|
+
> three context tickets stay **open** through delivery as usual; only
|
|
602
|
+
> the operator *wait* is suppressed. This is `/plan`'s **gate #2** —
|
|
603
|
+
> the second and last HITL STOP `--yes` suppresses. `--yes` does
|
|
604
|
+
> **not** alter risk routing or the review criteria themselves; it
|
|
605
|
+
> only forces a proceed where this gate would otherwise STOP. See
|
|
606
|
+
> [`plan.md` § Headless / non-interactive mode](../plan.md#headless--non-interactive-mode---yes).
|
|
565
607
|
- **Low risk** (`requiresReview === false` and no `--force-review`):
|
|
566
608
|
Emit the auto-proceed message from the persist stdout
|
|
567
609
|
(`reviewRouting.operatorMessage`) and **continue directly to Phase 8**
|
|
568
610
|
without an extra review stop. The Epic still carries
|
|
569
611
|
`agent::review-spec` until decomposition completes; the routing
|
|
570
|
-
decision is recorded in the `epic-plan-state` checkpoint.
|
|
612
|
+
decision is recorded in the `epic-plan-state` checkpoint. (`--yes` is
|
|
613
|
+
a no-op on this branch — there is no STOP to suppress.)
|
|
571
614
|
|
|
572
615
|
5. **Tech Spec freshness check (advisory)**: After the Tech Spec issue
|
|
573
616
|
is created, `epic-plan-spec.js` runs
|
|
@@ -68,6 +68,9 @@ to authoring the standalone Story body from the handed-off one-pager.
|
|
|
68
68
|
|
|
69
69
|
# Inspect the draft body without creating an Issue:
|
|
70
70
|
/plan --dry-run --body temp/single-story-draft.md
|
|
71
|
+
|
|
72
|
+
# Headless / non-interactive (auto-proceeds the draft-confirm gate):
|
|
73
|
+
/plan --idea "rip out the unused TaskBodyMigrator export" --yes
|
|
71
74
|
```
|
|
72
75
|
|
|
73
76
|
## Phase 1 — Emit Context
|
|
@@ -153,8 +156,18 @@ add a second stop.
|
|
|
153
156
|
|
|
154
157
|
Display the draft to the operator and **STOP**. Do not call the persist phase
|
|
155
158
|
until the operator explicitly confirms the draft. This mirrors the HITL gate
|
|
156
|
-
`/plan` Phase 3 enforces before opening the Epic Issue.
|
|
157
|
-
|
|
159
|
+
`/plan` Phase 3 enforces before opening the Epic Issue. This is the
|
|
160
|
+
story-path face of `/plan`'s **gate #1** (the ideation one-pager /
|
|
161
|
+
scope-triage confirm). The scope-triage verdict folds into this same stop:
|
|
162
|
+
|
|
163
|
+
> **`--yes` (headless) auto-proceed.** When `/plan` was invoked with `--yes`,
|
|
164
|
+
> this gate does **not** STOP: the draft confirm resolves as **approved** and
|
|
165
|
+
> the run proceeds to Phase 3 (persist). An `epic` verdict resolves to its
|
|
166
|
+
> **Recommended** branch — escalate to `/plan --idea` (carrying `--yes`),
|
|
167
|
+
> abandoning the draft — rather than prompting the three-way choice. Display
|
|
168
|
+
> the draft and the verdict line for the record, then proceed without
|
|
169
|
+
> waiting. See
|
|
170
|
+
> [`plan.md` § Headless / non-interactive mode](../plan.md#headless--non-interactive-mode---yes).
|
|
158
171
|
|
|
159
172
|
- **`story` verdict (or gate skipped via handoff)** → no extra prompt. The
|
|
160
173
|
operator confirms the draft as usual and the run proceeds to Phase 3
|
|
@@ -177,6 +190,9 @@ verdict folds into this same stop:
|
|
|
177
190
|
|
|
178
191
|
**Never auto-route.** The verdict is advisory; the operator always decides,
|
|
179
192
|
and no `agent::*` / label transition happens on either side of the choice.
|
|
193
|
+
(**`--yes` exception:** headless mode pre-authorizes the **Recommended**
|
|
194
|
+
branch deterministically — see the `--yes` note above — the only sanctioned
|
|
195
|
+
auto-route, present solely to make `/plan` driveable without an operator.)
|
|
180
196
|
|
|
181
197
|
## Phase 3 — Persist (`gh issue create`)
|
|
182
198
|
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
stage + commit the staged lockfile bump.
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
# /
|
|
13
|
+
# /mandrel-update
|
|
14
14
|
|
|
15
15
|
> **Upgrade owner.** The mechanical upgrade is owned end to end by the
|
|
16
16
|
> [`mandrel update`](../../lib/cli/update.js) CLI under the npm distribution
|
|
@@ -23,7 +23,7 @@ description: >-
|
|
|
23
23
|
|
|
24
24
|
## Overview
|
|
25
25
|
|
|
26
|
-
`/
|
|
26
|
+
`/mandrel-update` advances the consumer repo to the newest published
|
|
27
27
|
`mandrel` release, re-materializes `.agents/`, and regenerates the
|
|
28
28
|
flat `.claude/commands/` tree (invoked as `/<name>`) against the new workflow
|
|
29
29
|
set — then reconciles the consumer's own config, harness allowlist, and
|
|
@@ -105,7 +105,7 @@ day-0 failure modes — **wrong project**, a **dirty git index**, and being
|
|
|
105
105
|
consumer repo root:
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
|
-
node .agents/scripts/
|
|
108
|
+
node .agents/scripts/mandrel-update-preflight.js
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
The preflight runs three checks and prints a JSON envelope
|
|
@@ -243,8 +243,8 @@ CLI's stderr names it) and run the matching manual remedy from the consumer
|
|
|
243
243
|
repo root. These commands match the hint strings
|
|
244
244
|
[`lib/cli/update.js`](../../lib/cli/update.js) emits verbatim — it is the
|
|
245
245
|
single source of truth, kept in lockstep with this table by the
|
|
246
|
-
`
|
|
247
|
-
([`tests/bootstrap/
|
|
246
|
+
`mandrel-update-recovery-drift` contract test
|
|
247
|
+
([`tests/bootstrap/mandrel-update-recovery-drift.test.js`](../../tests/bootstrap/mandrel-update-recovery-drift.test.js)):
|
|
248
248
|
|
|
249
249
|
| Failed phase | Manual remedy |
|
|
250
250
|
| ----------------- | ------------------------------------------------------- |
|
|
@@ -319,7 +319,7 @@ The helper (Story #1995) is **default-aware** and **read-only**:
|
|
|
319
319
|
modified.
|
|
320
320
|
|
|
321
321
|
Full procedure reference:
|
|
322
|
-
[`helpers/
|
|
322
|
+
[`helpers/mandrel-sync-config.md`](helpers/mandrel-sync-config.md).
|
|
323
323
|
|
|
324
324
|
If the helper prints `No changes required` with no advisories, the config
|
|
325
325
|
is already in sync — carry on. If it lists `[REDUNDANT]` rows, you may
|
|
@@ -392,7 +392,7 @@ rest of the per-Epic temp tree):
|
|
|
392
392
|
contract for the framework.
|
|
393
393
|
|
|
394
394
|
A second run produces `no-change` on every install path, which is the
|
|
395
|
-
guarantee `
|
|
395
|
+
guarantee `mandrel-update`'s idempotence contract requires.
|
|
396
396
|
|
|
397
397
|
## Step 3.6 — Refresh the harness permission allowlist (`/fewer-permission-prompts`)
|
|
398
398
|
|
|
@@ -431,7 +431,7 @@ auto-applied change:
|
|
|
431
431
|
- Apply the accepted subset by editing `.claude/settings.json` and
|
|
432
432
|
stage it alongside the version bump in Step 5.
|
|
433
433
|
|
|
434
|
-
The maintenance cadence is **once per `/
|
|
434
|
+
The maintenance cadence is **once per `/mandrel-update` invocation** —
|
|
435
435
|
the same operator who just ran `mandrel update` is the one with the
|
|
436
436
|
freshest transcript context to review the proposed allowlist
|
|
437
437
|
diff. Skipping the step is fine when the bump introduces no new
|
|
@@ -44,6 +44,7 @@ forwards them to the active path helper:
|
|
|
44
44
|
| `--force` | Epic | Close + recreate an existing ticket tree on re-plan. |
|
|
45
45
|
| `--force-review` | Epic | Force the operator review gate even when risk routing would skip it. |
|
|
46
46
|
| `--allow-over-budget` | Epic | Permit a decomposition that exceeds the framework `maxTickets` reviewability budget. |
|
|
47
|
+
| `--yes` | both | **Non-interactive / headless mode.** Deterministically auto-proceeds the two `/plan` HITL STOP gates — the ideation one-pager / scope-triage confirm (gate #1) and the Phase-7 Epic operator review gate (gate #2) — without waiting for operator input. Parallel to [`/deliver --yes`](deliver.md). Composes with `--allow-over-budget` and with the risk-routed Phase-7 skip (it forces a proceed where those do not apply). Default (flag absent) behavior is unchanged: both gates still STOP for interactive use. |
|
|
47
48
|
| `--steal` | Epic | Forcibly transfer a foreign Epic-lease. |
|
|
48
49
|
| `--dry-run` | both | Author + validate without GitHub writes. |
|
|
49
50
|
| `--body <path>` | Story | Pre-authored Story body file; validate (and create, unless `--dry-run`) without re-authoring. |
|
|
@@ -58,6 +59,71 @@ commands (story-sized Epic ↘ Story; epic-sized Story draft ↗ Epic) is now
|
|
|
58
59
|
an **internal branch switch** inside this router: same skills, same
|
|
59
60
|
helpers, no command hop and no operator re-entry.
|
|
60
61
|
|
|
62
|
+
### Headless / non-interactive mode (`--yes`)
|
|
63
|
+
|
|
64
|
+
`--yes` is the headless escape hatch for an unattended driver (CI, a
|
|
65
|
+
benchmark harness, or any `claude -p` run with no human at the keyboard). It
|
|
66
|
+
is the `/plan`-side parallel of [`/deliver --yes`](deliver.md), which
|
|
67
|
+
suppresses that command's segment-plan confirmation. `/plan` has exactly
|
|
68
|
+
**two** HITL STOP gates, and `--yes` deterministically auto-proceeds **both**
|
|
69
|
+
without waiting for operator input:
|
|
70
|
+
|
|
71
|
+
1. **Gate #1 — the ideation one-pager / scope-triage / clarity confirm.**
|
|
72
|
+
This single conceptual gate has three faces depending on the entry form,
|
|
73
|
+
and `--yes` auto-proceeds **all three**:
|
|
74
|
+
- On the `--idea` Epic path,
|
|
75
|
+
[`helpers/plan-epic.md`](helpers/plan-epic.md) Phase 1 (folding in the
|
|
76
|
+
Phase 1.5 scope-triage verdict) STOPs to confirm the sharpened one-pager.
|
|
77
|
+
- On the `--idea` Story path,
|
|
78
|
+
[`helpers/plan-story.md`](helpers/plan-story.md) Phase 2 STOPs to
|
|
79
|
+
confirm the drafted Story body.
|
|
80
|
+
- On the existing-Epic (`/plan <epicId>`) path, the Phase 6 Epic Clarity
|
|
81
|
+
Gate's **needs-refinement** branch STOPs to confirm the refined-body
|
|
82
|
+
diff before persisting it.
|
|
83
|
+
|
|
84
|
+
Under `--yes` each auto-proceeds: the one-pager / draft / refined-body
|
|
85
|
+
confirm resolves as **approved**, and a `story` / `borderline` triage
|
|
86
|
+
verdict resolves to its **recommended** branch (the one the gate prose
|
|
87
|
+
marks "Recommended") rather than prompting the three-way choice. The
|
|
88
|
+
verdict / clarity scoring is still recorded in chat (one line); only the
|
|
89
|
+
*wait* is suppressed. The clarity-gate *scoring* itself (deterministic
|
|
90
|
+
section-presence in Phase 6 step 1) still runs — `--yes` suppresses only
|
|
91
|
+
the operator confirm of the proposed refinement.
|
|
92
|
+
2. **Gate #2 — the Phase-7 Epic operator review gate.** When risk routing
|
|
93
|
+
forces a review (`planningRisk.requiresReview === true`, or the operator
|
|
94
|
+
also passed `--force-review`),
|
|
95
|
+
[`helpers/plan-epic.md`](helpers/plan-epic.md) Phase 7 STOPs for operator
|
|
96
|
+
approval of the PRD / Tech Spec / Acceptance Spec before decomposition.
|
|
97
|
+
Under `--yes` this review auto-proceeds straight to Phase 8 — the three
|
|
98
|
+
context tickets stay **open** through delivery exactly as on the low-risk
|
|
99
|
+
auto-proceed path.
|
|
100
|
+
|
|
101
|
+
**Composition.** `--yes` is orthogonal to the other planning flags and
|
|
102
|
+
composes cleanly:
|
|
103
|
+
|
|
104
|
+
- With **`--allow-over-budget`**: `--yes` suppresses the gate *waits* while
|
|
105
|
+
`--allow-over-budget` still governs the `maxTickets` over-budget persist —
|
|
106
|
+
passing `--yes` alone does **not** waive the budget gate.
|
|
107
|
+
- With the **risk-routed Phase-7 skip**: when risk routing already skips the
|
|
108
|
+
Phase-7 review (low-risk, no `--force-review`), `--yes` is a no-op for that
|
|
109
|
+
gate — it only *forces a proceed where the gate would otherwise STOP*, it
|
|
110
|
+
never *adds* a stop or relaxes any non-HITL validator.
|
|
111
|
+
|
|
112
|
+
**`--yes` suppresses only the HITL operator *waits* above.** It does **not**
|
|
113
|
+
relax any deterministic gate — the Phase 6 Epic Clarity Gate **scoring**
|
|
114
|
+
(section-presence), the Phase 7.5 Tech Spec Section Gate, the file-assumption
|
|
115
|
+
/ DAG validators, the Phase 10 readiness healthcheck, and the `agent::blocked`
|
|
116
|
+
runtime pause all behave exactly as without the flag. A `--yes` run that hits
|
|
117
|
+
one of those still fails closed; the flag is an operator-input suppressor, not
|
|
118
|
+
a validation override. The other operator-input *waits* in the pipeline also
|
|
119
|
+
auto-proceed under `--yes` — the non-blocking Phase 2 duplicate-search pause
|
|
120
|
+
(distinct-Epic confirmed), the Phase 6 clarity refinement-diff confirm
|
|
121
|
+
(refined body approved), and the advisory Phase 8.3/8.4/8.5
|
|
122
|
+
consolidation/critic diffs (consolidated/critic output applied) — since they
|
|
123
|
+
are operator-input waits, not validators. The two *named* HITL STOP gates the
|
|
124
|
+
Story tracks (gate #1, gate #2) are the load-bearing pair; these additional
|
|
125
|
+
waits are auto-proceeded for the same headless reason.
|
|
126
|
+
|
|
61
127
|
## First-run preflight
|
|
62
128
|
|
|
63
129
|
Before routing to a path helper, run a **first-run preflight** to catch
|
|
@@ -109,9 +175,11 @@ stubbed docs, or an unready doctor verdict).
|
|
|
109
175
|
[`core/scope-triage`](../skills/core/scope-triage/SKILL.md) skill on the
|
|
110
176
|
seed. Record the verdict in chat (one line).
|
|
111
177
|
4. **Delegate.** Read the selected path helper **in full** and execute it
|
|
112
|
-
from its entry phase, forwarding the absorbed flags
|
|
113
|
-
numbering, HITL gates, and scripts are unchanged — this
|
|
114
|
-
phase content.
|
|
178
|
+
from its entry phase, forwarding the absorbed flags (including `--yes`).
|
|
179
|
+
The helper's phase numbering, HITL gates, and scripts are unchanged — this
|
|
180
|
+
router adds no phase content. When `--yes` is present, the two HITL STOP
|
|
181
|
+
gates auto-proceed per [Headless / non-interactive mode](#headless--non-interactive-mode---yes)
|
|
182
|
+
above; every deterministic gate still runs.
|
|
115
183
|
5. **Internal returns.** When a path helper would historically have handed
|
|
116
184
|
off to the other planning command, switch helpers in-place and continue;
|
|
117
185
|
surface the switch to the operator as a one-line note.
|
|
@@ -19,7 +19,7 @@ operator watches and gates.** Its human-led sibling is
|
|
|
19
19
|
the agent scribes/enriches. No human-driven flow lives in `/qa-explore`; if you
|
|
20
20
|
want to capture something *you* observed, use `/qa-assist` instead.
|
|
21
21
|
|
|
22
|
-
Unlike [`/qa-run
|
|
22
|
+
Unlike [`/qa-run`](qa-run.md) (which steps a known set of
|
|
23
23
|
Gherkin `.feature` scenarios through a browser), `/qa-explore` is **open-ended
|
|
24
24
|
exploration**: the agent probes the surface for product bugs, environment-setup
|
|
25
25
|
friction, tooling/DX gaps, missing tests, and enhancement ideas — each captured
|