maestro-flow 0.3.8 → 0.3.9
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/.claude/commands/learn-decompose.md +3 -3
- package/.claude/commands/learn-follow.md +5 -5
- package/.claude/commands/learn-investigate.md +3 -3
- package/.claude/commands/learn-retro.md +6 -6
- package/.claude/commands/learn-second-opinion.md +3 -3
- package/.claude/commands/maestro-analyze.md +123 -99
- package/.claude/commands/maestro-brainstorm.md +2 -2
- package/.claude/commands/maestro-execute.md +137 -97
- package/.claude/commands/maestro-fork.md +111 -0
- package/.claude/commands/maestro-init.md +6 -6
- package/.claude/commands/maestro-merge.md +77 -0
- package/.claude/commands/maestro-milestone-audit.md +72 -60
- package/.claude/commands/maestro-milestone-complete.md +67 -59
- package/.claude/commands/maestro-milestone-release.md +6 -6
- package/.claude/commands/maestro-plan.md +151 -130
- package/.claude/commands/maestro-quick.md +4 -4
- package/.claude/commands/maestro-roadmap.md +5 -5
- package/.claude/commands/maestro-spec-generate.md +5 -5
- package/.claude/commands/maestro-ui-design.md +3 -3
- package/.claude/commands/maestro-verify.md +106 -87
- package/.claude/commands/maestro.md +10 -4
- package/.claude/commands/manage-codebase-rebuild.md +4 -4
- package/.claude/commands/manage-codebase-refresh.md +1 -1
- package/.claude/commands/manage-harvest.md +5 -5
- package/.claude/commands/manage-issue-discover.md +1 -1
- package/.claude/commands/manage-issue-execute.md +6 -6
- package/.claude/commands/manage-issue.md +6 -6
- package/.claude/commands/manage-learn.md +2 -2
- package/.claude/commands/manage-memory-capture.md +4 -4
- package/.claude/commands/manage-memory.md +2 -2
- package/.claude/commands/manage-status.md +24 -24
- package/.claude/commands/quality-business-test.md +5 -5
- package/.claude/commands/quality-debug.md +4 -4
- package/.claude/commands/quality-integration-test.md +4 -4
- package/.claude/commands/quality-refactor.md +3 -3
- package/.claude/commands/quality-retrospective.md +2 -2
- package/.claude/commands/quality-review.md +4 -4
- package/.claude/commands/quality-sync.md +3 -3
- package/.claude/commands/quality-test-gen.md +4 -4
- package/.claude/commands/quality-test.md +9 -9
- package/.claude/commands/spec-add.md +2 -2
- package/.claude/commands/spec-load.md +1 -1
- package/.claude/commands/spec-setup.md +5 -5
- package/.claude/commands/wiki-connect.md +3 -3
- package/.claude/commands/wiki-digest.md +4 -4
- package/.codex/skills/maestro-analyze/SKILL.md +52 -14
- package/.codex/skills/maestro-execute/SKILL.md +27 -26
- package/.codex/skills/maestro-milestone-audit/SKILL.md +103 -209
- package/.codex/skills/maestro-milestone-complete/SKILL.md +149 -158
- package/.codex/skills/maestro-plan/SKILL.md +47 -17
- package/.codex/skills/maestro-roadmap/SKILL.md +3 -2
- package/.codex/skills/team-coordinate/roles/coordinator/commands/monitor.md +2 -2
- package/.codex/skills/team-executor/roles/executor/commands/monitor.md +1 -1
- package/.codex/skills/team-lifecycle-v4/roles/coordinator/commands/monitor.md +2 -2
- package/.codex/skills/team-lifecycle-v4/specs/knowledge-transfer.md +2 -2
- package/.codex/skills/team-quality-assurance/roles/coordinator/commands/monitor.md +1 -1
- package/.codex/skills/team-review/roles/coordinator/commands/monitor.md +1 -1
- package/.codex/skills/team-tech-debt/roles/coordinator/commands/monitor.md +1 -1
- package/.codex/skills/team-testing/roles/coordinator/commands/monitor.md +1 -1
- package/README.md +19 -14
- package/README.zh-CN.md +16 -12
- package/bin/maestro-mcp.js +1 -1
- package/chains/_intent-map.json +21 -9
- package/chains/_router.json +30 -77
- package/chains/brainstorm-driven.json +17 -6
- package/chains/full-lifecycle.json +22 -23
- package/chains/milestone-close.json +20 -7
- package/chains/milestone-fork-merge.json +50 -0
- package/chains/roadmap-driven.json +17 -6
- package/chains/spec-driven.json +17 -6
- package/dashboard/dist/assets/{ArtifactsPage-BmPOu8sO.js → ArtifactsPage-DZNCi6tn.js} +12 -7
- package/dashboard/dist/assets/ChatInput-Bvr-FeEq.js +49 -0
- package/dashboard/dist/assets/ChatPage-D9zTkJZo.js +22 -0
- package/dashboard/dist/assets/CollabPage-B4NAHXS2.js +1 -0
- package/dashboard/dist/assets/ExecutionPanel-CFt4LJyq.js +1 -0
- package/dashboard/dist/assets/KanbanPage-C8USth6H.js +21 -0
- package/dashboard/dist/assets/{MarkdownRenderer-BjZ43aSa.js → MarkdownRenderer-X4af_WNb.js} +1 -1
- package/dashboard/dist/assets/McpPage-BKfCVIyU.js +21 -0
- package/dashboard/dist/assets/OutputPanel-BlBQFJSW.js +1 -0
- package/dashboard/dist/assets/ProblemsPanel-De3DLvoI.js +1 -0
- package/dashboard/dist/assets/{RequirementBoardPage-B7yRL0s_.js → RequirementBoardPage-Bf1trzqs.js} +2 -2
- package/dashboard/dist/assets/{RequirementPage-D8J_-b6O.js → RequirementPage-Bllxe2XI.js} +10 -5
- package/dashboard/dist/assets/{SpecsPage-6lO8v8_C.js → SpecsPage-9lwxKT27.js} +2 -2
- package/dashboard/dist/assets/{SupervisorPage-Ds5N378a.js → SupervisorPage-SusdfHFq.js} +1 -1
- package/dashboard/dist/assets/{TeamsPage-DrkKr17T.js → TeamsPage-DsuM6OwC.js} +2 -2
- package/dashboard/dist/assets/TreeBrowser-Q12qobZs.js +6 -0
- package/dashboard/dist/assets/WorkflowPage-D_Fzdy3_.js +6 -0
- package/dashboard/dist/assets/{arrow-left-CadP5YgU.js → arrow-left-Bqtb2hle.js} +1 -1
- package/dashboard/dist/assets/{check-5xufDzS8.js → check-u6fGOwQO.js} +1 -1
- package/dashboard/dist/assets/{chevron-right-CYbpR4ev.js → chevron-right-Csu22t58.js} +1 -1
- package/dashboard/dist/assets/{circle-Bm-5Q-Yh.js → circle-CMrkbRNg.js} +1 -1
- package/dashboard/dist/assets/{circle-alert-BqcYuT7x.js → circle-alert-c3tH1P4z.js} +1 -1
- package/dashboard/dist/assets/{circle-check-big-yyzAFysU.js → circle-check-big-TDSeWstm.js} +1 -1
- package/dashboard/dist/assets/{circle-check-DEVzW_lm.js → circle-check-gYxxSYuH.js} +1 -1
- package/dashboard/dist/assets/{code-BBdC8Wmw.js → code-CFN2uX9V.js} +1 -1
- package/dashboard/dist/assets/{columns-3-CQ9Trztr.js → columns-3-38xIDlzy.js} +1 -1
- package/dashboard/dist/assets/{download-DayuF-sn.js → download-DC7KkKyP.js} +1 -1
- package/dashboard/dist/assets/{folder-CqXeSKeC.js → folder-CWq_lAnf.js} +1 -1
- package/dashboard/dist/assets/index-DWG-WrzT.js +231 -0
- package/dashboard/dist/assets/{index-Dru5HYy0.js → index-Do71weNR.js} +1 -1
- package/dashboard/dist/assets/index-GUNJodSR.css +1 -0
- package/dashboard/dist/assets/{list-DBOD6IUt.js → list-CgIP_2A-.js} +1 -1
- package/dashboard/dist/assets/{minus-fQI1Syn2.js → minus-DYoN5UGk.js} +1 -1
- package/dashboard/dist/assets/{pen-line-Bkbbngl5.js → pen-line-Bh_WKYHm.js} +1 -1
- package/dashboard/dist/assets/{proxy-teW12DdZ.js → proxy-BKxDAKTj.js} +1 -1
- package/dashboard/dist/assets/{search-Bq3ygFUW.js → search-SieXnOgr.js} +1 -1
- package/dashboard/dist/assets/{shallow-22ZN8sFt.js → shallow-Bme1JY57.js} +1 -1
- package/dashboard/dist/assets/{table-BEYtdWc4.js → table-llyEtj-7.js} +1 -1
- package/dashboard/dist/assets/terminal-BB3Xfuv5.js +6 -0
- package/dashboard/dist/assets/{trash-2-DMqGBgcF.js → trash-2-C8f4vFFM.js} +1 -1
- package/dashboard/dist/assets/{zap-9DVkGVtt.js → zap-4uwlzVm0.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist-server/dashboard/src/server/agents/claude-code-adapter.js +8 -4
- package/dashboard/dist-server/dashboard/src/server/agents/claude-code-adapter.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/entry-normalizer.d.ts +1 -0
- package/dashboard/dist-server/dashboard/src/server/agents/entry-normalizer.js +2 -1
- package/dashboard/dist-server/dashboard/src/server/agents/entry-normalizer.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.js +20 -10
- package/dashboard/dist-server/dashboard/src/server/agents/stream-json-adapter.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/routes/git.d.ts +2 -0
- package/dashboard/dist-server/dashboard/src/server/routes/git.js +79 -0
- package/dashboard/dist-server/dashboard/src/server/routes/git.js.map +1 -0
- package/dashboard/dist-server/dashboard/src/server/routes/index.js +3 -0
- package/dashboard/dist-server/dashboard/src/server/routes/index.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/routes/workspace.js +43 -0
- package/dashboard/dist-server/dashboard/src/server/routes/workspace.js.map +1 -1
- package/dashboard/dist-server/dashboard/src/server/state/state-manager.js +43 -3
- package/dashboard/dist-server/dashboard/src/server/state/state-manager.js.map +1 -1
- package/dashboard/package.json +59 -59
- package/dist/src/cli.js +3 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/{team.d.ts → collab.d.ts} +2 -2
- package/dist/src/commands/collab.d.ts.map +1 -0
- package/dist/src/commands/{team.js → collab.js} +391 -24
- package/dist/src/commands/collab.js.map +1 -0
- package/dist/src/commands/msg.d.ts.map +1 -1
- package/dist/src/commands/msg.js +4 -3
- package/dist/src/commands/msg.js.map +1 -1
- package/dist/src/hooks/team-monitor.d.ts.map +1 -1
- package/dist/src/hooks/team-monitor.js +16 -0
- package/dist/src/hooks/team-monitor.js.map +1 -1
- package/dist/src/tools/collab-adapter.d.ts +85 -0
- package/dist/src/tools/collab-adapter.d.ts.map +1 -0
- package/dist/src/tools/collab-adapter.js +320 -0
- package/dist/src/tools/collab-adapter.js.map +1 -0
- package/dist/src/tools/namespace-guard.d.ts +2 -0
- package/dist/src/tools/namespace-guard.d.ts.map +1 -1
- package/dist/src/tools/namespace-guard.js +12 -0
- package/dist/src/tools/namespace-guard.js.map +1 -1
- package/dist/src/tools/phase-gate-evaluator.d.ts +45 -0
- package/dist/src/tools/phase-gate-evaluator.d.ts.map +1 -0
- package/dist/src/tools/phase-gate-evaluator.js +42 -0
- package/dist/src/tools/phase-gate-evaluator.js.map +1 -0
- package/dist/src/tools/team-members.d.ts +18 -0
- package/dist/src/tools/team-members.d.ts.map +1 -1
- package/dist/src/tools/team-members.js +50 -0
- package/dist/src/tools/team-members.js.map +1 -1
- package/dist/src/tools/team-tasks.d.ts +120 -0
- package/dist/src/tools/team-tasks.d.ts.map +1 -0
- package/dist/src/tools/team-tasks.js +365 -0
- package/dist/src/tools/team-tasks.js.map +1 -0
- package/dist/src/tools/transition-recorder.d.ts +3 -0
- package/dist/src/tools/transition-recorder.d.ts.map +1 -1
- package/dist/src/tools/transition-recorder.js +52 -1
- package/dist/src/tools/transition-recorder.js.map +1 -1
- package/dist/src/utils/get-version.d.ts.map +1 -1
- package/dist/src/utils/get-version.js +15 -4
- package/dist/src/utils/get-version.js.map +1 -1
- package/package.json +1 -1
- package/templates/config.json +7 -0
- package/templates/worktree-scope.json +10 -0
- package/templates/worktrees.json +27 -0
- package/workflows/analyze.md +86 -36
- package/workflows/brainstorm.md +17 -37
- package/workflows/execute.md +94 -28
- package/workflows/fork.md +309 -0
- package/workflows/init.md +10 -1
- package/workflows/issue.md +66 -7
- package/workflows/maestro-coordinate.md +23 -16
- package/workflows/maestro.md +52 -35
- package/workflows/merge.md +285 -0
- package/workflows/milestone-audit.md +89 -70
- package/workflows/milestone-complete.md +89 -156
- package/workflows/plan.md +122 -17
- package/workflows/retrospective.md +3 -3
- package/workflows/roadmap.md +11 -3
- package/workflows/spec-generate.md +9 -0
- package/workflows/status.md +76 -27
- package/workflows/ui-design.md +14 -12
- package/workflows/verify.md +44 -8
- package/.claude/commands/maestro-phase-add.md +0 -63
- package/.claude/commands/maestro-phase-transition.md +0 -75
- package/.codex/skills/maestro-phase-add/SKILL.md +0 -154
- package/.codex/skills/maestro-phase-transition/SKILL.md +0 -173
- package/chains/singles/phase-add.json +0 -31
- package/chains/singles/phase-transition.json +0 -23
- package/dashboard/dist/assets/ChatInput-CL8YDfOU.js +0 -67
- package/dashboard/dist/assets/ChatPage-CT-ozBK2.js +0 -8
- package/dashboard/dist/assets/CollabPage-C0rWMden.js +0 -1
- package/dashboard/dist/assets/KanbanPage-C6WbAlwI.js +0 -16
- package/dashboard/dist/assets/McpPage-BPIXADQi.js +0 -16
- package/dashboard/dist/assets/TreeBrowser-g_QUKemL.js +0 -11
- package/dashboard/dist/assets/WorkflowPage-X8aNkDEr.js +0 -6
- package/dashboard/dist/assets/git-branch-SqFf4Ru5.js +0 -6
- package/dashboard/dist/assets/index-D2Mtyw7I.css +0 -1
- package/dashboard/dist/assets/index-nufWop4p.js +0 -231
- package/dashboard/dist/assets/wrench-B84-zdLI.js +0 -11
- package/dist/src/commands/team.d.ts.map +0 -1
- package/dist/src/commands/team.js.map +0 -1
- package/workflows/phase-add.md +0 -252
- package/workflows/phase-transition.md +0 -399
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Provides pure functions for building transition entries and appending
|
|
5
5
|
* them to the transition_history array in .workflow/state.json.
|
|
6
6
|
*/
|
|
7
|
-
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'node:fs';
|
|
8
|
+
import { join, dirname } from 'node:path';
|
|
9
|
+
import { evaluatePhaseGate } from './phase-gate-evaluator.js';
|
|
8
10
|
// ---------------------------------------------------------------------------
|
|
9
11
|
// Public API
|
|
10
12
|
// ---------------------------------------------------------------------------
|
|
@@ -33,10 +35,31 @@ export function buildTransitionEntry(opts) {
|
|
|
33
35
|
/**
|
|
34
36
|
* Append a transition entry to state.json's transition_history[].
|
|
35
37
|
* Creates the array if it doesn't exist.
|
|
38
|
+
*
|
|
39
|
+
* For phase-completion transitions, evaluates the phase gate first.
|
|
40
|
+
* Throws if the gate blocks and force is false.
|
|
36
41
|
*/
|
|
37
42
|
export function appendTransition(statePath, entry) {
|
|
38
43
|
if (!existsSync(statePath))
|
|
39
44
|
return;
|
|
45
|
+
// Gate check: validate phase readiness before allowing completion
|
|
46
|
+
if (entry.type === 'phase' && entry.from_phase != null) {
|
|
47
|
+
const phaseIndex = loadPhaseIndex(statePath, entry.from_phase);
|
|
48
|
+
if (phaseIndex) {
|
|
49
|
+
const gate = evaluatePhaseGate(phaseIndex);
|
|
50
|
+
if (!gate.allowed) {
|
|
51
|
+
if (!gate.overridable || !entry.force) {
|
|
52
|
+
const tag = gate.overridable ? '[GATE_BLOCKED]' : '[GATE_HARD_BLOCK]';
|
|
53
|
+
throw new Error(`${tag} Phase ${entry.from_phase} cannot be completed:\n` +
|
|
54
|
+
gate.reasons.map((r) => ` - ${r}`).join('\n') +
|
|
55
|
+
(gate.overridable ? '\nUse force=true to override soft blocks.' : '\nResolve BLOCK verdict before completing.'));
|
|
56
|
+
}
|
|
57
|
+
// Force override — record the reasons in snapshot for audit
|
|
58
|
+
entry.snapshot.verification_status =
|
|
59
|
+
`force_override: ${gate.reasons.join('; ')}`;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
40
63
|
const state = JSON.parse(readFileSync(statePath, 'utf8'));
|
|
41
64
|
if (!Array.isArray(state.transition_history)) {
|
|
42
65
|
state.transition_history = [];
|
|
@@ -45,4 +68,32 @@ export function appendTransition(statePath, entry) {
|
|
|
45
68
|
state.last_updated = new Date().toISOString();
|
|
46
69
|
writeFileSync(statePath, JSON.stringify(state, null, 2));
|
|
47
70
|
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Internal helpers
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
/**
|
|
75
|
+
* Load phase index.json from the phases directory sibling to state.json.
|
|
76
|
+
* Returns null if not found.
|
|
77
|
+
*/
|
|
78
|
+
function loadPhaseIndex(statePath, phaseNum) {
|
|
79
|
+
const workflowDir = dirname(statePath);
|
|
80
|
+
const phasesDir = join(workflowDir, 'phases');
|
|
81
|
+
if (!existsSync(phasesDir))
|
|
82
|
+
return null;
|
|
83
|
+
// Find directory starting with the phase number prefix (e.g. "01-")
|
|
84
|
+
try {
|
|
85
|
+
const prefix = String(phaseNum).padStart(2, '0') + '-';
|
|
86
|
+
const entries = readdirSync(phasesDir);
|
|
87
|
+
const phaseSlug = entries.find((e) => e.startsWith(prefix));
|
|
88
|
+
if (!phaseSlug)
|
|
89
|
+
return null;
|
|
90
|
+
const indexPath = join(phasesDir, phaseSlug, 'index.json');
|
|
91
|
+
if (!existsSync(indexPath))
|
|
92
|
+
return null;
|
|
93
|
+
return JSON.parse(readFileSync(indexPath, 'utf8'));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
48
99
|
//# sourceMappingURL=transition-recorder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transition-recorder.js","sourceRoot":"","sources":["../../../src/tools/transition-recorder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"transition-recorder.js","sourceRoot":"","sources":["../../../src/tools/transition-recorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-version.d.ts","sourceRoot":"","sources":["../../../src/utils/get-version.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"get-version.d.ts","sourceRoot":"","sources":["../../../src/utils/get-version.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAiB1C"}
|
|
@@ -12,10 +12,21 @@ let cached = null;
|
|
|
12
12
|
export function getPackageVersion() {
|
|
13
13
|
if (cached)
|
|
14
14
|
return cached;
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// Walk up from this file until we find a package.json with "maestro" in it
|
|
16
|
+
let dir = resolve(fileURLToPath(import.meta.url), '..');
|
|
17
|
+
for (let i = 0; i < 8; i++) {
|
|
18
|
+
const pkgPath = resolve(dir, 'package.json');
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
21
|
+
if (pkg.name === 'maestro-flow' || pkg.name === 'maestro') {
|
|
22
|
+
cached = pkg.version ?? '0.0.0';
|
|
23
|
+
return cached;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch { /* not found, keep going up */ }
|
|
27
|
+
dir = resolve(dir, '..');
|
|
28
|
+
}
|
|
29
|
+
cached = '0.0.0';
|
|
19
30
|
return cached;
|
|
20
31
|
}
|
|
21
32
|
//# sourceMappingURL=get-version.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-version.js","sourceRoot":"","sources":["../../../src/utils/get-version.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,
|
|
1
|
+
{"version":3,"file":"get-version.js","sourceRoot":"","sources":["../../../src/utils/get-version.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,IAAI,MAAM,GAAkB,IAAI,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,IAAI,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YACvD,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC1D,MAAM,GAAI,GAAG,CAAC,OAAkB,IAAI,OAAO,CAAC;gBAC5C,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,8BAA8B,CAAC,CAAC;QAC1C,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,GAAG,OAAO,CAAC;IACjB,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
package/templates/config.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"worktree": true,
|
|
3
|
+
"milestone_num": "{{MILESTONE_NUMBER}}",
|
|
4
|
+
"milestone": "{{MILESTONE_NAME}}",
|
|
5
|
+
"owned_phases": [],
|
|
6
|
+
"main_worktree": "{{MAIN_WORKTREE_PATH}}",
|
|
7
|
+
"branch": "milestone/{{MILESTONE_SLUG}}",
|
|
8
|
+
"base_commit": "{{BASE_COMMIT}}",
|
|
9
|
+
"created_at": "{{TIMESTAMP}}"
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"worktrees": [
|
|
4
|
+
{
|
|
5
|
+
"milestone_num": "{{MILESTONE_NUMBER}}",
|
|
6
|
+
"milestone": "{{MILESTONE_NAME}}",
|
|
7
|
+
"slug": "{{MILESTONE_SLUG}}",
|
|
8
|
+
"branch": "milestone/{{MILESTONE_SLUG}}",
|
|
9
|
+
"path": "{{WORKTREE_ROOT}}/m{{MILESTONE_NUMBER}}-{{MILESTONE_SLUG}}",
|
|
10
|
+
"base_commit": "{{BASE_COMMIT}}",
|
|
11
|
+
"status": "active",
|
|
12
|
+
"created_at": "{{TIMESTAMP}}",
|
|
13
|
+
"owned_phases": [],
|
|
14
|
+
"fork_session": "{{FORK_SESSION_ID}}"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"fork_sessions": [
|
|
18
|
+
{
|
|
19
|
+
"session_id": "fork-{{TIMESTAMP_SHORT}}",
|
|
20
|
+
"created_at": "{{TIMESTAMP}}",
|
|
21
|
+
"milestone_num": "{{MILESTONE_NUMBER}}",
|
|
22
|
+
"milestone": "{{MILESTONE_NAME}}",
|
|
23
|
+
"base_branch": "{{BASE_BRANCH}}",
|
|
24
|
+
"base_commit": "{{BASE_COMMIT}}"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
package/workflows/analyze.md
CHANGED
|
@@ -41,29 +41,60 @@ Quick mode (-q):
|
|
|
41
41
|
## Arguments
|
|
42
42
|
|
|
43
43
|
```
|
|
44
|
-
$ARGUMENTS: "
|
|
44
|
+
$ARGUMENTS: "[phase|topic] [-y] [-c] [-q]"
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
<
|
|
46
|
+
(no args) -- Milestone-wide analysis (requires init + roadmap)
|
|
47
|
+
<phase> -- Phase number (phase-scoped, requires init + roadmap)
|
|
48
|
+
<topic> -- Topic text (adhoc if milestone exists, standalone if not)
|
|
48
49
|
-y / --yes -- Auto mode, skip interactive scoping, auto-deepen
|
|
49
50
|
-c / --continue -- Resume from existing session
|
|
50
51
|
-q / --quick -- Quick mode, skip exploration + scoring, go straight to decision extraction
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
##
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
## Scope Routing
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
// Worktree scope check
|
|
58
|
+
IF file_exists(".workflow/worktree-scope.json"):
|
|
59
|
+
scope = read(".workflow/worktree-scope.json")
|
|
60
|
+
IF $ARGUMENTS matches /^\d+$/ AND parseInt($ARGUMENTS) NOT IN scope.owned_phases:
|
|
61
|
+
ERROR "Phase {$ARGUMENTS} not owned by this worktree. Owned: {scope.owned_phases}"
|
|
62
|
+
EXIT
|
|
63
|
+
|
|
64
|
+
// Auto-bootstrap state.json if missing
|
|
65
|
+
IF NOT file_exists(".workflow/state.json"):
|
|
66
|
+
mkdir -p .workflow/scratch/
|
|
67
|
+
Write minimal state.json: { project: null, status: "active", current_milestone: null,
|
|
68
|
+
current_task_id: null, milestones: [], artifacts: [], last_updated: now() }
|
|
69
|
+
|
|
70
|
+
// Scope determination
|
|
71
|
+
IF $ARGUMENTS is empty:
|
|
72
|
+
IF state.json.current_milestone is non-null AND roadmap.md exists:
|
|
73
|
+
→ scope = "milestone"
|
|
74
|
+
→ milestone_slug = slugify(current_milestone name)
|
|
75
|
+
→ Set OUTPUT_DIR = .workflow/scratch/analyze-{milestone_slug}-{date}/
|
|
76
|
+
ELSE:
|
|
77
|
+
→ ERROR E001 "No args and no roadmap — provide topic text or create roadmap first"
|
|
78
|
+
|
|
79
|
+
ELSE IF $ARGUMENTS matches /^\d+$/:
|
|
80
|
+
IF state.json.current_milestone is non-null AND roadmap.md exists:
|
|
81
|
+
→ scope = "phase"
|
|
82
|
+
→ phase_num = parsed number
|
|
83
|
+
→ phase_slug = resolve from roadmap.md
|
|
84
|
+
→ Set OUTPUT_DIR = .workflow/scratch/analyze-{phase_slug}-{date}/
|
|
85
|
+
ELSE:
|
|
86
|
+
→ ERROR "Phase number requires init + roadmap"
|
|
87
|
+
|
|
88
|
+
ELSE (text argument):
|
|
89
|
+
→ topic_slug = slugify(text, max 40 chars)
|
|
90
|
+
IF state.json.current_milestone is non-null:
|
|
91
|
+
→ scope = "adhoc"
|
|
92
|
+
ELSE:
|
|
93
|
+
→ scope = "standalone"
|
|
94
|
+
→ Set OUTPUT_DIR = .workflow/scratch/analyze-{topic_slug}-{date}/
|
|
95
|
+
|
|
96
|
+
// Create output directory
|
|
97
|
+
mkdir -p {OUTPUT_DIR}
|
|
67
98
|
```
|
|
68
99
|
|
|
69
100
|
## Output Structure
|
|
@@ -89,31 +120,23 @@ Parse $ARGUMENTS to determine mode and flags:
|
|
|
89
120
|
- `-c` present: locate existing session folder (discussion.md exists), resume from last round
|
|
90
121
|
- `-y` present: set AUTO_MODE=true
|
|
91
122
|
- `-q` present: set QUICK_MODE=true (skip Steps 2-7, jump to Step 8: Decision Extraction)
|
|
92
|
-
- Number (e.g., "3") = phase
|
|
93
|
-
- Text (e.g., "microservices vs monolith") =
|
|
94
|
-
- Missing/empty = error E001
|
|
123
|
+
- Number (e.g., "3") = phase scope: resolve phase slug from roadmap, output to scratch/analyze-{phase-slug}-{date}/
|
|
124
|
+
- Text (e.g., "microservices vs monolith") = adhoc/standalone scope: output to scratch/analyze-{slug}-{date}/
|
|
125
|
+
- Missing/empty = milestone scope (if roadmap exists) or error E001
|
|
95
126
|
|
|
96
127
|
**Session initialization:**
|
|
97
128
|
- Session ID: `ANL-{slug}-{YYYY-MM-DD}`
|
|
98
|
-
-
|
|
99
|
-
- Scratch mode output: `.workflow/scratch/analyze-{slug}-{date}/`
|
|
129
|
+
- Output: `OUTPUT_DIR` (always under `.workflow/scratch/`)
|
|
100
130
|
|
|
101
|
-
**Load prior context** (phase
|
|
131
|
+
**Load prior context** (milestone/phase scope):
|
|
102
132
|
1. Read `.workflow/project.md` — project vision, constraints, Validated requirements (already shipped), Active requirements (current scope)
|
|
103
133
|
2. Read `.workflow/roadmap.md` — phase structure and dependencies
|
|
104
|
-
3. Read
|
|
105
|
-
4.
|
|
106
|
-
5.
|
|
107
|
-
6.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
9. Read prior phases' `context.md` files — skip already-decided areas
|
|
111
|
-
10. Read existing `context.md` in this phase (if exists, for continuation)
|
|
112
|
-
11. Load project specs: `specs_content = maestro spec load --category planning`
|
|
113
|
-
Ensures analysis decisions don't conflict with existing architecture constraints.
|
|
114
|
-
12. Read `.workflow/state.json` → `accumulated_context` (key_decisions, deferred items, blockers)
|
|
115
|
-
|
|
116
|
-
**Load prior context** (scratch mode):
|
|
134
|
+
3. Read `.workflow/state.json` → `current_milestone`, `artifacts[]`, `accumulated_context` (key_decisions, deferred items, blockers)
|
|
135
|
+
4. Find prior analyze artifacts from `state.json.artifacts[]` where type=analyze and same milestone → load their `context.md` to skip already-decided areas
|
|
136
|
+
5. Find brainstorm artifacts from `state.json.artifacts[]` where type=brainstorm and same milestone → load `guidance-specification.md` if exists
|
|
137
|
+
6. Load project specs: `specs_content = maestro spec load --category planning`
|
|
138
|
+
|
|
139
|
+
**Load prior context** (adhoc/standalone scope):
|
|
117
140
|
1. Read `.workflow/project.md` (if exists) — project vision, Validated requirements, Active requirements, Key Decisions
|
|
118
141
|
2. Read `.workflow/state.json` (if exists) → `accumulated_context` (key_decisions, deferred, blockers)
|
|
119
142
|
3. Load project specs: `specs_content = maestro spec load --category planning`
|
|
@@ -571,6 +594,33 @@ IF deferred_items.length > 0:
|
|
|
571
594
|
Print: "Created {deferred_items.length} deferred issues for tracking"
|
|
572
595
|
```
|
|
573
596
|
|
|
597
|
+
### Step 8.8: Register Artifact
|
|
598
|
+
|
|
599
|
+
```
|
|
600
|
+
// Register in state.json artifact registry
|
|
601
|
+
Read .workflow/state.json
|
|
602
|
+
next_id = max(artifacts.filter(a => a.type == "analyze").map(a => parseInt(a.id.replace("ANL-","")))) + 1
|
|
603
|
+
// If no analyze artifacts exist: next_id = 1
|
|
604
|
+
|
|
605
|
+
artifact = {
|
|
606
|
+
id: "ANL-{next_id padded to 3}",
|
|
607
|
+
type: "analyze",
|
|
608
|
+
milestone: state.json.current_milestone, // null if standalone
|
|
609
|
+
phase: phase_num, // null if milestone/adhoc/standalone
|
|
610
|
+
scope: scope, // "milestone"|"phase"|"adhoc"|"standalone"
|
|
611
|
+
path: OUTPUT_DIR relative to .workflow/, // e.g. "scratch/analyze-auth-2026-04-20"
|
|
612
|
+
status: "completed",
|
|
613
|
+
depends_on: null,
|
|
614
|
+
harvested: false,
|
|
615
|
+
created_at: session_start_time,
|
|
616
|
+
completed_at: now()
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
state.json.artifacts.push(artifact)
|
|
620
|
+
state.json.last_updated = now()
|
|
621
|
+
Write state.json (atomic: write tmp + rename)
|
|
622
|
+
```
|
|
623
|
+
|
|
574
624
|
### Step 9: Report & Next Step
|
|
575
625
|
|
|
576
626
|
Display summary:
|
package/workflows/brainstorm.md
CHANGED
|
@@ -47,8 +47,8 @@ Phase 3: Single Role Analysis → Detection → Context → Agent → Validation
|
|
|
47
47
|
## Input
|
|
48
48
|
|
|
49
49
|
- `$ARGUMENTS`: topic text (auto mode) or role name (single role mode)
|
|
50
|
-
-
|
|
51
|
-
-
|
|
50
|
+
- All output goes to `.workflow/scratch/brainstorm-{slug}-{date}/`
|
|
51
|
+
- Registers artifact (type=brainstorm) in state.json on completion
|
|
52
52
|
|
|
53
53
|
### Parameters
|
|
54
54
|
|
|
@@ -80,32 +80,21 @@ Phase 3: Single Role Analysis → Detection → Context → Agent → Validation
|
|
|
80
80
|
|
|
81
81
|
### Directory Structure
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
.workflow/phases/{NN}-{slug}/
|
|
86
|
-
├── brainstorm.md # Legacy simple output (if no session)
|
|
87
|
-
├── index.json # Updated timestamps
|
|
88
|
-
└── .brainstorming/ # Full brainstorm session
|
|
89
|
-
├── guidance-specification.md # Phase 2 output
|
|
90
|
-
├── feature-index.json # Phase 4 output
|
|
91
|
-
├── synthesis-changelog.md # Phase 4 audit trail
|
|
92
|
-
├── feature-specs/ # Phase 4 feature specs
|
|
93
|
-
│ ├── F-001-{slug}.md
|
|
94
|
-
│ └── F-00N-{slug}.md
|
|
95
|
-
├── {role}/ # Phase 3 role analyses (immutable)
|
|
96
|
-
│ ├── {role}-context.md
|
|
97
|
-
│ ├── analysis.md
|
|
98
|
-
│ ├── analysis-cross-cutting.md
|
|
99
|
-
│ └── analysis-F-{id}-{slug}.md
|
|
100
|
-
└── synthesis-specification.md # Non-feature mode fallback
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Scratch mode**:
|
|
83
|
+
All brainstorm output goes to scratch:
|
|
104
84
|
```
|
|
105
85
|
.workflow/scratch/brainstorm-{slug}-{date}/
|
|
106
|
-
├──
|
|
107
|
-
|
|
108
|
-
|
|
86
|
+
├── guidance-specification.md # Phase 2 output
|
|
87
|
+
├── feature-index.json # Phase 4 output
|
|
88
|
+
├── synthesis-changelog.md # Phase 4 audit trail
|
|
89
|
+
├── feature-specs/ # Phase 4 feature specs
|
|
90
|
+
│ ├── F-001-{slug}.md
|
|
91
|
+
│ └── F-00N-{slug}.md
|
|
92
|
+
├── {role}/ # Phase 3 role analyses (immutable)
|
|
93
|
+
│ ├── {role}-context.md
|
|
94
|
+
│ ├── analysis.md
|
|
95
|
+
│ ├── analysis-cross-cutting.md
|
|
96
|
+
│ └── analysis-F-{id}-{slug}.md
|
|
97
|
+
└── synthesis-specification.md # Non-feature mode fallback
|
|
109
98
|
```
|
|
110
99
|
|
|
111
100
|
---
|
|
@@ -138,17 +127,8 @@ Parse $ARGUMENTS to determine execution mode:
|
|
|
138
127
|
|
|
139
128
|
**Output Directory Resolution**:
|
|
140
129
|
- Phase mode (number): `.workflow/phases/{NN}-{slug}/.brainstorming/`
|
|
141
|
-
-
|
|
142
|
-
- Existing session: use session
|
|
143
|
-
|
|
144
|
-
**Archive previous brainstorming session** (Phase mode only, skip if `--session` or `--update`):
|
|
145
|
-
```
|
|
146
|
-
PARENT_DIR = parent of output directory (e.g., .workflow/phases/{NN}-{slug}/)
|
|
147
|
-
IF directory exists "${PARENT_DIR}/.brainstorming" AND NOT --session AND NOT --update:
|
|
148
|
-
mkdir -p "${PARENT_DIR}/.history"
|
|
149
|
-
TIMESTAMP = current timestamp formatted as "YYYY-MM-DDTHH-mm-ss"
|
|
150
|
-
mv "${PARENT_DIR}/.brainstorming" "${PARENT_DIR}/.history/.brainstorming-${TIMESTAMP}"
|
|
151
|
-
```
|
|
130
|
+
- All output: `.workflow/scratch/brainstorm-{slug}-{date}/`
|
|
131
|
+
- Existing session: use existing session directory
|
|
152
132
|
|
|
153
133
|
---
|
|
154
134
|
|
package/workflows/execute.md
CHANGED
|
@@ -2,32 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
Wave-based parallel execution with atomic commits, breakpoint resume, and optional sync/reflection.
|
|
4
4
|
|
|
5
|
+
Core principle: **Execute per-plan, not per-phase.** Each plan's wave DAG runs independently. Multiple plans execute sequentially.
|
|
6
|
+
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
## Prerequisites
|
|
8
10
|
|
|
9
|
-
-
|
|
10
|
-
- `index.json` present with `plan.waves` populated
|
|
11
|
+
- Plan exists in scratch directory: `plan.json` + `.task/TASK-*.json`
|
|
11
12
|
- OR: executionContext handoff received from `/workflow:plan`
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
15
|
-
##
|
|
16
|
+
## Plan Resolution
|
|
16
17
|
|
|
17
18
|
```
|
|
18
|
-
Input:
|
|
19
|
+
Input: [phase] argument OR --dir <path>
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
# Worktree scope check
|
|
22
|
+
IF file_exists(".workflow/worktree-scope.json"):
|
|
23
|
+
scope = read(".workflow/worktree-scope.json")
|
|
24
|
+
IF <phase> is a number AND <phase> NOT IN scope.owned_phases:
|
|
25
|
+
ERROR "Phase {phase} not owned by this worktree. Owned: {scope.owned_phases}"
|
|
26
|
+
EXIT
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
# Auto-bootstrap state.json if missing
|
|
29
|
+
IF NOT file_exists(".workflow/state.json"):
|
|
30
|
+
mkdir -p .workflow/scratch/
|
|
31
|
+
Write minimal state.json
|
|
32
|
+
|
|
33
|
+
IF --dir <path> is provided:
|
|
34
|
+
1. Set PLAN_DIRS = [<path>] // single plan
|
|
35
|
+
2. Validate directory exists and contains plan.json
|
|
36
|
+
|
|
37
|
+
ELSE IF no arguments:
|
|
38
|
+
// Find all pending plans for current milestone
|
|
39
|
+
1. Read state.json.artifacts
|
|
40
|
+
2. Filter: milestone == current_milestone, type == "plan", status == "completed"
|
|
41
|
+
3. Exclude plans that already have a corresponding EXC artifact (same path)
|
|
42
|
+
4. Sort by phase order (from roadmap), adhoc plans last
|
|
43
|
+
5. Set PLAN_DIRS = filtered plan paths
|
|
44
|
+
6. If empty: ERROR E001 "No pending plans found"
|
|
45
|
+
|
|
46
|
+
ELSE IF argument is a number:
|
|
47
|
+
// Find pending plans for specific phase
|
|
48
|
+
1. Read state.json.artifacts
|
|
49
|
+
2. Filter: milestone == current_milestone, type == "plan", status == "completed", phase == arg
|
|
50
|
+
3. Exclude plans with existing EXC artifacts
|
|
51
|
+
4. Set PLAN_DIRS = filtered plan paths
|
|
52
|
+
|
|
53
|
+
// Execute plans sequentially
|
|
54
|
+
FOR each PLAN_DIR IN PLAN_DIRS:
|
|
55
|
+
execute_single_plan(PLAN_DIR)
|
|
56
|
+
register_exc_artifact(PLAN_DIR)
|
|
57
|
+
extract_incremental_learnings(PLAN_DIR)
|
|
31
58
|
```
|
|
32
59
|
|
|
33
60
|
---
|
|
@@ -43,11 +70,11 @@ ELSE (standard phase resolution):
|
|
|
43
70
|
|
|
44
71
|
---
|
|
45
72
|
|
|
46
|
-
## E1: Load Plan
|
|
73
|
+
## E1: Load Plan (per PLAN_DIR)
|
|
47
74
|
|
|
48
|
-
**Purpose:** Build or receive the execution queue.
|
|
75
|
+
**Purpose:** Build or receive the execution queue for a single plan.
|
|
49
76
|
|
|
50
|
-
### From executionContext handoff (preferred)
|
|
77
|
+
### From executionContext handoff (preferred, first plan only)
|
|
51
78
|
|
|
52
79
|
```
|
|
53
80
|
If executionContext is available in memory:
|
|
@@ -60,23 +87,22 @@ If executionContext is available in memory:
|
|
|
60
87
|
Skip disk reload
|
|
61
88
|
```
|
|
62
89
|
|
|
63
|
-
### From disk (fallback / resume)
|
|
90
|
+
### From disk (fallback / resume / subsequent plans)
|
|
64
91
|
|
|
65
92
|
```
|
|
66
|
-
Read ${
|
|
67
|
-
Read ${PHASE_DIR}/plan.json
|
|
93
|
+
Read ${PLAN_DIR}/plan.json
|
|
68
94
|
|
|
69
95
|
executionMethod = --method flag || config.json.execution.method || "agent"
|
|
70
96
|
defaultExecutor = --executor flag || config.json.execution.default_executor || "gemini"
|
|
71
|
-
executorAssignments =
|
|
97
|
+
executorAssignments = plan.json.executor_assignments || {}
|
|
72
98
|
```
|
|
73
99
|
|
|
74
100
|
### Detect completed tasks (breakpoint resume)
|
|
75
101
|
|
|
76
102
|
```
|
|
77
103
|
completed_tasks = []
|
|
78
|
-
For each task_id in
|
|
79
|
-
Read
|
|
104
|
+
For each task_id in plan.json.task_ids:
|
|
105
|
+
Read ${PLAN_DIR}/.task/${task_id}.json
|
|
80
106
|
If status == "completed":
|
|
81
107
|
completed_tasks.push(task_id)
|
|
82
108
|
|
|
@@ -89,7 +115,7 @@ If completed_tasks.length > 0:
|
|
|
89
115
|
### Build wave execution queue
|
|
90
116
|
|
|
91
117
|
```
|
|
92
|
-
waves = plan.json.waves
|
|
118
|
+
waves = plan.json.waves
|
|
93
119
|
|
|
94
120
|
execution_queue = []
|
|
95
121
|
For each wave in waves:
|
|
@@ -195,7 +221,9 @@ For each wave in execution_queue (sequential):
|
|
|
195
221
|
Read .workflow/state.json
|
|
196
222
|
If state.json.status != "executing":
|
|
197
223
|
state.json.status = "executing"
|
|
198
|
-
|
|
224
|
+
# Worktree mode: skip phases_summary (reconciled on merge)
|
|
225
|
+
IF NOT file_exists(".workflow/worktree-scope.json"):
|
|
226
|
+
state.json.phases_summary.in_progress += 1
|
|
199
227
|
state.json.last_updated = now()
|
|
200
228
|
Write .workflow/state.json
|
|
201
229
|
|
|
@@ -466,7 +494,7 @@ If config.json.workflow.reflection == true:
|
|
|
466
494
|
- Any blocked tasks?
|
|
467
495
|
- Patterns observed?
|
|
468
496
|
|
|
469
|
-
Append to ${
|
|
497
|
+
Append to ${PLAN_DIR}/reflection-log.md:
|
|
470
498
|
## Reflection - Wave Execution {timestamp}
|
|
471
499
|
- Strategy adjustments: [...]
|
|
472
500
|
- Patterns noted: [...]
|
|
@@ -506,12 +534,50 @@ If NOT SCRATCH_MODE:
|
|
|
506
534
|
|
|
507
535
|
---
|
|
508
536
|
|
|
537
|
+
## E5: Register Artifact & Extract Learnings (per PLAN_DIR)
|
|
538
|
+
|
|
539
|
+
**Purpose:** Register execution completion and extract incremental learnings.
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
// Register EXC artifact
|
|
543
|
+
Read .workflow/state.json
|
|
544
|
+
plan_artifact = state.json.artifacts.find(a => a.type == "plan" && a.path == PLAN_DIR_relative)
|
|
545
|
+
next_id = max(artifacts.filter(a => a.type == "execute").map(a => parseInt(a.id.replace("EXC-","")))) + 1
|
|
546
|
+
|
|
547
|
+
artifact = {
|
|
548
|
+
id: "EXC-{next_id padded to 3}",
|
|
549
|
+
type: "execute",
|
|
550
|
+
milestone: plan_artifact.milestone,
|
|
551
|
+
phase: plan_artifact.phase,
|
|
552
|
+
scope: plan_artifact.scope,
|
|
553
|
+
path: plan_artifact.path, // same path — execute writes into plan dir
|
|
554
|
+
status: "completed",
|
|
555
|
+
depends_on: plan_artifact.id,
|
|
556
|
+
harvested: false,
|
|
557
|
+
created_at: execution_start_time,
|
|
558
|
+
completed_at: now()
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
state.json.artifacts.push(artifact)
|
|
562
|
+
state.json.last_updated = now()
|
|
563
|
+
Write state.json (atomic)
|
|
564
|
+
|
|
565
|
+
// Incremental learning extraction
|
|
566
|
+
Read all ${PLAN_DIR}/.summaries/TASK-*-summary.md
|
|
567
|
+
Extract: strategy adjustments, patterns discovered, pitfalls encountered
|
|
568
|
+
Append to .workflow/specs/learnings.md under "## Entries"
|
|
569
|
+
Mark artifact.harvested = true
|
|
570
|
+
Write state.json (atomic)
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
---
|
|
574
|
+
|
|
509
575
|
## Error Handling
|
|
510
576
|
|
|
511
577
|
| Error | Action |
|
|
512
578
|
|-------|--------|
|
|
513
|
-
|
|
|
514
|
-
|
|
|
579
|
+
| No pending plans found | Abort: "No pending plans. Run /workflow:plan first." |
|
|
580
|
+
| Plan directory not found | Abort: "Plan dir not found." |
|
|
515
581
|
| Task file missing | Skip task, log error, continue wave |
|
|
516
582
|
| Agent spawn fails | Retry once, then mark task as "blocked" |
|
|
517
583
|
| Delegate fails | Resume with `--resume ${fixedId}`, then fallback to agent |
|