@house365/comate 0.2.0 → 0.2.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/bin/init-run.mjs CHANGED
@@ -82,8 +82,12 @@ export async function init(pkgRoot) {
82
82
  if (superpowersInstalled('global') || superpowersInstalled('project')) {
83
83
  results.push(['Superpowers', 'skipped', '已安装']);
84
84
  } else {
85
- console.log('\n→ 安装 Superpowers (skills add obra/superpowers -g)');
86
- const r = run(skillsInvocation(pkgRoot, ['add', 'obra/superpowers', '-g', '-y']), SKILLS_TIMEOUT_MS);
85
+ console.log('\n→ 安装 Superpowers');
86
+ const r = run(
87
+ skillsInvocation(pkgRoot, ['add', 'obra/superpowers', '-g', '-y']),
88
+ SKILLS_TIMEOUT_MS,
89
+ { quiet: true },
90
+ );
87
91
  // It clones from GitHub, so a bare exit code hides the usual cause: no
88
92
  // network. Say so rather than leaving the user with "exit code 1".
89
93
  const note = r.ok
@@ -92,11 +96,18 @@ export async function init(pkgRoot) {
92
96
  results.push(['Superpowers', r.ok ? 'installed' : 'failed', note]);
93
97
  }
94
98
 
95
- // 3. comate itself.
99
+ // 3. comate itself. The skills CLI reports per-agent failures without ever
100
+ // setting a non-zero exit code, and we swallow its output — so a zero status
101
+ // is not evidence the skill landed. Check the file.
96
102
  console.log('\n→ 安装 comate skills');
97
103
  const comateArgs = ['add', pkgRoot, '--skill', '*', '-g', '-y'];
98
- const r = run(skillsInvocation(pkgRoot, comateArgs), SKILLS_TIMEOUT_MS);
99
- results.push(['comate', r.ok ? 'installed' : 'failed', r.ok ? '' : r.reason]);
104
+ const r = run(skillsInvocation(pkgRoot, comateArgs), SKILLS_TIMEOUT_MS, { quiet: true });
105
+ const landed = existsSync(join(home, '.agents', 'skills', 'comate', 'SKILL.md'));
106
+ if (r.ok && !landed) {
107
+ results.push(['comate', 'failed', `未装到 ${join(home, '.agents', 'skills')},重跑看详情`]);
108
+ } else {
109
+ results.push(['comate', r.ok ? 'installed' : 'failed', r.ok ? '' : r.reason]);
110
+ }
100
111
 
101
112
  // 4. openspec/ project structure. Not optional: comate's open and archive
102
113
  // phases read it, so an install without it cannot actually run. An existing
@@ -105,8 +116,17 @@ export async function init(pkgRoot) {
105
116
  results.push(['openspec 结构', 'skipped', '已存在']);
106
117
  } else {
107
118
  console.log('\n→ 初始化 openspec/ 项目结构');
119
+ // --tools is not optional in practice: openspec derives the tool list by
120
+ // sniffing existing agent config dirs, so a fresh project (no .claude etc.)
121
+ // aborts with "No tools detected and no --tools flag provided". comate's
122
+ // skills are agent-agnostic and only openspec/ itself matters here, so ask
123
+ // for none rather than guessing which agents the user wants wired up.
108
124
  const r2 = run(
109
- { command: 'openspec', args: ['init', '.'], shell: process.platform === 'win32' },
125
+ {
126
+ command: 'openspec',
127
+ args: ['init', '.', '--tools', 'none'],
128
+ shell: process.platform === 'win32',
129
+ },
110
130
  NPM_TIMEOUT_MS,
111
131
  );
112
132
  results.push(['openspec 结构', r2.ok ? 'installed' : 'failed', r2.ok ? '' : r2.reason]);
package/bin/init.mjs CHANGED
@@ -75,14 +75,24 @@ function parsePackOutput(stdout) {
75
75
  throw new Error(`no usable file list in npm pack output:\n${stdout}`);
76
76
  }
77
77
 
78
- function run({ command, args, shell }, timeout) {
79
- const { status, error } = spawnSync(command, args, {
80
- stdio: 'inherit',
78
+ // quiet buffers the child's output and prints it only on failure. The skills
79
+ // CLI reports a per-agent failure for every agent that has no user-level skills
80
+ // dir (PromptScript et al.) — cosmetic, since it neither affects the exit code
81
+ // nor the agents that did get installed, but it reads like a broken install.
82
+ // init prints its own summary, so on success the child's output adds nothing.
83
+ function run({ command, args, shell }, timeout, { quiet = false } = {}) {
84
+ const { status, error, stdout, stderr } = spawnSync(command, args, {
85
+ stdio: quiet ? ['ignore', 'pipe', 'pipe'] : 'inherit',
86
+ encoding: quiet ? 'utf8' : undefined,
81
87
  timeout,
82
88
  ...(shell ? { shell: true } : {}),
83
89
  });
84
90
  if (error) return { ok: false, reason: error.message };
85
- if (status !== 0) return { ok: false, reason: `exit code ${String(status)}` };
91
+ if (status !== 0) {
92
+ // Without this the user gets a bare "exit code 1" and no way to diagnose.
93
+ if (quiet) process.stderr.write((stdout ?? '') + (stderr ?? ''));
94
+ return { ok: false, reason: `exit code ${String(status)}` };
95
+ }
86
96
  return { ok: true };
87
97
  }
88
98
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@house365/comate",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "comate —— OpenSpec + Superpowers 规约驱动的 AI 开发编排器(Agent Skills)",
5
5
  "type": "module",
6
6
  "license": "MIT",