mandrel 2.14.0 → 2.16.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/audit-checklists/navigability.md +1 -1
- package/.agents/docs/workflows.md +4 -4
- package/.agents/scripts/acceptance-eval.js +18 -1
- package/.agents/scripts/agents-bootstrap-github.js +22 -1
- package/.agents/scripts/apply-quality-bootstrap.js +6 -0
- package/.agents/scripts/audit-labels-bootstrap.js +15 -1
- package/.agents/scripts/audit-to-stories.js +26 -1
- package/.agents/scripts/boot-sweep.js +4 -1
- package/.agents/scripts/bootstrap.js +1 -0
- package/.agents/scripts/check-arch-cycles.js +20 -0
- package/.agents/scripts/check-baselines.js +8 -2
- package/.agents/scripts/check-context-budget.js +40 -5
- package/.agents/scripts/check-dead-exports.js +21 -0
- package/.agents/scripts/check-doc-links.js +12 -1
- package/.agents/scripts/check-lifecycle-doc-drift.js +9 -0
- package/.agents/scripts/check-workflow-citations.js +332 -0
- package/.agents/scripts/deliver-light.js +32 -3
- package/.agents/scripts/deliver-recover.js +4 -1
- package/.agents/scripts/diagnose-friction.js +17 -1
- package/.agents/scripts/diagnose.js +20 -14
- package/.agents/scripts/drain-pending-cleanup.js +20 -1
- package/.agents/scripts/evidence-gate.js +20 -1
- package/.agents/scripts/generate-config-docs.js +14 -1
- package/.agents/scripts/generate-lifecycle-docs.js +14 -1
- package/.agents/scripts/generate-workflows-doc.js +14 -1
- package/.agents/scripts/git-cleanup.js +32 -1
- package/.agents/scripts/lib/cli-usage.js +174 -0
- package/.agents/scripts/lib/cli-utils.js +12 -0
- package/.agents/scripts/lib/close-validation/process.js +61 -15
- package/.agents/scripts/lib/doc-tiers.js +53 -10
- package/.agents/scripts/lib/orchestration/complexity-gate.js +307 -89
- package/.agents/scripts/lib/orchestration/light-suitability.js +31 -9
- package/.agents/scripts/lib/orchestration/plan-context.js +205 -20
- package/.agents/scripts/lib/orchestration/single-story-close/gate-log.js +87 -13
- package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +24 -15
- package/.agents/scripts/lib/workflow-closure.js +431 -0
- package/.agents/scripts/mandrel-update-preflight.js +9 -0
- package/.agents/scripts/nav-registry-diff.js +13 -0
- package/.agents/scripts/plan-context.js +21 -2
- package/.agents/scripts/plan-critics.js +10 -0
- package/.agents/scripts/plan-persist.js +33 -1
- package/.agents/scripts/plan-run-epilogue.js +12 -1
- package/.agents/scripts/quality-preview.js +17 -1
- package/.agents/scripts/resolve-doc-tiers.js +13 -0
- package/.agents/scripts/resolve-stories.js +1 -0
- package/.agents/scripts/resync-status-column.js +4 -1
- package/.agents/scripts/signals-view.js +11 -0
- package/.agents/scripts/single-story-close.js +24 -0
- package/.agents/scripts/single-story-confirm-merge.js +16 -0
- package/.agents/scripts/single-story-init.js +21 -1
- package/.agents/scripts/stories-wave-tick.js +1 -0
- package/.agents/scripts/sync-agentrc.js +16 -4
- package/.agents/scripts/update-ticket-state.js +23 -2
- package/.agents/workflows/audit-navigability.md +2 -2
- package/.agents/workflows/audit-to-stories.md +1 -1
- package/.agents/workflows/deliver.md +80 -81
- package/.agents/workflows/git-cleanup.md +9 -14
- package/.agents/workflows/helpers/acceptance-self-eval.md +14 -13
- package/.agents/workflows/helpers/audit-lens-core.md +2 -2
- package/.agents/workflows/helpers/code-review.md +11 -11
- package/.agents/workflows/helpers/deliver-digest.md +7 -8
- package/.agents/workflows/helpers/deliver-light.md +222 -0
- package/.agents/workflows/helpers/deliver-reference.md +46 -14
- package/.agents/workflows/helpers/deliver-story-reference.md +55 -63
- package/.agents/workflows/helpers/deliver-story.md +22 -22
- package/.agents/workflows/helpers/mandrel-sync-config.md +2 -2
- package/.agents/workflows/helpers/parallel-tooling.md +1 -2
- package/.agents/workflows/helpers/plan-reference.md +96 -17
- package/.agents/workflows/helpers/worktree-lifecycle.md +1 -4
- package/.agents/workflows/mandrel-update.md +6 -6
- package/.agents/workflows/plan.md +90 -85
- package/.agents/workflows/prototype.md +104 -0
- package/docs/CHANGELOG.md +32 -0
- package/package.json +2 -1
- package/.agents/workflows/deliver-light.md +0 -148
|
@@ -108,10 +108,7 @@ PowerShell `Get-CimInstance Win32_Process`, terminating them with
|
|
|
108
108
|
|
|
109
109
|
> **Not a slash command (decision overturned).** The drain is **not** a
|
|
110
110
|
> `/drain-pending-cleanup` slash command — it was demoted to a
|
|
111
|
-
> directly-runnable script
|
|
112
|
-
> `docs/decisions.md` matrix row that originally kept it as a command).
|
|
113
|
-
> The wave-era automatic callers were deleted with the epic-runner in
|
|
114
|
-
> the v2 cutover, so the drain is now operator-driven:
|
|
111
|
+
> directly-runnable script. The drain is operator-driven:
|
|
115
112
|
> `node .agents/scripts/drain-pending-cleanup.js`.
|
|
116
113
|
|
|
117
114
|
### When to run it manually
|
|
@@ -4,7 +4,7 @@ description: >-
|
|
|
4
4
|
(resolve newest published version → install → re-materialize `.agents/` →
|
|
5
5
|
migrate → doctor → surface changelog) as the single mechanical step, then
|
|
6
6
|
walks the operator through the judgment wraparound the CLI deliberately
|
|
7
|
-
leaves unowned: reconcile `.agentrc.json`, install the
|
|
7
|
+
leaves unowned: reconcile `.agentrc.json`, install the stabilized
|
|
8
8
|
quality-gate surface, refresh the harness permission allowlist, reconcile
|
|
9
9
|
the consumer's `AGENTS.md` / runbooks against the surfaced changelog, and
|
|
10
10
|
stage + commit the staged lockfile bump.
|
|
@@ -14,10 +14,10 @@ description: >-
|
|
|
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
|
|
17
|
-
> model
|
|
17
|
+
> model. This workflow wraps that CLI: it runs
|
|
18
18
|
> `npx mandrel update`, then walks the operator through the
|
|
19
19
|
> **distribution-agnostic judgment steps** the CLI deliberately does **not**
|
|
20
|
-
> perform — config reconciliation, the
|
|
20
|
+
> perform — config reconciliation, the quality-gate installs, the
|
|
21
21
|
> permission-allowlist refresh, the consumer-side changelog reconciliation,
|
|
22
22
|
> and the stage-and-commit of the staged lockfile bump.
|
|
23
23
|
|
|
@@ -125,7 +125,7 @@ Recovery sequence: run the matching remedy, then **re-run
|
|
|
125
125
|
`npx mandrel update`** — it is idempotent (the install already landed, so a
|
|
126
126
|
clean re-run short-circuits the bump and re-drives the post-install
|
|
127
127
|
phases). Repeat until it reports success; only then proceed. A dedicated
|
|
128
|
-
`--resume` entrypoint was evaluated and deferred
|
|
128
|
+
`--resume` entrypoint was evaluated and deferred — the
|
|
129
129
|
per-phase remedies plus the idempotent re-run already cover every recovery
|
|
130
130
|
case.
|
|
131
131
|
|
|
@@ -135,7 +135,7 @@ case.
|
|
|
135
135
|
node .agents/scripts/sync-agentrc.js
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
The helper
|
|
138
|
+
The helper is default-aware and **read-only**: it validates
|
|
139
139
|
the consumer config against the new schema (non-zero exit → fix the
|
|
140
140
|
validation error and re-run before proceeding), never auto-fills missing
|
|
141
141
|
optional keys (the runtime layers defaults at read time), and flags
|
|
@@ -144,7 +144,7 @@ advisory rows you may optionally delete by hand (commit alongside the bump
|
|
|
144
144
|
in Step 5). Full procedure:
|
|
145
145
|
[`helpers/mandrel-sync-config.md`](helpers/mandrel-sync-config.md).
|
|
146
146
|
|
|
147
|
-
## Step 3.5 — Upgrade the stabilized-quality-gates surface
|
|
147
|
+
## Step 3.5 — Upgrade the stabilized-quality-gates surface
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
150
|
node .agents/scripts/apply-quality-bootstrap.js
|
|
@@ -5,48 +5,50 @@ description:
|
|
|
5
5
|
policy.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# /plan
|
|
8
|
+
# /plan
|
|
9
9
|
|
|
10
10
|
> **Lean spine.** Happy path + gate list; edge-case detail lives in on-demand
|
|
11
11
|
> [`helpers/plan-reference.md`](helpers/plan-reference.md).
|
|
12
12
|
|
|
13
13
|
## Inputs
|
|
14
14
|
|
|
15
|
-
Single planning path — there is no
|
|
16
|
-
|
|
15
|
+
Single planning path — there is no Epic/Story router, no scope-triage
|
|
16
|
+
`epic|story` verdict. **Derive the mode from what the operator typed, announce
|
|
17
|
+
it, then act**; there is nothing for them to remember:
|
|
17
18
|
|
|
18
|
-
| Invocation | Behavior |
|
|
19
|
-
| --- | --- |
|
|
20
|
-
| `/plan
|
|
21
|
-
| `/plan --
|
|
22
|
-
| `/plan
|
|
19
|
+
| Invocation | Mode | Behavior |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| `/plan` | ask | Ask what to plan; nothing runs first. |
|
|
22
|
+
| `/plan add a --json flag to doctor` | seed | Ideation from the prose: interrogate → author **one Story by default** → persist. |
|
|
23
|
+
| `/plan temp/notes/idea.md` | seed-file | Same, from notes. An argument resolving to an existing file is a path, never prose. |
|
|
24
|
+
| `/plan 4712[,4713…]` | tickets | Fetch issue(s), analyze into proper Stories (prefer N=1 rewrite). |
|
|
25
|
+
| `/plan 4712`, already delivered | amends | Amend a shipped Story from a **delta envelope**, not a re-interrogation. |
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
**Resolving a bare id.** Ids alone are ambiguous between *amend* and *tickets*,
|
|
28
|
+
so read live state rather than asking: `agent::done` can only be amended, an
|
|
29
|
+
open unplanned issue can only be planned. **Announce the derivation** — "4712
|
|
30
|
+
is `agent::done` → amending" — so a wrong read costs one correction, not a
|
|
31
|
+
wasted run. Ask **only** for an open Story already at `agent::ready`.
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
`--body` is **not** a `/plan` entry; persist goes through `plan-persist.js`.
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
| `--allow-over-budget` | Permit a plan exceeding `maxTickets`. |
|
|
38
|
-
| `--yes` | Non-interactive: auto-proceed gate #1 and gate #2 HITL waits. |
|
|
39
|
-
| `--dry-run` | Author + validate without GitHub writes; run as a pre-pass. |
|
|
35
|
+
## Saying what you want
|
|
36
|
+
|
|
37
|
+
No flags to remember — state intent and the workflow fills in the CLI
|
|
38
|
+
([reference](helpers/plan-reference.md)). Run any script with `--help` rather
|
|
39
|
+
than copying its surface here.
|
|
40
|
+
|
|
41
|
+
`--yes` is **runner-set, never operator-typed** — cron, `/loop`, and headless
|
|
42
|
+
dispatch set it to mean *nobody is at the keyboard*, which is what auto-proceeds
|
|
43
|
+
the gates below. Never offer it to an operator or add it to an attended run.
|
|
40
44
|
|
|
41
45
|
## Default-single split policy
|
|
42
46
|
|
|
43
|
-
Author **one Story** unless the pieces have **near-zero overlap**
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
(`assertAcceptancePartition` refuses coupled splits). **N=1 is the lean
|
|
49
|
-
path:** one authoring prompt, folded `## Spec`, no Epic-scale ceremony.
|
|
47
|
+
Author **one Story** unless the pieces have **near-zero overlap** or sit across
|
|
48
|
+
an **architectural seam** (different deployables, migration vs consumer).
|
|
49
|
+
Coupled work stays one Story — `## Slicing` checkpoints, not sibling tickets;
|
|
50
|
+
when N>1 every acceptance criterion belongs to exactly one Story
|
|
51
|
+
(`assertAcceptancePartition` refuses coupled splits). **N=1 is the lean path.**
|
|
50
52
|
|
|
51
53
|
## Procedure
|
|
52
54
|
|
|
@@ -58,49 +60,53 @@ node .agents/scripts/plan-context.js --seed "<seed>" \
|
|
|
58
60
|
# or: --seed-file <path> | --tickets 123,456 | --amends #<id>
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
**Always pass `--out`.** Persist auto-discovers
|
|
62
|
-
and derives source
|
|
63
|
-
|
|
63
|
+
**Always pass `--out`.** Persist auto-discovers the envelope from `--plan-dir`
|
|
64
|
+
and derives source ids from its `sourceTickets[]`; the CLI also writes
|
|
65
|
+
**`stories.template.json`**, the skeleton step 2 starts from.
|
|
64
66
|
|
|
65
67
|
The envelope carries docs context, the codebase snapshot, the story-author
|
|
66
68
|
prompt, `sourceTickets[]`, `duplicates[]` (open **Stories**, never Epics), and
|
|
67
|
-
advisory `complexitySignals` (**no routing authority
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Under `--yes`, do not ask free-form operator questions — unresolved unknowns
|
|
72
|
-
land in Key Assumptions.
|
|
69
|
+
advisory `complexitySignals` (**no routing authority**). A trivial scope earns
|
|
70
|
+
`--route-downgrade-reason "<why>"` at persist — shape-validated, failing closed
|
|
71
|
+
to `full` ([detail](helpers/plan-reference.md)). Under `--yes`, do not ask
|
|
72
|
+
free-form operator questions — unknowns land in Key Assumptions.
|
|
73
73
|
|
|
74
74
|
**Gate #1** — STOP to confirm the sharpened plan intent and any
|
|
75
|
-
duplicate-candidate review. Under `--yes`, auto-proceed.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
duplicate-candidate review. Under `--yes`, auto-proceed.
|
|
76
|
+
|
|
77
|
+
When `complexitySignals.deliverLightSuggestion.suggested` is `true`, offer —
|
|
78
|
+
**advisory, never an automatic reroute** — to deliver the seed instead of
|
|
79
|
+
planning it. On confirm, route **in this session** into
|
|
80
|
+
[`helpers/deliver-light.md`](helpers/deliver-light.md), filling its gate from
|
|
81
|
+
this envelope, not the raw seed; an `ask-operator` verdict returns here to
|
|
82
|
+
step 2 with the interrogation intact. Under `--yes` it is recorded and planning
|
|
83
|
+
proceeds — never auto-downgraded to light.
|
|
84
|
+
|
|
85
|
+
A truthy `complexitySignals.uiSurface` marks a UI-touching plan: name
|
|
86
|
+
[`/prototype`](prototype.md) as an operator option — never invoke it here.
|
|
79
87
|
|
|
80
88
|
### 2. Author
|
|
81
89
|
|
|
82
|
-
**One-shot authoring
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
**One-shot authoring.** Start from `stories.template.json`; author
|
|
91
|
+
`stories.json` in one pass. Entries are pre-resolved; keep tiers/assumptions
|
|
92
|
+
valid. `body` is a markdown string **or** a structured object; persist parses
|
|
93
|
+
either, serializes the canonical markdown, and syncs top-level `acceptance[]` /
|
|
94
|
+
`verify[]` into it — never dual-author those lists.
|
|
87
95
|
|
|
88
96
|
Each entry (the `stories.template.json` shape): `slug`
|
|
89
97
|
(`^[a-z0-9][a-z0-9-]*$`), `type: "story"`, `title`, `body` (`goal`, optional
|
|
90
98
|
`spec`, `changes[{path, assumption}]` — `creates|refactors-existing|deletes`,
|
|
91
|
-
`non_goals`, `reason_to_exist`), top-level `acceptance[]`, `verify[]`
|
|
92
|
-
(
|
|
99
|
+
`non_goals`, `reason_to_exist`), top-level `acceptance[]`, `verify[]` (`…
|
|
100
|
+
(unit|contract|e2e|validate)`), `depends_on[]` (N>1 only).
|
|
93
101
|
|
|
94
|
-
Artifacts under `temp/plan-<slug>/`: `stories.json`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
one cohesive Story. Split only under the policy above.
|
|
102
|
+
Artifacts under `temp/plan-<slug>/`: `stories.json` (**length 1 by default**;
|
|
103
|
+
over-budget Specs fail closed — split or tighten, never under `docs/`);
|
|
104
|
+
optional `techspec.md` (**N===1 only** — folded into `## Spec`); optional
|
|
105
|
+
`acceptance-manifest.json` (N>1 partition list — `--plan-acceptance`). For N=1
|
|
106
|
+
use the envelope `systemPrompts.story`; split only under the policy above.
|
|
100
107
|
|
|
101
|
-
**Tickets mode:** every Story authors a top-level `supersedes[]
|
|
102
|
-
|
|
103
|
-
([shape](helpers/plan-reference.md)).
|
|
108
|
+
**Tickets mode:** every Story authors a top-level `supersedes[]`; persist
|
|
109
|
+
refuses a partial map ([shape](helpers/plan-reference.md)).
|
|
104
110
|
|
|
105
111
|
### 2.5 Critics
|
|
106
112
|
|
|
@@ -110,29 +116,28 @@ node .agents/scripts/plan-critics.js \
|
|
|
110
116
|
[--tech-spec temp/plan-<slug>/techspec.md]
|
|
111
117
|
```
|
|
112
118
|
|
|
113
|
-
Run **before** persist — the last point a finding folds into a re-author
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
Run **before** persist — the last point a finding folds into a re-author round.
|
|
120
|
+
It exits 0 on **any** verdict (verdicts route work, they do not gate) and exits
|
|
121
|
+
**1** only on a usage/IO error — no critic ran, no skip ledgered: **do not
|
|
122
|
+
proceed to Persist**; fix and re-run.
|
|
117
123
|
|
|
118
124
|
- **Both `dispatch: false`** — proceed to Persist (each skip is ledgered).
|
|
119
125
|
- **Either `dispatch: true`** — dispatch **one fresh-context, maker-blind
|
|
120
|
-
sub-agent per firing critic** (hand it only the draft artifacts,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`textHygiene.findings[]` lints, and the role-scoped dispatch shape:
|
|
126
|
+
sub-agent per firing critic** (hand it only the draft artifacts, never the
|
|
127
|
+
authoring transcript), fold findings into Gate #2 or a re-author round, re-run
|
|
128
|
+
this step. Pre-mortem triggers (incl. the external-dependency probe), the
|
|
129
|
+
advisory-only `textHygiene.findings[]` lints, and the dispatch shape:
|
|
125
130
|
[`helpers/plan-reference.md` § Critic dispatch detail](helpers/plan-reference.md).
|
|
126
131
|
|
|
127
132
|
### 3. Persist
|
|
128
133
|
|
|
129
|
-
**Gate #2** —
|
|
130
|
-
|
|
134
|
+
**Gate #2** — STOP for approval before persist **only** when the operator asked
|
|
135
|
+
to review (`--force-review`). Under `--yes`, auto-proceed.
|
|
131
136
|
|
|
132
|
-
Run persist with `--dry-run` **first** — same command, GitHub writes
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
Run persist with `--dry-run` **first** — same command, GitHub writes suppressed;
|
|
138
|
+
every gate (validator, body parse, DAG, capacity, budget, reachability,
|
|
139
|
+
split/supersede partitions, Spec fold) runs before the first `createIssue`.
|
|
140
|
+
Then:
|
|
136
141
|
|
|
137
142
|
```bash
|
|
138
143
|
node .agents/scripts/plan-persist.js \
|
|
@@ -140,27 +145,27 @@ node .agents/scripts/plan-persist.js \
|
|
|
140
145
|
--plan-dir temp/plan-<slug> \
|
|
141
146
|
[--plan-acceptance temp/plan-<slug>/acceptance-manifest.json] \
|
|
142
147
|
[--tech-spec temp/plan-<slug>/techspec.md] \
|
|
143
|
-
[--source-tickets 123,456]
|
|
148
|
+
[--source-tickets 123,456]
|
|
144
149
|
```
|
|
145
150
|
|
|
146
151
|
At lite shape, `--chain-on-clean` chains that dry-run into the real persist in
|
|
147
|
-
one round-trip **only** when it is clean and `lite`; a full
|
|
148
|
-
|
|
152
|
+
one round-trip **only** when it is clean and `lite`; a full plan keeps its
|
|
153
|
+
review round-trip.
|
|
149
154
|
|
|
150
155
|
Persist creates `type::story` issue(s) plus a `plan-run::<id>` grouping label
|
|
151
|
-
(**metadata only
|
|
152
|
-
|
|
153
|
-
|
|
156
|
+
(**metadata only**); N>1 `depends_on` edges become `blocked by #<id>` footers.
|
|
157
|
+
`agent::ready` is the **terminal** flip after all receipts land. stdout is pure
|
|
158
|
+
JSON.
|
|
154
159
|
|
|
155
|
-
In
|
|
156
|
-
|
|
157
|
-
[detail](helpers/plan-reference.md)).
|
|
158
|
-
command — never hand-delete issues.
|
|
160
|
+
In tickets mode persist resolves source ids **envelope-first** and closes each
|
|
161
|
+
as `not_planned` with a comment (default on;
|
|
162
|
+
[detail](helpers/plan-reference.md)).
|
|
159
163
|
|
|
160
164
|
## Constraints
|
|
161
165
|
|
|
162
|
-
- `/plan`
|
|
163
|
-
|
|
166
|
+
- `/plan` starts delivery **only** through a confirmed Gate #1 light route —
|
|
167
|
+
never off its own authored Stories, which land via [`/deliver`](deliver.md).
|
|
168
|
+
- Duplicate search targets open Stories (`type::story`), not Epics.
|
|
164
169
|
- Deterministic gates still fail closed under `--yes`.
|
|
165
170
|
|
|
166
171
|
## See also
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: >-
|
|
3
|
+
Operator-invoked UI prototype pass. Discovers the consumer's design-system
|
|
4
|
+
SSOT first, then — only after the operator confirms — writes exactly one
|
|
5
|
+
self-contained HTML file under the gitignored workspace-root temp tree, so a
|
|
6
|
+
layout can be reviewed before its UI acceptance criteria are authored.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /prototype [what to prototype]
|
|
10
|
+
|
|
11
|
+
UI acceptance criteria are otherwise authored blind: "the dashboard shows the
|
|
12
|
+
active runs" says nothing about layout, density, or interaction, so delivery
|
|
13
|
+
resolves those by taste. `/prototype` puts a reviewable artifact in front of the
|
|
14
|
+
operator before the criteria are written.
|
|
15
|
+
|
|
16
|
+
**Operator-invoked only.** `/plan` may report that a plan touches UI and that
|
|
17
|
+
this command exists; it must never run it. No workflow, gate, or script invokes
|
|
18
|
+
`/prototype` — the whole design rests on the operator asking for it.
|
|
19
|
+
|
|
20
|
+
## Procedure
|
|
21
|
+
|
|
22
|
+
### Step 0 — Discover the design-system SSOT (first, before anything is drawn)
|
|
23
|
+
|
|
24
|
+
You cannot prototype *in the project's visual language* until you have found the
|
|
25
|
+
language. Locate and read the consumer's sources of truth — the same set
|
|
26
|
+
[`/audit-ux-ui`](audit-ux-ui.md) Step 0 mandates:
|
|
27
|
+
|
|
28
|
+
- **Design tokens / theme** — a `tailwind.config.{js,ts}`, CSS custom properties
|
|
29
|
+
(`:root { --color-*, --space-* }`), a `theme/` / `tokens/` /
|
|
30
|
+
`design-system/` directory, or a CSS-in-JS theme object.
|
|
31
|
+
- **Component roster** — the shared component directory (`components/ui/**`, a
|
|
32
|
+
published design-system package) that raw elements are expected to defer to.
|
|
33
|
+
- **Documented conventions** — `docs/style-guide.md`, plus `docs/web-routes.md`
|
|
34
|
+
when the surface is a route, whenever they exist in the consumer checkout.
|
|
35
|
+
|
|
36
|
+
Report what you found — token names, the component roster, the style-guide rules
|
|
37
|
+
— and draw only against that discovered baseline. **No artifact is drawn until
|
|
38
|
+
this step has run.**
|
|
39
|
+
|
|
40
|
+
### Step 0a — When no design-system SSOT is discoverable
|
|
41
|
+
|
|
42
|
+
Report the absence explicitly, then emit a **low-fidelity frame**: boxes,
|
|
43
|
+
labels, and hierarchy, in the host's default typography with no colour system.
|
|
44
|
+
Do **not** invent a visual language. A prototype in a palette the project never
|
|
45
|
+
adopted reviews the invention rather than the layout, and the operator cannot
|
|
46
|
+
tell which of the two they are approving.
|
|
47
|
+
|
|
48
|
+
### Step 1 — Confirm before writing (**hard gate**)
|
|
49
|
+
|
|
50
|
+
Describe the layout you intend — surfaces, hierarchy, states, and which
|
|
51
|
+
discovered tokens and components it reuses — and **STOP**. Nothing is written to
|
|
52
|
+
disk until the operator confirms; never write silently. This is the disk-write
|
|
53
|
+
policy [`core/idea-refinement`](../skills/core/idea-refinement/SKILL.md) already
|
|
54
|
+
applies to its one-pager.
|
|
55
|
+
|
|
56
|
+
### Step 2 — Write exactly one self-contained HTML file
|
|
57
|
+
|
|
58
|
+
On confirm, write **exactly one** self-contained `.html` file — inline CSS, no
|
|
59
|
+
build step, no fetched external assets — under the **gitignored workspace-root
|
|
60
|
+
temp tree** (`temp/prototypes/<slug>.html`). One file, because a prototype is a
|
|
61
|
+
thing to look at, not a codebase to maintain; self-contained, because it has to
|
|
62
|
+
open from disk with no server and no install.
|
|
63
|
+
|
|
64
|
+
Report the path, and iterate in place on that same file.
|
|
65
|
+
|
|
66
|
+
### Step 3 — Optional: publish to a host
|
|
67
|
+
|
|
68
|
+
Host publishing is an **optional upgrade of that same file** and never the
|
|
69
|
+
artifact of record — the file under the temp tree stays authoritative. Publish
|
|
70
|
+
only when the operator asks, and keep the two identical by re-publishing the
|
|
71
|
+
file rather than editing a published copy.
|
|
72
|
+
|
|
73
|
+
### Step 4 — Carry the review through to the Story
|
|
74
|
+
|
|
75
|
+
The **default carry-through is a fold into the Story's `## Spec`.** Delivery
|
|
76
|
+
reads the Story body and never the temp tree, so a layout that exists only as a
|
|
77
|
+
temp artifact is a layout delivery cannot see. Record the reviewed decisions —
|
|
78
|
+
surfaces, hierarchy, states, and the named tokens and components — as contract
|
|
79
|
+
prose in `## Spec`, and turn the observable ones into UI acceptance criteria.
|
|
80
|
+
|
|
81
|
+
**Committing a prototype is opt-in, per Story.** Ask; never default to it. A
|
|
82
|
+
prototype is wrong the moment the real UI ships, and a repository with a
|
|
83
|
+
documentation-freshness gate already carries that failure mode.
|
|
84
|
+
|
|
85
|
+
## Constraint
|
|
86
|
+
|
|
87
|
+
- **Nothing reaches disk without a confirm.** Step 1 is a hard gate, not a
|
|
88
|
+
courtesy.
|
|
89
|
+
- **One file, under the temp tree.** Never a second artifact, never outside the
|
|
90
|
+
gitignored workspace-root temp tree, and never a committed prototype
|
|
91
|
+
directory by default.
|
|
92
|
+
- **Never invoked automatically.** `/plan` records the offer and proceeds with
|
|
93
|
+
planning; no workflow, gate, or script may call this command.
|
|
94
|
+
- **Read-only over the codebase.** The prototype file is the only write. Do not
|
|
95
|
+
edit application source, tokens, or components to make a prototype render.
|
|
96
|
+
- **Discovered baseline only.** No invented palette, type scale, or component
|
|
97
|
+
vocabulary when the project defines none.
|
|
98
|
+
|
|
99
|
+
## See also
|
|
100
|
+
|
|
101
|
+
- [`/audit-ux-ui`](audit-ux-ui.md) — the same design-system SSOT discovery,
|
|
102
|
+
applied as a review lens after the UI ships.
|
|
103
|
+
- [`/plan`](plan.md) — where the advisory `complexitySignals.uiSurface` offer
|
|
104
|
+
surfaces. It names this command; it never runs it.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [2.16.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.15.0...mandrel-v2.16.0) (2026-07-25)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
* **workflows:** add operator-invoked /prototype and an advisory uiSurface offer (refs [#4765](https://github.com/dsj1984/mandrel/issues/4765)) ([#4769](https://github.com/dsj1984/mandrel/issues/4769)) ([d3f7173](https://github.com/dsj1984/mandrel/commit/d3f71734ef8573ffa40187b5f4f8a97be6e32041))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
* **close-validation:** drain gate output without stalling the child's pipe (refs [#4766](https://github.com/dsj1984/mandrel/issues/4766)) ([#4770](https://github.com/dsj1984/mandrel/issues/4770)) ([fd75550](https://github.com/dsj1984/mandrel/commit/fd75550288411a4c92831ac7c9b946e2cce5a686))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
* **routing:** scope the light path by effort and risk (refs [#4764](https://github.com/dsj1984/mandrel/issues/4764)) ([#4767](https://github.com/dsj1984/mandrel/issues/4767)) ([c4851ab](https://github.com/dsj1984/mandrel/commit/c4851abe218721145daaeb4353af400223b588e6))
|
|
21
|
+
|
|
22
|
+
## [2.15.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.14.0...mandrel-v2.15.0) (2026-07-25)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
* gate the workflow read-tier with a transitive mandatory-closure ratchet ([#4752](https://github.com/dsj1984/mandrel/issues/4752)) ([#4755](https://github.com/dsj1984/mandrel/issues/4755)) ([ac0f1e0](https://github.com/dsj1984/mandrel/commit/ac0f1e038560f4d69146f6dae46c2eb97ae2dbb2))
|
|
28
|
+
* make workflow-invoked orchestration scripts self-describing via --help ([#4750](https://github.com/dsj1984/mandrel/issues/4750)) ([#4756](https://github.com/dsj1984/mandrel/issues/4756)) ([922c278](https://github.com/dsj1984/mandrel/commit/922c278ed15f77761c88366ce6d166e0a0dd9157))
|
|
29
|
+
* **workflows:** one delivery door and derived invocation intent (refs [#4760](https://github.com/dsj1984/mandrel/issues/4760)) ([#4761](https://github.com/dsj1984/mandrel/issues/4761)) ([36bff50](https://github.com/dsj1984/mandrel/commit/36bff502b7d4e475569da7cae2eb0ec66d24b85d))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
* **deps:** bump brace-expansion to 5.0.8 for GHSA-mh99-v99m-4gvg ([#4753](https://github.com/dsj1984/mandrel/issues/4753)) ([3351100](https://github.com/dsj1984/mandrel/commit/3351100801b70e9e17cf3ed99245b3d81e162232))
|
|
35
|
+
* **tests:** resolve cli-usage argv[1] with fileURLToPath for Windows ([#4759](https://github.com/dsj1984/mandrel/issues/4759)) ([7fa3ee1](https://github.com/dsj1984/mandrel/commit/7fa3ee1e17c46995b9043fa879970a768b04b298))
|
|
36
|
+
|
|
5
37
|
## [2.14.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.13.0...mandrel-v2.14.0) (2026-07-24)
|
|
6
38
|
|
|
7
39
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mandrel",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"description": "Claude Code-first opinionated workflow framework: instructions, skills, rules, and SDLC workflows that govern AI coding assistants.",
|
|
5
5
|
"files": [
|
|
6
6
|
".agents/",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"maintainability:update": "node .agents/scripts/update-maintainability-baseline.js",
|
|
42
42
|
"check:arch": "node .agents/scripts/check-arch-cycles.js",
|
|
43
43
|
"check:context-budget": "node .agents/scripts/check-context-budget.js",
|
|
44
|
+
"check:workflow-citations": "node .agents/scripts/check-workflow-citations.js",
|
|
44
45
|
"crap:check": "node .agents/scripts/check-baselines.js --gate crap",
|
|
45
46
|
"crap:update": "node .agents/scripts/update-crap-baseline.js",
|
|
46
47
|
"duplication:check": "node .agents/scripts/check-baselines.js --gate duplication",
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
Single-session delivery for genuinely small work. Judges a prompt's
|
|
4
|
-
predicted footprint, authors a receipt Story, then lands it through the same
|
|
5
|
-
single-story-init / single-story-close engine — every close gate unchanged.
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# /deliver-light "<prompt>" | --amends '#<id>' "<prompt>"
|
|
9
|
-
|
|
10
|
-
> **Thin entry point, not a second engine.** `/deliver-light` removes the
|
|
11
|
-
> `/plan` session for small work — nothing else. It runs a suitability gate,
|
|
12
|
-
> authors a minimal receipt Story, then hands off to the SAME scripts
|
|
13
|
-
> [`/deliver`](deliver.md) uses. Read
|
|
14
|
-
> [`helpers/deliver-digest.md`](helpers/deliver-digest.md) once first — the
|
|
15
|
-
> engine invariants, gates, and terminal-envelope contract below are its.
|
|
16
|
-
|
|
17
|
-
## Role
|
|
18
|
-
|
|
19
|
-
For a genuinely trivial change — a one-file fix, a small addition, a small
|
|
20
|
-
amendment — the multi-session plan→deliver ceremony buys nothing the bare model
|
|
21
|
-
lacks except **gates and landing**. `/deliver-light` keeps exactly those: one
|
|
22
|
-
session straight to execution from an operator prompt, landing through the
|
|
23
|
-
unchanged close path. It never relaxes a close gate, never bypasses the PR to
|
|
24
|
-
`main`, and never lands over-scope work silently.
|
|
25
|
-
|
|
26
|
-
## Four invariants (do not skip one)
|
|
27
|
-
|
|
28
|
-
1. **Suitability gate.** The prompt's predicted footprint is judged by the
|
|
29
|
-
shared shape machinery (`deriveStoryShape` / `deriveChangeLevel`) **and** a
|
|
30
|
-
ledgered model verdict with a recorded reason. Both must agree on `lite`.
|
|
31
|
-
2. **Over-scope stops — it never hard-fails.** An over-ceiling prompt STOPS and
|
|
32
|
-
asks the operator to escalate to `/plan` or proceed light. Under `--yes` it
|
|
33
|
-
fails closed to an **`escalated` terminal envelope** that ends the session
|
|
34
|
-
(§ Escalation is terminal).
|
|
35
|
-
3. **Diff-derived backstop.** After implementation the ACTUAL change set is
|
|
36
|
-
re-checked — the diff is the real scope signal — and an over-ceiling diff is
|
|
37
|
-
blocked rather than landed.
|
|
38
|
-
4. **Minimal receipt Story.** A `type::story` is authored inline so `refs #`,
|
|
39
|
-
history, telemetry, and the `agent::executing → agent::done` state machine
|
|
40
|
-
all survive.
|
|
41
|
-
|
|
42
|
-
## Procedure
|
|
43
|
-
|
|
44
|
-
1. **Predict + gate.** Form the predicted footprint (new files, edited files,
|
|
45
|
-
acceptance count) and your ledgered verdict (a recorded reason for `lite`),
|
|
46
|
-
then run the gate:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
node .agents/scripts/deliver-light.js --prompt "<prompt>" \
|
|
50
|
-
--creates <csv> --refactors <csv> --acceptance <n> \
|
|
51
|
-
--route lite --reason "<why this is trivial>" [--amends '#<id>'] [--yes]
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Branch on `action` in the JSON envelope:
|
|
55
|
-
- **`proceed-light`** — the receipt Story is authored; read `storyId` and
|
|
56
|
-
`nextCommands`. Continue to step 2.
|
|
57
|
-
- **`ask-operator`** — predicted scope exceeds the light ceilings. STOP and
|
|
58
|
-
ask the operator to escalate to `/plan` or proceed light. Do not proceed
|
|
59
|
-
on your own. This is a **question, not a terminal** — wait for the answer.
|
|
60
|
-
- **over-scope under `--yes`** — no `action` to branch on: the gate emits an
|
|
61
|
-
**`escalated` terminal envelope** instead (exit 2). § Escalation is
|
|
62
|
-
terminal governs; you are finished.
|
|
63
|
-
|
|
64
|
-
`--amends '#<id>'` is the canonical light case — shape-checked identically; a
|
|
65
|
-
heavy amendment escalates to `/plan` like any other over-scope prompt.
|
|
66
|
-
|
|
67
|
-
2. **Init (same engine).** From the main checkout, synchronously, with the
|
|
68
|
-
maximum Bash timeout:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
node .agents/scripts/single-story-init.js --story <storyId>
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Capture `workCwd`; `remoteVerified: false` → flip `agent::blocked` and stop.
|
|
75
|
-
This is [`/deliver`](deliver.md)'s worktree/branch/lease/label engine,
|
|
76
|
-
invoked, not reimplemented.
|
|
77
|
-
|
|
78
|
-
3. **Implement + self-eval.** `cd` into `workCwd`, implement the change, run
|
|
79
|
-
`npm test` once in the worktree, then run the bounded acceptance self-eval
|
|
80
|
-
loop ([`helpers/deliver-story.md`](helpers/deliver-story.md) Step 1a). Commit
|
|
81
|
-
on `story-<id>` with `(refs #<storyId>)`.
|
|
82
|
-
|
|
83
|
-
4. **Diff backstop.** Before close, re-check the ACTUAL diff:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
node .agents/scripts/deliver-light.js --backstop --story <storyId>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Exit `3` (`blocked: true`) means the landed diff exceeds the light ceilings
|
|
90
|
-
(file count or a sensitive-path class). STOP, flip `agent::blocked`, and
|
|
91
|
-
escalate to `/plan` — do not land.
|
|
92
|
-
|
|
93
|
-
5. **Close and land (same engine).** Exactly [`/deliver`](deliver.md)'s close:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
node .agents/scripts/single-story-close.js --story <storyId> --cwd <main-repo>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Branch on the terminal envelope's `status` per
|
|
100
|
-
[`helpers/deliver-digest.md`](helpers/deliver-digest.md) § 5 — every close
|
|
101
|
-
gate runs byte-identical to the full path.
|
|
102
|
-
|
|
103
|
-
## Escalation is terminal {#escalation-is-terminal}
|
|
104
|
-
|
|
105
|
-
Over-scope under `--yes` emits a schema-validated `story-deliver-terminal`
|
|
106
|
-
envelope with **`status: "escalated"`**, `storyId: null`, and a `nextCommand`
|
|
107
|
-
naming the `/plan` invocation that owns the work.
|
|
108
|
-
|
|
109
|
-
**That envelope IS this session's terminal output.** Relay it and stop. There is
|
|
110
|
-
no remaining step, no degraded fallback, and no smaller version of the work to
|
|
111
|
-
attempt.
|
|
112
|
-
|
|
113
|
-
**Invoking `/plan` in this same session is forbidden.** Hand the operator the
|
|
114
|
-
`nextCommand`; `/plan` runs in a **fresh** session.
|
|
115
|
-
|
|
116
|
-
This is not style — it is the empirical finding that motivated the envelope.
|
|
117
|
-
A mandrel-bench 2.13.0 light-arm run read the escalation and continued anyway:
|
|
118
|
-
it invoked `/plan` in-session and delivered. The in-session plan authored **one**
|
|
119
|
-
Story against the scenario's 3–5 contract, where a fresh `/plan` session on the
|
|
120
|
-
identical seed authored **four**. Planning inside a session already framed as
|
|
121
|
-
small work under-decomposes, so walking past the escalation silently produced
|
|
122
|
-
the very outcome the guard exists to prevent. The gate's decision was right both
|
|
123
|
-
times; only the outcome's finality was missing.
|
|
124
|
-
|
|
125
|
-
Nothing is left half-started: an escalated run creates **no receipt Story, no
|
|
126
|
-
`story-<id>` branch, and no worktree** — the escalation path returns before
|
|
127
|
-
every creation call site, and `escalation.created` records all three as `false`
|
|
128
|
-
in a shape the schema pins, so a later run finds nothing to trip over.
|
|
129
|
-
|
|
130
|
-
## Constraints
|
|
131
|
-
|
|
132
|
-
- **Land, block, or escalate — never a silent local build.** The close push is
|
|
133
|
-
the only sanctioned landing; an `escalated` terminal is the only sanctioned
|
|
134
|
-
ending that delivers nothing, and it ends the session
|
|
135
|
-
(§ Escalation is terminal).
|
|
136
|
-
- **No parallel engine.** `/deliver-light` invokes `single-story-init.js` and
|
|
137
|
-
`single-story-close.js`; it never reimplements worktree, branch, PR, or merge
|
|
138
|
-
mechanics.
|
|
139
|
-
- **State only via `update-ticket-state.js`.** Drive every `agent::*`
|
|
140
|
-
transition through the script; report state, not process.
|
|
141
|
-
|
|
142
|
-
## See also
|
|
143
|
-
|
|
144
|
-
- [`/deliver`](deliver.md) — the multi-Story / planned delivery entry point.
|
|
145
|
-
- [`helpers/deliver-story.md`](helpers/deliver-story.md) — the one Story
|
|
146
|
-
delivery engine both entry points share.
|
|
147
|
-
- [`helpers/deliver-digest.md`](helpers/deliver-digest.md) — engine invariants,
|
|
148
|
-
gates, and the terminal-envelope contract.
|