harveyz-skill 0.1.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 +67 -0
- package/bin/cli.js +81 -0
- package/bundles.json +24 -0
- package/lib/bundles.js +39 -0
- package/lib/installer.js +46 -0
- package/lib/targets.js +23 -0
- package/package.json +42 -0
- package/skills/analysis/skill-analyzer/CHANGELOG.md +78 -0
- package/skills/analysis/skill-analyzer/SKILL.md +150 -0
- package/skills/harness/full-stack-debug-env/SKILL.md +468 -0
- package/skills/harness/full-stack-debug-env/references/README.md +31 -0
- package/skills/harness/full-stack-debug-env/references/tech-stacks/browser-spa.md +89 -0
- package/skills/harness/full-stack-debug-env/references/tech-stacks/docker-compose.md +77 -0
- package/skills/harness/full-stack-debug-env/references/tech-stacks/electron.md +123 -0
- package/skills/harness/full-stack-debug-env/references/tech-stacks/node-process.md +76 -0
- package/skills/superpowers-fork/brainstorming/SKILL.md +148 -0
- package/skills/superpowers-fork/executing-plans/SKILL.md +104 -0
- package/skills/superpowers-fork/systematic-debugging/SKILL.md +217 -0
- package/skills/superpowers-fork/using-git-worktrees/SKILL.md +192 -0
- package/skills/superpowers-fork/writing-plans/SKILL.md +187 -0
- package/skills/task/pm-task-dispatch/SKILL.md +165 -0
- package/skills/task/pm-task-dispatch/references/agent-mapping.md +59 -0
- package/skills/task/pm-task-dispatch/references/task-template.md +145 -0
- package/skills/task/task-close/SKILL.md +148 -0
- package/skills/task/task-close/references/output-templates.md +76 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Electron 日志最佳实践
|
|
2
|
+
|
|
3
|
+
适用场景:Electron 桌面应用(含主进程、preload、renderer)
|
|
4
|
+
|
|
5
|
+
## 时间戳处理
|
|
6
|
+
|
|
7
|
+
- **主进程 stdout**:通常无时间戳,capture 层注入(python3,跨平台):
|
|
8
|
+
```bash
|
|
9
|
+
electron . 2>&1 | python3 -u -c 'import sys,datetime; [print(datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), l.rstrip(), flush=True) for l in iter(sys.stdin.readline,"")]' >> main.log &
|
|
10
|
+
```
|
|
11
|
+
- **renderer console hook**:在 hook 代码里直接用 `new Date().toISOString()` 生成,已是 ISO 8601,无需额外处理(下方示例已包含)。
|
|
12
|
+
- **electron-log 库**:默认格式含时间戳但非 ISO,建议配置 `log.transports.file.format = '[{iso}] [{level}] {text}'`。
|
|
13
|
+
|
|
14
|
+
## 三条日志路径
|
|
15
|
+
|
|
16
|
+
| 层 | 日志去向 | 捕获方式 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| 主进程(main.js) | stdout/stderr(终端启动时可见) | 包裹启动命令(策略 B) |
|
|
19
|
+
| 内嵌子服务(spawn + pipe) | 主进程 stdout(前缀标识来源) | 同上,无独立文件 |
|
|
20
|
+
| preload 脚本 | renderer 的 DevTools console | renderer 层捕获 |
|
|
21
|
+
| renderer(页面 JS) | DevTools console(F12) | preload 拦截或 CDP |
|
|
22
|
+
|
|
23
|
+
**主进程 stdout 和 renderer console 是完全独立的两条路径,必须分别接入。内嵌子服务若通过 pipe 路由到主进程,则合并在主进程日志中,没有独立文件。**
|
|
24
|
+
|
|
25
|
+
## 主进程捕获
|
|
26
|
+
|
|
27
|
+
启动时包裹,写入独立文件,注入时间戳:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
LOGS=/tmp/myproject-logs
|
|
31
|
+
mkdir -p "$LOGS"
|
|
32
|
+
|
|
33
|
+
# python3 方案(跨平台,Linux/macOS 均可用)
|
|
34
|
+
PY_TS='import sys,datetime; [print(datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), l.rstrip(), flush=True) for l in iter(sys.stdin.readline,"")]'
|
|
35
|
+
|
|
36
|
+
electron . 2>&1 | python3 -u -c "$PY_TS" >> "$LOGS/main.log" &
|
|
37
|
+
# 或通过 npm script:
|
|
38
|
+
npm start 2>&1 | python3 -u -c "$PY_TS" >> "$LOGS/main.log" &
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
如果已通过 GUI 启动(非终端),主进程日志可能写入系统日志:
|
|
42
|
+
- macOS:`~/Library/Logs/<AppName>/main.log`(如用 electron-log)
|
|
43
|
+
- Windows:`%APPDATA%\<AppName>\logs\`
|
|
44
|
+
|
|
45
|
+
## Renderer Console 捕获
|
|
46
|
+
|
|
47
|
+
**方案 A:preload 拦截(推荐,无需修改业务代码)**
|
|
48
|
+
|
|
49
|
+
在 preload.js 中拦截 console,写入独立的 renderer 日志文件:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
// preload.js
|
|
53
|
+
const fs = require('fs');
|
|
54
|
+
const RENDERER_LOG = process.env.RENDERER_LOG || '/tmp/myproject-logs/renderer.log';
|
|
55
|
+
|
|
56
|
+
['log', 'info', 'warn', 'error'].forEach(level => {
|
|
57
|
+
const orig = console[level];
|
|
58
|
+
console[level] = (...args) => {
|
|
59
|
+
orig(...args);
|
|
60
|
+
const line = `${new Date().toISOString()} ${level} ${args.map(a =>
|
|
61
|
+
typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ')}\n`;
|
|
62
|
+
fs.appendFileSync(RENDERER_LOG, line);
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
window.addEventListener('error', e => {
|
|
67
|
+
fs.appendFileSync(RENDERER_LOG,
|
|
68
|
+
`${new Date().toISOString()} uncaught ${e.message} ${e.filename}:${e.lineno}\n`);
|
|
69
|
+
});
|
|
70
|
+
window.addEventListener('unhandledrejection', e => {
|
|
71
|
+
fs.appendFileSync(RENDERER_LOG,
|
|
72
|
+
`${new Date().toISOString()} unhandledRejection ${e.reason}\n`);
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
主进程写自己的日志文件(`main.log`),renderer 写自己的(`renderer.log`),两者独立。
|
|
77
|
+
|
|
78
|
+
**方案 B:CDP(Chrome DevTools Protocol)**
|
|
79
|
+
|
|
80
|
+
用于测试框架(Playwright with Electron、Spectron 等),在测试 setup 中注册:
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
const { _electron: electron } = require('playwright');
|
|
84
|
+
const RENDERER_LOG = '/tmp/myproject-logs/renderer.log';
|
|
85
|
+
const app = await electron.launch({ args: ['main.js'] });
|
|
86
|
+
const page = await app.firstWindow();
|
|
87
|
+
page.on('console', msg => {
|
|
88
|
+
const ts = new Date().toISOString();
|
|
89
|
+
fs.appendFileSync(RENDERER_LOG, `${ts} ${msg.type()} ${msg.text()}\n`);
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 嵌入式子服务(Electron 内嵌 HTTP/gRPC 服务)
|
|
94
|
+
|
|
95
|
+
Electron 应用常通过 `spawn` 在内部启动一个本地服务(HTTP、gRPC 等),并把子进程的 stdout/stderr pipe 到主进程的 console:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
// main-helpers.js 典型模式
|
|
99
|
+
httpProcess = spawn('node', ['services/http-server/index.js'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
100
|
+
httpProcess.stdout.on('data', buf => console.log(`[service-name] ${buf.toString().trimEnd()}`));
|
|
101
|
+
httpProcess.stderr.on('data', buf => console.warn(`[service-name] ${buf.toString().trimEnd()}`));
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**后果:子服务没有独立日志文件**,它的所有输出都以 `[service-name]` 前缀合并进 `main-process.log`。
|
|
105
|
+
|
|
106
|
+
**识别方法:** 若在第二阶段发现某个服务(如 HTTP API)有进程但找不到独立日志文件,检查 Electron 主进程的启动代码,看是否有 `spawn` + stdout pipe 的模式。
|
|
107
|
+
|
|
108
|
+
**查询方法:** 不要找独立的 `http.log`,直接在主进程日志里按前缀过滤:
|
|
109
|
+
```bash
|
|
110
|
+
grep '\[service-name\]' electron/main-process.log
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**注意:** 这种模式下,子服务的 Bearer token、端口等运行时信息由主进程生成并保存在内存中,外部脚本无法直接读取——验证脚本需要使用主进程保存到文件的 token,而不能从子服务日志里提取。
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 常见陷阱
|
|
118
|
+
|
|
119
|
+
- renderer 的 `console.log` 只在 DevTools 可见,在终端里什么都看不到 → 必须主动挂钩
|
|
120
|
+
- contextIsolation=true 时,preload 无法直接 require fs → 需用 ipcRenderer 把日志发到主进程写文件
|
|
121
|
+
- Electron 的 `app.getPath('logs')` 返回系统日志目录,可用于固定日志路径
|
|
122
|
+
- 生产包里没有 DevTools → 提前在 preload 挂好钩,否则 renderer 日志永久丢失
|
|
123
|
+
- **内嵌子服务没有独立日志文件** → 不要找 `http.log`,去主进程日志里按前缀 grep
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Node.js 进程日志最佳实践
|
|
2
|
+
|
|
3
|
+
适用场景:裸 Node.js 进程(Express、Fastify、Koa、NestJS、自定义 HTTP 服务等)
|
|
4
|
+
|
|
5
|
+
## 日志产生方式
|
|
6
|
+
|
|
7
|
+
Node.js 进程的日志通常来自三条路径:
|
|
8
|
+
1. `console.log/warn/error` → stdout/stderr
|
|
9
|
+
2. 写日志库(winston、pino、bunyan)→ 文件或 stdout
|
|
10
|
+
3. 未捕获异常 / unhandledRejection → stderr
|
|
11
|
+
|
|
12
|
+
## 时间戳处理
|
|
13
|
+
|
|
14
|
+
**pino / winston(JSON 格式)**:默认输出包含 ISO 8601 时间戳字段(`time` 或 `timestamp`),格式已符合要求,不需要额外处理。
|
|
15
|
+
|
|
16
|
+
**console.log 直接输出(无时间戳)**:capture 层注入(python3 方案,跨平台兼容):
|
|
17
|
+
```bash
|
|
18
|
+
node server.js 2>&1 | python3 -u -c '
|
|
19
|
+
import sys, datetime
|
|
20
|
+
for line in iter(sys.stdin.readline, ""):
|
|
21
|
+
ts = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
22
|
+
print(ts, line.rstrip(), flush=True)
|
|
23
|
+
' >> backend.log
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**注意:`awk strftime` 仅 Linux(gawk)可用,macOS BSD awk 不支持。统一用 python3 方案可避免平台差异。**
|
|
27
|
+
|
|
28
|
+
**winston plain text 格式**(形如 `2024-01-15 14:30:01 info message`):非 ISO 格式,capture 层替换:
|
|
29
|
+
```bash
|
|
30
|
+
node server.js 2>&1 | sed 's/^\([0-9-]* [0-9:]*\)/\1Z/' >> backend.log
|
|
31
|
+
# 或直接注入新时间戳,忽略原有格式(macOS 用上方 python3 方案)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 捕获原则
|
|
35
|
+
|
|
36
|
+
**优先捕获 stdout + stderr,而不是只捕获文件。**
|
|
37
|
+
即使进程同时写文件,文件可能有缓冲延迟;stdout/stderr 是实时的。
|
|
38
|
+
|
|
39
|
+
**如果进程写 JSON 日志(pino/winston JSON 格式),保留原始格式,不要提前 parse。**
|
|
40
|
+
在查询阶段用 `jq` 按需过滤,比提前展开更灵活。
|
|
41
|
+
|
|
42
|
+
## 接入方式
|
|
43
|
+
|
|
44
|
+
启动时包裹,注入时间戳写入独立文件:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# 无时间戳的进程(python3,跨平台)
|
|
48
|
+
node server.js 2>&1 \
|
|
49
|
+
| python3 -u -c 'import sys,datetime; [print(datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), l.rstrip(), flush=True) for l in iter(sys.stdin.readline,"")]' \
|
|
50
|
+
>> /tmp/myproject-logs/backend.log &
|
|
51
|
+
|
|
52
|
+
# 已有 ISO 8601 时间戳的进程(pino/winston JSON)
|
|
53
|
+
node server.js >> /tmp/myproject-logs/backend.log 2>&1 &
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
已在运行的进程无法重定向 stdout,只能读其写入的日志文件(确认该文件有 ISO 时间戳,否则另行处理)。
|
|
57
|
+
|
|
58
|
+
## 未捕获异常
|
|
59
|
+
|
|
60
|
+
确保进程注册了全局异常处理,否则崩溃时没有日志:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
process.on('uncaughtException', err => {
|
|
64
|
+
console.error('[fatal]', err.stack);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
67
|
+
process.on('unhandledRejection', (reason) => {
|
|
68
|
+
console.error('[unhandled-rejection]', reason);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 常见陷阱
|
|
73
|
+
|
|
74
|
+
- pino 默认异步写,进程崩溃时最后几行可能丢失 → 生产调试时用 `sync: true` 或 pino-pretty
|
|
75
|
+
- winston 的 `transports.File` 有写缓冲,tail 时可能看到延迟 → 设置 `maxsize` 触发 flush 或直接 tail stdout
|
|
76
|
+
- `NODE_ENV=production` 时部分框架会关闭 debug 日志 → 调试时显式设置 `DEBUG=*` 或对应变量
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstorming
|
|
3
|
+
description: "设计前强制探索阶段。在进行任何实现工作之前(创建功能、编写代码、修改行为),必须先理解用户意图、需求和设计方案。此技能确保每个任务都经过设计阶段再进入实现阶段(HARD-GATE)。触发场景:用户提出新功能需求、代码修改请求、或者需要将想法转化为具体实现方案时。"
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Brainstorming - 设计前探索
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
帮助将想法转化为完整的设计文档和规格说明。在开始实现前,必须先理解需求并获得用户批准设计。
|
|
13
|
+
|
|
14
|
+
## 核心原则:HARD-GATE
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
在获得用户对设计的批准之前,禁止:
|
|
18
|
+
- 调用任何实现技能
|
|
19
|
+
- 编写任何代码
|
|
20
|
+
- 搭建项目脚手架
|
|
21
|
+
- 采取任何实现行动
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**每个项目都必须经过此流程。** 即使是看似简单的任务,也必须先设计再实现。"简单"项目往往因为未经验证的假设而浪费最多时间。
|
|
25
|
+
|
|
26
|
+
## 流程概览
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
1. 探索项目上下文 → 检查文件、文档、最近提交
|
|
30
|
+
2. 提出澄清问题(一次一个)
|
|
31
|
+
3. 提出 2-3 个方案(含权衡和建议)
|
|
32
|
+
4. 展示分节设计 → 获得用户对每个部分的批准
|
|
33
|
+
5. 编写设计文档 → 保存到 docs/superpowers/specs/
|
|
34
|
+
6. 自检规格 → 检查占位符、矛盾、歧义、范围
|
|
35
|
+
7. 用户审查 → 等待用户批准书面规格
|
|
36
|
+
8. 转入 writing-plans → 创建实施计划
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 详细流程
|
|
40
|
+
|
|
41
|
+
### 1. 探索项目上下文
|
|
42
|
+
|
|
43
|
+
先了解当前项目状态:
|
|
44
|
+
- 检查相关文件(read 工具)
|
|
45
|
+
- 查看现有文档
|
|
46
|
+
- 查看最近的 git 提交历史
|
|
47
|
+
|
|
48
|
+
### 2. 澄清问题
|
|
49
|
+
|
|
50
|
+
一次问一个问题,理解:
|
|
51
|
+
- **目的** — 用户想解决什么问题?
|
|
52
|
+
- **约束** — 有哪些限制(技术、时间、资源)?
|
|
53
|
+
- **成功标准** — 如何衡量成功?
|
|
54
|
+
|
|
55
|
+
### 3. 提出方案
|
|
56
|
+
|
|
57
|
+
提出 2-3 个不同方案,包含:
|
|
58
|
+
- 每个方案的权衡
|
|
59
|
+
- 你的建议和理由
|
|
60
|
+
- 用对话方式呈现选项
|
|
61
|
+
|
|
62
|
+
### 4. 分节展示设计
|
|
63
|
+
|
|
64
|
+
根据复杂度调整每个部分的长度:
|
|
65
|
+
- 简单项目:几句话
|
|
66
|
+
- 复杂项目:每个部分 200-300 字
|
|
67
|
+
|
|
68
|
+
覆盖内容:架构、组件、数据流、错误处理、测试策略
|
|
69
|
+
|
|
70
|
+
### 5. 编写设计文档
|
|
71
|
+
|
|
72
|
+
保存到 `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
|
|
73
|
+
|
|
74
|
+
规格自检(内联修复):
|
|
75
|
+
1. **占位符扫描**:是否有"TBD"、"TODO"、不完整部分?
|
|
76
|
+
2. **内部一致性**:各部分是否矛盾?
|
|
77
|
+
3. **范围检查**:是否聚焦于单一实施计划?
|
|
78
|
+
4. **歧义检查**:是否有多种解释的需求?
|
|
79
|
+
|
|
80
|
+
### 6. 用户审查
|
|
81
|
+
|
|
82
|
+
> "规格已保存到 `<path>`。请在开始编写实施计划之前审查并告诉我是否需要修改。"
|
|
83
|
+
|
|
84
|
+
等待用户响应。如有修改,进行修改后重新自检。
|
|
85
|
+
|
|
86
|
+
### 7. 转入实施
|
|
87
|
+
|
|
88
|
+
调用 `writing-plans` 技能创建详细实施计划。
|
|
89
|
+
|
|
90
|
+
## 关键原则
|
|
91
|
+
|
|
92
|
+
- **一次一问** — 不要用多个问题压垮用户
|
|
93
|
+
- **多选优于开放** — 尽量提供选项
|
|
94
|
+
- **YAGNI 原则** — 从所有设计中剔除不必要功能
|
|
95
|
+
- **探索替代方案** — 选定前提出 2-3 个方案
|
|
96
|
+
- **增量验证** — 展示设计,获得批准后再继续
|
|
97
|
+
- **灵活调整** — 有疑问时返回澄清
|
|
98
|
+
|
|
99
|
+
## 大型项目分解
|
|
100
|
+
|
|
101
|
+
如果项目涵盖多个独立子系统:
|
|
102
|
+
1. 立即标记项目需要分解
|
|
103
|
+
2. 帮助用户将项目拆分为子项目
|
|
104
|
+
3. 确定独立部分及其关系
|
|
105
|
+
4. 确定构建顺序
|
|
106
|
+
5. 对第一个子项目进行正常设计流程
|
|
107
|
+
6. 每个子项目独立获得 spec → plan → implementation 循环
|
|
108
|
+
|
|
109
|
+
## 设计文档示例结构
|
|
110
|
+
|
|
111
|
+
```markdown
|
|
112
|
+
# [功能名称] 设计文档
|
|
113
|
+
|
|
114
|
+
## 概述
|
|
115
|
+
[1-2 句话描述]
|
|
116
|
+
|
|
117
|
+
## 背景
|
|
118
|
+
[为什么需要这个功能]
|
|
119
|
+
|
|
120
|
+
## 用户故事
|
|
121
|
+
[功能如何被使用]
|
|
122
|
+
|
|
123
|
+
## 架构设计
|
|
124
|
+
[主要组件和关系]
|
|
125
|
+
|
|
126
|
+
## 数据流
|
|
127
|
+
[数据如何流转]
|
|
128
|
+
|
|
129
|
+
## 错误处理
|
|
130
|
+
[异常情况如何处理]
|
|
131
|
+
|
|
132
|
+
## 测试策略
|
|
133
|
+
[如何验证功能]
|
|
134
|
+
|
|
135
|
+
## 风险和缓解
|
|
136
|
+
[已知风险及应对]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## 触发条件
|
|
140
|
+
|
|
141
|
+
当用户提出以下请求时触发此技能:
|
|
142
|
+
- "实现一个..."
|
|
143
|
+
- "添加...功能"
|
|
144
|
+
- "帮我做..."
|
|
145
|
+
- "我想让系统..."
|
|
146
|
+
- 任何需要设计和批准的新需求
|
|
147
|
+
|
|
148
|
+
**禁忌:** 不要跳过设计阶段直接实现。即使是"快速修复"或"简单改动"也需要先理解意图。
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: executing-plans
|
|
3
|
+
description: "当有书面实施计划需要执行时使用。执行计划中的任务,进行两阶段 review(规格合规性检查 → 代码质量检查)。基于 writing-plans 生成的任务列表驱动执行。必须先设置隔离工作区(using-git-worktrees)再开始执行。"
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Executing Plans - 计划执行
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
加载计划,批判性审查,执行所有任务,完成后报告。
|
|
13
|
+
|
|
14
|
+
**开始时宣布:** "正在使用 executing-plans 技能执行此计划。"
|
|
15
|
+
|
|
16
|
+
## 前置要求
|
|
17
|
+
|
|
18
|
+
**必须先执行:** `using-git-worktrees` 技能创建隔离工作区
|
|
19
|
+
|
|
20
|
+
## 执行流程
|
|
21
|
+
|
|
22
|
+
### Step 1: 加载和审查计划
|
|
23
|
+
|
|
24
|
+
1. 读取计划文件
|
|
25
|
+
2. 批判性审查 — 识别任何问题或顾虑
|
|
26
|
+
3. 如有问题:开始前向用户提出
|
|
27
|
+
4. 如无问题:创建 TodoWrite 并继续
|
|
28
|
+
|
|
29
|
+
### Step 2: 执行任务
|
|
30
|
+
|
|
31
|
+
对于每个任务:
|
|
32
|
+
1. 标记为进行中
|
|
33
|
+
2. 精确遵循每个步骤
|
|
34
|
+
3. 运行指定的验证
|
|
35
|
+
4. 标记为完成
|
|
36
|
+
|
|
37
|
+
### Step 3: 完成开发
|
|
38
|
+
|
|
39
|
+
所有任务完成后:
|
|
40
|
+
1. 宣布使用 `finishing-a-development-branch` 技能完成此工作
|
|
41
|
+
2. 验证测试
|
|
42
|
+
3. 呈现选项
|
|
43
|
+
4. 执行选择
|
|
44
|
+
|
|
45
|
+
## 两阶段 Review
|
|
46
|
+
|
|
47
|
+
### 阶段 1: 规格合规性
|
|
48
|
+
|
|
49
|
+
检查计划中的每个要求是否有对应实现:
|
|
50
|
+
- 浏览规格的每个部分
|
|
51
|
+
- 能指向实现它的任务吗?
|
|
52
|
+
- 列出任何空白
|
|
53
|
+
|
|
54
|
+
### 阶段 2: 代码质量
|
|
55
|
+
|
|
56
|
+
检查代码是否:
|
|
57
|
+
- 遵循项目现有模式
|
|
58
|
+
- 有适当的错误处理
|
|
59
|
+
- 有必要的测试覆盖
|
|
60
|
+
- 提交信息清晰
|
|
61
|
+
|
|
62
|
+
## 何时停止并寻求帮助
|
|
63
|
+
|
|
64
|
+
**立即停止当:**
|
|
65
|
+
- 遇到阻碍(缺少依赖、测试失败、指令不清)
|
|
66
|
+
- 计划有关键空白无法开始
|
|
67
|
+
- 不理解某条指令
|
|
68
|
+
- 验证反复失败
|
|
69
|
+
|
|
70
|
+
**宁可问清楚不要猜。**
|
|
71
|
+
|
|
72
|
+
## 何时返回早期步骤
|
|
73
|
+
|
|
74
|
+
**返回审查(Step 1)当:**
|
|
75
|
+
- 用户根据反馈更新了计划
|
|
76
|
+
- 基本方法需要重新思考
|
|
77
|
+
|
|
78
|
+
**不要强行通过阻碍** — 停止并问。
|
|
79
|
+
|
|
80
|
+
## 关键约束
|
|
81
|
+
|
|
82
|
+
- 审查计划要先批判性思考
|
|
83
|
+
- 精确遵循计划步骤
|
|
84
|
+
- 不要跳过验证
|
|
85
|
+
- 在隔离工作区执行
|
|
86
|
+
- 从不在 main/master 分支直接实现(除非明确用户许可)
|
|
87
|
+
|
|
88
|
+
## 与其他技能配合
|
|
89
|
+
|
|
90
|
+
**必需工作流技能:**
|
|
91
|
+
- **using-git-worktrees** — 设置隔离工作区
|
|
92
|
+
- **writing-plans** — 创建此技能执行的计划
|
|
93
|
+
- **systematic-debugging** — 遇到 bug 时
|
|
94
|
+
- **finishing-a-development-branch** — 完成后清理
|
|
95
|
+
|
|
96
|
+
## 常见错误
|
|
97
|
+
|
|
98
|
+
| 错误 | 正确做法 |
|
|
99
|
+
|------|----------|
|
|
100
|
+
| 未隔离就执行 | 先用 using-git-worktrees |
|
|
101
|
+
| 不审查直接执行 | 先批判性审查计划 |
|
|
102
|
+
| 跳过验证步骤 | 每个验证都要跑 |
|
|
103
|
+
| 遇到阻碍继续猜 | 停止并问清楚 |
|
|
104
|
+
| 主分支直接改 | 必须隔离分支 |
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: systematic-debugging
|
|
3
|
+
description: "遇到任何 bug、测试失败或意外行为时使用。在提出修复方案之前,必须先系统化地找到根本原因。核心原则:永远先找根本原因,再尝试修复。禁止在未完成第一阶段调查前提出任何修复方案。"
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Systematic Debugging - 系统化调试
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
随机修复浪费时间并创造新 bug。快速补丁掩盖潜在问题。
|
|
13
|
+
|
|
14
|
+
**核心原则:** 永远先找到根本原因再尝试修复。症状修复是失败。
|
|
15
|
+
|
|
16
|
+
## 铁律
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
未完成第一阶段调查,禁止提出修复方案
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
违反此过程的字面规定就是违反调试的精神。
|
|
23
|
+
|
|
24
|
+
## 何时使用
|
|
25
|
+
|
|
26
|
+
用于任何技术问题:
|
|
27
|
+
- 测试失败
|
|
28
|
+
- 生产 bug
|
|
29
|
+
- 意外行为
|
|
30
|
+
- 性能问题
|
|
31
|
+
- 构建失败
|
|
32
|
+
- 集成问题
|
|
33
|
+
|
|
34
|
+
**特别要使用当:**
|
|
35
|
+
- 时间压力大时(紧急情况使人容易猜测)
|
|
36
|
+
- "就一个快速修复"看似很明显时
|
|
37
|
+
- 已经尝试多种修复时
|
|
38
|
+
- 上次修复没效果时
|
|
39
|
+
- 不完全理解问题时
|
|
40
|
+
|
|
41
|
+
## 四阶段流程
|
|
42
|
+
|
|
43
|
+
必须完成每个阶段后再进入下一阶段。
|
|
44
|
+
|
|
45
|
+
### Phase 1: 根本原因调查
|
|
46
|
+
|
|
47
|
+
**在尝试任何修复之前:**
|
|
48
|
+
|
|
49
|
+
1. **仔细阅读错误信息**
|
|
50
|
+
- 不要跳过错误或警告
|
|
51
|
+
- 通常包含确切解决方案
|
|
52
|
+
- 完全阅读堆栈跟踪
|
|
53
|
+
- 记录行号、文件路径、错误码
|
|
54
|
+
|
|
55
|
+
2. **一致地复现**
|
|
56
|
+
- 能可靠地触发吗?
|
|
57
|
+
- 确切步骤是什么?
|
|
58
|
+
- 每次都发生吗?
|
|
59
|
+
- 如果不能复现 → 收集更多数据,不要猜
|
|
60
|
+
|
|
61
|
+
3. **检查最近更改**
|
|
62
|
+
- 什么更改可能导致这个?
|
|
63
|
+
- Git diff、最近提交
|
|
64
|
+
- 新依赖、配置更改
|
|
65
|
+
- 环境差异
|
|
66
|
+
|
|
67
|
+
4. **多组件系统收集证据**
|
|
68
|
+
|
|
69
|
+
**当系统有多个组件时(CI → 构建 → 签名,API → 服务 → 数据库):**
|
|
70
|
+
|
|
71
|
+
**提出修复前,为每个组件边界添加诊断插桩:**
|
|
72
|
+
```
|
|
73
|
+
对于每个组件边界:
|
|
74
|
+
- 记录什么数据进入组件
|
|
75
|
+
- 记录什么数据退出组件
|
|
76
|
+
- 验证环境/配置传播
|
|
77
|
+
- 检查每层状态
|
|
78
|
+
|
|
79
|
+
运行一次收集证据显示在哪里断裂
|
|
80
|
+
然后分析证据识别故障组件
|
|
81
|
+
然后调查那个特定组件
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
5. **追踪数据流**
|
|
85
|
+
|
|
86
|
+
**当错误在调用栈深处时:**
|
|
87
|
+
- 坏值从哪里起源?
|
|
88
|
+
- 什么调用时传入了坏值?
|
|
89
|
+
- 一直追踪到找到源头
|
|
90
|
+
- 在源头修复,不要在症状处修复
|
|
91
|
+
|
|
92
|
+
### Phase 2: 模式分析
|
|
93
|
+
|
|
94
|
+
**修复前找到模式:**
|
|
95
|
+
|
|
96
|
+
1. **找到工作示例**
|
|
97
|
+
- 在同一代码库找到类似的工作代码
|
|
98
|
+
- 什么工作着与坏掉的类似?
|
|
99
|
+
|
|
100
|
+
2. **与参考比较**
|
|
101
|
+
- 如果实现模式,完全阅读参考实现
|
|
102
|
+
- 不要略读 — 阅读每一行
|
|
103
|
+
- 在应用前完全理解模式
|
|
104
|
+
|
|
105
|
+
3. **识别差异**
|
|
106
|
+
- 工作和坏的区别是什么?
|
|
107
|
+
- 列出每个差异,无论多小
|
|
108
|
+
- 不要假设"那不可能有关系"
|
|
109
|
+
|
|
110
|
+
4. **理解依赖**
|
|
111
|
+
- 这个需要什么其他组件?
|
|
112
|
+
- 什么设置、配置、环境?
|
|
113
|
+
- 它做什么假设?
|
|
114
|
+
|
|
115
|
+
### Phase 3: 假设和测试
|
|
116
|
+
|
|
117
|
+
**科学方法:**
|
|
118
|
+
|
|
119
|
+
1. **形成单一假设**
|
|
120
|
+
- 清楚陈述:"我认为 X 是根本原因,因为 Y"
|
|
121
|
+
- 写下来
|
|
122
|
+
- 要具体,不要模糊
|
|
123
|
+
|
|
124
|
+
2. **最小化测试**
|
|
125
|
+
- 做最小的可能更改来测试假设
|
|
126
|
+
- 一次一个变量
|
|
127
|
+
- 不要同时修复多个东西
|
|
128
|
+
|
|
129
|
+
3. **验证后再继续**
|
|
130
|
+
- 成功了吗? → Phase 4
|
|
131
|
+
- 没成功? → 形成新假设
|
|
132
|
+
- 不要在顶上加更多修复
|
|
133
|
+
|
|
134
|
+
4. **当不知道时**
|
|
135
|
+
- 说"我不理解 X"
|
|
136
|
+
- 不要假装知道
|
|
137
|
+
- 问帮助
|
|
138
|
+
- 做更多研究
|
|
139
|
+
|
|
140
|
+
### Phase 4: 实施
|
|
141
|
+
|
|
142
|
+
**修复根本原因,不是症状:**
|
|
143
|
+
|
|
144
|
+
1. **创建失败测试用例**
|
|
145
|
+
- 最简单的复现
|
|
146
|
+
- 能自动化就自动化
|
|
147
|
+
- 无框架时一次性测试脚本
|
|
148
|
+
- 修复前必须有
|
|
149
|
+
|
|
150
|
+
2. **实施单一修复**
|
|
151
|
+
- 解决已识别的根本原因
|
|
152
|
+
- 一次一个更改
|
|
153
|
+
- 不要"既然来了"改进
|
|
154
|
+
- 不要打包重构
|
|
155
|
+
|
|
156
|
+
3. **验证修复**
|
|
157
|
+
- 测试现在通过?
|
|
158
|
+
- 其他测试没坏?
|
|
159
|
+
- 问题真的解决了?
|
|
160
|
+
|
|
161
|
+
4. **如果修复不工作**
|
|
162
|
+
- 停
|
|
163
|
+
- 数:已经尝试了多少修复?
|
|
164
|
+
- 如果 < 3:返回 Phase 1,用新信息重新分析
|
|
165
|
+
- **如果 ≥ 3:停并质疑架构(第5步)**
|
|
166
|
+
- 没有架构讨论不要尝试修复 #4
|
|
167
|
+
|
|
168
|
+
5. **如果 3+ 修复失败:质疑架构**
|
|
169
|
+
|
|
170
|
+
**表明架构问题的模式:**
|
|
171
|
+
- 每个修复在不同地方揭示新的共享状态/耦合/问题
|
|
172
|
+
- 修复需要"大规模重构"才能实施
|
|
173
|
+
- 每个修复在其他地方产生新症状
|
|
174
|
+
|
|
175
|
+
**停并质疑基础:**
|
|
176
|
+
- 这个模式根本上是合理的吗?
|
|
177
|
+
- 我们是"纯粹靠惯性坚持"吗?
|
|
178
|
+
- 应该重构架构 vs. 继续修复症状?
|
|
179
|
+
|
|
180
|
+
**在尝试更多修复前与用户讨论**
|
|
181
|
+
|
|
182
|
+
## 红旗 — 停并遵循流程
|
|
183
|
+
|
|
184
|
+
如果发现自己想:
|
|
185
|
+
- "先快速修复,后续调查"
|
|
186
|
+
- "就试试改 X 看看是否有效"
|
|
187
|
+
- "加多个更改,跑测试"
|
|
188
|
+
- "跳过测试,我会手动验证"
|
|
189
|
+
- "可能是 X,让我修复那个"
|
|
190
|
+
- "不完全理解但这可能有效"
|
|
191
|
+
- "模式说 X 但我会不同地适应"
|
|
192
|
+
- "主要问题有:[列出修复而非调查]"
|
|
193
|
+
- 未追踪数据流就提解决方案
|
|
194
|
+
- **"再试一次修复"(已经尝试 2+ 次)**
|
|
195
|
+
- **每个修复在不同地方揭示新问题**
|
|
196
|
+
|
|
197
|
+
**所有这些意思是:停。返回 Phase 1。**
|
|
198
|
+
|
|
199
|
+
## 快速参考
|
|
200
|
+
|
|
201
|
+
| 阶段 | 关键活动 | 成功标准 |
|
|
202
|
+
|------|----------|----------|
|
|
203
|
+
| **1. 根本原因** | 阅读错误、复现、检查更改、收集证据 | 理解什么和为什么 |
|
|
204
|
+
| **2. 模式** | 找工作示例、比较 | 识别差异 |
|
|
205
|
+
| **3. 假设** | 形成理论、最小测试 | 确认或新假设 |
|
|
206
|
+
| **4. 实施** | 创建测试、修复、验证 | Bug 解决,测试通过 |
|
|
207
|
+
|
|
208
|
+
## 过程揭示"无根本原因"时
|
|
209
|
+
|
|
210
|
+
如果系统化调查揭示问题确实是环境的、时序依赖的或外部的:
|
|
211
|
+
|
|
212
|
+
1. 你已完成流程
|
|
213
|
+
2. 记录调查了什么
|
|
214
|
+
3. 实施适当处理(重试、超时、错误消息)
|
|
215
|
+
4. 为未来调查添加监控/日志
|
|
216
|
+
|
|
217
|
+
**但:** 95% 的"无根本原因"案例是调查不完整。
|