@trevonistrevon/pi-loop 0.5.9 → 0.6.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 (121) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/AGENTS.md +52 -12
  3. package/CHANGELOG.md +59 -0
  4. package/CONTRIBUTING.md +13 -3
  5. package/README.md +47 -0
  6. package/coverage/coverage-final.json +35 -32
  7. package/coverage/index.html +64 -49
  8. package/coverage/src/api.ts.html +193 -0
  9. package/coverage/src/commands/index.html +32 -32
  10. package/coverage/src/commands/loop-command.ts.html +170 -170
  11. package/coverage/src/commands/tasks-command.ts.html +129 -129
  12. package/coverage/src/coordinator.ts.html +26 -26
  13. package/coverage/src/index.html +61 -106
  14. package/coverage/src/index.ts.html +224 -86
  15. package/coverage/src/loop-parse.ts.html +106 -73
  16. package/coverage/src/loop-reducer.ts.html +21 -21
  17. package/coverage/src/monitor-completion-coordinator.ts.html +1 -1
  18. package/coverage/src/monitor-manager.ts.html +95 -71
  19. package/coverage/src/monitor-reducer.ts.html +15 -15
  20. package/coverage/src/notification-reducer.ts.html +6 -6
  21. package/coverage/src/reducer-backed-store.ts.html +57 -57
  22. package/coverage/src/rpc/channels.ts.html +376 -0
  23. package/coverage/src/rpc/cross-extension-rpc.ts.html +541 -0
  24. package/coverage/src/rpc/index.html +131 -0
  25. package/coverage/src/runtime/index.html +68 -23
  26. package/coverage/src/{goal-coordinator.ts.html → runtime/loop-events.ts.html} +79 -73
  27. package/coverage/src/runtime/monitor-ondone-runtime.ts.html +5 -5
  28. package/coverage/src/runtime/native-task-rpc.ts.html +502 -0
  29. package/coverage/src/runtime/notification-runtime.ts.html +22 -22
  30. package/coverage/src/runtime/scope.ts.html +14 -14
  31. package/coverage/src/runtime/session-runtime.ts.html +32 -32
  32. package/coverage/src/runtime/task-backlog-runtime.ts.html +65 -23
  33. package/coverage/src/runtime/task-events.ts.html +2 -2
  34. package/coverage/src/runtime/task-mutations.ts.html +394 -0
  35. package/coverage/src/runtime/task-rpc.ts.html +102 -120
  36. package/coverage/src/scheduler.ts.html +29 -29
  37. package/coverage/src/store.ts.html +27 -27
  38. package/coverage/src/task-backlog-coordinator.ts.html +8 -8
  39. package/coverage/src/task-reducer.ts.html +42 -42
  40. package/coverage/src/task-store.ts.html +49 -49
  41. package/coverage/src/tools/index.html +39 -24
  42. package/coverage/src/tools/loop-tools.ts.html +12 -21
  43. package/coverage/src/tools/monitor-tools.ts.html +12 -21
  44. package/coverage/src/tools/native-task-tools.ts.html +57 -120
  45. package/coverage/src/tools/tool-result.ts.html +97 -0
  46. package/coverage/src/trigger-system.ts.html +12 -12
  47. package/coverage/src/ui/index.html +1 -1
  48. package/coverage/src/ui/widget.ts.html +23 -23
  49. package/dist/api.d.ts +11 -0
  50. package/dist/api.js +10 -0
  51. package/dist/commands/loop-command.js +2 -2
  52. package/dist/commands/tasks-command.js +3 -3
  53. package/dist/coordinator.d.ts +1 -1
  54. package/dist/index.js +48 -3
  55. package/dist/loop-parse.js +14 -5
  56. package/dist/reducer-backed-store.d.ts +1 -1
  57. package/dist/reducer-backed-store.js +1 -1
  58. package/dist/rpc/channels.d.ts +73 -0
  59. package/dist/rpc/channels.js +30 -0
  60. package/dist/rpc/cross-extension-rpc.d.ts +59 -0
  61. package/dist/rpc/cross-extension-rpc.js +117 -0
  62. package/dist/runtime/loop-events.d.ts +26 -0
  63. package/dist/runtime/loop-events.js +26 -0
  64. package/dist/runtime/native-task-rpc.d.ts +22 -0
  65. package/dist/runtime/native-task-rpc.js +50 -0
  66. package/dist/runtime/task-backlog-runtime.d.ts +3 -0
  67. package/dist/runtime/task-backlog-runtime.js +4 -1
  68. package/dist/runtime/task-mutations.d.ts +39 -0
  69. package/dist/runtime/task-mutations.js +68 -0
  70. package/dist/runtime/task-rpc.d.ts +4 -0
  71. package/dist/runtime/task-rpc.js +40 -58
  72. package/dist/scheduler.js +1 -1
  73. package/dist/tools/loop-tools.js +1 -3
  74. package/dist/tools/monitor-tools.js +1 -3
  75. package/dist/tools/native-task-tools.d.ts +2 -6
  76. package/dist/tools/native-task-tools.js +25 -55
  77. package/dist/tools/tool-result.d.ts +8 -0
  78. package/dist/tools/tool-result.js +4 -0
  79. package/docs/architecture/state-machine-migration.md +0 -44
  80. package/docs/architecture/state-machine-reducer-event-model.md +2 -3
  81. package/package.json +6 -1
  82. package/src/api.ts +36 -0
  83. package/src/commands/loop-command.ts +2 -2
  84. package/src/commands/tasks-command.ts +3 -3
  85. package/src/coordinator.ts +1 -1
  86. package/src/index.ts +49 -3
  87. package/src/loop-parse.ts +18 -7
  88. package/src/reducer-backed-store.ts +3 -3
  89. package/src/rpc/channels.ts +97 -0
  90. package/src/rpc/cross-extension-rpc.ts +152 -0
  91. package/src/runtime/loop-events.ts +60 -0
  92. package/src/runtime/native-task-rpc.ts +139 -0
  93. package/src/runtime/task-backlog-runtime.ts +14 -0
  94. package/src/runtime/task-mutations.ts +103 -0
  95. package/src/runtime/task-rpc.ts +48 -54
  96. package/src/scheduler.ts +1 -1
  97. package/src/tools/loop-tools.ts +1 -4
  98. package/src/tools/monitor-tools.ts +1 -4
  99. package/src/tools/native-task-tools.ts +31 -52
  100. package/src/tools/tool-result.ts +4 -0
  101. package/src/trigger-system.ts +4 -4
  102. package/vitest.config.ts +7 -7
  103. package/coverage/src/goal-reducer.ts.html +0 -982
  104. package/coverage/src/goal-store.ts.html +0 -742
  105. package/coverage/src/goal-verifier.ts.html +0 -808
  106. package/dist/goal-coordinator.d.ts +0 -22
  107. package/dist/goal-coordinator.js +0 -28
  108. package/dist/goal-reducer.d.ts +0 -98
  109. package/dist/goal-reducer.js +0 -190
  110. package/dist/goal-store.d.ts +0 -22
  111. package/dist/goal-store.js +0 -188
  112. package/dist/goal-types.d.ts +0 -82
  113. package/dist/goal-types.js +0 -1
  114. package/dist/goal-verifier.d.ts +0 -20
  115. package/dist/goal-verifier.js +0 -198
  116. package/docs/architecture/goal-state-schema.md +0 -505
  117. package/src/goal-coordinator.ts +0 -58
  118. package/src/goal-reducer.ts +0 -299
  119. package/src/goal-store.ts +0 -219
  120. package/src/goal-types.ts +0 -104
  121. package/src/goal-verifier.ts +0 -241
@@ -23,16 +23,16 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">88.54% </span>
26
+ <span class="strong">87.75% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>85/96</span>
28
+ <span class='fraction'>86/98</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">81.35% </span>
33
+ <span class="strong">78.94% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>48/59</span>
35
+ <span class='fraction'>60/76</span>
36
36
  </div>
37
37
 
38
38
 
@@ -44,9 +44,9 @@
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">91.35% </span>
47
+ <span class="strong">90.36% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>74/81</span>
49
+ <span class='fraction'>75/83</span>
50
50
  </div>
51
51
 
52
52
 
@@ -226,14 +226,27 @@
226
226
  <a name='L161'></a><a href='#L161'>161</a>
227
227
  <a name='L162'></a><a href='#L162'>162</a>
228
228
  <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">7x</span>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">8x</span>
230
241
  <span class="cline-any cline-neutral">&nbsp;</span>
231
242
  <span class="cline-any cline-neutral">&nbsp;</span>
232
243
  <span class="cline-any cline-neutral">&nbsp;</span>
233
244
  <span class="cline-any cline-neutral">&nbsp;</span>
234
245
  <span class="cline-any cline-neutral">&nbsp;</span>
235
246
  <span class="cline-any cline-neutral">&nbsp;</span>
236
- <span class="cline-any cline-yes">7x</span>
247
+ <span class="cline-any cline-yes">8x</span>
248
+ <span class="cline-any cline-neutral">&nbsp;</span>
249
+ <span class="cline-any cline-neutral">&nbsp;</span>
237
250
  <span class="cline-any cline-neutral">&nbsp;</span>
238
251
  <span class="cline-any cline-neutral">&nbsp;</span>
239
252
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -251,16 +264,16 @@
251
264
  <span class="cline-any cline-neutral">&nbsp;</span>
252
265
  <span class="cline-any cline-neutral">&nbsp;</span>
253
266
  <span class="cline-any cline-neutral">&nbsp;</span>
254
- <span class="cline-any cline-yes">260x</span>
255
- <span class="cline-any cline-yes">20x</span>
256
- <span class="cline-any cline-yes">20x</span>
257
- <span class="cline-any cline-yes">280x</span>
267
+ <span class="cline-any cline-yes">325x</span>
268
+ <span class="cline-any cline-yes">25x</span>
269
+ <span class="cline-any cline-yes">25x</span>
270
+ <span class="cline-any cline-yes">350x</span>
258
271
  <span class="cline-any cline-neutral">&nbsp;</span>
259
272
  <span class="cline-any cline-neutral">&nbsp;</span>
260
- <span class="cline-any cline-yes">20x</span>
273
+ <span class="cline-any cline-yes">25x</span>
261
274
  <span class="cline-any cline-neutral">&nbsp;</span>
262
- <span class="cline-any cline-yes">20x</span>
263
- <span class="cline-any cline-yes">16x</span>
275
+ <span class="cline-any cline-yes">25x</span>
276
+ <span class="cline-any cline-yes">21x</span>
264
277
  <span class="cline-any cline-neutral">&nbsp;</span>
265
278
  <span class="cline-any cline-yes">4x</span>
266
279
  <span class="cline-any cline-yes">4x</span>
@@ -271,78 +284,87 @@
271
284
  <span class="cline-any cline-neutral">&nbsp;</span>
272
285
  <span class="cline-any cline-neutral">&nbsp;</span>
273
286
  <span class="cline-any cline-neutral">&nbsp;</span>
274
- <span class="cline-any cline-yes">20x</span>
287
+ <span class="cline-any cline-yes">25x</span>
275
288
  <span class="cline-any cline-neutral">&nbsp;</span>
276
289
  <span class="cline-any cline-neutral">&nbsp;</span>
277
290
  <span class="cline-any cline-neutral">&nbsp;</span>
278
- <span class="cline-any cline-yes">33x</span>
279
- <span class="cline-any cline-yes">33x</span>
291
+ <span class="cline-any cline-yes">39x</span>
292
+ <span class="cline-any cline-yes">39x</span>
280
293
  <span class="cline-any cline-neutral">&nbsp;</span>
281
294
  <span class="cline-any cline-neutral">&nbsp;</span>
282
295
  <span class="cline-any cline-neutral">&nbsp;</span>
283
- <span class="cline-any cline-yes">33x</span>
296
+ <span class="cline-any cline-yes">39x</span>
284
297
  <span class="cline-any cline-neutral">&nbsp;</span>
285
- <span class="cline-any cline-yes">33x</span>
298
+ <span class="cline-any cline-yes">39x</span>
286
299
  <span class="cline-any cline-yes">9x</span>
287
300
  <span class="cline-any cline-neutral">&nbsp;</span>
288
301
  <span class="cline-any cline-neutral">&nbsp;</span>
289
- <span class="cline-any cline-yes">24x</span>
290
- <span class="cline-any cline-yes">24x</span>
291
- <span class="cline-any cline-yes">22x</span>
292
- <span class="cline-any cline-yes">22x</span>
293
- <span class="cline-any cline-yes">22x</span>
302
+ <span class="cline-any cline-yes">30x</span>
303
+ <span class="cline-any cline-yes">30x</span>
304
+ <span class="cline-any cline-yes">27x</span>
305
+ <span class="cline-any cline-yes">27x</span>
306
+ <span class="cline-any cline-yes">27x</span>
294
307
  <span class="cline-any cline-neutral">&nbsp;</span>
295
- <span class="cline-any cline-yes">22x</span>
308
+ <span class="cline-any cline-yes">27x</span>
296
309
  <span class="cline-any cline-yes">2x</span>
297
310
  <span class="cline-any cline-neutral">&nbsp;</span>
298
311
  <span class="cline-any cline-neutral">&nbsp;</span>
299
- <span class="cline-any cline-yes">20x</span>
312
+ <span class="cline-any cline-yes">25x</span>
300
313
  <span class="cline-any cline-neutral">&nbsp;</span>
301
314
  <span class="cline-any cline-neutral">&nbsp;</span>
302
- <span class="cline-any cline-yes">2x</span>
303
- <span class="cline-any cline-neutral">&nbsp;</span>
315
+ <span class="cline-any cline-yes">3x</span>
304
316
  <span class="cline-any cline-neutral">&nbsp;</span>
305
317
  <span class="cline-any cline-neutral">&nbsp;</span>
306
318
  <span class="cline-any cline-neutral">&nbsp;</span>
307
319
  <span class="cline-any cline-neutral">&nbsp;</span>
308
- <span class="cline-any cline-yes">43x</span>
309
- <span class="cline-any cline-yes">43x</span>
310
320
  <span class="cline-any cline-neutral">&nbsp;</span>
311
321
  <span class="cline-any cline-yes">42x</span>
312
322
  <span class="cline-any cline-yes">42x</span>
313
- <span class="cline-any cline-yes">42x</span>
314
323
  <span class="cline-any cline-neutral">&nbsp;</span>
315
- <span class="cline-any cline-yes">42x</span>
316
- <span class="cline-any cline-yes">1640x</span>
324
+ <span class="cline-any cline-yes">41x</span>
325
+ <span class="cline-any cline-yes">41x</span>
326
+ <span class="cline-any cline-neutral">&nbsp;</span>
327
+ <span class="cline-any cline-neutral">&nbsp;</span>
317
328
  <span class="cline-any cline-neutral">&nbsp;</span>
318
- <span class="cline-any cline-yes">1640x</span>
319
- <span class="cline-any cline-yes">62x</span>
320
- <span class="cline-any cline-yes">42x</span>
321
- <span class="cline-any cline-yes">42x</span>
322
- <span class="cline-any cline-yes">42x</span>
323
329
  <span class="cline-any cline-neutral">&nbsp;</span>
324
- <span class="cline-any cline-yes">42x</span>
325
330
  <span class="cline-any cline-neutral">&nbsp;</span>
326
331
  <span class="cline-any cline-neutral">&nbsp;</span>
327
332
  <span class="cline-any cline-no">&nbsp;</span>
328
333
  <span class="cline-any cline-neutral">&nbsp;</span>
334
+ <span class="cline-any cline-yes">41x</span>
335
+ <span class="cline-any cline-yes">41x</span>
329
336
  <span class="cline-any cline-neutral">&nbsp;</span>
337
+ <span class="cline-any cline-yes">41x</span>
338
+ <span class="cline-any cline-yes">1453x</span>
330
339
  <span class="cline-any cline-neutral">&nbsp;</span>
331
- <span class="cline-any cline-yes">1828x</span>
340
+ <span class="cline-any cline-yes">1453x</span>
341
+ <span class="cline-any cline-yes">57x</span>
342
+ <span class="cline-any cline-yes">41x</span>
343
+ <span class="cline-any cline-yes">41x</span>
344
+ <span class="cline-any cline-yes">41x</span>
332
345
  <span class="cline-any cline-neutral">&nbsp;</span>
333
- <span class="cline-any cline-yes">1666x</span>
334
- <span class="cline-any cline-yes">1666x</span>
335
- <span class="cline-any cline-yes">1706x</span>
346
+ <span class="cline-any cline-yes">41x</span>
347
+ <span class="cline-any cline-neutral">&nbsp;</span>
348
+ <span class="cline-any cline-neutral">&nbsp;</span>
349
+ <span class="cline-any cline-no">&nbsp;</span>
336
350
  <span class="cline-any cline-neutral">&nbsp;</span>
337
- <span class="cline-any cline-yes">1706x</span>
338
- <span class="cline-any cline-yes">97x</span>
339
- <span class="cline-any cline-yes">97x</span>
340
351
  <span class="cline-any cline-neutral">&nbsp;</span>
341
352
  <span class="cline-any cline-neutral">&nbsp;</span>
353
+ <span class="cline-any cline-yes">1633x</span>
342
354
  <span class="cline-any cline-neutral">&nbsp;</span>
343
- <span class="cline-any cline-yes">97x</span>
344
- <span class="cline-any cline-yes">97x</span>
345
- <span class="cline-any cline-yes">97x</span>
355
+ <span class="cline-any cline-yes">1475x</span>
356
+ <span class="cline-any cline-yes">1475x</span>
357
+ <span class="cline-any cline-yes">1515x</span>
358
+ <span class="cline-any cline-neutral">&nbsp;</span>
359
+ <span class="cline-any cline-yes">1515x</span>
360
+ <span class="cline-any cline-yes">116x</span>
361
+ <span class="cline-any cline-yes">116x</span>
362
+ <span class="cline-any cline-neutral">&nbsp;</span>
363
+ <span class="cline-any cline-neutral">&nbsp;</span>
364
+ <span class="cline-any cline-neutral">&nbsp;</span>
365
+ <span class="cline-any cline-yes">116x</span>
366
+ <span class="cline-any cline-yes">116x</span>
367
+ <span class="cline-any cline-yes">116x</span>
346
368
  <span class="cline-any cline-no">&nbsp;</span>
347
369
  <span class="cline-any cline-no">&nbsp;</span>
348
370
  <span class="cline-any cline-no">&nbsp;</span>
@@ -351,15 +373,15 @@
351
373
  <span class="cline-any cline-no">&nbsp;</span>
352
374
  <span class="cline-any cline-neutral">&nbsp;</span>
353
375
  <span class="cline-any cline-neutral">&nbsp;</span>
354
- <span class="cline-any cline-yes">97x</span>
355
- <span class="cline-any cline-yes">97x</span>
356
- <span class="cline-any cline-yes">1011x</span>
357
- <span class="cline-any cline-yes">978x</span>
376
+ <span class="cline-any cline-yes">116x</span>
377
+ <span class="cline-any cline-yes">116x</span>
378
+ <span class="cline-any cline-yes">1140x</span>
379
+ <span class="cline-any cline-yes">1108x</span>
358
380
  <span class="cline-any cline-neutral">&nbsp;</span>
359
- <span class="cline-any cline-yes">64x</span>
381
+ <span class="cline-any cline-yes">84x</span>
360
382
  <span class="cline-any cline-neutral">&nbsp;</span>
361
383
  <span class="cline-any cline-neutral">&nbsp;</span>
362
- <span class="cline-any cline-yes">1609x</span>
384
+ <span class="cline-any cline-yes">1399x</span>
363
385
  <span class="cline-any cline-yes">10x</span>
364
386
  <span class="cline-any cline-yes">10x</span>
365
387
  <span class="cline-any cline-yes">10x</span>
@@ -367,22 +389,22 @@
367
389
  <span class="cline-any cline-yes">8x</span>
368
390
  <span class="cline-any cline-neutral">&nbsp;</span>
369
391
  <span class="cline-any cline-neutral">&nbsp;</span>
370
- <span class="cline-any cline-yes">1599x</span>
392
+ <span class="cline-any cline-yes">1389x</span>
371
393
  <span class="cline-any cline-neutral">&nbsp;</span>
372
394
  <span class="cline-any cline-neutral">&nbsp;</span>
373
- <span class="cline-any cline-yes">1598x</span>
395
+ <span class="cline-any cline-yes">1412x</span>
374
396
  <span class="cline-any cline-neutral">&nbsp;</span>
375
397
  <span class="cline-any cline-neutral">&nbsp;</span>
376
398
  <span class="cline-any cline-neutral">&nbsp;</span>
377
- <span class="cline-any cline-yes">33x</span>
378
- <span class="cline-any cline-yes">33x</span>
379
- <span class="cline-any cline-yes">33x</span>
380
- <span class="cline-any cline-yes">33x</span>
399
+ <span class="cline-any cline-yes">32x</span>
400
+ <span class="cline-any cline-yes">32x</span>
401
+ <span class="cline-any cline-yes">32x</span>
402
+ <span class="cline-any cline-yes">32x</span>
381
403
  <span class="cline-any cline-neutral">&nbsp;</span>
382
- <span class="cline-any cline-yes">33x</span>
404
+ <span class="cline-any cline-yes">32x</span>
383
405
  <span class="cline-any cline-neutral">&nbsp;</span>
384
- <span class="cline-any cline-yes">33x</span>
385
- <span class="cline-any cline-yes">24x</span>
406
+ <span class="cline-any cline-yes">32x</span>
407
+ <span class="cline-any cline-yes">23x</span>
386
408
  <span class="cline-any cline-neutral">&nbsp;</span>
387
409
  <span class="cline-any cline-yes">9x</span>
388
410
  <span class="cline-any cline-no">&nbsp;</span>
@@ -414,8 +436,10 @@ const COMMON_INTERVALS: Record&lt;number, string&gt; = {
414
436
  };
415
437
  &nbsp;
416
438
  function roundToNearestCommon(seconds: number): { cron: string; description: string } {
439
+ // COMMON_INTERVALS is a non-empty const table, so keys[0] and
440
+ // COMMON_INTERVALS[best] below are true invariants, not runtime fallbacks.
417
441
  const keys = Object.keys(COMMON_INTERVALS).map(Number).sort((a, b) =&gt; a - b);
418
- let best = keys[0];
442
+ let best = keys[0] as number;
419
443
  for (const k of keys) {
420
444
  if (Math.abs(k - seconds) &lt; Math.abs(best - seconds)) best = k;
421
445
  }
@@ -434,7 +458,7 @@ function roundToNearestCommon(seconds: number): { cron: string; description: str
434
458
  }
435
459
  }
436
460
  &nbsp;
437
- return { cron: COMMON_INTERVALS[best], description };
461
+ return { cron: COMMON_INTERVALS[best] as string, description };
438
462
  }
439
463
  &nbsp;
440
464
  function isFullCron(expr: string): boolean {
@@ -451,8 +475,8 @@ export function parseInterval(input: string): { cron: string; description: strin
451
475
  &nbsp;
452
476
  const match = trimmed.match(/^(\d+)\s*(s|m|h|d)$/i);
453
477
  if (match) {
454
- const value = parseInt(match[1], 10);
455
- const unit = match[2].toLowerCase();
478
+ const value = parseInt(match[1] ?? <span class="branch-1 cbranch-no" title="branch not covered" >"", 1</span>0);
479
+ const unit = (match[2] ?? <span class="branch-1 cbranch-no" title="branch not covered" >"").t</span>oLowerCase();
456
480
  const totalSec = value * (UNIT_TO_CRON[unit] ?? <span class="branch-1 cbranch-no" title="branch not covered" >60);</span>
457
481
  &nbsp;
458
482
  if (totalSec &lt; 60) {
@@ -472,6 +496,15 @@ export function cronToNextFire(cronExpr: string, fromDate: Date = new Date()): D
472
496
  if (parts.length !== 5) throw new Error(`Invalid cron expression: ${cronExpr}`);
473
497
  &nbsp;
474
498
  const [minF, hourF, dayF, monthF, dowF] = parts;
499
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (
500
+ minF === undefined ||
501
+ hourF === undefined ||
502
+ dayF === undefined ||
503
+ monthF === undefined ||
504
+ dowF === undefined
505
+ ) {
506
+ <span class="cstat-no" title="statement not covered" > throw new Error(`Invalid cron expression: ${cronExpr}`);</span>
507
+ }
475
508
  const now = new Date(fromDate);
476
509
  now.setSeconds(0, 0);
477
510
  &nbsp;
@@ -498,7 +531,7 @@ function cronFieldMatches(field: string, value: number): boolean {
498
531
  <span class="missing-if-branch" title="if path not taken" >I</span>if (part === "*") <span class="cstat-no" title="statement not covered" >return true;</span>
499
532
  &nbsp;
500
533
  if (part.includes("/")) {
501
- const [range, stepStr] = part.split("/");
534
+ const [range = "", stepStr = ""] = part.split("/");
502
535
  const step = parseInt(stepStr, 10);
503
536
  let rangeMin: number;
504
537
  let rangeMax: number;
@@ -507,7 +540,7 @@ function cronFieldMatches(field: string, value: number): boolean {
507
540
  rangeMin = 0;
508
541
  rangeMax = 59;
509
542
  } else <span class="cstat-no" title="statement not covered" ><span class="missing-if-branch" title="else path not taken" >E</span>if (range.includes("-")) {</span>
510
- const [minS, maxS] = <span class="cstat-no" title="statement not covered" >range.split("-");</span>
543
+ const [minS = <span class="branch-0 cbranch-no" title="branch not covered" >"", m</span>axS = <span class="branch-0 cbranch-no" title="branch not covered" >""] = <span class="cstat-no" title="statement not covered" >r</span>ange.split("-");</span>
511
544
  <span class="cstat-no" title="statement not covered" > rangeMin = parseInt(minS, 10);</span>
512
545
  <span class="cstat-no" title="statement not covered" > rangeMax = parseInt(maxS, 10);</span>
513
546
  } else {
@@ -523,7 +556,7 @@ function cronFieldMatches(field: string, value: number): boolean {
523
556
  }
524
557
  &nbsp;
525
558
  if (part.includes("-")) {
526
- const [minS, maxS] = part.split("-");
559
+ const [minS = "", maxS = ""] = part.split("-");
527
560
  const min = parseInt(minS, 10);
528
561
  const max = parseInt(maxS, 10);
529
562
  if (value &gt;= min &amp;&amp; value &lt;= max) return true;
@@ -559,7 +592,7 @@ export function computeJitter(taskId: string, recurring: boolean, scheduleMinute
559
592
  <div class='footer quiet pad2 space-top1 center small'>
560
593
  Code coverage generated by
561
594
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
562
- at 2026-06-23T21:49:18.784Z
595
+ at 2026-07-02T19:31:50.067Z
563
596
  </div>
564
597
  <script src="../prettify.js"></script>
565
598
  <script>
@@ -223,7 +223,7 @@
223
223
  <a name='L158'></a><a href='#L158'>158</a>
224
224
  <a name='L159'></a><a href='#L159'>159</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
225
225
  <span class="cline-any cline-neutral">&nbsp;</span>
226
- <span class="cline-any cline-yes">10x</span>
226
+ <span class="cline-any cline-yes">11x</span>
227
227
  <span class="cline-any cline-neutral">&nbsp;</span>
228
228
  <span class="cline-any cline-neutral">&nbsp;</span>
229
229
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -232,7 +232,7 @@
232
232
  <span class="cline-any cline-neutral">&nbsp;</span>
233
233
  <span class="cline-any cline-neutral">&nbsp;</span>
234
234
  <span class="cline-any cline-neutral">&nbsp;</span>
235
- <span class="cline-any cline-yes">31x</span>
235
+ <span class="cline-any cline-yes">30x</span>
236
236
  <span class="cline-any cline-neutral">&nbsp;</span>
237
237
  <span class="cline-any cline-neutral">&nbsp;</span>
238
238
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -305,17 +305,17 @@
305
305
  <span class="cline-any cline-neutral">&nbsp;</span>
306
306
  <span class="cline-any cline-neutral">&nbsp;</span>
307
307
  <span class="cline-any cline-neutral">&nbsp;</span>
308
- <span class="cline-any cline-yes">200x</span>
308
+ <span class="cline-any cline-yes">208x</span>
309
309
  <span class="cline-any cline-neutral">&nbsp;</span>
310
310
  <span class="cline-any cline-neutral">&nbsp;</span>
311
311
  <span class="cline-any cline-neutral">&nbsp;</span>
312
312
  <span class="cline-any cline-neutral">&nbsp;</span>
313
313
  <span class="cline-any cline-neutral">&nbsp;</span>
314
314
  <span class="cline-any cline-neutral">&nbsp;</span>
315
- <span class="cline-any cline-yes">201x</span>
316
- <span class="cline-any cline-yes">130x</span>
317
- <span class="cline-any cline-yes">130x</span>
318
- <span class="cline-any cline-yes">130x</span>
315
+ <span class="cline-any cline-yes">209x</span>
316
+ <span class="cline-any cline-yes">137x</span>
317
+ <span class="cline-any cline-yes">137x</span>
318
+ <span class="cline-any cline-yes">137x</span>
319
319
  <span class="cline-any cline-neutral">&nbsp;</span>
320
320
  <span class="cline-any cline-neutral">&nbsp;</span>
321
321
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -330,26 +330,26 @@
330
330
  <span class="cline-any cline-neutral">&nbsp;</span>
331
331
  <span class="cline-any cline-neutral">&nbsp;</span>
332
332
  <span class="cline-any cline-neutral">&nbsp;</span>
333
- <span class="cline-any cline-yes">130x</span>
334
- <span class="cline-any cline-yes">130x</span>
333
+ <span class="cline-any cline-yes">137x</span>
334
+ <span class="cline-any cline-yes">137x</span>
335
335
  <span class="cline-any cline-neutral">&nbsp;</span>
336
336
  <span class="cline-any cline-neutral">&nbsp;</span>
337
337
  <span class="cline-any cline-neutral">&nbsp;</span>
338
338
  <span class="cline-any cline-neutral">&nbsp;</span>
339
339
  <span class="cline-any cline-neutral">&nbsp;</span>
340
- <span class="cline-any cline-yes">71x</span>
341
- <span class="cline-any cline-yes">71x</span>
342
- <span class="cline-any cline-yes">71x</span>
340
+ <span class="cline-any cline-yes">72x</span>
341
+ <span class="cline-any cline-yes">72x</span>
342
+ <span class="cline-any cline-yes">72x</span>
343
343
  <span class="cline-any cline-neutral">&nbsp;</span>
344
- <span class="cline-any cline-yes">70x</span>
344
+ <span class="cline-any cline-yes">71x</span>
345
345
  <span class="cline-any cline-neutral">&nbsp;</span>
346
346
  <span class="cline-any cline-neutral">&nbsp;</span>
347
347
  <span class="cline-any cline-neutral">&nbsp;</span>
348
348
  <span class="cline-any cline-neutral">&nbsp;</span>
349
349
  <span class="cline-any cline-neutral">&nbsp;</span>
350
- <span class="cline-any cline-yes">33x</span>
351
- <span class="cline-any cline-yes">33x</span>
352
- <span class="cline-any cline-yes">33x</span>
350
+ <span class="cline-any cline-yes">34x</span>
351
+ <span class="cline-any cline-yes">34x</span>
352
+ <span class="cline-any cline-yes">34x</span>
353
353
  <span class="cline-any cline-neutral">&nbsp;</span>
354
354
  <span class="cline-any cline-neutral">&nbsp;</span>
355
355
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -359,8 +359,8 @@
359
359
  <span class="cline-any cline-yes">37x</span>
360
360
  <span class="cline-any cline-neutral">&nbsp;</span>
361
361
  <span class="cline-any cline-yes">37x</span>
362
- <span class="cline-any cline-yes">7x</span>
363
- <span class="cline-any cline-yes">7x</span>
362
+ <span class="cline-any cline-yes">8x</span>
363
+ <span class="cline-any cline-yes">8x</span>
364
364
  <span class="cline-any cline-neutral">&nbsp;</span>
365
365
  <span class="cline-any cline-neutral">&nbsp;</span>
366
366
  <span class="cline-any cline-yes">37x</span>
@@ -369,8 +369,8 @@
369
369
  <span class="cline-any cline-neutral">&nbsp;</span>
370
370
  <span class="cline-any cline-neutral">&nbsp;</span>
371
371
  <span class="cline-any cline-yes">37x</span>
372
- <span class="cline-any cline-yes">28x</span>
373
- <span class="cline-any cline-yes">28x</span>
372
+ <span class="cline-any cline-yes">27x</span>
373
+ <span class="cline-any cline-yes">27x</span>
374
374
  <span class="cline-any cline-neutral">&nbsp;</span>
375
375
  <span class="cline-any cline-neutral">&nbsp;</span>
376
376
  <span class="cline-any cline-yes">37x</span>
@@ -544,7 +544,7 @@ export function reduceLoopState(state: LoopReducerState, event: LoopReducerEvent
544
544
  <div class='footer quiet pad2 space-top1 center small'>
545
545
  Code coverage generated by
546
546
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
547
- at 2026-06-23T21:49:18.784Z
547
+ at 2026-07-02T19:31:50.067Z
548
548
  </div>
549
549
  <script src="../prettify.js"></script>
550
550
  <script>
@@ -142,7 +142,7 @@ export function reduceMonitorCompletionEvent(event: MonitorCompletionEvent): Mon
142
142
  <div class='footer quiet pad2 space-top1 center small'>
143
143
  Code coverage generated by
144
144
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
145
- at 2026-06-23T21:49:18.784Z
145
+ at 2026-07-02T19:31:50.067Z
146
146
  </div>
147
147
  <script src="../prettify.js"></script>
148
148
  <script>