maestro-flow 0.3.9 → 0.3.10

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 (125) hide show
  1. package/.claude/commands/maestro-analyze.md +46 -3
  2. package/.claude/commands/maestro-execute.md +14 -0
  3. package/.claude/commands/maestro-plan.md +16 -0
  4. package/.claude/commands/manage-harvest.md +1 -1
  5. package/.claude/commands/manage-issue-discover.md +2 -2
  6. package/.claude/commands/manage-issue.md +3 -3
  7. package/.codex/skills/maestro/SKILL.md +463 -0
  8. package/.codex/skills/maestro-analyze/SKILL.md +28 -7
  9. package/.codex/skills/maestro-chain/SKILL.md +248 -0
  10. package/.codex/skills/maestro-coordinate/SKILL.md +279 -224
  11. package/.codex/skills/maestro-execute/SKILL.md +8 -0
  12. package/.codex/skills/maestro-plan/SKILL.md +9 -1
  13. package/README.md +7 -7
  14. package/README.zh-CN.md +7 -7
  15. package/chains/issue-lifecycle.json +13 -13
  16. package/chains/singles/issue-analyze.json +3 -3
  17. package/chains/singles/issue-execute.json +3 -3
  18. package/chains/singles/issue-plan.json +3 -3
  19. package/dashboard/dist-server/dashboard/src/server/commander/commander-agent.js +2 -2
  20. package/dashboard/dist-server/dashboard/src/server/commander/commander-agent.js.map +1 -1
  21. package/dashboard/dist-server/dashboard/src/server/coordinator/chain-map.js +3 -3
  22. package/dashboard/dist-server/dashboard/src/server/coordinator/chain-map.js.map +1 -1
  23. package/dashboard/dist-server/dashboard/src/server/routes/issues.js +34 -0
  24. package/dashboard/dist-server/dashboard/src/server/routes/issues.js.map +1 -1
  25. package/dashboard/dist-server/dashboard/src/server/ws/handlers/execution-handler.js +2 -3
  26. package/dashboard/dist-server/dashboard/src/server/ws/handlers/execution-handler.js.map +1 -1
  27. package/dashboard/dist-server/dashboard/src/shared/issue-types.d.ts +5 -0
  28. package/dashboard/dist-server/dashboard/src/shared/issue-types.js.map +1 -1
  29. package/dashboard/dist-server/dashboard/src/shared/normalize-task.d.ts +2 -0
  30. package/dashboard/dist-server/dashboard/src/shared/normalize-task.js +75 -0
  31. package/dashboard/dist-server/dashboard/src/shared/normalize-task.js.map +1 -0
  32. package/dashboard/dist-server/src/hooks/constants.d.ts +90 -12
  33. package/dashboard/dist-server/src/hooks/constants.js +149 -16
  34. package/dashboard/dist-server/src/hooks/constants.js.map +1 -1
  35. package/dashboard/dist-server/src/types/index.d.ts +5 -0
  36. package/dist/src/commands/collab.d.ts +1 -34
  37. package/dist/src/commands/collab.d.ts.map +1 -1
  38. package/dist/src/commands/collab.js +4 -72
  39. package/dist/src/commands/collab.js.map +1 -1
  40. package/dist/src/commands/hooks.d.ts +5 -1
  41. package/dist/src/commands/hooks.d.ts.map +1 -1
  42. package/dist/src/commands/hooks.js +50 -10
  43. package/dist/src/commands/hooks.js.map +1 -1
  44. package/dist/src/commands/install-ui/InstallConfirm.d.ts +3 -1
  45. package/dist/src/commands/install-ui/InstallConfirm.d.ts.map +1 -1
  46. package/dist/src/commands/install-ui/InstallConfirm.js +3 -1
  47. package/dist/src/commands/install-ui/InstallConfirm.js.map +1 -1
  48. package/dist/src/commands/install-ui/InstallExecution.d.ts.map +1 -1
  49. package/dist/src/commands/install-ui/InstallExecution.js +5 -1
  50. package/dist/src/commands/install-ui/InstallExecution.js.map +1 -1
  51. package/dist/src/commands/install-ui/InstallFlow.d.ts.map +1 -1
  52. package/dist/src/commands/install-ui/InstallFlow.js +7 -3
  53. package/dist/src/commands/install-ui/InstallFlow.js.map +1 -1
  54. package/dist/src/commands/install-ui/StatuslineConfig.d.ts +6 -1
  55. package/dist/src/commands/install-ui/StatuslineConfig.d.ts.map +1 -1
  56. package/dist/src/commands/install-ui/StatuslineConfig.js +27 -5
  57. package/dist/src/commands/install-ui/StatuslineConfig.js.map +1 -1
  58. package/dist/src/hooks/__tests__/statusline-visual-test.d.ts +7 -0
  59. package/dist/src/hooks/__tests__/statusline-visual-test.d.ts.map +1 -0
  60. package/dist/src/hooks/__tests__/statusline-visual-test.js +236 -0
  61. package/dist/src/hooks/__tests__/statusline-visual-test.js.map +1 -0
  62. package/dist/src/hooks/constants.d.ts +90 -12
  63. package/dist/src/hooks/constants.d.ts.map +1 -1
  64. package/dist/src/hooks/constants.js +149 -16
  65. package/dist/src/hooks/constants.js.map +1 -1
  66. package/dist/src/hooks/guards/index.d.ts +1 -0
  67. package/dist/src/hooks/guards/index.d.ts.map +1 -1
  68. package/dist/src/hooks/guards/index.js +1 -0
  69. package/dist/src/hooks/guards/index.js.map +1 -1
  70. package/dist/src/hooks/guards/preflight-guard.d.ts +29 -0
  71. package/dist/src/hooks/guards/preflight-guard.d.ts.map +1 -0
  72. package/dist/src/hooks/guards/preflight-guard.js +95 -0
  73. package/dist/src/hooks/guards/preflight-guard.js.map +1 -0
  74. package/dist/src/hooks/index.d.ts +1 -0
  75. package/dist/src/hooks/index.d.ts.map +1 -1
  76. package/dist/src/hooks/index.js +1 -0
  77. package/dist/src/hooks/index.js.map +1 -1
  78. package/dist/src/hooks/preflight-core.d.ts +37 -0
  79. package/dist/src/hooks/preflight-core.d.ts.map +1 -0
  80. package/dist/src/hooks/preflight-core.js +86 -0
  81. package/dist/src/hooks/preflight-core.js.map +1 -0
  82. package/dist/src/hooks/statusline.d.ts +8 -17
  83. package/dist/src/hooks/statusline.d.ts.map +1 -1
  84. package/dist/src/hooks/statusline.js +269 -112
  85. package/dist/src/hooks/statusline.js.map +1 -1
  86. package/dist/src/i18n/locales/en.d.ts.map +1 -1
  87. package/dist/src/i18n/locales/en.js +5 -0
  88. package/dist/src/i18n/locales/en.js.map +1 -1
  89. package/dist/src/i18n/locales/zh.d.ts.map +1 -1
  90. package/dist/src/i18n/locales/zh.js +5 -0
  91. package/dist/src/i18n/locales/zh.js.map +1 -1
  92. package/dist/src/i18n/types.d.ts +5 -0
  93. package/dist/src/i18n/types.d.ts.map +1 -1
  94. package/dist/src/tools/collab-adapter.d.ts +17 -0
  95. package/dist/src/tools/collab-adapter.d.ts.map +1 -1
  96. package/dist/src/tools/collab-adapter.js +138 -0
  97. package/dist/src/tools/collab-adapter.js.map +1 -1
  98. package/dist/src/tools/merge-validator.d.ts +24 -0
  99. package/dist/src/tools/merge-validator.d.ts.map +1 -0
  100. package/dist/src/tools/merge-validator.js +220 -0
  101. package/dist/src/tools/merge-validator.js.map +1 -0
  102. package/dist/src/types/index.d.ts +5 -0
  103. package/dist/src/types/index.d.ts.map +1 -1
  104. package/package.json +1 -1
  105. package/templates/cli/prompts/workflow-skill-conflict-patterns.txt +3 -3
  106. package/templates/cli/prompts/workflow-skill-lessons-learned.txt +3 -3
  107. package/templates/search-tools.md +1 -1
  108. package/workflows/cli-tools-usage.md +44 -27
  109. package/workflows/delegate-usage.md +3 -3
  110. package/workflows/issue-analyze.md +6 -2
  111. package/workflows/issue-discover.md +4 -4
  112. package/workflows/issue-execute.md +6 -3
  113. package/workflows/issue-plan.md +5 -2
  114. package/workflows/maestro-coordinate.codex.md +281 -470
  115. package/workflows/maestro-coordinate.md +14 -14
  116. package/workflows/maestro-link-coordinate.md +2 -2
  117. package/workflows/maestro.codex.md +710 -0
  118. package/workflows/maestro.md +10 -11
  119. package/workflows/retrospective.md +1 -1
  120. package/.claude/commands/manage-issue-analyze.md +0 -62
  121. package/.claude/commands/manage-issue-execute.md +0 -73
  122. package/.claude/commands/manage-issue-plan.md +0 -62
  123. package/.codex/skills/manage-issue-analyze/SKILL.md +0 -207
  124. package/.codex/skills/manage-issue-execute/SKILL.md +0 -200
  125. package/.codex/skills/manage-issue-plan/SKILL.md +0 -186
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  name: maestro-coordinate
3
- description: Team-agent pipeline coordinator — classifies intent, maps to skill chain, spawns one agent per step whose prompt contains the skill invocation ($skill-name "intent"). Step results propagate as context to each successor. Session state at .workflow/.maestro-coordinate/{session-id}/state.json.
4
- argument-hint: "\"intent text\" [-y] [-c|--continue] [--dry-run] [--chain <name>]"
5
- allowed-tools: spawn_agent, wait_agent, send_message, close_agent, Read, Write, Bash, Glob, Grep
3
+ description: CLI-based coordinator — analyze intent select command chain execute sequentially via codex delegate with auto-confirm. Async state machine with template-driven prompts and gemini analysis between steps.
4
+ argument-hint: "\"intent text\" [-y] [-c] [--dry-run] [--chain <name>] [--tool <tool>]"
5
+ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
6
6
  ---
7
7
 
8
8
  ## Auto Mode
9
9
 
10
- When `-y` or `--yes`: Skip clarification and confirmation prompts. Pass `-y` through to each step's skill invocation.
10
+ When `-y` or `--yes`: Skip clarification and confirmation prompts. Auto-confirm all delegate executions.
11
11
 
12
- # Maestro Coordinate
12
+ # Maestro Coordinate (CLI Delegate)
13
13
 
14
14
  ## Usage
15
15
 
@@ -19,13 +19,15 @@ $maestro-coordinate -y "refactor the payment module"
19
19
  $maestro-coordinate --continue
20
20
  $maestro-coordinate --dry-run "add rate limiting to API endpoints"
21
21
  $maestro-coordinate --chain feature "add dark mode toggle"
22
+ $maestro-coordinate --tool gemini "fix auth regression"
22
23
  ```
23
24
 
24
25
  **Flags**:
25
- - `-y, --yes` — Auto mode: skip all prompts; propagate `-y` to each skill
26
- - `--continue` — Resume latest paused session from last incomplete step
27
- - `--dry-run` — Display planned chain without spawning any agents
26
+ - `-y, --yes` — Auto mode: skip all prompts, inject auto-confirm into delegates
27
+ - `-c, --continue` — Resume previous session from last incomplete step
28
+ - `--dry-run` — Show planned chain without executing
28
29
  - `--chain <name>` — Force a specific chain (skips intent classification)
30
+ - `--tool <tool>` — CLI tool override (default: codex)
29
31
 
30
32
  **Session state**: `.workflow/.maestro-coordinate/{session-id}/state.json`
31
33
 
@@ -33,292 +35,345 @@ $maestro-coordinate --chain feature "add dark mode toggle"
33
35
 
34
36
  ## Overview
35
37
 
36
- Sequential pipeline coordinator (Pattern 2.5). Each chain step is one `spawn_agent` whose message contains a `$skill-name "intent"` invocation together with context accumulated from prior steps. The agent executes the skill and returns structured findings; those findings are injected into the next step's spawn message as `## Context from Previous Steps`.
38
+ Sequential CLI-delegate coordinator. Each chain step is executed via `codex delegate "prompt" --to <tool> --mode write` with a template-driven prompt. After each step completes, a gemini analysis evaluates output quality and generates optimization hints for subsequent steps. All execution is background-async with hook callbacks.
37
39
 
38
40
  ```
39
- Intent → Resolve Chain → Step 1 → Step 2 → Step N → Report
40
- (chainMap) spawn spawn spawn
41
- wait wait wait
42
- close close close
43
- │ │ │
44
- findings → prev_context → prev_context
41
+ Intent → Resolve Chain → Step 1 → Analysis → Step 2 → Analysis → Report
42
+ (chainMap) delegate gemini delegate gemini
43
+ callback callback callback callback
45
44
  ```
46
45
 
47
46
  ---
48
47
 
49
- ## Chain Map
50
-
51
- | Intent keywords | Chain | Steps (skills, in order) |
52
- |----------------|-------|--------------------------|
53
- | fix, bug, error, broken, crash | `quality-fix` | $manage-issue-analyze → $manage-issue-execute → $maestro-verify |
54
- | test, spec, coverage | `quality-test` | $quality-test |
55
- | refactor, cleanup, debt | `quality-refactor` | $quality-refactor |
56
- | feature, implement, add, build | `feature` | $maestro-plan → $maestro-execute → $maestro-verify |
57
- | review, check, audit | `quality-review` | $quality-review |
58
- | deploy, release, ship | `deploy` | $maestro-verify → $maestro-execute |
59
-
60
- ---
61
-
62
48
  ## Implementation
63
49
 
64
50
  > **Full implementation reference**: The complete `detectTaskType`, `detectNextAction`, and `chainMap` definitions (35+ intent patterns, 40+ chain types) are in `~/.maestro/workflows/maestro-coordinate.codex.md`. Read that file for authoritative logic before executing any step.
65
51
 
66
- ### Session Initialization
52
+ <required_reading>
53
+ @~/.maestro/workflows/maestro-coordinate.codex.md
54
+ </required_reading>
55
+
56
+ <deferred_reading>
57
+ - [coordinate template](~/.maestro/templates/cli/prompts/coordinate-step.txt) — read when filling step prompts
58
+ </deferred_reading>
59
+
60
+ ### Step 1: Parse Arguments
67
61
 
68
62
  ```javascript
69
- const dateStr = new Date().toISOString().substring(0, 10).replace(/-/g, '')
70
- const timeStr = new Date().toISOString().substring(11, 19).replace(/:/g, '')
71
- const sessionId = `MCC-${dateStr}-${timeStr}`
72
- const sessionDir = `.workflow/.maestro-coordinate/${sessionId}`
73
-
74
- Bash(`mkdir -p ${sessionDir}`)
75
-
76
- functions.update_plan({
77
- explanation: "Starting coordinate session",
78
- plan: [
79
- { step: "Phase 1: Resolve intent and chain", status: "in_progress" },
80
- { step: "Phase 2: Execute steps (pipeline)", status: "pending" },
81
- { step: "Phase 3: Completion report", status: "pending" }
82
- ]
83
- })
63
+ const args = $ARGUMENTS.trim();
64
+ const AUTO_YES = /\b(-y|--yes)\b/.test(args);
65
+ const RESUME = /\b(-c|--continue)\b/.test(args);
66
+ const DRY_RUN = /\b--dry-run\b/.test(args);
67
+ const forcedChain = args.match(/--chain\s+(\S+)/)?.[1] || null;
68
+ const cliTool = args.match(/--tool\s+(\S+)/)?.[1] || 'codex';
69
+ const intent = args
70
+ .replace(/\b(-y|--yes|-c|--continue|--dry-run)\b/g, '')
71
+ .replace(/--(chain|tool)\s+\S+/g, '')
72
+ .trim();
84
73
  ```
85
74
 
86
- ### Phase 1: Resolve Intent and Chain
75
+ **If RESUME:**
76
+ 1. Find latest `state.json` in `.workflow/.maestro-coordinate/`
77
+ 2. Load state → set `current_step` to first non-completed step
78
+ 3. Jump to **Step 6**
87
79
 
88
- **`--continue` mode**: Glob `.workflow/.maestro-coordinate/MCC-*/state.json` sorted by name desc; load the most recent; skip to Phase 2 at the first step where `status === "pending"`.
80
+ ---
89
81
 
90
- **Fresh mode**:
82
+ ### Step 2: Read Project State
91
83
 
92
- 1. Read `.workflow/state.json` for project context (`current_phase`, `workflow_name`)
93
- 2. If `--chain` is given, use it directly
94
- 3. Otherwise, classify intent with keyword heuristics (see Chain Map above)
95
- 4. If no keyword matches and not `AUTO_YES`: ask one clarifying question via `functions.request_user_input`
96
- 5. Resolve the chain's skill list from Chain Map
97
- 6. Write `state.json`:
84
+ Read `.workflow/state.json` + `.workflow/roadmap.md` + current phase `index.json`.
98
85
 
99
- ```javascript
100
- Write(`${sessionDir}/state.json`, JSON.stringify({
101
- id: sessionId,
102
- intent,
103
- chain: resolvedChain,
104
- auto_yes: AUTO_YES,
105
- status: "in_progress",
106
- started_at: new Date().toISOString(),
107
- steps: CHAIN_MAP[resolvedChain].map((skill, i) => ({
108
- step_n: i + 1,
109
- skill,
110
- status: "pending",
111
- findings: null,
112
- quality_score: null,
113
- hints_for_next: null
114
- }))
115
- }, null, 2))
116
- ```
86
+ **If missing:** `projectState = { initialized: false }`. If intent also empty → Error E001.
87
+
88
+ ---
89
+
90
+ ### Step 3: Classify Intent & Select Chain
91
+
92
+ Follow `~/.maestro/workflows/maestro-coordinate.md` Steps 3a–3d exactly:
93
+ - Exact-match keywords (fast path)
94
+ - Structured intent extraction (action × object matrix)
95
+ - State-based routing for `state_continue`
96
+ - Chain map lookup
97
+ - Phase/issue ID resolution
98
+
99
+ If clarity < 2 and not AUTO_YES: clarify via AskUserQuestion (max 2 rounds).
100
+
101
+ ---
117
102
 
118
- **`--dry-run`**: Display the chain plan and stop — no agents spawned.
103
+ ### Step 4: Confirm
104
+
105
+ **If `DRY_RUN`:** Display chain and exit.
119
106
 
120
107
  ```
121
- Chain: <resolvedChain>
122
- Steps:
123
- 1. <skill-1>
124
- 2. <skill-2>
125
- 3. <skill-3>
108
+ MAESTRO-COORDINATE: {chain_name} (dry run)
109
+ 1. [{cmd}] {args}
110
+ 2. [{cmd}] {args}
126
111
  ```
127
112
 
128
- **User confirmation** (skip if `AUTO_YES`): Display the plan above and prompt `Proceed? (yes/no)`.
113
+ **If not AUTO_YES:** AskUserQuestion Execute / Execute from step N / Cancel.
114
+
115
+ ---
116
+
117
+ ### Step 5: Setup Session
129
118
 
130
119
  ```javascript
131
- functions.update_plan({
132
- explanation: "Chain resolved, starting pipeline",
133
- plan: [
134
- { step: "Phase 1: Resolve intent and chain", status: "completed" },
135
- { step: "Phase 2: Execute steps (pipeline)", status: "in_progress" },
136
- { step: "Phase 3: Completion report", status: "pending" }
137
- ]
138
- })
120
+ const sessionId = `coord-${new Date().toISOString().replace(/[-:T]/g, '').slice(0, 15)}`;
121
+ const sessionDir = `.workflow/.maestro-coordinate/${sessionId}`;
122
+ Bash(`mkdir -p "${sessionDir}"`);
123
+
124
+ const state = {
125
+ session_id: sessionId, status: 'running',
126
+ created_at: new Date().toISOString(),
127
+ intent, task_type: taskType, chain_name: chainName,
128
+ tool: cliTool, auto_mode: AUTO_YES, phase: resolvedPhase,
129
+ current_step: 0,
130
+ gemini_session_id: null,
131
+ step_analyses: [],
132
+ steps: chain.map((s, i) => ({
133
+ index: i, cmd: s.cmd, args: s.args || '',
134
+ status: 'pending', exec_id: null, analysis: null
135
+ }))
136
+ };
137
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
139
138
  ```
140
139
 
141
140
  ---
142
141
 
143
- ### Phase 2: Execute Steps (Pipeline)
142
+ ### Step 6: Execute Step via codex delegate
144
143
 
145
- Sequential loop each step spawns one agent, waits for it, extracts findings, then closes it before spawning the next.
144
+ #### 6a: Assemble args
146
145
 
147
146
  ```javascript
148
- let prevContext = '' // accumulates across steps
149
-
150
- for (const step of state.steps.filter(s => s.status === 'pending')) {
151
- const skillFlag = AUTO_YES ? `-y` : ''
152
-
153
- // Assemble the agent prompt with the skill invocation embedded
154
- const stepPrompt = buildStepPrompt({
155
- step,
156
- totalSteps: state.steps.length,
157
- chain: state.chain,
158
- intent: state.intent,
159
- prevContext,
160
- skillFlag,
161
- sessionDir
162
- })
163
-
164
- // Spawn step agent
165
- const agent = spawn_agent({ message: stepPrompt })
166
-
167
- // Wait — initial spawn: 30 min
168
- let result = wait_agent({ timeout_ms: 1800000 })
169
- if (result.timed_out) {
170
- // Step 1: Status probe (non-interrupting, 3 min)
171
- followup_task({ target: agent, message: "STATUS_CHECK: Report current progress, findings so far, and estimated remaining work." })
172
- const status = wait_agent({ timeout_ms: 180000 })
173
- if (status.timed_out) {
174
- // Step 2: Force finalize (interrupt, 3 min)
175
- followup_task({ target: agent, message: "FINALIZE: Output all current findings immediately. Time limit reached.", interrupt: true })
176
- const forced = wait_agent({ timeout_ms: 180000 })
177
- if (forced.timed_out) {
178
- // Step 3: Abort
179
- close_agent({ target: agent })
180
- } else {
181
- result = forced
182
- }
183
- } else {
184
- result = status
185
- }
186
- }
187
-
188
- // Parse structured output from agent
189
- const output = parseLastJSON(result.status[agent].completed) ?? {
190
- quality_score: null,
191
- findings: result.status[agent].completed?.slice(-500) ?? "(no output)",
192
- hints_for_next: ""
193
- }
194
-
195
- close_agent({ target: agent })
196
-
197
- // Persist step result
198
- step.status = result.timed_out ? "failed" : "completed"
199
- step.findings = output.findings
200
- step.quality_score = output.quality_score
201
- step.hints_for_next = output.hints_for_next
202
- step.completed_at = new Date().toISOString()
203
- Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2))
204
-
205
- // Build prev_context for next step
206
- prevContext += `\n\n## Step ${step.step_n}: ${step.skill}\nFindings: ${step.findings}\nHints: ${step.hints_for_next ?? ''}`
207
-
208
- // Abort on failure — mark remaining steps as skipped
209
- if (step.status === "failed") {
210
- state.steps
211
- .filter(s => s.status === 'pending')
212
- .forEach(s => { s.status = 'skipped'; s.findings = `Blocked: step ${step.step_n} (${step.skill}) failed` })
213
- state.status = "aborted"
214
- Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2))
215
- break
147
+ const AUTO_FLAG_MAP = {
148
+ 'maestro-analyze': '-y', 'maestro-brainstorm': '-y', 'maestro-ui-design': '-y',
149
+ 'maestro-plan': '--auto', 'maestro-spec-generate': '-y', 'quality-test': '--auto-fix',
150
+ 'quality-retrospective': '--auto-yes',
151
+ };
152
+
153
+ function assembleArgs(step) {
154
+ let a = (step.args || '')
155
+ .replace(/\{phase\}/g, context.current_phase || '')
156
+ .replace(/\{description\}/g, context.user_intent || '')
157
+ .replace(/\{issue_id\}/g, context.issue_id || '')
158
+ .replace(/\{spec_session_id\}/g, context.spec_session_id || '')
159
+ .replace(/\{scratch_dir\}/g, context.scratch_dir || '');
160
+ if (state.auto_mode) {
161
+ const flag = AUTO_FLAG_MAP[step.cmd];
162
+ if (flag && !a.includes(flag)) a = a ? `${a} ${flag}` : flag;
216
163
  }
164
+ return a.trim();
217
165
  }
218
166
  ```
219
167
 
220
- ---
168
+ #### 6b: Build prompt from template
221
169
 
222
- #### Step Agent Prompt Template (`buildStepPrompt`)
170
+ Read `~/.maestro/templates/cli/prompts/coordinate-step.txt`, fill placeholders.
171
+ If previous step has analysis hints, inject them as `{{ANALYSIS_HINTS}}`.
223
172
 
224
- The assembled prompt embeds the skill call so the agent knows exactly what to invoke:
173
+ ```javascript
174
+ function escapeForShell(str) { return "'" + str.replace(/'/g, "'\\''") + "'"; }
175
+
176
+ const assembledArgs = assembleArgs(step);
177
+ const template = Read('~/.maestro/templates/cli/prompts/coordinate-step.txt');
178
+
179
+ let analysisHints = '';
180
+ const prevAnalysis = (state.step_analyses || []).find(a => a.step_index === state.current_step - 1);
181
+ if (prevAnalysis?.next_step_hints) {
182
+ const h = prevAnalysis.next_step_hints;
183
+ const parts = [];
184
+ if (h.prompt_additions) parts.push(h.prompt_additions);
185
+ if (h.cautions?.length) parts.push('Cautions: ' + h.cautions.join('; '));
186
+ if (h.context_to_carry) parts.push('Context from prior step: ' + h.context_to_carry);
187
+ if (parts.length) analysisHints = parts.join('\n');
188
+ }
189
+
190
+ const prompt = template
191
+ .replace('{{COMMAND}}', `/${step.cmd}`)
192
+ .replace('{{ARGS}}', assembledArgs)
193
+ .replace('{{STEP_N}}', `${state.current_step + 1}/${state.steps.length}`)
194
+ .replace('{{AUTO_DIRECTIVE}}', state.auto_mode ? 'Auto-confirm all prompts. No interactive questions.' : '')
195
+ .replace('{{CHAIN_NAME}}', state.chain_name)
196
+ .replace('{{ANALYSIS_HINTS}}', analysisHints);
197
+ ```
225
198
 
199
+ #### 6c: Launch via codex delegate
200
+
201
+ ```
202
+ ------------------------------------------------------------
203
+ STEP {i+1}/{total}: {step.cmd} | Tool: {cliTool}
204
+ ------------------------------------------------------------
226
205
  ```
227
- ## TASK ASSIGNMENT
228
206
 
229
- ### MANDATORY FIRST STEPS
230
- 1. Read: ~/.maestro/workflows/maestro-coordinate.codex.md
231
- 2. Read: ~/.codex/skills/{skill}/SKILL.md
207
+ ```javascript
208
+ state.steps[state.current_step].status = 'running';
209
+ state.steps[state.current_step].started_at = new Date().toISOString();
210
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
211
+
212
+ Bash({
213
+ command: `codex delegate ${escapeForShell(prompt)} --to ${state.tool} --mode write`,
214
+ run_in_background: true, timeout: 600000
215
+ });
216
+ // ■ STOP — wait for hook callback
217
+ ```
232
218
 
233
219
  ---
234
220
 
235
- **Coordinate Chain: {chain} | Step {step_n} of {totalSteps}**
221
+ ### Step 7: Post-Step Callback
236
222
 
237
- ## Skill Invocation
238
- Execute this skill call to complete your task:
223
+ ```javascript
224
+ const stepIdx = state.current_step;
225
+ const step = state.steps[stepIdx];
226
+ const output = /* callback output */;
227
+
228
+ step.exec_id = /* from callback stderr */;
229
+ step.completed_at = new Date().toISOString();
230
+
231
+ // Context propagation
232
+ const phaseMatch = output.match(/PHASE:\s*(\d+)/m);
233
+ if (phaseMatch) context.current_phase = phaseMatch[1];
234
+ const specMatch = output.match(/SPEC-[\w-]+/);
235
+ if (specMatch) context.spec_session_id = specMatch[0];
236
+ const scratchMatch = output.match(/scratch_dir:\s*(.+)/m);
237
+ if (scratchMatch) context.scratch_dir = scratchMatch[1].trim();
238
+
239
+ // Success/failure
240
+ const failed = /^STATUS:\s*FAILURE/m.test(output);
241
+ if (!failed) {
242
+ step.status = 'completed';
243
+ } else if (state.auto_mode) {
244
+ if (!step.retried) { step.retried = true; /* re-execute Step 6c */ return; }
245
+ step.status = 'skipped';
246
+ } else {
247
+ // AskUserQuestion: Retry / Skip / Abort
248
+ }
239
249
 
240
- ${skill} "{intent}" {skillFlag}
250
+ Write(`${sessionDir}/step-${stepIdx + 1}-output.txt`, output);
251
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
252
+
253
+ // → Step 7b: Gemini analysis (skip if step failed/skipped or single-step chain)
254
+ if (step.status === 'completed' && state.steps.length > 1) {
255
+ // → Step 7b
256
+ } else {
257
+ state.current_step = stepIdx + 1;
258
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
259
+ if (state.current_step < state.steps.length) { /* → Step 6 */ }
260
+ else { /* → Step 8 */ }
261
+ }
262
+ ```
241
263
 
242
- Follow the Implementation section of the skill file you read in step 2.
243
- The intent above is your driving goal.
264
+ ---
244
265
 
245
- {#if prevContext}
246
- ## Context from Previous Steps
247
- {prevContext}
266
+ ### Step 7b: Analyze Step Output (via gemini)
248
267
 
249
- Use hints from the previous step to guide execution priorities.
250
- {/if}
268
+ After each step completes, call gemini to evaluate execution quality and generate optimization hints.
251
269
 
252
- ## Output (required — last JSON block in your response)
253
- After execution complete, output exactly:
254
- ```json
270
+ ```javascript
271
+ const analysisPrompt = `PURPOSE: Evaluate execution quality of coordinate step "${step.cmd}" and generate optimization hints for the next step.
272
+ CHAIN: ${state.chain_name} | Intent: ${state.intent}
273
+ COMMAND: /${step.cmd} ${step.args || ''}
274
+ STEP OUTPUT (last 200 lines):
275
+ ${output.split('\n').slice(-200).join('\n')}
276
+ NEXT STEP: ${nextStep ? `/${nextStep.cmd} ${nextStep.args || ''}` : 'None (last step)'}
277
+ EXPECTED OUTPUT (strict JSON):
255
278
  {
256
- "quality_score": <0-10>,
257
- "findings": "<what was accomplished max 500 chars>",
258
- "hints_for_next": "<specific guidance for the next chain step>"
259
- }
279
+ "quality_score": <0-100>,
280
+ "execution_assessment": { "success": <bool>, "completeness": "<full|partial|minimal>", "key_outputs": [], "missing_outputs": [] },
281
+ "issues": [{ "severity": "critical|high|medium|low", "description": "" }],
282
+ "next_step_hints": {
283
+ "prompt_additions": "<extra context or constraints to inject into next step prompt>",
284
+ "cautions": ["<things next step should watch out for>"],
285
+ "context_to_carry": "<key facts from this step's output that next step needs>"
286
+ },
287
+ "step_summary": ""
288
+ }`;
289
+
290
+ let delegateCmd = `codex delegate ${escapeForShell(analysisPrompt)} --to gemini --mode analysis --rule analysis-review-code-quality`;
291
+ if (state.gemini_session_id) delegateCmd += ` --resume ${state.gemini_session_id}`;
292
+ Bash({ command: delegateCmd, run_in_background: true, timeout: 300000 });
293
+ // ■ STOP — wait for hook callback
260
294
  ```
261
295
 
262
- Session artifacts: {sessionDir}/
296
+ ### Step 7c: Post-Analyze Callback
297
+
298
+ ```javascript
299
+ const analysisResult = /* parsed JSON from callback output */;
300
+ state.gemini_session_id = /* from callback stderr */;
301
+
302
+ if (!state.step_analyses) state.step_analyses = [];
303
+ state.step_analyses.push({
304
+ step_index: stepIdx, cmd: step.cmd,
305
+ quality_score: analysisResult.quality_score,
306
+ issues: analysisResult.issues,
307
+ next_step_hints: analysisResult.next_step_hints,
308
+ summary: analysisResult.step_summary
309
+ });
310
+ step.analysis = {
311
+ quality_score: analysisResult.quality_score,
312
+ issue_count: (analysisResult.issues || []).length
313
+ };
314
+ Write(`${sessionDir}/step-${stepIdx + 1}-analysis.json`, JSON.stringify(analysisResult, null, 2));
315
+
316
+ // Advance
317
+ state.current_step = stepIdx + 1;
318
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
319
+
320
+ if (state.current_step < state.steps.length) { /* → Step 6 */ }
321
+ else { /* → Step 8 */ }
263
322
  ```
264
323
 
265
324
  ---
266
325
 
267
- ### Phase 3: Completion Report
326
+ ### Step 8: Completion Report
268
327
 
269
328
  ```javascript
270
- state.status = state.steps.every(s => s.status === 'completed') ? "completed" : state.status
271
- Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2))
272
-
273
- functions.update_plan({
274
- explanation: "Coordinate complete",
275
- plan: [
276
- { step: "Phase 1: Resolve intent and chain", status: "completed" },
277
- { step: "Phase 2: Execute steps (pipeline)", status: "completed" },
278
- { step: "Phase 3: Completion report", status: "completed" }
279
- ]
280
- })
329
+ const done = state.steps.filter(s => s.status === 'completed').length;
330
+ state.status = state.steps.some(s => s.status === 'failed') ? 'completed_with_errors' : 'completed';
331
+ state.completed_at = new Date().toISOString();
332
+ Write(`${sessionDir}/state.json`, JSON.stringify(state, null, 2));
281
333
  ```
282
334
 
283
- Display:
284
335
  ```
285
- === COORDINATE COMPLETE ===
286
- Session: <sessionId>
287
- Chain: <chain>
288
- Steps: <N completed>/<total>
289
-
290
- STEP RESULTS:
291
- [1] <skill> — score: <N>/10 ✓ <findings summary>
292
- [2] <skill> — score: <N>/10 ✓ <findings summary>
293
- [3] <skill> score: <N>/10 ✓ <findings summary>
294
-
295
- State: .workflow/.maestro-coordinate/<sessionId>/state.json
296
- Resume: $maestro-coordinate --continue
336
+ ============================================================
337
+ MAESTRO-COORDINATE COMPLETE
338
+ ============================================================
339
+ Session: {session_id}
340
+ Chain: {chain_name} ({done}/{total})
341
+ Tool: {cliTool}
342
+
343
+ Steps:
344
+ [] 1. maestro-plan completed (quality: 85/100)
345
+ [✓] 2. maestro-execute — completed (quality: 78/100)
346
+
347
+ Avg Quality: {avg_score}/100
348
+ Next: $maestro-coordinate --continue
349
+ ============================================================
297
350
  ```
298
351
 
299
352
  ---
300
353
 
301
354
  ## Error Handling
302
355
 
303
- | Code | Severity | Condition | Recovery |
304
- |------|----------|-----------|----------|
305
- | E001 | error | Intent unclassifiable after clarification | Default to `feature` chain; note in state.json |
306
- | E002 | error | `--chain` value not in chain map | List valid chains, abort |
307
- | E003 | error | Step agent timeout (4-step cascade exhausted) | Mark step `failed`; skip remaining steps; suggest `--continue` |
308
- | E004 | error | Step agent failed (non-JSON output) | Mark step `failed`; preserve raw output in `findings`; skip remaining |
309
- | E005 | error | `--continue`: no session found | Glob `.workflow/.maestro-coordinate/MCC-*/`, list sessions, prompt |
310
- | W001 | warning | Step output JSON missing `hints_for_next` | Continue with empty hints; next step still gets `findings` |
356
+ | Code | Severity | Description | Recovery |
357
+ |------|----------|-------------|----------|
358
+ | E001 | error | No intent and project not initialized | Suggest $maestro-init |
359
+ | E002 | error | Clarity too low after 2 rounds | Ask to rephrase |
360
+ | E003 | error | Step failed + abort | Suggest resume with -c |
361
+ | E004 | error | Resume session not found | Show available sessions |
362
+ | E005 | error | CLI tool unavailable | Try fallback tool |
311
363
 
312
364
  ---
313
365
 
314
366
  ## Core Rules
315
367
 
316
- 1. **Start Immediately**: Init session dir and write `state.json` before any spawn
317
- 2. **Sequential**: Never spawn step N+1 until step N agent is closed and results written
318
- 3. **Skill in Prompt**: Every step agent's message MUST contain `$skill-name "intent"` this is how the agent knows which skill to execute
319
- 4. **State.json is source of truth**: Write after every step; `--continue` reads it to resume
320
- 5. **Skip on Failure**: Step failure immediately marks all remaining steps `skipped` and aborts the loop
321
- 6. **Close before spawn**: Always `close_agent` the current step agent before spawning the next
322
- 7. **Dry-run is read-only**: Stop after displaying the chain plan never spawn agents
323
- 8. **Timeout handling**: 4-step cascadestatus probe force finalize abort; if all timed out → mark `failed`
324
- 9. **No CLI fallback**: All execution is agent-native no `exec_command("maestro delegate ...")`
368
+ 1. **Semantic routing** LLM-native structured extraction (`action × object`) replaces regex; disambiguates by context
369
+ 2. **STOP after each `codex delegate` call** background execution, wait for hook callback
370
+ 3. **State machine** advance via `current_step`, no sync loops for async operations
371
+ 4. **Template-driven** all steps use `coordinate-step.txt`, no per-command prompt assembly
372
+ 5. **Context propagation** parse PHASE / spec session ID / scratch_dir / issue_id from each step output, feed to next step
373
+ 6. **Quality gates** issue chains auto-include review; `issue-full` is default for issue execution
374
+ 7. **Tool fallback** if `codex delegate` fails: retry with same tool once, then try `gemini` → `qwen`
375
+ 8. **Auto-confirm injection**`{{AUTO_DIRECTIVE}}` in template prevents blocking during background execution
376
+ 9. **Resumable** `-c` reads `state.json`, jumps to first pending step
377
+ 10. **Gemini analysis after each step** — evaluate output quality via `codex delegate --to gemini --mode analysis`, chained via `--resume`
378
+ 11. **Session capture** — after each gemini callback, capture exec_id → `gemini_session_id` for resume chain
379
+ 12. **Analysis skip conditions** — skip gemini analysis for: failed/skipped steps, single-step chains
@@ -308,6 +308,14 @@ If a task is blocked/failed and other tasks in later waves depend on it:
308
308
  - Update `status` to match CSV status
309
309
  - Write back to disk
310
310
 
311
+ 3b. **Issue status sync**: For each completed/failed task that has `issue_id`:
312
+ - Read issue from `.workflow/issues/issues.jsonl` by `issue_id`
313
+ - Collect all `task_refs[]` statuses for that issue:
314
+ - All task_refs completed → `issue.status = "resolved"`
315
+ - Any task_ref failed → `issue.status = "in_progress"`
316
+ - Append history entry: `{ action: "executed", at: <ISO>, by: "maestro-execute", summary: "TASK-{NNN} {status}" }`
317
+ - Write updated issue back to `issues.jsonl`
318
+
311
319
  4. **Register EXC artifact in state.json**:
312
320
  ```
313
321
  Read .workflow/state.json
@@ -404,7 +404,15 @@ spawn_agents_on_csv({
404
404
  }
405
405
  ```
406
406
 
407
- 5. **Issue linking** (if --gaps): Update issues in `issues.jsonl` with status `planned`, link to TASK IDs.
407
+ 5. **Issue linking** (if --gaps):
408
+ For each created TASK-{NNN}.json that has `issue_id`:
409
+ - Update corresponding issue in `.workflow/issues/issues.jsonl`:
410
+ - `task_refs`: append TASK-{NNN} to array
411
+ - `task_plan_dir`: relative path to `.task/` directory
412
+ - `status`: "planned"
413
+ - `updated_at`: now()
414
+ - Append history entry: `{ action: "planned", at: <ISO>, by: "maestro-plan", summary: "Linked to TASK-{NNN}" }`
415
+ This ensures bidirectional issue ↔ TASK traceability for dashboard display.
408
416
 
409
417
  6. **Display summary + options** (skip options if AUTO_YES):
410
418
  ```