maestro-flow 0.4.14 → 0.4.15
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/SKILL.md +11 -31
- package/.agents/skills/maestro-ralph/SKILL.md +49 -47
- package/.agents/skills/maestro-ralph-execute/SKILL.md +31 -57
- package/.agy/skills/maestro/SKILL.md +11 -31
- package/.agy/skills/maestro-ralph/SKILL.md +49 -47
- package/.agy/skills/maestro-ralph-execute/SKILL.md +31 -57
- package/.claude/commands/maestro-ralph-execute.md +31 -57
- package/.claude/commands/maestro-ralph.md +49 -47
- package/.claude/commands/maestro.md +11 -31
- package/dist/src/commands/hooks.d.ts +30 -3
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +138 -11
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/install-backend.d.ts +49 -4
- package/dist/src/commands/install-backend.d.ts.map +1 -1
- package/dist/src/commands/install-backend.js +163 -53
- package/dist/src/commands/install-backend.js.map +1 -1
- package/dist/src/commands/install.d.ts.map +1 -1
- package/dist/src/commands/install.js +45 -10
- package/dist/src/commands/install.js.map +1 -1
- package/dist/src/commands/uninstall.d.ts.map +1 -1
- package/dist/src/commands/uninstall.js +25 -38
- package/dist/src/commands/uninstall.js.map +1 -1
- package/dist/src/core/manifest.d.ts +43 -0
- package/dist/src/core/manifest.d.ts.map +1 -1
- package/dist/src/core/manifest.js +37 -1
- package/dist/src/core/manifest.js.map +1 -1
- package/dist/src/tui/install-ui/ExecutionView.d.ts.map +1 -1
- package/dist/src/tui/install-ui/ExecutionView.js +13 -5
- package/dist/src/tui/install-ui/ExecutionView.js.map +1 -1
- package/dist/src/tui/install-ui/InstallExecution.d.ts.map +1 -1
- package/dist/src/tui/install-ui/InstallExecution.js +87 -45
- package/dist/src/tui/install-ui/InstallExecution.js.map +1 -1
- package/dist/src/tui/uninstall-ui/UninstallFlow.d.ts.map +1 -1
- package/dist/src/tui/uninstall-ui/UninstallFlow.js +12 -28
- package/dist/src/tui/uninstall-ui/UninstallFlow.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ Closed-loop decision engine for the maestro workflow lifecycle.
|
|
|
17
17
|
Reads project state → infers position → builds adaptive chain → delegates execution.
|
|
18
18
|
|
|
19
19
|
Entry points:
|
|
20
|
-
- **`/maestro-ralph "intent"`** — New session: infer → decompose → build →
|
|
20
|
+
- **`/maestro-ralph "intent"`** — New session: infer → decompose → build → emit /goal prompt(如有 decomposition)→ dispatch ralph-execute
|
|
21
21
|
- **`/maestro-ralph continue`** — Wrapper; dispatches to ralph-execute(首选直接 `/maestro-ralph-execute` 推进 step)
|
|
22
22
|
- **`/maestro-ralph status`** — Display session progress
|
|
23
23
|
|
|
@@ -25,10 +25,9 @@ Entry points:
|
|
|
25
25
|
|
|
26
26
|
Initial decomposition (S_DECOMPOSE): boundary-clarified via ≤3 questions for broad intents (重构/全面/迁移/重写). 写入 status.json 的 `boundary_contract` / `execution_criteria` / `task_decomposition`,附 `/goal` prompt。
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
- **decision**:
|
|
31
|
-
- **external**: 仅在显式声明时使用(`maestro delegate --to claude`)
|
|
28
|
+
Step kinds:
|
|
29
|
+
- **执行 step**: ralph-execute `Read({command_path})` 命令 .md,按内容内联执行
|
|
30
|
+
- **decision step**: `step.decision` 字段非空;回 ralph 评估(CLI 只读分析)
|
|
32
31
|
|
|
33
32
|
Key difference from maestro coordinator:
|
|
34
33
|
- maestro: static chain → one-time selection → runs all steps
|
|
@@ -45,8 +44,8 @@ Mutual invocation with `/maestro-ralph-execute` forms a self-perpetuating work l
|
|
|
45
44
|
│ writes status.json
|
|
46
45
|
│ emits /goal prompt
|
|
47
46
|
▼
|
|
48
|
-
ralph-execute ◀─┐
|
|
49
|
-
│ │ decision → Skill("maestro-ralph")
|
|
47
|
+
ralph-execute ◀─┐ 执行 step → Read(command_path) inline
|
|
48
|
+
│ │ decision step → Skill("maestro-ralph")
|
|
50
49
|
└─────────┘ writes step.completion_confirmed
|
|
51
50
|
loop until all completion_confirmed | paused
|
|
52
51
|
```
|
|
@@ -70,14 +69,14 @@ Remaining → intent
|
|
|
70
69
|
|
|
71
70
|
<invariants>
|
|
72
71
|
1. **Ralph never executes steps** — only creates sessions and evaluates decisions
|
|
73
|
-
2. **Handoff via Skill("maestro-ralph-execute")** —
|
|
72
|
+
2. **Handoff via Skill("maestro-ralph-execute")** — 创建 session 后始终自动 handoff;decision 评估后始终 handoff
|
|
74
73
|
3. **Decision delegates read-only** — `maestro delegate --role analyze --mode analysis`
|
|
75
|
-
4.
|
|
74
|
+
4. **执行 step 通过 Read 命令 .md 内联执行**
|
|
76
75
|
5. **status.json 是唯一真源** — 不生成 markdown 清单或侧文件
|
|
77
76
|
6. **每个 step 必须 `completion_confirmed: true`** — 基于 `--- COMPLETION STATUS ---` 的 `STATUS: DONE`;缺失则视为未完成
|
|
78
77
|
7. **command_path 在 A_BUILD_STEPS 解析** — 全局优先 `~/.claude/commands/{name}.md`,fallback 项目 `.claude/commands/{name}.md`,写入 status.json
|
|
79
|
-
8.
|
|
80
|
-
9. **Decomposition is outcome-oriented** — sub-goals 为可观测交付,禁止 lifecycle 复刻;`/goal` 用户绑定,ralph
|
|
78
|
+
8. **执行 step 加载契约** — ralph-execute 读 `command_path` 后,必须解析并加载该命令 `<required_reading>` 引用的所有文件("入口 + workflow"形式的核心),并把 `<deferred_reading>` 路径记录到 `step.deferred_reads`;加载完成后输出 `✓ skill {name} 加载完成`。ralph 在 build 阶段只解析路径,不读 .md 内容
|
|
79
|
+
9. **Decomposition is outcome-oriented** — sub-goals 为可观测交付,禁止 lifecycle 复刻;`/goal` 用户绑定,ralph 输出提示词后继续 handoff,用户可在执行过程中随时输入 `/goal`
|
|
81
80
|
10. **planning_mode governs arg granularity** — `unified` → skill args 无 `{phase}`;`independent` → 含 `{phase}`
|
|
82
81
|
11. **task_decomposition 驱动 steps[] 动态生长** — `post-goal-audit` 按 unmet 子目标插入 scoped mini-loop;字段可选/累加,既有字段不删不改
|
|
83
82
|
</invariants>
|
|
@@ -149,9 +148,8 @@ S_BUILD_CHAIN:
|
|
|
149
148
|
→ S_CREATE_SESSION DO: A_BUILD_STEPS
|
|
150
149
|
|
|
151
150
|
S_CREATE_SESSION:
|
|
152
|
-
→
|
|
153
|
-
→
|
|
154
|
-
→ S_DISPATCH WHEN: auto_confirm AND no decomposition DO: A_CREATE_SESSION
|
|
151
|
+
→ S_CONFIRM WHEN: not auto_confirm DO: A_CREATE_SESSION
|
|
152
|
+
→ S_DISPATCH WHEN: auto_confirm DO: A_CREATE_SESSION
|
|
155
153
|
|
|
156
154
|
S_CONFIRM:
|
|
157
155
|
→ S_DISPATCH WHEN: user selects "Proceed"
|
|
@@ -161,7 +159,7 @@ S_CONFIRM:
|
|
|
161
159
|
S_DISPATCH:
|
|
162
160
|
→ END DO: Skill({ skill: "maestro-ralph-execute" })
|
|
163
161
|
|
|
164
|
-
S_DECISION_EVAL:
|
|
162
|
+
S_DECISION_EVAL: (decision 节点 == `step.decision` 非空,下述 gate 名取自该字段)
|
|
165
163
|
→ S_APPLY_VERDICT WHEN: quality-gate (post-verify, post-business-test, post-review, post-test)
|
|
166
164
|
DO: A_DELEGATE_EVALUATE
|
|
167
165
|
→ S_APPLY_VERDICT WHEN: goal-gate (post-goal-audit)
|
|
@@ -200,7 +198,7 @@ S_FALLBACK:
|
|
|
200
198
|
|
|
201
199
|
1. Find latest ralph session (by created_at)
|
|
202
200
|
2. Display: Session, Status, Position, Progress, Current step
|
|
203
|
-
3. List steps: [✓] completion_confirmed, [▸] current, [ ] pending, [◆] decision
|
|
201
|
+
3. List steps: [✓] completion_confirmed, [▸] current, [ ] pending, [◆] decision(`step.decision` 非空);执行 step 附 `command_scope`(global/project) + `command_path`
|
|
204
202
|
4. If `task_decomposition` present (absent → skip):
|
|
205
203
|
```
|
|
206
204
|
Sub-goals ({done}/{total}) source: {session_dir}/status.json#/task_decomposition
|
|
@@ -380,24 +378,26 @@ narrow → derive defaults from intent + codebase, skip questions.
|
|
|
380
378
|
|
|
381
379
|
Generate steps from `session.lifecycle_position` to `milestone-complete`.
|
|
382
380
|
|
|
383
|
-
| Stage | Skill (independent) | Skill (unified) |
|
|
384
|
-
|
|
385
|
-
| brainstorm | `maestro-brainstorm "{intent}"` | *(same)* |
|
|
386
|
-
| blueprint | `maestro-blueprint "{intent}"` | *(same)* |
|
|
387
|
-
| init | `maestro-init` | *(same)* |
|
|
388
|
-
| analyze-macro | `maestro-analyze "{intent}"` | *(same)* |
|
|
389
|
-
| roadmap | `maestro-roadmap --from analyze:{analyze_macro_id}` | *(same)* |
|
|
390
|
-
| analyze | `maestro-analyze {phase}` | `maestro-analyze` |
|
|
391
|
-
| plan | `maestro-plan {phase}` *(scope=phase)* / `maestro-plan --from analyze:{analyze_macro_id}` *(scope=standalone)* / `maestro-plan --from blueprint:{blueprint_id}` *(scope=standalone)* | `maestro-plan` |
|
|
392
|
-
| execute | `maestro-execute {phase}` | `maestro-execute` |
|
|
393
|
-
| verify | `maestro-verify {phase}` | `maestro-verify` |
|
|
394
|
-
| business-test | `quality-auto-test {phase}` | `quality-auto-test` |
|
|
395
|
-
| review | `quality-review {phase}` | `quality-review` |
|
|
396
|
-
| test-gen | `quality-auto-test {phase}` | `quality-auto-test` |
|
|
397
|
-
| test | `quality-test {phase}` | `quality-test` |
|
|
398
|
-
| milestone-audit | `maestro-milestone-audit` | *(same)* |
|
|
399
|
-
| goal-audit | *(decision-only)* | *(same)* |
|
|
400
|
-
| milestone-complete | `maestro-milestone-complete` | *(same)* |
|
|
381
|
+
| Stage | Skill (independent) | Skill (unified) | Decision after | quality_mode |
|
|
382
|
+
|-------|---------------------|-----------------|----------------|--------------|
|
|
383
|
+
| brainstorm | `maestro-brainstorm "{intent}"` | *(same)* | — | all |
|
|
384
|
+
| blueprint | `maestro-blueprint "{intent}"` | *(same)* | — | all |
|
|
385
|
+
| init | `maestro-init` | *(same)* | — | all |
|
|
386
|
+
| analyze-macro | `maestro-analyze "{intent}"` | *(same)* | `post-analyze-scope` | all |
|
|
387
|
+
| roadmap | `maestro-roadmap --from analyze:{analyze_macro_id}` | *(same)* | — | all |
|
|
388
|
+
| analyze | `maestro-analyze {phase}` | `maestro-analyze` | — | all |
|
|
389
|
+
| plan | `maestro-plan {phase}` *(scope=phase)* / `maestro-plan --from analyze:{analyze_macro_id}` *(scope=standalone)* / `maestro-plan --from blueprint:{blueprint_id}` *(scope=standalone)* | `maestro-plan` | — | all |
|
|
390
|
+
| execute | `maestro-execute {phase}` | `maestro-execute` | — | all |
|
|
391
|
+
| verify | `maestro-verify {phase}` | `maestro-verify` | `post-verify` | all |
|
|
392
|
+
| business-test | `quality-auto-test {phase}` | `quality-auto-test` | `post-business-test` | full only |
|
|
393
|
+
| review | `quality-review {phase}` | `quality-review` | `post-review` | all (quick: append `--tier quick`) |
|
|
394
|
+
| test-gen | `quality-auto-test {phase}` | `quality-auto-test` | — | full / standard if coverage<80% |
|
|
395
|
+
| test | `quality-test {phase}` | `quality-test` | `post-test` | full, standard |
|
|
396
|
+
| milestone-audit | `maestro-milestone-audit` | *(same)* | — | all |
|
|
397
|
+
| goal-audit | *(decision-only)* | *(same)* | `post-goal-audit` | all (only if decomposed) |
|
|
398
|
+
| milestone-complete | `maestro-milestone-complete` | *(same)* | `post-milestone` | all |
|
|
399
|
+
|
|
400
|
+
> 所有执行 stage 统一通过 Read .md 内联执行;decision 节点单独作为独立 step 插入(见规则 4)。
|
|
401
401
|
|
|
402
402
|
**Build rules (按顺序应用):**
|
|
403
403
|
|
|
@@ -405,17 +405,17 @@ Generate steps from `session.lifecycle_position` to `milestone-complete`.
|
|
|
405
405
|
1. **起点**:从 `session.lifecycle_position` 开始
|
|
406
406
|
2. **跳过已完成**:跳过当前 milestone+phase 下已有 completed artifact 的 stage(按 `session.phase` 过滤);unified 按 milestone 过滤
|
|
407
407
|
3. **quality_mode 过滤**:按 `session.quality_mode` 排除不匹配 stage
|
|
408
|
-
4. **决策节点**:每个 Decision after 非空的 stage 之后插入 `{
|
|
408
|
+
4. **决策节点**:每个 Decision after 非空的 stage 之后插入 `{ decision: "<gate>", retry_count: 0, max_retries: 2, command_scope: null, command_path: null }`
|
|
409
409
|
5. **goal-audit 插入**:`task_decomposition` 存在时,在最后一个 evidence-producing stage(verify/review/test)之后、`milestone-complete` 之前插入 `decision:post-goal-audit`
|
|
410
410
|
6. **终点硬约束**:chain 以 `milestone-complete` 结尾
|
|
411
411
|
7. **goal_ref 传播**:`task_decomposition` 存在时,每个 step 按 `step.stage ∈ g.lifecycle` 匹配 `step.goal_ref = g.id`(多匹配取字典序最小);decision 节点不打 goal_ref
|
|
412
412
|
8. **占位符**:independent 保留 `{phase}` `{intent}`;unified 不带 `{phase}`
|
|
413
|
-
9. **command_path
|
|
413
|
+
9. **command_path 解析**(每个执行 step,decision 节点跳过):
|
|
414
414
|
- 取 skill 名(args 前的第一个 token)
|
|
415
415
|
- 全局优先:`~/.claude/commands/{name}.md` 存在 → `command_scope = "global"`
|
|
416
416
|
- Fallback:`.claude/commands/{name}.md` 存在 → `command_scope = "project"`
|
|
417
417
|
- 两者都缺 → `command_scope = "missing"`, `command_path = null`,A_CREATE_SESSION 报错 E006
|
|
418
|
-
- **不在 build 阶段读取 .md 内容**;`<required_reading>` / `<deferred_reading>` 解析与加载由 ralph-execute
|
|
418
|
+
- **不在 build 阶段读取 .md 内容**;`<required_reading>` / `<deferred_reading>` 解析与加载由 ralph-execute A_EXEC_STEP 负责(保持入口/工作流分离)
|
|
419
419
|
10. **每个 step 初始化** `completion_confirmed: false`, `completion_status: null`, `completion_evidence: null`, `deferred_reads: []`
|
|
420
420
|
11. **scope_verdict gating**(仅当 chain 起点 = `analyze-macro`):
|
|
421
421
|
- `scope_verdict ∈ {medium, small}` → 跳过 `roadmap` + `analyze` 两 stage;`plan` 选 standalone 列(`--from analyze:{analyze_macro_id}`),不带 `{phase}`
|
|
@@ -434,7 +434,7 @@ Generate steps from `session.lifecycle_position` to `milestone-complete`.
|
|
|
434
434
|
1. Validate: 所有 step 的 `command_scope != "missing"`;否则 raise E006 + 列出缺失 skill
|
|
435
435
|
2. Write `.workflow/.maestro/ralph-{YYYYMMDD-HHmmss}/status.json` (Appendix: Session Schema)
|
|
436
436
|
3. Display chain overview:每步显示 `{index}. {skill} [{type}] [{command_scope}]`
|
|
437
|
-
4. If `task_decomposition` present: display **Goal Prompt block** (Appendix)
|
|
437
|
+
4. If `task_decomposition` present: display **Goal Prompt block** (Appendix),不阻塞流程,继续 handoff
|
|
438
438
|
|
|
439
439
|
### A_DELEGATE_EVALUATE
|
|
440
440
|
|
|
@@ -609,12 +609,14 @@ Runs only when `task_decomposition` present.
|
|
|
609
609
|
"analysis_dir": null, "brainstorm_dir": null, "blueprint_dir": null },
|
|
610
610
|
"steps": [{
|
|
611
611
|
"index": 0,
|
|
612
|
-
"
|
|
613
|
-
"skill": "",
|
|
612
|
+
"skill": "", // 执行 step 有值;decision 节点为空字符串/null
|
|
614
613
|
"args": "",
|
|
615
614
|
"stage": "", // brainstorm|blueprint|init|analyze-macro|roadmap|analyze|plan|execute|verify|...
|
|
616
615
|
"scope": null, // "phase"|"standalone"|"milestone"|null(plan 等需要)
|
|
617
|
-
"
|
|
616
|
+
"decision": null, // 非 null → decision 节点(值为 gate 名,如 "post-verify");null → 执行 step
|
|
617
|
+
"retry_count": 0, // decision 节点专用
|
|
618
|
+
"max_retries": 2, // decision 节点专用
|
|
619
|
+
"command_scope": "global|project|missing|null", // 执行 step;decision 节点固定 null
|
|
618
620
|
"command_path": "~/.claude/commands/{name}.md | .claude/commands/{name}.md | null",
|
|
619
621
|
"milestone_id": null, // D-007 反查注入;仅含 {phase} 占位符的 step 有
|
|
620
622
|
"source_artifact_ref": null, // "analyze:ANL-xxx" | "blueprint:BLP-xxx" | null
|
|
@@ -624,7 +626,7 @@ Runs only when `task_decomposition` present.
|
|
|
624
626
|
"completion_status": null,
|
|
625
627
|
"completion_evidence": null,
|
|
626
628
|
"completed_at": null,
|
|
627
|
-
"deferred_reads": [] // 由 ralph-execute
|
|
629
|
+
"deferred_reads": [] // 由 ralph-execute A_EXEC_STEP 解析 .md 时填充
|
|
628
630
|
}],
|
|
629
631
|
"waves": [], "current_step": 0,
|
|
630
632
|
|
|
@@ -646,7 +648,7 @@ Runs only when `task_decomposition` present.
|
|
|
646
648
|
|
|
647
649
|
### Fix-Loop Templates
|
|
648
650
|
|
|
649
|
-
|
|
651
|
+
所有插入的执行 step 按 A_BUILD_STEPS 规则 9 解析 `command_path` + `command_scope`;`decision:*` 条目为 decision 节点(`step.decision` 字段)。
|
|
650
652
|
|
|
651
653
|
**post-verify:**
|
|
652
654
|
```
|
|
@@ -708,12 +710,12 @@ decision:post-goal-audit {retry+1}
|
|
|
708
710
|
链路概览后逐字显示(仅当 decomposition 已产出):
|
|
709
711
|
|
|
710
712
|
```
|
|
711
|
-
📋
|
|
713
|
+
📋 任务分解完成。可随时复制以下 /goal 设定终止条件(执行过程中输入即可):
|
|
712
714
|
|
|
713
715
|
/goal 直到 {session_dir}/status.json 的 task_decomposition[*] 与 steps[*] 全部 completion_confirmed=true 才停。每轮以 status.json 为唯一行动手册,通过 /maestro-ralph-execute 推进 step;decision 节点由其自动 handoff 回 ralph 评估。禁止手动执行 skill 或修改 boundary_contract.out_of_scope。
|
|
714
716
|
```
|
|
715
717
|
|
|
716
|
-
`/goal` 由用户输入;ralph
|
|
718
|
+
`/goal` 由用户输入;ralph 输出提示词后继续 handoff,不阻塞。
|
|
717
719
|
|
|
718
720
|
### Error Codes
|
|
719
721
|
|
|
@@ -745,8 +747,8 @@ decision:post-goal-audit {retry+1}
|
|
|
745
747
|
- [ ] quality_mode 由 A_DETERMINE_QUALITY_MODE 决定,过滤 build steps
|
|
746
748
|
- [ ] Decomposition: broad intent ≤3 question clarify;narrow auto-derive
|
|
747
749
|
- [ ] status.json 唯一真源:boundary_contract + execution_criteria + task_decomposition;无外部清单
|
|
748
|
-
- [ ]
|
|
749
|
-
- [ ] Ralph build 阶段只解析路径,不读 .md 内容;`<required_reading>` 加载由 ralph-execute
|
|
750
|
+
- [ ] 执行 step 含 `command_scope` + `command_path`(全局优先 fallback 项目);decision step 通过 `step.decision` 字段标识
|
|
751
|
+
- [ ] Ralph build 阶段只解析路径,不读 .md 内容;`<required_reading>` 加载由 ralph-execute A_EXEC_STEP 完成
|
|
750
752
|
- [ ] 每个 step 含 `completion_confirmed` + `completion_status` + `completion_evidence` + `deferred_reads`(初始 false/null/[])
|
|
751
753
|
- [ ] 每个 sub-goal 含 `completion_confirmed`(初始 false)
|
|
752
754
|
- [ ] post-goal-audit decision 仅在 decomposed 时插入,位于 milestone-complete 之前
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maestro
|
|
3
3
|
description: Auto-route intent to optimal command chain
|
|
4
|
-
argument-hint: "<intent> [-y] [-c] [--dry-run] [--
|
|
4
|
+
argument-hint: "<intent> [-y] [-c] [--dry-run] [--super]"
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
7
7
|
- Write
|
|
@@ -40,18 +40,16 @@ $ARGUMENTS — user intent text, or special keywords.
|
|
|
40
40
|
- `-y` / `--yes` — Auto mode: skip clarification, skip confirmation, auto-skip on errors
|
|
41
41
|
- `-c` / `--continue` — Resume previous session
|
|
42
42
|
- `--dry-run` — Show chain without executing
|
|
43
|
-
- `--exec <mode>` — `auto` (default), `cli`, `internal`
|
|
44
|
-
- `--tool <name>` — CLI tool for delegates (default: claude)
|
|
45
43
|
- `--super` — Read and follow `maestro-super.md`
|
|
46
44
|
</context>
|
|
47
45
|
|
|
48
46
|
<invariants>
|
|
49
47
|
1. **All chains dispatch via maestro-ralph-execute** — maestro never executes steps directly
|
|
50
48
|
2. **Session before execution** — status.json created before any step runs
|
|
51
|
-
3. **Auto
|
|
49
|
+
3. **Auto flag pass-through** — 仅当用户传入 `-y` 时透传 `-y` 到 skill args
|
|
52
50
|
4. **Decomposition contract shared with maestro-ralph** — broad/lifecycle intents run S_DECOMPOSE producing the SAME additive block (`boundary_contract`, `execution_criteria`, `task_decomposition`)。Reference maestro-ralph `A_DECOMPOSE_TASKS`
|
|
53
51
|
5. **status.json 唯一真源** — 不生成 `goal-checklist.md` 或外部清单
|
|
54
|
-
6.
|
|
52
|
+
6. **执行步骤统一 Read .md 内联** — chain 内每个执行 step 解析 `command_scope`/`command_path`(全局优先 `~/.claude/commands/{name}.md`,fallback 项目),由 ralph-execute `Read({command_path})` 内联执行;CLI 仅在 decision 节点做只读分析
|
|
55
53
|
7. **Topology awareness** — chain catalog 含 brainstorm / blueprint / analyze-macro(text) / analyze(numeric phase) / roadmap / plan(三路径) / execute / verify / ...;scope_verdict 路由由 ralph 在 `post-analyze-scope` 决定
|
|
56
54
|
8. **D-007 milestone 反查** — 数字 phase 步骤的 `milestone_id` 由 `state.json.milestones[].phase_slugs` 反查得出
|
|
57
55
|
9. **每个 step 必须 `completion_confirmed: true`** — 基于 `--- COMPLETION STATUS ---` 的 `STATUS: DONE`
|
|
@@ -141,7 +139,7 @@ S_FALLBACK:
|
|
|
141
139
|
- 数字 phase 上下文 → `analyze {phase}` → `plan {phase}` → `execute {phase}` → `verify {phase}` → quality pipeline
|
|
142
140
|
- 已有 analyze artifact 想直达执行 → `plan --from analyze:{ANL_ID}` → execute → verify
|
|
143
141
|
- 已有 blueprint artifact → `plan --from blueprint:{BLP_ID}` → execute → verify
|
|
144
|
-
4.
|
|
142
|
+
4. 执行 step 解析 `command_scope` + `command_path`(全局优先 fallback 项目);写入 `step.stage` / `step.scope` / `step.source_artifact_ref`(如 `--from` 注入时)。decision 节点通过 `step.decision` 字段标识
|
|
145
143
|
|
|
146
144
|
### A_CLARIFY
|
|
147
145
|
|
|
@@ -157,9 +155,9 @@ S_FALLBACK:
|
|
|
157
155
|
3. 派生 `execution_criteria` + `task_decomposition`(每个 sub-goal 含 `done_when` + `evidence` + `lifecycle` + `completion_confirmed: false`)
|
|
158
156
|
4. **status.json 唯一真源**:写入 `boundary_contract` / `execution_criteria` / `task_decomposition`;不生成 markdown 清单
|
|
159
157
|
5. 在最后一个 evidence-producing stage(verify/review/test)之后、`milestone-complete` 之前追加 `decision:post-goal-audit`。ralph-execute 在该节点按需动态生长 `steps[]`
|
|
160
|
-
6. **输出 `/goal`
|
|
158
|
+
6. **输出 `/goal` 绑定提示词(不阻塞,用户可在执行过程中随时输入):**
|
|
161
159
|
```
|
|
162
|
-
📋
|
|
160
|
+
📋 任务分解完成。可随时复制下面一行设定目标(执行过程中输入即可):
|
|
163
161
|
|
|
164
162
|
/goal 目标达成条件: {session_dir}/status.json 中 task_decomposition[*].status == "done" 且 task_decomposition[*].completion_confirmed == true 且 steps[*].completion_confirmed == true。未达成时:阅读 {session_dir}/status.json 取得 execution_criteria / boundary_contract / task_decomposition / steps 作为行动手册,调用 /maestro-ralph continue 推进;严禁手动执行 skill 或越界修改 status.json.boundary_contract.out_of_scope。
|
|
165
163
|
```
|
|
@@ -173,13 +171,14 @@ S_FALLBACK:
|
|
|
173
171
|
"session_id", "source": "maestro", "intent", "task_type", "chain_name",
|
|
174
172
|
"phase", "phase_is_new": false, "milestone": "",
|
|
175
173
|
"scope_verdict": null, "analyze_macro_id": null, "blueprint_id": null,
|
|
176
|
-
"auto_mode": false, "
|
|
174
|
+
"auto_mode": false, "cli_tool": "claude", // cli_tool: decision 节点 delegate 评估时的 CLI 工具
|
|
177
175
|
"context": { "scratch_dir": null, "plan_dir": null, "analysis_dir": null,
|
|
178
176
|
"brainstorm_dir": null, "blueprint_dir": null, "issue_id": null },
|
|
179
177
|
"steps": [{
|
|
180
|
-
"index": 0,
|
|
178
|
+
"index": 0,
|
|
181
179
|
"skill": "", "args": "",
|
|
182
180
|
"stage": "", "scope": null,
|
|
181
|
+
"decision": null, // 非 null → decision 节点;null → 执行节点
|
|
183
182
|
"command_scope": "global|project|missing|null",
|
|
184
183
|
"command_path": "~/.claude/commands/{name}.md | .claude/commands/{name}.md | null",
|
|
185
184
|
"milestone_id": null, "source_artifact_ref": null,
|
|
@@ -203,25 +202,6 @@ S_FALLBACK:
|
|
|
203
202
|
|
|
204
203
|
<appendix>
|
|
205
204
|
|
|
206
|
-
### Auto-Yes Flag Map
|
|
207
|
-
|
|
208
|
-
| Command | Auto Flag | Effect |
|
|
209
|
-
|---------|-----------|--------|
|
|
210
|
-
| maestro-init | `-y` | Skip interactive questioning |
|
|
211
|
-
| maestro-analyze | `-y` | Skip scoping, auto-deepen |
|
|
212
|
-
| maestro-brainstorm | `-y` | Skip questions, use defaults |
|
|
213
|
-
| maestro-blueprint | `-y` | Skip interview, use recommended defaults |
|
|
214
|
-
| maestro-roadmap | `-y` | Skip questions (create/revise/review) |
|
|
215
|
-
| maestro-impeccable | `-y` | Auto-select design variant + skip confirmations |
|
|
216
|
-
| maestro-plan | `-y` | Skip confirmations and clarification |
|
|
217
|
-
| maestro-execute | `-y` | Skip confirmations, blocked auto-continue |
|
|
218
|
-
| quality-auto-test | `-y` | Skip plan confirmation |
|
|
219
|
-
| quality-test | `-y --auto-fix` | Auto-trigger gap-fix loop |
|
|
220
|
-
| quality-retrospective | `-y` | Accept all routing recommendations |
|
|
221
|
-
| maestro-milestone-complete | `-y` | Skip knowledge promotion |
|
|
222
|
-
|
|
223
|
-
Unlisted commands have no auto flags.
|
|
224
|
-
|
|
225
205
|
### Error Codes
|
|
226
206
|
|
|
227
207
|
| Code | Severity | Description | Recovery |
|
|
@@ -246,8 +226,8 @@ Unlisted commands have no auto flags.
|
|
|
246
226
|
- [ ] status.json 唯一真源;无 markdown 清单;post-goal-audit 节点在 decomposed 时追加;/goal 提示词以 status.json 为判据
|
|
247
227
|
- [ ] Chain selected and confirmed (or auto-confirmed)
|
|
248
228
|
- [ ] Session dir created with status.json before execution; decomposition fields additive-only
|
|
249
|
-
- [ ]
|
|
250
|
-
- [ ]
|
|
229
|
+
- [ ] 执行 step 含 `command_scope` + `command_path` + `completion_confirmed` 字段;decision step 通过 `step.decision` 字段标识
|
|
230
|
+
- [ ] 用户传入 `-y` 时透传到 skill args
|
|
251
231
|
- [ ] All chains dispatched via maestro-ralph-execute
|
|
252
232
|
- [ ] Low-complexity intents routed to maestro-quick
|
|
253
233
|
- [ ] (super) Requirements validated before roadmap
|
|
@@ -51,7 +51,26 @@ export declare const CODEX_HOOK_DEFS: Record<string, CodexHookDef>;
|
|
|
51
51
|
export declare const CODEX_HOOK_LEVEL_DESCRIPTIONS: Record<HookLevel, string>;
|
|
52
52
|
export declare function getClaudeSettingsPath(): string;
|
|
53
53
|
export declare function loadClaudeSettings(settingsPath: string): ClaudeSettings;
|
|
54
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Remove maestro hooks from Claude settings.
|
|
56
|
+
*
|
|
57
|
+
* @param settings Parsed settings.json object (mutated in place)
|
|
58
|
+
* @param hookNames Optional whitelist of hook names to remove. When omitted,
|
|
59
|
+
* every command containing the "maestro" substring is stripped
|
|
60
|
+
* (legacy uninstall behavior).
|
|
61
|
+
*/
|
|
62
|
+
export declare function removeMaestroHooks(settings: ClaudeSettings, hookNames?: string[]): void;
|
|
63
|
+
/**
|
|
64
|
+
* Remove the maestro-installed statusline from Claude settings.
|
|
65
|
+
* Returns true if a statusline was removed.
|
|
66
|
+
*/
|
|
67
|
+
export declare function removeClaudeStatusline(settingsPath: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Uninstall hooks recorded under a HookRecord from a Claude settings file.
|
|
70
|
+
* Removes only the hooks listed in `installed` — does NOT strip statusline.
|
|
71
|
+
* Returns the number of hook entries removed.
|
|
72
|
+
*/
|
|
73
|
+
export declare function uninstallClaudeHooks(settingsPath: string, installed: string[]): number;
|
|
55
74
|
export interface InstallHooksResult {
|
|
56
75
|
settingsPath: string;
|
|
57
76
|
installedHooks: string[];
|
|
@@ -107,7 +126,11 @@ export declare function getCodexHooksPath(opts?: {
|
|
|
107
126
|
project?: boolean;
|
|
108
127
|
}): string;
|
|
109
128
|
export declare function loadCodexHooks(hooksPath: string): CodexHooksFile;
|
|
110
|
-
export declare function removeCodexMaestroHooks(hooksFile: CodexHooksFile): void;
|
|
129
|
+
export declare function removeCodexMaestroHooks(hooksFile: CodexHooksFile, hookNames?: string[]): void;
|
|
130
|
+
/**
|
|
131
|
+
* Uninstall codex hooks recorded under a HookRecord. Returns number of entries removed.
|
|
132
|
+
*/
|
|
133
|
+
export declare function uninstallCodexHooks(hooksPath: string, installed: string[]): number;
|
|
111
134
|
/**
|
|
112
135
|
* Check whether `codex_hooks = true` is set in config.toml.
|
|
113
136
|
* Returns true if the flag is found; prints a hint otherwise.
|
|
@@ -177,7 +200,11 @@ export declare function getAgyHooksPath(opts?: {
|
|
|
177
200
|
}): string;
|
|
178
201
|
export declare function loadAgyHooks(hooksPath: string): AgyHooksFile;
|
|
179
202
|
/** Strip all maestro-prefixed top-level entries (preserves user-defined hooks). */
|
|
180
|
-
export declare function removeAgyMaestroHooks(hooksFile: AgyHooksFile): void;
|
|
203
|
+
export declare function removeAgyMaestroHooks(hooksFile: AgyHooksFile, hookNames?: string[]): void;
|
|
204
|
+
/**
|
|
205
|
+
* Uninstall agy hooks recorded under a HookRecord. Returns number of entries removed.
|
|
206
|
+
*/
|
|
207
|
+
export declare function uninstallAgyHooks(hooksPath: string, installed: string[]): number;
|
|
181
208
|
/**
|
|
182
209
|
* Install hooks at the given level into Antigravity's hooks.json.
|
|
183
210
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BzC,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;QAC1B,gBAAgB,CAAC,EAAE,SAAS,EAAE,CAAC;QAC/B,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC;QAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,UAAU,OAAO;IACf,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,kBAAkB,GAAG,cAAc,GAAG,MAAM,CAAC;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,KAAK,EAAE,SAAS,CAAC;IACjB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAEjE,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAA4C,CAAC;AAEzF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAK7D,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAY7C,CAAC;AAMF,UAAU,YAAY;IACpB,KAAK,EAAE,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,kBAAkB,GAAG,MAAM,CAAC;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAUxD,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAKnE,CAAC;AAaF,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,CAGvE;AASD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/commands/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6BzC,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;QAC1B,gBAAgB,CAAC,EAAE,SAAS,EAAE,CAAC;QAC/B,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC;QAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAMD,UAAU,OAAO;IACf,KAAK,EAAE,YAAY,GAAG,aAAa,GAAG,kBAAkB,GAAG,cAAc,GAAG,MAAM,CAAC;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,KAAK,EAAE,SAAS,CAAC;IACjB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAEjE,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAA4C,CAAC;AAEzF,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAK7D,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAY7C,CAAC;AAMF,UAAU,YAAY;IACpB,KAAK,EAAE,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,kBAAkB,GAAG,MAAM,CAAC;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAUxD,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAKnE,CAAC;AAaF,wBAAgB,qBAAqB,IAAI,MAAM,CAG9C;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,cAAc,CAGvE;AASD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAuBvF;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAWpE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAYtF;AA4BD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,SAAS,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,GAAG,IAAI,CAMhF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CACX,GAAG,MAAM,CAoBd;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,EAChB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GAChF,kBAAkB,CA0CpB;AAMD,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3F;AAED,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,cAAc,EAAE,CAAC;QAChC,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;QAC9B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;QAC/B,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;QACpC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC;QACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAI1E;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAIhE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAwB7F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAYlF;AAYD;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAOpF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,kBAAkB,CAwCpB;AAuBD,oCAAoC;AACpC,KAAK,QAAQ,GAAG,YAAY,GAAG,aAAa,GAAG,eAAe,GAAG,gBAAgB,GAAG,MAAM,CAAC;AAE3F,UAAU,UAAU;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAiBpD,CAAC;AAEF,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAKjE,CAAC;AAGF,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC;IACjC,cAAc,CAAC,EAAE,cAAc,EAAE,CAAC;IAClC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,kEAAkE;AAClE,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAIlD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAI9F;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAQ5D;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAWzF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAYhF;AAOD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,SAAS,EAChB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACzE,kBAAkB,CAoCpB;AAoWD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkZ3D"}
|
|
@@ -74,15 +74,30 @@ function getMaestroBinDir() {
|
|
|
74
74
|
return resolve(new URL('../../../bin', import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1'));
|
|
75
75
|
}
|
|
76
76
|
const HOOK_MARKER = 'maestro';
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Remove maestro hooks from Claude settings.
|
|
79
|
+
*
|
|
80
|
+
* @param settings Parsed settings.json object (mutated in place)
|
|
81
|
+
* @param hookNames Optional whitelist of hook names to remove. When omitted,
|
|
82
|
+
* every command containing the "maestro" substring is stripped
|
|
83
|
+
* (legacy uninstall behavior).
|
|
84
|
+
*/
|
|
85
|
+
export function removeMaestroHooks(settings, hookNames) {
|
|
78
86
|
if (!settings.hooks)
|
|
79
87
|
return;
|
|
88
|
+
const targets = hookNames && hookNames.length > 0
|
|
89
|
+
? new Set(hookNames.map((n) => `hooks run ${n}`))
|
|
90
|
+
: null;
|
|
80
91
|
for (const eventKey of ['PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'Notification', 'Stop']) {
|
|
81
92
|
const groups = settings.hooks[eventKey];
|
|
82
93
|
if (!groups)
|
|
83
94
|
continue;
|
|
84
95
|
for (const group of groups) {
|
|
85
|
-
group.hooks = group.hooks.filter((h) =>
|
|
96
|
+
group.hooks = group.hooks.filter((h) => {
|
|
97
|
+
if (targets)
|
|
98
|
+
return ![...targets].some((needle) => h.command.includes(needle));
|
|
99
|
+
return !h.command.includes(HOOK_MARKER);
|
|
100
|
+
});
|
|
86
101
|
}
|
|
87
102
|
settings.hooks[eventKey] = groups.filter((g) => g.hooks.length > 0);
|
|
88
103
|
if (settings.hooks[eventKey].length === 0) {
|
|
@@ -93,6 +108,57 @@ export function removeMaestroHooks(settings) {
|
|
|
93
108
|
delete settings.hooks;
|
|
94
109
|
}
|
|
95
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Remove the maestro-installed statusline from Claude settings.
|
|
113
|
+
* Returns true if a statusline was removed.
|
|
114
|
+
*/
|
|
115
|
+
export function removeClaudeStatusline(settingsPath) {
|
|
116
|
+
if (!existsSync(settingsPath))
|
|
117
|
+
return false;
|
|
118
|
+
try {
|
|
119
|
+
const settings = loadClaudeSettings(settingsPath);
|
|
120
|
+
if (!settings.statusLine?.command?.includes(HOOK_MARKER))
|
|
121
|
+
return false;
|
|
122
|
+
delete settings.statusLine;
|
|
123
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Uninstall hooks recorded under a HookRecord from a Claude settings file.
|
|
132
|
+
* Removes only the hooks listed in `installed` — does NOT strip statusline.
|
|
133
|
+
* Returns the number of hook entries removed.
|
|
134
|
+
*/
|
|
135
|
+
export function uninstallClaudeHooks(settingsPath, installed) {
|
|
136
|
+
if (!existsSync(settingsPath) || installed.length === 0)
|
|
137
|
+
return 0;
|
|
138
|
+
try {
|
|
139
|
+
const settings = loadClaudeSettings(settingsPath);
|
|
140
|
+
const before = countHookEntries(settings.hooks);
|
|
141
|
+
removeMaestroHooks(settings, installed);
|
|
142
|
+
const after = countHookEntries(settings.hooks);
|
|
143
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
144
|
+
return Math.max(0, before - after);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function countHookEntries(hooks) {
|
|
151
|
+
if (!hooks)
|
|
152
|
+
return 0;
|
|
153
|
+
let count = 0;
|
|
154
|
+
for (const groups of Object.values(hooks)) {
|
|
155
|
+
if (!Array.isArray(groups))
|
|
156
|
+
continue;
|
|
157
|
+
for (const g of groups)
|
|
158
|
+
count += g.hooks.length;
|
|
159
|
+
}
|
|
160
|
+
return count;
|
|
161
|
+
}
|
|
96
162
|
function findHookInSettings(settings, hookName) {
|
|
97
163
|
if (!settings.hooks)
|
|
98
164
|
return false;
|
|
@@ -155,10 +221,9 @@ export function installHooksByLevel(level, opts = {}) {
|
|
|
155
221
|
? join(process.cwd(), '.claude', 'settings.json')
|
|
156
222
|
: getClaudeSettingsPath());
|
|
157
223
|
const settings = loadClaudeSettings(settingsPath);
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
224
|
+
// Note: statusline is NEVER auto-installed by hooks. It is opt-in only,
|
|
225
|
+
// controlled by the dedicated `installStatusline` flag in the install flow.
|
|
226
|
+
// The `skipStatusline` option is kept for API back-compat but ignored.
|
|
162
227
|
// --- Remove existing maestro hooks to avoid duplicates ---
|
|
163
228
|
removeMaestroHooks(settings);
|
|
164
229
|
// --- Register hooks matching the requested level ---
|
|
@@ -200,16 +265,23 @@ export function loadCodexHooks(hooksPath) {
|
|
|
200
265
|
return {};
|
|
201
266
|
}
|
|
202
267
|
}
|
|
203
|
-
export function removeCodexMaestroHooks(hooksFile) {
|
|
268
|
+
export function removeCodexMaestroHooks(hooksFile, hookNames) {
|
|
204
269
|
if (!hooksFile.hooks)
|
|
205
270
|
return;
|
|
271
|
+
const targets = hookNames && hookNames.length > 0
|
|
272
|
+
? new Set(hookNames.map((n) => `hooks run ${n}`))
|
|
273
|
+
: null;
|
|
206
274
|
const events = ['SessionStart', 'PreToolUse', 'PostToolUse', 'UserPromptSubmit', 'Stop'];
|
|
207
275
|
for (const eventKey of events) {
|
|
208
276
|
const groups = hooksFile.hooks[eventKey];
|
|
209
277
|
if (!groups)
|
|
210
278
|
continue;
|
|
211
279
|
for (const group of groups) {
|
|
212
|
-
group.hooks = group.hooks.filter((h) =>
|
|
280
|
+
group.hooks = group.hooks.filter((h) => {
|
|
281
|
+
if (targets)
|
|
282
|
+
return ![...targets].some((needle) => h.command.includes(needle));
|
|
283
|
+
return !h.command.includes(HOOK_MARKER);
|
|
284
|
+
});
|
|
213
285
|
}
|
|
214
286
|
hooksFile.hooks[eventKey] = groups.filter((g) => g.hooks.length > 0);
|
|
215
287
|
if (hooksFile.hooks[eventKey].length === 0) {
|
|
@@ -220,6 +292,36 @@ export function removeCodexMaestroHooks(hooksFile) {
|
|
|
220
292
|
delete hooksFile.hooks;
|
|
221
293
|
}
|
|
222
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Uninstall codex hooks recorded under a HookRecord. Returns number of entries removed.
|
|
297
|
+
*/
|
|
298
|
+
export function uninstallCodexHooks(hooksPath, installed) {
|
|
299
|
+
if (!existsSync(hooksPath) || installed.length === 0)
|
|
300
|
+
return 0;
|
|
301
|
+
try {
|
|
302
|
+
const hooksFile = loadCodexHooks(hooksPath);
|
|
303
|
+
const before = countCodexHookEntries(hooksFile);
|
|
304
|
+
removeCodexMaestroHooks(hooksFile, installed);
|
|
305
|
+
const after = countCodexHookEntries(hooksFile);
|
|
306
|
+
writeFileSync(hooksPath, JSON.stringify(hooksFile, null, 2));
|
|
307
|
+
return Math.max(0, before - after);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return 0;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function countCodexHookEntries(hooksFile) {
|
|
314
|
+
if (!hooksFile.hooks)
|
|
315
|
+
return 0;
|
|
316
|
+
let count = 0;
|
|
317
|
+
for (const groups of Object.values(hooksFile.hooks)) {
|
|
318
|
+
if (!Array.isArray(groups))
|
|
319
|
+
continue;
|
|
320
|
+
for (const g of groups)
|
|
321
|
+
count += g.hooks.length;
|
|
322
|
+
}
|
|
323
|
+
return count;
|
|
324
|
+
}
|
|
223
325
|
/**
|
|
224
326
|
* Check whether `codex_hooks = true` is set in config.toml.
|
|
225
327
|
* Returns true if the flag is found; prints a hint otherwise.
|
|
@@ -333,10 +435,36 @@ export function loadAgyHooks(hooksPath) {
|
|
|
333
435
|
}
|
|
334
436
|
}
|
|
335
437
|
/** Strip all maestro-prefixed top-level entries (preserves user-defined hooks). */
|
|
336
|
-
export function removeAgyMaestroHooks(hooksFile) {
|
|
438
|
+
export function removeAgyMaestroHooks(hooksFile, hookNames) {
|
|
439
|
+
const exact = hookNames && hookNames.length > 0
|
|
440
|
+
? new Set(hookNames.map((n) => `${AGY_HOOK_NAME_PREFIX}${n}`))
|
|
441
|
+
: null;
|
|
337
442
|
for (const key of Object.keys(hooksFile)) {
|
|
338
|
-
if (
|
|
443
|
+
if (exact) {
|
|
444
|
+
if (exact.has(key))
|
|
445
|
+
delete hooksFile[key];
|
|
446
|
+
}
|
|
447
|
+
else if (key.startsWith(AGY_HOOK_NAME_PREFIX)) {
|
|
339
448
|
delete hooksFile[key];
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Uninstall agy hooks recorded under a HookRecord. Returns number of entries removed.
|
|
454
|
+
*/
|
|
455
|
+
export function uninstallAgyHooks(hooksPath, installed) {
|
|
456
|
+
if (!existsSync(hooksPath) || installed.length === 0)
|
|
457
|
+
return 0;
|
|
458
|
+
try {
|
|
459
|
+
const hooksFile = loadAgyHooks(hooksPath);
|
|
460
|
+
const before = Object.keys(hooksFile).filter((k) => k.startsWith(AGY_HOOK_NAME_PREFIX)).length;
|
|
461
|
+
removeAgyMaestroHooks(hooksFile, installed);
|
|
462
|
+
const after = Object.keys(hooksFile).filter((k) => k.startsWith(AGY_HOOK_NAME_PREFIX)).length;
|
|
463
|
+
writeFileSync(hooksPath, JSON.stringify(hooksFile, null, 2));
|
|
464
|
+
return Math.max(0, before - after);
|
|
465
|
+
}
|
|
466
|
+
catch {
|
|
467
|
+
return 0;
|
|
340
468
|
}
|
|
341
469
|
}
|
|
342
470
|
/** Determines which event-key shape applies. */
|
|
@@ -807,7 +935,6 @@ export function registerHooksCommand(program) {
|
|
|
807
935
|
else {
|
|
808
936
|
const result = installHooksByLevel(level, { project: opts.project });
|
|
809
937
|
console.log(`Maestro hooks installed (level: ${level}):`);
|
|
810
|
-
console.log(` Statusline: installed`);
|
|
811
938
|
for (const name of result.installedHooks) {
|
|
812
939
|
const def = HOOK_DEFS[name];
|
|
813
940
|
const matcher = def.matcher ? ` [${def.matcher}]` : '';
|