@usine/engine 0.2.0 → 0.4.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 (192) hide show
  1. package/README.md +109 -36
  2. package/dist/board-moves/board-moves.d.ts +20 -0
  3. package/dist/board-moves/board-moves.d.ts.map +1 -0
  4. package/dist/board-moves/board-moves.js +74 -0
  5. package/dist/board-moves/board-moves.js.map +1 -0
  6. package/dist/board-moves/model.d.ts +21 -0
  7. package/dist/board-moves/model.d.ts.map +1 -0
  8. package/dist/board-moves/model.js +22 -0
  9. package/dist/board-moves/model.js.map +1 -0
  10. package/dist/cursor/cursor.d.ts +2 -6
  11. package/dist/cursor/cursor.d.ts.map +1 -1
  12. package/dist/cursor/cursor.js +2 -6
  13. package/dist/cursor/cursor.js.map +1 -1
  14. package/dist/cycle-budget/cycle-budget.d.ts +6 -6
  15. package/dist/cycle-budget/cycle-budget.d.ts.map +1 -1
  16. package/dist/cycle-budget/cycle-budget.js +5 -5
  17. package/dist/cycle-budget/cycle-budget.js.map +1 -1
  18. package/dist/cycle-budget/model.d.ts +2 -2
  19. package/dist/cycle-budget/model.d.ts.map +1 -1
  20. package/dist/cycle-budget/model.js +2 -2
  21. package/dist/cycle-budget/model.js.map +1 -1
  22. package/dist/cycle-budget/queries.d.ts +1 -1
  23. package/dist/cycle-budget/queries.d.ts.map +1 -1
  24. package/dist/cycle-budget/queries.js +3 -3
  25. package/dist/cycle-budget/queries.js.map +1 -1
  26. package/dist/database/database.d.ts +1 -1
  27. package/dist/database/database.d.ts.map +1 -1
  28. package/dist/database/local-sqlite.d.ts +10 -8
  29. package/dist/database/local-sqlite.d.ts.map +1 -1
  30. package/dist/database/local-sqlite.js +16 -9
  31. package/dist/database/local-sqlite.js.map +1 -1
  32. package/dist/database/schema.d.ts +581 -22
  33. package/dist/database/schema.d.ts.map +1 -1
  34. package/dist/database/schema.js +104 -23
  35. package/dist/database/schema.js.map +1 -1
  36. package/dist/{workflow → engine}/admission.d.ts +2 -2
  37. package/dist/engine/admission.d.ts.map +1 -0
  38. package/dist/{workflow → engine}/admission.js +4 -4
  39. package/dist/engine/admission.js.map +1 -0
  40. package/dist/engine/checkout-recovery.d.ts +69 -0
  41. package/dist/engine/checkout-recovery.d.ts.map +1 -0
  42. package/dist/engine/checkout-recovery.js +181 -0
  43. package/dist/engine/checkout-recovery.js.map +1 -0
  44. package/dist/engine/engine.d.ts +57 -24
  45. package/dist/engine/engine.d.ts.map +1 -1
  46. package/dist/engine/engine.js +144 -120
  47. package/dist/engine/engine.js.map +1 -1
  48. package/dist/engine/error.d.ts +36 -9
  49. package/dist/engine/error.d.ts.map +1 -1
  50. package/dist/engine/error.js +35 -7
  51. package/dist/engine/error.js.map +1 -1
  52. package/dist/engine/lifecycle.d.ts +81 -28
  53. package/dist/engine/lifecycle.d.ts.map +1 -1
  54. package/dist/engine/lifecycle.js +83 -44
  55. package/dist/engine/lifecycle.js.map +1 -1
  56. package/dist/engine/retry.d.ts +16 -0
  57. package/dist/engine/retry.d.ts.map +1 -0
  58. package/dist/engine/retry.js +18 -0
  59. package/dist/engine/retry.js.map +1 -0
  60. package/dist/engine/run-again.d.ts +45 -0
  61. package/dist/engine/run-again.d.ts.map +1 -0
  62. package/dist/engine/run-again.js +56 -0
  63. package/dist/engine/run-again.js.map +1 -0
  64. package/dist/engine/run-driver.d.ts +54 -0
  65. package/dist/engine/run-driver.d.ts.map +1 -0
  66. package/dist/engine/run-driver.js +362 -0
  67. package/dist/engine/run-driver.js.map +1 -0
  68. package/dist/engine/shutdown.d.ts +3 -4
  69. package/dist/engine/shutdown.d.ts.map +1 -1
  70. package/dist/engine/shutdown.js +3 -4
  71. package/dist/engine/shutdown.js.map +1 -1
  72. package/dist/engine/submission.d.ts +31 -11
  73. package/dist/engine/submission.d.ts.map +1 -1
  74. package/dist/engine/submission.js +42 -12
  75. package/dist/engine/submission.js.map +1 -1
  76. package/dist/item-projection/item-projection.d.ts +12 -4
  77. package/dist/item-projection/item-projection.d.ts.map +1 -1
  78. package/dist/item-projection/item-projection.js +41 -6
  79. package/dist/item-projection/item-projection.js.map +1 -1
  80. package/dist/item-projection/model.d.ts +5 -1
  81. package/dist/item-projection/model.d.ts.map +1 -1
  82. package/dist/item-projection/model.js +6 -2
  83. package/dist/item-projection/model.js.map +1 -1
  84. package/dist/loop-control/loop-control.d.ts +5 -5
  85. package/dist/loop-control/loop-control.d.ts.map +1 -1
  86. package/dist/loop-control/loop-control.js +4 -4
  87. package/dist/loop-control/loop-control.js.map +1 -1
  88. package/dist/loop-control/model.d.ts +1 -1
  89. package/dist/loop-control/model.d.ts.map +1 -1
  90. package/dist/loop-control/model.js +1 -1
  91. package/dist/loop-control/model.js.map +1 -1
  92. package/dist/repository-label-projection/model.d.ts +2 -2
  93. package/dist/repository-label-projection/model.d.ts.map +1 -1
  94. package/dist/repository-label-projection/model.js +2 -2
  95. package/dist/repository-label-projection/model.js.map +1 -1
  96. package/dist/repository-label-projection/repository-label-projection.d.ts +1 -1
  97. package/dist/repository-label-projection/repository-label-projection.d.ts.map +1 -1
  98. package/dist/repository-label-projection/repository-label-projection.js +1 -1
  99. package/dist/repository-label-projection/repository-label-projection.js.map +1 -1
  100. package/dist/run-reader/model.d.ts +62 -4
  101. package/dist/run-reader/model.d.ts.map +1 -1
  102. package/dist/run-reader/model.js +66 -7
  103. package/dist/run-reader/model.js.map +1 -1
  104. package/dist/run-reader/run-reader.d.ts +19 -9
  105. package/dist/run-reader/run-reader.d.ts.map +1 -1
  106. package/dist/run-reader/run-reader.js +23 -7
  107. package/dist/run-reader/run-reader.js.map +1 -1
  108. package/dist/step-executor.d.ts +65 -9
  109. package/dist/step-executor.d.ts.map +1 -1
  110. package/dist/step-executor.js +10 -2
  111. package/dist/step-executor.js.map +1 -1
  112. package/dist/store/attempt-windows.d.ts +8 -0
  113. package/dist/store/attempt-windows.d.ts.map +1 -0
  114. package/dist/store/attempt-windows.js +53 -0
  115. package/dist/store/attempt-windows.js.map +1 -0
  116. package/dist/store/codec.d.ts +381 -42
  117. package/dist/store/codec.d.ts.map +1 -1
  118. package/dist/store/codec.js +59 -15
  119. package/dist/store/codec.js.map +1 -1
  120. package/dist/store/leftovers.d.ts +10 -0
  121. package/dist/store/leftovers.d.ts.map +1 -0
  122. package/dist/store/leftovers.js +43 -0
  123. package/dist/store/leftovers.js.map +1 -0
  124. package/dist/store/loop-items.d.ts +16 -0
  125. package/dist/store/loop-items.d.ts.map +1 -0
  126. package/dist/store/loop-items.js +185 -0
  127. package/dist/store/loop-items.js.map +1 -0
  128. package/dist/store/queries.d.ts +345 -37
  129. package/dist/store/queries.d.ts.map +1 -1
  130. package/dist/store/queries.js +333 -160
  131. package/dist/store/queries.js.map +1 -1
  132. package/dist/store/store.d.ts +91 -54
  133. package/dist/store/store.d.ts.map +1 -1
  134. package/dist/store/store.js +481 -190
  135. package/dist/store/store.js.map +1 -1
  136. package/dist/store/transcript.d.ts +9 -0
  137. package/dist/store/transcript.d.ts.map +1 -0
  138. package/dist/store/transcript.js +90 -0
  139. package/dist/store/transcript.js.map +1 -0
  140. package/dist/transcript.d.ts +41 -20
  141. package/dist/transcript.d.ts.map +1 -1
  142. package/dist/transcript.js +45 -25
  143. package/dist/transcript.js.map +1 -1
  144. package/dist/trigger-condition.d.ts +23 -0
  145. package/dist/trigger-condition.d.ts.map +1 -0
  146. package/dist/trigger-condition.js +8 -0
  147. package/dist/trigger-condition.js.map +1 -0
  148. package/drizzle/20260912111855_operator_intervention/migration.sql +42 -0
  149. package/drizzle/20260912111855_operator_intervention/snapshot.json +1461 -0
  150. package/drizzle/20260917071139_resolve_run_failure/migration.sql +1 -0
  151. package/drizzle/20260917071139_resolve_run_failure/snapshot.json +1471 -0
  152. package/drizzle/20260918032643_attempt_salvage/migration.sql +1 -0
  153. package/drizzle/20260918032643_attempt_salvage/snapshot.json +1481 -0
  154. package/drizzle/20261011153856_drop_workflow_tables/migration.sql +4 -0
  155. package/drizzle/20261011153856_drop_workflow_tables/snapshot.json +1433 -0
  156. package/drizzle/20261017155043_attempt_salvage_check/migration.sql +41 -0
  157. package/drizzle/20261017155043_attempt_salvage_check/snapshot.json +1421 -0
  158. package/drizzle/20261018162700_discard_attempt_leftovers/migration.sql +1 -0
  159. package/drizzle/20261018162700_discard_attempt_leftovers/snapshot.json +1431 -0
  160. package/drizzle/20261018172605_loop_items_and_reopenings/migration.sql +15 -0
  161. package/drizzle/20261018172605_loop_items_and_reopenings/snapshot.json +1574 -0
  162. package/drizzle/20261018180339_attempt_ended_at/migration.sql +1 -0
  163. package/drizzle/20261018180339_attempt_ended_at/snapshot.json +1584 -0
  164. package/drizzle/20261019104043_run_approval_source/migration.sql +15 -0
  165. package/drizzle/20261019104043_run_approval_source/snapshot.json +1610 -0
  166. package/drizzle/20261019133538_board_moves/migration.sql +14 -0
  167. package/drizzle/20261019133538_board_moves/snapshot.json +1731 -0
  168. package/drizzle/20261019170538_item_projection_gone/migration.sql +1 -0
  169. package/drizzle/20261019170538_item_projection_gone/snapshot.json +1741 -0
  170. package/drizzle/20261019180649_run_again_events/migration.sql +7 -0
  171. package/drizzle/20261019180649_run_again_events/snapshot.json +1804 -0
  172. package/drizzle/20261019185008_trigger_event_permissions/migration.sql +1 -0
  173. package/drizzle/20261019185008_trigger_event_permissions/snapshot.json +1814 -0
  174. package/drizzle/20261020103746_attempt_start/migration.sql +5 -0
  175. package/drizzle/20261020103746_attempt_start/snapshot.json +1844 -0
  176. package/drizzle/20261020125211_attempt_comments/migration.sql +1 -0
  177. package/drizzle/20261020125211_attempt_comments/snapshot.json +1854 -0
  178. package/drizzle/20261020191320_run_closed_at/migration.sql +6 -0
  179. package/drizzle/20261020191320_run_closed_at/snapshot.json +1864 -0
  180. package/drizzle/20261023091428_rename_loop_item_hold_to_suppression/migration.sql +2 -0
  181. package/drizzle/20261023091428_rename_loop_item_hold_to_suppression/snapshot.json +1867 -0
  182. package/package.json +15 -5
  183. package/dist/workflow/admission.d.ts.map +0 -1
  184. package/dist/workflow/admission.js.map +0 -1
  185. package/dist/workflow/command.d.ts +0 -13
  186. package/dist/workflow/command.d.ts.map +0 -1
  187. package/dist/workflow/command.js +0 -17
  188. package/dist/workflow/command.js.map +0 -1
  189. package/dist/workflow/workflow.d.ts +0 -18
  190. package/dist/workflow/workflow.d.ts.map +0 -1
  191. package/dist/workflow/workflow.js +0 -108
  192. package/dist/workflow/workflow.js.map +0 -1
package/README.md CHANGED
@@ -1,46 +1,127 @@
1
1
  # @usine/engine
2
2
 
3
- The durable run engine for [usine](https://github.com/basaltbytes/usine). It turns a synthetic Event into a Run with one named Step and a durable Attempt history.
3
+ The durable run engine for [usine](https://github.com/basaltbytes/usine). It turns a synthetic event into a run with one named step and a durable attempt history. [Run lifecycle](https://docs.usine.dev/architecture/run-lifecycle/) covers these rules in depth.
4
4
 
5
- The default adapter stores usine's Event ledger and Run projections beside Effect's workflow tables in `<instance>/.usine/runtime.sqlite`. Submitting the same dedup key joins the original Run, including after a restart.
5
+ The default adapter stores the event ledger and run records in `<instance>/.usine/runtime.sqlite`. A run's id is a hash of its event's dedup key, so submitting the same key again joins the original run, also after a restart.
6
6
 
7
- `CursorStore` keeps typed keys with JSON values in that database. Trigger adapters use it for efficiency-only cursors such as GitHub watermarks and ETags; deleting a cursor causes a safe replay because the Event ledger remains the source of deduplication.
7
+ 0.x APIs can change. Supply `effect` at the workspace's pinned version.
8
8
 
9
- `LoopControl` keeps runtime pause state in the same database. Pausing or unpausing a Loop never edits its authored Markdown file. `RunReader.list()` returns lightweight durable Run summaries newest first for observe-and-intervene surfaces, without loading Event payloads or issuing one snapshot read per Run. `RunReader.forItems(itemKeys)` reads every saved Run and its Attempts for the selected Items, independently of the recent-history window. `RunReader.revision()` lets callers reuse an unchanged projection without rescanning history.
9
+ ## Stores and readers
10
10
 
11
- `ItemProjectionReader` and `ItemProjectionWriter` store the latest issue and pull-request snapshots already fetched by trigger polling. Board consumers can read that projection after a restart without making a second GitHub query; `ItemProjectionReader.list` returns the newest Items first, bounded by the caller's `limit`. Item writes update the shared projection revision only when the content hash changes.
11
+ - `CursorStore` stores typed keys with JSON values, for efficiency-only trigger cursors such as GitHub watermarks and ETags. Deleting one safely replays events; the ledger deduplicates.
12
+ - `LoopControl` stores loop pause state; pausing never edits the loop file.
13
+ - `ItemProjectionReader` and `ItemProjectionWriter` store the latest issue and pull request snapshots from polling, which the board reads after a restart without querying GitHub. `list` returns the newest items first, up to `limit`; `openIssues` returns the numbers of open issues not marked gone. Writes change the projection revision only if the content hash changes.
14
+ - `RepositoryLabelProjectionReader` and `RepositoryLabelProjectionWriter` store each repo's full label catalog from polling, so repos without items still get proposed lanes. Writes change the revision only if the label set changes.
15
+ - `BoardMoves` (`/board-moves`) stores each board move: repo, item, send time, source and destination lanes, and labels added and removed. The orchestrator records a move before sending its labels, so the factory app's label change for the operator isn't taken for an agent's. `onItem(itemKey, since)` returns an item's moves from `since`, oldest first. Moves don't change the revision.
12
16
 
13
- `RepositoryLabelProjectionReader` and `RepositoryLabelProjectionWriter` store the complete label catalog observed during repository polling. Repositories with no Items can still receive proposed Board lanes, and the catalog remains available after a restart. Catalog writes update the projection revision only when the label set changes.
17
+ `RunReader`:
18
+
19
+ - `list()`: lightweight run summaries, newest first, without event payloads or a snapshot read per run.
20
+ - `closed({ limit })`: the runs that closed last, by their last attempt's end.
21
+ - `forItems(itemKeys)`: every saved run and its attempts for those items, outside the recent-history window.
22
+ - `events(runIds)`: in one batch, the event that opened each run. Its payload is the item as the trigger saw it, before the agent changed it.
23
+ - `evidence(runId)`: the run snapshot and all its transcript entries, in append order and unpaged, from one transaction, consistent while attempts complete or append.
24
+ - `attemptsByWorker()`: per worker, the attempts that startup still visits, and how many are open.
25
+ - `revision()`: lets callers reuse an unchanged projection.
14
26
 
15
27
  ## Runtime rules
16
28
 
17
- - Approval-gated Runs wait for an approval Event before their first Attempt.
18
- - Infrastructure failures retry automatically, with a cap of three Attempts. Agent, defect, and guard failures wait for an operator retry.
19
- - A newer Event supersedes a pending, waiting, or queued Run. A running Attempt finishes first, then the engine opens only the newest queued Event for that Item.
20
- - Revoke stops pending, waiting, and queued Runs. Operator cancellation can also stop a running Attempt.
21
- - The startup sweep rejoins open workflow executions. If the process stopped during an Attempt, the engine records that Attempt as an infrastructure failure and resumes as N+1.
22
- - A defect escaping `StepExecutor` is saved as `DefectFailure`, preserving its original cause and requiring an operator retry. If the engine itself hits an invariant defect, the workflow suspends for inspection; `RunEngine.reconcile` (or a restart) repairs the projection.
23
- - Attempt channel envelopes are stored in an append-only transcript. Durable protocol-v3 envelopes remain readable after the live channel upgrades to v4. Normalized parent and child session events retain their session identity. `RunEngine.transcript` accepts distinct `TranscriptAllQuery`, `TranscriptTailQuery`, and `TranscriptPageQuery` variants, so full diagnostics, bounded live tails, and bounded backward pages cannot be confused. Tail and page queries require a positive row limit. A protocol-v4 `Started` frame writes the SDK-selected parent model onto the Attempt.
24
- - The submitted agent, rendered task, payload snapshot, effective parent model, and per-Attempt child brain survive restarts in the run ledger.
29
+ ### Approval and retries
30
+
31
+ - Approval-gated runs wait for an approval event before their first attempt.
32
+ - Infrastructure failures retry automatically, up to three attempts. Agent, defect, and guard failures wait for an operator retry. A defect escaping `StepExecutor` is saved as `DefectFailure` with its original cause.
33
+ - `RunEngine.retry(runId, request)` takes a `RetryRequest`: the operator login and the task and agent that an edit-and-retry changes.
34
+ - `Attempt.start` records why each attempt started: the event, an operator retry or edit-and-retry with its login, an infrastructure retry, or a restart. A reattached attempt keeps its reason and records `reattachedAt`.
35
+
36
+ ### Supersede, revoke, and reopening
37
+
38
+ - A newer event supersedes a pending, waiting, or queued run. A running attempt finishes first; then only the item's newest queued event opens.
39
+ - Before it opens, `TriggerCondition` (`/trigger-condition`, supplied by the deployment) re-evaluates the loop's trigger on the item's current state. If it no longer matches, the event is recorded as ignored (revoked) and opens no run. If the item's source no longer has the item, the events are revoked and `ItemProjectionWriter.markGone` marks it gone, so the board stops showing it as open.
40
+ - Revoke stops pending, waiting, and queued runs; operator cancel also stops a running attempt.
41
+ - The engine records what each loop last saw of an item: a submitted event, or a non-matching sighting. A canceled, superseded, or revoked run keeps its event while the item stays the same, and so does a queued event that a revoke ignored. If the loop saw the item not matching or changed, and it then matches again, the event reopens with the dedup key `["reopened", n, <original key>]`, so the new run gets its own id.
42
+ - Succeeded and failed runs always keep their event. A queued event superseded by a newer one stays ignored.
43
+
44
+ ### Run again
45
+
46
+ `RunEngine.runAgain(runId, request)` opens a new run for the item state of a succeeded or canceled run, with the request's task, agent, step, approval requirement, and cycle limit. Its dedup key, `["operator-run-again", n, <trigger key>]`, is numbered with the trigger event's reopenings, so a later sighting of the unchanged item joins it. The cycle budget can block it (`CycleBlocked`), and the approval gate applies. It fails with `RunOperationRejectedError` for other states and `RunRetryBlockedError` while the loop has another open run on the item. `RunSnapshot.runAgain` names the original run and who asked.
47
+
48
+ ### Questions, blockers, and resolution
49
+
50
+ An attempt ending with `QuestionFailure` or `BlockedFailure` starts a suppression of the item for its loop. The loop's next event, usually the agent's own comment, returns `Suppressed` and opens no run; queued events wait. An event with other content, a non-matching sighting, an operator retry, or `RunEngine.resolveFailure` lifts the suppression, and resolving gives the newest queued event its turn.
51
+
52
+ `RunEngine.resolveFailure(runId, attemptId)` stores the resolution of the current failed attempt. Repeats are safe; another attempt or a run no longer failed is rejected. Snapshots and summaries include `resolvedFailureAttemptId`, and resolution updates the revision. Outcomes, attempts, transcripts, and retry stay as they were.
53
+
54
+ ### Run fibers and restarts
55
+
56
+ Each open run has one fiber, and the run tables are the only durable state. At startup and every `ReconcileInterval` (three minutes by default), the engine starts a fiber for each open run without one, except runs waiting for approval, and opens the newest queued event of an item whose run closed first. A failed store operation is retried four times with exponential backoff. If the engine fails while driving a run (a defect, or a write that still fails), the fiber logs the cause and stops until the next reconcile or restart.
57
+
58
+ After a stop during an attempt, the engine asks `StepExecutor.isLive` whether its parent task survived:
59
+
60
+ - Live: the engine reattaches the attempt, with its identity, number, and worker, using no retry. `StepExecution.reattach` tells the executor to take over the checkout.
61
+ - Finished, and `StepExecutor.outcome` returns the stored result: the engine finishes the attempt with it.
62
+ - Otherwise: the attempt fails as an infrastructure failure, and the run continues with attempt N+1.
63
+
64
+ At startup, before any fiber starts, `StepExecutor.occupy` takes a slot on the worker of each open attempt whose checkout the engine keeps, so no new attempt takes it while the run calls `isLive`. The reattached attempt runs in that slot until it ends. If the run doesn't reattach, the reattachment fails before `ExecutionSink.checkoutAcquired`, or the operator cancels first, the slot stays taken until `StepExecutor.interrupt` confirms that the parent task stopped. A reattaching run without such a slot passes the worker to `StepExecutor.reserve`, then calls `isLive` again.
65
+
66
+ Also at startup, the engine passes every stored attempt on a worker in `StepExecutor.workers` to `StepExecutor.recover`, which records its salvage and reconciles its checkout. It first stops the parent task of each closed attempt. An open attempt whose parent task is live, or whose liveness can't be read, keeps its checkout for the run.
67
+
68
+ The engine handles that checkout's recovery until the reattaching execution runs `ExecutionSink.checkoutAcquired`, which `StepExecutor.execute` runs once preparation has the checkout, never on a failed preparation. If the run closes the attempt first (the task stopped before the run reserved a worker, liveness can't be read, the reattachment failed, or the operator canceled), the engine stops the parent task with `interrupt` and passes the still-open attempt to `recover`, which reconciles regardless of `isLive`. The next attempt resumes from that salvage.
69
+
70
+ If `interrupt` can't confirm the stop, the checkout and slot stay, the fiber stops before the next attempt and logs `Could not confirm that the parent task of an Attempt its Run does not reattach stopped`, and each reconcile tries again: it reattaches if the task is live, or retries the stop. This applies after another restart too.
71
+
72
+ Attempts on a worker that `StepExecutor.workers` doesn't list aren't reconciled. `RunEngine.discardLeftovers(worker)` stops tracking them and changes nothing on the worker. For a listed worker (declared, or removed with attempts still running), it fails with `LeftoversDiscardRejectedError`, which names the worker and counts its open attempts.
73
+
74
+ ### Transcripts
75
+
76
+ Attempt channel envelopes go to an append-only transcript. A redelivered envelope (same attempt, direction, and channel sequence, as a reattached parent can send) keeps the first copy. Envelopes from protocol v3 to v6 still read under v7. Parent and child session events keep their session identity. A protocol v4 `Started` writes the SDK-selected parent model to the attempt.
77
+
78
+ `RunEngine.transcript` takes distinct query types: `TranscriptAllQuery`, `TranscriptTailQuery` and `TranscriptPageQuery` (bounded, with a positive row limit), and `TranscriptUsageQuery`, which returns each session's highest `SessionTokensUpdated` report. Session queries keep each session's launch record with its latest state, so harness session ids and worker paths stay available after completion and outside the loaded page.
25
79
 
26
- The engine's [lifecycle decisions](src/engine/lifecycle.ts) determine Attempt completion, interrupted-Attempt recovery, cancellation, operator retry, and whether a new Event can replace a Run. `RunStore` reads the current records and applies each decision in one transaction, including the Step result and pending workflow commands. Normal completion and restart recovery share the three-Attempt retry cap; reconciliation from a final workflow result closes a typed failure without retrying it. Late executor results cannot settle a replacement Attempt. Effect Workflow continues to own durable execution and signal delivery, as described in [ADR 0003](../../docs/adr/0003-durable-execution-on-effect-workflow.md).
80
+ The run ledger keeps the submitted agent, rendered task, payload snapshot, effective parent model, and each attempt's child brain across restarts.
81
+
82
+ ### Attempt windows
83
+
84
+ The sink given to `StepExecutor.execute`, and the `RecoverySink` given to `StepExecutor.recover`, read as `windows` the attempt's own window on the item and the agent's overlapping windows there (`RunStore.attemptWindows`). The harvest reads them after GitHub lists the comments, so attempts started meanwhile count, as does an end recorded when a cancel closed the attempt before the executor stopped. It keeps only comments inside the own window and no other ([ADR 0006](../../docs/adr/0006-executor-contract-run-host-attempt-channel.md), #429). An attempt that ended before end times were recorded has no window: its harvest keeps no comment, and it overlaps no other attempt.
85
+
86
+ The sink also reads back the attempt's current-protocol envelopes in append order as `transcript` (`TranscriptAllQuery`), so a reattaching executor resumes its runaway guard.
87
+
88
+ ### Lifecycle decisions
89
+
90
+ The [lifecycle decisions](src/engine/lifecycle.ts) decide attempt completion, interrupted-attempt recovery, cancellation, operator retry, and whether a new event can replace a run. `RunStore` applies each decision and its step result in one transaction. Completion and restart recovery share the three-attempt cap, and a late executor result can't settle a replacement attempt. Approval, retry, cancel, supersede, and revoke commit through the store, then start or stop the fiber. [ADR 0003](../../docs/adr/0003-durable-execution-on-effect-workflow.md) records why the engine drives runs itself.
91
+
92
+ ## Cycle budgets
93
+
94
+ `CycleBudgets` (`/cycle-budget`) stores item-level exhaustion asks and idempotent reset events. `Submission.cycleLimit` defaults to three; schedule adapters pass `None`. Admission reserves the allowance in a transaction, or returns `CycleBlocked` if the item needs a reset. Retries don't count again, and canceled runs without attempts give their reservation back. On upgrade, existing history and queued events get the default budget.
95
+
96
+ A reset records a fresh polling request. Trigger adapters read `CycleBudgets.generation(itemKey)` before fetching and put it in `Submission.cycleGeneration` and the event identity. Admission supersedes older observations, including in-flight polls and queued events, and new polling creates an event with current settings. Labels, restarts, and loop changes never clear an ask. See [ADR 0022](../../docs/adr/0022-item-cycle-budgets-and-comment-reviews.md).
97
+
98
+ ## Drain and shutdown
99
+
100
+ `RunEngine.drain()` closes attempt admission for good and waits for admitted attempts to store their outcomes. Reservations, approval gates, and retries resume after a restart; interrupting the wait leaves admission closed. The host sets a deadline and closes its runtime scope afterward ([ADR 0023](../../docs/adr/0023-graceful-attempt-drain.md)).
101
+
102
+ To handle shutdown during startup, provide `RunEngineShutdown` (`/engine`): a fresh `Deferred<void>` allocated before building the runtime. Completing it closes admission at once, recovered work included. After startup, `drain()` waits for admitted outcomes. The server installs this before building its runtime.
27
103
 
28
104
  ## Composition
29
105
 
30
- Every subpath is platform-free except the Node local adapter at `@usine/engine/local-sqlite`. Its `layer` supplies local SQLite, Effect `SingleRunner`, workflow registration, and startup reconciliation. Provide a `StepExecutor` implementation at the composition root:
106
+ All subpaths are platform-free except the Node adapter `@usine/engine/local-sqlite`, whose `layer` provides SQLite, migrations, and startup recovery. Provide a `StepExecutor` at the composition root:
31
107
 
32
108
  ```ts
33
- import { Effect, Layer } from "effect"
109
+ import { Effect, Layer, Option } from "effect"
34
110
  import { WorkerName } from "@usine/core/worker"
35
111
  import { InstanceDirectory } from "@usine/core/instance"
36
112
  import { StepResult } from "@usine/core/step/result"
37
113
  import { StepExecutor } from "@usine/engine/step-executor"
114
+ import { TriggerCondition } from "@usine/engine/trigger-condition"
38
115
  import { layer } from "@usine/engine/local-sqlite"
39
116
  import { RunEngine } from "@usine/engine/engine"
40
117
  import { CursorStore } from "@usine/engine/cursor"
41
118
  import { LoopControl } from "@usine/engine/loop-control"
42
119
 
43
120
  const StepExecutorLive = Layer.succeed(StepExecutor)({
121
+ isLive: () => Effect.succeed(false),
122
+ outcome: () => Effect.succeed(Option.none()),
123
+ recover: () => Effect.void,
124
+ intervene: () => Effect.void,
44
125
  reserve: () => Effect.succeed({
45
126
  worker: WorkerName.make("local"),
46
127
  release: Effect.void,
@@ -52,8 +133,14 @@ const StepExecutorLive = Layer.succeed(StepExecutor)({
52
133
  interrupt: () => Effect.void,
53
134
  })
54
135
 
136
+ // Re-checks a queued Event's trigger before its Run opens; this one always matches.
137
+ const TriggerConditionLive = Layer.succeed(TriggerCondition)({
138
+ recheck: () => Effect.succeed("matches"),
139
+ })
140
+
55
141
  const EngineLive = layer(InstanceDirectory.make("/path/to/instance")).pipe(
56
142
  Layer.provide(StepExecutorLive),
143
+ Layer.provide(TriggerConditionLive),
57
144
  )
58
145
 
59
146
  const program = Effect.gen(function* () {
@@ -65,30 +152,16 @@ const program = Effect.gen(function* () {
65
152
  })
66
153
  ```
67
154
 
68
- `@usine/engine/engine` provides `RunEngine`, `Submission`, submission results, and typed engine errors. `@usine/engine/run-reader` provides `RunReader` and its snapshot, summary, and evidence types; `/transcript` provides transcript entries, sequence values, and query variants. Import projection contracts from `/item-projection` and `/repository-label-projection`, and loop pause state with `LoopControl` from `/loop-control`.
69
-
70
- `RunReader.evidence(runId)` reads the Run snapshot and every transcript entry for its Attempts in one database transaction. The returned `RunEvidence` stays consistent when an Attempt completes or appends output during the read. Transcript entries use append order with no page limit.
71
-
72
- For local maintenance commands, `runReaderLayer(instanceDirectory)` from `@usine/engine/local-sqlite` provides only `RunReader` using a read-only SQLite connection. It requires an existing runtime database and does not initialize tables, migrate the schema, or change the journal mode. A missing, unreadable, or incompatible database fails through `EnginePersistenceError`.
155
+ `/engine` exports `RunEngine`, `Submission`, submission results, and typed errors; `/run-reader` exports `RunReader` and its snapshot, summary, run event, and evidence types; `/transcript` exports entries, sequences, and queries. Projection contracts are in `/item-projection` and `/repository-label-projection`, and `LoopControl` is in `/loop-control`.
73
156
 
74
- `backup(instanceDirectory, destination)` from `@usine/engine/local-sqlite` copies every runtime table and committed WAL data while other connections remain active. It opens the source read-only, without migrations. The destination must be a new file in an existing directory that supports hard links; the adapter saves a complete owner-only copy without overwriting existing files.
157
+ `runReaderLayer(instanceDirectory)` (`/local-sqlite`) provides only `RunReader`, on a read-only connection, for maintenance commands. It needs an existing database and never creates tables, migrates, or changes the journal mode. A missing, unreadable, or incompatible database fails with `EnginePersistenceError`.
75
158
 
76
- `RuntimeStoreBackupError` includes the failed operation (`open`, `stage`, `copy`, or `publish`), both paths, and the underlying error message or code. Structured logs report failures and the number of pages copied on success. If interrupted, the adapter waits for Node's backup to finish before closing its connection and deleting temporary files.
159
+ `backup(instanceDirectory, destination)` (`/local-sqlite`) copies every runtime table and committed WAL data while other connections stay open. It opens the source read-only, without migrations. The destination must be a new file in an existing directory that supports hard links; the copy is complete, owner-only, and never overwrites a file. `RuntimeStoreBackupError` gives the failed operation (`open`, `stage`, `copy`, or `publish`), both paths, and the underlying message or code. Logs report failures, or the pages copied. If interrupted, the adapter waits for Node's backup to finish before closing and deleting temporary files.
77
160
 
78
- `layerWithDatabase` from `@usine/engine/engine` accepts another SQLite-compatible database layer. That layer must provide both `RunDatabase` from `@usine/engine/database` and the matching Effect `SqlClient`, preserving atomic transactions and keeping the run projections beside Effect's cluster tables; the deployment also supplies its platform `Crypto` layer, which the cluster uses to hash over-length deduplication keys. Cloudflare D1 is not supported by Drizzle RC.4 for this use yet because its Effect driver cannot execute the store's transactions.
161
+ `layerWithDatabase` (`/engine`) takes another SQLite-compatible layer providing `RunDatabase` (`/database`) with atomic transactions, plus the platform `Crypto` layer that hashes dedup keys into run ids. Cloudflare D1 doesn't work with Drizzle RC.4, because its Effect driver can't run the store's transactions.
79
162
 
80
- The Drizzle schema is the source of truth for usine tables. After changing it, generate and review a migration with:
163
+ The Drizzle schema defines usine's tables. After changing it, generate and review a migration:
81
164
 
82
165
  ```sh
83
166
  pnpm --filter @usine/engine db:generate --name <migration_name>
84
167
  ```
85
-
86
- Everything is 0.x, so APIs may change. Supply `effect` at the version pinned by the usine workspace.
87
-
88
- `CycleBudgets` at `@usine/engine/cycle-budget` persists Item-level exhaustion Asks and explicit, idempotent reset Events. `Submission.cycleLimit` defaults to three; schedule adapters supply `None`. Run admission reserves the allowance transactionally and returns `CycleBlocked` when the Item needs a reset. Attempt retries do not charge again, and canceled Runs without Attempts return their reservation. Existing history and queued Item Events acquire the default budget on upgrade.
89
-
90
- Reset records a fresh polling request. Trigger adapters capture `CycleBudgets.generation(itemKey)` before fetching input and include it in both `Submission.cycleGeneration` and the Event identity. Older observations are superseded at admission, including in-flight polls and queued Events; fresh polling creates a new Event with current execution settings. Labels, restarts, and Loop configuration changes never clear an Ask. See [ADR 0022](../../docs/adr/0022-item-cycle-budgets-and-comment-reviews.md).
91
-
92
- `RunEngine.drain()` permanently closes Attempt admission for that runtime and waits for admitted Attempts to persist their outcomes. Worker reservations, approval gates, and subsequent retries resume after restarting the runtime. Interrupting the drain wait keeps admission closed. The host supplies a shutdown deadline and closes its runtime scope after the wait; see [ADR 0023](../../docs/adr/0023-graceful-attempt-drain.md).
93
-
94
- Hosts that handle shutdown during startup can provide `RunEngineShutdown` from `/engine`: a fresh `Deferred<void>` allocated before building the runtime. Completing it immediately closes Attempt admission, including recovered work. After startup completes, `RunEngine.drain()` waits for the admitted outcomes. The server installs this protection before building its runtime.
@@ -0,0 +1,20 @@
1
+ import type { ItemKey } from "@usine/core/item";
2
+ import { Context, type DateTime, Effect, Layer } from "effect";
3
+ import { RunDatabase } from "../database/database.ts";
4
+ import { EnginePersistenceError } from "../engine/error.ts";
5
+ import { BoardMoveRecord } from "./model.ts";
6
+ declare const BoardMoves_base: Context.ServiceClass<BoardMoves, "@usine/engine/BoardMoves", {
7
+ /** Records a move before it's sent to GitHub. If recording fails, nothing was sent. */
8
+ readonly record: (move: BoardMoveRecord) => Effect.Effect<void, EnginePersistenceError>;
9
+ /** Returns the Item's moves at or after `since`, oldest first. */
10
+ readonly onItem: (itemKey: ItemKey, since: DateTime.Utc) => Effect.Effect<ReadonlyArray<BoardMoveRecord>, EnginePersistenceError>;
11
+ }>;
12
+ /**
13
+ * The service that records the operator's Board moves, so their label changes aren't attributed
14
+ * to an Agent. Each move is recorded before its labels are sent.
15
+ */
16
+ export declare class BoardMoves extends BoardMoves_base {
17
+ static readonly layer: Layer.Layer<BoardMoves, never, RunDatabase>;
18
+ }
19
+ export { BoardMoveRecord } from "./model.ts";
20
+ //# sourceMappingURL=board-moves.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board-moves.d.ts","sourceRoot":"","sources":["../../src/board-moves/board-moves.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;;IA4EzC,uFAAuF;qBACtE,CAAC,IAAI,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACvF,kEAAkE;qBACjD,CACf,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,QAAQ,CAAC,GAAG,KAChB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,sBAAsB,CAAC;;AAb9E;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAWD;IAC7B,MAAM,CAAC,QAAQ,CAAC,KAAK,8CAA4C;CAClE;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { and, asc, eq, gte } from "drizzle-orm";
2
+ import { Context, Effect, Layer, Schema } from "effect";
3
+ import { RunDatabase } from "../database/database.js";
4
+ import { boardMoves } from "../database/schema.js";
5
+ import { EnginePersistenceError } from "../engine/error.js";
6
+ import { encodeDateTime } from "../store/codec.js";
7
+ import { BoardMoveRecord } from "./model.js";
8
+ const BoardMoveRow = Schema.Struct({
9
+ repository: BoardMoveRecord.fields.repository,
10
+ itemKey: BoardMoveRecord.fields.itemKey,
11
+ at: Schema.DateTimeUtcFromString,
12
+ fromLane: BoardMoveRecord.fields.fromLane,
13
+ toLane: BoardMoveRecord.fields.toLane,
14
+ added: BoardMoveRecord.fields.added,
15
+ removed: BoardMoveRecord.fields.removed,
16
+ });
17
+ const decodeRows = Schema.decodeUnknownEffect(Schema.Array(BoardMoveRow));
18
+ const encodeAdded = Schema.encodeSync(BoardMoveRecord.fields.added);
19
+ const encodeRemoved = Schema.encodeSync(BoardMoveRecord.fields.removed);
20
+ const persistence = (operation) => (effect) => Effect.mapError(effect, (cause) => new EnginePersistenceError({ operation, cause }));
21
+ const makeBoardMoves = Effect.gen(function* () {
22
+ const database = yield* RunDatabase;
23
+ return {
24
+ record: Effect.fn("BoardMoves.record")(function* (move) {
25
+ yield* Effect.annotateCurrentSpan({ repository: move.repository, itemKey: move.itemKey });
26
+ yield* database
27
+ .insert(boardMoves)
28
+ .values({
29
+ repository: move.repository,
30
+ itemKey: move.itemKey,
31
+ movedAt: encodeDateTime(move.at),
32
+ fromLane: move.fromLane,
33
+ toLane: move.toLane,
34
+ addedJson: encodeAdded(move.added),
35
+ removedJson: encodeRemoved(move.removed),
36
+ })
37
+ .execute();
38
+ yield* Effect.logDebug("Recorded a Board move before writing its labels", {
39
+ repository: move.repository,
40
+ itemKey: move.itemKey,
41
+ at: encodeDateTime(move.at),
42
+ fromLane: move.fromLane,
43
+ toLane: move.toLane,
44
+ });
45
+ }, persistence("record board move")),
46
+ onItem: Effect.fn("BoardMoves.onItem")(function* (itemKey, since) {
47
+ yield* Effect.annotateCurrentSpan({ itemKey });
48
+ const rows = yield* database
49
+ .select({
50
+ repository: boardMoves.repository,
51
+ itemKey: boardMoves.itemKey,
52
+ at: boardMoves.movedAt,
53
+ fromLane: boardMoves.fromLane,
54
+ toLane: boardMoves.toLane,
55
+ added: boardMoves.addedJson,
56
+ removed: boardMoves.removedJson,
57
+ })
58
+ .from(boardMoves)
59
+ .where(and(eq(boardMoves.itemKey, itemKey), gte(boardMoves.movedAt, encodeDateTime(since))))
60
+ .orderBy(asc(boardMoves.movedAt), asc(boardMoves.moveId))
61
+ .execute();
62
+ return (yield* decodeRows(rows, { onExcessProperty: "error" })).map((row) => new BoardMoveRecord(row));
63
+ }, persistence("read board moves")),
64
+ };
65
+ });
66
+ /**
67
+ * The service that records the operator's Board moves, so their label changes aren't attributed
68
+ * to an Agent. Each move is recorded before its labels are sent.
69
+ */
70
+ export class BoardMoves extends Context.Service()("@usine/engine/BoardMoves") {
71
+ static layer = Layer.effect(BoardMoves, makeBoardMoves);
72
+ }
73
+ export { BoardMoveRecord } from "./model.js";
74
+ //# sourceMappingURL=board-moves.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board-moves.js","sourceRoot":"","sources":["../../src/board-moves/board-moves.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { Schema } from "effect";
2
+ declare const BoardMoveRecord_base: Schema.Class<BoardMoveRecord, Schema.Struct<{
3
+ readonly repository: Schema.brand<Schema.String, "RepositoryName">;
4
+ readonly itemKey: Schema.brand<Schema.NonEmptyString, "ItemKey">;
5
+ readonly at: Schema.DateTimeUtc;
6
+ /** The source lane's name on the Board at the time. */
7
+ readonly fromLane: Schema.NonEmptyString;
8
+ /** The target lane's name on the Board at the time. */
9
+ readonly toLane: Schema.NonEmptyString;
10
+ readonly added: Schema.$Array<Schema.NonEmptyString>;
11
+ readonly removed: Schema.$Array<Schema.NonEmptyString>;
12
+ }>, {}>;
13
+ /**
14
+ * An operator Board move and the lane labels sent to GitHub for it, including labels that were
15
+ * already in the requested state. `at` is taken before the first label is sent, so GitHub's
16
+ * change times are at or after it, within clock skew.
17
+ */
18
+ export declare class BoardMoveRecord extends BoardMoveRecord_base {
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/board-moves/model.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;IAc5B,uDAAuD;;IAEvD,uDAAuD;;;;;AAZ3D;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,oBAYpC;CAAG"}
@@ -0,0 +1,22 @@
1
+ import { ItemKey } from "@usine/core/item";
2
+ import { RepositoryName } from "@usine/core/repository";
3
+ import { Schema } from "effect";
4
+ const LabelNames = Schema.Array(Schema.NonEmptyString);
5
+ /**
6
+ * An operator Board move and the lane labels sent to GitHub for it, including labels that were
7
+ * already in the requested state. `at` is taken before the first label is sent, so GitHub's
8
+ * change times are at or after it, within clock skew.
9
+ */
10
+ export class BoardMoveRecord extends Schema.Class("@usine/engine/BoardMoveRecord")({
11
+ repository: RepositoryName,
12
+ itemKey: ItemKey,
13
+ at: Schema.DateTimeUtc,
14
+ /** The source lane's name on the Board at the time. */
15
+ fromLane: Schema.NonEmptyString,
16
+ /** The target lane's name on the Board at the time. */
17
+ toLane: Schema.NonEmptyString,
18
+ added: LabelNames.check(Schema.isNonEmpty()),
19
+ removed: LabelNames,
20
+ }) {
21
+ }
22
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/board-moves/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AAEvD;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,MAAM,CAAC,KAAK,CAAkB,+BAA+B,CAAC,CACjG;IACE,UAAU,EAAE,cAAc;IAC1B,OAAO,EAAE,OAAO;IAChB,EAAE,EAAE,MAAM,CAAC,WAAW;IACtB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,cAAc;IAC/B,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC,cAAc;IAC7B,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;IAC5C,OAAO,EAAE,UAAU;CACpB,CACF;CAAG"}
@@ -1,18 +1,14 @@
1
1
  import { Schema, Context, Effect, Layer, Option } from "effect";
2
2
  import { RunDatabase } from "../database/database.ts";
3
3
  import { EnginePersistenceError } from "../engine/error.ts";
4
- /** Identity of one cursor. Cursors only save work, so losing one is safe. */
4
+ /** The key of a cursor; losing a cursor only repeats work. */
5
5
  export declare const CursorKey: Schema.brand<Schema.NonEmptyString, "CursorKey">;
6
6
  export type CursorKey = typeof CursorKey.Type;
7
7
  declare const CursorStore_base: Context.ServiceClass<CursorStore, "@usine/engine/CursorStore", {
8
8
  readonly read: <T, E extends Schema.Json>(key: CursorKey, schema: Schema.Codec<T, E, never, never>) => Effect.Effect<Option.Option<T>, EnginePersistenceError>;
9
9
  readonly write: <T, E extends Schema.Json>(key: CursorKey, schema: Schema.Codec<T, E, never, never>, value: T) => Effect.Effect<void, EnginePersistenceError>;
10
10
  }>;
11
- /**
12
- * Durable storage for cursors that only save work. The module that owns a key
13
- * passes its schema per call; a stored value that no longer decodes reads as
14
- * absent and is logged.
15
- */
11
+ /** The durable cursor store. A stored value that no longer decodes with `schema` reads as `None` and is logged. */
16
12
  export declare class CursorStore extends CursorStore_base {
17
13
  static readonly layer: Layer.Layer<CursorStore, never, RunDatabase>;
18
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,6EAA6E;AAC7E,eAAO,MAAM,SAAS,kDAAwD,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC;;mBAkB3B,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,EACtC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KACrC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBAC5C,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,EACvC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EACxC,KAAK,EAAE,CAAC,KACL,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC;;AAhBpD;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAaD;IAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,+CAqDnB;CACH"}
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,8DAA8D;AAC9D,eAAO,MAAM,SAAS,kDAAwD,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC;;mBAc3B,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,EACtC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KACrC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBAC5C,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,EACvC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EACxC,KAAK,EAAE,CAAC,KACL,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC;;AAZpD,mHAAmH;AACnH,qBAAa,WAAY,SAAQ,gBAaD;IAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,+CAqDnB;CACH"}
@@ -3,16 +3,12 @@ import { eq } from "drizzle-orm";
3
3
  import { RunDatabase } from "../database/database.js";
4
4
  import { cursors } from "../database/schema.js";
5
5
  import { EnginePersistenceError } from "../engine/error.js";
6
- /** Identity of one cursor. Cursors only save work, so losing one is safe. */
6
+ /** The key of a cursor; losing a cursor only repeats work. */
7
7
  export const CursorKey = Schema.NonEmptyString.pipe(Schema.brand("CursorKey"));
8
8
  const CursorRow = Schema.Struct({ value: Schema.Json });
9
9
  const decodeCursorRows = Schema.decodeUnknownEffect(Schema.Array(CursorRow));
10
10
  const persistence = (operation) => (effect) => Effect.mapError(effect, (cause) => new EnginePersistenceError({ operation, cause }));
11
- /**
12
- * Durable storage for cursors that only save work. The module that owns a key
13
- * passes its schema per call; a stored value that no longer decodes reads as
14
- * absent and is logged.
15
- */
11
+ /** The durable cursor store. A stored value that no longer decodes with `schema` reads as `None` and is logged. */
16
12
  export class CursorStore extends Context.Service()("@usine/engine/CursorStore") {
17
13
  static layer = Layer.effect(CursorStore, Effect.gen(function* () {
18
14
  const database = yield* RunDatabase;
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/cursor/cursor.ts"],"names":[],"mappings":"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"}
@@ -6,18 +6,18 @@ import { RunDatabase } from "../database/database.ts";
6
6
  import { EnginePersistenceError } from "../engine/error.ts";
7
7
  import { CycleBudgetReset, CycleBudgetResetRejectedError } from "./model.ts";
8
8
  declare const CycleBudgets_base: Context.ServiceClass<CycleBudgets, "@usine/engine/CycleBudgets", {
9
- /** Capture this generation before fetching an Item's trigger input and include it in its Event identity. */
9
+ /** Returns the Item's cycle generation; callers read it before fetching trigger input and include it in the Event identity. */
10
10
  readonly generation: (itemKey: ItemKey) => Effect.Effect<CycleGeneration, EnginePersistenceError>;
11
- /** All unanswered cycle-budget Asks, including Items whose labels no longer match. */
11
+ /** Returns all unanswered cycle-budget Asks, including those for Items whose labels no longer match. */
12
12
  readonly asks: () => Effect.Effect<ReadonlyArray<CycleBudgetAsk>, EnginePersistenceError>;
13
- /** Records an answer for this exact Ask and requests fresh trigger evaluation. Repeats are idempotent. */
13
+ /** Records the answer to the Ask and requests fresh trigger evaluation; repeated calls are idempotent. */
14
14
  readonly reset: (askId: CycleBudgetAskId, answer: Event) => Effect.Effect<void, EnginePersistenceError | CycleBudgetResetRejectedError>;
15
- /** Resets still awaiting a durable polling-cursor restart. */
15
+ /** Returns the resets that still wait for a durable polling-cursor restart. */
16
16
  readonly pendingResets: () => Effect.Effect<ReadonlyArray<CycleBudgetReset>, EnginePersistenceError>;
17
- /** Acknowledges only this generation after fresh polling progress was durably recorded. */
17
+ /** Acknowledges the reset for its generation only, after fresh polling progress is recorded. */
18
18
  readonly acknowledgeReset: (reset: CycleBudgetReset) => Effect.Effect<void, EnginePersistenceError>;
19
19
  }>;
20
- /** Durable Item-level Asks and explicit resets, independent of trigger and notification transports. */
20
+ /** The service for Item-level cycle-budget Asks and operator resets. */
21
21
  export declare class CycleBudgets extends CycleBudgets_base {
22
22
  static readonly layer: Layer.Layer<CycleBudgets, never, RunDatabase>;
23
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cycle-budget.d.ts","sourceRoot":"","sources":["../../src/cycle-budget/cycle-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;;IAgBzE,4GAA4G;yBACvF,CACnB,OAAO,EAAE,OAAO,KACb,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;IAC3D,sFAAsF;mBACvE,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACzF,0GAA0G;oBAC1F,CACd,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,KAAK,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,GAAG,6BAA6B,CAAC;IAChF,8DAA8D;4BACtC,MAAM,MAAM,CAAC,MAAM,CACzC,aAAa,CAAC,gBAAgB,CAAC,EAC/B,sBAAsB,CACvB;IACD,2FAA2F;+BAChE,CACzB,KAAK,EAAE,gBAAgB,KACpB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC;;AAvBpD,uGAAuG;AACvG,qBAAa,YAAa,SAAQ,iBAwBD;IAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,gDA+InB;CACH;AAED,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"cycle-budget.d.ts","sourceRoot":"","sources":["../../src/cycle-budget/cycle-budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC;;IAgBzE,+HAA+H;yBAC1G,CACnB,OAAO,EAAE,OAAO,KACb,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;IAC3D,wGAAwG;mBACzF,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACzF,0GAA0G;oBAC1F,CACd,KAAK,EAAE,gBAAgB,EACvB,MAAM,EAAE,KAAK,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,GAAG,6BAA6B,CAAC;IAChF,+EAA+E;4BACvD,MAAM,MAAM,CAAC,MAAM,CACzC,aAAa,CAAC,gBAAgB,CAAC,EAC/B,sBAAsB,CACvB;IACD,gGAAgG;+BACrE,CACzB,KAAK,EAAE,gBAAgB,KACpB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC;;AAvBpD,wEAAwE;AACxE,qBAAa,YAAa,SAAQ,iBAwBD;IAC/B,MAAM,CAAC,QAAQ,CAAC,KAAK,gDA+InB;CACH;AAED,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAC"}
@@ -13,7 +13,7 @@ import { cycleQueries } from "./queries.js";
13
13
  const persistence = (effect) => effect.pipe(Effect.mapError((cause) => cause instanceof CycleBudgetResetRejectedError
14
14
  ? cause
15
15
  : new EnginePersistenceError({ operation: "update cycle budget", cause })));
16
- /** Durable Item-level Asks and explicit resets, independent of trigger and notification transports. */
16
+ /** The service for Item-level cycle-budget Asks and operator resets. */
17
17
  export class CycleBudgets extends Context.Service()("@usine/engine/CycleBudgets") {
18
18
  static layer = Layer.effect(CycleBudgets, Effect.gen(function* () {
19
19
  const database = yield* RunDatabase;
@@ -30,7 +30,7 @@ export class CycleBudgets extends Context.Service()("@usine/engine/CycleBudgets"
30
30
  });
31
31
  const asks = Effect.fn("CycleBudgets.asks")(() => queries
32
32
  .asks()
33
- .pipe(Effect.mapError((cause) => new EnginePersistenceError({ operation: "read cycle Asks", cause }))));
33
+ .pipe(Effect.mapError((cause) => new EnginePersistenceError({ operation: "read cycle asks", cause }))));
34
34
  const reset = Effect.fn("CycleBudgets.reset")(function* (askId, answer) {
35
35
  yield* Effect.annotateCurrentSpan({ askId, eventId: answer.id });
36
36
  yield* database
@@ -52,7 +52,7 @@ export class CycleBudgets extends Context.Service()("@usine/engine/CycleBudgets"
52
52
  return yield* new CycleBudgetResetRejectedError({ askId });
53
53
  const budget = yield* cycleQueries(transaction).get(ask.itemKey);
54
54
  if (Option.isNone(budget))
55
- return yield* Effect.die(new Error("Open cycle Ask has no budget"));
55
+ return yield* Effect.die(new Error("Open cycle ask has no budget"));
56
56
  const generation = budget.value.generation + 1;
57
57
  yield* transaction
58
58
  .insert(events)
@@ -72,8 +72,8 @@ export class CycleBudgets extends Context.Service()("@usine/engine/CycleBudgets"
72
72
  .set({ generation, askJson: null, resetPending: true })
73
73
  .where(eq(itemCycleBudgets.itemKey, ask.itemKey))
74
74
  .execute();
75
- // Pending work retains its reservation in the new allowance. Started
76
- // Runs finish against their original allowance and retries never charge again.
75
+ // Unstarted Runs move their reservation to the new generation. Started Runs keep the
76
+ // old one, and retries don't charge again.
77
77
  yield* transaction
78
78
  .update(cycleReservations)
79
79
  .set({ generation })
@@ -1 +1 @@
1
- {"version":3,"file":"cycle-budget.js","sourceRoot":"","sources":["../../src/cycle-budget/cycle-budget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cycle-budget.js","sourceRoot":"","sources":["../../src/cycle-budget/cycle-budget.ts"],"names":[],"mappings":"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"}
@@ -5,13 +5,13 @@ declare const CycleBudgetReset_base: Schema.Class<CycleBudgetReset, Schema.Struc
5
5
  readonly repository: Schema.brand<Schema.String, "RepositoryName">;
6
6
  readonly generation: Schema.brand<Schema.Int, "CycleGeneration">;
7
7
  }>, {}>;
8
- /** A reset whose Item still needs fresh trigger evaluation; acknowledgement is generation-bound. */
8
+ /** A reset whose Item still needs fresh trigger evaluation; acknowledgment is per generation. */
9
9
  export declare class CycleBudgetReset extends CycleBudgetReset_base {
10
10
  }
11
11
  declare const CycleBudgetResetRejectedError_base: Schema.Class<CycleBudgetResetRejectedError, Schema.TaggedStruct<"CycleBudgetResetRejectedError", {
12
12
  readonly askId: Schema.brand<Schema.brand<Schema.NonEmptyString, "EventId">, "CycleBudgetAskId">;
13
13
  }>, import("effect/Cause").YieldableError>;
14
- /** The requested Ask is absent, already answered differently, or no longer current. */
14
+ /** An error for an Ask that is absent, answered differently, or no longer current. */
15
15
  export declare class CycleBudgetResetRejectedError extends CycleBudgetResetRejectedError_base {
16
16
  }
17
17
  export declare const BudgetRow: Schema.Struct<{
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/cycle-budget/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAqC,MAAM,0BAA0B,CAAC;AAG7F,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;;AAEhC,oGAAoG;AACpG,qBAAa,gBAAiB,SAAQ,qBAIpC;CAAG;;;;AAEL,uFAAuF;AACvF,qBAAa,6BAA8B,SAAQ,kCAEY;CAAG;AAElE,eAAO,MAAM,SAAS;;;;;;EAIpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/cycle-budget/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAqC,MAAM,0BAA0B,CAAC;AAG7F,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;;;;;;AAEhC,iGAAiG;AACjG,qBAAa,gBAAiB,SAAQ,qBAIpC;CAAG;;;;AAEL,sFAAsF;AACtF,qBAAa,6BAA8B,SAAQ,kCAEY;CAAG;AAElE,eAAO,MAAM,SAAS;;;;;;EAIpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAC"}
@@ -2,14 +2,14 @@ import { CycleBudgetAsk, CycleBudgetAskId, CycleGeneration } from "@usine/core/c
2
2
  import { ItemKey } from "@usine/core/item";
3
3
  import { RepositoryName } from "@usine/core/repository";
4
4
  import { Schema } from "effect";
5
- /** A reset whose Item still needs fresh trigger evaluation; acknowledgement is generation-bound. */
5
+ /** A reset whose Item still needs fresh trigger evaluation; acknowledgment is per generation. */
6
6
  export class CycleBudgetReset extends Schema.Class("CycleBudgetReset")({
7
7
  itemKey: ItemKey,
8
8
  repository: RepositoryName,
9
9
  generation: CycleGeneration,
10
10
  }) {
11
11
  }
12
- /** The requested Ask is absent, already answered differently, or no longer current. */
12
+ /** An error for an Ask that is absent, answered differently, or no longer current. */
13
13
  export class CycleBudgetResetRejectedError extends Schema.TaggedError("CycleBudgetResetRejectedError")("CycleBudgetResetRejectedError", { askId: CycleBudgetAskId }) {
14
14
  }
15
15
  export const BudgetRow = Schema.Struct({