openmatrix 0.1.56 → 0.1.58

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,270 @@
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.researchCommand = void 0;
37
+ // src/cli/commands/research.ts
38
+ const commander_1 = require("commander");
39
+ const gitignore_js_1 = require("../../utils/gitignore.js");
40
+ const fs = __importStar(require("fs/promises"));
41
+ const path = __importStar(require("path"));
42
+ /**
43
+ * 生成并行研究 Agent 配置
44
+ */
45
+ function generateAgents(topic, domain, aspects) {
46
+ return [
47
+ {
48
+ role: 'domain_researcher',
49
+ focus: `搜索 ${domain} 领域的核心概念、行业标准、最佳实践。关键词: ${aspects.slice(0, 4).join(', ')}`,
50
+ status: 'pending'
51
+ },
52
+ {
53
+ role: 'tech_explorer',
54
+ focus: `搜索 ${domain} 的主流技术方案、开源项目、技术栈选择、架构模式`,
55
+ status: 'pending'
56
+ },
57
+ {
58
+ role: 'scenario_analyst',
59
+ focus: `结合用户具体需求 "${topic}",分析实际应用场景、常见挑战、经验教训`,
60
+ status: 'pending'
61
+ }
62
+ ];
63
+ }
64
+ exports.researchCommand = new commander_1.Command('research')
65
+ .description('领域调研和问题探索 - 为后续任务提供知识基础')
66
+ .argument('[topic]', '研究主题')
67
+ .option('--json', '输出 JSON 格式 (供 Skill 解析)')
68
+ .option('--confirm', '确认进入深度研究 (从 Skill 传入)')
69
+ .option('--complete', '标记研究完成,生成报告和任务上下文')
70
+ .option('--results <json>', '研究结果 JSON (从 Skill 传入)')
71
+ .action(async (topic, options) => {
72
+ const basePath = process.cwd();
73
+ const omPath = path.join(basePath, '.openmatrix');
74
+ const researchPath = path.join(omPath, 'research');
75
+ const knowledgePath = path.join(researchPath, 'knowledge');
76
+ // 确保目录存在
77
+ await fs.mkdir(omPath, { recursive: true });
78
+ await fs.mkdir(researchPath, { recursive: true });
79
+ await fs.mkdir(knowledgePath, { recursive: true });
80
+ // 确保 .openmatrix 被 git 忽略
81
+ await (0, gitignore_js_1.ensureOpenmatrixGitignore)(basePath);
82
+ const sessionPath = path.join(researchPath, 'session.json');
83
+ // ========== --complete 模式: 研究完成,汇总结果 ==========
84
+ if (options.complete) {
85
+ try {
86
+ const sessionData = await fs.readFile(sessionPath, 'utf-8');
87
+ const session = JSON.parse(sessionData);
88
+ // 如果传入了结果,合并
89
+ if (options.results) {
90
+ try {
91
+ const results = JSON.parse(options.results);
92
+ if (results.agents)
93
+ session.agents = results.agents;
94
+ if (results.report)
95
+ session.report = results.report;
96
+ if (results.knowledge)
97
+ session.knowledge = [...session.knowledge, ...results.knowledge];
98
+ if (results.context)
99
+ session.context = results.context;
100
+ if (results.domainQuestions)
101
+ session.domainQuestions = results.domainQuestions;
102
+ if (results.answers)
103
+ session.answers = { ...session.answers, ...results.answers };
104
+ }
105
+ catch {
106
+ // 忽略解析错误
107
+ }
108
+ }
109
+ session.status = 'completed';
110
+ session.completedAt = new Date().toISOString();
111
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
112
+ // 写入研究报告
113
+ if (session.report) {
114
+ await fs.writeFile(path.join(researchPath, 'RESEARCH.md'), session.report, 'utf-8');
115
+ }
116
+ // 写入知识条目
117
+ for (let i = 0; i < session.knowledge.length; i++) {
118
+ await fs.writeFile(path.join(knowledgePath, `finding-${i + 1}.md`), session.knowledge[i], 'utf-8');
119
+ }
120
+ // 写入任务上下文 (供 start 使用)
121
+ const taskContext = session.context || { goals: [], constraints: [], deliverables: [] };
122
+ await fs.writeFile(path.join(researchPath, 'context.json'), JSON.stringify({
123
+ topic: session.topic,
124
+ domain: session.domain,
125
+ ...taskContext,
126
+ reportPath: '.openmatrix/research/RESEARCH.md',
127
+ knowledgePath: '.openmatrix/research/knowledge/'
128
+ }, null, 2), 'utf-8');
129
+ if (options.json) {
130
+ console.log(JSON.stringify({
131
+ status: 'completed',
132
+ message: '研究完成',
133
+ topic: session.topic,
134
+ domain: session.domain,
135
+ report: session.report,
136
+ knowledge: session.knowledge,
137
+ context: taskContext,
138
+ reportPath: '.openmatrix/research/RESEARCH.md',
139
+ hint: '研究结果已保存,可以使用 /om:start 开始执行任务'
140
+ }));
141
+ }
142
+ else {
143
+ console.log('研究完成!');
144
+ console.log(` 主题: ${session.topic}`);
145
+ console.log(` 领域: ${session.domain}`);
146
+ console.log(` 知识条目: ${session.knowledge.length} 个`);
147
+ console.log('\n使用 /om:start 基于研究结果开始任务');
148
+ }
149
+ return;
150
+ }
151
+ catch {
152
+ if (options.json) {
153
+ console.log(JSON.stringify({ status: 'error', message: '没有进行中的研究会话' }));
154
+ }
155
+ else {
156
+ console.log('没有进行中的研究会话');
157
+ console.log(' 使用 openmatrix research <topic> 开始新的研究');
158
+ }
159
+ return;
160
+ }
161
+ }
162
+ // ========== --confirm 模式: 用户确认后进入深度研究 ==========
163
+ if (options.confirm) {
164
+ try {
165
+ const sessionData = await fs.readFile(sessionPath, 'utf-8');
166
+ const session = JSON.parse(sessionData);
167
+ if (session.status !== 'preview') {
168
+ if (options.json) {
169
+ console.log(JSON.stringify({ status: 'error', message: `当前状态为 ${session.status},无法确认` }));
170
+ }
171
+ else {
172
+ console.log(`当前状态为 ${session.status},无法确认`);
173
+ }
174
+ return;
175
+ }
176
+ // 生成研究 Agent
177
+ const agents = generateAgents(session.topic, session.domain, session.aspects);
178
+ session.status = 'researching';
179
+ session.agents = agents;
180
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
181
+ if (options.json) {
182
+ console.log(JSON.stringify({
183
+ status: 'researching',
184
+ message: '开始深度研究',
185
+ topic: session.topic,
186
+ domain: session.domain,
187
+ aspects: session.aspects,
188
+ agents: agents.map(a => ({ role: a.role, focus: a.focus, status: a.status })),
189
+ hint: '使用 Agent 工具并行执行研究'
190
+ }));
191
+ }
192
+ else {
193
+ console.log('\n开始深度研究...\n');
194
+ console.log(` 主题: ${session.topic}`);
195
+ console.log(` 领域: ${session.domain}`);
196
+ console.log('\n研究 Agent:');
197
+ agents.forEach((a, i) => {
198
+ console.log(` ${i + 1}. [${a.role}] ${a.focus}`);
199
+ });
200
+ }
201
+ return;
202
+ }
203
+ catch {
204
+ if (options.json) {
205
+ console.log(JSON.stringify({ status: 'error', message: '没有待确认的研究会话' }));
206
+ }
207
+ else {
208
+ console.log('没有待确认的研究会话');
209
+ }
210
+ return;
211
+ }
212
+ }
213
+ // ========== 初始模式: 创建会话,等待 AI 分析 ==========
214
+ let researchTopic = topic;
215
+ if (!researchTopic) {
216
+ const defaultPath = path.join(basePath, 'RESEARCH.md');
217
+ try {
218
+ const content = await fs.readFile(defaultPath, 'utf-8');
219
+ const lines = content.split('\n');
220
+ for (const line of lines) {
221
+ const match = line.match(/^#\s+(.+)$/);
222
+ if (match) {
223
+ researchTopic = match[1].trim();
224
+ break;
225
+ }
226
+ }
227
+ if (!researchTopic)
228
+ researchTopic = content.slice(0, 100).trim();
229
+ if (!options.json)
230
+ console.log(`读取研究文件: ${defaultPath}`);
231
+ }
232
+ catch {
233
+ if (options.json) {
234
+ console.log(JSON.stringify({ status: 'error', message: '请提供研究主题' }));
235
+ }
236
+ else {
237
+ console.log('请提供研究主题');
238
+ console.log(' 用法: openmatrix research <topic>');
239
+ console.log(' 或创建 RESEARCH.md 文件');
240
+ }
241
+ return;
242
+ }
243
+ }
244
+ // 创建初始会话 - 领域信息由 Agent 分析后更新
245
+ const session = {
246
+ status: 'initialized',
247
+ topic: researchTopic,
248
+ domain: '',
249
+ aspects: [],
250
+ estimatedQuestions: 0,
251
+ agents: [],
252
+ domainQuestions: [],
253
+ answers: {},
254
+ knowledge: [],
255
+ createdAt: new Date().toISOString()
256
+ };
257
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2));
258
+ if (options.json) {
259
+ console.log(JSON.stringify({
260
+ status: 'initialized',
261
+ message: '研究会话已创建,需要 AI 分析领域',
262
+ topic: researchTopic,
263
+ hint: '请使用 Agent 分析主题,识别领域和调研方向,然后更新会话并展示给用户确认'
264
+ }));
265
+ }
266
+ else {
267
+ console.log(`\n研究主题: ${researchTopic}`);
268
+ console.log('使用 /om:research 技能启动 AI 分析');
269
+ }
270
+ });
@@ -164,7 +164,11 @@ async function handleTasksJson(options, stateManager, state, omPath) {
164
164
  };
165
165
  // 解析质量配置
166
166
  const qualityLevel = tasksInput.quality || options.quality || 'balanced';
167
- const qualityConfig = index_js_1.QUALITY_PRESETS[qualityLevel.toLowerCase()] || index_js_1.QUALITY_PRESETS.balanced;
167
+ const qualityConfig = { ...(index_js_1.QUALITY_PRESETS[qualityLevel.toLowerCase()] || index_js_1.QUALITY_PRESETS.balanced) };
168
+ // E2E 测试覆盖(用户在 Skill 问答中选择启用)
169
+ if (tasksInput.e2eTests) {
170
+ qualityConfig.e2eTests = true;
171
+ }
168
172
  if (!options.json) {
169
173
  console.log(`\n📋 任务: ${parsedTask.title}`);
170
174
  console.log(` 目标: ${parsedTask.goals.join(', ')}`);
package/dist/cli/index.js CHANGED
@@ -15,6 +15,7 @@ const check_js_1 = require("./commands/check.js");
15
15
  const check_gitignore_js_1 = require("./commands/check-gitignore.js");
16
16
  const analyze_js_1 = require("./commands/analyze.js");
17
17
  const brainstorm_js_1 = require("./commands/brainstorm.js");
18
+ const research_js_1 = require("./commands/research.js");
18
19
  const complete_js_1 = require("./commands/complete.js");
19
20
  const step_js_1 = require("./commands/step.js");
20
21
  const program = new commander_1.Command();
@@ -38,5 +39,6 @@ program.addCommand(check_js_1.checkCommand);
38
39
  program.addCommand(check_gitignore_js_1.checkGitignoreCommand);
39
40
  program.addCommand(analyze_js_1.analyzeCommand);
40
41
  program.addCommand(brainstorm_js_1.brainstormCommand);
42
+ program.addCommand(research_js_1.researchCommand);
41
43
  // 默认帮助
42
44
  program.parse();
@@ -702,6 +702,13 @@ ACCEPT_FAILED
702
702
  updates.status = 'completed';
703
703
  }
704
704
  await this.stateManager.updateTask(task.id, updates);
705
+ // 持久化 Phase 结果到磁盘
706
+ await this.stateManager.savePhaseResult(task.id, phase, {
707
+ success: true,
708
+ output: result.output,
709
+ phaseStatus: 'completed',
710
+ completedAt: now
711
+ });
705
712
  // 自动提交代码
706
713
  if (this.runId) {
707
714
  try {
@@ -740,6 +747,13 @@ ACCEPT_FAILED
740
747
  status: 'failed',
741
748
  error: result.error || `${phase} phase failed`
742
749
  });
750
+ // 持久化失败结果
751
+ await this.stateManager.savePhaseResult(task.id, phase, {
752
+ success: false,
753
+ error: result.error || `${phase} phase failed`,
754
+ phaseStatus: 'failed',
755
+ failedAt: now
756
+ });
743
757
  return {
744
758
  phase,
745
759
  success: false,
@@ -17,6 +17,22 @@ export declare class StateManager {
17
17
  getTask(taskId: string): Promise<Task | null>;
18
18
  updateTask(taskId: string, updates: Partial<Task>): Promise<void>;
19
19
  listTasks(): Promise<Task[]>;
20
+ /**
21
+ * 保存 Phase 结果到任务子目录
22
+ */
23
+ savePhaseResult(taskId: string, phase: string, result: Record<string, unknown>): Promise<void>;
24
+ /**
25
+ * 读取 Phase 结果
26
+ */
27
+ getPhaseResult(taskId: string, phase: string): Promise<Record<string, unknown> | null>;
28
+ /**
29
+ * 保存 Agent 上下文到 context.md
30
+ */
31
+ saveTaskContext(taskId: string, content: string): Promise<void>;
32
+ /**
33
+ * 读取 Agent 上下文
34
+ */
35
+ getTaskContext(taskId: string): Promise<string | null>;
20
36
  private updateTaskStatistics;
21
37
  private generateRunId;
22
38
  private generateTaskId;
@@ -74,7 +74,9 @@ class StateManager {
74
74
  createdAt: now,
75
75
  updatedAt: now
76
76
  };
77
- await this.store.writeJson(`tasks/${taskId}.json`, task);
77
+ await this.store.writeJson(`tasks/${taskId}/task.json`, task);
78
+ // Create artifacts subdirectory
79
+ await this.store.ensureDir(`tasks/${taskId}/artifacts`);
78
80
  // Update statistics
79
81
  const state = await this.getState();
80
82
  await this.updateState({
@@ -87,7 +89,12 @@ class StateManager {
87
89
  return task;
88
90
  }
89
91
  async getTask(taskId) {
90
- return await this.store.readJson(`tasks/${taskId}.json`);
92
+ // Try subdirectory structure first, fall back to flat file
93
+ let task = await this.store.readJson(`tasks/${taskId}/task.json`);
94
+ if (!task) {
95
+ task = await this.store.readJson(`tasks/${taskId}.json`);
96
+ }
97
+ return task;
91
98
  }
92
99
  async updateTask(taskId, updates) {
93
100
  const task = await this.getTask(taskId);
@@ -99,22 +106,67 @@ class StateManager {
99
106
  ...updates,
100
107
  updatedAt: new Date().toISOString()
101
108
  };
102
- await this.store.writeJson(`tasks/${taskId}.json`, updatedTask);
109
+ // Always write to subdirectory structure
110
+ await this.store.writeJson(`tasks/${taskId}/task.json`, updatedTask);
103
111
  // Update statistics if status changed
104
112
  if (updates.status && updates.status !== oldStatus) {
105
113
  await this.updateTaskStatistics(oldStatus, updates.status);
106
114
  }
107
115
  }
108
116
  async listTasks() {
109
- const files = await this.store.listFiles('tasks');
110
117
  const tasks = [];
111
- for (const file of files) {
112
- const task = await this.store.readJson(`tasks/${file}`);
118
+ // Read from subdirectory structure: tasks/TASK-XXX/task.json
119
+ const dirs = await this.store.listDirs('tasks');
120
+ for (const dir of dirs) {
121
+ const task = await this.store.readJson(`tasks/${dir}/task.json`);
113
122
  if (task)
114
123
  tasks.push(task);
115
124
  }
125
+ // Also check flat files (backward compat)
126
+ const files = await this.store.listFiles('tasks');
127
+ for (const file of files) {
128
+ if (!file.endsWith('.json'))
129
+ continue;
130
+ const task = await this.store.readJson(`tasks/${file}`);
131
+ if (task) {
132
+ // Avoid duplicate if already found in subdirectory
133
+ if (!tasks.some(t => t.id === task.id)) {
134
+ tasks.push(task);
135
+ }
136
+ }
137
+ }
116
138
  return tasks.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
117
139
  }
140
+ // ============ Task Artifact Methods ============
141
+ /**
142
+ * 保存 Phase 结果到任务子目录
143
+ */
144
+ async savePhaseResult(taskId, phase, result) {
145
+ await this.store.writeJson(`tasks/${taskId}/${phase}.json`, {
146
+ taskId,
147
+ phase,
148
+ timestamp: new Date().toISOString(),
149
+ ...result
150
+ });
151
+ }
152
+ /**
153
+ * 读取 Phase 结果
154
+ */
155
+ async getPhaseResult(taskId, phase) {
156
+ return await this.store.readJson(`tasks/${taskId}/${phase}.json`);
157
+ }
158
+ /**
159
+ * 保存 Agent 上下文到 context.md
160
+ */
161
+ async saveTaskContext(taskId, content) {
162
+ await this.store.writeMarkdown(`tasks/${taskId}/context.md`, content);
163
+ }
164
+ /**
165
+ * 读取 Agent 上下文
166
+ */
167
+ async getTaskContext(taskId) {
168
+ return await this.store.readMarkdown(`tasks/${taskId}/context.md`);
169
+ }
118
170
  async updateTaskStatistics(oldStatus, newStatus) {
119
171
  const state = await this.getState();
120
172
  const stats = { ...state.statistics };
@@ -1,5 +1,6 @@
1
1
  export type TaskStatus = 'pending' | 'scheduled' | 'in_progress' | 'blocked' | 'waiting' | 'verify' | 'accept' | 'completed' | 'failed' | 'retry_queue';
2
2
  export type TaskPriority = 'P0' | 'P1' | 'P2' | 'P3';
3
+ export type ResearchMode = 'domain' | 'tech' | 'problem';
3
4
  export interface TaskPhase {
4
5
  status: TaskStatus;
5
6
  duration: number | null;
@@ -201,3 +202,38 @@ export interface ParsedTask {
201
202
  deliverables: string[];
202
203
  rawContent: string;
203
204
  }
205
+ export interface ResearchAgentConfig {
206
+ role: string;
207
+ focus: string;
208
+ status: 'pending' | 'running' | 'completed' | 'failed';
209
+ result?: string;
210
+ }
211
+ export interface ResearchQuestion {
212
+ id: string;
213
+ question: string;
214
+ header: string;
215
+ options: Array<{
216
+ label: string;
217
+ description: string;
218
+ }>;
219
+ multiSelect: boolean;
220
+ }
221
+ export interface ResearchSession {
222
+ status: 'initialized' | 'preview' | 'researching' | 'questioning' | 'completed';
223
+ topic: string;
224
+ domain: string;
225
+ aspects: string[];
226
+ estimatedQuestions: number;
227
+ agents: ResearchAgentConfig[];
228
+ domainQuestions: ResearchQuestion[];
229
+ answers: Record<string, string | string[]>;
230
+ report?: string;
231
+ knowledge: string[];
232
+ context?: {
233
+ goals: string[];
234
+ constraints: string[];
235
+ deliverables: string[];
236
+ };
237
+ createdAt: string;
238
+ completedAt?: string;
239
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmatrix",
3
- "version": "0.1.56",
3
+ "version": "0.1.58",
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",
@@ -25,20 +25,37 @@ description: 头脑风暴 - 探索需求和设计后再执行任务
25
25
  "status": "brainstorming",
26
26
  "message": "开始头脑风暴",
27
27
  "taskTitle": "任务标题",
28
- "questions": [
29
- {
30
- "id": "core_objective",
31
- "question": "这个任务的核心目标是什么?",
32
- "header": "核心目标",
33
- "options": [...],
34
- "multiSelect": false
35
- }
36
- ],
28
+ "questions": [...],
29
+ "suggestResearch": "游戏开发",
30
+ "researchHint": "检测到垂直领域「游戏开发」,建议先进行领域调研",
37
31
  "hint": "请逐一回答问题,完成后再调用 --complete"
38
32
  }
39
33
  ```
40
34
 
41
- 2. **交互式问答**
35
+ 2. **检测垂直领域** (如果 suggestResearch 存在)
36
+
37
+ 如果 CLI 返回了 `suggestResearch` 字段,说明检测到垂直领域:
38
+
39
+ ```typescript
40
+ if (result.suggestResearch) {
41
+ AskUserQuestion({
42
+ questions: [{
43
+ question: `检测到垂直领域「${result.suggestResearch}」,建议先进行领域调研。\n\n领域调研可以帮助您:\n• 了解行业最佳实践\n• 获取技术方案建议\n• 生成领域专属文档 (如 GDD/PRD)\n\n是否进入领域调研?`,
44
+ header: "领域调研",
45
+ options: [
46
+ { label: "进入调研 (推荐)", description: "启动 /om:research 进行深度调研" },
47
+ { label: "跳过调研", description: "直接进行头脑风暴问答" }
48
+ ],
49
+ multiSelect: false
50
+ }]
51
+ })
52
+ }
53
+ ```
54
+
55
+ - 如果用户选择"进入调研",调用 `/om:research`,研究完成后自动返回 start
56
+ - 如果用户选择"跳过调研",继续下面的问答流程
57
+
58
+ 3. **交互式问答**
42
59
 
43
60
  对每个问题使用 `AskUserQuestion` 进行提问:
44
61
 
@@ -58,7 +75,7 @@ description: 头脑风暴 - 探索需求和设计后再执行任务
58
75
  - 记录可能的设计决策
59
76
  - 识别潜在风险
60
77
 
61
- 3. **深入追问** (可选)
78
+ 4. **深入追问** (可选)
62
79
 
63
80
  如果用户选择了"其他"或回答不够清晰,进行追问:
64
81
  ```typescript
@@ -71,7 +88,7 @@ description: 头脑风暴 - 探索需求和设计后再执行任务
71
88
  })
72
89
  ```
73
90
 
74
- 4. **总结头脑风暴结果**
91
+ 5. **总结头脑风暴结果**
75
92
 
76
93
  所有问题回答完成后,总结:
77
94
  - 核心目标
@@ -121,15 +138,64 @@ description: 头脑风暴 - 探索需求和设计后再执行任务
121
138
  })
122
139
  ```
123
140
 
124
- 6. **自动执行 start**
141
+ 6. **智能检测 .openmatrix 状态后执行**
142
+
143
+ **先检测当前状态:**
144
+ ```bash
145
+ # 检查 .openmatrix 目录是否存在
146
+ ls .openmatrix/state.json 2>/dev/null
147
+ ```
148
+
149
+ **根据状态走不同路径:**
150
+
151
+ | .openmatrix 状态 | 处理方式 |
152
+ |-----------------|---------|
153
+ | 不存在 | 全新开始 → init → 写 tasks-input → CLI start |
154
+ | 存在,`status: completed` | 清理旧数据后重新开始 → 写 tasks-input → CLI start |
155
+ | 存在,`status: running` | 提示用户先完成或暂停当前任务 |
156
+ | 存在,`status: paused` | 询问用户:继续上次任务 还是 开始新任务 |
157
+ | 存在,`status: initialized` | 直接写 tasks-input → CLI start |
158
+
159
+ **路径 A: 全新开始 / 重新开始**
160
+ ```bash
161
+ # 初始化 (如果不存在)
162
+ openmatrix start --init-only
163
+
164
+ # 如果是重新开始,清理旧数据
165
+ # rm -rf .openmatrix/tasks/ .openmatrix/approvals/ .openmatrix/meetings/
166
+ ```
167
+
168
+ **将头脑风暴结论转换为 goals:**
169
+ ```json
170
+ {
171
+ "title": "任务标题",
172
+ "description": "基于头脑风暴的整体描述",
173
+ "goals": [
174
+ "目标1: 独立功能模块",
175
+ "目标2: 独立功能模块",
176
+ "..."
177
+ ],
178
+ "constraints": ["约束"],
179
+ "deliverables": ["交付物"],
180
+ "answers": { "问答答案" },
181
+ "quality": "strict/balanced/fast",
182
+ "mode": "auto",
183
+ "plan": "## 技术方案\n..."
184
+ }
185
+ ```
186
+
187
+ 写入 `.openmatrix/tasks-input.json` 后执行:
188
+ ```bash
189
+ openmatrix start --tasks-json @.openmatrix/tasks-input.json --json
190
+ ```
191
+
192
+ **路径 B: 继续上次任务**
193
+ ```bash
194
+ openmatrix step --json
195
+ ```
196
+ 从返回的 next task 继续执行。
125
197
 
126
- 如果用户选择"开始执行":
127
- - 调用 CLI 标记头脑风暴完成:
128
- ```bash
129
- openmatrix brainstorm --complete --json
130
- ```
131
- - 自动调用 `/om:start` 开始执行任务
132
- - 将头脑风暴收集的洞察传递给 start
198
+ **最终:从 CLI 返回的 `subagentTasks` 开始逐个执行 Agent**
133
199
 
134
200
  </process>
135
201