@litmers/cursorflow-orchestrator 0.1.31 → 0.1.34

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 (129) hide show
  1. package/README.md +144 -52
  2. package/commands/cursorflow-add.md +159 -0
  3. package/commands/cursorflow-monitor.md +23 -2
  4. package/commands/cursorflow-new.md +87 -0
  5. package/dist/cli/add.d.ts +7 -0
  6. package/dist/cli/add.js +377 -0
  7. package/dist/cli/add.js.map +1 -0
  8. package/dist/cli/clean.js +1 -0
  9. package/dist/cli/clean.js.map +1 -1
  10. package/dist/cli/config.d.ts +7 -0
  11. package/dist/cli/config.js +181 -0
  12. package/dist/cli/config.js.map +1 -0
  13. package/dist/cli/index.js +34 -30
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/logs.js +7 -33
  16. package/dist/cli/logs.js.map +1 -1
  17. package/dist/cli/monitor.js +51 -62
  18. package/dist/cli/monitor.js.map +1 -1
  19. package/dist/cli/new.d.ts +7 -0
  20. package/dist/cli/new.js +232 -0
  21. package/dist/cli/new.js.map +1 -0
  22. package/dist/cli/prepare.js +95 -193
  23. package/dist/cli/prepare.js.map +1 -1
  24. package/dist/cli/resume.js +11 -47
  25. package/dist/cli/resume.js.map +1 -1
  26. package/dist/cli/run.js +27 -22
  27. package/dist/cli/run.js.map +1 -1
  28. package/dist/cli/tasks.js +1 -2
  29. package/dist/cli/tasks.js.map +1 -1
  30. package/dist/core/failure-policy.d.ts +9 -0
  31. package/dist/core/failure-policy.js +9 -0
  32. package/dist/core/failure-policy.js.map +1 -1
  33. package/dist/core/orchestrator.d.ts +20 -6
  34. package/dist/core/orchestrator.js +213 -333
  35. package/dist/core/orchestrator.js.map +1 -1
  36. package/dist/core/runner/agent.d.ts +27 -0
  37. package/dist/core/runner/agent.js +294 -0
  38. package/dist/core/runner/agent.js.map +1 -0
  39. package/dist/core/runner/index.d.ts +5 -0
  40. package/dist/core/runner/index.js +22 -0
  41. package/dist/core/runner/index.js.map +1 -0
  42. package/dist/core/runner/pipeline.d.ts +9 -0
  43. package/dist/core/runner/pipeline.js +539 -0
  44. package/dist/core/runner/pipeline.js.map +1 -0
  45. package/dist/core/runner/prompt.d.ts +25 -0
  46. package/dist/core/runner/prompt.js +175 -0
  47. package/dist/core/runner/prompt.js.map +1 -0
  48. package/dist/core/runner/task.d.ts +26 -0
  49. package/dist/core/runner/task.js +283 -0
  50. package/dist/core/runner/task.js.map +1 -0
  51. package/dist/core/runner/utils.d.ts +37 -0
  52. package/dist/core/runner/utils.js +161 -0
  53. package/dist/core/runner/utils.js.map +1 -0
  54. package/dist/core/runner.d.ts +2 -96
  55. package/dist/core/runner.js +11 -1136
  56. package/dist/core/runner.js.map +1 -1
  57. package/dist/core/stall-detection.d.ts +326 -0
  58. package/dist/core/stall-detection.js +781 -0
  59. package/dist/core/stall-detection.js.map +1 -0
  60. package/dist/types/config.d.ts +6 -6
  61. package/dist/types/flow.d.ts +84 -0
  62. package/dist/types/flow.js +10 -0
  63. package/dist/types/flow.js.map +1 -0
  64. package/dist/types/index.d.ts +1 -0
  65. package/dist/types/index.js +3 -3
  66. package/dist/types/index.js.map +1 -1
  67. package/dist/types/lane.d.ts +0 -2
  68. package/dist/types/logging.d.ts +5 -1
  69. package/dist/types/task.d.ts +7 -11
  70. package/dist/utils/config.js +7 -15
  71. package/dist/utils/config.js.map +1 -1
  72. package/dist/utils/dependency.d.ts +36 -1
  73. package/dist/utils/dependency.js +256 -1
  74. package/dist/utils/dependency.js.map +1 -1
  75. package/dist/utils/enhanced-logger.d.ts +45 -82
  76. package/dist/utils/enhanced-logger.js +238 -844
  77. package/dist/utils/enhanced-logger.js.map +1 -1
  78. package/dist/utils/git.d.ts +29 -0
  79. package/dist/utils/git.js +115 -5
  80. package/dist/utils/git.js.map +1 -1
  81. package/dist/utils/state.js +0 -2
  82. package/dist/utils/state.js.map +1 -1
  83. package/dist/utils/task-service.d.ts +2 -2
  84. package/dist/utils/task-service.js +40 -31
  85. package/dist/utils/task-service.js.map +1 -1
  86. package/package.json +4 -3
  87. package/src/cli/add.ts +397 -0
  88. package/src/cli/clean.ts +1 -0
  89. package/src/cli/config.ts +177 -0
  90. package/src/cli/index.ts +36 -32
  91. package/src/cli/logs.ts +7 -31
  92. package/src/cli/monitor.ts +55 -71
  93. package/src/cli/new.ts +235 -0
  94. package/src/cli/prepare.ts +98 -205
  95. package/src/cli/resume.ts +13 -56
  96. package/src/cli/run.ts +311 -306
  97. package/src/cli/tasks.ts +1 -2
  98. package/src/core/failure-policy.ts +9 -0
  99. package/src/core/orchestrator.ts +277 -378
  100. package/src/core/runner/agent.ts +314 -0
  101. package/src/core/runner/index.ts +6 -0
  102. package/src/core/runner/pipeline.ts +567 -0
  103. package/src/core/runner/prompt.ts +174 -0
  104. package/src/core/runner/task.ts +320 -0
  105. package/src/core/runner/utils.ts +142 -0
  106. package/src/core/runner.ts +8 -1347
  107. package/src/core/stall-detection.ts +936 -0
  108. package/src/types/config.ts +6 -6
  109. package/src/types/flow.ts +91 -0
  110. package/src/types/index.ts +15 -3
  111. package/src/types/lane.ts +0 -2
  112. package/src/types/logging.ts +5 -1
  113. package/src/types/task.ts +7 -11
  114. package/src/utils/config.ts +8 -16
  115. package/src/utils/dependency.ts +311 -2
  116. package/src/utils/enhanced-logger.ts +263 -927
  117. package/src/utils/git.ts +145 -5
  118. package/src/utils/state.ts +0 -2
  119. package/src/utils/task-service.ts +48 -40
  120. package/commands/cursorflow-review.md +0 -56
  121. package/commands/cursorflow-runs.md +0 -59
  122. package/dist/cli/runs.d.ts +0 -5
  123. package/dist/cli/runs.js +0 -214
  124. package/dist/cli/runs.js.map +0 -1
  125. package/dist/core/reviewer.d.ts +0 -66
  126. package/dist/core/reviewer.js +0 -265
  127. package/dist/core/reviewer.js.map +0 -1
  128. package/src/cli/runs.ts +0 -212
  129. package/src/core/reviewer.ts +0 -285
@@ -21,124 +21,105 @@ interface PrepareOptions {
21
21
  lanes: number;
22
22
  template: string | null;
23
23
  preset: PresetType | null; // --preset complex|simple|merge
24
- sequential: boolean;
25
- deps: string | null;
26
24
  // Terminal-first options
27
25
  prompt: string | null;
28
26
  criteria: string[];
29
27
  model: string | null;
30
- taskSpecs: string[]; // Multiple --task "name|model|prompt|criteria"
28
+ taskSpecs: string[]; // Multiple --task "name|model|prompt|criteria|dependsOn|timeout"
31
29
  // Incremental options
32
30
  addLane: string | null; // Add lane to existing task dir
33
31
  addTask: string | null; // Add task to existing lane file
34
- dependsOnLanes: string[]; // --depends-on for new lane
35
32
  force: boolean;
36
33
  help: boolean;
37
34
  }
38
35
 
39
36
  function printHelp(): void {
40
37
  console.log(`
41
- Usage: cursorflow prepare <feature-name> [options]
42
-
43
- Prepare task files for a new feature - Terminal-first workflow.
38
+ cursorflow prepare - 태스크 파일 생성
44
39
 
45
40
  ═══════════════════════════════════════════════════════════════════════════════
46
- WORKFLOW: Requirements Lanes Tasks Validate → Run
41
+ 시나리오: "쇼핑몰" 프로젝트에서 백엔드 API와 프론트엔드 동시 개발
47
42
  ═══════════════════════════════════════════════════════════════════════════════
48
43
 
49
- ## Step 1: Create Initial Lanes (with Presets)
50
-
51
- # Complex implementation: plan implement test
52
- cursorflow prepare FeatureName --preset complex --prompt "Implement user auth"
53
-
54
- # Simple implementation: implement → test
55
- cursorflow prepare BugFix --preset simple --prompt "Fix login bug"
44
+ [Case 1] 가장 간단하게 - 버그 하나 고치기
45
+ ─────────────────────────────────────────
46
+ cursorflow prepare FixCartBug --prompt "장바구니 수량 버그 수정"
56
47
 
57
- # Merge lane: merge → test (for lanes with dependencies)
58
- cursorflow prepare Integration --preset merge --depends-on "01-lane-1,02-lane-2"
48
+ 결과: _cursorflow/tasks/2412251030_FixCartBug/
49
+ └── 01-FixCartBug.json (implement 태스크 1개)
59
50
 
60
- # Multiple sequential lanes (auto-detects merge preset for dependent lanes)
61
- cursorflow prepare FullStack --lanes 3 --sequential --prompt "Build your layer"
62
51
 
63
- ## Step 2: Add More Lanes (Incremental)
52
+ [Case 2] 프리셋 사용 - 계획부터 테스트까지
53
+ ─────────────────────────────────────────
54
+ cursorflow prepare PaymentAPI --preset complex --prompt "Stripe 결제 연동"
64
55
 
65
- # Add a merge lane to existing task directory
66
- cursorflow prepare --add-lane _cursorflow/tasks/2412211530_FullStack \\
67
- --preset merge --depends-on "01-lane-1,02-lane-2"
56
+ 결과: 01-PaymentAPI.json에 plan implement test 태스크 생성
68
57
 
69
- ## Step 3: Add More Tasks to a Lane
58
+ 프리셋:
59
+ --preset complex plan → implement → test
60
+ --preset simple implement → test
61
+ (없으면) implement만
70
62
 
71
- # Append a task to an existing lane
72
- cursorflow prepare --add-task _cursorflow/tasks/2412211530_FullStack/01-lane-1.json \\
73
- --task "verify|sonnet-4.5|Double-check all requirements|All criteria met"
74
63
 
75
- ## Step 4: Validate Configuration
64
+ [Case 3] 병렬 레인 - 백엔드/프론트 동시 개발
65
+ ─────────────────────────────────────────
66
+ cursorflow prepare ShopFeature --lanes 2 --preset complex \\
67
+ --prompt "상품 검색 기능"
76
68
 
77
- cursorflow doctor --tasks-dir _cursorflow/tasks/2412211530_FullStack
69
+ 결과: 01-lane-1.json (백엔드) ─┬─ 동시 실행
70
+ 02-lane-2.json (프론트) ─┘
78
71
 
79
- ## Step 5: Run
80
72
 
81
- cursorflow run _cursorflow/tasks/2412211530_FullStack
82
-
83
- ═══════════════════════════════════════════════════════════════════════════════
73
+ [Case 4] 의존성 - 프론트가 백엔드 완료 후 시작
74
+ ─────────────────────────────────────────
75
+ cursorflow prepare --add-task ./02-lane-2.json \\
76
+ --task "integrate|sonnet-4.5|API 연동|완료|01-lane-1:implement"
77
+ └─ 이 태스크 완료 후 시작
84
78
 
85
- ## Preset Templates
79
+ 실행 흐름:
80
+ 01-lane-1: [plan] → [implement] → [test]
81
+ ↓ 완료되면
82
+ 02-lane-2: [plan] ───────┴─────→ [integrate]
86
83
 
87
- --preset complex plan → implement → test (for complex features)
88
- --preset simple implement → test (for simple changes)
89
- --preset merge merge → test (auto-applied when --depends-on is set)
90
84
 
91
- ## Options
85
+ [Case 5] 커스텀 태스크 - 원하는 대로 구성
86
+ ─────────────────────────────────────────
87
+ cursorflow prepare CustomFlow \\
88
+ --task "setup|sonnet-4.5|DB 스키마 생성|완료" \\
89
+ --task "api|sonnet-4.5|REST API 구현|동작" \\
90
+ --task "test|sonnet-4.5|테스트 작성|통과"
92
91
 
93
- Core:
94
- <feature-name> Name of the feature (for new task directories)
95
- --lanes <num> Number of lanes to create (default: 1)
96
- --preset <type> Use preset template: complex | simple | merge
97
92
 
98
- Task Definition:
99
- --prompt <text> Task prompt (uses preset or single task)
100
- --criteria <list> Comma-separated acceptance criteria
101
- --model <model> Model to use (default: sonnet-4.5)
102
- --task <spec> Full task spec: "name|model|prompt|criteria|dependsOn|timeout" (repeatable)
93
+ [Case 6] 나중에 추가 - 레인이나 태스크 덧붙이기
94
+ ─────────────────────────────────────────
95
+ # 레인 추가
96
+ cursorflow prepare --add-lane ./tasks/ShopFeature --preset simple
103
97
 
104
- Dependencies:
105
- --sequential Chain lanes: 1 → 2 → 3
106
- --deps <spec> Custom dependencies: "2:1;3:1,2"
107
- --depends-on <lanes> Dependencies for --add-lane: "01-lane-1,02-lane-2"
108
- Task-level deps: In --task, add "lane:task" at the end.
109
- Example: "test|sonnet-4.5|Run tests|All pass|01-lane-1:setup"
110
- Task-level timeout: In --task, add milliseconds at the end.
111
- Example: "heavy|sonnet-4.5|Big task|Done||1200000"
112
-
113
- Incremental (add to existing):
114
- --add-lane <dir> Add a new lane to existing task directory
115
- --add-task <file> Append task(s) to existing lane JSON file
116
-
117
- Advanced:
118
- --template <path|url|name> External template JSON file, URL, or built-in name
119
- --force Overwrite existing files
98
+ # 기존 레인에 태스크 추가
99
+ cursorflow prepare --add-task ./01-lane-1.json \\
100
+ --task "docs|sonnet-4.5|API 문서화|완성"
120
101
 
121
102
  ═══════════════════════════════════════════════════════════════════════════════
122
103
 
123
- ## Examples
104
+ --task 형식: "이름|모델|프롬프트|완료조건|의존성|타임아웃"
124
105
 
125
- # 1. Complex feature with multiple lanes
126
- cursorflow prepare AuthSystem --lanes 3 --sequential --preset complex \\
127
- --prompt "Implement authentication for your layer"
106
+ 예시:
107
+ "build|sonnet-4.5|빌드하기|완료" 기본
108
+ "deploy|sonnet-4.5|배포|성공|01-lane:build" 의존성
109
+ "heavy|sonnet-4.5|대용량|완료||1200000" 타임아웃 20분
128
110
 
129
- # 2. Simple bug fix
130
- cursorflow prepare FixLoginBug --preset simple \\
131
- --prompt "Fix the login validation bug in auth.ts"
132
-
133
- # 3. Add a merge/integration lane
134
- cursorflow prepare --add-lane _cursorflow/tasks/2412211530_AuthSystem \\
135
- --preset merge --depends-on "01-lane-1,02-lane-2"
111
+ ═══════════════════════════════════════════════════════════════════════════════
136
112
 
137
- # 4. Custom multi-task lane (overrides preset)
138
- cursorflow prepare ComplexFeature \\
139
- --task "plan|sonnet-4.5-thinking|Create implementation plan|Plan documented" \\
140
- --task "implement|sonnet-4.5|Build the feature|Code complete" \\
141
- --task "test|sonnet-4.5|Write comprehensive tests|Tests pass"
113
+ 옵션 요약:
114
+ --prompt <text> 작업 설명
115
+ --preset <type> complex | simple | merge
116
+ --lanes <num> 병렬 레인 (기본: 1)
117
+ --task <spec> 커스텀 태스크 (반복 가능)
118
+ --add-lane <dir> 기존 디렉토리에 레인 추가
119
+ --add-task <file> 기존 레인에 태스크 추가
120
+ --model <model> AI 모델 (기본: sonnet-4.5)
121
+ --template <path> 외부 템플릿 파일
122
+ --force 덮어쓰기
142
123
  `);
143
124
  }
144
125
 
@@ -148,15 +129,12 @@ function parseArgs(args: string[]): PrepareOptions {
148
129
  lanes: 1,
149
130
  template: null,
150
131
  preset: null,
151
- sequential: false,
152
- deps: null,
153
132
  prompt: null,
154
133
  criteria: [],
155
134
  model: null,
156
135
  taskSpecs: [],
157
136
  addLane: null,
158
137
  addTask: null,
159
- dependsOnLanes: [],
160
138
  force: false,
161
139
  help: false,
162
140
  };
@@ -169,8 +147,6 @@ function parseArgs(args: string[]): PrepareOptions {
169
147
  result.help = true;
170
148
  } else if (arg === '--force') {
171
149
  result.force = true;
172
- } else if (arg === '--sequential') {
173
- result.sequential = true;
174
150
  } else if (arg === '--lanes' && args[i + 1]) {
175
151
  result.lanes = parseInt(args[++i]) || 1;
176
152
  } else if (arg === '--template' && args[i + 1]) {
@@ -182,8 +158,6 @@ function parseArgs(args: string[]): PrepareOptions {
182
158
  } else {
183
159
  throw new Error(`Invalid preset: "${presetValue}". Must be one of: complex, simple, merge`);
184
160
  }
185
- } else if (arg === '--deps' && args[i + 1]) {
186
- result.deps = args[++i];
187
161
  } else if (arg === '--prompt' && args[i + 1]) {
188
162
  result.prompt = args[++i];
189
163
  } else if (arg === '--criteria' && args[i + 1]) {
@@ -196,8 +170,6 @@ function parseArgs(args: string[]): PrepareOptions {
196
170
  result.addLane = args[++i];
197
171
  } else if (arg === '--add-task' && args[i + 1]) {
198
172
  result.addTask = args[++i];
199
- } else if (arg === '--depends-on' && args[i + 1]) {
200
- result.dependsOnLanes = args[++i].split(',').map(d => d.trim()).filter(d => d);
201
173
  } else if (!arg.startsWith('--') && !result.featureName) {
202
174
  result.featureName = arg;
203
175
  }
@@ -216,10 +188,7 @@ function parseTaskSpec(spec: string): Task {
216
188
  throw new Error(`Invalid task spec: "${spec}". Expected format: "name|model|prompt[|criteria[|dependsOn[|timeout]]]"`);
217
189
  }
218
190
 
219
- const [name, model, prompt, criteriaStr, depsStr, timeoutStr] = parts;
220
- const acceptanceCriteria = criteriaStr
221
- ? criteriaStr.split(',').map(c => c.trim()).filter(c => c)
222
- : undefined;
191
+ const [name, model, prompt, _criteriaStr, depsStr, timeoutStr] = parts;
223
192
 
224
193
  const dependsOn = depsStr
225
194
  ? depsStr.split(',').map(d => d.trim()).filter(d => d)
@@ -231,7 +200,6 @@ function parseTaskSpec(spec: string): Task {
231
200
  name: name.trim(),
232
201
  model: model.trim() || 'sonnet-4.5',
233
202
  prompt: prompt.trim(),
234
- ...(acceptanceCriteria && acceptanceCriteria.length > 0 ? { acceptanceCriteria } : {}),
235
203
  ...(dependsOn && dependsOn.length > 0 ? { dependsOn } : {}),
236
204
  ...(timeout ? { timeout } : {}),
237
205
  };
@@ -286,11 +254,6 @@ The plan document should include:
286
254
  - Data structures and interfaces
287
255
  - Step-by-step implementation tasks
288
256
  - Potential risks and edge cases`,
289
- acceptanceCriteria: [
290
- `Plan document saved to ${planDocPath}`,
291
- 'All required files are identified',
292
- 'Approach is clearly defined',
293
- ],
294
257
  },
295
258
  {
296
259
  name: 'implement',
@@ -318,11 +281,6 @@ ${basePrompt}
318
281
  - Refer back to the plan document if unsure about any step.
319
282
  - Verify all edge cases from the plan are handled.
320
283
  - Ensure code follows project conventions.`,
321
- acceptanceCriteria: criteria.length > 0 ? criteria : [
322
- 'Code implemented according to plan',
323
- 'No build errors',
324
- 'All edge cases handled',
325
- ],
326
284
  },
327
285
  {
328
286
  name: 'test',
@@ -346,11 +304,6 @@ Write comprehensive tests for the implementation.
346
304
  ## Important
347
305
  - All tests must pass before completing.
348
306
  - Cover happy path and error cases from the plan.`,
349
- acceptanceCriteria: [
350
- 'Unit tests written',
351
- 'All tests pass',
352
- 'Edge cases covered',
353
- ],
354
307
  }
355
308
  );
356
309
  break;
@@ -375,11 +328,6 @@ ${basePrompt}
375
328
  ## Important
376
329
  - Keep changes focused and minimal.
377
330
  - Follow existing code conventions.`,
378
- acceptanceCriteria: criteria.length > 0 ? criteria : [
379
- 'Implementation complete',
380
- 'No build errors',
381
- 'Code follows conventions',
382
- ],
383
331
  },
384
332
  {
385
333
  name: 'test',
@@ -397,10 +345,6 @@ Test the implementation thoroughly.
397
345
 
398
346
  ## Important
399
347
  - All tests must pass before completing.`,
400
- acceptanceCriteria: [
401
- 'Tests written/updated',
402
- 'All tests pass',
403
- ],
404
348
  }
405
349
  );
406
350
  break;
@@ -427,11 +371,6 @@ Merge dependent branches and resolve any conflicts.
427
371
  - Resolve all conflicts cleanly.
428
372
  - Ensure code from all merged branches works together.
429
373
  - Check that no functionality was broken by the merge.`,
430
- acceptanceCriteria: [
431
- 'All conflicts resolved',
432
- 'No build errors',
433
- 'Integration verified',
434
- ],
435
374
  },
436
375
  {
437
376
  name: 'test',
@@ -451,11 +390,6 @@ Run comprehensive tests after the merge.
451
390
  ## Important
452
391
  - All tests must pass.
453
392
  - Test the interaction between merged features.`,
454
- acceptanceCriteria: criteria.length > 0 ? criteria : [
455
- 'All unit tests pass',
456
- 'Integration tests pass',
457
- 'No regressions',
458
- ],
459
393
  }
460
394
  );
461
395
  break;
@@ -468,9 +402,9 @@ function buildTasksFromOptions(
468
402
  options: PrepareOptions,
469
403
  laneNumber: number,
470
404
  featureName: string,
471
- hasDependencies: boolean = false
405
+ _hasDependencies: boolean = false
472
406
  ): Task[] {
473
- // Priority: --task > --preset/dependencies > --prompt alone > default
407
+ // Priority: --task > --preset > --prompt alone > default
474
408
 
475
409
  // 1. Explicit --task specifications (highest priority)
476
410
  if (options.taskSpecs.length > 0) {
@@ -481,18 +415,16 @@ function buildTasksFromOptions(
481
415
  return tasks;
482
416
  }
483
417
 
484
- // 2. Preset template (use when --preset specified OR lane has dependencies)
418
+ // 2. Preset template (use when --preset specified)
485
419
  // --prompt serves as context when used with preset
486
- if (options.preset || hasDependencies) {
487
- // Auto-apply merge preset if lane has dependencies and no explicit preset
488
- const preset = options.preset || (hasDependencies ? 'merge' : 'complex');
420
+ if (options.preset) {
489
421
  return buildTasksFromPreset(
490
- preset,
422
+ options.preset,
491
423
  featureName,
492
424
  laneNumber,
493
425
  options.prompt || `Implement ${featureName}`,
494
426
  options.criteria,
495
- hasDependencies
427
+ false
496
428
  );
497
429
  }
498
430
 
@@ -504,10 +436,6 @@ function buildTasksFromOptions(
504
436
  prompt: options.prompt,
505
437
  };
506
438
 
507
- if (options.criteria.length > 0) {
508
- task.acceptanceCriteria = options.criteria;
509
- }
510
-
511
439
  return [task];
512
440
  }
513
441
 
@@ -518,7 +446,7 @@ function buildTasksFromOptions(
518
446
  laneNumber,
519
447
  `Implement ${featureName}`,
520
448
  options.criteria,
521
- hasDependencies
449
+ false
522
450
  );
523
451
  }
524
452
 
@@ -538,11 +466,6 @@ function getDefaultConfig(laneNumber: number, featureName: string, tasks: Task[]
538
466
  lockfileReadOnly: true,
539
467
  },
540
468
 
541
- // Review Settings
542
- enableReview: true,
543
- reviewModel: 'sonnet-4.5-thinking',
544
- maxReviewIterations: 3,
545
-
546
469
  // Lane Metadata
547
470
  laneNumber: laneNumber,
548
471
  devPort: 3000 + laneNumber,
@@ -552,24 +475,6 @@ function getDefaultConfig(laneNumber: number, featureName: string, tasks: Task[]
552
475
  };
553
476
  }
554
477
 
555
- function parseDeps(depsStr: string): Map<number, number[]> {
556
- const map = new Map<number, number[]>();
557
- // Format: "2:1;3:1,2"
558
- const lanes = depsStr.split(';');
559
- for (const lane of lanes) {
560
- const [targetStr, depsPart] = lane.split(':');
561
- if (!targetStr || !depsPart) continue;
562
-
563
- const target = parseInt(targetStr);
564
- const deps = depsPart.split(',').map(d => parseInt(d)).filter(d => !isNaN(d));
565
-
566
- if (!isNaN(target) && deps.length > 0) {
567
- map.set(target, deps);
568
- }
569
- }
570
- return map;
571
- }
572
-
573
478
  function replacePlaceholders(obj: any, context: { featureName: string; laneNumber: number; devPort: number }): any {
574
479
  if (typeof obj === 'string') {
575
480
  return obj
@@ -626,8 +531,6 @@ async function addLaneToDir(options: PrepareOptions): Promise<void> {
626
531
  const fileName = `${laneNumber.toString().padStart(2, '0')}-${laneName}.json`;
627
532
  const filePath = safeJoin(taskDir, fileName);
628
533
 
629
- const hasDependencies = options.dependsOnLanes.length > 0;
630
-
631
534
  // Load template if provided
632
535
  let template = null;
633
536
  if (options.template) {
@@ -639,24 +542,18 @@ async function addLaneToDir(options: PrepareOptions): Promise<void> {
639
542
  if (template) {
640
543
  taskConfig = { ...template, laneNumber, devPort: 3000 + laneNumber };
641
544
  } else {
642
- // Build tasks from options (auto-detects merge preset if has dependencies)
643
- const tasks = buildTasksFromOptions(options, laneNumber, featureName, hasDependencies);
545
+ // Build tasks from options
546
+ const tasks = buildTasksFromOptions(options, laneNumber, featureName, false);
644
547
  taskConfig = getDefaultConfig(laneNumber, featureName, tasks);
645
548
  }
646
549
 
647
550
  // Replace placeholders
648
- const processedConfig = replacePlaceholders(taskConfig, {
551
+ const finalConfig = replacePlaceholders(taskConfig, {
649
552
  featureName,
650
553
  laneNumber,
651
554
  devPort: 3000 + laneNumber,
652
555
  });
653
556
 
654
- // Add dependencies if specified
655
- const finalConfig = {
656
- ...processedConfig,
657
- ...(hasDependencies ? { dependsOn: options.dependsOnLanes } : {}),
658
- };
659
-
660
557
  // Use atomic write with wx flag to avoid TOCTOU race condition (unless force is set)
661
558
  // SECURITY NOTE: Writing user-defined task configuration to the file system.
662
559
  // The input is from CLI arguments and templates, used to generate CursorFlow lane files.
@@ -672,10 +569,9 @@ async function addLaneToDir(options: PrepareOptions): Promise<void> {
672
569
 
673
570
  const tasksList = finalConfig.tasks || [];
674
571
  const taskSummary = tasksList.map((t: any) => t.name).join(' → ');
675
- const depsInfo = hasDependencies ? ` (depends: ${options.dependsOnLanes.join(', ')})` : '';
676
- const presetInfo = options.preset ? ` [${options.preset}]` : (hasDependencies ? ' [merge]' : (template ? ' [template]' : ''));
572
+ const presetInfo = options.preset ? ` [${options.preset}]` : (template ? ' [template]' : '');
677
573
 
678
- logger.success(`Added lane: ${fileName} [${taskSummary}]${presetInfo}${depsInfo}`);
574
+ logger.success(`Added lane: ${fileName} [${taskSummary}]${presetInfo}`);
679
575
  logger.info(`Directory: ${taskDir}`);
680
576
 
681
577
  console.log(`\nNext steps:`);
@@ -750,29 +646,17 @@ async function createNewFeature(options: PrepareOptions): Promise<void> {
750
646
  template = await resolveTemplate(options.template);
751
647
  }
752
648
 
753
- // Calculate dependencies
754
- const dependencyMap = options.sequential
755
- ? new Map(Array.from({ length: options.lanes - 1 }, (_, i) => [i + 2, [i + 1]]))
756
- : (options.deps ? parseDeps(options.deps) : new Map<number, number[]>());
757
-
758
- const laneInfoList: { name: string; fileName: string; dependsOn: string[]; preset: string }[] = [];
649
+ const laneInfoList: { name: string; fileName: string; preset: string }[] = [];
759
650
 
760
651
  for (let i = 1; i <= options.lanes; i++) {
761
652
  const laneName = `lane-${i}`;
762
653
  const fileName = `${i.toString().padStart(2, '0')}-${laneName}.json`;
763
654
  const filePath = safeJoin(taskDir, fileName);
764
655
 
765
- const depNums = dependencyMap.get(i) || [];
766
- const dependsOn = depNums.map(n => {
767
- const depLaneName = `lane-${n}`;
768
- return `${n.toString().padStart(2, '0')}-${depLaneName}`;
769
- });
770
-
771
- const hasDependencies = dependsOn.length > 0;
772
656
  const devPort = 3000 + i;
773
657
 
774
658
  let taskConfig;
775
- let effectivePreset: EffectivePresetType = options.preset || (hasDependencies ? 'merge' : 'complex');
659
+ let effectivePreset: EffectivePresetType = options.preset || 'complex';
776
660
 
777
661
  if (template) {
778
662
  // Use template
@@ -780,31 +664,25 @@ async function createNewFeature(options: PrepareOptions): Promise<void> {
780
664
  effectivePreset = 'custom';
781
665
  } else {
782
666
  // Build from CLI options
783
- const tasks = buildTasksFromOptions(options, i, options.featureName, hasDependencies);
667
+ const tasks = buildTasksFromOptions(options, i, options.featureName, false);
784
668
  taskConfig = getDefaultConfig(i, options.featureName, tasks);
785
669
  }
786
670
 
787
671
  // Replace placeholders
788
- const processedConfig = replacePlaceholders(taskConfig, {
672
+ const finalConfig = replacePlaceholders(taskConfig, {
789
673
  featureName: options.featureName,
790
674
  laneNumber: i,
791
675
  devPort: devPort,
792
676
  });
793
677
 
794
- // Add dependencies if any
795
- const finalConfig = {
796
- ...processedConfig,
797
- ...(dependsOn.length > 0 ? { dependsOn } : {}),
798
- };
799
-
800
678
  // SECURITY NOTE: Writing generated lane configuration (containing user prompts) to file system.
801
679
  fs.writeFileSync(filePath, JSON.stringify(finalConfig, null, 2) + '\n', 'utf8');
802
680
 
803
681
  const taskSummary = finalConfig.tasks?.map((t: any) => t.name).join(' → ') || 'default';
804
682
  const presetLabel = effectivePreset !== 'custom' ? ` [${effectivePreset}]` : '';
805
- logger.success(`Created: ${fileName} [${taskSummary}]${presetLabel}${dependsOn.length > 0 ? ` (depends: ${dependsOn.join(', ')})` : ''}`);
683
+ logger.success(`Created: ${fileName} [${taskSummary}]${presetLabel}`);
806
684
 
807
- laneInfoList.push({ name: laneName, fileName, dependsOn, preset: effectivePreset });
685
+ laneInfoList.push({ name: laneName, fileName, preset: effectivePreset });
808
686
  }
809
687
 
810
688
  // Create README
@@ -826,14 +704,29 @@ cursorflow run ${path.relative(config.projectRoot, taskDir)}
826
704
 
827
705
  ## Lanes
828
706
 
829
- ${laneInfoList.map(l => `- **${l.fileName.replace('.json', '')}** [${l.preset}]${l.dependsOn.length > 0 ? ` (depends: ${l.dependsOn.join(', ')})` : ''}`).join('\n')}
707
+ ${laneInfoList.map(l => `- **${l.fileName.replace('.json', '')}** [${l.preset}]`).join('\n')}
708
+
709
+ ## Task-Level Dependencies
710
+
711
+ To make a task wait for another task to complete before starting, use the \`dependsOn\` field:
712
+
713
+ \`\`\`json
714
+ {
715
+ "tasks": [
716
+ {
717
+ "name": "my-task",
718
+ "prompt": "...",
719
+ "dependsOn": ["other-lane:other-task"]
720
+ }
721
+ ]
722
+ }
723
+ \`\`\`
830
724
 
831
725
  ## Modifying Tasks
832
726
 
833
727
  \`\`\`bash
834
- # Add a new lane (with merge preset for dependent lanes)
835
- cursorflow prepare --add-lane ${path.relative(config.projectRoot, taskDir)} \\
836
- --preset merge --depends-on "01-lane-1"
728
+ # Add a new lane
729
+ cursorflow prepare --add-lane ${path.relative(config.projectRoot, taskDir)} --preset complex
837
730
 
838
731
  # Add task to existing lane
839
732
  cursorflow prepare --add-task ${path.relative(config.projectRoot, taskDir)}/01-lane-1.json \\