maestro-flow 0.4.21 → 0.4.23
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/.agents/skills/maestro-analyze/SKILL.md +78 -34
- package/.agents/skills/maestro-blueprint/SKILL.md +57 -24
- package/.agents/skills/maestro-brainstorm/SKILL.md +69 -34
- package/.agents/skills/maestro-execute/SKILL.md +45 -15
- package/.agents/skills/maestro-grill/SKILL.md +63 -38
- package/.agents/skills/maestro-init/SKILL.md +59 -17
- package/.agents/skills/maestro-milestone-audit/SKILL.md +48 -5
- package/.agents/skills/maestro-milestone-complete/SKILL.md +48 -6
- package/.agents/skills/maestro-milestone-release/SKILL.md +42 -11
- package/.agents/skills/maestro-plan/SKILL.md +19 -13
- package/.agents/skills/maestro-roadmap/SKILL.md +59 -29
- package/.agents/skills/maestro-verify/SKILL.md +46 -11
- package/.agents/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.agents/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.agents/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.agents/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.agents/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.agents/skills/team-swarm/scripts/aco.py +15 -15
- package/.agents/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.agents/skills/team-swarm/scripts/scoring.py +1 -1
- package/.agy/skills/maestro-analyze/SKILL.md +78 -34
- package/.agy/skills/maestro-blueprint/SKILL.md +57 -24
- package/.agy/skills/maestro-brainstorm/SKILL.md +69 -34
- package/.agy/skills/maestro-execute/SKILL.md +45 -15
- package/.agy/skills/maestro-grill/SKILL.md +63 -38
- package/.agy/skills/maestro-init/SKILL.md +59 -17
- package/.agy/skills/maestro-milestone-audit/SKILL.md +48 -5
- package/.agy/skills/maestro-milestone-complete/SKILL.md +48 -6
- package/.agy/skills/maestro-milestone-release/SKILL.md +42 -11
- package/.agy/skills/maestro-plan/SKILL.md +19 -13
- package/.agy/skills/maestro-roadmap/SKILL.md +59 -29
- package/.agy/skills/maestro-verify/SKILL.md +46 -11
- package/.agy/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.agy/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.agy/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.agy/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.agy/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.agy/skills/team-swarm/scripts/aco.py +15 -15
- package/.agy/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.agy/skills/team-swarm/scripts/scoring.py +1 -1
- package/.claude/commands/maestro-analyze.md +78 -34
- package/.claude/commands/maestro-blueprint.md +57 -24
- package/.claude/commands/maestro-brainstorm.md +69 -34
- package/.claude/commands/maestro-execute.md +45 -15
- package/.claude/commands/maestro-grill.md +63 -38
- package/.claude/commands/maestro-init.md +59 -17
- package/.claude/commands/maestro-milestone-audit.md +48 -5
- package/.claude/commands/maestro-milestone-complete.md +48 -6
- package/.claude/commands/maestro-milestone-release.md +42 -11
- package/.claude/commands/maestro-plan.md +19 -13
- package/.claude/commands/maestro-roadmap.md +59 -29
- package/.claude/commands/maestro-verify.md +46 -11
- package/.claude/skills/team-adversarial-swarm/scripts/__pycache__/pheromone.cpython-313.pyc +0 -0
- package/.claude/skills/team-adversarial-swarm/scripts/__pycache__/scoring.cpython-313.pyc +0 -0
- package/.claude/skills/team-adversarial-swarm/scripts/aco.py +15 -15
- package/.claude/skills/team-adversarial-swarm/scripts/pheromone.py +2 -2
- package/.claude/skills/team-adversarial-swarm/scripts/scoring.py +1 -1
- package/.claude/skills/team-swarm/scripts/aco.py +15 -15
- package/.claude/skills/team-swarm/scripts/pheromone.py +2 -2
- package/.claude/skills/team-swarm/scripts/scoring.py +1 -1
- package/package.json +1 -1
- package/workflows/command-authoring.md +823 -0
- package/workflows/interview-mechanics.md +7 -0
|
@@ -89,7 +89,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
89
89
|
paths = SessionPaths(Path(args.session))
|
|
90
90
|
if not paths.config.exists():
|
|
91
91
|
_fail(2, f"config not found: {paths.config}")
|
|
92
|
-
config = json.loads(paths.config.read_text())
|
|
92
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
93
93
|
|
|
94
94
|
paths.ensure_dirs()
|
|
95
95
|
|
|
@@ -107,7 +107,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
107
107
|
"start_nodes": config.get("task_space", {}).get("start_nodes", "any"),
|
|
108
108
|
"edges": config.get("task_space", {}).get("edges", "complete"),
|
|
109
109
|
}
|
|
110
|
-
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False))
|
|
110
|
+
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
111
111
|
|
|
112
112
|
# Initialize pheromone
|
|
113
113
|
aco_cfg = config.get("aco", {})
|
|
@@ -148,9 +148,9 @@ def _pick_start_node(nodes: List[str], state: PheromoneState, mode: str) -> str:
|
|
|
148
148
|
|
|
149
149
|
def cmd_select(args: argparse.Namespace) -> None:
|
|
150
150
|
paths = SessionPaths(Path(args.session))
|
|
151
|
-
config = json.loads(paths.config.read_text())
|
|
151
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
152
152
|
state = PheromoneState.load(paths.pheromone_current)
|
|
153
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
153
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
154
154
|
|
|
155
155
|
n_ants = config.get("swarm", {}).get("n_ants", 5)
|
|
156
156
|
nodes = task_space["nodes"]
|
|
@@ -190,7 +190,7 @@ def _load_iteration_artifacts(paths: SessionPaths, iteration: int) -> List[dict]
|
|
|
190
190
|
artifacts = []
|
|
191
191
|
for f in files:
|
|
192
192
|
try:
|
|
193
|
-
artifacts.append(json.loads(Path(f).read_text()))
|
|
193
|
+
artifacts.append(json.loads(Path(f).read_text(encoding="utf-8")))
|
|
194
194
|
except json.JSONDecodeError as e:
|
|
195
195
|
print(f"warning: skipped malformed artifact {f}: {e}", file=sys.stderr)
|
|
196
196
|
return artifacts
|
|
@@ -213,9 +213,9 @@ def _validate_artifact(art: dict, valid_nodes: set) -> Optional[str]:
|
|
|
213
213
|
|
|
214
214
|
def cmd_update(args: argparse.Namespace) -> None:
|
|
215
215
|
paths = SessionPaths(Path(args.session))
|
|
216
|
-
config = json.loads(paths.config.read_text())
|
|
216
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
217
217
|
state = PheromoneState.load(paths.pheromone_current)
|
|
218
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
218
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
219
219
|
valid_nodes = set(task_space["nodes"])
|
|
220
220
|
|
|
221
221
|
artifacts = _load_iteration_artifacts(paths, args.iter)
|
|
@@ -266,7 +266,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
266
266
|
# Elitist: re-load best history, deposit extra on best path
|
|
267
267
|
best_data = None
|
|
268
268
|
if paths.best.exists():
|
|
269
|
-
best_data = json.loads(paths.best.read_text())
|
|
269
|
+
best_data = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
270
270
|
current_best = max(scored, key=lambda x: x["score"]) if scored else None
|
|
271
271
|
if current_best:
|
|
272
272
|
best_art = next(a for a in artifacts if a["ant_id"] == current_best["ant_id"])
|
|
@@ -281,7 +281,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
281
281
|
"evidence": best_art.get("evidence", []),
|
|
282
282
|
"updated_at": time.time(),
|
|
283
283
|
}
|
|
284
|
-
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False))
|
|
284
|
+
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
285
285
|
# Elite deposit
|
|
286
286
|
state.deposit(best_data["path"], best_data["score"])
|
|
287
287
|
|
|
@@ -292,14 +292,14 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
292
292
|
|
|
293
293
|
# Persist trails
|
|
294
294
|
trails_file = paths.trails / f"{args.iter}.jsonl"
|
|
295
|
-
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log))
|
|
295
|
+
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log), encoding="utf-8")
|
|
296
296
|
|
|
297
297
|
mean_score = sum(s["score"] for s in scored) / len(scored) if scored else 0.0
|
|
298
298
|
best_score = best_data["score"] if best_data else 0.0
|
|
299
299
|
prev_best = 0.0
|
|
300
300
|
history_files = sorted(paths.pheromone_history.glob("*.json"))
|
|
301
301
|
if len(history_files) >= 2:
|
|
302
|
-
prev = json.loads(history_files[-2].read_text())
|
|
302
|
+
prev = json.loads(history_files[-2].read_text(encoding="utf-8"))
|
|
303
303
|
prev_best = prev.get("stats", {}).get("best_known", best_score)
|
|
304
304
|
delta = best_score - prev_best
|
|
305
305
|
|
|
@@ -323,7 +323,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
323
323
|
|
|
324
324
|
def cmd_converged(args: argparse.Namespace) -> None:
|
|
325
325
|
paths = SessionPaths(Path(args.session))
|
|
326
|
-
config = json.loads(paths.config.read_text())
|
|
326
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
327
327
|
cv = config.get("convergence", {})
|
|
328
328
|
|
|
329
329
|
state = PheromoneState.load(paths.pheromone_current)
|
|
@@ -339,7 +339,7 @@ def cmd_converged(args: argparse.Namespace) -> None:
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
if paths.best.exists():
|
|
342
|
-
metrics["best_score"] = json.loads(paths.best.read_text()).get("score", 0.0)
|
|
342
|
+
metrics["best_score"] = json.loads(paths.best.read_text(encoding="utf-8")).get("score", 0.0)
|
|
343
343
|
|
|
344
344
|
# max_iterations
|
|
345
345
|
max_iter = cv.get("max_iterations", 5)
|
|
@@ -397,7 +397,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
397
397
|
|
|
398
398
|
best = None
|
|
399
399
|
if paths.best.exists():
|
|
400
|
-
best = json.loads(paths.best.read_text())
|
|
400
|
+
best = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
401
401
|
|
|
402
402
|
# Top-K trails across all iterations
|
|
403
403
|
all_trails = []
|
|
@@ -410,7 +410,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
410
410
|
# Convergence curve
|
|
411
411
|
curve = []
|
|
412
412
|
for hf in sorted(paths.pheromone_history.glob("*.json"), key=lambda p: int(p.stem)):
|
|
413
|
-
snap = json.loads(hf.read_text())
|
|
413
|
+
snap = json.loads(hf.read_text(encoding="utf-8"))
|
|
414
414
|
curve.append({
|
|
415
415
|
"iteration": snap["iteration"],
|
|
416
416
|
"entropy": snap["stats"]["entropy"],
|
|
@@ -114,11 +114,11 @@ class PheromoneState:
|
|
|
114
114
|
|
|
115
115
|
def save(self, path: Path) -> None:
|
|
116
116
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
-
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False))
|
|
117
|
+
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8")
|
|
118
118
|
|
|
119
119
|
@classmethod
|
|
120
120
|
def load(cls, path: Path) -> "PheromoneState":
|
|
121
|
-
return cls.from_dict(json.loads(path.read_text()))
|
|
121
|
+
return cls.from_dict(json.loads(path.read_text(encoding="utf-8")))
|
|
122
122
|
|
|
123
123
|
def select_neighbors(
|
|
124
124
|
self,
|
|
@@ -62,7 +62,7 @@ def load_verified_scores(scores_file: Path) -> Dict[str, float]:
|
|
|
62
62
|
"""Load pre-computed verified_scores from scorer role output (if exists)."""
|
|
63
63
|
if not scores_file.exists():
|
|
64
64
|
return {}
|
|
65
|
-
data = json.loads(scores_file.read_text())
|
|
65
|
+
data = json.loads(scores_file.read_text(encoding="utf-8"))
|
|
66
66
|
return {
|
|
67
67
|
ant_id: entry["verified_score"]
|
|
68
68
|
for ant_id, entry in data.get("scores", {}).items()
|
|
@@ -89,7 +89,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
89
89
|
paths = SessionPaths(Path(args.session))
|
|
90
90
|
if not paths.config.exists():
|
|
91
91
|
_fail(2, f"config not found: {paths.config}")
|
|
92
|
-
config = json.loads(paths.config.read_text())
|
|
92
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
93
93
|
|
|
94
94
|
paths.ensure_dirs()
|
|
95
95
|
|
|
@@ -107,7 +107,7 @@ def cmd_init(args: argparse.Namespace) -> None:
|
|
|
107
107
|
"start_nodes": config.get("task_space", {}).get("start_nodes", "any"),
|
|
108
108
|
"edges": config.get("task_space", {}).get("edges", "complete"),
|
|
109
109
|
}
|
|
110
|
-
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False))
|
|
110
|
+
paths.task_space.write_text(json.dumps(task_space, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
111
111
|
|
|
112
112
|
# Initialize pheromone
|
|
113
113
|
aco_cfg = config.get("aco", {})
|
|
@@ -148,9 +148,9 @@ def _pick_start_node(nodes: List[str], state: PheromoneState, mode: str) -> str:
|
|
|
148
148
|
|
|
149
149
|
def cmd_select(args: argparse.Namespace) -> None:
|
|
150
150
|
paths = SessionPaths(Path(args.session))
|
|
151
|
-
config = json.loads(paths.config.read_text())
|
|
151
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
152
152
|
state = PheromoneState.load(paths.pheromone_current)
|
|
153
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
153
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
154
154
|
|
|
155
155
|
n_ants = config.get("swarm", {}).get("n_ants", 5)
|
|
156
156
|
nodes = task_space["nodes"]
|
|
@@ -190,7 +190,7 @@ def _load_iteration_artifacts(paths: SessionPaths, iteration: int) -> List[dict]
|
|
|
190
190
|
artifacts = []
|
|
191
191
|
for f in files:
|
|
192
192
|
try:
|
|
193
|
-
artifacts.append(json.loads(Path(f).read_text()))
|
|
193
|
+
artifacts.append(json.loads(Path(f).read_text(encoding="utf-8")))
|
|
194
194
|
except json.JSONDecodeError as e:
|
|
195
195
|
print(f"warning: skipped malformed artifact {f}: {e}", file=sys.stderr)
|
|
196
196
|
return artifacts
|
|
@@ -213,9 +213,9 @@ def _validate_artifact(art: dict, valid_nodes: set) -> Optional[str]:
|
|
|
213
213
|
|
|
214
214
|
def cmd_update(args: argparse.Namespace) -> None:
|
|
215
215
|
paths = SessionPaths(Path(args.session))
|
|
216
|
-
config = json.loads(paths.config.read_text())
|
|
216
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
217
217
|
state = PheromoneState.load(paths.pheromone_current)
|
|
218
|
-
task_space = json.loads(paths.task_space.read_text())
|
|
218
|
+
task_space = json.loads(paths.task_space.read_text(encoding="utf-8"))
|
|
219
219
|
valid_nodes = set(task_space["nodes"])
|
|
220
220
|
|
|
221
221
|
artifacts = _load_iteration_artifacts(paths, args.iter)
|
|
@@ -266,7 +266,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
266
266
|
# Elitist: re-load best history, deposit extra on best path
|
|
267
267
|
best_data = None
|
|
268
268
|
if paths.best.exists():
|
|
269
|
-
best_data = json.loads(paths.best.read_text())
|
|
269
|
+
best_data = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
270
270
|
current_best = max(scored, key=lambda x: x["score"]) if scored else None
|
|
271
271
|
if current_best:
|
|
272
272
|
best_art = next(a for a in artifacts if a["ant_id"] == current_best["ant_id"])
|
|
@@ -281,7 +281,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
281
281
|
"evidence": best_art.get("evidence", []),
|
|
282
282
|
"updated_at": time.time(),
|
|
283
283
|
}
|
|
284
|
-
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False))
|
|
284
|
+
paths.best.write_text(json.dumps(best_data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
285
285
|
# Elite deposit
|
|
286
286
|
state.deposit(best_data["path"], best_data["score"])
|
|
287
287
|
|
|
@@ -292,14 +292,14 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
292
292
|
|
|
293
293
|
# Persist trails
|
|
294
294
|
trails_file = paths.trails / f"{args.iter}.jsonl"
|
|
295
|
-
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log))
|
|
295
|
+
trails_file.write_text("\n".join(json.dumps(t, ensure_ascii=False) for t in trail_log), encoding="utf-8")
|
|
296
296
|
|
|
297
297
|
mean_score = sum(s["score"] for s in scored) / len(scored) if scored else 0.0
|
|
298
298
|
best_score = best_data["score"] if best_data else 0.0
|
|
299
299
|
prev_best = 0.0
|
|
300
300
|
history_files = sorted(paths.pheromone_history.glob("*.json"))
|
|
301
301
|
if len(history_files) >= 2:
|
|
302
|
-
prev = json.loads(history_files[-2].read_text())
|
|
302
|
+
prev = json.loads(history_files[-2].read_text(encoding="utf-8"))
|
|
303
303
|
prev_best = prev.get("stats", {}).get("best_known", best_score)
|
|
304
304
|
delta = best_score - prev_best
|
|
305
305
|
|
|
@@ -323,7 +323,7 @@ def cmd_update(args: argparse.Namespace) -> None:
|
|
|
323
323
|
|
|
324
324
|
def cmd_converged(args: argparse.Namespace) -> None:
|
|
325
325
|
paths = SessionPaths(Path(args.session))
|
|
326
|
-
config = json.loads(paths.config.read_text())
|
|
326
|
+
config = json.loads(paths.config.read_text(encoding="utf-8"))
|
|
327
327
|
cv = config.get("convergence", {})
|
|
328
328
|
|
|
329
329
|
state = PheromoneState.load(paths.pheromone_current)
|
|
@@ -339,7 +339,7 @@ def cmd_converged(args: argparse.Namespace) -> None:
|
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
if paths.best.exists():
|
|
342
|
-
metrics["best_score"] = json.loads(paths.best.read_text()).get("score", 0.0)
|
|
342
|
+
metrics["best_score"] = json.loads(paths.best.read_text(encoding="utf-8")).get("score", 0.0)
|
|
343
343
|
|
|
344
344
|
# max_iterations
|
|
345
345
|
max_iter = cv.get("max_iterations", 5)
|
|
@@ -397,7 +397,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
397
397
|
|
|
398
398
|
best = None
|
|
399
399
|
if paths.best.exists():
|
|
400
|
-
best = json.loads(paths.best.read_text())
|
|
400
|
+
best = json.loads(paths.best.read_text(encoding="utf-8"))
|
|
401
401
|
|
|
402
402
|
# Top-K trails across all iterations
|
|
403
403
|
all_trails = []
|
|
@@ -410,7 +410,7 @@ def cmd_report(args: argparse.Namespace) -> None:
|
|
|
410
410
|
# Convergence curve
|
|
411
411
|
curve = []
|
|
412
412
|
for hf in sorted(paths.pheromone_history.glob("*.json"), key=lambda p: int(p.stem)):
|
|
413
|
-
snap = json.loads(hf.read_text())
|
|
413
|
+
snap = json.loads(hf.read_text(encoding="utf-8"))
|
|
414
414
|
curve.append({
|
|
415
415
|
"iteration": snap["iteration"],
|
|
416
416
|
"entropy": snap["stats"]["entropy"],
|
|
@@ -114,11 +114,11 @@ class PheromoneState:
|
|
|
114
114
|
|
|
115
115
|
def save(self, path: Path) -> None:
|
|
116
116
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
-
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False))
|
|
117
|
+
path.write_text(json.dumps(self.to_dict(), indent=2, ensure_ascii=False), encoding="utf-8")
|
|
118
118
|
|
|
119
119
|
@classmethod
|
|
120
120
|
def load(cls, path: Path) -> "PheromoneState":
|
|
121
|
-
return cls.from_dict(json.loads(path.read_text()))
|
|
121
|
+
return cls.from_dict(json.loads(path.read_text(encoding="utf-8")))
|
|
122
122
|
|
|
123
123
|
def select_neighbors(
|
|
124
124
|
self,
|
|
@@ -62,7 +62,7 @@ def load_verified_scores(scores_file: Path) -> Dict[str, float]:
|
|
|
62
62
|
"""Load pre-computed verified_scores from scorer role output (if exists)."""
|
|
63
63
|
if not scores_file.exists():
|
|
64
64
|
return {}
|
|
65
|
-
data = json.loads(scores_file.read_text())
|
|
65
|
+
data = json.loads(scores_file.read_text(encoding="utf-8"))
|
|
66
66
|
return {
|
|
67
67
|
ant_id: entry["verified_score"]
|
|
68
68
|
for ant_id, entry in data.get("scores", {}).items()
|
|
@@ -22,6 +22,8 @@ Combines structured 6-dimension scoring with iterative deepening and decision ex
|
|
|
22
22
|
Use `-q` for quick decision extraction only (skip exploration + scoring).
|
|
23
23
|
|
|
24
24
|
Use `--gaps` for issue-focused root cause analysis (replaces manage-issue-analyze). Loads issues from issues.jsonl, performs CLI exploration against issue context/location, synthesizes root cause into issue.analysis, and outputs context.md for downstream `plan --gaps`.
|
|
25
|
+
|
|
26
|
+
Pipeline position: downstream of maestro-grill, maestro-brainstorm, and maestro-blueprint (optional upstream enrichment); upstream of maestro-plan and maestro-roadmap (consumes analysis context).
|
|
25
27
|
</purpose>
|
|
26
28
|
|
|
27
29
|
<required_reading>
|
|
@@ -47,31 +49,47 @@ $ARGUMENTS -- phase number for micro mode, topic text for macro/adhoc mode, no a
|
|
|
47
49
|
- Mixed input like `"1 phase"` is treated as text → macro mode (only bare numerics trigger micro)
|
|
48
50
|
|
|
49
51
|
**Flags:**
|
|
50
|
-
- `-y` / `--yes`: Auto mode — skip interactive scoping, use recommended defaults, auto-deepen
|
|
51
|
-
- `-c` / `--continue`: Resume from existing session (auto-detect session folder + discussion.md)
|
|
52
|
-
- `-q` / `--quick`: Quick mode — skip exploration + scoring, go straight to decision extraction (context.md only)
|
|
53
|
-
- `--from <source>`: Load upstream context package (grill:ID, brainstorm:ID, blueprint:BLP-xxx, @file, or path)
|
|
54
|
-
- `--gaps [ISS-ID]`: Issue root cause analysis mode. If ISS-ID provided, analyze single issue. If omitted, analyze all open/registered issues from issues.jsonl.
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
| Flag | Effect | Default |
|
|
54
|
+
|------|--------|---------|
|
|
55
|
+
| `-y` / `--yes` | Auto mode — skip interactive scoping, use recommended defaults, auto-deepen | false |
|
|
56
|
+
| `-c` / `--continue` | Resume from existing session (auto-detect session folder + discussion.md) | false |
|
|
57
|
+
| `-q` / `--quick` | Quick mode — skip exploration + scoring, go straight to decision extraction (context.md only) | false |
|
|
58
|
+
| `--from <source>` | Load upstream context package (grill:ID, brainstorm:ID, blueprint:BLP-xxx, @file, or path) | — |
|
|
59
|
+
| `--gaps [ISS-ID]` | Issue root cause analysis mode. If ISS-ID provided, analyze single issue. If omitted, analyze all open/registered issues from issues.jsonl | — |
|
|
60
|
+
|
|
61
|
+
**Scope routing:**
|
|
62
|
+
| Input | Mode | Scope |
|
|
63
|
+
|-------|------|-------|
|
|
64
|
+
| Pure digits (e.g. `1`, `42`) | micro | Phase-level deep analysis |
|
|
65
|
+
| Non-numeric text (e.g. `auth-refactor`) | macro | Topic impact surface |
|
|
66
|
+
| No positional arg + roadmap | micro | Milestone-wide |
|
|
67
|
+
| No positional arg + no roadmap | macro | Fallback |
|
|
68
|
+
| `--gaps [ISS-ID]` | gaps | Issue root cause analysis |
|
|
69
|
+
|
|
70
|
+
Output directory format, artifact registration schema, and output artifact listing are defined in workflow analyze.md (Output Structure section).
|
|
71
|
+
|
|
72
|
+
### Pre-load
|
|
73
|
+
|
|
74
|
+
1. **Codebase docs**: IF `.workflow/codebase/doc-index.json` exists → Read ARCHITECTURE.md for module boundaries
|
|
75
|
+
2. **Specs**: `maestro spec load --category arch` — load architecture constraints
|
|
76
|
+
3. **Wiki search**: `maestro wiki search "{topic keywords}" --json` → top 5-10 entries as prior knowledge
|
|
77
|
+
4. All optional — proceed without if unavailable (log warning)
|
|
57
78
|
|
|
58
79
|
### Role Knowledge
|
|
59
80
|
`maestro wiki list --category debug` → select relevant → `maestro wiki load`
|
|
60
81
|
</context>
|
|
61
82
|
|
|
62
83
|
<interview_protocol>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Exit: when all decision points are settled (or user explicitly signals to proceed), finalize session metadata. The decision table (populated incrementally during interview) uses this schema:
|
|
74
|
-
`| # | Decision | Choice | Source (user / code / default) |`
|
|
84
|
+
Follows @~/.maestro/workflows/interview-mechanics.md standard.
|
|
85
|
+
|
|
86
|
+
**Interaction mode**: convergent menu-driven
|
|
87
|
+
**Decision tree** (strict order): scope (phase / topic / milestone-wide / adhoc / --gaps) → depth (quick / standard / deep) → dimensions (which of the 6 to keep) → Go/No-Go threshold
|
|
88
|
+
**Scope guard**: only analyze decisions; do not prejudge plan/execute concerns
|
|
89
|
+
**Writeback target**: discussion.md (top table) + context.md "Interview Decisions"
|
|
90
|
+
**Additional search sources**: issues.jsonl (--gaps mode), roadmap.md
|
|
91
|
+
**Additional skip conditions**: input is already specific (explicit phase number or unambiguous topic)
|
|
92
|
+
**Exit condition**: all decision points settled → finalize session metadata
|
|
75
93
|
</interview_protocol>
|
|
76
94
|
|
|
77
95
|
<execution>
|
|
@@ -108,23 +126,52 @@ Phase 4: Output context.md for downstream plan --gaps
|
|
|
108
126
|
- `large` (3+ independent subsystems or hard serial dependencies) → suggest `/maestro-roadmap --from analyze:ANL-xxx`
|
|
109
127
|
- `medium` (1-2 subsystems, parallelizable) → suggest `/maestro-plan --from analyze:ANL-xxx`
|
|
110
128
|
- `small` (single-file or few-file change) → suggest `/maestro-plan --from analyze:ANL-xxx`
|
|
129
|
+
</execution>
|
|
111
130
|
|
|
112
|
-
|
|
131
|
+
<completion>
|
|
132
|
+
### Standalone report
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
```
|
|
135
|
+
=== ANALYSIS READY ===
|
|
136
|
+
Artifact: ANL-{id}
|
|
137
|
+
Scope: {micro|macro|adhoc|gaps}
|
|
138
|
+
Go/No-Go: {GO|NO-GO|CONDITIONAL}
|
|
139
|
+
Confidence: {high|medium|low}
|
|
140
|
+
Outputs: analysis.md, context.md, conclusions.json, discussion.md
|
|
141
|
+
Session dir: {output_dir}
|
|
142
|
+
===
|
|
143
|
+
```
|
|
118
144
|
|
|
119
|
-
|
|
120
|
-
- scope_verdict = large → `/maestro-roadmap --from analyze:ANL-xxx`
|
|
121
|
-
- scope_verdict = medium/small → `/maestro-plan --from analyze:ANL-xxx`
|
|
122
|
-
- Need more exploration → `/maestro-analyze {topic} -c`
|
|
145
|
+
### Ralph-invoked completion
|
|
123
146
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
147
|
+
End the step by calling the CLI (no text block output):
|
|
148
|
+
```
|
|
149
|
+
maestro ralph complete <idx> --status {STATUS} [--evidence {path}]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Status verdicts:
|
|
153
|
+
- **DONE** — Normal completion
|
|
154
|
+
- **DONE_WITH_CONCERNS** — Completed with caveats; pass `--concerns`
|
|
155
|
+
- **NEEDS_RETRY** — Tooling error / transient issue; ralph will retry
|
|
156
|
+
- **BLOCKED** — External hard blocker; pass `--reason`
|
|
157
|
+
|
|
158
|
+
### Next-step routing
|
|
159
|
+
|
|
160
|
+
| Condition | Suggestion |
|
|
161
|
+
|-----------|-----------|
|
|
162
|
+
| Phase/Milestone scope, Go, UI work needed | `/maestro-impeccable build {target}` |
|
|
163
|
+
| Phase/Milestone scope, Go, ready to plan | `/maestro-plan` or `/maestro-plan {phase}` |
|
|
164
|
+
| Phase/Milestone scope, No-Go | Revisit requirements or `/maestro-brainstorm {topic}` |
|
|
165
|
+
| Macro/Adhoc, scope_verdict = large | `/maestro-roadmap --from analyze:ANL-xxx` |
|
|
166
|
+
| Macro/Adhoc, scope_verdict = medium/small | `/maestro-plan --from analyze:ANL-xxx` |
|
|
167
|
+
| Need more exploration | `/maestro-analyze {topic} -c` |
|
|
168
|
+
| Gaps scope, issues analyzed | `/maestro-plan --gaps` |
|
|
169
|
+
| Gaps scope, need more context | `/maestro-analyze --gaps {ISS-ID}` |
|
|
170
|
+
|
|
171
|
+
### Session seal
|
|
172
|
+
|
|
173
|
+
@~/.maestro/workflows/finish-work.md — SESSION_DIR=OUTPUT_DIR, SESSION_TYPE=analyze, SESSION_ID={artifact_id}, LINKED_MILESTONE={target_milestone or null}
|
|
174
|
+
</completion>
|
|
128
175
|
|
|
129
176
|
<error_codes>
|
|
130
177
|
| Code | Severity | Condition | Recovery |
|
|
@@ -168,6 +215,3 @@ Both modes (full + quick):
|
|
|
168
215
|
- [ ] Session sealed via finish-work (archive.json written, optional spec/knowhow extraction)
|
|
169
216
|
</success_criteria>
|
|
170
217
|
|
|
171
|
-
<on_complete>
|
|
172
|
-
@~/.maestro/workflows/finish-work.md — SESSION_DIR=OUTPUT_DIR, SESSION_TYPE=analyze, SESSION_ID={artifact_id}, LINKED_MILESTONE={target_milestone or null}
|
|
173
|
-
</on_complete>
|
|
@@ -22,6 +22,8 @@ Parallel to `brainstorm` as an upstream origin command:
|
|
|
22
22
|
- **blueprint** = convergent documentation (heavyweight, 6-phase formal spec chain)
|
|
23
23
|
|
|
24
24
|
Output: `.workflow/blueprint/BLP-{slug}-{date}/` containing Product Brief, PRD, Architecture, and Epics.
|
|
25
|
+
|
|
26
|
+
Pipeline position: downstream of maestro-brainstorm (optional). Upstream of maestro-analyze, maestro-roadmap, and maestro-plan.
|
|
25
27
|
</purpose>
|
|
26
28
|
|
|
27
29
|
<required_reading>
|
|
@@ -36,10 +38,13 @@ Output: `.workflow/blueprint/BLP-{slug}-{date}/` containing Product Brief, PRD,
|
|
|
36
38
|
$ARGUMENTS -- idea text, @file reference, or upstream context source.
|
|
37
39
|
|
|
38
40
|
**Flags:**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
| Flag | Effect | Default |
|
|
43
|
+
|------|--------|---------|
|
|
44
|
+
| `-y` / `--yes` | Auto mode — skip interactive questions, use recommended defaults | false |
|
|
45
|
+
| `-c` / `--continue` | Resume from last checkpoint (reads blueprint-config.json) | false |
|
|
46
|
+
| `--from <source>` | Load upstream context package (brainstorm:ID, @file, or path). Consumes context-package.json | — |
|
|
47
|
+
| `--from-brainstorm SESSION-ID` | Backward compat alias for `--from brainstorm:ID` | — |
|
|
43
48
|
|
|
44
49
|
**Input types:**
|
|
45
50
|
- Direct text: `"Build a real-time collaboration platform with WebSocket"`
|
|
@@ -58,23 +63,22 @@ maestro-analyze → maestro-roadmap → maestro-plan
|
|
|
58
63
|
|
|
59
64
|
**Output boundary**: ALL file writes MUST target `.workflow/blueprint/BLP-{slug}-{date}/` or `.workflow/state.json` only. NEVER modify source code or files outside these paths.
|
|
60
65
|
|
|
61
|
-
### Pre-load
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
### Pre-load
|
|
67
|
+
|
|
68
|
+
1. **Specs**: `maestro spec load --category arch` — load architecture constraints for Phase 4 decisions
|
|
69
|
+
2. **Wiki search**: `maestro wiki search "{topic keywords}" --json` → prior knowledge context
|
|
70
|
+
3. All optional — proceed without if unavailable
|
|
64
71
|
</context>
|
|
65
72
|
|
|
66
73
|
<interview_protocol>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Decision points: scope (full product / feature set / single feature) → spec type (service / api / library / platform) → focus areas → whether to run codebase exploration.
|
|
76
|
-
|
|
77
|
-
Exit: on consensus or explicit user signal to proceed, finalize blueprint-config.json (decisions already written incrementally) and proceed to Phase 1.
|
|
74
|
+
Follows @~/.maestro/workflows/interview-mechanics.md standard.
|
|
75
|
+
|
|
76
|
+
**Interaction mode**: convergent menu-driven, depth-first
|
|
77
|
+
**Decision tree** (strict depth-first): scope (full product / feature set / single feature) → spec type (service / api / library / platform) → focus areas → whether to run codebase exploration → requirement priorities
|
|
78
|
+
**Scope guard**: only specification shape; do not pre-resolve roadmap phases or plan tasks
|
|
79
|
+
**Writeback target**: blueprint-config.json (each decision persisted before next question)
|
|
80
|
+
**Additional skip conditions**: none beyond standard (-y, -c)
|
|
81
|
+
**Exit condition**: all decision points settled → finalize blueprint-config.json, proceed to Phase 1
|
|
78
82
|
</interview_protocol>
|
|
79
83
|
|
|
80
84
|
<execution>
|
|
@@ -88,15 +92,44 @@ P0: Spec Study → P1: Discovery → P1.5: Req Expansion → P2: Product Brief
|
|
|
88
92
|
|
|
89
93
|
P6 gate: Pass (>=80%) → Handoff | Review (60-79%) → Handoff w/caveats | Fail (<60%) → P6.5 Auto-Fix (max 2 iter) → re-check
|
|
90
94
|
|
|
91
|
-
|
|
95
|
+
</execution>
|
|
96
|
+
|
|
97
|
+
<completion>
|
|
98
|
+
### Standalone report
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
=== BLUEPRINT READY ===
|
|
102
|
+
Session: BLP-{slug}-{date}
|
|
103
|
+
Phases completed: P0–P6
|
|
104
|
+
Readiness score: {score}%
|
|
105
|
+
Gate verdict: {Pass|Review|Fail}
|
|
106
|
+
Output: .workflow/blueprint/BLP-{slug}-{date}/
|
|
107
|
+
Key artifacts: product-brief.md, requirements/, architecture/, epics/, readiness-report.md
|
|
108
|
+
===
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Ralph-invoked completion
|
|
112
|
+
|
|
113
|
+
End the step by calling the CLI (no text block output):
|
|
114
|
+
```
|
|
115
|
+
maestro ralph complete <idx> --status {STATUS} [--evidence {path}]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Status verdicts:
|
|
119
|
+
- **DONE** — Normal completion
|
|
120
|
+
- **DONE_WITH_CONCERNS** — Completed with caveats; pass `--concerns`
|
|
121
|
+
- **NEEDS_RETRY** — Tooling error / transient issue; ralph will retry
|
|
122
|
+
- **BLOCKED** — External hard blocker; pass `--reason`
|
|
123
|
+
|
|
124
|
+
### Next-step routing
|
|
92
125
|
|
|
93
126
|
| Condition | Suggestion |
|
|
94
127
|
|-----------|-----------|
|
|
95
|
-
| Need codebase analysis |
|
|
96
|
-
| Ready for roadmap |
|
|
97
|
-
| Small scope, direct plan |
|
|
98
|
-
| Need project setup |
|
|
99
|
-
</
|
|
128
|
+
| Need codebase analysis | `/maestro-analyze {topic} --from blueprint:BLP-xxx` |
|
|
129
|
+
| Ready for roadmap | `/maestro-roadmap --from blueprint:BLP-xxx` |
|
|
130
|
+
| Small scope, direct plan | `/maestro-plan --from blueprint:BLP-xxx` |
|
|
131
|
+
| Need project setup | `/maestro-init` |
|
|
132
|
+
</completion>
|
|
100
133
|
|
|
101
134
|
<error_codes>
|
|
102
135
|
| Code | Severity | Condition | Recovery |
|