@emiliosp/pi-maestro 0.9.5 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +7 -2
- package/ROADMAP.md +131 -10
- package/agents/verifier.md +1 -1
- package/docs/glossary.md +1 -0
- package/docs/workflow.md +34 -22
- package/package.json +1 -1
- package/src/MaestroPaths.ts +4 -32
- package/src/artifacts/builder-handoff/assertBuilderHandoff.ts +23 -29
- package/src/artifacts/verifier-handoff/assertVerifierHandoff.ts +14 -18
- package/src/artifacts/verifier-handoff/schema.ts +9 -0
- package/src/config/loadConfiguration.ts +20 -50
- package/src/maestro/instructions/getMaestroInstructions.ts +40 -22
- package/src/maestro/status/formatMaestroStatus.ts +6 -6
- package/src/specs/create.ts +7 -24
- package/src/tools/main/mark-spec-ready.ts +1 -1
- package/src/tools/main/resolve-escalations.ts +11 -4
- package/src/tools/main/resolve-findings.ts +30 -3
- package/src/tools/main/run-builder.ts +39 -49
- package/src/tools/main/run-verifier.ts +12 -23
- package/src/utils/path-within-or-equal.ts +3 -4
- package/src/workflow/builder/resolveEscalations.ts +50 -31
- package/src/workflow/builder/utils/getWorkflowEventByBuilderHandoff.ts +1 -1
- package/src/workflow/builder/utils/getWorkflowEventBySpecChangeRequired.ts +16 -0
- package/src/workflow/state/schema.ts +10 -9
- package/src/workflow/transitions.ts +22 -20
- package/src/workflow/utils/getAgentRole.ts +2 -2
- package/src/workflow/verifier/resolveFindings.ts +56 -69
- package/src/workflow/verifier/utils/getWorkflowEventByVerifierHandoff.ts +11 -3
- package/templates/spec.md +9 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
This file summarizes meaningful changes to the codebase, including behavior, data formats, architecture, and development tools. Git tags identify version boundaries; GitHub Releases are not required. Version-only changes and routine maintenance are omitted.
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
1. Added `success`, `failure`, and `unchanged` coverage labels to the `spec` template and `Maestro` guidance. Approval validation and `handoff` formats remain unchanged.
|
|
8
|
+
2. Required `Maestro` to inspect existing tests before writing `acceptance criteria` and remove criteria whose exact scenarios already have coverage. Requirements remain documented in the `spec`.
|
|
9
|
+
|
|
10
|
+
## 0.10.0
|
|
11
|
+
|
|
12
|
+
1. Saved complete `owner` decision batches in their original `handoffs` before changing phase, including when the `spec` requires revision. See [PR #38](https://github.com/emilioSp/pi-maestro/pull/38).
|
|
13
|
+
2. Added `revise-spec` decisions for `verifier` `findings`, with the owner's reason and agreed requirement change. Revision takes priority over code fixes and rejections.
|
|
14
|
+
3. Unified both revision paths through `drafting-spec`, with renewed `GREEN FLAG` before separate approval and another `builder` `run`. Approval is allowed only from `drafting-spec`.
|
|
15
|
+
4. Renamed workflow events to identify `builder` and `owner` actions. Both revision paths share `OWNER_REQUEST_SPEC_REVISION`.
|
|
16
|
+
5. Breaking: supply the required boolean `specChangeRequired` when calling `maestro_resolve_escalations`.
|
|
17
|
+
6. Breaking: saved decision phases are now `escalation-decisions` and `finding-decisions`. Existing workflows using older names require manual `owner` handling. No automatic migration is provided.
|
|
18
|
+
|
|
19
|
+
## 0.9.5
|
|
20
|
+
|
|
21
|
+
1. Added a shared check that requires every approved `spec` criterion ID in `builder` and `verifier` `handoffs`. See [PR #37](https://github.com/emilioSp/pi-maestro/pull/37).
|
|
22
|
+
2. Missing IDs reject submission before saving a report or changing phase. Extra report IDs remain allowed, and existing report validation is unchanged.
|
|
23
|
+
3. Reused the raw heading rule `^### AC(\d+):`, including leading zeros and matching lines inside code blocks. No matching headings impose no new restriction.
|
|
24
|
+
4. Added unit tests for extraction and one missing-ID integration test per role.
|
|
25
|
+
|
|
5
26
|
## 0.9.4
|
|
6
27
|
|
|
7
28
|
1. Added numbering validation to `spec` approval. Matched `acceptance criterion` headings must start at `AC1` and continue without gaps. See [PR #36](https://github.com/emilioSp/pi-maestro/pull/36).
|
package/README.md
CHANGED
|
@@ -10,12 +10,13 @@ Pi extension for a spec-driven multiagent development workflow.
|
|
|
10
10
|
|
|
11
11
|
A `specification` (`spec`) describes one reversible change. The `builder` implements it. An independent `verifier` checks every `acceptance criterion`. The `owner` performs the final review.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Five principles hold the workflow together:
|
|
14
14
|
|
|
15
15
|
1. The approved `spec` defines the required work for the `builder` and `verifier`.
|
|
16
16
|
2. No agent approves its own work.
|
|
17
17
|
3. Every `acceptance criterion` is checked independently.
|
|
18
18
|
4. The `owner` decides requirements, scope, and unresolved questions.
|
|
19
|
+
5. Each agent has one and only one role. Specific and with clear instruction.
|
|
19
20
|
|
|
20
21
|
## The roles
|
|
21
22
|
|
|
@@ -79,7 +80,11 @@ The `owner` must not edit product files while the workflow runs.
|
|
|
79
80
|
`Maestro` can perform temporary experiments with `owner` agreement during `spec` preparation and permitted revisions. See [Workflow](docs/workflow.md#spec-approval).
|
|
80
81
|
|
|
81
82
|
An `escalation` asks the `owner` to decide an implementation question, and a `finding` records a technical issue reported by the `verifier`. The `owner` discusses both with `Maestro`, never directly with the `builder` or `verifier`.
|
|
82
|
-
|
|
83
|
+
`Maestro` records all current `escalation` answers or `finding` decisions in the active `handoff` before changing phase.
|
|
84
|
+
|
|
85
|
+
If any decision requires a `spec` change, the workflow returns to `drafting-spec` before the `owner` and `Maestro` revise the same `spec`.
|
|
86
|
+
The `owner` reviews the revised `spec` and replies `GREEN FLAG` again.
|
|
87
|
+
`Maestro` records renewed approval separately before another `builder` `run`.
|
|
83
88
|
|
|
84
89
|
The workflow ends at `candidate-ready`. Rejected `findings` retain their reasons. Later changes are outside the completed verification. The `owner` controls any later Git use, pull request, and merge.
|
|
85
90
|
|
package/ROADMAP.md
CHANGED
|
@@ -6,6 +6,30 @@ This roadmap records planned outcomes, not permission to implement them. The `ow
|
|
|
6
6
|
|
|
7
7
|
Item identifiers remain stable when priorities change. The `owner` approves changes to priorities and scope.
|
|
8
8
|
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
| ID | Title | Status | Summary |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| R-01 | [Improve status presentation and activation feedback](#r-01-improve-status-presentation-and-activation-feedback) | Completed | Show clearer status and configured agent details without adding model context. |
|
|
14
|
+
| R-02 | [Store escalations and owner decisions in builder handoffs](#r-02-store-escalations-and-owner-decisions-in-builder-handoffs) | Completed | Keep `escalation` questions and `owner` answers together in numbered `builder` `handoffs`. |
|
|
15
|
+
| R-03 | [Route builder failures through owner escalations](#r-03-route-builder-failures-through-owner-escalations) | Completed | Route reportable `builder` problems through `owner` `escalations` instead of a terminal failure phase. |
|
|
16
|
+
| R-12 | [Format glossary terms consistently](#r-12-format-glossary-terms-consistently) | Completed | Apply glossary formatting across documentation and record its exclusions. |
|
|
17
|
+
| R-14 | [Introduce Maestro at activation](#r-14-introduce-maestro-at-activation) | Completed | Introduce `Maestro` at activation and load relevant documentation only when needed. |
|
|
18
|
+
| R-15 | [Rename the test support directory](#r-15-rename-the-test-support-directory) | Completed | Rename `test/` to `tests/` and update affected references. |
|
|
19
|
+
| R-16 | [Verify code quality against AGENTS.md instructions](#r-16-verify-code-quality-against-agentsmd-instructions) | Completed | Require the `verifier` to review affected code against applicable `AGENTS.md` code-quality directives. |
|
|
20
|
+
| R-06 | [Check subagent extensions at activation](#r-06-check-subagent-extensions-at-activation) | Completed | Require a successful parent `pi-subagents` availability reply before activation. |
|
|
21
|
+
| R-05 | [Keep acceptance criterion numbering continuous](#r-05-keep-acceptance-criterion-numbering-continuous) | Completed | Reject gaps in `acceptance criterion` numbering before approving a `spec`. |
|
|
22
|
+
| R-10 | [Match handoff criteria to the approved spec](#r-10-match-handoff-criteria-to-the-approved-spec) | Completed | Require every approved `spec` criterion ID in each submitted `builder` and `verifier` `handoff`. |
|
|
23
|
+
| R-17 | [Record escalation resolutions when the spec changes](#r-17-record-escalation-resolutions-when-the-spec-changes) | Completed | Save all current `escalation` answers before changing phase, including when the `spec` requires revision. |
|
|
24
|
+
| R-20 | [Route finding-driven spec revisions through drafting-spec](#r-20-route-finding-driven-spec-revisions-through-drafting-spec) | Completed | Record `finding` decisions before `spec` revision and require renewed `GREEN FLAG` before another `builder` `run`. |
|
|
25
|
+
| R-18 | [Label acceptance criterion coverage](#r-18-label-acceptance-criterion-coverage) | Completed | Label each `acceptance criterion` as success, failure, or unchanged behavior. |
|
|
26
|
+
| R-19 | [Avoid acceptance criteria already covered by tests](#r-19-avoid-acceptance-criteria-already-covered-by-tests) | Completed | Omit `acceptance criteria` whose exact scenarios already have test coverage. |
|
|
27
|
+
| R-04 | [Rename the npm package](#r-04-rename-the-npm-package) | Later | Rename `@emiliosp/pi-maestro` to `pi-maestro-sdd` with compatibility decisions defined in the `spec`. |
|
|
28
|
+
| R-07 | [Guide initial configuration](#r-07-guide-initial-configuration) | Later | Help the `owner` create valid `Maestro` configuration through an interview. |
|
|
29
|
+
| R-08 | [Change agent models before a builder run](#r-08-change-agent-models-before-a-builder-run) | Later | Let the `owner` change `builder` and `verifier` models before subsequent `runs`. |
|
|
30
|
+
| R-09 | [Define workflow reconciliation](#r-09-define-workflow-reconciliation) | Later | Define how `Maestro` can reconcile saved `artifacts` and workflow state. |
|
|
31
|
+
| R-21 | [Add a simplifier with one clear purpose per agent](#r-21-add-a-simplifier-with-one-clear-purpose-per-agent) | Later | Add a simplifier after successful verification to reduce complexity without changing behavior. |
|
|
32
|
+
|
|
9
33
|
## Completed
|
|
10
34
|
|
|
11
35
|
### R-01: Improve status presentation and activation feedback
|
|
@@ -60,7 +84,7 @@ Renamed `test/` to `tests/` at the owner's request. Updated imports, fixture pat
|
|
|
60
84
|
|
|
61
85
|
#### Evidence
|
|
62
86
|
|
|
63
|
-
[Test support](tests/support/), [fixtures](tests/fixtures/), [lint configuration](biome.json)
|
|
87
|
+
[Test support](tests/support/), [fixtures](tests/fixtures/), and [lint configuration](biome.json).
|
|
64
88
|
|
|
65
89
|
### R-16: Verify code quality against AGENTS.md instructions
|
|
66
90
|
|
|
@@ -98,27 +122,102 @@ All 3 `acceptance criteria` passed with no `verifier` `findings`. The saved work
|
|
|
98
122
|
|
|
99
123
|
[Specification](.specs/20261013-202811-check-acceptance-criterion-numbering-before-builder-execution/spec.md), [verifier report](.specs/20261013-202811-check-acceptance-criterion-numbering-before-builder-execution/handoffs/verifier/V1.json), and [merged PR #36](https://github.com/emilioSp/pi-maestro/pull/36).
|
|
100
124
|
|
|
101
|
-
## Now
|
|
102
|
-
|
|
103
125
|
### R-10: Match handoff criteria to the approved spec
|
|
104
126
|
|
|
127
|
+
Implemented in `0.9.5` with the narrower scope approved by the `owner`. Both `handoff` submissions require every `acceptance criterion` ID from the approved `spec` before saving a report or changing phase. Extra report IDs remain allowed. Existing report validation is unchanged, and no new check rejects duplicate `spec` IDs.
|
|
128
|
+
|
|
129
|
+
Both `acceptance criteria` passed independent verification with no `findings`. The saved workflow reached `candidate-ready`.
|
|
130
|
+
|
|
131
|
+
Later changes requested by the `owner` extracted the shared check and replaced repeated integration scenarios with unit tests. One missing-ID integration test remains per role. These changes are outside the completed independent verification. The final `npm run check` passed all 227 tests and coverage thresholds.
|
|
132
|
+
|
|
133
|
+
#### Evidence
|
|
134
|
+
|
|
135
|
+
[Specification](.specs/20261013-211629-match-handoff-criteria-to-the-approved-spec/spec.md), [verifier report](.specs/20261013-211629-match-handoff-criteria-to-the-approved-spec/handoffs/verifier/V1.json), and [merged PR #37](https://github.com/emilioSp/pi-maestro/pull/37).
|
|
136
|
+
|
|
137
|
+
### R-17: Record escalation resolutions when the spec changes
|
|
138
|
+
|
|
105
139
|
#### Objective
|
|
106
140
|
|
|
107
|
-
|
|
141
|
+
Save every current `escalation` answer in the original `builder` `handoff`, whether the `spec` stays unchanged or requires revision.
|
|
142
|
+
Each `resolution` records the owner's chosen solution and reason. A decision requiring revision also identifies the `escalation` and describes the agreed `spec` change.
|
|
143
|
+
|
|
144
|
+
#### Agreed flow
|
|
145
|
+
|
|
146
|
+
`Maestro` records the complete decision batch through `maestro_resolve_escalations` before changing phase.
|
|
108
147
|
|
|
109
|
-
|
|
148
|
+
| Decision | Next phase and action |
|
|
149
|
+
|---|---|
|
|
150
|
+
| No `spec` change | `escalation-decisions` → `ready-for-builder`. The `builder` continues under the approved `spec`, without renewed approval. |
|
|
151
|
+
| `Spec` change required | `escalation-decisions` → `drafting-spec`. The `owner` and `Maestro` revise and review the same `spec`. |
|
|
152
|
+
| Revised `spec` receives renewed `GREEN FLAG` | `drafting-spec` → `ready-for-builder` through separate `maestro_mark_spec_ready` approval. |
|
|
153
|
+
|
|
154
|
+
Direct `spec` approval from `escalation-decisions` is rejected. Recording answers does not move to `ready-for-verifier`; that phase requires a completed `builder` `pass`.
|
|
155
|
+
|
|
156
|
+
#### Implementation boundaries
|
|
157
|
+
|
|
158
|
+
Reuse the existing resolution operation and `handoff` fields. Do not add a parallel decision store, tool, or workflow phase.
|
|
159
|
+
Define both resolution transitions explicitly in `src/workflow/transitions.ts` and apply them through `transitionWorkflow`. Direct phase assignment elsewhere is banned.
|
|
160
|
+
Preserve initial `spec` approval, `verifier` `finding` decisions, existing batch validation, and historical `handoffs`.
|
|
110
161
|
|
|
111
162
|
#### Completed when
|
|
112
163
|
|
|
113
|
-
|
|
164
|
+
Saved `resolutions`, workflow phases, tool results, agent instructions, and human documentation follow the agreed flow.
|
|
165
|
+
Verification checks both observable behavior and use of the central transition definitions for each resolution branch. Passing behavior tests alone is not enough.
|
|
166
|
+
The new `spec` includes coverage labels and omits `acceptance criteria` already covered by tests of the same scenario.
|
|
167
|
+
|
|
168
|
+
### R-20: Route finding-driven spec revisions through drafting-spec
|
|
169
|
+
|
|
170
|
+
Implemented the approved revision route. `Maestro` records every current `finding` decision before returning to `drafting-spec` when revision is required.
|
|
171
|
+
The `owner` reviews the same revised `spec` and gives renewed `GREEN FLAG` before separate approval and another `builder` `run`.
|
|
172
|
+
Revision takes priority in mixed batches. Direct approval from `finding-decisions` is rejected.
|
|
173
|
+
|
|
174
|
+
Later event naming cleanup identifies `builder` and `owner` actions explicitly. Both revision routes use `OWNER_REQUEST_SPEC_REVISION` without changing the phase flow. Batch resolution uses `RESOLVE_ESCALATIONS`, and the status label refers to `escalations` in the plural. The saved decision phases are named `escalation-decisions` and `finding-decisions`.
|
|
175
|
+
|
|
176
|
+
#### Evidence
|
|
177
|
+
|
|
178
|
+
[Specification](.specs/20261015-154812-route-finding-driven-spec-revisions-through-drafting-spec/spec.md) and [resolution integration tests](src/tools/main/resolve-findings.integration.test.ts).
|
|
179
|
+
|
|
180
|
+
### R-18: Label acceptance criterion coverage
|
|
181
|
+
|
|
182
|
+
Implemented with R-19 as one task, as selected by the `owner`.
|
|
183
|
+
The `spec` template and `Maestro` guidance require one `Coverage` label per `acceptance criterion`:
|
|
114
184
|
|
|
115
|
-
|
|
185
|
+
| Label | Purpose |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `success` | A valid action produces the required result. |
|
|
188
|
+
| `failure` | An invalid action is correctly rejected. |
|
|
189
|
+
| `unchanged` | The change preserves existing behavior. |
|
|
116
190
|
|
|
117
|
-
|
|
191
|
+
Use `unchanged` when the criterion explicitly checks behavior that the change must preserve.
|
|
192
|
+
Labels describe scenarios, not test outcomes. A `failure` scenario passes when the invalid action is correctly rejected.
|
|
193
|
+
A `spec` does not need all three categories.
|
|
194
|
+
`Maestro` includes labels when presenting criteria to the `owner` and checks them against scenarios and `expected results` during review.
|
|
195
|
+
Approval validation and `handoff` formats remain unchanged.
|
|
118
196
|
|
|
119
|
-
|
|
197
|
+
The existing creation integration test now checks that the generated `spec` includes the coverage field.
|
|
198
|
+
The final `npm run check` passed all 238 tests and coverage thresholds. No model trials were performed.
|
|
120
199
|
|
|
121
|
-
|
|
200
|
+
#### Evidence
|
|
201
|
+
|
|
202
|
+
[Spec template](templates/spec.md), [Maestro guidance](src/maestro/instructions/getMaestroInstructions.ts), [creation integration test](src/specs/create.integration.test.ts), and [workflow documentation](docs/workflow.md#acceptance-criteria).
|
|
203
|
+
|
|
204
|
+
### R-19: Avoid acceptance criteria already covered by tests
|
|
205
|
+
|
|
206
|
+
Implemented with R-18. `Maestro` inspects existing tests before writing `acceptance criteria`.
|
|
207
|
+
It omits a criterion only when a test covers the same starting conditions, action, and `expected result`.
|
|
208
|
+
Partial or uncertain coverage does not justify omission. Similar tests do not count.
|
|
209
|
+
|
|
210
|
+
During `spec` review, `Maestro` removes criteria whose exact scenarios already have test coverage.
|
|
211
|
+
It keeps numbering continuous from `AC1` and updates affected references. Required behavior remains documented in the requirements and constraints.
|
|
212
|
+
The same rules apply during `spec` revisions. No automatic approval check was added.
|
|
213
|
+
|
|
214
|
+
Verification consisted of inspecting the written guidance and running `npm run check`. No model trials were performed.
|
|
215
|
+
|
|
216
|
+
#### Evidence
|
|
217
|
+
|
|
218
|
+
[Maestro guidance](src/maestro/instructions/getMaestroInstructions.ts), [spec template](templates/spec.md), and [workflow documentation](docs/workflow.md#acceptance-criteria).
|
|
219
|
+
|
|
220
|
+
## Now
|
|
122
221
|
|
|
123
222
|
## Next
|
|
124
223
|
|
|
@@ -167,3 +266,25 @@ Explore how `Maestro` can reconcile saved `artifacts` and workflow state. The re
|
|
|
167
266
|
#### Completed when
|
|
168
267
|
|
|
169
268
|
Not yet defined. The `owner` must define the intended outcome, recovery boundaries, and completion condition before this item can move forward.
|
|
269
|
+
|
|
270
|
+
### R-21: Add a simplifier with one clear purpose per agent
|
|
271
|
+
|
|
272
|
+
#### Objective
|
|
273
|
+
|
|
274
|
+
Each agent has exactly one purpose. The `builder` implements the approved `spec`. The `verifier` independently checks its `acceptance criteria`. The simplifier refactors verified code.
|
|
275
|
+
|
|
276
|
+
Add the simplifier after the `verifier`. It receives code built by the `builder` only after verification confirms that all checks defined in the `acceptance criteria` pass.
|
|
277
|
+
|
|
278
|
+
The simplifier reduces complexity while preserving exact behavior. The goal is code that is easier to read, understand, modify, and debug, not fewer lines.
|
|
279
|
+
Every simplification must pass this test: "Would a new team member understand this faster than the original?"
|
|
280
|
+
|
|
281
|
+
#### Scope boundaries
|
|
282
|
+
|
|
283
|
+
Remove the "Review code quality" section from `agents/verifier.md`. This replaces the additional review introduced in R-16, not independent verification of `acceptance criteria`.
|
|
284
|
+
|
|
285
|
+
The simplifier's detailed instructions will be defined during `spec` preparation. This roadmap item does not define them.
|
|
286
|
+
|
|
287
|
+
#### Completed when
|
|
288
|
+
|
|
289
|
+
The workflow includes the simplifier after successful verification. Agent instructions keep implementation, verification, and simplification as separate responsibilities.
|
|
290
|
+
The simplifier preserves exact behavior and follows the instructions agreed in the approved `spec`.
|
package/agents/verifier.md
CHANGED
|
@@ -115,5 +115,5 @@ Do not delete artifacts, change workflow state, or bypass the tool to force comp
|
|
|
115
115
|
If restoration or submission cannot be completed safely, report the exact blocker and remaining changes to Maestro and stop.
|
|
116
116
|
|
|
117
117
|
After a successful handoff, return a concise summary and the saved artifact path to Maestro and stop. Do not run more checks.
|
|
118
|
-
The handoff produces `
|
|
118
|
+
The handoff produces `finding-decisions` when findings exist and `candidate-ready` when none exist.
|
|
119
119
|
Report that tool result without deciding whether the owner must accept, reject, or fix any finding.
|
package/docs/glossary.md
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
| `Escalation` | An implementation question or reportable technical problem that the `builder` records in its `handoff` for an `owner` decision. |
|
|
22
22
|
| `GREEN FLAG` | The owner's explicit reply that approves the current `spec` and starts the `builder`. |
|
|
23
23
|
| `fix-code` | An `owner` decision that requests code fixes without changing the approved `spec`. |
|
|
24
|
+
| `revise-spec` | An `owner` decision that records a reason and agreed requirement change, then returns to `drafting-spec` for revision and renewed approval. |
|
|
24
25
|
| `reject` | An `owner` decision that declines a `finding` and records a reason. It does not mean that verification passed. |
|
|
25
26
|
| `candidate-ready` | The completed workflow phase. The `verifier` reported no `findings`, or the `owner` rejected every `finding` with a reason. Final review remains with the `owner`. |
|
|
26
27
|
|
package/docs/workflow.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
The approved `spec.md` defines behavior, scope, constraints, technical decisions, and `acceptance criteria` for the change.
|
|
6
6
|
|
|
7
|
-
An `acceptance criterion` contains a `probe`, an `expected result`, and an example. A `probe` is a scenario used to test behavior.
|
|
7
|
+
An `acceptance criterion` contains a coverage label, a `probe`, an `expected result`, and an example. A `probe` is a scenario used to test behavior.
|
|
8
8
|
|
|
9
9
|
A `handoff` is a saved report from a `builder` or `verifier` `run`. It records the result, `probe` outcomes, and notes.
|
|
10
10
|
|
|
@@ -61,16 +61,16 @@ flowchart TD
|
|
|
61
61
|
findings -->|None| candidate
|
|
62
62
|
|
|
63
63
|
buildOutcome -->|Escalation| ownerEscalation{Owner decides every question}
|
|
64
|
-
ownerEscalation
|
|
65
|
-
recordEscalation
|
|
66
|
-
|
|
64
|
+
ownerEscalation --> recordEscalation[Maestro records all answers]
|
|
65
|
+
recordEscalation -->|Spec unchanged| build
|
|
66
|
+
recordEscalation -->|Spec changes| reviseSpec[Owner and Maestro revise the spec]
|
|
67
67
|
reviseSpec --> approval
|
|
68
68
|
|
|
69
69
|
findings -->|One or more| ownerFindings[Owner decides every finding]
|
|
70
|
-
ownerFindings
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
ownerFindings --> recordFindings[Maestro records all decisions]
|
|
71
|
+
recordFindings -->|Reject all with reasons| candidate
|
|
72
|
+
recordFindings -->|Fix code without spec changes| build
|
|
73
|
+
recordFindings -->|Spec changes| reviseSpec
|
|
74
74
|
|
|
75
75
|
candidate --> summary
|
|
76
76
|
summary --> review
|
|
@@ -86,13 +86,13 @@ The default path is `.specs/<spec-id>/workflow.json`. The `spec` directory is [c
|
|
|
86
86
|
|
|
87
87
|
| Phase | Meaning |
|
|
88
88
|
|---|---|
|
|
89
|
-
| `drafting-spec` | The `owner` and `Maestro`
|
|
89
|
+
| `drafting-spec` | The `owner` and `Maestro` prepare the initial `spec` or revise it after recorded `escalation` answers or `finding` decisions. |
|
|
90
90
|
| `ready-for-builder` | The approved `spec` or recorded `owner` decisions permit a `builder` `run`. |
|
|
91
91
|
| `builder-running` | A `builder` `run` is active. |
|
|
92
|
-
| `escalation-
|
|
92
|
+
| `escalation-decisions` | The `owner` must decide how to handle every `escalation` question. |
|
|
93
93
|
| `ready-for-verifier` | The `builder` completed the work and the `verifier` can start. |
|
|
94
94
|
| `verifier-running` | A `verifier` `run` is active. |
|
|
95
|
-
| `
|
|
95
|
+
| `finding-decisions` | The `owner` must decide how to handle every current `finding`. |
|
|
96
96
|
| `candidate-ready` | The `verifier` reported no `findings`, or the `owner` rejected every `finding` with a reason. The workflow is complete. |
|
|
97
97
|
|
|
98
98
|
## Spec approval
|
|
@@ -104,7 +104,7 @@ For the initial `spec`:
|
|
|
104
104
|
3. `Maestro` asks the `owner` to inspect the current `spec.md` and reply `GREEN FLAG` to approve it and start the `builder`.
|
|
105
105
|
4. After that reply, `Maestro` saves `ready-for-builder` and starts the `builder` in the foreground.
|
|
106
106
|
|
|
107
|
-
Approval freezes the `spec`. The `spec` and its visual prototypes remain unchanged during `builder` and `verifier` execution.
|
|
107
|
+
Approval freezes the `spec`. The `spec` and its visual prototypes remain unchanged during `builder` and `verifier` execution. See [Spec revision](#spec-revision) for permitted revisions.
|
|
108
108
|
|
|
109
109
|
## Acceptance criteria
|
|
110
110
|
|
|
@@ -114,6 +114,7 @@ Each criterion contains these parts:
|
|
|
114
114
|
|
|
115
115
|
| Part | Content |
|
|
116
116
|
|---|---|
|
|
117
|
+
| Coverage | One label that states the scenario's purpose: `success`, `failure`, or `unchanged`. |
|
|
117
118
|
| `Probe` | Starting conditions and the action or observation that checks the behavior. |
|
|
118
119
|
| `Expected result` | The measurable result the `probe` observes. |
|
|
119
120
|
| Example | Concrete starting conditions, an input or action, and the exact `expected result`. |
|
|
@@ -125,14 +126,17 @@ For instance a technical failure, an undefined behavior, a conflict with the `sp
|
|
|
125
126
|
|
|
126
127
|
The `builder` saves all questions from one `pass` in the `escalations` list of its numbered `handoff`. `Maestro` identifies each question with both report and `escalation` IDs, such as `B1/E1`. See [Escalation references](glossary.md#escalation-references) for their scope.
|
|
127
128
|
|
|
128
|
-
`Maestro` presents each question, evidence, options, consequences, and next steps. The workflow pauses in `escalation-
|
|
129
|
+
`Maestro` presents each question, evidence, options, consequences, and next steps. The workflow pauses in `escalation-decisions` while the `owner` decides how to proceed.
|
|
129
130
|
|
|
130
|
-
|
|
131
|
+
The `owner` gives `Maestro` an answer and reason for every current question, whether or not the `spec` must change.
|
|
132
|
+
The `owner` can select a listed option or give a different decision.
|
|
133
|
+
|
|
134
|
+
`Maestro` saves all answers in the current `builder` `handoff` before the workflow continues.
|
|
131
135
|
|
|
132
136
|
| `Owner` choice | Result |
|
|
133
137
|
|---|---|
|
|
134
|
-
| Keep the current `spec` | `Maestro`
|
|
135
|
-
| Change the `spec` | The `owner` and `Maestro` revise the same `spec` and
|
|
138
|
+
| Keep the current `spec` | `Maestro` starts another `builder` `run` without renewed approval. |
|
|
139
|
+
| Change the `spec` | The `owner` and `Maestro` revise the same `spec`. The `owner` reviews it and replies `GREEN FLAG` before another `builder` `run`. |
|
|
136
140
|
|
|
137
141
|
`Owner` decisions update only the questions' `resolution` fields. The handoff's other content and earlier `handoffs` remain unchanged.
|
|
138
142
|
|
|
@@ -147,19 +151,27 @@ Every current `finding` requires an `owner` decision, regardless of severity. `M
|
|
|
147
151
|
| Decision | Result |
|
|
148
152
|
|---|---|
|
|
149
153
|
| `reject` | Records the owner's reason. If every `finding` is rejected, the workflow reaches `candidate-ready`. |
|
|
150
|
-
| `fix-code` | Keeps the current `spec` and returns to `ready-for-builder` for code fixes. |
|
|
154
|
+
| `fix-code` | Keeps the current `spec` and returns to `ready-for-builder` for code fixes when no decision requires revision. |
|
|
155
|
+
| `revise-spec` | Records the owner's reason and agreed requirement change, then returns to `drafting-spec`. |
|
|
151
156
|
|
|
152
|
-
|
|
157
|
+
`Maestro` saves every current decision together before the phase changes.
|
|
158
|
+
If any `finding` requires revision, revision takes priority over code fixes and rejections. See [Spec revision](#spec-revision).
|
|
153
159
|
|
|
154
|
-
|
|
160
|
+
Without revision, any `fix-code` decision requires another `builder` `run`, including when other `findings` are rejected.
|
|
161
|
+
After the `builder` completes the fixes, the `verifier` checks the work again.
|
|
155
162
|
|
|
156
163
|
## Spec revision
|
|
157
164
|
|
|
158
|
-
|
|
165
|
+
For either `escalation` answers or `finding` decisions, `Maestro` records the complete batch before the workflow returns to `drafting-spec`.
|
|
166
|
+
This decision does not approve the `spec` or start an agent.
|
|
167
|
+
The `owner` and `Maestro` then revise the same `spec` together in `drafting-spec`.
|
|
159
168
|
|
|
160
|
-
|
|
169
|
+
The `owner` reviews the changes and replies `GREEN FLAG` again.
|
|
170
|
+
`Maestro` records that renewed approval separately, moves to `ready-for-builder`, and starts another `builder` `run`.
|
|
171
|
+
Approval is permitted only in `drafting-spec`, not directly from either decision phase.
|
|
161
172
|
|
|
162
|
-
|
|
173
|
+
The revised `spec` controls subsequent work.
|
|
174
|
+
Earlier `escalations`, `findings`, and their decisions remain historical context.
|
|
163
175
|
|
|
164
176
|
## Verification boundary
|
|
165
177
|
|
package/package.json
CHANGED
package/src/MaestroPaths.ts
CHANGED
|
@@ -100,36 +100,15 @@ export class MaestroPaths {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
public getSpecFilePath(specId: string): string {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return resolve(
|
|
106
|
-
this.projectRoot,
|
|
107
|
-
this.specDirectoryFromRoot,
|
|
108
|
-
specId,
|
|
109
|
-
PATHS.SPEC_FILE,
|
|
110
|
-
);
|
|
103
|
+
return resolve(this.getSpecPath(specId), PATHS.SPEC_FILE);
|
|
111
104
|
}
|
|
112
105
|
|
|
113
106
|
public getWorkflowPath(specId: string): string {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return resolve(
|
|
117
|
-
this.projectRoot,
|
|
118
|
-
this.specDirectoryFromRoot,
|
|
119
|
-
specId,
|
|
120
|
-
PATHS.WORKFLOW_FILE,
|
|
121
|
-
);
|
|
107
|
+
return resolve(this.getSpecPath(specId), PATHS.WORKFLOW_FILE);
|
|
122
108
|
}
|
|
123
109
|
|
|
124
110
|
public getHandoffsPath(specId: string): string {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return resolve(
|
|
128
|
-
this.projectRoot,
|
|
129
|
-
this.specDirectoryFromRoot,
|
|
130
|
-
specId,
|
|
131
|
-
PATHS.HANDOFFS_PATH,
|
|
132
|
-
);
|
|
111
|
+
return resolve(this.getSpecPath(specId), PATHS.HANDOFFS_PATH);
|
|
133
112
|
}
|
|
134
113
|
|
|
135
114
|
public getBuilderHandoffsPath(specId: string): string {
|
|
@@ -208,14 +187,7 @@ export class MaestroPaths {
|
|
|
208
187
|
}
|
|
209
188
|
|
|
210
189
|
public getPrototypesPath(specId: string): string {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return resolve(
|
|
214
|
-
this.projectRoot,
|
|
215
|
-
this.specDirectoryFromRoot,
|
|
216
|
-
specId,
|
|
217
|
-
PATHS.PROTOTYPES_PATH,
|
|
218
|
-
);
|
|
190
|
+
return resolve(this.getSpecPath(specId), PATHS.PROTOTYPES_PATH);
|
|
219
191
|
}
|
|
220
192
|
|
|
221
193
|
public getPrototypePath({
|
|
@@ -66,37 +66,31 @@ export function assertBuilderHandoff(
|
|
|
66
66
|
throw new Error('Done builder handoff requires every probe to pass.');
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
throw new Error('Escalation option IDs must be unique.');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
escalation.recommendation !== null &&
|
|
83
|
-
!optionIds.has(escalation.recommendation.optionId)
|
|
84
|
-
) {
|
|
85
|
-
throw new Error('Escalation recommendation references unknown option.');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
escalation.resolution !== null &&
|
|
90
|
-
escalation.resolution.selectedOptionId !== null &&
|
|
91
|
-
!optionIds.has(escalation.resolution.selectedOptionId)
|
|
92
|
-
) {
|
|
93
|
-
throw new Error('Escalation resolution references unknown option.');
|
|
94
|
-
}
|
|
69
|
+
for (const [index, escalation] of handoff.escalations.entries()) {
|
|
70
|
+
if (escalation.id !== `E${index + 1}`) {
|
|
71
|
+
throw new Error('Escalation IDs must be sequential in array order.');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const optionIds = new Set(escalation.options.map(({ id }) => id));
|
|
75
|
+
|
|
76
|
+
if (optionIds.size !== escalation.options.length) {
|
|
77
|
+
throw new Error('Escalation option IDs must be unique.');
|
|
95
78
|
}
|
|
96
|
-
}
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
if (
|
|
81
|
+
escalation.recommendation !== null &&
|
|
82
|
+
!optionIds.has(escalation.recommendation.optionId)
|
|
83
|
+
) {
|
|
84
|
+
throw new Error('Escalation recommendation references unknown option.');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
escalation.resolution !== null &&
|
|
89
|
+
escalation.resolution.selectedOptionId !== null &&
|
|
90
|
+
!optionIds.has(escalation.resolution.selectedOptionId)
|
|
91
|
+
) {
|
|
92
|
+
throw new Error('Escalation resolution references unknown option.');
|
|
93
|
+
}
|
|
100
94
|
}
|
|
101
95
|
|
|
102
96
|
if (handoff.specId !== specId) {
|
|
@@ -40,18 +40,17 @@ export function assertVerifierHandoff(
|
|
|
40
40
|
throw new Error(`Invalid verifier handoff spec ID: "${handoff.specId}".`);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const acceptanceCriterionIds = new Set(
|
|
44
|
+
handoff.acceptanceCriteria.map((criterion) => criterion.id),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (acceptanceCriterionIds.size !== handoff.acceptanceCriteria.length) {
|
|
47
48
|
throw new Error(
|
|
48
49
|
'Verifier handoff acceptance criterion IDs must be unique.',
|
|
49
50
|
);
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
const
|
|
53
|
-
handoff.acceptanceCriteria.map((criterion) => criterion.id),
|
|
54
|
-
);
|
|
53
|
+
const criterionIdsWithFindings = new Set<string>();
|
|
55
54
|
|
|
56
55
|
for (const [index, finding] of handoff.findings.entries()) {
|
|
57
56
|
const expectedId = `F${index + 1}`;
|
|
@@ -62,26 +61,23 @@ export function assertVerifierHandoff(
|
|
|
62
61
|
);
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
if (finding.acceptanceCriterion === null) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!acceptanceCriterionIds.has(finding.acceptanceCriterion)) {
|
|
69
69
|
throw new Error(
|
|
70
70
|
`Verifier handoff finding "${finding.id}" references unknown acceptance criterion "${finding.acceptanceCriterion}".`,
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
|
-
}
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
finding.acceptanceCriterion === null ? [] : [finding.acceptanceCriterion],
|
|
78
|
-
),
|
|
79
|
-
);
|
|
74
|
+
criterionIdsWithFindings.add(finding.acceptanceCriterion);
|
|
75
|
+
}
|
|
80
76
|
|
|
81
77
|
for (const criterion of handoff.acceptanceCriteria) {
|
|
82
78
|
if (
|
|
83
79
|
criterion.probeStatus !== PROBE_STATUSES.PASSED &&
|
|
84
|
-
!
|
|
80
|
+
!criterionIdsWithFindings.has(criterion.id)
|
|
85
81
|
) {
|
|
86
82
|
throw new Error(
|
|
87
83
|
`Verifier handoff incomplete acceptance criterion "${criterion.id}" requires a finding.`,
|
|
@@ -35,10 +35,19 @@ const FindingEvidenceSchema = Type.Object(
|
|
|
35
35
|
export const FINDING_DECISIONS = {
|
|
36
36
|
REJECT: 'reject',
|
|
37
37
|
FIX_CODE: 'fix-code',
|
|
38
|
+
REVISE_SPEC: 'revise-spec',
|
|
38
39
|
} as const;
|
|
39
40
|
|
|
40
41
|
const FindingDecisionSchema = Type.Union([
|
|
41
42
|
Type.Null(),
|
|
43
|
+
Type.Object(
|
|
44
|
+
{
|
|
45
|
+
decision: Type.Literal(FINDING_DECISIONS.REVISE_SPEC),
|
|
46
|
+
reason: Type.String({ minLength: 1, pattern: '\\S' }),
|
|
47
|
+
specChange: Type.String({ minLength: 1, pattern: '\\S' }),
|
|
48
|
+
},
|
|
49
|
+
{ additionalProperties: false },
|
|
50
|
+
),
|
|
42
51
|
Type.Object(
|
|
43
52
|
{
|
|
44
53
|
decision: Type.Literal(FINDING_DECISIONS.REJECT),
|