openmatrix 0.2.26 → 0.2.28

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.
@@ -0,0 +1,352 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WorktreeSyncManager = void 0;
37
+ // src/utils/worktree-sync.ts
38
+ const child_process_1 = require("child_process");
39
+ const util_1 = require("util");
40
+ const fs = __importStar(require("fs/promises"));
41
+ const path = __importStar(require("path"));
42
+ const error_handler_js_1 = require("./error-handler.js");
43
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
44
+ /**
45
+ * WorktreeSyncManager - 管理 Git Worktree 同步
46
+ *
47
+ * 当 Agent 在 worktree 中工作时,改动会提交到 worktree 的分支。
48
+ * 此类负责将这些改动同步回主工作树。
49
+ *
50
+ * 同步策略:
51
+ * 1. 检测 Agent 创建的 worktree
52
+ * 2. 获取 worktree 中的提交和改动文件
53
+ * 3. 将改动文件复制到主工作树(或 cherry-pick 提交)
54
+ * 4. 清理临时 worktree
55
+ */
56
+ class WorktreeSyncManager {
57
+ repoPath;
58
+ gitRoot = null;
59
+ constructor(repoPath = process.cwd()) {
60
+ this.repoPath = repoPath;
61
+ }
62
+ /**
63
+ * 获取 git 仓库根目录
64
+ */
65
+ async getGitRoot() {
66
+ if (this.gitRoot)
67
+ return this.gitRoot;
68
+ try {
69
+ const { stdout } = await execAsync('git rev-parse --show-toplevel', { cwd: this.repoPath });
70
+ this.gitRoot = stdout.trim();
71
+ }
72
+ catch (error) {
73
+ (0, error_handler_js_1.logError)(error, { operation: 'getGitRoot', file: this.repoPath });
74
+ this.gitRoot = this.repoPath;
75
+ }
76
+ return this.gitRoot;
77
+ }
78
+ /**
79
+ * 列出所有 worktree
80
+ */
81
+ async listWorktrees() {
82
+ try {
83
+ const { stdout } = await execAsync('git worktree list --porcelain', { cwd: this.repoPath });
84
+ const worktrees = [];
85
+ const lines = stdout.split('\n');
86
+ let current = {};
87
+ for (const line of lines) {
88
+ if (line.startsWith('worktree ')) {
89
+ if (current.path) {
90
+ worktrees.push({
91
+ path: current.path,
92
+ branch: current.branch || '',
93
+ commit: current.commit || '',
94
+ isMain: current.isMain || false
95
+ });
96
+ }
97
+ current = { path: line.slice(9) };
98
+ // 第一个 worktree 是主工作树
99
+ current.isMain = worktrees.length === 0;
100
+ }
101
+ else if (line.startsWith('HEAD ')) {
102
+ current.commit = line.slice(5);
103
+ }
104
+ else if (line.startsWith('branch ')) {
105
+ current.branch = line.slice(7);
106
+ }
107
+ }
108
+ // 添加最后一个
109
+ if (current.path) {
110
+ worktrees.push({
111
+ path: current.path,
112
+ branch: current.branch || '',
113
+ commit: current.commit || '',
114
+ isMain: current.isMain || false
115
+ });
116
+ }
117
+ return worktrees;
118
+ }
119
+ catch (error) {
120
+ (0, error_handler_js_1.logError)(error, { operation: 'listWorktrees', file: this.repoPath });
121
+ return [];
122
+ }
123
+ }
124
+ /**
125
+ * 获取 Agent worktree 目录
126
+ *
127
+ * Claude Code 创建的 worktree 通常在 .claude/worktrees/ 目录下
128
+ */
129
+ async getAgentWorktrees() {
130
+ const worktrees = await this.listWorktrees();
131
+ const gitRoot = await this.getGitRoot();
132
+ // 过滤出 Agent 创建的 worktree(通常以 agent- 开头或在 .claude/worktrees 下)
133
+ return worktrees.filter(w => !w.isMain &&
134
+ (w.path.includes('.claude/worktrees') || w.path.includes('agent-')));
135
+ }
136
+ /**
137
+ * 获取 worktree 相对于主工作树的改动
138
+ */
139
+ async getWorktreeChanges(worktreePath) {
140
+ try {
141
+ const gitRoot = await this.getGitRoot();
142
+ // 获取 worktree 相对于主分支的改动文件
143
+ const { stdout } = await execAsync(`git diff --name-only HEAD "${worktreePath}"`, { cwd: gitRoot });
144
+ return stdout.split('\n').filter(f => f.trim());
145
+ }
146
+ catch (error) {
147
+ // 如果上面的方法失败,尝试直接在 worktree 中获取未提交的改动
148
+ try {
149
+ const { stdout } = await execAsync('git diff --name-only HEAD', { cwd: worktreePath });
150
+ return stdout.split('\n').filter(f => f.trim());
151
+ }
152
+ catch (innerError) {
153
+ (0, error_handler_js_1.logError)(innerError, { operation: 'getWorktreeChanges', file: worktreePath });
154
+ return [];
155
+ }
156
+ }
157
+ }
158
+ /**
159
+ * 获取 worktree 中最新提交的改动文件
160
+ */
161
+ async getLatestCommitChanges(worktreePath) {
162
+ try {
163
+ // 在 worktree 中获取最新提交改动的文件
164
+ const { stdout } = await execAsync('git diff --name-only HEAD~1 HEAD', { cwd: worktreePath });
165
+ return stdout.split('\n').filter(f => f.trim());
166
+ }
167
+ catch (error) {
168
+ // 可能只有一个提交,尝试获取与初始提交的差异
169
+ try {
170
+ const { stdout } = await execAsync('git diff --name-only HEAD', { cwd: worktreePath });
171
+ return stdout.split('\n').filter(f => f.trim());
172
+ }
173
+ catch (innerError) {
174
+ (0, error_handler_js_1.logError)(innerError, { operation: 'getLatestCommitChanges', file: worktreePath });
175
+ return [];
176
+ }
177
+ }
178
+ }
179
+ /**
180
+ * 同步 worktree 改动到主工作树
181
+ *
182
+ * 策略:
183
+ * 1. 获取 worktree 中已提交但未同步的改动
184
+ * 2. 将改动文件复制到主工作树
185
+ * 3. 在主工作树中暂存这些文件
186
+ *
187
+ * @param worktreePath worktree 路径(可选,不提供则自动检测所有 Agent worktree)
188
+ */
189
+ async syncWorktreeToMain(worktreePath) {
190
+ const gitRoot = await this.getGitRoot();
191
+ const worktrees = worktreePath
192
+ ? [{ path: worktreePath, branch: '', commit: '', isMain: false }]
193
+ : await this.getAgentWorktrees();
194
+ if (worktrees.length === 0) {
195
+ return [{
196
+ success: true,
197
+ syncedFiles: [],
198
+ error: 'No agent worktrees found'
199
+ }];
200
+ }
201
+ const results = [];
202
+ for (const wt of worktrees) {
203
+ try {
204
+ // 1. 获取改动文件
205
+ const changedFiles = await this.getLatestCommitChanges(wt.path);
206
+ if (changedFiles.length === 0) {
207
+ results.push({
208
+ success: true,
209
+ syncedFiles: [],
210
+ branch: wt.branch,
211
+ error: 'No changes in worktree'
212
+ });
213
+ continue;
214
+ }
215
+ // 2. 复制文件到主工作树
216
+ const syncedFiles = [];
217
+ for (const file of changedFiles) {
218
+ const srcPath = path.join(wt.path, file);
219
+ const destPath = path.join(gitRoot, file);
220
+ try {
221
+ // 确保目标目录存在
222
+ const destDir = path.dirname(destPath);
223
+ await fs.mkdir(destDir, { recursive: true });
224
+ // 复制文件
225
+ await fs.copyFile(srcPath, destPath);
226
+ syncedFiles.push(file);
227
+ }
228
+ catch (copyError) {
229
+ (0, error_handler_js_1.logError)(copyError, { operation: 'copyFile', file: srcPath, metadata: { dest: destPath } });
230
+ }
231
+ }
232
+ // 3. 在主工作树中暂存文件
233
+ if (syncedFiles.length > 0) {
234
+ const filesArg = syncedFiles.map(f => `"${f}"`).join(' ');
235
+ await execAsync(`git add ${filesArg}`, { cwd: gitRoot });
236
+ }
237
+ // 4. 获取 worktree 的最新提交 hash
238
+ let commitHash;
239
+ try {
240
+ const { stdout } = await execAsync('git rev-parse HEAD', { cwd: wt.path });
241
+ commitHash = stdout.trim();
242
+ }
243
+ catch { }
244
+ results.push({
245
+ success: true,
246
+ syncedFiles,
247
+ commitHash,
248
+ branch: wt.branch
249
+ });
250
+ }
251
+ catch (error) {
252
+ results.push({
253
+ success: false,
254
+ syncedFiles: [],
255
+ branch: wt.branch,
256
+ error: error instanceof Error ? error.message : String(error)
257
+ });
258
+ }
259
+ }
260
+ return results;
261
+ }
262
+ /**
263
+ * Cherry-pick worktree 的提交到主工作树
264
+ *
265
+ * 替代方案:直接 cherry-pick worktree 的提交
266
+ * 适用于:改动较大、需要保留完整提交历史的场景
267
+ */
268
+ async cherryPickWorktreeCommit(worktreePath) {
269
+ const gitRoot = await this.getGitRoot();
270
+ try {
271
+ // 1. 获取 worktree 的最新提交 hash
272
+ const { stdout: commitHash } = await execAsync('git rev-parse HEAD', { cwd: worktreePath });
273
+ const hash = commitHash.trim();
274
+ // 2. 在主工作树中 cherry-pick 这个提交
275
+ await execAsync(`git cherry-pick ${hash} --no-commit`, { cwd: gitRoot });
276
+ // 3. 获取被 cherry-pick 的文件列表
277
+ const { stdout: files } = await execAsync('git diff --name-only --cached', { cwd: gitRoot });
278
+ const syncedFiles = files.split('\n').filter(f => f.trim());
279
+ return {
280
+ success: true,
281
+ syncedFiles,
282
+ commitHash: hash
283
+ };
284
+ }
285
+ catch (error) {
286
+ // Cherry-pick 可能失败(冲突),尝试放弃并返回错误
287
+ try {
288
+ await execAsync('git cherry-pick --abort', { cwd: gitRoot });
289
+ }
290
+ catch { }
291
+ return {
292
+ success: false,
293
+ syncedFiles: [],
294
+ error: error instanceof Error ? error.message : String(error)
295
+ };
296
+ }
297
+ }
298
+ /**
299
+ * 清理已同步的 worktree
300
+ */
301
+ async cleanupWorktree(worktreePath) {
302
+ try {
303
+ const gitRoot = await this.getGitRoot();
304
+ // 1. 移除 worktree
305
+ await execAsync(`git worktree remove "${worktreePath}" --force`, { cwd: gitRoot });
306
+ // 2. 清理可能的残留分支(如果是临时分支)
307
+ // 注意:不自动删除分支,因为可能还需要
308
+ return true;
309
+ }
310
+ catch (error) {
311
+ (0, error_handler_js_1.logError)(error, { operation: 'cleanupWorktree', file: worktreePath });
312
+ return false;
313
+ }
314
+ }
315
+ /**
316
+ * 完整的同步流程
317
+ *
318
+ * 1. 检测所有 Agent worktree
319
+ * 2. 同步改动到主工作树
320
+ * 3. 清理 worktree
321
+ *
322
+ * @returns 同步结果
323
+ */
324
+ async fullSync() {
325
+ // 1. 同步
326
+ const syncResults = await this.syncWorktreeToMain();
327
+ // 2. 清理已成功同步的 worktree
328
+ const cleanupResults = [];
329
+ const worktrees = await this.getAgentWorktrees();
330
+ for (const wt of worktrees) {
331
+ const syncResult = syncResults.find(r => r.branch === wt.branch);
332
+ if (syncResult?.success && syncResult.syncedFiles.length > 0) {
333
+ const cleanupSuccess = await this.cleanupWorktree(wt.path);
334
+ cleanupResults.push({ path: wt.path, success: cleanupSuccess });
335
+ }
336
+ }
337
+ return { syncResults, cleanupResults };
338
+ }
339
+ /**
340
+ * 检查是否有未同步的 worktree 改动
341
+ */
342
+ async hasUnsyncedChanges() {
343
+ const worktrees = await this.getAgentWorktrees();
344
+ for (const wt of worktrees) {
345
+ const changes = await this.getLatestCommitChanges(wt.path);
346
+ if (changes.length > 0)
347
+ return true;
348
+ }
349
+ return false;
350
+ }
351
+ }
352
+ exports.WorktreeSyncManager = WorktreeSyncManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmatrix",
3
- "version": "0.2.26",
3
+ "version": "0.2.28",
4
4
  "description": "AI Agent task orchestration system with Claude Code Skills integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/skills/approve.md CHANGED
@@ -35,7 +35,7 @@ description: "Use when handling pending approvals including plan review, merge c
35
35
  </INTENT-JUDGMENT>
36
36
 
37
37
  <NO-OTHER-SKILLS>
38
- 执行此技能时,不得调用 superpowers、gsd 或其他任务编排相关的技能。OpenMatrix 独立运行,不依赖外部任务编排系统。
38
+ skill 与其他任务编排技能功能重叠,请勿同时使用。
39
39
  </NO-OTHER-SKILLS>
40
40
 
41
41
  <objective>
package/skills/auto.md CHANGED
@@ -37,14 +37,9 @@ description: "Use when the user wants fully automated task execution with zero m
37
37
  </INTENT-JUDGMENT>
38
38
 
39
39
  <NO-OTHER-SKILLS>
40
- **绝对禁止**调用以下任何技能或工具:
41
- - gsd-executor、gsd:* 等 GSD 相关技能
42
- - superpowers:* 等 superpowers 相关技能
43
- - 任何其他任务编排相关的 Agent 或工具
40
+ 本 skill 与其他任务编排技能功能重叠,请勿同时使用。
44
41
 
45
- **Step 5 只能使用 Agent 工具** — 直接调用 Agent,不通过任何中间层。
46
-
47
- 违规调用将导致执行失败。
42
+ **Step 5 使用 Agent 工具执行子任务。**
48
43
 
49
44
  **相关技能**: `/om:brainstorm` (需求探索) | `/om:plan` (方案生成) | `/om:start` (交互式执行) | `/om:status` (状态查看) | `/om:report` (报告)
50
45
  </NO-OTHER-SKILLS>
@@ -80,6 +75,22 @@ Step 5: 逐个执行 subagentTasks(调用 Agent 工具) ← 只
80
75
  **执行时不要请求用户确认任何操作。**
81
76
  </BYPASS-MODE>
82
77
 
78
+ <RED-FLAGS>
79
+ ## 红旗警告 - 停止并检查
80
+
81
+ 这些想法意味着你在找借口:
82
+
83
+ | 想法 | 真相 |
84
+ |-----|------|
85
+ | "全自动不需要检查" | 全自动更需要状态持久化 |
86
+ | "跳过 CLI 调用更快" | CLI 是唯一正确的入口 |
87
+ | "我不需要验证状态" | 上下文压缩会丢失状态 |
88
+ | "直接用 Bash 写代码" | 业务代码必须通过 Agent |
89
+ | "忘记任务顺序没关系" | 用 `openmatrix step` 重新获取 |
90
+ | "这个歧义不重要" | 所有歧义都写入 Meeting |
91
+
92
+ </RED-FLAGS>
93
+
83
94
  <objective>
84
95
  全自动执行任务。读取已有的 plan.md + tasks-input.json,通过 CLI 拆分任务,然后通过 Agent 逐个执行。无交互、无审批、无中断。
85
96
 
@@ -101,11 +112,21 @@ openmatrix start --init-only
101
112
 
102
113
  ### Step 2: 验证前置条件
103
114
 
104
- **检查 plan.md 和 tasks-input.json 是否已存在:**
115
+ **先获取当前 runId:**
116
+ ```bash
117
+ cat .openmatrix/current.json 2>/dev/null || echo '{"runId":"run-default"}'
118
+ ```
119
+
120
+ **检查 plan.md 和 tasks-input.json 是否已存在(使用 runId):**
121
+
122
+ ```bash
123
+ cat .openmatrix/${runId}/tasks-input.json 2>/dev/null || echo "NOT_FOUND"
124
+ cat .openmatrix/${runId}/plan.md 2>/dev/null || echo "NOT_FOUND"
125
+ ```
105
126
 
127
+ **或通过 CLI 检查(推荐):**
106
128
  ```bash
107
- cat .openmatrix/tasks-input.json 2>/dev/null || echo "NOT_FOUND"
108
- cat .openmatrix/plan.md 2>/dev/null || echo "NOT_FOUND"
129
+ openmatrix status --json | jq '.files'
109
130
  ```
110
131
 
111
132
  | 情况 | 处理方式 |
@@ -119,15 +140,17 @@ cat .openmatrix/plan.md 2>/dev/null || echo "NOT_FOUND"
119
140
 
120
141
  ### Step 3: 调用 CLI 创建任务 ⚠️ 不可跳过
121
142
 
143
+ **CLI 自动从当前 runId 目录读取 tasks-input.json 和 plan.md。**
144
+
122
145
  **这是最关键的步骤。必须执行以下命令,不能跳过:**
123
146
 
124
147
  ```bash
125
- openmatrix start --tasks-json @.openmatrix/tasks-input.json --quality <质量等级> --mode auto --json
148
+ openmatrix start --tasks-json @tasks-input.json --quality <质量等级> --mode auto --json
126
149
  ```
127
150
 
128
151
  如果启用了 E2E 测试,加上 `--e2e-tests`:
129
152
  ```bash
130
- openmatrix start --tasks-json @.openmatrix/tasks-input.json --quality strict --mode auto --e2e-tests --json
153
+ openmatrix start --tasks-json @tasks-input.json --quality strict --mode auto --e2e-tests --json
131
154
  ```
132
155
 
133
156
  此命令会:
@@ -262,6 +285,11 @@ Agent({
262
285
  openmatrix complete TASK-XXX --success
263
286
  ```
264
287
 
288
+ **注意**: `openmatrix complete` 会自动执行以下操作:
289
+ 1. 🔄 **同步 Worktree 改动** - 如果 Agent 在 worktree 中工作,自动将改动同步到主工作树
290
+ 2. 📝 **更新上下文** - 将执行摘要写入全局 context.md
291
+ 3. ✅ **标记完成** - 更新任务状态并触发 Git 提交
292
+
265
293
  3. **获取下一个任务(必须执行,防止上下文压缩丢失):**
266
294
  ```bash
267
295
  openmatrix step --json
@@ -346,8 +374,10 @@ auto 和 start 在同一位置,区别在于:
346
374
  - **auto**: 零交互,不询问任何问题,无审批节点,质量通过 --quality 指定
347
375
 
348
376
  前置条件(同 start):
349
- - `.openmatrix/plan.md` — 技术方案(由 /om:plan 生成)
350
- - `.openmatrix/tasks-input.json` — 结构化元数据(由 /om:plan 生成)
377
+ - `.openmatrix/{runId}/plan.md` — 技术方案(由 /om:plan 生成)
378
+ - `.openmatrix/{runId}/tasks-input.json` — 结构化元数据(由 /om:plan 生成)
379
+
380
+ CLI 自动通过 `current.json` 定位当前 runId。
351
381
 
352
382
  如果前置条件不满足,自动调用 /om:plan 生成。
353
383
 
@@ -36,11 +36,7 @@ description: "Use when the user wants to explore requirements, design alternativ
36
36
  </INTENT-JUDGMENT>
37
37
 
38
38
  <NO-OTHER-SKILLS>
39
- **绝对禁止**调用以下技能(OpenMatrix 完全替代它们):
40
- - ❌ superpowers:brainstorming → 你已经在 om:brainstorm 中了
41
- - ❌ superpowers:* → 全部被 OpenMatrix 替代
42
- - ❌ gsd:* → 全部被 OpenMatrix 替代
43
- - ❌ 任何其他任务编排相关的技能
39
+ skill 与其他任务编排技能功能重叠,请勿同时使用。
44
40
 
45
41
  **相关技能**: `/om:research` (领域调研) | `/om:plan` (方案生成) | `/om:start` (任务执行) | `/om:auto` (全自动)
46
42
  </NO-OTHER-SKILLS>
package/skills/check.md CHANGED
@@ -4,7 +4,7 @@ description: 自动检测项目可改进点并提供升级建议,用户确认
4
4
  ---
5
5
 
6
6
  <NO-OTHER-SKILLS>
7
- 执行此技能时,不得调用 superpowers、gsd 或其他任务编排相关的技能。OpenMatrix 独立运行,不依赖外部任务编排系统。
7
+ skill 与其他任务编排技能功能重叠,请勿同时使用。
8
8
  </NO-OTHER-SKILLS>
9
9
 
10
10
  <objective>