@jspg-ai/coding-bb 0.0.3-beta.7 → 0.0.3-beta.8

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.
@@ -103,7 +103,7 @@ trigger: always_on
103
103
 
104
104
  **仅当工作目录是业务空间根(存在 `workspace-config.json`)时生效:写操作命令必须落在需求工作树内。**
105
105
 
106
- 业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`/cbb:worktree-init` `/cbb-worktree-init`),之后:
106
+ 业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`cbb-worktree-init` skill,或斜杠命令 `/cbb-worktree-init`),之后:
107
107
 
108
108
  - 一切产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录:显式 `cd` 或绝对路径
109
109
  - 禁止在空间根执行写操作:不在主分支提交代码、不在空间根创建 openspec 变更产物、不改 `.codespace/` 基准代码
@@ -13,9 +13,7 @@ module.exports = {
13
13
  rulesDir: '.claude/rules',
14
14
  skillsDir: '.claude/skills',
15
15
  commandsDir: '.claude/commands/opsx',
16
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
17
- worktreeCommandsDir: '.claude/commands/cbb',
18
- // 用户级 settings,写入全局生效,不污染项目目录
16
+ // 用户级 settings,写入全局生效,不污染项目目录
19
17
  settingsFile: path.join(os.homedir(), '.claude', 'settings.json'),
20
18
  settingsFileIsUserLevel: true,
21
19
  hookEvents: ['UserPromptSubmit'],
@@ -21,8 +21,6 @@ module.exports = {
21
21
  rulesDir: '.codebuddy/rules',
22
22
  skillsDir: '.codebuddy/skills',
23
23
  commandsDir: '.codebuddy/commands/opsx',
24
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
25
- worktreeCommandsDir: '.codebuddy/commands/cbb',
26
24
  // 规则 frontmatter 改写:Qoder 风格 → CodeBuddy 风格
27
25
  ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
28
26
  // 用户级 settings,写入全局生效,不污染项目目录
@@ -72,8 +72,9 @@ const SUPERPOWERS_WHITELIST = [
72
72
  'test-driven-development', // TDD 计划结构 + TDD Evidence 方法论基底
73
73
  ];
74
74
 
75
- // worktree 运行时部署清单:init / close / push 三件套(SKILL.md + scripts),
76
- // 部署到 .cbb/skills/<name>/(每空间一份,不分工具;命令文件统一指向此处)
75
+ // worktree 管理 skill 清单:init / close / push 三件套(SKILL.md + scripts)。
76
+ // skill 形态部署到各工具的 skillsDir,使这三个能力可被 AI 在对话中自动触发
77
+ // (description 驱动),同时工具也会把它们暴露为斜杠命令供用户手动指定。
77
78
  const WORKTREE_SKILLS = ['cbb-worktree-init', 'cbb-worktree-close', 'cbb-worktree-push'];
78
79
 
79
80
  // 装到空间的 tools skills:当前不分发。
@@ -221,6 +222,39 @@ function removePath(targetPath) {
221
222
  }
222
223
  }
223
224
 
225
+ /**
226
+ * 清理因删除文件/目录而变空的祖先目录(从深到浅,止于 TARGET_DIR)。
227
+ *
228
+ * 删除清单路径只删到该路径本身,其父目录会留空(如改名后残留的空 `.cbb/skills/`)。
229
+ * 此处统一收尾,升级与卸载共用。仅删除「存在且为空」的目录,非空目录(含用户文件)
230
+ * 一律保留。
231
+ *
232
+ * @param {Iterable<string>} relativePaths 已删除的相对路径(正斜杠)
233
+ * @returns {string[]} 实际删除的空目录相对路径
234
+ */
235
+ function cleanupEmptyParentDirs(relativePaths) {
236
+ const dirsToCheck = new Set();
237
+ for (const relativePath of relativePaths) {
238
+ let dir = path.dirname(relativePath);
239
+ while (dir && dir !== '.') {
240
+ dirsToCheck.add(dir);
241
+ dir = path.dirname(dir);
242
+ }
243
+ }
244
+
245
+ const removed = [];
246
+ [...dirsToCheck]
247
+ .sort((a, b) => b.split('/').length - a.split('/').length)
248
+ .forEach(dir => {
249
+ const fullPath = path.join(TARGET_DIR, dir);
250
+ if (fs.existsSync(fullPath) && fs.readdirSync(fullPath).length === 0) {
251
+ removePath(fullPath);
252
+ removed.push(dir);
253
+ }
254
+ });
255
+ return removed;
256
+ }
257
+
224
258
  /**
225
259
  * 安全删除目标路径(文件或目录)
226
260
  * 在清单中 → 直接删除(本包旧版本)
@@ -580,29 +614,6 @@ function deployCommandFiles(adapter, srcDir, destDir, prefix, filter) {
580
614
  return { count: commandFiles.length, names: commandFiles.map(f => prefix + f) };
581
615
  }
582
616
 
583
- /**
584
- * worktree 运行时部署:SKILL.md + scripts 复制到 .cbb/skills/<name>/(每空间一份,不分工具)。
585
- * 单形态 command 收敛后,worktree 不进各工具的 skills 目录——新版工具会把 skills 暴露成
586
- * 斜杠命令,与命令文件在面板里重复;脚本与流程文档统一放 .cbb/skills/,命令文件指向此处。
587
- */
588
- function deployWorktreeRuntime(newPaths) {
589
- const srcDir = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'skills');
590
- if (!fs.existsSync(srcDir)) return 0;
591
- const runtimeDir = path.join(TARGET_DIR, '.cbb', 'skills');
592
- fs.mkdirSync(runtimeDir, { recursive: true });
593
- let count = 0;
594
- WORKTREE_SKILLS.forEach(name => {
595
- const src = path.join(srcDir, name);
596
- if (!fs.existsSync(src)) return;
597
- const destDir = path.join(runtimeDir, name);
598
- removePath(destDir);
599
- fs.cpSync(src, destDir, { recursive: true });
600
- newPaths.add(`.cbb/skills/${name}`);
601
- count++;
602
- });
603
- return count;
604
- }
605
-
606
617
  /**
607
618
  * 命令 frontmatter 消毒:opencode 新版校验命令配置(description 必须为 string | undefined),
608
619
  * 上游个别命令(openspec/commands/update.md)的 description 为空值(YAML 解析为 null),
@@ -656,13 +667,6 @@ function deployCommands(adapter, isUpgrade, managedPaths, srcDir, filter) {
656
667
  adapter, srcDir, path.join(TARGET_DIR, adapter.commandsDir), adapter.commandPrefix || '', filter);
657
668
  }
658
669
 
659
- /** worktree 管理命令(cbb/worktrees/commands/ → adapter.worktreeCommandsDir) */
660
- function deployWorktreeCommands(adapter, srcDir, filter) {
661
- if (!adapter.worktreeCommandsDir) return { count: 0, names: [] };
662
- return deployCommandFiles(
663
- adapter, srcDir, path.join(TARGET_DIR, adapter.worktreeCommandsDir), adapter.worktreeCommandPrefix || '', filter);
664
- }
665
-
666
670
  // ── 设置 OpenSpec 工作流 ──────────────────────────────────
667
671
 
668
672
  /**
@@ -1050,6 +1054,20 @@ async function init(targetDir, options = {}) {
1050
1054
  if (stdCount > 0) log(`规范 Skills → ${skillsDests.join(', ')} (${stdCount} 个)`, 'success');
1051
1055
  if (extCount > 0) log(`扩展 Skills → ${skillsDests.join(', ')} (${extCount} 个)`, 'success');
1052
1056
 
1057
+ // 部署 worktree 管理 Skills(init / close / push;skill 形态,可被对话自动触发)
1058
+ const worktreeSkillsSrc = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'skills');
1059
+ let wtCount = 0;
1060
+ if (fs.existsSync(worktreeSkillsSrc)) {
1061
+ skillsAdapters.forEach(adapter => {
1062
+ const wtResult = deploySkills(adapter, isUpgrade, managedPaths, worktreeSkillsSrc, WORKTREE_SKILLS);
1063
+ if (wtResult.count > 0) {
1064
+ wtCount = wtResult.count;
1065
+ wtResult.names.forEach(name => newPaths.add(`${adapter.skillsDir}/${name}`));
1066
+ }
1067
+ });
1068
+ if (wtCount > 0) log(`Worktree Skills → ${skillsDests.join(', ')} (${wtCount} 个)`, 'success');
1069
+ }
1070
+
1053
1071
  // 部署 Superpowers Skills(白名单:openspec 工作流依赖 + 方法论基底)
1054
1072
  const superpowersSkillsSrc = superpowers.SUPERPOWERS_SKILLS_DIR;
1055
1073
  let spCount = 0;
@@ -1071,22 +1089,16 @@ async function init(targetDir, options = {}) {
1071
1089
  await detectUserLevelSuperpowers(selectedAdapters, yes);
1072
1090
  }
1073
1091
 
1074
- // worktree 运行时(SKILL.md + scripts)→ .cbb/skills/(每空间一份,不分工具)
1075
- const runtimeCount = deployWorktreeRuntime(newPaths);
1076
- if (runtimeCount > 0) log(`worktree 运行时 → .cbb/skills (${runtimeCount} 个)`, 'success');
1077
-
1078
- // 安装 Commands(官方 11 个 → /opsx:*,onboard 不分发;worktree 管理 → /cbb:worktree-*,init/close/push 三件套)
1092
+ // 安装 Commands(官方 11 /opsx:*,onboard 不分发)
1079
1093
  const commandsAdapters = selectedAdapters.filter(a => a.commandsDir);
1080
1094
  if (commandsAdapters.length > 0) {
1081
1095
  console.log(`\n ⚡ ${action} Commands...`);
1082
1096
  const commandsBaseSrc = path.join(SHARED_STANDARDS_DIR, 'openspec', 'commands');
1083
- const commandsExtendsSrc = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'commands');
1084
- const cmdFilter = ['worktree-init.md', 'worktree-close.md', 'worktree-push.md'];
1085
1097
  const openspecCmdInclude = fs.readdirSync(commandsBaseSrc)
1086
1098
  .filter(f => f.endsWith('.md') && !OPENSPEC_COMMANDS_EXCLUDE.includes(f));
1087
1099
 
1088
1100
  const cmdDests = [...new Set(commandsAdapters
1089
- .flatMap(a => [a.commandsDir, a.worktreeCommandsDir])
1101
+ .map(a => a.commandsDir)
1090
1102
  .filter(Boolean))];
1091
1103
  let cmdCount = 0;
1092
1104
  commandsAdapters.forEach(adapter => {
@@ -1097,12 +1109,6 @@ async function init(targetDir, options = {}) {
1097
1109
  adapterCmdCount += baseResult.count;
1098
1110
  baseResult.names.forEach(name => newPaths.add(`${adapter.commandsDir}/${name}`));
1099
1111
  }
1100
- // worktree 管理 Commands(cbb/worktrees/commands/)
1101
- const extResult = deployWorktreeCommands(adapter, commandsExtendsSrc, cmdFilter);
1102
- if (extResult.count > 0) {
1103
- adapterCmdCount += extResult.count;
1104
- extResult.names.forEach(name => newPaths.add(`${adapter.worktreeCommandsDir}/${name}`));
1105
- }
1106
1112
  cmdCount = Math.max(cmdCount, adapterCmdCount);
1107
1113
  });
1108
1114
  if (cmdCount > 0) log(`Commands → ${cmdDests.join(', ')} (${cmdCount} 个)`, 'success');
@@ -1168,6 +1174,8 @@ async function init(targetDir, options = {}) {
1168
1174
  if (oldPaths.length > MAX_DISPLAY) {
1169
1175
  log(` ... 还有 ${oldPaths.length - MAX_DISPLAY} 个`, 'dim');
1170
1176
  }
1177
+ // 收尾:清掉因此变空的祖先目录(如改名后残留的空 .cbb/skills/)
1178
+ cleanupEmptyParentDirs(oldPaths).forEach(dir => log(` 清理空目录 ${dir}/`, 'dim'));
1171
1179
  }
1172
1180
 
1173
1181
  const kept = protectedKeptPaths(managedPaths, newPaths);
@@ -1948,22 +1956,7 @@ async function uninstall() {
1948
1956
  });
1949
1957
 
1950
1958
  // 清理可能变空的父目录(从深到浅)
1951
- const dirsToCheck = new Set();
1952
- managedPaths.forEach(relativePath => {
1953
- let dir = path.dirname(relativePath);
1954
- while (dir && dir !== '.') {
1955
- dirsToCheck.add(dir);
1956
- dir = path.dirname(dir);
1957
- }
1958
- });
1959
- // 按深度排序,深层先处理
1960
- [...dirsToCheck].sort((a, b) => b.split('/').length - a.split('/').length).forEach(dir => {
1961
- const fullPath = path.join(TARGET_DIR, dir);
1962
- if (fs.existsSync(fullPath) && fs.readdirSync(fullPath).length === 0) {
1963
- removePath(fullPath);
1964
- log(`清理空目录 ${dir}/`, 'success');
1965
- }
1966
- });
1959
+ cleanupEmptyParentDirs(managedPaths).forEach(dir => log(`清理空目录 ${dir}/`, 'success'));
1967
1960
 
1968
1961
  // 删除清单文件和 .va 目录
1969
1962
  removePath(manifestDir);
@@ -9,8 +9,7 @@
9
9
  * 官方支持的配置位置:全局目录 / 项目根 / .opencode 目录内均会被发现)
10
10
  * - skills:.opencode/skills/<name>/SKILL.md,结构与 Claude 同构
11
11
  * - commands:命令名 = 文件名(嵌套目录无命名空间,且 init.md 等会撞内置 /init),
12
- * 因此扁平化为 opsx-<name>.md(/opsx-propose);worktree 管理命令同理扁平化为
13
- * cbb-<name>.md(/cbb-worktree-init),部署副本中的 /opsx: 与 /cbb: 引用同步改写
12
+ * 因此扁平化为 opsx-<name>.md(/opsx-propose);部署副本中的 /opsx: 与 /cbb: 引用同步改写
14
13
  * - hooks:opencode 无 UserPromptSubmit 等价事件,版本检查 hook 不安装(settingsFile 留空即跳过)
15
14
  */
16
15
 
@@ -22,9 +21,6 @@ module.exports = {
22
21
  commandsDir: '.opencode/commands',
23
22
  // 部署时给命令文件名加此前缀(规避内置命令名冲突)
24
23
  commandPrefix: 'opsx-',
25
- // worktree 管理命令(非 openspec 上游)落在同一扁平目录,用 cbb- 前缀区分
26
- worktreeCommandsDir: '.opencode/commands',
27
- worktreeCommandPrefix: 'cbb-',
28
24
  // 部署副本中将该引用串改写为 opencode 的命令风格(配合 commandPrefix)
29
25
  contentRewrites: [['/opsx:', '/opsx-'], ['/cbb:', '/cbb-']],
30
26
  // 命令显示名取自 frontmatter name,部署副本重写为 kebab-case(/opsx-propose,与文档一致)
@@ -13,9 +13,7 @@ module.exports = {
13
13
  rulesDir: '.qoder/rules',
14
14
  skillsDir: '.qoder/skills',
15
15
  commandsDir: '.qoder/commands/opsx',
16
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
17
- worktreeCommandsDir: '.qoder/commands/cbb',
18
- // 用户级 settings,写入全局生效,不污染项目目录
16
+ // 用户级 settings,写入全局生效,不污染项目目录
19
17
  settingsFile: path.join(os.homedir(), '.qoder', 'settings.json'),
20
18
  settingsFileIsUserLevel: true,
21
19
  hookEvents: ['UserPromptSubmit'],
@@ -22,8 +22,6 @@ module.exports = {
22
22
  rulesDir: '.trae/rules',
23
23
  skillsDir: '.trae/skills',
24
24
  commandsDir: '.trae/commands/opsx',
25
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
26
- worktreeCommandsDir: '.trae/commands/cbb',
27
25
  // 规则 frontmatter 改写:Qoder 风格 → Trae 风格
28
26
  ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
29
27
  // 用户级 hooks 配置(Trae 用 hooks.json,国内版目录为 ~/.trae-cn/)
@@ -1,12 +1,6 @@
1
1
  ---
2
2
  name: cbb-worktree-close
3
3
  description: "关闭/清理/删除需求工作空间的 worktree 和分支。触发:用户明确说关闭/清理/删除 worktree、结束隔离开发、合并完要清理。禁止在 cbb-worktree-init 执行后自动调用——只有用户主动要求关闭时才触发。"
4
- license: MIT
5
- compatibility: Requires git (>=2.30) and Node.js (>=16.7.0). All commands are pure Node.js scripts under `scripts/`, fully cross-platform (Windows / macOS / Linux, bash / PowerShell / Git Bash).
6
- metadata:
7
- author: Contributors
8
- version: "2.0"
9
- generatedBy: coding-bb
10
4
  ---
11
5
 
12
6
  # Close Worktree(跨平台脚本化版本 v2.0)
@@ -29,12 +23,28 @@ metadata:
29
23
 
30
24
  ---
31
25
 
26
+ ## 调用脚本的统一方式
27
+
28
+ **重要**:本技能的所有脚本位于**本 SKILL.md 所在目录的 `scripts/` 下**(skill 目录)。
29
+
30
+ 调用时用**本技能目录的绝对路径**拼接脚本名(AI 读取本 SKILL.md 时即已知该目录),例如:
31
+
32
+ ```bash
33
+ node "<skill_dir>/scripts/<name>.js" <参数>
34
+ ```
35
+
36
+ > - `<skill_dir>` = 本 SKILL.md 所在目录的绝对路径(AI 从读取路径即可推出)
37
+ > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `workspace-config.json` 与 git 仓库
38
+ > - 不要用 `./scripts/...` 裸相对路径(AI 的 cwd 不是技能目录,会解析失败)
39
+
40
+ ---
41
+
32
42
  ## Step 0:前置校验
33
43
 
34
44
  ### 0.1 环境健康探活
35
45
 
36
46
  ```bash
37
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/check-env.js"
47
+ node "<skill_dir>/scripts/check-env.js"
38
48
  ```
39
49
 
40
50
  **解读输出**:
@@ -45,7 +55,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/check-env.js
45
55
  ### 0.2 定位工作空间根目录
46
56
 
47
57
  ```bash
48
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/find-workspace-root.js"
58
+ node "<skill_dir>/scripts/find-workspace-root.js"
49
59
  ```
50
60
 
51
61
  **解读输出**:
@@ -69,7 +79,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/find-workspa
69
79
  3. AI agent 列出 `.worktrees/` 下的所有 worktree:
70
80
 
71
81
  ```bash
72
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/find-target-worktree.js "<ws_root>"
82
+ node "<skill_dir>/scripts/find-target-worktree.js "<ws_root>"
73
83
  ```
74
84
 
75
85
  > 注:本技能支持工作空间根目录或 worktree 内执行,find-target-worktree 自动从 cwd 反推或列出。
@@ -84,7 +94,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/find-target-
84
94
  ### 1.2 发现关联应用 worktree
85
95
 
86
96
  ```bash
87
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/discover-apps.js "<ws_root>" "<branch>"
97
+ node "<skill_dir>/scripts/discover-apps.js "<ws_root>" "<branch>"
88
98
  ```
89
99
 
90
100
  脚本自动从 `workspace-config.json` 读取应用列表,扫描 `.worktrees/worktree-<branch>/<应用名>/` 实际存在的子目录。
@@ -93,12 +103,12 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/discover-app
93
103
  - `workspace` 字段:workspace worktree 绝对路径(AI agent 记录供后续命令使用)
94
104
  - `apps` 数组:实际存在的应用 worktree 列表(每项含 `name`, `repo`, `side`, `wt_path`, `app_path`)
95
105
 
96
- > 说明:app worktree 物理嵌套在 workspace worktree 内,移除 workspace worktree 时嵌套的子目录会一并消失,但各 app 仓库的 git worktree 元数据(`.git/worktrees/`)仍需通过 `git worktree remove` 逐个清理。AI 配置目录(`.claude/`、`.qoder/`、`.cbb/`)在每个 worktree 内由 init-worktree 独立安装,随 worktree 目录删除而清理,skill 无需特殊处理。
106
+ > 说明:app worktree 物理嵌套在 workspace worktree 内,移除 workspace worktree 时嵌套的子目录会一并消失,但各 app 仓库的 git worktree 元数据(`.git/worktrees/`)仍需通过 `git worktree remove` 逐个清理。AI 配置只装在业务空间根(单层安装),worktree 内没有 AI 配置目录,无需特殊处理。
97
107
 
98
108
  ### 1.3 检查未归档 change
99
109
 
100
110
  ```bash
101
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/check-unarchived.js "<ws_root>"
111
+ node "<skill_dir>/scripts/check-unarchived.js "<ws_root>"
102
112
  ```
103
113
 
104
114
  脚本扫描 `openspec/changes/` 目录,筛选出非 `archive/` 子目录的 change 名称列表。
@@ -117,7 +127,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/check-unarch
117
127
  对 workspace worktree 和每个关联应用 worktree,依次执行三项检查并汇总成安全状态表。**这是破坏性操作前的必经环节,结果将驱动 Step 3 的用户决策。**
118
128
 
119
129
  ```bash
120
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/safety-check.js "<ws_root>" "<branch>"
130
+ node "<skill_dir>/scripts/safety-check.js "<ws_root>" "<branch>"
121
131
  ```
122
132
 
123
133
  脚本内部对每个仓库自动执行:
@@ -226,10 +236,10 @@ AskUserQuestion({
226
236
 
227
237
  ```bash
228
238
  # 仅删本地分支(已合并自动 -d,未合并自动 -D;含 squash 合并 -D 兜底)
229
- node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local
239
+ node "<skill_dir>/scripts/delete-branches.js" "<ws_root>" "<branch>" local
230
240
 
231
241
  # 删本地 + 远程分支
232
- node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
242
+ node "<skill_dir>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
233
243
  ```
234
244
 
235
245
  **调用前的强警告**(调用方需自评):
@@ -260,7 +270,7 @@ node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
260
270
  [中止] 终止流程,我先手动处理
261
271
  ```
262
272
 
263
- - 用户选择「先推送」→ AI 引导用户执行 `cbb-worktree-push`(或 `/cbb:worktree-push`),完成后**重新跑** Step 2 safety-check 确认 `unpushed_count = 0` 再回到本步骤
273
+ - 用户选择「先推送」→ AI 引导用户执行 `cbb-worktree-push` skill(或 `/cbb-worktree-push`),完成后**重新跑** Step 2 safety-check 确认 `unpushed_count = 0` 再回到本步骤
264
274
  - 用户选择「接受丢失」→ 必须二次确认(ahead 提交真的会丢),确认后继续 Step 4
265
275
  - 用户选择「中止」→ 终止流程
266
276
 
@@ -289,7 +299,7 @@ node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
289
299
  **顺序:先移除各应用 worktree,再移除 workspace worktree**(逆序于创建;也为后续删分支扫清"分支仍被检出"的障碍)。
290
300
 
291
301
  ```bash
292
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/remove-worktrees.js "<ws_root>" "<branch>" "<force>"
302
+ node "<skill_dir>/scripts/remove-worktrees.js "<ws_root>" "<branch>" "<force>"
293
303
  ```
294
304
 
295
305
  **三层降级策略**:`git worktree remove` 实际包含两个动作——①清理 git 元数据(`.git/worktrees/`)②删除物理目录。当 IDE 占用目录时 ② 会被 Windows 文件锁阻塞,但 ① 永远不受影响。脚本将这两个动作解耦:
@@ -333,9 +343,9 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-close/scripts/remove-workt
333
343
  如用户在 Step 1.1 选定 worktree 时已要求"删除分支",或运行后需要单独清理,可在此步骤**手动调用**:
334
344
 
335
345
  ```bash
336
- node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local
346
+ node "<skill_dir>/scripts/delete-branches.js" "<ws_root>" "<branch>" local
337
347
  # 或
338
- node "<skill>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
348
+ node "<skill_dir>/scripts/delete-branches.js" "<ws_root>" "<branch>" local_remote
339
349
  ```
340
350
 
341
351
  脚本内部对每个仓库:
@@ -388,7 +398,6 @@ git -C "<ws_root>" worktree list
388
398
  ⏭️ fix-payment-timeout → 用户选择跳过
389
399
  (无未归档 change 时不显示本节)
390
400
  分支处理:feature-xxx 已保留(默认行为;如需删除分支,手动调用 scripts/delete-branches.js)
391
- AI 配置:worktree 内独立安装,随 worktree 删除而清理;工作空间根目录的 AI 配置保留
392
401
  剩余工作空间 worktree:<列出仍存在的,或 "无" >
393
402
  Workspace cleaned up.
394
403
  ```
@@ -411,7 +420,7 @@ git -C "<ws_root>" worktree list
411
420
  - 未经用户确认用 `--force` 丢弃未提交修改,或主动调用 `delete-branches.js` 对未合并分支执行 `-D` 强删
412
421
  - 操作 `.worktrees/worktree-<需求名>` 以外的任何 worktree(如 `~/.qoder/worktree/...` 会话 worktree)
413
422
  - 移除/删除前跳过 Step 2 安全评估
414
- - 删除工作空间根目录的 AI 配置目录(`.claude/`、`.qoder/`、`.cbb/` 等源目录)
423
+ - 删除工作空间根目录的 AI 配置目录(`.claude/`、`.qoder/`、`.opencode/` 等)
415
424
  - 用 `AskUserQuestion` 收集自由文本(分支名等直接对话提问)
416
425
  - 手动改任何仓库的 `.gitignore`(关闭流程不碰它)
417
426
  - 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
@@ -429,7 +438,7 @@ git -C "<ws_root>" worktree list
429
438
  - **合并判定依赖刷新后的远程引用,故 Step 2.0 先主动 `git fetch`**:feature 多由他人经 MR 合入远端,本地引用否则会陈旧误判
430
439
  - **并行块用临时文件收结果、不用共享变量**:原 bash 版本中 `&` 后台任务跑在独立子 shell;Node.js 同步执行无此问题
431
440
  - **`.gitignore` 无需清理**:创建时的 `.worktrees/` 条目提交在 feature 分支上,删分支时随分支消失(未合并)或无害保留(已合并)
432
- - **AI 配置目录在每个 worktree 内独立安装**:关闭 worktree 时这些目录随 worktree 目录一起删除
441
+ - **AI 配置只装在空间根(单层安装)**:worktree 内没有 AI 配置目录,关闭时无需处理
433
442
  - **部分 `worktree remove` 失败**:已移除的无需回退,未移除的报告详情让用户处理后重跑
434
443
  - **Windows IDE 目录锁的三层降级**:`git worktree remove` 内部做两件事——①清元数据 ②删目录。Windows 文件锁只阻塞 ②,不阻塞 ①
435
444
 
@@ -1,12 +1,6 @@
1
1
  ---
2
2
  name: cbb-worktree-init
3
3
  description: "为一个需求在 workspace 与各关联应用仓库(= workspace-config.json 全量 apps)同步创建同名物理 git worktree,直聚在 `.worktrees/worktree-<需求名>/` 下。触发:用户明确要求创建需求工作空间/开发隔离环境,或为已有需求补齐新增应用(重跑本技能即幂等)。禁止自动串联 cbb-worktree-close——除非用户明确说了要关闭。"
4
- license: MIT
5
- compatibility: Requires git (>=2.30) and Node.js (>=16.7.0). All commands are pure Node.js scripts under `scripts/`, fully cross-platform (Windows / macOS / Linux, bash / PowerShell / Git Bash).
6
- metadata:
7
- author: Contributors
8
- version: "2.0"
9
- generatedBy: coding-bb
10
4
  ---
11
5
 
12
6
  # Init Worktree(跨平台脚本化版本 v2.0)
@@ -28,13 +22,18 @@ metadata:
28
22
 
29
23
  ## 调用脚本的统一方式
30
24
 
31
- **重要**:所有脚本必须用**绝对路径**调用。`./scripts/...` 相对路径在 Agent 运行环境中不适用(AI agent 的 cwd 不一定是技能目录)。worktree 运行时统一部署在空间根 `.cbb/skills/` 下,各工具一致。
25
+ **重要**:本技能的所有脚本位于**本 SKILL.md 所在目录的 `scripts/` 下**(skill 目录)。
32
26
 
33
- 调用方式(推荐用绝对路径):
34
- ```
35
- node "D:\workspace\<用户工作空间>\.cbb\skills\cbb-worktree-init\scripts\<name>.js" <参数>
27
+ 调用时用**本技能目录的绝对路径**拼接脚本名(AI 读取本 SKILL.md 时即已知该目录),例如:
28
+
29
+ ```bash
30
+ node "<skill_dir>/scripts/<name>.js" <参数>
36
31
  ```
37
32
 
33
+ > - `<skill_dir>` = 本 SKILL.md 所在目录的绝对路径(AI 从读取路径即可推出)
34
+ > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `workspace-config.json` 与 git 仓库
35
+ > - 不要用 `./scripts/...` 裸相对路径(AI 的 cwd 不是技能目录,会解析失败)
36
+
38
37
  脚本输出:
39
38
  - 人类可读报告(OK / FAIL / WARN)
40
39
  - 机器可读摘要(末行以 XXX_OK / XXX_FAILED / XXX_RESULT 开头)
@@ -54,7 +53,7 @@ node "D:\workspace\<用户工作空间>\.cbb\skills\cbb-worktree-init\scripts\<n
54
53
  ### 0.1 环境健康探活
55
54
 
56
55
  ```bash
57
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-env.js"
56
+ node "<skill_dir>/scripts/check-env.js"
58
57
  ```
59
58
 
60
59
  **解读输出**:
@@ -67,7 +66,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-env.js"
67
66
  提前检测权限/版本问题,把可能在后续步骤暴露的失败前移到流程最开始:
68
67
 
69
68
  ```bash
70
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-env-deep.js"
69
+ node "<skill_dir>/scripts/check-env-deep.js"
71
70
  ```
72
71
 
73
72
  **解读输出**:
@@ -81,7 +80,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-env-dee
81
80
  ### 0.2 读取并校验 workspace-config.json
82
81
 
83
82
  ```bash
84
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/parse-config.js"
83
+ node "<skill_dir>/scripts/parse-config.js"
85
84
  ```
86
85
 
87
86
  **解读输出**:
@@ -148,7 +147,7 @@ worktree 需要知道要关联哪些应用仓库。
148
147
 
149
148
  ```bash
150
149
  # ws_root 来自 AI agent 维护的状态
151
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/sync-repos.js" "<ws_root>"
150
+ node "<skill_dir>/scripts/sync-repos.js" "<ws_root>"
152
151
  ```
153
152
 
154
153
  **用法**:
@@ -192,7 +191,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/sync-repos.js
192
191
  | 当前在主分支上 | ✅ | ❌ |
193
192
 
194
193
  ```bash
195
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-repos.js" "<ws_root>"
194
+ node "<skill_dir>/scripts/check-repos.js" "<ws_root>"
196
195
  ```
197
196
 
198
197
  **解读输出**:
@@ -220,7 +219,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/check-repos.j
220
219
  ### 3.2 安全更新 .gitignore(前置)
221
220
 
222
221
  ```bash
223
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/update-gitignore.js "<ws_root>" "<branch>"
222
+ node "<skill_dir>/scripts/update-gitignore.js "<ws_root>" "<branch>"
224
223
  ```
225
224
 
226
225
  脚本内部自动完成:stash 保护 → 切分支 → 添加 `.worktrees/` 和 `.codespace/` → 提交 → 切回 → pop stash
@@ -234,7 +233,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/update-gitign
234
233
  ### 3.3 创建分支
235
234
 
236
235
  ```bash
237
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/create-branches.js" "<ws_root>" "<branch>"
236
+ node "<skill_dir>/scripts/create-branches.js" "<ws_root>" "<branch>"
238
237
  ```
239
238
 
240
239
  **解读输出**:
@@ -259,7 +258,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/create-branch
259
258
  ### 3.4 推送并建立 upstream
260
259
 
261
260
  ```bash
262
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/push-branches.js" "<ws_root>" "<branch>"
261
+ node "<skill_dir>/scripts/push-branches.js" "<ws_root>" "<branch>"
263
262
  ```
264
263
 
265
264
  脚本内部自动完成:
@@ -287,7 +286,7 @@ node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/push-branches
287
286
  ### 3.5 创建 Worktree(含自愈清理)
288
287
 
289
288
  ```bash
290
- node "D:/workspace/<ws_root>/.cbb/skills/cbb-worktree-init/scripts/create-worktrees.js" "<ws_root>" "<branch>"
289
+ node "<skill_dir>/scripts/create-worktrees.js" "<ws_root>" "<branch>"
291
290
  ```
292
291
 
293
292
  脚本内部自动完成:
@@ -347,7 +346,7 @@ WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
347
346
  |------|----------|
348
347
  | 空间新增了应用(编辑 `workspace-config.json` 后) | Step 1 拉取新应用代码 → Step 3.3 为新应用建分支 → Step 3.4 推送(已一致的分支 `skipped`,不一致则阻塞询问)→ Step 3.5 创建缺失的嵌套 worktree |
349
348
  | 上次 init 中途失败 | 已存在的分支 / worktree 自动复用,`.gitignore` 处理自动跳过,仅补齐缺失部分 |
350
- | 应用从 config 移除 | 已创建的分支 / worktree **不会**自动删除;如需清理用 `/cbb:worktree-close` 关闭后重建 |
349
+ | 应用从 config 移除 | 已创建的分支 / worktree **不会**自动删除;如需清理用 `cbb-worktree-close` skill 关闭后重建 |
351
350
 
352
351
  > ⓘ 重跑**不会静默推送**开发中的本地提交:远程分支已存在但与本地不一致时,Step 3.4 走阻塞式 `remote-exists` 决策(展示 commit 元信息让用户选择)。
353
352
 
@@ -368,7 +367,7 @@ WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
368
367
  | 运行环境 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
369
368
  | push 失败(SSH/HTTPS/网络/保护) | push-branches.js 退出码 2,AI 阻塞并询问用户三选项(修复后重试/跳过失败仓库/完全终止) |
370
369
  | 远程分支已存在 | push-branches.js 输出 metadata,AI 展示 commit 元信息后询问两选项(关联/终止+重新创建) |
371
- | 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调 `/cbb:worktree-push` 或 `cbb-worktree-push` skill 推送(详见该 skill) |
370
+ | 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调 `cbb-worktree-push` skill 推送(详见该 skill) |
372
371
 
373
372
  ---
374
373
 
@@ -467,7 +466,7 @@ WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
467
466
  - workspace 仓库标准检查(当前在主分支等),app 仓库轻量检查(fetch + `origin/main` 可用即可)
468
467
  - app 仓库分支从 `origin/main` 创建(`git branch <需求名> ${REMOTE}/${MAIN}`),不依赖本地主分支状态
469
468
  - 严格 Step 3.3 → Step 3.4 顺序(先统一创建分支,再统一创建 worktree;workspace 工作树先建,各应用按序补建)
470
- - 所有脚本调用以 `node "<WS_ROOT>\.cbb\skills\cbb-worktree-init\scripts\<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 由脚本内部从 workspace-config.json 读取),**不依赖跨调用的 cwd**
469
+ - 所有脚本调用以 `node "<skill_dir>/scripts/<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 由脚本内部从 workspace-config.json 读取);**执行时 cwd 保持在工作空间根**(`check-env.js` / `parse-config.js` 按 cwd 定位)
471
470
  - **Step 3.4 push 步骤必须执行且插入在 create-branches.js (3.3) 之后、create-worktrees.js (3.5) 之前** — 失败时阻塞整个 init-worktree 流程
472
471
  - **Step 3.4 仅覆盖创建 worktree 时的空 commit** — 开发过程中产生的本地 commit(如 apply 任务实现)必须由用户在 worktree 中手动提交并调 `cbb-worktree-push` 推送;不允许依赖 Step 3.4 之后的自动推送(不存在)
473
472
 
@@ -1,19 +1,15 @@
1
1
  ---
2
2
  name: cbb-worktree-push
3
- description: " worktree 提交并推送当前需求的所有关联仓库。触发:用户说'提交'/'commit'/'push'/'推送'/'提交并push'/'推到远端';用户在 .worktrees/worktree-<需求名>/ 下工作要求批量推送;apply 完成后准备推送所有 worktree;close-worktree 前需要先推送未提交改动。"
4
- license: MIT
5
- compatibility: Requires git (>=2.30) and Node.js (>=16.7.0). All commands are pure Node.js scripts under `scripts/`, fully cross-platform (Windows / macOS / Linux, bash / PowerShell / Git Bash).
6
- metadata:
7
- author: Contributors
8
- version: "1.0"
9
- generatedBy: coding-bb
3
+ description: "提交并推送当前需求的所有关联仓库(跨 worktree 批量)。触发:用户说'提交'/'commit'/'push'/'推送'/'提交并push'/'推到远端';用户在 .worktrees/worktree-<需求名>/ 下工作要求批量推送;apply 完成后准备推送所有 worktree;close-worktree 前需要先推送未提交改动。注意:本技能会先识别场景——不在 cbb 工作空间时降级为普通单仓库提交推送。"
10
4
  ---
11
5
 
12
6
  # Push Worktrees(跨平台脚本化版本 v1.0)
13
7
 
14
- worktree 提交并推送当前需求的所有关联仓库到 origin。专门解决"开发完成后批量推送"和"用户口语化提交并push"两类场景,弥补 [cbb-worktree-init Step 3.4](file:///d:/workspace/va-ai/coding-bb/cbb/worktrees/skills/cbb-worktree-init/SKILL.md) 仅推送初始空 commit 的缺口。
8
+ 提交并推送当前需求的所有关联仓库(跨 worktree 批量)。专门解决"开发完成后批量推送"和"用户口语化提交并push"两类场景,弥补 [cbb-worktree-init Step 3.4](file:///d:/workspace/va-ai/coding-bb/cbb/worktrees/skills/cbb-worktree-init/SKILL.md) 仅推送初始空 commit 的缺口。
15
9
 
16
- **启动时声明:** "我正在使用 cbb-worktree-push 技能来批量提交并推送当前需求的所有 worktree 仓库。"
10
+ > **本技能描述含宽泛触发词("提交"/"push"),允许被误触发**。因此第一步永远是 **Step 0 场景识别**:在 cbb 工作空间内才走跨 worktree 批量流程;在普通 git 仓库降级为单仓库提交推送;非 git 目录则退出。
11
+
12
+ **启动时声明:** "我正在使用 cbb-worktree-push 技能来推送当前需求的关联仓库。"
17
13
 
18
14
  ## 核心原则
19
15
 
@@ -30,12 +26,18 @@ metadata:
30
26
 
31
27
  ## 调用脚本的统一方式
32
28
 
33
- **所有脚本必须用绝对路径调用**(Agent 运行环境中 AI agent cwd 不一定是技能目录)。
29
+ **重要**:本技能的所有脚本位于**本 SKILL.md 所在目录的 `scripts/` 下**(skill 目录)。
30
+
31
+ 调用时用**本技能目录的绝对路径**拼接脚本名(AI 读取本 SKILL.md 时即已知该目录):
34
32
 
35
33
  ```
36
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/<name>.js" <参数>
34
+ node "<skill_dir>/scripts/<name>.js" <参数>
37
35
  ```
38
36
 
37
+ > - `<skill_dir>` = 本 SKILL.md 所在目录的绝对路径(AI 从读取路径即可推出)
38
+ > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `workspace-config.json` 与 git 仓库
39
+ > - 不要用 `./scripts/...` 裸相对路径(AI 的 cwd 不是技能目录,会解析失败)
40
+
39
41
  脚本输出:
40
42
  - 人类可读报告(OK / FAIL / WARN)
41
43
  - 机器可读摘要(末行以 `COMMIT_RESULT` / `PUSH_RESULT` 开头)
@@ -43,22 +45,48 @@ node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/<name>.js" <参数>
43
45
 
44
46
  ---
45
47
 
46
- ## Step 0:定位工作空间
48
+ ## Step 0:场景识别(先判场景,再定策略)
49
+
50
+ **本技能允许被"提交"/"push"这类宽泛措辞误触发**。执行任何操作前,先判断当前处于哪种场景,按场景选择策略——**不要硬套 cbb 工作空间流程**。
51
+
52
+ 判断依据(任一命中即定场景):
53
+
54
+ | 场景 | 判据 | 策略 |
55
+ |------|------|------|
56
+ | **A. cbb 工作空间根** | cwd(或其 git 顶层)含 `workspace-config.json`;`find-workspace-root.js` 退出码 0 | 走 **Step 1 → 6** 的跨 worktree 批量流程 |
57
+ | **B. worktree 内** | cwd 命中 `<ws_root>/.worktrees/worktree-<需求名>/` | 用 cwd 反推 `<需求名>`,走 **Step 1 → 6** 批量流程 |
58
+ | **C. 普通 git 仓库** | 在 git 仓库内,但无 `workspace-config.json`(`find-workspace-root.js` 退出码 1) | **降级为单仓库提交推送**:不调 worktree 脚本,按常规 `git add -u` → 向用户询问 commit 信息 → `git commit` → `git push`(保留本 skill 的"必问 commit 信息"约束) |
59
+ | **D. 非 git 目录** | `git rev-parse --is-inside-work-tree` 失败 | 说明"当前目录不是 git 仓库",终止,不做任何操作 |
60
+
61
+ **判场景与定位(A/B 场景):**
47
62
 
48
63
  ```bash
49
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/find-workspace-root.js"
64
+ node "<skill_dir>/scripts/find-workspace-root.js"
50
65
  ```
51
66
 
52
67
  **解读末行**:
53
- - 退出码 0 + 末行(纯路径) → WS_ROOT
54
- - 退出码 1 → 未找到工作空间根目录,**终止流程**
68
+ - 退出码 0 + 末行(纯路径) → WS_ROOT(场景 A/B),继续 Step 1
69
+ - 退出码 1 → 无工作空间:**先判断场景 C 还是 D**(`git rev-parse --is-inside-work-tree`):
70
+ - 是 git 仓库 → 场景 C,按降级策略走(见下)
71
+ - 不是 → 场景 D,终止
72
+
73
+ **场景 C 降级流程**(普通仓库误触):
74
+
75
+ 1. `git status` 报告改动现状
76
+ 2. 直接对话询问 commit 信息(**禁止**自动生成)
77
+ 3. `git add -u`(默认不含未追踪文件;用户明确要求时才 `git add -A`)
78
+ 4. `git commit -m "<用户提供的信息>"`
79
+ 5. `git push`(无 upstream 时先询问用户是否 `-u`)
80
+ 6. 汇报结果;**不要**提及 worktree 批量流程
81
+
82
+ > 场景 C 是兜底:让"提交代码"在普通仓库里也能正常完成,而不是因找不到 `workspace-config.json` 报错。
55
83
 
56
84
  ---
57
85
 
58
- ## Step 1:识别目标 worktree
86
+ ## Step 1:识别目标 worktree(A/B 场景)
59
87
 
60
88
  ```bash
61
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/find-target-worktree.js" "<ws_root>"
89
+ node "<skill_dir>/scripts/find-target-worktree.js" "<ws_root>"
62
90
  ```
63
91
 
64
92
  **解读末行**:
@@ -72,7 +100,7 @@ node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/find-target-worktree.js" "
72
100
 
73
101
  ```bash
74
102
  # 仅 commit 阶段先做 dry-run 预览
75
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --message "preview" --dry-run
103
+ node "<skill_dir>/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --message "preview" --dry-run
76
104
  ```
77
105
 
78
106
  **解读末行 `COMMIT_RESULT`**:每项仓库的状态
@@ -119,16 +147,16 @@ AI agent 在执行真实 commit 前**必须**在对话中向用户确认 commit
119
147
 
120
148
  ```bash
121
149
  # 统一信息
122
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --message "feat(<branch>): 实现客户运费逻辑"
150
+ node "<skill_dir>/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --message "feat(<branch>): 实现客户运费逻辑"
123
151
 
124
152
  # 多仓库分别
125
- node "..." "<ws_root>" "<branch>" --per-repo "ep-foo-app:feat(<branch>): 实现 saveClientExpectFreight;ep-bar-app:refactor(<branch>): 拆分 PlanService"
153
+ node "<skill_dir>/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --per-repo "ep-foo-app:feat(<branch>): 实现 saveClientExpectFreight;ep-bar-app:refactor(<branch>): 拆分 PlanService"
126
154
 
127
155
  # 含未追踪文件
128
- node "..." "<ws_root>" "<branch>" --message "..." --untracked
156
+ node "<skill_dir>/scripts/commit-worktrees.js" "<ws_root>" "<branch>" --message "..." --untracked
129
157
 
130
158
  # wt_path 形式(用户在 worktree 内)
131
- node "..." "<ws_root>/.worktrees/worktree-<branch>" --message "..."
159
+ node "<skill_dir>/scripts/commit-worktrees.js" "<ws_root>/.worktrees/worktree-<branch>" --message "..."
132
160
  ```
133
161
 
134
162
  **选项**:
@@ -155,10 +183,10 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>" --message "..."
155
183
  ## Step 5:批量 push
156
184
 
157
185
  ```bash
158
- node "<ws_root>/.cbb/skills/cbb-worktree-push/scripts/push-worktrees.js" "<ws_root>" "<branch>"
186
+ node "<skill_dir>/scripts/push-worktrees.js" "<ws_root>" "<branch>"
159
187
 
160
188
  # 或 wt_path 形式
161
- node "..." "<ws_root>/.worktrees/worktree-<branch>"
189
+ node "<skill_dir>/scripts/push-worktrees.js" "<ws_root>/.worktrees/worktree-<branch>"
162
190
  ```
163
191
 
164
192
  **解读末行 `PUSH_RESULT`**:
@@ -210,8 +238,7 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>"
210
238
  workspace: ✅ origin/<branch>
211
239
  ep-foo-app: ✅ origin/<branch>
212
240
  ep-bar-app: ⚠️ 远程分支已存在(需用户决策 → 已关联)
213
- AI 配置目录:worktree 内独立安装,无需处理
214
- 后续:可继续开发 / 调 /opsx:verify 验证 / 调 /opsx:archive 归档 / 调 /cbb:worktree-close 关闭
241
+ 后续:可继续开发 / 调 /opsx:verify 验证 / 调 /opsx:archive 归档 / 调 `cbb-worktree-close` skill 关闭
215
242
  ```
216
243
 
217
244
  ---
@@ -220,8 +247,11 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>"
220
247
 
221
248
  | 场景 | 处理方式 |
222
249
  |------|----------|
223
- | 用户说"提交并push"且 cwd 在 worktree 内 | 自动用 cwd 反推分支,Step 2 扫描后进入 Step 3 问 commit 信息 |
224
- | 用户说"提交并push"且 cwd 在 WS_ROOT | Step 0 定位后,多个 worktree 时让用户选 |
250
+ | **任何触发** | **先做 Step 0 场景识别**,再决定策略 |
251
+ | 场景 A:cwd 在 cbb 工作空间根 | find-workspace-root 成功 多个 worktree 时让用户选 |
252
+ | 场景 B:cwd 在 worktree 内 | 自动用 cwd 反推分支,扫描后进入询问 commit 信息 |
253
+ | 场景 C:cwd 在普通 git 仓库(无 workspace-config.json) | **降级为单仓库提交推送**,不调用 worktree 脚本 |
254
+ | 场景 D:cwd 非 git 目录 | 说明情况并终止,不做任何操作 |
225
255
  | commit 信息缺失 | 必须询问用户;禁止自动生成(可基于 apply task 上下文给建议) |
226
256
  | 多仓库需不同 commit 信息 | 用 `--per-repo "ep-foo:m1;ep-bar:m2"`,必须由用户逐条提供 |
227
257
  | 仓库干净 | commit-worktrees 自动 skipped,只 push 不 commit |
@@ -236,6 +266,11 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>"
236
266
 
237
267
  ## 常见错误
238
268
 
269
+ ### 误触后硬套 worktree 流程
270
+
271
+ - **问题:** 用户在普通仓库说"提交代码",技能被 description 匹配触发,直接跑 `find-workspace-root.js` 失败并报错终止
272
+ - **修复:** Step 0 先判场景;场景 C(普通 git 仓库)降级为单仓库提交推送,不调用 worktree 脚本、不提及批量流程
273
+
239
274
  ### 自动生成 commit 信息不让用户确认
240
275
 
241
276
  - **问题:** agent 拍脑袋写 "feat: xxx",与用户实际意图不符
@@ -286,8 +321,9 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>"
286
321
 
287
322
  **必须执行**
288
323
 
289
- - 严格按 Step 0 → 1 → 2 → 3 → 4 → 5 → 6 顺序执行
290
- - 所有脚本调用以 `node "..." "<绝对路径>"` 形式发起
324
+ - 严格按 Step 0 → 1 → 2 → 3 → 4 → 5 → 6 顺序执行(场景 C/D 除外,按 Step 0 降级策略)
325
+ - 所有脚本调用以 `node "<skill_dir>/scripts/<name>.js"` 形式发起(`<skill_dir>` = 本 SKILL.md 所在目录)
326
+ - 执行脚本时 cwd 保持在工作空间根;场景 C 降级时按普通 git 流程
291
327
  - Step 2 dry-run 必跑,让用户看到将要 commit 的内容
292
328
  - Step 3 必问用户 commit 信息(自由文本),禁止自动生成
293
329
  - commit 信息涉及业务语义时(feature/refactor/fix 等)必须从 apply task 上下文生成建议并由用户确认
@@ -17,15 +17,15 @@ artifacts:
17
17
  2. 拿到用户输入后,整理并复述目标,**让用户确认**理解是否正确。未确认前禁止进入下一阶段。
18
18
  3. 信息不足或目标模糊时,继续追问,直到目标清晰无歧义。
19
19
 
20
- ### 阶段二:查阅知识库(需求确认后,代码扫描前)
20
+ ### 阶段二:收集参考材料(需求确认后,代码扫描前)
21
21
 
22
- 1. 询问用户是否有知识库、参考文档等可提供。
23
- 2. 若有知识库:通过 INDEX.md(路径见 CLAUDE.md "知识库" 章节)按层级进入。从 INDEX.md → 域索引 → 子域 → 知识条目。仅跟随索引中的已有链接,**禁止 glob 或全库搜索**。记录每个被引用的文档。
24
- 3. 若无知识库或 INDEX.md 不存在:记录"知识库暂无覆盖",直接进入阶段三,**禁止编造或强行搜索**。
22
+ 1. 用 AskUserQuestion 询问用户:除 PRD 外还有哪些参考材料(设计文档、WIKI 链接、历史方案等)?
23
+ 2. 用户指认了文档/目录:定向阅读所指范围。指认到目录级时,可浏览该目录内的文件名并阅读相关文档;目录之外的内容与全库 glob 搜索仍然禁止。
24
+ 3. 无参考材料:记录"暂无参考文档",直接进入阶段三,禁止凭空编造背景信息。
25
25
 
26
- ### 阶段三:扫描代码(带着确认后的目标 + 知识库结果去扫)
26
+ ### 阶段三:扫描代码(带着确认后的目标 + 参考材料去扫)
27
27
 
28
- 1. 以阶段一确认的目标和阶段二收集的知识库为上下文,扫描代码库。
28
+ 1. 以阶段一确认的目标和阶段二收集的参考材料为上下文,扫描代码库。
29
29
  2. 只扫与本次需求相关的入口类/方法、已有实现、依赖链。**禁止无目标的全库扫描**。
30
30
  3. 扫描结果应直接支撑「四、代码改动清单」的编写。
31
31
 
@@ -37,7 +37,7 @@ artifacts:
37
37
  - **禁止推测**:需求细节必须来自上述三阶段的产出;信息不足时回退到对应阶段补充
38
38
  - **来源标注**:一、为什么 / 二、变更简述 / 三、变更清单 / 四、代码改动清单 / 五、影响 中每一条断言后附来源,示例:
39
39
  - "(来自 PRD §3.2)"
40
- - "(知识库: myb-user-domain/auth-flow.md)"
40
+ - "(文档: docs/design/auth-flow.md)"
41
41
  - "(代码: com.x.user.facade.UserFacade#resetPassword)"
42
42
  - **存疑必问,禁止猜测**:撰写过程中遇到以下情况,必须暂停并用 AskUserQuestion 让用户决策,禁止自行假设后继续:
43
43
  - 需求逻辑不合理或自相矛盾
@@ -45,18 +45,17 @@ artifacts:
45
45
  - 存在潜在风险(资损、性能、兼容性、安全)
46
46
  - 多种可行方案各有取舍
47
47
  每次向用户确认后,将决策逐条记录到「六、决策记录」表格中。
48
- - **知识库引用**还应一并带到 design.md 的"知识库参考"章节
49
48
 
50
49
  章节(顺序:动机 → 变更简述 → 能力契约 → 代码入口 → 影响 → 决策记录;每章带中文数字序号):
51
50
  - **一、为什么**(必选):1-3 句话说清问题或机会。要解决什么?为什么是现在?
52
- - **二、变更简述**(必选):1-5 句话最精简易读地描述本需求要做的事情
51
+ - **二、变更简述**(必选):1-3 句话最精简易读地描述本需求要做的事情。破坏性变更(接口不兼容、数据结构破坏等)在句尾标注 **BREAKING**
53
52
  - **三、变更清单**(必选):能力维度的变更盘点(新增 / 修改 / 删除)。每个能力对应 `openspec/specs/<name>/spec.md`。identifier 与中文名解耦
54
53
  - **identifier 与展示名解耦**:identifier 列(`能力名` / `现有 spec 名` / `已废弃 spec 名`)填英文 kebab-case(用于 path / CLI / 跨引用),新增一列 `中文名` 填人类阅读用名
55
54
  - **新增能力**:每个对应一份新建 `specs/<name>/spec.md`
56
- - **修改能力**:每个对应一份 delta spec 文件
55
+ - **修改能力**:每个对应一份 delta spec 文件。仅限 spec 级行为变化——纯实现细节重构不算,避免生成无意义 delta
57
56
  - **删除能力**:整段能力下线。spec 文件保留并写 `## REMOVED Requirements` 段,避免后续误用
58
57
  - **四、代码改动清单**(必选):每个代码入口一行。
59
- - **必须基于实际扫代码 + 读知识库得出,禁止凭 PRD 直接推测**
58
+ - **必须基于实际扫代码 + 读参考文档得出,禁止凭 PRD 直接推测**
60
59
  - 字段:应用 / 变更类型 / 代码入口类型 / 代码入口 / 所属能力 / 变更简述 / 备注
61
60
  - 后端 代码入口类型 仅允许:rpc / rest / mq / job / sql / config / constant / enum
62
61
  - 前端 代码入口类型 固定为 `前端`;代码入口列允许 `文件路径 —— 简短描述` 自然语言
@@ -67,7 +66,14 @@ artifacts:
67
66
  - **五、影响**(必选):列出受影响的代码、接口、依赖、上下游系统。**复杂影响分析**(灰度步骤、回滚方案、跨团队协作)进入 § design 阶段
68
67
  - **六、决策记录**(必选):撰写过程中向用户确认过的每个决策点,逐条填入表格。字段:序号 / 决策点 / 用户决策 / 影响。无决策则填一行"无"
69
68
 
70
- 重要:变更清单章节是 proposal 与 spec 阶段的契约核心。动笔前先研究现有 spec。每列出的能力都对应一份 spec 文件。
69
+ 重要:变更清单章节是 proposal 与 spec 阶段的契约核心。动笔前先研究现有 spec,禁止凭空起名:
70
+ 1. `openspec list --specs` 拉取项目能力清单
71
+ 2. 对疑似相关的 spec 先用 `openspec show "<spec-id>" --type spec --json --no-scenarios` 概览(返回能力用途与需求文本,不拉全文)
72
+ 3. 决定增改前,对相关 spec 全文阅读:`openspec show "<spec-id>" --type spec`(含 scenarios)
73
+ 4. 修改能力必须复用 `openspec/specs/` 下已有能力的准确路径,禁止引入近似重复名
74
+ 每列出的能力都对应一份 spec 文件。
75
+
76
+ 零能力变更的处理:若本次变更不涉及任何能力(纯重构、工具、文档、纯基础设施改动),变更清单三个子表留空,并在 change 的 `.openspec.yaml` 中设置 `skip_specs: true` —— `openspec validate` 会拒绝零 delta 的 change,该标记是唯一出口。禁止为通过校验编造能力或需求。
71
77
 
72
78
  保持简洁(1-2 页)。专注"为什么"而非"怎么做"——实现细节归 design.md。
73
79
 
@@ -105,23 +111,9 @@ artifacts:
105
111
  instruction: |
106
112
  Create the design document that explains HOW to implement the change.
107
113
 
108
- **Knowledge Base Reference (MANDATORY):**
109
- Before writing design, you MUST consult the project's knowledge base:
110
- 1. Read the knowledge base root INDEX.md (path defined in CLAUDE.md under "知识库")
111
- 2. Navigate from INDEX.md → relevant domain index → sub-domain → knowledge chunks
112
- 3. Collect all knowledge documents relevant to this change's design sections
113
- 4. Fill the "知识库参考" section in the template with: knowledge point name, full file path, corresponding design section
114
- 5. If a design section has no matching knowledge base coverage, note it as "知识库暂无覆盖,建议补充"
115
-
116
- Knowledge-to-design-section mapping reference:
117
- - 需求背景 → business domain indexes (myb-*-domain/)
118
- - 架构设计 → application indexes (project/<app>/)
119
- - 领域模型设计 → domain indexes (myb-*-domain/)
120
- - 核心流程设计 → domain knowledge chunks
121
- - 数据库模型 → application indexes + domain knowledge
122
- - MQ设计 → domain knowledge chunks
123
- - 稳定性设计 → tech-asset/tech-gray/
124
- - 防资损设计 → domain knowledge chunks
114
+ **Reference documents:**
115
+ Build on the reference documents gathered during the proposal phase (see its source annotations, e.g. "(文档: …)").
116
+ If the design needs additional documents, ask the user to designate them (targeted reading only, no repo-wide globbing).
125
117
 
126
118
  When to include design.md (create only if any apply):
127
119
  - Cross-cutting change (multiple services/modules) or new architectural pattern
@@ -130,7 +122,6 @@ artifacts:
130
122
  - Ambiguity that benefits from technical decisions before coding
131
123
 
132
124
  Sections (follow design.md template):
133
- - **知识库参考**(必选):列出本次设计参考的知识库文档路径及对应章节
134
125
  - **需求或项目背景**(必选):问题/目标、PRD/DMPT链接
135
126
  - **Checklist事项**(必选):逐项检查技术风险(新接口、改接口、新枚举、新依赖、新表/MQ、sentinel、敏感数据、SQL、历史兼容、Redis、验签)
136
127
  - **功能拆解**(必选):按模块拆分功能点,标注变更类型和FTAPI
@@ -12,24 +12,6 @@
12
12
 
13
13
  ---
14
14
 
15
- ## 零、知识库参考(必选)
16
-
17
- <!-- AI理解要点:此章节记录本次设计参考了哪些知识库文档,确保设计基于已有知识而非凭空构思。
18
- 通过知识库索引(INDEX.md)逐级定位后,列出实际读取的知识文档路径。 -->
19
-
20
- | 序号 | 参考知识点 | 知识库路径 | 对应设计章节 | 备注 |
21
- | ---- | ---------- | ---------- | ------------ | ---- |
22
- | 1 | <!-- 知识点名称 --> | <!-- 从INDEX.md逐级定位的完整路径 --> | <!-- 架构设计/领域模型/... --> | <!-- 参考了什么 --> |
23
-
24
- <!-- 知识库导航方式:
25
- 1. 从知识库根索引 INDEX.md 出发
26
- 2. 按业务域/技术域逐级定位到具体知识文档
27
- 3. 将实际读取的文档路径填入上表
28
- 4. 如果某章节无对应知识库文档,在备注中标注"知识库暂无覆盖,建议补充"
29
- -->
30
-
31
- ---
32
-
33
15
  ## 一、需求或项目背景(必选)
34
16
 
35
17
  <!-- AI理解要点:此章节提供需求的上下文信息,帮助理解业务背景和目标 -->
@@ -2,16 +2,17 @@
2
2
 
3
3
  <!-- 说明这次变更的动机。要解决什么问题?为什么是现在? -->
4
4
 
5
- ## 二、变更摘要
5
+ ## 二、变更简述
6
6
 
7
- <!-- 1-3 句话最精简易读地描述本需求要做的事情。 -->
7
+ <!-- 1-3 句话最精简易读地描述本需求要做的事情。破坏性变更(接口不兼容、数据结构破坏等)在句尾标注 **BREAKING**。 -->
8
8
 
9
9
  ## 三、变更清单
10
10
 
11
11
  <!-- 能力维度的变更盘点(新增 / 修改 / 删除)。每个能力对应 `openspec/specs/<name>/spec.md`。
12
12
  表格同时承载"能力本身的静态信息(identifier / 中文名 / 简述)"和"本次变更对它的动作"。
13
13
  第四章"代码改动清单"是落到代码层的具体改动点。两章通过 identifier 字段双向关联。
14
- **identifier 与展示名解耦**:identifier 列填英文 kebab-case(用于 path / CLI / 跨引用);`中文名` 列填人类阅读用名,可与 identifier 不同。 -->
14
+ **identifier 与展示名解耦**:identifier 列填英文 kebab-case(用于 path / CLI / 跨引用);`中文名` 列填人类阅读用名,可与 identifier 不同。
15
+ 零能力变更:三章全部留空(纯重构 / 工具 / 文档 / 纯基础设施),并在 change 的 `.openspec.yaml` 设 `skip_specs: true` —— `openspec validate` 拒绝零 delta 的 change,该标记是唯一出口;禁止为通过校验编造能力。 -->
15
16
 
16
17
  ### 新增能力
17
18
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  1. **本目录不做需求开发**。本目录(业务空间主分支)只负责组织与调度;需求开发的**写操作**都在 `.worktrees/worktree-<需求名>/` 隔离目录内进行,**AI 会话仍停在空间根**(worktree 内不装 AI 配置)。
9
9
  2. **AI 配置安装在空间根**:编码规范、OpenSpec 命令、worktree 管理技能都装在本目录(`cbb setup` / `cbb update` 安装);worktree 内**不安装** AI 配置,AI 会话始终以空间根为基础。
10
- 3. **接到新需求先建 worktree**:在本目录执行 `/cbb:worktree-init <需求名>`(opencode 写法:`/cbb-worktree-init`)。它会为 `workspace-config.json` 中的全量关联应用同步创建同名 worktree。
10
+ 3. **接到新需求先建 worktree**:使用 `/cbb-worktree-init <需求名>`(skill 形态,各工具写法见文末),或直接自然语言说"为 <需求名> 创建工作空间"。它会为 `workspace-config.json` 中的全量关联应用同步创建同名 worktree。
11
11
  4. **开发命令在本会话执行,写操作指向 worktree**:需求提案 / 实现 / 验证 / 归档(`/opsx:propose` → `/opsx:apply` → `/opsx:verify` → `/opsx:archive`)在空间根会话执行;但所有产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录(显式 `cd` 或绝对路径);**禁止在空间根(主分支)执行写操作**。
12
12
  5. **关联应用增减只改配置**:编辑 `workspace-config.json` 的 `apps` 数组(`name` / `repo` / `side` / `desc`),然后用同一需求名重跑 worktree 初始化即幂等补齐;不要手工 `git clone` 应用仓库。
13
13
  6. **不要绕过 worktree 直接修改 `.codespace/` 或本目录的代码**。`.codespace/` 是工具维护的基准代码,不是开发区。
@@ -20,19 +20,19 @@
20
20
  | `.codespace/` | 各关联应用的基准代码(每个应用一个子目录) | `cbb setup` 与 worktree 流程自动 clone / fetch;**勿手动编辑**;已 gitignore,不提交 |
21
21
  | `.worktrees/` | 需求隔离开发区(每个需求一个 `worktree-<需求名>/` 目录) | worktree 命令自动创建 / 清理;不提交(首次执行 worktree 流程时自动加入 .gitignore) |
22
22
  | `openspec/` | OpenSpec 工作流配置(`config.yaml` + `schemas/`) | 由 cbb 安装;需求变更产物(`openspec/changes/` 等)在**需求工作树内**生成,随需求分支提交 |
23
- | `.claude/` `.qoder/` `.opencode/` `.codebuddy/` `.trae/` | AI 工具适配目录:编码规范规则、OpenSpec 命令、worktree 管理命令 | 由 cbb 按 setup 时选择的工具安装;已 gitignore,不提交,勿手动改 |
24
- | `.cbb/` | cbb 安装清单 + worktree 运行时(`.cbb/skills/`:流程文档与脚本,各工具命令共用) | 由 cbb 管理;**勿手动编辑** |
23
+ | `.claude/` `.qoder/` `.opencode/` `.codebuddy/` `.trae/` | AI 工具适配目录:编码规范规则、OpenSpec 命令、worktree 管理技能(skill 形态) | 由 cbb 按 setup 时选择的工具安装;已 gitignore,不提交,勿手动改 |
24
+ | `.cbb/` | cbb 安装清单与状态(`.managed-by-cbb`、`.last-tools`) | 由 cbb 管理;**勿手动编辑** |
25
25
 
26
26
  ## 典型流程
27
27
 
28
28
  ```
29
- 本目录:/cbb:worktree-init <需求名>
29
+ 本目录:对 AI 说"为 <需求名> 创建工作空间"(或 /cbb-worktree-init <需求名>)
30
30
  → 继续在当前会话开发:写操作命令以 .worktrees/worktree-<需求名>/ 为工作目录
31
31
  (/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive)
32
- → /cbb:worktree-push 推送 → 合并后 /cbb:worktree-close 关闭
32
+ 说"提交并推送"(或 /cbb-worktree-push)→ 合并后说"关闭工作空间"(或 /cbb-worktree-close
33
33
  ```
34
34
 
35
- > 命令写法因 AI 工具而异:Claude Code / Qoder / WorkBuddy / Trae `/cbb:worktree-init`、`/opsx:propose`;opencode 因「文件名即命令名」且 Windows 文件名不允许 `:`,扁平化为 `/cbb-worktree-init`、`/opsx-propose`。
35
+ > worktree 管理三件套(init / close / push)以 **skill 形态**分发:既能被 AI 在对话中按意图**自动触发**,也能用斜杠命令手动指定(`/cbb-worktree-init` 等,各工具一致)。OpenSpec 命令为 `/opsx:propose`(opencode 扁平化为 `/opsx-propose`)。
36
36
 
37
37
  ---
38
38
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jspg-ai/coding-bb",
3
- "version": "0.0.3-beta.7",
3
+ "version": "0.0.3-beta.8",
4
4
  "description": "整合业界热门且高价值的工具、框架与技能,为 AI CODING AGENT 提供统一的行为准则与工作流,辅助开发者将需求高效落地为符合规范的代码",
5
5
  "main": "cbb/lib/install/init.js",
6
6
  "bin": {
@@ -1,63 +0,0 @@
1
- ---
2
- name: "CBB: Worktree Close"
3
- description: 关闭/清理由 worktree-init 创建的多仓库联动 worktree 工作空间,移除 worktree 并按用户选择处理特性分支
4
- category: Workflow
5
- tags: [worktree, cleanup, worktree, git-worktree]
6
- ---
7
-
8
- # CBB: Worktree Close - 关闭 Worktree
9
-
10
- ## 重要:第一步必须用 Read 工具直接打开 SKILL.md
11
-
12
- **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md。这些命令在 Agent 运行环境(Qoder Windows PowerShell 等)中经常失败。
13
-
14
- **直接路径**(各工具统一,worktree 运行时部署在空间根 `.cbb/skills/`):
15
- - `.cbb/skills/cbb-worktree-close/SKILL.md`
16
-
17
- **第一步**:
18
- 1. 用 Read 工具直接打开 `.cbb/skills/cbb-worktree-close/SKILL.md`
19
- 2. 按 SKILL.md 的 Step 0 → 1 → 2 → 3 → 4 → 5 → 6 顺序执行
20
- 3. 每次调用 Node.js 脚本时使用**绝对路径**
21
-
22
- ## Input
23
-
24
- 参数 `<分支名>`(可选),指定要关闭的 worktree 对应的特性分支。**未提供时按 SKILL.md Step 1 在对话中询问或自动选取唯一 worktree**。
25
-
26
- **Steps 概述**(完整流程见 SKILL.md)
27
-
28
- 1. Step 0:前置校验(Git 仓库检测、workspace-config.json 检测,支持向上查找)
29
- 2. Step 1:确定要关闭的目标 worktree(列出 `.worktrees/` 下的工作空间 worktree,用户选择或自动选取)
30
- 3. Step 2:发现关联应用 worktree(读 workspace-config.json,按实际存在性确定关联清单)
31
- 4. Step 3:安全检查(未提交修改 / 是否合并到主分支 / 是否推到远程,含主动 fetch 刷新远程引用)
32
- 5. Step 4:用户决策(未提交修改处理方式 + 分支处理方式,AskUserQuestion 固定选项)
33
- 6. Step 5:移除 Worktree(三层降级策略:正常移除 → prune+物理删除 → 仅 prune 延迟清理)
34
- 7. Step 5.5:二次确认 worktree 已移除(确保分支不再被检出)
35
- 8. Step 6:删除分支(按用户选择的 MODE:保留 / 删本地 / 删本地+远程)
36
- 9. Step 8:确认收尾(pwd 确认、残留检查、最终报告)
37
-
38
- **Output**
39
-
40
- ```
41
- ✅ 工作空间 worktree 已关闭
42
- 当前目录:<工作空间根目录绝对路径>
43
- 已移除 worktree:
44
- - .worktrees/worktree-<需求名>(workspace)
45
- - .worktrees/worktree-<需求名>/<应用名1>(嵌套)
46
- - .worktrees/worktree-<需求名>/<应用名2>(嵌套)
47
- 未提交修改:已丢弃(--force)/ 无
48
- 分支处理:<需求名> 已删除(本地+远程)/ 已删除(本地)/ 已保留
49
- 剩余工作空间 worktree:<列出仍存在的,或 "无" >
50
- Workspace cleaned up.
51
- ```
52
-
53
- 详细输出格式与安全检查报告,见 SKILL.md「最终报告」与「Step 3」段。
54
-
55
- **Guardrails**
56
-
57
- - 必须在业务工作空间根目录执行(包含 workspace-config.json 的目录),支持从 worktree 内部向上查找
58
- - 顺序硬约束:**先移除所有 worktree,再删除分支**(先删分支会报 `Cannot delete branch checked out at`)
59
- - 破坏性操作必须先报告、经用户确认才执行(未提交修改、未合并分支绝不静默 `--force` 或 `-D`)
60
- - 只操作 `.worktrees/worktree-<需求名>` 路径,绝不碰其它 worktree(如 IDE 会话 worktree)
61
- - 关联应用以实际存在的 worktree 为准,不假设 workspace-config.json 中所有应用都有关联
62
- - 依赖 shell 函数的脚本必须整段在一次 Bash 调用中执行(函数不跨调用保留)
63
- - git 操作一律用 `git -C <仓库>` 绝对路径,不依赖跨调用的 cwd
@@ -1,50 +0,0 @@
1
- ---
2
- name: "CBB: Worktree Init"
3
- description: 为一个需求在 workspace 与各关联应用仓库同步创建同名 git worktree,物理直聚在 `.worktrees/<需求名>/` 目录
4
- category: Workflow
5
- tags: [worktree, isolation, worktree, git-worktree]
6
- ---
7
-
8
- # CBB: Worktree Init - 创建 Worktree
9
-
10
- ## 重要:第一步必须用 Read 工具直接打开 SKILL.md
11
-
12
- **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md 是否存在。**这些命令在 Agent 运行环境(Qoder Windows PowerShell 等)中经常失败**(如 `head` 不存在、stderr 重定向无效等)。
13
-
14
- **直接路径**(各工具统一,worktree 运行时部署在空间根 `.cbb/skills/`):
15
- - `.cbb/skills/cbb-worktree-init/SKILL.md`
16
-
17
- **第一步**:
18
- 1. 用 Read 工具直接打开 `.cbb/skills/cbb-worktree-init/SKILL.md`
19
- 2. 按 SKILL.md 的 Step 0 → 1 → 2 → 3 → 4 顺序执行
20
- 3. 每次调用 Node.js 脚本时,使用**绝对路径**(避免依赖相对路径):
21
- ```
22
- node "D:\workspace\<用户工作空间>\.cbb\skills\cbb-worktree-init\scripts\<name>.js" <参数>
23
- ```
24
- - 参数形式:
25
- - `check-env.js`:无参数
26
- - `parse-config.js`:无参数
27
- - `sync-repos.js`:`<ws_root>`
28
- - `check-repos.js`:`<ws_root>`
29
- - `create-branches.js`:`<ws_root> <branch>`
30
- - `update-gitignore.js`:`<ws_root> <branch>`
31
- - `create-worktrees.js`:`<ws_root> <branch>`
32
-
33
- ## Input
34
-
35
- 参数 `<需求名>`(kebab-case),同时作分支名和 workspace 工作树目录名。**未提供时按 SKILL.md Step 3.1 在对话中询问**。
36
-
37
- ## 流程总览(完整流程见 SKILL.md)
38
-
39
- 1. Step 0:环境探活 + 解析 workspace-config.json
40
- 2. Step 1:同步 .codespace/ 仓库(fetch --all)
41
- 3. Step 2:状态检查(5 项 / 3 项分级)
42
- 4. Step 3:创建分支 → 推送 upstream → 创建 worktree(workspace + 嵌套 app)
43
- 5. Step 4:收尾与交接(继续当前会话,声明目录纪律)
44
-
45
- ## 关键 Guardrails
46
-
47
- - workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)由 git worktree 自动 checkout——**禁止 cp / clone / symlink “带过来”**
48
- - 必须用 `git branch` 而非 `git checkout -b`(分支不能同时在主目录与 worktree 检出)
49
- - 运行环境 node 不可用时 fail-fast:终止流程并提示用户到系统终端重试
50
- - **不要试图搜索 SKILL.md**——直接用 Read 工具打开
@@ -1,42 +0,0 @@
1
- ---
2
- name: "CBB: Worktree Push"
3
- description: 跨 worktree 提交并推送当前需求的所有关联仓库到 origin
4
- category: Workflow
5
- tags: [workflow, push, commit, worktree, experimental]
6
- ---
7
-
8
- 跨 worktree 提交并推送当前需求的所有关联仓库到 origin。
9
-
10
- **Input**: 可选指定需求名(如 `/cbb:worktree-push ft-diff-on-cargo`)。省略时从 cwd 的 `.worktrees/worktree-<需求名>/` 路径推断(cwd 在工作空间根目录时由 Step 0 定位)。
11
-
12
- **何时使用**:
13
-
14
- - apply 完成后准备推送所有改动
15
- - close-worktree 前需要先确保 ahead 提交已推送(避免丢)
16
- - 开发过程中想保存中间进度
17
- - 用户口语化说"提交并push" / "推一下"
18
-
19
- **Steps 摘要**(详细流程见空间根 `.cbb/skills/cbb-worktree-push/SKILL.md`):
20
-
21
- 1. **Step 0**:定位工作空间根(find-workspace-root.js)
22
- 2. **Step 1**:识别目标 worktree(find-target-worktree.js)
23
- 3. **Step 2**:扫描所有 worktree 仓库状态(commit-worktrees.js --dry-run)
24
- 4. **Step 3**:对话中收集 commit 信息(必须由用户提供)
25
- 5. **Step 4**:批量 commit(commit-worktrees.js)
26
- 6. **Step 5**:批量 push(push-worktrees.js)
27
- 7. **Step 6**:汇总报告
28
-
29
- **关键 Guardrails**:
30
-
31
- - 严格按 Step 0 → 1 → 2 → 3 → 4 → 5 → 6 顺序执行
32
- - **Step 2 dry-run 必跑**,让用户看到将要 commit 的内容
33
- - **Step 3 必问用户 commit 信息**(自由文本),禁止自动生成
34
- - 默认 `git add -u`(仅 tracked),避免误纳未追踪文件
35
- - push 失败时阻塞并按错误码分类处理,**禁止**自动跳过失败仓库
36
- - 远程分支已存在时必须输出 commit 元信息再询问用户决策
37
-
38
- **Failure Handling**:
39
-
40
- - commit-worktrees.js 退出码 2 → 部分 commit 失败,**阻塞流程**,询问用户
41
- - push-worktrees.js 退出码 2 → 部分 push 失败,**阻塞流程**,按错误码询问用户
42
- - 远程分支已存在 → 先输出元信息,再 AskUserQuestion 让用户选择「关联」或「终止」