@litmers/cursorflow-orchestrator 0.1.3 → 0.1.6

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 (90) hide show
  1. package/CHANGELOG.md +17 -7
  2. package/README.md +33 -2
  3. package/commands/cursorflow-doctor.md +24 -0
  4. package/commands/cursorflow-signal.md +19 -0
  5. package/dist/cli/clean.d.ts +5 -0
  6. package/dist/cli/clean.js +57 -0
  7. package/dist/cli/clean.js.map +1 -0
  8. package/dist/cli/doctor.d.ts +15 -0
  9. package/dist/cli/doctor.js +139 -0
  10. package/dist/cli/doctor.js.map +1 -0
  11. package/dist/cli/index.d.ts +6 -0
  12. package/dist/cli/index.js +125 -0
  13. package/dist/cli/index.js.map +1 -0
  14. package/dist/cli/init.d.ts +7 -0
  15. package/dist/cli/init.js +302 -0
  16. package/dist/cli/init.js.map +1 -0
  17. package/dist/cli/monitor.d.ts +8 -0
  18. package/dist/cli/monitor.js +210 -0
  19. package/dist/cli/monitor.js.map +1 -0
  20. package/dist/cli/resume.d.ts +5 -0
  21. package/dist/cli/resume.js +128 -0
  22. package/dist/cli/resume.js.map +1 -0
  23. package/dist/cli/run.d.ts +5 -0
  24. package/dist/cli/run.js +128 -0
  25. package/dist/cli/run.js.map +1 -0
  26. package/dist/cli/setup-commands.d.ts +23 -0
  27. package/dist/cli/setup-commands.js +234 -0
  28. package/dist/cli/setup-commands.js.map +1 -0
  29. package/dist/cli/signal.d.ts +7 -0
  30. package/dist/cli/signal.js +99 -0
  31. package/dist/cli/signal.js.map +1 -0
  32. package/dist/core/orchestrator.d.ts +47 -0
  33. package/dist/core/orchestrator.js +192 -0
  34. package/dist/core/orchestrator.js.map +1 -0
  35. package/dist/core/reviewer.d.ts +60 -0
  36. package/dist/core/reviewer.js +239 -0
  37. package/dist/core/reviewer.js.map +1 -0
  38. package/dist/core/runner.d.ts +51 -0
  39. package/dist/core/runner.js +499 -0
  40. package/dist/core/runner.js.map +1 -0
  41. package/dist/utils/config.d.ts +31 -0
  42. package/dist/utils/config.js +198 -0
  43. package/dist/utils/config.js.map +1 -0
  44. package/dist/utils/cursor-agent.d.ts +61 -0
  45. package/dist/utils/cursor-agent.js +263 -0
  46. package/dist/utils/cursor-agent.js.map +1 -0
  47. package/dist/utils/doctor.d.ts +63 -0
  48. package/dist/utils/doctor.js +280 -0
  49. package/dist/utils/doctor.js.map +1 -0
  50. package/dist/utils/git.d.ts +131 -0
  51. package/dist/utils/git.js +272 -0
  52. package/dist/utils/git.js.map +1 -0
  53. package/dist/utils/logger.d.ts +68 -0
  54. package/dist/utils/logger.js +158 -0
  55. package/dist/utils/logger.js.map +1 -0
  56. package/dist/utils/state.d.ts +65 -0
  57. package/dist/utils/state.js +216 -0
  58. package/dist/utils/state.js.map +1 -0
  59. package/dist/utils/types.d.ts +118 -0
  60. package/dist/utils/types.js +6 -0
  61. package/dist/utils/types.js.map +1 -0
  62. package/examples/README.md +155 -0
  63. package/examples/demo-project/README.md +262 -0
  64. package/examples/demo-project/_cursorflow/tasks/demo-test/01-create-utils.json +18 -0
  65. package/examples/demo-project/_cursorflow/tasks/demo-test/02-add-tests.json +18 -0
  66. package/examples/demo-project/_cursorflow/tasks/demo-test/README.md +109 -0
  67. package/package.json +71 -61
  68. package/scripts/ai-security-check.js +11 -4
  69. package/scripts/local-security-gate.sh +76 -0
  70. package/src/cli/{clean.js → clean.ts} +11 -5
  71. package/src/cli/doctor.ts +127 -0
  72. package/src/cli/{index.js → index.ts} +27 -16
  73. package/src/cli/{init.js → init.ts} +26 -18
  74. package/src/cli/{monitor.js → monitor.ts} +57 -44
  75. package/src/cli/resume.ts +119 -0
  76. package/src/cli/run.ts +109 -0
  77. package/src/cli/{setup-commands.js → setup-commands.ts} +38 -18
  78. package/src/cli/signal.ts +89 -0
  79. package/src/core/{orchestrator.js → orchestrator.ts} +44 -26
  80. package/src/core/{reviewer.js → reviewer.ts} +36 -29
  81. package/src/core/{runner.js → runner.ts} +125 -76
  82. package/src/utils/{config.js → config.ts} +17 -25
  83. package/src/utils/{cursor-agent.js → cursor-agent.ts} +38 -47
  84. package/src/utils/doctor.ts +312 -0
  85. package/src/utils/{git.js → git.ts} +70 -56
  86. package/src/utils/{logger.js → logger.ts} +170 -178
  87. package/src/utils/{state.js → state.ts} +30 -38
  88. package/src/utils/types.ts +134 -0
  89. package/src/cli/resume.js +0 -31
  90. package/src/cli/run.js +0 -51
@@ -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,134 @@
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
+ tasksFile?: string; // Original tasks file path
112
+ }
113
+
114
+ export interface ConversationEntry {
115
+ timestamp: string;
116
+ role: 'user' | 'assistant' | 'reviewer' | 'system';
117
+ task: string | null;
118
+ fullText: string;
119
+ textLength: number;
120
+ model: string | null;
121
+ }
122
+
123
+ export interface GitLogEntry {
124
+ timestamp: string;
125
+ operation: string;
126
+ [key: string]: any;
127
+ }
128
+
129
+ export interface EventEntry {
130
+ timestamp: string;
131
+ event: string;
132
+ [key: string]: any;
133
+ }
134
+
package/src/cli/resume.js DELETED
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CursorFlow resume command (stub)
4
- */
5
-
6
- const logger = require('../utils/logger');
7
-
8
- function parseArgs(args) {
9
- return {
10
- lane: args[0],
11
- runDir: null,
12
- clean: args.includes('--clean'),
13
- restart: args.includes('--restart'),
14
- };
15
- }
16
-
17
- async function resume(args) {
18
- logger.section('🔁 Resuming Lane');
19
-
20
- const options = parseArgs(args);
21
-
22
- logger.info('This command will be fully implemented in the next phase');
23
- logger.info(`Lane: ${options.lane}`);
24
- logger.info(`Clean: ${options.clean}`);
25
- logger.info(`Restart: ${options.restart}`);
26
-
27
- logger.warn('\n⚠️ Implementation pending');
28
- logger.info('This will resume interrupted lanes');
29
- }
30
-
31
- module.exports = resume;
package/src/cli/run.js DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * CursorFlow run command
4
- */
5
-
6
- const path = require('path');
7
- const fs = require('fs');
8
- const logger = require('../utils/logger');
9
- const { orchestrate } = require('../core/orchestrator');
10
- const { loadConfig } = require('../utils/config');
11
-
12
- function parseArgs(args) {
13
- return {
14
- tasksDir: args.find(a => !a.startsWith('--')),
15
- dryRun: args.includes('--dry-run'),
16
- executor: args[args.indexOf('--executor') + 1] || null,
17
- };
18
- }
19
-
20
- async function run(args) {
21
- const options = parseArgs(args);
22
-
23
- if (!options.tasksDir) {
24
- logger.error('Tasks directory required');
25
- console.log('\nUsage: cursorflow run <tasks-dir> [options]');
26
- process.exit(1);
27
- }
28
-
29
- if (!fs.existsSync(options.tasksDir)) {
30
- logger.error(`Tasks directory not found: ${options.tasksDir}`);
31
- process.exit(1);
32
- }
33
-
34
- const config = loadConfig();
35
-
36
- try {
37
- await orchestrate(options.tasksDir, {
38
- executor: options.executor || config.executor,
39
- pollInterval: config.pollInterval * 1000,
40
- runDir: path.join(config.logsDir, 'runs', `run-${Date.now()}`),
41
- });
42
- } catch (error) {
43
- logger.error(`Orchestration failed: ${error.message}`);
44
- if (process.env.DEBUG) {
45
- console.error(error.stack);
46
- }
47
- process.exit(1);
48
- }
49
- }
50
-
51
- module.exports = run;