@emiliosp/pi-maestro 0.10.1 → 0.11.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/ADR.md +53 -9
- package/CHANGELOG.md +73 -33
- package/MISSION.md +4 -2
- package/README.md +29 -14
- package/ROADMAP.md +114 -85
- package/TECH_STACK.md +12 -11
- package/agents/simplifier.md +214 -0
- package/agents/verifier.md +1 -16
- package/docs/configuration.md +27 -16
- package/docs/glossary.md +41 -36
- package/docs/subagent-integration.md +23 -13
- package/docs/workflow.md +102 -71
- package/extensions/maestro-subagent.ts +3 -1
- package/extensions/maestro.ts +10 -0
- package/package.json +1 -1
- package/src/MaestroPaths.ts +4 -0
- package/src/artifacts/simplifier-handoff/assertSimplifierHandoff.ts +56 -0
- package/src/artifacts/simplifier-handoff/readSimplifierHandoff.ts +29 -0
- package/src/artifacts/simplifier-handoff/schema.ts +26 -0
- package/src/config/assertConfiguration.ts +1 -1
- package/src/config/defaults.ts +7 -0
- package/src/config/loadConfiguration.ts +1 -0
- package/src/config/schema.ts +3 -0
- package/src/maestro/checks/assertEnvironment.ts +7 -3
- package/src/maestro/instructions/getMaestroInstructions.ts +16 -6
- package/src/maestro/status/formatMaestroStatus.ts +3 -0
- package/src/tools/child/record-simplifier-handoff.ts +73 -0
- package/src/tools/main/resolve-findings.ts +1 -1
- package/src/tools/main/run-simplifier.ts +182 -0
- package/src/tools/main/run-verifier.ts +5 -5
- package/src/workflow/roles.ts +2 -1
- package/src/workflow/simplifier/completeSimplifierPass.ts +57 -0
- package/src/workflow/state/schema.ts +4 -0
- package/src/workflow/transitions.ts +9 -1
- package/src/workflow/utils/getAgentRole.ts +5 -1
|
@@ -40,7 +40,7 @@ const RunVerifierToolParameters = Type.Object(
|
|
|
40
40
|
const MILLISECONDS_PER_MINUTE = 60_000;
|
|
41
41
|
|
|
42
42
|
type VerifierTerminalPhase =
|
|
43
|
-
| typeof WORKFLOW_PHASES.
|
|
43
|
+
| typeof WORKFLOW_PHASES.SIMPLIFIER_RUNNING
|
|
44
44
|
| typeof WORKFLOW_PHASES.FINDING_DECISIONS;
|
|
45
45
|
|
|
46
46
|
type VerifierRunResult = {
|
|
@@ -62,7 +62,7 @@ const readTerminalVerifierResult = async ({
|
|
|
62
62
|
state,
|
|
63
63
|
}: ReadTerminalVerifierResultInput): Promise<VerifierRunResult> => {
|
|
64
64
|
if (
|
|
65
|
-
state.phase !== WORKFLOW_PHASES.
|
|
65
|
+
state.phase !== WORKFLOW_PHASES.SIMPLIFIER_RUNNING &&
|
|
66
66
|
state.phase !== WORKFLOW_PHASES.FINDING_DECISIONS
|
|
67
67
|
) {
|
|
68
68
|
throw new Error(
|
|
@@ -78,7 +78,7 @@ const readTerminalVerifierResult = async ({
|
|
|
78
78
|
const expectedPhase =
|
|
79
79
|
handoff.findings.length > 0
|
|
80
80
|
? WORKFLOW_PHASES.FINDING_DECISIONS
|
|
81
|
-
: WORKFLOW_PHASES.
|
|
81
|
+
: WORKFLOW_PHASES.SIMPLIFIER_RUNNING;
|
|
82
82
|
|
|
83
83
|
if (state.phase !== expectedPhase) {
|
|
84
84
|
throw new Error(
|
|
@@ -131,8 +131,8 @@ const readVerifierResult = async ({
|
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
const formatVerifierResult = (result: VerifierRunResult): string => {
|
|
134
|
-
if (result.outcome === WORKFLOW_PHASES.
|
|
135
|
-
return `Verifier completed spec ${result.specId}. The workflow is
|
|
134
|
+
if (result.outcome === WORKFLOW_PHASES.SIMPLIFIER_RUNNING) {
|
|
135
|
+
return `Verifier completed spec ${result.specId}. The workflow is simplifier-running. Call maestro_run_simplifier next with this specId, without another approval or verifier pass.`;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
return `Verifier found ${result.handoff.findings.length} finding(s) for spec ${result.specId}. The workflow is waiting for owner decisions.`;
|
package/src/workflow/roles.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Objective: Define the roles used by the Maestro workflow.
|
|
3
|
-
* Used: When workflow code identifies
|
|
3
|
+
* Used: When workflow code identifies agent responsibilities.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export const WORKFLOW_ROLES = {
|
|
7
7
|
BUILDER: 'builder',
|
|
8
8
|
VERIFIER: 'verifier',
|
|
9
|
+
SIMPLIFIER: 'simplifier',
|
|
9
10
|
} as const;
|
|
10
11
|
|
|
11
12
|
export type WorkflowRole = (typeof WORKFLOW_ROLES)[keyof typeof WORKFLOW_ROLES];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Objective: Save a validated simplifier handoff before completing the workflow.
|
|
3
|
+
* Used: When the simplifier records its single result.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { mkdir } from 'node:fs/promises';
|
|
7
|
+
import { dirname } from 'node:path';
|
|
8
|
+
import { assertSimplifierHandoff } from '#artifacts/simplifier-handoff/assertSimplifierHandoff.ts';
|
|
9
|
+
import type { MaestroPaths } from '#MaestroPaths.ts';
|
|
10
|
+
import { writeJson } from '#utils/write-json.ts';
|
|
11
|
+
import { readWorkflowState } from '#workflow/state/readWorkflowState.ts';
|
|
12
|
+
import { WORKFLOW_EVENTS, WORKFLOW_PHASES } from '#workflow/state/schema.ts';
|
|
13
|
+
import { writeWorkflowState } from '#workflow/state/writeWorkflowState.ts';
|
|
14
|
+
import { transitionWorkflow } from '#workflow/transitions.ts';
|
|
15
|
+
|
|
16
|
+
type CompleteSimplifierPassInput = {
|
|
17
|
+
paths: MaestroPaths;
|
|
18
|
+
specId: string;
|
|
19
|
+
handoff: unknown;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const completeSimplifierPass = async ({
|
|
23
|
+
paths,
|
|
24
|
+
specId,
|
|
25
|
+
handoff,
|
|
26
|
+
}: CompleteSimplifierPassInput) => {
|
|
27
|
+
const workflowPath = paths.getWorkflowPath(specId);
|
|
28
|
+
const state = await readWorkflowState(workflowPath);
|
|
29
|
+
|
|
30
|
+
if (state.specId !== specId) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Workflow spec ID mismatch: expected "${specId}", found "${state.specId}".`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (state.phase !== WORKFLOW_PHASES.SIMPLIFIER_RUNNING) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Simplifier handoff requires simplifier-running state, found "${state.phase}".`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const input = { handoff, specId, projectRoot: paths.getProjectRoot() };
|
|
43
|
+
assertSimplifierHandoff(input);
|
|
44
|
+
|
|
45
|
+
const handoffPath = paths.getSimplifierHandoffPath(specId);
|
|
46
|
+
await mkdir(dirname(handoffPath), { recursive: true });
|
|
47
|
+
await writeJson({ path: handoffPath, data: input.handoff });
|
|
48
|
+
|
|
49
|
+
const nextState = transitionWorkflow({
|
|
50
|
+
state,
|
|
51
|
+
event: WORKFLOW_EVENTS.SIMPLIFIER_DONE,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
await writeWorkflowState({ path: workflowPath, state: nextState });
|
|
55
|
+
|
|
56
|
+
return { handoff: input.handoff, handoffPath, state: nextState };
|
|
57
|
+
};
|
|
@@ -17,6 +17,7 @@ export const WORKFLOW_PHASES = {
|
|
|
17
17
|
READY_FOR_VERIFIER: 'ready-for-verifier',
|
|
18
18
|
VERIFIER_RUNNING: 'verifier-running',
|
|
19
19
|
FINDING_DECISIONS: 'finding-decisions',
|
|
20
|
+
SIMPLIFIER_RUNNING: 'simplifier-running',
|
|
20
21
|
CANDIDATE_READY: 'candidate-ready',
|
|
21
22
|
} as const;
|
|
22
23
|
|
|
@@ -30,6 +31,8 @@ export const WORKFLOW_EVENTS = {
|
|
|
30
31
|
RUN_VERIFIER: 'run-verifier',
|
|
31
32
|
VERIFIER_FOUND_FINDINGS: 'verifier-found-findings',
|
|
32
33
|
VERIFIER_DONE: 'verifier-done',
|
|
34
|
+
SIMPLIFIER_DONE: 'simplifier-done',
|
|
35
|
+
SIMPLIFIER_SKIPPED: 'simplifier-skipped',
|
|
33
36
|
OWNER_REJECT_FINDINGS: 'owner-reject-findings',
|
|
34
37
|
OWNER_REQUEST_FIXES: 'owner-request-fixes',
|
|
35
38
|
} as const;
|
|
@@ -42,6 +45,7 @@ export const WorkflowPhaseSchema = Type.Union([
|
|
|
42
45
|
Type.Literal(WORKFLOW_PHASES.READY_FOR_VERIFIER),
|
|
43
46
|
Type.Literal(WORKFLOW_PHASES.VERIFIER_RUNNING),
|
|
44
47
|
Type.Literal(WORKFLOW_PHASES.FINDING_DECISIONS),
|
|
48
|
+
Type.Literal(WORKFLOW_PHASES.SIMPLIFIER_RUNNING),
|
|
45
49
|
Type.Literal(WORKFLOW_PHASES.CANDIDATE_READY),
|
|
46
50
|
]);
|
|
47
51
|
|
|
@@ -55,10 +55,18 @@ export const WORKFLOW_TRANSITIONS: Record<WorkflowEvent, WorkflowTransition> = {
|
|
|
55
55
|
},
|
|
56
56
|
[WORKFLOW_EVENTS.VERIFIER_DONE]: {
|
|
57
57
|
from: [WORKFLOW_PHASES.VERIFIER_RUNNING],
|
|
58
|
-
to: WORKFLOW_PHASES.
|
|
58
|
+
to: WORKFLOW_PHASES.SIMPLIFIER_RUNNING,
|
|
59
59
|
},
|
|
60
60
|
[WORKFLOW_EVENTS.OWNER_REJECT_FINDINGS]: {
|
|
61
61
|
from: [WORKFLOW_PHASES.FINDING_DECISIONS],
|
|
62
|
+
to: WORKFLOW_PHASES.SIMPLIFIER_RUNNING,
|
|
63
|
+
},
|
|
64
|
+
[WORKFLOW_EVENTS.SIMPLIFIER_DONE]: {
|
|
65
|
+
from: [WORKFLOW_PHASES.SIMPLIFIER_RUNNING],
|
|
66
|
+
to: WORKFLOW_PHASES.CANDIDATE_READY,
|
|
67
|
+
},
|
|
68
|
+
[WORKFLOW_EVENTS.SIMPLIFIER_SKIPPED]: {
|
|
69
|
+
from: [WORKFLOW_PHASES.SIMPLIFIER_RUNNING],
|
|
62
70
|
to: WORKFLOW_PHASES.CANDIDATE_READY,
|
|
63
71
|
},
|
|
64
72
|
[WORKFLOW_EVENTS.OWNER_REQUEST_FIXES]: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Objective: Resolve the agent responsible for a workflow phase.
|
|
3
|
-
* Used: When workflow logic maps persisted phases to
|
|
3
|
+
* Used: When workflow logic maps persisted phases to agent roles.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { WorkflowRole } from '#workflow/roles.ts';
|
|
@@ -29,5 +29,9 @@ export const getAgentRole = (
|
|
|
29
29
|
return WORKFLOW_ROLES.VERIFIER;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
if (phase === WORKFLOW_PHASES.SIMPLIFIER_RUNNING) {
|
|
33
|
+
return WORKFLOW_ROLES.SIMPLIFIER;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
return null;
|
|
33
37
|
};
|