@smthrs/engine-store 1.0.0-rc.4 → 1.0.0-rc.6

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 (257) hide show
  1. package/README.md +5 -5
  2. package/dist/cjs/ArtifactGc.d.ts +1 -1
  3. package/dist/cjs/ArtifactGc.d.ts.map +1 -1
  4. package/dist/cjs/ArtifactGc.js +1 -1
  5. package/dist/cjs/ArtifactGc.js.map +1 -1
  6. package/dist/cjs/DeferredClockFold.d.ts +4 -4
  7. package/dist/cjs/DeferredClockFold.d.ts.map +1 -1
  8. package/dist/cjs/DeferredClockFold.js +1 -1
  9. package/dist/cjs/DeferredClockFold.js.map +1 -1
  10. package/dist/cjs/DisasterRecovery.d.ts +1 -1
  11. package/dist/cjs/DisasterRecovery.d.ts.map +1 -1
  12. package/dist/cjs/DisasterRecovery.js +1 -1
  13. package/dist/cjs/DisasterRecovery.js.map +1 -1
  14. package/dist/cjs/DurableEngineState.d.ts +1 -1
  15. package/dist/cjs/DurableEngineState.d.ts.map +1 -1
  16. package/dist/cjs/DurableEngineState.js +1 -1
  17. package/dist/cjs/DurableEngineState.js.map +1 -1
  18. package/dist/cjs/ExecutionSnapshot.d.ts +2 -2
  19. package/dist/cjs/ExecutionSnapshot.d.ts.map +1 -1
  20. package/dist/cjs/ExecutionSnapshot.js +1 -1
  21. package/dist/cjs/ExecutionSnapshot.js.map +1 -1
  22. package/dist/cjs/Migrations.d.ts +2 -2
  23. package/dist/cjs/Migrations.d.ts.map +1 -1
  24. package/dist/cjs/OwnerIdentity.js +1 -1
  25. package/dist/cjs/OwnerIdentity.js.map +2 -2
  26. package/dist/cjs/PlanInputStore.d.ts +1 -1
  27. package/dist/cjs/PlanInputStore.d.ts.map +1 -1
  28. package/dist/cjs/PlanInputStore.js +1 -1
  29. package/dist/cjs/PlanInputStore.js.map +1 -1
  30. package/dist/cjs/PlanMergeStore.d.ts +1 -1
  31. package/dist/cjs/PlanMergeStore.d.ts.map +1 -1
  32. package/dist/cjs/PlanMergeStore.js +1 -1
  33. package/dist/cjs/PlanMergeStore.js.map +1 -1
  34. package/dist/cjs/Retention.d.ts +2 -2
  35. package/dist/cjs/Retention.d.ts.map +1 -1
  36. package/dist/cjs/Retention.js +1 -1
  37. package/dist/cjs/Retention.js.map +1 -1
  38. package/dist/cjs/RunChangeFeed.d.ts +1 -1
  39. package/dist/cjs/RunChangeFeed.d.ts.map +1 -1
  40. package/dist/cjs/RunChangeFeed.js +1 -1
  41. package/dist/cjs/RunChangeFeed.js.map +1 -1
  42. package/dist/cjs/SelectionStore.d.ts +1 -1
  43. package/dist/cjs/SelectionStore.d.ts.map +1 -1
  44. package/dist/cjs/SelectionStore.js +1 -1
  45. package/dist/cjs/SelectionStore.js.map +1 -1
  46. package/dist/cjs/StepBoundary.js +3 -3
  47. package/dist/cjs/StepBoundary.js.map +2 -2
  48. package/dist/cjs/StepCacheFold.d.ts +2 -2
  49. package/dist/cjs/StepCacheFold.d.ts.map +1 -1
  50. package/dist/cjs/StepCacheFold.js +1 -1
  51. package/dist/cjs/StepCacheFold.js.map +1 -1
  52. package/dist/cjs/internal/EngineStateSchema.d.ts +1 -1
  53. package/dist/cjs/internal/EngineStateSchema.d.ts.map +1 -1
  54. package/dist/cjs/internal/EngineStateSchema.js.map +1 -1
  55. package/dist/cjs/internal/ExecutionSnapshotRead.d.ts +3 -3
  56. package/dist/cjs/internal/ExecutionSnapshotRead.d.ts.map +1 -1
  57. package/dist/cjs/internal/ExecutionSnapshotRead.js.map +1 -1
  58. package/dist/cjs/internal/ExecutionSnapshotRelations.d.ts +1 -1
  59. package/dist/cjs/internal/ExecutionSnapshotRelations.d.ts.map +1 -1
  60. package/dist/cjs/internal/ExecutionSnapshotRelations.js.map +1 -1
  61. package/dist/cjs/internal/RetentionOps.d.ts +2 -2
  62. package/dist/cjs/internal/RetentionOps.d.ts.map +1 -1
  63. package/dist/cjs/internal/RetentionOps.js +1 -1
  64. package/dist/cjs/internal/RetentionOps.js.map +1 -1
  65. package/dist/cjs/internal/RunCatalogOps.d.ts +1 -1
  66. package/dist/cjs/internal/RunCatalogOps.d.ts.map +1 -1
  67. package/dist/cjs/internal/RunCatalogOps.js +1 -1
  68. package/dist/cjs/internal/RunCatalogOps.js.map +1 -1
  69. package/dist/cjs/internal/RunListing.d.ts +1 -1
  70. package/dist/cjs/internal/RunListing.d.ts.map +1 -1
  71. package/dist/cjs/internal/RunListing.js +1 -1
  72. package/dist/cjs/internal/RunListing.js.map +1 -1
  73. package/dist/cjs/migrations/0001_initial.d.ts +1 -1
  74. package/dist/cjs/migrations/0001_initial.d.ts.map +1 -1
  75. package/dist/cjs/migrations/0001_initial.js +1 -1
  76. package/dist/cjs/migrations/0001_initial.js.map +1 -1
  77. package/dist/cjs/migrations/0002_selection_store.d.ts +1 -1
  78. package/dist/cjs/migrations/0002_selection_store.d.ts.map +1 -1
  79. package/dist/cjs/migrations/0002_selection_store.js +1 -1
  80. package/dist/cjs/migrations/0002_selection_store.js.map +1 -1
  81. package/dist/cjs/migrations/0003_plan_inputs.d.ts +1 -1
  82. package/dist/cjs/migrations/0003_plan_inputs.d.ts.map +1 -1
  83. package/dist/cjs/migrations/0003_plan_inputs.js +1 -1
  84. package/dist/cjs/migrations/0003_plan_inputs.js.map +1 -1
  85. package/dist/cjs/migrations/0004_plan_environment.d.ts +1 -1
  86. package/dist/cjs/migrations/0004_plan_environment.d.ts.map +1 -1
  87. package/dist/cjs/migrations/0004_plan_environment.js +1 -1
  88. package/dist/cjs/migrations/0004_plan_environment.js.map +1 -1
  89. package/dist/cjs/migrations/0005_plan_merges.d.ts +1 -1
  90. package/dist/cjs/migrations/0005_plan_merges.d.ts.map +1 -1
  91. package/dist/cjs/migrations/0005_plan_merges.js +1 -1
  92. package/dist/cjs/migrations/0005_plan_merges.js.map +1 -1
  93. package/dist/cjs/migrations/0006_execution_listing.d.ts +1 -1
  94. package/dist/cjs/migrations/0006_execution_listing.d.ts.map +1 -1
  95. package/dist/cjs/migrations/0006_execution_listing.js +1 -1
  96. package/dist/cjs/migrations/0006_execution_listing.js.map +1 -1
  97. package/dist/cjs/migrations/0007_run_parent_sequence.d.ts +1 -1
  98. package/dist/cjs/migrations/0007_run_parent_sequence.d.ts.map +1 -1
  99. package/dist/cjs/migrations/0007_run_parent_sequence.js +1 -1
  100. package/dist/cjs/migrations/0007_run_parent_sequence.js.map +1 -1
  101. package/dist/cjs/migrations/0008_deferred_consumption.d.ts +1 -1
  102. package/dist/cjs/migrations/0008_deferred_consumption.d.ts.map +1 -1
  103. package/dist/cjs/migrations/0008_deferred_consumption.js +1 -1
  104. package/dist/cjs/migrations/0008_deferred_consumption.js.map +1 -1
  105. package/dist/cjs/migrations/0009_deferred_clock_facts.d.ts +1 -1
  106. package/dist/cjs/migrations/0009_deferred_clock_facts.d.ts.map +1 -1
  107. package/dist/cjs/migrations/0009_deferred_clock_facts.js +1 -1
  108. package/dist/cjs/migrations/0009_deferred_clock_facts.js.map +1 -1
  109. package/dist/cjs/migrations/0010_pending_cancellation.d.ts +1 -1
  110. package/dist/cjs/migrations/0010_pending_cancellation.d.ts.map +1 -1
  111. package/dist/cjs/migrations/0010_pending_cancellation.js +1 -1
  112. package/dist/cjs/migrations/0010_pending_cancellation.js.map +1 -1
  113. package/dist/cjs/test/TestStores.d.ts +4 -4
  114. package/dist/cjs/test/TestStores.d.ts.map +1 -1
  115. package/dist/esm/ArtifactGc.d.ts +1 -1
  116. package/dist/esm/ArtifactGc.d.ts.map +1 -1
  117. package/dist/esm/ArtifactGc.js +1 -1
  118. package/dist/esm/ArtifactGc.js.map +1 -1
  119. package/dist/esm/DeferredClockFold.d.ts +4 -4
  120. package/dist/esm/DeferredClockFold.d.ts.map +1 -1
  121. package/dist/esm/DeferredClockFold.js +1 -1
  122. package/dist/esm/DeferredClockFold.js.map +1 -1
  123. package/dist/esm/DisasterRecovery.d.ts +1 -1
  124. package/dist/esm/DisasterRecovery.d.ts.map +1 -1
  125. package/dist/esm/DisasterRecovery.js +1 -1
  126. package/dist/esm/DisasterRecovery.js.map +1 -1
  127. package/dist/esm/DurableEngineState.d.ts +1 -1
  128. package/dist/esm/DurableEngineState.d.ts.map +1 -1
  129. package/dist/esm/DurableEngineState.js +1 -1
  130. package/dist/esm/DurableEngineState.js.map +1 -1
  131. package/dist/esm/ExecutionSnapshot.d.ts +2 -2
  132. package/dist/esm/ExecutionSnapshot.d.ts.map +1 -1
  133. package/dist/esm/ExecutionSnapshot.js +1 -1
  134. package/dist/esm/ExecutionSnapshot.js.map +1 -1
  135. package/dist/esm/Migrations.d.ts +2 -2
  136. package/dist/esm/Migrations.d.ts.map +1 -1
  137. package/dist/esm/OwnerIdentity.js +1 -1
  138. package/dist/esm/OwnerIdentity.js.map +1 -1
  139. package/dist/esm/PlanInputStore.d.ts +1 -1
  140. package/dist/esm/PlanInputStore.d.ts.map +1 -1
  141. package/dist/esm/PlanInputStore.js +1 -1
  142. package/dist/esm/PlanInputStore.js.map +1 -1
  143. package/dist/esm/PlanMergeStore.d.ts +1 -1
  144. package/dist/esm/PlanMergeStore.d.ts.map +1 -1
  145. package/dist/esm/PlanMergeStore.js +1 -1
  146. package/dist/esm/PlanMergeStore.js.map +1 -1
  147. package/dist/esm/Retention.d.ts +2 -2
  148. package/dist/esm/Retention.d.ts.map +1 -1
  149. package/dist/esm/Retention.js +1 -1
  150. package/dist/esm/Retention.js.map +1 -1
  151. package/dist/esm/RunChangeFeed.d.ts +1 -1
  152. package/dist/esm/RunChangeFeed.d.ts.map +1 -1
  153. package/dist/esm/RunChangeFeed.js +1 -1
  154. package/dist/esm/RunChangeFeed.js.map +1 -1
  155. package/dist/esm/SelectionStore.d.ts +1 -1
  156. package/dist/esm/SelectionStore.d.ts.map +1 -1
  157. package/dist/esm/SelectionStore.js +1 -1
  158. package/dist/esm/SelectionStore.js.map +1 -1
  159. package/dist/esm/StepBoundary.js +3 -3
  160. package/dist/esm/StepBoundary.js.map +1 -1
  161. package/dist/esm/StepCacheFold.d.ts +2 -2
  162. package/dist/esm/StepCacheFold.d.ts.map +1 -1
  163. package/dist/esm/StepCacheFold.js +1 -1
  164. package/dist/esm/StepCacheFold.js.map +1 -1
  165. package/dist/esm/internal/EngineStateSchema.d.ts +1 -1
  166. package/dist/esm/internal/EngineStateSchema.d.ts.map +1 -1
  167. package/dist/esm/internal/EngineStateSchema.js.map +1 -1
  168. package/dist/esm/internal/ExecutionSnapshotRead.d.ts +3 -3
  169. package/dist/esm/internal/ExecutionSnapshotRead.d.ts.map +1 -1
  170. package/dist/esm/internal/ExecutionSnapshotRead.js.map +1 -1
  171. package/dist/esm/internal/ExecutionSnapshotRelations.d.ts +1 -1
  172. package/dist/esm/internal/ExecutionSnapshotRelations.d.ts.map +1 -1
  173. package/dist/esm/internal/ExecutionSnapshotRelations.js.map +1 -1
  174. package/dist/esm/internal/RetentionOps.d.ts +2 -2
  175. package/dist/esm/internal/RetentionOps.d.ts.map +1 -1
  176. package/dist/esm/internal/RetentionOps.js +1 -1
  177. package/dist/esm/internal/RetentionOps.js.map +1 -1
  178. package/dist/esm/internal/RunCatalogOps.d.ts +1 -1
  179. package/dist/esm/internal/RunCatalogOps.d.ts.map +1 -1
  180. package/dist/esm/internal/RunCatalogOps.js +1 -1
  181. package/dist/esm/internal/RunCatalogOps.js.map +1 -1
  182. package/dist/esm/internal/RunListing.d.ts +1 -1
  183. package/dist/esm/internal/RunListing.d.ts.map +1 -1
  184. package/dist/esm/internal/RunListing.js +1 -1
  185. package/dist/esm/internal/RunListing.js.map +1 -1
  186. package/dist/esm/migrations/0001_initial.d.ts +1 -1
  187. package/dist/esm/migrations/0001_initial.d.ts.map +1 -1
  188. package/dist/esm/migrations/0001_initial.js +1 -1
  189. package/dist/esm/migrations/0001_initial.js.map +1 -1
  190. package/dist/esm/migrations/0002_selection_store.d.ts +1 -1
  191. package/dist/esm/migrations/0002_selection_store.d.ts.map +1 -1
  192. package/dist/esm/migrations/0002_selection_store.js +1 -1
  193. package/dist/esm/migrations/0002_selection_store.js.map +1 -1
  194. package/dist/esm/migrations/0003_plan_inputs.d.ts +1 -1
  195. package/dist/esm/migrations/0003_plan_inputs.d.ts.map +1 -1
  196. package/dist/esm/migrations/0003_plan_inputs.js +1 -1
  197. package/dist/esm/migrations/0003_plan_inputs.js.map +1 -1
  198. package/dist/esm/migrations/0004_plan_environment.d.ts +1 -1
  199. package/dist/esm/migrations/0004_plan_environment.d.ts.map +1 -1
  200. package/dist/esm/migrations/0004_plan_environment.js +1 -1
  201. package/dist/esm/migrations/0004_plan_environment.js.map +1 -1
  202. package/dist/esm/migrations/0005_plan_merges.d.ts +1 -1
  203. package/dist/esm/migrations/0005_plan_merges.d.ts.map +1 -1
  204. package/dist/esm/migrations/0005_plan_merges.js +1 -1
  205. package/dist/esm/migrations/0005_plan_merges.js.map +1 -1
  206. package/dist/esm/migrations/0006_execution_listing.d.ts +1 -1
  207. package/dist/esm/migrations/0006_execution_listing.d.ts.map +1 -1
  208. package/dist/esm/migrations/0006_execution_listing.js +1 -1
  209. package/dist/esm/migrations/0006_execution_listing.js.map +1 -1
  210. package/dist/esm/migrations/0007_run_parent_sequence.d.ts +1 -1
  211. package/dist/esm/migrations/0007_run_parent_sequence.d.ts.map +1 -1
  212. package/dist/esm/migrations/0007_run_parent_sequence.js +1 -1
  213. package/dist/esm/migrations/0007_run_parent_sequence.js.map +1 -1
  214. package/dist/esm/migrations/0008_deferred_consumption.d.ts +1 -1
  215. package/dist/esm/migrations/0008_deferred_consumption.d.ts.map +1 -1
  216. package/dist/esm/migrations/0008_deferred_consumption.js +1 -1
  217. package/dist/esm/migrations/0008_deferred_consumption.js.map +1 -1
  218. package/dist/esm/migrations/0009_deferred_clock_facts.d.ts +1 -1
  219. package/dist/esm/migrations/0009_deferred_clock_facts.d.ts.map +1 -1
  220. package/dist/esm/migrations/0009_deferred_clock_facts.js +1 -1
  221. package/dist/esm/migrations/0009_deferred_clock_facts.js.map +1 -1
  222. package/dist/esm/migrations/0010_pending_cancellation.d.ts +1 -1
  223. package/dist/esm/migrations/0010_pending_cancellation.d.ts.map +1 -1
  224. package/dist/esm/migrations/0010_pending_cancellation.js +1 -1
  225. package/dist/esm/migrations/0010_pending_cancellation.js.map +1 -1
  226. package/dist/esm/test/TestStores.d.ts +4 -4
  227. package/dist/esm/test/TestStores.d.ts.map +1 -1
  228. package/package.json +22 -22
  229. package/src/ArtifactGc.ts +1 -1
  230. package/src/DeferredClockFold.ts +1 -1
  231. package/src/DisasterRecovery.ts +1 -1
  232. package/src/DurableEngineState.ts +1 -1
  233. package/src/ExecutionSnapshot.ts +1 -1
  234. package/src/OwnerIdentity.ts +1 -1
  235. package/src/PlanInputStore.ts +1 -1
  236. package/src/PlanMergeStore.ts +1 -1
  237. package/src/Retention.ts +2 -2
  238. package/src/RunChangeFeed.ts +1 -1
  239. package/src/SelectionStore.ts +1 -1
  240. package/src/StepBoundary.ts +3 -3
  241. package/src/StepCacheFold.ts +1 -1
  242. package/src/internal/EngineStateSchema.ts +1 -1
  243. package/src/internal/ExecutionSnapshotRead.ts +1 -1
  244. package/src/internal/ExecutionSnapshotRelations.ts +1 -1
  245. package/src/internal/RetentionOps.ts +2 -2
  246. package/src/internal/RunCatalogOps.ts +1 -1
  247. package/src/internal/RunListing.ts +1 -1
  248. package/src/migrations/0001_initial.ts +1 -1
  249. package/src/migrations/0002_selection_store.ts +1 -1
  250. package/src/migrations/0003_plan_inputs.ts +1 -1
  251. package/src/migrations/0004_plan_environment.ts +1 -1
  252. package/src/migrations/0005_plan_merges.ts +1 -1
  253. package/src/migrations/0006_execution_listing.ts +1 -1
  254. package/src/migrations/0007_run_parent_sequence.ts +1 -1
  255. package/src/migrations/0008_deferred_consumption.ts +1 -1
  256. package/src/migrations/0009_deferred_clock_facts.ts +1 -1
  257. package/src/migrations/0010_pending_cancellation.ts +1 -1
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import type { RunStoreError } from "@smthrs/run-store/RunStore";
7
7
  import { Context, Effect, Layer } from "effect";
8
- import * as SqlClient from "effect/unstable/sql/SqlClient";
8
+ import * as SqlClient from "effect/sql/SqlClient";
9
9
  import * as Read from "./internal/ExecutionSnapshotRead.ts";
10
10
  import * as Relations from "./internal/ExecutionSnapshotRelations.ts";
11
11
  export type { RelatedOptions, RelatedPage } from "./internal/ExecutionSnapshotRelations.ts";
@@ -73,7 +73,7 @@ export declare const maximumBatchSize = 200;
73
73
  * @category constructors
74
74
  * @since 1.0.0
75
75
  */
76
- export declare const withReadTransaction: <A, E, R>(sql: SqlClient.SqlClient, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, import("effect/unstable/sql/SqlError").SqlError | E, R>;
76
+ export declare const withReadTransaction: <A, E, R>(sql: SqlClient.SqlClient, effect: Effect.Effect<A, E, R>) => Effect.Effect<A, import("effect/sql/SqlError").SqlError | E, R>;
77
77
  /**
78
78
  * Engine observation operations.
79
79
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ExecutionSnapshot.d.ts","sourceRoot":"","sources":["../../src/ExecutionSnapshot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,IAAI,MAAM,qCAAqC,CAAA;AAC3D,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAA;AAErE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAE3F;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;AACpC;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;AACpC;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;AAClC;;;;;GAKG;AACH,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;AACzC;;;;;GAKG;AACH,MAAM,WAAW,KAAM,SAAQ,QAAQ;IACrC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;CAC5C;AACD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,iJAAmB,CAAA;AACnD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;IACrF,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,cAAc,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;CAC7G;;AACD;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,sBAEtC;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,QAAQ,EAAE,SAAS,QAAQ,KAAG,OACY,CAAA;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,IAAI,QAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CA8DrE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CAA2C,CAAA"}
1
+ {"version":3,"file":"ExecutionSnapshot.d.ts","sourceRoot":"","sources":["../../src/ExecutionSnapshot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,IAAI,MAAM,qCAAqC,CAAA;AAC3D,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAA;AAErE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0CAA0C,CAAA;AAE3F;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;AACpC;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;AACpC;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;AAClC;;;;;GAKG;AACH,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;AACzC;;;;;GAKG;AACH,MAAM,WAAW,KAAM,SAAQ,QAAQ;IACrC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;CAC5C;AACD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAA;AACnC;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,wIAAmB,CAAA;AACnD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;IACrF,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,cAAc,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;CAC7G;;AACD;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,sBAEtC;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,QAAQ,EAAE,SAAS,QAAQ,KAAG,OACY,CAAA;AAE5E;;;;;GAKG;AACH,eAAO,MAAM,IAAI,QAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CA8DrE,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CAA2C,CAAA"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import * as Dialect from "@smthrs/database/Dialect";
7
7
  import { Context, Effect, Layer, Schema } from "effect";
8
- import * as SqlClient from "effect/unstable/sql/SqlClient";
8
+ import * as SqlClient from "effect/sql/SqlClient";
9
9
  import * as Read from "./internal/ExecutionSnapshotRead.js";
10
10
  import * as Relations from "./internal/ExecutionSnapshotRelations.js";
11
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ExecutionSnapshot.js","sourceRoot":"","sources":["../../src/ExecutionSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Revisioned, round-scoped engine observations.\n *\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport type { RunStoreError } from \"@smthrs/run-store/RunStore\"\nimport { Context, Effect, Layer, Schema } from \"effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\nimport * as Read from \"./internal/ExecutionSnapshotRead.ts\"\nimport * as Relations from \"./internal/ExecutionSnapshotRelations.ts\"\n\nexport type { RelatedOptions, RelatedPage } from \"./internal/ExecutionSnapshotRelations.ts\"\n\n/**\n * Engine database identity and observed watermark.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Position = Read.Position\n/**\n * An authoritative execution row.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Observed = Read.Observed\n/**\n * A structured durable wait.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Waiting = Read.Waiting\n/**\n * Absence is explicit; deleted distinguishes retained deletion evidence.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Missing extends Position {\n readonly _tag: \"Missing\"\n readonly runId: string\n readonly deleted: boolean\n}\n/**\n * One requested execution observation.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Snapshot = Observed | Missing\n/**\n * Coherent observations in request order, including duplicates.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Batch extends Position {\n readonly snapshots: ReadonlyArray<Snapshot>\n}\n/**\n * Maximum IDs admitted by one read.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const maximumBatchSize = 200\n/**\n * Reserves a deferred SQLite / repeatable-read PostgreSQL read transaction\n * without the durable writer's admission lock. An existing transaction is\n * reused with its caller-selected isolation.\n * The supplied effect must contain observations only.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const withReadTransaction = Read.transaction\n/**\n * Engine observation operations.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Service {\n readonly read: (runIds: ReadonlyArray<string>) => Effect.Effect<Batch, RunStoreError>\n readonly related: (options: Relations.RelatedOptions) => Effect.Effect<Relations.RelatedPage, RunStoreError>\n}\n/**\n * Engine observation service.\n *\n * @category services\n * @since 1.0.0\n */\nexport class ExecutionSnapshot extends Context.Service<ExecutionSnapshot, Service>()(\n \"@smthrs/engine-store/ExecutionSnapshot\"\n) {}\n\n/**\n * Guard for applying observations and tombstones to a source-bound projection.\n * Source replacement requires an explicit rebuild, never a revision comparison.\n * @category guards\n * @since 1.0.0\n */\nexport const isNewer = (incoming: Position, current: Position): boolean =>\n incoming.source === current.source && incoming.revision > current.revision\n\n/**\n * Constructs the SQL read port; migrations must already be applied.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const make = (): Effect.Effect<Service, never, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const read: Service[\"read\"] = (runIds) =>\n Read.boundary(\n \"ExecutionSnapshot.read\",\n Effect.gen(function*() {\n const ids = yield* Read.decode(\n Schema.Array(Read.Identifier).check(Schema.isMaxLength(maximumBatchSize)),\n runIds\n )\n const batch = yield* Read.transaction(\n sql,\n Effect.gen(function*() {\n const at = yield* Read.position(sql)\n if (ids.length === 0) return { ...at, snapshots: [] }\n const rows = yield* Dialect.query(\n sql,\n `SELECT ${Read.selectColumns} FROM flows_runs r\n LEFT JOIN flows_run_changes c ON c.run_id = r.run_id\n WHERE r.run_id IN (${ids.map(() => \"?\").join(\",\")})`,\n ids\n )\n const snapshots = new Map<string, Snapshot>()\n for (const row of rows) {\n const value = yield* Read.observed(row, at)\n snapshots.set(value.runId, value)\n }\n const changes = yield* Dialect.query<{ run_id: string; revision: number; deleted: number }>(\n sql,\n `SELECT run_id, revision, deleted FROM flows_run_changes WHERE run_id IN (${\n ids.map(() => \"?\").join(\",\")\n })`,\n ids\n )\n for (const change of changes) {\n if (snapshots.has(change.run_id)) continue\n const revision = yield* Read.decode(\n Read.Natural.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(at.revision)),\n change.revision\n )\n yield* Read.decode(Schema.Literal(1), change.deleted)\n snapshots.set(change.run_id, {\n _tag: \"Missing\",\n runId: change.run_id,\n source: at.source,\n revision,\n deleted: true\n })\n }\n return {\n ...at,\n snapshots: ids.map((runId): Snapshot =>\n snapshots.get(runId) ?? { _tag: \"Missing\", runId, ...at, deleted: false }\n )\n }\n })\n )\n return yield* Read.coherentBatch(ids, batch)\n })\n )\n return { read, related: Relations.make(sql, read) }\n })\n\n/**\n * Provides the SQL observation port.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layer: Layer.Layer<ExecutionSnapshot, never, SqlClient.SqlClient> = Layer.effect(ExecutionSnapshot)(make())\n"]}
1
+ {"version":3,"file":"ExecutionSnapshot.js","sourceRoot":"","sources":["../../src/ExecutionSnapshot.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Revisioned, round-scoped engine observations.\n *\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport type { RunStoreError } from \"@smthrs/run-store/RunStore\"\nimport { Context, Effect, Layer, Schema } from \"effect\"\nimport * as SqlClient from \"effect/sql/SqlClient\"\nimport * as Read from \"./internal/ExecutionSnapshotRead.ts\"\nimport * as Relations from \"./internal/ExecutionSnapshotRelations.ts\"\n\nexport type { RelatedOptions, RelatedPage } from \"./internal/ExecutionSnapshotRelations.ts\"\n\n/**\n * Engine database identity and observed watermark.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Position = Read.Position\n/**\n * An authoritative execution row.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Observed = Read.Observed\n/**\n * A structured durable wait.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Waiting = Read.Waiting\n/**\n * Absence is explicit; deleted distinguishes retained deletion evidence.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Missing extends Position {\n readonly _tag: \"Missing\"\n readonly runId: string\n readonly deleted: boolean\n}\n/**\n * One requested execution observation.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Snapshot = Observed | Missing\n/**\n * Coherent observations in request order, including duplicates.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Batch extends Position {\n readonly snapshots: ReadonlyArray<Snapshot>\n}\n/**\n * Maximum IDs admitted by one read.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const maximumBatchSize = 200\n/**\n * Reserves a deferred SQLite / repeatable-read PostgreSQL read transaction\n * without the durable writer's admission lock. An existing transaction is\n * reused with its caller-selected isolation.\n * The supplied effect must contain observations only.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const withReadTransaction = Read.transaction\n/**\n * Engine observation operations.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Service {\n readonly read: (runIds: ReadonlyArray<string>) => Effect.Effect<Batch, RunStoreError>\n readonly related: (options: Relations.RelatedOptions) => Effect.Effect<Relations.RelatedPage, RunStoreError>\n}\n/**\n * Engine observation service.\n *\n * @category services\n * @since 1.0.0\n */\nexport class ExecutionSnapshot extends Context.Service<ExecutionSnapshot, Service>()(\n \"@smthrs/engine-store/ExecutionSnapshot\"\n) {}\n\n/**\n * Guard for applying observations and tombstones to a source-bound projection.\n * Source replacement requires an explicit rebuild, never a revision comparison.\n * @category guards\n * @since 1.0.0\n */\nexport const isNewer = (incoming: Position, current: Position): boolean =>\n incoming.source === current.source && incoming.revision > current.revision\n\n/**\n * Constructs the SQL read port; migrations must already be applied.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const make = (): Effect.Effect<Service, never, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const read: Service[\"read\"] = (runIds) =>\n Read.boundary(\n \"ExecutionSnapshot.read\",\n Effect.gen(function*() {\n const ids = yield* Read.decode(\n Schema.Array(Read.Identifier).check(Schema.isMaxLength(maximumBatchSize)),\n runIds\n )\n const batch = yield* Read.transaction(\n sql,\n Effect.gen(function*() {\n const at = yield* Read.position(sql)\n if (ids.length === 0) return { ...at, snapshots: [] }\n const rows = yield* Dialect.query(\n sql,\n `SELECT ${Read.selectColumns} FROM flows_runs r\n LEFT JOIN flows_run_changes c ON c.run_id = r.run_id\n WHERE r.run_id IN (${ids.map(() => \"?\").join(\",\")})`,\n ids\n )\n const snapshots = new Map<string, Snapshot>()\n for (const row of rows) {\n const value = yield* Read.observed(row, at)\n snapshots.set(value.runId, value)\n }\n const changes = yield* Dialect.query<{ run_id: string; revision: number; deleted: number }>(\n sql,\n `SELECT run_id, revision, deleted FROM flows_run_changes WHERE run_id IN (${\n ids.map(() => \"?\").join(\",\")\n })`,\n ids\n )\n for (const change of changes) {\n if (snapshots.has(change.run_id)) continue\n const revision = yield* Read.decode(\n Read.Natural.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(at.revision)),\n change.revision\n )\n yield* Read.decode(Schema.Literal(1), change.deleted)\n snapshots.set(change.run_id, {\n _tag: \"Missing\",\n runId: change.run_id,\n source: at.source,\n revision,\n deleted: true\n })\n }\n return {\n ...at,\n snapshots: ids.map((runId): Snapshot =>\n snapshots.get(runId) ?? { _tag: \"Missing\", runId, ...at, deleted: false }\n )\n }\n })\n )\n return yield* Read.coherentBatch(ids, batch)\n })\n )\n return { read, related: Relations.make(sql, read) }\n })\n\n/**\n * Provides the SQL observation port.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layer: Layer.Layer<ExecutionSnapshot, never, SqlClient.SqlClient> = Layer.effect(ExecutionSnapshot)(make())\n"]}
@@ -44,7 +44,7 @@ export declare const sets: ReadonlyArray<DatabaseMigrations.MigrationSet>;
44
44
  * @category migrations
45
45
  * @since 0.1.0
46
46
  */
47
- export declare const run: import("effect/Effect").Effect<readonly (readonly [id: number, name: string])[], import("effect/unstable/sql/SqlError").SqlError | import("effect/unstable/sql/Migrator").MigrationError, import("effect/unstable/sql/SqlClient").SqlClient>;
47
+ export declare const run: import("effect/Effect").Effect<readonly (readonly [id: number, name: string])[], import("effect/sql/SqlError").SqlError | import("effect/sql/Migrator").MigrationError, import("effect/sql/SqlClient").SqlClient>;
48
48
  /**
49
49
  * Layer that installs the complete durable engine schema before exposing the
50
50
  * database to any durable service.
@@ -52,5 +52,5 @@ export declare const run: import("effect/Effect").Effect<readonly (readonly [id:
52
52
  * @category layers
53
53
  * @since 0.1.0
54
54
  */
55
- export declare const layer: Layer.Layer<never, import("effect/unstable/sql/SqlError").SqlError | import("effect/unstable/sql/Migrator").MigrationError, import("effect/unstable/sql/SqlClient").SqlClient>;
55
+ export declare const layer: Layer.Layer<never, import("effect/sql/SqlError").SqlError | import("effect/sql/Migrator").MigrationError, import("effect/sql/SqlClient").SqlClient>;
56
56
  //# sourceMappingURL=Migrations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Migrations.d.ts","sourceRoot":"","sources":["../../src/Migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,kBAAkB,MAAM,6BAA6B,CAAA;AAKjE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAYrC;;;;;GAKG;AACH,eAAO,MAAM,GAAG,EAAE,kBAAkB,CAAC,YAepC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,YAAY,CAM/D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,GAAG,8OAA+B,CAAA;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,gLAA2B,CAAA"}
1
+ {"version":3,"file":"Migrations.d.ts","sourceRoot":"","sources":["../../src/Migrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,kBAAkB,MAAM,6BAA6B,CAAA;AAKjE,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAYrC;;;;;GAKG;AACH,eAAO,MAAM,GAAG,EAAE,kBAAkB,CAAC,YAepC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,YAAY,CAM/D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,GAAG,mNAA+B,CAAA;AAE/C;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,qJAA2B,CAAA"}
@@ -73,7 +73,7 @@ export const makeIncarnation = (pid, crypto) => {
73
73
  return {
74
74
  hostId,
75
75
  pid: yield* incarnationId,
76
- nonce: yield* crypto.randomUUIDv4.pipe(Effect.orDie)
76
+ nonce: yield* crypto.randomUUIDv4().pipe(Effect.orDie)
77
77
  };
78
78
  })
79
79
  });
@@ -1 +1 @@
1
- {"version":3,"file":"OwnerIdentity.js","sourceRoot":"","sources":["../../src/OwnerIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAiBvC;;;;;GAKG;AACH,MAAM,OAAO,aAAc,SAAQ,OAAO,CAAC,OAAO,EAA0B,CAAC,oCAAoC,CAAC;CAAG;AAErH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAW,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;AAE5E;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,GAAuB,EAAE,CAC5C,UAA+D,CAAC,OAAO,EAAE,GAAG,CAAA;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAuB,EAAE,MAAqB,EAAW,EAAE;IACzF,MAAM,aAAa,GAA0B,GAAG,KAAK,SAAS;QAC5D,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACvB,OAAO,IAAI,CAAC;QACV,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EAAC,MAAM;YAC1D,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YAC7C,OAAO;gBACL,MAAM;gBACN,GAAG,EAAE,KAAK,CAAC,CAAC,aAAa;gBACzB,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;aACnC,CAAA;QACrB,CAAC,CAAC;KACH,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAqD,KAAK,CAAC,MAAM,CACjF,aAAa,EACb,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,CAAC,CAChF,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAA8B,EAAE,CAC1E,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA","sourcesContent":["/**\n * The source of the fencing identity a store incarnation runs under.\n *\n * Minting an {@link OwnerId} is an act of nondeterminism against the host: it\n * reads a process identifier and draws a fresh nonce. Both belong behind a\n * port rather than in the composition itself — the closed-host doctrine in\n * `@smthrs/kernel`'s `HostServices` admits no ambient `process` and no static\n * `node:crypto` import, and browser support is a hard requirement, so a store\n * that reached for either directly could not be composed in a tab at all.\n *\n * Governing design: `docs/concepts/ownership-and-fencing.md`.\n *\n * @since 0.1.0\n */\n\nimport type { OwnerId } from \"@smthrs/journal/OwnerId\"\nimport * as Context from \"effect/Context\"\nimport * as Crypto from \"effect/Crypto\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as Random from \"effect/Random\"\n\n/**\n * Owner identity operations.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Service {\n /**\n * Mints the identity this incarnation fences its durable writes with. The\n * host supplies the incarnation; the caller supplies the host id, because\n * which host a store speaks for is a composition decision, not a host fact.\n */\n readonly ownerId: (hostId: string) => Effect.Effect<OwnerId>\n}\n\n/**\n * Service tag for the owner identity source.\n *\n * @category services\n * @since 0.1.0\n */\nexport class OwnerIdentity extends Context.Service<OwnerIdentity, Service>()(\"@smthrs/engine-store/OwnerIdentity\") {}\n\n/**\n * Constructs an owner identity source from an implementation.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = (service: Service): Service => OwnerIdentity.of(service)\n\n/**\n * The host's process identifier, when the platform has one.\n *\n * Read off `globalThis` rather than through a bare `process` reference so the\n * module carries no Node binding at all: a browser bundle sees `undefined`\n * here and falls through to a drawn incarnation number instead. The read\n * happens at layer construction — {@link layer} — so importing the module\n * touches nothing.\n */\nconst hostProcessId = (): number | undefined =>\n (globalThis as { readonly process?: { readonly pid?: number } }).process?.pid\n\n/**\n * Builds the standard identity source over an explicitly supplied process id\n * and the injected `Crypto` service.\n *\n * On node and bun `pid` is the real process id, so the minted token is exactly\n * what the store produced before this service existed. A browser tab has no\n * process, and no stable per-tab integer that means the same thing, so\n * `undefined` draws an incarnation number instead: the component's only job is\n * to distinguish concurrent incarnations on one host, and `Random` is the\n * sanctioned port for drawing one. Effect's own cluster storage does the same\n * where a backend exposes no connection pid (`reference/effect`\n * `unstable/cluster/SqlRunnerStorage.ts`).\n *\n * The nonce is a UUIDv4 drawn from the injected `effect/Crypto` service — the\n * closed-host seam every composition already provides for digesting — so no\n * ambient `crypto` global is reached from a hot path. A host whose crypto\n * cannot mint a UUID cannot fence anything, so that refusal is a defect.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const makeIncarnation = (pid: number | undefined, crypto: Crypto.Crypto): Service => {\n const incarnationId: Effect.Effect<number> = pid === undefined\n ? Random.nextIntBetween(0, Number.MAX_SAFE_INTEGER, { halfOpen: true })\n : Effect.succeed(pid)\n return make({\n ownerId: Effect.fn(\"OwnerIdentity.ownerId\")(function*(hostId) {\n yield* Effect.annotateCurrentSpan({ hostId })\n return {\n hostId,\n pid: yield* incarnationId,\n nonce: yield* crypto.randomUUIDv4.pipe(Effect.orDie)\n } satisfies OwnerId\n })\n })\n}\n\n/**\n * Provides {@link makeIncarnation} over whatever process id the running\n * platform reports and the composition's `Crypto` service. This is what\n * engine composition supplies unless a host has a better answer.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer: Layer.Layer<OwnerIdentity, never, Crypto.Crypto> = Layer.effect(\n OwnerIdentity,\n Effect.map(Crypto.Crypto, (crypto) => makeIncarnation(hostProcessId(), crypto))\n)\n\n/**\n * Provides a fixed identity. A test — or a host that derives ownership from\n * something outside this process, such as a lease it already holds — pins the\n * whole token instead of letting the default draw one.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerConstant = (owner: OwnerId): Layer.Layer<OwnerIdentity> =>\n Layer.succeed(OwnerIdentity)(make({ ownerId: () => Effect.succeed(owner) }))\n"]}
1
+ {"version":3,"file":"OwnerIdentity.js","sourceRoot":"","sources":["../../src/OwnerIdentity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAiBvC;;;;;GAKG;AACH,MAAM,OAAO,aAAc,SAAQ,OAAO,CAAC,OAAO,EAA0B,CAAC,oCAAoC,CAAC;CAAG;AAErH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAW,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;AAE5E;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,GAAuB,EAAE,CAC5C,UAA+D,CAAC,OAAO,EAAE,GAAG,CAAA;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAuB,EAAE,MAAqB,EAAW,EAAE;IACzF,MAAM,aAAa,GAA0B,GAAG,KAAK,SAAS;QAC5D,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACvB,OAAO,IAAI,CAAC;QACV,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EAAC,MAAM;YAC1D,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;YAC7C,OAAO;gBACL,MAAM;gBACN,GAAG,EAAE,KAAK,CAAC,CAAC,aAAa;gBACzB,KAAK,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;aACrC,CAAA;QACrB,CAAC,CAAC;KACH,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,KAAK,GAAqD,KAAK,CAAC,MAAM,CACjF,aAAa,EACb,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,CAAC,CAChF,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAA8B,EAAE,CAC1E,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAA","sourcesContent":["/**\n * The source of the fencing identity a store incarnation runs under.\n *\n * Minting an {@link OwnerId} is an act of nondeterminism against the host: it\n * reads a process identifier and draws a fresh nonce. Both belong behind a\n * port rather than in the composition itself — the closed-host doctrine in\n * `@smthrs/kernel`'s `HostServices` admits no ambient `process` and no static\n * `node:crypto` import, and browser support is a hard requirement, so a store\n * that reached for either directly could not be composed in a tab at all.\n *\n * Governing design: `docs/concepts/ownership-and-fencing.md`.\n *\n * @since 0.1.0\n */\n\nimport type { OwnerId } from \"@smthrs/journal/OwnerId\"\nimport * as Context from \"effect/Context\"\nimport * as Crypto from \"effect/Crypto\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport * as Random from \"effect/Random\"\n\n/**\n * Owner identity operations.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Service {\n /**\n * Mints the identity this incarnation fences its durable writes with. The\n * host supplies the incarnation; the caller supplies the host id, because\n * which host a store speaks for is a composition decision, not a host fact.\n */\n readonly ownerId: (hostId: string) => Effect.Effect<OwnerId>\n}\n\n/**\n * Service tag for the owner identity source.\n *\n * @category services\n * @since 0.1.0\n */\nexport class OwnerIdentity extends Context.Service<OwnerIdentity, Service>()(\"@smthrs/engine-store/OwnerIdentity\") {}\n\n/**\n * Constructs an owner identity source from an implementation.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = (service: Service): Service => OwnerIdentity.of(service)\n\n/**\n * The host's process identifier, when the platform has one.\n *\n * Read off `globalThis` rather than through a bare `process` reference so the\n * module carries no Node binding at all: a browser bundle sees `undefined`\n * here and falls through to a drawn incarnation number instead. The read\n * happens at layer construction — {@link layer} — so importing the module\n * touches nothing.\n */\nconst hostProcessId = (): number | undefined =>\n (globalThis as { readonly process?: { readonly pid?: number } }).process?.pid\n\n/**\n * Builds the standard identity source over an explicitly supplied process id\n * and the injected `Crypto` service.\n *\n * On node and bun `pid` is the real process id, so the minted token is exactly\n * what the store produced before this service existed. A browser tab has no\n * process, and no stable per-tab integer that means the same thing, so\n * `undefined` draws an incarnation number instead: the component's only job is\n * to distinguish concurrent incarnations on one host, and `Random` is the\n * sanctioned port for drawing one. Effect's own cluster storage does the same\n * where a backend exposes no connection pid (`reference/effect`\n * `unstable/cluster/SqlRunnerStorage.ts`).\n *\n * The nonce is a UUIDv4 drawn from the injected `effect/Crypto` service — the\n * closed-host seam every composition already provides for digesting — so no\n * ambient `crypto` global is reached from a hot path. A host whose crypto\n * cannot mint a UUID cannot fence anything, so that refusal is a defect.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const makeIncarnation = (pid: number | undefined, crypto: Crypto.Crypto): Service => {\n const incarnationId: Effect.Effect<number> = pid === undefined\n ? Random.nextIntBetween(0, Number.MAX_SAFE_INTEGER, { halfOpen: true })\n : Effect.succeed(pid)\n return make({\n ownerId: Effect.fn(\"OwnerIdentity.ownerId\")(function*(hostId) {\n yield* Effect.annotateCurrentSpan({ hostId })\n return {\n hostId,\n pid: yield* incarnationId,\n nonce: yield* crypto.randomUUIDv4().pipe(Effect.orDie)\n } satisfies OwnerId\n })\n })\n}\n\n/**\n * Provides {@link makeIncarnation} over whatever process id the running\n * platform reports and the composition's `Crypto` service. This is what\n * engine composition supplies unless a host has a better answer.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer: Layer.Layer<OwnerIdentity, never, Crypto.Crypto> = Layer.effect(\n OwnerIdentity,\n Effect.map(Crypto.Crypto, (crypto) => makeIncarnation(hostProcessId(), crypto))\n)\n\n/**\n * Provides a fixed identity. A test — or a host that derives ownership from\n * something outside this process, such as a lease it already holds — pins the\n * whole token instead of letting the default draw one.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerConstant = (owner: OwnerId): Layer.Layer<OwnerIdentity> =>\n Layer.succeed(OwnerIdentity)(make({ ownerId: () => Effect.succeed(owner) }))\n"]}
@@ -7,7 +7,7 @@ import { DurableWriter } from "@smthrs/database/DurableWriter";
7
7
  import { OwnerId } from "@smthrs/run-store/Ownership";
8
8
  import { Context, Effect, Layer, Option, Schema } from "effect";
9
9
  import type * as Crypto from "effect/Crypto";
10
- import * as SqlClient from "effect/unstable/sql/SqlClient";
10
+ import * as SqlClient from "effect/sql/SqlClient";
11
11
  /**
12
12
  * Address of an append-only observation generation. `environmentDigest` comes
13
13
  * from `StepKey.environmentIdentity` and binds every generation of the run.
@@ -1 +1 @@
1
- {"version":3,"file":"PlanInputStore.d.ts","sourceRoot":"","sources":["../../src/PlanInputStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAI1D;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;;;;EAMlB,CAAA;AACF;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AAEzD;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;EAYnB,CAAA;AACF;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;;;;;;AAE3C;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,mBAWlC;CAAG;AAEL;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAA;IAC1G,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;CACnH;;AAED;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,mBAAiF;CAAG;AAsCxH;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAuInG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAGjG,CAAA"}
1
+ {"version":3,"file":"PlanInputStore.d.ts","sourceRoot":"","sources":["../../src/PlanInputStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AAIjD;;;;;GAKG;AACH,eAAO,MAAM,OAAO;;;;;;EAMlB,CAAA;AACF;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AAEzD;;;;GAIG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;EAYnB,CAAA;AACF;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;;;;;;AAE3C;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,mBAWlC;CAAG;AAEL;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAA;IAC1G,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;CACnH;;AAED;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,mBAAiF;CAAG;AAsCxH;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAuInG,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAGjG,CAAA"}
@@ -8,7 +8,7 @@ import { DurableWriter } from "@smthrs/database/DurableWriter";
8
8
  import { FileSet, Plan } from "@smthrs/plan";
9
9
  import { OwnerId } from "@smthrs/run-store/Ownership";
10
10
  import { Context, Effect, Layer, Option, Schema } from "effect";
11
- import * as SqlClient from "effect/unstable/sql/SqlClient";
11
+ import * as SqlClient from "effect/sql/SqlClient";
12
12
  const Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
13
13
  /**
14
14
  * Address of an append-only observation generation. `environmentDigest` comes
@@ -1 +1 @@
1
- {"version":3,"file":"PlanInputStore.js","sourceRoot":"","sources":["../../src/PlanInputStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authoritative source observations for one durable plan execution. These are\n * replay state, not approval data, journal projections, or evictable cache rows.\n * @since 1.0.0\n */\n\nimport { Sha256 } from \"@smthrs/crypto\"\nimport { DurableWriter } from \"@smthrs/database/DurableWriter\"\nimport { FileSet, Plan } from \"@smthrs/plan\"\nimport { OwnerId } from \"@smthrs/run-store/Ownership\"\nimport { Context, Effect, Layer, Option, Schema } from \"effect\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\nconst Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))\n\n/**\n * Address of an append-only observation generation. `environmentDigest` comes\n * from `StepKey.environmentIdentity` and binds every generation of the run.\n * @since 1.0.0\n * @category schemas\n */\nexport const Address = Schema.Struct({\n runId: Schema.NonEmptyString,\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NonEmptyString,\n generation: Natural\n})\n/**\n * Address of an append-only observation generation.\n * @since 1.0.0\n * @category models\n */\nexport type Address = typeof Address.Type\n\n/**\n * Maximum encoded snapshot size, in JavaScript string code units.\n * @since 1.0.0\n * @category constants\n */\nexport const maximumSnapshotCharacters = 16 * 1024 * 1024\n\n/**\n * Frozen membership and newly pinned source digests for one generation.\n * @since 1.0.0\n * @category schemas\n */\nexport const Snapshot = Schema.Struct({\n version: Schema.Literal(1),\n generation: Natural,\n nodes: Schema.Array(Schema.Struct({\n id: Schema.NonEmptyString,\n key: Schema.NonEmptyString,\n reads: Schema.Array(Schema.Struct({\n entry: FileSet.ReadEntry,\n sourcePaths: Schema.Array(FileSet.Pattern)\n }))\n })).check(Schema.isMaxLength(Plan.maximumPlanNodes)),\n pins: Schema.Array(Schema.Struct({ path: FileSet.Pattern, digest: Schema.NonEmptyString }))\n})\n/**\n * Frozen membership and newly pinned source digests for one generation.\n * @since 1.0.0\n * @category models\n */\nexport type Snapshot = typeof Snapshot.Type\n\n/**\n * A durable observation cannot be read or safely admitted.\n * @since 1.0.0\n * @category errors\n */\nexport class PlanInputError extends Schema.TaggedError<PlanInputError>()(\"@smthrs/engine-store/PlanInputError\", {\n code: Schema.Literals([\n \"invalid_input\",\n \"corrupt_state\",\n \"incompatible_state\",\n \"fence_lost\",\n \"transaction_open\",\n \"persistence_failed\"\n ]),\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown)\n}) {}\n\n/**\n * `get` is a committed-state admission gate and refuses an enclosing SQL\n * transaction. `record` is first-writer-wins and may join a write transaction;\n * callers must wait for its outer commit before executing affected actions.\n * @since 1.0.0\n * @category models\n */\nexport interface Service {\n readonly get: (address: Address, owner: OwnerId) => Effect.Effect<Option.Option<Snapshot>, PlanInputError>\n readonly record: (address: Address, snapshot: Snapshot, owner: OwnerId) => Effect.Effect<Snapshot, PlanInputError>\n}\n\n/**\n * Durable plan-input service.\n * @since 1.0.0\n * @category services\n */\nexport class PlanInputStore extends Context.Service<PlanInputStore, Service>()(\"@smthrs/engine-store/PlanInputStore\") {}\n\nconst failure = (code: PlanInputError[\"code\"], message: string, cause?: unknown) =>\n new PlanInputError({ code, message, ...(cause === undefined ? {} : { cause }) })\nconst persistError = (cause: unknown) =>\n cause instanceof PlanInputError ?\n cause :\n failure(\"persistence_failed\", \"could not access durable plan inputs\", cause)\n\nconst decode = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n value: unknown,\n code: \"invalid_input\" | \"corrupt_state\"\n) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value, { onExcessProperty: \"error\" }),\n catch: (cause) => failure(code, \"invalid plan input observation\", cause)\n })\n\nconst validateSnapshot = (snapshot: Snapshot, generation: number, code: \"invalid_input\" | \"corrupt_state\") => {\n if (\n snapshot.generation !== generation ||\n new Set(snapshot.nodes.map((node) => node.id)).size !== snapshot.nodes.length ||\n new Set(snapshot.pins.map((pin) => pin.path)).size !== snapshot.pins.length ||\n snapshot.nodes.some((node) =>\n node.reads.some((read) =>\n new Set(read.sourcePaths).size !== read.sourcePaths.length ||\n read.sourcePaths.some((path) =>\n typeof read.entry === \"string\" ? path !== read.entry : !FileSet.matchesGlob(read.entry, path)\n )\n )\n )\n ) {\n return Effect.fail(failure(code, \"plan input observation has inconsistent membership or generation\"))\n }\n return Effect.void\n}\n\n/**\n * Builds the SQL-backed, owner-fenced store.\n * @since 1.0.0\n * @category constructors\n */\nexport const make: Effect.Effect<Service, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Effect.gen(\n function*() {\n const sql = yield* SqlClient.SqlClient\n const writer = yield* DurableWriter\n const crypto = yield* Effect.context<Crypto.Crypto>()\n const checksum = (value: string) => Schema.decodeUnknownEffect(Sha256)(value).pipe(Effect.provide(crypto))\n\n const fence = (address: Address, owner: OwnerId) =>\n Effect.gen(function*() {\n const owned = yield* sql`SELECT run_id FROM flows_runs WHERE run_id = ${address.runId}\n AND status = 'running' AND cancel_requested_at_ms IS NULL\n AND owner_host_id = ${owner.hostId} AND owner_pid = ${owner.pid} AND owner_nonce = ${owner.nonce}`\n if (owned.length !== 1) {\n return yield* Effect.fail(failure(\"fence_lost\", \"plan input owner no longer owns the run\"))\n }\n const legacy = yield* sql`SELECT run_id FROM flows_plan_input_legacy_runs WHERE run_id = ${address.runId}`\n if (legacy.length > 0) {\n return yield* Effect.fail(\n failure(\n \"incompatible_state\",\n \"this run executed before durable plan inputs were recorded; its original sources cannot be reconstructed\"\n )\n )\n }\n })\n\n const load = (address: Address) =>\n Effect.gen(function*() {\n const heads = yield* sql<\n { planId: string; baseDigest: string; environmentDigest: string | null; generation: number }\n >`SELECT plan_id AS \"planId\", base_digest AS \"baseDigest\", environment_digest AS \"environmentDigest\", generation\n FROM flows_plan_input_heads WHERE run_id = ${address.runId}`\n const head = heads[0]\n if (head === undefined) {\n const orphan = yield* sql`SELECT 1 FROM flows_plan_input_generations\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId} LIMIT 1`\n if (address.generation !== 0 || orphan.length > 0) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input history has no initial generation\"))\n }\n return Option.none<Snapshot>()\n }\n yield* decode(\n Schema.Struct({\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NullOr(Schema.NonEmptyString),\n generation: Natural\n }),\n head,\n \"corrupt_state\"\n )\n if (head.planId !== address.planId || head.baseDigest !== address.baseDigest) {\n return yield* Effect.fail(\n failure(\"incompatible_state\", \"this run already observed a different approved plan\")\n )\n }\n if (head.environmentDigest === null || head.environmentDigest !== address.environmentDigest) {\n return yield* Effect.fail(failure(\n \"incompatible_state\",\n \"this run has a different or unrecorded execution environment; recover with its original runtime or explicitly reconcile before starting a new run\"\n ))\n }\n const counts = yield* sql<{ count: number; first: number; last: number }>`SELECT COUNT(*) AS count,\n MIN(generation) AS first, MAX(generation) AS last FROM flows_plan_input_generations\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId}`\n if (\n counts[0]!.count !== head.generation + 1 || counts[0]!.first !== 0 || counts[0]!.last !== head.generation ||\n address.generation > head.generation + 1\n ) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input history has a missing generation\"))\n }\n if (address.generation > head.generation) return Option.none<Snapshot>()\n const rows = yield* sql<\n { snapshotJson: string; checksum: string }\n >`SELECT snapshot_json AS \"snapshotJson\", checksum\n FROM flows_plan_input_generations WHERE run_id = ${address.runId} AND plan_id = ${address.planId}\n AND generation = ${address.generation}`\n const row = rows[0]!\n if (\n row.snapshotJson.length > maximumSnapshotCharacters || (yield* checksum(row.snapshotJson)) !== row.checksum\n ) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input snapshot failed its size or integrity check\"))\n }\n const snapshot = yield* decode(Schema.fromJsonString(Snapshot), row.snapshotJson, \"corrupt_state\")\n yield* validateSnapshot(snapshot, address.generation, \"corrupt_state\")\n return Option.some(snapshot)\n })\n\n const get: Service[\"get\"] = Effect.fn(\"PlanInputStore.get\")((input, ownerInput) =>\n Effect.gen(function*() {\n const address = yield* decode(Address, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n if (Option.isSome(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(\n failure(\"transaction_open\", \"plan execution requires committed source observations\")\n )\n }\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(address, owner)\n return yield* load(address)\n }))\n }).pipe(Effect.mapError(persistError))\n )\n\n const record: Service[\"record\"] = Effect.fn(\"PlanInputStore.record\")((input, value, ownerInput) =>\n Effect.gen(function*() {\n const address = yield* decode(Address, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const snapshot = yield* decode(Snapshot, value, \"invalid_input\")\n yield* validateSnapshot(snapshot, address.generation, \"invalid_input\")\n const encoded = JSON.stringify(snapshot)\n if (encoded.length > maximumSnapshotCharacters) {\n return yield* Effect.fail(failure(\"invalid_input\", \"plan input snapshot exceeds the durable size limit\"))\n }\n const hash = yield* checksum(encoded)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(address, owner)\n const existing = yield* load(address)\n if (Option.isSome(existing)) return existing.value\n if (address.generation === 0) {\n yield* sql`INSERT INTO flows_plan_input_heads (run_id, plan_id, base_digest, environment_digest, merge_state_version, generation)\n VALUES (${address.runId}, ${address.planId}, ${address.baseDigest}, ${address.environmentDigest}, 1, 0)`\n } else {\n yield* sql`UPDATE flows_plan_input_heads SET generation = ${address.generation}\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId}`\n }\n yield* sql`INSERT INTO flows_plan_input_generations (run_id, plan_id, generation, snapshot_json, checksum)\n VALUES (${address.runId}, ${address.planId}, ${address.generation}, ${encoded}, ${hash})`\n return snapshot\n }))\n }).pipe(Effect.mapError(persistError))\n )\n\n return { get, record }\n }\n)\n\n/**\n * Provides the SQL-backed input store over the same database as the run/attempt stores.\n * @since 1.0.0\n * @category layers\n */\nexport const layer: Layer.Layer<PlanInputStore, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Layer\n .effect(\n PlanInputStore\n )(make)\n"]}
1
+ {"version":3,"file":"PlanInputStore.js","sourceRoot":"","sources":["../../src/PlanInputStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Authoritative source observations for one durable plan execution. These are\n * replay state, not approval data, journal projections, or evictable cache rows.\n * @since 1.0.0\n */\n\nimport { Sha256 } from \"@smthrs/crypto\"\nimport { DurableWriter } from \"@smthrs/database/DurableWriter\"\nimport { FileSet, Plan } from \"@smthrs/plan\"\nimport { OwnerId } from \"@smthrs/run-store/Ownership\"\nimport { Context, Effect, Layer, Option, Schema } from \"effect\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as SqlClient from \"effect/sql/SqlClient\"\n\nconst Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))\n\n/**\n * Address of an append-only observation generation. `environmentDigest` comes\n * from `StepKey.environmentIdentity` and binds every generation of the run.\n * @since 1.0.0\n * @category schemas\n */\nexport const Address = Schema.Struct({\n runId: Schema.NonEmptyString,\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NonEmptyString,\n generation: Natural\n})\n/**\n * Address of an append-only observation generation.\n * @since 1.0.0\n * @category models\n */\nexport type Address = typeof Address.Type\n\n/**\n * Maximum encoded snapshot size, in JavaScript string code units.\n * @since 1.0.0\n * @category constants\n */\nexport const maximumSnapshotCharacters = 16 * 1024 * 1024\n\n/**\n * Frozen membership and newly pinned source digests for one generation.\n * @since 1.0.0\n * @category schemas\n */\nexport const Snapshot = Schema.Struct({\n version: Schema.Literal(1),\n generation: Natural,\n nodes: Schema.Array(Schema.Struct({\n id: Schema.NonEmptyString,\n key: Schema.NonEmptyString,\n reads: Schema.Array(Schema.Struct({\n entry: FileSet.ReadEntry,\n sourcePaths: Schema.Array(FileSet.Pattern)\n }))\n })).check(Schema.isMaxLength(Plan.maximumPlanNodes)),\n pins: Schema.Array(Schema.Struct({ path: FileSet.Pattern, digest: Schema.NonEmptyString }))\n})\n/**\n * Frozen membership and newly pinned source digests for one generation.\n * @since 1.0.0\n * @category models\n */\nexport type Snapshot = typeof Snapshot.Type\n\n/**\n * A durable observation cannot be read or safely admitted.\n * @since 1.0.0\n * @category errors\n */\nexport class PlanInputError extends Schema.TaggedError<PlanInputError>()(\"@smthrs/engine-store/PlanInputError\", {\n code: Schema.Literals([\n \"invalid_input\",\n \"corrupt_state\",\n \"incompatible_state\",\n \"fence_lost\",\n \"transaction_open\",\n \"persistence_failed\"\n ]),\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown)\n}) {}\n\n/**\n * `get` is a committed-state admission gate and refuses an enclosing SQL\n * transaction. `record` is first-writer-wins and may join a write transaction;\n * callers must wait for its outer commit before executing affected actions.\n * @since 1.0.0\n * @category models\n */\nexport interface Service {\n readonly get: (address: Address, owner: OwnerId) => Effect.Effect<Option.Option<Snapshot>, PlanInputError>\n readonly record: (address: Address, snapshot: Snapshot, owner: OwnerId) => Effect.Effect<Snapshot, PlanInputError>\n}\n\n/**\n * Durable plan-input service.\n * @since 1.0.0\n * @category services\n */\nexport class PlanInputStore extends Context.Service<PlanInputStore, Service>()(\"@smthrs/engine-store/PlanInputStore\") {}\n\nconst failure = (code: PlanInputError[\"code\"], message: string, cause?: unknown) =>\n new PlanInputError({ code, message, ...(cause === undefined ? {} : { cause }) })\nconst persistError = (cause: unknown) =>\n cause instanceof PlanInputError ?\n cause :\n failure(\"persistence_failed\", \"could not access durable plan inputs\", cause)\n\nconst decode = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n value: unknown,\n code: \"invalid_input\" | \"corrupt_state\"\n) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value, { onExcessProperty: \"error\" }),\n catch: (cause) => failure(code, \"invalid plan input observation\", cause)\n })\n\nconst validateSnapshot = (snapshot: Snapshot, generation: number, code: \"invalid_input\" | \"corrupt_state\") => {\n if (\n snapshot.generation !== generation ||\n new Set(snapshot.nodes.map((node) => node.id)).size !== snapshot.nodes.length ||\n new Set(snapshot.pins.map((pin) => pin.path)).size !== snapshot.pins.length ||\n snapshot.nodes.some((node) =>\n node.reads.some((read) =>\n new Set(read.sourcePaths).size !== read.sourcePaths.length ||\n read.sourcePaths.some((path) =>\n typeof read.entry === \"string\" ? path !== read.entry : !FileSet.matchesGlob(read.entry, path)\n )\n )\n )\n ) {\n return Effect.fail(failure(code, \"plan input observation has inconsistent membership or generation\"))\n }\n return Effect.void\n}\n\n/**\n * Builds the SQL-backed, owner-fenced store.\n * @since 1.0.0\n * @category constructors\n */\nexport const make: Effect.Effect<Service, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Effect.gen(\n function*() {\n const sql = yield* SqlClient.SqlClient\n const writer = yield* DurableWriter\n const crypto = yield* Effect.context<Crypto.Crypto>()\n const checksum = (value: string) => Schema.decodeUnknownEffect(Sha256)(value).pipe(Effect.provide(crypto))\n\n const fence = (address: Address, owner: OwnerId) =>\n Effect.gen(function*() {\n const owned = yield* sql`SELECT run_id FROM flows_runs WHERE run_id = ${address.runId}\n AND status = 'running' AND cancel_requested_at_ms IS NULL\n AND owner_host_id = ${owner.hostId} AND owner_pid = ${owner.pid} AND owner_nonce = ${owner.nonce}`\n if (owned.length !== 1) {\n return yield* Effect.fail(failure(\"fence_lost\", \"plan input owner no longer owns the run\"))\n }\n const legacy = yield* sql`SELECT run_id FROM flows_plan_input_legacy_runs WHERE run_id = ${address.runId}`\n if (legacy.length > 0) {\n return yield* Effect.fail(\n failure(\n \"incompatible_state\",\n \"this run executed before durable plan inputs were recorded; its original sources cannot be reconstructed\"\n )\n )\n }\n })\n\n const load = (address: Address) =>\n Effect.gen(function*() {\n const heads = yield* sql<\n { planId: string; baseDigest: string; environmentDigest: string | null; generation: number }\n >`SELECT plan_id AS \"planId\", base_digest AS \"baseDigest\", environment_digest AS \"environmentDigest\", generation\n FROM flows_plan_input_heads WHERE run_id = ${address.runId}`\n const head = heads[0]\n if (head === undefined) {\n const orphan = yield* sql`SELECT 1 FROM flows_plan_input_generations\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId} LIMIT 1`\n if (address.generation !== 0 || orphan.length > 0) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input history has no initial generation\"))\n }\n return Option.none<Snapshot>()\n }\n yield* decode(\n Schema.Struct({\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NullOr(Schema.NonEmptyString),\n generation: Natural\n }),\n head,\n \"corrupt_state\"\n )\n if (head.planId !== address.planId || head.baseDigest !== address.baseDigest) {\n return yield* Effect.fail(\n failure(\"incompatible_state\", \"this run already observed a different approved plan\")\n )\n }\n if (head.environmentDigest === null || head.environmentDigest !== address.environmentDigest) {\n return yield* Effect.fail(failure(\n \"incompatible_state\",\n \"this run has a different or unrecorded execution environment; recover with its original runtime or explicitly reconcile before starting a new run\"\n ))\n }\n const counts = yield* sql<{ count: number; first: number; last: number }>`SELECT COUNT(*) AS count,\n MIN(generation) AS first, MAX(generation) AS last FROM flows_plan_input_generations\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId}`\n if (\n counts[0]!.count !== head.generation + 1 || counts[0]!.first !== 0 || counts[0]!.last !== head.generation ||\n address.generation > head.generation + 1\n ) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input history has a missing generation\"))\n }\n if (address.generation > head.generation) return Option.none<Snapshot>()\n const rows = yield* sql<\n { snapshotJson: string; checksum: string }\n >`SELECT snapshot_json AS \"snapshotJson\", checksum\n FROM flows_plan_input_generations WHERE run_id = ${address.runId} AND plan_id = ${address.planId}\n AND generation = ${address.generation}`\n const row = rows[0]!\n if (\n row.snapshotJson.length > maximumSnapshotCharacters || (yield* checksum(row.snapshotJson)) !== row.checksum\n ) {\n return yield* Effect.fail(failure(\"corrupt_state\", \"plan input snapshot failed its size or integrity check\"))\n }\n const snapshot = yield* decode(Schema.fromJsonString(Snapshot), row.snapshotJson, \"corrupt_state\")\n yield* validateSnapshot(snapshot, address.generation, \"corrupt_state\")\n return Option.some(snapshot)\n })\n\n const get: Service[\"get\"] = Effect.fn(\"PlanInputStore.get\")((input, ownerInput) =>\n Effect.gen(function*() {\n const address = yield* decode(Address, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n if (Option.isSome(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(\n failure(\"transaction_open\", \"plan execution requires committed source observations\")\n )\n }\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(address, owner)\n return yield* load(address)\n }))\n }).pipe(Effect.mapError(persistError))\n )\n\n const record: Service[\"record\"] = Effect.fn(\"PlanInputStore.record\")((input, value, ownerInput) =>\n Effect.gen(function*() {\n const address = yield* decode(Address, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const snapshot = yield* decode(Snapshot, value, \"invalid_input\")\n yield* validateSnapshot(snapshot, address.generation, \"invalid_input\")\n const encoded = JSON.stringify(snapshot)\n if (encoded.length > maximumSnapshotCharacters) {\n return yield* Effect.fail(failure(\"invalid_input\", \"plan input snapshot exceeds the durable size limit\"))\n }\n const hash = yield* checksum(encoded)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(address, owner)\n const existing = yield* load(address)\n if (Option.isSome(existing)) return existing.value\n if (address.generation === 0) {\n yield* sql`INSERT INTO flows_plan_input_heads (run_id, plan_id, base_digest, environment_digest, merge_state_version, generation)\n VALUES (${address.runId}, ${address.planId}, ${address.baseDigest}, ${address.environmentDigest}, 1, 0)`\n } else {\n yield* sql`UPDATE flows_plan_input_heads SET generation = ${address.generation}\n WHERE run_id = ${address.runId} AND plan_id = ${address.planId}`\n }\n yield* sql`INSERT INTO flows_plan_input_generations (run_id, plan_id, generation, snapshot_json, checksum)\n VALUES (${address.runId}, ${address.planId}, ${address.generation}, ${encoded}, ${hash})`\n return snapshot\n }))\n }).pipe(Effect.mapError(persistError))\n )\n\n return { get, record }\n }\n)\n\n/**\n * Provides the SQL-backed input store over the same database as the run/attempt stores.\n * @since 1.0.0\n * @category layers\n */\nexport const layer: Layer.Layer<PlanInputStore, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Layer\n .effect(\n PlanInputStore\n )(make)\n"]}
@@ -7,7 +7,7 @@ import { DurableWriter } from "@smthrs/database/DurableWriter";
7
7
  import { OwnerId } from "@smthrs/run-store/Ownership";
8
8
  import { Context, Effect, Layer, Schema } from "effect";
9
9
  import type * as Crypto from "effect/Crypto";
10
- import * as SqlClient from "effect/unstable/sql/SqlClient";
10
+ import * as SqlClient from "effect/sql/SqlClient";
11
11
  /** Execution binding shared by every decision of one plan run.
12
12
  * @since 1.0.0
13
13
  * @category schemas
@@ -1 +1 @@
1
- {"version":3,"file":"PlanMergeStore.d.ts","sourceRoot":"","sources":["../../src/PlanMergeStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAM1D;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;EAKnB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAC3C;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;EAQjB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;EAQrB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAC/C;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;CACjC;;;;;;AACD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAYlC;CAAG;AACL;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAA;IAC7G,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC9G,QAAQ,CAAC,QAAQ,EAAE,CACjB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,KACX,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;CAC/C;;AACD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAAiF;CAAG;AACxH;;;GAGG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AAiBzD;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAyLnG,CAAA;AACD;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAC3E,CAAA"}
1
+ {"version":3,"file":"PlanMergeStore.d.ts","sourceRoot":"","sources":["../../src/PlanMergeStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AAMjD;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;;EAKnB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAC3C;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;EAQjB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;EAQrB,CAAA;AACF;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAC/C;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;CACjC;;;;;;AACD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAYlC;CAAG;AACL;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,CAAA;IAC7G,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IAC9G,QAAQ,CAAC,QAAQ,EAAE,CACjB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,OAAO,KACX,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;CAC/C;;AACD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAAiF;CAAG;AACxH;;;GAGG;AACH,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AAiBzD;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAyLnG,CAAA;AACD;;;GAGG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,CAC3E,CAAA"}
@@ -8,7 +8,7 @@ import { DurableWriter } from "@smthrs/database/DurableWriter";
8
8
  import { Plan } from "@smthrs/plan";
9
9
  import { OwnerId } from "@smthrs/run-store/Ownership";
10
10
  import { Context, Effect, Layer, Option, Schema } from "effect";
11
- import * as SqlClient from "effect/unstable/sql/SqlClient";
11
+ import * as SqlClient from "effect/sql/SqlClient";
12
12
  const Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
13
13
  const Positive = Schema.Int.check(Schema.isGreaterThan(0));
14
14
  const Names = Schema.Array(Schema.NonEmptyString).check(Schema.isMaxLength(Plan.maximumPlanNodes));
@@ -1 +1 @@
1
- {"version":3,"file":"PlanMergeStore.js","sourceRoot":"","sources":["../../src/PlanMergeStore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Owner-fenced scheduler decisions, distinct from action failure evidence and\n * redacted journal projections. Intent survives before a merge is appended.\n * @since 1.0.0\n */\n\nimport { Sha256 } from \"@smthrs/crypto\"\nimport { DurableWriter } from \"@smthrs/database/DurableWriter\"\nimport { Plan } from \"@smthrs/plan\"\nimport { OwnerId } from \"@smthrs/run-store/Ownership\"\nimport { Context, Effect, Layer, Option, Schema } from \"effect\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\nconst Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))\nconst Positive = Schema.Int.check(Schema.isGreaterThan(0))\nconst Names = Schema.Array(Schema.NonEmptyString).check(Schema.isMaxLength(Plan.maximumPlanNodes))\n\n/** Execution binding shared by every decision of one plan run.\n * @since 1.0.0\n * @category schemas\n */\nexport const Identity = Schema.Struct({\n runId: Schema.NonEmptyString,\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NonEmptyString\n})\n/** Execution binding.\n * @since 1.0.0\n * @category models\n */\nexport type Identity = typeof Identity.Type\n/** A stopped attempt and the exact cohort eligible to supply merge winners.\n * @since 1.0.0\n * @category schemas\n */\nexport const Intent = Schema.Struct({\n version: Schema.Literal(1),\n nodeId: Schema.NonEmptyString,\n nodeKey: Schema.NonEmptyString,\n dispatchKey: Schema.NonEmptyString,\n attempts: Positive,\n rebases: Natural,\n peers: Names\n})\n/** Durable stopped-attempt decision.\n * @since 1.0.0\n * @category models\n */\nexport type Intent = typeof Intent.Type\n/** The plan extension committed for an intent.\n * @since 1.0.0\n * @category schemas\n */\nexport const Completion = Schema.Struct({\n version: Schema.Literal(1),\n generation: Positive,\n parentDigest: Schema.NonEmptyString,\n planDigest: Schema.NonEmptyString,\n mergeId: Schema.NonEmptyString,\n mergeKey: Schema.NonEmptyString,\n winners: Names\n})\n/** Committed merge extension.\n * @since 1.0.0\n * @category models\n */\nexport type Completion = typeof Completion.Type\n/** Intent with its optional committed extension.\n * @since 1.0.0\n * @category models\n */\nexport interface Decision {\n readonly intent: Intent\n readonly completion?: Completion\n}\n/** Typed admission/storage refusal.\n * @since 1.0.0\n * @category errors\n */\nexport class PlanMergeError extends Schema.TaggedError<PlanMergeError>()(\"@smthrs/engine-store/PlanMergeError\", {\n code: Schema.Literals([\n \"invalid_input\",\n \"corrupt_state\",\n \"incompatible_state\",\n \"fence_lost\",\n \"transaction_open\",\n \"transaction_required\",\n \"persistence_failed\"\n ]),\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown)\n}) {}\n/** Store operations; writes may join the owning transaction, reads require committed state.\n * @since 1.0.0\n * @category models\n */\nexport interface Service {\n readonly list: (identity: Identity, owner: OwnerId) => Effect.Effect<ReadonlyArray<Decision>, PlanMergeError>\n readonly intend: (identity: Identity, intent: Intent, owner: OwnerId) => Effect.Effect<Intent, PlanMergeError>\n readonly complete: (\n identity: Identity,\n nodeId: string,\n completion: Completion,\n owner: OwnerId\n ) => Effect.Effect<Completion, PlanMergeError>\n}\n/** Durable merge decision service.\n * @since 1.0.0\n * @category services\n */\nexport class PlanMergeStore extends Context.Service<PlanMergeStore, Service>()(\"@smthrs/engine-store/PlanMergeStore\") {}\n/** Encoded decision limit, in JavaScript code units.\n * @since 1.0.0\n * @category constants\n */\nexport const maximumDecisionCharacters = 16 * 1024 * 1024\nconst error = (code: PlanMergeError[\"code\"], message: string, cause?: unknown) =>\n new PlanMergeError({ code, message, ...(cause === undefined ? {} : { cause }) })\nconst storageError = (cause: unknown) =>\n cause instanceof PlanMergeError ? cause : error(\"persistence_failed\", \"could not access plan merge decisions\", cause)\nconst decode = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n value: unknown,\n code: \"invalid_input\" | \"corrupt_state\"\n) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value, { onExcessProperty: \"error\" }),\n catch: (cause) => error(code, \"invalid plan merge decision\", cause)\n })\nconst unique = (names: ReadonlyArray<string>, code: \"invalid_input\" | \"corrupt_state\") =>\n new Set(names).size === names.length ? Effect.void : Effect.fail(error(code, \"duplicate merge peer identity\"))\n\n/** SQL constructor; all collaborating stores must use the same database/writer.\n * @since 1.0.0\n * @category constructors\n */\nexport const make: Effect.Effect<Service, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Effect.gen(\n function*() {\n const sql = yield* SqlClient.SqlClient\n const writer = yield* DurableWriter\n const crypto = yield* Effect.context<Crypto.Crypto>()\n const hash = (value: string) => Schema.decodeUnknownEffect(Sha256)(value).pipe(Effect.provide(crypto))\n const fence = (identity: Identity, owner: OwnerId, requireHead: boolean) =>\n Effect.gen(function*() {\n const owned = yield* sql`SELECT run_id FROM flows_runs WHERE run_id = ${identity.runId}\n AND status = 'running' AND cancel_requested_at_ms IS NULL\n AND owner_host_id = ${owner.hostId} AND owner_pid = ${owner.pid} AND owner_nonce = ${owner.nonce}`\n if (owned.length !== 1) {\n return yield* Effect.fail(error(\"fence_lost\", \"merge decision owner no longer owns the run\"))\n }\n const heads = yield* sql<\n { planId: string; baseDigest: string; environmentDigest: string | null; version: number | null }\n >`SELECT\n plan_id AS \"planId\", base_digest AS \"baseDigest\", environment_digest AS \"environmentDigest\", merge_state_version AS version\n FROM flows_plan_input_heads WHERE run_id = ${identity.runId}`\n const head = heads[0]\n if (head === undefined) {\n const orphan = yield* sql`SELECT 1 FROM flows_plan_merge_intents WHERE run_id = ${identity.runId} LIMIT 1`\n if (requireHead || orphan.length > 0) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge intent has no admitted input generation\"))\n }\n return\n }\n if (\n head.version !== 1 || head.planId !== identity.planId || head.baseDigest !== identity.baseDigest ||\n head.environmentDigest !== identity.environmentDigest\n ) {\n return yield* Effect.fail(\n error(\n \"incompatible_state\",\n \"this run has different or unrecorded merge execution state; recover with its original runtime or reconcile before starting a new run\"\n )\n )\n }\n })\n const encoded = <A>(value: A) =>\n Effect.gen(function*() {\n const json = JSON.stringify(value)\n if (json.length > maximumDecisionCharacters) {\n return yield* Effect.fail(error(\"invalid_input\", \"merge decision exceeds its durable size limit\"))\n }\n return { json, checksum: yield* hash(json) }\n })\n const stored = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n row: { json: string; checksum: string }\n ) =>\n Effect.gen(function*() {\n if (row.json.length > maximumDecisionCharacters || (yield* hash(row.json)) !== row.checksum) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge decision failed its size or integrity check\"))\n }\n return yield* decode(Schema.fromJsonString(schema), row.json, \"corrupt_state\")\n })\n const load = (identity: Identity, nodeId?: string) =>\n Effect.gen(function*() {\n const rows = yield* sql<\n {\n nodeId: string\n json: string\n checksum: string\n generation: number | null\n mergeId: string | null\n completionJson: string | null\n completionChecksum: string | null\n }\n >`SELECT i.stopped_node_id AS \"nodeId\", i.intent_json AS json, i.checksum,\n c.generation, c.merge_node_id AS \"mergeId\", c.completion_json AS \"completionJson\",\n c.checksum AS \"completionChecksum\"\n FROM flows_plan_merge_intents i LEFT JOIN flows_plan_merge_completions c\n ON c.run_id = i.run_id AND c.stopped_node_id = i.stopped_node_id\n WHERE i.run_id = ${identity.runId} ${nodeId === undefined ? sql`` : sql`AND i.stopped_node_id = ${nodeId}`}\n ORDER BY i.stopped_node_id LIMIT ${Plan.maximumPlanNodes + 1}`\n if (rows.length > Plan.maximumPlanNodes) {\n return yield* Effect.fail(error(\"corrupt_state\", \"too many merge decisions for one plan\"))\n }\n return yield* Effect.forEach(rows, (row) =>\n Effect.gen(function*() {\n const intent = yield* stored(Intent, row)\n yield* unique(intent.peers, \"corrupt_state\")\n if (intent.nodeId !== row.nodeId || intent.peers.includes(intent.nodeId)) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge intent identity is inconsistent\"))\n }\n if (row.completionJson === null) return { intent } satisfies Decision\n const completion = yield* stored(Completion, {\n json: row.completionJson,\n checksum: row.completionChecksum!\n })\n yield* unique(completion.winners, \"corrupt_state\")\n if (\n completion.generation !== row.generation || completion.mergeId !== row.mergeId ||\n completion.winners.some((id) => !intent.peers.includes(id))\n ) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge completion does not match its intent\"))\n }\n return { intent, completion } satisfies Decision\n }))\n })\n const list: Service[\"list\"] = (input, ownerInput) =>\n Effect.gen(function*() {\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n if (Option.isSome(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(error(\"transaction_open\", \"merge recovery requires committed decisions\"))\n }\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, false)\n return yield* load(identity)\n }))\n }).pipe(Effect.mapError(storageError))\n const intend: Service[\"intend\"] = (input, value, ownerInput) =>\n Effect.gen(function*() {\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const intent = yield* decode(Intent, value, \"invalid_input\")\n yield* unique(intent.peers, \"invalid_input\")\n if (intent.peers.includes(intent.nodeId)) {\n return yield* Effect.fail(error(\"invalid_input\", \"a merge cannot stop its own peer\"))\n }\n const data = yield* encoded(intent)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, true)\n const [existing] = yield* load(identity, intent.nodeId)\n if (existing !== undefined) return existing.intent\n const [count] = yield* sql<{ count: number }>`SELECT count(*) AS count\n FROM flows_plan_merge_intents WHERE run_id = ${identity.runId}`\n if (count!.count >= Plan.maximumPlanNodes) {\n return yield* Effect.fail(error(\"invalid_input\", \"too many merge intents for one plan\"))\n }\n yield* sql`INSERT INTO flows_plan_merge_intents (run_id, stopped_node_id, intent_json, checksum)\n VALUES (${identity.runId}, ${intent.nodeId}, ${data.json}, ${data.checksum})`\n return intent\n }))\n }).pipe(Effect.mapError(storageError))\n const complete: Service[\"complete\"] = (input, nodeIdInput, value, ownerInput) =>\n Effect.gen(function*() {\n if (Option.isNone(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(\n error(\"transaction_required\", \"merge completion must join the plan/input append transaction\")\n )\n }\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const nodeId = yield* decode(Schema.NonEmptyString, nodeIdInput, \"invalid_input\")\n const completion = yield* decode(Completion, value, \"invalid_input\")\n yield* unique(completion.winners, \"invalid_input\")\n const data = yield* encoded(completion)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, true)\n const [decision] = yield* load(identity, nodeId)\n if (decision === undefined) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge completion has no intent\"))\n }\n if (decision.completion !== undefined) {\n if (JSON.stringify(decision.completion) !== JSON.stringify(completion)) {\n return yield* Effect.fail(\n error(\"incompatible_state\", \"a merge intent already committed a different extension\")\n )\n }\n return decision.completion\n }\n if (completion.winners.some((id) => !decision.intent.peers.includes(id))) {\n return yield* Effect.fail(error(\"invalid_input\", \"merge winner was not an admitted peer\"))\n }\n const appended =\n yield* sql`SELECT p.plan_id FROM flows_plans p JOIN flows_plan_input_generations i ON i.plan_id = p.plan_id\n JOIN flows_plan_nodes n ON n.plan_id = p.plan_id AND n.generation = p.generation\n WHERE p.plan_id = ${identity.planId} AND p.digest = ${completion.planDigest} AND p.generation = ${completion.generation}\n AND i.run_id = ${identity.runId} AND i.generation = ${completion.generation}\n AND n.node_id = ${completion.mergeId} AND n.key_digest = ${completion.mergeKey} AND n.kind = 'merge'`\n if (appended.length !== 1) {\n return yield* Effect.fail(\n error(\"corrupt_state\", \"merge completion requires its plan and input generation in the same transaction\")\n )\n }\n yield* sql`INSERT INTO flows_plan_merge_completions (run_id, stopped_node_id, generation, merge_node_id, completion_json, checksum)\n VALUES (${identity.runId}, ${nodeId}, ${completion.generation}, ${completion.mergeId}, ${data.json}, ${data.checksum})`\n return completion\n }))\n }).pipe(Effect.mapError(storageError))\n return { list, intend, complete }\n }\n)\n/** SQL-backed merge decisions; migrations must run first.\n * @since 1.0.0\n * @category layers\n */\nexport const layer: Layer.Layer<PlanMergeStore, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Layer\n .effect(PlanMergeStore)(make)\n"]}
1
+ {"version":3,"file":"PlanMergeStore.js","sourceRoot":"","sources":["../../src/PlanMergeStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/D,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AAEjD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;AAClE,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;AAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;AAElG;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,cAAc;IAC5B,MAAM,EAAE,MAAM,CAAC,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC,cAAc;IACjC,iBAAiB,EAAE,MAAM,CAAC,cAAc;CACzC,CAAC,CAAA;AAMF;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC,cAAc;IAC9B,WAAW,EAAE,MAAM,CAAC,cAAc;IAClC,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,KAAK;CACb,CAAC,CAAA;AAMF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1B,UAAU,EAAE,QAAQ;IACpB,YAAY,EAAE,MAAM,CAAC,cAAc;IACnC,UAAU,EAAE,MAAM,CAAC,cAAc;IACjC,OAAO,EAAE,MAAM,CAAC,cAAc;IAC9B,QAAQ,EAAE,MAAM,CAAC,cAAc;IAC/B,OAAO,EAAE,KAAK;CACf,CAAC,CAAA;AAcF;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,MAAM,CAAC,WAAW,EAAkB,CAAC,qCAAqC,EAAE;IAC9G,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC;QACpB,eAAe;QACf,eAAe;QACf,oBAAoB;QACpB,YAAY;QACZ,kBAAkB;QAClB,sBAAsB;QACtB,oBAAoB;KACrB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;CACvC,CAAC;CAAG;AAeL;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,OAAO,CAAC,OAAO,EAA2B,CAAC,qCAAqC,CAAC;CAAG;AACxH;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AACzD,MAAM,KAAK,GAAG,CAAC,IAA4B,EAAE,OAAe,EAAE,KAAe,EAAE,EAAE,CAC/E,IAAI,cAAc,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;AAClF,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,EAAE,CACtC,KAAK,YAAY,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,EAAE,uCAAuC,EAAE,KAAK,CAAC,CAAA;AACvH,MAAM,MAAM,GAAG,CACb,MAAS,EACT,KAAc,EACd,IAAuC,EACvC,EAAE,CACF,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;IACjF,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,6BAA6B,EAAE,KAAK,CAAC;CACpE,CAAC,CAAA;AACJ,MAAM,MAAM,GAAG,CAAC,KAA4B,EAAE,IAAuC,EAAE,EAAE,CACvF,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC,CAAA;AAEhH;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAuF,MAAM,CAAC,GAAG,CAChH,QAAQ,CAAC;IACP,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAA;IACtC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,aAAa,CAAA;IACnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAiB,CAAA;IACrD,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IACtG,MAAM,KAAK,GAAG,CAAC,QAAkB,EAAE,KAAc,EAAE,WAAoB,EAAE,EAAE,CACzE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,CAAA,gDAAgD,QAAQ,CAAC,KAAK;;4BAElE,KAAK,CAAC,MAAM,oBAAoB,KAAK,CAAC,GAAG,sBAAsB,KAAK,CAAC,KAAK,EAAE,CAAA;QAChG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,6CAA6C,CAAC,CAAC,CAAA;QAC/F,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,GAAG,CAEvB;;mDAE0C,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACrB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAA,yDAAyD,QAAQ,CAAC,KAAK,UAAU,CAAA;YAC1G,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,+CAA+C,CAAC,CAAC,CAAA;YACpG,CAAC;YACD,OAAM;QACR,CAAC;QACD,IACE,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;YAChG,IAAI,CAAC,iBAAiB,KAAK,QAAQ,CAAC,iBAAiB,EACrD,CAAC;YACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,KAAK,CACH,oBAAoB,EACpB,sIAAsI,CACvI,CACF,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IACJ,MAAM,OAAO,GAAG,CAAI,KAAQ,EAAE,EAAE,CAC9B,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QAClC,IAAI,IAAI,CAAC,MAAM,GAAG,yBAAyB,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,+CAA+C,CAAC,CAAC,CAAA;QACpG,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAA;IAC9C,CAAC,CAAC,CAAA;IACJ,MAAM,MAAM,GAAG,CACb,MAAS,EACT,GAAuC,EACvC,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,yBAAyB,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC5F,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,mDAAmD,CAAC,CAAC,CAAA;QACxG,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IACJ,MAAM,IAAI,GAAG,CAAC,QAAkB,EAAE,MAAe,EAAE,EAAE,CACnD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAUtB;;;;;yBAKgB,QAAQ,CAAC,KAAK,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAA,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA,2BAA2B,MAAM,EAAE;yCACvE,IAAI,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAA;QAC5D,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,uCAAuC,CAAC,CAAC,CAAA;QAC5F,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CACzC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;YACzC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;YAC5C,IAAI,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,uCAAuC,CAAC,CAAC,CAAA;YAC5F,CAAC;YACD,IAAI,GAAG,CAAC,cAAc,KAAK,IAAI;gBAAE,OAAO,EAAE,MAAM,EAAqB,CAAA;YACrE,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;gBAC3C,IAAI,EAAE,GAAG,CAAC,cAAc;gBACxB,QAAQ,EAAE,GAAG,CAAC,kBAAmB;aAClC,CAAC,CAAA;YACF,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;YAClD,IACE,UAAU,CAAC,UAAU,KAAK,GAAG,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,KAAK,GAAG,CAAC,OAAO;gBAC9E,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAC3D,CAAC;gBACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,4CAA4C,CAAC,CAAC,CAAA;YACjG,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAqB,CAAA;QAClD,CAAC,CAAC,CAAC,CAAA;IACP,CAAC,CAAC,CAAA;IACJ,MAAM,IAAI,GAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAClD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;QAChE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;QACjE,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,6CAA6C,CAAC,CAAC,CAAA;QACrG,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC7C,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;YACpC,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC9B,CAAC,CAAC,CAAC,CAAA;IACL,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IACxC,MAAM,MAAM,GAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAC7D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;QAChE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;QAC5D,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,CAAA;QAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,kCAAkC,CAAC,CAAC,CAAA;QACvF,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACnC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC7C,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;YACvD,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAC,MAAM,CAAA;YAClD,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAmB;uDACA,QAAQ,CAAC,KAAK,EAAE,CAAA;YAC7D,IAAI,KAAM,CAAC,KAAK,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC1C,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC,CAAA;YAC1F,CAAC;YACD,KAAK,CAAC,CAAC,GAAG,CAAA;kBACF,QAAQ,CAAC,KAAK,KAAK,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,GAAG,CAAA;YAC3E,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAC,CAAA;IACL,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAC9E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;YACvE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,KAAK,CAAC,sBAAsB,EAAE,8DAA8D,CAAC,CAC9F,CAAA;QACH,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;QAChE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,EAAE,eAAe,CAAC,CAAA;QACjF,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,eAAe,CAAC,CAAA;QACpE,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QACvC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC7C,KAAK,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;YACnC,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAChD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,gCAAgC,CAAC,CAAC,CAAA;YACrF,CAAC;YACD,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBACtC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;oBACvE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,KAAK,CAAC,oBAAoB,EAAE,wDAAwD,CAAC,CACtF,CAAA;gBACH,CAAC;gBACD,OAAO,QAAQ,CAAC,UAAU,CAAA;YAC5B,CAAC;YACD,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACzE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,uCAAuC,CAAC,CAAC,CAAA;YAC5F,CAAC;YACD,MAAM,QAAQ,GACZ,KAAK,CAAC,CAAC,GAAG,CAAA;;4BAEM,QAAQ,CAAC,MAAM,mBAAmB,UAAU,CAAC,UAAU,uBAAuB,UAAU,CAAC,UAAU;yBACtG,QAAQ,CAAC,KAAK,uBAAuB,UAAU,CAAC,UAAU;0BACzD,UAAU,CAAC,OAAO,uBAAuB,UAAU,CAAC,QAAQ,uBAAuB,CAAA;YACnG,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CACvB,KAAK,CAAC,eAAe,EAAE,iFAAiF,CAAC,CAC1G,CAAA;YACH,CAAC;YACD,KAAK,CAAC,CAAC,GAAG,CAAA;kBACF,QAAQ,CAAC,KAAK,KAAK,MAAM,KAAK,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,GAAG,CAAA;YACrH,OAAO,UAAU,CAAA;QACnB,CAAC,CAAC,CAAC,CAAA;IACL,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IACxC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AACnC,CAAC,CACF,CAAA;AACD;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAA4F,KAAK;KAChH,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAA","sourcesContent":["/**\n * Owner-fenced scheduler decisions, distinct from action failure evidence and\n * redacted journal projections. Intent survives before a merge is appended.\n * @since 1.0.0\n */\n\nimport { Sha256 } from \"@smthrs/crypto\"\nimport { DurableWriter } from \"@smthrs/database/DurableWriter\"\nimport { Plan } from \"@smthrs/plan\"\nimport { OwnerId } from \"@smthrs/run-store/Ownership\"\nimport { Context, Effect, Layer, Option, Schema } from \"effect\"\nimport type * as Crypto from \"effect/Crypto\"\nimport * as SqlClient from \"effect/sql/SqlClient\"\n\nconst Natural = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))\nconst Positive = Schema.Int.check(Schema.isGreaterThan(0))\nconst Names = Schema.Array(Schema.NonEmptyString).check(Schema.isMaxLength(Plan.maximumPlanNodes))\n\n/** Execution binding shared by every decision of one plan run.\n * @since 1.0.0\n * @category schemas\n */\nexport const Identity = Schema.Struct({\n runId: Schema.NonEmptyString,\n planId: Schema.NonEmptyString,\n baseDigest: Schema.NonEmptyString,\n environmentDigest: Schema.NonEmptyString\n})\n/** Execution binding.\n * @since 1.0.0\n * @category models\n */\nexport type Identity = typeof Identity.Type\n/** A stopped attempt and the exact cohort eligible to supply merge winners.\n * @since 1.0.0\n * @category schemas\n */\nexport const Intent = Schema.Struct({\n version: Schema.Literal(1),\n nodeId: Schema.NonEmptyString,\n nodeKey: Schema.NonEmptyString,\n dispatchKey: Schema.NonEmptyString,\n attempts: Positive,\n rebases: Natural,\n peers: Names\n})\n/** Durable stopped-attempt decision.\n * @since 1.0.0\n * @category models\n */\nexport type Intent = typeof Intent.Type\n/** The plan extension committed for an intent.\n * @since 1.0.0\n * @category schemas\n */\nexport const Completion = Schema.Struct({\n version: Schema.Literal(1),\n generation: Positive,\n parentDigest: Schema.NonEmptyString,\n planDigest: Schema.NonEmptyString,\n mergeId: Schema.NonEmptyString,\n mergeKey: Schema.NonEmptyString,\n winners: Names\n})\n/** Committed merge extension.\n * @since 1.0.0\n * @category models\n */\nexport type Completion = typeof Completion.Type\n/** Intent with its optional committed extension.\n * @since 1.0.0\n * @category models\n */\nexport interface Decision {\n readonly intent: Intent\n readonly completion?: Completion\n}\n/** Typed admission/storage refusal.\n * @since 1.0.0\n * @category errors\n */\nexport class PlanMergeError extends Schema.TaggedError<PlanMergeError>()(\"@smthrs/engine-store/PlanMergeError\", {\n code: Schema.Literals([\n \"invalid_input\",\n \"corrupt_state\",\n \"incompatible_state\",\n \"fence_lost\",\n \"transaction_open\",\n \"transaction_required\",\n \"persistence_failed\"\n ]),\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown)\n}) {}\n/** Store operations; writes may join the owning transaction, reads require committed state.\n * @since 1.0.0\n * @category models\n */\nexport interface Service {\n readonly list: (identity: Identity, owner: OwnerId) => Effect.Effect<ReadonlyArray<Decision>, PlanMergeError>\n readonly intend: (identity: Identity, intent: Intent, owner: OwnerId) => Effect.Effect<Intent, PlanMergeError>\n readonly complete: (\n identity: Identity,\n nodeId: string,\n completion: Completion,\n owner: OwnerId\n ) => Effect.Effect<Completion, PlanMergeError>\n}\n/** Durable merge decision service.\n * @since 1.0.0\n * @category services\n */\nexport class PlanMergeStore extends Context.Service<PlanMergeStore, Service>()(\"@smthrs/engine-store/PlanMergeStore\") {}\n/** Encoded decision limit, in JavaScript code units.\n * @since 1.0.0\n * @category constants\n */\nexport const maximumDecisionCharacters = 16 * 1024 * 1024\nconst error = (code: PlanMergeError[\"code\"], message: string, cause?: unknown) =>\n new PlanMergeError({ code, message, ...(cause === undefined ? {} : { cause }) })\nconst storageError = (cause: unknown) =>\n cause instanceof PlanMergeError ? cause : error(\"persistence_failed\", \"could not access plan merge decisions\", cause)\nconst decode = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n value: unknown,\n code: \"invalid_input\" | \"corrupt_state\"\n) =>\n Effect.try({\n try: () => Schema.decodeUnknownSync(schema)(value, { onExcessProperty: \"error\" }),\n catch: (cause) => error(code, \"invalid plan merge decision\", cause)\n })\nconst unique = (names: ReadonlyArray<string>, code: \"invalid_input\" | \"corrupt_state\") =>\n new Set(names).size === names.length ? Effect.void : Effect.fail(error(code, \"duplicate merge peer identity\"))\n\n/** SQL constructor; all collaborating stores must use the same database/writer.\n * @since 1.0.0\n * @category constructors\n */\nexport const make: Effect.Effect<Service, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Effect.gen(\n function*() {\n const sql = yield* SqlClient.SqlClient\n const writer = yield* DurableWriter\n const crypto = yield* Effect.context<Crypto.Crypto>()\n const hash = (value: string) => Schema.decodeUnknownEffect(Sha256)(value).pipe(Effect.provide(crypto))\n const fence = (identity: Identity, owner: OwnerId, requireHead: boolean) =>\n Effect.gen(function*() {\n const owned = yield* sql`SELECT run_id FROM flows_runs WHERE run_id = ${identity.runId}\n AND status = 'running' AND cancel_requested_at_ms IS NULL\n AND owner_host_id = ${owner.hostId} AND owner_pid = ${owner.pid} AND owner_nonce = ${owner.nonce}`\n if (owned.length !== 1) {\n return yield* Effect.fail(error(\"fence_lost\", \"merge decision owner no longer owns the run\"))\n }\n const heads = yield* sql<\n { planId: string; baseDigest: string; environmentDigest: string | null; version: number | null }\n >`SELECT\n plan_id AS \"planId\", base_digest AS \"baseDigest\", environment_digest AS \"environmentDigest\", merge_state_version AS version\n FROM flows_plan_input_heads WHERE run_id = ${identity.runId}`\n const head = heads[0]\n if (head === undefined) {\n const orphan = yield* sql`SELECT 1 FROM flows_plan_merge_intents WHERE run_id = ${identity.runId} LIMIT 1`\n if (requireHead || orphan.length > 0) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge intent has no admitted input generation\"))\n }\n return\n }\n if (\n head.version !== 1 || head.planId !== identity.planId || head.baseDigest !== identity.baseDigest ||\n head.environmentDigest !== identity.environmentDigest\n ) {\n return yield* Effect.fail(\n error(\n \"incompatible_state\",\n \"this run has different or unrecorded merge execution state; recover with its original runtime or reconcile before starting a new run\"\n )\n )\n }\n })\n const encoded = <A>(value: A) =>\n Effect.gen(function*() {\n const json = JSON.stringify(value)\n if (json.length > maximumDecisionCharacters) {\n return yield* Effect.fail(error(\"invalid_input\", \"merge decision exceeds its durable size limit\"))\n }\n return { json, checksum: yield* hash(json) }\n })\n const stored = <S extends Schema.Top & { readonly DecodingServices: never }>(\n schema: S,\n row: { json: string; checksum: string }\n ) =>\n Effect.gen(function*() {\n if (row.json.length > maximumDecisionCharacters || (yield* hash(row.json)) !== row.checksum) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge decision failed its size or integrity check\"))\n }\n return yield* decode(Schema.fromJsonString(schema), row.json, \"corrupt_state\")\n })\n const load = (identity: Identity, nodeId?: string) =>\n Effect.gen(function*() {\n const rows = yield* sql<\n {\n nodeId: string\n json: string\n checksum: string\n generation: number | null\n mergeId: string | null\n completionJson: string | null\n completionChecksum: string | null\n }\n >`SELECT i.stopped_node_id AS \"nodeId\", i.intent_json AS json, i.checksum,\n c.generation, c.merge_node_id AS \"mergeId\", c.completion_json AS \"completionJson\",\n c.checksum AS \"completionChecksum\"\n FROM flows_plan_merge_intents i LEFT JOIN flows_plan_merge_completions c\n ON c.run_id = i.run_id AND c.stopped_node_id = i.stopped_node_id\n WHERE i.run_id = ${identity.runId} ${nodeId === undefined ? sql`` : sql`AND i.stopped_node_id = ${nodeId}`}\n ORDER BY i.stopped_node_id LIMIT ${Plan.maximumPlanNodes + 1}`\n if (rows.length > Plan.maximumPlanNodes) {\n return yield* Effect.fail(error(\"corrupt_state\", \"too many merge decisions for one plan\"))\n }\n return yield* Effect.forEach(rows, (row) =>\n Effect.gen(function*() {\n const intent = yield* stored(Intent, row)\n yield* unique(intent.peers, \"corrupt_state\")\n if (intent.nodeId !== row.nodeId || intent.peers.includes(intent.nodeId)) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge intent identity is inconsistent\"))\n }\n if (row.completionJson === null) return { intent } satisfies Decision\n const completion = yield* stored(Completion, {\n json: row.completionJson,\n checksum: row.completionChecksum!\n })\n yield* unique(completion.winners, \"corrupt_state\")\n if (\n completion.generation !== row.generation || completion.mergeId !== row.mergeId ||\n completion.winners.some((id) => !intent.peers.includes(id))\n ) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge completion does not match its intent\"))\n }\n return { intent, completion } satisfies Decision\n }))\n })\n const list: Service[\"list\"] = (input, ownerInput) =>\n Effect.gen(function*() {\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n if (Option.isSome(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(error(\"transaction_open\", \"merge recovery requires committed decisions\"))\n }\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, false)\n return yield* load(identity)\n }))\n }).pipe(Effect.mapError(storageError))\n const intend: Service[\"intend\"] = (input, value, ownerInput) =>\n Effect.gen(function*() {\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const intent = yield* decode(Intent, value, \"invalid_input\")\n yield* unique(intent.peers, \"invalid_input\")\n if (intent.peers.includes(intent.nodeId)) {\n return yield* Effect.fail(error(\"invalid_input\", \"a merge cannot stop its own peer\"))\n }\n const data = yield* encoded(intent)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, true)\n const [existing] = yield* load(identity, intent.nodeId)\n if (existing !== undefined) return existing.intent\n const [count] = yield* sql<{ count: number }>`SELECT count(*) AS count\n FROM flows_plan_merge_intents WHERE run_id = ${identity.runId}`\n if (count!.count >= Plan.maximumPlanNodes) {\n return yield* Effect.fail(error(\"invalid_input\", \"too many merge intents for one plan\"))\n }\n yield* sql`INSERT INTO flows_plan_merge_intents (run_id, stopped_node_id, intent_json, checksum)\n VALUES (${identity.runId}, ${intent.nodeId}, ${data.json}, ${data.checksum})`\n return intent\n }))\n }).pipe(Effect.mapError(storageError))\n const complete: Service[\"complete\"] = (input, nodeIdInput, value, ownerInput) =>\n Effect.gen(function*() {\n if (Option.isNone(yield* Effect.serviceOption(sql.transactionService))) {\n return yield* Effect.fail(\n error(\"transaction_required\", \"merge completion must join the plan/input append transaction\")\n )\n }\n const identity = yield* decode(Identity, input, \"invalid_input\")\n const owner = yield* decode(OwnerId, ownerInput, \"invalid_input\")\n const nodeId = yield* decode(Schema.NonEmptyString, nodeIdInput, \"invalid_input\")\n const completion = yield* decode(Completion, value, \"invalid_input\")\n yield* unique(completion.winners, \"invalid_input\")\n const data = yield* encoded(completion)\n return yield* writer.write(Effect.gen(function*() {\n yield* fence(identity, owner, true)\n const [decision] = yield* load(identity, nodeId)\n if (decision === undefined) {\n return yield* Effect.fail(error(\"corrupt_state\", \"merge completion has no intent\"))\n }\n if (decision.completion !== undefined) {\n if (JSON.stringify(decision.completion) !== JSON.stringify(completion)) {\n return yield* Effect.fail(\n error(\"incompatible_state\", \"a merge intent already committed a different extension\")\n )\n }\n return decision.completion\n }\n if (completion.winners.some((id) => !decision.intent.peers.includes(id))) {\n return yield* Effect.fail(error(\"invalid_input\", \"merge winner was not an admitted peer\"))\n }\n const appended =\n yield* sql`SELECT p.plan_id FROM flows_plans p JOIN flows_plan_input_generations i ON i.plan_id = p.plan_id\n JOIN flows_plan_nodes n ON n.plan_id = p.plan_id AND n.generation = p.generation\n WHERE p.plan_id = ${identity.planId} AND p.digest = ${completion.planDigest} AND p.generation = ${completion.generation}\n AND i.run_id = ${identity.runId} AND i.generation = ${completion.generation}\n AND n.node_id = ${completion.mergeId} AND n.key_digest = ${completion.mergeKey} AND n.kind = 'merge'`\n if (appended.length !== 1) {\n return yield* Effect.fail(\n error(\"corrupt_state\", \"merge completion requires its plan and input generation in the same transaction\")\n )\n }\n yield* sql`INSERT INTO flows_plan_merge_completions (run_id, stopped_node_id, generation, merge_node_id, completion_json, checksum)\n VALUES (${identity.runId}, ${nodeId}, ${completion.generation}, ${completion.mergeId}, ${data.json}, ${data.checksum})`\n return completion\n }))\n }).pipe(Effect.mapError(storageError))\n return { list, intend, complete }\n }\n)\n/** SQL-backed merge decisions; migrations must run first.\n * @since 1.0.0\n * @category layers\n */\nexport const layer: Layer.Layer<PlanMergeStore, never, SqlClient.SqlClient | DurableWriter | Crypto.Crypto> = Layer\n .effect(PlanMergeStore)(make)\n"]}
@@ -31,8 +31,8 @@
31
31
  * @since 1.0.0
32
32
  */
33
33
  import * as Effect from "effect/Effect";
34
- import * as SqlClient from "effect/unstable/sql/SqlClient";
35
- import type { SqlError } from "effect/unstable/sql/SqlError";
34
+ import * as SqlClient from "effect/sql/SqlClient";
35
+ import type { SqlError } from "effect/sql/SqlError";
36
36
  import * as RetentionOps from "./internal/RetentionOps.ts";
37
37
  export { defaultLimit, layer, make, type RetainOptions, type RetainReport, Retention, RetentionError, RetentionErrorCode, type RunScopedTable,
38
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Retention.d.ts","sourceRoot":"","sources":["../../src/Retention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,KAAK,YAAY,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EACL,YAAY,EACZ,KAAK,EACL,IAAI,EACJ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,KAAK,cAAc;AACnB;;;;;;GAMG;AACH,eAAe,EACf,KAAK,OAAO,EACZ,gBAAgB,EACjB,MAAM,4BAA4B,CAAA;AAEnC;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACpC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,iFAAiF;IACjF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;CAClD;AA4CD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,aAAa,MAAM,EACnB,cAAiC,KAChC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAIlE,CAAA;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,OAAO,GAClB,SAAS,OAAO,KACf,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC,cAAc,EAAE,SAAS,CAAC,SAAS,CA+BhF,CAAA"}
1
+ {"version":3,"file":"Retention.d.ts","sourceRoot":"","sources":["../../src/Retention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,YAAY,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EACL,YAAY,EACZ,KAAK,EACL,IAAI,EACJ,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,KAAK,cAAc;AACnB;;;;;;GAMG;AACH,eAAe,EACf,KAAK,OAAO,EACZ,gBAAgB,EACjB,MAAM,4BAA4B,CAAA;AAEnC;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACpC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,iFAAiF;IACjF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,uFAAuF;IACvF,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;CAClD;AA4CD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GACnB,aAAa,MAAM,EACnB,cAAiC,KAChC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAIlE,CAAA;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,OAAO,GAClB,SAAS,OAAO,KACf,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC,cAAc,EAAE,SAAS,CAAC,SAAS,CA+BhF,CAAA"}
@@ -33,7 +33,7 @@
33
33
  import * as Dialect from "@smthrs/database/Dialect";
34
34
  import * as DurableWriter from "@smthrs/database/DurableWriter";
35
35
  import * as Effect from "effect/Effect";
36
- import * as SqlClient from "effect/unstable/sql/SqlClient";
36
+ import * as SqlClient from "effect/sql/SqlClient";
37
37
  import * as RetentionOps from "./internal/RetentionOps.js";
38
38
  export { defaultLimit, layer, make, Retention, RetentionError, RetentionErrorCode,
39
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Retention.js","sourceRoot":"","sources":["../../src/Retention.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Deleting run history that has outlived its usefulness.\n *\n * Nothing in the durable stores forgets on its own: a finished run keeps its\n * row, every attempt, every journal event, and every archived frame forever.\n * That is the right default — a run's history is the only account of what an\n * agent did to a repository — and it is why `smithers gc` exists rather than a\n * background sweeper. Retention is an operator decision, taken explicitly,\n * with a dry run available before anything is deleted.\n *\n * This module is the public surface. The operation lives in\n * `internal/RetentionOps.ts` beside the other modules that read this package's\n * own tables, so `internal/` is never imported by a consumer — the same split\n * `Errors.ts` uses. {@link retain} and {@link layer} are that operation: one\n * bounded pass over the engine ladder, inside one `journal.transact`.\n *\n * {@link collect} is the host-facing pass `smithers gc` runs, and it is a\n * facade over the same guard. A project keeps its history in two files — the\n * control plane's database and the engine's — and a sweep of one without the\n * other leaves half of a deleted run behind, so the pass takes the database as\n * a service and runs once per file. Which runs it may delete is\n * {@link RetentionOps.lineagePrelude}'s answer, not a second guard written\n * here: a run stays whenever a live run stands above or below it, over BOTH\n * relations that make one run the parent of another — the `flows_run_parents`\n * edge a spawned child records, and the `parent_run_id` column a trampoline\n * lineage is chained through.\n *\n * Only terminal runs are ever considered. A `pending`, `running`, or\n * `suspended` row belongs to work that can still resume.\n *\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as DurableWriter from \"@smthrs/database/DurableWriter\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\nimport type { SqlError } from \"effect/unstable/sql/SqlError\"\nimport * as RetentionOps from \"./internal/RetentionOps.ts\"\n\nexport {\n defaultLimit,\n layer,\n make,\n type RetainOptions,\n type RetainReport,\n Retention,\n RetentionError,\n RetentionErrorCode,\n type RunScopedTable,\n /**\n * Every table a deleted run leaves rows in. One inventory serves this pass\n * and {@link Service.retain}, so neither can leak what the other deletes.\n *\n * @category constants\n * @since 1.0.0\n */\n runScopedTables,\n type Service,\n terminalStatuses\n} from \"./internal/RetentionOps.ts\"\n\n/**\n * What one retention pass would delete, or did.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Report {\n readonly database: string\n /** The threshold, as an epoch millisecond value. */\n readonly olderThanMs: number\n readonly runs: ReadonlyArray<string>\n /** Rows deleted per table; empty under a dry run. */\n readonly deleted: Readonly<Record<string, number>>\n readonly dryRun: boolean\n}\n\n/**\n * Arguments accepted by {@link collect}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Options {\n /** Delete terminal runs that finished strictly before this epoch millisecond. */\n readonly olderThanMs: number\n readonly dryRun?: boolean | undefined\n /** A label for the report; the host's database path. */\n readonly database?: string | undefined\n /** Largest number of runs considered by this pass. Defaults to 1,000. */\n readonly limit?: number | undefined\n /** Runs retained by a host's cross-store ancestry, in addition to local live roots. */\n readonly pins?: ReadonlyArray<string> | undefined\n}\n\n/** Whether a table exists in the connected database. */\nconst hasTable = (table: string): Effect.Effect<boolean, SqlError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const rows = yield* Dialect.tables(sql).pipe(Effect.map((rows) => rows.filter((row) => row.name === table)))\n return rows.length > 0\n })\n\n/**\n * The runs one pass would delete, oldest first, each with the run it names as\n * its parent.\n *\n * The same candidate query `retain` runs: children before parents, so a\n * trampoline lineage longer than the bound still loses a run every pass, and\n * a run is excluded whenever a live run stands above or below it. Downward,\n * deleting a parent whose child is still running would break the\n * `parent_run_id` foreign key and drop the live child's edges with the\n * `flows_run_parents_gc` trigger. Upward, a parked parent still reads a\n * settled child's result out of its run row through `agent/await`, and it can\n * be parked for longer than the threshold before it ever asks.\n */\nconst eligibleCandidates = (\n olderThanMs: number,\n limit: number | undefined,\n pins?: ReadonlyArray<string>\n): Effect.Effect<ReadonlyArray<RetentionOps.Candidate>, SqlError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n if (!(yield* hasTable(\"flows_runs\"))) return []\n // The engine's edge table is absent from the control-plane database, which\n // migrates the run store and the journal and nothing else. The prelude\n // drops that half of the walk there and keeps the `parent_run_id` half, so\n // one guard covers both files.\n return yield* RetentionOps.candidatesOf(sql, {\n cutoffMs: olderThanMs,\n inclusive: false,\n parentEdges: yield* hasTable(\"flows_run_parents\"),\n pins,\n limit: RetentionOps.normalizeLimit(limit)\n })\n })\n\n/**\n * The terminal runs one pass would delete, oldest first.\n *\n * @category getters\n * @since 1.0.0\n */\nexport const eligible = (\n olderThanMs: number,\n limit = RetentionOps.defaultLimit\n): Effect.Effect<ReadonlyArray<string>, SqlError, SqlClient.SqlClient> =>\n Effect.map(\n eligibleCandidates(olderThanMs, limit),\n (candidates) => candidates.map((candidate) => candidate.runId)\n )\n\n/**\n * Runs one retention pass.\n *\n * The deletion itself is {@link RetentionOps.deleteRuns}, the same one\n * {@link Service.retain} runs, so this pass cannot hold a shorter table list\n * than that one and cannot delete run rows in an order the self-referential\n * `parent_run_id` foreign key refuses. A handoff parent always sorts before\n * its successor, so deleting in age order broke as soon as one lineage\n * straddled a chunk boundary, and it broke AFTER the dependent rows of every\n * eligible run were already gone. `assumeLadder: false` because this pass also\n * runs against the control plane's database, which composed fewer stores.\n *\n * Eligibility and deletion share one retryable transaction: another writer\n * cannot attach a live parent between the lineage scan and deletion. A busy\n * retry recomputes eligibility rather than replaying an old candidate list.\n * One transaction, for the reason `retain` opens one: a pass that removed a\n * run's history and then refused on its row would have destroyed what it could\n * not put back, and a workspace whose next pass refuses the same way can never\n * be collected again.\n *\n * Under `dryRun` nothing is written and `deleted` is empty: the report names\n * exactly the runs a real pass would remove, which is what makes\n * `smithers gc --dry-run` worth trusting.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const collect = (\n options: Options\n): Effect.Effect<Report, SqlError | RetentionOps.RetentionError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const dryRun = options.dryRun === true\n const pass = Effect.gen(function*() {\n const candidates = yield* eligibleCandidates(options.olderThanMs, options.limit, options.pins)\n return yield* RetentionOps.deleteRuns(sql, candidates, {\n dryRun,\n assumeLadder: false\n })\n })\n const removed = yield* (dryRun ? sql.withTransaction(pass) : DurableWriter.make(sql).write(pass).pipe(\n Effect.catchIf(\n (cause): cause is DurableWriter.DatabaseError => cause instanceof DurableWriter.DatabaseError,\n (cause) =>\n Effect.fail(\n new RetentionOps.RetentionError({\n code: \"delete_failed\",\n message: \"retention transaction failed; no history was deleted\",\n cause\n })\n )\n )\n ))\n return {\n database: options.database ?? \"\",\n olderThanMs: options.olderThanMs,\n runs: removed.runIds,\n deleted: dryRun ? {} : removed.deleted,\n dryRun\n }\n })\n"]}
1
+ {"version":3,"file":"Retention.js","sourceRoot":"","sources":["../../src/Retention.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Deleting run history that has outlived its usefulness.\n *\n * Nothing in the durable stores forgets on its own: a finished run keeps its\n * row, every attempt, every journal event, and every archived frame forever.\n * That is the right default — a run's history is the only account of what an\n * agent did to a repository — and it is why `smithers gc` exists rather than a\n * background sweeper. Retention is an operator decision, taken explicitly,\n * with a dry run available before anything is deleted.\n *\n * This module is the public surface. The operation lives in\n * `internal/RetentionOps.ts` beside the other modules that read this package's\n * own tables, so `internal/` is never imported by a consumer — the same split\n * `Errors.ts` uses. {@link retain} and {@link layer} are that operation: one\n * bounded pass over the engine ladder, inside one `journal.transact`.\n *\n * {@link collect} is the host-facing pass `smithers gc` runs, and it is a\n * facade over the same guard. A project keeps its history in two files — the\n * control plane's database and the engine's — and a sweep of one without the\n * other leaves half of a deleted run behind, so the pass takes the database as\n * a service and runs once per file. Which runs it may delete is\n * {@link RetentionOps.lineagePrelude}'s answer, not a second guard written\n * here: a run stays whenever a live run stands above or below it, over BOTH\n * relations that make one run the parent of another — the `flows_run_parents`\n * edge a spawned child records, and the `parent_run_id` column a trampoline\n * lineage is chained through.\n *\n * Only terminal runs are ever considered. A `pending`, `running`, or\n * `suspended` row belongs to work that can still resume.\n *\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as DurableWriter from \"@smthrs/database/DurableWriter\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/sql/SqlClient\"\nimport type { SqlError } from \"effect/sql/SqlError\"\nimport * as RetentionOps from \"./internal/RetentionOps.ts\"\n\nexport {\n defaultLimit,\n layer,\n make,\n type RetainOptions,\n type RetainReport,\n Retention,\n RetentionError,\n RetentionErrorCode,\n type RunScopedTable,\n /**\n * Every table a deleted run leaves rows in. One inventory serves this pass\n * and {@link Service.retain}, so neither can leak what the other deletes.\n *\n * @category constants\n * @since 1.0.0\n */\n runScopedTables,\n type Service,\n terminalStatuses\n} from \"./internal/RetentionOps.ts\"\n\n/**\n * What one retention pass would delete, or did.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Report {\n readonly database: string\n /** The threshold, as an epoch millisecond value. */\n readonly olderThanMs: number\n readonly runs: ReadonlyArray<string>\n /** Rows deleted per table; empty under a dry run. */\n readonly deleted: Readonly<Record<string, number>>\n readonly dryRun: boolean\n}\n\n/**\n * Arguments accepted by {@link collect}.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Options {\n /** Delete terminal runs that finished strictly before this epoch millisecond. */\n readonly olderThanMs: number\n readonly dryRun?: boolean | undefined\n /** A label for the report; the host's database path. */\n readonly database?: string | undefined\n /** Largest number of runs considered by this pass. Defaults to 1,000. */\n readonly limit?: number | undefined\n /** Runs retained by a host's cross-store ancestry, in addition to local live roots. */\n readonly pins?: ReadonlyArray<string> | undefined\n}\n\n/** Whether a table exists in the connected database. */\nconst hasTable = (table: string): Effect.Effect<boolean, SqlError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const rows = yield* Dialect.tables(sql).pipe(Effect.map((rows) => rows.filter((row) => row.name === table)))\n return rows.length > 0\n })\n\n/**\n * The runs one pass would delete, oldest first, each with the run it names as\n * its parent.\n *\n * The same candidate query `retain` runs: children before parents, so a\n * trampoline lineage longer than the bound still loses a run every pass, and\n * a run is excluded whenever a live run stands above or below it. Downward,\n * deleting a parent whose child is still running would break the\n * `parent_run_id` foreign key and drop the live child's edges with the\n * `flows_run_parents_gc` trigger. Upward, a parked parent still reads a\n * settled child's result out of its run row through `agent/await`, and it can\n * be parked for longer than the threshold before it ever asks.\n */\nconst eligibleCandidates = (\n olderThanMs: number,\n limit: number | undefined,\n pins?: ReadonlyArray<string>\n): Effect.Effect<ReadonlyArray<RetentionOps.Candidate>, SqlError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n if (!(yield* hasTable(\"flows_runs\"))) return []\n // The engine's edge table is absent from the control-plane database, which\n // migrates the run store and the journal and nothing else. The prelude\n // drops that half of the walk there and keeps the `parent_run_id` half, so\n // one guard covers both files.\n return yield* RetentionOps.candidatesOf(sql, {\n cutoffMs: olderThanMs,\n inclusive: false,\n parentEdges: yield* hasTable(\"flows_run_parents\"),\n pins,\n limit: RetentionOps.normalizeLimit(limit)\n })\n })\n\n/**\n * The terminal runs one pass would delete, oldest first.\n *\n * @category getters\n * @since 1.0.0\n */\nexport const eligible = (\n olderThanMs: number,\n limit = RetentionOps.defaultLimit\n): Effect.Effect<ReadonlyArray<string>, SqlError, SqlClient.SqlClient> =>\n Effect.map(\n eligibleCandidates(olderThanMs, limit),\n (candidates) => candidates.map((candidate) => candidate.runId)\n )\n\n/**\n * Runs one retention pass.\n *\n * The deletion itself is {@link RetentionOps.deleteRuns}, the same one\n * {@link Service.retain} runs, so this pass cannot hold a shorter table list\n * than that one and cannot delete run rows in an order the self-referential\n * `parent_run_id` foreign key refuses. A handoff parent always sorts before\n * its successor, so deleting in age order broke as soon as one lineage\n * straddled a chunk boundary, and it broke AFTER the dependent rows of every\n * eligible run were already gone. `assumeLadder: false` because this pass also\n * runs against the control plane's database, which composed fewer stores.\n *\n * Eligibility and deletion share one retryable transaction: another writer\n * cannot attach a live parent between the lineage scan and deletion. A busy\n * retry recomputes eligibility rather than replaying an old candidate list.\n * One transaction, for the reason `retain` opens one: a pass that removed a\n * run's history and then refused on its row would have destroyed what it could\n * not put back, and a workspace whose next pass refuses the same way can never\n * be collected again.\n *\n * Under `dryRun` nothing is written and `deleted` is empty: the report names\n * exactly the runs a real pass would remove, which is what makes\n * `smithers gc --dry-run` worth trusting.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const collect = (\n options: Options\n): Effect.Effect<Report, SqlError | RetentionOps.RetentionError, SqlClient.SqlClient> =>\n Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n const dryRun = options.dryRun === true\n const pass = Effect.gen(function*() {\n const candidates = yield* eligibleCandidates(options.olderThanMs, options.limit, options.pins)\n return yield* RetentionOps.deleteRuns(sql, candidates, {\n dryRun,\n assumeLadder: false\n })\n })\n const removed = yield* (dryRun ? sql.withTransaction(pass) : DurableWriter.make(sql).write(pass).pipe(\n Effect.catchIf(\n (cause): cause is DurableWriter.DatabaseError => cause instanceof DurableWriter.DatabaseError,\n (cause) =>\n Effect.fail(\n new RetentionOps.RetentionError({\n code: \"delete_failed\",\n message: \"retention transaction failed; no history was deleted\",\n cause\n })\n )\n )\n ))\n return {\n database: options.database ?? \"\",\n olderThanMs: options.olderThanMs,\n runs: removed.runIds,\n deleted: dryRun ? {} : removed.deleted,\n dryRun\n }\n })\n"]}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { RunStoreError } from "@smthrs/run-store/RunStore";
7
7
  import { Context, Effect, Layer } from "effect";
8
- import * as SqlClient from "effect/unstable/sql/SqlClient";
8
+ import * as SqlClient from "effect/sql/SqlClient";
9
9
  import type { Position } from "./ExecutionSnapshot.ts";
10
10
  /**
11
11
  * A live-row change or retained tombstone.
@@ -1 +1 @@
1
- {"version":3,"file":"RunChangeFeed.d.ts","sourceRoot":"","sources":["../../src/RunChangeFeed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD;;;;;GAKG;AACH,MAAM,WAAW,MAAO,SAAQ,QAAQ;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,WAAW,IAAK,SAAQ,QAAQ;IACpC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IACxD,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;CAC9G;;AACD;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,kBAA+E;CAAG;AACrH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,OAAO,CAAA;AAQnC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,QAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CA8CrE,CAAA;AACJ;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CAAuC,CAAA"}
1
+ {"version":3,"file":"RunChangeFeed.d.ts","sourceRoot":"","sources":["../../src/RunChangeFeed.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AACvD,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAGtD;;;;;GAKG;AACH,MAAM,WAAW,MAAO,SAAQ,QAAQ;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,WAAW,IAAK,SAAQ,QAAQ;IACpC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IACvC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AACD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IACxD,QAAQ,CAAC,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;CAC9G;;AACD;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,kBAA+E;CAAG;AACrH;;;;;GAKG;AACH,eAAO,MAAM,eAAe,OAAO,CAAA;AAQnC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,QAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CA8CrE,CAAA;AACJ;;;;;GAKG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,CAAuC,CAAA"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { RunStoreError } from "@smthrs/run-store/RunStore";
7
7
  import { Context, Effect, Layer, Schema } from "effect";
8
- import * as SqlClient from "effect/unstable/sql/SqlClient";
8
+ import * as SqlClient from "effect/sql/SqlClient";
9
9
  import * as Read from "./internal/ExecutionSnapshotRead.js";
10
10
  /**
11
11
  * Durable change-feed service.