@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.
Files changed (92) hide show
  1. package/cbb/dev-standards/rules/cbb-ai-behavior.md +1 -1
  2. package/cbb/lib/install/claude-code.js +1 -3
  3. package/cbb/lib/install/codebuddy.js +0 -2
  4. package/cbb/lib/install/init.js +115 -85
  5. package/cbb/lib/install/opencode.js +1 -5
  6. package/cbb/lib/install/qoder.js +1 -3
  7. package/cbb/lib/install/trae.js +0 -2
  8. package/cbb/lib/openspec/index.js +337 -554
  9. package/cbb/lib/superpowers/index.js +246 -265
  10. package/cbb/lib/utils/tar.js +92 -0
  11. package/cbb/lib/utils/upstream.js +90 -0
  12. package/cbb/worktrees/skills/cbb-worktree-close/SKILL.md +31 -22
  13. package/cbb/worktrees/skills/cbb-worktree-init/SKILL.md +21 -22
  14. package/cbb/worktrees/skills/cbb-worktree-push/SKILL.md +66 -30
  15. package/config/openspec/schemas/spec-driven/schema.yaml +21 -30
  16. package/config/openspec/schemas/spec-driven/templates/design.md +0 -18
  17. package/config/openspec/schemas/spec-driven/templates/proposal.md +4 -3
  18. package/config/upstream-mirrors.json +12 -0
  19. package/config/workspace-agents.sample.md +6 -6
  20. package/openspec/.version +2 -3
  21. package/openspec/commands/apply.md +189 -175
  22. package/openspec/commands/archive.md +237 -216
  23. package/openspec/commands/bulk-archive.md +355 -327
  24. package/openspec/commands/continue.md +116 -105
  25. package/openspec/commands/explore.md +230 -199
  26. package/openspec/commands/ff.md +115 -104
  27. package/openspec/commands/new.md +74 -63
  28. package/openspec/commands/onboard.md +557 -548
  29. package/openspec/commands/propose.md +161 -150
  30. package/openspec/commands/sync.md +277 -249
  31. package/openspec/commands/update.md +92 -80
  32. package/openspec/commands/verify.md +175 -162
  33. package/openspec/skills/openspec-apply-change/SKILL.md +20 -5
  34. package/openspec/skills/openspec-archive-change/SKILL.md +30 -8
  35. package/openspec/skills/openspec-bulk-archive-change/SKILL.md +36 -6
  36. package/openspec/skills/openspec-continue-change/SKILL.md +14 -2
  37. package/openspec/skills/openspec-explore/SKILL.md +21 -9
  38. package/openspec/skills/openspec-ff-change/SKILL.md +14 -2
  39. package/openspec/skills/openspec-new-change/SKILL.md +13 -1
  40. package/openspec/skills/openspec-onboard/SKILL.md +49 -39
  41. package/openspec/skills/openspec-propose/SKILL.md +15 -3
  42. package/openspec/skills/openspec-sync-specs/SKILL.md +31 -2
  43. package/openspec/skills/openspec-update-change/SKILL.md +27 -14
  44. package/openspec/skills/openspec-verify-change/SKILL.md +17 -3
  45. package/package.json +1 -1
  46. package/superpowers/.version +4 -4
  47. package/superpowers/skills/brainstorming/SKILL.md +47 -12
  48. package/superpowers/skills/brainstorming/scripts/frame-template.html +213 -213
  49. package/superpowers/skills/brainstorming/scripts/server.cjs +723 -723
  50. package/superpowers/skills/brainstorming/visual-companion.md +6 -6
  51. package/superpowers/skills/diagnosing-superpowers/SKILL.md +120 -0
  52. package/superpowers/skills/diagnosing-superpowers/prompts/analyst-common.md +38 -0
  53. package/superpowers/skills/diagnosing-superpowers/prompts/cost-and-time.md +28 -0
  54. package/superpowers/skills/diagnosing-superpowers/prompts/plan-adherence.md +29 -0
  55. package/superpowers/skills/diagnosing-superpowers/prompts/quality-evidence.md +26 -0
  56. package/superpowers/skills/diagnosing-superpowers/prompts/repeated-work.md +30 -0
  57. package/superpowers/skills/diagnosing-superpowers/prompts/request-conflicts.md +20 -0
  58. package/superpowers/skills/diagnosing-superpowers/prompts/scrub-audit.md +33 -0
  59. package/superpowers/skills/diagnosing-superpowers/prompts/scrub.md +29 -0
  60. package/superpowers/skills/diagnosing-superpowers/prompts/similar-session.md +38 -0
  61. package/superpowers/skills/diagnosing-superpowers/prompts/skill-timeline.md +30 -0
  62. package/superpowers/skills/diagnosing-superpowers/prompts/stumbles.md +28 -0
  63. package/superpowers/skills/diagnosing-superpowers/references/context-safety.md +22 -0
  64. package/superpowers/skills/diagnosing-superpowers/references/github-issues.md +47 -0
  65. package/superpowers/skills/diagnosing-superpowers/references/redaction-policy.md +34 -0
  66. package/superpowers/skills/diagnosing-superpowers/references/session-discovery.md +31 -0
  67. package/superpowers/skills/diagnosing-superpowers/templates/bundle-README.md +77 -0
  68. package/superpowers/skills/diagnosing-superpowers/templates/case.md +64 -0
  69. package/superpowers/skills/diagnosing-superpowers/templates/issue.md +51 -0
  70. package/superpowers/skills/diagnosing-superpowers/templates/report.md +82 -0
  71. package/superpowers/skills/executing-plans/SKILL.md +350 -41
  72. package/superpowers/skills/executing-plans/scripts/task-done +52 -0
  73. package/superpowers/skills/executing-plans/scripts/task-start +28 -0
  74. package/superpowers/skills/requesting-code-review/SKILL.md +1 -1
  75. package/superpowers/skills/requesting-code-review/code-reviewer.md +17 -0
  76. package/superpowers/skills/subagent-driven-development/SKILL.md +18 -18
  77. package/superpowers/skills/subagent-driven-development/re-review-prompt.md +1 -1
  78. package/superpowers/skills/subagent-driven-development/scripts/review-package +53 -46
  79. package/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +82 -40
  80. package/superpowers/skills/subagent-driven-development/scripts/task-brief +43 -41
  81. package/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +2 -2
  82. package/superpowers/skills/systematic-debugging/root-cause-tracing.md +1 -1
  83. package/superpowers/skills/test-driven-development/SKILL.md +10 -0
  84. package/superpowers/skills/using-superpowers/SKILL.md +2 -0
  85. package/superpowers/skills/using-superpowers/references/claude-code-tools.md +29 -0
  86. package/superpowers/skills/using-superpowers/references/muse-tools.md +35 -0
  87. package/superpowers/skills/writing-plans/SKILL.md +30 -9
  88. package/superpowers/skills/writing-skills/SKILL.md +4 -2
  89. package/superpowers/skills/writing-skills/graphviz-conventions.dot +171 -171
  90. package/cbb/worktrees/commands/worktree-close.md +0 -63
  91. package/cbb/worktrees/commands/worktree-init.md +0 -50
  92. 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
- 业务空间根(主分支)只负责组织与调度,不做需求开发。接到需求先建工作树(`/cbb:worktree-init` `/cbb-worktree-init`),之后:
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
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
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,写入全局生效,不污染项目目录
@@ -61,8 +61,8 @@ const adapters = [
61
61
  require('./claude-code'),
62
62
  ];
63
63
 
64
- // superpowers 部署白名单:仅装 openspec 工作流硬依赖 + 方法论基底(源仓库仍保留全量 14 个,
65
- // 供 cbb update --upstream-superpowers 维护;砍掉的与 openspec 工作流重叠或属低频场景)
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 运行时部署清单:init / close / push 三件套(SKILL.md + scripts),
76
- // 部署到 .cbb/skills/<name>/(每空间一份,不分工具;命令文件统一指向此处)
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
- // worktree 运行时(SKILL.md + scripts)→ .cbb/skills/(每空间一份,不分工具)
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
- .flatMap(a => [a.commandsDir, a.worktreeCommandsDir])
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
- const dirsToCheck = new Set();
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
- // 维护者选项:从 GitHub 拉取上游原生内容到本包源仓库(发布流程用)
2059
+ // 维护者选项:按 .version 的 pin 重新拉取上游原生内容到本包源仓库(发布流程用)
2028
2060
  if (upstreamSuperpowers) {
2029
2061
  superpowers.fetchLatestSkills().then(result => {
2030
2062
  if (result.skipped) {
2031
- log(`superpowers skills 已是最新 (${result.sha.slice(0, 8)})`, 'success');
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
- if (!result.skipped) {
2048
- const validation = openspec.validateDeployed();
2049
- if (!validation.valid) {
2050
- log(`部署不完整,缺失: ${validation.missing.join(', ')}`, 'error');
2051
- process.exit(1);
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 GitHub 拉取最新 superpowers skills
2120
- cbbm update --upstream-openspec GitHub 拉取最新 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);worktree 管理命令同理扁平化为
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,与文档一致)
@@ -13,9 +13,7 @@ module.exports = {
13
13
  rulesDir: '.qoder/rules',
14
14
  skillsDir: '.qoder/skills',
15
15
  commandsDir: '.qoder/commands/opsx',
16
- // worktree 管理命令(非 openspec 上游):独立命名空间 /cbb:worktree-*
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'],
@@ -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/)