@jspg-ai/coding-bb 0.0.1

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 (183) hide show
  1. package/README.md +41 -0
  2. package/cbb/dev-standards/rules/cbb-ai-behavior.md +104 -0
  3. package/cbb/dev-standards/rules/cbb-coding-rule.md +50 -0
  4. package/cbb/dev-standards/rules/cbb-priority.md +56 -0
  5. package/cbb/dev-standards/skills/architecture-specs/SKILL.md +129 -0
  6. package/cbb/dev-standards/skills/coding-specs/SKILL.md +376 -0
  7. package/cbb/dev-standards/skills/coding-specs/references/concurrency.md +53 -0
  8. package/cbb/dev-standards/skills/coding-specs/references/config-center.md +16 -0
  9. package/cbb/dev-standards/skills/coding-specs/references/distributed.md +42 -0
  10. package/cbb/dev-standards/skills/coding-specs/references/es-coding.md +60 -0
  11. package/cbb/dev-standards/skills/coding-specs/references/scheduled-task.md +25 -0
  12. package/cbb/dev-standards/skills/coding-specs/references/security.md +11 -0
  13. package/cbb/dev-standards/skills/coding-specs/references/unit-testing.md +43 -0
  14. package/cbb/dev-standards/skills/es-design-specs/SKILL.md +104 -0
  15. package/cbb/dev-standards/skills/mysql-design-specs/SKILL.md +89 -0
  16. package/cbb/lib/install/claude-code.js +20 -0
  17. package/cbb/lib/install/cleanup.js +64 -0
  18. package/cbb/lib/install/init.js +1875 -0
  19. package/cbb/lib/install/qoder.js +20 -0
  20. package/cbb/lib/install/workspaces.js +232 -0
  21. package/cbb/lib/openspec/index.js +554 -0
  22. package/cbb/lib/superpowers/index.js +265 -0
  23. package/cbb/lib/utils/check-update.js +147 -0
  24. package/cbb/lib/utils/checkbox.js +383 -0
  25. package/cbb/lib/utils/gitignore.js +69 -0
  26. package/cbb/lib/utils/output.js +64 -0
  27. package/cbb/lib/utils/settings.js +119 -0
  28. package/cbb/lib/utils/version.js +135 -0
  29. package/cbb/lib/wiki/api-client.js +358 -0
  30. package/cbb/lib/wiki/cli.js +427 -0
  31. package/cbb/lib/wiki/convert.js +464 -0
  32. package/cbb/lib/wiki/index.js +218 -0
  33. package/cbb/lib/wiki/mermaid-guard.js +103 -0
  34. package/cbb/lib/wiki/split.js +131 -0
  35. package/cbb/tools/cbb-decompile-jar/SKILL.md +220 -0
  36. package/cbb/tools/cbb-decompile-jar/scripts/decompile.py +863 -0
  37. package/cbb/tools/cbb-design-to-wiki/SKILL.md +180 -0
  38. package/cbb/tools/cbb-mvn-guide/SKILL.md +281 -0
  39. package/cbb/tools/cbb-mvn-guide/scripts/mvn_jdk_manager.py +378 -0
  40. package/cbb/tools/cbb-mvn-guide/scripts/mvn_pom_jdk_reader.py +197 -0
  41. package/cbb/tools/cbb-plantuml-authoring/SKILL.md +448 -0
  42. package/cbb/tools/cbb-plantuml-authoring/references/drawing-templates.md +479 -0
  43. package/cbb/tools/cbb-wiki-ops/SKILL.md +134 -0
  44. package/cbb/tools/cbb-wiki-ops/scripts/check-auth.js +44 -0
  45. package/cbb/worktrees/_shared/scripts/find-target-worktree.js +96 -0
  46. package/cbb/worktrees/_shared/scripts/find-workspace-root.js +67 -0
  47. package/cbb/worktrees/_shared/scripts/push-core.js +136 -0
  48. package/cbb/worktrees/_shared/scripts/silence-popup.js +23 -0
  49. package/cbb/worktrees/commands/close.md +64 -0
  50. package/cbb/worktrees/commands/extend.md +65 -0
  51. package/cbb/worktrees/commands/init.md +55 -0
  52. package/cbb/worktrees/commands/push.md +42 -0
  53. package/cbb/worktrees/skills/openspec-close-worktree/SKILL.md +449 -0
  54. package/cbb/worktrees/skills/openspec-close-worktree/scripts/check-env.js +76 -0
  55. package/cbb/worktrees/skills/openspec-close-worktree/scripts/check-unarchived.js +48 -0
  56. package/cbb/worktrees/skills/openspec-close-worktree/scripts/delete-branches.js +136 -0
  57. package/cbb/worktrees/skills/openspec-close-worktree/scripts/discover-apps.js +76 -0
  58. package/cbb/worktrees/skills/openspec-close-worktree/scripts/find-target-worktree.js +96 -0
  59. package/cbb/worktrees/skills/openspec-close-worktree/scripts/find-workspace-root.js +67 -0
  60. package/cbb/worktrees/skills/openspec-close-worktree/scripts/remove-worktrees.js +124 -0
  61. package/cbb/worktrees/skills/openspec-close-worktree/scripts/safety-check.js +174 -0
  62. package/cbb/worktrees/skills/openspec-close-worktree/scripts/silence-popup.js +23 -0
  63. package/cbb/worktrees/skills/openspec-extend-worktree/SKILL.md +390 -0
  64. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/check-env.js +95 -0
  65. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/check-repos.js +98 -0
  66. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/create-branches-and-worktrees.js +135 -0
  67. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/find-target-worktree.js +96 -0
  68. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/find-workspace-root.js +67 -0
  69. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/install-ai.js +150 -0
  70. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/list-available-apps.js +88 -0
  71. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/push-core.js +136 -0
  72. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/silence-popup.js +23 -0
  73. package/cbb/worktrees/skills/openspec-extend-worktree/scripts/sync-repos.js +93 -0
  74. package/cbb/worktrees/skills/openspec-init-worktree/SKILL.md +539 -0
  75. package/cbb/worktrees/skills/openspec-init-worktree/scripts/auto-open.js +136 -0
  76. package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-env-deep.js +87 -0
  77. package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-env.js +90 -0
  78. package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-repos.js +171 -0
  79. package/cbb/worktrees/skills/openspec-init-worktree/scripts/create-branches.js +103 -0
  80. package/cbb/worktrees/skills/openspec-init-worktree/scripts/create-worktrees.js +154 -0
  81. package/cbb/worktrees/skills/openspec-init-worktree/scripts/find-workspace-root.js +67 -0
  82. package/cbb/worktrees/skills/openspec-init-worktree/scripts/generate-app-options.js +93 -0
  83. package/cbb/worktrees/skills/openspec-init-worktree/scripts/install-ai.js +177 -0
  84. package/cbb/worktrees/skills/openspec-init-worktree/scripts/parse-config.js +67 -0
  85. package/cbb/worktrees/skills/openspec-init-worktree/scripts/push-branches.js +101 -0
  86. package/cbb/worktrees/skills/openspec-init-worktree/scripts/push-core.js +136 -0
  87. package/cbb/worktrees/skills/openspec-init-worktree/scripts/silence-popup.js +23 -0
  88. package/cbb/worktrees/skills/openspec-init-worktree/scripts/sync-repos.js +95 -0
  89. package/cbb/worktrees/skills/openspec-init-worktree/scripts/update-gitignore.js +134 -0
  90. package/cbb/worktrees/skills/openspec-push-worktrees/SKILL.md +307 -0
  91. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/commit-worktrees.js +269 -0
  92. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/find-target-worktree.js +96 -0
  93. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/find-workspace-root.js +67 -0
  94. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/push-core.js +136 -0
  95. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/push-worktrees.js +159 -0
  96. package/cbb/worktrees/skills/openspec-push-worktrees/scripts/silence-popup.js +23 -0
  97. package/config/cbb.yaml +6 -0
  98. package/config/config.sample.json +16 -0
  99. package/config/openspec/config.yaml +28 -0
  100. package/config/openspec/schemas/spec-driven/schema.yaml +247 -0
  101. package/config/openspec/schemas/spec-driven/templates/design.md +475 -0
  102. package/config/openspec/schemas/spec-driven/templates/proposal.md +58 -0
  103. package/config/openspec/schemas/spec-driven/templates/spec.md +8 -0
  104. package/config/openspec/schemas/spec-driven/templates/tasks.md +9 -0
  105. package/config/workspaces.json +15 -0
  106. package/openspec/.version +6 -0
  107. package/openspec/commands/apply.md +182 -0
  108. package/openspec/commands/archive.md +223 -0
  109. package/openspec/commands/bulk-archive.md +334 -0
  110. package/openspec/commands/continue.md +112 -0
  111. package/openspec/commands/explore.md +206 -0
  112. package/openspec/commands/ff.md +111 -0
  113. package/openspec/commands/new.md +70 -0
  114. package/openspec/commands/onboard.md +555 -0
  115. package/openspec/commands/propose.md +157 -0
  116. package/openspec/commands/sync.md +256 -0
  117. package/openspec/commands/update.md +85 -0
  118. package/openspec/commands/verify.md +169 -0
  119. package/openspec/skills/openspec-apply-change/SKILL.md +187 -0
  120. package/openspec/skills/openspec-archive-change/SKILL.md +181 -0
  121. package/openspec/skills/openspec-bulk-archive-change/SKILL.md +338 -0
  122. package/openspec/skills/openspec-continue-change/SKILL.md +117 -0
  123. package/openspec/skills/openspec-explore/SKILL.md +342 -0
  124. package/openspec/skills/openspec-ff-change/SKILL.md +116 -0
  125. package/openspec/skills/openspec-new-change/SKILL.md +76 -0
  126. package/openspec/skills/openspec-onboard/SKILL.md +560 -0
  127. package/openspec/skills/openspec-propose/SKILL.md +162 -0
  128. package/openspec/skills/openspec-sync-specs/SKILL.md +261 -0
  129. package/openspec/skills/openspec-update-change/SKILL.md +90 -0
  130. package/openspec/skills/openspec-verify-change/SKILL.md +174 -0
  131. package/package.json +46 -0
  132. package/superpowers/.version +6 -0
  133. package/superpowers/skills/brainstorming/SKILL.md +250 -0
  134. package/superpowers/skills/brainstorming/scripts/frame-template.html +213 -0
  135. package/superpowers/skills/brainstorming/scripts/helper.js +167 -0
  136. package/superpowers/skills/brainstorming/scripts/server.cjs +723 -0
  137. package/superpowers/skills/brainstorming/scripts/start-server.sh +209 -0
  138. package/superpowers/skills/brainstorming/scripts/stop-server.sh +120 -0
  139. package/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  140. package/superpowers/skills/brainstorming/visual-companion.md +299 -0
  141. package/superpowers/skills/dispatching-parallel-agents/SKILL.md +167 -0
  142. package/superpowers/skills/executing-plans/SKILL.md +64 -0
  143. package/superpowers/skills/finishing-a-development-branch/SKILL.md +225 -0
  144. package/superpowers/skills/receiving-code-review/SKILL.md +205 -0
  145. package/superpowers/skills/requesting-code-review/SKILL.md +95 -0
  146. package/superpowers/skills/requesting-code-review/code-reviewer.md +181 -0
  147. package/superpowers/skills/subagent-driven-development/SKILL.md +568 -0
  148. package/superpowers/skills/subagent-driven-development/implementer-prompt.md +154 -0
  149. package/superpowers/skills/subagent-driven-development/re-review-prompt.md +115 -0
  150. package/superpowers/skills/subagent-driven-development/scripts/review-package +46 -0
  151. package/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +40 -0
  152. package/superpowers/skills/subagent-driven-development/scripts/task-brief +41 -0
  153. package/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +207 -0
  154. package/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
  155. package/superpowers/skills/systematic-debugging/SKILL.md +283 -0
  156. package/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  157. package/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
  158. package/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
  159. package/superpowers/skills/systematic-debugging/find-polluter.sh +72 -0
  160. package/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
  161. package/superpowers/skills/systematic-debugging/test-academic.md +14 -0
  162. package/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
  163. package/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
  164. package/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
  165. package/superpowers/skills/test-driven-development/SKILL.md +320 -0
  166. package/superpowers/skills/test-driven-development/writing-good-tests.md +198 -0
  167. package/superpowers/skills/using-git-worktrees/SKILL.md +167 -0
  168. package/superpowers/skills/using-superpowers/SKILL.md +63 -0
  169. package/superpowers/skills/using-superpowers/references/antigravity-tools.md +23 -0
  170. package/superpowers/skills/using-superpowers/references/codex-tools.md +108 -0
  171. package/superpowers/skills/using-superpowers/references/gemini-tools.md +63 -0
  172. package/superpowers/skills/using-superpowers/references/hermes-tools.md +56 -0
  173. package/superpowers/skills/using-superpowers/references/pi-tools.md +16 -0
  174. package/superpowers/skills/verification-before-completion/SKILL.md +120 -0
  175. package/superpowers/skills/writing-plans/SKILL.md +171 -0
  176. package/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  177. package/superpowers/skills/writing-skills/SKILL.md +679 -0
  178. package/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
  179. package/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  180. package/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
  181. package/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
  182. package/superpowers/skills/writing-skills/render-graphs.js +169 -0
  183. package/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
@@ -0,0 +1,67 @@
1
+ require('./silence-popup');
2
+ /**
3
+ * openspec-shared 工作空间根目录定位
4
+ *
5
+ * 唯一真源:cbb/worktrees/_shared/scripts/find-workspace-root.js
6
+ * 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / extend / close / push)。
7
+ *
8
+ * 优先:git worktree list 第一行(主仓库根目录,不受 worktree 内 CONFIG.json 副本干扰)
9
+ * 兜底:当前目录含 CONFIG.json
10
+ *
11
+ * 退出码:
12
+ * 0 - 定位成功,输出 WS_ROOT 绝对路径
13
+ * 1 - 未找到工作空间根目录
14
+ *
15
+ * 输出格式:
16
+ * 第一行:人类可读报告
17
+ * 最后一行:纯路径(便于 AI agent 解析后用于 cd)
18
+ */
19
+
20
+ const { execSync } = require('child_process');
21
+ const fs = require('fs');
22
+ const path = require('path');
23
+
24
+ function tryExec(cmd) {
25
+ try {
26
+ return { ok: true, out: execSync(cmd, { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] }).trim() };
27
+ } catch (e) {
28
+ return { ok: false };
29
+ }
30
+ }
31
+
32
+ let wsRoot = '';
33
+
34
+ // 优先:git worktree list 第一行
35
+ const worktreeList = tryExec('git worktree list');
36
+ if (worktreeList.ok) {
37
+ const firstLine = worktreeList.out.split('\n')[0];
38
+ if (firstLine) {
39
+ // 格式:<path> <sha> [<branch>]
40
+ const candidate = firstLine.split(/\s+/)[0];
41
+ if (candidate && fs.existsSync(candidate)) {
42
+ wsRoot = candidate;
43
+ }
44
+ }
45
+ }
46
+
47
+ // 兜底:当前目录含 CONFIG.json
48
+ if (!wsRoot) {
49
+ const cwd = process.cwd();
50
+ if (fs.existsSync(path.join(cwd, 'CONFIG.json'))) {
51
+ wsRoot = cwd;
52
+ }
53
+ }
54
+
55
+ // 校验
56
+ if (!wsRoot || !fs.existsSync(path.join(wsRoot, 'CONFIG.json'))) {
57
+ console.error('❌ 未找到工作空间根目录');
58
+ console.error(' 原因:git worktree list 失败且当前目录无 CONFIG.json');
59
+ console.error(' 请在业务工作空间根目录(由 cbb setup 初始化、包含 CONFIG.json)下执行本技能');
60
+ process.exit(1);
61
+ }
62
+
63
+ console.log('✅ 工作空间根目录:' + wsRoot);
64
+ console.log('---');
65
+ // 最后一行输出纯路径,AI agent 可直接 cd 使用
66
+ console.log(wsRoot);
67
+ process.exit(0);
@@ -0,0 +1,136 @@
1
+ require('./silence-popup');
2
+ /**
3
+ * openspec-shared 推送核心模块
4
+ *
5
+ * 唯一真源:cbb/worktrees/_shared/scripts/push-core.js
6
+ * 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init-worktree / extend-worktree / push-worktrees)。
7
+ *
8
+ * 公开 API:
9
+ * - tryExec(cmd, cwd, execImpl) 包装 execSync,统一返回 {ok, out|err}
10
+ * - escapeBranch(name) 分支名 shell 转义(防命令注入)
11
+ * - classifyError(stderr) 将 stderr 归类为 8 种错误码之一
12
+ * - pushSingle(repoPath, repoName, branch) 推送单个仓库并建立 upstream
13
+ * - collectRemoteMetadata(repoPath, branch, remote) 采集远程 commit 元信息
14
+ *
15
+ * 错误码契约(classifyError 输出):
16
+ * - ssh-auth-failed Permission denied (publickey)
17
+ * - https-auth-failed Authentication failed
18
+ * - network-unreachable Could not resolve host / hung up / connection refused
19
+ * - branch-protected protected branch / deny updating
20
+ * - remote-exists already exists
21
+ * - no-remote (pushSingle 内部判定)
22
+ * - non-fast-forward non-fast-forward
23
+ * - unknown 兜底
24
+ */
25
+
26
+ const { execSync: realExecSync } = require('child_process');
27
+
28
+ const PUSH_TIMEOUT_MS = 60000;
29
+
30
+ function tryExec(cmd, cwd, execImpl) {
31
+ const execSync = (execImpl || realExecSync);
32
+ try {
33
+ return {
34
+ ok: true,
35
+ out: execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], timeout: PUSH_TIMEOUT_MS }).toString().trim(),
36
+ };
37
+ } catch (e) {
38
+ const stderr = (e.stderr ? e.stderr.toString() : e.message || String(e)).trim();
39
+ return { ok: false, err: stderr };
40
+ }
41
+ }
42
+
43
+ function escapeBranch(name) {
44
+ return '"' + String(name).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
45
+ }
46
+
47
+ function classifyError(stderr) {
48
+ const s = (stderr || '').toLowerCase();
49
+ if (s.includes('permission denied (publickey)')) return 'ssh-auth-failed';
50
+ if (s.includes('authentication failed')) return 'https-auth-failed';
51
+ if (s.includes('could not resolve host') || s.includes('hung up') || s.includes('connection refused')) {
52
+ return 'network-unreachable';
53
+ }
54
+ if (s.includes('protected branch') || s.includes('deny updating')) return 'branch-protected';
55
+ if (s.includes('already exists')) return 'remote-exists';
56
+ if (s.includes('non-fast-forward')) return 'non-fast-forward';
57
+ return 'unknown';
58
+ }
59
+
60
+ /**
61
+ * 采集远程分支的元信息(hash/author/date/message + 本地 hash)
62
+ * 任意子命令失败时返回 null(不抛错)
63
+ * @param {string} repoPath
64
+ * @param {string} branch
65
+ * @param {string} remote
66
+ * @param {{ execSyncImpl?: Function }} [opts]
67
+ * @returns {{ remote: {hash, author, date, message}, local: {hash} } | null}
68
+ */
69
+ function collectRemoteMetadata(repoPath, branch, remote, opts) {
70
+ const execImpl = opts && opts.execSyncImpl;
71
+ try {
72
+ const remoteHash = tryExec('git rev-parse ' + escapeBranch(remote + '/' + branch), repoPath, execImpl);
73
+ if (!remoteHash.ok || !remoteHash.out) return null;
74
+
75
+ const remoteLog = tryExec('git log -1 --format="%an <%ae> | %ad | %s" ' + escapeBranch(remote + '/' + branch), repoPath, execImpl);
76
+ const localHash = tryExec('git rev-parse ' + escapeBranch(branch), repoPath, execImpl);
77
+ if (!remoteLog.ok || !localHash.ok || !localHash.out) return null;
78
+
79
+ // 解析 "author <email> | date | message"
80
+ const parts = remoteLog.out.split(' | ');
81
+ const author = parts[0] || '';
82
+ const date = parts[1] || '';
83
+ const message = parts.slice(2).join(' | ') || '';
84
+
85
+ return {
86
+ remote: {
87
+ hash: remoteHash.out,
88
+ author,
89
+ date,
90
+ message,
91
+ },
92
+ local: {
93
+ hash: localHash.out,
94
+ },
95
+ };
96
+ } catch (e) {
97
+ return null;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * 推送单个仓库的分支并建立 upstream
103
+ * @param {string} repoPath
104
+ * @param {string} repoName
105
+ * @param {string} branch
106
+ * @param {{ execSyncImpl?: Function }} [opts]
107
+ * @returns {{ name: string, status: string, upstream?: string, error?: string, message?: string, metadata?: object }}
108
+ */
109
+ function pushSingle(repoPath, repoName, branch, opts) {
110
+ const execImpl = opts && opts.execSyncImpl;
111
+ const remote = tryExec('git remote', repoPath, execImpl);
112
+ if (!remote.ok || !remote.out) {
113
+ return { name: repoName, status: 'failed', error: 'no-remote', message: '无远程配置' };
114
+ }
115
+ const r = remote.out.split(/\r?\n/)[0];
116
+ const branchEsc = escapeBranch(branch);
117
+ const remoteEsc = '"' + String(r).replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
118
+ const pushResult = tryExec('git push -u ' + remoteEsc + ' ' + branchEsc, repoPath, execImpl);
119
+ if (pushResult.ok) {
120
+ return { name: repoName, status: 'pushed', upstream: r + '/' + branch };
121
+ }
122
+ const errCode = classifyError(pushResult.err);
123
+ if (errCode === 'remote-exists') {
124
+ const metadata = collectRemoteMetadata(repoPath, branch, r, opts);
125
+ return {
126
+ name: repoName,
127
+ status: 'remote-exists',
128
+ error: errCode,
129
+ message: '远程分支已存在,需用户决策',
130
+ metadata,
131
+ };
132
+ }
133
+ return { name: repoName, status: 'failed', error: errCode, message: pushResult.err.split(/\r?\n/)[0] };
134
+ }
135
+
136
+ module.exports = { tryExec, escapeBranch, classifyError, pushSingle, collectRemoteMetadata };
@@ -0,0 +1,159 @@
1
+ require('./silence-popup');
2
+ /**
3
+ * openspec-push-worktrees 推送所有 worktree 仓库
4
+ *
5
+ * 用法:
6
+ * node push-worktrees.js <ws_root> <branch>
7
+ * node push-worktrees.js <wt_path> # wt_path 必须是 <ws_root>/.worktrees/worktree-<branch> 形态
8
+ *
9
+ * 行为:
10
+ * 1. 扫描 <ws_root>/.worktrees/worktree-<branch>/ 下所有 git 仓库(workspace + 各 app 子 worktree)
11
+ * 2. 对每个仓库调 push-core.pushSingle(已建立 upstream 时直接 push -u;否则建立 upstream)
12
+ * 3. 逐个报告状态,输出末行 PUSH_RESULT
13
+ *
14
+ * 退出码:
15
+ * 0 - 全部推送成功
16
+ * 1 - 参数错误(ws_root/branch 无法识别)
17
+ * 2 - 部分或全部推送失败(AI agent 必须阻塞流程)
18
+ *
19
+ * 与 init-worktree/scripts/push-branches.js 的区别:
20
+ * - push-branches.js 推送 workspace 主目录 + .code/<app>/(创建 worktree 时使用)
21
+ * - push-worktrees.js 推送 .worktrees/worktree-<branch>/ 下所有 worktree(开发完成时使用)
22
+ *
23
+ * 错误码契约复用 push-core.classifyError:
24
+ * - pushed / remote-exists / failed(ssh-auth-failed / https-auth-failed / network-unreachable
25
+ * / branch-protected / no-remote / non-fast-forward / unknown)
26
+ */
27
+
28
+ const { pushSingle } = require('./push-core');
29
+ const fs = require('fs');
30
+ const path = require('path');
31
+
32
+ function resolveInputs(argv) {
33
+ // argv[2] 单独:wt_path 形式
34
+ // argv[2] + argv[3]:ws_root + branch 形式
35
+ if (argv.length === 3) {
36
+ const wtPath = path.resolve(argv[2]);
37
+ // 形如 <ws_root>/.worktrees/worktree-<branch>
38
+ const m = wtPath.match(/^(.+)[\\\/]\.worktrees[\\\/]worktree-(.+)$/);
39
+ if (!m) {
40
+ return { error: 'argv[2] 必须是 <ws_root>/.worktrees/worktree-<branch> 形态,或同时传 ws_root + branch' };
41
+ }
42
+ return { wsRoot: m[1], branch: m[2] };
43
+ }
44
+ if (argv.length >= 4) {
45
+ return { wsRoot: path.resolve(argv[2]), branch: argv[3] };
46
+ }
47
+ return { error: '用法:node push-worktrees.js <ws_root> <branch> | node push-worktrees.js <wt_path>' };
48
+ }
49
+
50
+ function isGitRepo(p) {
51
+ try {
52
+ // worktree 顶层是 .git 文件(gitdir 指向真实 .git),主目录是 .git 目录
53
+ return fs.existsSync(path.join(p, '.git'));
54
+ } catch (e) {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * 扫描 worktree 下的所有 git 仓库
61
+ * - workspace worktree:<ws_root>/.worktrees/worktree-<branch>/ 本身
62
+ * - app worktree:<ws_root>/.worktrees/worktree-<branch>/<app_name>/(嵌套子目录)
63
+ */
64
+ function scanWorktreeRepos(wsRoot, branch) {
65
+ const wtRoot = path.join(wsRoot, '.worktrees', 'worktree-' + branch);
66
+ const repos = [];
67
+
68
+ if (!fs.existsSync(wtRoot)) {
69
+ return { wtRoot, repos, error: 'worktree 目录不存在:' + wtRoot };
70
+ }
71
+
72
+ // workspace worktree(自身是 git worktree)
73
+ if (isGitRepo(wtRoot)) {
74
+ repos.push({ name: 'workspace', wt: wtRoot, repo: wsRoot });
75
+ }
76
+
77
+ // app worktree(嵌套子目录)
78
+ const entries = fs.readdirSync(wtRoot, { withFileTypes: true });
79
+ for (const e of entries) {
80
+ if (!e.isDirectory()) continue;
81
+ // 跳过 . 开头的隐藏目录(如 .va、.claude、.qoder)
82
+ if (e.name.startsWith('.')) continue;
83
+ const appWt = path.join(wtRoot, e.name);
84
+ if (!isGitRepo(appWt)) continue;
85
+ repos.push({ name: e.name, wt: appWt, repo: path.join(wsRoot, '.code', e.name) });
86
+ }
87
+ return { wtRoot, repos, error: null };
88
+ }
89
+
90
+ /**
91
+ * 编排:扫描 + 逐个 push
92
+ * @param {{ wsRoot: string, branch: string, execSyncImpl?: Function }} opts
93
+ * @returns {{ wtRoot: string, results: Array }}
94
+ */
95
+ function executePush(opts) {
96
+ const { wtRoot, repos, error } = scanWorktreeRepos(opts.wsRoot, opts.branch);
97
+ if (error) {
98
+ return { wtRoot, results: [], error };
99
+ }
100
+ const results = [];
101
+ for (const r of repos) {
102
+ // push 在 worktree 目录下执行(worktree 自带 .git 引用,git push 走 worktree 检出状态)
103
+ const pushOpts = { execSyncImpl: opts.execSyncImpl };
104
+ const res = pushSingle(r.wt, r.name, opts.branch, pushOpts);
105
+ results.push(res);
106
+ }
107
+ return { wtRoot, results, error: null };
108
+ }
109
+
110
+ // 导出供单测
111
+ module.exports = { resolveInputs, scanWorktreeRepos, executePush };
112
+
113
+ function main() {
114
+ const inputs = resolveInputs(process.argv);
115
+ if (inputs.error) {
116
+ console.error('❌ ' + inputs.error);
117
+ process.exit(1);
118
+ }
119
+
120
+ console.log('=== 推送所有 worktree 仓库 ===');
121
+ console.log('工作空间根:' + inputs.wsRoot);
122
+ console.log('需求名(分支):' + inputs.branch);
123
+
124
+ const { wtRoot, results, error } = executePush({ wsRoot: inputs.wsRoot, branch: inputs.branch });
125
+
126
+ if (error) {
127
+ console.error('❌ ' + error);
128
+ process.exit(1);
129
+ }
130
+
131
+ if (results.length === 0) {
132
+ console.log('⚠️ 未在 worktree 下发现任何 git 仓库');
133
+ console.log('---');
134
+ console.log('PUSH_RESULT', JSON.stringify([]));
135
+ process.exit(0);
136
+ }
137
+
138
+ // 人类可读报告
139
+ for (const r of results) {
140
+ if (r.status === 'pushed') {
141
+ console.log('✅ ' + r.name + ': 已推送 ' + r.upstream);
142
+ } else if (r.status === 'remote-exists') {
143
+ console.log('⚠️ ' + r.name + ': 远程分支已存在(需用户决策)');
144
+ } else {
145
+ console.error('❌ ' + r.name + ': 推送失败 - ' + (r.message || r.error));
146
+ }
147
+ }
148
+
149
+ const hasFailure = results.some(r => r.status === 'failed' || r.status === 'remote-exists');
150
+
151
+ console.log('---');
152
+ console.log('PUSH_RESULT', JSON.stringify(results));
153
+ process.exit(hasFailure ? 2 : 0);
154
+ }
155
+
156
+ // CLI 入口
157
+ if (require.main === module) {
158
+ main();
159
+ }
@@ -0,0 +1,23 @@
1
+ // silence-popup.js (shared)
2
+ // Silences Windows 0xc0000142 (STATUS_DLL_INIT_FAILED) popups from child git processes.
3
+ // Cross-platform: only effective on Windows; no-op on macOS/Linux.
4
+ // koffi is resolved from cbb global install (no local node_modules needed).
5
+ //
6
+ // 唯一真源:cbb/worktrees/_shared/scripts/silence-popup.js
7
+ // 由 scripts/sync-shared.js 展开到各 skill 的 scripts/ 下(init / extend / close / push)。
8
+ // skill 内同目录引用:脚本第一行 `require('./silence-popup')`。
9
+ if (process.platform === 'win32') {
10
+ try {
11
+ const path = require('path');
12
+ const { execSync } = require('child_process');
13
+ const globalRoot = execSync('npm root -g', { stdio: 'pipe', timeout: 5000 }).toString().trim();
14
+ const koffiPath = path.join(globalRoot, '@jspg-ai', 'coding-bb', 'node_modules', 'koffi');
15
+ const koffi = require(koffiPath);
16
+ const kernel32 = koffi.load('kernel32.dll');
17
+ const SetErrorMode = kernel32.func('uint __stdcall SetErrorMode(uint uMode)');
18
+ // SEM_FAILCRITICALERRORS=0x0001 | SEM_NOGPFAULTERRORBOX=0x0002 | SEM_NOOPENFILEERRORBOX=0x8000
19
+ SetErrorMode(0x0001 | 0x0002 | 0x8000);
20
+ } catch (e) {
21
+ // koffi unavailable or SetErrorMode failed: silently continue (worst case: popups may reappear)
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ # 项目级总配置(定位类似 Spring Boot 的 application.yaml)
2
+ # 所有项目级配置集中于此:团队共享、进 git。个人凭据(如 Wiki 认证)仍放 ~/.cbb/wiki-config.json。
3
+
4
+ wiki:
5
+ # Confluence Wiki 地址:一个公司通常只有一个,按需修改
6
+ baseUrl: wiki.amh-group.com
@@ -0,0 +1,16 @@
1
+ {
2
+ "_comment": "AI 开发工作空间配置样例(请勿修改本文件,复制为工作空间根目录的 CONFIG.json 后编辑使用)。apps 数组中每个对象需包含:name(应用名,同时作为 .code/ 子目录名)、repo(Git 仓库地址,支持 SSH 或 HTTPS)、side(仓库类型,'front' 表示前端工程,'back' 表示后端工程)。",
3
+ "apps":
4
+ [
5
+ {
6
+ "name": "ep-user-auth-app",
7
+ "repo": "git@code.example.com:team/ep-user-auth-app.git",
8
+ "side": "back"
9
+ },
10
+ {
11
+ "name": "ep-user-web",
12
+ "repo": "git@code.example.com:team/ep-user-web.git",
13
+ "side": "front"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,28 @@
1
+ schema: spec-driven
2
+
3
+ context: |
4
+ # 工作目录约束
5
+ 不要 cd 进子仓库目录。读取代码用绝对路径,所有命令在当前目录执行。
6
+
7
+ 语言:中文(简体)
8
+ 所有文档必须使用中文简体编写,但技术术语保持英文,如 API、REST、RPC、MQ 等。
9
+
10
+ # Java 技术栈
11
+
12
+ ## 核心框架
13
+ - Java 1.8 或 Java 21
14
+ - Spring Boot 2.0.4.RELEASE
15
+ - Ironman 1.3.19
16
+
17
+ ## 中间件
18
+ - 数据库:Zebra 分库分表 (Ironman-SQL)
19
+ - RPC:Pigeon (Ironman-RPC)
20
+ - 消息队列:RocketMQ (Ironman-MQ)
21
+ - 缓存:Redis (Ironman-Redis)
22
+ - 配置中心:Lion (Ironman-Config)
23
+
24
+ ## 文档写作原则
25
+ - 每个章节先给结论或概览,再展开细节
26
+ - 用业务语言描述目标和规则,用技术语言描述实现方式
27
+ - 图优于表,表优于列表,列表优于段落
28
+ - 只写不显而易见的内容,标准实践不写