@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.
@@ -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
- * 不装 base 工作流、编码规范、superpowers、版本检查 hook--这些属于 sandbox worktree
1029
- * 内的开发配置,由 worktree `cbbm init --yes` 完整模式安装。在 workspace 根目录
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 已安装(.cbb/.managed-by-cbb 存在),比较已装版本与当前包版本决定是否继续。
1163
+ * 若 targetDir 已安装,比较已装版本与当前包版本决定是否继续安装。
1159
1164
  * - 版本一致 → 返回 'skip'(不询问、不重复安装)
1160
- * - 版本不同 → 询问是否升级到当前包版本,用户拒绝返回 'cancel'
1165
+ * - 版本不同 → 返回 'install'(setup 已整体确认过,直接升级到当前包版本,不再二次询问)
1161
1166
  * - 未安装 → 返回 'install'(不提示,直接继续)
1162
1167
  *
1163
1168
  * 注:只比较「已装版本 vs 当前包版本」——安装动作只能落盘当前包的产物,
1164
1169
  * registry 是否有更新由用户级版本检查 hook 提醒,不在此处联网查询。
1165
- * @returns {Promise<'install'|'skip'|'cancel'>}
1170
+ * @returns {'install'|'skip'}
1166
1171
  */
1167
- async function confirmUpgradeIfInstalled(targetDir) {
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. 若已安装:版本未变化直接跳过;有新版本需用户确认;用户拒绝则跳过本 workspace
1478
- const decision = await confirmUpgradeIfInstalled(targetDir);
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` 生成(仅缺失时写入,之后不会覆盖或删除,可自由增补团队约定)。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jspg-ai/coding-bb",
3
- "version": "0.0.2-beta.25",
3
+ "version": "0.0.2-beta.27",
4
4
  "description": "整合业界热门且高价值的工具、框架与技能,为 AI CODING AGENT 提供统一的行为准则与工作流,辅助开发者将需求高效落地为符合规范的代码",
5
5
  "main": "cbb/lib/install/init.js",
6
6
  "bin": {