@jspg-ai/coding-bb 0.0.3-beta.33 → 0.0.3-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cbb/dev-standards/rules/cbb-ai-behavior.md +0 -33
- package/cbb/dev-standards/rules/cbb-workspace-discipline.md +36 -0
- package/cbb/lib/install/init.js +3 -2
- package/cbb/worktrees/_shared/scripts/delete-branches.js +147 -0
- package/cbb/worktrees/_shared/scripts/find-target-worktree.js +1 -1
- package/cbb/worktrees/_shared/scripts/find-workspace-root.js +1 -1
- package/cbb/worktrees/_shared/scripts/push-core.js +1 -1
- package/cbb/worktrees/_shared/scripts/silence-popup.js +1 -1
- package/cbb/worktrees/skills/cbb-local-mode/SKILL.md +9 -5
- package/cbb/worktrees/skills/cbb-local-mode/scripts/delete-branches.js +147 -0
- package/cbb/worktrees/skills/cbb-local-mode/scripts/silence-popup.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-close/SKILL.md +3 -2
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/check-env.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/delete-branches.js +147 -138
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/find-target-worktree.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/find-workspace-root.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/silence-popup.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +13 -10
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/push-core.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/silence-popup.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +1 -1
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/find-target-worktree.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/find-workspace-root.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/merge-branches.js +469 -0
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/push-core.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/silence-popup.js +1 -1
- package/config/workspace-agents.sample.md +1 -1
- package/package.json +2 -2
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/find-workspace-root.js +0 -67
|
@@ -1,138 +1,147 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
require('./silence-popup');
|
|
3
|
-
/**
|
|
4
|
-
* cbb
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
console.log('
|
|
137
|
-
|
|
138
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('./silence-popup');
|
|
3
|
+
/**
|
|
4
|
+
* 删除需求分支(共享脚本,真源:cbb/worktrees/_shared/scripts/)
|
|
5
|
+
*
|
|
6
|
+
* 供 cbb-worktree-close(Step 4.4 交付完成后自动删本地 + 远程分支)与
|
|
7
|
+
* cbb-local-mode(Step 5.4 收尾删远程分支)调用。
|
|
8
|
+
*
|
|
9
|
+
* 用法:node delete-branches.js <ws_root> <branch> <mode> # mode: keep / local / local_remote
|
|
10
|
+
*
|
|
11
|
+
* 逐仓库执行:本地分支按合并判定选 -d / -D(squash 合并 -d 失败回退 -D);
|
|
12
|
+
* local_remote 模式追加 git push <remote> --delete。
|
|
13
|
+
* 清理阶段失败报告并继续其余仓库,不回滚(ADR 0007)。
|
|
14
|
+
*/
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
const wsRoot = process.argv[2];
|
|
20
|
+
const branch = process.argv[3];
|
|
21
|
+
const mode = process.argv[4];
|
|
22
|
+
|
|
23
|
+
if (!wsRoot || !branch || !mode) {
|
|
24
|
+
console.error('Usage: node delete-branches.js <ws_root> <branch> <mode>');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (mode === 'keep') {
|
|
29
|
+
console.log('Keep branch, skip delete');
|
|
30
|
+
console.log('---');
|
|
31
|
+
console.log('BRANCH_DELETE_RESULT', JSON.stringify({ mode: 'keep', ok: true, deleted: [] }));
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (mode !== 'local' && mode !== 'local_remote') {
|
|
36
|
+
console.error('mode must be keep / local / local_remote');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function run(cmd, cwd, env) {
|
|
41
|
+
try {
|
|
42
|
+
return { ok: true, out: execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env, ...(env || {}) } }).trim() };
|
|
43
|
+
} catch (e) {
|
|
44
|
+
return { ok: false, err: (e.stderr || e.message || String(e)).trim() };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function detectMain(repoPath) {
|
|
49
|
+
const remote = run('git remote', repoPath);
|
|
50
|
+
if (!remote.ok || !remote.out) return 'main';
|
|
51
|
+
const r = remote.out.split(/\r?\n/)[0];
|
|
52
|
+
const symbolic = run('git symbolic-ref "refs/remotes/' + r + '/HEAD"', repoPath);
|
|
53
|
+
if (symbolic.ok && symbolic.out) {
|
|
54
|
+
return symbolic.out.replace('refs/remotes/' + r + '/', '');
|
|
55
|
+
}
|
|
56
|
+
return 'main';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function mergedTo(repoPath, from, to) {
|
|
60
|
+
// 0=merged, 1=unmerged, 2=to-ref-missing
|
|
61
|
+
if (!run('git rev-parse --verify --quiet "' + from + '"', repoPath).ok) return 1;
|
|
62
|
+
if (!run('git rev-parse --verify --quiet "' + to + '"', repoPath).ok) return 2;
|
|
63
|
+
if (run('git merge-base --is-ancestor "' + from + '" "' + to + '" && echo Y', repoPath).out === 'Y') return 0;
|
|
64
|
+
// 跨平台:不用 grep(Windows 无 grep),解析 git cherry 输出(+ 前缀 = 未合并提交)
|
|
65
|
+
const cherry = run('git cherry "' + to + '" "' + from + '"', repoPath);
|
|
66
|
+
if (!cherry.ok) return 1;
|
|
67
|
+
if (cherry.out.split(/\r?\n/).filter(Boolean).some(l => l.indexOf('+') === 0)) return 1;
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function mergedToMain(repoPath, branchName, main) {
|
|
72
|
+
if (mergedTo(repoPath, branchName, main) === 0) return true;
|
|
73
|
+
if (mergedTo(repoPath, branchName, 'origin/' + main) === 0) return true;
|
|
74
|
+
// release-* transit
|
|
75
|
+
const releaseList = run('git for-each-ref --format="%(refname:short)" "refs/heads/release-*" "refs/remotes/origin/release-*"', repoPath);
|
|
76
|
+
if (releaseList.ok && releaseList.out) {
|
|
77
|
+
const releases = releaseList.out.split(/\r?\n/).filter(Boolean).sort();
|
|
78
|
+
for (const rel of releases) {
|
|
79
|
+
if (mergedTo(repoPath, branchName, rel) === 0) {
|
|
80
|
+
if (mergedTo(repoPath, rel, main) === 0) return true;
|
|
81
|
+
if (mergedTo(repoPath, rel, 'origin/' + main) === 0) return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function deleteBranch(repoPath, name) {
|
|
89
|
+
const checkLocal = run('git branch --list "' + branch + '"', repoPath);
|
|
90
|
+
if (checkLocal.ok && checkLocal.out) {
|
|
91
|
+
const main = detectMain(repoPath);
|
|
92
|
+
const merged = main ? mergedToMain(repoPath, branch, main) : false;
|
|
93
|
+
let flag = merged ? '-d' : '-D';
|
|
94
|
+
const del = run('git branch ' + flag + ' "' + branch + '"', repoPath);
|
|
95
|
+
if (del.ok) {
|
|
96
|
+
console.log('OK ' + name + ' local branch deleted (' + flag + ', ' + (merged ? 'merged' : 'unmerged') + ')');
|
|
97
|
+
} else {
|
|
98
|
+
if (flag === '-d') {
|
|
99
|
+
const fallback = run('git branch -D "' + branch + '"', repoPath);
|
|
100
|
+
if (fallback.ok) {
|
|
101
|
+
console.log('OK ' + name + ' local branch deleted (squash merge, fallback -D)');
|
|
102
|
+
} else {
|
|
103
|
+
console.error('FAIL ' + name + ' local branch delete failed');
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
console.error('FAIL ' + name + ' local branch delete failed');
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
console.log('Skip ' + name + ': no local branch ' + branch);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (mode === 'local_remote') {
|
|
116
|
+
const remote = run('git remote', repoPath);
|
|
117
|
+
if (remote.ok && remote.out) {
|
|
118
|
+
const r = remote.out.split(/\r?\n/)[0];
|
|
119
|
+
const pushDel = run('git push "' + r + '" --delete "' + branch + '"', repoPath, { GIT_TERMINAL_PROMPT: '0' });
|
|
120
|
+
if (pushDel.ok) {
|
|
121
|
+
console.log('OK ' + name + ' remote branch deleted');
|
|
122
|
+
} else {
|
|
123
|
+
console.log('Skip ' + name + ': remote has no ' + branch);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
|
|
131
|
+
let config = {};
|
|
132
|
+
try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (e) {}
|
|
133
|
+
|
|
134
|
+
const apps = config.apps || [];
|
|
135
|
+
|
|
136
|
+
console.log('=== Delete Workspace Branch ===');
|
|
137
|
+
deleteBranch(wsRoot, 'workspace');
|
|
138
|
+
|
|
139
|
+
console.log('=== Delete App Branches ===');
|
|
140
|
+
for (const app of apps) {
|
|
141
|
+
const appPath = path.join(wsRoot, '.codespace', app.name);
|
|
142
|
+
deleteBranch(appPath, app.name);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
console.log('---');
|
|
146
|
+
console.log('BRANCH_DELETE_RESULT', JSON.stringify({ mode, ok: true }));
|
|
147
|
+
process.exit(0);
|
|
@@ -3,7 +3,7 @@ require('./silence-popup');
|
|
|
3
3
|
* openspec-shared 目标需求名识别
|
|
4
4
|
*
|
|
5
5
|
* 唯一真源:cbb/worktrees/_shared/scripts/find-target-worktree.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(close / push)。
|
|
7
7
|
*
|
|
8
8
|
* 用法:node find-target-worktree.js <ws_root>
|
|
9
9
|
*
|
|
@@ -3,7 +3,7 @@ require('./silence-popup');
|
|
|
3
3
|
* openspec-shared 工作空间根目录定位
|
|
4
4
|
*
|
|
5
5
|
* 唯一真源:cbb/worktrees/_shared/scripts/find-workspace-root.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(close / push)。
|
|
7
7
|
*
|
|
8
8
|
* 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 CBB-WORKSPACE.json 副本干扰)
|
|
9
9
|
* 兜底:当前目录含 CBB-WORKSPACE.json
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// koffi is resolved from cbb global install (no local node_modules needed).
|
|
5
5
|
//
|
|
6
6
|
// 唯一真源:cbb/worktrees/_shared/scripts/silence-popup.js
|
|
7
|
-
// 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init /
|
|
7
|
+
// 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / close / push / local-mode)。
|
|
8
8
|
// skill 内同目录引用:脚本第一行 `require('./silence-popup')`。
|
|
9
9
|
if (process.platform === 'win32') {
|
|
10
10
|
try {
|
|
@@ -17,7 +17,7 @@ description: "为一个需求在 workspace 与各关联应用仓库同步创建
|
|
|
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
19
|
- **本技能必须在业务工作空间根目录执行**(即由 `cbb setup` 初始化、包含 `CBB-WORKSPACE.json` 的目录)
|
|
20
|
-
-
|
|
20
|
+
- 输入约定:**自由文本**(需求名、需求描述等)直接在对话中提问并等待回复,禁止使用 `AskUserQuestion`;`AskUserQuestion` 仅用于固定选项决策场景(如 Step 3.1 候选名选择、push 失败处理、远程分支已存在时的二选一)
|
|
21
21
|
- 关联应用恒为 `CBB-WORKSPACE.json` 的**全量 apps**,AI 不询问范围、不从需求语境收窄(worktree 单仓库创建成本低,全量镜像空间根布局);仅当**用户显式点名**应用时才经 `--apps` 传子集(见 Step 1),需要增减应用时编辑该文件并重跑本技能(幂等)
|
|
22
22
|
- **模式选择(ADR 0002)**:接到需求先判断用户要哪种模式——要**并行 / 隔离** → 本技能;**单线程快改、当前会话就地干** → 引导 `cbb-local-mode`。用户明确指定即遵从,agent 只给推荐不代决
|
|
23
23
|
|
|
@@ -207,17 +207,20 @@ node "<skill_dir>/scripts/check-repos.js" "<ws_root>"
|
|
|
207
207
|
|
|
208
208
|
### 3.1 询问需求名
|
|
209
209
|
|
|
210
|
-
**直接在对话中**向用户提问(不要使用 `AskUserQuestion` 工具):*"请输入需求名(同时作为分支名和 workspace
|
|
210
|
+
**直接在对话中**向用户提问(不要使用 `AskUserQuestion` 工具):*"请输入需求名(同时作为分支名和 workspace 工作树目录名);也可以输入一段需求描述,我来推荐几个英文名供你选择:"*,然后等待用户的纯文本回复。
|
|
211
|
+
|
|
212
|
+
**两种输入:**
|
|
213
|
+
- **直接输入名字** → 按下方命名规则校验后采用
|
|
214
|
+
- **输入需求描述**(中英文不限)→ agent 生成 **3–5 个** kebab-case 英文候选(语义对应描述,可按需带类型前缀 `feature-` / `fix-` / `refactor-` 等,候选间风格拉开),用 `AskUserQuestion` 列出供选择;不满意可直接回复自己的名字 → 获选名按命名规则校验后采用
|
|
215
|
+
|
|
216
|
+
> 示例:描述"修复 2026 Q2 数据泄漏" → 候选 `fix-2026q2-data-leak`、`fix-q2-data-leak`、`patch-data-leak-2026q2`
|
|
211
217
|
|
|
212
218
|
**命名规则:**
|
|
213
219
|
- 推荐 kebab-case,如 `feature-login`、`ep-user-rebuild`、`fix-2026q2-leak`
|
|
214
220
|
- 禁止包含 `..`、路径分隔符(`/`、`\`)、空格、git 分支禁用字符
|
|
215
221
|
- **需求名同时**作为分支名和 workspace 工作树目录名(`.worktrees/worktree-<需求名>/`)
|
|
216
222
|
|
|
217
|
-
|
|
218
|
-
- 分支名:`feature-login`
|
|
219
|
-
- workspace 工作树目录:`.worktrees/worktree-feature-login`
|
|
220
|
-
- 各应用 worktree 子目录:`.worktrees/worktree-feature-login/<应用名>`
|
|
223
|
+
例:`feature-login` → 分支 `feature-login`;workspace 工作树 `.worktrees/worktree-feature-login/`;应用子目录 `.worktrees/worktree-feature-login/.codespace/<应用名>/`(ADR 0003)
|
|
221
224
|
|
|
222
225
|
### 3.2 安全更新 .gitignore(前置)
|
|
223
226
|
|
|
@@ -265,7 +268,7 @@ node "<skill_dir>/scripts/create-branches.js" "<ws_root>" "<branch>" [--apps "ap
|
|
|
265
268
|
|
|
266
269
|
### 3.4 分支就位(lazy push,不推远端)
|
|
267
270
|
|
|
268
|
-
**本技能不执行任何远端推送(ADR 0002 lazy push)**:分支创建止步于本地。远端副作用收敛到 `cbb-worktree-push` 唯一出口(dry-run 预览 → agent 生成 commit 信息并提交 → push → MR
|
|
271
|
+
**本技能不执行任何远端推送(ADR 0002 lazy push)**:分支创建止步于本地。远端副作用收敛到 `cbb-worktree-push` 唯一出口(dry-run 预览 → agent 生成 commit 信息并提交 → push → Step 7 交付选择:提 MR / 直接合并,ADR 0008)——推送类失败(认证/网络/保护分支)在 push 技能内暴露并处理,不在创建流程中阻塞。
|
|
269
272
|
|
|
270
273
|
> 旧版在本步骤推送空分支建立 upstream(`push-branches.js`),自 0.0.3-beta.22 起移除:避免每个需求在远端留下空分支尸体;`push-worktrees.js` 首次推送时自动建立 upstream,行为等价。
|
|
271
274
|
|
|
@@ -381,7 +384,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
|
|
|
381
384
|
| 部分应用 worktree 创建失败 | 提示已创建的回滚清理命令 |
|
|
382
385
|
| workspace 主分支 tracked 内容(openspec/、cbb/ 等) | 自动 checkout 到工作树,无需额外动作(cp/clone 都是多余的) |
|
|
383
386
|
| AI 配置目录(.claude/、.qoder/、.opencode/ 等) | Step 3.6 junction 内容子目录进工作树;唯一物理副本在空间根,`cbb update` 一处生效 |
|
|
384
|
-
| 需求名(同时作分支名和工作树目录名) |
|
|
387
|
+
| 需求名(同时作分支名和工作树目录名) | 对话纯文本输入:直接给名,或给需求描述由 agent 推荐 3–5 个英文候选(`AskUserQuestion` 选定);命名规则见 Step 3.1 |
|
|
385
388
|
| 关联应用范围 | 恒为全量(不询问、不从需求语境收窄);用户显式点名应用时 `--apps` 传子集;增减应用后重跑本技能(幂等) |
|
|
386
389
|
| 单线程快改 / 不需要隔离 | 引导 cbb-local-mode(本地模式,就地切分支) |
|
|
387
390
|
| 运行环境 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
|
|
@@ -430,7 +433,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
|
|
|
430
433
|
### 用 AskUserQuestion 收集自由文本输入
|
|
431
434
|
|
|
432
435
|
- **问题:** 需求名需要用户自由输入文本,却用了 `AskUserQuestion` 工具,被迫提供预设选项
|
|
433
|
-
- **修复:**
|
|
436
|
+
- **修复:** 自由文本(需求名、需求描述)一律**直接在对话中提问**;`AskUserQuestion` 仅用于固定选项——如 Step 3.1 输入描述后的候选名选择
|
|
434
437
|
|
|
435
438
|
### 完成后开发会话未开进 worktree
|
|
436
439
|
|
|
@@ -464,7 +467,7 @@ node "<skill_dir>/scripts/junction-ai-config.js" "<ws_root>" "<wt_path>"
|
|
|
464
467
|
- 跳过或绕过 Step 2 状态检查;状态检查失败后继续
|
|
465
468
|
- workspace 仓库创建工作树前不验证 `.worktrees/` 和 `.codespace/` 在 `.gitignore`
|
|
466
469
|
- 用 `git checkout -b` 切分支后再建 worktree(分支检出冲突)
|
|
467
|
-
- 用 `AskUserQuestion` 收集自由文本(需求名 /
|
|
470
|
+
- 用 `AskUserQuestion` 收集自由文本(需求名 / 需求描述 / 分支选项等)——从固定候选中选名(Step 3.1)除外
|
|
468
471
|
- 运行环境 node 不可用时强行继续 → 改为 fail-fast 提示用户
|
|
469
472
|
- **在本技能内向远端推送任何分支**(lazy push,ADR 0002)——推送只发生在 `cbb-worktree-push`
|
|
470
473
|
- **hook 拦截 main 载荷提交后用 `--no-verify` 绕过**——仅限用户显式要求
|
|
@@ -3,7 +3,7 @@ require('./silence-popup');
|
|
|
3
3
|
* openspec-shared 推送核心模块
|
|
4
4
|
*
|
|
5
5
|
* 唯一真源:cbb/worktrees/_shared/scripts/push-core.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / push)。
|
|
7
7
|
*
|
|
8
8
|
* 公开 API:
|
|
9
9
|
* - tryExec(cmd, cwd, execImpl) 包装 execSync,统一返回 {ok, out|err}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// koffi is resolved from cbb global install (no local node_modules needed).
|
|
5
5
|
//
|
|
6
6
|
// 唯一真源:cbb/worktrees/_shared/scripts/silence-popup.js
|
|
7
|
-
// 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init /
|
|
7
|
+
// 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / close / push / local-mode)。
|
|
8
8
|
// skill 内同目录引用:脚本第一行 `require('./silence-popup')`。
|
|
9
9
|
if (process.platform === 'win32') {
|
|
10
10
|
try {
|
|
@@ -344,6 +344,7 @@ node "<skill_dir>/scripts/merge-branches.js" "<ws_root>" "<branch>" --apps "<app
|
|
|
344
344
|
- 退出码 0 → 交付完成
|
|
345
345
|
- `need-mr`(目标分支受保护)→ 报明细并**转出口 A**
|
|
346
346
|
- `failed`(含 `merge-failed` / `push-failed`)→ 报明细,修复后重跑(幂等)
|
|
347
|
+
- `not-on-main`(仅主干路径)→ 空间根检出被其他需求占用(本地模式进行中):**先收尾该本地需求或改用出口 A 提 MR**;不得用 `--allow-checkout` 抢占(该参数属本地模式收尾,会切走占用者的工作区)
|
|
347
348
|
|
|
348
349
|
报告形态:
|
|
349
350
|
|
|
@@ -496,4 +497,3 @@ node "<skill_dir>/scripts/merge-branches.js" "<ws_root>" "<branch>" --apps "<app
|
|
|
496
497
|
| `push-core.js` | 推送核心(classifyError / pushSingle / collectRemoteMetadata,共享脚本,源仓库真源在 `_shared/scripts/`) | (共享模块) | - |
|
|
497
498
|
| `check-unarchived.js` | 未归档 change 检查(Step 7 直合并的归档前置,共享脚本) | ws_root, branch | 0/1 |
|
|
498
499
|
| `merge-branches.js` | 直合并(Step 7 出口 B / 收尾门禁;预检 → merge --no-ff → push;`--target` 支持测试分支,共享脚本) | ws_root, branch, --apps / --target / --allow-checkout / --dry-run / --check | 0/1/2 |
|
|
499
|
-
| `deprecate-branches.js` | 废弃重命名(收尾门禁出口三,共享脚本) | ws_root, branch, --apps | 0/1/2 |
|
|
@@ -3,7 +3,7 @@ require('./silence-popup');
|
|
|
3
3
|
* openspec-shared 目标需求名识别
|
|
4
4
|
*
|
|
5
5
|
* 唯一真源:cbb/worktrees/_shared/scripts/find-target-worktree.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(close / push)。
|
|
7
7
|
*
|
|
8
8
|
* 用法:node find-target-worktree.js <ws_root>
|
|
9
9
|
*
|
|
@@ -3,7 +3,7 @@ require('./silence-popup');
|
|
|
3
3
|
* openspec-shared 工作空间根目录定位
|
|
4
4
|
*
|
|
5
5
|
* 唯一真源:cbb/worktrees/_shared/scripts/find-workspace-root.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(close / push)。
|
|
7
7
|
*
|
|
8
8
|
* 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 CBB-WORKSPACE.json 副本干扰)
|
|
9
9
|
* 兜底:当前目录含 CBB-WORKSPACE.json
|