@jspg-ai/coding-bb 0.0.3-beta.6 → 0.0.3-beta.8
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 +1 -1
- package/cbb/lib/install/claude-code.js +1 -3
- package/cbb/lib/install/codebuddy.js +0 -2
- package/cbb/lib/install/init.js +115 -85
- package/cbb/lib/install/opencode.js +1 -5
- package/cbb/lib/install/qoder.js +1 -3
- package/cbb/lib/install/trae.js +0 -2
- package/cbb/lib/openspec/index.js +337 -554
- package/cbb/lib/superpowers/index.js +246 -265
- 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 +31 -22
- package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +21 -22
- package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +66 -30
- package/config/openspec/schemas/spec-driven/schema.yaml +21 -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 +6 -6
- 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 +1 -1
- 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 -63
- package/cbb/worktrees/commands/worktree-init.md +0 -50
- package/cbb/worktrees/commands/worktree-push.md +0 -42
|
@@ -103,7 +103,7 @@ trigger: always_on
|
|
|
103
103
|
|
|
104
104
|
**仅当工作目录是业务空间根(存在 `workspace-config.json`)时生效:写操作命令必须落在需求工作树内。**
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`cbb-worktree-init` skill,或斜杠命令 `/cbb-worktree-init`),之后:
|
|
107
107
|
|
|
108
108
|
- 一切产生写操作的命令(git commit / openspec / 构建 / 测试 / 文件修改)必须以 `.worktrees/worktree-<需求名>/`(或其应用子目录)为工作目录:显式 `cd` 或绝对路径
|
|
109
109
|
- 禁止在空间根执行写操作:不在主分支提交代码、不在空间根创建 openspec 变更产物、不改 `.codespace/` 基准代码
|
|
@@ -13,9 +13,7 @@ module.exports = {
|
|
|
13
13
|
rulesDir: '.claude/rules',
|
|
14
14
|
skillsDir: '.claude/skills',
|
|
15
15
|
commandsDir: '.claude/commands/opsx',
|
|
16
|
-
//
|
|
17
|
-
worktreeCommandsDir: '.claude/commands/cbb',
|
|
18
|
-
// 用户级 settings,写入全局生效,不污染项目目录
|
|
16
|
+
// 用户级 settings,写入全局生效,不污染项目目录
|
|
19
17
|
settingsFile: path.join(os.homedir(), '.claude', 'settings.json'),
|
|
20
18
|
settingsFileIsUserLevel: true,
|
|
21
19
|
hookEvents: ['UserPromptSubmit'],
|
|
@@ -21,8 +21,6 @@ module.exports = {
|
|
|
21
21
|
rulesDir: '.codebuddy/rules',
|
|
22
22
|
skillsDir: '.codebuddy/skills',
|
|
23
23
|
commandsDir: '.codebuddy/commands/opsx',
|
|
24
|
-
// worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
|
|
25
|
-
worktreeCommandsDir: '.codebuddy/commands/cbb',
|
|
26
24
|
// 规则 frontmatter 改写:Qoder 风格 → CodeBuddy 风格
|
|
27
25
|
ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
|
|
28
26
|
// 用户级 settings,写入全局生效,不污染项目目录
|
package/cbb/lib/install/init.js
CHANGED
|
@@ -61,8 +61,8 @@ const adapters = [
|
|
|
61
61
|
require('./claude-code'),
|
|
62
62
|
];
|
|
63
63
|
|
|
64
|
-
// superpowers 部署白名单:仅装 openspec 工作流硬依赖 + 方法论基底(源仓库仍保留全量
|
|
65
|
-
// 供
|
|
64
|
+
// superpowers 部署白名单:仅装 openspec 工作流硬依赖 + 方法论基底(源仓库仍保留全量 15 个,
|
|
65
|
+
// 供 cbbm update --upstream-superpowers 维护;砍掉的与 openspec 工作流重叠或属低频场景)
|
|
66
66
|
const SUPERPOWERS_WHITELIST = [
|
|
67
67
|
'writing-plans', // openspec apply:生成 plan.md(schema.yaml 引用)
|
|
68
68
|
'subagent-driven-development', // openspec apply:执行 plan.md(schema.yaml 引用)
|
|
@@ -72,8 +72,9 @@ const SUPERPOWERS_WHITELIST = [
|
|
|
72
72
|
'test-driven-development', // TDD 计划结构 + TDD Evidence 方法论基底
|
|
73
73
|
];
|
|
74
74
|
|
|
75
|
-
// worktree
|
|
76
|
-
//
|
|
75
|
+
// worktree 管理 skill 清单:init / close / push 三件套(SKILL.md + scripts)。
|
|
76
|
+
// 按 skill 形态部署到各工具的 skillsDir,使这三个能力可被 AI 在对话中自动触发
|
|
77
|
+
// (description 驱动),同时工具也会把它们暴露为斜杠命令供用户手动指定。
|
|
77
78
|
const WORKTREE_SKILLS = ['cbb-worktree-init', 'cbb-worktree-close', 'cbb-worktree-push'];
|
|
78
79
|
|
|
79
80
|
// 装到空间的 tools skills:当前不分发。
|
|
@@ -221,6 +222,39 @@ function removePath(targetPath) {
|
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
224
|
|
|
225
|
+
/**
|
|
226
|
+
* 清理因删除文件/目录而变空的祖先目录(从深到浅,止于 TARGET_DIR)。
|
|
227
|
+
*
|
|
228
|
+
* 删除清单路径只删到该路径本身,其父目录会留空(如改名后残留的空 `.cbb/skills/`)。
|
|
229
|
+
* 此处统一收尾,升级与卸载共用。仅删除「存在且为空」的目录,非空目录(含用户文件)
|
|
230
|
+
* 一律保留。
|
|
231
|
+
*
|
|
232
|
+
* @param {Iterable<string>} relativePaths 已删除的相对路径(正斜杠)
|
|
233
|
+
* @returns {string[]} 实际删除的空目录相对路径
|
|
234
|
+
*/
|
|
235
|
+
function cleanupEmptyParentDirs(relativePaths) {
|
|
236
|
+
const dirsToCheck = new Set();
|
|
237
|
+
for (const relativePath of relativePaths) {
|
|
238
|
+
let dir = path.dirname(relativePath);
|
|
239
|
+
while (dir && dir !== '.') {
|
|
240
|
+
dirsToCheck.add(dir);
|
|
241
|
+
dir = path.dirname(dir);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const removed = [];
|
|
246
|
+
[...dirsToCheck]
|
|
247
|
+
.sort((a, b) => b.split('/').length - a.split('/').length)
|
|
248
|
+
.forEach(dir => {
|
|
249
|
+
const fullPath = path.join(TARGET_DIR, dir);
|
|
250
|
+
if (fs.existsSync(fullPath) && fs.readdirSync(fullPath).length === 0) {
|
|
251
|
+
removePath(fullPath);
|
|
252
|
+
removed.push(dir);
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
return removed;
|
|
256
|
+
}
|
|
257
|
+
|
|
224
258
|
/**
|
|
225
259
|
* 安全删除目标路径(文件或目录)
|
|
226
260
|
* 在清单中 → 直接删除(本包旧版本)
|
|
@@ -580,29 +614,6 @@ function deployCommandFiles(adapter, srcDir, destDir, prefix, filter) {
|
|
|
580
614
|
return { count: commandFiles.length, names: commandFiles.map(f => prefix + f) };
|
|
581
615
|
}
|
|
582
616
|
|
|
583
|
-
/**
|
|
584
|
-
* worktree 运行时部署:SKILL.md + scripts 复制到 .cbb/skills/<name>/(每空间一份,不分工具)。
|
|
585
|
-
* 单形态 command 收敛后,worktree 不进各工具的 skills 目录——新版工具会把 skills 暴露成
|
|
586
|
-
* 斜杠命令,与命令文件在面板里重复;脚本与流程文档统一放 .cbb/skills/,命令文件指向此处。
|
|
587
|
-
*/
|
|
588
|
-
function deployWorktreeRuntime(newPaths) {
|
|
589
|
-
const srcDir = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'skills');
|
|
590
|
-
if (!fs.existsSync(srcDir)) return 0;
|
|
591
|
-
const runtimeDir = path.join(TARGET_DIR, '.cbb', 'skills');
|
|
592
|
-
fs.mkdirSync(runtimeDir, { recursive: true });
|
|
593
|
-
let count = 0;
|
|
594
|
-
WORKTREE_SKILLS.forEach(name => {
|
|
595
|
-
const src = path.join(srcDir, name);
|
|
596
|
-
if (!fs.existsSync(src)) return;
|
|
597
|
-
const destDir = path.join(runtimeDir, name);
|
|
598
|
-
removePath(destDir);
|
|
599
|
-
fs.cpSync(src, destDir, { recursive: true });
|
|
600
|
-
newPaths.add(`.cbb/skills/${name}`);
|
|
601
|
-
count++;
|
|
602
|
-
});
|
|
603
|
-
return count;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
617
|
/**
|
|
607
618
|
* 命令 frontmatter 消毒:opencode 新版校验命令配置(description 必须为 string | undefined),
|
|
608
619
|
* 上游个别命令(openspec/commands/update.md)的 description 为空值(YAML 解析为 null),
|
|
@@ -656,13 +667,6 @@ function deployCommands(adapter, isUpgrade, managedPaths, srcDir, filter) {
|
|
|
656
667
|
adapter, srcDir, path.join(TARGET_DIR, adapter.commandsDir), adapter.commandPrefix || '', filter);
|
|
657
668
|
}
|
|
658
669
|
|
|
659
|
-
/** worktree 管理命令(cbb/worktrees/commands/ → adapter.worktreeCommandsDir) */
|
|
660
|
-
function deployWorktreeCommands(adapter, srcDir, filter) {
|
|
661
|
-
if (!adapter.worktreeCommandsDir) return { count: 0, names: [] };
|
|
662
|
-
return deployCommandFiles(
|
|
663
|
-
adapter, srcDir, path.join(TARGET_DIR, adapter.worktreeCommandsDir), adapter.worktreeCommandPrefix || '', filter);
|
|
664
|
-
}
|
|
665
|
-
|
|
666
670
|
// ── 设置 OpenSpec 工作流 ──────────────────────────────────
|
|
667
671
|
|
|
668
672
|
/**
|
|
@@ -1050,6 +1054,20 @@ async function init(targetDir, options = {}) {
|
|
|
1050
1054
|
if (stdCount > 0) log(`规范 Skills → ${skillsDests.join(', ')} (${stdCount} 个)`, 'success');
|
|
1051
1055
|
if (extCount > 0) log(`扩展 Skills → ${skillsDests.join(', ')} (${extCount} 个)`, 'success');
|
|
1052
1056
|
|
|
1057
|
+
// 部署 worktree 管理 Skills(init / close / push;skill 形态,可被对话自动触发)
|
|
1058
|
+
const worktreeSkillsSrc = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'skills');
|
|
1059
|
+
let wtCount = 0;
|
|
1060
|
+
if (fs.existsSync(worktreeSkillsSrc)) {
|
|
1061
|
+
skillsAdapters.forEach(adapter => {
|
|
1062
|
+
const wtResult = deploySkills(adapter, isUpgrade, managedPaths, worktreeSkillsSrc, WORKTREE_SKILLS);
|
|
1063
|
+
if (wtResult.count > 0) {
|
|
1064
|
+
wtCount = wtResult.count;
|
|
1065
|
+
wtResult.names.forEach(name => newPaths.add(`${adapter.skillsDir}/${name}`));
|
|
1066
|
+
}
|
|
1067
|
+
});
|
|
1068
|
+
if (wtCount > 0) log(`Worktree Skills → ${skillsDests.join(', ')} (${wtCount} 个)`, 'success');
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1053
1071
|
// 部署 Superpowers Skills(白名单:openspec 工作流依赖 + 方法论基底)
|
|
1054
1072
|
const superpowersSkillsSrc = superpowers.SUPERPOWERS_SKILLS_DIR;
|
|
1055
1073
|
let spCount = 0;
|
|
@@ -1071,22 +1089,16 @@ async function init(targetDir, options = {}) {
|
|
|
1071
1089
|
await detectUserLevelSuperpowers(selectedAdapters, yes);
|
|
1072
1090
|
}
|
|
1073
1091
|
|
|
1074
|
-
//
|
|
1075
|
-
const runtimeCount = deployWorktreeRuntime(newPaths);
|
|
1076
|
-
if (runtimeCount > 0) log(`worktree 运行时 → .cbb/skills (${runtimeCount} 个)`, 'success');
|
|
1077
|
-
|
|
1078
|
-
// 安装 Commands(官方 11 个 → /opsx:*,onboard 不分发;worktree 管理 → /cbb:worktree-*,init/close/push 三件套)
|
|
1092
|
+
// 安装 Commands(官方 11 个 → /opsx:*,onboard 不分发)
|
|
1079
1093
|
const commandsAdapters = selectedAdapters.filter(a => a.commandsDir);
|
|
1080
1094
|
if (commandsAdapters.length > 0) {
|
|
1081
1095
|
console.log(`\n ⚡ ${action} Commands...`);
|
|
1082
1096
|
const commandsBaseSrc = path.join(SHARED_STANDARDS_DIR, 'openspec', 'commands');
|
|
1083
|
-
const commandsExtendsSrc = path.join(SHARED_STANDARDS_DIR, 'cbb', 'worktrees', 'commands');
|
|
1084
|
-
const cmdFilter = ['worktree-init.md', 'worktree-close.md', 'worktree-push.md'];
|
|
1085
1097
|
const openspecCmdInclude = fs.readdirSync(commandsBaseSrc)
|
|
1086
1098
|
.filter(f => f.endsWith('.md') && !OPENSPEC_COMMANDS_EXCLUDE.includes(f));
|
|
1087
1099
|
|
|
1088
1100
|
const cmdDests = [...new Set(commandsAdapters
|
|
1089
|
-
.
|
|
1101
|
+
.map(a => a.commandsDir)
|
|
1090
1102
|
.filter(Boolean))];
|
|
1091
1103
|
let cmdCount = 0;
|
|
1092
1104
|
commandsAdapters.forEach(adapter => {
|
|
@@ -1097,12 +1109,6 @@ async function init(targetDir, options = {}) {
|
|
|
1097
1109
|
adapterCmdCount += baseResult.count;
|
|
1098
1110
|
baseResult.names.forEach(name => newPaths.add(`${adapter.commandsDir}/${name}`));
|
|
1099
1111
|
}
|
|
1100
|
-
// worktree 管理 Commands(cbb/worktrees/commands/)
|
|
1101
|
-
const extResult = deployWorktreeCommands(adapter, commandsExtendsSrc, cmdFilter);
|
|
1102
|
-
if (extResult.count > 0) {
|
|
1103
|
-
adapterCmdCount += extResult.count;
|
|
1104
|
-
extResult.names.forEach(name => newPaths.add(`${adapter.worktreeCommandsDir}/${name}`));
|
|
1105
|
-
}
|
|
1106
1112
|
cmdCount = Math.max(cmdCount, adapterCmdCount);
|
|
1107
1113
|
});
|
|
1108
1114
|
if (cmdCount > 0) log(`Commands → ${cmdDests.join(', ')} (${cmdCount} 个)`, 'success');
|
|
@@ -1168,6 +1174,8 @@ async function init(targetDir, options = {}) {
|
|
|
1168
1174
|
if (oldPaths.length > MAX_DISPLAY) {
|
|
1169
1175
|
log(` ... 还有 ${oldPaths.length - MAX_DISPLAY} 个`, 'dim');
|
|
1170
1176
|
}
|
|
1177
|
+
// 收尾:清掉因此变空的祖先目录(如改名后残留的空 .cbb/skills/)
|
|
1178
|
+
cleanupEmptyParentDirs(oldPaths).forEach(dir => log(` 清理空目录 ${dir}/`, 'dim'));
|
|
1171
1179
|
}
|
|
1172
1180
|
|
|
1173
1181
|
const kept = protectedKeptPaths(managedPaths, newPaths);
|
|
@@ -1948,22 +1956,7 @@ async function uninstall() {
|
|
|
1948
1956
|
});
|
|
1949
1957
|
|
|
1950
1958
|
// 清理可能变空的父目录(从深到浅)
|
|
1951
|
-
|
|
1952
|
-
managedPaths.forEach(relativePath => {
|
|
1953
|
-
let dir = path.dirname(relativePath);
|
|
1954
|
-
while (dir && dir !== '.') {
|
|
1955
|
-
dirsToCheck.add(dir);
|
|
1956
|
-
dir = path.dirname(dir);
|
|
1957
|
-
}
|
|
1958
|
-
});
|
|
1959
|
-
// 按深度排序,深层先处理
|
|
1960
|
-
[...dirsToCheck].sort((a, b) => b.split('/').length - a.split('/').length).forEach(dir => {
|
|
1961
|
-
const fullPath = path.join(TARGET_DIR, dir);
|
|
1962
|
-
if (fs.existsSync(fullPath) && fs.readdirSync(fullPath).length === 0) {
|
|
1963
|
-
removePath(fullPath);
|
|
1964
|
-
log(`清理空目录 ${dir}/`, 'success');
|
|
1965
|
-
}
|
|
1966
|
-
});
|
|
1959
|
+
cleanupEmptyParentDirs(managedPaths).forEach(dir => log(`清理空目录 ${dir}/`, 'success'));
|
|
1967
1960
|
|
|
1968
1961
|
// 删除清单文件和 .va 目录
|
|
1969
1962
|
removePath(manifestDir);
|
|
@@ -1981,11 +1974,50 @@ async function uninstall() {
|
|
|
1981
1974
|
console.log(`\n✅ 卸载完成!共移除 ${removed} 个文件/目录\n`);
|
|
1982
1975
|
}
|
|
1983
1976
|
|
|
1977
|
+
// ── 上游版本检查 ──────────────────────────────────────────────
|
|
1978
|
+
|
|
1979
|
+
/**
|
|
1980
|
+
* 检查 openspec / superpowers 是否有上游新版本(只读,不改动任何文件)。
|
|
1981
|
+
* 供 cbbm check-upstream 调用。
|
|
1982
|
+
*/
|
|
1983
|
+
async function checkUpstream() {
|
|
1984
|
+
const results = await Promise.allSettled([
|
|
1985
|
+
openspec.checkUpstream().then(r => ({ name: 'openspec', ...r })),
|
|
1986
|
+
superpowers.checkUpstream().then(r => ({ name: 'superpowers', ...r })),
|
|
1987
|
+
]);
|
|
1988
|
+
|
|
1989
|
+
let outdated = false;
|
|
1990
|
+
for (const r of results) {
|
|
1991
|
+
if (r.status === 'rejected') {
|
|
1992
|
+
log(`检查失败: ${r.reason.message}`, 'error');
|
|
1993
|
+
continue;
|
|
1994
|
+
}
|
|
1995
|
+
const { name, current, latest, outdated: isOutdated } = r.value;
|
|
1996
|
+
if (!latest) {
|
|
1997
|
+
log(`${name}: 无法获取上游版本`, 'warn');
|
|
1998
|
+
continue;
|
|
1999
|
+
}
|
|
2000
|
+
if (!current) {
|
|
2001
|
+
log(`${name}: 本地无 pin(上游最新 ${latest})`, 'warn');
|
|
2002
|
+
outdated = true;
|
|
2003
|
+
} else if (isOutdated) {
|
|
2004
|
+
log(`${name}: ${current} → ${latest}(有新版本)`, 'warn');
|
|
2005
|
+
outdated = true;
|
|
2006
|
+
} else {
|
|
2007
|
+
log(`${name}: ${current} 已是最新`, 'success');
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
if (outdated) {
|
|
2012
|
+
log('升级方式:修改对应 .version 的 pin 后,执行 cbbm update --upstream-openspec / --upstream-superpowers', 'info');
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
|
|
1984
2016
|
// ── CLI 入口 ──────────────────────────────────────────────
|
|
1985
2017
|
|
|
1986
2018
|
// 入口身份:cbb(用户命令) / cbbm(内部命令,由流程、hook、Agent 技能调用)
|
|
1987
2019
|
const ENTRY = process.env.CBB_ENTRY === 'cbbm' ? 'cbbm' : 'cbb';
|
|
1988
|
-
const INTERNAL_COMMANDS = ['check-update', 'wiki', 'wp'];
|
|
2020
|
+
const INTERNAL_COMMANDS = ['check-update', 'check-upstream', 'wiki', 'wp'];
|
|
1989
2021
|
const UPSTREAM_FLAGS = ['--upstream-superpowers', '--upstream-openspec'];
|
|
1990
2022
|
|
|
1991
2023
|
const args = process.argv.slice(2);
|
|
@@ -2024,11 +2056,11 @@ switch (command) {
|
|
|
2024
2056
|
const upstreamSuperpowers = restArgs.includes('--upstream-superpowers');
|
|
2025
2057
|
const upstreamOpenspec = restArgs.includes('--upstream-openspec');
|
|
2026
2058
|
if (upstreamSuperpowers || upstreamOpenspec) {
|
|
2027
|
-
//
|
|
2059
|
+
// 维护者选项:按 .version 的 pin 重新拉取上游原生内容到本包源仓库(发布流程用)
|
|
2028
2060
|
if (upstreamSuperpowers) {
|
|
2029
2061
|
superpowers.fetchLatestSkills().then(result => {
|
|
2030
2062
|
if (result.skipped) {
|
|
2031
|
-
log(`superpowers skills 已是最新 (${result.
|
|
2063
|
+
log(`superpowers skills 已是最新 (${result.tag})`, 'success');
|
|
2032
2064
|
}
|
|
2033
2065
|
const validation = superpowers.validateSkills();
|
|
2034
2066
|
if (!validation.valid) {
|
|
@@ -2044,22 +2076,13 @@ switch (command) {
|
|
|
2044
2076
|
}
|
|
2045
2077
|
if (upstreamOpenspec) {
|
|
2046
2078
|
openspec.fetchLatestOpenSpec().then(result => {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
}
|
|
2053
|
-
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2054
|
-
} else {
|
|
2055
|
-
const validation = openspec.validateDeployed();
|
|
2056
|
-
if (!validation.valid) {
|
|
2057
|
-
log(`本地 openspec 工作流不完整,请重新运行 cbb update --upstream-openspec:`, 'error');
|
|
2058
|
-
for (const m of validation.missing) log(` - 缺失 ${m}`, 'error');
|
|
2059
|
-
process.exit(1);
|
|
2060
|
-
}
|
|
2061
|
-
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2079
|
+
const validation = openspec.validateDeployed();
|
|
2080
|
+
if (!validation.valid) {
|
|
2081
|
+
log(`部署不完整,缺失: ${validation.missing.join(', ')}`, 'error');
|
|
2082
|
+
for (const m of validation.missing) log(` - 缺失 ${m}`, 'error');
|
|
2083
|
+
process.exit(1);
|
|
2062
2084
|
}
|
|
2085
|
+
log(`openspec 工作流完整性校验通过`, 'success');
|
|
2063
2086
|
}).catch(err => {
|
|
2064
2087
|
log(`更新失败: ${err.message}`, 'error');
|
|
2065
2088
|
process.exit(1);
|
|
@@ -2082,6 +2105,12 @@ switch (command) {
|
|
|
2082
2105
|
case 'check-update':
|
|
2083
2106
|
require('../utils/check-update.js');
|
|
2084
2107
|
break;
|
|
2108
|
+
case 'check-upstream':
|
|
2109
|
+
checkUpstream().catch(err => {
|
|
2110
|
+
log(err.message, 'error');
|
|
2111
|
+
process.exit(1);
|
|
2112
|
+
});
|
|
2113
|
+
break;
|
|
2085
2114
|
case 'wp':
|
|
2086
2115
|
require('../wiki/index.js').publish(restArgs);
|
|
2087
2116
|
break;
|
|
@@ -2113,11 +2142,12 @@ function showHelp() {
|
|
|
2113
2142
|
@jspg-ai/coding-bb v${pkg.version} — cbbm:内部命令(由流程 / hook / Agent 技能调用)
|
|
2114
2143
|
|
|
2115
2144
|
cbbm check-update 版本检查(用户级 hook 每日自动触发)
|
|
2145
|
+
cbbm check-upstream 检查 openspec / superpowers 是否有上游新版本
|
|
2116
2146
|
cbbm wiki / cbbm wp Wiki 查询与发布(AI 通过技能调用)
|
|
2117
2147
|
|
|
2118
|
-
|
|
2119
|
-
cbbm update --upstream-superpowers
|
|
2120
|
-
cbbm update --upstream-openspec
|
|
2148
|
+
维护者选项(按 .version 的 pin 重新拉取上游原生内容到本包源仓库):
|
|
2149
|
+
cbbm update --upstream-superpowers 按 pin tag 拉取 superpowers skills(走镜像)
|
|
2150
|
+
cbbm update --upstream-openspec 按 pin 版本从 npmmirror 渲染 OpenSpec 工作流
|
|
2121
2151
|
`);
|
|
2122
2152
|
return;
|
|
2123
2153
|
}
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
* 官方支持的配置位置:全局目录 / 项目根 / .opencode 目录内均会被发现)
|
|
10
10
|
* - skills:.opencode/skills/<name>/SKILL.md,结构与 Claude 同构
|
|
11
11
|
* - commands:命令名 = 文件名(嵌套目录无命名空间,且 init.md 等会撞内置 /init),
|
|
12
|
-
* 因此扁平化为 opsx-<name>.md(/opsx-propose
|
|
13
|
-
* cbb-<name>.md(/cbb-worktree-init),部署副本中的 /opsx: 与 /cbb: 引用同步改写
|
|
12
|
+
* 因此扁平化为 opsx-<name>.md(/opsx-propose);部署副本中的 /opsx: 与 /cbb: 引用同步改写
|
|
14
13
|
* - hooks:opencode 无 UserPromptSubmit 等价事件,版本检查 hook 不安装(settingsFile 留空即跳过)
|
|
15
14
|
*/
|
|
16
15
|
|
|
@@ -22,9 +21,6 @@ module.exports = {
|
|
|
22
21
|
commandsDir: '.opencode/commands',
|
|
23
22
|
// 部署时给命令文件名加此前缀(规避内置命令名冲突)
|
|
24
23
|
commandPrefix: 'opsx-',
|
|
25
|
-
// worktree 管理命令(非 openspec 上游)落在同一扁平目录,用 cbb- 前缀区分
|
|
26
|
-
worktreeCommandsDir: '.opencode/commands',
|
|
27
|
-
worktreeCommandPrefix: 'cbb-',
|
|
28
24
|
// 部署副本中将该引用串改写为 opencode 的命令风格(配合 commandPrefix)
|
|
29
25
|
contentRewrites: [['/opsx:', '/opsx-'], ['/cbb:', '/cbb-']],
|
|
30
26
|
// 命令显示名取自 frontmatter name,部署副本重写为 kebab-case(/opsx-propose,与文档一致)
|
package/cbb/lib/install/qoder.js
CHANGED
|
@@ -13,9 +13,7 @@ module.exports = {
|
|
|
13
13
|
rulesDir: '.qoder/rules',
|
|
14
14
|
skillsDir: '.qoder/skills',
|
|
15
15
|
commandsDir: '.qoder/commands/opsx',
|
|
16
|
-
//
|
|
17
|
-
worktreeCommandsDir: '.qoder/commands/cbb',
|
|
18
|
-
// 用户级 settings,写入全局生效,不污染项目目录
|
|
16
|
+
// 用户级 settings,写入全局生效,不污染项目目录
|
|
19
17
|
settingsFile: path.join(os.homedir(), '.qoder', 'settings.json'),
|
|
20
18
|
settingsFileIsUserLevel: true,
|
|
21
19
|
hookEvents: ['UserPromptSubmit'],
|
package/cbb/lib/install/trae.js
CHANGED
|
@@ -22,8 +22,6 @@ module.exports = {
|
|
|
22
22
|
rulesDir: '.trae/rules',
|
|
23
23
|
skillsDir: '.trae/skills',
|
|
24
24
|
commandsDir: '.trae/commands/opsx',
|
|
25
|
-
// worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
|
|
26
|
-
worktreeCommandsDir: '.trae/commands/cbb',
|
|
27
25
|
// 规则 frontmatter 改写:Qoder 风格 → Trae 风格
|
|
28
26
|
ruleRewrites: [['trigger: always_on', 'alwaysApply: true']],
|
|
29
27
|
// 用户级 hooks 配置(Trae 用 hooks.json,国内版目录为 ~/.trae-cn/)
|