@jspg-ai/coding-bb 0.0.2-beta.29 → 0.0.3-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cbb/bin/cbbm.js +1 -1
- package/cbb/dev-standards/rules/cbb-ai-behavior.md +118 -103
- package/cbb/lib/install/claude-code.js +1 -3
- package/cbb/lib/install/codebuddy.js +30 -0
- package/cbb/lib/install/init.js +354 -305
- package/cbb/lib/install/opencode.js +35 -31
- package/cbb/lib/install/qoder.js +1 -3
- package/cbb/lib/install/rule-rewrite.js +27 -0
- package/cbb/lib/install/trae.js +33 -0
- package/cbb/lib/install/workspaces.js +24 -0
- package/cbb/lib/openspec/index.js +337 -554
- package/cbb/lib/superpowers/index.js +246 -265
- package/cbb/lib/utils/check-update.js +9 -2
- package/cbb/lib/utils/gitignore.js +2 -0
- package/cbb/lib/utils/settings.js +17 -4
- package/cbb/lib/utils/tar.js +92 -0
- package/cbb/lib/utils/upstream.js +90 -0
- package/cbb/worktrees/skills/cbb-worktree-close/SKILL.md +33 -24
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/check-env.js +4 -4
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/remove-worktrees.js +2 -2
- package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +61 -78
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-env-deep.js +3 -33
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-env.js +5 -14
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/create-worktrees.js +15 -37
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/update-gitignore.js +25 -9
- package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +67 -31
- package/config/openspec/schemas/spec-driven/schema.yaml +29 -30
- package/config/openspec/schemas/spec-driven/templates/design.md +0 -18
- package/config/openspec/schemas/spec-driven/templates/proposal.md +4 -3
- package/config/upstream-mirrors.json +12 -0
- package/config/workspace-agents.sample.md +17 -13
- package/config/workspaces.json +5 -0
- package/openspec/.version +2 -3
- package/openspec/commands/apply.md +189 -175
- package/openspec/commands/archive.md +237 -216
- package/openspec/commands/bulk-archive.md +355 -327
- package/openspec/commands/continue.md +116 -105
- package/openspec/commands/explore.md +230 -199
- package/openspec/commands/ff.md +115 -104
- package/openspec/commands/new.md +74 -63
- package/openspec/commands/onboard.md +557 -548
- package/openspec/commands/propose.md +161 -150
- package/openspec/commands/sync.md +277 -249
- package/openspec/commands/update.md +92 -80
- package/openspec/commands/verify.md +175 -162
- package/openspec/skills/openspec-apply-change/SKILL.md +20 -5
- package/openspec/skills/openspec-archive-change/SKILL.md +30 -8
- package/openspec/skills/openspec-bulk-archive-change/SKILL.md +36 -6
- package/openspec/skills/openspec-continue-change/SKILL.md +14 -2
- package/openspec/skills/openspec-explore/SKILL.md +21 -9
- package/openspec/skills/openspec-ff-change/SKILL.md +14 -2
- package/openspec/skills/openspec-new-change/SKILL.md +13 -1
- package/openspec/skills/openspec-onboard/SKILL.md +49 -39
- package/openspec/skills/openspec-propose/SKILL.md +15 -3
- package/openspec/skills/openspec-sync-specs/SKILL.md +31 -2
- package/openspec/skills/openspec-update-change/SKILL.md +27 -14
- package/openspec/skills/openspec-verify-change/SKILL.md +17 -3
- package/package.json +2 -2
- package/superpowers/.version +4 -4
- package/superpowers/skills/brainstorming/SKILL.md +47 -12
- package/superpowers/skills/brainstorming/scripts/frame-template.html +213 -213
- package/superpowers/skills/brainstorming/scripts/server.cjs +723 -723
- package/superpowers/skills/brainstorming/visual-companion.md +6 -6
- package/superpowers/skills/diagnosing-superpowers/SKILL.md +120 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/analyst-common.md +38 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/cost-and-time.md +28 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/plan-adherence.md +29 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/quality-evidence.md +26 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/repeated-work.md +30 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/request-conflicts.md +20 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/scrub-audit.md +33 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/scrub.md +29 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/similar-session.md +38 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/skill-timeline.md +30 -0
- package/superpowers/skills/diagnosing-superpowers/prompts/stumbles.md +28 -0
- package/superpowers/skills/diagnosing-superpowers/references/context-safety.md +22 -0
- package/superpowers/skills/diagnosing-superpowers/references/github-issues.md +47 -0
- package/superpowers/skills/diagnosing-superpowers/references/redaction-policy.md +34 -0
- package/superpowers/skills/diagnosing-superpowers/references/session-discovery.md +31 -0
- package/superpowers/skills/diagnosing-superpowers/templates/bundle-README.md +77 -0
- package/superpowers/skills/diagnosing-superpowers/templates/case.md +64 -0
- package/superpowers/skills/diagnosing-superpowers/templates/issue.md +51 -0
- package/superpowers/skills/diagnosing-superpowers/templates/report.md +82 -0
- package/superpowers/skills/executing-plans/SKILL.md +350 -41
- package/superpowers/skills/executing-plans/scripts/task-done +52 -0
- package/superpowers/skills/executing-plans/scripts/task-start +28 -0
- package/superpowers/skills/requesting-code-review/SKILL.md +1 -1
- package/superpowers/skills/requesting-code-review/code-reviewer.md +17 -0
- package/superpowers/skills/subagent-driven-development/SKILL.md +18 -18
- package/superpowers/skills/subagent-driven-development/re-review-prompt.md +1 -1
- package/superpowers/skills/subagent-driven-development/scripts/review-package +53 -46
- package/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +82 -40
- package/superpowers/skills/subagent-driven-development/scripts/task-brief +43 -41
- package/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +2 -2
- package/superpowers/skills/systematic-debugging/root-cause-tracing.md +1 -1
- package/superpowers/skills/test-driven-development/SKILL.md +10 -0
- package/superpowers/skills/using-superpowers/SKILL.md +2 -0
- package/superpowers/skills/using-superpowers/references/claude-code-tools.md +29 -0
- package/superpowers/skills/using-superpowers/references/muse-tools.md +35 -0
- package/superpowers/skills/writing-plans/SKILL.md +30 -9
- package/superpowers/skills/writing-skills/SKILL.md +4 -2
- package/superpowers/skills/writing-skills/graphviz-conventions.dot +171 -171
- package/cbb/worktrees/commands/worktree-close.md +0 -64
- package/cbb/worktrees/commands/worktree-init.md +0 -55
- package/cbb/worktrees/commands/worktree-push.md +0 -42
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/auto-open.js +0 -136
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/install-ai.js +0 -177
|
@@ -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
|
-
|
|
25
|
+
**重要**:本技能的所有脚本位于**本 SKILL.md 所在目录的 `scripts/` 下**(skill 目录)。
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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,20 +53,20 @@ node "D:\workspace\<用户工作空间>\.qoder\skills\cbb-worktree-init\scripts\
|
|
|
54
53
|
### 0.1 环境健康探活
|
|
55
54
|
|
|
56
55
|
```bash
|
|
57
|
-
node "
|
|
56
|
+
node "<skill_dir>/scripts/check-env.js"
|
|
58
57
|
```
|
|
59
58
|
|
|
60
59
|
**解读输出**:
|
|
61
60
|
- 退出码 0 + 末行 `ENV_OK {...}` → 探活通过,继续
|
|
62
|
-
- 退出码 1 → git
|
|
61
|
+
- 退出码 1 → git 不可用(运行环境 DLL 问题),**终止流程,提示用户到系统终端重试**
|
|
63
62
|
- 退出码 2 → 当前不在 git 仓库,**终止流程,提示用户到工作空间根目录**
|
|
64
63
|
|
|
65
64
|
### 0.1.5 环境健康自检(check-env-deep)
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
提前检测权限/版本问题,把可能在后续步骤暴露的失败前移到流程最开始:
|
|
68
67
|
|
|
69
68
|
```bash
|
|
70
|
-
node "
|
|
69
|
+
node "<skill_dir>/scripts/check-env-deep.js"
|
|
71
70
|
```
|
|
72
71
|
|
|
73
72
|
**解读输出**:
|
|
@@ -76,14 +75,12 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/check-env-d
|
|
|
76
75
|
|
|
77
76
|
**检测项**:
|
|
78
77
|
- Node.js >= 16.7.0
|
|
79
|
-
- npm 官方源可达(`https://registry.npmjs.org`)
|
|
80
|
-
- cbb 是否已安装(未安装仅警告,由 Step 4 自动安装)
|
|
81
78
|
- `.worktrees/` 目录可写
|
|
82
79
|
|
|
83
80
|
### 0.2 读取并校验 workspace-config.json
|
|
84
81
|
|
|
85
82
|
```bash
|
|
86
|
-
node "
|
|
83
|
+
node "<skill_dir>/scripts/parse-config.js"
|
|
87
84
|
```
|
|
88
85
|
|
|
89
86
|
**解读输出**:
|
|
@@ -150,7 +147,7 @@ worktree 需要知道要关联哪些应用仓库。
|
|
|
150
147
|
|
|
151
148
|
```bash
|
|
152
149
|
# ws_root 来自 AI agent 维护的状态
|
|
153
|
-
node "
|
|
150
|
+
node "<skill_dir>/scripts/sync-repos.js" "<ws_root>"
|
|
154
151
|
```
|
|
155
152
|
|
|
156
153
|
**用法**:
|
|
@@ -194,7 +191,7 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/sync-repos.
|
|
|
194
191
|
| 当前在主分支上 | ✅ | ❌ |
|
|
195
192
|
|
|
196
193
|
```bash
|
|
197
|
-
node "
|
|
194
|
+
node "<skill_dir>/scripts/check-repos.js" "<ws_root>"
|
|
198
195
|
```
|
|
199
196
|
|
|
200
197
|
**解读输出**:
|
|
@@ -222,21 +219,23 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/check-repos
|
|
|
222
219
|
### 3.2 安全更新 .gitignore(前置)
|
|
223
220
|
|
|
224
221
|
```bash
|
|
225
|
-
node "
|
|
222
|
+
node "<skill_dir>/scripts/update-gitignore.js" "<ws_root>" "<branch>"
|
|
226
223
|
```
|
|
227
224
|
|
|
228
|
-
脚本内部自动完成:stash 保护 → 切分支 → 添加 `.worktrees/` 和 `.codespace/` → 提交 → 切回 → pop stash
|
|
225
|
+
脚本内部自动完成:stash 保护 → 分支不存在则从 HEAD 创建 → 切分支 → 添加 `.worktrees/` 和 `.codespace/` → 提交 → 切回 → pop stash
|
|
229
226
|
|
|
230
227
|
**解读输出**:
|
|
231
228
|
- 退出码 0 + 末行 `GITIGNORE_OK` → 成功
|
|
232
229
|
- 退出码 2 → 执行失败,**终止流程**
|
|
233
230
|
|
|
234
|
-
>
|
|
231
|
+
> ⓘ **分支自动创建**:本步骤先于 Step 3.3 执行,workspace 分支此时不存在,脚本会自动从 HEAD 创建(与 `create-branches.js` 对 workspace 的行为一致,Step 3.3 报 `reused`)。`.gitignore` 提交正好落在需求分支上,由 Step 3.4 push 一并推送。
|
|
232
|
+
|
|
233
|
+
> ⚠️ 必须在提交后切回主分支,否则 Step 3.5 的 `git worktree add` 会因分支已检出而失败(脚本已自动处理)。
|
|
235
234
|
|
|
236
235
|
### 3.3 创建分支
|
|
237
236
|
|
|
238
237
|
```bash
|
|
239
|
-
node "
|
|
238
|
+
node "<skill_dir>/scripts/create-branches.js" "<ws_root>" "<branch>"
|
|
240
239
|
```
|
|
241
240
|
|
|
242
241
|
**解读输出**:
|
|
@@ -261,7 +260,7 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/create-bran
|
|
|
261
260
|
### 3.4 推送并建立 upstream
|
|
262
261
|
|
|
263
262
|
```bash
|
|
264
|
-
node "
|
|
263
|
+
node "<skill_dir>/scripts/push-branches.js" "<ws_root>" "<branch>"
|
|
265
264
|
```
|
|
266
265
|
|
|
267
266
|
脚本内部自动完成:
|
|
@@ -286,20 +285,20 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/push-branch
|
|
|
286
285
|
|
|
287
286
|
**为什么 push 放在 worktree 之前:** 失败早暴露,无 worktree 损失;成功后再创建 worktree,分支天然有 upstream;独立脚本便于单测。
|
|
288
287
|
|
|
289
|
-
### 3.5 创建 Worktree
|
|
288
|
+
### 3.5 创建 Worktree
|
|
290
289
|
|
|
291
290
|
```bash
|
|
292
|
-
node "
|
|
291
|
+
node "<skill_dir>/scripts/create-worktrees.js" "<ws_root>" "<branch>"
|
|
293
292
|
```
|
|
294
293
|
|
|
295
294
|
脚本内部自动完成:
|
|
296
|
-
1.
|
|
295
|
+
1. **元数据自愈**:仅 `git worktree prune`(清理"目录已缺失/失效"的注册项);**绝不删除任何物理目录**(0.0.3-beta.11 起——旧版"清理无元数据残留目录"因 Windows 路径分隔符不匹配会误删活跃 worktree,已整体移除)
|
|
297
296
|
2. **workspace worktree 创建**:`git worktree add .worktrees/worktree-<branch> <branch>`
|
|
298
297
|
3. **app worktree 创建**(物理嵌套在 workspace worktree 内)
|
|
299
298
|
|
|
300
299
|
**解读输出**:
|
|
301
|
-
- 退出码 0 + 末行 `WT_PATH <绝对路径>` → 全部成功,AI 解析出 worktree 绝对路径供后续 Step 4
|
|
302
|
-
- 退出码 2 → workspace worktree
|
|
300
|
+
- 退出码 0 + 末行 `WT_PATH <绝对路径>` → 全部成功,AI 解析出 worktree 绝对路径供后续 Step 4 使用
|
|
301
|
+
- 退出码 2 → workspace worktree 创建失败(分支已检出/权限不足),或目标目录存在但非有效 worktree(上次 close 被 IDE 锁残留)——**终止流程**,按脚本提示引导用户跑 `cbb-worktree-close` 或手动删除该目录 + `git worktree prune` 后重跑
|
|
303
302
|
- 退出码 3 → 部分 app worktree 创建失败,**报告已创建/失败详情,用户需手动清理**
|
|
304
303
|
|
|
305
304
|
**报告示例**:
|
|
@@ -313,52 +312,38 @@ WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
|
|
|
313
312
|
|
|
314
313
|
> ⓘ **tracked 内容自动 checkout**:workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)在 workspace 工作树创建时**自动从 git 对象库 checkout**——**不需要 `cp`、`git clone` 或任何“带过来”动作**。各应用 worktree 同理。
|
|
315
314
|
|
|
316
|
-
> ⓘ **AI 配置目录(.claude/、.qoder/
|
|
315
|
+
> ⓘ **AI 配置目录(.claude/、.qoder/、.opencode/ 等)**:统一安装在业务空间根(`cbb setup` / `cbb update`),**worktree 内不安装**;AI 会话始终以空间根为基础,开发动作指向本 worktree 路径。
|
|
317
316
|
|
|
318
317
|
---
|
|
319
318
|
|
|
320
|
-
## Step 4
|
|
321
|
-
|
|
322
|
-
workspace 主分支的 `.claude/` `.qoder/` `.cbb/` 通常为 gitignore'd,创建 worktree 时不会自动带入。
|
|
323
|
-
**本步骤在 worktree 内执行 `cbbm init --yes` 是必要步骤**——缺失 AI 配置会导致后续
|
|
324
|
-
openspec-propose/apply/verify/ff 等技能全部不可用,worktree 将处于"半残"状态。
|
|
325
|
-
|
|
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
|
-
```
|
|
319
|
+
## Step 4:收尾与交接(必要步骤)
|
|
331
320
|
|
|
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` 后重跑
|
|
321
|
+
不执行脚本。AI agent 向用户输出最终报告(格式见「最终报告」),并完成以下交接声明:
|
|
337
322
|
|
|
338
|
-
|
|
323
|
+
1. **继续在当前会话开发**:本技能不打开新窗口;需求工作目录为 `<wt_path>`
|
|
324
|
+
2. **目录纪律**:本会话后续所有产生写操作的命令(git commit / openspec / 构建 / 测试等)必须以 `<wt_path>`(或其应用子目录)为工作目录(显式 `cd` 或绝对路径);**禁止在空间根(主分支)执行任何写操作**
|
|
325
|
+
3. 不自动安装依赖:各仓库技术栈不一(Maven 依赖本机 `~/.m2` 全局共享、无需初始化;Node/Python 等由你进入 worktree 后执行正确的命令,如 `npm ci` / `pnpm`)
|
|
326
|
+
4. **输出下一步建议**:最终报告必须包含「下一步建议」段(格式见「最终报告」),告知用户后续可走的流程;仅提示,不自动串联执行任何后续技能
|
|
339
327
|
|
|
340
328
|
---
|
|
341
329
|
|
|
342
|
-
##
|
|
330
|
+
## 最终报告
|
|
343
331
|
|
|
344
|
-
|
|
332
|
+
最终报告格式:
|
|
345
333
|
|
|
346
|
-
```
|
|
347
|
-
|
|
334
|
+
```
|
|
335
|
+
✅ worktree 已创建:<wt_path>
|
|
336
|
+
关联应用:<应用名 → 嵌套路径> 列表
|
|
337
|
+
📌 继续在当前会话开发:后续写操作命令一律以上述目录为工作目录
|
|
338
|
+
👉 下一步建议:
|
|
339
|
+
1. 开始需求开发(二选一):
|
|
340
|
+
- 走 OpenSpec 工作流:/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive
|
|
341
|
+
- 或直接对话开发:把需求告诉我,在 <wt_path> 内实现
|
|
342
|
+
2. 开发中提交推送:说"提交并推送"(cbb-worktree-push)
|
|
343
|
+
3. 需求完成后:说"关闭工作空间"(cbb-worktree-close)
|
|
348
344
|
```
|
|
349
345
|
|
|
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`)。猜测安装命令易出错,故不在本步骤处理。
|
|
346
|
+
> 若 Step 3.5 为部分失败(退出码 3),报告必须列出已创建/失败详情与回滚清理命令。
|
|
362
347
|
|
|
363
348
|
---
|
|
364
349
|
|
|
@@ -370,7 +355,7 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
|
|
|
370
355
|
|------|----------|
|
|
371
356
|
| 空间新增了应用(编辑 `workspace-config.json` 后) | Step 1 拉取新应用代码 → Step 3.3 为新应用建分支 → Step 3.4 推送(已一致的分支 `skipped`,不一致则阻塞询问)→ Step 3.5 创建缺失的嵌套 worktree |
|
|
372
357
|
| 上次 init 中途失败 | 已存在的分支 / worktree 自动复用,`.gitignore` 处理自动跳过,仅补齐缺失部分 |
|
|
373
|
-
| 应用从 config 移除 | 已创建的分支 / worktree **不会**自动删除;如需清理用
|
|
358
|
+
| 应用从 config 移除 | 已创建的分支 / worktree **不会**自动删除;如需清理用 `cbb-worktree-close` skill 关闭后重建 |
|
|
374
359
|
|
|
375
360
|
> ⓘ 重跑**不会静默推送**开发中的本地提交:远程分支已存在但与本地不一致时,Step 3.4 走阻塞式 `remote-exists` 决策(展示 commit 元信息让用户选择)。
|
|
376
361
|
|
|
@@ -381,17 +366,17 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
|
|
|
381
366
|
| 场景 | 处理方式 |
|
|
382
367
|
|------|----------|
|
|
383
368
|
| `.worktrees/` 或 `.codespace/` 未在 `.gitignore` | workspace 仓库自动添加并提交(在 Step 3.2) |
|
|
384
|
-
| `git worktree add` 权限被拒 |
|
|
369
|
+
| `git worktree add` 权限被拒 | 运行环境降级,中断并告知用户 |
|
|
385
370
|
| 状态检查任一失败 | 终止并报告所有问题 |
|
|
386
371
|
| 部分应用 worktree 创建失败 | 提示已创建的回滚清理命令 |
|
|
387
372
|
| workspace 主分支 tracked 内容(openspec/、cbb/ 等) | 自动 checkout 到工作树,无需额外动作(cp/clone 都是多余的) |
|
|
388
|
-
| AI 配置目录(.claude/、.qoder/ 等) |
|
|
373
|
+
| AI 配置目录(.claude/、.qoder/、.opencode/ 等) | 统一安装在空间根(`cbb setup` / `cbb update`);worktree 内不安装、也不需要 |
|
|
389
374
|
| 需求名(同时作分支名和工作树目录名) | 用户在对话中纯文本输入,参考 Step 3.1 命名规则(kebab-case,禁 `..`、路径分隔符、空格) |
|
|
390
375
|
| 关联应用范围 | 固定为 `workspace-config.json` 全量 apps(无勾选);增减应用后重跑本技能(幂等) |
|
|
391
|
-
|
|
|
376
|
+
| 运行环境 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
|
|
392
377
|
| push 失败(SSH/HTTPS/网络/保护) | push-branches.js 退出码 2,AI 阻塞并询问用户三选项(修复后重试/跳过失败仓库/完全终止) |
|
|
393
378
|
| 远程分支已存在 | push-branches.js 输出 metadata,AI 展示 commit 元信息后询问两选项(关联/终止+重新创建) |
|
|
394
|
-
| 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调
|
|
379
|
+
| 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调 `cbb-worktree-push` skill 推送(详见该 skill) |
|
|
395
380
|
|
|
396
381
|
---
|
|
397
382
|
|
|
@@ -462,10 +447,10 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
|
|
|
462
447
|
- **问题:** 试图在 Bash 调用中嵌套 Node 脚本与 shell 变量,导致变量解析失败
|
|
463
448
|
- **修复:** 所有脚本参数(`<ws_root>`、`<branch>`)由 AI agent 在对话上下文中维护,**作为字符串参数传入脚本**,不要在 Bash 命令中拼 shell 变量
|
|
464
449
|
|
|
465
|
-
###
|
|
450
|
+
### 在空间根执行写操作命令
|
|
466
451
|
|
|
467
|
-
- **问题:**
|
|
468
|
-
- **修复:** Step 4
|
|
452
|
+
- **问题:** worktree 创建成功后,会话仍在空间根运行 git commit / openspec / 构建命令,污染主分支或把变更产物生成在主分支上
|
|
453
|
+
- **修复:** Step 4 交接已声明需求工作目录 `<wt_path>`;所有写操作命令必须显式 `cd` 或用绝对路径指向 worktree
|
|
469
454
|
|
|
470
455
|
---
|
|
471
456
|
|
|
@@ -479,18 +464,18 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
|
|
|
479
464
|
- workspace 仓库创建工作树前不验证 `.worktrees/` 和 `.codespace/` 在 `.gitignore`
|
|
480
465
|
- 用 `git checkout -b` 切分支后再建 worktree(分支检出冲突)
|
|
481
466
|
- 用 `AskUserQuestion` 收集自由文本(需求名 / 分支选项等)
|
|
482
|
-
-
|
|
467
|
+
- 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
|
|
483
468
|
- **Step 3.4 推送失败后跳过失败仓库直接继续** → 必须阻塞并询问用户决策
|
|
484
469
|
- **远程分支已存在时脚本自动 set-upstream-to** → 必须由用户决策,避免关联到他人的同名分支
|
|
485
470
|
- **AI 询问关联选项前不输出 commit 元信息** → 必须先在 AskUserQuestion 之前输出远程 hash/author/date/message + 本地 hash
|
|
486
|
-
-
|
|
471
|
+
- **在空间根执行 git/openspec/构建等写操作命令** → 必须显式指定需求工作树路径(`<wt_path>` 或其应用子目录)
|
|
487
472
|
|
|
488
473
|
**必须执行**
|
|
489
474
|
|
|
490
475
|
- workspace 仓库标准检查(当前在主分支等),app 仓库轻量检查(fetch + `origin/main` 可用即可)
|
|
491
476
|
- app 仓库分支从 `origin/main` 创建(`git branch <需求名> ${REMOTE}/${MAIN}`),不依赖本地主分支状态
|
|
492
477
|
- 严格 Step 3.3 → Step 3.4 顺序(先统一创建分支,再统一创建 worktree;workspace 工作树先建,各应用按序补建)
|
|
493
|
-
- 所有脚本调用以 `node "<
|
|
478
|
+
- 所有脚本调用以 `node "<skill_dir>/scripts/<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 由脚本内部从 workspace-config.json 读取);**执行时 cwd 保持在工作空间根**(`check-env.js` / `parse-config.js` 按 cwd 定位)
|
|
494
479
|
- **Step 3.4 push 步骤必须执行且插入在 create-branches.js (3.3) 之后、create-worktrees.js (3.5) 之前** — 失败时阻塞整个 init-worktree 流程
|
|
495
480
|
- **Step 3.4 仅覆盖创建 worktree 时的空 commit** — 开发过程中产生的本地 commit(如 apply 任务实现)必须由用户在 worktree 中手动提交并调 `cbb-worktree-push` 推送;不允许依赖 Step 3.4 之后的自动推送(不存在)
|
|
496
481
|
|
|
@@ -506,8 +491,6 @@ node "D:/workspace/<ws_root>/.qoder/skills/cbb-worktree-init/scripts/auto-open.j
|
|
|
506
491
|
| `check-repos.js` | 状态检查 | ws_root | 0/1/2 |
|
|
507
492
|
| `update-gitignore.js` | 安全更新 .gitignore | ws_root, branch | 0/1/2 |
|
|
508
493
|
| `create-branches.js` | 创建分支 | ws_root, branch | 0/1/2 |
|
|
509
|
-
| `create-worktrees.js` | 创建 worktree
|
|
510
|
-
| `install-ai.js` | 安装 AI 配置(**必要步骤**) | wt_path | 0/1/2 |
|
|
494
|
+
| `create-worktrees.js` | 创建 worktree(仅 prune 元数据,不删物理目录) | ws_root, branch | 0/1/2/3 |
|
|
511
495
|
| `push-branches.js` | 推送并建立 upstream(已一致则 skipped;带错误归类 + 元信息采集) | ws_root, branch | 0/1/2 |
|
|
512
|
-
| `check-env-deep.js` | 环境健康自检(Node 版本 /
|
|
513
|
-
| `auto-open.js` | 环境感知自动打开(**新窗口**) | wt_path | 0(始终) |
|
|
496
|
+
| `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.
|
|
11
|
-
* 3. cbb 是否已安装(未安装视为软警告,由 Step 4 自动安装)
|
|
12
|
-
* 4. .worktrees/ 目录可写性
|
|
10
|
+
* 2. .worktrees/ 目录可写性
|
|
13
11
|
*
|
|
14
12
|
* 退出码:
|
|
15
13
|
* 0 - 全部通过(DOCTOR_OK)
|
|
16
|
-
* 2 - 致命问题(Node 版本 /
|
|
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.
|
|
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
|
-
* 提前发现
|
|
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
|
-
|
|
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
|
-
// ──
|
|
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
|
|
67
|
+
console.log('🛡️ Qoder Agent 运行环境:若后续 node/git DLL 错误,请到系统终端重试');
|
|
76
68
|
} else {
|
|
77
|
-
console.log('✅
|
|
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
|
};
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
require('./silence-popup');
|
|
3
3
|
/**
|
|
4
|
-
* cbb-worktree-init 创建 Worktree
|
|
4
|
+
* cbb-worktree-init 创建 Worktree(自愈清理仅限元数据 prune)
|
|
5
5
|
*
|
|
6
6
|
* 用法:node create-worktrees.js <ws_root> <branch>
|
|
7
7
|
* (apps 由脚本内部从 <ws_root>/workspace-config.json 读取)
|
|
8
8
|
*
|
|
9
9
|
* 行为:
|
|
10
|
-
* 1.
|
|
10
|
+
* 1. 自愈清理:仅 git worktree prune(元数据),**绝不删除任何物理目录**
|
|
11
|
+
* (0.0.3-beta.11 事故修复:旧版按"不在 worktree list"负向推断递归删残留目录,
|
|
12
|
+
* Windows 下 git 输出正斜杠路径与 realpathSync 反斜杠永不匹配,误删活跃 worktree)
|
|
11
13
|
* 2. workspace worktree 创建(.worktrees/worktree-<branch>)
|
|
12
14
|
* 3. 各 app worktree 创建(物理嵌套在 workspace worktree 内)
|
|
13
15
|
* 4. 失败时输出回滚提示
|
|
@@ -15,7 +17,7 @@ require('./silence-popup');
|
|
|
15
17
|
* 退出码:
|
|
16
18
|
* 0 - 全部成功
|
|
17
19
|
* 1 - 参数错误
|
|
18
|
-
* 2 - workspace worktree
|
|
20
|
+
* 2 - workspace worktree 创建失败(含目标目录存在但非有效 worktree 的残留场景)
|
|
19
21
|
* 3 - 部分 app worktree 创建失败
|
|
20
22
|
*/
|
|
21
23
|
|
|
@@ -54,52 +56,28 @@ function run(cmd, cwd) {
|
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
// 1.
|
|
58
|
-
console.log('===
|
|
59
|
+
// 1. 自愈清理(仅元数据:prune 只清理"目录已缺失/失效"的 worktree 注册项,不碰物理目录)
|
|
60
|
+
console.log('=== 自愈清理(仅 prune 元数据,不删物理目录)===');
|
|
59
61
|
|
|
60
|
-
// 1.1 prune 所有仓库
|
|
61
62
|
const allRepos = [wsRoot, ...apps.map(a => path.join(wsRoot, '.codespace', a.name))];
|
|
62
63
|
for (const repo of allRepos) {
|
|
63
64
|
if (fs.existsSync(repo)) {
|
|
64
65
|
run('git worktree prune', repo);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
console.log('✅ 已 prune 所有仓库的 worktree
|
|
68
|
-
|
|
69
|
-
// 1.2 清理 .worktrees/ 下无元数据的物理目录
|
|
70
|
-
const worktreesDir = path.join(wsRoot, '.worktrees');
|
|
71
|
-
if (fs.existsSync(worktreesDir)) {
|
|
72
|
-
const validWts = run('git worktree list --porcelain', wsRoot);
|
|
73
|
-
const validPaths = new Set();
|
|
74
|
-
if (validWts.ok) {
|
|
75
|
-
validWts.out.split('\n').forEach(line => {
|
|
76
|
-
if (line.startsWith('worktree ')) {
|
|
77
|
-
validPaths.add(line.substring(9).trim());
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const entries = fs.readdirSync(worktreesDir, { withFileTypes: true });
|
|
83
|
-
for (const entry of entries) {
|
|
84
|
-
if (!entry.isDirectory()) continue;
|
|
85
|
-
const dir = path.join(worktreesDir, entry.name);
|
|
86
|
-
let absDir;
|
|
87
|
-
try { absDir = fs.realpathSync(dir); } catch { continue; }
|
|
88
|
-
if (!validPaths.has(absDir)) {
|
|
89
|
-
try {
|
|
90
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
91
|
-
console.log('🧹 已清理残留目录:' + entry.name);
|
|
92
|
-
} catch (e) {
|
|
93
|
-
console.log('⏳ 残留目录仍被占用,跳过:' + entry.name);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
68
|
+
console.log('✅ 已 prune 所有仓库的 worktree 元数据(物理目录一律保留)');
|
|
98
69
|
|
|
99
70
|
// 2. workspace worktree 创建
|
|
100
71
|
console.log('=== 创建 Workspace Worktree ===');
|
|
101
72
|
const wtDir = path.join(wsRoot, '.worktrees', 'worktree-' + branch);
|
|
102
73
|
if (fs.existsSync(wtDir)) {
|
|
74
|
+
if (!fs.existsSync(path.join(wtDir, '.git'))) {
|
|
75
|
+
console.error('❌ 目标目录已存在但不是有效 worktree(缺 .git 指针):' + wtDir);
|
|
76
|
+
console.error(' 可能是上次 close / init 中断的残留。本脚本不会自动删除任何目录,请二选一后重跑:');
|
|
77
|
+
console.error(' 1) 执行 cbb-worktree-close 技能清理该需求');
|
|
78
|
+
console.error(' 2) 手动删除上述目录后执行:git -C "' + wsRoot + '" worktree prune');
|
|
79
|
+
process.exit(2);
|
|
80
|
+
}
|
|
103
81
|
console.log('⏭️ workspace worktree 已存在,复用:' + wtDir);
|
|
104
82
|
} else {
|
|
105
83
|
const created = run('git worktree add ".worktrees/worktree-' + branch + '" "' + branch + '"', wsRoot);
|
|
@@ -6,13 +6,13 @@ require('./silence-popup');
|
|
|
6
6
|
* 用法:node update-gitignore.js <ws_root> <branch>
|
|
7
7
|
*
|
|
8
8
|
* 行为:
|
|
9
|
-
* 1. stash
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* 1. stash 当前未提交修改(仅 untracked 时不产生 stash)
|
|
10
|
+
* 2. 目标分支不存在则从 HEAD 创建(首跑时分支尚未由 create-branches.js 建立,
|
|
11
|
+
* 顺序无关自愈;create-branches.js 后续会报 reused)
|
|
12
|
+
* 3. 切换到目标分支
|
|
13
|
+
* 4. 检查 .worktrees/ 和 .codespace/ 是否在 .gitignore,缺失则添加并提交
|
|
14
|
+
* 5. 切回原分支
|
|
15
|
+
* 6. pop stash(如有)
|
|
16
16
|
*
|
|
17
17
|
* 幂等:目标分支已在某个 worktree 中检出(init-worktree 重跑场景,上次已处理过
|
|
18
18
|
* .gitignore)时,跳过全部操作直接输出 GITIGNORE_OK——避免 checkout 与 worktree 检出冲突。
|
|
@@ -67,8 +67,12 @@ const status = run('git status --porcelain', wsRoot);
|
|
|
67
67
|
if (status.ok && status.out) {
|
|
68
68
|
const stash = run('git stash push -m "init-worktree-temp"', wsRoot);
|
|
69
69
|
if (stash.ok) {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
if (/No local changes to save/.test(stash.out)) {
|
|
71
|
+
console.log('ℹ️ 仅 untracked 文件,无需 stash');
|
|
72
|
+
} else {
|
|
73
|
+
stashed = true;
|
|
74
|
+
console.log('✅ 已 stash 未提交修改');
|
|
75
|
+
}
|
|
72
76
|
} else {
|
|
73
77
|
console.error('❌ git stash 失败:' + stash.err);
|
|
74
78
|
process.exit(2);
|
|
@@ -77,6 +81,18 @@ if (status.ok && status.out) {
|
|
|
77
81
|
console.log('ℹ️ 无未提交修改,跳过 stash');
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
// 2.1 目标分支不存在则从 HEAD 创建(Step 3.2 先于 Step 3.3 执行时分支尚未建立)
|
|
85
|
+
const branchList = run('git branch --list "' + branch + '"', wsRoot);
|
|
86
|
+
if (branchList.ok && !branchList.out) {
|
|
87
|
+
const create = run('git branch "' + branch + '"', wsRoot);
|
|
88
|
+
if (!create.ok) {
|
|
89
|
+
console.error('❌ 创建分支 ' + branch + ' 失败:' + create.err);
|
|
90
|
+
if (stashed) run('git stash pop', wsRoot);
|
|
91
|
+
process.exit(2);
|
|
92
|
+
}
|
|
93
|
+
console.log('✅ 分支 ' + branch + ' 不存在,已从 HEAD 创建');
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
// 3. 切换到目标分支
|
|
81
97
|
const checkout = run('git checkout "' + branch + '"', wsRoot);
|
|
82
98
|
if (!checkout.ok) {
|