@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.
Files changed (35) hide show
  1. package/ADR.md +53 -9
  2. package/CHANGELOG.md +73 -33
  3. package/MISSION.md +4 -2
  4. package/README.md +29 -14
  5. package/ROADMAP.md +114 -85
  6. package/TECH_STACK.md +12 -11
  7. package/agents/simplifier.md +214 -0
  8. package/agents/verifier.md +1 -16
  9. package/docs/configuration.md +27 -16
  10. package/docs/glossary.md +41 -36
  11. package/docs/subagent-integration.md +23 -13
  12. package/docs/workflow.md +102 -71
  13. package/extensions/maestro-subagent.ts +3 -1
  14. package/extensions/maestro.ts +10 -0
  15. package/package.json +1 -1
  16. package/src/MaestroPaths.ts +4 -0
  17. package/src/artifacts/simplifier-handoff/assertSimplifierHandoff.ts +56 -0
  18. package/src/artifacts/simplifier-handoff/readSimplifierHandoff.ts +29 -0
  19. package/src/artifacts/simplifier-handoff/schema.ts +26 -0
  20. package/src/config/assertConfiguration.ts +1 -1
  21. package/src/config/defaults.ts +7 -0
  22. package/src/config/loadConfiguration.ts +1 -0
  23. package/src/config/schema.ts +3 -0
  24. package/src/maestro/checks/assertEnvironment.ts +7 -3
  25. package/src/maestro/instructions/getMaestroInstructions.ts +16 -6
  26. package/src/maestro/status/formatMaestroStatus.ts +3 -0
  27. package/src/tools/child/record-simplifier-handoff.ts +73 -0
  28. package/src/tools/main/resolve-findings.ts +1 -1
  29. package/src/tools/main/run-simplifier.ts +182 -0
  30. package/src/tools/main/run-verifier.ts +5 -5
  31. package/src/workflow/roles.ts +2 -1
  32. package/src/workflow/simplifier/completeSimplifierPass.ts +57 -0
  33. package/src/workflow/state/schema.ts +4 -0
  34. package/src/workflow/transitions.ts +9 -1
  35. 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.CANDIDATE_READY
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.CANDIDATE_READY &&
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.CANDIDATE_READY;
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.CANDIDATE_READY) {
135
- return `Verifier completed spec ${result.specId}. The workflow is candidate-ready.`;
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.`;
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Objective: Define the roles used by the Maestro workflow.
3
- * Used: When workflow code identifies builder and verifier responsibilities.
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.CANDIDATE_READY,
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 builder or verifier roles.
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
  };