clawpilot 0.1.1 → 0.2.0
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 +160 -67
- package/bin/cli.js +591 -100
- package/docs/PUBLISH_CHECKLIST.md +31 -22
- package/docs/plans/2026-02-13-v0.3-clawra-gap-plan.md +199 -0
- package/docs/plans/2026-02-13-v0.3-implementation.md +434 -0
- package/docs/releases/v0.1.2.md +57 -0
- package/docs/releases/v0.2.0-draft.md +24 -0
- package/docs/releases/v0.2.1-draft.md +19 -0
- package/docs/troubleshooting.md +44 -0
- package/package.json +1 -1
- package/skill/SKILL.md +33 -22
- package/src/config/migrations.js +68 -0
- package/src/install.js +248 -181
- package/src/preflight.js +288 -0
- package/src/runtime/index.js +127 -0
- package/src/runtime/openclaw-gateway.js +135 -0
- package/src/runtime/productivity.js +42 -0
- package/src/runtime/role-pack.js +11 -0
- package/src/runtime/social-formatters.js +22 -0
- package/src/runtime/state-store.js +33 -0
- package/src/runtime/template-renderer.js +7 -0
- package/src/runtime/weekly-report.js +19 -0
- package/templates/content/evening.md +7 -0
- package/templates/content/midday.md +8 -0
- package/templates/content/morning.md +8 -0
- package/templates/content/report.md +5 -0
- package/templates/content/social-linkedin.md +8 -0
- package/templates/content/social-telegram.md +8 -0
- package/templates/content/social-x.md +8 -0
- package/templates/role-packs/hana.json +7 -0
- package/templates/role-packs/minji.json +7 -0
- package/templates/soul-injection.md +38 -14
|
@@ -1,22 +1,31 @@
|
|
|
1
|
-
# Publish Checklist
|
|
2
|
-
|
|
3
|
-
Use this checklist before publishing a new `clawpilot` version to npm.
|
|
4
|
-
|
|
5
|
-
1. Verify tests:
|
|
6
|
-
- `npm test`
|
|
7
|
-
2. Verify installer behavior locally:
|
|
8
|
-
- `node bin/cli.js install --home <temp-dir>`
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- `
|
|
12
|
-
- `bin`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- `
|
|
20
|
-
|
|
21
|
-
- `
|
|
22
|
-
|
|
1
|
+
# Publish Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist before publishing a new `clawpilot` version to npm.
|
|
4
|
+
|
|
5
|
+
1. Verify tests:
|
|
6
|
+
- `npm test`
|
|
7
|
+
2. Verify installer behavior locally:
|
|
8
|
+
- `node bin/cli.js install --home <temp-dir>`
|
|
9
|
+
- `node bin/cli.js install --preflight`
|
|
10
|
+
3. Verify runtime dry-run behavior:
|
|
11
|
+
- `node bin/cli.js run --command morning --dry-run --timezone UTC --role-pack hana`
|
|
12
|
+
- `node bin/cli.js run --command report --dry-run --timezone UTC`
|
|
13
|
+
4. Verify structured error output:
|
|
14
|
+
- `node bin/cli.js run --command morning --json-errors` (without channel should return `channel_required`)
|
|
15
|
+
5. Verify troubleshooting documentation references:
|
|
16
|
+
- `docs/troubleshooting.md`
|
|
17
|
+
6. Review package metadata:
|
|
18
|
+
- `name`
|
|
19
|
+
- `version`
|
|
20
|
+
- `bin`
|
|
21
|
+
- `license`
|
|
22
|
+
7. Confirm npm auth:
|
|
23
|
+
- `npm whoami`
|
|
24
|
+
8. Dry-run package contents:
|
|
25
|
+
- `npm pack --dry-run`
|
|
26
|
+
9. Publish:
|
|
27
|
+
- `npm publish --access public`
|
|
28
|
+
- If your account has publish 2FA enabled: `npm publish --access public --otp=<6-digit-code>`
|
|
29
|
+
10. Validate release:
|
|
30
|
+
- `npm view clawpilot version`
|
|
31
|
+
- `npx clawpilot@latest --help`
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Clawpilot v0.3 Plan (Clawra Gap Fill)
|
|
2
|
+
|
|
3
|
+
Date: 2026-02-13
|
|
4
|
+
Owner: RyanSparkc / clawpilot
|
|
5
|
+
Status: Draft (local only)
|
|
6
|
+
|
|
7
|
+
## 1) Goal
|
|
8
|
+
|
|
9
|
+
在不複製「女友版」定位的前提下,補齊 clawra 的關鍵可用性能力,讓 clawpilot 達到:
|
|
10
|
+
|
|
11
|
+
- 第一次安裝就能成功跑通
|
|
12
|
+
- 發送失敗可被快速定位與修復
|
|
13
|
+
- 有清楚的升級路徑與 demo 體驗
|
|
14
|
+
- 維持「虛構韓系美感,不綁定真人身份」策略
|
|
15
|
+
|
|
16
|
+
## 2) Scope (This Round)
|
|
17
|
+
|
|
18
|
+
優先納入以下 7 項(依優先順序):
|
|
19
|
+
|
|
20
|
+
1. 安裝前檢查(OpenClaw / Gateway / 設定完整性)
|
|
21
|
+
2. 引導式安裝流程(step-by-step)
|
|
22
|
+
3. 重裝 / 升級處理(update/skip/reinstall)
|
|
23
|
+
4. 送訊可靠性(錯誤分類 + 修復指引)
|
|
24
|
+
5. 一鍵範例腳本(safe/send 雙軌 first success demo)
|
|
25
|
+
6. 配置集中管理(delivery/channel/role-pack/runtime defaults)
|
|
26
|
+
7. Troubleshooting 擴充(常見錯誤清單)
|
|
27
|
+
|
|
28
|
+
## 3) Out of Scope (v0.3)
|
|
29
|
+
|
|
30
|
+
- 真實人物身份綁定與肖像生成
|
|
31
|
+
- 自動上傳多平台圖片(Discord/WhatsApp/Telegram 同時送圖)
|
|
32
|
+
- 需要外部付費 API 的完整圖生產線(先保留接口,不強綁)
|
|
33
|
+
|
|
34
|
+
## 4) Milestones
|
|
35
|
+
|
|
36
|
+
## M1: Installer Reliability Foundation
|
|
37
|
+
|
|
38
|
+
Target:
|
|
39
|
+
- 安裝流程先做「前置檢查 + 引導」
|
|
40
|
+
|
|
41
|
+
Tasks:
|
|
42
|
+
- 新增 `preflight` 檢查模組,至少包含:
|
|
43
|
+
- `openclaw` CLI 是否可執行與版本資訊
|
|
44
|
+
- `openclaw` home / `skills` / `workspace` 目錄可寫入
|
|
45
|
+
- 既有 `openclaw.json` 可解析性
|
|
46
|
+
- `delivery.mode=openclaw-gateway` 時的必要欄位(如 channel / token 來源)
|
|
47
|
+
- 在 `install` 內加入互動式步驟(timezone、delivery channel、role pack)
|
|
48
|
+
- `--yes` 模式保留非互動安裝,缺值時給明確錯誤碼與修復指令
|
|
49
|
+
|
|
50
|
+
Likely files:
|
|
51
|
+
- `src/install.js`
|
|
52
|
+
- `bin/cli.js`
|
|
53
|
+
- `src/runtime/openclaw-gateway.js`
|
|
54
|
+
|
|
55
|
+
Acceptance:
|
|
56
|
+
- 缺失條件能在安裝前阻擋並提示修復方式
|
|
57
|
+
- `npx -y clawpilot@latest install --yes ...` 在 CI/自動化可穩定執行
|
|
58
|
+
- preflight 輸出含 machine-readable summary(供測試斷言)
|
|
59
|
+
|
|
60
|
+
## M2: Upgrade/Reinstall + Config Centralization
|
|
61
|
+
|
|
62
|
+
Target:
|
|
63
|
+
- 已安裝狀態下,提供明確更新路徑,避免覆寫驚喜
|
|
64
|
+
|
|
65
|
+
Tasks:
|
|
66
|
+
- 偵測既有安裝,提供 `update / skip / reinstall` 分支(CLI 與 `--yes` 都可用)
|
|
67
|
+
- 將 `delivery/channel/role-pack/runtime defaults` 集中到單一 config entry
|
|
68
|
+
- 導入版本化配置遷移:
|
|
69
|
+
- 新增 `configSchemaVersion`
|
|
70
|
+
- 建立 `vN -> vN+1` migration table(可重複執行且結果一致)
|
|
71
|
+
- 保留未知欄位與使用者覆寫值
|
|
72
|
+
|
|
73
|
+
Likely files:
|
|
74
|
+
- `src/install.js`
|
|
75
|
+
- `src/runtime/index.js`
|
|
76
|
+
- `skill/manifest.json`
|
|
77
|
+
|
|
78
|
+
Acceptance:
|
|
79
|
+
- 重新安裝不會重複注入內容
|
|
80
|
+
- 版本升級時保留使用者舊設定
|
|
81
|
+
- migration 對同一份 config 執行兩次結果相同(idempotent)
|
|
82
|
+
|
|
83
|
+
## M3: Delivery Error Taxonomy + Troubleshooting
|
|
84
|
+
|
|
85
|
+
Target:
|
|
86
|
+
- 送訊失敗時,能回傳可行動的錯誤資訊
|
|
87
|
+
|
|
88
|
+
Tasks:
|
|
89
|
+
- 建立錯誤分類:
|
|
90
|
+
- `gateway_missing`
|
|
91
|
+
- `gateway_unreachable`
|
|
92
|
+
- `auth_invalid`
|
|
93
|
+
- `channel_not_found`
|
|
94
|
+
- `permission_denied`
|
|
95
|
+
- `network_timeout`
|
|
96
|
+
- `invalid_payload`
|
|
97
|
+
- `rate_limited`
|
|
98
|
+
- `unknown`
|
|
99
|
+
- 建立 stderr/status -> error code 映射規則(Regex + fallback)
|
|
100
|
+
- CLI 失敗輸出標準化(`code + reason + one-line fix + docs link`)
|
|
101
|
+
- `--json-errors` 輸出機制(給自動化與監控)
|
|
102
|
+
- 新增 troubleshooting 文件與 FAQ
|
|
103
|
+
|
|
104
|
+
Likely files:
|
|
105
|
+
- `src/runtime/openclaw-gateway.js`
|
|
106
|
+
- `src/runtime/index.js`
|
|
107
|
+
- `README.md`
|
|
108
|
+
- `docs/troubleshooting.md`(新檔,必要時由 `PUBLISH_CHECKLIST` 連結)
|
|
109
|
+
|
|
110
|
+
Acceptance:
|
|
111
|
+
- 常見失敗可在 1 次輸出內看懂原因與下一步
|
|
112
|
+
- 測試覆蓋每個錯誤分類與映射分支
|
|
113
|
+
|
|
114
|
+
## M4: One-Command Demo Path
|
|
115
|
+
|
|
116
|
+
Target:
|
|
117
|
+
- 新手可快速達成 first success,且避免誤發送
|
|
118
|
+
|
|
119
|
+
Tasks:
|
|
120
|
+
- 提供雙軌 demo script(PowerShell + Bash):
|
|
121
|
+
- `demo-safe`: 安裝 + morning dry-run(不實送)
|
|
122
|
+
- `demo-send`: 實送流程,需 `--confirm` 或互動確認
|
|
123
|
+
- README 加入 copy-paste 範例
|
|
124
|
+
- demo 過程若缺設定,直接導向 M1 的引導式補齊流程
|
|
125
|
+
|
|
126
|
+
Likely files:
|
|
127
|
+
- `scripts/demo-safe.ps1`
|
|
128
|
+
- `scripts/demo-safe.sh`
|
|
129
|
+
- `scripts/demo-send.ps1`
|
|
130
|
+
- `scripts/demo-send.sh`
|
|
131
|
+
- `README.md`
|
|
132
|
+
|
|
133
|
+
Acceptance:
|
|
134
|
+
- 新使用者依 README 5 分鐘內可完成首次成功 dry-run
|
|
135
|
+
- 有明確確認機制後可完成首次成功實送
|
|
136
|
+
|
|
137
|
+
## 5) Optional Extension (Behind Feature Flag)
|
|
138
|
+
|
|
139
|
+
主題:Image capability 接口化(不綁真人)
|
|
140
|
+
|
|
141
|
+
- 僅新增 provider interface,不內建真人 prompt
|
|
142
|
+
- 預設 persona 為 fictional K-style descriptors
|
|
143
|
+
- 先支援 `--image-dry-run` 生成 prompt payload,不直接走付費 API
|
|
144
|
+
|
|
145
|
+
## 6) Test Plan
|
|
146
|
+
|
|
147
|
+
以 coverage matrix 為主,不以「測試數量」作為唯一指標。
|
|
148
|
+
|
|
149
|
+
- Installer
|
|
150
|
+
- preflight fail/success matrix(CLI 缺失、無權限、壞 config、完整通過)
|
|
151
|
+
- `--yes` 缺值錯誤碼與訊息
|
|
152
|
+
- Migration
|
|
153
|
+
- `update / skip / reinstall` 分支
|
|
154
|
+
- `configSchemaVersion` 遷移與 idempotency
|
|
155
|
+
- 舊設定保留(含未知欄位)
|
|
156
|
+
- Runtime Delivery
|
|
157
|
+
- gateway error taxonomy mapping(所有錯誤碼)
|
|
158
|
+
- `--json-errors` 輸出格式穩定性
|
|
159
|
+
- Demo/Docs
|
|
160
|
+
- script smoke checks(safe/send)
|
|
161
|
+
- README 指令與 `--help` 一致
|
|
162
|
+
|
|
163
|
+
## 7) Release Plan
|
|
164
|
+
|
|
165
|
+
- `v0.2.x` 維護:只收 bugfix
|
|
166
|
+
- `v0.3.0-beta.1`:M1 + M2
|
|
167
|
+
- `v0.3.0-beta.2`:M3 + M4
|
|
168
|
+
- `v0.3.0`:穩定版發布
|
|
169
|
+
|
|
170
|
+
Go/No-Go Gates(GA 前):
|
|
171
|
+
- 首次安裝成功率(fresh env)達既定門檻(建議 >= 90%)
|
|
172
|
+
- Top 錯誤類型可被正確分類並給出修復指引(建議 >= 95%)
|
|
173
|
+
- 回歸測試全綠,且無 P0/P1 已知問題
|
|
174
|
+
|
|
175
|
+
Rollback 機制:
|
|
176
|
+
- 若 beta 發現高嚴重度回歸,立即凍結新功能
|
|
177
|
+
- 以 patch release 回復上一穩定行為並補 migration 修復腳本
|
|
178
|
+
|
|
179
|
+
## 8) Risks and Mitigation
|
|
180
|
+
|
|
181
|
+
- Risk: OpenClaw/Gateway 版本差異造成安裝邏輯不一致
|
|
182
|
+
Mitigation: preflight 顯示偵測版本並提供最小版本提示
|
|
183
|
+
|
|
184
|
+
- Risk: 互動流程讓自動化部署變慢
|
|
185
|
+
Mitigation: `--yes` 保留完整無互動模式,並保證可機器可讀錯誤輸出
|
|
186
|
+
|
|
187
|
+
- Risk: 錯誤訊息仍偏技術、使用者看不懂
|
|
188
|
+
Mitigation: 錯誤輸出固定「原因 + 一行修復命令 + 文件連結」
|
|
189
|
+
|
|
190
|
+
- Risk: config migration 破壞既有用戶設定
|
|
191
|
+
Mitigation: migration idempotency test + unknown fields preservation + rollback plan
|
|
192
|
+
|
|
193
|
+
## 9) Definition of Done
|
|
194
|
+
|
|
195
|
+
- M1-M3 全數完成(必要項)
|
|
196
|
+
- M4 完成,或以 issue 明確延期並提供替代 demo-safe 體驗
|
|
197
|
+
- 測試全綠(含新增 matrix 測試)
|
|
198
|
+
- README 與 CLI 行為一致
|
|
199
|
+
- `npx clawpilot@latest install` 新手流程可跑通
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
# Clawpilot v0.3 Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|
4
|
+
|
|
5
|
+
**Goal:** 以最小風險完成 v0.3 gap 補齊,讓安裝、升級與送訊錯誤處理可預期且可觀測。
|
|
6
|
+
**Architecture:** 先補 installer preflight 與 config migration 基礎,再加上 gateway 錯誤分類與 CLI 統一錯誤輸出,最後補 demo 與文件。所有功能以 TDD 驅動,先寫失敗測試,再補最小實作。
|
|
7
|
+
**Tech Stack:** Node.js 18+, CommonJS, `node:test`, `node:assert/strict`, PowerShell/Bash scripts.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
### Task 1: Preflight 檢查模組
|
|
12
|
+
|
|
13
|
+
**Files:**
|
|
14
|
+
- Create: `src/preflight.js`
|
|
15
|
+
- Test: `test/preflight.test.cjs`
|
|
16
|
+
- Modify: `src/install.js`
|
|
17
|
+
|
|
18
|
+
**Step 1: Write the failing test**
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
test('preflight returns gateway_missing when openclaw command is unavailable', () => {
|
|
22
|
+
const summary = runPreflight({
|
|
23
|
+
openClawHome: 'C:/tmp/.openclaw',
|
|
24
|
+
commandRunner: () => ({ status: 1, stderr: 'not found' }),
|
|
25
|
+
fsOps: fakeFsWithWritableDirs()
|
|
26
|
+
});
|
|
27
|
+
assert.equal(summary.ok, false);
|
|
28
|
+
assert.equal(summary.issues[0].code, 'gateway_missing');
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Step 2: Run test to verify it fails**
|
|
33
|
+
|
|
34
|
+
Run: `node --test test/preflight.test.cjs`
|
|
35
|
+
Expected: FAIL with `runPreflight is not a function` (or module not found).
|
|
36
|
+
|
|
37
|
+
**Step 3: Write minimal implementation**
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
function runPreflight({ openClawHome, commandRunner, fsOps }) {
|
|
41
|
+
const issues = [];
|
|
42
|
+
const cmd = commandRunner('openclaw', ['--version']);
|
|
43
|
+
if (cmd.status !== 0) issues.push({ code: 'gateway_missing', reason: 'openclaw unavailable' });
|
|
44
|
+
return { ok: issues.length === 0, issues };
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Step 4: Run test to verify it passes**
|
|
49
|
+
|
|
50
|
+
Run: `node --test test/preflight.test.cjs`
|
|
51
|
+
Expected: PASS.
|
|
52
|
+
|
|
53
|
+
**Step 5: Commit**
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git add src/preflight.js test/preflight.test.cjs src/install.js
|
|
57
|
+
git commit -m "feat: add installer preflight foundation"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Task 2: 安裝流程接 preflight + `--yes` 明確錯誤
|
|
61
|
+
|
|
62
|
+
**Files:**
|
|
63
|
+
- Modify: `bin/cli.js`
|
|
64
|
+
- Modify: `src/install.js`
|
|
65
|
+
- Test: `test/cli-install-options.test.cjs`
|
|
66
|
+
|
|
67
|
+
**Step 1: Write the failing test**
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
test('install --yes fails with machine-readable code when preflight fails', () => {
|
|
71
|
+
const result = runCli(['install', '--yes'], { CLAWPILOT_TEST_FORCE_PREFLIGHT_FAIL: '1' });
|
|
72
|
+
assert.notEqual(result.status, 0);
|
|
73
|
+
assert.match(result.stderr, /code: gateway_missing/i);
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Step 2: Run test to verify it fails**
|
|
78
|
+
|
|
79
|
+
Run: `node --test test/cli-install-options.test.cjs`
|
|
80
|
+
Expected: FAIL because `code: gateway_missing` is not printed.
|
|
81
|
+
|
|
82
|
+
**Step 3: Write minimal implementation**
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
if (options.yes && !preflight.ok) {
|
|
86
|
+
throw new Error(`code: ${preflight.issues[0].code} fix: npm i -g openclaw`);
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Step 4: Run test to verify it passes**
|
|
91
|
+
|
|
92
|
+
Run: `node --test test/cli-install-options.test.cjs`
|
|
93
|
+
Expected: PASS.
|
|
94
|
+
|
|
95
|
+
**Step 5: Commit**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
git add bin/cli.js src/install.js test/cli-install-options.test.cjs
|
|
99
|
+
git commit -m "feat: block install on preflight failure in --yes mode"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Task 3: 版本化配置遷移 (`configSchemaVersion`)
|
|
103
|
+
|
|
104
|
+
**Files:**
|
|
105
|
+
- Create: `src/config/migrations.js`
|
|
106
|
+
- Test: `test/config-migrations.test.cjs`
|
|
107
|
+
- Modify: `src/install.js`
|
|
108
|
+
|
|
109
|
+
**Step 1: Write the failing test**
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
test('migrateConfig upgrades v1 to v2 and preserves unknown fields', () => {
|
|
113
|
+
const next = migrateConfig({ configSchemaVersion: 1, xCustom: true, skills: {} });
|
|
114
|
+
assert.equal(next.configSchemaVersion, 2);
|
|
115
|
+
assert.equal(next.xCustom, true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('migrateConfig is idempotent', () => {
|
|
119
|
+
const first = migrateConfig({ configSchemaVersion: 1, skills: {} });
|
|
120
|
+
const second = migrateConfig(first);
|
|
121
|
+
assert.deepEqual(second, first);
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Step 2: Run test to verify it fails**
|
|
126
|
+
|
|
127
|
+
Run: `node --test test/config-migrations.test.cjs`
|
|
128
|
+
Expected: FAIL with `migrateConfig is not a function`.
|
|
129
|
+
|
|
130
|
+
**Step 3: Write minimal implementation**
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
function migrateConfig(input) {
|
|
134
|
+
const current = { ...input };
|
|
135
|
+
const from = current.configSchemaVersion || 1;
|
|
136
|
+
if (from < 2) current.configSchemaVersion = 2;
|
|
137
|
+
return current;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Step 4: Run test to verify it passes**
|
|
142
|
+
|
|
143
|
+
Run: `node --test test/config-migrations.test.cjs`
|
|
144
|
+
Expected: PASS.
|
|
145
|
+
|
|
146
|
+
**Step 5: Commit**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
git add src/config/migrations.js src/install.js test/config-migrations.test.cjs
|
|
150
|
+
git commit -m "feat: add versioned config migration pipeline"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Task 4: `update / skip / reinstall` 分支
|
|
154
|
+
|
|
155
|
+
**Files:**
|
|
156
|
+
- Modify: `bin/cli.js`
|
|
157
|
+
- Modify: `src/install.js`
|
|
158
|
+
- Test: `test/install-existing-behavior.test.cjs`
|
|
159
|
+
|
|
160
|
+
**Step 1: Write the failing test**
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
test('existing installation with --on-existing skip exits successfully without overwrite', async () => {
|
|
164
|
+
const result = await installSkill({ openClawHome: tmpHome, packageRoot: tmpPkg, onExisting: 'skip' });
|
|
165
|
+
assert.equal(result.action, 'skip');
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Step 2: Run test to verify it fails**
|
|
170
|
+
|
|
171
|
+
Run: `node --test test/install-existing-behavior.test.cjs`
|
|
172
|
+
Expected: FAIL because `onExisting` is unsupported.
|
|
173
|
+
|
|
174
|
+
**Step 3: Write minimal implementation**
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
if (fs.existsSync(skillDir)) {
|
|
178
|
+
if (onExisting === 'skip') return { action: 'skip', skillDir, configPath, workspaceSoulPath, identityPath };
|
|
179
|
+
if (onExisting === 'update') { /* no rm, only merge config+templates */ }
|
|
180
|
+
if (onExisting === 'reinstall') fs.rmSync(skillDir, { recursive: true, force: true });
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Step 4: Run test to verify it passes**
|
|
185
|
+
|
|
186
|
+
Run: `node --test test/install-existing-behavior.test.cjs`
|
|
187
|
+
Expected: PASS.
|
|
188
|
+
|
|
189
|
+
**Step 5: Commit**
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git add bin/cli.js src/install.js test/install-existing-behavior.test.cjs
|
|
193
|
+
git commit -m "feat: support update skip reinstall install paths"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Task 5: Gateway 錯誤分類與映射
|
|
197
|
+
|
|
198
|
+
**Files:**
|
|
199
|
+
- Modify: `src/runtime/openclaw-gateway.js`
|
|
200
|
+
- Test: `test/openclaw-gateway.test.cjs`
|
|
201
|
+
|
|
202
|
+
**Step 1: Write the failing test**
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
test('maps ENOENT to gateway_missing', () => {
|
|
206
|
+
const err = classifyGatewayError({ status: 1, stderr: 'ENOENT openclaw' });
|
|
207
|
+
assert.equal(err.code, 'gateway_missing');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('maps timeout text to network_timeout', () => {
|
|
211
|
+
const err = classifyGatewayError({ status: 1, stderr: 'ETIMEDOUT connect' });
|
|
212
|
+
assert.equal(err.code, 'network_timeout');
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Step 2: Run test to verify it fails**
|
|
217
|
+
|
|
218
|
+
Run: `node --test test/openclaw-gateway.test.cjs`
|
|
219
|
+
Expected: FAIL with `classifyGatewayError is not a function`.
|
|
220
|
+
|
|
221
|
+
**Step 3: Write minimal implementation**
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
function classifyGatewayError(result) {
|
|
225
|
+
const text = `${result.stderr || ''} ${result.stdout || ''}`;
|
|
226
|
+
if (/ENOENT|not found/i.test(text)) return { code: 'gateway_missing' };
|
|
227
|
+
if (/timed?out|ETIMEDOUT/i.test(text)) return { code: 'network_timeout' };
|
|
228
|
+
return { code: 'unknown' };
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Step 4: Run test to verify it passes**
|
|
233
|
+
|
|
234
|
+
Run: `node --test test/openclaw-gateway.test.cjs`
|
|
235
|
+
Expected: PASS.
|
|
236
|
+
|
|
237
|
+
**Step 5: Commit**
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
git add src/runtime/openclaw-gateway.js test/openclaw-gateway.test.cjs
|
|
241
|
+
git commit -m "feat: add gateway error taxonomy mapping"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Task 6: CLI 統一錯誤輸出與 `--json-errors`
|
|
245
|
+
|
|
246
|
+
**Files:**
|
|
247
|
+
- Modify: `bin/cli.js`
|
|
248
|
+
- Modify: `src/runtime/index.js`
|
|
249
|
+
- Test: `test/cli-run-command.test.cjs`
|
|
250
|
+
- Create: `test/cli-errors.test.cjs`
|
|
251
|
+
|
|
252
|
+
**Step 1: Write the failing test**
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
test('run outputs json error when --json-errors is enabled', () => {
|
|
256
|
+
const result = runCli(['run', '--command', 'morning', '--json-errors']);
|
|
257
|
+
const payload = JSON.parse(result.stderr);
|
|
258
|
+
assert.equal(payload.code, 'channel_required');
|
|
259
|
+
assert.match(payload.fix, /--channel/);
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Step 2: Run test to verify it fails**
|
|
264
|
+
|
|
265
|
+
Run: `node --test test/cli-errors.test.cjs`
|
|
266
|
+
Expected: FAIL because CLI does not emit JSON errors.
|
|
267
|
+
|
|
268
|
+
**Step 3: Write minimal implementation**
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
catch (error) {
|
|
272
|
+
const normalized = normalizeCliError(error);
|
|
273
|
+
if (options.jsonErrors) process.stderr.write(`${JSON.stringify(normalized)}\n`);
|
|
274
|
+
else console.error(`${normalized.code}: ${normalized.reason}\nFix: ${normalized.fix}`);
|
|
275
|
+
process.exitCode = 1;
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Step 4: Run test to verify it passes**
|
|
280
|
+
|
|
281
|
+
Run: `node --test test/cli-errors.test.cjs`
|
|
282
|
+
Expected: PASS.
|
|
283
|
+
|
|
284
|
+
**Step 5: Commit**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
git add bin/cli.js src/runtime/index.js test/cli-errors.test.cjs test/cli-run-command.test.cjs
|
|
288
|
+
git commit -m "feat: standardize cli error output with json mode"
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Task 7: Troubleshooting 文件與 README 對齊
|
|
292
|
+
|
|
293
|
+
**Files:**
|
|
294
|
+
- Create: `docs/troubleshooting.md`
|
|
295
|
+
- Modify: `README.md`
|
|
296
|
+
- Modify: `docs/PUBLISH_CHECKLIST.md`
|
|
297
|
+
- Test: `test/docs-smoke.test.cjs`
|
|
298
|
+
|
|
299
|
+
**Step 1: Write the failing test**
|
|
300
|
+
|
|
301
|
+
```js
|
|
302
|
+
test('README references troubleshooting doc and json-errors flag', () => {
|
|
303
|
+
const readme = fs.readFileSync(path.join(__dirname, '..', 'README.md'), 'utf8');
|
|
304
|
+
assert.match(readme, /docs\/troubleshooting\.md/);
|
|
305
|
+
assert.match(readme, /--json-errors/);
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Step 2: Run test to verify it fails**
|
|
310
|
+
|
|
311
|
+
Run: `node --test test/docs-smoke.test.cjs`
|
|
312
|
+
Expected: FAIL because references are missing.
|
|
313
|
+
|
|
314
|
+
**Step 3: Write minimal implementation**
|
|
315
|
+
|
|
316
|
+
```md
|
|
317
|
+
## Troubleshooting
|
|
318
|
+
- See `docs/troubleshooting.md`
|
|
319
|
+
- Use `clawpilot run ... --json-errors` for machine-readable diagnostics
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Step 4: Run test to verify it passes**
|
|
323
|
+
|
|
324
|
+
Run: `node --test test/docs-smoke.test.cjs`
|
|
325
|
+
Expected: PASS.
|
|
326
|
+
|
|
327
|
+
**Step 5: Commit**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
git add README.md docs/troubleshooting.md docs/PUBLISH_CHECKLIST.md test/docs-smoke.test.cjs
|
|
331
|
+
git commit -m "docs: add runtime troubleshooting and json error guidance"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Task 8: Demo 腳本(safe/send)與 smoke 測試
|
|
335
|
+
|
|
336
|
+
**Files:**
|
|
337
|
+
- Create: `scripts/demo-safe.ps1`
|
|
338
|
+
- Create: `scripts/demo-safe.sh`
|
|
339
|
+
- Create: `scripts/demo-send.ps1`
|
|
340
|
+
- Create: `scripts/demo-send.sh`
|
|
341
|
+
- Create: `test/demo-scripts-smoke.test.cjs`
|
|
342
|
+
- Modify: `README.md`
|
|
343
|
+
|
|
344
|
+
**Step 1: Write the failing test**
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
test('demo-safe scripts include --dry-run and never send media', () => {
|
|
348
|
+
const ps1 = fs.readFileSync(path.join(repo, 'scripts', 'demo-safe.ps1'), 'utf8');
|
|
349
|
+
assert.match(ps1, /--dry-run/);
|
|
350
|
+
assert.doesNotMatch(ps1, /openclaw message send/);
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Step 2: Run test to verify it fails**
|
|
355
|
+
|
|
356
|
+
Run: `node --test test/demo-scripts-smoke.test.cjs`
|
|
357
|
+
Expected: FAIL because scripts do not exist.
|
|
358
|
+
|
|
359
|
+
**Step 3: Write minimal implementation**
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# demo-safe.sh
|
|
363
|
+
node bin/cli.js install --yes --timezone UTC
|
|
364
|
+
node bin/cli.js run --command morning --dry-run --timezone UTC
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
```powershell
|
|
368
|
+
# demo-send.ps1
|
|
369
|
+
param([string]$Channel,[switch]$Confirm)
|
|
370
|
+
if (-not $Confirm) { throw "Pass -Confirm to send" }
|
|
371
|
+
node bin/cli.js run --command morning --channel $Channel --timezone UTC
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Step 4: Run test to verify it passes**
|
|
375
|
+
|
|
376
|
+
Run: `node --test test/demo-scripts-smoke.test.cjs`
|
|
377
|
+
Expected: PASS.
|
|
378
|
+
|
|
379
|
+
**Step 5: Commit**
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
git add scripts/demo-safe.ps1 scripts/demo-safe.sh scripts/demo-send.ps1 scripts/demo-send.sh test/demo-scripts-smoke.test.cjs README.md
|
|
383
|
+
git commit -m "feat: add safe and confirmed send demo scripts"
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Task 9: 全量驗證與發布前檢查
|
|
387
|
+
|
|
388
|
+
**Files:**
|
|
389
|
+
- Modify: `package.json` (if adding script aliases)
|
|
390
|
+
- Modify: `docs/plans/2026-02-13-v0.3-clawra-gap-plan.md` (status updates)
|
|
391
|
+
|
|
392
|
+
**Step 1: Run full test suite**
|
|
393
|
+
|
|
394
|
+
Run: `npm test`
|
|
395
|
+
Expected: PASS all tests.
|
|
396
|
+
|
|
397
|
+
**Step 2: Smoke CLI behavior**
|
|
398
|
+
|
|
399
|
+
Run: `node bin/cli.js --help`
|
|
400
|
+
Expected: Includes `--json-errors`, `--on-existing`, demo docs references.
|
|
401
|
+
|
|
402
|
+
**Step 3: Validate README command examples**
|
|
403
|
+
|
|
404
|
+
Run: `node --test test/docs-smoke.test.cjs`
|
|
405
|
+
Expected: PASS.
|
|
406
|
+
|
|
407
|
+
**Step 4: Tag release readiness note**
|
|
408
|
+
|
|
409
|
+
```md
|
|
410
|
+
- v0.3.0-beta.1 gate: PASS (M1/M2)
|
|
411
|
+
- v0.3.0-beta.2 gate: PASS (M3/M4)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Step 5: Commit**
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
git add docs/plans/2026-02-13-v0.3-clawra-gap-plan.md README.md package.json
|
|
418
|
+
git commit -m "chore: prepare v0.3 release gates and validation notes"
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Execution Order
|
|
422
|
+
|
|
423
|
+
1. Task 1 -> Task 2 (installer preflight path)
|
|
424
|
+
2. Task 3 -> Task 4 (migration + existing install behavior)
|
|
425
|
+
3. Task 5 -> Task 6 (runtime error taxonomy + CLI output)
|
|
426
|
+
4. Task 7 -> Task 8 (docs + demo paths)
|
|
427
|
+
5. Task 9 (final verification and release gate notes)
|
|
428
|
+
|
|
429
|
+
## Non-Negotiable Checks
|
|
430
|
+
|
|
431
|
+
- 每個 Task 先跑失敗測試,再寫最小實作,再回測。
|
|
432
|
+
- 每次 commit 僅包含單一任務主題。
|
|
433
|
+
- 不可跳過 `npm test` 與 docs smoke 測試。
|
|
434
|
+
- 任何新增錯誤碼都必須在 `docs/troubleshooting.md` 出現。
|