@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,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,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('./silence-popup');
|
|
3
|
+
/**
|
|
4
|
+
* openspec-extend-worktree 同步待补加应用的 .code/ 仓库
|
|
5
|
+
*
|
|
6
|
+
* 用法:node sync-repos.js <ws_root> '<apps_json>'
|
|
7
|
+
*
|
|
8
|
+
* 对每个待补加应用:
|
|
9
|
+
* - .code/<name>/.git 存在 → fetch --all
|
|
10
|
+
* - 不存在 → clone(从 app.repo)
|
|
11
|
+
*
|
|
12
|
+
* 退出码:
|
|
13
|
+
* 0 - 全部成功
|
|
14
|
+
* 1 - 参数错误
|
|
15
|
+
* 2 - 部分失败
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { execSync } = require('child_process');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
const wsRoot = process.argv[2];
|
|
23
|
+
// appsNames: 应用名逗号分隔字符串,如 "app1,app2,app3"
|
|
24
|
+
const appsNames = process.argv[3];
|
|
25
|
+
|
|
26
|
+
if (!wsRoot || !appsNames) {
|
|
27
|
+
console.error('❌ 用法:node sync-repos.js <ws_root> <app1,app2,...>');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 从 CONFIG.json 读取所有 apps,过滤出 appsNames 中指定的应用。
|
|
33
|
+
* appsNames 格式:逗号分隔的应用名字符串
|
|
34
|
+
*/
|
|
35
|
+
function loadSelectedApps() {
|
|
36
|
+
const configPath = path.join(wsRoot, 'CONFIG.json');
|
|
37
|
+
if (!fs.existsSync(configPath)) return null;
|
|
38
|
+
let config;
|
|
39
|
+
try { config = JSON.parse(fs.readFileSync(configPath, 'utf-8')); } catch (e) { return null; }
|
|
40
|
+
const allApps = Array.isArray(config.apps) ? config.apps : [];
|
|
41
|
+
const namesSet = new Set(appsNames.split(',').map(s => s.trim()).filter(Boolean));
|
|
42
|
+
const selected = allApps.filter(a => namesSet.has(a.name));
|
|
43
|
+
if (selected.length === 0) return null;
|
|
44
|
+
return selected;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const apps = loadSelectedApps();
|
|
48
|
+
if (!apps) {
|
|
49
|
+
console.error('❌ CONFIG.json 中未找到指定应用(' + appsNames + ')');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const codeDir = path.join(wsRoot, '.code');
|
|
54
|
+
fs.mkdirSync(codeDir, { recursive: true });
|
|
55
|
+
|
|
56
|
+
const results = [];
|
|
57
|
+
|
|
58
|
+
for (const app of apps) {
|
|
59
|
+
const target = path.join(codeDir, app.name);
|
|
60
|
+
const isGit = fs.existsSync(path.join(target, '.git'));
|
|
61
|
+
|
|
62
|
+
if (isGit) {
|
|
63
|
+
// 已存在:fetch --all
|
|
64
|
+
try {
|
|
65
|
+
execSync('git fetch --all -q', { cwd: target, stdio: 'pipe' });
|
|
66
|
+
console.log('✅ ' + app.name + ': 代码已更新(fetch)');
|
|
67
|
+
results.push({ name: app.name, status: 'updated' });
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.log('⚠️ ' + app.name + ': fetch 失败(离线或无权限,使用本地已有代码)');
|
|
70
|
+
results.push({ name: app.name, status: 'fetch-failed' });
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
// 不存在:clone
|
|
74
|
+
if (!app.repo) {
|
|
75
|
+
console.error('❌ ' + app.name + ': 在 CONFIG.json 中找不到 repo URL');
|
|
76
|
+
results.push({ name: app.name, status: 'no-repo' });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
execSync('git clone -q "' + app.repo + '" "' + target + '"', { stdio: 'pipe' });
|
|
81
|
+
console.log('✅ ' + app.name + ': 已 clone(' + target + ')');
|
|
82
|
+
results.push({ name: app.name, status: 'cloned' });
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.error('❌ ' + app.name + ': clone 失败 — ' + app.repo);
|
|
85
|
+
results.push({ name: app.name, status: 'clone-failed', error: (e.stderr || e.message || '').toString().trim() });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hasFailures = results.some(r => r.status === 'clone-failed' || r.status === 'no-repo');
|
|
91
|
+
console.log('---');
|
|
92
|
+
console.log('SYNC_RESULT', JSON.stringify(results));
|
|
93
|
+
process.exit(hasFailures ? 2 : 0);
|
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: openspec-init-worktree
|
|
3
|
+
description: "为一个需求在 workspace 与各关联应用仓库同步创建同名物理 git worktree,直聚在 `.worktrees/worktree-<需求名>/` 下。触发:用户明确要求创建需求工作空间/开发隔离环境。禁止自动串联 openspec-extend-worktree 或 openspec-close-worktree——除非用户明确说了要补加应用或关闭。"
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires git (>=2.30) and Node.js (>=16.7.0). All commands are pure Node.js scripts under `scripts/`, fully cross-platform (Windows / macOS / Linux, bash / PowerShell / Git Bash).
|
|
6
|
+
metadata:
|
|
7
|
+
author: Contributors
|
|
8
|
+
version: "2.0"
|
|
9
|
+
generatedBy: coding-bb
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Init Worktree(跨平台脚本化版本 v2.0)
|
|
13
|
+
|
|
14
|
+
为一个需求在 workspace 与各关联应用仓库同步创建同名 git worktree,物理直聚在 `.worktrees/worktree-<需求名>/` 目录下。当你需要跨多个微服务仓库并行开发某个需求时,本技能一次性完成工作空间和所有关联应用仓库的 worktree 创建。
|
|
15
|
+
|
|
16
|
+
**启动时声明:** "我正在使用 openspec-init-worktree 技能来创建多仓库联动的隔离 worktree 环境。"
|
|
17
|
+
|
|
18
|
+
## 核心原则
|
|
19
|
+
|
|
20
|
+
- 本技能的所有原子操作封装为 `scripts/*.js` Node.js 脚本,**跨平台执行**(Windows PowerShell / macOS bash / Linux bash / Git Bash 均无需适配)
|
|
21
|
+
- 物理位置与 `init-worktree` 兼容:`.worktrees/worktree-<需求名>/<应用名>/`
|
|
22
|
+
- 所有仓库使用统一的分支名(不加前缀);worktree 目录名自动加 `worktree-` 前缀
|
|
23
|
+
- **本技能必须在业务工作空间根目录执行**(即由 `cbb setup` 初始化、包含 `CONFIG.json` 的目录)
|
|
24
|
+
- 输入约定:**自由文本**(需求名、应用仓库 URL 等)直接在对话中提问并等待回复,禁止使用 `AskUserQuestion`;**固定列表多选**(如应用选择)使用 `AskUserQuestion`(`multiSelect: true`),按 side 分组排列选项
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 调用脚本的统一方式
|
|
29
|
+
|
|
30
|
+
**重要**:所有脚本必须用**绝对路径**调用。`./scripts/...` 相对路径在 Qoder 沙箱中不适用(AI agent 的 cwd 不一定是技能目录)。
|
|
31
|
+
|
|
32
|
+
调用方式(推荐用绝对路径):
|
|
33
|
+
```
|
|
34
|
+
node "D:\workspace\<用户工作空间>\.qoder\skills\openspec-init-worktree\scripts\<name>.js" <参数>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
脚本输出:
|
|
38
|
+
- 人类可读报告(OK / FAIL / WARN)
|
|
39
|
+
- 机器可读摘要(末行以 XXX_OK / XXX_FAILED / XXX_RESULT 开头)
|
|
40
|
+
- AI agent 解析末行摘要决定下一步
|
|
41
|
+
|
|
42
|
+
所有参数都用绝对路径:
|
|
43
|
+
- `<ws_root>`:工作空间根目录绝对路径
|
|
44
|
+
- `<branch>`:需求名字符串
|
|
45
|
+
- `<wt_path>`:worktree 绝对路径
|
|
46
|
+
|
|
47
|
+
所有脚本读 CONFIG.json:app 列表从 `<ws_root>/CONFIG.json` 读取,不需要传 JSON 参数。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Step 0:前置校验
|
|
52
|
+
|
|
53
|
+
### 0.1 环境健康探活
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/check-env.js"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**解读输出**:
|
|
60
|
+
- 退出码 0 + 末行 `ENV_OK {...}` → 探活通过,继续
|
|
61
|
+
- 退出码 1 → git 不可用(沙箱 DLL 问题),**终止流程,提示用户到系统终端重试**
|
|
62
|
+
- 退出码 2 → 当前不在 git 仓库,**终止流程,提示用户到工作空间根目录**
|
|
63
|
+
|
|
64
|
+
### 0.1.5 环境健康自检(check-env-deep)
|
|
65
|
+
|
|
66
|
+
提前检测网络/权限/版本问题,把可能在 Step 3.4 push 或 Step 4 install-ai 暴露的失败前移到流程最开始:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/check-env-deep.js"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**解读输出**:
|
|
73
|
+
- 退出码 0 + 末行 `DOCTOR_OK` → 探活通过,继续 Step 0.2
|
|
74
|
+
- 退出码 2 + 末行 `DOCTOR_FAILED` → 致命问题(npm 源不可达 / Node 版本过低 / 权限不足),**直接终止**,根据提示修复后重试
|
|
75
|
+
|
|
76
|
+
**检测项**:
|
|
77
|
+
- Node.js >= 16.7.0
|
|
78
|
+
- npm 官方源可达(`https://registry.npmjs.org`)
|
|
79
|
+
- cbb 是否已安装(未安装仅警告,由 Step 4 自动安装)
|
|
80
|
+
- `.worktrees/` 目录可写
|
|
81
|
+
|
|
82
|
+
### 0.2 读取并校验 CONFIG.json
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/parse-config.js"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**解读输出**:
|
|
89
|
+
- 退出码 0 + 末行 `CONFIG_OK [{...}]` → 解析成功,AI 解析 JSON 获取 apps 列表
|
|
90
|
+
- 退出码 1 + 末行 `CONFIG_MISSING` 或 `CONFIG_INVALID` → 进入 0.3 配置引导
|
|
91
|
+
- 退出码 2 + 末行 `CONFIG_EMPTY` → 进入 0.3 配置引导
|
|
92
|
+
|
|
93
|
+
### 0.3 配置引导
|
|
94
|
+
|
|
95
|
+
当 `CONFIG.json` 缺失、`apps` 为空或格式错误时,向用户说明情况并给出两个选项:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
⚠️ 当前工作空间尚未配置关联应用(CONFIG.json 缺失或 apps 为空)。
|
|
99
|
+
worktree 需要知道要关联哪些应用仓库。
|
|
100
|
+
|
|
101
|
+
请选择:
|
|
102
|
+
[1] 我自行配置 CONFIG.json,配好后告诉你继续
|
|
103
|
+
[2] 提供应用仓库地址,我帮你写入 CONFIG.json
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**选项 1:用户自行配置**
|
|
107
|
+
- 停止当前技能流程
|
|
108
|
+
- 提示用户:*"请编辑 CONFIG.json 后回复'继续',或重新执行 init-worktree。"*
|
|
109
|
+
- 用户回复"继续"后,重新从 Step 0 开始校验
|
|
110
|
+
|
|
111
|
+
**选项 2:帮用户写入 CONFIG.json**
|
|
112
|
+
- 直接在对话中请用户提供应用信息,格式示例:
|
|
113
|
+
```
|
|
114
|
+
应用名: ep-user-auth-app
|
|
115
|
+
仓库地址: git@code.example.com:team/ep-user-auth-app.git
|
|
116
|
+
类型: back(后端)
|
|
117
|
+
|
|
118
|
+
应用名: ep-user-info-server
|
|
119
|
+
仓库地址: git@code.example.com:team/ep-user-info-server.git
|
|
120
|
+
类型: back(后端)
|
|
121
|
+
```
|
|
122
|
+
- 解析后写入 `CONFIG.json`:
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"apps": [
|
|
126
|
+
{ "name": "ep-user-auth-app", "repo": "git@code.example.com:team/ep-user-auth-app.git", "side": "back" },
|
|
127
|
+
{ "name": "ep-user-info-server", "repo": "git@code.example.com:team/ep-user-info-server.git", "side": "back" }
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
- 写入成功后提交到当前分支(确保 Step 2 状态检查通过):
|
|
132
|
+
```bash
|
|
133
|
+
git add CONFIG.json
|
|
134
|
+
git commit -m "chore: add CONFIG.json"
|
|
135
|
+
```
|
|
136
|
+
> 若当前不在主分支上,提示用户切回主分支后再提交;若已在主分支上则直接提交。
|
|
137
|
+
- 提交后重新从 Step 0 校验,通过后继续 Step 1
|
|
138
|
+
|
|
139
|
+
> ⚠️ **禁止**:在 CONFIG.json 无效时跳过本步骤直接创建 worktree,否则无法确定关联应用。
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Step 1:应用选择与代码同步
|
|
144
|
+
|
|
145
|
+
> 🚨 **label 由脚本硬生成,不由 AI 拼接**:调用 `generate-app-options.js` 获取 options,禁止手动构造 label。
|
|
146
|
+
|
|
147
|
+
### 1.1 读取配置并选择应用
|
|
148
|
+
|
|
149
|
+
> **绝对禁止**:不要从 Step 0.2 `parse-config.js` 的输出中自行解析 JSON 来构造 options。`parse-config.js` 仅用于校验 CONFIG.json 是否有效,其输出**不包含**格式化后的 label。必须通过下方脚本获取 options。
|
|
150
|
+
|
|
151
|
+
1. **必须运行 `generate-app-options.js` 脚本**获取 options。这是获取应用选项的**唯一合法途径**。脚本内部用 `JSON.parse` 读取 CONFIG.json,用硬编码公式 `【sideLabel】 - app.name` 逐条生成 label——`app.name` 逐字符原样复制,绝不会被翻译或替换。
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
node ".qoder/skills/openspec-init-worktree/scripts/generate-app-options.js"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**解读输出**:
|
|
158
|
+
- 退出码 0 + 末行 `APP_OPTIONS [{...}]` → 提取该行 JSON 数组,即为 options
|
|
159
|
+
- 退出码 1/2 → 出错,**终止流程**
|
|
160
|
+
|
|
161
|
+
options 中每个元素含:
|
|
162
|
+
- `label`:直接用于 AskUserQuestion 的选项文本(已格式化,如 `【后端】 - ep-user-auth-app`)
|
|
163
|
+
- `name`:CONFIG.json 中 name 的原始值(用于后续步骤匹配)
|
|
164
|
+
|
|
165
|
+
2. **初始消息已点名应用名**:逐个按 `name` 在 options 中匹配;不在配置中的询问用户手动输入 git URL,然后跳到 1.3。
|
|
166
|
+
|
|
167
|
+
3. **否则使用 `AskUserQuestion`(`multiSelect: true`)让用户勾选**:将脚本输出的 options 数组**原样传入**,不增、不减、不改任何字段:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
AskUserQuestion({
|
|
171
|
+
questions: [{
|
|
172
|
+
header: "关联应用",
|
|
173
|
+
multiSelect: true,
|
|
174
|
+
options: <脚本输出的 options 数组,不做任何修改>
|
|
175
|
+
}]
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
4. **解析选择结果**:从 `AskUserQuestion` 返回的选中项中提取应用名(去掉 `【后端】 - ` / `【前端】 - ` 前缀),得到选中的应用列表。用户未选任何项时终止流程。
|
|
180
|
+
|
|
181
|
+
### 1.2 同步 `.code/` 目录代码
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# ws_root 来自 AI agent 维护的状态
|
|
185
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/sync-repos.js" "<ws_root>"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**用法**:
|
|
189
|
+
- `<ws_root>`:工作空间根绝对路径
|
|
190
|
+
- `<app1,app2,...>`:上一步选中的 apps 数组 JSON 字符串
|
|
191
|
+
|
|
192
|
+
**解读输出**:
|
|
193
|
+
- 退出码 0 + 末行 `SYNC_RESULT [...]` → 全部成功
|
|
194
|
+
- 退出码 2 + 末行 `SYNC_RESULT [...]`(含 `clone-failed` 项)→ 部分 clone 失败,**终止流程**
|
|
195
|
+
|
|
196
|
+
> ⓘ **`.code/` 目录**:所有应用代码统一存放在工作空间的 `.code/` 下。基准代码由 `cbb setup` 命令首次 clone,本脚本检查时如已存在则 fetch 更新(秒级),不存在则 clone 兜底。该目录在 Step 3.2 加入 `.gitignore`,不被 workspace 仓库跟踪。
|
|
197
|
+
|
|
198
|
+
### 1.3 最终输出
|
|
199
|
+
|
|
200
|
+
列出确认的关联应用及本地路径(保留序号便于复核),向用户展示并确认:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
确认关联应用:
|
|
204
|
+
后端:
|
|
205
|
+
[1] ep-user-auth-app → .code/ep-user-auth-app
|
|
206
|
+
[2] ep-user-info-server → .code/ep-user-info-server
|
|
207
|
+
前端:
|
|
208
|
+
[3] ep-user-web → .code/ep-user-web
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
> 后续所有步骤中的 `APP_REPOS` 均指向 `$WS_ROOT/.code/<应用名>/`,不再依赖开发者手动配置本地路径。
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Step 2:状态检查
|
|
216
|
+
|
|
217
|
+
对工作空间和关联应用仓库执行**分级检查**——workspace 仓库标准检查(`.gitignore` 操作由 Step 3.2 的 stash 机制保护),app 仓库轻量检查(仅需确保 `origin/main` 引用可用)。**全部通过才继续,任一失败则终止并报告所有问题**(不 fail-fast,跑完所有仓库再汇总)。
|
|
218
|
+
|
|
219
|
+
| 检查项 | workspace 仓库 | app 仓库 |
|
|
220
|
+
|--------|:---:|:---:|
|
|
221
|
+
| 路径存在且是 git 仓库 | ✅ | ✅ |
|
|
222
|
+
| 不在 worktree 中(排除 submodule) | ✅ | ✅ |
|
|
223
|
+
| 不是 submodule | ✅ | ✅ |
|
|
224
|
+
| `git fetch` 拉取远程最新 | ✅ | ✅ |
|
|
225
|
+
| 本地主分支已最新 | ✅ | ❌(直接从 `origin/main` 创建分支) |
|
|
226
|
+
| 无未提交修改 | ❌(由 Step 3.2 stash 处理) | ❌ |
|
|
227
|
+
| 当前在主分支上 | ✅ | ❌ |
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/check-repos.js "<ws_root>" '<app1,app2,...>'
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**解读输出**:
|
|
234
|
+
- 退出码 0 + 末行 `CHECK_RESULT ALL_OK` → 全部通过,继续 Step 3
|
|
235
|
+
- 退出码 2 + 末行 `CHECK_RESULT HAS_FAILURES` → 部分失败,AI agent 报告上面列出的所有问题,**终止流程**
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Step 3:创建分支与 Worktree
|
|
240
|
+
|
|
241
|
+
### 3.1 询问需求名
|
|
242
|
+
|
|
243
|
+
**直接在对话中**向用户提问(不要使用 `AskUserQuestion` 工具):*"请输入需求名(同时作为分支名和 workspace 工作树目录名):"*,然后等待用户的纯文本回复。
|
|
244
|
+
|
|
245
|
+
**命名规则:**
|
|
246
|
+
- 推荐 kebab-case,如 `feature-login`、`ep-user-rebuild`、`fix-2026q2-leak`
|
|
247
|
+
- 禁止包含 `..`、路径分隔符(`/`、`\`)、空格、git 分支禁用字符
|
|
248
|
+
- **需求名同时**作为分支名和 workspace 工作树目录名(`.worktrees/worktree-<需求名>/`)
|
|
249
|
+
|
|
250
|
+
用户输入如 `feature-login`:
|
|
251
|
+
- 分支名:`feature-login`
|
|
252
|
+
- workspace 工作树目录:`.worktrees/worktree-feature-login`
|
|
253
|
+
- 各应用 worktree 子目录:`.worktrees/worktree-feature-login/<应用名>`
|
|
254
|
+
|
|
255
|
+
### 3.2 安全更新 .gitignore(前置)
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/update-gitignore.js "<ws_root>" "<branch>"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
脚本内部自动完成:stash 保护 → 切分支 → 添加 `.worktrees/` 和 `.code/` → 提交 → 切回 → pop stash
|
|
262
|
+
|
|
263
|
+
**解读输出**:
|
|
264
|
+
- 退出码 0 + 末行 `GITIGNORE_OK` → 成功
|
|
265
|
+
- 退出码 2 → 执行失败,**终止流程**
|
|
266
|
+
|
|
267
|
+
> ⚠️ 必须在提交后切回主分支,否则 Step 3.4 的 `git worktree add` 会因分支已检出而失败(脚本已自动处理)。
|
|
268
|
+
|
|
269
|
+
### 3.3 创建分支
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/create-branches.js" "<ws_root>" "<branch>"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**解读输出**:
|
|
276
|
+
- 退出码 0 + 末行 `BRANCH_RESULT [...]` → 全部创建或复用成功
|
|
277
|
+
- 退出码 2 + 末行 `BRANCH_RESULT [...]`(含 `failed` 项)→ 部分失败,**终止流程**
|
|
278
|
+
|
|
279
|
+
**报告示例**:
|
|
280
|
+
```
|
|
281
|
+
✅ workspace: 分支 feature-login 创建成功(从 HEAD)
|
|
282
|
+
⏭️ ep-user-auth-app: 分支已存在,复用
|
|
283
|
+
✅ ep-user-info-server: 分支 feature-login 创建成功(从 origin/main)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
> ⓘ **app 仓库从 `origin/main` 创建分支**:Step 2 已 fetch 确保 `origin/main` 引用是最新的。此方式不依赖 app 仓库当前在哪个分支、是否有未提交修改,实现与本地工作目录状态完全解耦。
|
|
287
|
+
|
|
288
|
+
> ⚠️ 必须用 `git branch` 而非 `git checkout -b`:因为同一分支不能同时在主目录和 worktree 中检出,切换后 Step 3.4 的 `git worktree add` 会报 `fatal: '<branch>' is already checked out`。
|
|
289
|
+
|
|
290
|
+
**情况 B:任一仓库已存在该分支 → 复用**
|
|
291
|
+
- 脚本自动跳过已存在分支(`status: 'reused'`),不阻塞流程
|
|
292
|
+
- 不再提供「复用/修改/中断」选项(脚本自动处理)
|
|
293
|
+
|
|
294
|
+
### 3.4 推送并建立 upstream
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/push-branches.js" "<ws_root>" "<branch>"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
脚本内部自动完成:
|
|
301
|
+
1. **远程探测**:每个仓库先 `git remote` 确认存在远程名
|
|
302
|
+
2. **推送**:执行 `git push -u <remote> <branch>` 推送并建立 upstream
|
|
303
|
+
3. **错误归类**:stderr 含 `Permission denied (publickey)` / `Authentication failed` / `Could not resolve host` / `protected branch` / `already exists` / `non-fast-forward` 时归类为对应错误码
|
|
304
|
+
4. **远程分支已存在**:自动采集 `git rev-parse` + `git log -1` 元信息(hash/author/date/message),附加到 PUSH_RESULT
|
|
305
|
+
|
|
306
|
+
**解读输出:**
|
|
307
|
+
- 退出码 0 + 末行 `PUSH_RESULT [...]` → 全部推送成功,继续 Step 3.5
|
|
308
|
+
- 退出码 2 + 末行 `PUSH_RESULT [...]`(含 `failed` 或 `remote-exists` 项)→ **阻塞流程,AI agent 必须询问用户决策**(见下方"失败处理")
|
|
309
|
+
|
|
310
|
+
**失败处理(AI agent 行为):**
|
|
311
|
+
|
|
312
|
+
| 错误码 | 处理 |
|
|
313
|
+
|--------|------|
|
|
314
|
+
| `ssh-auth-failed` / `https-auth-failed` / `network-unreachable` / `branch-protected` / `no-remote` / `non-fast-forward` / `unknown` | 输出失败明细,按 error 码分组汇总。AskUserQuestion 提供三个选项:1) 修复后重试(推荐) 2) 跳过失败仓库继续 3) 完全终止 |
|
|
315
|
+
| `remote-exists` | 先在纯文本中输出远程 commit 元信息 + 本地 HEAD hash(**二次确认**),再 AskUserQuestion 提供两个选项:1) 关联到 origin/<branch>(执行 set-upstream-to) 2) 终止流程,关闭需求空间后重新创建 |
|
|
316
|
+
|
|
317
|
+
**禁止:** 脚本**禁止**自动 `git branch --set-upstream-to=origin/<branch>`;AI 在询问关联前**必须**先输出 commit 元信息。
|
|
318
|
+
|
|
319
|
+
**为什么 push 放在 worktree 之前:** 失败早暴露,无 worktree 损失;成功后再创建 worktree,分支天然有 upstream;独立脚本便于单测。
|
|
320
|
+
|
|
321
|
+
### 3.5 创建 Worktree(含自愈清理)
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/create-worktrees.js" "<ws_root>" "<branch>"
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
脚本内部自动完成:
|
|
328
|
+
1. **自愈清理**:`git worktree prune` + 物理目录清理(close 因 IDE 锁未能删除的物理目录)
|
|
329
|
+
2. **workspace worktree 创建**:`git worktree add .worktrees/worktree-<branch> <branch>`
|
|
330
|
+
3. **app worktree 创建**(物理嵌套在 workspace worktree 内)
|
|
331
|
+
|
|
332
|
+
**解读输出**:
|
|
333
|
+
- 退出码 0 + 末行 `WT_PATH <绝对路径>` → 全部成功,AI 解析出 worktree 绝对路径供后续 Step 4/5 使用
|
|
334
|
+
- 退出码 2 → workspace worktree 创建失败(分支已检出/权限不足),**终止流程**
|
|
335
|
+
- 退出码 3 → 部分 app worktree 创建失败,**报告已创建/失败详情,用户需手动清理**
|
|
336
|
+
|
|
337
|
+
**报告示例**:
|
|
338
|
+
```
|
|
339
|
+
✅ workspace worktree 已创建:d:\workspace\xxx\.worktrees\worktree-feature-login
|
|
340
|
+
✅ ep-user-auth-app: 嵌套 worktree 创建成功
|
|
341
|
+
✅ ep-user-info-server: 嵌套 worktree 创建成功
|
|
342
|
+
---
|
|
343
|
+
WT_PATH d:\workspace\xxx\.worktrees\worktree-feature-login
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
> ⓘ **tracked 内容自动 checkout**:workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)在 workspace 工作树创建时**自动从 git 对象库 checkout**——**不需要 `cp`、`git clone` 或任何“带过来”动作**。各应用 worktree 同理。
|
|
347
|
+
|
|
348
|
+
> ⓘ **AI 配置目录(.claude/、.qoder/ 等)**:workspace 主分支中这些目录通常为 gitignore'd,不会自动出现在 worktree 中。本 skill 在 Step 4 统一在 worktree 内执行 `cbb init -y` 安装 AI 配置,无需依赖用户手动配置。
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Step 4:安装 AI 配置(必要步骤)
|
|
353
|
+
|
|
354
|
+
workspace 主分支的 `.claude/` `.qoder/` `.cbb/` 通常为 gitignore'd,创建 worktree 时不会自动带入。
|
|
355
|
+
**本步骤在 worktree 内执行 `cbb init --yes` 是必要步骤**——缺失 AI 配置会导致后续
|
|
356
|
+
openspec-propose/apply/verify/ff 等技能全部不可用,worktree 将处于"半残"状态。
|
|
357
|
+
|
|
358
|
+
> 与 push-branches(Step 3.4)一致:**本步骤失败将阻塞 init-worktree**,用户必须手动恢复后重跑。
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/install-ai.js "<wt_path>"
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**解读输出**:
|
|
365
|
+
- 退出码 0 + 末行 `AI_INIT_OK` → 成功,继续 Step 5
|
|
366
|
+
- 退出码 1 → 参数错误(脚本 bug)
|
|
367
|
+
- 退出码 2 + 末行 `AI_INIT_FAILED` → cbb init 执行失败,**init-worktree 中断**,
|
|
368
|
+
按错误提示手动执行 `cd "<wt_path>" && cbb init --yes` 后重跑
|
|
369
|
+
|
|
370
|
+
> `-y` 表示非交互模式:默认选中所有适配器、前置依赖未安装时自动继续,适合 skill 自动化执行。
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Step 5:环境收尾
|
|
375
|
+
|
|
376
|
+
所有步骤完成后,检测当前运行环境,**在新窗口打开 IDE** 并定位到 workspace worktree 目录。
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
node "D:/workspace/<ws_root>/.qoder/skills/openspec-init-worktree/scripts/auto-open.js "<wt_path>"
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**解读末行**:
|
|
383
|
+
- `ENV=QODER_GUI` / `CURSOR_GUI` / `VSCODE_GUI` / `JETBRAINS_GUI` → GUI 模式(已在新窗口打开 IDE)
|
|
384
|
+
- `ENV=CLI` → CLI 模式(AI agent 自行 cd 到 wt_path)
|
|
385
|
+
- `OPEN_FAILED` → 自动打开失败,提示用户手动操作
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## 最终报告
|
|
390
|
+
|
|
391
|
+
最终报告由 AI agent 根据 `auto-open.js` 的末行输出生成,格式同 v1(GUI / CLI / OPEN_FAILED 三种)。
|
|
392
|
+
|
|
393
|
+
> 不自动安装依赖:各仓库技术栈不一(Maven 依赖本机 `~/.m2` 全局共享、无需初始化;Node/Python 等由你进入 worktree 后执行正确的命令,如 `npm ci` / `pnpm`)。猜测安装命令易出错,故不在本步骤处理。
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 快速参考
|
|
398
|
+
|
|
399
|
+
| 场景 | 处理方式 |
|
|
400
|
+
|------|----------|
|
|
401
|
+
| `.worktrees/` 或 `.code/` 未在 `.gitignore` | workspace 仓库自动添加并提交(在 Step 3.2) |
|
|
402
|
+
| `git worktree add` 权限被拒 | 沙箱降级,中断并告知用户 |
|
|
403
|
+
| 状态检查任一失败 | 终止并报告所有问题 |
|
|
404
|
+
| 部分应用 worktree 创建失败 | 提示已创建的回滚清理命令 |
|
|
405
|
+
| workspace 主分支 tracked 内容(openspec/、cbb/ 等) | 自动 checkout 到工作树,无需额外动作(cp/clone 都是多余的) |
|
|
406
|
+
| AI 配置目录(.claude/、.qoder/ 等) | gitignore'd,不在仓库中;**Step 4 是必要步骤**,执行 `cbb init --yes` 自动安装(失败会阻塞 init-worktree) |
|
|
407
|
+
| 需求名(同时作分支名和工作树目录名) | 用户在对话中纯文本输入,参考 Step 3.1 命名规则(kebab-case,禁 `..`、路径分隔符、空格) |
|
|
408
|
+
| 应用选择 | 输入序号(`1,3` / `1-3` / `all`),按 `CONFIG.json` 数组顺序查行 |
|
|
409
|
+
| 沙箱内 node 不可用 | 脚本 fail-fast 并提示用户到系统终端重试 |
|
|
410
|
+
| push 失败(SSH/HTTPS/网络/保护) | push-branches.js 退出码 2,AI 阻塞并询问用户三选项(修复后重试/跳过失败仓库/完全终止) |
|
|
411
|
+
| 远程分支已存在 | push-branches.js 输出 metadata,AI 展示 commit 元信息后询问两选项(关联/终止+重新创建) |
|
|
412
|
+
| 开发过程中推送所有 worktree | Step 3.4 仅覆盖创建时的空 commit;开发过程中产生的提交必须调 `/opsx:push` 或 `openspec-push-worktrees` skill 推送(详见该 skill) |
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 常见错误
|
|
417
|
+
|
|
418
|
+
### 跳过 CONFIG.json 直接硬编码仓库地址
|
|
419
|
+
|
|
420
|
+
- **问题:** 直接在代码中写死仓库 URL 或本地路径,不同团队的仓库地址不同
|
|
421
|
+
- **修复:** 始终从 `CONFIG.json` 读取应用与远程仓库的映射,找不到配置文件时询问用户手动输入 git URL
|
|
422
|
+
|
|
423
|
+
### 状态检查对 app 仓库执行完整五项检查
|
|
424
|
+
|
|
425
|
+
- **问题:** 对所有仓库一视同仁执行全部五项检查(含"当前在主分支""无未提交修改"),导致开发者在 feature 分支上或有 WIP 时无法创建新 worktree
|
|
426
|
+
- **修复:** Step 2 采用分级检查——workspace 仓库完整检查,app 仓库仅轻量检查(路径有效 + fetch 成功 + `origin/main` 可用)
|
|
427
|
+
|
|
428
|
+
### 状态检查失败后继续执行
|
|
429
|
+
|
|
430
|
+
- **问题:** workspace 仓库检查失败但仍继续,导致后续 `.gitignore` 切分支操作失败或带入脏状态
|
|
431
|
+
- **修复:** 任一仓库的任一检查失败立即终止并报告所有问题
|
|
432
|
+
|
|
433
|
+
### 忽略 .gitignore 安全验证
|
|
434
|
+
|
|
435
|
+
- **问题:** `.worktrees/` 或 `.code/` 目录未被忽略,工作树或代码目录内容被 git 跟踪
|
|
436
|
+
- **修复:** 创建工作树前必须用 `git check-ignore` 验证两者均已忽略
|
|
437
|
+
|
|
438
|
+
### 未先创建分支就直接创建 worktree
|
|
439
|
+
|
|
440
|
+
- **问题:** 直接用 `git worktree add -b` 同时创建分支和 worktree,导致部分仓库分支创建成功但 worktree 失败时状态不一致
|
|
441
|
+
- **修复:** 严格按 Step 3 先统一创建分支(3.3)、再统一创建 worktree(3.4)的顺序执行
|
|
442
|
+
|
|
443
|
+
### 用 checkout -b 创建分支后再创建 worktree
|
|
444
|
+
|
|
445
|
+
- **问题:** `git checkout -b <需求名>` 将主目录切到新分支,随后 `git worktree add .worktrees/worktree-<需求名> <需求名>` 报 `fatal: '<需求名>' is already checked out`
|
|
446
|
+
- **修复:** Step 3.3 只用 `git branch` 创建分支,不切换;分支检出由 Step 3.4 的 worktree 完成
|
|
447
|
+
|
|
448
|
+
### 把 worktree 内容当作"软链/克隆"处理
|
|
449
|
+
|
|
450
|
+
- **问题:** 模型误以为工作树是"凭空组装"出来的,写出 `cp`、`cp -r`、`git clone`、`ln -s` 等脚本"把主目录内容带过去"——这都是无用功
|
|
451
|
+
- **修复:** workspace 主分支 tracked 的所有内容(openspec/、cbb/ 等)在 `git worktree add` 时**自动 checkout**;各应用 worktree 同理。如果准备写 cp/clone/symlink 来“带过来”代码,先停下来
|
|
452
|
+
|
|
453
|
+
### label 被 AI 翻译或丢失(已从根本上解决)
|
|
454
|
+
|
|
455
|
+
- **问题:** 历史版本中 Step 1.1 要求 AI 手动拼接 label 字符串,导致 `app.name` 被翻译(`ep-user-auth-app` → `智能客服Agent应用`)或完全丢失(只输出 `后端应用`)。
|
|
456
|
+
- **修复:** 改为调用 `generate-app-options.js` 脚本生成 options——脚本用硬编码公式 `【sideLabel】 - app.name` 逐条生成,`app.name` 逐字符原样复制,AI 只需将脚本输出的 options 数组原样传入 `AskUserQuestion`,不允许手动修改任何字段。
|
|
457
|
+
|
|
458
|
+
### 用 AskUserQuestion 收集自由文本输入
|
|
459
|
+
|
|
460
|
+
- **问题:** 需求名、应用名需要用户自由输入文本,却用了 `AskUserQuestion` 工具,被迫提供预设选项
|
|
461
|
+
- **修复:** 自由文本输入场景一律**直接在对话中提问**并等待用户文本回复;`AskUserQuestion` 仅用于固定选项的选择场景
|
|
462
|
+
|
|
463
|
+
### 完成后未进入 worktree
|
|
464
|
+
|
|
465
|
+
- **问题:** 流程结束后仍停留在工作空间根目录,或跨多次 Bash 调用后丢失 cwd,后续命令作用在错误上下文
|
|
466
|
+
- **修复:** Step 5 起的所有命令用 `cd "<worktree 绝对路径>" && <cmd>` 单次 Bash 调用发起,首条命令后接 `pwd` 确认;最终报告首行输出 `当前目录`
|
|
467
|
+
|
|
468
|
+
### push 失败时跳过失败仓库继续
|
|
469
|
+
|
|
470
|
+
- **问题:** push 失败但 init-worktree 流程继续,导致后续 agent 在 worktree 中遇到无 upstream 分支
|
|
471
|
+
- **修复:** push-branches.js 退出码 2 时必须阻塞流程并询问用户;不允许脚本或 AI 自动跳过失败仓库
|
|
472
|
+
|
|
473
|
+
### 远程分支已存在时自动 set-upstream
|
|
474
|
+
|
|
475
|
+
- **问题:** 看到 origin/<branch> 已存在就直接 `git branch --set-upstream-to`,可能关联到他人的同名分支
|
|
476
|
+
- **修复:** 脚本输出 metadata 后必须由用户决策(关联 vs 终止);AI 在 AskUserQuestion 之前必须先输出 commit 元信息作为二次确认
|
|
477
|
+
|
|
478
|
+
### 用 `git checkout -b` 在 push 后切分支
|
|
479
|
+
|
|
480
|
+
- **问题:** Step 3.5 创建 worktree 前先切到新分支,导致 worktree 创建时分支已检出冲突
|
|
481
|
+
- **修复:** Step 3.3 已统一用 `git branch`(不切换);Step 3.5 的 `git worktree add` 会自动处理 checkout
|
|
482
|
+
|
|
483
|
+
### 把脚本调用与 Shell 变量混用
|
|
484
|
+
|
|
485
|
+
- **问题:** 试图在 Bash 调用中嵌套 Node 脚本与 shell 变量,导致变量解析失败
|
|
486
|
+
- **修复:** 所有脚本参数(`<ws_root>`、`<app1,app2,...>`、`<branch>`)由 AI agent 在对话上下文中维护,**作为字符串参数传入脚本**,不要在 Bash 命令中拼 shell 变量
|
|
487
|
+
|
|
488
|
+
### 把 install-ai 当作可失败步骤
|
|
489
|
+
|
|
490
|
+
- **问题:** 以为 worktree 创建成功就能继续工作,忽略了 Step 4 失败,导致后续 openspec-* 技能全部报"找不到 skill"
|
|
491
|
+
- **修复:** Step 4 失败必须手动 `cd <wt_path> && cbb init --yes`,然后重跑 init-worktree(脚本会自动跳过已初始化的部分)
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## 红线规则
|
|
496
|
+
|
|
497
|
+
以下为硬性红线,违反任一会导致工作树状态不一致或创建失败。
|
|
498
|
+
|
|
499
|
+
**绝不允许**
|
|
500
|
+
|
|
501
|
+
- 跳过或绕过 Step 2 状态检查;状态检查失败后继续
|
|
502
|
+
- workspace 仓库创建工作树前不验证 `.worktrees/` 和 `.code/` 在 `.gitignore`
|
|
503
|
+
- 用 `git checkout -b` 切分支后再建 worktree(分支检出冲突)
|
|
504
|
+
- 用 `AskUserQuestion` 收集自由文本(需求名 / 分支选项等)
|
|
505
|
+
- **Step 1.1 手动构造 AskUserQuestion options(禁止)**——必须调用 `generate-app-options.js` 脚本生成 options,将输出原样传入 `AskUserQuestion`,不得手动拼接 label。详见 [Step 1.1](#11-读取配置并选择应用)
|
|
506
|
+
- 沙箱内 node 不可用时强行继续 → 改为 fail-fast 提示用户
|
|
507
|
+
- **Step 3.4 推送失败后跳过失败仓库直接继续** → 必须阻塞并询问用户决策
|
|
508
|
+
- **远程分支已存在时脚本自动 set-upstream-to** → 必须由用户决策,避免关联到他人的同名分支
|
|
509
|
+
- **AI 询问关联选项前不输出 commit 元信息** → 必须先在 AskUserQuestion 之前输出远程 hash/author/date/message + 本地 hash
|
|
510
|
+
- **Step 4 install-ai 失败时强行继续** → 必须阻塞并按错误提示恢复,AI 不得绕过退出码 2 继续执行
|
|
511
|
+
|
|
512
|
+
**必须执行**
|
|
513
|
+
|
|
514
|
+
- workspace 仓库标准检查(当前在主分支等),app 仓库轻量检查(fetch + `origin/main` 可用即可)
|
|
515
|
+
- app 仓库分支从 `origin/main` 创建(`git branch <需求名> ${REMOTE}/${MAIN}`),不依赖本地主分支状态
|
|
516
|
+
- 严格 Step 3.3 → Step 3.4 顺序(先统一创建分支,再统一创建 worktree;workspace 工作树先建,各应用按序补建)
|
|
517
|
+
- 所有脚本调用以 `node "<WS_ROOT>\.qoder\skills\openspec-init-worktree\scripts\<name>.js" "<绝对路径>" "<branch>"` 形式发起(apps 由脚本内部从 CONFIG.json 读取),**不依赖跨调用的 cwd**
|
|
518
|
+
- **Step 1.1 调用 `AskUserQuestion` 前必须由脚本生成 options**:执行 `node ".qoder/skills/openspec-init-worktree/scripts/generate-app-options.js"`,将 `APP_OPTIONS` 输出的 JSON 数组原样传入 `AskUserQuestion` options,禁止手动修改。
|
|
519
|
+
- **Step 3.4 push 步骤必须执行且插入在 create-branches.js (3.3) 之后、create-worktrees.js (3.5) 之前** — 失败时阻塞整个 init-worktree 流程
|
|
520
|
+
- **Step 3.4 仅覆盖创建 worktree 时的空 commit** — 开发过程中产生的本地 commit(如 apply 任务实现)必须由用户在 worktree 中手动提交并调 `openspec-push-worktrees` 推送;不允许依赖 Step 3.4 之后的自动推送(不存在)
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## 附录:脚本清单
|
|
525
|
+
|
|
526
|
+
| 脚本 | 功能 | 参数 | 退出码 |
|
|
527
|
+
|------|------|------|--------|
|
|
528
|
+
| `check-env.js` | 环境探活 | 无 | 0/1/2 |
|
|
529
|
+
| `parse-config.js` | 解析 CONFIG.json | 无 | 0/1/2 |
|
|
530
|
+
| `generate-app-options.js` | 机械生成 AskUserQuestion options(杜绝翻译) | [--filter=name1,name2] | 0/1/2 |
|
|
531
|
+
| `sync-repos.js` | 同步 .code/ 仓库 | ws_root, apps_json | 0/1/2 |
|
|
532
|
+
| `check-repos.js` | 状态检查 | ws_root, apps_json | 0/1/2 |
|
|
533
|
+
| `update-gitignore.js` | 安全更新 .gitignore | ws_root, branch | 0/1/2 |
|
|
534
|
+
| `create-branches.js` | 创建分支 | ws_root, branch | 0/1/2 |
|
|
535
|
+
| `create-worktrees.js` | 创建 worktree(含自愈清理) | ws_root, branch | 0/1/2/3 |
|
|
536
|
+
| `install-ai.js` | 安装 AI 配置(**必要步骤**) | wt_path | 0/1/2 |
|
|
537
|
+
| `push-branches.js` | 推送并建立 upstream(带错误归类 + 元信息采集) | ws_root, branch | 0/1/2 |
|
|
538
|
+
| `check-env-deep.js` | 环境健康自检(Node 版本 / npm 源 / 权限) | 无 | 0/2 |
|
|
539
|
+
| `auto-open.js` | 环境感知自动打开(**新窗口**) | wt_path | 0(始终) |
|