@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.
- package/README.md +41 -0
- package/cbb/dev-standards/rules/cbb-ai-behavior.md +104 -0
- package/cbb/dev-standards/rules/cbb-coding-rule.md +50 -0
- package/cbb/dev-standards/rules/cbb-priority.md +56 -0
- package/cbb/dev-standards/skills/architecture-specs/SKILL.md +129 -0
- package/cbb/dev-standards/skills/coding-specs/SKILL.md +376 -0
- package/cbb/dev-standards/skills/coding-specs/references/concurrency.md +53 -0
- package/cbb/dev-standards/skills/coding-specs/references/config-center.md +16 -0
- package/cbb/dev-standards/skills/coding-specs/references/distributed.md +42 -0
- package/cbb/dev-standards/skills/coding-specs/references/es-coding.md +60 -0
- package/cbb/dev-standards/skills/coding-specs/references/scheduled-task.md +25 -0
- package/cbb/dev-standards/skills/coding-specs/references/security.md +11 -0
- package/cbb/dev-standards/skills/coding-specs/references/unit-testing.md +43 -0
- package/cbb/dev-standards/skills/es-design-specs/SKILL.md +104 -0
- package/cbb/dev-standards/skills/mysql-design-specs/SKILL.md +89 -0
- package/cbb/lib/install/claude-code.js +20 -0
- package/cbb/lib/install/cleanup.js +64 -0
- package/cbb/lib/install/init.js +1875 -0
- package/cbb/lib/install/qoder.js +20 -0
- package/cbb/lib/install/workspaces.js +232 -0
- package/cbb/lib/openspec/index.js +554 -0
- package/cbb/lib/superpowers/index.js +265 -0
- package/cbb/lib/utils/check-update.js +147 -0
- package/cbb/lib/utils/checkbox.js +383 -0
- package/cbb/lib/utils/gitignore.js +69 -0
- package/cbb/lib/utils/output.js +64 -0
- package/cbb/lib/utils/settings.js +119 -0
- package/cbb/lib/utils/version.js +135 -0
- package/cbb/lib/wiki/api-client.js +358 -0
- package/cbb/lib/wiki/cli.js +427 -0
- package/cbb/lib/wiki/convert.js +464 -0
- package/cbb/lib/wiki/index.js +218 -0
- package/cbb/lib/wiki/mermaid-guard.js +103 -0
- package/cbb/lib/wiki/split.js +131 -0
- package/cbb/tools/cbb-decompile-jar/SKILL.md +220 -0
- package/cbb/tools/cbb-decompile-jar/scripts/decompile.py +863 -0
- package/cbb/tools/cbb-design-to-wiki/SKILL.md +180 -0
- package/cbb/tools/cbb-mvn-guide/SKILL.md +281 -0
- package/cbb/tools/cbb-mvn-guide/scripts/mvn_jdk_manager.py +378 -0
- package/cbb/tools/cbb-mvn-guide/scripts/mvn_pom_jdk_reader.py +197 -0
- package/cbb/tools/cbb-plantuml-authoring/SKILL.md +448 -0
- package/cbb/tools/cbb-plantuml-authoring/references/drawing-templates.md +479 -0
- package/cbb/tools/cbb-wiki-ops/SKILL.md +134 -0
- package/cbb/tools/cbb-wiki-ops/scripts/check-auth.js +44 -0
- package/cbb/worktrees/_shared/scripts/find-target-worktree.js +96 -0
- package/cbb/worktrees/_shared/scripts/find-workspace-root.js +67 -0
- package/cbb/worktrees/_shared/scripts/push-core.js +136 -0
- package/cbb/worktrees/_shared/scripts/silence-popup.js +23 -0
- package/cbb/worktrees/commands/close.md +64 -0
- package/cbb/worktrees/commands/extend.md +65 -0
- package/cbb/worktrees/commands/init.md +55 -0
- package/cbb/worktrees/commands/push.md +42 -0
- package/cbb/worktrees/skills/openspec-close-worktree/SKILL.md +449 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/check-env.js +76 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/check-unarchived.js +48 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/delete-branches.js +136 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/discover-apps.js +76 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/find-target-worktree.js +96 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/find-workspace-root.js +67 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/remove-worktrees.js +124 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/safety-check.js +174 -0
- package/cbb/worktrees/skills/openspec-close-worktree/scripts/silence-popup.js +23 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/SKILL.md +390 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/check-env.js +95 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/check-repos.js +98 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/create-branches-and-worktrees.js +135 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/find-target-worktree.js +96 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/find-workspace-root.js +67 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/install-ai.js +150 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/list-available-apps.js +88 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/push-core.js +136 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/silence-popup.js +23 -0
- package/cbb/worktrees/skills/openspec-extend-worktree/scripts/sync-repos.js +93 -0
- package/cbb/worktrees/skills/openspec-init-worktree/SKILL.md +539 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/auto-open.js +136 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-env-deep.js +87 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-env.js +90 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/check-repos.js +171 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/create-branches.js +103 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/create-worktrees.js +154 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/find-workspace-root.js +67 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/generate-app-options.js +93 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/install-ai.js +177 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/parse-config.js +67 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/push-branches.js +101 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/push-core.js +136 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/silence-popup.js +23 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/sync-repos.js +95 -0
- package/cbb/worktrees/skills/openspec-init-worktree/scripts/update-gitignore.js +134 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/SKILL.md +307 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/commit-worktrees.js +269 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/find-target-worktree.js +96 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/find-workspace-root.js +67 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/push-core.js +136 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/push-worktrees.js +159 -0
- package/cbb/worktrees/skills/openspec-push-worktrees/scripts/silence-popup.js +23 -0
- package/config/cbb.yaml +6 -0
- package/config/config.sample.json +16 -0
- package/config/openspec/config.yaml +28 -0
- package/config/openspec/schemas/spec-driven/schema.yaml +247 -0
- package/config/openspec/schemas/spec-driven/templates/design.md +475 -0
- package/config/openspec/schemas/spec-driven/templates/proposal.md +58 -0
- package/config/openspec/schemas/spec-driven/templates/spec.md +8 -0
- package/config/openspec/schemas/spec-driven/templates/tasks.md +9 -0
- package/config/workspaces.json +15 -0
- package/openspec/.version +6 -0
- package/openspec/commands/apply.md +182 -0
- package/openspec/commands/archive.md +223 -0
- package/openspec/commands/bulk-archive.md +334 -0
- package/openspec/commands/continue.md +112 -0
- package/openspec/commands/explore.md +206 -0
- package/openspec/commands/ff.md +111 -0
- package/openspec/commands/new.md +70 -0
- package/openspec/commands/onboard.md +555 -0
- package/openspec/commands/propose.md +157 -0
- package/openspec/commands/sync.md +256 -0
- package/openspec/commands/update.md +85 -0
- package/openspec/commands/verify.md +169 -0
- package/openspec/skills/openspec-apply-change/SKILL.md +187 -0
- package/openspec/skills/openspec-archive-change/SKILL.md +181 -0
- package/openspec/skills/openspec-bulk-archive-change/SKILL.md +338 -0
- package/openspec/skills/openspec-continue-change/SKILL.md +117 -0
- package/openspec/skills/openspec-explore/SKILL.md +342 -0
- package/openspec/skills/openspec-ff-change/SKILL.md +116 -0
- package/openspec/skills/openspec-new-change/SKILL.md +76 -0
- package/openspec/skills/openspec-onboard/SKILL.md +560 -0
- package/openspec/skills/openspec-propose/SKILL.md +162 -0
- package/openspec/skills/openspec-sync-specs/SKILL.md +261 -0
- package/openspec/skills/openspec-update-change/SKILL.md +90 -0
- package/openspec/skills/openspec-verify-change/SKILL.md +174 -0
- package/package.json +46 -0
- package/superpowers/.version +6 -0
- package/superpowers/skills/brainstorming/SKILL.md +250 -0
- package/superpowers/skills/brainstorming/scripts/frame-template.html +213 -0
- package/superpowers/skills/brainstorming/scripts/helper.js +167 -0
- package/superpowers/skills/brainstorming/scripts/server.cjs +723 -0
- package/superpowers/skills/brainstorming/scripts/start-server.sh +209 -0
- package/superpowers/skills/brainstorming/scripts/stop-server.sh +120 -0
- package/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/superpowers/skills/brainstorming/visual-companion.md +299 -0
- package/superpowers/skills/dispatching-parallel-agents/SKILL.md +167 -0
- package/superpowers/skills/executing-plans/SKILL.md +64 -0
- package/superpowers/skills/finishing-a-development-branch/SKILL.md +225 -0
- package/superpowers/skills/receiving-code-review/SKILL.md +205 -0
- package/superpowers/skills/requesting-code-review/SKILL.md +95 -0
- package/superpowers/skills/requesting-code-review/code-reviewer.md +181 -0
- package/superpowers/skills/subagent-driven-development/SKILL.md +568 -0
- package/superpowers/skills/subagent-driven-development/implementer-prompt.md +154 -0
- package/superpowers/skills/subagent-driven-development/re-review-prompt.md +115 -0
- package/superpowers/skills/subagent-driven-development/scripts/review-package +46 -0
- package/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +40 -0
- package/superpowers/skills/subagent-driven-development/scripts/task-brief +41 -0
- package/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +207 -0
- package/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/superpowers/skills/systematic-debugging/SKILL.md +283 -0
- package/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/superpowers/skills/systematic-debugging/find-polluter.sh +72 -0
- package/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/superpowers/skills/systematic-debugging/test-academic.md +14 -0
- package/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/superpowers/skills/test-driven-development/SKILL.md +320 -0
- package/superpowers/skills/test-driven-development/writing-good-tests.md +198 -0
- package/superpowers/skills/using-git-worktrees/SKILL.md +167 -0
- package/superpowers/skills/using-superpowers/SKILL.md +63 -0
- package/superpowers/skills/using-superpowers/references/antigravity-tools.md +23 -0
- package/superpowers/skills/using-superpowers/references/codex-tools.md +108 -0
- package/superpowers/skills/using-superpowers/references/gemini-tools.md +63 -0
- package/superpowers/skills/using-superpowers/references/hermes-tools.md +56 -0
- package/superpowers/skills/using-superpowers/references/pi-tools.md +16 -0
- package/superpowers/skills/verification-before-completion/SKILL.md +120 -0
- package/superpowers/skills/writing-plans/SKILL.md +171 -0
- package/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/superpowers/skills/writing-skills/SKILL.md +679 -0
- package/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
- package/superpowers/skills/writing-skills/render-graphs.js +169 -0
- package/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -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,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,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('./silence-popup');
|
|
3
|
+
/**
|
|
4
|
+
* openspec-init-worktree 同步 .code/ 仓库
|
|
5
|
+
*
|
|
6
|
+
* 用法:node sync-repos.js <ws_root> '<apps_json>'
|
|
7
|
+
* - ws_root: 工作空间根绝对路径
|
|
8
|
+
* - apps_json: 应用列表 JSON 数组(来自 parse-config.js)
|
|
9
|
+
*
|
|
10
|
+
* 对每个 app:
|
|
11
|
+
* - .code/<name>/.git 存在 → fetch --all
|
|
12
|
+
* - 不存在 → clone(从 repo URL)
|
|
13
|
+
*
|
|
14
|
+
* 退出码:
|
|
15
|
+
* 0 - 全部成功
|
|
16
|
+
* 1 - 参数错误
|
|
17
|
+
* 2 - 部分失败
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { execSync } = require('child_process');
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
|
|
24
|
+
const wsRoot = process.argv[2];
|
|
25
|
+
const appsJson = process.argv[3];
|
|
26
|
+
|
|
27
|
+
if (!wsRoot) {
|
|
28
|
+
console.error('❌ 用法:node sync-repos.js <ws_root>');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 从 CONFIG.json 读取 apps(避免 shell 字符串传递中的转义问题)
|
|
34
|
+
*/
|
|
35
|
+
function loadAppsFromConfig() {
|
|
36
|
+
const configPath = path.join(wsRoot, 'CONFIG.json');
|
|
37
|
+
if (!fs.existsSync(configPath)) {
|
|
38
|
+
console.error('❌ CONFIG.json 不存在:' + configPath);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
43
|
+
if (!config.apps || !Array.isArray(config.apps) || config.apps.length === 0) {
|
|
44
|
+
console.error('❌ CONFIG.json 中 apps 为空');
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return config.apps;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error('❌ CONFIG.json 解析失败:' + e.message);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const apps = loadAppsFromConfig();
|
|
55
|
+
if (!apps) {
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const codeDir = path.join(wsRoot, '.code');
|
|
60
|
+
fs.mkdirSync(codeDir, { recursive: true });
|
|
61
|
+
|
|
62
|
+
const results = [];
|
|
63
|
+
|
|
64
|
+
for (const app of apps) {
|
|
65
|
+
const target = path.join(codeDir, app.name);
|
|
66
|
+
const isGit = fs.existsSync(path.join(target, '.git'));
|
|
67
|
+
|
|
68
|
+
if (isGit) {
|
|
69
|
+
// 已存在:fetch --all
|
|
70
|
+
try {
|
|
71
|
+
execSync('git fetch --all -q', { cwd: target, stdio: 'pipe' });
|
|
72
|
+
console.log('✅ ' + app.name + ': 代码已更新(fetch --all)');
|
|
73
|
+
results.push({ name: app.name, status: 'updated' });
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.log('⚠️ ' + app.name + ': fetch 失败(离线或无权限,使用本地已有代码)');
|
|
76
|
+
results.push({ name: app.name, status: 'fetch-failed' });
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
// 不存在:clone
|
|
80
|
+
try {
|
|
81
|
+
execSync('git clone -q "' + app.repo + '" "' + target + '"', { stdio: 'pipe' });
|
|
82
|
+
console.log('✅ ' + app.name + ': 代码已拉取(clone)');
|
|
83
|
+
results.push({ name: app.name, status: 'cloned' });
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('❌ ' + app.name + ': clone 失败 — ' + app.repo);
|
|
86
|
+
results.push({ name: app.name, status: 'clone-failed', error: (e.stderr || e.message || '').toString().trim() });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 机器可读摘要
|
|
92
|
+
const hasFailures = results.some(r => r.status === 'clone-failed');
|
|
93
|
+
console.log('---');
|
|
94
|
+
console.log('SYNC_RESULT', JSON.stringify(results));
|
|
95
|
+
process.exit(hasFailures ? 2 : 0);
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('./silence-popup');
|
|
3
|
+
/**
|
|
4
|
+
* openspec-init-worktree 安全更新 .gitignore
|
|
5
|
+
*
|
|
6
|
+
* 用法:node update-gitignore.js <ws_root> <branch>
|
|
7
|
+
*
|
|
8
|
+
* 行为:
|
|
9
|
+
* 1. stash 当前未提交修改
|
|
10
|
+
* 2. 切换到目标分支
|
|
11
|
+
* 3. 检查 .worktrees/ 和 .code/ 是否在 .gitignore
|
|
12
|
+
* 4. 添加缺失条目
|
|
13
|
+
* 5. 提交 .gitignore
|
|
14
|
+
* 6. 切回原分支
|
|
15
|
+
* 7. pop stash(如有)
|
|
16
|
+
*
|
|
17
|
+
* 退出码:
|
|
18
|
+
* 0 - 成功
|
|
19
|
+
* 1 - 参数错误
|
|
20
|
+
* 2 - 执行失败
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const { execSync } = require('child_process');
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
|
|
27
|
+
const wsRoot = process.argv[2];
|
|
28
|
+
const branch = process.argv[3];
|
|
29
|
+
|
|
30
|
+
if (!wsRoot || !branch) {
|
|
31
|
+
console.error('❌ 用法:node update-gitignore.js <ws_root> <branch>');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function run(cmd, cwd) {
|
|
36
|
+
try {
|
|
37
|
+
return { ok: true, out: execSync(cmd, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] }).trim() };
|
|
38
|
+
} catch (e) {
|
|
39
|
+
return { ok: false, err: (e.stderr || e.message || String(e)).trim() };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 1. 检测当前分支
|
|
44
|
+
const origBranch = run('git rev-parse --abbrev-ref HEAD', wsRoot);
|
|
45
|
+
if (!origBranch.ok) {
|
|
46
|
+
console.error('❌ 无法获取当前分支:' + origBranch.err);
|
|
47
|
+
process.exit(2);
|
|
48
|
+
}
|
|
49
|
+
console.log('当前分支:' + origBranch.out);
|
|
50
|
+
|
|
51
|
+
// 2. stash 当前未提交修改
|
|
52
|
+
let stashed = false;
|
|
53
|
+
const status = run('git status --porcelain', wsRoot);
|
|
54
|
+
if (status.ok && status.out) {
|
|
55
|
+
const stash = run('git stash push -m "init-worktree-temp"', wsRoot);
|
|
56
|
+
if (stash.ok) {
|
|
57
|
+
stashed = true;
|
|
58
|
+
console.log('✅ 已 stash 未提交修改');
|
|
59
|
+
} else {
|
|
60
|
+
console.error('❌ git stash 失败:' + stash.err);
|
|
61
|
+
process.exit(2);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
console.log('ℹ️ 无未提交修改,跳过 stash');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 3. 切换到目标分支
|
|
68
|
+
const checkout = run('git checkout "' + branch + '"', wsRoot);
|
|
69
|
+
if (!checkout.ok) {
|
|
70
|
+
console.error('❌ 切换到分支 ' + branch + ' 失败:' + checkout.err);
|
|
71
|
+
if (stashed) run('git stash pop', wsRoot);
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
console.log('✅ 切换到分支:' + branch);
|
|
75
|
+
|
|
76
|
+
// 4. 检查并添加 .worktrees/ 和 .code/ 到 .gitignore
|
|
77
|
+
const gitignorePath = path.join(wsRoot, '.gitignore');
|
|
78
|
+
let content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, 'utf-8') : '';
|
|
79
|
+
const original = content;
|
|
80
|
+
const needCommit = [];
|
|
81
|
+
|
|
82
|
+
for (const dir of ['.worktrees/', '.code/']) {
|
|
83
|
+
const check = run('git check-ignore -q "' + dir + '"', wsRoot);
|
|
84
|
+
if (!check.ok) {
|
|
85
|
+
// 未忽略:添加
|
|
86
|
+
if (content && !content.endsWith('\n')) content += '\n';
|
|
87
|
+
content += dir + '\n';
|
|
88
|
+
needCommit.push(dir);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (needCommit.length === 0) {
|
|
93
|
+
console.log('ℹ️ .worktrees/ 和 .code/ 均已在 .gitignore 中,跳过提交');
|
|
94
|
+
} else {
|
|
95
|
+
fs.writeFileSync(gitignorePath, content);
|
|
96
|
+
console.log('✅ .gitignore 已添加:' + needCommit.join(', '));
|
|
97
|
+
const add = run('git add .gitignore', wsRoot);
|
|
98
|
+
if (!add.ok) {
|
|
99
|
+
console.error('❌ git add .gitignore 失败');
|
|
100
|
+
run('git checkout "' + origBranch.out + '"', wsRoot);
|
|
101
|
+
if (stashed) run('git stash pop', wsRoot);
|
|
102
|
+
process.exit(2);
|
|
103
|
+
}
|
|
104
|
+
const commit = run('git commit -m "chore: add .worktrees/ and .code/ to gitignore"', wsRoot);
|
|
105
|
+
if (!commit.ok) {
|
|
106
|
+
console.error('❌ git commit 失败:' + commit.err);
|
|
107
|
+
run('git checkout "' + origBranch.out + '"', wsRoot);
|
|
108
|
+
if (stashed) run('git stash pop', wsRoot);
|
|
109
|
+
process.exit(2);
|
|
110
|
+
}
|
|
111
|
+
console.log('✅ .gitignore 已提交');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 5. 切回原分支
|
|
115
|
+
const back = run('git checkout "' + origBranch.out + '"', wsRoot);
|
|
116
|
+
if (!back.ok) {
|
|
117
|
+
console.error('❌ 切回原分支失败:' + back.err);
|
|
118
|
+
process.exit(2);
|
|
119
|
+
}
|
|
120
|
+
console.log('✅ 已切回:' + origBranch.out);
|
|
121
|
+
|
|
122
|
+
// 6. pop stash
|
|
123
|
+
if (stashed) {
|
|
124
|
+
const pop = run('git stash pop', wsRoot);
|
|
125
|
+
if (pop.ok) {
|
|
126
|
+
console.log('✅ 已恢复 stash');
|
|
127
|
+
} else {
|
|
128
|
+
console.error('⚠️ stash pop 失败,请手动检查:' + pop.err);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log('---');
|
|
133
|
+
console.log('GITIGNORE_OK');
|
|
134
|
+
process.exit(0);
|