harnessed 3.0.0 → 3.0.1

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # harnessed
2
2
 
3
3
  > AI coding harness 包管理器 + composition orchestrator
4
- > CLAUDE.md 三层栈协作规则机器化为可执行 engine
4
+ > 把三层栈协作方法论 (gstack 决策 + GSD 项目经理 + superpowers 资深工程师 + karpathy 心法 + mattpocock 招式) 机器化为可执行 engine
5
5
 
6
6
  [![npm](https://img.shields.io/npm/v/harnessed?label=npm&color=blue)](https://npmjs.com/package/harnessed)
7
7
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)
@@ -17,46 +17,72 @@
17
17
 
18
18
  ---
19
19
 
20
- ## 🎯 关键差异化 (v3.0)
20
+ ## 🎯 关键差异化
21
21
 
22
22
  - **三层栈机器化** — `gstack 决策` + `GSD 项目经理` + `superpowers 资深工程师` + `karpathy 4 心法` + `mattpocock 23 招式`,5 支柱 100% capture
23
23
  - **不 vendor 上游** — manifest describe install/check;上游升级用户 re-install 即获最新版
24
- - **Composition Skill (v3.0 重构)** — 自家 workflow skill 当指挥棒,调度多个上游协同。v3.0 把 v2.0 的 4 个 monolithic workflow 拆成 **4 master orchestrator + 18 sub-workflow + 2 standalone = 24 namespace-layered workflow**,完整 4-stage 机器化 (`/discuss /plan /task /verify` 4 master + 三层栈 18 sub + `/research /retro` 2 standalone)
25
- - **L0 Discipline Substrate (v3.0 NEW)** — 全局 cross-stage 行为基准 (karpathy 心法 + output-style + language + operational + priority + protocols),applied universally to L1-L7
24
+ - **Composition Skill** — 自家 workflow skill 当指挥棒,调度多个上游协同。**4 master orchestrator + 18 sub-workflow + 2 standalone = 24 namespace-layered workflow**,完整 4-stage 机器化 (`/discuss /plan /task /verify` 4 master + 三层栈 18 sub + `/research /retro` 2 standalone)
25
+ - **L0 Discipline Substrate** — 全局 cross-stage 行为基准 (karpathy 心法 + output-style + language + operational + priority + protocols),applied universally
26
26
  - **包管理器思维** — install dependency graph 自动解析, doctor 健康检查, install-base 一键装齐
27
27
  - **统一入口** — 用户面对 `/discuss /plan /task /verify` 等 master slash command,不需学每家上游术语;sub command 显式调用单 stage (例如 `/discuss-strategic` 只跑战略层澄清)
28
28
 
29
29
  ---
30
30
 
31
- ## 🆕 v3.0 highlight — 4-stage namespace-layered architecture
31
+ ## 📦 快速安装
32
32
 
33
- v3.0 是对 v2.0 4-workflow 的 **breaking refactor**,把 4 个 monolithic skill 重组为 **24 个 namespace-layered skill**,1:1 对位 `~/.claude/CLAUDE.md` 4-stage cadence。
33
+ ```bash
34
+ npm install -g harnessed && harnessed setup
35
+ ```
36
+
37
+ ---
34
38
 
35
- ### 4-stage 流程图 (mermaid)
39
+ ## 📐 4-stage 流程图
36
40
 
37
41
  ```mermaid
38
- graph LR
39
- subgraph Discuss[Discuss 战略澄清]
40
- DS[discuss-strategic] & DP[discuss-phase] & DT[discuss-subtask]
42
+ graph TD
43
+ RS([ /research — 前置多源调研 可选]):::optional
44
+ subgraph Discuss[ Discuss 战略澄清]
41
45
  DM[/discuss master/]
46
+ DS[discuss-strategic]
47
+ DP[discuss-phase]
48
+ DT[discuss-subtask]
49
+ DM --> DS & DP & DT
42
50
  end
43
- subgraph Plan[Plan 任务规划]
44
- PA[plan-architecture] & PP[plan-phase]
51
+ subgraph Plan[Plan 任务规划]
45
52
  PM[/plan master/]
53
+ PA[plan-architecture]
54
+ PP[plan-phase]
55
+ PM --> PA & PP
46
56
  end
47
- subgraph Task[Task 执行]
48
- TC[task-clarify] & TCo[task-code] & TT[task-test] & TD[task-deliver]
57
+ subgraph Task[Task 执行]
49
58
  TM[/task master/]
59
+ TC[task-clarify]
60
+ TCo[task-code]
61
+ TT[task-test]
62
+ TD[task-deliver]
63
+ TM --> TC --> TCo --> TT --> TD
50
64
  end
51
- subgraph Verify[Verify 验证]
52
- VP[verify-progress] & VC[verify-code-review] & VPa[verify-paranoid]
53
- VQ[verify-qa] & VS[verify-security] & VD[verify-design]
54
- VSi[verify-simplify] & VM[verify-multispec]
65
+ subgraph Verify[Verify 验证]
55
66
  VMs[/verify master/]
67
+ VP[verify-progress]
68
+ VC[verify-code-review]
69
+ VPa[verify-paranoid]
70
+ VQ[verify-qa]
71
+ VS[verify-security]
72
+ VD[verify-design]
73
+ VSi[verify-simplify]
74
+ VM[verify-multispec]
75
+ VMs --> VP & VC & VPa & VQ & VS & VD & VSi & VM
56
76
  end
77
+ RT([⑤ /retro — 里程碑总结 可选]):::optional
78
+ RS --> Discuss
57
79
  Discuss --> Plan --> Task --> Verify
80
+ Verify --> RT
81
+ classDef optional stroke-dasharray:5 5,fill:#f5f5f5,color:#666
58
82
  ```
59
83
 
84
+ > 虚框 = 可选 standalone (`/research` 战略前调研 / `/retro` 里程碑后总结);实框 = 主流程 4-stage cadence。
85
+
60
86
  ### 24 workflow 总览表
61
87
 
62
88
  | Slash cmd | Stage | Type | Capability / Upstream | Brief |
@@ -73,7 +99,7 @@ graph LR
73
99
  | `/task-code` | ③ Task | Sub | karpathy 4 心法 + `/zoom-out` / `/improve-codebase-architecture` / `/diagnose` conditional | 子任务编码 + 跨 session progress.md 同步 |
74
100
  | `/task-test` | ③ Task | Sub | superpowers TDD red-green-refactor + `/diagnose` conditional | 核心逻辑 TDD 强制 (alias mattpocock `/tdd`) |
75
101
  | `/task-deliver` | ③ Task | Sub | `ralph-loop` SDK wrapper + Agent Teams conditional | 至 verbatim `COMPLETE` + R20.10 max_iter fallback |
76
- | `/verify` | ④ Verify | Master | masterOrchestrator | 7 sub CLAUDE.md verbatim conditional dispatch |
102
+ | `/verify` | ④ Verify | Master | masterOrchestrator | 7 sub 按场景 conditional dispatch |
77
103
  | `/verify-progress` | ④ Verify | Sub | GSD `/gsd-verify-work` + `/gsd-progress` | 必跑串行起点 — UAT 验收 + 状态同步 |
78
104
  | `/verify-code-review` | ④ Verify | Sub | `code-review` 多 subagent fan-out | 高置信度 finding 并行 |
79
105
  | `/verify-paranoid` | ④ Verify | Sub | gstack `/review` (Paranoid Staff Engineer) | 关键模块 PR 前强制 |
@@ -90,49 +116,6 @@ graph LR
90
116
 
91
117
  ---
92
118
 
93
- ## 🔄 Migrating from v2.0 to v3.0
94
-
95
- v3.0 是 **breaking refactor**。v2.0 的 3 个 monolithic slash cmd 全部 DROP,改用 v3 namespace-layered 等价物:
96
-
97
- | v2.0 (DROPPED) | v3.0 (NEW) |
98
- |----------------|------------|
99
- | `/plan-feature` | `/plan` (master, 自动 gate-route) OR `/plan-phase` (直接 sub) |
100
- | `/execute-task` | `/task` (master, 串行 4 sub) OR `/task-{clarify,code,test,deliver}` (单 stage) |
101
- | `/verify-work` | `/verify` (master, 7 sub conditional) OR `/verify-{progress,code-review,paranoid,qa,security,design,simplify,multispec}` (单维度) |
102
-
103
- `/research` (v2.0 NEW) 不变,schema bump v2 → v3 但 phases verbatim 保留。
104
-
105
- ### 升级步骤
106
-
107
- ```bash
108
- # 1. 升级 npm package
109
- npm install -g harnessed@3
110
-
111
- # 2. 重新 setup — v3 把 24 个 workflow skill 装到 ~/.claude/skills/
112
- harnessed setup --apply
113
-
114
- # 3. (可选) 手动清理 v2 残留 skill dir (per K12 mitigation)
115
- rm -rf ~/.claude/skills/plan-feature ~/.claude/skills/execute-task ~/.claude/skills/verify-work
116
- ```
117
-
118
- > v2.0 SHIPPED & ARCHIVED 2026-05-19 (17/20 phases 85%);v3.0 v1.0-RC2 minor STARTING;v1.0 GA target 2026-05-22~23 — 详 [.planning/STATE.md](./.planning/STATE.md)。
119
-
120
- ---
121
-
122
- ## 📦 快速安装
123
-
124
- ```bash
125
- npm install -g harnessed
126
- ```
127
-
128
- 或不全局安装 (ephemeral 模式):
129
-
130
- ```bash
131
- npx harnessed@latest <command>
132
- ```
133
-
134
- ---
135
-
136
119
  ## 🚩 命令一览
137
120
 
138
121
  ### 主命令
@@ -152,21 +135,24 @@ npx harnessed@latest <command>
152
135
 
153
136
  ### 参数 (Flags)
154
137
 
138
+ > 所有命令默认 **apply (immediate write)**,无需加 flag。高级用户可加 `--dry-run` 预览。
139
+
155
140
  | Flag | 说明 |
156
141
  | ---- | ---- |
157
- | `--apply` | 显式执行 (默认 dry-run) |
158
- | `--dry-run` | 永不写盘 (即使加 `--apply` 也优先 dry-run) |
159
- | `--non-interactive` | CI / 脚本场景;必须配合 `--apply` 或 `--dry-run` |
142
+ | `--dry-run` | 预览不写盘 (高级用户 opt-in) |
143
+ | `--non-interactive` | CI / 脚本场景 |
160
144
  | `--system` | L4 全局装允许 (否则降级 L1 npx ephemeral) |
161
145
  | `--yes` | uninstall 跳过交互 confirm |
162
146
  | `--full-diff` | 展开 > 200 行的 diff 折叠 |
163
147
  | `--no-color` | 强制 nocolor (即使 TTY) |
164
148
 
149
+ > `--apply` flag 仍保留为向后兼容 alias (no-op, 旧脚本不破)。
150
+
165
151
  ---
166
152
 
167
153
  ## ⚡ 使用流程
168
154
 
169
- v3.0 4-stage 三层栈方法论 — 推荐 4 个 master orchestrator 串行驱动:
155
+ 4-stage 三层栈方法论 — 推荐 4 个 master orchestrator 串行驱动:
170
156
 
171
157
  ```
172
158
  /discuss → /plan → /task → /verify
@@ -184,7 +170,7 @@ v3.0 4-stage 三层栈方法论 — 推荐 4 个 master orchestrator 串行驱
184
170
 
185
171
  ```bash
186
172
  # 1. 装 workflow 上游 (一行装齐 gstack + GSD + superpowers + planning-with-files)
187
- harnessed setup --apply
173
+ harnessed setup
188
174
 
189
175
  # 2. 在 Claude Code 内跑 4-stage cadence
190
176
  /discuss "新功能 X" # 战略 + Phase + 子任务 3 层澄清
@@ -202,7 +188,7 @@ harnessed resume
202
188
 
203
189
  ---
204
190
 
205
- ## 🗂️ 架构 (v3.0 — 4-stage namespace-layered)
191
+ ## 🗂️ 架构 (4-stage namespace-layered)
206
192
 
207
193
  ### 1. 目录结构
208
194
 
@@ -229,11 +215,11 @@ harnessed/
229
215
  │ │ ├── parallelism-gate.yaml # L5b execution mechanism routing
230
216
  │ │ ├── tdd-gate.yaml
231
217
  │ │ ├── fallback.yaml # 3 铁律: skip_with_transparency + override + chain_isolation
232
- │ │ ├── web-design-routing.yaml # rules/web-design.md codify
233
- │ │ ├── web-testing-routing.yaml # rules/web-testing.md codify
234
- │ │ ├── web-search-routing.yaml # rules/web-search.md codify
218
+ │ │ ├── web-design-routing.yaml # UI 设计工具路由
219
+ │ │ ├── web-testing-routing.yaml # E2E / 浏览器测试工具路由
220
+ │ │ ├── web-search-routing.yaml # 网页搜索 / 文档抓取路由
235
221
  │ │ └── stage-routing.yaml # master orchestrator sub-stage 路由
236
- │ └── disciplines/ # L0: NEW v3.0 global cross-stage behavioral norms
222
+ │ └── disciplines/ # L0: 全局 cross-stage 行为基准
237
223
  │ ├── karpathy.yaml # 4 心法 + ≤200L
238
224
  │ ├── output-style.yaml # BLUF + no-emoji + no-em-dash
239
225
  │ ├── language.yaml # zh-Hans default + English preserve
@@ -246,7 +232,7 @@ harnessed/
246
232
  ├── tests/ # vitest unit + integration + dogfood (R8.1 dogfood-first)
247
233
  ├── scripts/ # CI gate (check-workflow-schema, transparency-verdict, state-archive)
248
234
  ├── .planning/ # project memory (STATE + ROADMAP + REQUIREMENTS + per-phase + milestones)
249
- └── docs/adr/ # 架构决策记录 (ADR 0001-0032)
235
+ └── docs/adr/ # 架构决策记录
250
236
  ```
251
237
 
252
238
  ### 2. 逻辑分层 (8 层)
@@ -276,21 +262,21 @@ harnessed/
276
262
  ├────────────────────────────────────────────────────────────┤
277
263
  │ L1 Upstream components (NOT vendored) │
278
264
  ├────────────────────────────────────────────────────────────┤
279
- │ L0 Discipline Substrate (NEW v3.0 — 全局生效)
265
+ │ L0 Discipline Substrate (全局生效)
280
266
  │ karpathy 心法 + output-style + language + operational + │
281
267
  │ priority + protocols (applied universally to L1-L7) │
282
268
  └────────────────────────────────────────────────────────────┘
283
269
  ```
284
270
 
285
- ### 3. Cross-cutting Capabilities (capabilities.yaml 7 category, ~70 entry)
271
+ ### 3. Cross-cutting Capabilities (capabilities.yaml 7 category, ~83 entry)
286
272
 
287
273
  ```
288
- behavioral (1): karpathy-guidelines (4 心法 always-on)
289
- tool-slash-cmd (40+): gstack 30+ optional + gsd 10+ + mattpocock 12 高频
290
- tool-mcp (4): chrome-devtools-mcp / tavily-mcp / exa-mcp / playwright-mcp
291
- tool-cli (3): ctx7 / playwright-cli / gws
274
+ behavioral (6): karpathy-guidelines + output-style + language + operational + priority + protocols
275
+ tool-slash-cmd (~60): gstack 30+ optional + gsd 10+ + mattpocock 12 高频 + 等
276
+ tool-mcp (3): chrome-devtools-mcp / tavily-mcp / exa-mcp
277
+ tool-cli (2): ctx7 / gws
292
278
  tool-plugin (2): planning-with-files / @playwright/test
293
- tool-bundled (2): ralph-loop / webapp-testing
279
+ tool-bundled (3): ralph-loop / webapp-testing / playwright-cli
294
280
  agent-platform (3): agent-teams-create / send-message / shutdown
295
281
  ```
296
282
 
@@ -324,35 +310,25 @@ planning-with-files /plan (cross-cutting tool) → write artifacts to .planning/
324
310
 
325
311
  ### 5. 抉择路由矩阵 (rules-based, codified in judgments + capabilities)
326
312
 
327
- | 场景 | Rule source | Default → Escalate |
328
- |------|------------|---------------------|
329
- | 并行机制 | rules/agent-teams.md | subagent → Agent Teams Pattern A/B/C (5 触发) |
330
- | UI 设计主方案 | rules/web-design.md | ui-ux-pro-max → frontend-design (用户明示风格) |
331
- | E2E 浏览器探查 | rules/web-testing.md | playwright-cli (Bash 一行 token 省) |
332
- | E2E commit-able TS | rules/web-testing.md | @playwright/test 默认 |
333
- | E2E Python 后端联动 | rules/web-testing.md | webapp-testing |
334
- | 性能/a11y/内存 | rules/web-testing.md | chrome-devtools-mcp |
335
- | Web 搜索 (关键词) | rules/web-search.md | Tavily MCP 默认 |
336
- | Web 搜索 (描述式/学术) | rules/web-search.md | Exa MCP |
337
- | 库 API 文档 | rules/context7.md | ctx7 CLI |
338
- | GitHub URL | rules/web-search.md | gh CLI |
339
- | 单 URL 抓取 | rules/web-search.md | WebFetch 内置 |
340
- | Gmail/Drive/Calendar | rules/google-workspace.md | gws CLI |
341
- | 架构审查 (复杂) | CLAUDE.md Stage ② | gstack /plan-eng-review |
342
- | TDD 强制 (核心算法) | CLAUDE.md Stage ③ | superpowers TDD OR mattpocock /tdd |
343
- | 关键模块 PR | CLAUDE.md Stage ④ | gstack /review |
344
- | 大重构 PR multi-dim | CLAUDE.md Stage + Pattern C | 4-spec Agent Team |
345
- | 跨 CC 协议 | rules/cc-handoff.md | discipline.protocols self-contained design doc |
346
-
347
- ### v3.0 superset commitment
348
-
349
- harnessed v3.0 是 user 个人 `~/.claude/CLAUDE.md` + Obsidian doc + `~/.claude/rules/` 的 **machine-codified superset**:
350
- - ✅ 4-stage cadence verbatim 机器化 (20 workflows)
351
- - ✅ 三层栈判据 + fallback 3 铁律 (judgments/ 10 file)
352
- - ✅ Pattern A/B/C Agent Teams routing (L5b mechanism)
353
- - ✅ Rules-based tool routing (4 NEW judgments + capabilities)
354
- - ✅ Global discipline (L0 substrate, 6 yaml)
355
- - ✅ harnessed > user manual via: auto gate-route + Pure bundled + cross-session memory + ADR audit + Token cost estimation + real-time discipline enforcement
313
+ | 场景 | Default → Escalate |
314
+ |------|---------------------|
315
+ | 并行机制 | subagent → Agent Teams Pattern A/B/C (5 触发) |
316
+ | UI 设计主方案 | ui-ux-pro-max → frontend-design (用户明示风格) |
317
+ | E2E 浏览器探查 | playwright-cli (Bash 一行 token 省) |
318
+ | E2E commit-able TS | @playwright/test 默认 |
319
+ | E2E Python 后端联动 | webapp-testing |
320
+ | 性能 / a11y / 内存诊断 | chrome-devtools-mcp |
321
+ | Web 搜索 (关键词) | Tavily MCP 默认 |
322
+ | Web 搜索 (描述式 / 学术) | Exa MCP |
323
+ | 库 API 文档 | ctx7 CLI |
324
+ | GitHub URL | gh CLI |
325
+ | 单 URL 抓取 | WebFetch 内置 |
326
+ | Gmail / Drive / Calendar | gws CLI |
327
+ | 架构审查 (复杂) | gstack /plan-eng-review |
328
+ | TDD 强制 (核心算法) | superpowers TDD OR mattpocock /tdd |
329
+ | 关键模块 PR | gstack /review |
330
+ | 大重构 PR 多维度审查 | 4-specialist Agent Team Pattern C |
331
+ | 跨 session hand-off | discipline.protocols self-contained design doc |
356
332
 
357
333
  ---
358
334
 
@@ -401,7 +377,7 @@ harnessed setup --apply # 自动装齐 gstack + GSD + superpowers + planning-wi
401
377
  | Orchestration | GSD | 高层 phase 任务图 + 依赖分析 |
402
378
  | Persistence | planning-with-files | 持久化 `task_plan.md` / `progress.md` / `findings.md` |
403
379
 
404
- v3.0 `/discuss /plan /task /verify` 4 个 master 把 4 阶段串起来,每个 master 内部再 delegate 到对应 sub。每个阶段做不同事,输出喂给下一阶段。**没有合并**。
380
+ `/discuss /plan /task /verify` 4 个 master 把 4 阶段串起来,每个 master 内部再 delegate 到对应 sub。每个阶段做不同事,输出喂给下一阶段。**没有合并**。
405
381
 
406
382
  </details>
407
383
 
@@ -428,25 +404,13 @@ v3.0 `/discuss /plan /task /verify` 4 个 master 把 4 阶段串起来,每个 ma
428
404
 
429
405
  - `npx harnessed@latest setup` 跑的是 **Node.js CLI** (`bin/harnessed`)
430
406
  - setup 装的 **workflow skills** (markdown) 进 `~/.claude/skills/`,由 Claude Code 运行时加载
431
- - `/discuss` / `/plan` / `/task` / `/verify` (v3.0) 等是 CC 内的 slash command,触发 skill 执行
407
+ - `/discuss` / `/plan` / `/task` / `/verify` 等是 CC 内的 slash command,触发 skill 执行
432
408
  - CLI 和 CC skill 共享 `.harnessed/checkpoints/` 状态目录
433
409
 
434
410
  </details>
435
411
 
436
412
  ---
437
413
 
438
- ## 📚 文档导航
439
-
440
- - [docs/WORKFLOW.md](./docs/WORKFLOW.md) — 4-stage workflow mermaid + 各 stage 详解
441
- - [docs/INSTALLER-CONTRACT.md](./docs/INSTALLER-CONTRACT.md) — installer 6 条用户视角硬契约
442
- - [docs/MAINTAINER-ONBOARDING.md](./docs/MAINTAINER-ONBOARDING.md) — 30 分钟跑通 dev 环境
443
- - [docs/adr/](./docs/adr/) — 架构决策记录 (ADR 0001-0023)
444
- - [CHANGELOG.md](./CHANGELOG.md) — 完整版本历史
445
- - [CONTRIBUTING.md](./CONTRIBUTING.md) — 贡献指南
446
- - [SECURITY.md](./SECURITY.md) — 漏洞披露通道
447
-
448
- ---
449
-
450
414
  ## License
451
415
 
452
416
  [Apache-2.0](./LICENSE) — 见 [NOTICE](./NOTICE) (含 Harness Inc. 商标 disclaimer)
package/dist/cli.mjs CHANGED
@@ -793,7 +793,7 @@ var init_resume = __esm({
793
793
 
794
794
  // package.json
795
795
  var package_default = {
796
- version: "3.0.0"};
796
+ version: "3.0.1"};
797
797
 
798
798
  // src/manifest/errors.ts
799
799
  function instancePathToKeyPath(instancePath) {
@@ -2940,7 +2940,12 @@ function validateNonInteractiveFlags(raw, cmdName) {
2940
2940
 
2941
2941
  // src/cli/execute-task.ts
2942
2942
  function registerExecuteTask(program2) {
2943
- program2.command("execute-task").description("Run execute-task workflow (4-phase chain \u2192 ralph-loop COMPLETE)").requiredOption("--task <text>", "task description (required)").option("--workflow <name>", "workflow name", "execute-task").option("--apply", "execute the spawn (default: dry-run preview)").option("--dry-run", "force dry-run (overrides --apply if both set)").option("--non-interactive", "CI / scripts \u2014 requires --apply or --dry-run").option("--model <model>", "subagent model: 'haiku' | 'sonnet' | 'opus'").option("--model-tier <tier>", "override: 'inherit' bypasses per-phase phase.model (B-10)").option("--max-iterations <n>", "ralph-loop max iter (default 20)", (v) => parseInt(v, 10)).action(async (raw) => {
2943
+ program2.command("execute-task").description(
2944
+ "Run execute-task workflow (4-phase chain \u2192 ralph-loop COMPLETE; immediate by default \u2014 use --dry-run for preview)"
2945
+ ).requiredOption("--task <text>", "task description (required)").option("--workflow <name>", "workflow name", "execute-task").option(
2946
+ "--apply",
2947
+ "(deprecated; kept for backward compat \u2014 execute-task spawns immediately by default)"
2948
+ ).option("--dry-run", "preview only \u2014 do not spawn subagent (opt-in for advanced users)").option("--non-interactive", "CI / scripts \u2014 requires --apply or --dry-run").option("--model <model>", "subagent model: 'haiku' | 'sonnet' | 'opus'").option("--model-tier <tier>", "override: 'inherit' bypasses per-phase phase.model (B-10)").option("--max-iterations <n>", "ralph-loop max iter (default 20)", (v) => parseInt(v, 10)).action(async (raw) => {
2944
2949
  validateNonInteractiveFlags(raw, "execute-task --task <text>");
2945
2950
  if (!raw.task) {
2946
2951
  console.error("error: --task <text> is required");
@@ -2963,7 +2968,7 @@ function registerExecuteTask(program2) {
2963
2968
  };
2964
2969
  }
2965
2970
  const taskCtx = { task: raw.task, task_type: "execute-task" };
2966
- const isDryRun = raw.dryRun === true || !raw.apply && !raw.nonInteractive;
2971
+ const isDryRun = raw.dryRun === true;
2967
2972
  if (isDryRun) {
2968
2973
  console.log(
2969
2974
  JSON.stringify({ workflow: phases.workflow, phases: phases.phases, taskCtx }, null, 2)
@@ -3041,8 +3046,10 @@ async function dirSizeKb(dir) {
3041
3046
  return Math.round(total / 1024);
3042
3047
  }
3043
3048
  function registerGc(program2) {
3044
- program2.command("gc").description("Garbage-collect old backup snapshots (dry-run by default)").option("--older-than <duration>", "delete snapshots older than (e.g. 30d / 24h / 4w)", "30d").option("--keep-last <N>", "always keep the most recent N snapshots", "0").option("--apply", "actually delete (default: dry-run preview only)").option("--dry-run", "force dry-run (overrides --apply)").action(async (opts) => {
3045
- const dryRun = opts.dryRun === true || opts.apply !== true;
3049
+ program2.command("gc").description(
3050
+ "Garbage-collect old backup snapshots (immediate by default \u2014 use --dry-run for preview)"
3051
+ ).option("--older-than <duration>", "delete snapshots older than (e.g. 30d / 24h / 4w)", "30d").option("--keep-last <N>", "always keep the most recent N snapshots", "0").option("--apply", "(deprecated; kept for backward compat \u2014 gc deletes immediately by default)").option("--dry-run", "preview only \u2014 do not delete (opt-in for advanced users)").action(async (opts) => {
3052
+ const dryRun = opts.dryRun === true;
3046
3053
  const olderMs = parseDuration(opts.olderThan ?? "30d");
3047
3054
  if (olderMs == null) {
3048
3055
  console.error(
@@ -3092,7 +3099,7 @@ function registerGc(program2) {
3092
3099
  console.log(` ${c.ts} ${c.manifest} (${c.sizeKb} KB)`);
3093
3100
  if (!dryRun) await rm(c.path, { recursive: true, force: true });
3094
3101
  }
3095
- if (dryRun) console.log("\n(dry-run \u2014 re-run with --apply to actually delete)");
3102
+ if (dryRun) console.log("\n(dry-run \u2014 re-run without --dry-run to actually delete)");
3096
3103
  });
3097
3104
  }
3098
3105
  async function confirmAt(level, ctx) {
@@ -4465,7 +4472,7 @@ function formatError(e) {
4465
4472
  return `${head}${where}${tip}`;
4466
4473
  }
4467
4474
  function registerInstall(program2) {
4468
- program2.command("install <name>").description("Install an upstream (dry-run by default \u2014 pass --apply to execute)").option("--apply", "execute the install (default: dry-run preview only)").option("--dry-run", "force dry-run (overrides --apply if both are set)").option("--system", "allow L4 system-wide install (e.g. global npm install)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").option("--full-diff", "expand diffs longer than 200 lines").option("--no-color", "disable ANSI colors (auto-detected when piped)").option(
4475
+ program2.command("install <name>").description("Install an upstream (immediate by default \u2014 use --dry-run for preview)").option("--apply", "(deprecated; kept for backward compat \u2014 install is immediate by default)").option("--dry-run", "preview only \u2014 do not write to disk (opt-in for advanced users)").option("--system", "allow L4 system-wide install (e.g. global npm install)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").option("--full-diff", "expand diffs longer than 200 lines").option("--no-color", "disable ANSI colors (auto-detected when piped)").option(
4469
4476
  "--known-good",
4470
4477
  "use known-good version lock from versions/<harnessed-ver>-known-good.yaml"
4471
4478
  ).action(async (name, raw) => {
@@ -4497,9 +4504,10 @@ function registerInstall(program2) {
4497
4504
  console.error(` fix: run 'harnessed audit' to inspect manifest issues`);
4498
4505
  process.exit(1);
4499
4506
  }
4507
+ const dryRun = raw.dryRun === true;
4500
4508
  const opts = {
4501
- apply: raw.apply === true,
4502
- dryRun: raw.dryRun === true,
4509
+ apply: !dryRun,
4510
+ dryRun,
4503
4511
  system: raw.system === true,
4504
4512
  nonInteractive: raw.nonInteractive === true,
4505
4513
  fullDiff: raw.fullDiff === true,
@@ -4545,11 +4553,17 @@ async function listBaseManifests(cwd) {
4545
4553
  return out;
4546
4554
  }
4547
4555
  function registerInstallBase(program2) {
4548
- program2.command("install-base").description("Install the phase 1.3 base profile (auto-glob manifests; dry-run by default)").option("--apply", "execute the install (default: dry-run preview only)").option("--dry-run", "force dry-run (overrides --apply if both are set)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").action(async (raw) => {
4556
+ program2.command("install-base").description(
4557
+ "Install the phase 1.3 base profile (immediate by default \u2014 use --dry-run for preview)"
4558
+ ).option(
4559
+ "--apply",
4560
+ "(deprecated; kept for backward compat \u2014 install-base is immediate by default)"
4561
+ ).option("--dry-run", "preview only \u2014 do not write to disk (opt-in for advanced users)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").action(async (raw) => {
4549
4562
  validateNonInteractiveFlags(raw, "install-base");
4563
+ const dryRun = raw.dryRun === true;
4550
4564
  const opts = {
4551
- apply: raw.apply === true,
4552
- dryRun: raw.dryRun === true,
4565
+ apply: !dryRun,
4566
+ dryRun,
4553
4567
  system: false,
4554
4568
  nonInteractive: raw.nonInteractive === true,
4555
4569
  fullDiff: false,
@@ -4609,7 +4623,12 @@ function basename(upstream) {
4609
4623
  return (upstream.split("/").pop() ?? upstream).replace(/\.git$/, "");
4610
4624
  }
4611
4625
  function registerManifestAdd(program2) {
4612
- program2.command("manifest-add <upstream>").description("Add a new upstream adapter (EE-5 5-question merge gate, D-03 BOTH dry-run/apply)").option("--category <cat>", "manifest category (skill-packs | tools)", "skill-packs").option("--name <name>", "short adapter name (defaults to <upstream> basename)").option("--apply", "persist EE-5 answers (default: dry-run preview)").option("--dry-run", "force dry-run (overrides --apply if both set)").option("--non-interactive", "CI/scripts \u2014 requires --apply or --dry-run; WARN-only dry-run").action(async (upstream, raw) => {
4626
+ program2.command("manifest-add <upstream>").description(
4627
+ "Add a new upstream adapter (EE-5 5-question merge gate; immediate by default \u2014 use --dry-run for preview)"
4628
+ ).option("--category <cat>", "manifest category (skill-packs | tools)", "skill-packs").option("--name <name>", "short adapter name (defaults to <upstream> basename)").option(
4629
+ "--apply",
4630
+ "(deprecated; kept for backward compat \u2014 manifest-add persists immediately by default)"
4631
+ ).option("--dry-run", "preview only \u2014 do not write JSON (opt-in for advanced users)").option("--non-interactive", "CI/scripts \u2014 requires --apply or --dry-run; WARN-only dry-run").action(async (upstream, raw) => {
4613
4632
  validateNonInteractiveFlags(raw, "manifest-add <upstream>");
4614
4633
  const name = raw.name ?? basename(upstream);
4615
4634
  const category = raw.category ?? "skill-packs";
@@ -4638,7 +4657,8 @@ function registerManifestAdd(program2) {
4638
4657
  payload[f] = a;
4639
4658
  }
4640
4659
  rl.close();
4641
- if (raw.apply) {
4660
+ const dryRun = raw.dryRun === true;
4661
+ if (!dryRun) {
4642
4662
  writeFileSync(outPath, `${JSON.stringify(payload, null, 2)}
4643
4663
  `, "utf8");
4644
4664
  console.log(`[manifest-add] EE-5 gate passed; wrote ${outPath}`);
@@ -4652,14 +4672,19 @@ function registerManifestAdd(program2) {
4652
4672
 
4653
4673
  // src/cli/research.ts
4654
4674
  function registerResearch(program2) {
4655
- program2.command("research").description("Run research workflow (search category sub-routing \u2192 spawn \u2192 verbatim COMPLETE)").requiredOption("--query <text>", "research prompt (required)").option("--apply", "execute the spawn (default: dry-run preview only)").option("--dry-run", "force dry-run (overrides --apply if both are set)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").option("--model <model>", "subagent model: 'haiku' | 'sonnet' | 'opus'").action(async (raw) => {
4675
+ program2.command("research").description(
4676
+ "Run research workflow (search category sub-routing \u2192 spawn \u2192 verbatim COMPLETE; immediate by default \u2014 use --dry-run for preview)"
4677
+ ).requiredOption("--query <text>", "research prompt (required)").option(
4678
+ "--apply",
4679
+ "(deprecated; kept for backward compat \u2014 research spawns immediately by default)"
4680
+ ).option("--dry-run", "preview only \u2014 do not spawn subagent (opt-in for advanced users)").option("--non-interactive", "skip all prompts (CI / scripts) \u2014 requires --apply or --dry-run").option("--model <model>", "subagent model: 'haiku' | 'sonnet' | 'opus'").action(async (raw) => {
4656
4681
  validateNonInteractiveFlags(raw, "research --query <text>");
4657
4682
  if (!raw.query) {
4658
4683
  console.error("error: --query <text> is required");
4659
4684
  process.exit(2);
4660
4685
  }
4661
4686
  const taskCtx = { task: raw.query, task_type: "search" };
4662
- if (raw.dryRun === true || !raw.apply && !raw.nonInteractive) {
4687
+ if (raw.dryRun === true) {
4663
4688
  const preview = await runRouting(taskCtx, {
4664
4689
  skillsRoot: void 0,
4665
4690
  // Stub spawn — dry-run never reaches it; explicit COMPLETE keeps shape happy.
@@ -4677,7 +4702,9 @@ function registerResearch(program2) {
4677
4702
  }
4678
4703
  console.log(`[dry-run] matched_rule: ${preview.matchedRule?.id ?? "(fallback supervisor)"}`);
4679
4704
  console.log(`[dry-run] query: ${raw.query}`);
4680
- console.log(" (use --apply to spawn the subagent and emit verbatim COMPLETE round-trip)");
4705
+ console.log(
4706
+ " (run without --dry-run to spawn the subagent and emit verbatim COMPLETE round-trip)"
4707
+ );
4681
4708
  process.exit(0);
4682
4709
  }
4683
4710
  const result = await runRouting(taskCtx, {
@@ -5320,12 +5347,12 @@ async function runUninstall(manifest, opts) {
5320
5347
 
5321
5348
  // src/cli/uninstall.ts
5322
5349
  function registerUninstall(program2) {
5323
- program2.command("uninstall <name>").description("Uninstall an upstream (dry-run by default \u2014 pass --apply to execute)").option("--apply", "execute the uninstall (default: dry-run preview only)").option("--dry-run", "force dry-run (overrides --apply if both are set)").option("--yes", "skip interactive confirm \u2014 requires --apply (CI / scripts)").option("--non-interactive", "alias for --yes (CI compat)").action(async (name, raw) => {
5350
+ program2.command("uninstall <name>").description("Uninstall an upstream (immediate by default \u2014 use --dry-run for preview)").option("--apply", "(deprecated; kept for backward compat \u2014 uninstall is immediate by default)").option("--dry-run", "preview only \u2014 do not delete files (opt-in for advanced users)").option("--yes", "skip interactive confirm (CI / scripts) \u2014 fatal with --dry-run").option("--non-interactive", "alias for --yes (CI compat)").action(async (name, raw) => {
5324
5351
  const yes = raw.yes === true || raw.nonInteractive === true;
5325
- if (yes && !raw.apply) {
5352
+ if (yes && raw.dryRun) {
5326
5353
  console.error(
5327
- `error: --yes requires --apply to execute
5328
- fix: harnessed uninstall ${name} --yes --apply`
5354
+ `error: --yes is incompatible with --dry-run (dry-run does not mutate)
5355
+ fix: harnessed uninstall ${name} --yes (immediate) OR harnessed uninstall ${name} --dry-run (preview)`
5329
5356
  );
5330
5357
  process.exit(2);
5331
5358
  }
@@ -5356,10 +5383,10 @@ function registerUninstall(program2) {
5356
5383
  process.exit(1);
5357
5384
  }
5358
5385
  const method = v.manifest.spec.install.method;
5359
- const dryRun = raw.dryRun === true || !raw.apply;
5386
+ const dryRun = raw.dryRun === true;
5360
5387
  if (dryRun) {
5361
5388
  console.log(`[dry-run] would uninstall '${resolvedName}' via method '${method}'`);
5362
- console.log(` run with --apply to execute`);
5389
+ console.log(` run without --dry-run to execute`);
5363
5390
  process.exit(2);
5364
5391
  }
5365
5392
  if (!yes) {