@litmers/cursorflow-orchestrator 0.1.2 → 0.1.5

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 (74) hide show
  1. package/CHANGELOG.md +7 -6
  2. package/dist/cli/clean.d.ts +5 -0
  3. package/dist/cli/clean.js +57 -0
  4. package/dist/cli/clean.js.map +1 -0
  5. package/dist/cli/index.d.ts +6 -0
  6. package/dist/cli/index.js +120 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/cli/init.d.ts +7 -0
  9. package/dist/cli/init.js +302 -0
  10. package/dist/cli/init.js.map +1 -0
  11. package/dist/cli/monitor.d.ts +8 -0
  12. package/dist/cli/monitor.js +210 -0
  13. package/dist/cli/monitor.js.map +1 -0
  14. package/dist/cli/resume.d.ts +5 -0
  15. package/dist/cli/resume.js +58 -0
  16. package/dist/cli/resume.js.map +1 -0
  17. package/dist/cli/run.d.ts +5 -0
  18. package/dist/cli/run.js +74 -0
  19. package/dist/cli/run.js.map +1 -0
  20. package/dist/cli/setup-commands.d.ts +19 -0
  21. package/dist/cli/setup-commands.js +218 -0
  22. package/dist/cli/setup-commands.js.map +1 -0
  23. package/dist/core/orchestrator.d.ts +47 -0
  24. package/dist/core/orchestrator.js +192 -0
  25. package/dist/core/orchestrator.js.map +1 -0
  26. package/dist/core/reviewer.d.ts +60 -0
  27. package/dist/core/reviewer.js +239 -0
  28. package/dist/core/reviewer.js.map +1 -0
  29. package/dist/core/runner.d.ts +49 -0
  30. package/dist/core/runner.js +475 -0
  31. package/dist/core/runner.js.map +1 -0
  32. package/dist/utils/config.d.ts +31 -0
  33. package/dist/utils/config.js +198 -0
  34. package/dist/utils/config.js.map +1 -0
  35. package/dist/utils/cursor-agent.d.ts +61 -0
  36. package/dist/utils/cursor-agent.js +263 -0
  37. package/dist/utils/cursor-agent.js.map +1 -0
  38. package/dist/utils/git.d.ts +131 -0
  39. package/dist/utils/git.js +272 -0
  40. package/dist/utils/git.js.map +1 -0
  41. package/dist/utils/logger.d.ts +68 -0
  42. package/dist/utils/logger.js +158 -0
  43. package/dist/utils/logger.js.map +1 -0
  44. package/dist/utils/state.d.ts +65 -0
  45. package/dist/utils/state.js +216 -0
  46. package/dist/utils/state.js.map +1 -0
  47. package/dist/utils/types.d.ts +117 -0
  48. package/dist/utils/types.js +6 -0
  49. package/dist/utils/types.js.map +1 -0
  50. package/examples/README.md +155 -0
  51. package/examples/demo-project/README.md +262 -0
  52. package/examples/demo-project/_cursorflow/tasks/demo-test/01-create-utils.json +18 -0
  53. package/examples/demo-project/_cursorflow/tasks/demo-test/02-add-tests.json +18 -0
  54. package/examples/demo-project/_cursorflow/tasks/demo-test/README.md +109 -0
  55. package/package.json +71 -61
  56. package/scripts/ai-security-check.js +11 -4
  57. package/scripts/local-security-gate.sh +76 -0
  58. package/src/cli/{clean.js → clean.ts} +11 -5
  59. package/src/cli/{index.js → index.ts} +22 -16
  60. package/src/cli/{init.js → init.ts} +26 -18
  61. package/src/cli/{monitor.js → monitor.ts} +57 -44
  62. package/src/cli/{resume.js → resume.ts} +11 -5
  63. package/src/cli/run.ts +54 -0
  64. package/src/cli/{setup-commands.js → setup-commands.ts} +19 -18
  65. package/src/core/{orchestrator.js → orchestrator.ts} +44 -26
  66. package/src/core/{reviewer.js → reviewer.ts} +36 -29
  67. package/src/core/{runner.js → runner.ts} +78 -56
  68. package/src/utils/{config.js → config.ts} +17 -25
  69. package/src/utils/{cursor-agent.js → cursor-agent.ts} +38 -47
  70. package/src/utils/{git.js → git.ts} +70 -56
  71. package/src/utils/{logger.js → logger.ts} +170 -178
  72. package/src/utils/{state.js → state.ts} +30 -38
  73. package/src/utils/types.ts +133 -0
  74. package/src/cli/run.js +0 -51
@@ -1,178 +1,170 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Logging utilities for CursorFlow
4
- */
5
-
6
- const LOG_LEVELS = {
7
- error: 0,
8
- warn: 1,
9
- info: 2,
10
- debug: 3,
11
- };
12
-
13
- const COLORS = {
14
- reset: '\x1b[0m',
15
- red: '\x1b[31m',
16
- yellow: '\x1b[33m',
17
- green: '\x1b[32m',
18
- blue: '\x1b[34m',
19
- cyan: '\x1b[36m',
20
- gray: '\x1b[90m',
21
- };
22
-
23
- let currentLogLevel = LOG_LEVELS.info;
24
-
25
- /**
26
- * Set log level
27
- */
28
- function setLogLevel(level) {
29
- if (typeof level === 'string') {
30
- currentLogLevel = LOG_LEVELS[level] ?? LOG_LEVELS.info;
31
- } else {
32
- currentLogLevel = level;
33
- }
34
- }
35
-
36
- /**
37
- * Format message with timestamp
38
- */
39
- function formatMessage(level, message, emoji = '') {
40
- const timestamp = new Date().toISOString();
41
- const prefix = emoji ? `${emoji} ` : '';
42
- return `[${timestamp}] [${level.toUpperCase()}] ${prefix}${message}`;
43
- }
44
-
45
- /**
46
- * Log with color
47
- */
48
- function logWithColor(color, level, message, emoji = '') {
49
- if (LOG_LEVELS[level] > currentLogLevel) {
50
- return;
51
- }
52
-
53
- const formatted = formatMessage(level, message, emoji);
54
- console.log(`${color}${formatted}${COLORS.reset}`);
55
- }
56
-
57
- /**
58
- * Error log
59
- */
60
- function error(message, emoji = '❌') {
61
- logWithColor(COLORS.red, 'error', message, emoji);
62
- }
63
-
64
- /**
65
- * Warning log
66
- */
67
- function warn(message, emoji = '⚠️') {
68
- logWithColor(COLORS.yellow, 'warn', message, emoji);
69
- }
70
-
71
- /**
72
- * Info log
73
- */
74
- function info(message, emoji = 'ℹ️') {
75
- logWithColor(COLORS.cyan, 'info', message, emoji);
76
- }
77
-
78
- /**
79
- * Success log
80
- */
81
- function success(message, emoji = '✅') {
82
- logWithColor(COLORS.green, 'info', message, emoji);
83
- }
84
-
85
- /**
86
- * Debug log
87
- */
88
- function debug(message, emoji = '🔍') {
89
- logWithColor(COLORS.gray, 'debug', message, emoji);
90
- }
91
-
92
- /**
93
- * Progress log
94
- */
95
- function progress(message, emoji = '🔄') {
96
- logWithColor(COLORS.blue, 'info', message, emoji);
97
- }
98
-
99
- /**
100
- * Section header
101
- */
102
- function section(message) {
103
- console.log('');
104
- console.log(`${COLORS.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${COLORS.reset}`);
105
- console.log(`${COLORS.cyan} ${message}${COLORS.reset}`);
106
- console.log(`${COLORS.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${COLORS.reset}`);
107
- console.log('');
108
- }
109
-
110
- /**
111
- * Simple log without formatting
112
- */
113
- function log(message) {
114
- console.log(message);
115
- }
116
-
117
- /**
118
- * Log JSON data (pretty print in debug mode)
119
- */
120
- function json(data) {
121
- if (currentLogLevel >= LOG_LEVELS.debug) {
122
- console.log(JSON.stringify(data, null, 2));
123
- }
124
- }
125
-
126
- /**
127
- * Create spinner (simple implementation)
128
- */
129
- function createSpinner(message) {
130
- const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
131
- let i = 0;
132
- let interval = null;
133
-
134
- return {
135
- start() {
136
- process.stdout.write(`${message} ${frames[0]}`);
137
- interval = setInterval(() => {
138
- i = (i + 1) % frames.length;
139
- process.stdout.write(`\r${message} ${frames[i]}`);
140
- }, 80);
141
- },
142
-
143
- stop(finalMessage = null) {
144
- if (interval) {
145
- clearInterval(interval);
146
- interval = null;
147
- }
148
- process.stdout.write('\r\x1b[K'); // Clear line
149
- if (finalMessage) {
150
- console.log(finalMessage);
151
- }
152
- },
153
-
154
- succeed(message) {
155
- this.stop(`${COLORS.green}✓${COLORS.reset} ${message}`);
156
- },
157
-
158
- fail(message) {
159
- this.stop(`${COLORS.red}✗${COLORS.reset} ${message}`);
160
- },
161
- };
162
- }
163
-
164
- module.exports = {
165
- setLogLevel,
166
- error,
167
- warn,
168
- info,
169
- success,
170
- debug,
171
- progress,
172
- section,
173
- log,
174
- json,
175
- createSpinner,
176
- COLORS,
177
- LOG_LEVELS,
178
- };
1
+ /**
2
+ * Logging utilities for CursorFlow
3
+ */
4
+
5
+ export enum LogLevel {
6
+ error = 0,
7
+ warn = 1,
8
+ info = 2,
9
+ debug = 3,
10
+ }
11
+
12
+ export const COLORS = {
13
+ reset: '\x1b[0m',
14
+ red: '\x1b[31m',
15
+ yellow: '\x1b[33m',
16
+ green: '\x1b[32m',
17
+ blue: '\x1b[34m',
18
+ cyan: '\x1b[36m',
19
+ gray: '\x1b[90m',
20
+ };
21
+
22
+ let currentLogLevel: number = LogLevel.info;
23
+
24
+ /**
25
+ * Set log level
26
+ */
27
+ export function setLogLevel(level: string | number): void {
28
+ if (typeof level === 'string') {
29
+ currentLogLevel = (LogLevel as any)[level] ?? LogLevel.info;
30
+ } else {
31
+ currentLogLevel = level;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Format message with timestamp
37
+ */
38
+ function formatMessage(level: string, message: string, emoji = ''): string {
39
+ const timestamp = new Date().toISOString();
40
+ const prefix = emoji ? `${emoji} ` : '';
41
+ return `[${timestamp}] [${level.toUpperCase()}] ${prefix}${message}`;
42
+ }
43
+
44
+ /**
45
+ * Log with color
46
+ */
47
+ function logWithColor(color: string, level: keyof typeof LogLevel, message: string, emoji = ''): void {
48
+ if (LogLevel[level] > currentLogLevel) {
49
+ return;
50
+ }
51
+
52
+ const formatted = formatMessage(level, message, emoji);
53
+ console.log(`${color}${formatted}${COLORS.reset}`);
54
+ }
55
+
56
+ /**
57
+ * Error log
58
+ */
59
+ export function error(message: string, emoji = '❌'): void {
60
+ logWithColor(COLORS.red, 'error', message, emoji);
61
+ }
62
+
63
+ /**
64
+ * Warning log
65
+ */
66
+ export function warn(message: string, emoji = '⚠️'): void {
67
+ logWithColor(COLORS.yellow, 'warn', message, emoji);
68
+ }
69
+
70
+ /**
71
+ * Info log
72
+ */
73
+ export function info(message: string, emoji = 'ℹ️'): void {
74
+ logWithColor(COLORS.cyan, 'info', message, emoji);
75
+ }
76
+
77
+ /**
78
+ * Success log
79
+ */
80
+ export function success(message: string, emoji = '✅'): void {
81
+ logWithColor(COLORS.green, 'info', message, emoji);
82
+ }
83
+
84
+ /**
85
+ * Debug log
86
+ */
87
+ export function debug(message: string, emoji = '🔍'): void {
88
+ logWithColor(COLORS.gray, 'debug', message, emoji);
89
+ }
90
+
91
+ /**
92
+ * Progress log
93
+ */
94
+ export function progress(message: string, emoji = '🔄'): void {
95
+ logWithColor(COLORS.blue, 'info', message, emoji);
96
+ }
97
+
98
+ /**
99
+ * Section header
100
+ */
101
+ export function section(message: string): void {
102
+ console.log('');
103
+ console.log(`${COLORS.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${COLORS.reset}`);
104
+ console.log(`${COLORS.cyan} ${message}${COLORS.reset}`);
105
+ console.log(`${COLORS.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${COLORS.reset}`);
106
+ console.log('');
107
+ }
108
+
109
+ /**
110
+ * Simple log without formatting
111
+ */
112
+ export function log(message: string | any): void {
113
+ console.log(message);
114
+ }
115
+
116
+ /**
117
+ * Log JSON data (pretty print in debug mode)
118
+ */
119
+ export function json(data: any): void {
120
+ if (currentLogLevel >= LogLevel.debug) {
121
+ console.log(JSON.stringify(data, null, 2));
122
+ }
123
+ }
124
+
125
+ export interface Spinner {
126
+ start(): void;
127
+ stop(finalMessage?: string | null): void;
128
+ succeed(message: string): void;
129
+ fail(message: string): void;
130
+ }
131
+
132
+ /**
133
+ * Create spinner (simple implementation)
134
+ */
135
+ export function createSpinner(message: string): Spinner {
136
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
137
+ let i = 0;
138
+ let interval: NodeJS.Timeout | null = null;
139
+
140
+ const spinner: Spinner = {
141
+ start() {
142
+ process.stdout.write(`${message} ${frames[0]}`);
143
+ interval = setInterval(() => {
144
+ i = (i + 1) % frames.length;
145
+ process.stdout.write(`\r${message} ${frames[i]}`);
146
+ }, 80);
147
+ },
148
+
149
+ stop(finalMessage: string | null = null) {
150
+ if (interval) {
151
+ clearInterval(interval);
152
+ interval = null;
153
+ }
154
+ process.stdout.write('\r\x1b[K'); // Clear line
155
+ if (finalMessage) {
156
+ console.log(finalMessage);
157
+ }
158
+ },
159
+
160
+ succeed(message: string) {
161
+ this.stop(`${COLORS.green}✓${COLORS.reset} ${message}`);
162
+ },
163
+
164
+ fail(message: string) {
165
+ this.stop(`${COLORS.red}✗${COLORS.reset} ${message}`);
166
+ },
167
+ };
168
+
169
+ return spinner;
170
+ }
@@ -1,15 +1,22 @@
1
- #!/usr/bin/env node
2
1
  /**
3
2
  * State management utilities for CursorFlow
4
3
  */
5
4
 
6
- const fs = require('fs');
7
- const path = require('path');
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import {
8
+ LaneState,
9
+ ConversationEntry,
10
+ GitLogEntry,
11
+ EventEntry,
12
+ RunnerConfig
13
+ } from './types';
14
+ export { LaneState, ConversationEntry, GitLogEntry, EventEntry };
8
15
 
9
16
  /**
10
17
  * Save state to JSON file
11
18
  */
12
- function saveState(statePath, state) {
19
+ export function saveState(statePath: string, state: any): void {
13
20
  const stateDir = path.dirname(statePath);
14
21
 
15
22
  if (!fs.existsSync(stateDir)) {
@@ -22,15 +29,15 @@ function saveState(statePath, state) {
22
29
  /**
23
30
  * Load state from JSON file
24
31
  */
25
- function loadState(statePath) {
32
+ export function loadState<T = any>(statePath: string): T | null {
26
33
  if (!fs.existsSync(statePath)) {
27
34
  return null;
28
35
  }
29
36
 
30
37
  try {
31
38
  const content = fs.readFileSync(statePath, 'utf8');
32
- return JSON.parse(content);
33
- } catch (error) {
39
+ return JSON.parse(content) as T;
40
+ } catch (error: any) {
34
41
  console.warn(`Warning: Failed to parse state file ${statePath}: ${error.message}`);
35
42
  return null;
36
43
  }
@@ -39,7 +46,7 @@ function loadState(statePath) {
39
46
  /**
40
47
  * Append to JSONL log file
41
48
  */
42
- function appendLog(logPath, entry) {
49
+ export function appendLog(logPath: string, entry: any): void {
43
50
  const logDir = path.dirname(logPath);
44
51
 
45
52
  if (!fs.existsSync(logDir)) {
@@ -53,7 +60,7 @@ function appendLog(logPath, entry) {
53
60
  /**
54
61
  * Read JSONL log file
55
62
  */
56
- function readLog(logPath) {
63
+ export function readLog<T = any>(logPath: string): T[] {
57
64
  if (!fs.existsSync(logPath)) {
58
65
  return [];
59
66
  }
@@ -63,8 +70,8 @@ function readLog(logPath) {
63
70
  return content
64
71
  .split('\n')
65
72
  .filter(line => line.trim())
66
- .map(line => JSON.parse(line));
67
- } catch (error) {
73
+ .map(line => JSON.parse(line) as T);
74
+ } catch (error: any) {
68
75
  console.warn(`Warning: Failed to parse log file ${logPath}: ${error.message}`);
69
76
  return [];
70
77
  }
@@ -73,7 +80,7 @@ function readLog(logPath) {
73
80
  /**
74
81
  * Create initial lane state
75
82
  */
76
- function createLaneState(laneName, config) {
83
+ export function createLaneState(laneName: string, config: RunnerConfig): LaneState {
77
84
  return {
78
85
  label: laneName,
79
86
  status: 'pending',
@@ -91,7 +98,7 @@ function createLaneState(laneName, config) {
91
98
  /**
92
99
  * Update lane state
93
100
  */
94
- function updateLaneState(state, updates) {
101
+ export function updateLaneState(state: LaneState, updates: Partial<LaneState>): LaneState {
95
102
  return {
96
103
  ...state,
97
104
  ...updates,
@@ -102,10 +109,10 @@ function updateLaneState(state, updates) {
102
109
  /**
103
110
  * Create conversation log entry
104
111
  */
105
- function createConversationEntry(role, text, options = {}) {
112
+ export function createConversationEntry(role: ConversationEntry['role'], text: string, options: { task?: string; model?: string } = {}): ConversationEntry {
106
113
  return {
107
114
  timestamp: new Date().toISOString(),
108
- role, // 'user' | 'assistant' | 'reviewer' | 'system'
115
+ role,
109
116
  task: options.task || null,
110
117
  fullText: text,
111
118
  textLength: text.length,
@@ -116,10 +123,10 @@ function createConversationEntry(role, text, options = {}) {
116
123
  /**
117
124
  * Create git operation log entry
118
125
  */
119
- function createGitLogEntry(operation, details = {}) {
126
+ export function createGitLogEntry(operation: string, details: any = {}): GitLogEntry {
120
127
  return {
121
128
  timestamp: new Date().toISOString(),
122
- operation, // 'commit' | 'push' | 'merge' | 'worktree-add' | etc.
129
+ operation,
123
130
  ...details,
124
131
  };
125
132
  }
@@ -127,7 +134,7 @@ function createGitLogEntry(operation, details = {}) {
127
134
  /**
128
135
  * Create event log entry
129
136
  */
130
- function createEventEntry(event, data = {}) {
137
+ export function createEventEntry(event: string, data: any = {}): EventEntry {
131
138
  return {
132
139
  timestamp: new Date().toISOString(),
133
140
  event,
@@ -138,7 +145,7 @@ function createEventEntry(event, data = {}) {
138
145
  /**
139
146
  * Get latest run directory
140
147
  */
141
- function getLatestRunDir(logsDir) {
148
+ export function getLatestRunDir(logsDir: string): string | null {
142
149
  if (!fs.existsSync(logsDir)) {
143
150
  return null;
144
151
  }
@@ -152,13 +159,13 @@ function getLatestRunDir(logsDir) {
152
159
  return null;
153
160
  }
154
161
 
155
- return path.join(logsDir, runs[0]);
162
+ return path.join(logsDir, runs[0]!);
156
163
  }
157
164
 
158
165
  /**
159
166
  * List all lanes in a run directory
160
167
  */
161
- function listLanesInRun(runDir) {
168
+ export function listLanesInRun(runDir: string): { name: string; dir: string; statePath: string }[] {
162
169
  if (!fs.existsSync(runDir)) {
163
170
  return [];
164
171
  }
@@ -175,8 +182,8 @@ function listLanesInRun(runDir) {
175
182
  /**
176
183
  * Get lane state summary
177
184
  */
178
- function getLaneStateSummary(statePath) {
179
- const state = loadState(statePath);
185
+ export function getLaneStateSummary(statePath: string): { status: string; progress: string; label?: string; error?: string | null } {
186
+ const state = loadState<LaneState>(statePath);
180
187
  if (!state) {
181
188
  return { status: 'unknown', progress: '-' };
182
189
  }
@@ -190,18 +197,3 @@ function getLaneStateSummary(statePath) {
190
197
  error: state.error,
191
198
  };
192
199
  }
193
-
194
- module.exports = {
195
- saveState,
196
- loadState,
197
- appendLog,
198
- readLog,
199
- createLaneState,
200
- updateLaneState,
201
- createConversationEntry,
202
- createGitLogEntry,
203
- createEventEntry,
204
- getLatestRunDir,
205
- listLanesInRun,
206
- getLaneStateSummary,
207
- };
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Shared type definitions for CursorFlow
3
+ */
4
+
5
+ export interface LaneConfig {
6
+ devPort: number;
7
+ autoCreatePr: boolean;
8
+ }
9
+
10
+ export interface CursorFlowConfig {
11
+ tasksDir: string;
12
+ logsDir: string;
13
+ baseBranch: string;
14
+ branchPrefix: string;
15
+ executor: 'cursor-agent' | 'cloud';
16
+ pollInterval: number;
17
+ allowDependencyChange: boolean;
18
+ lockfileReadOnly: boolean;
19
+ enableReview: boolean;
20
+ reviewModel: string;
21
+ maxReviewIterations: number;
22
+ defaultLaneConfig: LaneConfig;
23
+ logLevel: string;
24
+ verboseGit: boolean;
25
+ worktreePrefix: string;
26
+ maxConcurrentLanes: number;
27
+ projectRoot: string;
28
+ }
29
+
30
+ export interface DependencyPolicy {
31
+ allowDependencyChange: boolean;
32
+ lockfileReadOnly: boolean;
33
+ }
34
+
35
+ export interface Task {
36
+ name: string;
37
+ prompt: string;
38
+ model?: string;
39
+ }
40
+
41
+ export interface RunnerConfig {
42
+ tasks: Task[];
43
+ pipelineBranch?: string;
44
+ branchPrefix?: string;
45
+ worktreeRoot?: string;
46
+ baseBranch?: string;
47
+ model?: string;
48
+ dependencyPolicy: DependencyPolicy;
49
+ reviewModel?: string;
50
+ maxReviewIterations?: number;
51
+ acceptanceCriteria?: string[];
52
+ }
53
+
54
+ export interface DependencyRequestPlan {
55
+ reason: string;
56
+ changes: string[];
57
+ commands: string[];
58
+ notes?: string;
59
+ }
60
+
61
+ export interface TaskExecutionResult {
62
+ taskName: string;
63
+ taskBranch: string;
64
+ status: 'FINISHED' | 'ERROR' | 'BLOCKED_DEPENDENCY';
65
+ error?: string;
66
+ dependencyRequest?: DependencyRequestPlan | null;
67
+ }
68
+
69
+ export interface AgentSendResult {
70
+ ok: boolean;
71
+ exitCode: number;
72
+ error?: string;
73
+ sessionId?: string;
74
+ resultText?: string;
75
+ }
76
+
77
+ export interface ReviewIssue {
78
+ severity: 'critical' | 'major' | 'minor';
79
+ description: string;
80
+ file?: string;
81
+ suggestion?: string;
82
+ }
83
+
84
+ export interface ReviewResult {
85
+ status: 'approved' | 'needs_changes';
86
+ buildSuccess: boolean;
87
+ issues: ReviewIssue[];
88
+ suggestions: string[];
89
+ summary: string;
90
+ raw: string;
91
+ }
92
+
93
+ export interface TaskResult {
94
+ taskName: string;
95
+ taskBranch: string;
96
+ [key: string]: any;
97
+ }
98
+
99
+ export interface LaneState {
100
+ label: string;
101
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'paused' | 'waiting' | 'reviewing';
102
+ currentTaskIndex: number;
103
+ totalTasks: number;
104
+ worktreeDir: string | null;
105
+ pipelineBranch: string | null;
106
+ startTime: number;
107
+ endTime: number | null;
108
+ error: string | null;
109
+ dependencyRequest: DependencyRequestPlan | null;
110
+ updatedAt?: number;
111
+ }
112
+
113
+ export interface ConversationEntry {
114
+ timestamp: string;
115
+ role: 'user' | 'assistant' | 'reviewer' | 'system';
116
+ task: string | null;
117
+ fullText: string;
118
+ textLength: number;
119
+ model: string | null;
120
+ }
121
+
122
+ export interface GitLogEntry {
123
+ timestamp: string;
124
+ operation: string;
125
+ [key: string]: any;
126
+ }
127
+
128
+ export interface EventEntry {
129
+ timestamp: string;
130
+ event: string;
131
+ [key: string]: any;
132
+ }
133
+