@exaudeus/workrail 3.31.1 → 3.33.0

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 (82) hide show
  1. package/dist/cli/commands/index.d.ts +1 -0
  2. package/dist/cli/commands/index.js +3 -1
  3. package/dist/cli/commands/worktrain-await.js +11 -9
  4. package/dist/cli/commands/worktrain-daemon-install.d.ts +35 -0
  5. package/dist/cli/commands/worktrain-daemon-install.js +291 -0
  6. package/dist/cli/commands/worktrain-daemon.d.ts +31 -0
  7. package/dist/cli/commands/worktrain-daemon.js +272 -0
  8. package/dist/cli/commands/worktrain-spawn.js +11 -9
  9. package/dist/cli-worktrain.js +329 -0
  10. package/dist/cli.js +4 -22
  11. package/dist/console/standalone-console.d.ts +28 -0
  12. package/dist/console/standalone-console.js +142 -0
  13. package/dist/{console/assets/index-6H9DeFxj.js → console-ui/assets/index-BuJFLLfY.js} +1 -1
  14. package/dist/{console → console-ui}/index.html +1 -1
  15. package/dist/daemon/agent-loop.d.ts +26 -0
  16. package/dist/daemon/agent-loop.js +53 -2
  17. package/dist/daemon/daemon-events.d.ts +103 -0
  18. package/dist/daemon/daemon-events.js +56 -0
  19. package/dist/daemon/workflow-runner.d.ts +6 -3
  20. package/dist/daemon/workflow-runner.js +229 -33
  21. package/dist/infrastructure/session/HttpServer.js +133 -34
  22. package/dist/manifest.json +134 -70
  23. package/dist/mcp/output-schemas.d.ts +30 -30
  24. package/dist/mcp/transports/bridge-events.d.ts +4 -0
  25. package/dist/mcp/transports/fatal-exit.js +4 -0
  26. package/dist/mcp/transports/http-entry.js +2 -0
  27. package/dist/mcp/transports/stdio-entry.js +26 -6
  28. package/dist/mcp/v2/tools.d.ts +4 -4
  29. package/dist/trigger/adapters/github-poller.d.ts +44 -0
  30. package/dist/trigger/adapters/github-poller.js +190 -0
  31. package/dist/trigger/adapters/gitlab-poller.d.ts +27 -0
  32. package/dist/trigger/adapters/gitlab-poller.js +81 -0
  33. package/dist/trigger/delivery-client.d.ts +2 -1
  34. package/dist/trigger/delivery-client.js +4 -1
  35. package/dist/trigger/index.d.ts +4 -1
  36. package/dist/trigger/index.js +5 -1
  37. package/dist/trigger/polled-event-store.d.ts +22 -0
  38. package/dist/trigger/polled-event-store.js +173 -0
  39. package/dist/trigger/polling-scheduler.d.ts +20 -0
  40. package/dist/trigger/polling-scheduler.js +249 -0
  41. package/dist/trigger/trigger-listener.d.ts +5 -0
  42. package/dist/trigger/trigger-listener.js +53 -4
  43. package/dist/trigger/trigger-router.d.ts +4 -2
  44. package/dist/trigger/trigger-router.js +7 -4
  45. package/dist/trigger/trigger-store.js +114 -33
  46. package/dist/trigger/types.d.ts +17 -1
  47. package/dist/v2/durable-core/schemas/export-bundle/index.d.ts +224 -224
  48. package/dist/v2/durable-core/schemas/session/events.d.ts +42 -42
  49. package/dist/v2/durable-core/schemas/session/manifest.d.ts +6 -6
  50. package/dist/v2/durable-core/schemas/session/validation-event.d.ts +2 -2
  51. package/dist/v2/durable-core/tokens/payloads.d.ts +52 -52
  52. package/dist/v2/usecases/console-routes.js +3 -3
  53. package/dist/v2/usecases/console-service.js +133 -9
  54. package/dist/v2/usecases/console-types.d.ts +7 -0
  55. package/docs/design/daemon-conversation-logging-plan.md +98 -0
  56. package/docs/design/daemon-conversation-logging-review.md +55 -0
  57. package/docs/design/daemon-conversation-logging.md +129 -0
  58. package/docs/design/github-polling-adapter-design-candidates.md +226 -0
  59. package/docs/design/github-polling-adapter-design-review-findings.md +131 -0
  60. package/docs/design/github-polling-adapter-implementation-plan.md +284 -0
  61. package/docs/design/implementation_plan.md +192 -0
  62. package/docs/design/workflow-id-validation-at-startup.md +146 -0
  63. package/docs/design/workflow-id-validation-design-review.md +87 -0
  64. package/docs/design/workflow-id-validation-implementation-plan.md +185 -0
  65. package/docs/design/worktrain-system-prompt-report-issue-candidates.md +135 -0
  66. package/docs/design/worktrain-system-prompt-report-issue-design-review.md +73 -0
  67. package/docs/ideas/backlog.md +465 -0
  68. package/package.json +1 -1
  69. package/workflows/architecture-scalability-audit.json +1 -1
  70. package/workflows/bug-investigation.agentic.v2.json +3 -3
  71. package/workflows/coding-task-workflow-agentic.json +32 -32
  72. package/workflows/coding-task-workflow-agentic.lean.v2.json +1 -1
  73. package/workflows/coding-task-workflow-agentic.v2.json +7 -7
  74. package/workflows/mr-review-workflow.agentic.v2.json +21 -12
  75. package/workflows/personal-learning-materials-creation-branched.json +2 -2
  76. package/workflows/production-readiness-audit.json +1 -1
  77. package/workflows/relocation-workflow-us.json +2 -2
  78. package/workflows/ui-ux-design-workflow.json +14 -14
  79. package/workflows/workflow-for-workflows.json +3 -3
  80. package/workflows/workflow-for-workflows.v2.json +2 -2
  81. package/workflows/wr.discovery.json +1 -1
  82. /package/dist/{console → console-ui}/assets/index-8dh0Psu-.css +0 -0
@@ -75,7 +75,10 @@ let HttpServer = class HttpServer {
75
75
  const start = Date.now();
76
76
  res.on('finish', () => {
77
77
  const duration = Date.now() - start;
78
- console.error(`[HTTP] ${req.method} ${req.path} ${res.statusCode} (${duration}ms)`);
78
+ try {
79
+ process.stderr.write(`[HTTP] ${req.method} ${req.path} ${res.statusCode} (${duration}ms)\n`);
80
+ }
81
+ catch { }
79
82
  });
80
83
  next();
81
84
  });
@@ -217,7 +220,10 @@ let HttpServer = class HttpServer {
217
220
  res.write(`data: ${JSON.stringify({ type: 'update', session: event.session })}\n\n`);
218
221
  }
219
222
  catch (error) {
220
- console.error(`[SSE] Write error for ${workflow}/${id}:`, error);
223
+ try {
224
+ process.stderr.write(`[SSE] Write error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
225
+ }
226
+ catch { }
221
227
  cleanup();
222
228
  }
223
229
  };
@@ -231,7 +237,10 @@ let HttpServer = class HttpServer {
231
237
  return true;
232
238
  }
233
239
  catch (error) {
234
- console.error(`[SSE] Write error for ${workflow}/${id}:`, error);
240
+ try {
241
+ process.stderr.write(`[SSE] Write error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
242
+ }
243
+ catch { }
235
244
  cleanup();
236
245
  return false;
237
246
  }
@@ -241,7 +250,10 @@ let HttpServer = class HttpServer {
241
250
  res.setHeader('Connection', 'keep-alive');
242
251
  res.setHeader('X-Accel-Buffering', 'no');
243
252
  maxConnectionTimeout = setTimeout(() => {
244
- console.error(`[SSE] Max connection time reached for ${workflow}/${id}, closing`);
253
+ try {
254
+ process.stderr.write(`[SSE] Max connection time reached for ${workflow}/${id}, closing\n`);
255
+ }
256
+ catch { }
245
257
  cleanup();
246
258
  }, 30 * 60 * 1000);
247
259
  if (!safeWrite(`data: ${JSON.stringify({ type: 'connected', workflowId: workflow, sessionId: id })}\n\n`)) {
@@ -263,11 +275,17 @@ let HttpServer = class HttpServer {
263
275
  }, 30000);
264
276
  req.on('close', cleanup);
265
277
  req.on('error', (error) => {
266
- console.error(`[SSE] Request error for ${workflow}/${id}:`, error);
278
+ try {
279
+ process.stderr.write(`[SSE] Request error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
280
+ }
281
+ catch { }
267
282
  cleanup();
268
283
  });
269
284
  res.on('error', (error) => {
270
- console.error(`[SSE] Response error for ${workflow}/${id}:`, error);
285
+ try {
286
+ process.stderr.write(`[SSE] Response error for ${workflow}/${id}: ${error?.message ?? String(error)}\n`);
287
+ }
288
+ catch { }
271
289
  cleanup();
272
290
  });
273
291
  res.on('finish', cleanup);
@@ -287,7 +305,10 @@ let HttpServer = class HttpServer {
287
305
  });
288
306
  }
289
307
  catch (error) {
290
- console.error('[HttpServer] Delete session error:', error);
308
+ try {
309
+ process.stderr.write(`[HttpServer] Delete session error: ${error?.message ?? String(error)}\n`);
310
+ }
311
+ catch { }
291
312
  res.status(500).json({
292
313
  success: false,
293
314
  error: error.message || 'Failed to delete session'
@@ -311,7 +332,10 @@ let HttpServer = class HttpServer {
311
332
  });
312
333
  }
313
334
  catch (error) {
314
- console.error('[HttpServer] Bulk delete error:', error);
335
+ try {
336
+ process.stderr.write(`[HttpServer] Bulk delete error: ${error?.message ?? String(error)}\n`);
337
+ }
338
+ catch { }
315
339
  res.status(500).json({
316
340
  success: false,
317
341
  error: error.message || 'Failed to delete sessions'
@@ -335,7 +359,10 @@ let HttpServer = class HttpServer {
335
359
  this._stopPromise = null;
336
360
  const mode = this.config.dashboardMode ?? this.dashboardMode;
337
361
  if (mode.kind === 'legacy') {
338
- console.error('[Dashboard] Unified dashboard disabled, using legacy mode');
362
+ try {
363
+ process.stderr.write('[Dashboard] Unified dashboard disabled, using legacy mode\n');
364
+ }
365
+ catch { }
339
366
  return await this.startLegacyMode();
340
367
  }
341
368
  if (await this.tryBecomePrimary()) {
@@ -345,8 +372,11 @@ let HttpServer = class HttpServer {
345
372
  }
346
373
  catch (error) {
347
374
  if (error.code === 'EADDRINUSE') {
348
- console.error(`[Dashboard] Port ${this.port} still held by previous instance -- ` +
349
- `running on next available port. Restart the old instance to move to ${this.port}.`);
375
+ try {
376
+ process.stderr.write(`[Dashboard] Port ${this.port} still held by previous instance -- ` +
377
+ `running on next available port. Restart the old instance to move to ${this.port}.\n`);
378
+ }
379
+ catch { }
350
380
  await promises_1.default.unlink(this.lockFile).catch(() => { });
351
381
  return await this.startLegacyMode();
352
382
  }
@@ -354,7 +384,10 @@ let HttpServer = class HttpServer {
354
384
  }
355
385
  }
356
386
  else {
357
- console.error(`[Dashboard] ✅ Unified dashboard at http://localhost:${this.port}`);
387
+ try {
388
+ process.stderr.write(`[Dashboard] Unified dashboard at http://localhost:${this.port}\n`);
389
+ }
390
+ catch { }
358
391
  return null;
359
392
  }
360
393
  }
@@ -371,7 +404,10 @@ let HttpServer = class HttpServer {
371
404
  version: CURRENT_VERSION
372
405
  };
373
406
  await promises_1.default.writeFile(this.lockFile, JSON.stringify(lockData, null, 2), { flag: 'wx' });
374
- console.error('[Dashboard] Primary elected');
407
+ try {
408
+ process.stderr.write('[Dashboard] Primary elected\n');
409
+ }
410
+ catch { }
375
411
  this.isPrimary = true;
376
412
  this.setupPrimaryCleanup();
377
413
  this.heartbeat.start();
@@ -382,7 +418,10 @@ let HttpServer = class HttpServer {
382
418
  return await this.reclaimStaleLock();
383
419
  }
384
420
  else if (error.code === 'EACCES' || error.code === 'EPERM') {
385
- console.error('[Dashboard] Cannot write lock file (permission denied)');
421
+ try {
422
+ process.stderr.write('[Dashboard] Cannot write lock file (permission denied)\n');
423
+ }
424
+ catch { }
386
425
  return false;
387
426
  }
388
427
  throw error;
@@ -525,15 +564,24 @@ let HttpServer = class HttpServer {
525
564
  if (isCleaningUp || !this.isPrimary)
526
565
  return;
527
566
  isCleaningUp = true;
528
- console.error('[Dashboard] Primary shutting down (sync cleanup)');
567
+ try {
568
+ process.stderr.write('[Dashboard] Primary shutting down (sync cleanup)\n');
569
+ }
570
+ catch { }
529
571
  this.heartbeat.stop();
530
572
  try {
531
573
  (0, DashboardLockRelease_js_1.releaseLockFileSync)(this.lockFile);
532
- console.error('[Dashboard] Lock file released');
574
+ try {
575
+ process.stderr.write('[Dashboard] Lock file released\n');
576
+ }
577
+ catch { }
533
578
  }
534
579
  catch (error) {
535
580
  if (error.code !== 'ENOENT') {
536
- console.error('[Dashboard] Failed to release lock file:', error.message);
581
+ try {
582
+ process.stderr.write(`[Dashboard] Failed to release lock file: ${error.message}\n`);
583
+ }
584
+ catch { }
537
585
  }
538
586
  }
539
587
  this.isPrimary = false;
@@ -542,9 +590,15 @@ let HttpServer = class HttpServer {
542
590
  if (isCleaningUp)
543
591
  return;
544
592
  isCleaningUp = true;
545
- console.error(`[Dashboard] Received ${signal}`);
593
+ try {
594
+ process.stderr.write(`[Dashboard] Received ${signal}\n`);
595
+ }
596
+ catch { }
546
597
  this.stop()
547
- .catch(err => console.error('[Dashboard] Cleanup error:', err))
598
+ .catch(err => { try {
599
+ process.stderr.write(`[Dashboard] Cleanup error: ${err.message}\n`);
600
+ }
601
+ catch { } })
548
602
  .finally(() => {
549
603
  if (signal !== 'exit') {
550
604
  this.shutdownEvents.emit({ kind: 'shutdown_requested', signal });
@@ -589,7 +643,10 @@ let HttpServer = class HttpServer {
589
643
  });
590
644
  });
591
645
  this.baseUrl = `http://localhost:${this.port}`;
592
- console.error(`[Dashboard] Started in legacy mode on port ${this.port}`);
646
+ try {
647
+ process.stderr.write(`[Dashboard] Started in legacy mode on port ${this.port}\n`);
648
+ }
649
+ catch { }
593
650
  this.printBanner();
594
651
  return this.baseUrl;
595
652
  }
@@ -648,10 +705,16 @@ let HttpServer = class HttpServer {
648
705
  if (behavior.kind === 'auto_open') {
649
706
  try {
650
707
  await (0, open_1.default)(url);
651
- console.error(`🌐 Opened dashboard: ${url}`);
708
+ try {
709
+ process.stderr.write(`Opened dashboard: ${url}\n`);
710
+ }
711
+ catch { }
652
712
  }
653
713
  catch (error) {
654
- console.error(`🌐 Dashboard URL: ${url} (auto-open failed, please open manually)`);
714
+ try {
715
+ process.stderr.write(`Dashboard URL: ${url} (auto-open failed, please open manually)\n`);
716
+ }
717
+ catch { }
655
718
  }
656
719
  }
657
720
  return url;
@@ -678,12 +741,18 @@ let HttpServer = class HttpServer {
678
741
  if (!this.server)
679
742
  return resolve();
680
743
  const closeTimeout = setTimeout(() => {
681
- console.error('[Dashboard] Server close timeout after 5s, forcing shutdown');
744
+ try {
745
+ process.stderr.write('[Dashboard] Server close timeout after 5s, forcing shutdown\n');
746
+ }
747
+ catch { }
682
748
  resolve();
683
749
  }, 5000);
684
750
  this.server.close(() => {
685
751
  clearTimeout(closeTimeout);
686
- console.error('HTTP server stopped');
752
+ try {
753
+ process.stderr.write('HTTP server stopped\n');
754
+ }
755
+ catch { }
687
756
  resolve();
688
757
  });
689
758
  });
@@ -717,45 +786,75 @@ let HttpServer = class HttpServer {
717
786
  try {
718
787
  const busyPorts = await this.getWorkrailPorts();
719
788
  if (busyPorts.length === 0) {
720
- console.error('[Cleanup] No workrail processes found');
789
+ try {
790
+ process.stderr.write('[Cleanup] No workrail processes found\n');
791
+ }
792
+ catch { }
721
793
  return 0;
722
794
  }
723
- console.error(`[Cleanup] Found ${busyPorts.length} workrail process(es), removing all...`);
795
+ try {
796
+ process.stderr.write(`[Cleanup] Found ${busyPorts.length} workrail process(es), removing all...\n`);
797
+ }
798
+ catch { }
724
799
  let cleanedCount = 0;
725
800
  for (const { port, pid } of busyPorts) {
726
801
  if (pid === process.pid) {
727
- console.error(`[Cleanup] Skipping current process ${pid}`);
802
+ try {
803
+ process.stderr.write(`[Cleanup] Skipping current process ${pid}\n`);
804
+ }
805
+ catch { }
728
806
  continue;
729
807
  }
730
- console.error(`[Cleanup] Killing process ${pid} on port ${port}`);
808
+ try {
809
+ process.stderr.write(`[Cleanup] Killing process ${pid} on port ${port}\n`);
810
+ }
811
+ catch { }
731
812
  try {
732
813
  process.kill(pid, 'SIGTERM');
733
814
  await new Promise(r => setTimeout(r, 1000));
734
815
  try {
735
816
  process.kill(pid, 0);
736
817
  process.kill(pid, 'SIGKILL');
737
- console.error(`[Cleanup] Force killed process ${pid}`);
818
+ try {
819
+ process.stderr.write(`[Cleanup] Force killed process ${pid}\n`);
820
+ }
821
+ catch { }
738
822
  }
739
823
  catch {
740
- console.error(`[Cleanup] Process ${pid} terminated gracefully`);
824
+ try {
825
+ process.stderr.write(`[Cleanup] Process ${pid} terminated gracefully\n`);
826
+ }
827
+ catch { }
741
828
  }
742
829
  cleanedCount++;
743
830
  }
744
831
  catch (error) {
745
- console.error(`[Cleanup] Failed to kill process ${pid}:`, error);
832
+ try {
833
+ process.stderr.write(`[Cleanup] Failed to kill process ${pid}: ${error?.message ?? String(error)}\n`);
834
+ }
835
+ catch { }
746
836
  }
747
837
  }
748
- console.error(`[Cleanup] Cleaned up ${cleanedCount} process(es)`);
838
+ try {
839
+ process.stderr.write(`[Cleanup] Cleaned up ${cleanedCount} process(es)\n`);
840
+ }
841
+ catch { }
749
842
  try {
750
843
  await promises_1.default.unlink(this.lockFile);
751
- console.error('[Cleanup] Removed lock file');
844
+ try {
845
+ process.stderr.write('[Cleanup] Removed lock file\n');
846
+ }
847
+ catch { }
752
848
  }
753
849
  catch {
754
850
  }
755
851
  return cleanedCount;
756
852
  }
757
853
  catch (error) {
758
- console.error('[Cleanup] Full cleanup failed:', error);
854
+ try {
855
+ process.stderr.write(`[Cleanup] Full cleanup failed: ${error?.message ?? String(error)}\n`);
856
+ }
857
+ catch { }
759
858
  throw error;
760
859
  }
761
860
  }