@house365/comate 0.7.0 → 0.9.0

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Jian Liang
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jian Liang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,102 +1,102 @@
1
- # comate
2
-
3
- OpenSpec + Superpowers 规约驱动的 AI 开发编排器。
4
-
5
- comate 把 **OpenSpec**(WHAT:提案、规约生命周期、归档)和 **Superpowers**(HOW:设计、规划、执行、收尾)整合成统一的五阶段工作流。核心原则:每个变更都要经过深度设计(fix 预设除外)。
6
-
7
- ## 五阶段
8
-
9
- ```
10
- [原始 PRD] ─→ /comate-gate ─┐ (阶段 0:门禁+拆分)
11
- ▼
12
- /comate ──自动探测阶段──────→ open → design → build → verify → archive
13
- ```
14
-
15
- | 阶段 | skill | 职责 |
16
- |------|-------|------|
17
- | gate | `/comate-gate` | (阶段 0,可选)对原始 PRD 做质量门禁 + 拆分成 N 个 change |
18
- | open | `/comate-open` | 探索想法,创建 change 结构并初始化 `.comate.yaml` |
19
- | design | `/comate-design` | 技术设计与方案 brainstorming |
20
- | build | `/comate-build` | 按任务实现并提交 |
21
- | verify | `/comate-verify` | 验证、出报告、处理分支 |
22
- | archive | `/comate-archive` | 同步增量规约并归档 |
23
-
24
- 预设路径:`/comate-fix`(快速小改动,覆盖 bug 修复与文案/配置小调整两种模式)。
25
-
26
- 工具 skill:
27
- - `/comate-grill`(决策点穷追式澄清)——对计划/设计/PRD 的模糊点逐个深挖,每问附推荐答案、一次一问,直到歧义清零。comate-gate 在阻断问题多、有依赖链时会自动提供「深度澄清」选项调用它;也可单独 `/comate-grill <话题>` 挑战自己的计划草稿。
28
- - `/comate-kb-integration`(第三方对接档案生成)——从官方文档 URL 抓取并按 `docs/knowledge-base/integrations/_TEMPLATE/` 规范产出对接档案(`<service-id>/README.md` + `api-snapshot.md`),自动追加根索引一行。是知识库 integrations scaffold 的配套建档工具;遇 JS 动态渲染文档站自动降级 Playwright 无头抓取。
29
-
30
- **阶段 0(PRD 门禁与拆分)**:需求若来自一份**原始 PRD**,先过 `/comate-gate`——它审阅 PRD 质量、百分制评分、建阻断台账,门禁通过前禁止建任何 change;通过后按依赖/独立性判定把 PRD 拆成 1 或 N 个 change(粒度由用户定),逐个交给 `/comate-open`。门禁状态钉在 PRD 同级 `<PRD>.gate.yaml`,PRD 通过后被改会自动失效需重跑。需求来自对话时无需此阶段,直接从 open 起步。
31
-
32
- ## 安装
33
-
34
- ```bash
35
- npm install -g @house365/comate
36
- ```
37
-
38
- 到项目目录初始化:
39
-
40
- ```bash
41
- cd your-project
42
- comate init
43
- ```
44
-
45
- `init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),创建 `openspec/` 项目结构,并铺出 `docs/` 知识库骨架(`docs/knowledge-base/requirements/` 放 PRD + PRD 模板、`docs/architecture/` 架构规范占位、integrations 对接模板)——`/comate-gate` 从这里读 PRD。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过,已有的 docs 文件不覆盖。
46
-
47
- skills 装到用户级(`~/.agents/skills`),装一次所有项目共用;`openspec/` 是项目自己的规约,建在当前目录,所以 `init` 需要在项目目录下运行。
48
-
49
- 装完输入 `/comate` 开始使用,`comate doctor` 可自检。
50
-
51
- ## 更新
52
-
53
- ```bash
54
- npm install -g @house365/comate@latest
55
- cd your-project && comate init
56
- ```
57
-
58
- 两步都要跑:`npm` 只换 CLI 本身,skills 是 `comate init` 铺到 `~/.agents/skills` 的,npm 不管。这里的 `@latest` 不能省——本地已装时,不带 tag 的 `npm install -g` 可能认为已满足而不去 registry 取新版。
59
-
60
- ## 用法
61
-
62
- 输入 `/comate` 自动探测当前阶段并分派,或直接调用某个阶段 skill。状态记录在每个 change 的 `openspec/changes/<name>/.comate.yaml` 中,支持上下文压缩后断点恢复。
63
-
64
- ## Token 用量:`comate usage`
65
-
66
- 查看**当前项目**的 token 消耗与估算成本(封装 [ccusage](https://github.com/ryoppippi/ccusage),随 comate 一起装):
67
-
68
- ```bash
69
- comate usage # 本项目按会话(session)统计
70
- comate usage daily # 本项目按天
71
- comate usage --global # 全部项目(不做项目隔离)
72
- comate usage --json -s 2026-08-01 # 其余参数原样透传给 ccusage
73
- ```
74
-
75
- 默认只统计当前工作目录这一个项目:Claude Code 数据按 `~/.claude/projects/<项目>/` 隔离,Codex 数据按会话记录里的 `cwd` 过滤,两者都不会混入其它项目的用量。加 `--global` 看全量,或用 `comate usage codex ...` 单看某个 agent。
76
-
77
- > 粒度到项目/会话级;不做 open/design/build 阶段级归因(那需要在状态机打时间戳,属后续增强)。
78
-
79
- ## 目录结构
80
-
81
- ```
82
- skills/
83
- comate/ 主编排器:SKILL.md + 脚本 + 参考文档 + 测试
84
- scripts/ comate.sh(CLI)、comate-lib.sh(共享库)
85
- reference/ 决策点、脏工作树协议、前置条件
86
- tests/ bats 测试
87
- comate-open/ design/ build/ verify/ archive/ 各阶段 skill
88
- comate-gate/ 阶段 0:PRD 门禁与拆分
89
- comate-fix/ 预设路径 skill(bug + 小调整)
90
- comate-grill/ 决策点穷追式澄清工具
91
- comate-kb-integration/ 第三方对接档案生成工具(知识库配套)
92
- docs/
93
- COMATE_MANUAL.md 完整操作手册
94
- ```
95
-
96
- ## 文档
97
-
98
- 完整说明见 [docs/COMATE_MANUAL.md](docs/COMATE_MANUAL.md):安装前置、命令参考、阶段详解、状态文件字段、决策阻塞点、故障排除。
99
-
100
- ## License
101
-
102
- [MIT](LICENSE)
1
+ # comate
2
+
3
+ OpenSpec + Superpowers 规约驱动的 AI 开发编排器。
4
+
5
+ comate 把 **OpenSpec**(WHAT:提案、规约生命周期、归档)和 **Superpowers**(HOW:设计、规划、执行、收尾)整合成统一的五阶段工作流。核心原则:每个变更都要经过深度设计(fix 预设除外)。
6
+
7
+ ## 五阶段
8
+
9
+ ```
10
+ [原始 PRD] ─→ /comate-gate ─┐ (阶段 0:门禁+拆分)
11
+ ▼
12
+ /comate ──自动探测阶段──────→ open → design → build → verify → archive
13
+ ```
14
+
15
+ | 阶段 | skill | 职责 |
16
+ |------|-------|------|
17
+ | gate | `/comate-gate` | (阶段 0,可选)对原始 PRD 做质量门禁 + 拆分成 N 个 change |
18
+ | open | `/comate-open` | 探索想法,创建 change 结构并初始化 `.comate.yaml` |
19
+ | design | `/comate-design` | 技术设计与方案 brainstorming |
20
+ | build | `/comate-build` | 按任务实现并提交 |
21
+ | verify | `/comate-verify` | 验证、出报告、处理分支 |
22
+ | archive | `/comate-archive` | 同步增量规约并归档 |
23
+
24
+ 预设路径:`/comate-fix`(快速小改动,覆盖 bug 修复与文案/配置小调整两种模式)。
25
+
26
+ 工具 skill:
27
+ - `/comate-grill`(决策点穷追式澄清)——对计划/设计/PRD 的模糊点逐个深挖,每问附推荐答案、一次一问,直到歧义清零。comate-gate 在阻断问题多、有依赖链时会自动提供「深度澄清」选项调用它;也可单独 `/comate-grill <话题>` 挑战自己的计划草稿。
28
+ - `/comate-kb-integration`(第三方对接档案生成)——从官方文档 URL 抓取并按 `docs/knowledge-base/integrations/_TEMPLATE/` 规范产出对接档案(`<service-id>/README.md` + `api-snapshot.md`),自动追加根索引一行。是知识库 integrations scaffold 的配套建档工具;遇 JS 动态渲染文档站自动降级 Playwright 无头抓取。
29
+
30
+ **阶段 0(PRD 门禁与拆分)**:需求若来自一份**原始 PRD**,先过 `/comate-gate`——它审阅 PRD 质量、百分制评分、建阻断台账,门禁通过前禁止建任何 change;通过后按依赖/独立性判定把 PRD 拆成 1 或 N 个 change(粒度由用户定),逐个交给 `/comate-open`。门禁状态钉在 PRD 同级 `<PRD>.gate.yaml`,PRD 通过后被改会自动失效需重跑。需求来自对话时无需此阶段,直接从 open 起步。
31
+
32
+ ## 安装
33
+
34
+ ```bash
35
+ npm install -g @house365/comate
36
+ ```
37
+
38
+ 到项目目录初始化:
39
+
40
+ ```bash
41
+ cd your-project
42
+ comate init
43
+ ```
44
+
45
+ `init` 会装好 comate 及其依赖(OpenSpec CLI、Superpowers),创建 `openspec/` 项目结构,并铺出 `docs/` 知识库骨架(`docs/knowledge-base/requirements/` 放 PRD + PRD 模板、`docs/architecture/` 架构规范占位、integrations 对接模板)——`/comate-gate` 从这里读 PRD。支持 Claude Code、Codex、Cursor 等 70+ agent。可重复执行,已装的自动跳过,已有的 docs 文件不覆盖。
46
+
47
+ skills 装到用户级(`~/.agents/skills`),装一次所有项目共用;`openspec/` 是项目自己的规约,建在当前目录,所以 `init` 需要在项目目录下运行。
48
+
49
+ 装完输入 `/comate` 开始使用,`comate doctor` 可自检。
50
+
51
+ ## 更新
52
+
53
+ ```bash
54
+ npm install -g @house365/comate@latest
55
+ cd your-project && comate init
56
+ ```
57
+
58
+ 两步都要跑:`npm` 只换 CLI 本身,skills 是 `comate init` 铺到 `~/.agents/skills` 的,npm 不管。这里的 `@latest` 不能省——本地已装时,不带 tag 的 `npm install -g` 可能认为已满足而不去 registry 取新版。
59
+
60
+ ## 用法
61
+
62
+ 输入 `/comate` 自动探测当前阶段并分派,或直接调用某个阶段 skill。状态记录在每个 change 的 `openspec/changes/<name>/.comate.yaml` 中,支持上下文压缩后断点恢复。
63
+
64
+ ## Token 用量:`comate usage`
65
+
66
+ 查看**当前项目**的 token 消耗与估算成本(封装 [ccusage](https://github.com/ryoppippi/ccusage),随 comate 一起装):
67
+
68
+ ```bash
69
+ comate usage # 本项目按会话(session)统计
70
+ comate usage daily # 本项目按天
71
+ comate usage --global # 全部项目(不做项目隔离)
72
+ comate usage --json -s 2026-08-01 # 其余参数原样透传给 ccusage
73
+ ```
74
+
75
+ 默认只统计当前工作目录这一个项目:Claude Code 数据按 `~/.claude/projects/<项目>/` 隔离,Codex 数据按会话记录里的 `cwd` 过滤,两者都不会混入其它项目的用量。加 `--global` 看全量,或用 `comate usage codex ...` 单看某个 agent。
76
+
77
+ > 粒度到项目/会话级;不做 open/design/build 阶段级归因(那需要在状态机打时间戳,属后续增强)。
78
+
79
+ ## 目录结构
80
+
81
+ ```
82
+ skills/
83
+ comate/ 主编排器:SKILL.md + 脚本 + 参考文档 + 测试
84
+ scripts/ comate.sh(CLI)、comate-lib.sh(共享库)
85
+ reference/ 决策点、脏工作树协议、前置条件
86
+ tests/ bats 测试
87
+ comate-open/ design/ build/ verify/ archive/ 各阶段 skill
88
+ comate-gate/ 阶段 0:PRD 门禁与拆分
89
+ comate-fix/ 预设路径 skill(bug + 小调整)
90
+ comate-grill/ 决策点穷追式澄清工具
91
+ comate-kb-integration/ 第三方对接档案生成工具(知识库配套)
92
+ docs/
93
+ COMATE_MANUAL.md 完整操作手册
94
+ ```
95
+
96
+ ## 文档
97
+
98
+ 完整说明见 [docs/COMATE_MANUAL.md](docs/COMATE_MANUAL.md):安装前置、命令参考、阶段详解、状态文件字段、决策阻塞点、故障排除。
99
+
100
+ ## License
101
+
102
+ [MIT](LICENSE)
package/bin/init-run.mjs CHANGED
@@ -11,10 +11,12 @@ import {
11
11
  SKILLS_TIMEOUT_MS,
12
12
  npmInvocation,
13
13
  openSpecState,
14
+ pruneDeprecatedSkills,
14
15
  run,
15
16
  scaffoldDocs,
16
17
  skillsInvocation,
17
18
  superpowersInstalled,
19
+ userSkillsRoot,
18
20
  } from './init.mjs';
19
21
 
20
22
  // `comate init` — no flags. Skills go user-level (~/.agents/skills), matching how
@@ -133,6 +135,13 @@ export async function init(pkgRoot) {
133
135
  results.push(['comate', r.ok ? 'installed' : 'failed', r.ok ? '' : r.reason, r.output]);
134
136
  }
135
137
 
138
+ // Prune comate skill dirs renamed/dropped in past releases. `skills add` above
139
+ // only adds/overwrites, so /comate-hotfix etc. would otherwise linger as dead
140
+ // slash commands. The postinstall hook does this too, but --ignore-scripts
141
+ // users never run it — init is their only path, so it must clean up here.
142
+ const pruned = pruneDeprecatedSkills(userSkillsRoot(home));
143
+ if (pruned.length) results.push(['清理废弃 skill', 'installed', pruned.join('、')]);
144
+
136
145
  // 4. openspec/ project structure. Not optional: comate's open and archive
137
146
  // phases read it, so an install without it cannot actually run. An existing
138
147
  // one is left alone, which covers projects that already keep it elsewhere.
package/bin/init.mjs CHANGED
@@ -9,7 +9,7 @@
9
9
  // ponytail: no SKILLS_AGENT_MAP here. The skills CLI detects the running agent
10
10
  // on its own, so translating platform ids to agent names would be dead code.
11
11
  import { spawnSync } from 'node:child_process';
12
- import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync } from 'node:fs';
12
+ import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, lstatSync, rmSync } from 'node:fs';
13
13
  import { createRequire } from 'node:module';
14
14
  import { dirname, join } from 'node:path';
15
15
 
@@ -211,6 +211,83 @@ function scaffoldDocs(pkgRoot, cwd = process.cwd()) {
211
211
  return { ok: true, created, skipped };
212
212
  }
213
213
 
214
+ // comate skill dirs that later releases renamed or dropped. `skills add` only
215
+ // adds/overwrites, never removes, so without an explicit prune these linger in
216
+ // ~/.agents/skills as dead slash commands (e.g. /comate-hotfix after it became
217
+ // /comate-fix). ONLY these exact names are ever deleted: the dir also holds
218
+ // unrelated third-party skills (lark-*, openspec-*), so a prefix sweep or a
219
+ // diff-against-current strategy could wipe a user's own work. Add a line here
220
+ // whenever a comate skill is renamed or removed.
221
+ const DEPRECATED_SKILLS = ['comate-hotfix', 'comate-tweak', 'comate-intake'];
222
+
223
+ function userSkillsRoot(home = process.env.HOME ?? process.env.USERPROFILE ?? '') {
224
+ return join(home, '.agents', 'skills');
225
+ }
226
+
227
+ // lstat, not stat: only a real directory is a comate-installed skill. A symlink
228
+ // is a developer's deliberate dev setup pointing elsewhere — never remove it.
229
+ function isRealDir(p) {
230
+ try {
231
+ return lstatSync(p).isDirectory();
232
+ } catch {
233
+ return false;
234
+ }
235
+ }
236
+
237
+ // Delete only the exact DEPRECATED_SKILLS dirs present under skillsRoot. Every
238
+ // dependency is injectable so tests never touch a real ~/.agents/skills. Never
239
+ // throws — a permission error or race on one dir must not abort an install.
240
+ // Returns the names actually removed (for the caller to report).
241
+ function pruneDeprecatedSkills(
242
+ skillsRoot,
243
+ {
244
+ names = DEPRECATED_SKILLS,
245
+ exists = existsSync,
246
+ isDir = isRealDir,
247
+ rm = (p) => rmSync(p, { recursive: true, force: true }),
248
+ } = {},
249
+ ) {
250
+ const removed = [];
251
+ for (const name of names) {
252
+ const dir = join(skillsRoot, name);
253
+ if (!exists(dir) || !isDir(dir)) continue;
254
+ try {
255
+ rm(dir);
256
+ removed.push(name);
257
+ } catch {
258
+ // A stuck dir (locked, permission) is not worth failing the install over.
259
+ }
260
+ }
261
+ return removed;
262
+ }
263
+
264
+ // True only when the pinned `skills` dependency resolves locally. A postinstall
265
+ // must never reach the network, so this gates syncComateSkills: if resolution
266
+ // fails we skip rather than let skillsInvocation fall back to `npx skills@latest`.
267
+ function skillsResolvesLocally(pkgRoot) {
268
+ try {
269
+ createRequire(join(pkgRoot, 'package.json')).resolve('skills/package.json');
270
+ return true;
271
+ } catch {
272
+ return false;
273
+ }
274
+ }
275
+
276
+ // Copy comate's own skills into ~/.agents/skills via the bundled skills CLI —
277
+ // the exact command `comate init` runs, so the layout is identical. Local-only:
278
+ // skips (never goes to network) when the skills dep can't be resolved, leaving
279
+ // `comate init` as the fallback. Returns { ok, skipped }.
280
+ function syncComateSkills(pkgRoot, { home = process.env.HOME ?? process.env.USERPROFILE ?? '', runner = run } = {}) {
281
+ if (!skillsResolvesLocally(pkgRoot)) return { ok: false, skipped: 'no-local-cli' };
282
+ const r = runner(
283
+ skillsInvocation(pkgRoot, ['add', pkgRoot, '--skill', '*', '-g', '-y']),
284
+ SKILLS_TIMEOUT_MS,
285
+ { quiet: true },
286
+ );
287
+ const landed = existsSync(join(home, '.agents', 'skills', 'comate', 'SKILL.md'));
288
+ return { ok: r.ok && landed, skipped: null };
289
+ }
290
+
214
291
  export {
215
292
  MIN_OPENSPEC,
216
293
  NPM_TIMEOUT_MS,
@@ -228,4 +305,8 @@ export {
228
305
  scaffoldSourceDir,
229
306
  copyTreeSkipExisting,
230
307
  scaffoldDocs,
308
+ DEPRECATED_SKILLS,
309
+ userSkillsRoot,
310
+ pruneDeprecatedSkills,
311
+ syncComateSkills,
231
312
  };
@@ -14,13 +14,33 @@ if (isCI() || isDevInstall()) {
14
14
 
15
15
  const { banner, pkgVersion } = await import('./init-run.mjs');
16
16
 
17
+ // Best-effort: refresh the user-level skills so `npm i -g @latest` alone updates
18
+ // them, and prune dirs renamed/dropped in past releases. All guarded — a failure
19
+ // here must never break the npm install, and `comate init` remains the fallback
20
+ // for --ignore-scripts users (who never reach this hook) and per-project setup.
21
+ const sync = await syncSkillsQuietly();
22
+
17
23
  console.log(banner(pkgVersion(pkgRoot)));
18
24
  console.log(` 🎉 Congratulations! comate 已成功安装。\n`);
25
+ if (sync.synced) console.log(' ✓ 已把 skills 同步到 ~/.agents/skills');
26
+ if (sync.removed.length) console.log(` ✓ 已清理废弃 skill:${sync.removed.join('、')}`);
19
27
  console.log(' 下一步:');
20
- console.log(' 在你的项目目录下运行 comate init 开始使用');
28
+ console.log(' 在你的项目目录下运行 comate init 完成项目初始化(openspec/、docs/)');
21
29
  console.log(' 或运行 comate doctor 健康检查');
22
30
  console.log(' 更多帮助 comate --help\n');
23
31
 
32
+ async function syncSkillsQuietly() {
33
+ try {
34
+ const { syncComateSkills, pruneDeprecatedSkills, userSkillsRoot } = await import('./init.mjs');
35
+ const { ok } = syncComateSkills(pkgRoot);
36
+ const removed = pruneDeprecatedSkills(userSkillsRoot());
37
+ return { synced: ok, removed };
38
+ } catch {
39
+ // Any failure (no skills CLI resolvable, fs error) is silent: init covers it.
40
+ return { synced: false, removed: [] };
41
+ }
42
+ }
43
+
24
44
  function isCI() {
25
45
  return Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
26
46
  }