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.
- package/dist/cli/commands/start.js +24 -13
- package/dist/cli/commands/status.js +13 -1
- package/dist/orchestrator/git-commit-manager.d.ts +13 -0
- package/dist/orchestrator/git-commit-manager.js +57 -0
- package/dist/storage/state-manager.d.ts +108 -0
- package/dist/storage/state-manager.js +169 -1
- package/dist/utils/gitignore.js +2 -0
- package/dist/utils/worktree-sync.d.ts +100 -0
- package/dist/utils/worktree-sync.js +352 -0
- package/package.json +1 -1
- package/skills/approve.md +1 -1
- package/skills/auto.md +44 -14
- package/skills/brainstorm.md +1 -5
- package/skills/check.md +1 -1
- package/skills/debug.md +692 -765
- package/skills/deploy.md +1 -1
- package/skills/feature.md +17 -14
- package/skills/meeting.md +1 -1
- package/skills/om.md +71 -5
- package/skills/openmatrix.md +5 -14
- package/skills/plan.md +54 -19
- package/skills/report.md +1 -1
- package/skills/research.md +16 -1
- package/skills/resume.md +3 -5
- package/skills/retry.md +1 -1
- package/skills/start.md +758 -621
- package/skills/status.md +1 -1
- package/skills/test.md +105 -8
|
@@ -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
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
package/skills/brainstorm.md
CHANGED
|
@@ -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
|
-
|
|
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>
|