openmatrix 0.2.30 → 0.2.33

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 (49) hide show
  1. package/README.md +154 -154
  2. package/dist/cli/commands/approve.js +35 -1
  3. package/dist/cli/commands/auto.js +2 -2
  4. package/dist/cli/commands/check-gitignore.js +34 -30
  5. package/dist/cli/commands/check.js +1 -1
  6. package/dist/cli/commands/complete.js +35 -7
  7. package/dist/cli/commands/debug.js +2 -1
  8. package/dist/cli/commands/deploy.js +1 -1
  9. package/dist/cli/commands/install-skills.js +3 -0
  10. package/dist/cli/commands/meeting.js +37 -1
  11. package/dist/cli/commands/report.js +1 -1
  12. package/dist/cli/commands/resume.js +35 -1
  13. package/dist/cli/commands/retry.js +130 -56
  14. package/dist/cli/commands/start.js +14 -3
  15. package/dist/cli/commands/status.js +32 -29
  16. package/dist/cli/commands/step.js +4 -1
  17. package/dist/orchestrator/ai-reviewer.d.ts +5 -0
  18. package/dist/orchestrator/ai-reviewer.js +9 -2
  19. package/dist/orchestrator/context-collector.js +17 -5
  20. package/dist/orchestrator/executor.d.ts +8 -0
  21. package/dist/orchestrator/executor.js +38 -8
  22. package/dist/orchestrator/phase-executor.d.ts +4 -0
  23. package/dist/orchestrator/phase-executor.js +21 -4
  24. package/dist/storage/file-store.js +8 -0
  25. package/dist/storage/state-manager.js +52 -19
  26. package/dist/test/generator.js +113 -113
  27. package/dist/types/index.d.ts +2 -0
  28. package/dist/utils/error-handler.d.ts +18 -0
  29. package/dist/utils/error-handler.js +32 -0
  30. package/dist/utils/worktree-sync.js +24 -3
  31. package/package.json +61 -61
  32. package/skills/SKILL.md +53 -53
  33. package/skills/auto.md +410 -413
  34. package/skills/brainstorm.md +19 -12
  35. package/skills/debug.md +694 -691
  36. package/skills/deploy.md +658 -658
  37. package/skills/feature.md +713 -686
  38. package/skills/plan.md +298 -296
  39. package/skills/report.md +9 -5
  40. package/skills/resume.md +292 -287
  41. package/skills/start.md +117 -27
  42. package/skills/status.md +5 -4
  43. package/skills/test.md +875 -875
  44. package/dist/agents/base-agent.d.ts +0 -46
  45. package/dist/agents/base-agent.js +0 -17
  46. package/dist/cli/commands/analyze.d.ts +0 -2
  47. package/dist/cli/commands/analyze.js +0 -50
  48. package/dist/orchestrator/smart-question-analyzer.d.ts +0 -90
  49. package/dist/orchestrator/smart-question-analyzer.js +0 -512
@@ -150,17 +150,17 @@ function generateTestContent(source, config) {
150
150
  // 测试块
151
151
  const testBlocks = source.exports.map(exp => generateTestBlock(exp, framework, usesDescribeIt, source.fileType));
152
152
  // 组装内容
153
- const content = `${needsViImport ? `import { vi } from 'vitest';\n` : ''}${imports}
154
- ${needsLifecycle ? `
155
- beforeEach(() => {
156
- vi.clearAllMocks();
157
- });
158
-
159
- afterEach(() => {
160
- vi.restoreAllMocks();
161
- });
162
- ` : ''}
163
- ${testBlocks.join('\n\n')}
153
+ const content = `${needsViImport ? `import { vi } from 'vitest';\n` : ''}${imports}
154
+ ${needsLifecycle ? `
155
+ beforeEach(() => {
156
+ vi.clearAllMocks();
157
+ });
158
+
159
+ afterEach(() => {
160
+ vi.restoreAllMocks();
161
+ });
162
+ ` : ''}
163
+ ${testBlocks.join('\n\n')}
164
164
  `;
165
165
  return content;
166
166
  }
@@ -186,14 +186,14 @@ function generateTestBlock(exportName, framework, usesDescribeIt, fileType) {
186
186
  // 根据文件类型生成不同的测试场景
187
187
  const testCases = generateBusinessTestCases(exportName, fileType);
188
188
  const testBlocks = testCases.map(tc => generateTestCaseBlock(tc, exportName));
189
- return `describe('${getDescribeTitle(exportName, fileType)}', () => {
190
- ${testBlocks.join('\n\n')}
189
+ return `describe('${getDescribeTitle(exportName, fileType)}', () => {
190
+ ${testBlocks.join('\n\n')}
191
191
  });`;
192
192
  }
193
193
  else {
194
- return `test('${exportName}', () => {
195
- expect(${exportName}).toBeDefined();
196
- expect(${exportName}(null)).toBeDefined();
194
+ return `test('${exportName}', () => {
195
+ expect(${exportName}).toBeDefined();
196
+ expect(${exportName}(null)).toBeDefined();
197
197
  });`;
198
198
  }
199
199
  }
@@ -206,10 +206,10 @@ function generateBusinessTestCases(exportName, fileType) {
206
206
  return [
207
207
  {
208
208
  name: 'should return valid result on successful execution',
209
- arrange: `// Arrange - 准备有效的输入参数
210
- const params = { id: 'test-id', data: {} };
209
+ arrange: `// Arrange - 准备有效的输入参数
210
+ const params = { id: 'test-id', data: {} };
211
211
  const spy = vi.spyOn({ ${exportName} }, '${exportName}');`,
212
- act: `// Act - 执行服务方法
212
+ act: `// Act - 执行服务方法
213
213
  const result = await ${exportName}(params);`,
214
214
  assert: [
215
215
  'expect(result).toBeDefined();',
@@ -221,9 +221,9 @@ function generateBusinessTestCases(exportName, fileType) {
221
221
  },
222
222
  {
223
223
  name: 'should handle invalid input gracefully',
224
- arrange: `// Arrange - 准备无效输入
224
+ arrange: `// Arrange - 准备无效输入
225
225
  const invalidParams = { id: null, data: undefined };`,
226
- act: `// Act - 使用无效参数调用
226
+ act: `// Act - 使用无效参数调用
227
227
  const result = await ${exportName}(invalidParams);`,
228
228
  assert: [
229
229
  'expect(result).toBeDefined();',
@@ -233,7 +233,7 @@ function generateBusinessTestCases(exportName, fileType) {
233
233
  {
234
234
  name: 'should handle empty parameters',
235
235
  arrange: `// Arrange - 空参数测试`,
236
- act: `// Act & Assert - 验证空参数处理
236
+ act: `// Act & Assert - 验证空参数处理
237
237
  const result = await ${exportName}({});`,
238
238
  assert: [
239
239
  'expect(result).toBeDefined();',
@@ -254,11 +254,11 @@ function generateBusinessTestCases(exportName, fileType) {
254
254
  return [
255
255
  {
256
256
  name: 'should process valid input correctly',
257
- arrange: `// Arrange - 准备有效输入
258
- const input = 'test-value';
259
- const expected = 'expected-result';
257
+ arrange: `// Arrange - 准备有效输入
258
+ const input = 'test-value';
259
+ const expected = 'expected-result';
260
260
  const spy = vi.spyOn({ ${exportName} }, '${exportName}');`,
261
- act: `// Act
261
+ act: `// Act
262
262
  const result = ${exportName}(input);`,
263
263
  assert: [
264
264
  'expect(result).toBeDefined();',
@@ -280,7 +280,7 @@ function generateBusinessTestCases(exportName, fileType) {
280
280
  {
281
281
  name: 'should handle empty string input',
282
282
  arrange: `// Arrange - 空字符串输入`,
283
- act: `// Act
283
+ act: `// Act
284
284
  const result = ${exportName}('');`,
285
285
  assert: [
286
286
  'expect(result).toBeDefined();',
@@ -305,9 +305,9 @@ function generateBusinessTestCases(exportName, fileType) {
305
305
  return [
306
306
  {
307
307
  name: 'should render without crashing',
308
- arrange: `// Arrange - 准备组件 props
308
+ arrange: `// Arrange - 准备组件 props
309
309
  const props = { title: \'Test Title\', onClick: vi.fn() };`,
310
- act: `// Act - 渲染组件
310
+ act: `// Act - 渲染组件
311
311
  const { container } = render(<${exportName} {...props} />);`,
312
312
  assert: [
313
313
  'expect(container).toBeDefined();',
@@ -316,11 +316,11 @@ function generateBusinessTestCases(exportName, fileType) {
316
316
  },
317
317
  {
318
318
  name: 'should handle user interaction',
319
- arrange: `// Arrange - 准备交互测试
320
- const handleClick = vi.fn();
319
+ arrange: `// Arrange - 准备交互测试
320
+ const handleClick = vi.fn();
321
321
  const props = { onClick: handleClick };`,
322
- act: `// Act - 模拟用户点击
323
- const { getByRole } = render(<${exportName} {...props} />);
322
+ act: `// Act - 模拟用户点击
323
+ const { getByRole } = render(<${exportName} {...props} />);
324
324
  fireEvent.click(getByRole(\'button\'));`,
325
325
  assert: [
326
326
  'expect(handleClick).toHaveBeenCalledTimes(1);'
@@ -328,10 +328,10 @@ function generateBusinessTestCases(exportName, fileType) {
328
328
  },
329
329
  {
330
330
  name: 'should display correct content with props',
331
- arrange: `// Arrange - 准备显示内容测试
332
- const testContent = \'Hello World\';
331
+ arrange: `// Arrange - 准备显示内容测试
332
+ const testContent = \'Hello World\';
333
333
  const props = { children: testContent };`,
334
- act: `// Act - 渲染并检查内容
334
+ act: `// Act - 渲染并检查内容
335
335
  const { getByText } = render(<${exportName} {...props} />);`,
336
336
  assert: [
337
337
  'expect(getByText(testContent)).toBeInTheDocument();'
@@ -340,7 +340,7 @@ function generateBusinessTestCases(exportName, fileType) {
340
340
  {
341
341
  name: 'should handle missing optional props',
342
342
  arrange: `// Arrange - 无可选 props`,
343
- act: `// Act - 仅传递必需 props
343
+ act: `// Act - 仅传递必需 props
344
344
  const { container } = render(<${exportName} />);`,
345
345
  assert: [
346
346
  'expect(container).toBeDefined();',
@@ -352,11 +352,11 @@ function generateBusinessTestCases(exportName, fileType) {
352
352
  return [
353
353
  {
354
354
  name: 'should return success response for valid request',
355
- arrange: `// Arrange - 准备有效的 API 请求参数
356
- const request = { method: \'GET\', path: \'/api/test\' };
357
- const mockResponse = { status: 200, data: { id: 1 } };
355
+ arrange: `// Arrange - 准备有效的 API 请求参数
356
+ const request = { method: \'GET\', path: \'/api/test\' };
357
+ const mockResponse = { status: 200, data: { id: 1 } };
358
358
  const spy = vi.spyOn({ ${exportName} }, '${exportName}').mockResolvedValue(mockResponse);`,
359
- act: `// Act - 执行 API 调用
359
+ act: `// Act - 执行 API 调用
360
360
  const response = await ${exportName}(request);`,
361
361
  assert: [
362
362
  'expect(response).toBeDefined();',
@@ -368,11 +368,11 @@ function generateBusinessTestCases(exportName, fileType) {
368
368
  },
369
369
  {
370
370
  name: 'should handle 404 not found',
371
- arrange: `// Arrange - 准备不存在的资源请求
372
- const request = { method: \'GET\', path: \'/api/nonexistent\' };
373
- const mockResponse = { status: 404, error: \'Not Found\' };
371
+ arrange: `// Arrange - 准备不存在的资源请求
372
+ const request = { method: \'GET\', path: \'/api/nonexistent\' };
373
+ const mockResponse = { status: 404, error: \'Not Found\' };
374
374
  vi.spyOn({ ${exportName} }, '${exportName}').mockResolvedValue(mockResponse);`,
375
- act: `// Act - 请求不存在的资源
375
+ act: `// Act - 请求不存在的资源
376
376
  const response = await ${exportName}(request);`,
377
377
  assert: [
378
378
  'expect(response.status).toBe(404);',
@@ -381,11 +381,11 @@ function generateBusinessTestCases(exportName, fileType) {
381
381
  },
382
382
  {
383
383
  name: 'should handle invalid request body',
384
- arrange: `// Arrange - 准备无效的请求体
385
- const request = { method: \'POST\', path: \'/api/test\', body: null };
386
- const mockResponse = { status: 400, error: \'invalid request\' };
384
+ arrange: `// Arrange - 准备无效的请求体
385
+ const request = { method: \'POST\', path: \'/api/test\', body: null };
386
+ const mockResponse = { status: 400, error: \'invalid request\' };
387
387
  vi.spyOn({ ${exportName} }, '${exportName}').mockResolvedValue(mockResponse);`,
388
- act: `// Act - 发送无效请求
388
+ act: `// Act - 发送无效请求
389
389
  const response = await ${exportName}(request);`,
390
390
  assert: [
391
391
  'expect(response.status).toBe(400);',
@@ -394,8 +394,8 @@ function generateBusinessTestCases(exportName, fileType) {
394
394
  },
395
395
  {
396
396
  name: 'should handle network errors gracefully',
397
- arrange: `// Arrange - 模拟网络错误
398
- const request = { method: \'GET\', path: \'/api/error\' };
397
+ arrange: `// Arrange - 模拟网络错误
398
+ const request = { method: \'GET\', path: \'/api/error\' };
399
399
  vi.spyOn({ ${exportName} }, '${exportName}').mockRejectedValue(new Error('Network Error'));`,
400
400
  act: `// Act - 处理错误响应`,
401
401
  assert: [
@@ -409,9 +409,9 @@ function generateBusinessTestCases(exportName, fileType) {
409
409
  return [
410
410
  {
411
411
  name: 'should return defined result for valid input',
412
- arrange: `// Arrange - 准备有效输入
412
+ arrange: `// Arrange - 准备有效输入
413
413
  const input = {};`,
414
- act: `// Act - 执行函数
414
+ act: `// Act - 执行函数
415
415
  const result = ${exportName}(input);`,
416
416
  assert: [
417
417
  'expect(result).toBeDefined();'
@@ -443,10 +443,10 @@ function generateTestCaseBlock(tc, exportName) {
443
443
  const indent = ' ';
444
444
  const actIndent = tc.act.includes('\n') ? indent : indent + ' ';
445
445
  const assertLines = tc.assert.map(a => `${indent} ${a}`).join('\n');
446
- return `${indent}it('${tc.name}', () => {
447
- ${indent} ${tc.arrange}
448
- ${actIndent}${tc.act}
449
- ${assertLines}
446
+ return `${indent}it('${tc.name}', () => {
447
+ ${indent} ${tc.arrange}
448
+ ${actIndent}${tc.act}
449
+ ${assertLines}
450
450
  ${indent}});`;
451
451
  }
452
452
  /**
@@ -518,21 +518,21 @@ function generateMockFiles(sources, config, projectRoot) {
518
518
  */
519
519
  function generateMockContent(source, config) {
520
520
  const mockExports = source.exports.map(exp => {
521
- return `export const ${exp} = vi.fn(() => ({
522
- // Default mock implementation
523
- data: null,
524
- error: null
521
+ return `export const ${exp} = vi.fn(() => ({
522
+ // Default mock implementation
523
+ data: null,
524
+ error: null
525
525
  }));`;
526
526
  });
527
- return `// Mock for ${source.path}
528
- import { vi } from 'vitest';
529
-
530
- ${mockExports.join('\n\n')}
531
-
532
- // Reset all mocks before each test
533
- beforeEach(() => {
534
- vi.clearAllMocks();
535
- });
527
+ return `// Mock for ${source.path}
528
+ import { vi } from 'vitest';
529
+
530
+ ${mockExports.join('\n\n')}
531
+
532
+ // Reset all mocks before each test
533
+ beforeEach(() => {
534
+ vi.clearAllMocks();
535
+ });
536
536
  `;
537
537
  }
538
538
  /**
@@ -562,52 +562,52 @@ function generateE2ETestFiles(scanResult, config, uiComponents) {
562
562
  */
563
563
  function generateE2EContent(component, framework) {
564
564
  if (framework === 'playwright') {
565
- return `// E2E test for ${component.path}
566
- import { test, expect } from '@playwright/test';
567
-
568
- test.describe('${component.exports[0] || 'Component'} E2E', () => {
569
- test.beforeEach(async ({ page }) => {
570
- await page.goto('/');
571
- });
572
-
573
- test('should render correctly', async ({ page }) => {
574
- // Navigate to component page
575
- await page.waitForSelector('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]');
576
-
577
- // Take screenshot
578
- await page.screenshot({ path: 'screenshots/${component.exports[0]?.toLowerCase() || 'component'}.png' });
579
- });
580
-
581
- test('should handle user interaction', async ({ page }) => {
582
- const element = await page.locator('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]');
583
- await element.click();
584
-
585
- // Verify state change
586
- await expect(element).toHaveAttribute('data-active', 'true');
587
- });
588
- });
565
+ return `// E2E test for ${component.path}
566
+ import { test, expect } from '@playwright/test';
567
+
568
+ test.describe('${component.exports[0] || 'Component'} E2E', () => {
569
+ test.beforeEach(async ({ page }) => {
570
+ await page.goto('/');
571
+ });
572
+
573
+ test('should render correctly', async ({ page }) => {
574
+ // Navigate to component page
575
+ await page.waitForSelector('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]');
576
+
577
+ // Take screenshot
578
+ await page.screenshot({ path: 'screenshots/${component.exports[0]?.toLowerCase() || 'component'}.png' });
579
+ });
580
+
581
+ test('should handle user interaction', async ({ page }) => {
582
+ const element = await page.locator('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]');
583
+ await element.click();
584
+
585
+ // Verify state change
586
+ await expect(element).toHaveAttribute('data-active', 'true');
587
+ });
588
+ });
589
589
  `;
590
590
  }
591
591
  // Default Cypress style
592
- return `// E2E test for ${component.path}
593
- describe('${component.exports[0] || 'Component'} E2E', () => {
594
- beforeEach(() => {
595
- cy.visit('/');
596
- });
597
-
598
- it('should render correctly', () => {
599
- cy.get('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]')
600
- .should('be.visible');
601
-
602
- cy.screenshot('${component.exports[0]?.toLowerCase() || 'component'}');
603
- });
604
-
605
- it('should handle user interaction', () => {
606
- cy.get('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]')
607
- .click()
608
- .should('have.attr', 'data-active', 'true');
609
- });
610
- });
592
+ return `// E2E test for ${component.path}
593
+ describe('${component.exports[0] || 'Component'} E2E', () => {
594
+ beforeEach(() => {
595
+ cy.visit('/');
596
+ });
597
+
598
+ it('should render correctly', () => {
599
+ cy.get('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]')
600
+ .should('be.visible');
601
+
602
+ cy.screenshot('${component.exports[0]?.toLowerCase() || 'component'}');
603
+ });
604
+
605
+ it('should handle user interaction', () => {
606
+ cy.get('[data-testid="${component.exports[0]?.toLowerCase() || 'component'}"]')
607
+ .click()
608
+ .should('have.attr', 'data-active', 'true');
609
+ });
610
+ });
611
611
  `;
612
612
  }
613
613
  /**
@@ -104,6 +104,8 @@ export interface AppConfig {
104
104
  model: string;
105
105
  /** 质量配置 */
106
106
  quality?: QualityConfig;
107
+ /** Agent 执行模式:parallel(多 Agent 并行)或 single(单 Agent 串行) */
108
+ agentMode?: 'parallel' | 'single';
107
109
  }
108
110
  /**
109
111
  * 质量配置 - 控制自动化质量门禁
@@ -44,3 +44,21 @@ export declare function isRecoverableError(error: unknown): boolean;
44
44
  * 判断错误是否为文件系统错误
45
45
  */
46
46
  export declare function isFileSystemError(error: unknown): boolean;
47
+ /**
48
+ * ID 验证正则表达式
49
+ */
50
+ export declare const ID_PATTERNS: {
51
+ taskId: RegExp;
52
+ approvalId: RegExp;
53
+ meetingId: RegExp;
54
+ runId: RegExp;
55
+ };
56
+ /**
57
+ * 验证 ID 格式
58
+ * @returns true if valid, false otherwise
59
+ */
60
+ export declare function validateId(id: string, type: keyof typeof ID_PATTERNS): boolean;
61
+ /**
62
+ * 验证并返回 ID,如果无效则抛出错误
63
+ */
64
+ export declare function validateIdOrThrow(id: string, type: keyof typeof ID_PATTERNS): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ID_PATTERNS = void 0;
3
4
  exports.toError = toError;
4
5
  exports.logError = logError;
5
6
  exports.wrapError = wrapError;
@@ -9,6 +10,8 @@ exports.safeExecuteSync = safeExecuteSync;
9
10
  exports.executeWithError = executeWithError;
10
11
  exports.isRecoverableError = isRecoverableError;
11
12
  exports.isFileSystemError = isFileSystemError;
13
+ exports.validateId = validateId;
14
+ exports.validateIdOrThrow = validateIdOrThrow;
12
15
  // src/utils/error-handler.ts
13
16
  const logger_js_1 = require("./logger.js");
14
17
  /**
@@ -121,3 +124,32 @@ function isFileSystemError(error) {
121
124
  ];
122
125
  return fsPatterns.some(p => p.test(err.message));
123
126
  }
127
+ /**
128
+ * ID 验证正则表达式
129
+ */
130
+ exports.ID_PATTERNS = {
131
+ taskId: /^TASK-\d{3,}$/,
132
+ approvalId: /^APPR-[A-Z0-9]+$/,
133
+ meetingId: /^meeting-[a-z0-9]+$/,
134
+ runId: /^run-\d{8}-[a-z0-9]{4}$/
135
+ };
136
+ /**
137
+ * 验证 ID 格式
138
+ * @returns true if valid, false otherwise
139
+ */
140
+ function validateId(id, type) {
141
+ if (!id || typeof id !== 'string')
142
+ return false;
143
+ // 防止路径遍历攻击:拒绝包含 .. 或 / 或 \ 的 ID
144
+ if (id.includes('..') || id.includes('/') || id.includes('\\'))
145
+ return false;
146
+ return exports.ID_PATTERNS[type].test(id);
147
+ }
148
+ /**
149
+ * 验证并返回 ID,如果无效则抛出错误
150
+ */
151
+ function validateIdOrThrow(id, type) {
152
+ if (!validateId(id, type)) {
153
+ throw new Error(`Invalid ${type} format: ${id}`);
154
+ }
155
+ }
@@ -301,15 +301,36 @@ class WorktreeSyncManager {
301
301
  async cleanupWorktree(worktreePath) {
302
302
  try {
303
303
  const gitRoot = await this.getGitRoot();
304
+ // 0. 检查是否有未提交的改动(防止丢失工作)
305
+ try {
306
+ const { stdout: statusOutput } = await execAsync(`git status --porcelain`, { cwd: worktreePath });
307
+ if (statusOutput.trim().length > 0) {
308
+ // 有未提交改动,记录警告但不强制移除
309
+ console.warn(`⚠️ Worktree ${worktreePath} 有未提交改动,跳过清理`);
310
+ console.warn(` 未提交文件: ${statusOutput.trim().split('\n').length} 个`);
311
+ return false;
312
+ }
313
+ }
314
+ catch {
315
+ // status 检查失败,继续尝试清理(可能 worktree 已损坏)
316
+ }
304
317
  // 1. 移除 worktree
305
- await execAsync(`git worktree remove "${worktreePath}" --force`, { cwd: gitRoot });
318
+ await execAsync(`git worktree remove "${worktreePath}"`, { cwd: gitRoot });
306
319
  // 2. 清理可能的残留分支(如果是临时分支)
307
320
  // 注意:不自动删除分支,因为可能还需要
308
321
  return true;
309
322
  }
310
323
  catch (error) {
311
- (0, error_handler_js_1.logError)(error, { operation: 'cleanupWorktree', file: worktreePath });
312
- return false;
324
+ // 如果普通移除失败,尝试强制移除(但已确认无未提交改动)
325
+ try {
326
+ const gitRoot = await this.getGitRoot();
327
+ await execAsync(`git worktree remove "${worktreePath}" --force`, { cwd: gitRoot });
328
+ return true;
329
+ }
330
+ catch (forceError) {
331
+ (0, error_handler_js_1.logError)(forceError, { operation: 'cleanupWorktreeForce', file: worktreePath });
332
+ return false;
333
+ }
313
334
  }
314
335
  }
315
336
  /**
package/package.json CHANGED
@@ -1,61 +1,61 @@
1
- {
2
- "name": "openmatrix",
3
- "version": "0.2.30",
4
- "description": "AI Agent task orchestration system with Claude Code Skills integration",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "bin": {
8
- "openmatrix": "dist/cli/index.js"
9
- },
10
- "files": [
11
- "dist",
12
- "skills",
13
- "scripts",
14
- "README.md"
15
- ],
16
- "scripts": {
17
- "build": "tsc",
18
- "dev": "tsx src/cli/index.ts",
19
- "test": "vitest",
20
- "lint": "eslint src --ext .ts",
21
- "typecheck": "tsc --noEmit",
22
- "postinstall": "node scripts/install-skills.js"
23
- },
24
- "keywords": [
25
- "claude",
26
- "claude-code",
27
- "ai-agent",
28
- "task-orchestration",
29
- "automation",
30
- "multi-agent"
31
- ],
32
- "author": "",
33
- "license": "MIT",
34
- "type": "commonjs",
35
- "repository": {
36
- "type": "git",
37
- "url": "git+https://github.com/bigfish1913/openmatrix.git"
38
- },
39
- "homepage": "https://github.com/bigfish1913/openmatrix#readme",
40
- "bugs": {
41
- "url": "https://github.com/bigfish1913/openmatrix/issues"
42
- },
43
- "dependencies": {
44
- "chalk": "^5.6.2",
45
- "chokidar": "^5.0.0",
46
- "commander": "^14.0.3",
47
- "winston": "^3.19.0"
48
- },
49
- "devDependencies": {
50
- "@types/node": "^22.0.0",
51
- "@typescript-eslint/eslint-plugin": "^8.58.1",
52
- "@typescript-eslint/parser": "^8.58.1",
53
- "@vitest/coverage-v8": "^1.6.1",
54
- "eslint": "^10.2.0",
55
- "typescript": "^5.3.3",
56
- "vitest": "^1.6.0"
57
- },
58
- "engines": {
59
- "node": ">=18.0.0"
60
- }
61
- }
1
+ {
2
+ "name": "openmatrix",
3
+ "version": "0.2.33",
4
+ "description": "AI Agent task orchestration system with Claude Code Skills integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "openmatrix": "dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "skills",
13
+ "scripts",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsx src/cli/index.ts",
19
+ "test": "vitest",
20
+ "lint": "eslint src --ext .ts",
21
+ "typecheck": "tsc --noEmit",
22
+ "postinstall": "node scripts/install-skills.js"
23
+ },
24
+ "keywords": [
25
+ "claude",
26
+ "claude-code",
27
+ "ai-agent",
28
+ "task-orchestration",
29
+ "automation",
30
+ "multi-agent"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "type": "commonjs",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/bigfish1913/openmatrix.git"
38
+ },
39
+ "homepage": "https://github.com/bigfish1913/openmatrix#readme",
40
+ "bugs": {
41
+ "url": "https://github.com/bigfish1913/openmatrix/issues"
42
+ },
43
+ "dependencies": {
44
+ "chalk": "^5.6.2",
45
+ "chokidar": "^5.0.0",
46
+ "commander": "^14.0.3",
47
+ "winston": "^3.19.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^22.0.0",
51
+ "@typescript-eslint/eslint-plugin": "^8.58.1",
52
+ "@typescript-eslint/parser": "^8.58.1",
53
+ "@vitest/coverage-v8": "^1.6.1",
54
+ "eslint": "^10.2.0",
55
+ "typescript": "^5.3.3",
56
+ "vitest": "^1.6.0"
57
+ },
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ }
61
+ }