@litmers/cursorflow-orchestrator 0.1.39 → 0.2.2

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 (214) hide show
  1. package/CHANGELOG.md +0 -2
  2. package/README.md +20 -16
  3. package/commands/cursorflow-init.md +0 -4
  4. package/dist/cli/logs.js +108 -9
  5. package/dist/cli/logs.js.map +1 -1
  6. package/dist/cli/models.js +20 -3
  7. package/dist/cli/models.js.map +1 -1
  8. package/dist/cli/monitor.d.ts +7 -10
  9. package/dist/cli/monitor.js +1088 -1240
  10. package/dist/cli/monitor.js.map +1 -1
  11. package/dist/cli/prepare.js +0 -1
  12. package/dist/cli/prepare.js.map +1 -1
  13. package/dist/cli/resume.js +23 -5
  14. package/dist/cli/resume.js.map +1 -1
  15. package/dist/cli/run.js +28 -9
  16. package/dist/cli/run.js.map +1 -1
  17. package/dist/cli/signal.d.ts +6 -1
  18. package/dist/cli/signal.js +94 -12
  19. package/dist/cli/signal.js.map +1 -1
  20. package/dist/cli/tasks.js +3 -46
  21. package/dist/cli/tasks.js.map +1 -1
  22. package/dist/core/agent-supervisor.d.ts +23 -0
  23. package/dist/core/agent-supervisor.js +42 -0
  24. package/dist/core/agent-supervisor.js.map +1 -0
  25. package/dist/core/auto-recovery.d.ts +2 -1
  26. package/dist/core/auto-recovery.js +6 -1
  27. package/dist/core/auto-recovery.js.map +1 -1
  28. package/dist/core/failure-policy.d.ts +0 -1
  29. package/dist/core/failure-policy.js +0 -1
  30. package/dist/core/failure-policy.js.map +1 -1
  31. package/dist/core/git-lifecycle-manager.d.ts +284 -0
  32. package/dist/core/git-lifecycle-manager.js +778 -0
  33. package/dist/core/git-lifecycle-manager.js.map +1 -0
  34. package/dist/core/git-pipeline-coordinator.d.ts +21 -0
  35. package/dist/core/git-pipeline-coordinator.js +205 -0
  36. package/dist/core/git-pipeline-coordinator.js.map +1 -0
  37. package/dist/core/intervention.d.ts +176 -0
  38. package/dist/core/intervention.js +424 -0
  39. package/dist/core/intervention.js.map +1 -0
  40. package/dist/core/lane-state-machine.d.ts +423 -0
  41. package/dist/core/lane-state-machine.js +890 -0
  42. package/dist/core/lane-state-machine.js.map +1 -0
  43. package/dist/core/orchestrator.d.ts +4 -1
  44. package/dist/core/orchestrator.js +38 -63
  45. package/dist/core/orchestrator.js.map +1 -1
  46. package/dist/core/runner/agent.d.ts +7 -1
  47. package/dist/core/runner/agent.js +45 -30
  48. package/dist/core/runner/agent.js.map +1 -1
  49. package/dist/core/runner/pipeline.js +283 -109
  50. package/dist/core/runner/pipeline.js.map +1 -1
  51. package/dist/core/runner/task.d.ts +4 -5
  52. package/dist/core/runner/task.js +6 -77
  53. package/dist/core/runner/task.js.map +1 -1
  54. package/dist/core/runner.js +11 -2
  55. package/dist/core/runner.js.map +1 -1
  56. package/dist/core/stall-detection.d.ts +27 -4
  57. package/dist/core/stall-detection.js +116 -28
  58. package/dist/core/stall-detection.js.map +1 -1
  59. package/dist/hooks/contexts/index.d.ts +104 -0
  60. package/dist/hooks/contexts/index.js +134 -0
  61. package/dist/hooks/contexts/index.js.map +1 -0
  62. package/dist/hooks/data-accessor.d.ts +86 -0
  63. package/dist/hooks/data-accessor.js +410 -0
  64. package/dist/hooks/data-accessor.js.map +1 -0
  65. package/dist/hooks/flow-controller.d.ts +136 -0
  66. package/dist/hooks/flow-controller.js +351 -0
  67. package/dist/hooks/flow-controller.js.map +1 -0
  68. package/dist/hooks/index.d.ts +68 -0
  69. package/dist/hooks/index.js +105 -0
  70. package/dist/hooks/index.js.map +1 -0
  71. package/dist/hooks/manager.d.ts +129 -0
  72. package/dist/hooks/manager.js +389 -0
  73. package/dist/hooks/manager.js.map +1 -0
  74. package/dist/hooks/types.d.ts +463 -0
  75. package/dist/hooks/types.js +45 -0
  76. package/dist/hooks/types.js.map +1 -0
  77. package/dist/services/logging/buffer.d.ts +2 -2
  78. package/dist/services/logging/buffer.js +95 -42
  79. package/dist/services/logging/buffer.js.map +1 -1
  80. package/dist/services/logging/console.js +8 -5
  81. package/dist/services/logging/console.js.map +1 -1
  82. package/dist/services/logging/formatter.d.ts +9 -3
  83. package/dist/services/logging/formatter.js +64 -17
  84. package/dist/services/logging/formatter.js.map +1 -1
  85. package/dist/services/logging/index.d.ts +0 -1
  86. package/dist/services/logging/index.js +0 -1
  87. package/dist/services/logging/index.js.map +1 -1
  88. package/dist/services/logging/paths.d.ts +8 -0
  89. package/dist/services/logging/paths.js +48 -0
  90. package/dist/services/logging/paths.js.map +1 -0
  91. package/dist/services/logging/raw-log.d.ts +6 -0
  92. package/dist/services/logging/raw-log.js +37 -0
  93. package/dist/services/logging/raw-log.js.map +1 -0
  94. package/dist/services/process/index.js +1 -1
  95. package/dist/services/process/index.js.map +1 -1
  96. package/dist/types/agent.d.ts +15 -0
  97. package/dist/types/config.d.ts +24 -1
  98. package/dist/types/event-categories.d.ts +601 -0
  99. package/dist/types/event-categories.js +233 -0
  100. package/dist/types/event-categories.js.map +1 -0
  101. package/dist/types/events.d.ts +0 -20
  102. package/dist/types/flow.d.ts +10 -6
  103. package/dist/types/index.d.ts +1 -1
  104. package/dist/types/index.js +17 -3
  105. package/dist/types/index.js.map +1 -1
  106. package/dist/types/lane.d.ts +1 -1
  107. package/dist/types/logging.d.ts +1 -1
  108. package/dist/types/task.d.ts +13 -2
  109. package/dist/ui/log-viewer.d.ts +3 -0
  110. package/dist/ui/log-viewer.js +3 -0
  111. package/dist/ui/log-viewer.js.map +1 -1
  112. package/dist/utils/config.js +15 -1
  113. package/dist/utils/config.js.map +1 -1
  114. package/dist/utils/cursor-agent.d.ts +11 -1
  115. package/dist/utils/cursor-agent.js +63 -16
  116. package/dist/utils/cursor-agent.js.map +1 -1
  117. package/dist/utils/enhanced-logger.d.ts +5 -1
  118. package/dist/utils/enhanced-logger.js +99 -20
  119. package/dist/utils/enhanced-logger.js.map +1 -1
  120. package/dist/utils/event-registry.d.ts +222 -0
  121. package/dist/utils/event-registry.js +463 -0
  122. package/dist/utils/event-registry.js.map +1 -0
  123. package/dist/utils/events.d.ts +1 -13
  124. package/dist/utils/events.js.map +1 -1
  125. package/dist/utils/flow.d.ts +10 -0
  126. package/dist/utils/flow.js +75 -0
  127. package/dist/utils/flow.js.map +1 -1
  128. package/dist/utils/git.d.ts +12 -1
  129. package/dist/utils/git.js +54 -1
  130. package/dist/utils/git.js.map +1 -1
  131. package/dist/utils/log-constants.d.ts +1 -0
  132. package/dist/utils/log-constants.js +2 -1
  133. package/dist/utils/log-constants.js.map +1 -1
  134. package/dist/utils/log-formatter.d.ts +3 -2
  135. package/dist/utils/log-formatter.js +11 -11
  136. package/dist/utils/log-formatter.js.map +1 -1
  137. package/dist/utils/logger.d.ts +11 -0
  138. package/dist/utils/logger.js +82 -3
  139. package/dist/utils/logger.js.map +1 -1
  140. package/dist/utils/repro-thinking-logs.js +0 -13
  141. package/dist/utils/repro-thinking-logs.js.map +1 -1
  142. package/dist/utils/run-service.js +1 -1
  143. package/dist/utils/run-service.js.map +1 -1
  144. package/examples/README.md +0 -2
  145. package/examples/demo-project/README.md +1 -2
  146. package/package.json +18 -28
  147. package/scripts/setup-security.sh +0 -1
  148. package/scripts/test-log-parser.ts +171 -0
  149. package/scripts/verify-change.sh +272 -0
  150. package/src/cli/logs.ts +121 -10
  151. package/src/cli/models.ts +20 -3
  152. package/src/cli/monitor.ts +1257 -1342
  153. package/src/cli/prepare.ts +0 -1
  154. package/src/cli/resume.ts +29 -5
  155. package/src/cli/run.ts +29 -11
  156. package/src/cli/signal.ts +115 -17
  157. package/src/cli/tasks.ts +2 -59
  158. package/src/core/agent-supervisor.ts +64 -0
  159. package/src/core/auto-recovery.ts +7 -1
  160. package/src/core/failure-policy.ts +0 -1
  161. package/src/core/git-lifecycle-manager.ts +1011 -0
  162. package/src/core/git-pipeline-coordinator.ts +221 -0
  163. package/src/core/intervention.ts +481 -0
  164. package/src/core/lane-state-machine.ts +1097 -0
  165. package/src/core/orchestrator.ts +45 -62
  166. package/src/core/runner/agent.ts +66 -33
  167. package/src/core/runner/pipeline.ts +318 -122
  168. package/src/core/runner/task.ts +12 -93
  169. package/src/core/runner.ts +12 -2
  170. package/src/core/stall-detection.ts +145 -28
  171. package/src/hooks/contexts/index.ts +256 -0
  172. package/src/hooks/data-accessor.ts +488 -0
  173. package/src/hooks/flow-controller.ts +425 -0
  174. package/src/hooks/index.ts +154 -0
  175. package/src/hooks/manager.ts +434 -0
  176. package/src/hooks/types.ts +544 -0
  177. package/src/services/logging/buffer.ts +104 -43
  178. package/src/services/logging/console.ts +9 -5
  179. package/src/services/logging/formatter.ts +74 -17
  180. package/src/services/logging/index.ts +0 -2
  181. package/src/services/logging/paths.ts +14 -0
  182. package/src/services/logging/raw-log.ts +43 -0
  183. package/src/services/process/index.ts +1 -1
  184. package/src/types/agent.ts +15 -0
  185. package/src/types/config.ts +25 -1
  186. package/src/types/event-categories.ts +663 -0
  187. package/src/types/events.ts +0 -25
  188. package/src/types/flow.ts +10 -6
  189. package/src/types/index.ts +50 -4
  190. package/src/types/lane.ts +1 -2
  191. package/src/types/logging.ts +2 -1
  192. package/src/types/task.ts +13 -2
  193. package/src/ui/log-viewer.ts +3 -0
  194. package/src/utils/config.ts +17 -1
  195. package/src/utils/cursor-agent.ts +68 -16
  196. package/src/utils/enhanced-logger.ts +106 -20
  197. package/src/utils/event-registry.ts +595 -0
  198. package/src/utils/events.ts +0 -16
  199. package/src/utils/flow.ts +84 -0
  200. package/src/utils/git.ts +59 -1
  201. package/src/utils/log-constants.ts +2 -1
  202. package/src/utils/log-formatter.ts +11 -12
  203. package/src/utils/logger.ts +49 -3
  204. package/src/utils/repro-thinking-logs.ts +0 -15
  205. package/src/utils/run-service.ts +1 -1
  206. package/dist/services/logging/file-writer.d.ts +0 -71
  207. package/dist/services/logging/file-writer.js +0 -516
  208. package/dist/services/logging/file-writer.js.map +0 -1
  209. package/dist/types/review.d.ts +0 -17
  210. package/dist/types/review.js +0 -6
  211. package/dist/types/review.js.map +0 -1
  212. package/scripts/ai-security-check.js +0 -233
  213. package/src/services/logging/file-writer.ts +0 -526
  214. package/src/types/review.ts +0 -20
@@ -27,12 +27,58 @@ export {
27
27
  // Agent
28
28
  export * from './agent';
29
29
 
30
- // Review
31
- export * from './review';
32
-
33
- // Events
30
+ // Events (기존 - 호환성 유지)
34
31
  export * from './events';
35
32
 
33
+ // Event Categories (v2.1 - 카테고리별 분류, 새 아키텍처)
34
+ // 중복 이름은 명시적으로 제외하고 새 카테고리 관련 타입만 export
35
+ export {
36
+ // Event Categories
37
+ EventCategory,
38
+
39
+ // Event Type Enums
40
+ OrchestrationEventType,
41
+ LaneEventType,
42
+ TaskEventType,
43
+ GitEventType,
44
+ RecoveryEventType,
45
+ AgentEventType,
46
+ StateEventType,
47
+ SystemEventType,
48
+ AllEventTypes,
49
+
50
+ // Event Payload Map & Typed Event
51
+ EventPayloadMap,
52
+ TypedCursorFlowEvent,
53
+ TypedEventHandler,
54
+ GenericEventHandler,
55
+ getCategoryFromEventType,
56
+
57
+ // New Payload Types (이름 충돌 없는 것들)
58
+ CycleDetectedPayload,
59
+ LaneWaitingPayload,
60
+ LaneBlockedPayload,
61
+ TaskRetryPayload,
62
+ TaskWaitingDependencyPayload,
63
+ GitBranchCreatedPayload,
64
+ GitCommittedPayload,
65
+ GitPushedPayload,
66
+ GitMergeStartedPayload,
67
+ GitMergeCompletedPayload,
68
+ GitMergeConflictPayload,
69
+ GitPushRejectedPayload,
70
+ GitErrorPayload,
71
+ RecoveryStartedPayload,
72
+ RecoveryConflictResolvedPayload,
73
+ AgentConnectionErrorPayload,
74
+ StateTransitionPayload,
75
+ StateTransitionFailedPayload,
76
+ StateCorruptedPayload,
77
+ StateRepairedPayload,
78
+ SystemHealthCheckPayload,
79
+ SystemSignalReceivedPayload,
80
+ } from './event-categories';
81
+
36
82
  // Logging
37
83
  export * from './logging';
38
84
 
package/src/types/lane.ts CHANGED
@@ -10,8 +10,7 @@ export type LaneStatus =
10
10
  | 'completed'
11
11
  | 'failed'
12
12
  | 'paused'
13
- | 'waiting'
14
- | 'reviewing';
13
+ | 'waiting';
15
14
 
16
15
  export interface LaneInfo {
17
16
  name: string;
@@ -26,7 +26,8 @@ export type MessageType =
26
26
  | 'debug'
27
27
  | 'progress'
28
28
  | 'stdout'
29
- | 'stderr';
29
+ | 'stderr'
30
+ | 'raw'; // Pre-formatted output that should be printed as-is
30
31
 
31
32
  export interface ParsedMessage {
32
33
  type: MessageType;
package/src/types/task.ts CHANGED
@@ -13,6 +13,8 @@ export interface Task {
13
13
  dependsOn?: string[];
14
14
  /** Task execution timeout in milliseconds. Overrides lane-level timeout. */
15
15
  timeout?: number;
16
+ /** Enable browser automation for this task. Required for web testing/scraping. */
17
+ browser?: boolean;
16
18
  }
17
19
 
18
20
  export interface RunnerConfig {
@@ -26,13 +28,13 @@ export interface RunnerConfig {
26
28
  model?: string;
27
29
  dependencyPolicy: DependencyPolicy;
28
30
  /** Output format for cursor-agent (default: 'json') */
29
- agentOutputFormat?: 'json' | 'plain' | 'stream-json';
31
+ agentOutputFormat?: 'json' | 'stream-json';
30
32
  /** Task execution timeout in milliseconds. Default: 600000 (10 minutes) */
31
33
  timeout?: number;
32
34
  /**
33
35
  * Enable intervention feature (stdin piping for message injection).
34
36
  * Warning: May cause stdout buffering issues on some systems.
35
- * Default: false
37
+ * Default: true
36
38
  */
37
39
  enableIntervention?: boolean;
38
40
  /**
@@ -40,6 +42,15 @@ export interface RunnerConfig {
40
42
  * Default: false
41
43
  */
42
44
  verboseGit?: boolean;
45
+ /**
46
+ * Enable browser automation for all tasks in this config.
47
+ * Required for web testing/scraping.
48
+ */
49
+ browser?: boolean;
50
+ /** Auto-approve commands (--force flag). Default: true */
51
+ autoApproveCommands?: boolean;
52
+ /** Auto-approve MCP servers (--approve-mcps flag). Default: true */
53
+ autoApproveMcps?: boolean;
43
54
  }
44
55
 
45
56
  export interface TaskDirInfo {
@@ -8,6 +8,9 @@
8
8
  * - Importance filtering
9
9
  * - Text search
10
10
  * - Readable format toggle
11
+ *
12
+ * Note: This viewer only reads lane/subprocess logs. Main process logs are
13
+ * written to the run-level main log file and shown by default in CLI logs.
11
14
  */
12
15
 
13
16
  import * as readline from 'readline';
@@ -60,6 +60,9 @@ export function loadConfig(projectRoot: string | null = null): CursorFlowConfig
60
60
  allowDependencyChange: false,
61
61
  lockfileReadOnly: true,
62
62
 
63
+ // Intervention
64
+ enableIntervention: true,
65
+
63
66
  // Lane defaults
64
67
  defaultLaneConfig: {
65
68
  devPort: 3001,
@@ -93,6 +96,11 @@ export function loadConfig(projectRoot: string | null = null): CursorFlowConfig
93
96
  // Default AI model
94
97
  defaultModel: 'gemini-3-flash',
95
98
 
99
+ // Agent execution flags (cursor-agent CLI options)
100
+ autoApproveCommands: true, // --force flag
101
+ autoApproveMcps: true, // --approve-mcps flag
102
+ browser: true, // --browser flag
103
+
96
104
  // Internal
97
105
  projectRoot,
98
106
  };
@@ -193,6 +201,9 @@ export function createDefaultConfig(projectRoot: string, force = false): string
193
201
  allowDependencyChange: false,
194
202
  lockfileReadOnly: true,
195
203
 
204
+ // Intervention - allows sending messages to running agents
205
+ enableIntervention: true,
206
+
196
207
  // Lane configuration
197
208
  defaultLaneConfig: {
198
209
  devPort: 3001, // 3000 + laneNumber
@@ -206,7 +217,7 @@ export function createDefaultConfig(projectRoot: string, force = false): string
206
217
  // Advanced
207
218
  worktreePrefix: 'cursorflow-',
208
219
  maxConcurrentLanes: 10,
209
- agentOutputFormat: 'json', // 'json' | 'plain'
220
+ agentOutputFormat: 'stream-json', // 'json' | 'stream-json'
210
221
 
211
222
  // Webhook configuration
212
223
  // webhooks: [
@@ -228,6 +239,11 @@ export function createDefaultConfig(projectRoot: string, force = false): string
228
239
  writeJsonLog: true, // Write structured JSON logs
229
240
  timestampFormat: 'iso', // 'iso' | 'relative' | 'short'
230
241
  },
242
+
243
+ // Agent execution flags (cursor-agent CLI options)
244
+ autoApproveCommands: true, // --force flag
245
+ autoApproveMcps: true, // --approve-mcps flag
246
+ browser: false, // --browser flag
231
247
  };
232
248
  `;
233
249
 
@@ -110,19 +110,45 @@ export function validateSetup(executor = 'cursor-agent'): { valid: boolean; erro
110
110
  };
111
111
  }
112
112
 
113
+ /**
114
+ * Known models in cursor-agent (2025.12 version)
115
+ * Reference: docs/CURSOR_AGENT_GUIDE.md
116
+ */
117
+ export const KNOWN_MODELS = [
118
+ // Special modes
119
+ 'composer-1',
120
+ 'auto',
121
+ // Anthropic Claude models
122
+ 'sonnet-4.5',
123
+ 'sonnet-4.5-thinking',
124
+ 'opus-4.5',
125
+ 'opus-4.5-thinking',
126
+ 'opus-4.1',
127
+ // Google Gemini models
128
+ 'gemini-3-flash',
129
+ 'gemini-3-pro',
130
+ // OpenAI GPT models
131
+ 'gpt-5.2',
132
+ 'gpt-5.2-high',
133
+ 'gpt-5.1',
134
+ 'gpt-5.1-high',
135
+ // OpenAI Codex models
136
+ 'gpt-5.1-codex',
137
+ 'gpt-5.1-codex-high',
138
+ 'gpt-5.1-codex-max',
139
+ 'gpt-5.1-codex-max-high',
140
+ // xAI
141
+ 'grok',
142
+ ] as const;
143
+
144
+ export type KnownModel = typeof KNOWN_MODELS[number];
145
+
113
146
  /**
114
147
  * Get available models (if cursor-agent supports it)
115
148
  */
116
149
  export function getAvailableModels(): string[] {
117
- // Known models in the current version of cursor-agent
118
- const knownModels = [
119
- 'sonnet-4.5',
120
- 'sonnet-4.5-thinking',
121
- 'opus-4.5',
122
- 'opus-4.5-thinking',
123
- 'gpt-5.2',
124
- 'gpt-5.2-high',
125
- ];
150
+ // Use the known models list
151
+ const knownModels = [...KNOWN_MODELS];
126
152
 
127
153
  try {
128
154
  // Try to trigger a model list by using an invalid model with --print
@@ -236,34 +262,49 @@ export interface AuthCheckResult {
236
262
  }
237
263
 
238
264
  /**
239
- * Check cursor-agent authentication
265
+ * Check cursor-agent authentication using status/whoami command
266
+ * This is faster and has no side effects (unlike create-chat which creates a session)
267
+ *
268
+ * Reference: docs/CURSOR_AGENT_GUIDE.md
269
+ * Expected output: " ✓ Logged in as user@email.com"
240
270
  */
241
271
  export function checkCursorAuth(): AuthCheckResult {
242
272
  try {
243
- const result = spawnSync('cursor-agent', ['create-chat'], {
273
+ // Use 'status' command (or 'whoami' alias) - faster than create-chat
274
+ const result = spawnSync('cursor-agent', ['status'], {
244
275
  encoding: 'utf8',
245
276
  stdio: 'pipe',
246
277
  timeout: 10000, // 10 second timeout
247
278
  });
248
279
 
249
- if (result.status === 0 && result.stdout.trim()) {
280
+ const output = (result.stdout?.trim() || '').toString();
281
+ const errorOutput = (result.stderr?.trim() || '').toString();
282
+
283
+ // Check for successful login (output contains "Logged in as")
284
+ if (result.status === 0 && output.includes('Logged in')) {
285
+ // Extract email if present
286
+ const emailMatch = output.match(/Logged in as\s+(\S+)/i);
287
+ const email = emailMatch ? emailMatch[1] : undefined;
288
+
250
289
  return {
251
290
  authenticated: true,
252
291
  message: 'Cursor authentication OK',
292
+ details: email ? `Logged in as ${email}` : undefined,
253
293
  };
254
294
  }
255
295
 
256
- const errorMsg = (result.stderr?.trim() || result.stdout?.trim() || '').toString();
296
+ const errorMsg = errorOutput || output;
257
297
 
258
298
  // Check for authentication errors
259
299
  if (errorMsg.includes('not authenticated') ||
300
+ errorMsg.includes('not logged') ||
260
301
  errorMsg.includes('login') ||
261
302
  errorMsg.includes('auth')) {
262
303
  return {
263
304
  authenticated: false,
264
305
  message: 'Not authenticated with Cursor',
265
306
  details: errorMsg,
266
- help: 'Please open Cursor IDE and sign in to your account',
307
+ help: 'Run: cursor-agent login',
267
308
  };
268
309
  }
269
310
 
@@ -279,13 +320,24 @@ export function checkCursorAuth(): AuthCheckResult {
279
320
  };
280
321
  }
281
322
 
323
+ // If status command failed but no specific error, might still be authenticated
324
+ // Fall back to checking if cursor-agent is responsive
325
+ if (result.status !== 0) {
326
+ return {
327
+ authenticated: false,
328
+ message: 'Authentication status check failed',
329
+ details: errorMsg || `Exit code: ${result.status}`,
330
+ help: 'Try running: cursor-agent status',
331
+ };
332
+ }
333
+
282
334
  return {
283
335
  authenticated: false,
284
- message: 'Unknown error',
336
+ message: 'Unknown authentication status',
285
337
  details: errorMsg,
286
338
  };
287
339
  } catch (error: any) {
288
- if (error.code === 'ETIMEDOUT') {
340
+ if (error.code === 'ETIMEDOUT' || error.killed) {
289
341
  return {
290
342
  authenticated: false,
291
343
  message: 'Connection timeout',
@@ -11,6 +11,7 @@ import * as path from 'path';
11
11
  import { EnhancedLogConfig, ParsedMessage, LogSession } from '../types';
12
12
  import { formatMessageForConsole } from './log-formatter';
13
13
  import { safeJoin } from './path';
14
+ import { getLaneLogPath } from '../services/logging/paths';
14
15
 
15
16
  export { EnhancedLogConfig, ParsedMessage, LogSession };
16
17
 
@@ -115,9 +116,11 @@ export class EnhancedLogManager {
115
116
  // Ensure log directory exists
116
117
  fs.mkdirSync(logDir, { recursive: true });
117
118
 
119
+ // Subprocess (lane) logs live in the lane run directory to avoid nesting with main logs.
120
+ // Main process logs are written separately to a run-level file (see utils/logger.ts).
118
121
  // Set up log file paths (simplified)
119
- this.rawLogPath = safeJoin(logDir, 'terminal-raw.log');
120
- this.readableLogPath = safeJoin(logDir, 'terminal-readable.log');
122
+ this.rawLogPath = getLaneLogPath(logDir, 'raw');
123
+ this.readableLogPath = getLaneLogPath(logDir, 'readable');
121
124
 
122
125
  // Initialize log files
123
126
  this.initLogFiles();
@@ -131,13 +134,13 @@ export class EnhancedLogManager {
131
134
  }
132
135
 
133
136
  /**
134
- * Get lane-task label like [L1-T2-lanename10]
137
+ * Get lane-task label like [1-1-refactor]
135
138
  */
136
139
  private getLaneTaskLabel(): string {
137
140
  const laneNum = (this.session.laneIndex ?? 0) + 1;
138
141
  const taskNum = (this.session.taskIndex ?? 0) + 1;
139
- const shortLaneName = this.session.laneName.substring(0, 10);
140
- return `L${laneNum}-T${taskNum}-${shortLaneName}`;
142
+ const shortLaneName = this.session.laneName.substring(0, 8);
143
+ return `${laneNum}-${taskNum}-${shortLaneName}`;
141
144
  }
142
145
 
143
146
  /**
@@ -267,7 +270,7 @@ export class EnhancedLogManager {
267
270
  */
268
271
  public writeReadableMessage(msg: ParsedMessage): void {
269
272
  // Use formatMessageForConsole for consistent formatting
270
- // Use short lane-task label like [L01-T02]
273
+ // Use short lane-task label like [1-1-lanename10]
271
274
  const formatted = formatMessageForConsole(msg, {
272
275
  laneLabel: `[${this.getLaneTaskLabel()}]`,
273
276
  includeTimestamp: false, // We'll add our own short timestamp
@@ -308,6 +311,17 @@ export class EnhancedLogManager {
308
311
  this.writeReadableMessage(msg);
309
312
  continue;
310
313
  }
314
+ // parseJsonToMessage returned null - create fallback message for known JSON
315
+ if (json.type) {
316
+ const fallbackMsg: ParsedMessage = {
317
+ type: 'info',
318
+ role: 'system',
319
+ content: `[${json.type}] ${json.subtype || ''} ${JSON.stringify(json).substring(0, 150)}...`,
320
+ timestamp: json.timestamp_ms || Date.now(),
321
+ };
322
+ this.writeReadableMessage(fallbackMsg);
323
+ continue;
324
+ }
311
325
  } catch {
312
326
  // Not valid JSON, fall through
313
327
  }
@@ -318,16 +332,38 @@ export class EnhancedLogManager {
318
332
  if (cleanLine && !this.isNoiseLog(cleanLine)) {
319
333
  const hasTimestamp = /^\[(\d{4}-\d{2}-\d{2}T|\d{2}:\d{2}:\d{2})\]/.test(cleanLine);
320
334
  const label = this.getLaneTaskLabel();
335
+ const ts = this.getShortTime();
321
336
 
337
+ // For file output, use clean line (no ANSI codes)
338
+ let fileFormattedLine: string;
322
339
  if (hasTimestamp) {
323
- // If already has timestamp, just ensure label is present
324
- const formatted = cleanLine.includes(`[${label}]`)
340
+ fileFormattedLine = cleanLine.includes(`[${label}]`)
325
341
  ? cleanLine
326
342
  : cleanLine.replace(/^(\[[^\]]+\])/, `$1 [${label}]`);
327
- this.writeToReadableLog(`${formatted}\n`);
328
343
  } else {
329
- const ts = this.getShortTime();
330
- this.writeToReadableLog(`[${ts}] [${label}] ${cleanLine}\n`);
344
+ fileFormattedLine = `[${ts}] [${label}] ${cleanLine}`;
345
+ }
346
+
347
+ this.writeToReadableLog(`${fileFormattedLine}\n`);
348
+
349
+ // For console output, preserve ANSI colors from original line
350
+ if (this.onParsedMessage) {
351
+ let consoleFormattedLine: string;
352
+ if (hasTimestamp) {
353
+ consoleFormattedLine = trimmed.includes(`[${label}]`)
354
+ ? trimmed
355
+ : trimmed.replace(/^(\[[^\]]+\])/, `$1 [${label}]`);
356
+ } else {
357
+ consoleFormattedLine = `[${ts}] [${label}] ${trimmed}`;
358
+ }
359
+
360
+ const rawMsg: ParsedMessage = {
361
+ type: 'raw',
362
+ role: 'system',
363
+ content: consoleFormattedLine,
364
+ timestamp: Date.now(),
365
+ };
366
+ this.onParsedMessage(rawMsg);
331
367
  }
332
368
  }
333
369
  }
@@ -426,6 +462,15 @@ export class EnhancedLogManager {
426
462
  return null;
427
463
 
428
464
  default:
465
+ // Fallback: show unknown JSON types with basic formatting
466
+ if (type) {
467
+ return {
468
+ type: 'info',
469
+ role: 'system',
470
+ content: `[${type}] ${JSON.stringify(json).substring(0, 200)}`,
471
+ timestamp,
472
+ };
473
+ }
429
474
  return null;
430
475
  }
431
476
  }
@@ -439,27 +484,68 @@ export class EnhancedLogManager {
439
484
  // Write raw log
440
485
  this.writeToRawLog(data);
441
486
 
442
- // Write to readable log with error prefix
487
+ // Write to readable log - treat stderr same as stdout
488
+ // Git and many tools use stderr for non-error output
443
489
  const lines = text.split('\n');
444
490
  for (const line of lines) {
445
491
  const cleanLine = stripAnsi(line).trim();
446
492
  if (cleanLine && !this.isNoiseLog(cleanLine)) {
447
493
  const hasTimestamp = /^\[(\d{4}-\d{2}-\d{2}T|\d{2}:\d{2}:\d{2})\]/.test(cleanLine);
448
494
  const label = this.getLaneTaskLabel();
495
+ const ts = this.getShortTime();
449
496
 
497
+ // Determine if this is actually an error message
498
+ const isError = this.isErrorLine(cleanLine);
499
+ const prefix = isError ? '❌ ERR' : '';
500
+
501
+ let formattedLine: string;
450
502
  if (hasTimestamp) {
451
- const formatted = cleanLine.includes(`[${label}]`)
503
+ formattedLine = cleanLine.includes(`[${label}]`)
452
504
  ? cleanLine
453
- : cleanLine.replace(/^(\[[^\]]+\])/, `$1 [${label}] ERR`);
454
- this.writeToReadableLog(`${formatted}\n`);
505
+ : cleanLine.replace(/^(\[[^\]]+\])/, `$1 [${label}]${prefix ? ' ' + prefix : ''}`);
455
506
  } else {
456
- const ts = this.getShortTime();
457
- this.writeToReadableLog(`[${ts}] [${label}] ERR ${cleanLine}\n`);
507
+ formattedLine = prefix
508
+ ? `[${ts}] [${label}] ${prefix} ${cleanLine}`
509
+ : `[${ts}] [${label}] ${cleanLine}`;
510
+ }
511
+
512
+ this.writeToReadableLog(`${formattedLine}\n`);
513
+
514
+ // Output to console
515
+ if (this.onParsedMessage) {
516
+ const rawMsg: ParsedMessage = {
517
+ type: 'raw',
518
+ role: 'system',
519
+ content: formattedLine,
520
+ timestamp: Date.now(),
521
+ };
522
+ this.onParsedMessage(rawMsg);
458
523
  }
459
524
  }
460
525
  }
461
526
  }
462
527
 
528
+ /**
529
+ * Check if a line is actually an error message
530
+ */
531
+ private isErrorLine(text: string): boolean {
532
+ const errorPatterns = [
533
+ /^error:/i,
534
+ /^fatal:/i,
535
+ /^panic:/i,
536
+ /\berror\b.*:/i,
537
+ /\bfailed\b/i,
538
+ /\bexception\b/i,
539
+ /^ENOENT:/i,
540
+ /^EACCES:/i,
541
+ /^EPERM:/i,
542
+ /^ERR!/i,
543
+ /npm ERR!/i,
544
+ ];
545
+
546
+ return errorPatterns.some(p => p.test(text));
547
+ }
548
+
463
549
  /**
464
550
  * Write a custom log entry
465
551
  */
@@ -644,12 +730,12 @@ export function exportLogs(
644
730
  format: 'text' | 'json' | 'markdown' | 'html',
645
731
  outputPath?: string
646
732
  ): string {
647
- const readableLogPath = safeJoin(laneRunDir, 'terminal-readable.log');
733
+ const logPath = getLaneLogPath(laneRunDir, 'raw');
648
734
 
649
735
  let output = '';
650
736
 
651
- if (fs.existsSync(readableLogPath)) {
652
- output = fs.readFileSync(readableLogPath, 'utf8');
737
+ if (fs.existsSync(logPath)) {
738
+ output = fs.readFileSync(logPath, 'utf8');
653
739
  }
654
740
 
655
741
  if (outputPath) {