@netpilot/skills 0.3.2 → 0.6.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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +25 -9
- package/CHANGELOG.md +27 -0
- package/README.md +78 -112
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/codex/architecture-designer.toml +2 -1
- package/agents/codex/backend-reviewer.toml +3 -1
- package/agents/codex/frontend-reviewer.toml +3 -1
- package/agents/codex/test-verifier.toml +4 -1
- package/bin/netpilot-skills.mjs +130 -6
- package/docs/agent-authoring.md +15 -5
- package/package.json +1 -1
- package/scripts/sync.mjs +1304 -101
- package/scripts/validate.mjs +68 -14
- package/skills/ask/SKILL.md +51 -47
- package/skills/ask/agents/openai.yaml +3 -3
- package/skills/code-review/SKILL.md +68 -52
- package/skills/code-review/agents/openai.yaml +2 -2
- package/skills/codebase-design/SKILL.md +87 -50
- package/skills/codebase-design/agents/openai.yaml +2 -2
- package/skills/codebase-design/references/deepening.md +60 -0
- package/skills/codebase-design/references/design-it-twice.md +54 -0
- package/skills/diagnosing-bugs/SKILL.md +124 -54
- package/skills/diagnosing-bugs/agents/openai.yaml +2 -2
- package/skills/diagnosing-bugs/scripts/hitl-loop.template.mjs +52 -0
- package/skills/domain-modeling/SKILL.md +65 -55
- package/skills/domain-modeling/agents/openai.yaml +2 -2
- package/skills/domain-modeling/references/adr-format.md +47 -0
- package/skills/domain-modeling/references/context-format.md +60 -0
- package/skills/domain-modeling/references/domain-docs.md +53 -0
- package/skills/grill-me/SKILL.md +13 -0
- package/skills/grill-me/agents/openai.yaml +6 -0
- package/skills/grill-with-docs/SKILL.md +16 -63
- package/skills/grill-with-docs/agents/openai.yaml +3 -3
- package/skills/grilling/SKILL.md +10 -54
- package/skills/grilling/agents/openai.yaml +2 -2
- package/skills/handoff/SKILL.md +24 -42
- package/skills/handoff/agents/openai.yaml +3 -3
- package/skills/implement/SKILL.md +18 -55
- package/skills/implement/agents/openai.yaml +3 -3
- package/skills/improve-codebase-architecture/SKILL.md +88 -0
- package/skills/improve-codebase-architecture/agents/openai.yaml +6 -0
- package/skills/improve-codebase-architecture/references/html-report.md +158 -0
- package/skills/prototype/SKILL.md +21 -53
- package/skills/prototype/agents/openai.yaml +2 -2
- package/skills/prototype/references/logic.md +87 -0
- package/skills/prototype/references/ui.md +108 -0
- package/skills/research/SKILL.md +9 -66
- package/skills/research/agents/openai.yaml +2 -2
- package/skills/resolving-merge-conflicts/SKILL.md +94 -0
- package/skills/resolving-merge-conflicts/agents/openai.yaml +6 -0
- package/skills/tdd/SKILL.md +30 -46
- package/skills/tdd/agents/openai.yaml +2 -2
- package/skills/tdd/references/mocking.md +70 -0
- package/skills/tdd/references/tests.md +95 -0
- package/skills/teach/SKILL.md +115 -47
- package/skills/teach/agents/openai.yaml +3 -3
- package/skills/teach/references/glossary-format.md +35 -10
- package/skills/teach/references/learning-record-format.md +41 -11
- package/skills/teach/references/mission-format.md +20 -17
- package/skills/teach/references/resources-format.md +34 -16
- package/skills/to-spec/SKILL.md +56 -51
- package/skills/to-spec/agents/openai.yaml +3 -3
- package/skills/to-tickets/SKILL.md +84 -45
- package/skills/to-tickets/agents/openai.yaml +3 -3
- package/skills/triage/SKILL.md +171 -0
- package/skills/triage/agents/openai.yaml +6 -0
- package/skills/triage/references/agent-brief.md +168 -0
- package/skills/triage/references/issue-tracker-github.md +42 -0
- package/skills/triage/references/issue-tracker-gitlab.md +42 -0
- package/skills/triage/references/issue-tracker-local.md +28 -0
- package/skills/triage/references/out-of-scope.md +113 -0
- package/skills/triage/references/project-config.md +57 -0
- package/skills/triage/references/triage-labels.md +13 -0
- package/skills/wayfinder/SKILL.md +158 -51
- package/skills/wayfinder/agents/openai.yaml +3 -3
- package/skills/writing-great-skills/SKILL.md +96 -54
- package/skills/writing-great-skills/agents/openai.yaml +3 -3
- package/skills/writing-great-skills/references/glossary.md +279 -0
- package/agents/codex/code-reader.toml +0 -11
- package/skills/grill/SKILL.md +0 -54
- package/skills/grill/agents/openai.yaml +0 -6
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Deepening
|
|
2
|
+
|
|
3
|
+
本指南说明如何在已有依赖条件下,把一组 shallow modules 安全地深化为 deep module。词汇沿用上级 `SKILL.md` 中的 Module、Interface、Seam 与 Adapter。
|
|
4
|
+
|
|
5
|
+
## 依赖类别
|
|
6
|
+
|
|
7
|
+
评估 deepening 候选项时,先分类它的依赖。类别决定如何跨 Seam 测试深化后的 Module。
|
|
8
|
+
|
|
9
|
+
### 进程内(In-process)
|
|
10
|
+
|
|
11
|
+
纯计算或内存状态,没有 I/O。
|
|
12
|
+
|
|
13
|
+
始终可以 deepening:合并相关 Module,直接通过新 Interface 测试,无需 Adapter。
|
|
14
|
+
|
|
15
|
+
### 可由本地替身替换(Local-substitutable)
|
|
16
|
+
|
|
17
|
+
具有本地测试替身的依赖,例如 Postgres 对应 PGLite、真实文件系统对应 in-memory filesystem。
|
|
18
|
+
|
|
19
|
+
只有在稳定替身确实存在时才 deepening。测试套件运行该替身;Seam 保持在 Module 内部,不要为了测试把 port 暴露到外部 Interface。
|
|
20
|
+
|
|
21
|
+
### 远程但由团队拥有:Ports & Adapters
|
|
22
|
+
|
|
23
|
+
跨网络调用但仍由团队拥有的服务,例如内部 API、microservice 或 queue consumer。
|
|
24
|
+
|
|
25
|
+
在 Seam 上定义 port。Deep module 拥有业务逻辑,transport 作为 Adapter 注入:
|
|
26
|
+
|
|
27
|
+
- 生产使用 HTTP、gRPC 或 queue Adapter;
|
|
28
|
+
- 测试使用 in-memory Adapter。
|
|
29
|
+
|
|
30
|
+
推荐用这类形状明确表达:
|
|
31
|
+
|
|
32
|
+
> 在 Seam 上定义 port,生产提供 HTTP Adapter,测试提供 in-memory Adapter。这样即使部署跨越网络,业务逻辑仍集中在一个 deep module 中。
|
|
33
|
+
|
|
34
|
+
### 真正的外部系统:Mock
|
|
35
|
+
|
|
36
|
+
无法控制的第三方服务,例如 payment、email 或 messaging provider。
|
|
37
|
+
|
|
38
|
+
Deep module 接收外部依赖 port;测试提供 mock Adapter。Mock 只模拟该真实系统边界,不模拟自有内部 Module。
|
|
39
|
+
|
|
40
|
+
## Seam 纪律
|
|
41
|
+
|
|
42
|
+
- 一个 Adapter 代表假想 Seam,两个 Adapter 才代表真实 Seam。除非生产与测试或两个真实实现都需要替换,不要创建 port。
|
|
43
|
+
- Deep module 可以有 internal seams 与 external seam。不要因为内部测试使用某个 Seam,就把它暴露给调用者。
|
|
44
|
+
- Seam 应隔离真实变化,不应复制业务规则或让 transport 拥有领域决策。
|
|
45
|
+
|
|
46
|
+
## 测试策略:replace, don’t layer
|
|
47
|
+
|
|
48
|
+
- 在新 Interface 上建立测试后,原 shallow modules 的内部单元测试会变成重复负担。
|
|
49
|
+
- 在授权范围内,先让新 Interface 测试变绿,再删除仅验证旧内部结构的测试;不要保留两套同义测试形成 layer。
|
|
50
|
+
- 测试只断言通过 Interface 可观察到的结果,不读取内部状态。
|
|
51
|
+
- 测试应能承受 Implementation 重构。若只改内部实现就必须改测试,测试已经越过 Interface。
|
|
52
|
+
- 若旧测试仍覆盖新 Interface 未表达的重要行为,先补齐 Interface 或新测试,不可直接删除。
|
|
53
|
+
|
|
54
|
+
## 完成标准
|
|
55
|
+
|
|
56
|
+
- 每项依赖均已分类。
|
|
57
|
+
- 每个 Seam 都有真实变化依据。
|
|
58
|
+
- 测试替身与 dependency category 相符。
|
|
59
|
+
- 新测试通过 Interface 覆盖行为后,才处理旧内部测试。
|
|
60
|
+
- 没有为了测试方便扩大外部 Interface。
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Design It Twice
|
|
2
|
+
|
|
3
|
+
当已选定 deepening 候选项,但 Interface 仍有多种合理形状时,至少设计两次;首个想法通常不是最佳方案。
|
|
4
|
+
|
|
5
|
+
## 框定问题空间
|
|
6
|
+
|
|
7
|
+
先向用户展示:
|
|
8
|
+
|
|
9
|
+
- 所有候选 Interface 都必须满足的约束;
|
|
10
|
+
- 依赖及其 dependency category;
|
|
11
|
+
- Seam 后面应隐藏的行为;
|
|
12
|
+
- 一个用于说明约束的粗略代码草图。它不是提案,只用于让问题具体化。
|
|
13
|
+
|
|
14
|
+
展示后立即进入下一步;用户可以在并行设计进行时阅读和思考。
|
|
15
|
+
|
|
16
|
+
## 生成彼此独立的设计
|
|
17
|
+
|
|
18
|
+
宿主支持并行子代理时,并行启动至少 3 个;不支持时,进行至少 3 次相互隔离的设计 pass,后一轮不得以修饰前一轮为目标。
|
|
19
|
+
|
|
20
|
+
给每个设计者独立的技术 brief,包括文件路径、耦合关系、dependency category、Seam 后面的职责、`CONTEXT.md` 领域语言和上级 `SKILL.md` 词汇。
|
|
21
|
+
|
|
22
|
+
为各设计施加不同约束:
|
|
23
|
+
|
|
24
|
+
1. **最小 Interface**:最多 1–3 个入口,最大化每个入口的 Leverage。
|
|
25
|
+
2. **最大灵活性**:支持更多用例与扩展。
|
|
26
|
+
3. **优化最常见调用者**:让默认场景极其简单。
|
|
27
|
+
4. **Ports & Adapters**:存在跨网络依赖时,专门围绕 port 与 Adapter 设计。
|
|
28
|
+
|
|
29
|
+
每个设计必须输出:
|
|
30
|
+
|
|
31
|
+
1. Interface:类型、方法、参数,以及不变量、顺序、错误模式;
|
|
32
|
+
2. 调用示例;
|
|
33
|
+
3. Implementation 在 Seam 后隐藏了什么;
|
|
34
|
+
4. 依赖策略与 Adapter;
|
|
35
|
+
5. 取舍:哪里 Leverage 高,哪里仍然 shallow。
|
|
36
|
+
|
|
37
|
+
## 依次展示并比较
|
|
38
|
+
|
|
39
|
+
先依次展示每个设计,让用户能单独理解,再用连贯文字比较:
|
|
40
|
+
|
|
41
|
+
- Depth;
|
|
42
|
+
- Locality;
|
|
43
|
+
- Seam placement;
|
|
44
|
+
- 调用者认知负担;
|
|
45
|
+
- 迁移成本与可逆性。
|
|
46
|
+
|
|
47
|
+
最后给出明确推荐,不只提供菜单。若不同设计可以组合,提出 hybrid,并说明组合后是否仍保持小 Interface。
|
|
48
|
+
|
|
49
|
+
## 完成标准
|
|
50
|
+
|
|
51
|
+
- 至少三个方案在结构上真正不同,而不是重命名。
|
|
52
|
+
- 每个方案都说明完整 Interface、调用示例、隐藏行为和依赖策略。
|
|
53
|
+
- 比较使用统一的 Depth、Locality 和 Seam 语言。
|
|
54
|
+
- 最终给出有理由的首选方案或 hybrid。
|
|
@@ -1,82 +1,152 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: diagnosing-bugs
|
|
3
|
-
description:
|
|
3
|
+
description: 当用户要求 diagnose/debug,或报告复杂故障、异常、测试失败、构建失败、偶发错误或性能回退且根因未知时使用。它要求先建立能捕获精确症状的 tight feedback loop,再复现、最小化、提出可证伪假设和收集证据;根因已知且只需实施修复时不使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Diagnosing Bugs
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
这是处理困难缺陷的纪律。只有明确说明理由时才能跳过阶段。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
默认产物是有证据支持的根因。若用户没有要求修复,不修改受版本控制文件,只完成诊断与修复建议。需要临时 instrumentation、生产访问、敏感数据或外部写入时,先获得相应授权。
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
探索代码库时读取相关 `CONTEXT.md` 和 ADR,使术语、Module 与约束保持一致。
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
- 触发条件:什么输入、状态或时序使它出现;
|
|
16
|
-
- 根因:哪个机制违反了哪个不变量;
|
|
17
|
-
- 影响:哪些用户、数据或路径受到波及。
|
|
14
|
+
## 阶段 1:建立 feedback loop
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
**这就是本 skill 的核心。** 只要存在一个能在“这个缺陷”上变红的 tight pass/fail signal,就能通过二分、假设检验和 instrumentation 找到原因。没有它,仅靠阅读代码无法可靠定位。
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
在这一阶段投入最多精力。要主动、创造性地尝试,不要轻易放弃。
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
2. 确认当前基线,检查相关代码、配置、依赖和近期变更。
|
|
25
|
-
3. 若无法稳定复现,收集时间、并发、缓存、网络和环境差异,设计能区分假设的观测点。
|
|
26
|
-
4. 涉及生产、敏感数据或外部写入时,先限定范围并获得必要授权;优先在隔离环境复现。
|
|
20
|
+
### 构造方式
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
大致按以下顺序尝试:
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
1. **Failing test**:选择能到达缺陷的 unit、integration 或 e2e Seam。
|
|
25
|
+
2. **Curl / HTTP script**:针对运行中的开发服务器。
|
|
26
|
+
3. **CLI invocation**:使用 fixture 输入,并将 stdout 与 known-good snapshot 比较。
|
|
27
|
+
4. **Headless browser script**:驱动 UI,断言 DOM、console 或 network。
|
|
28
|
+
5. **Replay captured trace**:保存真实 request、payload 或 event log,再隔离重放。
|
|
29
|
+
6. **Throwaway harness**:只启动最小系统子集,以一次函数调用走过缺陷路径。
|
|
30
|
+
7. **Property / fuzz loop**:对“偶发错误输出”运行大量随机输入并捕获失败模式。
|
|
31
|
+
8. **Bisection harness**:自动启动某个 commit、dataset 或 version 并判定,使其可供 `git bisect run` 使用。
|
|
32
|
+
9. **Differential loop**:相同输入分别经过 old/new version 或两套 config,再比较输出。
|
|
33
|
+
10. **HITL script**:只有人必须点击时才使用。复制并调整 [HITL template](scripts/hitl-loop.template.mjs),由脚本引导人执行步骤并把捕获结果返回给 agent。
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
- 二分版本、输入、配置或执行阶段;
|
|
34
|
-
- 定向日志、断言、调试器和最小测试;
|
|
35
|
-
- 逐层验证接口前置条件与输出不变量;
|
|
36
|
-
- 一次只改变一个变量的实验。
|
|
35
|
+
正确 feedback loop 建成后,缺陷已经解决了大半。
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
### 收紧 loop
|
|
39
38
|
|
|
40
|
-
|
|
39
|
+
把 loop 当成产品持续收紧:
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
- 能否更快:缓存 setup、跳过无关初始化、缩小测试范围?
|
|
42
|
+
- signal 能否更锐利:断言具体症状,而不是“没有崩溃”?
|
|
43
|
+
- 能否更确定:固定时间、随机种子、文件系统和网络?
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
- 能说明为何只在特定条件出现;
|
|
46
|
-
- 移除或控制该机制后,复现行为按预测变化;
|
|
47
|
-
- 与代码、配置、运行输出或版本历史中的证据一致。
|
|
45
|
+
30 秒且偶发的 loop 几乎不能调试;2 秒且确定的 loop 才是 tight loop。
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
### 非确定性故障
|
|
50
48
|
|
|
51
|
-
|
|
49
|
+
目标不是一次干净复现,而是提高 reproduction rate。
|
|
52
50
|
|
|
53
|
-
|
|
51
|
+
重复触发 100 次、并行施压、缩小时序窗口或注入 delay。50% 的 flake 可以调试,1% 的 flake 很难调试;继续提高复现率,直到能稳定比较实验。
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
### 确实无法构建 loop 时
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
## 诊断结论
|
|
59
|
-
- 现象与影响:
|
|
60
|
-
- 复现步骤:
|
|
61
|
-
- 根因:
|
|
62
|
-
- 证据链:
|
|
63
|
-
- 被排除的假设:
|
|
64
|
-
- 建议修复:
|
|
65
|
-
- 回归验证:
|
|
66
|
-
- 剩余未知与风险:
|
|
67
|
-
```
|
|
55
|
+
明确停止并说明:
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
- 已尝试什么;
|
|
58
|
+
- 为什么不能得到 red-capable signal;
|
|
59
|
+
- 需要用户提供哪一种条件:可复现环境访问、HAR/日志/core dump/带时间戳录屏等 captured artifact,或添加临时生产 instrumentation 的权限。
|
|
70
60
|
|
|
71
|
-
|
|
72
|
-
- 根因有完整证据链并能预测故障条件。
|
|
73
|
-
- 症状、触发条件和根因被清楚区分。
|
|
74
|
-
- 如果实施修复,已有失败回归测试和修复后验证。
|
|
61
|
+
**没有 loop,不进入假设阶段。**
|
|
75
62
|
|
|
76
|
-
|
|
63
|
+
### 阶段 1 的完成门禁
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
65
|
+
必须能给出一个已经实际运行至少一次的命令及其输出,并满足:
|
|
66
|
+
|
|
67
|
+
- [ ] **Red-capable**:走真实缺陷路径,并断言用户的精确症状;修复前可 red,修复后可 green。
|
|
68
|
+
- [ ] **Deterministic**:每次 verdict 一致;偶发缺陷则具有固定且足够高的复现率。
|
|
69
|
+
- [ ] **Fast**:以秒而不是分钟计。
|
|
70
|
+
- [ ] **Agent-runnable**:可以无人值守运行;必须有人操作时只通过 HITL script 组织。
|
|
71
|
+
|
|
72
|
+
若在该命令存在前开始阅读代码建立理论,立即停止。没有 red-capable command,不进入阶段 2。
|
|
73
|
+
|
|
74
|
+
## 阶段 2:复现并最小化
|
|
75
|
+
|
|
76
|
+
运行 loop 并亲眼确认 red。
|
|
77
|
+
|
|
78
|
+
检查:
|
|
79
|
+
|
|
80
|
+
- [ ] 捕获的是用户描述的 failure mode,而不是附近的另一个错误。
|
|
81
|
+
- [ ] 多次运行可以复现,或偶发错误达到足够高的复现率。
|
|
82
|
+
- [ ] 已保存精确 symptom:错误信息、错误输出或性能数值。
|
|
83
|
+
|
|
84
|
+
### 最小化
|
|
85
|
+
|
|
86
|
+
在保持 red 的前提下,依次删除输入、调用者、配置、数据和步骤。一次只删一个元素,每次都重新运行 loop。
|
|
87
|
+
|
|
88
|
+
完成条件:每个剩余元素都是 load-bearing;移除任意一个都会变 green。最小复现既会缩小阶段 3 的 hypothesis space,也会直接成为阶段 5 regression test 的起点。
|
|
89
|
+
|
|
90
|
+
没有完成复现与最小化,不进入阶段 3。
|
|
91
|
+
|
|
92
|
+
## 阶段 3:提出假设
|
|
93
|
+
|
|
94
|
+
在测试任何假设前,先生成并排序 3–5 个假设,避免锚定第一个看似合理的解释。
|
|
95
|
+
|
|
96
|
+
每个假设必须可证伪,并写出预测:
|
|
97
|
+
|
|
98
|
+
> 如果 X 是原因,那么改变 Y 会让缺陷消失,或改变 Z 会让缺陷更严重。
|
|
99
|
+
|
|
100
|
+
无法给出预测的只是一种感觉,应丢弃或继续收紧。
|
|
101
|
+
|
|
102
|
+
把排序后的列表展示给用户。用户的领域信息可能立刻改变优先级;这不是阻塞点,用户暂时不在线时按当前排序继续。
|
|
103
|
+
|
|
104
|
+
## 阶段 4:加入观测
|
|
105
|
+
|
|
106
|
+
每个 probe 必须对应阶段 3 中某项预测。一次只改变一个变量。
|
|
107
|
+
|
|
108
|
+
工具偏好:
|
|
109
|
+
|
|
110
|
+
1. 环境支持时优先 debugger / REPL;一个 breakpoint 胜过十条日志。
|
|
111
|
+
2. 在能区分假设的边缘加入 targeted logs。
|
|
112
|
+
3. 不要“记录一切再 grep”。
|
|
113
|
+
|
|
114
|
+
所有临时日志都带唯一前缀,例如 `[DEBUG-a4f2]`,以便结束时一次清除。
|
|
115
|
+
|
|
116
|
+
若诊断任务未授权修改项目文件,使用 debugger、现有日志或 scratch harness;确需改源码加入 instrumentation 时先请求写入授权。
|
|
117
|
+
|
|
118
|
+
### 性能问题分支
|
|
119
|
+
|
|
120
|
+
性能回退通常不适合用普通日志诊断。先建立 baseline measurement,例如 timing harness、profiler 或 query plan,然后二分。先测量,再修复。
|
|
121
|
+
|
|
122
|
+
## 阶段 5:修复并补 regression test
|
|
123
|
+
|
|
124
|
+
只有用户要求修复时才进入本阶段;否则输出根因、证据与建议并停止。
|
|
125
|
+
|
|
126
|
+
在修复前写 regression test,但只在存在正确 Seam 时写。正确 Seam 必须能复现调用点上的真实缺陷模式。
|
|
127
|
+
|
|
128
|
+
若仅有过浅 Seam,例如缺陷需要多个调用者但测试只能覆盖单一调用者,则该测试会制造虚假信心。没有正确 Seam 本身就是诊断发现:记录它,并把架构改进建议交给 `$improve-codebase-architecture`。
|
|
129
|
+
|
|
130
|
+
存在正确 Seam 时:
|
|
131
|
+
|
|
132
|
+
1. 调用 `$tdd`,把最小复现转为失败测试;
|
|
133
|
+
2. 亲眼确认失败;
|
|
134
|
+
3. 修复造成错误状态的最早合理位置;
|
|
135
|
+
4. 确认测试通过;
|
|
136
|
+
5. 用原始、未最小化的阶段 1 loop 重新验证。
|
|
137
|
+
|
|
138
|
+
不要只压制异常、增加重试、清空缓存或扩大 timeout 来掩盖机制问题。
|
|
139
|
+
|
|
140
|
+
## 阶段 6:清理与复盘
|
|
141
|
+
|
|
142
|
+
声明完成前必须确认:
|
|
143
|
+
|
|
144
|
+
- [ ] 原始复现不再出现;
|
|
145
|
+
- [ ] regression test 通过,或无正确 Seam 的原因已记录;
|
|
146
|
+
- [ ] 所有 `[DEBUG-...]` instrumentation 已通过搜索确认移除;
|
|
147
|
+
- [ ] 全部一次性诊断产物都已删除或移到明确标记的 debug 位置,包括 throwaway harness、临时 browser script、replay harness、debug prototype 与一次性 probe;
|
|
148
|
+
- [ ] 若当前工作流已授权 commit 或 PR,正确假设与根因已写入 commit/PR message。
|
|
149
|
+
|
|
150
|
+
最后追问:什么可以防止该缺陷再次出现?
|
|
151
|
+
|
|
152
|
+
若答案是“缺少正确测试 Seam、调用者纠缠或隐藏耦合”,在修复完成后建议用户显式调用 `$improve-codebase-architecture`,并传递具体证据。不要在修复前抢先做架构重构。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Diagnosing Bugs"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "请使用 $diagnosing-bugs
|
|
3
|
+
short_description: "先建立 tight feedback loop,再最小化并用可证伪假设定位根因"
|
|
4
|
+
default_prompt: "请使用 $diagnosing-bugs 为这个故障建立可变红的 tight loop,并形成证据充分的根因。"
|
|
5
5
|
policy:
|
|
6
6
|
allow_implicit_invocation: true
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// 先复制到 scratch/debug 位置再按当前缺陷修改。
|
|
4
|
+
// 运行方式:node <path>/hitl-loop.mjs
|
|
5
|
+
// 仅使用 Node.js 内置模块,可在 Windows、macOS 与 Linux 运行。
|
|
6
|
+
|
|
7
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
8
|
+
import { createInterface } from "node:readline/promises";
|
|
9
|
+
|
|
10
|
+
const rl = createInterface({ input, output });
|
|
11
|
+
const captured = new Map();
|
|
12
|
+
const responses = rl[Symbol.asyncIterator]();
|
|
13
|
+
|
|
14
|
+
async function ask(prompt) {
|
|
15
|
+
output.write(prompt);
|
|
16
|
+
const { value, done } = await responses.next();
|
|
17
|
+
if (done) throw new Error("Input ended before the HITL loop completed");
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function step(instruction) {
|
|
22
|
+
output.write(`\n>>> ${instruction}\n`);
|
|
23
|
+
await ask(" [完成后按 Enter] ");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function capture(key, question) {
|
|
27
|
+
if (!/^[A-Z][A-Z0-9_]*$/.test(key)) {
|
|
28
|
+
throw new Error(`Invalid capture key: ${key}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
output.write(`\n>>> ${question}\n`);
|
|
32
|
+
const answer = await ask(" > ");
|
|
33
|
+
captured.set(key, answer);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
// --- 从这里开始按当前缺陷修改 ---------------------------------------
|
|
38
|
+
|
|
39
|
+
await step("打开 http://localhost:3000 并登录。");
|
|
40
|
+
await capture("ERRORED", "点击“Export”按钮。是否出现错误?(y/n)");
|
|
41
|
+
await capture("ERROR_MSG", "粘贴错误信息;没有则输入 none:");
|
|
42
|
+
|
|
43
|
+
// --- 到这里结束修改 -------------------------------------------------
|
|
44
|
+
} finally {
|
|
45
|
+
rl.close();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
output.write("\n--- Captured ---\n");
|
|
49
|
+
|
|
50
|
+
for (const [key, value] of captured) {
|
|
51
|
+
output.write(`${key}=${value}\n`);
|
|
52
|
+
}
|
|
@@ -1,85 +1,95 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: domain-modeling
|
|
3
|
-
description:
|
|
3
|
+
description: 当用户要建立或收紧领域模型、统一 ubiquitous language、澄清同名异义、验证领域关系、记录满足门禁的架构决策,或另一 skill 需要维护 domain model 时使用。它主动挑战术语并在结论形成时维护 CONTEXT.md 与必要 ADR;仅仅读取既有词汇或处理纯技术结构时不使用。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Domain Modeling
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
在设计过程中主动建立并收紧项目领域模型:挑战术语、构造边界场景,并在语言或决策真正形成时立即记录。仅仅读取 `CONTEXT.md` 是所有 skill 都可做的一行习惯,不属于本 skill;只有正在改变模型时才调用。
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
通用读取约定见 [domain-docs.md](references/domain-docs.md)。
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
2. **识别冲突**:找出同义多名、同名异义、技术名冒充业务概念和边界不清的词。
|
|
14
|
-
3. **限定上下文**:说明每个概念在哪个业务上下文中成立;同一个词跨上下文含义不同是允许的,但必须显式映射。
|
|
15
|
-
4. **描述行为**:优先用“谁基于什么规则执行什么动作并产生什么结果”建模,不只画数据结构。
|
|
16
|
-
5. **提炼不变量**:记录任何有效状态都必须满足的业务规则、权限条件、唯一性和时间约束。
|
|
17
|
-
6. **验证语言**:用真实场景、反例和边界案例让用户确认模型。
|
|
12
|
+
## 文件结构
|
|
18
13
|
|
|
19
|
-
|
|
14
|
+
多数仓库只有一个 context:
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
```text
|
|
17
|
+
/
|
|
18
|
+
├── CONTEXT.md
|
|
19
|
+
├── docs/
|
|
20
|
+
│ └── adr/
|
|
21
|
+
│ ├── 0001-event-sourced-orders.md
|
|
22
|
+
│ └── 0002-postgres-for-write-model.md
|
|
23
|
+
└── src/
|
|
24
|
+
```
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
若根目录存在 `CONTEXT-MAP.md`,则由它指向多个 contexts:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
/
|
|
30
|
+
├── CONTEXT-MAP.md
|
|
31
|
+
├── docs/
|
|
32
|
+
│ └── adr/ ← 系统级 decisions
|
|
33
|
+
└── src/
|
|
34
|
+
├── ordering/
|
|
35
|
+
│ ├── CONTEXT.md
|
|
36
|
+
│ └── docs/adr/ ← context-specific decisions
|
|
37
|
+
└── billing/
|
|
38
|
+
├── CONTEXT.md
|
|
39
|
+
└── docs/adr/
|
|
40
|
+
```
|
|
24
41
|
|
|
25
|
-
|
|
26
|
-
| --- | --- | --- | --- | --- |
|
|
42
|
+
按需创建文件:第一个术语确定时才创建 `CONTEXT.md`,第一个符合门禁的 decision 出现时才创建 ADR 目录。没有稳定内容时不建立空骨架。
|
|
27
43
|
|
|
28
|
-
|
|
44
|
+
## 会话中的工作
|
|
29
45
|
|
|
30
|
-
###
|
|
46
|
+
### 对照 glossary 挑战用词
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
用户使用的词若与现有 `CONTEXT.md` 冲突,立即指出:
|
|
49
|
+
|
|
50
|
+
> Glossary 把“取消”定义为 X,但这里似乎在表达 Y。它们是同一概念,还是两个不同概念?
|
|
51
|
+
|
|
52
|
+
不要静默选择解释。
|
|
53
|
+
|
|
54
|
+
### 收紧模糊语言
|
|
55
|
+
|
|
56
|
+
对模糊或重载词提出精确 canonical term:
|
|
57
|
+
|
|
58
|
+
> 这里的“账号”是 Customer 还是 User?它们承担的业务角色不同。
|
|
59
|
+
|
|
60
|
+
每个 context 内一个概念只保留一个主名称。跨 context 可以同名异义,但必须明确映射。
|
|
41
61
|
|
|
42
|
-
###
|
|
62
|
+
### 讨论具体场景
|
|
43
63
|
|
|
44
|
-
|
|
64
|
+
用正常路径、反例、时间边界和权限边界挑战关系,迫使概念边界变得可判定。例如:
|
|
45
65
|
|
|
46
|
-
|
|
66
|
+
- 部分取消与整单取消是否是同一动作?
|
|
67
|
+
- 已支付但未履约时,谁拥有退款决定?
|
|
68
|
+
- 两个 context 同时看到 Customer 时,谁拥有修改权?
|
|
69
|
+
- 同一业务事件重复到达时,不变量是什么?
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
### 与代码交叉核验
|
|
49
72
|
|
|
50
|
-
|
|
51
|
-
2. **对照证据**:用代码、现有文档和真实场景检查用户描述。发现冲突时展示证据并让用户裁决,不静默选择一方。
|
|
52
|
-
3. **最小更新**:只修改承载当前已确认结论的最小片段。多上下文归属不清时先问,不新建一套平行文档结构。
|
|
73
|
+
用户陈述行为时,用代码和已有文档核验。发现矛盾立即展示证据:
|
|
53
74
|
|
|
54
|
-
|
|
75
|
+
> 代码会取消整个 Order,但刚才的模型允许部分取消——哪一个才是事实?
|
|
55
76
|
|
|
56
|
-
|
|
57
|
-
- 每个概念选择一个主名称,用一至两句定义“它是什么”,并列出应避免的别名。
|
|
58
|
-
- 不写实现细节、规格、任务清单、会议纪要、偏好或待验证假设。
|
|
77
|
+
不要把推断写成项目事实。
|
|
59
78
|
|
|
60
|
-
###
|
|
79
|
+
### 即时更新 `CONTEXT.md`
|
|
61
80
|
|
|
62
|
-
|
|
81
|
+
用户显式调用本 skill,或显式 user-invoked 父 skill 已把领域文档写入列入动作范围并传递了目标唯一的仓库与 context 时,术语一经确认就做最小更新,无需把所有结论积到会话结束。合法父 skill 包括但不限于 `grill-with-docs`,以及正文明确授权领域文档写入的 `triage`、`wayfinder` 或 `improve-codebase-architecture`。
|
|
63
82
|
|
|
64
|
-
|
|
65
|
-
2. 缺少背景时,未来维护者会对当前选择感到意外;
|
|
66
|
-
3. 存在真实替代方案,并基于具体取舍作出选择。
|
|
83
|
+
普通隐式触发、用户只要求分析、父 skill 没有领域文档写入授权,或目标 context 不唯一时,只返回建议片段。Invocation classification 本身不授予写入权限。
|
|
67
84
|
|
|
68
|
-
|
|
85
|
+
更新前读取 [context-format.md](references/context-format.md) 并遵循项目已有格式。`CONTEXT.md` 只做 glossary,不是 spec、scratch pad、task list、会议纪要或实现说明。
|
|
69
86
|
|
|
70
|
-
|
|
87
|
+
### 谨慎提出 ADR
|
|
71
88
|
|
|
72
|
-
|
|
73
|
-
- 关键行为、状态变化和不变量能用真实示例解释。
|
|
74
|
-
- 业务模型与数据库、API 或框架实现没有混为一谈。
|
|
75
|
-
- 需要沉淀的稳定知识有明确落点。
|
|
76
|
-
- 项目文档只包含获得授权且经过确认的内容,ADR 全部通过三项门禁。
|
|
89
|
+
只有以下三项同时成立才提出 ADR:
|
|
77
90
|
|
|
78
|
-
|
|
91
|
+
1. **Hard to reverse**:日后改变成本明显;
|
|
92
|
+
2. **Surprising without context**:未来维护者缺少背景会不理解当前选择;
|
|
93
|
+
3. **Real trade-off**:存在真实替代方案,并因具体取舍选择其一。
|
|
79
94
|
|
|
80
|
-
-
|
|
81
|
-
- 不要为了使用模式而创造无业务意义的实体、聚合或事件。
|
|
82
|
-
- 不要让同一概念在不同文档中继续使用多个主名称。
|
|
83
|
-
- 不要把未确认的推断写进项目事实文件。
|
|
84
|
-
- 不要把 `CONTEXT.md` 写成实现说明或访谈纪要。
|
|
85
|
-
- 不要为容易撤销、没有真实替代方案或显而易见的选择创建 ADR。
|
|
95
|
+
缺少任意一项就不创建。用户接受记录该 decision 且目标唯一后,读取 [adr-format.md](references/adr-format.md);已有同一 decision 时优先更新、deprecated 或 supersede,而不是重复创建。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Domain Modeling"
|
|
3
|
-
short_description: "
|
|
4
|
-
default_prompt: "请使用 $domain-modeling
|
|
3
|
+
short_description: "收紧领域语言、行为、不变量与上下文,并维护必要决策记录"
|
|
4
|
+
default_prompt: "请使用 $domain-modeling 挑战当前领域词汇与关系,并沉淀已授权的稳定结论。"
|
|
5
5
|
policy:
|
|
6
6
|
allow_implicit_invocation: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# ADR 格式
|
|
2
|
+
|
|
3
|
+
ADR 默认位于 `docs/adr/`,文件名按序号排列:`0001-slug.md`、`0002-slug.md`。若仓库已有其他约定,优先遵循现有约定。
|
|
4
|
+
|
|
5
|
+
目录只在第一个 ADR 确实需要且写入已授权时创建。
|
|
6
|
+
|
|
7
|
+
## 最小模板
|
|
8
|
+
|
|
9
|
+
```md
|
|
10
|
+
# {Short title of the decision}
|
|
11
|
+
|
|
12
|
+
{1–3 句:背景是什么、选择了什么、为什么。}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
到这里就可以结束。ADR 的价值是记录“做了什么决定,以及为什么”,不是填满模板。
|
|
16
|
+
|
|
17
|
+
## 可选章节
|
|
18
|
+
|
|
19
|
+
只在确有价值时增加:
|
|
20
|
+
|
|
21
|
+
- **Status** frontmatter:`proposed | accepted | deprecated | superseded by ADR-NNNN`
|
|
22
|
+
- **Considered Options**:被拒方案值得未来维护者记住时
|
|
23
|
+
- **Consequences**:存在不明显的后续影响时
|
|
24
|
+
|
|
25
|
+
## 编号
|
|
26
|
+
|
|
27
|
+
扫描目标 ADR 目录中的最大现有编号,再加一。不要猜编号。
|
|
28
|
+
|
|
29
|
+
## 三项门禁
|
|
30
|
+
|
|
31
|
+
必须同时满足:
|
|
32
|
+
|
|
33
|
+
1. Hard to reverse;
|
|
34
|
+
2. Surprising without context;
|
|
35
|
+
3. Result of a real trade-off。
|
|
36
|
+
|
|
37
|
+
## 符合条件的例子
|
|
38
|
+
|
|
39
|
+
- 架构形状,例如 monorepo、event-sourced write model。
|
|
40
|
+
- contexts 间集成方式,例如 domain events 而非 synchronous HTTP。
|
|
41
|
+
- 带来显著 lock-in 的数据库、message bus、auth provider 或 deployment target。
|
|
42
|
+
- 所有权和 scope decisions,例如 Customer data 只由 Customer context 拥有。
|
|
43
|
+
- 对明显方案的刻意偏离,例如因具体约束使用 manual SQL 而非 ORM。
|
|
44
|
+
- 代码中不可见的约束,例如 compliance 或 partner latency contract。
|
|
45
|
+
- 不明显的 rejected alternative,避免未来反复重提。
|
|
46
|
+
|
|
47
|
+
容易撤销、没有真实替代方案或无需背景即可理解的选择,不写 ADR。
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# `CONTEXT.md` 格式
|
|
2
|
+
|
|
3
|
+
## 结构
|
|
4
|
+
|
|
5
|
+
```md
|
|
6
|
+
# {Context Name}
|
|
7
|
+
|
|
8
|
+
{用一至两句说明这个 context 是什么,以及它为何存在。}
|
|
9
|
+
|
|
10
|
+
## 语言
|
|
11
|
+
|
|
12
|
+
**订单(Order)**:
|
|
13
|
+
客户提交、并由系统跟踪履约状态的一次购买承诺。
|
|
14
|
+
_Avoid_:Purchase、Transaction
|
|
15
|
+
|
|
16
|
+
**发票(Invoice)**:
|
|
17
|
+
交付后向客户发出的付款请求。
|
|
18
|
+
_Avoid_:Bill、Payment Request
|
|
19
|
+
|
|
20
|
+
**客户(Customer)**:
|
|
21
|
+
下单的个人或组织。
|
|
22
|
+
_Avoid_:Client、Buyer、Account
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 规则
|
|
26
|
+
|
|
27
|
+
- **Be opinionated。** 多个词表达同一概念时,选择最佳 canonical term,其余列在 `_Avoid_`。
|
|
28
|
+
- **Keep definitions tight。** 每个定义最多一至两句,说明“它是什么”,不要展开实现或流程。
|
|
29
|
+
- **只记录项目 context 特有术语。** timeout、error type、utility pattern 等通用编程概念不属于此处。
|
|
30
|
+
- **自然形成簇时使用子标题。** 若所有术语属于一个紧密领域,扁平列表即可。
|
|
31
|
+
- **业务主名称与代码映射可以并列。** 代码 identifier 保持稳定英文,中文文档仍使用统一业务名称。
|
|
32
|
+
|
|
33
|
+
## 单 context 与多 context
|
|
34
|
+
|
|
35
|
+
单 context 使用根目录 `CONTEXT.md`。
|
|
36
|
+
|
|
37
|
+
多个 contexts 使用根目录 `CONTEXT-MAP.md`:
|
|
38
|
+
|
|
39
|
+
```md
|
|
40
|
+
# Context Map
|
|
41
|
+
|
|
42
|
+
## Contexts
|
|
43
|
+
|
|
44
|
+
- [Ordering](./src/ordering/CONTEXT.md) — 接收并跟踪客户订单
|
|
45
|
+
- [Billing](./src/billing/CONTEXT.md) — 生成发票并处理付款
|
|
46
|
+
- [Fulfillment](./src/fulfillment/CONTEXT.md) — 管理拣货与发运
|
|
47
|
+
|
|
48
|
+
## Relationships
|
|
49
|
+
|
|
50
|
+
- **Ordering → Fulfillment**:Ordering 发出 `OrderPlaced`,Fulfillment 消费后开始拣货
|
|
51
|
+
- **Fulfillment → Billing**:Fulfillment 发出 `ShipmentDispatched`,Billing 消费后生成发票
|
|
52
|
+
- **Ordering ↔ Billing**:共享 `CustomerId` 与 `Money` 的业务含义
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
判断顺序:
|
|
56
|
+
|
|
57
|
+
1. 存在 `CONTEXT-MAP.md`:读取它定位 context;
|
|
58
|
+
2. 只有根目录 `CONTEXT.md`:按单 context 处理;
|
|
59
|
+
3. 两者都不存在:第一个术语稳定且写入已授权后,才懒创建根目录 `CONTEXT.md`;
|
|
60
|
+
4. 多 context 归属不清时先问,不创建平行结构。
|