@jspg-ai/coding-bb 0.0.2-beta.25 → 0.0.2-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cbb/lib/install/init.js
CHANGED
|
@@ -1024,9 +1024,10 @@ async function init(targetDir, options = {}) {
|
|
|
1024
1024
|
/**
|
|
1025
1025
|
* 为 workspace 根目录安装 AI 配置子集(由 cbb setup 调用)。
|
|
1026
1026
|
*
|
|
1027
|
-
* 只装 worktree 生命周期管理(init/close/push)+ openspec
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1027
|
+
* 只装 worktree 生命周期管理(init/close/push)+ openspec 运行时配置 + 空间导航
|
|
1028
|
+
* AGENTS.md(仅缺失时生成,永不覆盖),不装 base 工作流、编码规范、superpowers、
|
|
1029
|
+
* 版本检查 hook--这些属于 sandbox worktree 内的开发配置,由 worktree 内
|
|
1030
|
+
* `cbbm init --yes` 完整模式安装。在 workspace 根目录
|
|
1030
1031
|
* (主分支)装 base 工作流会诱导绕过 worktree 直接在主分支做需求开发。
|
|
1031
1032
|
*/
|
|
1032
1033
|
async function installWorkspaceConfig(targetDir, options = {}) {
|
|
@@ -1106,6 +1107,9 @@ async function installWorkspaceConfig(targetDir, options = {}) {
|
|
|
1106
1107
|
const openspecRes = setupOpenSpec(isUpgrade, managedPaths);
|
|
1107
1108
|
newPaths.add('openspec/config.yaml');
|
|
1108
1109
|
|
|
1110
|
+
// 空间导航文件 AGENTS.md:仅缺失时生成,永不覆盖(不登记清单,卸载不删)
|
|
1111
|
+
const agentsMdState = workspaces.ensureWorkspaceAgentsMd(TARGET_DIR);
|
|
1112
|
+
|
|
1109
1113
|
// 升级时清理旧路径(workspace 曾装过的 base 工作流等不属于此子集,删除)
|
|
1110
1114
|
const cleaned = [];
|
|
1111
1115
|
const keptDocs = [];
|
|
@@ -1139,6 +1143,7 @@ async function installWorkspaceConfig(targetDir, options = {}) {
|
|
|
1139
1143
|
if (openspecRes.installed.length > 0) {
|
|
1140
1144
|
parts.push(`openspec ${openspecRes.defaultSchema || openspecRes.installed.join('/')}`);
|
|
1141
1145
|
}
|
|
1146
|
+
if (agentsMdState === 'created') parts.push('AGENTS.md(空间导航)');
|
|
1142
1147
|
const configLabel = 'AI 配置';
|
|
1143
1148
|
step('✓', configLabel, parts.join(' · '));
|
|
1144
1149
|
if (cleaned.length > 0) {
|
|
@@ -1155,16 +1160,16 @@ async function installWorkspaceConfig(targetDir, options = {}) {
|
|
|
1155
1160
|
// ── cbb setup 命令 ──────────────────────────────────────
|
|
1156
1161
|
|
|
1157
1162
|
/**
|
|
1158
|
-
* 若 targetDir
|
|
1163
|
+
* 若 targetDir 已安装,比较已装版本与当前包版本决定是否继续安装。
|
|
1159
1164
|
* - 版本一致 → 返回 'skip'(不询问、不重复安装)
|
|
1160
|
-
* - 版本不同 →
|
|
1165
|
+
* - 版本不同 → 返回 'install'(setup 已整体确认过,直接升级到当前包版本,不再二次询问)
|
|
1161
1166
|
* - 未安装 → 返回 'install'(不提示,直接继续)
|
|
1162
1167
|
*
|
|
1163
1168
|
* 注:只比较「已装版本 vs 当前包版本」——安装动作只能落盘当前包的产物,
|
|
1164
1169
|
* registry 是否有更新由用户级版本检查 hook 提醒,不在此处联网查询。
|
|
1165
|
-
* @returns {
|
|
1170
|
+
* @returns {'install'|'skip'}
|
|
1166
1171
|
*/
|
|
1167
|
-
|
|
1172
|
+
function decideUpgradeIfInstalled(targetDir) {
|
|
1168
1173
|
const installed = version.readInstalledVersion(targetDir);
|
|
1169
1174
|
if (!installed) return 'install'; // 未安装:不提示,直接继续
|
|
1170
1175
|
|
|
@@ -1177,11 +1182,6 @@ async function confirmUpgradeIfInstalled(targetDir) {
|
|
|
1177
1182
|
}
|
|
1178
1183
|
|
|
1179
1184
|
step('⏳', '版本', `v${installed} → v${pkg.version}`, { iconColor: 'cyan' });
|
|
1180
|
-
const answer = await ask(`? 升级到 v${pkg.version}?(Y/n) `);
|
|
1181
|
-
if (answer && answer.toLowerCase() === 'n') {
|
|
1182
|
-
step('!', '版本', '已跳过安装/升级', { iconColor: 'yellow' });
|
|
1183
|
-
return 'cancel';
|
|
1184
|
-
}
|
|
1185
1185
|
return 'install';
|
|
1186
1186
|
}
|
|
1187
1187
|
|
|
@@ -1474,11 +1474,8 @@ async function initSingleWorkspace(w, opts = {}) {
|
|
|
1474
1474
|
console.log(` ${c('gray', `${names} → 编辑 workspace-config.json 填入真实仓库地址`)}`);
|
|
1475
1475
|
}
|
|
1476
1476
|
|
|
1477
|
-
// 5.
|
|
1478
|
-
const decision =
|
|
1479
|
-
if (decision === 'cancel') {
|
|
1480
|
-
return { ok: false, error: 'USER_CANCELLED', skipped: true };
|
|
1481
|
-
}
|
|
1477
|
+
// 5. 若已安装:版本未变化直接跳过;有新版本直接升级(setup 已整体确认过,不再二次询问)
|
|
1478
|
+
const decision = decideUpgradeIfInstalled(targetDir);
|
|
1482
1479
|
if (decision === 'skip') {
|
|
1483
1480
|
return { ok: true, subdir: subdirName, upToDate: true };
|
|
1484
1481
|
}
|
|
@@ -1501,7 +1498,6 @@ function describeBatchError(r) {
|
|
|
1501
1498
|
case 'CLONE_FAILED': return `git clone 失败:${r.message || ''}`.trim();
|
|
1502
1499
|
case 'PULL_FAILED': return `工作空间仓库同步失败:${r.message || ''}`.trim();
|
|
1503
1500
|
case 'CONFIG_INVALID': return `workspace-config.json 不合法:${r.message || ''}`.trim();
|
|
1504
|
-
case 'USER_CANCELLED': return '用户取消升级';
|
|
1505
1501
|
case 'INIT_FAILED': return `初始化失败:${r.message || ''}`.trim();
|
|
1506
1502
|
default: return r.error || '未知错误';
|
|
1507
1503
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - 加载 + 校验
|
|
9
9
|
* - 归一化 remote URL(兼容 SSH / HTTPS 两种写法)
|
|
10
10
|
* - 检测当前目录是否已拉取指定 workspace 的仓库
|
|
11
|
+
* - 空间种子文件生成(AGENTS.md 空间导航,仅缺失时)
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
const fs = require('fs');
|
|
@@ -16,6 +17,7 @@ const { execSync } = require('child_process');
|
|
|
16
17
|
|
|
17
18
|
const DEFAULT_CONFIG = 'config/workspaces.json';
|
|
18
19
|
const SAMPLE_CONFIG = 'config/workspace-config.sample.json';
|
|
20
|
+
const SAMPLE_AGENTS_MD = 'config/workspace-agents.sample.md';
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* 归一化 git remote URL:提取 "namespace/repo" 形式(去掉 .git 后缀)。
|
|
@@ -166,6 +168,24 @@ function validateWorkspaceConfig(configPath) {
|
|
|
166
168
|
return { valid: true, config: raw };
|
|
167
169
|
}
|
|
168
170
|
|
|
171
|
+
/**
|
|
172
|
+
* 确保业务空间根目录存在 AGENTS.md(空间导航文件,讲清目录职责与协作约定)。
|
|
173
|
+
*
|
|
174
|
+
* 仅缺失时从包内模板复制;已存在(可能含团队自维护内容)一律不覆盖。
|
|
175
|
+
* 该文件不登记安装清单,升级 / 卸载均不触碰。
|
|
176
|
+
*
|
|
177
|
+
* @param {string} targetDir 业务空间根目录
|
|
178
|
+
* @returns {'exists' | 'created'}
|
|
179
|
+
*/
|
|
180
|
+
function ensureWorkspaceAgentsMd(targetDir) {
|
|
181
|
+
const agentsPath = path.join(targetDir, 'AGENTS.md');
|
|
182
|
+
if (fs.existsSync(agentsPath)) return 'exists';
|
|
183
|
+
|
|
184
|
+
const samplePath = path.resolve(__dirname, '..', '..', '..', SAMPLE_AGENTS_MD);
|
|
185
|
+
fs.copyFileSync(samplePath, agentsPath);
|
|
186
|
+
return 'created';
|
|
187
|
+
}
|
|
188
|
+
|
|
169
189
|
/**
|
|
170
190
|
* 在指定目录执行 `git remote -v`,解析出 [{ name, url }] 列表。
|
|
171
191
|
* 任何异常静默返回空数组,便于上层用 state 机判定。
|
|
@@ -259,10 +279,12 @@ function findSampleApps(apps) {
|
|
|
259
279
|
module.exports = {
|
|
260
280
|
DEFAULT_CONFIG,
|
|
261
281
|
SAMPLE_CONFIG,
|
|
282
|
+
SAMPLE_AGENTS_MD,
|
|
262
283
|
normalizeRepoUrl,
|
|
263
284
|
matchesConfiguredRepo,
|
|
264
285
|
loadWorkspaces,
|
|
265
286
|
validateWorkspaceConfig,
|
|
287
|
+
ensureWorkspaceAgentsMd,
|
|
266
288
|
readGitRemotes,
|
|
267
289
|
detectRepo,
|
|
268
290
|
extractRepoBasename,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 业务空间使用说明(AI Agent 导航)
|
|
2
|
+
|
|
3
|
+
本目录是由 `@jspg-ai/coding-bb` 初始化的**多仓库联动开发业务空间**。
|
|
4
|
+
进入本目录工作时,请先按本文件理解目录职责与协作约定,再动手。
|
|
5
|
+
|
|
6
|
+
## 核心约定
|
|
7
|
+
|
|
8
|
+
1. **本目录不做需求开发**。本目录(业务空间主分支)只负责组织与调度;所有需求开发都在 `.worktrees/worktree-<需求名>/` 隔离目录内进行。
|
|
9
|
+
2. **接到新需求先建 worktree**:在本目录执行 `/cbb:worktree-init <需求名>`(opencode 写法:`/cbb-worktree-init`)。它会为 `workspace-config.json` 中的全量关联应用同步创建同名 worktree,并自动安装沙箱内的编码规范与 OpenSpec 工作流。
|
|
10
|
+
3. **开发动作全部在 worktree 内**:需求提案 / 实现 / 验证 / 归档(`/opsx:propose` → `/opsx:apply` → `/opsx:verify` → `/opsx:archive`)在 worktree 沙箱内执行;跨仓库提交推送用 `/cbb:worktree-push`,需求收尾用 `/cbb:worktree-close`。
|
|
11
|
+
4. **关联应用增减只改配置**:编辑 `workspace-config.json` 的 `apps` 数组(`name` / `repo` / `side` / `desc`),然后用同一需求名重跑 worktree 初始化即幂等补齐;不要手工 `git clone` 应用仓库。
|
|
12
|
+
5. **不要绕过 worktree 直接修改 `.codespace/` 或本目录的代码**。`.codespace/` 是工具维护的基准代码,不是开发区。
|
|
13
|
+
|
|
14
|
+
## 目录结构与职责
|
|
15
|
+
|
|
16
|
+
| 路径 | 职责 | 维护方式 |
|
|
17
|
+
|------|------|----------|
|
|
18
|
+
| `workspace-config.json` | 关联应用清单,所有应用联动的唯一数据源 | 人工编辑 |
|
|
19
|
+
| `.codespace/` | 各关联应用的基准代码(每个应用一个子目录) | `cbb setup` 与 worktree 流程自动 clone / fetch;**勿手动编辑**;已 gitignore,不提交 |
|
|
20
|
+
| `.worktrees/` | 需求隔离开发区(每个需求一个 `worktree-<需求名>/` 目录) | worktree 命令自动创建 / 清理;不提交(首次执行 worktree 流程时自动加入 .gitignore) |
|
|
21
|
+
| `openspec/` | OpenSpec 工作流配置(`config.yaml` + `schemas/`) | 由 cbb 安装;需求变更产物(`openspec/changes/` 等)在 worktree 内生成,随需求分支提交 |
|
|
22
|
+
| `.claude/` `.qoder/` `.opencode/` | AI 工具适配目录:worktree 管理技能与命令;**故意不含**编码规范(防止在空间根直接开发) | 由 cbb 按 setup 时选择的工具安装;已 gitignore,不提交,勿手动改 |
|
|
23
|
+
| `.cbb/` | cbb 安装清单,记录本包管理的全部路径 | 由 cbb 管理;**勿手动编辑** |
|
|
24
|
+
|
|
25
|
+
## 典型流程
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
本目录:/cbb:worktree-init <需求名>
|
|
29
|
+
→ .worktrees/worktree-<需求名>/ 内开发(/opsx:propose → /opsx:apply → /opsx:verify → /opsx:archive)
|
|
30
|
+
→ /cbb:worktree-push 推送 → 合并后 /cbb:worktree-close 关闭
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> 命令写法因 AI 工具而异:Claude Code / Qoder 为 `/cbb:worktree-init`,opencode 为 `/cbb-worktree-init`;`/opsx:*` 同理(opencode 为 `/opsx-*`)。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
本文件由 `@jspg-ai/coding-bb` 生成(仅缺失时写入,之后不会覆盖或删除,可自由增补团队约定)。
|