@jspg-ai/coding-bb 0.0.2-beta.28 → 0.0.3-beta.1

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.
@@ -87,8 +87,8 @@ function renderLines(state) {
87
87
  const lines = [];
88
88
 
89
89
  if (header) {
90
- lines.push(c('bold', header));
91
- lines.push(c('gray', '─'.repeat(48)));
90
+ lines.push(' ' + c('bold', header));
91
+ lines.push(' ' + c('gray', '─'.repeat(48)));
92
92
  }
93
93
 
94
94
  if (items.length === 0) {
@@ -99,21 +99,21 @@ function renderLines(state) {
99
99
  const isSelected = selected.has(i);
100
100
  const cursorMark = isCursor ? c('cyan', '❯') : ' ';
101
101
  const checkMark = isSelected ? c('green', '☑') : c('gray', '☐');
102
- const raw = ` ${cursorMark} ${checkMark} ${item.label}`;
102
+ const raw = ` ${cursorMark} ${checkMark} ${item.label}`;
103
103
  // 当前行整体加粗 + 反转视频:浅色终端也能识别
104
104
  const line = isCursor && COLOR_ENABLED
105
105
  ? `${COLOR.bold}${COLOR.reverse}${raw}${COLOR.reset}`
106
106
  : (isCursor ? c('bold', raw) : raw);
107
107
  lines.push(line);
108
108
  if (item.hint) {
109
- lines.push(c('gray', ' ' + item.hint));
109
+ lines.push(c('gray', ' ' + item.hint));
110
110
  }
111
111
  });
112
112
  }
113
113
 
114
114
  if (footer) {
115
115
  lines.push('');
116
- lines.push(c('gray', footer));
116
+ lines.push(' ' + c('gray', footer));
117
117
  }
118
118
 
119
119
  return lines;
@@ -325,21 +325,21 @@ function promptCheckboxFallback({ items, header, footer, preSelected }) {
325
325
  };
326
326
 
327
327
  // 输出列表(无光标、无高亮,逐项标号)
328
- console.log(c('bold', header) || '');
329
- console.log(c('gray', '─'.repeat(48)));
328
+ console.log(' ' + (c('bold', header) || ''));
329
+ console.log(' ' + c('gray', '─'.repeat(48)));
330
330
  items.forEach((item, i) => {
331
- console.log(` ${c('cyan', String(i + 1) + '.')} ${item.label}`);
332
- if (item.hint) console.log(c('gray', ' ' + item.hint));
331
+ console.log(` ${c('cyan', String(i + 1) + '.')} ${item.label}`);
332
+ if (item.hint) console.log(c('gray', ' ' + item.hint));
333
333
  });
334
334
  console.log('');
335
- if (footer) console.log(c('gray', footer));
335
+ if (footer) console.log(' ' + c('gray', footer));
336
336
 
337
337
  const rl = readline.createInterface({
338
338
  input: process.stdin,
339
339
  output: process.stdout,
340
340
  });
341
341
 
342
- rl.question(`请输入编号(多选用逗号分隔): `, (answer) => {
342
+ rl.question(` 请输入编号(多选用逗号分隔): `, (answer) => {
343
343
  rl.close();
344
344
  const selected = parseBulkInput(answer, items.length);
345
345
  resolve(selected);
@@ -37,34 +37,51 @@ const LOG_STYLES = {
37
37
 
38
38
  function log(msg, type = 'info') {
39
39
  const s = LOG_STYLES[type] || LOG_STYLES.info;
40
- const text = `${s.icon} ${msg}`;
40
+ const text = ` ${s.icon} ${msg}`;
41
41
  console.log(s.color ? c(s.color, text) : text);
42
42
  }
43
43
 
44
44
  /** 输出一行分节标题(带图标 + 颜色),紧跟一行灰色分隔线 */
45
45
  function section(icon, title) {
46
46
  console.log('');
47
- console.log(c('bold', `${icon} ${title}`));
48
- console.log(c('gray', '─'.repeat(48)));
47
+ console.log(' ' + c('bold', `${icon} ${title}`));
48
+ console.log(' ' + c('gray', '─'.repeat(48)));
49
+ }
50
+
51
+ /** 单字符视觉宽度:CJK / 全角按 2 列计,其余按 1 列 */
52
+ function charWidth(ch) {
53
+ const cp = ch.codePointAt(0);
54
+ const wide =
55
+ (cp >= 0x1100 && cp <= 0x115f) ||
56
+ cp === 0x2329 || cp === 0x232a ||
57
+ (cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||
58
+ (cp >= 0xac00 && cp <= 0xd7a3) ||
59
+ (cp >= 0xf900 && cp <= 0xfaff) ||
60
+ (cp >= 0xfe30 && cp <= 0xfe6f) ||
61
+ (cp >= 0xff00 && cp <= 0xff60) ||
62
+ (cp >= 0xffe0 && cp <= 0xffe6);
63
+ return wide ? 2 : 1;
49
64
  }
50
65
 
51
66
  /** 视觉宽度:CJK / 全角字符按 2 列计,其余按 1 列(终端对齐用) */
52
67
  function visualWidth(text) {
53
68
  let w = 0;
69
+ for (const ch of String(text)) w += charWidth(ch);
70
+ return w;
71
+ }
72
+
73
+ /** 按视觉宽度截断文本(超出补 …),用于防止进度行折行残留 */
74
+ function sliceVisual(text, maxWidth) {
75
+ if (visualWidth(text) <= maxWidth) return text;
76
+ let w = 0;
77
+ let out = '';
54
78
  for (const ch of String(text)) {
55
- const cp = ch.codePointAt(0);
56
- const wide =
57
- (cp >= 0x1100 && cp <= 0x115f) ||
58
- cp === 0x2329 || cp === 0x232a ||
59
- (cp >= 0x2e80 && cp <= 0xa4cf && cp !== 0x303f) ||
60
- (cp >= 0xac00 && cp <= 0xd7a3) ||
61
- (cp >= 0xf900 && cp <= 0xfaff) ||
62
- (cp >= 0xfe30 && cp <= 0xfe6f) ||
63
- (cp >= 0xff00 && cp <= 0xff60) ||
64
- (cp >= 0xffe0 && cp <= 0xffe6);
65
- w += wide ? 2 : 1;
79
+ const cw = charWidth(ch);
80
+ if (w + cw > maxWidth - 1) return out + '…';
81
+ out += ch;
82
+ w += cw;
66
83
  }
67
- return w;
84
+ return out;
68
85
  }
69
86
 
70
87
  /** 按视觉宽度右补空格(中文标签对齐用) */
@@ -96,7 +113,11 @@ function progress(label, opts = {}) {
96
113
 
97
114
  const render = () => {
98
115
  const sec = elapsed();
99
- const value = sec > 0 ? `${text} ${c('gray', sec + 's')}` : text;
116
+ // 按终端宽度截断内容,防止折行后 \x1b[2K 清不净留下残影
117
+ const cols = stream.columns || 0;
118
+ const maxText = cols > 0 ? Math.max(16, cols - 22) : 0;
119
+ const shown = maxText > 0 ? sliceVisual(text, maxText) : text;
120
+ const value = sec > 0 ? `${shown} ${c('gray', sec + 's')}` : shown;
100
121
  stream.write(`\r\x1b[2K${head(SPINNER_FRAMES[frame++ % SPINNER_FRAMES.length])} ${value}`);
101
122
  };
102
123
 
@@ -146,6 +167,7 @@ module.exports = {
146
167
  log,
147
168
  section,
148
169
  visualWidth,
170
+ sliceVisual,
149
171
  padVisual,
150
172
  progress,
151
173
  step,
@@ -9,7 +9,7 @@ tags: [worktree, cleanup, worktree, git-worktree]
9
9
 
10
10
  ## 重要:第一步必须用 Read 工具直接打开 SKILL.md
11
11
 
12
- **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md。这些命令在 Qoder Windows PowerShell 沙箱中经常失败。
12
+ **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md。这些命令在 Agent 运行环境(Qoder Windows PowerShell 等)中经常失败。
13
13
 
14
14
  **直接路径**:
15
15
  - Qoder 适配器:`.qoder/skills/cbb-worktree-close/SKILL.md`
@@ -9,7 +9,7 @@ tags: [worktree, isolation, worktree, git-worktree]
9
9
 
10
10
  ## 重要:第一步必须用 Read 工具直接打开 SKILL.md
11
11
 
12
- **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md 是否存在。**这些命令在 Qoder Windows PowerShell 沙箱中经常失败**(如 `head` 不存在、stderr 重定向无效等)。
12
+ **禁止**用 `ls` / `find` / `cat` / `head` / `grep` 等 bash 命令搜索 SKILL.md 是否存在。**这些命令在 Agent 运行环境(Qoder Windows PowerShell 等)中经常失败**(如 `head` 不存在、stderr 重定向无效等)。
13
13
 
14
14
  **直接路径**:
15
15
  - Qoder 适配器:`.qoder/skills/cbb-worktree-init/SKILL.md`
@@ -17,7 +17,7 @@ tags: [worktree, isolation, worktree, git-worktree]
17
17
 
18
18
  **第一步**:
19
19
  1. 用 Read 工具直接打开 `.qoder/skills/cbb-worktree-init/SKILL.md`(或 `.claude/skills/...`)
20
- 2. 按 SKILL.md 的 Step 0 → 1 → 2 → 3 → 4 → 5 → 6 顺序执行
20
+ 2. 按 SKILL.md 的 Step 0 → 1 → 2 → 3 → 4 顺序执行
21
21
  3. 每次调用 Node.js 脚本时,使用**绝对路径**(避免依赖相对路径):
22
22
  ```
23
23
  node "D:\workspace\<用户工作空间>\.qoder\skills\cbb-worktree-init\scripts\<name>.js" <参数>
@@ -29,9 +29,7 @@ tags: [worktree, isolation, worktree, git-worktree]
29
29
  - `check-repos.js`:`<ws_root>`
30
30
  - `create-branches.js`:`<ws_root> <branch>`
31
31
  - `update-gitignore.js`:`<ws_root> <branch>`
32
- - `create-worktrees.js`:`<ws_root> <branch>`
33
- - `install-ai.js`:`<wt_path>`
34
- - `auto-open.js`:`<wt_path>`
32
+ - `create-worktrees.js`:`<ws_root> <branch>`
35
33
 
36
34
  ## Input
37
35
 
@@ -42,14 +40,12 @@ tags: [worktree, isolation, worktree, git-worktree]
42
40
  1. Step 0:环境探活 + 解析 workspace-config.json
43
41
  2. Step 1:同步 .codespace/ 仓库(fetch --all)
44
42
  3. Step 2:状态检查(5 项 / 3 项分级)
45
- 4. Step 3:创建分支(workspace HEAD,app 从 origin/master
46
- 5. Step 4:创建 worktree(workspace + 嵌套 app)
47
- 6. Step 5:在 worktree 中安装 AI 配置(cbbm init -y)
48
- 7. Step 6:环境感知 + 进入工作目录
43
+ 4. Step 3:创建分支 → 推送 upstream → 创建 worktree(workspace + 嵌套 app)
44
+ 5. Step 4:收尾与交接(继续当前会话,声明目录纪律)
49
45
 
50
46
  ## 关键 Guardrails
51
47
 
52
48
  - workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)由 git worktree 自动 checkout——**禁止 cp / clone / symlink “带过来”**
53
49
  - 必须用 `git branch` 而非 `git checkout -b`(分支不能同时在主目录与 worktree 检出)
54
- - 沙箱内 node 不可用时 fail-fast:终止流程并提示用户到系统终端重试
50
+ - 运行环境 node 不可用时 fail-fast:终止流程并提示用户到系统终端重试
55
51
  - **不要试图搜索 SKILL.md**——直接用 Read 工具打开
@@ -414,7 +414,7 @@ git -C "<ws_root>" worktree list
414
414
  - 删除工作空间根目录的 AI 配置目录(`.claude/`、`.qoder/`、`.cbb/` 等源目录)
415
415
  - 用 `AskUserQuestion` 收集自由文本(分支名等直接对话提问)
416
416
  - 手动改任何仓库的 `.gitignore`(关闭流程不碰它)
417
- - 沙箱内 node 不可用时强行继续 → 改为 fail-fast 提示用户
417
+ - 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
418
418
 
419
419
  ### 必须执行
420
420
 
@@ -34,7 +34,7 @@ const checks = {};
34
34
  // ── 必检:git ─────────────────────────────────────────
35
35
  checks.git = tryExec('git --version');
36
36
  if (!checks.git.ok) {
37
- console.error('❌ git 启动失败(可能是 Qoder 沙箱 DLL 问题 0xc0000142)');
37
+ console.error('❌ git 启动失败(可能是 Agent 运行环境 DLL 问题 0xc0000142)');
38
38
  console.error(' 解决方案:到系统终端重新执行本技能');
39
39
  process.exit(1);
40
40
  }
@@ -57,12 +57,12 @@ if (!checks.node.ok) {
57
57
  console.log('✅ node OK:', checks.node.out);
58
58
  }
59
59
 
60
- // ── 沙箱检测 ─────────────────────────────────────────
60
+ // ── 运行环境检测 ─────────────────────────────────────────
61
61
  const inWorktree = !!(process.env.QODER_AGENT || process.env.QODER_WORKTREE);
62
62
  if (inWorktree) {
63
- console.log('🛡️ Qoder 沙箱环境:移除 worktree 时如遇 IDE 锁,将降级处理');
63
+ console.log('🛡️ Qoder Agent 运行环境:移除 worktree 时如遇 IDE 锁,将降级处理');
64
64
  } else {
65
- console.log('✅ 非沙箱环境');
65
+ console.log('✅ 系统终端环境');
66
66
  }
67
67
 
68
68
  const summary = {
@@ -28,7 +28,7 @@ metadata:
28
28
 
29
29
  ## 调用脚本的统一方式
30
30
 
31
- **重要**:所有脚本必须用**绝对路径**调用。`./scripts/...` 相对路径在 Qoder 沙箱中不适用(AI agent 的 cwd 不一定是技能目录)。
31
+ **重要**:所有脚本必须用**绝对路径**调用。`./scripts/...` 相对路径在 Agent 运行环境中不适用(AI agent 的 cwd 不一定是技能目录)。
32
32
 
33
33
  调用方式(推荐用绝对路径):
34
34
  ```
@@ -59,12 +59,12 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/check-env.j
59
59
 
60
60
  **解读输出**:
61
61
  - 退出码 0 + 末行 `ENV_OK {...}` → 探活通过,继续
62
- - 退出码 1 → git 不可用(沙箱 DLL 问题),**终止流程,提示用户到系统终端重试**
62
+ - 退出码 1 → git 不可用(运行环境 DLL 问题),**终止流程,提示用户到系统终端重试**
63
63
  - 退出码 2 → 当前不在 git 仓库,**终止流程,提示用户到工作空间根目录**
64
64
 
65
65
  ### 0.1.5 环境健康自检(check-env-deep)
66
66
 
67
- 提前检测网络/权限/版本问题,把可能在 Step 3.4 push 或 Step 4 install-ai 暴露的失败前移到流程最开始:
67
+ 提前检测权限/版本问题,把可能在后续步骤暴露的失败前移到流程最开始:
68
68
 
69
69
  ```bash
70
70
  node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/check-env-deep.js"
@@ -76,8 +76,6 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/check-env-d
76
76
 
77
77
  **检测项**:
78
78
  - Node.js >= 16.7.0
79
- - npm 官方源可达(`https://registry.npmjs.org`)
80
- - cbb 是否已安装(未安装仅警告,由 Step 4 自动安装)
81
79
  - `.worktrees/` 目录可写
82
80
 
83
81
  ### 0.2 读取并校验 workspace-config.json
@@ -298,7 +296,7 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/create-work
298
296
  3. **app worktree 创建**(物理嵌套在 workspace worktree 内)
299
297
 
300
298
  **解读输出**:
301
- - 退出码 0 + 末行 `WT_PATH <绝对路径>` → 全部成功,AI 解析出 worktree 绝对路径供后续 Step 4/5 使用
299
+ - 退出码 0 + 末行 `WT_PATH <绝对路径>` → 全部成功,AI 解析出 worktree 绝对路径供后续 Step 4 使用
302
300
  - 退出码 2 → workspace worktree 创建失败(分支已检出/权限不足),**终止流程**
303
301
  - 退出码 3 → 部分 app worktree 创建失败,**报告已创建/失败详情,用户需手动清理**
304
302
 
@@ -313,52 +311,31 @@ WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
313
311
 
314
312
  > ⓘ **tracked 内容自动 checkout**:workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)在 workspace 工作树创建时**自动从 git 对象库 checkout**——**不需要 `cp`、`git clone` 或任何“带过来”动作**。各应用 worktree 同理。
315
313
 
316
- > ⓘ **AI 配置目录(.claude/、.qoder/ 等)**:workspace 主分支中这些目录通常为 gitignore'd,不会自动出现在 worktree 中。本 skill 在 Step 4 统一在 worktree 内执行 `cbbm init -y` 安装 AI 配置,无需依赖用户手动配置。
314
+ > ⓘ **AI 配置目录(.claude/、.qoder/、.opencode/ 等)**:统一安装在业务空间根(`cbb setup` / `cbb update`),**worktree 内不安装**;AI 会话始终以空间根为基础,开发动作指向本 worktree 路径。
317
315
 
318
316
  ---
319
317
 
320
- ## Step 4:安装 AI 配置(必要步骤)
318
+ ## Step 4:收尾与交接(必要步骤)
321
319
 
322
- workspace 主分支的 `.claude/` `.qoder/` `.cbb/` 通常为 gitignore'd,创建 worktree 时不会自动带入。
323
- **本步骤在 worktree 内执行 `cbbm init --yes` 是必要步骤**——缺失 AI 配置会导致后续
324
- openspec-propose/apply/verify/ff 等技能全部不可用,worktree 将处于"半残"状态。
320
+ 不执行脚本。AI agent 向用户输出最终报告(格式见「最终报告」),并完成以下交接声明:
325
321
 
326
- > push-branches(Step 3.4)一致:**本步骤失败将阻塞 init-worktree**,用户必须手动恢复后重跑。
327
-
328
- ```bash
329
- node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/install-ai.js "<wt_path>"
330
- ```
331
-
332
- **解读输出**:
333
- - 退出码 0 + 末行 `AI_INIT_OK` → 成功,继续 Step 5
334
- - 退出码 1 → 参数错误(脚本 bug)
335
- - 退出码 2 + 末行 `AI_INIT_FAILED` → cbbm init 执行失败,**init-worktree 中断**,
336
- 按错误提示手动执行 `cd "<wt_path>" && cbbm init --yes` 后重跑
337
-
338
- > `-y` 表示非交互模式:默认选中所有适配器、前置依赖未安装时自动继续,适合 skill 自动化执行。
322
+ 1. **继续在当前会话开发**:本技能不打开新窗口;需求工作目录为 `<wt_path>`
323
+ 2. **目录纪律**:本会话后续所有产生写操作的命令(git commit / openspec / 构建 / 测试等)必须以 `<wt_path>`(或其应用子目录)为工作目录(显式 `cd` 或绝对路径);**禁止在空间根(主分支)执行任何写操作**
324
+ 3. 不自动安装依赖:各仓库技术栈不一(Maven 依赖本机 `~/.m2` 全局共享、无需初始化;Node/Python 等由你进入 worktree 后执行正确的命令,如 `npm ci` / `pnpm`)
339
325
 
340
326
  ---
341
327
 
342
- ## Step 5:环境收尾
328
+ ## 最终报告
343
329
 
344
- 所有步骤完成后,检测当前运行环境,**在新窗口打开 IDE** 并定位到 workspace worktree 目录。
330
+ 最终报告格式:
345
331
 
346
- ```bash
347
- node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.js "<wt_path>"
332
+ ```
333
+ worktree 已创建:<wt_path>
334
+ 关联应用:<应用名 → 嵌套路径> 列表
335
+ 📌 继续在当前会话开发:后续写操作命令一律以上述目录为工作目录
348
336
  ```
349
337
 
350
- **解读末行**:
351
- - `ENV=QODER_GUI` / `CURSOR_GUI` / `VSCODE_GUI` / `JETBRAINS_GUI` → GUI 模式(已在新窗口打开 IDE)
352
- - `ENV=CLI` → CLI 模式(AI agent 自行 cd 到 wt_path)
353
- - `OPEN_FAILED` → 自动打开失败,提示用户手动操作
354
-
355
- ---
356
-
357
- ## 最终报告
358
-
359
- 最终报告由 AI agent 根据 `auto-open.js` 的末行输出生成,格式同 v1(GUI / CLI / OPEN_FAILED 三种)。
360
-
361
- > 不自动安装依赖:各仓库技术栈不一(Maven 依赖本机 `~/.m2` 全局共享、无需初始化;Node/Python 等由你进入 worktree 后执行正确的命令,如 `npm ci` / `pnpm`)。猜测安装命令易出错,故不在本步骤处理。
338
+ > 若 Step 3.5 为部分失败(退出码 3),报告必须列出已创建/失败详情与回滚清理命令。
362
339
 
363
340
  ---
364
341
 
@@ -381,14 +358,14 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
381
358
  | 场景 | 处理方式 |
382
359
  |------|----------|
383
360
  | `.worktrees/` 或 `.codespace/` 未在 `.gitignore` | workspace 仓库自动添加并提交(在 Step 3.2) |
384
- | `git worktree add` 权限被拒 | 沙箱降级,中断并告知用户 |
361
+ | `git worktree add` 权限被拒 | 运行环境降级,中断并告知用户 |
385
362
  | 状态检查任一失败 | 终止并报告所有问题 |
386
363
  | 部分应用 worktree 创建失败 | 提示已创建的回滚清理命令 |
387
364
  | workspace 主分支 tracked 内容(openspec/、cbb/ 等) | 自动 checkout 到工作树,无需额外动作(cp/clone 都是多余的) |
388
- | AI 配置目录(.claude/、.qoder/ 等) | gitignore'd,不在仓库中;**Step 4 是必要步骤**,执行 `cbbm init --yes` 自动安装(失败会阻塞 init-worktree |
365
+ | AI 配置目录(.claude/、.qoder/、.opencode/ 等) | 统一安装在空间根(`cbb setup` / `cbb update`);worktree 内不安装、也不需要 |
389
366
  | 需求名(同时作分支名和工作树目录名) | 用户在对话中纯文本输入,参考 Step 3.1 命名规则(kebab-case,禁 `..`、路径分隔符、空格) |
390
367
  | 关联应用范围 | 固定为 `workspace-config.json` 全量 apps(无勾选);增减应用后重跑本技能(幂等) |
391
- | 沙箱内 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
368
+ | 运行环境 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
392
369
  | push 失败(SSH/HTTPS/网络/保护) | push-branches.js 退出码 2,AI 阻塞并询问用户三选项(修复后重试/跳过失败仓库/完全终止) |
393
370
  | 远程分支已存在 | push-branches.js 输出 metadata,AI 展示 commit 元信息后询问两选项(关联/终止+重新创建) |
394
371
  | 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调 `/cbb:worktree-push` 或 `cbb-worktree-push` skill 推送(详见该 skill) |
@@ -462,10 +439,10 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
462
439
  - **问题:** 试图在 Bash 调用中嵌套 Node 脚本与 shell 变量,导致变量解析失败
463
440
  - **修复:** 所有脚本参数(`<ws_root>`、`<branch>`)由 AI agent 在对话上下文中维护,**作为字符串参数传入脚本**,不要在 Bash 命令中拼 shell 变量
464
441
 
465
- ### 把 install-ai 当作可失败步骤
442
+ ### 在空间根执行写操作命令
466
443
 
467
- - **问题:** 以为 worktree 创建成功就能继续工作,忽略了 Step 4 失败,导致后续 openspec-* 技能全部报"找不到 skill"
468
- - **修复:** Step 4 失败必须手动 `cd <wt_path> && cbbm init --yes`,然后重跑 init-worktree(脚本会自动跳过已初始化的部分)
444
+ - **问题:** worktree 创建成功后,会话仍在空间根运行 git commit / openspec / 构建命令,污染主分支或把变更产物生成在主分支上
445
+ - **修复:** Step 4 交接已声明需求工作目录 `<wt_path>`;所有写操作命令必须显式 `cd` 或用绝对路径指向 worktree
469
446
 
470
447
  ---
471
448
 
@@ -479,11 +456,11 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
479
456
  - workspace 仓库创建工作树前不验证 `.worktrees/` 和 `.codespace/` 在 `.gitignore`
480
457
  - 用 `git checkout -b` 切分支后再建 worktree(分支检出冲突)
481
458
  - 用 `AskUserQuestion` 收集自由文本(需求名 / 分支选项等)
482
- - 沙箱内 node 不可用时强行继续 → 改为 fail-fast 提示用户
459
+ - 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
483
460
  - **Step 3.4 推送失败后跳过失败仓库直接继续** → 必须阻塞并询问用户决策
484
461
  - **远程分支已存在时脚本自动 set-upstream-to** → 必须由用户决策,避免关联到他人的同名分支
485
462
  - **AI 询问关联选项前不输出 commit 元信息** → 必须先在 AskUserQuestion 之前输出远程 hash/author/date/message + 本地 hash
486
- - **Step 4 install-ai 失败时强行继续** 必须阻塞并按错误提示恢复,AI 不得绕过退出码 2 继续执行
463
+ - **在空间根执行 git/openspec/构建等写操作命令**必须显式指定需求工作树路径(`<wt_path>` 或其应用子目录)
487
464
 
488
465
  **必须执行**
489
466
 
@@ -507,7 +484,5 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
507
484
  | `update-gitignore.js` | 安全更新 .gitignore | ws_root, branch | 0/1/2 |
508
485
  | `create-branches.js` | 创建分支 | ws_root, branch | 0/1/2 |
509
486
  | `create-worktrees.js` | 创建 worktree(含自愈清理) | ws_root, branch | 0/1/2/3 |
510
- | `install-ai.js` | 安装 AI 配置(**必要步骤**) | wt_path | 0/1/2 |
511
487
  | `push-branches.js` | 推送并建立 upstream(已一致则 skipped;带错误归类 + 元信息采集) | ws_root, branch | 0/1/2 |
512
- | `check-env-deep.js` | 环境健康自检(Node 版本 / npm 源 / 权限) | 无 | 0/2 |
513
- | `auto-open.js` | 环境感知自动打开(**新窗口**) | wt_path | 0(始终) |
488
+ | `check-env-deep.js` | 环境健康自检(Node 版本 / 权限) | 无 | 0/2 |
@@ -7,26 +7,15 @@ require('./silence-popup');
7
7
  *
8
8
  * 检测项:
9
9
  * 1. Node.js 版本(>= 16.7.0)
10
- * 2. npm 官方源可达性(https://registry.npmjs.org)
11
- * 3. cbb 是否已安装(未安装视为软警告,由 Step 4 自动安装)
12
- * 4. .worktrees/ 目录可写性
10
+ * 2. .worktrees/ 目录可写性
13
11
  *
14
12
  * 退出码:
15
13
  * 0 - 全部通过(DOCTOR_OK)
16
- * 2 - 致命问题(Node 版本 / npm 源 / 权限),必须修复后重试
14
+ * 2 - 致命问题(Node 版本 / 权限),必须修复后重试
17
15
  */
18
- const { execSync } = require('child_process');
19
16
  const fs = require('fs');
20
17
  const path = require('path');
21
18
 
22
- function run(cmd) {
23
- try {
24
- return { ok: true, out: execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim() };
25
- } catch (e) {
26
- return { ok: false, err: (e.stderr || e.message || String(e)).trim() };
27
- }
28
- }
29
-
30
19
  let hasFatal = false;
31
20
 
32
21
  // ── 1. Node.js 版本 ──
@@ -40,26 +29,7 @@ if (nodeMajor < 16 || (nodeMajor === 16 && parseInt(nodeVersion.split('.')[1], 1
40
29
  console.log('✅ Node.js: ' + nodeVersion);
41
30
  }
42
31
 
43
- // ── 2. npm 内部源可达性 ──
44
- const npmPing = run('npm ping --registry=https://registry.npmjs.org');
45
- if (!npmPing.ok) {
46
- console.error('❌ npm 内部源不可达:' + npmPing.err);
47
- console.error(' → 检查代理设置:npm config get registry');
48
- console.error(' → 检查网络是否能访问 https://registry.npmjs.org');
49
- hasFatal = true;
50
- } else {
51
- console.log('✅ npm 官方源可达(https://registry.npmjs.org)');
52
- }
53
-
54
- // ── 3. cbbm 检测(软警告) ──
55
- const cbbInfo = run('cbbm --version');
56
- if (cbbInfo.ok) {
57
- console.log('✅ cbbm 已安装:' + cbbInfo.out);
58
- } else {
59
- console.log('⚠️ cbbm 未安装(Step 4 install-ai 会自动安装,软警告不阻塞)');
60
- }
61
-
62
- // ── 4. .worktrees 目录可写性 ──
32
+ // ── 2. .worktrees 目录可写性 ──
63
33
  const wsRoot = process.cwd();
64
34
  const wtDir = path.join(wsRoot, '.worktrees');
65
35
  try {
@@ -3,7 +3,7 @@ require('./silence-popup');
3
3
  /**
4
4
  * cbb-worktree-init 环境健康探活
5
5
  *
6
- * 提前发现 Qoder 沙箱 DLL 问题(0xc0000142)以及其他子进程启动失败。
6
+ * 提前发现 Agent 运行环境 DLL 问题(0xc0000142)以及其他子进程启动失败。
7
7
  * 失败时输出明确错误信息并以非零退出码终止,AI agent 据此决定是否继续。
8
8
  *
9
9
  * 跨平台:
@@ -38,7 +38,7 @@ const checks = {};
38
38
  checks.git = tryExec('git --version');
39
39
  if (!checks.git.ok) {
40
40
  console.error('❌ git 启动失败');
41
- console.error(' 可能是 Qoder 沙箱 DLL 问题(0xc0000142)');
41
+ console.error(' 可能是 Agent 运行环境 DLL 问题(0xc0000142)');
42
42
  console.error(' 解决方案:到系统终端(非 Qoder AI 终端)重新执行本技能');
43
43
  process.exit(1);
44
44
  }
@@ -61,27 +61,18 @@ if (!checks.node.ok) {
61
61
  console.log('✅ node OK:', checks.node.out);
62
62
  }
63
63
 
64
- // ── 选检:cbbm(Step 5 才需要) ────────────────────
65
- checks.cbbInfo = tryExec('cbbm --version');
66
- if (!checks.cbbInfo.ok) {
67
- console.log('ℹ️ cbbm 未全局安装(Step 5 会兜底自动安装)');
68
- } else {
69
- console.log('✅ cbbm OK:', checks.cbbInfo.out);
70
- }
71
-
72
- // ── 沙箱检测 ─────────────────────────────────────────
64
+ // ── 运行环境检测 ───────────────────────────────────────
73
65
  const inWorktree = !!(process.env.QODER_AGENT || process.env.QODER_WORKTREE);
74
66
  if (inWorktree) {
75
- console.log('🛡️ Qoder 沙箱环境:若后续 node/git DLL 错误,请到系统终端重试');
67
+ console.log('🛡️ Qoder Agent 运行环境:若后续 node/git DLL 错误,请到系统终端重试');
76
68
  } else {
77
- console.log('✅ 非沙箱环境:所有子进程以默认 PATH 运行');
69
+ console.log('✅ 系统终端环境:所有子进程以默认 PATH 运行');
78
70
  }
79
71
 
80
72
  // 输出机器可读摘要(AI agent 可解析)
81
73
  const summary = {
82
74
  git: checks.git.ok,
83
75
  node: checks.node.ok,
84
- cbbInfo: checks.cbbInfo.ok,
85
76
  inWorktree,
86
77
  ok: true,
87
78
  };
@@ -30,7 +30,7 @@ metadata:
30
30
 
31
31
  ## 调用脚本的统一方式
32
32
 
33
- **所有脚本必须用绝对路径调用**(Qoder 沙箱中 AI agent 的 cwd 不一定是技能目录)。
33
+ **所有脚本必须用绝对路径调用**(Agent 运行环境中 AI agent 的 cwd 不一定是技能目录)。
34
34
 
35
35
  ```
36
36
  node "<ws_root>/.qoder/skills/cbb-worktree-push/scripts/<name>.js" <参数>
@@ -282,7 +282,7 @@ node "..." "<ws_root>/.worktrees/worktree-<branch>"
282
282
  - push 失败后跳过失败仓库直接继续
283
283
  - 远程分支已存在时脚本自动 set-upstream-to
284
284
  - AI 询问关联选项前不输出 commit 元信息
285
- - 沙箱内 node 不可用时强行继续 → 改为 fail-fast 提示用户
285
+ - 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
286
286
 
287
287
  **必须执行**
288
288
 
@@ -1,37 +1,39 @@
1
- # 业务空间使用说明(AI Agent 导航)
2
-
3
- 本目录是由 `@jspg-ai/coding-bb` 初始化的**多仓库联动开发业务空间**。
4
- 进入本目录工作时,请先按本文件理解目录职责与协作约定,再动手。
5
-
6
- ## 核心约定
7
-
8
- 1. **本目录不做需求开发**。本目录(业务空间主分支)只负责组织与调度;所有需求开发都在 `.worktrees/worktree-<需求名>/` 隔离目录内进行。
9
- 2. **接到新需求先建 worktree**:在本目录执行 `/cbb:worktree-init <需求名>`(opencode 写法:`/cbb-worktree-init`)。它会为 `workspace-config.json` 中的全量关联应用同步创建同名 worktree,并自动安装沙箱内的编码规范与 OpenSpec 工作流。
10
- 3. **开发动作全部在 worktree 内**:需求提案 / 实现 / 验证 / 归档(`/opsx:propose` → `/opsx:apply` → `/opsx:verify` → `/opsx:archive`)在 worktree 沙箱内执行;跨仓库提交推送用 `/cbb:worktree-push`,需求收尾用 `/cbb:worktree-close`。
11
- 4. **关联应用增减只改配置**:编辑 `workspace-config.json` `apps` 数组(`name` / `repo` / `side` / `desc`),然后用同一需求名重跑 worktree 初始化即幂等补齐;不要手工 `git clone` 应用仓库。
12
- 5. **不要绕过 worktree 直接修改 `.codespace/` 或本目录的代码**。`.codespace/` 是工具维护的基准代码,不是开发区。
13
-
14
- ## 目录结构与职责
15
-
16
- | 路径 | 职责 | 维护方式 |
17
- |------|------|----------|
18
- | `workspace-config.json` | 关联应用清单,所有应用联动的唯一数据源 | 人工编辑 |
19
- | `.codespace/` | 各关联应用的基准代码(每个应用一个子目录) | `cbb setup` 与 worktree 流程自动 clone / fetch;**勿手动编辑**;已 gitignore,不提交 |
20
- | `.worktrees/` | 需求隔离开发区(每个需求一个 `worktree-<需求名>/` 目录) | worktree 命令自动创建 / 清理;不提交(首次执行 worktree 流程时自动加入 .gitignore |
21
- | `openspec/` | OpenSpec 工作流配置(`config.yaml` + `schemas/`) | cbb 安装;需求变更产物(`openspec/changes/` 等)在 worktree 内生成,随需求分支提交 |
22
- | `.claude/` `.qoder/` `.opencode/` | AI 工具适配目录:worktree 管理技能与命令;**故意不含**编码规范(防止在空间根直接开发) | 由 cbb setup 时选择的工具安装;已 gitignore,不提交,勿手动改 |
23
- | `.cbb/` | cbb 安装清单,记录本包管理的全部路径 | 由 cbb 管理;**勿手动编辑** |
24
-
25
- ## 典型流程
26
-
27
- ```
28
- 本目录:/cbb:worktree-init <需求名>
29
- → .worktrees/worktree-<需求名>/ 内开发(/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive)
30
- /cbb:worktree-push 推送 → 合并后 /cbb:worktree-close 关闭
31
- ```
32
-
33
- > 命令写法因 AI 工具而异:Claude Code / Qoder 为 `/cbb:worktree-init`,opencode 为 `/cbb-worktree-init`;`/opsx:*` 同理(opencode 为 `/opsx-*`)。
34
-
35
- ---
36
-
37
- 本文件由 `@jspg-ai/coding-bb` 生成(仅缺失时写入,之后不会覆盖或删除,可自由增补团队约定)。
1
+ # 业务空间使用说明(AI Agent 导航)
2
+
3
+ 本目录是由 `@jspg-ai/coding-bb` 初始化的**多仓库联动开发业务空间**。
4
+ 进入本目录工作时,请先按本文件理解目录职责与协作约定,再动手。
5
+
6
+ ## 核心约定
7
+
8
+ 1. **本目录不做需求开发**。本目录(业务空间主分支)只负责组织与调度;所有需求开发都在 `.worktrees/worktree-<需求名>/` 隔离目录内进行。
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
11
+ 4. **开发命令在本会话执行,写操作指向 worktree**:需求提案 / 实现 / 验证 / 归档(`/opsx:propose` `/opsx:apply` → `/opsx:verify` → `/opsx:archive`)在空间根会话执行;但所有产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录(显式 `cd` 或绝对路径);**禁止在空间根(主分支)执行写操作**。
12
+ 5. **关联应用增减只改配置**:编辑 `workspace-config.json` 的 `apps` 数组(`name` / `repo` / `side` / `desc`),然后用同一需求名重跑 worktree 初始化即幂等补齐;不要手工 `git clone` 应用仓库。
13
+ 6. **不要绕过 worktree 直接修改 `.codespace/` 或本目录的代码**。`.codespace/` 是工具维护的基准代码,不是开发区。
14
+
15
+ ## 目录结构与职责
16
+
17
+ | 路径 | 职责 | 维护方式 |
18
+ |------|----------|----------|
19
+ | `workspace-config.json` | 关联应用清单,所有应用联动的唯一数据源 | 人工编辑 |
20
+ | `.codespace/` | 各关联应用的基准代码(每个应用一个子目录) | `cbb setup` worktree 流程自动 clone / fetch;**勿手动编辑**;已 gitignore,不提交 |
21
+ | `.worktrees/` | 需求隔离开发区(每个需求一个 `worktree-<需求名>/` 目录) | worktree 命令自动创建 / 清理;不提交(首次执行 worktree 流程时自动加入 .gitignore) |
22
+ | `openspec/` | OpenSpec 工作流配置(`config.yaml` + `schemas/`) | 由 cbb 安装;需求变更产物(`openspec/changes/` 等)在**需求工作树内**生成,随需求分支提交 |
23
+ | `.claude/` `.qoder/` `.opencode/` | AI 工具适配目录:编码规范规则、OpenSpec 命令、worktree 管理技能与命令 | 由 cbb setup 时选择的工具安装;已 gitignore,不提交,勿手动改 |
24
+ | `.cbb/` | cbb 安装清单,记录本包管理的全部路径 | 由 cbb 管理;**勿手动编辑** |
25
+
26
+ ## 典型流程
27
+
28
+ ```
29
+ 本目录:/cbb:worktree-init <需求名>
30
+ 继续在当前会话开发:写操作命令以 .worktrees/worktree-<需求名>/ 为工作目录
31
+ (/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive)
32
+ → /cbb:worktree-push 推送 → 合并后 /cbb:worktree-close 关闭
33
+ ```
34
+
35
+ > 命令写法因 AI 工具而异:Claude Code / Qoder 为 `/cbb:worktree-init`,opencode 为 `/cbb-worktree-init`;`/opsx:*` 同理(opencode 为 `/opsx-*`)。
36
+
37
+ ---
38
+
39
+ 本文件由 `@jspg-ai/coding-bb` 生成(仅缺失时写入,之后不会覆盖或删除,可自由增补团队约定)。
@@ -15,6 +15,11 @@
15
15
  "name": "数据标注平台-AI开发工作空间",
16
16
  "repo": "http://git.portjs.cn/jspg-ai/ai-workspace/jspg-data-labeling-aiws.git",
17
17
  "businessLine": "yzg-ai"
18
+ },
19
+ {
20
+ "name": "集团EDI一体化-AI开发工作空间",
21
+ "repo": "http://git.portjs.cn/jspg-ai/ai-workspace/jspg-edi-yth-aiws.git",
22
+ "businessLine": "yth"
18
23
  }
19
24
  ]
20
25
  }