@litmers/cursorflow-orchestrator 0.1.18 → 0.1.26

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 (234) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +25 -7
  3. package/commands/cursorflow-clean.md +19 -0
  4. package/commands/cursorflow-runs.md +59 -0
  5. package/commands/cursorflow-stop.md +55 -0
  6. package/dist/cli/clean.js +178 -6
  7. package/dist/cli/clean.js.map +1 -1
  8. package/dist/cli/index.js +12 -1
  9. package/dist/cli/index.js.map +1 -1
  10. package/dist/cli/init.js +8 -7
  11. package/dist/cli/init.js.map +1 -1
  12. package/dist/cli/logs.js +126 -77
  13. package/dist/cli/logs.js.map +1 -1
  14. package/dist/cli/monitor.d.ts +7 -0
  15. package/dist/cli/monitor.js +1021 -202
  16. package/dist/cli/monitor.js.map +1 -1
  17. package/dist/cli/prepare.js +39 -21
  18. package/dist/cli/prepare.js.map +1 -1
  19. package/dist/cli/resume.js +268 -163
  20. package/dist/cli/resume.js.map +1 -1
  21. package/dist/cli/run.js +11 -5
  22. package/dist/cli/run.js.map +1 -1
  23. package/dist/cli/runs.d.ts +5 -0
  24. package/dist/cli/runs.js +214 -0
  25. package/dist/cli/runs.js.map +1 -0
  26. package/dist/cli/setup-commands.js +0 -0
  27. package/dist/cli/signal.js +8 -8
  28. package/dist/cli/signal.js.map +1 -1
  29. package/dist/cli/stop.d.ts +5 -0
  30. package/dist/cli/stop.js +215 -0
  31. package/dist/cli/stop.js.map +1 -0
  32. package/dist/cli/tasks.d.ts +10 -0
  33. package/dist/cli/tasks.js +165 -0
  34. package/dist/cli/tasks.js.map +1 -0
  35. package/dist/core/auto-recovery.d.ts +212 -0
  36. package/dist/core/auto-recovery.js +737 -0
  37. package/dist/core/auto-recovery.js.map +1 -0
  38. package/dist/core/failure-policy.d.ts +156 -0
  39. package/dist/core/failure-policy.js +488 -0
  40. package/dist/core/failure-policy.js.map +1 -0
  41. package/dist/core/orchestrator.d.ts +16 -2
  42. package/dist/core/orchestrator.js +439 -105
  43. package/dist/core/orchestrator.js.map +1 -1
  44. package/dist/core/reviewer.d.ts +2 -0
  45. package/dist/core/reviewer.js +2 -0
  46. package/dist/core/reviewer.js.map +1 -1
  47. package/dist/core/runner.d.ts +33 -10
  48. package/dist/core/runner.js +374 -164
  49. package/dist/core/runner.js.map +1 -1
  50. package/dist/services/logging/buffer.d.ts +67 -0
  51. package/dist/services/logging/buffer.js +309 -0
  52. package/dist/services/logging/buffer.js.map +1 -0
  53. package/dist/services/logging/console.d.ts +89 -0
  54. package/dist/services/logging/console.js +169 -0
  55. package/dist/services/logging/console.js.map +1 -0
  56. package/dist/services/logging/file-writer.d.ts +71 -0
  57. package/dist/services/logging/file-writer.js +516 -0
  58. package/dist/services/logging/file-writer.js.map +1 -0
  59. package/dist/services/logging/formatter.d.ts +39 -0
  60. package/dist/services/logging/formatter.js +227 -0
  61. package/dist/services/logging/formatter.js.map +1 -0
  62. package/dist/services/logging/index.d.ts +11 -0
  63. package/dist/services/logging/index.js +30 -0
  64. package/dist/services/logging/index.js.map +1 -0
  65. package/dist/services/logging/parser.d.ts +31 -0
  66. package/dist/services/logging/parser.js +222 -0
  67. package/dist/services/logging/parser.js.map +1 -0
  68. package/dist/services/process/index.d.ts +59 -0
  69. package/dist/services/process/index.js +257 -0
  70. package/dist/services/process/index.js.map +1 -0
  71. package/dist/types/agent.d.ts +20 -0
  72. package/dist/types/agent.js +6 -0
  73. package/dist/types/agent.js.map +1 -0
  74. package/dist/types/config.d.ts +65 -0
  75. package/dist/types/config.js +6 -0
  76. package/dist/types/config.js.map +1 -0
  77. package/dist/types/events.d.ts +125 -0
  78. package/dist/types/events.js +6 -0
  79. package/dist/types/events.js.map +1 -0
  80. package/dist/types/index.d.ts +12 -0
  81. package/dist/types/index.js +37 -0
  82. package/dist/types/index.js.map +1 -0
  83. package/dist/types/lane.d.ts +43 -0
  84. package/dist/types/lane.js +6 -0
  85. package/dist/types/lane.js.map +1 -0
  86. package/dist/types/logging.d.ts +71 -0
  87. package/dist/types/logging.js +16 -0
  88. package/dist/types/logging.js.map +1 -0
  89. package/dist/types/review.d.ts +17 -0
  90. package/dist/types/review.js +6 -0
  91. package/dist/types/review.js.map +1 -0
  92. package/dist/types/run.d.ts +32 -0
  93. package/dist/types/run.js +6 -0
  94. package/dist/types/run.js.map +1 -0
  95. package/dist/types/task.d.ts +71 -0
  96. package/dist/types/task.js +6 -0
  97. package/dist/types/task.js.map +1 -0
  98. package/dist/ui/components.d.ts +134 -0
  99. package/dist/ui/components.js +389 -0
  100. package/dist/ui/components.js.map +1 -0
  101. package/dist/ui/log-viewer.d.ts +49 -0
  102. package/dist/ui/log-viewer.js +449 -0
  103. package/dist/ui/log-viewer.js.map +1 -0
  104. package/dist/utils/checkpoint.d.ts +87 -0
  105. package/dist/utils/checkpoint.js +317 -0
  106. package/dist/utils/checkpoint.js.map +1 -0
  107. package/dist/utils/config.d.ts +4 -0
  108. package/dist/utils/config.js +18 -8
  109. package/dist/utils/config.js.map +1 -1
  110. package/dist/utils/cursor-agent.js.map +1 -1
  111. package/dist/utils/dependency.d.ts +74 -0
  112. package/dist/utils/dependency.js +420 -0
  113. package/dist/utils/dependency.js.map +1 -0
  114. package/dist/utils/doctor.js +17 -11
  115. package/dist/utils/doctor.js.map +1 -1
  116. package/dist/utils/enhanced-logger.d.ts +10 -33
  117. package/dist/utils/enhanced-logger.js +108 -20
  118. package/dist/utils/enhanced-logger.js.map +1 -1
  119. package/dist/utils/git.d.ts +121 -0
  120. package/dist/utils/git.js +484 -11
  121. package/dist/utils/git.js.map +1 -1
  122. package/dist/utils/health.d.ts +91 -0
  123. package/dist/utils/health.js +556 -0
  124. package/dist/utils/health.js.map +1 -0
  125. package/dist/utils/lock.d.ts +95 -0
  126. package/dist/utils/lock.js +332 -0
  127. package/dist/utils/lock.js.map +1 -0
  128. package/dist/utils/log-buffer.d.ts +17 -0
  129. package/dist/utils/log-buffer.js +14 -0
  130. package/dist/utils/log-buffer.js.map +1 -0
  131. package/dist/utils/log-constants.d.ts +23 -0
  132. package/dist/utils/log-constants.js +28 -0
  133. package/dist/utils/log-constants.js.map +1 -0
  134. package/dist/utils/log-formatter.d.ts +25 -0
  135. package/dist/utils/log-formatter.js +237 -0
  136. package/dist/utils/log-formatter.js.map +1 -0
  137. package/dist/utils/log-service.d.ts +19 -0
  138. package/dist/utils/log-service.js +47 -0
  139. package/dist/utils/log-service.js.map +1 -0
  140. package/dist/utils/logger.d.ts +46 -27
  141. package/dist/utils/logger.js +82 -60
  142. package/dist/utils/logger.js.map +1 -1
  143. package/dist/utils/path.d.ts +19 -0
  144. package/dist/utils/path.js +77 -0
  145. package/dist/utils/path.js.map +1 -0
  146. package/dist/utils/process-manager.d.ts +21 -0
  147. package/dist/utils/process-manager.js +138 -0
  148. package/dist/utils/process-manager.js.map +1 -0
  149. package/dist/utils/retry.d.ts +121 -0
  150. package/dist/utils/retry.js +374 -0
  151. package/dist/utils/retry.js.map +1 -0
  152. package/dist/utils/run-service.d.ts +88 -0
  153. package/dist/utils/run-service.js +412 -0
  154. package/dist/utils/run-service.js.map +1 -0
  155. package/dist/utils/state.d.ts +62 -3
  156. package/dist/utils/state.js +317 -11
  157. package/dist/utils/state.js.map +1 -1
  158. package/dist/utils/task-service.d.ts +82 -0
  159. package/dist/utils/task-service.js +348 -0
  160. package/dist/utils/task-service.js.map +1 -0
  161. package/dist/utils/template.d.ts +14 -0
  162. package/dist/utils/template.js +122 -0
  163. package/dist/utils/template.js.map +1 -0
  164. package/dist/utils/types.d.ts +2 -271
  165. package/dist/utils/types.js +16 -0
  166. package/dist/utils/types.js.map +1 -1
  167. package/package.json +38 -23
  168. package/scripts/ai-security-check.js +0 -1
  169. package/scripts/local-security-gate.sh +0 -0
  170. package/scripts/monitor-lanes.sh +94 -0
  171. package/scripts/patches/test-cursor-agent.js +0 -1
  172. package/scripts/release.sh +0 -0
  173. package/scripts/setup-security.sh +0 -0
  174. package/scripts/stream-logs.sh +72 -0
  175. package/scripts/verify-and-fix.sh +0 -0
  176. package/src/cli/clean.ts +187 -6
  177. package/src/cli/index.ts +12 -1
  178. package/src/cli/init.ts +8 -7
  179. package/src/cli/logs.ts +124 -77
  180. package/src/cli/monitor.ts +1815 -898
  181. package/src/cli/prepare.ts +41 -21
  182. package/src/cli/resume.ts +753 -626
  183. package/src/cli/run.ts +12 -5
  184. package/src/cli/runs.ts +212 -0
  185. package/src/cli/setup-commands.ts +0 -0
  186. package/src/cli/signal.ts +8 -7
  187. package/src/cli/stop.ts +209 -0
  188. package/src/cli/tasks.ts +154 -0
  189. package/src/core/auto-recovery.ts +909 -0
  190. package/src/core/failure-policy.ts +592 -0
  191. package/src/core/orchestrator.ts +1131 -704
  192. package/src/core/reviewer.ts +4 -0
  193. package/src/core/runner.ts +444 -180
  194. package/src/services/logging/buffer.ts +326 -0
  195. package/src/services/logging/console.ts +193 -0
  196. package/src/services/logging/file-writer.ts +526 -0
  197. package/src/services/logging/formatter.ts +268 -0
  198. package/src/services/logging/index.ts +16 -0
  199. package/src/services/logging/parser.ts +232 -0
  200. package/src/services/process/index.ts +261 -0
  201. package/src/types/agent.ts +24 -0
  202. package/src/types/config.ts +79 -0
  203. package/src/types/events.ts +156 -0
  204. package/src/types/index.ts +29 -0
  205. package/src/types/lane.ts +56 -0
  206. package/src/types/logging.ts +96 -0
  207. package/src/types/review.ts +20 -0
  208. package/src/types/run.ts +37 -0
  209. package/src/types/task.ts +79 -0
  210. package/src/ui/components.ts +430 -0
  211. package/src/ui/log-viewer.ts +485 -0
  212. package/src/utils/checkpoint.ts +374 -0
  213. package/src/utils/config.ts +18 -8
  214. package/src/utils/cursor-agent.ts +1 -1
  215. package/src/utils/dependency.ts +482 -0
  216. package/src/utils/doctor.ts +18 -11
  217. package/src/utils/enhanced-logger.ts +122 -60
  218. package/src/utils/git.ts +517 -11
  219. package/src/utils/health.ts +596 -0
  220. package/src/utils/lock.ts +346 -0
  221. package/src/utils/log-buffer.ts +28 -0
  222. package/src/utils/log-constants.ts +26 -0
  223. package/src/utils/log-formatter.ts +245 -0
  224. package/src/utils/log-service.ts +49 -0
  225. package/src/utils/logger.ts +100 -51
  226. package/src/utils/path.ts +45 -0
  227. package/src/utils/process-manager.ts +100 -0
  228. package/src/utils/retry.ts +413 -0
  229. package/src/utils/run-service.ts +433 -0
  230. package/src/utils/state.ts +385 -11
  231. package/src/utils/task-service.ts +370 -0
  232. package/src/utils/template.ts +92 -0
  233. package/src/utils/types.ts +2 -314
  234. package/templates/basic.json +21 -0
@@ -14,10 +14,10 @@
14
14
  import * as fs from 'fs';
15
15
  import * as path from 'path';
16
16
  import { Transform, TransformCallback } from 'stream';
17
- import { EnhancedLogConfig } from './types';
18
-
19
- // Re-export for backwards compatibility
20
- export { EnhancedLogConfig } from './types';
17
+ import * as logger from './logger';
18
+ import { EnhancedLogConfig, ParsedMessage, JsonLogEntry, LogSession } from '../types';
19
+ export { EnhancedLogConfig, ParsedMessage, JsonLogEntry, LogSession };
20
+ import { safeJoin } from './path';
21
21
 
22
22
  export const DEFAULT_LOG_CONFIG: EnhancedLogConfig = {
23
23
  enabled: true,
@@ -26,6 +26,8 @@ export const DEFAULT_LOG_CONFIG: EnhancedLogConfig = {
26
26
  maxFileSize: 50 * 1024 * 1024, // 50MB
27
27
  maxFiles: 5,
28
28
  keepRawLogs: true,
29
+ keepAbsoluteRawLogs: false,
30
+ raw: false,
29
31
  writeJsonLog: true,
30
32
  timestampFormat: 'iso',
31
33
  };
@@ -207,14 +209,6 @@ export class StreamingMessageParser {
207
209
  }
208
210
  }
209
211
 
210
- export interface ParsedMessage {
211
- type: 'system' | 'user' | 'assistant' | 'tool' | 'tool_result' | 'result' | 'thinking';
212
- role: string;
213
- content: string;
214
- timestamp: number;
215
- metadata?: Record<string, any>;
216
- }
217
-
218
212
  /**
219
213
  * ANSI escape sequence regex pattern
220
214
  * Matches:
@@ -275,35 +269,12 @@ export function formatTimestamp(format: 'iso' | 'relative' | 'short', startTime?
275
269
  }
276
270
 
277
271
  /**
278
- * JSON log entry structure
279
- */
280
- export interface JsonLogEntry {
281
- timestamp: string;
282
- level: 'stdout' | 'stderr' | 'info' | 'error' | 'debug' | 'session';
283
- source?: string;
284
- task?: string;
285
- lane?: string;
286
- message: string;
287
- raw?: string;
288
- metadata?: Record<string, any>;
289
- }
290
-
291
- /**
292
- * Session context for logging
293
- */
294
- export interface LogSession {
295
- id: string;
296
- laneName: string;
297
- taskName?: string;
298
- model?: string;
299
- startTime: number;
300
- metadata?: Record<string, any>;
301
- }
302
-
303
- /**
304
- * Regex to detect if a line already has an ISO timestamp at the start
272
+ * Regex to detect if a line already has a timestamp at the start
273
+ * Matches:
274
+ * - ISO format: [2024-01-01T12:34:56...]
275
+ * - Short format: [12:34:56]
305
276
  */
306
- const EXISTING_TIMESTAMP_REGEX = /^\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
277
+ const EXISTING_TIMESTAMP_REGEX = /^\[(\d{4}-\d{2}-\d{2}T)?\d{2}:\d{2}:\d{2}/;
307
278
 
308
279
  /**
309
280
  * Check if a line already has a timestamp
@@ -387,16 +358,19 @@ export class EnhancedLogManager {
387
358
 
388
359
  private cleanLogPath: string;
389
360
  private rawLogPath: string;
361
+ private absoluteRawLogPath: string;
390
362
  private jsonLogPath: string;
391
363
  private readableLogPath: string;
392
364
 
393
365
  private cleanLogFd: number | null = null;
394
366
  private rawLogFd: number | null = null;
367
+ private absoluteRawLogFd: number | null = null;
395
368
  private jsonLogFd: number | null = null;
396
369
  private readableLogFd: number | null = null;
397
370
 
398
371
  private cleanLogSize: number = 0;
399
372
  private rawLogSize: number = 0;
373
+ private absoluteRawLogSize: number = 0;
400
374
 
401
375
  private cleanTransform: CleanLogTransform | null = null;
402
376
  private streamingParser: StreamingMessageParser | null = null;
@@ -405,6 +379,12 @@ export class EnhancedLogManager {
405
379
 
406
380
  constructor(logDir: string, session: LogSession, config: Partial<EnhancedLogConfig> = {}, onParsedMessage?: (msg: ParsedMessage) => void) {
407
381
  this.config = { ...DEFAULT_LOG_CONFIG, ...config };
382
+
383
+ // Support 'raw' as alias for 'keepAbsoluteRawLogs'
384
+ if (this.config.raw) {
385
+ this.config.keepAbsoluteRawLogs = true;
386
+ }
387
+
408
388
  this.session = session;
409
389
  this.logDir = logDir;
410
390
  this.onParsedMessage = onParsedMessage;
@@ -413,10 +393,15 @@ export class EnhancedLogManager {
413
393
  fs.mkdirSync(logDir, { recursive: true });
414
394
 
415
395
  // Set up log file paths
416
- this.cleanLogPath = path.join(logDir, 'terminal.log');
417
- this.rawLogPath = path.join(logDir, 'terminal-raw.log');
418
- this.jsonLogPath = path.join(logDir, 'terminal.jsonl');
419
- this.readableLogPath = path.join(logDir, 'terminal-readable.log');
396
+ this.cleanLogPath = safeJoin(logDir, 'terminal.log');
397
+ this.rawLogPath = safeJoin(logDir, 'terminal-raw.log');
398
+ this.absoluteRawLogPath = safeJoin(logDir, 'terminal-absolute-raw.log');
399
+ this.jsonLogPath = safeJoin(logDir, 'terminal.jsonl');
400
+ this.readableLogPath = safeJoin(logDir, 'terminal-readable.log');
401
+
402
+ if (this.config.raw) {
403
+ logger.info(`[${session.laneName}] 📄 Raw data capture enabled: ${this.absoluteRawLogPath}`);
404
+ }
420
405
 
421
406
  // Initialize log files
422
407
  this.initLogFiles();
@@ -431,6 +416,9 @@ export class EnhancedLogManager {
431
416
  if (this.config.keepRawLogs) {
432
417
  this.rotateIfNeeded(this.rawLogPath, 'raw');
433
418
  }
419
+ if (this.config.keepAbsoluteRawLogs) {
420
+ this.rotateIfNeeded(this.absoluteRawLogPath, 'raw');
421
+ }
434
422
 
435
423
  // Open file descriptors
436
424
  this.cleanLogFd = fs.openSync(this.cleanLogPath, 'a');
@@ -438,6 +426,10 @@ export class EnhancedLogManager {
438
426
  if (this.config.keepRawLogs) {
439
427
  this.rawLogFd = fs.openSync(this.rawLogPath, 'a');
440
428
  }
429
+
430
+ if (this.config.keepAbsoluteRawLogs) {
431
+ this.absoluteRawLogFd = fs.openSync(this.absoluteRawLogPath, 'a');
432
+ }
441
433
 
442
434
  if (this.config.writeJsonLog) {
443
435
  this.jsonLogFd = fs.openSync(this.jsonLogPath, 'a');
@@ -452,9 +444,13 @@ export class EnhancedLogManager {
452
444
  if (this.config.keepRawLogs) {
453
445
  this.rawLogSize = fs.statSync(this.rawLogPath).size;
454
446
  }
447
+ if (this.config.keepAbsoluteRawLogs) {
448
+ this.absoluteRawLogSize = fs.statSync(this.absoluteRawLogPath).size;
449
+ }
455
450
  } catch {
456
451
  this.cleanLogSize = 0;
457
452
  this.rawLogSize = 0;
453
+ this.absoluteRawLogSize = 0;
458
454
  }
459
455
 
460
456
  // Write session header
@@ -620,8 +616,8 @@ export class EnhancedLogManager {
620
616
 
621
617
  // Shift existing rotated files
622
618
  for (let i = this.config.maxFiles - 1; i >= 1; i--) {
623
- const oldPath = path.join(dir, `${base}.${i}${ext}`);
624
- const newPath = path.join(dir, `${base}.${i + 1}${ext}`);
619
+ const oldPath = safeJoin(dir, `${base}.${i}${ext}`);
620
+ const newPath = safeJoin(dir, `${base}.${i + 1}${ext}`);
625
621
 
626
622
  if (fs.existsSync(oldPath)) {
627
623
  if (i === this.config.maxFiles - 1) {
@@ -633,7 +629,7 @@ export class EnhancedLogManager {
633
629
  }
634
630
 
635
631
  // Rotate current to .1
636
- const rotatedPath = path.join(dir, `${base}.1${ext}`);
632
+ const rotatedPath = safeJoin(dir, `${base}.1${ext}`);
637
633
  fs.renameSync(logPath, rotatedPath);
638
634
  }
639
635
 
@@ -675,6 +671,25 @@ export class EnhancedLogManager {
675
671
  }
676
672
  }
677
673
 
674
+ /**
675
+ * Write to absolute raw log with size tracking
676
+ */
677
+ private writeToAbsoluteRawLog(data: string | Buffer): void {
678
+ if (this.absoluteRawLogFd === null) return;
679
+
680
+ const buffer = typeof data === 'string' ? Buffer.from(data) : data;
681
+ fs.writeSync(this.absoluteRawLogFd, buffer);
682
+ this.absoluteRawLogSize += buffer.length;
683
+
684
+ // Check if rotation needed
685
+ if (this.absoluteRawLogSize >= this.config.maxFileSize) {
686
+ fs.closeSync(this.absoluteRawLogFd);
687
+ this.rotateLog(this.absoluteRawLogPath);
688
+ this.absoluteRawLogFd = fs.openSync(this.absoluteRawLogPath, 'a');
689
+ this.absoluteRawLogSize = 0;
690
+ }
691
+ }
692
+
678
693
  /**
679
694
  * Write a JSON log entry
680
695
  */
@@ -691,6 +706,11 @@ export class EnhancedLogManager {
691
706
  public writeStdout(data: Buffer | string): void {
692
707
  const text = data.toString();
693
708
 
709
+ // Write absolute raw log
710
+ if (this.config.keepAbsoluteRawLogs) {
711
+ this.writeToAbsoluteRawLog(data);
712
+ }
713
+
694
714
  // Write raw log
695
715
  if (this.config.keepRawLogs) {
696
716
  this.writeToRawLog(text);
@@ -710,7 +730,7 @@ export class EnhancedLogManager {
710
730
  const cleanLine = stripAnsi(line).trim();
711
731
  if (!cleanLine) continue;
712
732
 
713
- // Handle streaming JSON messages (for boxes, etc. in readable log)
733
+ // Handle streaming JSON messages
714
734
  if (cleanLine.startsWith('{')) {
715
735
  if (this.streamingParser) {
716
736
  this.streamingParser.parseLine(cleanLine);
@@ -724,8 +744,10 @@ export class EnhancedLogManager {
724
744
  let metadata = { ...json };
725
745
 
726
746
  // Extract cleaner text for significant AI message types
727
- if (json.type === 'thinking' && json.text) {
728
- displayMsg = json.text;
747
+ if ((json.type === 'thinking' || json.type === 'thought') && (json.text || json.thought)) {
748
+ displayMsg = json.text || json.thought;
749
+ // Clean up any double newlines at the end of deltas
750
+ displayMsg = displayMsg.replace(/\n+$/, '\n');
729
751
  } else if (json.type === 'assistant' && json.message?.content) {
730
752
  displayMsg = json.message.content
731
753
  .filter((c: any) => c.type === 'text')
@@ -760,6 +782,25 @@ export class EnhancedLogManager {
760
782
  // Not valid JSON or error, fall through to regular logging
761
783
  }
762
784
  }
785
+ } else {
786
+ // Parse standard text logs into ParsedMessage
787
+ // Format: [HH:MM:SS] [LANE] ℹ️ INFO message
788
+ const textLogRegex = /^\[(\d{2}:\d{2}:\d{2})\]\s+\[(.*?)\]\s+(.*?)\s+(INFO|WARN|ERROR|SUCCESS|DONE|PROGRESS)\s+(.*)/;
789
+ const match = cleanLine.match(textLogRegex);
790
+
791
+ if (match && this.onParsedMessage) {
792
+ const [, time, , emoji, level, content] = match;
793
+ // Convert HH:MM:SS to a timestamp for today
794
+ const [h, m, s] = time!.split(':').map(Number);
795
+ const timestamp = new Date().setHours(h!, m!, s!, 0);
796
+
797
+ this.onParsedMessage({
798
+ type: level!.toLowerCase().replace('done', 'result').replace('success', 'result') as any,
799
+ role: 'system',
800
+ content: `${emoji} ${content}`,
801
+ timestamp,
802
+ });
803
+ }
763
804
  }
764
805
 
765
806
  // Also include significant info/status lines in readable log (compact)
@@ -809,6 +850,11 @@ export class EnhancedLogManager {
809
850
  public writeStderr(data: Buffer | string): void {
810
851
  const text = data.toString();
811
852
 
853
+ // Write absolute raw log
854
+ if (this.config.keepAbsoluteRawLogs) {
855
+ this.writeToAbsoluteRawLog(data);
856
+ }
857
+
812
858
  // Write raw log
813
859
  if (this.config.keepRawLogs) {
814
860
  this.writeToRawLog(text);
@@ -853,7 +899,7 @@ export class EnhancedLogManager {
853
899
  */
854
900
  public log(level: 'info' | 'error' | 'debug', message: string, metadata?: Record<string, any>): void {
855
901
  const ts = formatTimestamp(this.config.timestampFormat, this.session.startTime);
856
- const prefix = level.toUpperCase().padEnd(5);
902
+ const prefix = level.toUpperCase().padEnd(8);
857
903
 
858
904
  const line = `[${ts}] [${prefix}] ${message}\n`;
859
905
  this.writeToCleanLog(line);
@@ -862,6 +908,10 @@ export class EnhancedLogManager {
862
908
  this.writeToRawLog(line);
863
909
  }
864
910
 
911
+ if (this.config.keepAbsoluteRawLogs) {
912
+ this.writeToAbsoluteRawLog(line);
913
+ }
914
+
865
915
  // Write to readable log (compact)
866
916
  if (this.readableLogFd !== null) {
867
917
  const typeLabel = level === 'error' ? '❌ ERROR' : level === 'info' ? 'ℹ️ INFO' : '🔍 DEBUG';
@@ -894,6 +944,9 @@ export class EnhancedLogManager {
894
944
  if (this.config.keepRawLogs) {
895
945
  this.writeToRawLog(line);
896
946
  }
947
+ if (this.config.keepAbsoluteRawLogs) {
948
+ this.writeToAbsoluteRawLog(line);
949
+ }
897
950
 
898
951
  // Write to readable log (compact)
899
952
  if (this.readableLogFd !== null) {
@@ -951,10 +1004,11 @@ export class EnhancedLogManager {
951
1004
  /**
952
1005
  * Get paths to all log files
953
1006
  */
954
- public getLogPaths(): { clean: string; raw?: string; json?: string; readable: string } {
1007
+ public getLogPaths(): { clean: string; raw?: string; absoluteRaw?: string; json?: string; readable: string } {
955
1008
  return {
956
1009
  clean: this.cleanLogPath,
957
1010
  raw: this.config.keepRawLogs ? this.rawLogPath : undefined,
1011
+ absoluteRaw: this.config.keepAbsoluteRawLogs ? this.absoluteRawLogPath : undefined,
958
1012
  json: this.config.writeJsonLog ? this.jsonLogPath : undefined,
959
1013
  readable: this.readableLogPath,
960
1014
  };
@@ -1008,6 +1062,11 @@ export class EnhancedLogManager {
1008
1062
  this.rawLogFd = null;
1009
1063
  }
1010
1064
 
1065
+ if (this.absoluteRawLogFd !== null) {
1066
+ fs.closeSync(this.absoluteRawLogFd);
1067
+ this.absoluteRawLogFd = null;
1068
+ }
1069
+
1011
1070
  if (this.jsonLogFd !== null) {
1012
1071
  this.writeJsonEntry({
1013
1072
  timestamp: new Date().toISOString(),
@@ -1101,8 +1160,8 @@ export function exportLogs(
1101
1160
  format: 'text' | 'json' | 'markdown' | 'html',
1102
1161
  outputPath?: string
1103
1162
  ): string {
1104
- const cleanLogPath = path.join(laneRunDir, 'terminal.log');
1105
- const jsonLogPath = path.join(laneRunDir, 'terminal.jsonl');
1163
+ const cleanLogPath = safeJoin(laneRunDir, 'terminal.log');
1164
+ const jsonLogPath = safeJoin(laneRunDir, 'terminal.jsonl');
1106
1165
 
1107
1166
  let output = '';
1108
1167
 
@@ -1168,8 +1227,10 @@ function exportToMarkdown(jsonLogPath: string, cleanLogPath: string): string {
1168
1227
  md += `### Task: ${task}\n\n`;
1169
1228
  md += '```\n';
1170
1229
  for (const entry of taskEntries) {
1171
- if (entry.level !== 'session') {
1172
- md += `[${entry.timestamp}] [${entry.level.toUpperCase()}] ${entry.message}\n`;
1230
+ const level = entry.level || 'info';
1231
+ const message = entry.message || '';
1232
+ if (level !== 'session') {
1233
+ md += `[${entry.timestamp}] [${level.toUpperCase()}] ${message}\n`;
1173
1234
  }
1174
1235
  }
1175
1236
  md += '```\n\n';
@@ -1208,11 +1269,13 @@ function exportToHtml(jsonLogPath: string, cleanLogPath: string): string {
1208
1269
  `;
1209
1270
 
1210
1271
  for (const entry of entries) {
1211
- html += ` <div class="entry ${entry.level}">
1272
+ const level = entry.level || 'info';
1273
+ const message = entry.message || '';
1274
+ html += ` <div class="entry ${level}">
1212
1275
  <span class="timestamp">${entry.timestamp}</span>
1213
- <span class="level">[${entry.level}]</span>
1276
+ <span class="level">[${level}]</span>
1214
1277
  ${entry.task ? `<span class="task">[${entry.task}]</span>` : ''}
1215
- <pre>${escapeHtml(entry.message)}</pre>
1278
+ <pre>${escapeHtml(message)}</pre>
1216
1279
  </div>\n`;
1217
1280
  }
1218
1281
 
@@ -1228,4 +1291,3 @@ function escapeHtml(text: string): string {
1228
1291
  .replace(/"/g, '&quot;')
1229
1292
  .replace(/'/g, '&#039;');
1230
1293
  }
1231
-