@house365/comate 0.10.3 → 1.0.2-next.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.
Files changed (73) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +104 -64
  3. package/bin/cli.mjs +197 -190
  4. package/bin/doctor.mjs +29 -41
  5. package/bin/init-run.mjs +310 -368
  6. package/bin/init.mjs +53 -71
  7. package/bin/postinstall.mjs +56 -56
  8. package/docs/CHANGELOG-fix-simplification.md +145 -0
  9. package/docs/COMATE_BETA.md +90 -0
  10. package/docs/COMATE_MANUAL.md +239 -665
  11. package/docs/superpowers/plans/2026-10-14-review-fixes.md +48 -0
  12. package/docs/superpowers/plans/2026-10-14-workflow-quality.md +48 -0
  13. package/package.json +54 -55
  14. package/skills/comate/SKILL.md +42 -325
  15. package/skills/comate/reference/archive.md +50 -0
  16. package/skills/comate/reference/build.md +67 -0
  17. package/skills/comate/reference/fix.md +150 -0
  18. package/skills/comate/reference/open.md +162 -0
  19. package/skills/comate/reference/verify.md +123 -0
  20. package/skills/comate/scaffold/comate/README.md +18 -0
  21. package/skills/{comate-gate/scaffold/docs → comate/scaffold/comate}/architecture/README.md +5 -6
  22. package/skills/comate/scaffold/comate/comate/config.json +10 -0
  23. package/skills/comate/scaffold/comate/knowledge-base/README.md +42 -0
  24. package/skills/{comate-gate/scaffold/docs → comate/scaffold/comate}/knowledge-base/integrations/_TEMPLATE/README.md +2 -2
  25. package/skills/{comate-gate/scaffold/docs → comate/scaffold/comate}/knowledge-base/integrations/_TEMPLATE/api-snapshot.md +47 -47
  26. package/skills/{comate-gate/scaffold/docs → comate/scaffold/comate}/knowledge-base/requirements/_templates/PRD.md +4 -4
  27. package/skills/comate/scripts/comate.mjs +147 -0
  28. package/skills/comate/scripts/lib/acceptance.mjs +112 -0
  29. package/skills/comate/scripts/lib/brief.mjs +50 -0
  30. package/skills/comate/scripts/lib/checks.mjs +178 -0
  31. package/skills/comate/scripts/lib/cmd-archive.mjs +152 -0
  32. package/skills/comate/scripts/lib/cmd-decide.mjs +116 -0
  33. package/skills/comate/scripts/lib/cmd-init.mjs +75 -0
  34. package/skills/comate/scripts/lib/cmd-loop.mjs +273 -0
  35. package/skills/comate/scripts/lib/cmd-open.mjs +161 -0
  36. package/skills/comate/scripts/lib/cmd-status.mjs +121 -0
  37. package/skills/comate/scripts/lib/common.mjs +85 -0
  38. package/skills/comate/scripts/lib/docs.mjs +45 -0
  39. package/skills/comate/scripts/lib/finish.mjs +108 -0
  40. package/skills/comate/scripts/lib/git.mjs +112 -0
  41. package/skills/comate/scripts/lib/md.mjs +85 -0
  42. package/skills/comate/scripts/lib/next.mjs +217 -0
  43. package/skills/comate/scripts/lib/paths.mjs +96 -0
  44. package/skills/comate/scripts/lib/render.mjs +46 -0
  45. package/skills/comate/scripts/lib/spec.mjs +106 -0
  46. package/skills/comate/scripts/lib/state.mjs +128 -0
  47. package/skills/comate/scripts/lib/tasks.mjs +53 -0
  48. package/skills/comate/scripts/lib/templates.mjs +58 -0
  49. package/skills/comate/scripts/lib/util.mjs +108 -0
  50. package/skills/comate-kb-integration/SKILL.md +128 -128
  51. package/skills/comate-kb-integration/scripts/fetch_rendered_doc.py +84 -84
  52. package/bin/cleanup-duplicate-superpowers.mjs +0 -119
  53. package/docs/COMATE_BEGINNER_GUIDE.md +0 -188
  54. package/docs/COMATE_INIT_DIRECTORY_GUIDE.md +0 -201
  55. package/docs/superpowers/plans/2026-09-13-fast-workflow.md +0 -62
  56. package/skills/comate/reference/decision-points.md +0 -103
  57. package/skills/comate/reference/dirty-worktree.md +0 -58
  58. package/skills/comate/reference/prerequisites.md +0 -89
  59. package/skills/comate/scripts/comate-lib.sh +0 -559
  60. package/skills/comate/scripts/comate.sh +0 -2147
  61. package/skills/comate/tests/comate.bats +0 -1019
  62. package/skills/comate/tests/run.sh +0 -101
  63. package/skills/comate-archive/SKILL.md +0 -63
  64. package/skills/comate-build/SKILL.md +0 -278
  65. package/skills/comate-design/SKILL.md +0 -178
  66. package/skills/comate-fix/SKILL.md +0 -195
  67. package/skills/comate-gate/SKILL.md +0 -319
  68. package/skills/comate-gate/scaffold/docs/README.md +0 -36
  69. package/skills/comate-gate/scaffold/docs/knowledge-base/README.md +0 -47
  70. package/skills/comate-grill/SKILL.md +0 -185
  71. package/skills/comate-open/SKILL.md +0 -240
  72. package/skills/comate-verify/SKILL.md +0 -212
  73. /package/skills/{comate-gate/scaffold/docs → comate/scaffold/comate}/knowledge-base/integrations/README.md +0 -0
package/bin/init.mjs CHANGED
@@ -1,19 +1,14 @@
1
- // `comate-skills init` — install comate's prerequisites, then comate itself.
2
- //
3
- // Three dependencies, each already has an installer we can drive:
4
- // OpenSpec CLI -> npm install -g @fission-ai/openspec@latest (PATH command,
5
- // so always global regardless of the chosen skill scope)
6
- // Superpowers -> npx skills add obra/superpowers (scope-aware)
7
- // comate -> npx skills add <this package> (scope-aware)
1
+ // `comate init` helpers. comate 1.0 has no external workflow dependencies: it
2
+ // needs Node and git, installs its own skills through the pinned `skills` CLI,
3
+ // and lays down the comate/ project scaffold.
8
4
  //
9
5
  // ponytail: no SKILLS_AGENT_MAP here. The skills CLI detects the running agent
10
6
  // on its own, so translating platform ids to agent names would be dead code.
11
7
  import { spawnSync } from 'node:child_process';
12
- import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, lstatSync, rmSync, readFileSync } from 'node:fs';
8
+ import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, lstatSync, renameSync, rmSync } from 'node:fs';
13
9
  import { createRequire } from 'node:module';
14
10
  import { dirname, join } from 'node:path';
15
11
 
16
- const MIN_OPENSPEC = '1.5.0';
17
12
  const NPM_TIMEOUT_MS = 180_000;
18
13
  const SKILLS_TIMEOUT_MS = 300_000;
19
14
 
@@ -141,63 +136,17 @@ function skillsInvocation(pkgRoot, args) {
141
136
  }
142
137
  }
143
138
 
144
- function openSpecState() {
145
- // shell:true on Windows: npm installs this as openspec.cmd, which cannot be
146
- // spawned directly. bashVersion needs no shell — it has a real executable path.
147
- const version = capture('openspec', ['--version'], { shell: process.platform === 'win32' });
148
- if (version === null) return { status: 'missing' };
149
- return { status: atLeast(version, MIN_OPENSPEC) ? 'ready' : 'outdated', version };
150
- }
151
-
152
- // Detect skills CLI installation (flattens obra/superpowers into one dir per
153
- // skill) and Claude Code plugin installation (installed_plugins.json registry).
154
- const SUPERPOWERS_MARKERS = [
155
- ['using-superpowers'],
156
- ['brainstorming'],
157
- ];
158
-
159
- function superpowersInstalled(scope) {
160
- const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
161
- const roots =
162
- scope === 'global'
163
- ? ['.agents/skills', '.claude/skills', '.config/skills', '.cursor/skills']
164
- .map((r) => join(home, r))
165
- : ['.agents/skills', '.claude/skills', '.cursor/skills', '.codex/skills'];
166
-
167
- // Check skills CLI installation
168
- if (roots.some((root) => SUPERPOWERS_MARKERS.some((m) => existsSync(join(root, ...m))))) {
169
- return true;
170
- }
171
-
172
- // Check Claude Code plugin installation (only for global scope - plugins are user-level)
173
- if (scope === 'global') {
174
- const pluginRegistry = join(home, '.claude', 'plugins', 'installed_plugins.json');
175
- try {
176
- const registry = JSON.parse(readFileSync(pluginRegistry, 'utf8'));
177
- // Check if superpowers plugin is installed (any marketplace)
178
- return Object.keys(registry.plugins || {}).some((key) =>
179
- key.startsWith('superpowers@') && Array.isArray(registry.plugins[key]) && registry.plugins[key].length > 0
180
- );
181
- } catch {
182
- // File doesn't exist or parse failed - not a plugin install
183
- return false;
184
- }
185
- }
186
-
187
- return false;
188
- }
189
-
190
- // The docs scaffold ships inside the comate skill, so it is present both in dev
191
- // (repo checkout) and after `skills add` copies the skill to ~/.agents/skills.
139
+ // The comate/ scaffold ships inside the comate skill, so it is present both in
140
+ // dev (repo checkout) and after `skills add` copies the skill to ~/.agents/skills.
192
141
  // Locating it relative to pkgRoot means init reads the same tree it packed.
193
142
  function scaffoldSourceDir(pkgRoot) {
194
- return join(pkgRoot, 'skills', 'comate-gate', 'scaffold', 'docs');
143
+ return join(pkgRoot, 'skills', 'comate', 'scaffold', 'comate');
195
144
  }
196
145
 
197
146
  // copyTreeSkipExisting — recursively copy src→dst, never overwriting a file that
198
147
  // already exists. Returns { created, skipped } counts so init can report whether
199
- // it actually laid anything down (matching the openspec/ step's idempotence:
200
- // an existing docs/ is left alone, only missing pieces are filled in).
148
+ // it actually laid anything down: an existing comate/ is left alone, only
149
+ // missing pieces are filled in.
201
150
  function copyTreeSkipExisting(src, dst, acc = { created: 0, skipped: 0 }) {
202
151
  mkdirSync(dst, { recursive: true });
203
152
  for (const entry of readdirSync(src)) {
@@ -215,17 +164,45 @@ function copyTreeSkipExisting(src, dst, acc = { created: 0, skipped: 0 }) {
215
164
  return acc;
216
165
  }
217
166
 
218
- // scaffoldDocs — lay down docs/ (knowledge-base + architecture placeholder + PRD
219
- // template) so /comate-gate has somewhere to read PRDs from. comate_kb_root in
220
- // comate-lib.sh is hardcoded to docs/knowledge-base, so this path is not
221
- // configurable — it must match. Idempotent: existing files are never clobbered.
222
- function scaffoldDocs(pkgRoot, cwd = process.cwd()) {
167
+ // scaffoldComate — lay down comate/ (config.json, knowledge-base with the PRD
168
+ // template, architecture placeholder). The layout is fixed: comate.mjs looks for
169
+ // comate/comate/config.json under the git root. Idempotent: existing files are
170
+ // never clobbered.
171
+ function scaffoldComate(pkgRoot, cwd = process.cwd()) {
223
172
  const src = scaffoldSourceDir(pkgRoot);
224
173
  if (!existsSync(src)) return { ok: false, reason: `scaffold source missing: ${src}` };
225
- const { created, skipped } = copyTreeSkipExisting(src, join(cwd, 'docs'));
174
+ const { created, skipped } = copyTreeSkipExisting(src, join(cwd, 'comate'));
226
175
  return { ok: true, created, skipped };
227
176
  }
228
177
 
178
+ // 0.x kept long-lived docs under docs/; 1.0 keeps everything under comate/.
179
+ // Only these two directories move — the rest of docs/ belongs to the project.
180
+ const LAYOUT_MOVES = [
181
+ ['docs/knowledge-base', 'comate/knowledge-base'],
182
+ ['docs/architecture', 'comate/architecture'],
183
+ ];
184
+
185
+ // -> { moves: [{ from, to, status: 'move' | 'conflict' | 'moved' }], ok }.
186
+ // git mv keeps history; a destination that already exists is a conflict and
187
+ // nothing is moved at all, so a half-migrated tree never happens.
188
+ function migrateLayout(cwd = process.cwd(), { dryRun = true } = {}) {
189
+ const moves = LAYOUT_MOVES.filter(([from]) => existsSync(join(cwd, from))).map(([from, to]) => ({
190
+ from,
191
+ to,
192
+ status: existsSync(join(cwd, to)) ? 'conflict' : 'move',
193
+ }));
194
+ const ok = moves.every((m) => m.status !== 'conflict');
195
+ if (dryRun || !ok) return { moves, ok };
196
+ const inGit = spawnSync('git', ['rev-parse', '--git-dir'], { cwd, stdio: 'ignore' }).status === 0;
197
+ for (const m of moves) {
198
+ mkdirSync(dirname(join(cwd, m.to)), { recursive: true });
199
+ const r = inGit ? spawnSync('git', ['mv', m.from, m.to], { cwd, encoding: 'utf8' }) : null;
200
+ if (!r || r.status !== 0) renameSync(join(cwd, m.from), join(cwd, m.to));
201
+ m.status = 'moved';
202
+ }
203
+ return { moves, ok };
204
+ }
205
+
229
206
  // comate skill dirs that later releases renamed or dropped. `skills add` only
230
207
  // adds/overwrites, never removes, so without an explicit prune these linger in
231
208
  // ~/.agents/skills as dead slash commands (e.g. /comate-hotfix after it became
@@ -233,7 +210,13 @@ function scaffoldDocs(pkgRoot, cwd = process.cwd()) {
233
210
  // unrelated third-party skills (lark-*, openspec-*), so a prefix sweep or a
234
211
  // diff-against-current strategy could wipe a user's own work. Add a line here
235
212
  // whenever a comate skill is renamed or removed.
236
- const DEPRECATED_SKILLS = ['comate-hotfix', 'comate-tweak', 'comate-intake'];
213
+ // 1.0: one /comate skill drives every phase through the Node state machine; the
214
+ // per-phase skills (gate/spec/build/verify/fix) are gone.
215
+ const DEPRECATED_SKILLS = [
216
+ 'comate-hotfix', 'comate-tweak', 'comate-intake',
217
+ 'comate-open', 'comate-design', 'comate-archive', 'comate-grill',
218
+ 'comate-gate', 'comate-spec', 'comate-build', 'comate-verify', 'comate-fix',
219
+ ];
237
220
 
238
221
  function userSkillsRoot(home = process.env.HOME ?? process.env.USERPROFILE ?? '') {
239
222
  return join(home, '.agents', 'skills');
@@ -304,7 +287,6 @@ function syncComateSkills(pkgRoot, { home = process.env.HOME ?? process.env.USER
304
287
  }
305
288
 
306
289
  export {
307
- MIN_OPENSPEC,
308
290
  NPM_TIMEOUT_MS,
309
291
  SKILLS_TIMEOUT_MS,
310
292
  findNpmCli,
@@ -315,11 +297,11 @@ export {
315
297
  run,
316
298
  capture,
317
299
  atLeast,
318
- openSpecState,
319
- superpowersInstalled,
320
300
  scaffoldSourceDir,
321
301
  copyTreeSkipExisting,
322
- scaffoldDocs,
302
+ scaffoldComate,
303
+ migrateLayout,
304
+ LAYOUT_MOVES,
323
305
  DEPRECATED_SKILLS,
324
306
  userSkillsRoot,
325
307
  pruneDeprecatedSkills,
@@ -1,56 +1,56 @@
1
- #!/usr/bin/env node
2
- // Postinstall hook: show the wordmark and next steps after npm install finishes.
3
- // Skipped in CI (where the logo wouldn't render anyway) and local dev installs
4
- // (where the developer already knows what they installed).
5
- import { fileURLToPath } from 'node:url';
6
- import { dirname, resolve } from 'node:path';
7
-
8
- const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
9
-
10
- // Skip in CI, or when installing the package's own dependencies during dev.
11
- if (isCI() || isDevInstall()) {
12
- process.exit(0);
13
- }
14
-
15
- const { banner, pkgVersion } = await import('./init-run.mjs');
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
-
23
- console.log(banner(pkgVersion(pkgRoot)));
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('、')}`);
27
- console.log(' 下一步:');
28
- console.log(' 在你的项目目录下运行 comate init 完成项目初始化(openspec/、docs/)');
29
- console.log(' 或运行 comate doctor 健康检查');
30
- console.log(' 更多帮助 comate --help\n');
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
-
44
- function isCI() {
45
- return Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
46
- }
47
-
48
- // When npm installs a package's own dependencies (npm i in the repo itself),
49
- // INIT_CWD points to the package root. A user installing comate globally or as
50
- // a dependency has INIT_CWD pointing elsewhere.
51
- function isDevInstall() {
52
- const initCwd = process.env.INIT_CWD;
53
- if (!initCwd) return false;
54
- const normalise = (p) => resolve(p).replace(/[\\/]+$/, '').toLowerCase();
55
- return normalise(initCwd) === normalise(pkgRoot);
56
- }
1
+ #!/usr/bin/env node
2
+ // Postinstall hook: show the wordmark and next steps after npm install finishes.
3
+ // Skipped in CI (where the logo wouldn't render anyway) and local dev installs
4
+ // (where the developer already knows what they installed).
5
+ import { fileURLToPath } from 'node:url';
6
+ import { dirname, resolve } from 'node:path';
7
+
8
+ const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
9
+
10
+ // Skip in CI, or when installing the package's own dependencies during dev.
11
+ if (isCI() || isDevInstall()) {
12
+ process.exit(0);
13
+ }
14
+
15
+ const { banner, pkgVersion } = await import('./init-run.mjs');
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
+
23
+ console.log(banner(pkgVersion(pkgRoot)));
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('、')}`);
27
+ console.log(' 下一步:');
28
+ console.log(' 在你的项目目录下运行 comate init 完成项目初始化(comate/)');
29
+ console.log(' 或运行 comate doctor 健康检查');
30
+ console.log(' 更多帮助 comate --help\n');
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
+
44
+ function isCI() {
45
+ return Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
46
+ }
47
+
48
+ // When npm installs a package's own dependencies (npm i in the repo itself),
49
+ // INIT_CWD points to the package root. A user installing comate globally or as
50
+ // a dependency has INIT_CWD pointing elsewhere.
51
+ function isDevInstall() {
52
+ const initCwd = process.env.INIT_CWD;
53
+ if (!initCwd) return false;
54
+ const normalise = (p) => resolve(p).replace(/[\\/]+$/, '').toLowerCase();
55
+ return normalise(initCwd) === normalise(pkgRoot);
56
+ }
@@ -0,0 +1,145 @@
1
+ # fix 模式简化:原则而非清单
2
+
3
+ **日期**: 2026-10-08
4
+ **改动范围**: `skills/comate/reference/fix.md`, `skills/comate/reference/open.md`, `skills/comate/SKILL.md`
5
+
6
+ ## 背景
7
+
8
+ 之前的 fix 模式虽然简化了 brief 结构(三章 vs 七章),但在澄清阶段仍然要求走九大视角的清单式检查。这对于边界清楚的小修来说过于繁重,限制了模型的自主判断能力。
9
+
10
+ ## 改动内容
11
+
12
+ ### 1. fix 模式采用原则驱动澄清
13
+
14
+ **之前**:fix 模式在 open 阶段仍需逐项检查九大视角
15
+ **现在**:只需回答三个核心问题
16
+
17
+ ```markdown
18
+ 1. **修什么**(目标) — 现象、影响范围、复现方式
19
+ 2. **怎么验收**(验收示例) — 至少一条「修复后原问题不再出现」
20
+ 3. **为什么这样修**(决定) — 根因分析与修复方式
21
+ ```
22
+
23
+ ### 2. 按需查证而非强制清单
24
+
25
+ **新增"何时需要查证"指引**:
26
+
27
+ | 情况 | 处理方式 |
28
+ |---|---|
29
+ | 根因不明 | 先复现问题、定位根因,再写 brief |
30
+ | 影响范围不确定 | 检查调用链、依赖关系,明确波及范围 |
31
+ | 修复方案有多种 | 评估可逆性和副作用,选最小改动;不确定时问用户 |
32
+ | 可能破坏已有行为 | 列出可能受影响的场景,验收示例必须包含回归检查 |
33
+
34
+ **判断标准**:如果写完 brief 后发现"其实不太确定影响范围"或"可能有副作用但说不清",那就是该查证的信号。
35
+
36
+ ### 3. full 模式九大视角增加快速判定指南
37
+
38
+ 在 `reference/open.md` 的九大视角表格中新增第三列"何时可快速标记'不适用'":
39
+
40
+ - **用户与场景**:纯内部技术重构、CLI 工具、开发者工具
41
+ - **架构与边界**:单一模块内的局部改动,不涉及模块间交互
42
+ - **旅程与状态**:无状态变更(纯查询、纯展示)
43
+ - **数据与规则**:不涉及数据存储或传输(纯前端交互)
44
+ - **风险与反例**:仅管理员可见、无外部输入、单机运行
45
+ - 等等...
46
+
47
+ 标记"不适用"的判断标准:遗漏这一项**不会**导致返工或生产问题。
48
+
49
+ ### 4. 明确 fix 的适用场景和升级时机
50
+
51
+ **适合 fix**:
52
+ - 明确的 bug,能快速复现和定位
53
+ - 影响范围清楚(单一模块或功能)
54
+ - 修复方案直接(不涉及架构调整)
55
+ - 改动文件少(bug 修复 ≤3 个文件,调整 ≤5 个文件)
56
+
57
+ **升级为 full 的时机**:
58
+ - 改动规模超出预期(涉及 3+ 文件或需改 schema/API/架构)
59
+ - 影响范围扩大(需要新的用户可见行为)
60
+ - 根因复杂(需要分阶段处理或产品决策)
61
+
62
+ **边界不清时,默认用 full**。
63
+
64
+ ### 5. 增强验收要求
65
+
66
+ 明确 Bug 修复的验收**必须包含**:
67
+ 1. **正向验证** — 修复后原问题消失
68
+ 2. **回归验证** — 相关场景不受影响(列出具体场景)
69
+ 3. **边界验证** — 极值、空值、并发(按实际风险选择)
70
+
71
+ ## 设计理念
72
+
73
+ ### 从"清单驱动"到"原则驱动"
74
+
75
+ **清单驱动**(full 模式):
76
+ - 优势:系统性覆盖,不遗漏关键维度
77
+ - 劣势:认知负担重,可能过度工程,限制模型创造性
78
+
79
+ **原则驱动**(fix 模式):
80
+ - 优势:轻量快速,信任模型判断,聚焦核心问题
81
+ - 劣势:需要明确的边界判断能力
82
+
83
+ ### 平衡点
84
+
85
+ - **fix 模式**:信任强模型在边界清楚时的快速决策能力
86
+ - **full 模式**:保留系统性框架,用于复杂或高风险场景
87
+ - **快速判定指南**:降低 full 模式的认知负担,避免为了填表而填表
88
+
89
+ ## 向后兼容性
90
+
91
+ - **代码层面**:无破坏性变更,所有测试通过(26 个测试全部 pass)
92
+ - **文档层面**:fix 模式行为不变(三章 brief + 免确认),只是澄清方式从隐式继承九大视角改为显式的原则驱动
93
+ - **状态机**:`mode: fix` 的状态转换逻辑不变
94
+
95
+ ## 使用示例
96
+
97
+ ### fix 模式的 brief 示例
98
+
99
+ ```markdown
100
+ # 目标
101
+
102
+ 用户在订单列表页滚动到底部时,点击「加载更多」无反应。
103
+ 影响范围:所有用户,订单超过 20 条时必现。
104
+ 复现:登录 → 订单列表 → 滚动到底部 → 点击「加载更多」→ 无反应。
105
+
106
+ # 验收示例
107
+
108
+ - 修复后,点击「加载更多」能正常加载下一页订单
109
+ - 已加载全部订单时,「加载更多」按钮变灰且显示「已加载全部」
110
+ - 回归:其他分页场景(商品列表、搜索结果)不受影响
111
+
112
+ # 决定
113
+
114
+ 根因:分页请求的 offset 计算错误,`offset = page * pageSize` 应为 `offset = (page - 1) * pageSize`。
115
+ 修复方式:修正 `api/orders.js:45` 的 offset 计算公式。
116
+ 不改其他分页实现(已单独封装且行为正确)。
117
+ ```
118
+
119
+ **注意**:没有走九大视角,但根因、影响范围、回归场景都明确了。
120
+
121
+ ## 未来展望
122
+
123
+ 可进一步考虑的方向:
124
+
125
+ 1. **分级策略**:增加 `--rigor standard|minimal|adaptive` 参数
126
+ 2. **澄清策略元能力**:在 open 开始前,先评估需求应该用什么澄清策略
127
+ 3. **动态调整**:根据过程中发现的复杂度,自动建议从 fix 升级到 full
128
+
129
+ ## 测试结果
130
+
131
+ ```bash
132
+ npm test
133
+ # ✔ fix 模式:prepare 直接进 build,可省 tasks.md (1102.3283ms)
134
+ # ℹ tests 26
135
+ # ℹ pass 26
136
+ # ℹ fail 0
137
+ ```
138
+
139
+ 所有测试通过,包括 fix 模式的专项测试。
140
+
141
+ ## 参考
142
+
143
+ - 借鉴 **Comet Native** 的"原则而非清单"设计
144
+ - 参考 Ponytail 模式的"懒惰即高效"哲学
145
+ - 保持与 full 模式的清晰边界,避免混淆
@@ -0,0 +1,90 @@
1
+ # comate 1.0 试用说明
2
+
3
+ 1.0 使用单个 `/comate` skill 和 Node 状态机,流程为 open → build ⇄ verify → archive。相比 0.x,不再依赖 OpenSpec CLI 和 Superpowers 编排;项目资料统一放在 `comate/`,进行中的旧 change 不自动转换。
4
+
5
+ ## 安装与试用环境
6
+
7
+ 需要 Node.js ≥ 20、git,以及支持 skills 的 AI 开发工具。完整验收需要工具支持独立子 agent;不支持时,按流程明确接受降级验收。
8
+
9
+ 新版安装钩子和 `comate init` 会更新用户级 `~/.agents/skills`,并清理旧版 comate 阶段 skills。需要继续使用旧版的用户,请在独立系统用户、虚拟机或容器中试用。新 clone、worktree 和 `npx` 都不能隔离全局 skills。
10
+
11
+ 第一轮请使用新建的测试项目,或已有项目的独立测试副本;测试副本仍需配合独立用户环境来隔离 skills。旧版进行中的 change 请先用旧版完成。
12
+
13
+ 发布后安装试用渠道:
14
+
15
+ ```bash
16
+ npm install -g @house365/comate@next
17
+ cd your-test-project
18
+ comate init
19
+ comate doctor
20
+ comate --version
21
+ ```
22
+
23
+ 本轮固定版本为 `1.0.0-beta.1`。需要复现本轮反馈时,用 `npm install -g @house365/comate@1.0.0-beta.1` 安装。
24
+
25
+ 在 AI 开发工具中新开会话,输入 `/comate` 开始。切换版本后请重新打开会话,避免沿用旧 skill 的上下文。
26
+
27
+ ## 建议试用任务
28
+
29
+ 每人选择一个能判断结果的小任务,至少跑完一次归档。建议覆盖:
30
+
31
+ - 创建一个完整变更,确认需求、实现、独立验收、归档。
32
+ - 用 fix 模式处理一个边界清楚的小修,检查澄清与实现是否顺畅。
33
+ - 验收发现问题后,检查是否能回修并重新验收。
34
+ - 中途关闭会话,重新输入 `/comate`,检查是否能恢复正确阶段。
35
+ - 收尾选择 keep,检查主规格、归档目录和 git 状态。
36
+
37
+ 第一轮不要求迁移旧项目。`init --migrate` 和 `import-specs` 留到单独的迁移试用中,先用 `--dry-run` 检查清单,再决定是否执行。
38
+
39
+ ## 更新与回退
40
+
41
+ 更新试用版:
42
+
43
+ ```bash
44
+ npm install -g @house365/comate@next
45
+ cd your-test-project
46
+ comate init
47
+ ```
48
+
49
+ 当前 `comate update` 固定跟随 `latest`,试用期间请使用上面的命令。
50
+
51
+ 需要恢复本次试用前的稳定版时:
52
+
53
+ ```bash
54
+ npm install -g @house365/comate@0.10.3
55
+ cd your-old-project
56
+ comate init
57
+ comate --version
58
+ ```
59
+
60
+ 这会恢复旧版 CLI 和 skills,但不会把新版 change 转回旧格式,也不会自动撤销目录迁移。回退后在旧项目继续工作,新版测试项目保留用于反馈;再次使用 AI 工具时新开会话。用户自行修改过的全局 skills,请在首次切换前另行备份。
61
+
62
+ ## 反馈
63
+
64
+ 通过 [GitHub Issues](https://github.com/liangjiankk/comate/issues) 提交,建议标题以 `[1.0 beta]` 开头,并提供:
65
+
66
+ - `comate --version`、操作系统、Node 版本、AI 工具及模型。
67
+ - 任务目标、发生问题的阶段、最短复现步骤。
68
+ - 预期结果、实际结果,以及相关报错或 `comate status --json` 输出。
69
+ - 本次哪些确认或操作造成了额外负担。
70
+
71
+ 只提供复现所需片段,提交前移除密钥、个人信息和项目敏感内容。
72
+
73
+ ## 维护者发布步骤
74
+
75
+ 稳定版继续在 `main` 维护并发布到 `latest`;新版在试用分支维护,发布到 `next`。当前包的 `publishConfig.tag` 默认设为 `next`,防止遗漏渠道参数时切换 `latest`。
76
+
77
+ 发布前将本轮试用涉及的代码和文档整理成一个可追踪的提交,检查其中包含预期内容,然后执行:
78
+
79
+ ```bash
80
+ npm run prepublishOnly
81
+ npm publish --dry-run --tag next
82
+ npm run publish:next
83
+ npm view @house365/comate dist-tags --json --registry=https://registry.npmjs.org
84
+ ```
85
+
86
+ 预期渠道为 `latest: 0.10.3`、`next: 1.0.0-beta.1`。实际发布需要 npm 账号拥有 `@house365/comate` 的发布权限,并按 npm 提示完成认证。
87
+
88
+ 后续每轮同步修改 `package.json` 和 `package-lock.json` 的版本,使用新的 `1.0.0-beta.N` 版本号,并更新本文的固定版本和预期渠道;已发布的版本不重复使用。
89
+
90
+ 正式发布时再移除默认的 `next` 配置、使用正式版本号、明确指定 `--tag latest`,并同步安装和更新说明。