@jspg-ai/coding-bb 0.0.3-beta.24 → 0.0.3-beta.26

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.
Files changed (33) hide show
  1. package/cbb/dev-standards/rules/cbb-ai-behavior.md +3 -3
  2. package/cbb/lib/install/init.js +23 -21
  3. package/cbb/lib/install/workspaces.js +15 -15
  4. package/cbb/lib/utils/githook.js +9 -7
  5. package/cbb/worktrees/_shared/scripts/find-workspace-root.js +7 -7
  6. package/cbb/worktrees/_shared/scripts/install-git-hook.js +1 -1
  7. package/cbb/worktrees/_shared/scripts/start-local.js +4 -4
  8. package/cbb/worktrees/skills/cbb-local-mode/scripts/install-git-hook.js +1 -1
  9. package/cbb/worktrees/skills/cbb-local-mode/scripts/start-local.js +4 -4
  10. package/cbb/worktrees/skills/cbb-worktree-close/SKILL.md +11 -8
  11. package/cbb/worktrees/skills/cbb-worktree-close/scripts/check-env.js +3 -3
  12. package/cbb/worktrees/skills/cbb-worktree-close/scripts/delete-branches.js +1 -1
  13. package/cbb/worktrees/skills/cbb-worktree-close/scripts/discover-apps.js +4 -4
  14. package/cbb/worktrees/skills/cbb-worktree-close/scripts/find-workspace-root.js +7 -7
  15. package/cbb/worktrees/skills/cbb-worktree-close/scripts/remove-worktrees.js +1 -1
  16. package/cbb/worktrees/skills/cbb-worktree-close/scripts/safety-check.js +1 -1
  17. package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +30 -26
  18. package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-env.js +1 -1
  19. package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-repos.js +2 -2
  20. package/cbb/worktrees/skills/cbb-worktree-init/scripts/create-branches.js +3 -3
  21. package/cbb/worktrees/skills/cbb-worktree-init/scripts/create-worktrees.js +4 -4
  22. package/cbb/worktrees/skills/cbb-worktree-init/scripts/find-workspace-root.js +7 -7
  23. package/cbb/worktrees/skills/cbb-worktree-init/scripts/install-git-hook.js +1 -1
  24. package/cbb/worktrees/skills/cbb-worktree-init/scripts/parse-config.js +7 -7
  25. package/cbb/worktrees/skills/cbb-worktree-init/scripts/push-branches.js +3 -3
  26. package/cbb/worktrees/skills/cbb-worktree-init/scripts/sync-repos.js +6 -6
  27. package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +7 -7
  28. package/cbb/worktrees/skills/cbb-worktree-push/scripts/commit-worktrees.js +2 -2
  29. package/cbb/worktrees/skills/cbb-worktree-push/scripts/find-workspace-root.js +7 -7
  30. package/cbb/worktrees/skills/cbb-worktree-push/scripts/push-worktrees.js +2 -2
  31. package/config/{workspace-config.sample.json → CBB-WORKSPACE.sample.json} +1 -1
  32. package/config/workspace-agents.sample.md +4 -44
  33. package/package.json +1 -1
@@ -83,7 +83,7 @@ function removeWt(repoPath, wtPath, name) {
83
83
  }
84
84
 
85
85
  // 1. 应用 worktrees
86
- const configPath = path.join(wsRoot, 'workspace-config.json');
86
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
87
87
  let config = {};
88
88
  try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (e) {}
89
89
 
@@ -152,7 +152,7 @@ function checkRepo(name, repoPath, wtPath) {
152
152
  return { name, wt: wtPath, fetch_ok: fetchOk, dirty_files: dirtyFiles, merged, main, remote_exists: remoteExists, remote: remoteName, unpushed_count: unpushedCount };
153
153
  }
154
154
 
155
- const configPath = path.join(wsRoot, 'workspace-config.json');
155
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
156
156
  let config = {};
157
157
  try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (e) {}
158
158
 
@@ -16,9 +16,9 @@ description: "为一个需求在 workspace 与各关联应用仓库同步创建
16
16
  - 所有仓库使用统一的分支名(不加前缀);worktree 目录名自动加 `worktree-` 前缀;**分支基线统一取 `origin/<main>`(ADR 0002,不取 HEAD)**
17
17
  - **lazy push(ADR 0002)**:本技能**不向远端推送任何分支**——远端副作用收敛到 `cbb-worktree-push` 唯一出口;推送失败早暴露的职责由 push 技能的 dry-run 承担
18
18
  - **AI 配置 junction(ADR 0002 防线 B)**:创建 worktree 后把根的 AI 配置**内容子目录**(rules / skills / commands)junction 进工作树——开发会话开在 `<wt_path>`(上游 `/opsx:*` 相对路径原样生效,零翻译);工具状态落在工作树自建空壳目录,不互相污染;`cbb update` 在根跑一次全 worktree 生效
19
- - **本技能必须在业务工作空间根目录执行**(即由 `cbb setup` 初始化、包含 `workspace-config.json` 的目录)
19
+ - **本技能必须在业务工作空间根目录执行**(即由 `cbb setup` 初始化、包含 `CBB-WORKSPACE.json` 的目录)
20
20
  - 输入约定:**自由文本**(需求名等)直接在对话中提问并等待回复,禁止使用 `AskUserQuestion`;`AskUserQuestion` 仅用于固定选项决策场景(如 push 失败处理、远程分支已存在时的二选一)
21
- - 关联应用默认为 `workspace-config.json` 的**全量 apps**;支持按需求语境传入**应用子集**(见 Step 1),需要增减应用时编辑该文件并重跑本技能(幂等)
21
+ - 关联应用默认为 `CBB-WORKSPACE.json` 的**全量 apps**;支持按需求语境传入**应用子集**(见 Step 1),需要增减应用时编辑该文件并重跑本技能(幂等)
22
22
  - **模式选择(ADR 0002)**:接到需求先判断用户要哪种模式——要**并行 / 隔离** → 本技能;**单线程快改、当前会话就地干** → 引导 `cbb-local-mode`。用户明确指定即遵从,agent 只给推荐不代决
23
23
 
24
24
  ---
@@ -34,7 +34,7 @@ node "<skill_dir>/scripts/<name>.js" <参数>
34
34
  ```
35
35
 
36
36
  > - `<skill_dir>` = 本 SKILL.md 所在目录的绝对路径(AI 从读取路径即可推出)
37
- > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `workspace-config.json` 与 git 仓库
37
+ > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `CBB-WORKSPACE.json` 与 git 仓库
38
38
  > - 不要用 `./scripts/...` 裸相对路径(AI 的 cwd 不是技能目录,会解析失败)
39
39
 
40
40
  脚本输出:
@@ -47,7 +47,7 @@ node "<skill_dir>/scripts/<name>.js" <参数>
47
47
  - `<branch>`:需求名字符串
48
48
  - `<wt_path>`:worktree 绝对路径
49
49
 
50
- 所有脚本读 workspace-config.json:app 列表从 `<ws_root>/workspace-config.json` 读取,不需要传 JSON 参数。
50
+ 所有脚本读 CBB-WORKSPACE.json:app 列表从 `<ws_root>/CBB-WORKSPACE.json` 读取,不需要传 JSON 参数。
51
51
 
52
52
  ---
53
53
 
@@ -80,7 +80,7 @@ node "<skill_dir>/scripts/check-env-deep.js"
80
80
  - Node.js >= 16.7.0
81
81
  - `.worktrees/` 目录可写
82
82
 
83
- ### 0.2 读取并校验 workspace-config.json
83
+ ### 0.2 读取并校验 CBB-WORKSPACE.json
84
84
 
85
85
  ```bash
86
86
  node "<skill_dir>/scripts/parse-config.js"
@@ -93,23 +93,23 @@ node "<skill_dir>/scripts/parse-config.js"
93
93
 
94
94
  ### 0.3 配置引导
95
95
 
96
- 当 `workspace-config.json` 缺失、`apps` 为空或格式错误时,向用户说明情况并给出两个选项:
96
+ 当 `CBB-WORKSPACE.json` 缺失、`apps` 为空或格式错误时,向用户说明情况并给出两个选项:
97
97
 
98
98
  ```
99
- ⚠️ 当前工作空间尚未配置关联应用(workspace-config.json 缺失或 apps 为空)。
99
+ ⚠️ 当前工作空间尚未配置关联应用(CBB-WORKSPACE.json 缺失或 apps 为空)。
100
100
  worktree 需要知道要关联哪些应用仓库。
101
101
 
102
102
  请选择:
103
- [1] 我自行配置 workspace-config.json,配好后告诉你继续
104
- [2] 提供应用仓库地址,我帮你写入 workspace-config.json
103
+ [1] 我自行配置 CBB-WORKSPACE.json,配好后告诉你继续
104
+ [2] 提供应用仓库地址,我帮你写入 CBB-WORKSPACE.json
105
105
  ```
106
106
 
107
107
  **选项 1:用户自行配置**
108
108
  - 停止当前技能流程
109
- - 提示用户:*"请编辑 workspace-config.json 后回复'继续',或重新执行 init-worktree。"*
109
+ - 提示用户:*"请编辑 CBB-WORKSPACE.json 后回复'继续',或重新执行 init-worktree。"*
110
110
  - 用户回复"继续"后,重新从 Step 0 开始校验
111
111
 
112
- **选项 2:帮用户写入 workspace-config.json**
112
+ **选项 2:帮用户写入 CBB-WORKSPACE.json**
113
113
  - 直接在对话中请用户提供应用信息,格式示例:
114
114
  ```
115
115
  应用名: ep-user-auth-app
@@ -120,7 +120,7 @@ worktree 需要知道要关联哪些应用仓库。
120
120
  仓库地址: git@code.example.com:team/ep-user-info-server.git
121
121
  类型: back(可选值:front 前端 / back 后端 / mixed 前后端混合)
122
122
  ```
123
- - 解析后写入 `workspace-config.json`:
123
+ - 解析后写入 `CBB-WORKSPACE.json`:
124
124
  ```json
125
125
  {
126
126
  "apps": [
@@ -131,20 +131,20 @@ worktree 需要知道要关联哪些应用仓库。
131
131
  ```
132
132
  - 写入成功后提交到当前分支(确保 Step 2 状态检查通过):
133
133
  ```bash
134
- git add workspace-config.json
135
- git commit -m "chore: add workspace-config.json"
134
+ git add CBB-WORKSPACE.json
135
+ git commit -m "chore: add CBB-WORKSPACE.json"
136
136
  ```
137
137
  > 若当前不在主分支上,提示用户切回主分支后再提交;若已在主分支上则直接提交。
138
138
  - 提交后重新从 Step 0 校验,通过后继续 Step 1
139
139
 
140
- > ⚠️ **禁止**:在 workspace-config.json 无效时跳过本步骤直接创建 worktree,否则无法确定关联应用。
140
+ > ⚠️ **禁止**:在 CBB-WORKSPACE.json 无效时跳过本步骤直接创建 worktree,否则无法确定关联应用。
141
141
 
142
142
  ---
143
143
 
144
144
  ## Step 1:关联应用与代码同步
145
145
 
146
146
  > ⓘ **关联应用 = 需求涉及的应用子集**:从需求语境提取("改订单导出" → 订单相关应用);纯 workspace 内容的需求 → 仅 workspace。子集判断错了零代价——重跑本技能幂等补齐(已存在的分支/worktree 自动复用,详见「幂等重跑」章节)。涉及全部应用 / 不确定时用全量。
147
- > 需要增减应用时,编辑 `workspace-config.json` 后**重跑本技能**即可。
147
+ > 需要增减应用时,编辑 `CBB-WORKSPACE.json` 后**重跑本技能**即可。
148
148
 
149
149
  ### 1.1 同步 `.codespace/` 目录代码
150
150
 
@@ -154,7 +154,7 @@ node "<skill_dir>/scripts/sync-repos.js" "<ws_root>"
154
154
  ```
155
155
 
156
156
  **用法**:
157
- - `<ws_root>`:工作空间根绝对路径(apps 由脚本内部从 `<ws_root>/workspace-config.json` 读取,全量 fetch/clone)
157
+ - `<ws_root>`:工作空间根绝对路径(apps 由脚本内部从 `<ws_root>/CBB-WORKSPACE.json` 读取,全量 fetch/clone)
158
158
 
159
159
  **解读输出**:
160
160
  - 退出码 0 + 末行 `SYNC_RESULT [...]` → 全部成功
@@ -320,7 +320,10 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
320
320
 
321
321
  不执行脚本。AI agent 向用户输出最终报告(格式见「最终报告」),并完成以下交接声明:
322
322
 
323
- 1. **开发会话开进 worktree**:新开 IDE 窗口 / agent 会话于 `<wt_path>`(AI 配置已 junction 就位,`/opsx:*` 等命令与技能在该会话可用);本(根)会话保留作控制面——后续创建/关闭 worktree、`cbb update` 等空间级操作在此执行
323
+ 1. **开发会话开进 worktree**(按工具形态,二选一):
324
+ - **桌面端(单窗口工作流)**:将当前窗口的工作区根切到 `<wt_path>`(打开文件夹 / Open Folder / 切换工作目录)——**无需新窗口**,聊天上下文保留;AI 配置已 junction 就位(`/opsx:*` 等命令照常可用),`.codespace/<app>/...` 相对路径原样生效
325
+ - **CLI / TUI agent**:新开会话于 `<wt_path>`;根会话保留作控制面——后续创建/关闭 worktree、`cbb update` 等空间级操作在此执行
326
+ - 无论哪种形态,**必须向用户报出空间根绝对路径 `<ws_root>`**(控制面地址:close 关闭 worktree 后回切用)
324
327
  2. **目录纪律(worktree 会话内自然成立)**:会话 cwd == 开发目录,上游相对路径原样生效;**分支感知 hook 已覆盖全部仓库**——任何落 main 的载荷提交会被拦截(大声失败是防线,不是故障)
325
328
  3. 不自动安装依赖:各仓库技术栈不一(Maven 依赖本机 `~/.m2` 全局共享、无需初始化;Node/Python 等由你进入 worktree 后执行正确的命令,如 `npm ci` / `pnpm`)
326
329
  4. **输出下一步建议**:最终报告必须包含「下一步建议」段(格式见「最终报告」),告知用户后续可走的流程;仅提示,不自动串联执行任何后续技能
@@ -335,7 +338,8 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
335
338
  ✅ worktree 已创建:<wt_path>
336
339
  关联应用:<应用名 → .codespace/<应用名> 路径> 列表(应用子集或全量)
337
340
  🔗 AI 配置已 junction 就位:rules / skills / commands(cbb update 一处生效)
338
- 📌 开发会话请开在 <wt_path>(新开 IDE 窗口 / agent 会话);本根会话保留作控制面
341
+ 📌 开发会话开进 <wt_path>(桌面端:当前窗口切换工作区根即可,无需新窗口;CLI 端:新开会话)
342
+ 空间根路径(控制面,close 后回切):<ws_root>
339
343
  👉 下一步建议:
340
344
  1. 开始需求开发(开发会话内,二选一):
341
345
  - 走 OpenSpec 工作流:/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive
@@ -354,7 +358,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
354
358
 
355
359
  | 场景 | 重跑行为 |
356
360
  |------|----------|
357
- | 空间新增了应用(编辑 `workspace-config.json` 后) | Step 1 拉取新应用代码 → Step 3.3 为新应用建分支 → Step 3.5 在 `.codespace/` 容器内创建缺失的 app worktree → Step 3.6 补 junction |
361
+ | 空间新增了应用(编辑 `CBB-WORKSPACE.json` 后) | Step 1 拉取新应用代码 → Step 3.3 为新应用建分支 → Step 3.5 在 `.codespace/` 容器内创建缺失的 app worktree → Step 3.6 补 junction |
358
362
  | 上次 init 中途失败 | 已存在的分支 / worktree 自动复用,`.gitignore` 处理自动跳过,仅补齐缺失部分 |
359
363
  | 应用从 config 移除 | 已创建的分支 / worktree **不会**自动删除;如需清理用 `cbb-worktree-close` skill 关闭后重建 |
360
364
  | **本地模式升级 worktree**(ADR 0002) | Step 3.3 分支已存在 → reused(本地阶段提交随身带走);先 `git checkout main` 腾出各仓库本地检出,再重跑本技能 |
@@ -385,10 +389,10 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
385
389
 
386
390
  ## 常见错误
387
391
 
388
- ### 跳过 workspace-config.json 直接硬编码仓库地址
392
+ ### 跳过 CBB-WORKSPACE.json 直接硬编码仓库地址
389
393
 
390
394
  - **问题:** 直接在代码中写死仓库 URL 或本地路径,不同团队的仓库地址不同
391
- - **修复:** 始终从 `workspace-config.json` 读取应用与远程仓库的映射;配置缺失/为空时按 Step 0.3 配置引导处理,不支持在流程中临时指定配置外的仓库
395
+ - **修复:** 始终从 `CBB-WORKSPACE.json` 读取应用与远程仓库的映射;配置缺失/为空时按 Step 0.3 配置引导处理,不支持在流程中临时指定配置外的仓库
392
396
 
393
397
  ### 状态检查对 app 仓库执行完整五项检查
394
398
 
@@ -428,7 +432,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
428
432
  ### 完成后开发会话未开进 worktree
429
433
 
430
434
  - **问题:** 流程结束后开发会话仍停留在工作空间根目录(junction 好的 AI 配置没人加载),agent 在根会话里靠路径翻译干活,回到第一代失败模式
431
- - **修复:** Step 4 交接必须明确"开发会话开在 `<wt_path>`"(新 IDE 窗口 / agent 会话);根会话保留作控制面(worktree 生灭、`cbb update`)
435
+ - **修复:** Step 4 交接必须明确"开发会话开在 `<wt_path>`"(桌面端 = 当前窗口切工作区根;CLI = 新开会话);根会话保留作控制面(worktree 生灭、`cbb update`)
432
436
 
433
437
  ### 用 `git checkout -b` 在创建 worktree 前切分支
434
438
 
@@ -468,8 +472,8 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
468
472
  - 所有仓库分支统一从 `origin/<main>` 创建(`git branch <需求名> ${REMOTE}/${MAIN}`),不依赖本地检出状态(本地模式进行中重跑不受污染)
469
473
  - 严格 Step 3.3 → Step 3.5 顺序(先统一创建分支,再统一创建 worktree;workspace 工作树先建,各应用按序补建)
470
474
  - Step 3.6 junction AI 配置(失败不阻塞,但要报告)
471
- - 所有脚本调用以 `node "<skill_dir>/scripts/<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 缺省由脚本内部从 workspace-config.json 读取,子集用 `--apps` 传入);**执行时 cwd 保持在工作空间根**(`check-env.js` / `parse-config.js` 按 cwd 定位)
472
- - Step 4 交接必须声明"开发会话开在 `<wt_path>`、根会话保留作控制面"
475
+ - 所有脚本调用以 `node "<skill_dir>/scripts/<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 缺省由脚本内部从 CBB-WORKSPACE.json 读取,子集用 `--apps` 传入);**执行时 cwd 保持在工作空间根**(`check-env.js` / `parse-config.js` 按 cwd 定位)
476
+ - Step 4 交接必须声明"开发会话开在 `<wt_path>`(桌面端 = 当前窗口切工作区根,CLI = 新开会话)、空间根路径在案作控制面"
473
477
 
474
478
  ---
475
479
 
@@ -478,7 +482,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
478
482
  | 脚本 | 功能 | 参数 | 退出码 |
479
483
  |------|------|------|--------|
480
484
  | `check-env.js` | 环境探活 | 无 | 0/1/2 |
481
- | `parse-config.js` | 解析 workspace-config.json | 无 | 0/1/2 |
485
+ | `parse-config.js` | 解析 CBB-WORKSPACE.json | 无 | 0/1/2 |
482
486
  | `sync-repos.js` | 同步 .codespace/ 仓库(兜底 clone 时补装提交防线 hook) | ws_root | 0/1/2 |
483
487
  | `check-repos.js` | 状态检查 | ws_root | 0/1/2 |
484
488
  | `update-gitignore.js` | 安全更新 .gitignore | ws_root, branch | 0/1/2 |
@@ -48,7 +48,7 @@ console.log('✅ git OK:', checks.git.out);
48
48
  const insideRepo = tryExec('git rev-parse --is-inside-work-tree');
49
49
  if (!insideRepo.ok || insideRepo.out !== 'true') {
50
50
  console.error('❌ 当前目录不是 Git 仓库');
51
- console.error(' init-worktree 必须在工作空间根目录(包含 workspace-config.json)下执行');
51
+ console.error(' init-worktree 必须在工作空间根目录(包含 CBB-WORKSPACE.json)下执行');
52
52
  process.exit(2);
53
53
  }
54
54
  console.log('✅ 当前目录是 git 仓库');
@@ -36,7 +36,7 @@ if (!wsRoot) {
36
36
  }
37
37
 
38
38
  function loadAppsFromConfig() {
39
- const configPath = path.join(wsRoot, "workspace-config.json");
39
+ const configPath = path.join(wsRoot, "CBB-WORKSPACE.json");
40
40
  if (!fs.existsSync(configPath)) return null;
41
41
  try {
42
42
  const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
@@ -46,7 +46,7 @@ function loadAppsFromConfig() {
46
46
 
47
47
  const apps = loadAppsFromConfig();
48
48
  if (!apps) {
49
- console.error("workspace-config.json missing or apps empty");
49
+ console.error("CBB-WORKSPACE.json missing or apps empty");
50
50
  process.exit(1);
51
51
  }
52
52
 
@@ -25,7 +25,7 @@ if (appsFlagIdx >= 0) {
25
25
  }
26
26
 
27
27
  function loadAppsFromConfig() {
28
- const configPath = path.join(wsRoot, 'workspace-config.json');
28
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
29
29
  if (!fs.existsSync(configPath)) return null;
30
30
  try {
31
31
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
@@ -35,7 +35,7 @@ function loadAppsFromConfig() {
35
35
 
36
36
  const allApps = loadAppsFromConfig();
37
37
  if (!allApps) {
38
- console.error('workspace-config.json missing or apps empty');
38
+ console.error('CBB-WORKSPACE.json missing or apps empty');
39
39
  process.exit(1);
40
40
  }
41
41
 
@@ -46,7 +46,7 @@ const apps = appFilter
46
46
  if (appFilter) {
47
47
  const unknown = [...appFilter].filter(n => !allApps.some(a => a.name === n));
48
48
  if (unknown.length > 0) {
49
- console.error('❌ --apps 中的应用不在 workspace-config.json:' + unknown.join(', '));
49
+ console.error('❌ --apps 中的应用不在 CBB-WORKSPACE.json:' + unknown.join(', '));
50
50
  process.exit(1);
51
51
  }
52
52
  console.log('ℹ️ 应用子集(' + apps.length + '/' + allApps.length + '):' + apps.map(a => a.name).join(', '));
@@ -4,7 +4,7 @@ require('./silence-popup');
4
4
  * cbb-worktree-init 创建 Worktree(自愈清理仅限元数据 prune)
5
5
  *
6
6
  * 用法:node create-worktrees.js <ws_root> <branch>
7
- * (apps 由脚本内部从 <ws_root>/workspace-config.json 读取)
7
+ * (apps 由脚本内部从 <ws_root>/CBB-WORKSPACE.json 读取)
8
8
  *
9
9
  * 行为:
10
10
  * 1. 自愈清理:仅 git worktree prune(元数据),**绝不删除任何物理目录**
@@ -41,7 +41,7 @@ if (appsFlagIdx >= 0) {
41
41
  }
42
42
 
43
43
  function loadAppsFromConfig() {
44
- const configPath = path.join(wsRoot, 'workspace-config.json');
44
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
45
45
  if (!fs.existsSync(configPath)) return null;
46
46
  try {
47
47
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
@@ -51,7 +51,7 @@ function loadAppsFromConfig() {
51
51
 
52
52
  const allApps = loadAppsFromConfig();
53
53
  if (!allApps) {
54
- console.error('❌ workspace-config.json 缺失或 apps 为空');
54
+ console.error('❌ CBB-WORKSPACE.json 缺失或 apps 为空');
55
55
  process.exit(1);
56
56
  }
57
57
 
@@ -62,7 +62,7 @@ const apps = appFilter
62
62
  if (appFilter) {
63
63
  const unknown = [...appFilter].filter(n => !allApps.some(a => a.name === n));
64
64
  if (unknown.length > 0) {
65
- console.error('❌ --apps 中的应用不在 workspace-config.json:' + unknown.join(', '));
65
+ console.error('❌ --apps 中的应用不在 CBB-WORKSPACE.json:' + unknown.join(', '));
66
66
  process.exit(1);
67
67
  }
68
68
  console.log('ℹ️ 应用子集(' + apps.length + '/' + allApps.length + '):' + apps.map(a => a.name).join(', '));
@@ -5,8 +5,8 @@ require('./silence-popup');
5
5
  * 唯一真源:cbb/worktrees/_shared/scripts/find-workspace-root.js
6
6
  * 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / extend / close / push)。
7
7
  *
8
- * 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 workspace-config.json 副本干扰)
9
- * 兜底:当前目录含 workspace-config.json
8
+ * 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 CBB-WORKSPACE.json 副本干扰)
9
+ * 兜底:当前目录含 CBB-WORKSPACE.json
10
10
  *
11
11
  * 退出码:
12
12
  * 0 - 定位成功,输出 WS_ROOT 绝对路径
@@ -44,19 +44,19 @@ if (worktreeList.ok) {
44
44
  }
45
45
  }
46
46
 
47
- // 兜底:当前目录含 workspace-config.json
47
+ // 兜底:当前目录含 CBB-WORKSPACE.json
48
48
  if (!wsRoot) {
49
49
  const cwd = process.cwd();
50
- if (fs.existsSync(path.join(cwd, 'workspace-config.json'))) {
50
+ if (fs.existsSync(path.join(cwd, 'CBB-WORKSPACE.json'))) {
51
51
  wsRoot = cwd;
52
52
  }
53
53
  }
54
54
 
55
55
  // 校验
56
- if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'workspace-config.json'))) {
56
+ if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'CBB-WORKSPACE.json'))) {
57
57
  console.error('❌ 未找到工作空间根目录');
58
- console.error(' 原因:git worktree list 失败且当前目录无 workspace-config.json');
59
- console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含 workspace-config.json)下执行本技能');
58
+ console.error(' 原因:git worktree list 失败且当前目录无 CBB-WORKSPACE.json');
59
+ console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含 CBB-WORKSPACE.json)下执行本技能');
60
60
  process.exit(1);
61
61
  }
62
62
 
@@ -20,7 +20,7 @@ const HOOK_FILE = 'pre-commit';
20
20
  const BACKUP_SUFFIX = '.cbb-backup';
21
21
 
22
22
  // 与 cbb/lib/utils/githook.js 的 buildPreCommitSource() 输出完全一致(构建时注入)
23
- const PRE_COMMIT_SOURCE = "#!/usr/bin/env node\n// managed-by-cbb v1 —— 分支感知提交防线(ADR 0002)\n// main 上:workspace 仓库只放行控制面白名单,应用仓库全拦;非 main 一律放行。\n// 绕过逃生口仅限用户显式 git commit --no-verify。\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nfunction run(cmd) {\n try { return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim(); }\n catch (e) { return null; }\n}\nconst branch = run('git branch --show-current') || '';\n// 主干名:优先远端 HEAD 指向;探测失败按本地 main/master 存在性回退\nlet main = null;\nconst remotes = run('git remote');\nif (remotes) {\n const r = remotes.split(/\\r?\\n/)[0];\n const sym = run('git symbolic-ref \"refs/remotes/' + r + '/HEAD\"');\n if (sym) main = sym.replace('refs/remotes/' + r + '/', '');\n}\nif (!main) {\n if (run('git rev-parse --verify --quiet refs/heads/main')) main = 'main';\n else if (run('git rev-parse --verify --quiet refs/heads/master')) main = 'master';\n}\n// 非主干(含 detached / 探测失败)→ 放行\nif (!main || branch !== main) process.exit(0);\n\n// 主干上的提交:收集 staged 变更(空提交放行)\nconst staged = run('git diff --cached --name-only') || '';\nconst files = staged.split(/\\r?\\n/).filter(Boolean);\nif (files.length === 0) process.exit(0);\n\n// 仓库类型:workspace 仓库 = 检出含 workspace-config.json\nconst isWorkspace = fs.existsSync('workspace-config.json');\n\nfunction deny(bad) {\n console.error('[cbb-guard] 主干上拦截载荷提交(ADR 0002):');\n bad.forEach(f => console.error(' ' + f));\n console.error('需求载荷须在需求分支上提交:本地模式先 git checkout -b <需求名>;worktree 模式在 .worktrees/ 工作树内提交。');\n console.error('控制面白名单:workspace-config.json / .gitignore / AGENTS.md / openspec/config.yaml / openspec/schemas/** / .cbb/**');\n console.error('如确需在主干提交,须由用户显式 git commit --no-verify。');\n process.exit(1);\n}\n\nif (isWorkspace) {\n const EXACT = new Set(['workspace-config.json', '.gitignore', 'AGENTS.md', 'openspec/config.yaml']);\n const PREFIXES = ['openspec/schemas/', '.cbb/'];\n const bad = files.filter(f => !EXACT.has(f) && !PREFIXES.some(p => f.indexOf(p) === 0));\n if (bad.length) deny(bad);\n} else {\n deny(files);\n}\nprocess.exit(0);\n";
23
+ const PRE_COMMIT_SOURCE = "#!/usr/bin/env node\n// managed-by-cbb v1 —— 分支感知提交防线(ADR 0002)\n// main 上:workspace 仓库只放行控制面白名单,应用仓库全拦;非 main 一律放行。\n// 绕过逃生口仅限用户显式 git commit --no-verify。\nconst { execSync } = require('child_process');\nconst fs = require('fs');\nfunction run(cmd) {\n try { return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim(); }\n catch (e) { return null; }\n}\nconst branch = run('git branch --show-current') || '';\n// 主干名:优先远端 HEAD 指向;探测失败按本地 main/master 存在性回退\nlet main = null;\nconst remotes = run('git remote');\nif (remotes) {\n const r = remotes.split(/\\r?\\n/)[0];\n const sym = run('git symbolic-ref \"refs/remotes/' + r + '/HEAD\"');\n if (sym) main = sym.replace('refs/remotes/' + r + '/', '');\n}\nif (!main) {\n if (run('git rev-parse --verify --quiet refs/heads/main')) main = 'main';\n else if (run('git rev-parse --verify --quiet refs/heads/master')) main = 'master';\n}\n// 非主干(含 detached / 探测失败)→ 放行\nif (!main || branch !== main) process.exit(0);\n\n// 主干上的提交:收集 staged 变更(空提交放行)\nconst staged = run('git diff --cached --name-only') || '';\nconst files = staged.split(/\\r?\\n/).filter(Boolean);\nif (files.length === 0) process.exit(0);\n\n// 仓库类型:workspace 仓库 = 检出含 CBB-WORKSPACE.json(或旧名,改名过渡期识别)\nconst isWorkspace = fs.existsSync('CBB-WORKSPACE.json') || fs.existsSync('workspace-config.json');\n\nfunction deny(bad) {\n console.error('[cbb-guard] 主干上拦截载荷提交(ADR 0002):');\n bad.forEach(f => console.error(' ' + f));\n console.error('需求载荷须在需求分支上提交:本地模式先 git checkout -b <需求名>;worktree 模式在 .worktrees/ 工作树内提交。');\n console.error('控制面白名单:CBB-WORKSPACE.json / .gitignore / AGENTS.md / openspec/config.yaml / openspec/schemas/** / .cbb/**');\n console.error('如确需在主干提交,须由用户显式 git commit --no-verify。');\n process.exit(1);\n}\n\nif (isWorkspace) {\n // 旧名仅放行删除条目:更名迁移提交(git mv)会产生旧名删除 + 新名新增两条\n const EXACT = new Set(['CBB-WORKSPACE.json', 'workspace-config.json', '.gitignore', 'AGENTS.md', 'openspec/config.yaml']);\n const PREFIXES = ['openspec/schemas/', '.cbb/'];\n const bad = files.filter(f => !EXACT.has(f) && !PREFIXES.some(p => f.indexOf(p) === 0));\n if (bad.length) deny(bad);\n} else {\n deny(files);\n}\nprocess.exit(0);\n";
24
24
 
25
25
  function isCbbHookContent(content) {
26
26
  return typeof content === 'string' && content.includes(HOOK_MARKER);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  require('./silence-popup');
3
3
  /**
4
- * cbb-worktree-init 读取并校验 workspace-config.json
4
+ * cbb-worktree-init 读取并校验 CBB-WORKSPACE.json
5
5
  *
6
6
  * 退出码:
7
7
  * 0 - 成功,输出应用列表 JSON
@@ -15,10 +15,10 @@ require('./silence-popup');
15
15
  const fs = require('fs');
16
16
  const path = require('path');
17
17
 
18
- const configPath = path.join(process.cwd(), 'workspace-config.json');
18
+ const configPath = path.join(process.cwd(), 'CBB-WORKSPACE.json');
19
19
 
20
20
  if (!fs.existsSync(configPath)) {
21
- console.error('❌ workspace-config.json 不存在');
21
+ console.error('❌ CBB-WORKSPACE.json 不存在');
22
22
  console.error(' 请先在 cbb setup 阶段创建,或手动配置');
23
23
  console.error('---');
24
24
  console.error('CONFIG_MISSING');
@@ -29,7 +29,7 @@ let config;
29
29
  try {
30
30
  config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
31
31
  } catch (e) {
32
- console.error('❌ workspace-config.json 解析失败:', e.message);
32
+ console.error('❌ CBB-WORKSPACE.json 解析失败:', e.message);
33
33
  console.error(' 请检查 JSON 格式');
34
34
  console.error('---');
35
35
  console.error('CONFIG_INVALID');
@@ -38,8 +38,8 @@ try {
38
38
 
39
39
  const apps = config.apps || [];
40
40
  if (apps.length === 0) {
41
- console.error('❌ workspace-config.json 中 apps 为空');
42
- console.error(' 请编辑 workspace-config.json 配置关联应用');
41
+ console.error('❌ CBB-WORKSPACE.json 中 apps 为空');
42
+ console.error(' 请编辑 CBB-WORKSPACE.json 配置关联应用');
43
43
  console.error('---');
44
44
  console.error('CONFIG_EMPTY');
45
45
  process.exit(2);
@@ -61,7 +61,7 @@ for (const app of apps) {
61
61
  }
62
62
  }
63
63
 
64
- console.log('✅ workspace-config.json 有效(' + apps.length + ' 个应用)');
64
+ console.log('✅ CBB-WORKSPACE.json 有效(' + apps.length + ' 个应用)');
65
65
  console.log('---');
66
66
  console.log('CONFIG_OK', JSON.stringify(apps));
67
67
  process.exit(0);
@@ -20,7 +20,7 @@ const fs = require('fs');
20
20
  const path = require('path');
21
21
 
22
22
  function loadAppsFromConfig(wsRoot) {
23
- const configPath = path.join(wsRoot, 'workspace-config.json');
23
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
24
24
  if (!fs.existsSync(configPath)) return null;
25
25
  try {
26
26
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
@@ -40,7 +40,7 @@ function executePush(opts) {
40
40
  const branch = opts.branch;
41
41
  const apps = opts.apps != null ? opts.apps : loadAppsFromConfig(wsRoot);
42
42
  if (apps == null) {
43
- throw new Error('workspace-config.json missing or apps empty');
43
+ throw new Error('CBB-WORKSPACE.json missing or apps empty');
44
44
  }
45
45
 
46
46
  const results = [];
@@ -68,7 +68,7 @@ function main() {
68
68
 
69
69
  const apps = loadAppsFromConfig(wsRoot);
70
70
  if (apps == null) {
71
- console.error('❌ workspace-config.json 缺失或 apps 为空');
71
+ console.error('❌ CBB-WORKSPACE.json 缺失或 apps 为空');
72
72
  process.exit(1);
73
73
  }
74
74
 
@@ -4,7 +4,7 @@ require('./silence-popup');
4
4
  * cbb-worktree-init 同步 .codespace/ 仓库
5
5
  *
6
6
  * 用法:node sync-repos.js <ws_root>
7
- * - ws_root: 工作空间根绝对路径(apps 从 <ws_root>/workspace-config.json 读取)
7
+ * - ws_root: 工作空间根绝对路径(apps 从 <ws_root>/CBB-WORKSPACE.json 读取)
8
8
  *
9
9
  * 对每个 app:
10
10
  * - .codespace/<name>/.git 存在 → fetch --all
@@ -29,23 +29,23 @@ if (!wsRoot) {
29
29
  }
30
30
 
31
31
  /**
32
- * 从 workspace-config.json 读取 apps(避免 shell 字符串传递中的转义问题)
32
+ * 从 CBB-WORKSPACE.json 读取 apps(避免 shell 字符串传递中的转义问题)
33
33
  */
34
34
  function loadAppsFromConfig() {
35
- const configPath = path.join(wsRoot, 'workspace-config.json');
35
+ const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
36
36
  if (!fs.existsSync(configPath)) {
37
- console.error('❌ workspace-config.json 不存在:' + configPath);
37
+ console.error('❌ CBB-WORKSPACE.json 不存在:' + configPath);
38
38
  return null;
39
39
  }
40
40
  try {
41
41
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
42
42
  if (!config.apps || !Array.isArray(config.apps) || config.apps.length === 0) {
43
- console.error('❌ workspace-config.json 中 apps 为空');
43
+ console.error('❌ CBB-WORKSPACE.json 中 apps 为空');
44
44
  return null;
45
45
  }
46
46
  return config.apps;
47
47
  } catch (e) {
48
- console.error('❌ workspace-config.json 解析失败:' + e.message);
48
+ console.error('❌ CBB-WORKSPACE.json 解析失败:' + e.message);
49
49
  return null;
50
50
  }
51
51
  }
@@ -36,7 +36,7 @@ node "<skill_dir>/scripts/<name>.js" <参数>
36
36
  ```
37
37
 
38
38
  > - `<skill_dir>` = 本 SKILL.md 所在目录的绝对路径(AI 从读取路径即可推出)
39
- > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `workspace-config.json` 与 git 仓库
39
+ > - **cwd 必须保持在工作空间根目录**:脚本按 cwd 定位 `CBB-WORKSPACE.json` 与 git 仓库
40
40
  > - 不要用 `./scripts/...` 裸相对路径(AI 的 cwd 不是技能目录,会解析失败)
41
41
 
42
42
  脚本输出:
@@ -54,9 +54,9 @@ node "<skill_dir>/scripts/<name>.js" <参数>
54
54
 
55
55
  | 场景 | 判据 | 策略 |
56
56
  |------|------|------|
57
- | **A. cbb 工作空间根** | cwd(或其 git 顶层)含 `workspace-config.json`;`find-workspace-root.js` 退出码 0 | 走 **Step 1 → 6** 的跨 worktree 批量流程 |
57
+ | **A. cbb 工作空间根** | cwd(或其 git 顶层)含 `CBB-WORKSPACE.json`;`find-workspace-root.js` 退出码 0 | 走 **Step 1 → 6** 的跨 worktree 批量流程 |
58
58
  | **B. worktree 内** | cwd 命中 `<ws_root>/.worktrees/worktree-<需求名>/` | 用 cwd 反推 `<需求名>`,走 **Step 1 → 6** 批量流程 |
59
- | **C. 普通 git 仓库** | 在 git 仓库内,但无 `workspace-config.json`(`find-workspace-root.js` 退出码 1) | **降级为单仓库提交推送**:不调 worktree 脚本,按常规 `git add -u` → 向用户询问 commit 信息 → `git commit` → `git push`(保留本 skill 的"必问 commit 信息"约束) |
59
+ | **C. 普通 git 仓库** | 在 git 仓库内,但无 `CBB-WORKSPACE.json`(`find-workspace-root.js` 退出码 1) | **降级为单仓库提交推送**:不调 worktree 脚本,按常规 `git add -u` → 向用户询问 commit 信息 → `git commit` → `git push`(保留本 skill 的"必问 commit 信息"约束) |
60
60
  | **D. 非 git 目录** | `git rev-parse --is-inside-work-tree` 失败 | 说明"当前目录不是 git 仓库",终止,不做任何操作 |
61
61
 
62
62
  **判场景与定位(A/B 场景):**
@@ -80,7 +80,7 @@ node "<skill_dir>/scripts/find-workspace-root.js"
80
80
  5. `git push`(无 upstream 时先询问用户是否 `-u`)
81
81
  6. 汇报结果;**不要**提及 worktree 批量流程
82
82
 
83
- > 场景 C 是兜底:让"提交代码"在普通仓库里也能正常完成,而不是因找不到 `workspace-config.json` 报错。
83
+ > 场景 C 是兜底:让"提交代码"在普通仓库里也能正常完成,而不是因找不到 `CBB-WORKSPACE.json` 报错。
84
84
 
85
85
  ---
86
86
 
@@ -123,7 +123,7 @@ AI agent 在执行真实 commit 前**必须**在对话中向用户确认 commit
123
123
 
124
124
  ```
125
125
  检测到以下 worktree 仓库有未提交改动:
126
- - workspace: 5 个文件(workspace-config.json, openspec/changes/foo/...)
126
+ - workspace: 5 个文件(CBB-WORKSPACE.json, openspec/changes/foo/...)
127
127
  - ep-foo-app: 12 个文件
128
128
  - ep-bar-app: 3 个文件
129
129
 
@@ -284,7 +284,7 @@ node "<skill_dir>/scripts/make-mr-urls.js" "<ws_root>" "<branch>" "<target>" --o
284
284
  | **任何触发** | **先做 Step 0 场景识别**,再决定策略 |
285
285
  | 场景 A:cwd 在 cbb 工作空间根 | find-workspace-root 成功 → 多个 worktree 时让用户选 |
286
286
  | 场景 B:cwd 在 worktree 内 | 自动用 cwd 反推分支,扫描后进入询问 commit 信息 |
287
- | 场景 C:cwd 在普通 git 仓库(无 workspace-config.json) | **降级为单仓库提交推送**,不调用 worktree 脚本 |
287
+ | 场景 C:cwd 在普通 git 仓库(无 CBB-WORKSPACE.json) | **降级为单仓库提交推送**,不调用 worktree 脚本 |
288
288
  | 场景 D:cwd 非 git 目录 | 说明情况并终止,不做任何操作 |
289
289
  | commit 信息缺失 | 必须询问用户;禁止自动生成(可基于 apply task 上下文给建议) |
290
290
  | 多仓库需不同 commit 信息 | 用 `--per-repo "ep-foo:m1;ep-bar:m2"`,必须由用户逐条提供 |
@@ -330,7 +330,7 @@ node "<skill_dir>/scripts/make-mr-urls.js" "<ws_root>" "<branch>" "<target>" --o
330
330
 
331
331
  ### 多仓库用同一条 commit 信息
332
332
 
333
- - **问题:** workspace 改了 workspace-config.json,ep-foo-app 改了 Java 代码,硬塞同一条 "feat: 实现 XX" 信息不准确
333
+ - **问题:** workspace 改了 CBB-WORKSPACE.json,ep-foo-app 改了 Java 代码,硬塞同一条 "feat: 实现 XX" 信息不准确
334
334
  - **修复:** 用 `--per-repo` 模式,让用户逐仓库提供
335
335
 
336
336
  ### push 失败时跳过失败仓库直接继续
@@ -97,10 +97,10 @@ function isGitRepo(p) {
97
97
  return fs.existsSync(path.join(p, '.git'));
98
98
  }
99
99
 
100
- /** 读取 workspace-config.json 的 app 名列表(旧布局兼容判定用;缺失返回 []) */
100
+ /** 读取 CBB-WORKSPACE.json 的 app 名列表(旧布局兼容判定用;缺失返回 []) */
101
101
  function loadAppNames(wsRoot) {
102
102
  try {
103
- const cfg = JSON.parse(fs.readFileSync(path.join(wsRoot, 'workspace-config.json'), 'utf-8'));
103
+ const cfg = JSON.parse(fs.readFileSync(path.join(wsRoot, 'CBB-WORKSPACE.json'), 'utf-8'));
104
104
  return Array.isArray(cfg.apps) ? cfg.apps.map(a => a.name).filter(Boolean) : [];
105
105
  } catch (e) {
106
106
  return [];
@@ -5,8 +5,8 @@ require('./silence-popup');
5
5
  * 唯一真源:cbb/worktrees/_shared/scripts/find-workspace-root.js
6
6
  * 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / extend / close / push)。
7
7
  *
8
- * 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 workspace-config.json 副本干扰)
9
- * 兜底:当前目录含 workspace-config.json
8
+ * 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 CBB-WORKSPACE.json 副本干扰)
9
+ * 兜底:当前目录含 CBB-WORKSPACE.json
10
10
  *
11
11
  * 退出码:
12
12
  * 0 - 定位成功,输出 WS_ROOT 绝对路径
@@ -44,19 +44,19 @@ if (worktreeList.ok) {
44
44
  }
45
45
  }
46
46
 
47
- // 兜底:当前目录含 workspace-config.json
47
+ // 兜底:当前目录含 CBB-WORKSPACE.json
48
48
  if (!wsRoot) {
49
49
  const cwd = process.cwd();
50
- if (fs.existsSync(path.join(cwd, 'workspace-config.json'))) {
50
+ if (fs.existsSync(path.join(cwd, 'CBB-WORKSPACE.json'))) {
51
51
  wsRoot = cwd;
52
52
  }
53
53
  }
54
54
 
55
55
  // 校验
56
- if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'workspace-config.json'))) {
56
+ if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'CBB-WORKSPACE.json'))) {
57
57
  console.error('❌ 未找到工作空间根目录');
58
- console.error(' 原因:git worktree list 失败且当前目录无 workspace-config.json');
59
- console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含 workspace-config.json)下执行本技能');
58
+ console.error(' 原因:git worktree list 失败且当前目录无 CBB-WORKSPACE.json');
59
+ console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含 CBB-WORKSPACE.json)下执行本技能');
60
60
  process.exit(1);
61
61
  }
62
62
 
@@ -59,10 +59,10 @@ function isGitRepo(p) {
59
59
  }
60
60
  }
61
61
 
62
- /** 读取 workspace-config.json 的 app 名列表(旧布局兼容判定用;缺失返回 []) */
62
+ /** 读取 CBB-WORKSPACE.json 的 app 名列表(旧布局兼容判定用;缺失返回 []) */
63
63
  function loadAppNames(wsRoot) {
64
64
  try {
65
- const cfg = JSON.parse(fs.readFileSync(path.join(wsRoot, 'workspace-config.json'), 'utf-8'));
65
+ const cfg = JSON.parse(fs.readFileSync(path.join(wsRoot, 'CBB-WORKSPACE.json'), 'utf-8'));
66
66
  return Array.isArray(cfg.apps) ? cfg.apps.map(a => a.name).filter(Boolean) : [];
67
67
  } catch (e) {
68
68
  return [];
@@ -1,5 +1,5 @@
1
1
  {
2
- "_comment": "AI 开发工作空间配置样例(请勿修改本文件,复制为工作空间根目录的 workspace-config.json 后编辑使用)。apps 数组中每个对象需包含:name(应用名,同时作为 .codespace/ 子目录名)、repo(Git 仓库地址,支持 SSH 或 HTTPS)、side(仓库类型,'front' 表示前端工程,'back' 表示后端工程,'mixed' 表示前后端混合工程);可选 desc(该应用的职责描述,便于人与 AI 理解应用分工)。",
2
+ "_comment": "AI 开发工作空间配置样例(请勿修改本文件,复制为工作空间根目录的 CBB-WORKSPACE.json 后编辑使用)。apps 数组中每个对象需包含:name(应用名,同时作为 .codespace/ 子目录名)、repo(Git 仓库地址,支持 SSH 或 HTTPS)、side(仓库类型,'front' 表示前端工程,'back' 表示后端工程,'mixed' 表示前后端混合工程);可选 desc(该应用的职责描述,便于人与 AI 理解应用分工)。",
3
3
  "apps":
4
4
  [
5
5
  {