@jspg-ai/coding-bb 0.0.3-beta.4 → 0.0.3-beta.7
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/cbb/dev-standards/rules/cbb-ai-behavior.md +118 -116
- package/cbb/lib/install/codebuddy.js +32 -0
- package/cbb/lib/install/init.js +85 -35
- package/cbb/lib/install/rule-rewrite.js +27 -0
- package/cbb/lib/install/trae.js +35 -0
- package/cbb/lib/openspec/index.js +337 -554
- package/cbb/lib/superpowers/index.js +246 -265
- package/cbb/lib/utils/check-update.js +8 -1
- package/cbb/lib/utils/gitignore.js +2 -0
- package/cbb/lib/utils/settings.js +17 -4
- package/cbb/lib/utils/tar.js +92 -0
- package/cbb/lib/utils/upstream.js +90 -0
- package/cbb/worktrees/commands/worktree-close.md +1 -1
- package/config/upstream-mirrors.json +12 -0
- package/config/workspace-agents.sample.md +41 -39
- package/openspec/.version +2 -3
- package/openspec/commands/apply.md +189 -175
- package/openspec/commands/archive.md +237 -216
- package/openspec/commands/bulk-archive.md +355 -327
- package/openspec/commands/continue.md +116 -105
- package/openspec/commands/explore.md +230 -199
- package/openspec/commands/ff.md +115 -104
- package/openspec/commands/new.md +74 -63
- package/openspec/commands/onboard.md +557 -548
- package/openspec/commands/propose.md +161 -150
- package/openspec/commands/sync.md +277 -249
- package/openspec/commands/update.md +92 -80
- package/openspec/commands/verify.md +175 -162
- package/openspec/skills/openspec-apply-change/SKILL.md +20 -5
- package/openspec/skills/openspec-archive-change/SKILL.md +30 -8
- package/openspec/skills/openspec-bulk-archive-change/SKILL.md +36 -6
- package/openspec/skills/openspec-continue-change/SKILL.md +14 -2
- package/openspec/skills/openspec-explore/SKILL.md +21 -9
- package/openspec/skills/openspec-ff-change/SKILL.md +14 -2
- package/openspec/skills/openspec-new-change/SKILL.md +13 -1
- package/openspec/skills/openspec-onboard/SKILL.md +49 -39
- package/openspec/skills/openspec-propose/SKILL.md +15 -3
- package/openspec/skills/openspec-sync-specs/SKILL.md +31 -2
- package/openspec/skills/openspec-update-change/SKILL.md +27 -14
- package/openspec/skills/openspec-verify-change/SKILL.md +17 -3
- package/package.json +2 -2
- package/superpowers/.version +4 -4
- package/superpowers/skills/brainstorming/SKILL.md +47 -12
- package/superpowers/skills/brainstorming/scripts/frame-template.html +213 -213
- package/superpowers/skills/brainstorming/scripts/server.cjs +723 -723
- package/superpowers/skills/brainstorming/visual-companion.md +6 -6
- package/superpowers/skills/diagnosing-superpowers/SKILL.md +120 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/analyst-common.md +38 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/cost-and-time.md +28 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/plan-adherence.md +29 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/quality-evidence.md +26 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/repeated-work.md +30 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/request-conflicts.md +20 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/scrub-audit.md +33 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/scrub.md +29 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/similar-session.md +38 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/skill-timeline.md +30 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/stumbles.md +28 -0
- package/superpowers/skills/diagnosing-superpowers/references/context-safety.md +22 -0
- package/superpowers/skills/diagnosing-superpowers/references/github-issues.md +47 -0
- package/superpowers/skills/diagnosing-superpowers/references/redaction-policy.md +34 -0
- package/superpowers/skills/diagnosing-superpowers/references/session-discovery.md +31 -0
- package/superpowers/skills/diagnosing-superpowers/templates/bundle-README.md +77 -0
- package/superpowers/skills/diagnosing-superpowers/templates/case.md +64 -0
- package/superpowers/skills/diagnosing-superpowers/templates/issue.md +51 -0
- package/superpowers/skills/diagnosing-superpowers/templates/report.md +82 -0
- package/superpowers/skills/executing-plans/SKILL.md +350 -41
- package/superpowers/skills/executing-plans/scripts/task-done +52 -0
- package/superpowers/skills/executing-plans/scripts/task-start +28 -0
- package/superpowers/skills/requesting-code-review/SKILL.md +1 -1
- package/superpowers/skills/requesting-code-review/code-reviewer.md +17 -0
- package/superpowers/skills/subagent-driven-development/SKILL.md +18 -18
- package/superpowers/skills/subagent-driven-development/re-review-prompt.md +1 -1
- package/superpowers/skills/subagent-driven-development/scripts/review-package +53 -46
- package/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +82 -40
- package/superpowers/skills/subagent-driven-development/scripts/task-brief +43 -41
- package/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +2 -2
- package/superpowers/skills/systematic-debugging/root-cause-tracing.md +1 -1
- package/superpowers/skills/test-driven-development/SKILL.md +10 -0
- package/superpowers/skills/using-superpowers/SKILL.md +2 -0
- package/superpowers/skills/using-superpowers/references/claude-code-tools.md +29 -0
- package/superpowers/skills/using-superpowers/references/muse-tools.md +35 -0
- package/superpowers/skills/writing-plans/SKILL.md +30 -9
- package/superpowers/skills/writing-skills/SKILL.md +4 -2
- package/superpowers/skills/writing-skills/graphviz-conventions.dot +171 -171
|
@@ -1,117 +1,119 @@
|
|
|
1
|
-
---
|
|
2
|
-
trigger: always_on
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# AI 行为准则
|
|
6
|
-
|
|
7
|
-
七条行为准则,减少 AI 编码常见错误。源自 [Andrej Karpathy 对 LLM 编码缺陷的观察](https://x.com/karpathy/status/2015883857489522876)。
|
|
8
|
-
|
|
9
|
-
**权衡:** 这些准则倾向于谨慎而非速度。对于简单任务(如修 typo、改文案),按常识判断即可。
|
|
10
|
-
|
|
11
|
-
## 1. 先想后写
|
|
12
|
-
|
|
13
|
-
**不假设,不隐藏困惑,主动呈现权衡。**
|
|
14
|
-
|
|
15
|
-
实现前:
|
|
16
|
-
- 明确声明假设,不确定时主动询问
|
|
17
|
-
- 若存在多种解释,呈现出来而非自己默默选一种
|
|
18
|
-
- 若有更简单的方案,说出来,必要时 push back
|
|
19
|
-
- 若有不明确的地方,停下来,说出困惑,请求澄清
|
|
20
|
-
|
|
21
|
-
## 2. 简洁至上
|
|
22
|
-
|
|
23
|
-
**用最少代码解决问题,不加推测性内容。**
|
|
24
|
-
|
|
25
|
-
- 不实现用户未要求的功能
|
|
26
|
-
- 不为单次使用的代码创建抽象
|
|
27
|
-
- 不添加用户未要求的"灵活性"或"可配置性"
|
|
28
|
-
- 不为不可能发生的场景写错误处理
|
|
29
|
-
- 写了 200 行却发现 50 行就能搞定 → 重写
|
|
30
|
-
|
|
31
|
-
自问:"资深工程师会说过度设计吗?"如果会,简化。
|
|
32
|
-
|
|
33
|
-
## 3. 外科手术式修改
|
|
34
|
-
|
|
35
|
-
**只改必须改的,只清理自己造成的烂摊子。**
|
|
36
|
-
|
|
37
|
-
编辑已有代码时:
|
|
38
|
-
- 不顺手"改进"相邻代码、注释或格式
|
|
39
|
-
- 不重构没坏的东西
|
|
40
|
-
- 匹配现有风格,即使你更习惯另一种写法
|
|
41
|
-
- 发现无关的死代码,口头提及即可,不要删除
|
|
42
|
-
|
|
43
|
-
当你的改动产生孤儿代码时:
|
|
44
|
-
- 删除因你的改动而不再使用的 import / 变量 / 函数
|
|
45
|
-
- 不删除已有的死代码,除非用户要求
|
|
46
|
-
|
|
47
|
-
**检验标准:** 每一行改动都应该能追溯到用户的需求。
|
|
48
|
-
|
|
49
|
-
## 4. 目标驱动执行
|
|
50
|
-
|
|
51
|
-
**定义成功标准,循环直到验证通过。**
|
|
52
|
-
|
|
53
|
-
将命令式任务转换为可验证的目标:
|
|
54
|
-
|
|
55
|
-
| 而非… | 转换为… |
|
|
56
|
-
|--------|---------|
|
|
57
|
-
| "加个校验" | "先写无效输入的测试,再让测试通过" |
|
|
58
|
-
| "修这个 bug" | "先写能复现的测试,再修到测试通过" |
|
|
59
|
-
| "重构 X" | "确保重构前后测试全部通过" |
|
|
60
|
-
|
|
61
|
-
多步任务先给简短计划:
|
|
62
|
-
```
|
|
63
|
-
1. [步骤] → 验证: [检查项]
|
|
64
|
-
2. [步骤] → 验证: [检查项]
|
|
65
|
-
3. [步骤] → 验证: [检查项]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
清晰的成功标准让 AI 可以独立循环验证,模糊的标准("搞一下")需要反复澄清。
|
|
69
|
-
|
|
70
|
-
## 5. 失败要大声说出来
|
|
71
|
-
|
|
72
|
-
**悄悄绕过失败比直接失败更糟糕。**
|
|
73
|
-
|
|
74
|
-
- 有步骤被跳过,"完成"就是错的——说出来
|
|
75
|
-
- 有测试被跳过,"测试通过"就是错的——说出来
|
|
76
|
-
- 不确定就直接说不确定,不假装确认
|
|
77
|
-
- 默认暴露不确定性,不掩盖
|
|
78
|
-
|
|
79
|
-
**检验标准:** 任何跳过的步骤、不确定的结论、未验证的结果,都以标记形式呈现,不悄悄带过。
|
|
80
|
-
|
|
81
|
-
## 6. 不认同也要说出来
|
|
82
|
-
|
|
83
|
-
当项目现有约定明显有问题时:
|
|
84
|
-
|
|
85
|
-
- 照样遵循,保持一致——不悄悄另起炉灶
|
|
86
|
-
- 明确提出来——指出风险,给出替代方案
|
|
87
|
-
- 让用户做决策,不要替用户做选择
|
|
88
|
-
|
|
89
|
-
**检验标准:** 你的代码放进现有代码中,读不出"换了一个人写的"。发现的问题以建议形式呈现,而非悄悄用另一种方式实现。
|
|
90
|
-
|
|
91
|
-
## 7. 先批准,后动工
|
|
92
|
-
|
|
93
|
-
**任何实现动作前,先陈述方案并获得用户批准。**
|
|
94
|
-
|
|
95
|
-
- 动手前说出打算怎么做(方案、涉及文件、验证方式),等用户确认
|
|
96
|
-
- 仪式随任务缩放:小改动两三句话说清即可;大改动走 openspec 工作流(propose → specs → design)
|
|
97
|
-
- "太简单不需要方案"是最危险的念头——简单意味着方案短,而不是没有方案
|
|
98
|
-
- 中途发现复杂度超出预期:停下来重新说明,不要闷头扩大改动范围
|
|
99
|
-
|
|
100
|
-
**检验标准:** 用户从未因"AI 直接改了代码没打招呼"而感到意外。
|
|
101
|
-
|
|
102
|
-
## 8. 业务空间目录纪律
|
|
103
|
-
|
|
104
|
-
**仅当工作目录是业务空间根(存在 `workspace-config.json`)时生效:写操作命令必须落在需求工作树内。**
|
|
105
|
-
|
|
106
|
-
业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`/cbb:worktree-init` 或 `/cbb-worktree-init`),之后:
|
|
107
|
-
|
|
108
|
-
- 一切产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录:显式 `cd` 或绝对路径
|
|
109
|
-
- 禁止在空间根执行写操作:不在主分支提交代码、不在空间根创建 openspec 变更产物、不改 `.codespace/` 基准代码
|
|
110
|
-
- 只读命令(git status / log、查看文件)在空间根执行无妨
|
|
111
|
-
- 会话开始时确认本次需求对应的工作树路径;存在多个未完成工作树时,先与用户确认目标,不要猜
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
---
|
|
2
|
+
trigger: always_on
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# AI 行为准则
|
|
6
|
+
|
|
7
|
+
七条行为准则,减少 AI 编码常见错误。源自 [Andrej Karpathy 对 LLM 编码缺陷的观察](https://x.com/karpathy/status/2015883857489522876)。
|
|
8
|
+
|
|
9
|
+
**权衡:** 这些准则倾向于谨慎而非速度。对于简单任务(如修 typo、改文案),按常识判断即可。
|
|
10
|
+
|
|
11
|
+
## 1. 先想后写
|
|
12
|
+
|
|
13
|
+
**不假设,不隐藏困惑,主动呈现权衡。**
|
|
14
|
+
|
|
15
|
+
实现前:
|
|
16
|
+
- 明确声明假设,不确定时主动询问
|
|
17
|
+
- 若存在多种解释,呈现出来而非自己默默选一种
|
|
18
|
+
- 若有更简单的方案,说出来,必要时 push back
|
|
19
|
+
- 若有不明确的地方,停下来,说出困惑,请求澄清
|
|
20
|
+
|
|
21
|
+
## 2. 简洁至上
|
|
22
|
+
|
|
23
|
+
**用最少代码解决问题,不加推测性内容。**
|
|
24
|
+
|
|
25
|
+
- 不实现用户未要求的功能
|
|
26
|
+
- 不为单次使用的代码创建抽象
|
|
27
|
+
- 不添加用户未要求的"灵活性"或"可配置性"
|
|
28
|
+
- 不为不可能发生的场景写错误处理
|
|
29
|
+
- 写了 200 行却发现 50 行就能搞定 → 重写
|
|
30
|
+
|
|
31
|
+
自问:"资深工程师会说过度设计吗?"如果会,简化。
|
|
32
|
+
|
|
33
|
+
## 3. 外科手术式修改
|
|
34
|
+
|
|
35
|
+
**只改必须改的,只清理自己造成的烂摊子。**
|
|
36
|
+
|
|
37
|
+
编辑已有代码时:
|
|
38
|
+
- 不顺手"改进"相邻代码、注释或格式
|
|
39
|
+
- 不重构没坏的东西
|
|
40
|
+
- 匹配现有风格,即使你更习惯另一种写法
|
|
41
|
+
- 发现无关的死代码,口头提及即可,不要删除
|
|
42
|
+
|
|
43
|
+
当你的改动产生孤儿代码时:
|
|
44
|
+
- 删除因你的改动而不再使用的 import / 变量 / 函数
|
|
45
|
+
- 不删除已有的死代码,除非用户要求
|
|
46
|
+
|
|
47
|
+
**检验标准:** 每一行改动都应该能追溯到用户的需求。
|
|
48
|
+
|
|
49
|
+
## 4. 目标驱动执行
|
|
50
|
+
|
|
51
|
+
**定义成功标准,循环直到验证通过。**
|
|
52
|
+
|
|
53
|
+
将命令式任务转换为可验证的目标:
|
|
54
|
+
|
|
55
|
+
| 而非… | 转换为… |
|
|
56
|
+
|--------|---------|
|
|
57
|
+
| "加个校验" | "先写无效输入的测试,再让测试通过" |
|
|
58
|
+
| "修这个 bug" | "先写能复现的测试,再修到测试通过" |
|
|
59
|
+
| "重构 X" | "确保重构前后测试全部通过" |
|
|
60
|
+
|
|
61
|
+
多步任务先给简短计划:
|
|
62
|
+
```
|
|
63
|
+
1. [步骤] → 验证: [检查项]
|
|
64
|
+
2. [步骤] → 验证: [检查项]
|
|
65
|
+
3. [步骤] → 验证: [检查项]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
清晰的成功标准让 AI 可以独立循环验证,模糊的标准("搞一下")需要反复澄清。
|
|
69
|
+
|
|
70
|
+
## 5. 失败要大声说出来
|
|
71
|
+
|
|
72
|
+
**悄悄绕过失败比直接失败更糟糕。**
|
|
73
|
+
|
|
74
|
+
- 有步骤被跳过,"完成"就是错的——说出来
|
|
75
|
+
- 有测试被跳过,"测试通过"就是错的——说出来
|
|
76
|
+
- 不确定就直接说不确定,不假装确认
|
|
77
|
+
- 默认暴露不确定性,不掩盖
|
|
78
|
+
|
|
79
|
+
**检验标准:** 任何跳过的步骤、不确定的结论、未验证的结果,都以标记形式呈现,不悄悄带过。
|
|
80
|
+
|
|
81
|
+
## 6. 不认同也要说出来
|
|
82
|
+
|
|
83
|
+
当项目现有约定明显有问题时:
|
|
84
|
+
|
|
85
|
+
- 照样遵循,保持一致——不悄悄另起炉灶
|
|
86
|
+
- 明确提出来——指出风险,给出替代方案
|
|
87
|
+
- 让用户做决策,不要替用户做选择
|
|
88
|
+
|
|
89
|
+
**检验标准:** 你的代码放进现有代码中,读不出"换了一个人写的"。发现的问题以建议形式呈现,而非悄悄用另一种方式实现。
|
|
90
|
+
|
|
91
|
+
## 7. 先批准,后动工
|
|
92
|
+
|
|
93
|
+
**任何实现动作前,先陈述方案并获得用户批准。**
|
|
94
|
+
|
|
95
|
+
- 动手前说出打算怎么做(方案、涉及文件、验证方式),等用户确认
|
|
96
|
+
- 仪式随任务缩放:小改动两三句话说清即可;大改动走 openspec 工作流(propose → specs → design)
|
|
97
|
+
- "太简单不需要方案"是最危险的念头——简单意味着方案短,而不是没有方案
|
|
98
|
+
- 中途发现复杂度超出预期:停下来重新说明,不要闷头扩大改动范围
|
|
99
|
+
|
|
100
|
+
**检验标准:** 用户从未因"AI 直接改了代码没打招呼"而感到意外。
|
|
101
|
+
|
|
102
|
+
## 8. 业务空间目录纪律
|
|
103
|
+
|
|
104
|
+
**仅当工作目录是业务空间根(存在 `workspace-config.json`)时生效:写操作命令必须落在需求工作树内。**
|
|
105
|
+
|
|
106
|
+
业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`/cbb:worktree-init` 或 `/cbb-worktree-init`),之后:
|
|
107
|
+
|
|
108
|
+
- 一切产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录:显式 `cd` 或绝对路径
|
|
109
|
+
- 禁止在空间根执行写操作:不在主分支提交代码、不在空间根创建 openspec 变更产物、不改 `.codespace/` 基准代码
|
|
110
|
+
- 只读命令(git status / log、查看文件)在空间根执行无妨
|
|
111
|
+
- 会话开始时确认本次需求对应的工作树路径;存在多个未完成工作树时,先与用户确认目标,不要猜
|
|
112
|
+
|
|
113
|
+
**会话与工作目录是两回事:** AI 会话窗口始终停在**空间根**(worktree 内不装 AI 配置,无工作流命令),`/opsx:*` 等命令仍在空间根会话发起;只是**产生写操作的工作目录**指向需求工作树(显式 `cd` 或绝对路径)。不要把会话切到 worktree 内,也不要因「在 worktree 内开发」就在空间根直接动手。
|
|
114
|
+
|
|
115
|
+
**检验标准:** 空间根主分支的 `git status` 永远干净(除工具维护的配置文件外),openspec 变更产物只出现在需求工作树内。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
117
119
|
**这些准则生效的标志:** diff 中不必要的改动减少、不会因过度设计而重写、澄清问题在实现前而非出错后提出。
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkBuddy / CodeBuddy 适配器
|
|
3
|
+
*
|
|
4
|
+
* 腾讯 WorkBuddy 桌面工作台与 CodeBuddy IDE / CLI 共用项目级配置目录 `.codebuddy/`,
|
|
5
|
+
* 故一个适配器同时覆盖两者。
|
|
6
|
+
*
|
|
7
|
+
* 与 Claude Code / Qoder 的映射差异:
|
|
8
|
+
* - rules:`.codebuddy/rules/*.md`(扁平文件、递归加载),frontmatter 用
|
|
9
|
+
* `alwaysApply: true`(Qoder 的 `trigger: always_on` 需改写,见 ruleRewrites)
|
|
10
|
+
* - skills:`.codebuddy/skills/<name>/SKILL.md`,结构与 Claude 同构
|
|
11
|
+
* - commands:`.codebuddy/commands/`,支持目录嵌套(`/group:command`),与 Claude 同风格
|
|
12
|
+
* - hooks:完全兼容 Claude Code Hooks 规范,settings 结构一致,直接复用 settingsManager
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const os = require('os');
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
name: 'codebuddy',
|
|
20
|
+
displayName: 'WorkBuddy(CodeBuddy)',
|
|
21
|
+
rulesDir: '.codebuddy/rules',
|
|
22
|
+
skillsDir: '.codebuddy/skills',
|
|
23
|
+
commandsDir: '.codebuddy/commands/opsx',
|
|
24
|
+
// worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
|
|
25
|
+
worktreeCommandsDir: '.codebuddy/commands/cbb',
|
|
26
|
+
// 规则 frontmatter 改写:Qoder 风格 → CodeBuddy 风格
|
|
27
|
+
ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
|
|
28
|
+
// 用户级 settings,写入全局生效,不污染项目目录
|
|
29
|
+
settingsFile: path.join(os.homedir(), '.codebuddy', 'settings.json'),
|
|
30
|
+
settingsFileIsUserLevel: true,
|
|
31
|
+
hookEvents: ['UserPromptSubmit'],
|
|
32
|
+
};
|
package/cbb/lib/install/init.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* OpenSpec Shared Standards 安装脚本
|
|
5
5
|
*
|
|
6
6
|
* 将AI 编码规范与工作流套件安装到目标项目中。
|
|
7
|
-
* 支持工具:Claude Code (.claude/rules/)、Qoder (.qoder/rules/)、opencode (.opencode/rules/)
|
|
7
|
+
* 支持工具:Claude Code (.claude/rules/)、Qoder (.qoder/rules/)、opencode (.opencode/rules/)、
|
|
8
|
+
* WorkBuddy/CodeBuddy (.codebuddy/rules/)、TraeWork/TraeCode (.trae/rules/)
|
|
8
9
|
*
|
|
9
10
|
* 使用方式:
|
|
10
11
|
* npm install -g @jspg-ai/coding-bb # 首次使用
|
|
@@ -51,14 +52,17 @@ const MANIFEST_FILE = path.join(MANIFEST_DIR, '.managed-by-cbb');
|
|
|
51
52
|
const LAST_TOOLS_FILE = path.join(MANIFEST_DIR, '.last-tools');
|
|
52
53
|
|
|
53
54
|
// 适配器
|
|
55
|
+
// 适配器(数组顺序 = 工具选择面板的显示顺序)
|
|
54
56
|
const adapters = [
|
|
55
|
-
require('./claude-code'),
|
|
56
|
-
require('./qoder'),
|
|
57
57
|
require('./opencode'),
|
|
58
|
+
require('./codebuddy'),
|
|
59
|
+
require('./trae'),
|
|
60
|
+
require('./qoder'),
|
|
61
|
+
require('./claude-code'),
|
|
58
62
|
];
|
|
59
63
|
|
|
60
|
-
// superpowers 部署白名单:仅装 openspec 工作流硬依赖 + 方法论基底(源仓库仍保留全量
|
|
61
|
-
// 供
|
|
64
|
+
// superpowers 部署白名单:仅装 openspec 工作流硬依赖 + 方法论基底(源仓库仍保留全量 15 个,
|
|
65
|
+
// 供 cbbm update --upstream-superpowers 维护;砍掉的与 openspec 工作流重叠或属低频场景)
|
|
62
66
|
const SUPERPOWERS_WHITELIST = [
|
|
63
67
|
'writing-plans', // openspec apply:生成 plan.md(schema.yaml 引用)
|
|
64
68
|
'subagent-driven-development', // openspec apply:执行 plan.md(schema.yaml 引用)
|
|
@@ -83,9 +87,17 @@ const OPENSPEC_COMMANDS_EXCLUDE = ['onboard.md'];
|
|
|
83
87
|
// settings.json hook 工具
|
|
84
88
|
const settingsManager = require('../utils/settings');
|
|
85
89
|
|
|
90
|
+
/** 适配器的 hook 方言参数(Trae 需顶层 version 字段等差异) */
|
|
91
|
+
function hookOpts(adapter) {
|
|
92
|
+
return adapter.hookDialect ? { dialect: adapter.hookDialect } : {};
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
// 清单驱动的文件清理决策(保护用户文档 CLAUDE.md / AGENTS.md 等)
|
|
87
96
|
const { pathsToDelete, protectedKeptPaths } = require('./cleanup');
|
|
88
97
|
|
|
98
|
+
// 规则 frontmatter 改写(Trae/CodeBuddy 需 alwaysApply: true)
|
|
99
|
+
const { applyRuleRewrites } = require('./rule-rewrite');
|
|
100
|
+
|
|
89
101
|
// .gitignore 条目决策(纯函数:检测/写入/卸载移除)
|
|
90
102
|
const gitignore = require('../utils/gitignore');
|
|
91
103
|
|
|
@@ -306,7 +318,8 @@ function deployCoreRules(adapter, isUpgrade, managedPaths) {
|
|
|
306
318
|
// 同名文件存在时直接覆盖
|
|
307
319
|
removePath(destPath);
|
|
308
320
|
|
|
309
|
-
|
|
321
|
+
const content = applyRuleRewrites(adapter, fs.readFileSync(srcPath, 'utf-8'));
|
|
322
|
+
fs.writeFileSync(destPath, content);
|
|
310
323
|
}
|
|
311
324
|
});
|
|
312
325
|
|
|
@@ -1128,9 +1141,9 @@ async function init(targetDir, options = {}) {
|
|
|
1128
1141
|
const settingsPath = adapter.settingsFileIsUserLevel
|
|
1129
1142
|
? adapter.settingsFile
|
|
1130
1143
|
: path.join(TARGET_DIR, adapter.settingsFile);
|
|
1131
|
-
settingsManager.addHooks(settingsPath, command, adapter.hookEvents);
|
|
1144
|
+
settingsManager.addHooks(settingsPath, command, adapter.hookEvents, hookOpts(adapter));
|
|
1132
1145
|
// 清理旧版本遗留的 SessionStart hook(现已仅安装 UserPromptSubmit)
|
|
1133
|
-
if (settingsManager.removeLegacyHooks(settingsPath)) {
|
|
1146
|
+
if (settingsManager.removeLegacyHooks(settingsPath, hookOpts(adapter))) {
|
|
1134
1147
|
log(`清理 ${adapter.displayName} 遗留的 SessionStart hook`, 'success');
|
|
1135
1148
|
}
|
|
1136
1149
|
if (!adapter.settingsFileIsUserLevel) newPaths.add(adapter.settingsFile);
|
|
@@ -1739,8 +1752,8 @@ async function setupUserLevelComponents(targetAdapters = adapters) {
|
|
|
1739
1752
|
if (hookAdapters.length > 0) {
|
|
1740
1753
|
const command = settingsManager.getCheckUpdateCommand();
|
|
1741
1754
|
hookAdapters.forEach(adapter => {
|
|
1742
|
-
settingsManager.addHooks(adapter.settingsFile, command, adapter.hookEvents);
|
|
1743
|
-
settingsManager.removeLegacyHooks(adapter.settingsFile);
|
|
1755
|
+
settingsManager.addHooks(adapter.settingsFile, command, adapter.hookEvents, hookOpts(adapter));
|
|
1756
|
+
settingsManager.removeLegacyHooks(adapter.settingsFile, hookOpts(adapter));
|
|
1744
1757
|
});
|
|
1745
1758
|
summaryParts.push(`版本检查 hook → ${hookAdapters.map(a => a.displayName).join('、')}`);
|
|
1746
1759
|
}
|
|
@@ -1856,7 +1869,7 @@ async function uninstallUserLevelComponents() {
|
|
|
1856
1869
|
// 移除版本检查 hook(保留用户其余配置)
|
|
1857
1870
|
adapters.forEach(adapter => {
|
|
1858
1871
|
if (!adapter.settingsFile || !adapter.hookEvents) return;
|
|
1859
|
-
if (settingsManager.removeHooks(adapter.settingsFile, adapter.hookEvents)) {
|
|
1872
|
+
if (settingsManager.removeHooks(adapter.settingsFile, adapter.hookEvents, hookOpts(adapter))) {
|
|
1860
1873
|
log(`${adapter.settingsFile}: 移除版本检查 hook,保留用户配置`, 'success');
|
|
1861
1874
|
}
|
|
1862
1875
|
});
|
|
@@ -1887,7 +1900,7 @@ async function uninstall() {
|
|
|
1887
1900
|
// 是否同时卸载用户级组件(工具 skills + 版本检查 hook,作用于 ~/.claude 等用户目录)
|
|
1888
1901
|
let removeUserLevel = false;
|
|
1889
1902
|
if (fs.existsSync(USER_MANIFEST_FILE)) {
|
|
1890
|
-
const answerUser = await ask('是否同时卸载用户级组件(~/.claude、~/.qoder 的版本检查 hook)?(y/N): ');
|
|
1903
|
+
const answerUser = await ask('是否同时卸载用户级组件(~/.claude、~/.qoder、~/.codebuddy、~/.trae-cn 的版本检查 hook)?(y/N): ');
|
|
1891
1904
|
removeUserLevel = answerUser.toLowerCase() === 'y' || answerUser.toLowerCase() === 'yes';
|
|
1892
1905
|
}
|
|
1893
1906
|
|
|
@@ -1906,11 +1919,11 @@ async function uninstall() {
|
|
|
1906
1919
|
: path.join(TARGET_DIR, adapter.settingsFile);
|
|
1907
1920
|
// 项目级:需在清单中才处理
|
|
1908
1921
|
if (!adapter.settingsFileIsUserLevel && !managedPaths.has(adapter.settingsFile)) return;
|
|
1909
|
-
if (removeUserLevel && settingsManager.removeHooks(settingsPath, adapter.hookEvents)) {
|
|
1922
|
+
if (removeUserLevel && settingsManager.removeHooks(settingsPath, adapter.hookEvents, hookOpts(adapter))) {
|
|
1910
1923
|
log(`${adapter.settingsFile}: 移除版本检查 hook,保留用户配置`, 'success');
|
|
1911
1924
|
}
|
|
1912
1925
|
// 清理旧版本遗留的 SessionStart hook(无版本差异,无条件清理)
|
|
1913
|
-
if (settingsManager.removeLegacyHooks(settingsPath)) {
|
|
1926
|
+
if (settingsManager.removeLegacyHooks(settingsPath, hookOpts(adapter))) {
|
|
1914
1927
|
log(`${adapter.settingsFile}: 清理遗留 SessionStart hook`, 'success');
|
|
1915
1928
|
}
|
|
1916
1929
|
skippedPaths.add(adapter.settingsFile);
|
|
@@ -1968,11 +1981,50 @@ async function uninstall() {
|
|
|
1968
1981
|
console.log(`\n✅ 卸载完成!共移除 ${removed} 个文件/目录\n`);
|
|
1969
1982
|
}
|
|
1970
1983
|
|
|
1984
|
+
// ── 上游版本检查 ──────────────────────────────────────────────
|
|
1985
|
+
|
|
1986
|
+
/**
|
|
1987
|
+
* 检查 openspec / superpowers 是否有上游新版本(只读,不改动任何文件)。
|
|
1988
|
+
* 供 cbbm check-upstream 调用。
|
|
1989
|
+
*/
|
|
1990
|
+
async function checkUpstream() {
|
|
1991
|
+
const results = await Promise.allSettled([
|
|
1992
|
+
openspec.checkUpstream().then(r => ({ name: 'openspec', ...r })),
|
|
1993
|
+
superpowers.checkUpstream().then(r => ({ name: 'superpowers', ...r })),
|
|
1994
|
+
]);
|
|
1995
|
+
|
|
1996
|
+
let outdated = false;
|
|
1997
|
+
for (const r of results) {
|
|
1998
|
+
if (r.status === 'rejected') {
|
|
1999
|
+
log(`检查失败: ${r.reason.message}`, 'error');
|
|
2000
|
+
continue;
|
|
2001
|
+
}
|
|
2002
|
+
const { name, current, latest, outdated: isOutdated } = r.value;
|
|
2003
|
+
if (!latest) {
|
|
2004
|
+
log(`${name}: 无法获取上游版本`, 'warn');
|
|
2005
|
+
continue;
|
|
2006
|
+
}
|
|
2007
|
+
if (!current) {
|
|
2008
|
+
log(`${name}: 本地无 pin(上游最新 ${latest})`, 'warn');
|
|
2009
|
+
outdated = true;
|
|
2010
|
+
} else if (isOutdated) {
|
|
2011
|
+
log(`${name}: ${current} → ${latest}(有新版本)`, 'warn');
|
|
2012
|
+
outdated = true;
|
|
2013
|
+
} else {
|
|
2014
|
+
log(`${name}: ${current} 已是最新`, 'success');
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
if (outdated) {
|
|
2019
|
+
log('升级方式:修改对应 .version 的 pin 后,执行 cbbm update --upstream-openspec / --upstream-superpowers', 'info');
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
|
|
1971
2023
|
// ── CLI 入口 ──────────────────────────────────────────────
|
|
1972
2024
|
|
|
1973
2025
|
// 入口身份:cbb(用户命令) / cbbm(内部命令,由流程、hook、Agent 技能调用)
|
|
1974
2026
|
const ENTRY = process.env.CBB_ENTRY === 'cbbm' ? 'cbbm' : 'cbb';
|
|
1975
|
-
const INTERNAL_COMMANDS = ['check-update', 'wiki', 'wp'];
|
|
2027
|
+
const INTERNAL_COMMANDS = ['check-update', 'check-upstream', 'wiki', 'wp'];
|
|
1976
2028
|
const UPSTREAM_FLAGS = ['--upstream-superpowers', '--upstream-openspec'];
|
|
1977
2029
|
|
|
1978
2030
|
const args = process.argv.slice(2);
|
|
@@ -2011,11 +2063,11 @@ switch (command) {
|
|
|
2011
2063
|
const upstreamSuperpowers = restArgs.includes('--upstream-superpowers');
|
|
2012
2064
|
const upstreamOpenspec = restArgs.includes('--upstream-openspec');
|
|
2013
2065
|
if (upstreamSuperpowers || upstreamOpenspec) {
|
|
2014
|
-
//
|
|
2066
|
+
// 维护者选项:按 .version 的 pin 重新拉取上游原生内容到本包源仓库(发布流程用)
|
|
2015
2067
|
if (upstreamSuperpowers) {
|
|
2016
2068
|
superpowers.fetchLatestSkills().then(result => {
|
|
2017
2069
|
if (result.skipped) {
|
|
2018
|
-
log(`superpowers skills 已是最新 (${result.
|
|
2070
|
+
log(`superpowers skills 已是最新 (${result.tag})`, 'success');
|
|
2019
2071
|
}
|
|
2020
2072
|
const validation = superpowers.validateSkills();
|
|
2021
2073
|
if (!validation.valid) {
|
|
@@ -2031,22 +2083,13 @@ switch (command) {
|
|
|
2031
2083
|
}
|
|
2032
2084
|
if (upstreamOpenspec) {
|
|
2033
2085
|
openspec.fetchLatestOpenSpec().then(result => {
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
}
|
|
2040
|
-
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2041
|
-
} else {
|
|
2042
|
-
const validation = openspec.validateDeployed();
|
|
2043
|
-
if (!validation.valid) {
|
|
2044
|
-
log(`本地 openspec 工作流不完整,请重新运行 cbb update --upstream-openspec:`, 'error');
|
|
2045
|
-
for (const m of validation.missing) log(` - 缺失 ${m}`, 'error');
|
|
2046
|
-
process.exit(1);
|
|
2047
|
-
}
|
|
2048
|
-
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2086
|
+
const validation = openspec.validateDeployed();
|
|
2087
|
+
if (!validation.valid) {
|
|
2088
|
+
log(`部署不完整,缺失: ${validation.missing.join(', ')}`, 'error');
|
|
2089
|
+
for (const m of validation.missing) log(` - 缺失 ${m}`, 'error');
|
|
2090
|
+
process.exit(1);
|
|
2049
2091
|
}
|
|
2092
|
+
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2050
2093
|
}).catch(err => {
|
|
2051
2094
|
log(`更新失败: ${err.message}`, 'error');
|
|
2052
2095
|
process.exit(1);
|
|
@@ -2069,6 +2112,12 @@ switch (command) {
|
|
|
2069
2112
|
case 'check-update':
|
|
2070
2113
|
require('../utils/check-update.js');
|
|
2071
2114
|
break;
|
|
2115
|
+
case 'check-upstream':
|
|
2116
|
+
checkUpstream().catch(err => {
|
|
2117
|
+
log(err.message, 'error');
|
|
2118
|
+
process.exit(1);
|
|
2119
|
+
});
|
|
2120
|
+
break;
|
|
2072
2121
|
case 'wp':
|
|
2073
2122
|
require('../wiki/index.js').publish(restArgs);
|
|
2074
2123
|
break;
|
|
@@ -2100,11 +2149,12 @@ function showHelp() {
|
|
|
2100
2149
|
@jspg-ai/coding-bb v${pkg.version} — cbbm:内部命令(由流程 / hook / Agent 技能调用)
|
|
2101
2150
|
|
|
2102
2151
|
cbbm check-update 版本检查(用户级 hook 每日自动触发)
|
|
2152
|
+
cbbm check-upstream 检查 openspec / superpowers 是否有上游新版本
|
|
2103
2153
|
cbbm wiki / cbbm wp Wiki 查询与发布(AI 通过技能调用)
|
|
2104
2154
|
|
|
2105
|
-
|
|
2106
|
-
cbbm update --upstream-superpowers
|
|
2107
|
-
cbbm update --upstream-openspec
|
|
2155
|
+
维护者选项(按 .version 的 pin 重新拉取上游原生内容到本包源仓库):
|
|
2156
|
+
cbbm update --upstream-superpowers 按 pin tag 拉取 superpowers skills(走镜像)
|
|
2157
|
+
cbbm update --upstream-openspec 按 pin 版本从 npmmirror 渲染 OpenSpec 工作流
|
|
2108
2158
|
`);
|
|
2109
2159
|
return;
|
|
2110
2160
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 规则 frontmatter 改写(纯函数,无副作用,便于单测)。
|
|
5
|
+
*
|
|
6
|
+
* 源规则(cbb/dev-standards/rules/*.md)用 Qoder 的 frontmatter 约定
|
|
7
|
+
* `trigger: always_on`。各工具对"始终生效"的字段名不同:
|
|
8
|
+
* - Qoder:trigger: always_on(源格式)
|
|
9
|
+
* - Claude Code / opencode:无该字段,靠各自机制加载
|
|
10
|
+
* - WorkBuddy/CodeBuddy、Trae:alwaysApply: true
|
|
11
|
+
*
|
|
12
|
+
* 适配器通过 ruleRewrites([[from, to], ...])声明改写规则,部署时套用;
|
|
13
|
+
* 无 ruleRewrites 的适配器原样返回。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 按适配器的 ruleRewrites 改写规则文本。
|
|
18
|
+
* @param {object} adapter 适配器配置
|
|
19
|
+
* @param {string} text 规则文件原文
|
|
20
|
+
* @returns {string} 改写后的文本(无 ruleRewrites 时原样返回)
|
|
21
|
+
*/
|
|
22
|
+
function applyRuleRewrites(adapter, text) {
|
|
23
|
+
if (!adapter || !adapter.ruleRewrites) return text;
|
|
24
|
+
return adapter.ruleRewrites.reduce((t, [from, to]) => t.split(from).join(to), text);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = { applyRuleRewrites };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TraeWork / TraeCode 适配器
|
|
3
|
+
*
|
|
4
|
+
* 字节 TraeWork 桌面工作台与 TraeCode IDE 共用项目级配置目录 `.trae/`,
|
|
5
|
+
* 故一个适配器同时覆盖两者。
|
|
6
|
+
*
|
|
7
|
+
* 与 Claude Code / Qoder 的映射差异:
|
|
8
|
+
* - rules:`.trae/rules/*.md`(扁平文件、支持子目录,最多 3 层),frontmatter 用
|
|
9
|
+
* `alwaysApply: true`(Qoder 的 `trigger: always_on` 需改写,见 ruleRewrites)
|
|
10
|
+
* - skills:`.trae/skills/<name>/SKILL.md`,结构与 Claude 同构
|
|
11
|
+
* - commands:`.trae/commands/`,支持目录嵌套(最多 3 层),与 Claude 同风格
|
|
12
|
+
* - hooks:`~/.trae-cn/hooks.json`,格式与 Claude 相近但需顶层 `version: 1`
|
|
13
|
+
* (由 settingsManager 的 hookDialect 处理),事件名/输出字段一致
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
name: 'trae',
|
|
21
|
+
displayName: 'TraeWork(TraeCode)',
|
|
22
|
+
rulesDir: '.trae/rules',
|
|
23
|
+
skillsDir: '.trae/skills',
|
|
24
|
+
commandsDir: '.trae/commands/opsx',
|
|
25
|
+
// worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
|
|
26
|
+
worktreeCommandsDir: '.trae/commands/cbb',
|
|
27
|
+
// 规则 frontmatter 改写:Qoder 风格 → Trae 风格
|
|
28
|
+
ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
|
|
29
|
+
// 用户级 hooks 配置(Trae 用 hooks.json,国内版目录为 ~/.trae-cn/)
|
|
30
|
+
settingsFile: path.join(os.homedir(), '.trae-cn', 'hooks.json'),
|
|
31
|
+
settingsFileIsUserLevel: true,
|
|
32
|
+
hookEvents: ['UserPromptSubmit'],
|
|
33
|
+
// Trae 的 hooks.json 需顶层 version: 1(Claude 风格 settings.json 无此字段)
|
|
34
|
+
hookDialect: 'trae',
|
|
35
|
+
};
|