@jspg-ai/coding-bb 0.0.3-beta.3 → 0.0.3-beta.31
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 +135 -116
- package/cbb/lib/external/index.js +228 -0
- package/cbb/lib/install/agents-nav.js +92 -0
- package/cbb/lib/install/claude-code.js +7 -2
- package/cbb/lib/install/command-skill.js +105 -0
- package/cbb/lib/install/init.js +502 -168
- package/cbb/lib/install/minimax.js +60 -0
- package/cbb/lib/install/opencode.js +3 -5
- package/cbb/lib/install/qoder.js +1 -3
- package/cbb/lib/install/rule-rewrite.js +27 -0
- package/cbb/lib/install/setup-decision.js +48 -0
- package/cbb/lib/install/tool-selection.js +45 -0
- package/cbb/lib/install/trae.js +43 -0
- package/cbb/lib/install/workbuddy.js +36 -0
- package/cbb/lib/install/workspaces.js +21 -17
- package/cbb/lib/openspec/index.js +337 -554
- package/cbb/lib/superpowers/index.js +246 -265
- package/cbb/lib/utils/check-update.js +17 -2
- package/cbb/lib/utils/githook.js +226 -0
- package/cbb/lib/utils/gitignore.js +16 -3
- package/cbb/lib/utils/plugin-hook.js +92 -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/_shared/scripts/check-local-state.js +114 -0
- package/cbb/worktrees/_shared/scripts/find-target-worktree.js +148 -96
- package/cbb/worktrees/_shared/scripts/find-workspace-root.js +7 -7
- package/cbb/worktrees/_shared/scripts/install-git-hook.js +70 -0
- package/cbb/worktrees/_shared/scripts/junction-ai-config.js +127 -0
- package/cbb/worktrees/_shared/scripts/start-local.js +180 -0
- package/cbb/worktrees/skills/cbb-local-mode/SKILL.md +158 -0
- package/cbb/worktrees/skills/cbb-local-mode/scripts/check-local-state.js +114 -0
- package/cbb/worktrees/skills/cbb-local-mode/scripts/install-git-hook.js +70 -0
- package/cbb/worktrees/skills/cbb-local-mode/scripts/silence-popup.js +23 -0
- package/cbb/worktrees/skills/cbb-local-mode/scripts/start-local.js +180 -0
- package/cbb/worktrees/skills/cbb-worktree-close/SKILL.md +60 -43
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/check-env.js +3 -3
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/check-unarchived.js +75 -48
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/delete-branches.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/discover-apps.js +14 -5
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/find-target-worktree.js +148 -96
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/find-workspace-root.js +7 -7
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/remove-worktrees.js +13 -4
- package/cbb/worktrees/skills/cbb-worktree-close/scripts/safety-check.js +11 -2
- package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +138 -129
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-env.js +1 -1
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/check-repos.js +2 -2
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/create-branches.js +33 -8
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/create-worktrees.js +60 -46
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/find-workspace-root.js +7 -7
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/install-git-hook.js +70 -0
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/junction-ai-config.js +127 -0
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/parse-config.js +7 -7
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/push-branches.js +3 -3
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/sync-repos.js +11 -7
- package/cbb/worktrees/skills/cbb-worktree-init/scripts/update-gitignore.js +37 -9
- package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +140 -71
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/commit-worktrees.js +70 -12
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/find-target-worktree.js +148 -96
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/find-workspace-root.js +7 -7
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/make-mr-urls.js +211 -0
- package/cbb/worktrees/skills/cbb-worktree-push/scripts/push-worktrees.js +67 -20
- package/config/{workspace-config.sample.json → CBB-WORKSPACE.sample.json} +1 -1
- package/config/openspec/schemas/spec-driven/schema.yaml +40 -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 +17 -0
- package/config/workspace-agents.sample.md +4 -33
- package/external/frontend-design/.version +6 -0
- package/external/frontend-design/LICENSE.txt +177 -0
- package/external/frontend-design/SKILL.md +71 -0
- package/openspec/.version +2 -3
- package/openspec/commands/apply.md +189 -175
- package/openspec/commands/archive.md +244 -216
- package/openspec/commands/bulk-archive.md +362 -327
- package/openspec/commands/continue.md +115 -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 +562 -548
- package/openspec/commands/propose.md +161 -150
- package/openspec/commands/sync.md +277 -249
- package/openspec/commands/update.md +98 -80
- package/openspec/commands/verify.md +206 -162
- package/openspec/skills/openspec-apply-change/SKILL.md +20 -5
- package/openspec/skills/openspec-archive-change/SKILL.md +40 -11
- package/openspec/skills/openspec-bulk-archive-change/SKILL.md +46 -9
- package/openspec/skills/openspec-continue-change/SKILL.md +14 -3
- package/openspec/skills/openspec-explore/SKILL.md +22 -10
- package/openspec/skills/openspec-ff-change/SKILL.md +15 -3
- package/openspec/skills/openspec-new-change/SKILL.md +13 -1
- package/openspec/skills/openspec-onboard/SKILL.md +58 -43
- 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 +34 -15
- package/openspec/skills/openspec-verify-change/SKILL.md +72 -26
- package/package.json +3 -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 +62 -29
- 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 -51
- package/cbb/worktrees/commands/worktree-push.md +0 -42
- package/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +0 -49
|
@@ -5,7 +5,7 @@ require('./silence-popup');
|
|
|
5
5
|
*
|
|
6
6
|
* 用法:node discover-apps.js <ws_root> <branch>
|
|
7
7
|
*
|
|
8
|
-
* 从
|
|
8
|
+
* 从 CBB-WORKSPACE.json 读取应用列表,扫描 .worktrees/worktree-<branch>/ 实际存在的子目录。
|
|
9
9
|
*
|
|
10
10
|
* 输出末行:DISCOVER_RESULT { workspace: <wt_path>, apps: [{name, repo, side, wt_path}] }
|
|
11
11
|
*
|
|
@@ -26,9 +26,9 @@ if (!wsRoot || !branch) {
|
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const configPath = path.join(wsRoot, '
|
|
29
|
+
const configPath = path.join(wsRoot, 'CBB-WORKSPACE.json');
|
|
30
30
|
if (!fs.existsSync(configPath)) {
|
|
31
|
-
console.error('❌
|
|
31
|
+
console.error('❌ CBB-WORKSPACE.json 不存在:' + configPath);
|
|
32
32
|
process.exit(1);
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -36,7 +36,7 @@ let config;
|
|
|
36
36
|
try {
|
|
37
37
|
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
38
38
|
} catch (e) {
|
|
39
|
-
console.error('❌
|
|
39
|
+
console.error('❌ CBB-WORKSPACE.json 解析失败:' + e.message);
|
|
40
40
|
process.exit(1);
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -50,9 +50,18 @@ if (!fs.existsSync(wtDir)) {
|
|
|
50
50
|
process.exit(2);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** 解析 app worktree 物理路径:新布局 .codespace/<app> 优先,兼容 ≤beta.23 旧平铺 <app> */
|
|
54
|
+
function resolveAppWt(appName) {
|
|
55
|
+
const nested = path.join(wtDir, '.codespace', appName);
|
|
56
|
+
if (fs.existsSync(path.join(nested, '.git'))) return nested;
|
|
57
|
+
const legacy = path.join(wtDir, appName);
|
|
58
|
+
if (fs.existsSync(path.join(legacy, '.git'))) return legacy;
|
|
59
|
+
return nested;
|
|
60
|
+
}
|
|
61
|
+
|
|
53
62
|
const found = [];
|
|
54
63
|
for (const app of apps) {
|
|
55
|
-
const appWt =
|
|
64
|
+
const appWt = resolveAppWt(app.name);
|
|
56
65
|
if (fs.existsSync(appWt) && fs.existsSync(path.join(appWt, '.git'))) {
|
|
57
66
|
console.log('✅ ' + app.name + ':存在嵌套 worktree(' + appWt + ')');
|
|
58
67
|
found.push({
|
|
@@ -1,96 +1,148 @@
|
|
|
1
|
-
require('./silence-popup');
|
|
2
|
-
/**
|
|
3
|
-
* openspec-shared 目标需求名识别
|
|
4
|
-
*
|
|
5
|
-
* 唯一真源:cbb/worktrees/_shared/scripts/find-target-worktree.js
|
|
6
|
-
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(extend / close / push)。
|
|
7
|
-
*
|
|
8
|
-
* 用法:node find-target-worktree.js <ws_root>
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* 1. cwd 在 .worktrees/worktree-xxx/ 内 → 自动从路径反推
|
|
12
|
-
* 2.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
console.
|
|
68
|
-
console.
|
|
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
|
-
|
|
1
|
+
require('./silence-popup');
|
|
2
|
+
/**
|
|
3
|
+
* openspec-shared 目标需求名识别
|
|
4
|
+
*
|
|
5
|
+
* 唯一真源:cbb/worktrees/_shared/scripts/find-target-worktree.js
|
|
6
|
+
* 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(extend / close / push)。
|
|
7
|
+
*
|
|
8
|
+
* 用法:node find-target-worktree.js <ws_root>
|
|
9
|
+
*
|
|
10
|
+
* 优先级(ADR 0002 双布局):
|
|
11
|
+
* 1. cwd 在 .worktrees/worktree-xxx/ 内 → 自动从路径反推
|
|
12
|
+
* 2. 收集候选:worktree 目录(.worktrees/worktree-xxx)
|
|
13
|
+
* + 本地布局(根 / .codespace/<app>/ 检出在非主干分支,本地模式进行中)
|
|
14
|
+
* 同一需求名两种布局共存时合并为一项(标 both)
|
|
15
|
+
* 3. 唯一候选 → 自动选用;多个 → 按 mtime 倒序列出(本地布局用分支检出时间)
|
|
16
|
+
*
|
|
17
|
+
* 输出:
|
|
18
|
+
* 末行输出需求名(用于 AI agent 解析)
|
|
19
|
+
* 多个时按 [1] xxx ⭐ / [2] yyy 列出
|
|
20
|
+
*
|
|
21
|
+
* 退出码:
|
|
22
|
+
* 0 - 唯一识别(自动或唯一)
|
|
23
|
+
* 1 - 多个候选,需用户输入
|
|
24
|
+
* 2 - 无候选(无 worktree 且无本地布局检出)
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const { execSync } = require('child_process');
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
|
|
31
|
+
const wsRoot = process.argv[2];
|
|
32
|
+
|
|
33
|
+
if (!wsRoot) {
|
|
34
|
+
console.error('❌ 用法:node find-target-worktree.js <ws_root>');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function run(cmd, cwd) {
|
|
39
|
+
try {
|
|
40
|
+
return execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
41
|
+
} catch (e) { return null; }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function currentBranch(cwd) {
|
|
45
|
+
return run('git branch --show-current', cwd) || '';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** 主干名(探测失败返回 null → 该仓库任何非空检出都视为候选) */
|
|
49
|
+
function detectMain(cwd) {
|
|
50
|
+
const remotes = run('git remote', cwd);
|
|
51
|
+
if (remotes) {
|
|
52
|
+
const r = remotes.split(/\r?\n/)[0];
|
|
53
|
+
const sym = run('git symbolic-ref "refs/remotes/' + r + '/HEAD"', cwd);
|
|
54
|
+
if (sym) return sym.replace('refs/remotes/' + r + '/', '');
|
|
55
|
+
}
|
|
56
|
+
if (run('git rev-parse --verify --quiet refs/heads/main', cwd)) return 'main';
|
|
57
|
+
if (run('git rev-parse --verify --quiet refs/heads/master', cwd)) return 'master';
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 优先级 1:cwd 反推
|
|
62
|
+
const cwd = process.cwd();
|
|
63
|
+
const cwdMatch = cwd.match(/\.worktrees[\\\/]worktree-([^\\\/]+)/);
|
|
64
|
+
if (cwdMatch) {
|
|
65
|
+
const branch = cwdMatch[1];
|
|
66
|
+
console.log('✅ 从 cwd 反推需求名:' + branch);
|
|
67
|
+
console.log('---');
|
|
68
|
+
console.log(branch);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 优先级 2a:worktree 目录候选
|
|
73
|
+
const candidates = new Map(); // name → { layouts: Set, mtime }
|
|
74
|
+
|
|
75
|
+
const worktreesDir = path.join(wsRoot, '.worktrees');
|
|
76
|
+
if (fs.existsSync(worktreesDir)) {
|
|
77
|
+
const entries = fs.readdirSync(worktreesDir, { withFileTypes: true })
|
|
78
|
+
.filter(e => e.isDirectory() && e.name.startsWith('worktree-'));
|
|
79
|
+
for (const e of entries) {
|
|
80
|
+
const name = e.name.substring('worktree-'.length);
|
|
81
|
+
const full = path.join(worktreesDir, e.name);
|
|
82
|
+
const item = candidates.get(name) || { layouts: new Set(), mtime: 0 };
|
|
83
|
+
item.layouts.add('worktree');
|
|
84
|
+
item.mtime = Math.max(item.mtime, fs.statSync(full).mtime.getTime());
|
|
85
|
+
candidates.set(name, item);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 优先级 2b:本地布局候选(根 + .codespace/<app>/ 检出在非主干分支)
|
|
90
|
+
function addLocalCandidate(name, cwdPath) {
|
|
91
|
+
if (!name) return;
|
|
92
|
+
const item = candidates.get(name) || { layouts: new Set(), mtime: 0 };
|
|
93
|
+
item.layouts.add('local');
|
|
94
|
+
try {
|
|
95
|
+
item.mtime = Math.max(item.mtime, fs.statSync(path.join(cwdPath, '.git')).mtime.getTime());
|
|
96
|
+
} catch (_) { /* .git 状态时间不可读则保持 */ }
|
|
97
|
+
candidates.set(name, item);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const rootMain = detectMain(wsRoot);
|
|
101
|
+
const rootBranch = currentBranch(wsRoot);
|
|
102
|
+
if (rootBranch && (!rootMain || rootBranch !== rootMain)) {
|
|
103
|
+
addLocalCandidate(rootBranch, wsRoot);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const codeDir = path.join(wsRoot, '.codespace');
|
|
107
|
+
if (fs.existsSync(codeDir)) {
|
|
108
|
+
for (const app of fs.readdirSync(codeDir).sort()) {
|
|
109
|
+
const appDir = path.join(codeDir, app);
|
|
110
|
+
if (!fs.existsSync(path.join(appDir, '.git'))) continue;
|
|
111
|
+
const appMain = detectMain(appDir);
|
|
112
|
+
const appBranch = currentBranch(appDir);
|
|
113
|
+
if (appBranch && (!appMain || appBranch !== appMain)) {
|
|
114
|
+
addLocalCandidate(appBranch, appDir);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (candidates.size === 0) {
|
|
120
|
+
console.error('❌ 未找到任何进行中的需求(无 worktree,且无仓库检出在非主干分支)');
|
|
121
|
+
console.error(' worktree 模式请先执行 cbb-worktree-init;本地模式请先执行 cbb-local-mode');
|
|
122
|
+
console.log('---');
|
|
123
|
+
console.log('NO_WORKTREE');
|
|
124
|
+
process.exit(2);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 唯一候选 → 自动选用
|
|
128
|
+
if (candidates.size === 1) {
|
|
129
|
+
const [name] = [...candidates.keys()];
|
|
130
|
+
const layouts = [...candidates.get(name).layouts].join('+');
|
|
131
|
+
console.log('✅ 自动选用唯一进行中需求:' + name + '(' + layouts + ')');
|
|
132
|
+
console.log('---');
|
|
133
|
+
console.log(name);
|
|
134
|
+
process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 多候选 → 按 mtime 倒序列出
|
|
138
|
+
const sorted = [...candidates.entries()].sort((a, b) => b[1].mtime - a[1].mtime);
|
|
139
|
+
console.log('⚠️ 检测到 ' + sorted.length + ' 个进行中的需求(按最近活动排序):');
|
|
140
|
+
sorted.forEach(([name, item], i) => {
|
|
141
|
+
const layouts = [...item.layouts].join('+');
|
|
142
|
+
const tag = i === 0 ? ' ⭐ (推荐:最近活动)' : '';
|
|
143
|
+
console.log(' [' + (i + 1) + '] ' + name + '(' + layouts + ')' + tag);
|
|
144
|
+
});
|
|
145
|
+
console.log('请在对话中输入序号(1/2/3)或完整分支名:');
|
|
146
|
+
console.log('---');
|
|
147
|
+
console.log('MULTIPLE_WORKTREEES');
|
|
148
|
+
process.exit(1);
|
|
@@ -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 内
|
|
9
|
-
* 兜底:当前目录含
|
|
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
|
-
// 兜底:当前目录含
|
|
47
|
+
// 兜底:当前目录含 CBB-WORKSPACE.json
|
|
48
48
|
if (!wsRoot) {
|
|
49
49
|
const cwd = process.cwd();
|
|
50
|
-
if (fs.existsSync(path.join(cwd, '
|
|
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, '
|
|
56
|
+
if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'CBB-WORKSPACE.json'))) {
|
|
57
57
|
console.error('❌ 未找到工作空间根目录');
|
|
58
|
-
console.error(' 原因:git worktree list 失败且当前目录无
|
|
59
|
-
console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含
|
|
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
|
|
|
@@ -78,19 +78,28 @@ function removeWt(repoPath, wtPath, name) {
|
|
|
78
78
|
|
|
79
79
|
// 第 3 层:目录被锁
|
|
80
80
|
lockedDirs.push(wtPath);
|
|
81
|
-
console.log('⏳ ' + name + '
|
|
81
|
+
console.log('⏳ ' + name + ' 元数据已清理,物理目录被锁定(init 不会自动删除目录,需手动清理)');
|
|
82
82
|
results.push({ name, status: 'locked' });
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// 1. 应用 worktrees
|
|
86
|
-
const configPath = path.join(wsRoot, '
|
|
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
|
|
|
90
90
|
const apps = config.apps || [];
|
|
91
|
+
/** 解析 app worktree 物理路径:新布局 .codespace/<app> 优先,兼容 ≤beta.23 旧平铺 <app> */
|
|
92
|
+
function resolveAppWt(appName) {
|
|
93
|
+
const nested = path.join(wtDir, '.codespace', appName);
|
|
94
|
+
if (fs.existsSync(path.join(nested, '.git'))) return nested;
|
|
95
|
+
const legacy = path.join(wtDir, appName);
|
|
96
|
+
if (fs.existsSync(path.join(legacy, '.git'))) return legacy;
|
|
97
|
+
return nested;
|
|
98
|
+
}
|
|
99
|
+
|
|
91
100
|
console.log('=== 移除应用 Worktrees ===');
|
|
92
101
|
for (const app of apps) {
|
|
93
|
-
const appWt =
|
|
102
|
+
const appWt = resolveAppWt(app.name);
|
|
94
103
|
const appPath = path.join(wsRoot, '.codespace', app.name);
|
|
95
104
|
removeWt(appPath, appWt, app.name);
|
|
96
105
|
}
|
|
@@ -110,7 +119,7 @@ if (lockedDirs.length > 0) {
|
|
|
110
119
|
console.log('');
|
|
111
120
|
console.log('⏳ 以下目录被外部进程占用(IDE 等),git 元数据已清理,物理目录仍保留:');
|
|
112
121
|
lockedDirs.forEach(d => console.log(' - ' + d));
|
|
113
|
-
console.log(' → 请关闭占用这些目录的程序(如 IDE
|
|
122
|
+
console.log(' → 请关闭占用这些目录的程序(如 IDE)后手动删除(init 不再自动清理物理目录)');
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
console.log('---');
|
|
@@ -152,19 +152,28 @@ 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, '
|
|
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
|
|
|
159
159
|
const apps = config.apps || [];
|
|
160
160
|
const wtDir = path.join(wsRoot, '.worktrees', 'worktree-' + branch);
|
|
161
161
|
|
|
162
|
+
/** 解析 app worktree 物理路径:新布局 .codespace/<app> 优先,兼容 ≤beta.23 旧平铺 <app> */
|
|
163
|
+
function resolveAppWt(appName) {
|
|
164
|
+
const nested = path.join(wtDir, '.codespace', appName);
|
|
165
|
+
if (fs.existsSync(path.join(nested, '.git'))) return nested;
|
|
166
|
+
const legacy = path.join(wtDir, appName);
|
|
167
|
+
if (fs.existsSync(path.join(legacy, '.git'))) return legacy;
|
|
168
|
+
return nested;
|
|
169
|
+
}
|
|
170
|
+
|
|
162
171
|
const results = [];
|
|
163
172
|
|
|
164
173
|
results.push(checkRepo('workspace', wsRoot, wtDir));
|
|
165
174
|
|
|
166
175
|
for (const app of apps) {
|
|
167
|
-
const appWt =
|
|
176
|
+
const appWt = resolveAppWt(app.name);
|
|
168
177
|
const appPath = path.join(wsRoot, '.codespace', app.name);
|
|
169
178
|
results.push(checkRepo(app.name, appPath, appWt));
|
|
170
179
|
}
|