@emiliosp/pi-maestro 0.6.3 → 0.7.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.
Files changed (30) hide show
  1. package/README.md +10 -5
  2. package/agents/builder.md +6 -7
  3. package/agents/verifier.md +3 -3
  4. package/docs/glossary.md +69 -0
  5. package/docs/subagent-integration.md +1 -1
  6. package/docs/workflow.md +55 -23
  7. package/extensions/maestro-subagent.ts +0 -2
  8. package/extensions/maestro.ts +5 -5
  9. package/package.json +3 -4
  10. package/src/MaestroPaths.ts +0 -32
  11. package/src/artifacts/builder-handoff/assertBuilderHandoff.ts +29 -0
  12. package/src/artifacts/builder-handoff/schema.ts +87 -23
  13. package/src/maestro/instructions/getMaestroInstructions.ts +7 -7
  14. package/src/specs/create.ts +0 -4
  15. package/src/tools/child/record-builder-handoff.ts +14 -16
  16. package/src/tools/main/resolve-escalations.ts +72 -0
  17. package/src/tools/main/run-builder.ts +14 -10
  18. package/src/workflow/builder/completeBuilderPass.ts +20 -32
  19. package/src/workflow/escalation/resolveEscalations.ts +100 -0
  20. package/src/artifacts/escalation/assertEscalation.ts +0 -66
  21. package/src/artifacts/escalation/createEscalation.ts +0 -52
  22. package/src/artifacts/escalation/getNextEscalationId.ts +0 -23
  23. package/src/artifacts/escalation/readEscalation.ts +0 -40
  24. package/src/artifacts/escalation/readEscalationHistory.ts +0 -44
  25. package/src/artifacts/escalation/resolveEscalation.ts +0 -43
  26. package/src/artifacts/escalation/schema.ts +0 -73
  27. package/src/tools/child/open-escalation.ts +0 -71
  28. package/src/tools/main/resolve-escalation.ts +0 -65
  29. package/src/workflow/escalation/openBuilderEscalation.ts +0 -82
  30. package/src/workflow/escalation/resolveBuilderEscalation.ts +0 -118
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # pi-maestro
2
2
 
3
+ [![Coverage](https://img.shields.io/codecov/c/github/emiliosp/pi-maestro?logo=codecov)](https://codecov.io/gh/emiliosp/pi-maestro)
4
+
3
5
  Pi extension for a spec-driven multiagent development workflow.
4
6
 
5
7
  ![Maestro workflow](docs/maestro.png)
@@ -66,11 +68,11 @@ The owner follows this workflow:
66
68
  1. Describes one change to Maestro.
67
69
  2. Reviews the spec, including its acceptance criteria and concrete examples.
68
70
  3. Replies `GREEN FLAG` when Maestro asks for approval. Maestro records the approval and starts the builder.
69
- 4. Reviews builder escalations and decides how to proceed.
71
+ 4. Reviews every current builder escalation and gives Maestro an answer and reason for each question.
70
72
  5. Reviews verifier findings and chooses an action for every finding.
71
73
  6. Reads Maestro's summary at `candidate-ready` and performs the final review.
72
74
 
73
- Maestro starts the verifier after a successful builder run.
75
+ Maestro starts the verifier after a successful builder run.
74
76
  Both agents run in the foreground: Pi waits for each run to finish and Maestro shows the current phase in Pi's status, while `pi-subagents` FleetView and `/subagents-fleet` show agent activity and transcripts.
75
77
 
76
78
  The owner must not edit product files while the workflow runs.
@@ -89,6 +91,9 @@ Maestro uses default values when `.pi/maestro.json` is absent from the project r
89
91
 
90
92
  ## Documentation
91
93
 
92
- 1. [Workflow](docs/workflow.md).
93
- 2. [Configuration](docs/configuration.md).
94
- 3. [Subagent integration](docs/subagent-integration.md).
94
+ The reading order is:
95
+
96
+ 1. [Glossary](docs/glossary.md): terms and identifiers used in specs, reports, and Maestro messages. Read this before the first workflow.
97
+ 2. [Workflow](docs/workflow.md): approvals, decisions, and how each run produces artifacts.
98
+ 3. [Configuration](docs/configuration.md): project paths, models, and timeouts.
99
+ 4. [Subagent integration](docs/subagent-integration.md): agent context, execution, and activity tracking.
package/agents/builder.md CHANGED
@@ -6,7 +6,6 @@ systemPromptMode: replace
6
6
  inheritProjectContext: true
7
7
  inheritGlobalContext: true
8
8
  inheritSkills: true
9
- completionGuard: false
10
9
  subagentOnlyExtensions: ../extensions/maestro-subagent.ts
11
10
  ---
12
11
 
@@ -22,7 +21,7 @@ Do not delegate, contact the owner directly, or approve your own work.
22
21
  1. Use the exact `specId` supplied by Maestro. Do not select another spec.
23
22
  2. Locate `<specDirectory>/<specId>/` relative to the canonical Pi working directory supplied by Maestro. Use `specDirectory` from `.pi/maestro.json`, or `.specs` when unset.
24
23
  3. Read `spec.md`, relevant `prototypes/`, `workflow.json`, and applicable `AGENTS.md` files.
25
- 4. Read available handoffs and escalation resolutions for this spec. Earlier numbered artifacts remain on the file system.
24
+ 4. Read available handoffs and their embedded escalation resolutions for this spec. Earlier numbered artifacts remain on the file system.
26
25
  5. Confirm that the workflow identifies this spec and is in `builder-running`. Maestro already saved that phase.
27
26
 
28
27
  If the supplied spec is missing or the phase is wrong, report the mismatch to Maestro and stop. Do not repair workflow state.
@@ -32,7 +31,7 @@ The highest numeric sequence is the active handoff for each role. Earlier record
32
31
 
33
32
  Do not edit the frozen spec during builder or verifier execution.
34
33
  The approved spec defines the required behavior, constraints, technical decisions, scope, and acceptance criteria.
35
- If this pass follows an escalation resolution, follow the recorded owner decision without changing the contract.
34
+ If this pass follows escalation resolutions, read them from the active builder handoff and follow each owner decision.
36
35
  If this pass follows `fix-code`, fix all current findings assigned for repair. These contain an explicit `decision: { decision: "fix-code" }` from the owner.
37
36
  Do not fix rejected findings merely because they appear in the handoff.
38
37
  After a spec revision, earlier escalations and findings are historical context, not active repair instructions.
@@ -43,8 +42,8 @@ Use the active spec and the active handoff to assess repair instructions. A find
43
42
  Change only product files needed to meet the approved contract, within the project root.
44
43
  Use existing repository patterns for routine implementation details that the spec leaves open. Do not add unrelated improvements.
45
44
  Follow applicable repository commands and technical rules. Inspect scripts before running them. Do not invent required commands.
46
- Do not edit `spec.md`, prototypes, `workflow.json`, handoffs, or escalation files directly through any tool.
47
- Use `maestro_record_builder_handoff` or `maestro_open_escalation` for protocol changes. The tools supply artifact paths and versions.
45
+ Do not edit `spec.md`, prototypes, `workflow.json`, or handoffs directly through any tool.
46
+ Use `maestro_record_builder_handoff` for protocol changes. The tool supplies artifact paths and versions.
48
47
 
49
48
  If a significant discovery requires an owner choice, stop implementation and use the escalation outcome below.
50
49
  Examples include a spec conflict, undefined behavior, a material architectural alternative, scope changes, or verification and reversibility decisions.
@@ -75,8 +74,8 @@ Include every spec criterion once. Do not omit unrun criteria, fabricate evidenc
75
74
  Before any terminal tool call, restore temporary verification changes and remove temporary verification files. Keep the implementation work.
76
75
  Choose the outcome from the actual result:
77
76
 
78
- 1. `done`: Implementation and required checks are complete. Every criterion has `probeStatus: passed`. Call `maestro_record_builder_handoff` with `specId`, `status: done`, `summary`, `acceptanceCriteria`, and `notes`.
79
- 2. Escalation: An owner decision is required. Call `maestro_open_escalation` with `specId`, `question`, `context`, `options`, `recommendation`, and `notes`. Include evidence in the context. Give each option an ID, description, consequences, and next step. Use `recommendation: null` unless evidence supports a specific option. Do not also submit a builder handoff.
77
+ 1. `done`: Implementation and required checks are complete. Every criterion has `probeStatus: passed`. Call `maestro_record_builder_handoff` with `specId`, `status: done`, `summary`, `acceptanceCriteria`, `notes`, and `escalations: []`.
78
+ 2. `escalation`: An owner decision is required. Call `maestro_record_builder_handoff` with `specId`, `status: escalation`, `summary`, every criterion result, `notes`, and all `escalations`. Assign sequential IDs in array order: `E1`, `E2`, and so on. Restart at `E1` for each handoff. Each entry contains `id`, `question`, `context`, `options`, `recommendation`, `notes`, and `resolution: null`. Include evidence in the context. Give each option an ID, description, consequences, and next step. Use `recommendation: null` unless evidence supports an option. Refer to questions with both IDs, such as `B1/E1`. Record actual probe results, including incomplete probes. All probes can pass when an owner decision remains necessary. Save one handoff and stop.
80
79
  3. `failed`: You cannot complete the work for a technical reason that needs no owner decision. Call `maestro_record_builder_handoff` with `specId`, `status: failed`, `summary`, all criterion results, `failure.reason`, and `notes`. Report actual statuses, including `not-run` where applicable.
81
80
 
82
81
  After a successful terminal call, return the saved outcome and artifact path to Maestro. Stop the pass.
@@ -6,7 +6,6 @@ systemPromptMode: replace
6
6
  inheritProjectContext: true
7
7
  inheritGlobalContext: true
8
8
  inheritSkills: true
9
- completionGuard: false
10
9
  subagentOnlyExtensions: ../extensions/maestro-subagent.ts
11
10
  ---
12
11
 
@@ -22,7 +21,7 @@ Do not delegate, contact the owner directly, repair the implementation, or issue
22
21
  1. Use the exact `specId` and project directory supplied by Maestro. Do not select another spec or project.
23
22
  2. Locate `<specDirectory>/<specId>/` relative to the canonical Pi working directory supplied by Maestro. Use `specDirectory` from `.pi/maestro.json`, or `.specs` when unset.
24
23
  3. Read `spec.md`, relevant `prototypes/`, `workflow.json`, and applicable `AGENTS.md` files.
25
- 4. Read the builder handoff and available earlier handoffs, escalation resolutions, and finding decisions. Earlier numbered artifacts remain on the file system.
24
+ 4. Read the builder handoff and available earlier handoffs, embedded escalation resolutions in builder handoffs, and finding decisions. Earlier numbered artifacts remain on the file system.
26
25
  5. Confirm that the workflow identifies this spec and is in `verifier-running`.
27
26
 
28
27
  If the required inputs or phase do not match, report the mismatch to Maestro and stop. Do not reset unrelated changes.
@@ -30,6 +29,7 @@ The candidate is the live project. Maestro creates no product snapshot or file-h
30
29
  This workflow assumes no external product edits during verification.
31
30
  Handoffs use `handoffs/builder/B1.json`, `B2.json` and `handoffs/verifier/V1.json`, `V2.json`.
32
31
  The highest numeric sequence is the active handoff for each role. Earlier handoffs and their owner decisions remain references.
32
+ Escalation questions and owner resolutions are inside builder handoffs. Use handoff-qualified references, such as `B1/E1` and `B2/E1`.
33
33
  You start with a fresh context. Use artifacts as context, never as proof or as a replacement for the active spec.
34
34
  After a spec revision, assess historical observations against the revised contract. Do not carry forward old findings without fresh evidence.
35
35
 
@@ -89,7 +89,7 @@ Before each temporary change, retain the exact original file contents and note w
89
89
  Before handoff, restore only your temporary changes from probes and repository checks to those exact contents.
90
90
  Remove only temporary files created during this pass. Preserve all pre-existing files and content. Do not use blanket cleanup commands.
91
91
  For example, restore `src/total.ts` from `return 0` to its original `return 42`, remove your `probe.txt`, and leave pre-existing `notes.txt` unchanged.
92
- The spec, prototypes, earlier handoffs, and escalation files must remain unchanged. Findings do not relax this requirement.
92
+ The spec, prototypes, and earlier handoffs must remain unchanged. Findings do not relax this requirement.
93
93
  If cleanup cannot finish safely, stop and report the remaining changes. Maestro validates the protocol, not product restoration.
94
94
 
95
95
  Call `maestro_record_verifier_handoff` with `specId`, `summary`, every criterion result, `findings`, and `notes`.
@@ -0,0 +1,69 @@
1
+ # Glossary
2
+
3
+ ## Terms
4
+
5
+ | Term | Meaning |
6
+ |---|---|
7
+ | Owner | The person who approves the spec, decides questions and findings, and performs the final review. |
8
+ | Maestro | The coordinator that prepares the spec, runs the agents, and records owner decisions. |
9
+ | Builder | The agent that implements the approved spec and runs its probes. |
10
+ | Verifier | The independent agent that checks the implementation and reports technical issues. |
11
+ | Spec | A specification that describes one change and its acceptance criteria. It is saved as `spec.md`. |
12
+ | Contract | The approved spec that defines the required behavior and scope. |
13
+ | Acceptance criterion (AC) | One required, observable result defined in the spec. |
14
+ | Probe | A scenario used to test an acceptance criterion. Reports record the actual command or procedure and its outcome. |
15
+ | Expected result | The observable result that a probe must produce. |
16
+ | Artifact | A saved workflow file, such as a spec, or a handoff between agents. |
17
+ | Handoff | A saved builder or verifier report with results, probe outcomes, and notes. |
18
+ | Run or pass | One execution of the builder or verifier with a fresh conversation. |
19
+ | Candidate | The project files created by agents after a workflow run |
20
+ | Finding | A technical issue that the verifier records for an owner decision. |
21
+ | Escalation | An implementation question that the builder records in its handoff for an owner decision. |
22
+ | `GREEN FLAG` | The owner's explicit reply that approves the current spec and starts the builder. |
23
+ | `fix-code` | An owner decision that requests code fixes without changing the approved spec. |
24
+ | `reject` | An owner decision that declines a finding and records a reason. It does not mean that verification passed. |
25
+ | `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
+ ## Identifiers and file names
28
+
29
+ An ID is an identifier that names one record. These labels refer to records within one spec, not across all workflows.
30
+
31
+ | Label | Meaning | Location or scope |
32
+ |---|---|---|
33
+ | `<spec-id>` | The identifier shared by the spec and its workflow artifacts. | The directory name under `<project-root>/.specs/` by default. |
34
+ | `B1`, `B2` | Builder handoff 1, builder handoff 2. | `handoffs/builder/B1.json`, `handoffs/builder/B2.json`. |
35
+ | `V1`, `V2` | Verifier handoff 1, verifier handoff 2. | `handoffs/verifier/V1.json`, `handoffs/verifier/V2.json`. |
36
+ | `E1`, `E2` | Escalation 1, escalation 2 within one builder report. | Entries in that report's `escalations` list. |
37
+ | `F1`, `F2` | Finding 1, finding 2 within one verifier report. | Entries in that report's `findings` list. |
38
+ | `AC1`, `AC2` | Acceptance criterion 1, acceptance criterion 2. | Criteria in `spec.md` and the matching `acceptanceCriteria` entries in reports. |
39
+ | `B1/E1` | Escalation 1 in builder handoff 1. | The question with `id: "E1"` inside `handoffs/builder/B1.json`. |
40
+ | `V1/F2` | Finding 2 in verifier handoff 1. | The finding with `id: "F2"` inside `handoffs/verifier/V1.json`. |
41
+
42
+ All paths in this table are relative to the spec directory unless stated otherwise. The [configuration](configuration.md#path-rules) can change the directory that contains specs.
43
+
44
+ The `AC` prefix is the template's naming convention. Criterion IDs must be unique within the spec. Reports use the exact IDs from the spec.
45
+
46
+ Builder and verifier numbers count saved handoffs in separate sequences.
47
+
48
+ ## Escalation references
49
+
50
+ Read `B1/E1` as "escalation 1 in builder report 1". `B1` selects `handoffs/builder/B1.json`. `E1` selects the entry with `id: "E1"` in its `escalations` list.
51
+
52
+ Escalation numbers restart at `E1` in each builder report. `B1/E1` and `B2/E1` identify different questions, even if they concern the same topic.
53
+
54
+ The owner discusses every current question with Maestro. Maestro records all answers and reasons together in that same builder report. See [Escalations](workflow.md#escalations) for the available choices and their effects.
55
+
56
+ ## Finding references
57
+
58
+ Read `V1/F2` as "finding 2 in verifier report 1". `V1` selects `handoffs/verifier/V1.json`. `F2` selects the entry with `id: "F2"` in its `findings` list.
59
+
60
+ Finding numbers restart at `F1` in each verifier report. `V1/F2` and `V2/F2` identify different records, even if they describe a similar issue.
61
+
62
+ For example, a finding about a saved title can appear in a Maestro message like this:
63
+
64
+ > Verifier report 1, finding 2 (`V1/F2`): the title returns to "Draft" after saving "Ready" and reopening the item.
65
+ > Acceptance criterion 1 (`AC1`) requires the saved title to remain "Ready".
66
+
67
+ In this example, the finding's `acceptanceCriterion: "AC1"` connects the issue to criterion `AC1` in `spec.md`.
68
+
69
+ The owner discusses the issue with Maestro. Maestro records the decision in the same verifier report. See [Findings](workflow.md#findings) for the available choices and their effects.
@@ -23,7 +23,7 @@ Runs stay in the foreground and occur one at a time. Pi waits for each run to fi
23
23
 
24
24
  Maestro's Pi status shows the workflow phase. `pi-subagents` FleetView shows agent activity, and `/subagents-fleet` opens its inspector for details and transcripts.
25
25
 
26
- Each child saves its result through Maestro tools before returning.
26
+ Each child saves its result through Maestro tools before returning. Builder results produce `B1.json`, `B2.json`, and so on. Verifier results produce `V1.json`, `V2.json`, and so on. See [Stored artifacts](workflow.md#stored-artifacts) for the creation sequence.
27
27
 
28
28
  If a run fails or returns without a valid saved result, Maestro reports the error and stops. Manual follow-up is described in [Limitations](workflow.md#limitations).
29
29
 
package/docs/workflow.md CHANGED
@@ -4,15 +4,12 @@ Maestro manages one spec-driven workflow in the current Pi session. The owner wo
4
4
 
5
5
  The approved `spec.md` is the contract for the change. It defines behavior, scope, constraints, technical decisions, and acceptance criteria.
6
6
 
7
- An acceptance criterion contains a probe, an expected result and an example. The probe checks an acceptance criterion against its expected result.
7
+ An acceptance criterion contains a probe, an expected result, and an example. A probe is a scenario used to test behavior.
8
8
 
9
- An agent run result is a handoff.
10
- The handoff can contain:
11
- - Escalations: the owner have to decide implementation questions.
12
- - Findings: technical issues on the implementation
13
- - Evidences: work executed by agents
9
+ A handoff is a saved report from a builder or verifier run. It records the result, probe outcomes, and notes.
14
10
 
15
- The workflow uses files in the [project root](configuration.md#project-root).
11
+ A builder handoff can contain escalations, which are questions that need owner decisions.
12
+ A verifier handoff can contain findings, which are technical issues.
16
13
 
17
14
  ## Roles
18
15
 
@@ -50,8 +47,8 @@ flowchart TD
50
47
  verify --> findings
51
48
  findings -->|None| candidate
52
49
 
53
- buildOutcome -->|Escalation| ownerEscalation{Owner decides}
54
- ownerEscalation -->|Contract unchanged| recordEscalation[Maestro records the answer]
50
+ buildOutcome -->|Escalation| ownerEscalation{Owner decides every question}
51
+ ownerEscalation -->|Contract unchanged| recordEscalation[Maestro records all answers]
55
52
  recordEscalation --> build
56
53
  ownerEscalation -->|Contract changes| reviseSpec[Owner and Maestro revise the spec]
57
54
  reviseSpec --> approval
@@ -81,7 +78,7 @@ The default path is `.specs/<spec-id>/workflow.json`. The spec directory is [con
81
78
  | `drafting-spec` | The owner and Maestro are preparing the initial spec. |
82
79
  | `ready-for-builder` | The approved spec or recorded owner decisions permit a builder run. |
83
80
  | `builder-running` | A builder run is active. |
84
- | `escalation-decision` | The owner must decide how to handle the current escalation. |
81
+ | `escalation-decision` | The owner must decide how to handle every escalation question. |
85
82
  | `builder-failed` | The builder recorded a technical failure. The workflow stops. |
86
83
  | `ready-for-verifier` | The builder completed the work and the verifier can start. |
87
84
  | `verifier-running` | A verifier run is active. |
@@ -101,7 +98,9 @@ Approval freezes the spec as the contract. The spec and its visual prototypes re
101
98
 
102
99
  ## Acceptance criteria
103
100
 
104
- Each acceptance criterion has a unique ID and describes one observable result. It contains these parts:
101
+ Each acceptance criterion has a unique ID and describes one observable result.
102
+
103
+ Each criterion contains these parts:
105
104
 
106
105
  | Part | Content |
107
106
  |---|---|
@@ -113,19 +112,27 @@ Each acceptance criterion has a unique ID and describes one observable result. I
113
112
 
114
113
  An escalation returns an implementation decision to the owner. It does not necessarily mean that a technical failure occurred. Examples include undefined behavior, a conflict with the spec, or a possible scope change.
115
114
 
116
- Maestro presents the question, evidence, options, consequences, and next steps. The workflow pauses in `escalation-decision` until the owner decides.
115
+ 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.
116
+
117
+ Maestro presents each question, evidence, options, consequences, and next steps. The workflow pauses in `escalation-decision` while the owner decides how to proceed.
118
+
119
+ If the contract stays unchanged, the owner gives Maestro an answer and reason for every current question. The owner can select a listed option or give a different decision.
117
120
 
118
121
  | Owner choice | Result |
119
122
  |---|---|
120
- | Keep the current contract | Maestro records the answer and reason, returns to `ready-for-builder`, and starts another builder run. |
123
+ | Keep the current contract | Maestro saves all answers and reasons together in the active builder handoff, returns to `ready-for-builder`, and starts another builder run. |
121
124
  | Change the contract | The owner and Maestro revise the same spec and obtain renewed approval before another builder run. |
122
125
 
123
- The escalation file remains available as history.
126
+ Owner decisions update only the questions' `resolution` fields. The handoff's other content and earlier handoffs remain unchanged.
124
127
 
125
128
  ## Findings
126
129
 
127
130
  Every current finding requires an owner decision, regardless of severity. Maestro explains the issue, evidence, practical effect, and available choices.
128
131
 
132
+ Maestro identifies each finding with its report and finding IDs. For example, `V1/F2` means finding 2 in verifier report `V1.json`. The finding is an entry in that file's `findings` list, not a separate `F2.json` file. Finding numbers restart at `F1` in each verifier report. See [Finding references](glossary.md#finding-references) for a worked example.
133
+
134
+ Maestro records owner decisions in the same verifier report, e.g. decisions about `V1/F2` update `V1.json`, not a new `V2.json`. A new verifier result creates the next report (`V2.json`).
135
+
129
136
  | Decision | Result |
130
137
  |---|---|
131
138
  | `reject` | Records the owner's reason. If every finding is rejected, the workflow reaches `candidate-ready`. |
@@ -141,7 +148,7 @@ Contract revisions are allowed only in `escalation-decision` or `findings-decisi
141
148
 
142
149
  After review and cleanup, Maestro asks the owner to inspect the revised spec and reply `GREEN FLAG` again. Maestro then records `ready-for-builder` and starts another builder run.
143
150
 
144
- Previous escalations, findings, and handoffs remain as historical context. The revised spec is the contract for subsequent work.
151
+ Previous escalations, findings, and handoffs remain as historical context. The new (revised) spec is the contract for subsequent work.
145
152
 
146
153
  ## Verification boundary
147
154
 
@@ -157,7 +164,27 @@ The owner performs the final review and controls any later Git use, pull request
157
164
 
158
165
  ## Stored artifacts
159
166
 
160
- Maestro creates the spec directory with `spec.md`, `workflow.json`, and empty `handoffs/escalations/` and `prototypes/` directories. Builder and verifier handoff directories appear when those results are saved.
167
+ An artifact is a saved workflow file. Maestro creates the spec directory with `spec.md`, `workflow.json`, and an empty `prototypes/` directory. Builder and verifier handoff directories appear when those results are saved.
168
+
169
+ The agents submit results through Maestro tools instead of writing the reports directly. A successful submission saves the result and updates the phase in `workflow.json` before the agent returns.
170
+
171
+ Builder (`B`) and verifier (`V`) numbers count saved handoffs within one spec. Each sequence starts at 1 and advances independently. Every saved builder outcome, including escalation, creates the next `B` report. Revising the same spec keeps these sequences. A new spec starts new sequences.
172
+
173
+ Escalation (`E`) numbers identify questions within a builder handoff. They restart at `E1` in each handoff.
174
+
175
+ For example, a repair cycle with successful builder results produces these files:
176
+
177
+ | Step | Action | Report saved or updated |
178
+ |---|---|---|
179
+ | 1 | The builder completes the implementation. | Creates `handoffs/builder/B1.json`. |
180
+ | 2 | The verifier checks it and reports findings. | Creates `handoffs/verifier/V1.json`. |
181
+ | 3 | The owner decides every finding and requests a code fix. | Updates decisions in the existing `V1.json`. |
182
+ | 4 | A new builder run completes the fixes. | Creates `handoffs/builder/B2.json`. |
183
+ | 5 | A new verifier run checks the work again and reports no findings. | Creates `handoffs/verifier/V2.json`. The workflow reaches `candidate-ready`. |
184
+
185
+ If the first builder run escalates, it creates `B1.json` with its questions. Owner answers update `B1.json`. The next saved builder result creates `B2.json`.
186
+
187
+ A builder report with `status: failed` stops the workflow without a verifier run. If an agent returns without a valid saved result, Maestro stops and reports the error. See [Limitations](#limitations).
161
188
 
162
189
  The default layout after multiple runs is:
163
190
 
@@ -169,19 +196,24 @@ The default layout after multiple runs is:
169
196
  │ ├── builder/
170
197
  │ │ ├── B1.json
171
198
  │ │ └── B2.json
172
- │ ├── verifier/
173
- │ │ ├── V1.json
174
- │ │ └── V2.json
175
- │ └── escalations/
176
- │ ├── E1.json
177
- │ └── ...
199
+ │ └── verifier/
200
+ │ ├── V1.json
201
+ │ └── V2.json
178
202
  └── prototypes/
179
203
  ```
180
204
 
181
- Each new handoff gets the next number in its role's sequence. Maestro uses the latest handoff in each sequence as the active result, and earlier handoffs remain on the file system as references.
205
+ Maestro uses the latest saved handoff in each role's sequence as the active result. New results do not replace earlier numbered reports. Earlier reports remain available as context, not as proof for the current run. Owner decisions update the active builder or verifier handoff without creating another numbered report.
182
206
 
183
207
  ## Limitations
184
208
 
209
+ ### No small models
210
+ The owner must not use small models with a `low` thinking level for this workflow. These combinations cannot reliably follow the workflow rules.
211
+ One example is `gpt-luna-6` with `thinking: "low"`.
212
+
213
+ Moreover, the workflow works well with a defined harness: tests, lint for code rules, anti-slop checks for unwanted patterns, and `AGENTS.md`. Maestro does not supply these project-specific checks.
214
+
215
+ ### No automatic rollback
185
216
  Maestro provides no automatic rollback, repair, or recovery for failed or interrupted workflows. The files that remain are available for owner inspection. The owner handles the workflow manually.
186
217
 
218
+ ### No reconciliation
187
219
  Disabling Maestro, restarting Pi, or using `/resume` clears live Maestro session state and leaves project files unchanged. Maestro starts disabled in a new or resumed session. Reactivating it does not reconstruct or resume a saved workflow.
@@ -4,12 +4,10 @@
4
4
  */
5
5
 
6
6
  import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
7
- import { registerOpenEscalationTool } from '#tools/child/open-escalation.ts';
8
7
  import { registerRecordBuilderHandoffTool } from '#tools/child/record-builder-handoff.ts';
9
8
  import { registerRecordVerifierHandoffTool } from '#tools/child/record-verifier-handoff.ts';
10
9
 
11
10
  export default (pi: ExtensionAPI): void => {
12
- registerOpenEscalationTool(pi);
13
11
  registerRecordBuilderHandoffTool(pi);
14
12
  registerRecordVerifierHandoffTool(pi);
15
13
  };
@@ -18,9 +18,9 @@ import {
18
18
  registerMarkSpecReadyTool,
19
19
  } from '#tools/main/mark-spec-ready.ts';
20
20
  import {
21
- RESOLVE_ESCALATION_TOOL,
22
- registerResolveEscalationTool,
23
- } from '#tools/main/resolve-escalation.ts';
21
+ RESOLVE_ESCALATIONS_TOOL,
22
+ registerResolveEscalationsTool,
23
+ } from '#tools/main/resolve-escalations.ts';
24
24
  import {
25
25
  RESOLVE_FINDINGS_TOOL,
26
26
  registerResolveFindingsTool,
@@ -38,7 +38,7 @@ const MAIN_TOOL_NAMES: readonly string[] = [
38
38
  CREATE_SPEC_TOOL.NAME,
39
39
  MARK_SPEC_READY_TOOL.NAME,
40
40
  RUN_BUILDER_TOOL.NAME,
41
- RESOLVE_ESCALATION_TOOL.NAME,
41
+ RESOLVE_ESCALATIONS_TOOL.NAME,
42
42
  RUN_VERIFIER_TOOL.NAME,
43
43
  RESOLVE_FINDINGS_TOOL.NAME,
44
44
  ];
@@ -47,7 +47,7 @@ export default (pi: ExtensionAPI): void => {
47
47
  registerCreateSpecTool(pi);
48
48
  registerMarkSpecReadyTool(pi);
49
49
  registerRunBuilderTool(pi);
50
- registerResolveEscalationTool(pi);
50
+ registerResolveEscalationsTool(pi);
51
51
  registerRunVerifierTool(pi);
52
52
  registerResolveFindingsTool(pi);
53
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emiliosp/pi-maestro",
3
- "version": "0.6.3",
3
+ "version": "0.7.0",
4
4
  "description": "A spec-driven multiagent development workflow for Pi.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -50,9 +50,7 @@
50
50
  },
51
51
  "scripts": {
52
52
  "typecheck": "tsc --noEmit",
53
- "test": "npm run test:unit && npm run test:integration",
54
- "test:unit": "vitest run --exclude \"**/*.integration.test.ts\"",
55
- "test:integration": "vitest run --exclude \"**/*.unit.test.ts\"",
53
+ "test": "vitest run --coverage --config vitest.config.ts",
56
54
  "check": "npm run lint:fix && npm run typecheck && npm test",
57
55
  "prepublishOnly": "npm run check",
58
56
  "publish:npm": "npm publish --access public",
@@ -75,6 +73,7 @@
75
73
  "@biomejs/biome": "2.5.15",
76
74
  "@earendil-works/pi-agent-core": "1.0.3",
77
75
  "@earendil-works/pi-tui": "1.0.3",
76
+ "@vitest/coverage-v8": "5.0.3",
78
77
  "@types/node": "26.6.4",
79
78
  "oxlint": "1.87.0",
80
79
  "oxlint-anti-slop": "0.3.3",
@@ -15,7 +15,6 @@ const PATHS = {
15
15
  HANDOFFS_PATH: 'handoffs',
16
16
  BUILDER_HANDOFFS_PATH: 'handoffs/builder',
17
17
  VERIFIER_HANDOFFS_PATH: 'handoffs/verifier',
18
- ESCALATIONS_PATH: 'handoffs/escalations',
19
18
  PROTOTYPES_PATH: 'prototypes',
20
19
  } as const;
21
20
 
@@ -55,11 +54,6 @@ export type MaestroPathsInput = {
55
54
  config: MaestroConfig;
56
55
  };
57
56
 
58
- type EscalationPathInput = {
59
- specId: string;
60
- escalationNumber: number;
61
- };
62
-
63
57
  type HandoffPathInput = {
64
58
  specId: string;
65
59
  handoffPassNumber: number;
@@ -213,32 +207,6 @@ export class MaestroPaths {
213
207
  });
214
208
  }
215
209
 
216
- public getEscalationsPath(specId: string): string {
217
- assertSpecId(specId);
218
-
219
- return resolve(
220
- this.projectRoot,
221
- this.specDirectoryFromRoot,
222
- specId,
223
- PATHS.ESCALATIONS_PATH,
224
- );
225
- }
226
-
227
- public getEscalationPath({
228
- specId,
229
- escalationNumber,
230
- }: EscalationPathInput): string {
231
- assertArtifactNumber(escalationNumber);
232
- assertSpecId(specId);
233
-
234
- return resolve(
235
- this.projectRoot,
236
- this.specDirectoryFromRoot,
237
- specId,
238
- `${PATHS.ESCALATIONS_PATH}/E${escalationNumber}.json`,
239
- );
240
- }
241
-
242
210
  public getPrototypesPath(specId: string): string {
243
211
  assertSpecId(specId);
244
212
 
@@ -80,6 +80,35 @@ export function assertBuilderHandoff(
80
80
  );
81
81
  }
82
82
 
83
+ if (handoff.status === BUILDER_HANDOFF_STATUSES.ESCALATION) {
84
+ for (const [index, escalation] of handoff.escalations.entries()) {
85
+ if (escalation.id !== `E${index + 1}`) {
86
+ throw new Error('Escalation IDs must be sequential in array order.');
87
+ }
88
+
89
+ const optionIds = new Set(escalation.options.map(({ id }) => id));
90
+
91
+ if (optionIds.size !== escalation.options.length) {
92
+ throw new Error('Escalation option IDs must be unique.');
93
+ }
94
+
95
+ if (
96
+ escalation.recommendation !== null &&
97
+ !optionIds.has(escalation.recommendation.optionId)
98
+ ) {
99
+ throw new Error('Escalation recommendation references unknown option.');
100
+ }
101
+
102
+ if (
103
+ escalation.resolution !== null &&
104
+ escalation.resolution.selectedOptionId !== null &&
105
+ !optionIds.has(escalation.resolution.selectedOptionId)
106
+ ) {
107
+ throw new Error('Escalation resolution references unknown option.');
108
+ }
109
+ }
110
+ }
111
+
83
112
  if (!isValidSpecId(specId)) {
84
113
  throw new Error(`Invalid expected builder handoff spec ID: "${specId}".`);
85
114
  }