@earendil-works/pi-durable 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +287 -82
  3. package/dist/codemode/codemode.d.ts +4 -4
  4. package/dist/codemode/codemode.d.ts.map +1 -1
  5. package/dist/codemode/codemode.js +21 -16
  6. package/dist/codemode/codemode.js.map +1 -1
  7. package/dist/codemode/models.d.ts.map +1 -1
  8. package/dist/codemode/models.js +6 -4
  9. package/dist/codemode/models.js.map +1 -1
  10. package/dist/documents.d.ts +1 -1
  11. package/dist/documents.d.ts.map +1 -1
  12. package/dist/documents.js.map +1 -1
  13. package/dist/env/index.d.ts +12 -10
  14. package/dist/env/index.d.ts.map +1 -1
  15. package/dist/env/index.js.map +1 -1
  16. package/dist/env/node-watch.d.ts +3 -3
  17. package/dist/env/node-watch.d.ts.map +1 -1
  18. package/dist/env/node-watch.js +18 -16
  19. package/dist/env/node-watch.js.map +1 -1
  20. package/dist/env/node.d.ts +2 -2
  21. package/dist/env/node.d.ts.map +1 -1
  22. package/dist/env/node.js +12 -4
  23. package/dist/env/node.js.map +1 -1
  24. package/dist/errors.d.ts +18 -2
  25. package/dist/errors.d.ts.map +1 -1
  26. package/dist/errors.js +26 -3
  27. package/dist/errors.js.map +1 -1
  28. package/dist/harness/agent.d.ts +13 -2
  29. package/dist/harness/agent.d.ts.map +1 -1
  30. package/dist/harness/agent.js +48 -6
  31. package/dist/harness/agent.js.map +1 -1
  32. package/dist/harness/compaction.d.ts +3 -1
  33. package/dist/harness/compaction.d.ts.map +1 -1
  34. package/dist/harness/compaction.js +38 -6
  35. package/dist/harness/compaction.js.map +1 -1
  36. package/dist/harness/context.d.ts +23 -7
  37. package/dist/harness/context.d.ts.map +1 -1
  38. package/dist/harness/context.js +71 -25
  39. package/dist/harness/context.js.map +1 -1
  40. package/dist/harness/define.d.ts +7 -3
  41. package/dist/harness/define.d.ts.map +1 -1
  42. package/dist/harness/define.js +4 -0
  43. package/dist/harness/define.js.map +1 -1
  44. package/dist/harness/generation.d.ts +38 -5
  45. package/dist/harness/generation.d.ts.map +1 -1
  46. package/dist/harness/generation.js +497 -108
  47. package/dist/harness/generation.js.map +1 -1
  48. package/dist/harness/harness.d.ts +7 -2
  49. package/dist/harness/harness.d.ts.map +1 -1
  50. package/dist/harness/harness.js +147 -57
  51. package/dist/harness/harness.js.map +1 -1
  52. package/dist/harness/inbox.d.ts +7 -3
  53. package/dist/harness/inbox.d.ts.map +1 -1
  54. package/dist/harness/inbox.js +7 -4
  55. package/dist/harness/inbox.js.map +1 -1
  56. package/dist/harness/json.d.ts +20 -4
  57. package/dist/harness/json.d.ts.map +1 -1
  58. package/dist/harness/json.js +23 -5
  59. package/dist/harness/json.js.map +1 -1
  60. package/dist/harness/live.d.ts +122 -16
  61. package/dist/harness/live.d.ts.map +1 -1
  62. package/dist/harness/live.js +93 -12
  63. package/dist/harness/live.js.map +1 -1
  64. package/dist/harness/partial-changes.d.ts +54 -0
  65. package/dist/harness/partial-changes.d.ts.map +1 -0
  66. package/dist/harness/partial-changes.js +162 -0
  67. package/dist/harness/partial-changes.js.map +1 -0
  68. package/dist/harness/prompt.d.ts +1 -1
  69. package/dist/harness/prompt.d.ts.map +1 -1
  70. package/dist/harness/prompt.js +1 -1
  71. package/dist/harness/prompt.js.map +1 -1
  72. package/dist/harness/registry-reader.d.ts +11 -0
  73. package/dist/harness/registry-reader.d.ts.map +1 -0
  74. package/dist/harness/registry-reader.js +25 -0
  75. package/dist/harness/registry-reader.js.map +1 -0
  76. package/dist/harness/scheduler.d.ts +86 -14
  77. package/dist/harness/scheduler.d.ts.map +1 -1
  78. package/dist/harness/scheduler.js +1459 -369
  79. package/dist/harness/scheduler.js.map +1 -1
  80. package/dist/harness/submissions.d.ts +23 -11
  81. package/dist/harness/submissions.d.ts.map +1 -1
  82. package/dist/harness/submissions.js +104 -36
  83. package/dist/harness/submissions.js.map +1 -1
  84. package/dist/harness/task-graph.d.ts +28 -8
  85. package/dist/harness/task-graph.d.ts.map +1 -1
  86. package/dist/harness/task-graph.js +85 -36
  87. package/dist/harness/task-graph.js.map +1 -1
  88. package/dist/harness/telemetry.d.ts +307 -0
  89. package/dist/harness/telemetry.d.ts.map +1 -0
  90. package/dist/harness/telemetry.js +136 -0
  91. package/dist/harness/telemetry.js.map +1 -0
  92. package/dist/harness/tool.d.ts +2 -0
  93. package/dist/harness/tool.d.ts.map +1 -1
  94. package/dist/harness/tool.js +223 -61
  95. package/dist/harness/tool.js.map +1 -1
  96. package/dist/harness/transcript.d.ts +72 -0
  97. package/dist/harness/transcript.d.ts.map +1 -0
  98. package/dist/harness/transcript.js +264 -0
  99. package/dist/harness/transcript.js.map +1 -0
  100. package/dist/harness/types.d.ts +302 -48
  101. package/dist/harness/types.d.ts.map +1 -1
  102. package/dist/harness/types.js.map +1 -1
  103. package/dist/harness/util.d.ts +7 -1
  104. package/dist/harness/util.d.ts.map +1 -1
  105. package/dist/harness/util.js +13 -0
  106. package/dist/harness/util.js.map +1 -1
  107. package/dist/harness/view.d.ts +43 -22
  108. package/dist/harness/view.d.ts.map +1 -1
  109. package/dist/harness/view.js +130 -71
  110. package/dist/harness/view.js.map +1 -1
  111. package/dist/index.d.ts +13 -9
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +7 -5
  114. package/dist/index.js.map +1 -1
  115. package/dist/search.d.ts +19 -3
  116. package/dist/search.d.ts.map +1 -1
  117. package/dist/search.js +107 -44
  118. package/dist/search.js.map +1 -1
  119. package/dist/session/cached-storage.d.ts +71 -0
  120. package/dist/session/cached-storage.d.ts.map +1 -0
  121. package/dist/session/cached-storage.js +269 -0
  122. package/dist/session/cached-storage.js.map +1 -0
  123. package/dist/session/conversation-tails.d.ts +33 -0
  124. package/dist/session/conversation-tails.d.ts.map +1 -0
  125. package/dist/session/conversation-tails.js +101 -0
  126. package/dist/session/conversation-tails.js.map +1 -0
  127. package/dist/session/keys.d.ts +68 -0
  128. package/dist/session/keys.d.ts.map +1 -0
  129. package/dist/session/keys.js +161 -0
  130. package/dist/session/keys.js.map +1 -0
  131. package/dist/session/session.d.ts +181 -29
  132. package/dist/session/session.d.ts.map +1 -1
  133. package/dist/session/session.js +1073 -183
  134. package/dist/session/session.js.map +1 -1
  135. package/dist/session/transaction.d.ts +86 -4
  136. package/dist/session/transaction.d.ts.map +1 -1
  137. package/dist/session/transaction.js +250 -38
  138. package/dist/session/transaction.js.map +1 -1
  139. package/dist/session/writer.d.ts +74 -0
  140. package/dist/session/writer.d.ts.map +1 -0
  141. package/dist/session/writer.js +294 -0
  142. package/dist/session/writer.js.map +1 -0
  143. package/dist/storage/indexeddb.d.ts +68 -0
  144. package/dist/storage/indexeddb.d.ts.map +1 -0
  145. package/dist/storage/indexeddb.js +881 -0
  146. package/dist/storage/indexeddb.js.map +1 -0
  147. package/dist/storage/jsonl/storage.d.ts +30 -2
  148. package/dist/storage/jsonl/storage.d.ts.map +1 -1
  149. package/dist/storage/jsonl/storage.js +88 -24
  150. package/dist/storage/jsonl/storage.js.map +1 -1
  151. package/dist/storage/memory.d.ts +7 -2
  152. package/dist/storage/memory.d.ts.map +1 -1
  153. package/dist/storage/memory.js +29 -3
  154. package/dist/storage/memory.js.map +1 -1
  155. package/dist/storage/sqlite/cloudflare.d.ts +2 -51
  156. package/dist/storage/sqlite/cloudflare.d.ts.map +1 -1
  157. package/dist/storage/sqlite/cloudflare.js +2 -133
  158. package/dist/storage/sqlite/cloudflare.js.map +1 -1
  159. package/dist/storage/sqlite/database.d.ts +1 -36
  160. package/dist/storage/sqlite/database.d.ts.map +1 -1
  161. package/dist/storage/sqlite/database.js.map +1 -1
  162. package/dist/storage/sqlite/index.d.ts +1 -1
  163. package/dist/storage/sqlite/index.d.ts.map +1 -1
  164. package/dist/storage/sqlite/index.js.map +1 -1
  165. package/dist/storage/sqlite/migrations.d.ts +2 -5
  166. package/dist/storage/sqlite/migrations.d.ts.map +1 -1
  167. package/dist/storage/sqlite/migrations.js +28 -28
  168. package/dist/storage/sqlite/migrations.js.map +1 -1
  169. package/dist/storage/sqlite/node.d.ts +2 -37
  170. package/dist/storage/sqlite/node.d.ts.map +1 -1
  171. package/dist/storage/sqlite/node.js +3 -174
  172. package/dist/storage/sqlite/node.js.map +1 -1
  173. package/dist/storage/sqlite/schema.d.ts +1 -3
  174. package/dist/storage/sqlite/schema.d.ts.map +1 -1
  175. package/dist/storage/sqlite/schema.js +2 -9
  176. package/dist/storage/sqlite/schema.js.map +1 -1
  177. package/dist/storage/sqlite/storage.d.ts +15 -3
  178. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  179. package/dist/storage/sqlite/storage.js +110 -36
  180. package/dist/storage/sqlite/storage.js.map +1 -1
  181. package/dist/storage/store/commit.d.ts +33 -0
  182. package/dist/storage/store/commit.d.ts.map +1 -0
  183. package/dist/storage/store/commit.js +286 -0
  184. package/dist/storage/store/commit.js.map +1 -0
  185. package/dist/storage/store/documents.d.ts +43 -0
  186. package/dist/storage/store/documents.d.ts.map +1 -0
  187. package/dist/storage/store/documents.js +102 -0
  188. package/dist/storage/store/documents.js.map +1 -0
  189. package/dist/storage/store/index.d.ts +2 -0
  190. package/dist/storage/store/index.d.ts.map +1 -0
  191. package/dist/storage/store/index.js +2 -0
  192. package/dist/storage/store/index.js.map +1 -0
  193. package/dist/storage/store/queries.d.ts +49 -0
  194. package/dist/storage/store/queries.d.ts.map +1 -0
  195. package/dist/storage/store/queries.js +93 -0
  196. package/dist/storage/store/queries.js.map +1 -0
  197. package/dist/storage/store/storage.d.ts +59 -0
  198. package/dist/storage/store/storage.d.ts.map +1 -0
  199. package/dist/storage/store/storage.js +438 -0
  200. package/dist/storage/store/storage.js.map +1 -0
  201. package/dist/storage/store/tables.d.ts +54 -0
  202. package/dist/storage/store/tables.d.ts.map +1 -0
  203. package/dist/storage/store/tables.js +108 -0
  204. package/dist/storage/store/tables.js.map +1 -0
  205. package/dist/testing/commit-writes.d.ts +5 -0
  206. package/dist/testing/commit-writes.d.ts.map +1 -0
  207. package/dist/testing/commit-writes.js +12 -0
  208. package/dist/testing/commit-writes.js.map +1 -0
  209. package/dist/testing/env-conformance.js +7 -7
  210. package/dist/testing/env-conformance.js.map +1 -1
  211. package/dist/testing/index.d.ts +1 -0
  212. package/dist/testing/index.d.ts.map +1 -1
  213. package/dist/testing/index.js +1 -0
  214. package/dist/testing/index.js.map +1 -1
  215. package/dist/testing/storage-benchmark.d.ts.map +1 -1
  216. package/dist/testing/storage-benchmark.js +18 -17
  217. package/dist/testing/storage-benchmark.js.map +1 -1
  218. package/dist/testing/storage-conformance.d.ts.map +1 -1
  219. package/dist/testing/storage-conformance.js +369 -67
  220. package/dist/testing/storage-conformance.js.map +1 -1
  221. package/dist/timers.d.ts +21 -0
  222. package/dist/timers.d.ts.map +1 -0
  223. package/dist/timers.js +72 -0
  224. package/dist/timers.js.map +1 -0
  225. package/dist/tool-search/tool-search.d.ts +6 -12
  226. package/dist/tool-search/tool-search.d.ts.map +1 -1
  227. package/dist/tool-search/tool-search.js +7 -7
  228. package/dist/tool-search/tool-search.js.map +1 -1
  229. package/dist/tools/bash.d.ts +12 -12
  230. package/dist/tools/bash.d.ts.map +1 -1
  231. package/dist/tools/bash.js +16 -15
  232. package/dist/tools/bash.js.map +1 -1
  233. package/dist/tools/edit.d.ts +7 -7
  234. package/dist/tools/edit.d.ts.map +1 -1
  235. package/dist/tools/edit.js +9 -9
  236. package/dist/tools/edit.js.map +1 -1
  237. package/dist/tools/index.d.ts +32 -32
  238. package/dist/tools/read.d.ts +6 -6
  239. package/dist/tools/read.d.ts.map +1 -1
  240. package/dist/tools/read.js +19 -8
  241. package/dist/tools/read.js.map +1 -1
  242. package/dist/tools/write.d.ts +4 -4
  243. package/dist/tools/write.d.ts.map +1 -1
  244. package/dist/tools/write.js +5 -5
  245. package/dist/tools/write.js.map +1 -1
  246. package/dist/types.d.ts +331 -64
  247. package/dist/types.d.ts.map +1 -1
  248. package/dist/types.js.map +1 -1
  249. package/package.json +27 -10
  250. package/dist/harness/events.d.ts +0 -186
  251. package/dist/harness/events.d.ts.map +0 -1
  252. package/dist/harness/events.js +0 -373
  253. package/dist/harness/events.js.map +0 -1
  254. package/dist/session/observation.d.ts +0 -42
  255. package/dist/session/observation.d.ts.map +0 -1
  256. package/dist/session/observation.js +0 -281
  257. package/dist/session/observation.js.map +0 -1
@@ -1,15 +1,25 @@
1
1
  import { type Context } from "@earendil-works/chord";
2
+ import { type TelemetryContext, type TelemetrySpan } from "@earendil-works/pi-telemetry";
2
3
  import type { SessionImpl } from "../session/session.ts";
3
- import type { ConversationId, Storage, SubmissionId, SubmissionRecord, Tx } from "../types.ts";
4
+ import type { ConversationId, SubmissionId, SubmissionRecord, Tx } from "../types.ts";
4
5
  import { type QueueModes } from "./inbox.ts";
5
6
  import type { SettledSubmissionRecord, Submission, SubmissionDraft } from "./types.ts";
6
7
  type AbortResult = "aborted" | "already_placed" | "settled";
8
+ type Admission = {
9
+ readonly id: SubmissionId;
10
+ readonly status: "queued" | "placed" | "done";
11
+ };
7
12
  /** Admission, waits, and withdrawal of the durable submissions of one Harness. */
8
13
  export declare class Submissions {
9
14
  #private;
10
- constructor(session: SessionImpl, storage: Storage, now: () => number, queueModes: () => QueueModes, resume: () => void);
15
+ constructor(session: SessionImpl, now: () => number, queueModes: () => QueueModes, resume: () => void, telemetry?: TelemetryContext);
11
16
  /** Admit a submission in one commit; see `admitSubmission()`. */
12
17
  submit(conversationId: ConversationId, draft: SubmissionDraft, context: Context): Promise<Submission>;
18
+ /**
19
+ * Admit a submission inside the caller's commit `tx`, with the rules of `submit()`. The admission is stored or lost
20
+ * with that commit. It must come before the commit's first table write, another admission's included.
21
+ */
22
+ admit(tx: Tx, conversationId: ConversationId, draft: SubmissionDraft): Promise<SubmissionId>;
13
23
  /** Handle for an existing submission, or `undefined`. */
14
24
  get(id: SubmissionId, context: Context): Promise<Submission | undefined>;
15
25
  status(id: SubmissionId, context: Context): Promise<SubmissionRecord>;
@@ -18,15 +28,17 @@ export declare class Submissions {
18
28
  abort(id: SubmissionId, context: Context, conversationId?: ConversationId): Promise<AbortResult | "not_found">;
19
29
  }
20
30
  /**
21
- * Admit a submission inside a commit (spec §6); `Conversation.submit()` and conversation-owned compactions share it. A
22
- * known request ID returns its existing submission without writing. A display-only write (only `kind` and `data`) is
23
- * appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a queued reset it
24
- * queues, so it lands after the reset instead of before it in the context the reset ends. A busy conversation queues anything else in
25
- * `pi.inbox`, or rejects `whenBusy: "reject"` input with `ConversationBusy`. An idle conversation with queued items
26
- * queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the input's
27
- * own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head reaches
28
- * before the active range.
31
+ * Admit a submission inside a commit (spec §6); both `Conversation.submit()` forms and conversation-owned compactions
32
+ * share it. A known request ID returns its existing submission without writing. A display-only write (only `kind` and
33
+ * `data`) is appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a
34
+ * queued reset it queues, so it lands after the reset instead of before it in the context the reset ends. A busy
35
+ * conversation queues anything else in `pi.inbox`, or rejects `whenBusy: "reject"` input and any continue with
36
+ * `ConversationBusy`; an idle one rejects `whenIdle: "reject"` input with `ConversationIdle`. An idle continue places
37
+ * queued items and starts a run with them and itself, placing no entry of its own. An idle conversation with queued
38
+ * items queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the
39
+ * input's own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head
40
+ * reaches before the active range.
29
41
  */
30
- export declare function admitSubmission(tx: Tx, conversationId: ConversationId, draft: SubmissionDraft, now: number, queueModes: QueueModes): Promise<SubmissionId>;
42
+ export declare function admitSubmission(tx: Tx, conversationId: ConversationId, draft: SubmissionDraft, now: number, queueModes: QueueModes, span?: TelemetrySpan): Promise<Admission>;
31
43
  export {};
32
44
  //# sourceMappingURL=submissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"submissions.d.ts","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAqC,MAAM,uBAAuB,CAAC;AAExF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAEX,cAAc,EAEd,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,EAAE,EACF,MAAM,aAAa,CAAC;AAErB,OAAO,EASN,KAAK,UAAU,EAEf,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAc,uBAAuB,EAAE,UAAU,EAAE,eAAe,EAAa,MAAM,YAAY,CAAC;AAG9G,KAAK,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE5D,kFAAkF;AAClF,qBAAa,WAAW;;IAWvB,YACC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,MAAM,EACjB,UAAU,EAAE,MAAM,UAAU,EAC5B,MAAM,EAAE,MAAM,IAAI,EAYlB;IAED,iEAAiE;IAC3D,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAO1G;IAED,yDAAyD;IACnD,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG7E;IAEK,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAI1E;IAEK,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAY/E;IAED,kHAAkH;IAClH,KAAK,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,CAa7G;CAQD;AAwCD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACpC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,UAAU,GACpB,OAAO,CAAC,YAAY,CAAC,CAgEvB"}
1
+ {"version":3,"file":"submissions.d.ts","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAqC,MAAM,uBAAuB,CAAC;AAExF,OAAO,EAGN,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAc,YAAY,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAElG,OAAO,EASN,KAAK,UAAU,EAEf,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAc,uBAAuB,EAAE,UAAU,EAAE,eAAe,EAAa,MAAM,YAAY,CAAC;AAG9G,KAAK,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAC5D,KAAK,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAA;CAAE,CAAC;AAE9F,kFAAkF;AAClF,qBAAa,WAAW;;IAWvB,YACC,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,MAAM,MAAM,EACjB,UAAU,EAAE,MAAM,UAAU,EAC5B,MAAM,EAAE,MAAM,IAAI,EAClB,SAAS,GAAE,gBAAyC,EAYpD;IAED,iEAAiE;IAC3D,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ1G;IAED;;;OAGG;IACG,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAQjG;IAkCD,yDAAyD;IACnD,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG7E;IAEK,MAAM,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAI1E;IAEK,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAY/E;IAED,kHAAkH;IAClH,KAAK,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,CAa7G;CAUD;AAwCD;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACpC,EAAE,EAAE,EAAE,EACN,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,UAAU,EACtB,IAAI,CAAC,EAAE,aAAa,GAClB,OAAO,CAAC,SAAS,CAAC,CAuFpB"}
@@ -1,13 +1,16 @@
1
1
  import { copyJson } from "@earendil-works/chord";
2
- import { ConversationBusy } from "../errors.js";
2
+ import { withTelemetry } from "@earendil-works/chord/context";
3
+ import { createTypedSpanStarter, NOOP_TELEMETRY_CONTEXT, } from "@earendil-works/pi-telemetry";
4
+ import { ConversationBusy, ConversationIdle, ReadAfterWrite } from "../errors.js";
3
5
  import { startRun } from "./generation.js";
4
6
  import { appendInput, applyBoundary, hasQueuedReset, InboxDoc, isDisplayOnly, isStale, pickInputEntry, prepareBoundary, removeInboxItem, } from "./inbox.js";
5
7
  import { LiveDoc } from "./live.js";
8
+ import { DURABLE_TELEMETRY_SCHEMA } from "./telemetry.js";
6
9
  import { closedError, Waiters } from "./util.js";
7
10
  /** Admission, waits, and withdrawal of the durable submissions of one Harness. */
8
11
  export class Submissions {
12
+ #telemetry;
9
13
  #session;
10
- #storage;
11
14
  #now;
12
15
  /** Read at each admission, on the Session line. */
13
16
  #queueModes;
@@ -15,13 +18,13 @@ export class Submissions {
15
18
  #resume;
16
19
  #waiters = new Waiters();
17
20
  #closed = false;
18
- constructor(session, storage, now, queueModes, resume) {
21
+ constructor(session, now, queueModes, resume, telemetry = NOOP_TELEMETRY_CONTEXT) {
22
+ this.#telemetry = telemetry;
19
23
  this.#session = session;
20
- this.#storage = storage;
21
24
  this.#now = now;
22
25
  this.#queueModes = queueModes;
23
26
  this.#resume = resume;
24
- session.observeCommits((publication) => this.#observe(publication));
27
+ session.followCommits((publication) => this.#observe(publication));
25
28
  session.subscribeClose(() => {
26
29
  this.#closed = true;
27
30
  this.#waiters.rejectAll(closedError(this.#session));
@@ -29,17 +32,53 @@ export class Submissions {
29
32
  }
30
33
  /** Admit a submission in one commit; see `admitSubmission()`. */
31
34
  async submit(conversationId, draft, context) {
32
- this.#resume();
33
- const id = await this.#session.commitWith((tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes()), context);
35
+ const { id } = await this.#traced(conversationId, draft, context, (span) => this.#session.commitWith((tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span), withTelemetry(span, context)));
34
36
  return new SubmissionHandle(id, this);
35
37
  }
38
+ /**
39
+ * Admit a submission inside the caller's commit `tx`, with the rules of `submit()`. The admission is stored or lost
40
+ * with that commit. It must come before the commit's first table write, another admission's included.
41
+ */
42
+ async admit(tx, conversationId, draft) {
43
+ if (!this.#session.ownsTransaction(tx))
44
+ throw new Error("The transaction belongs to another Session");
45
+ // Enforced on every path: admission reads tables only on some (request IDs, an idle boundary, a steer's trace).
46
+ if (tx.hasTableWrite)
47
+ throw new ReadAfterWrite("submit(tx, draft)");
48
+ const admission = await this.#traced(conversationId, draft, tx.context, (span) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span));
49
+ return admission.id;
50
+ }
51
+ /** Run one admission in its `pi.durable.submit` span, asking for progress first, as the run it starts needs it. */
52
+ #traced(conversationId, draft, context, admit) {
53
+ this.#resume();
54
+ // Inputs and continues start runs: root traces linked to their callers.
55
+ const startsRun = draft.type !== "write";
56
+ const parent = startsRun ? this.#telemetry : context.telemetry;
57
+ return createTypedSpanStarter(parent, [DURABLE_TELEMETRY_SCHEMA])("pi.durable.submit", {
58
+ "submission.type": draft.type,
59
+ "conversation.id": conversationId,
60
+ }, async (span) => {
61
+ if (startsRun)
62
+ span.addLink({ context: context.telemetry });
63
+ try {
64
+ const admission = await admit(span);
65
+ span.setAttributes({ "submission.id": admission.id, result: admission.status });
66
+ return admission;
67
+ }
68
+ catch (error) {
69
+ // Error text may contain caller content. Record only the status.
70
+ span.setStatus({ status: "error" });
71
+ throw error;
72
+ }
73
+ });
74
+ }
36
75
  /** Handle for an existing submission, or `undefined`. */
37
76
  async get(id, context) {
38
- const record = await this.#session.readOnLine(() => this.#storage.submission(id, context));
77
+ const record = await this.#session.readOnLine((storage) => storage.submission(id, context));
39
78
  return record === undefined ? undefined : new SubmissionHandle(record.id, this);
40
79
  }
41
80
  async status(id, context) {
42
- const record = await this.#session.readOnLine(() => this.#storage.submission(id, context));
81
+ const record = await this.#session.readOnLine((storage) => storage.submission(id, context));
43
82
  if (record === undefined)
44
83
  throw new Error(`Submission ${id} does not exist`);
45
84
  return record;
@@ -47,8 +86,8 @@ export class Submissions {
47
86
  async wait(id, context) {
48
87
  this.#resume();
49
88
  // Check and register on the line so no settling publication falls between them.
50
- const found = await this.#session.readOnLine(async () => {
51
- const record = await this.#storage.submission(id, context);
89
+ const found = await this.#session.readOnLine(async (storage) => {
90
+ const record = await storage.submission(id, context);
52
91
  if (record === undefined)
53
92
  throw new Error(`Submission ${id} does not exist`);
54
93
  if (isSettled(record))
@@ -76,6 +115,9 @@ export class Submissions {
76
115
  }, context);
77
116
  }
78
117
  #observe(publication) {
118
+ // A commit held in memory changes documents only.
119
+ if (publication.kind === "memory")
120
+ return;
79
121
  for (const change of publication.changes) {
80
122
  if (change.type !== "submission" || !isSettled(change.value))
81
123
  continue;
@@ -114,16 +156,18 @@ function checkInputEntry(entry) {
114
156
  }
115
157
  }
116
158
  /**
117
- * Admit a submission inside a commit (spec §6); `Conversation.submit()` and conversation-owned compactions share it. A
118
- * known request ID returns its existing submission without writing. A display-only write (only `kind` and `data`) is
119
- * appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a queued reset it
120
- * queues, so it lands after the reset instead of before it in the context the reset ends. A busy conversation queues anything else in
121
- * `pi.inbox`, or rejects `whenBusy: "reject"` input with `ConversationBusy`. An idle conversation with queued items
122
- * queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the input's
123
- * own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head reaches
124
- * before the active range.
159
+ * Admit a submission inside a commit (spec §6); both `Conversation.submit()` forms and conversation-owned compactions
160
+ * share it. A known request ID returns its existing submission without writing. A display-only write (only `kind` and
161
+ * `data`) is appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a
162
+ * queued reset it queues, so it lands after the reset instead of before it in the context the reset ends. A busy
163
+ * conversation queues anything else in `pi.inbox`, or rejects `whenBusy: "reject"` input and any continue with
164
+ * `ConversationBusy`; an idle one rejects `whenIdle: "reject"` input with `ConversationIdle`. An idle continue places
165
+ * queued items and starts a run with them and itself, placing no entry of its own. An idle conversation with queued
166
+ * items queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the
167
+ * input's own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head
168
+ * reaches before the active range.
125
169
  */
126
- export async function admitSubmission(tx, conversationId, draft, now, queueModes) {
170
+ export async function admitSubmission(tx, conversationId, draft, now, queueModes, span) {
127
171
  if (draft.type === "input" && draft.entry !== undefined)
128
172
  checkInputEntry(draft.entry);
129
173
  if (draft.requestId !== undefined) {
@@ -132,27 +176,48 @@ export async function admitSubmission(tx, conversationId, draft, now, queueModes
132
176
  if (existing.type !== draft.type) {
133
177
  throw new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);
134
178
  }
135
- return existing.id;
179
+ return { id: existing.id, status: existing.status === "unanswered" ? "done" : existing.status };
136
180
  }
137
181
  }
138
- const requestId = draft.requestId === undefined ? {} : { requestId: draft.requestId };
182
+ const fields = { conversationId, requestId: draft.requestId, trace: span?.propagation?.inject(span) };
139
183
  if (draft.type === "write" &&
140
184
  isDisplayOnly(draft.entry) &&
141
185
  !hasQueuedReset((await tx.doc(InboxDoc, conversationId)).items)) {
142
186
  const entry = await tx.appendEntry(conversationId, draft.entry);
143
- const write = { conversationId, ...requestId, type: "write", status: "done", entry: entry.id };
144
- return (await tx.createSubmission(write)).id;
187
+ const write = { ...fields, type: "write", status: "done", entry: entry.id };
188
+ return { id: (await tx.createSubmission(write)).id, status: "done" };
145
189
  }
146
190
  const live = await tx.doc(LiveDoc, conversationId);
147
191
  const busy = live.run !== undefined;
192
+ if (draft.type === "input" &&
193
+ draft.whenBusy === "steer" &&
194
+ live.run !== undefined &&
195
+ span?.propagation !== undefined) {
196
+ const run = await tx.task(live.run.taskId);
197
+ if (run?.trace !== undefined)
198
+ span.addLink({ context: span.propagation.extract(run.trace) });
199
+ }
148
200
  if (busy && draft.type === "input" && draft.whenBusy === "reject")
149
201
  throw new ConversationBusy(conversationId);
202
+ if (!busy && draft.type === "input" && draft.whenIdle === "reject")
203
+ throw new ConversationIdle(conversationId);
204
+ if (draft.type === "continue") {
205
+ // Never queued: whether a run can continue depends on how the current one ends. Rejected before any write.
206
+ if (busy)
207
+ throw new ConversationBusy(conversationId);
208
+ const boundary = await prepareBoundary(tx, conversationId, queueModes);
209
+ const { id } = await tx.createSubmission({ ...fields, type: "continue", status: "placed" });
210
+ // Items an earlier failed run left queued (`afterFailedRun: "keep"`) are placed first and join the run. Its history
211
+ // starts with the failed run's, so `afterRun` hooks see what that run did.
212
+ const { users, first } = await applyBoundary(tx, boundary, "final", now);
213
+ await startRun(tx, conversationId, live, { inputs: [...users, id], first: live.runFailure?.first ?? first });
214
+ return { id, status: "placed" };
215
+ }
150
216
  // A boundary reads the table, so it is prepared before the first table write; a busy one needs none.
151
217
  const boundary = busy ? undefined : await prepareBoundary(tx, conversationId, queueModes);
152
218
  if (boundary === undefined || boundary.inbox.items.length > 0) {
153
219
  const { id } = await tx.createSubmission({
154
- conversationId,
155
- ...requestId,
220
+ ...fields,
156
221
  type: draft.type,
157
222
  status: "queued",
158
223
  });
@@ -170,25 +235,28 @@ export async function admitSubmission(tx, conversationId, draft, now, queueModes
170
235
  items.push({ id, mode, content, ...entry });
171
236
  }
172
237
  if (boundary === undefined)
173
- return id;
174
- const { users } = await applyBoundary(tx, boundary, "final", now);
238
+ return { id, status: "queued" };
239
+ const { users, first } = await applyBoundary(tx, boundary, "final", now);
175
240
  if (users.length > 0)
176
- await startRun(tx, conversationId, live, users);
177
- return id;
241
+ await startRun(tx, conversationId, live, { inputs: users, first });
242
+ return { id, status: draft.type === "write" ? "done" : users.at(-1) === id ? "placed" : "queued" };
178
243
  }
179
244
  if (draft.type === "write") {
180
245
  if (isStale(boundary, draft.entry)) {
181
246
  const stale = { status: "unanswered", reason: "stale" };
182
- return (await tx.createSubmission({ conversationId, ...requestId, type: "write", ...stale })).id;
247
+ return {
248
+ id: (await tx.createSubmission({ ...fields, type: "write", ...stale })).id,
249
+ status: "done",
250
+ };
183
251
  }
184
252
  const entry = await tx.appendEntry(conversationId, draft.entry);
185
- const write = { conversationId, ...requestId, type: "write", status: "done", entry: entry.id };
186
- return (await tx.createSubmission(write)).id;
253
+ const write = { ...fields, type: "write", status: "done", entry: entry.id };
254
+ return { id: (await tx.createSubmission(write)).id, status: "done" };
187
255
  }
188
256
  const entry = await appendInput(tx, conversationId, draft.content, draft.entry, now);
189
- const input = { conversationId, ...requestId, type: "input", status: "placed", entry: entry.id };
257
+ const input = { ...fields, type: "input", status: "placed", entry: entry.id };
190
258
  const { id } = await tx.createSubmission(input);
191
- await startRun(tx, conversationId, live, [id]);
192
- return id;
259
+ await startRun(tx, conversationId, live, { inputs: [id], first: entry.id });
260
+ return { id, status: "placed" };
193
261
  }
194
262
  //# sourceMappingURL=submissions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"submissions.js","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, copyJson, type JsonRepresentation } from \"@earendil-works/chord\";\nimport { ConversationBusy } from \"../errors.ts\";\nimport type { SessionImpl } from \"../session/session.ts\";\nimport type {\n\tCommitPublication,\n\tConversationId,\n\tJsonObject,\n\tStorage,\n\tSubmissionId,\n\tSubmissionRecord,\n\tTx,\n} from \"../types.ts\";\nimport { startRun } from \"./generation.ts\";\nimport {\n\tappendInput,\n\tapplyBoundary,\n\thasQueuedReset,\n\tInboxDoc,\n\tisDisplayOnly,\n\tisStale,\n\tpickInputEntry,\n\tprepareBoundary,\n\ttype QueueModes,\n\tremoveInboxItem,\n} from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport type { InputEntry, SettledSubmissionRecord, Submission, SubmissionDraft, UserInput } from \"./types.ts\";\nimport { closedError, Waiters } from \"./util.ts\";\n\ntype AbortResult = \"aborted\" | \"already_placed\" | \"settled\";\n\n/** Admission, waits, and withdrawal of the durable submissions of one Harness. */\nexport class Submissions {\n\treadonly #session: SessionImpl;\n\treadonly #storage: Storage;\n\treadonly #now: () => number;\n\t/** Read at each admission, on the Session line. */\n\treadonly #queueModes: () => QueueModes;\n\t/** Enable task scheduling; submitting or waiting asks for progress. */\n\treadonly #resume: () => void;\n\treadonly #waiters = new Waiters<SubmissionId, SettledSubmissionRecord>();\n\t#closed = false;\n\n\tconstructor(\n\t\tsession: SessionImpl,\n\t\tstorage: Storage,\n\t\tnow: () => number,\n\t\tqueueModes: () => QueueModes,\n\t\tresume: () => void,\n\t) {\n\t\tthis.#session = session;\n\t\tthis.#storage = storage;\n\t\tthis.#now = now;\n\t\tthis.#queueModes = queueModes;\n\t\tthis.#resume = resume;\n\t\tsession.observeCommits((publication) => this.#observe(publication));\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tthis.#waiters.rejectAll(closedError(this.#session));\n\t\t});\n\t}\n\n\t/** Admit a submission in one commit; see `admitSubmission()`. */\n\tasync submit(conversationId: ConversationId, draft: SubmissionDraft, context: Context): Promise<Submission> {\n\t\tthis.#resume();\n\t\tconst id = await this.#session.commitWith(\n\t\t\t(tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes()),\n\t\t\tcontext,\n\t\t);\n\t\treturn new SubmissionHandle(id, this);\n\t}\n\n\t/** Handle for an existing submission, or `undefined`. */\n\tasync get(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\treturn record === undefined ? undefined : new SubmissionHandle(record.id, this);\n\t}\n\n\tasync status(id: SubmissionId, context: Context): Promise<SubmissionRecord> {\n\t\tconst record = await this.#session.readOnLine(() => this.#storage.submission(id, context));\n\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\treturn record;\n\t}\n\n\tasync wait(id: SubmissionId, context: Context): Promise<SettledSubmissionRecord> {\n\t\tthis.#resume();\n\t\t// Check and register on the line so no settling publication falls between them.\n\t\tconst found = await this.#session.readOnLine(async () => {\n\t\t\tconst record = await this.#storage.submission(id, context);\n\t\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\t\tif (isSettled(record)) return { promise: Promise.resolve(record) };\n\t\t\t// Close rejects registered waiters synchronously and may begin during the read.\n\t\t\tif (this.#closed) throw closedError(this.#session);\n\t\t\treturn { promise: this.#waiters.add(id, context) };\n\t\t});\n\t\treturn found.promise;\n\t}\n\n\t/** Withdraw a queued submission and remove its inbox item; placed inputs and settled submissions are reported. */\n\tabort(id: SubmissionId, context: Context, conversationId?: ConversationId): Promise<AbortResult | \"not_found\"> {\n\t\treturn this.#session.commitWith(async (tx) => {\n\t\t\tconst record = await tx.submission(id);\n\t\t\tif (record === undefined || (conversationId !== undefined && record.conversationId !== conversationId)) {\n\t\t\t\treturn \"not_found\";\n\t\t\t}\n\t\t\tif (record.status === \"queued\") {\n\t\t\t\ttx.settleSubmission(id, { status: \"unanswered\", reason: \"aborted\" });\n\t\t\t\tawait removeInboxItem(tx, record.conversationId, id);\n\t\t\t\treturn \"aborted\";\n\t\t\t}\n\t\t\treturn record.status === \"placed\" ? \"already_placed\" : \"settled\";\n\t\t}, context);\n\t}\n\n\t#observe(publication: CommitPublication): void {\n\t\tfor (const change of publication.changes) {\n\t\t\tif (change.type !== \"submission\" || !isSettled(change.value)) continue;\n\t\t\tthis.#waiters.resolve(change.value.id, change.value);\n\t\t}\n\t}\n}\n\nclass SubmissionHandle implements Submission {\n\treadonly id: SubmissionId;\n\treadonly #submissions: Submissions;\n\n\tconstructor(id: SubmissionId, submissions: Submissions) {\n\t\tthis.id = id;\n\t\tthis.#submissions = submissions;\n\t}\n\n\tstatus(context: Context): Promise<SubmissionRecord> {\n\t\treturn this.#submissions.status(this.id, context);\n\t}\n\n\twait(context: Context): Promise<SettledSubmissionRecord> {\n\t\treturn this.#submissions.wait(this.id, context);\n\t}\n\n\tasync abort(context: Context): Promise<AbortResult> {\n\t\tconst result = await this.#submissions.abort(this.id, context);\n\t\tif (result === \"not_found\") throw new Error(`Submission ${this.id} does not exist`);\n\t\treturn result;\n\t}\n}\n\nfunction isSettled(record: SubmissionRecord): record is SettledSubmissionRecord {\n\treturn record.status === \"done\" || record.status === \"unanswered\";\n}\n\n/** Reject an input entry an untyped caller got wrong: its kind must be a non-empty string outside the `pi.` prefix. */\nfunction checkInputEntry(entry: InputEntry): void {\n\tconst { kind } = entry;\n\tif (typeof kind !== \"string\" || kind.length === 0 || kind.startsWith(\"pi.\")) {\n\t\tthrow new TypeError(\n\t\t\t`An input entry's kind must be a non-empty string not starting with \"pi.\", got ${String(kind)}`,\n\t\t);\n\t}\n}\n\n/**\n * Admit a submission inside a commit (spec §6); `Conversation.submit()` and conversation-owned compactions share it. A\n * known request ID returns its existing submission without writing. A display-only write (only `kind` and `data`) is\n * appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a queued reset it\n * queues, so it lands after the reset instead of before it in the context the reset ends. A busy conversation queues anything else in\n * `pi.inbox`, or rejects `whenBusy: \"reject\"` input with `ConversationBusy`. An idle conversation with queued items\n * queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the input's\n * own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head reaches\n * before the active range.\n */\nexport async function admitSubmission(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tdraft: SubmissionDraft,\n\tnow: number,\n\tqueueModes: QueueModes,\n): Promise<SubmissionId> {\n\tif (draft.type === \"input\" && draft.entry !== undefined) checkInputEntry(draft.entry);\n\tif (draft.requestId !== undefined) {\n\t\tconst existing = await tx.submissionByRequest(conversationId, draft.requestId);\n\t\tif (existing !== undefined) {\n\t\t\tif (existing.type !== draft.type) {\n\t\t\t\tthrow new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);\n\t\t\t}\n\t\t\treturn existing.id;\n\t\t}\n\t}\n\tconst requestId = draft.requestId === undefined ? {} : { requestId: draft.requestId };\n\tif (\n\t\tdraft.type === \"write\" &&\n\t\tisDisplayOnly(draft.entry) &&\n\t\t!hasQueuedReset((await tx.doc(InboxDoc, conversationId)).items)\n\t) {\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { conversationId, ...requestId, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn (await tx.createSubmission(write)).id;\n\t}\n\tconst live = await tx.doc(LiveDoc, conversationId);\n\tconst busy = live.run !== undefined;\n\tif (busy && draft.type === \"input\" && draft.whenBusy === \"reject\") throw new ConversationBusy(conversationId);\n\t// A boundary reads the table, so it is prepared before the first table write; a busy one needs none.\n\tconst boundary = busy ? undefined : await prepareBoundary(tx, conversationId, queueModes);\n\tif (boundary === undefined || boundary.inbox.items.length > 0) {\n\t\tconst { id } = await tx.createSubmission({\n\t\t\tconversationId,\n\t\t\t...requestId,\n\t\t\ttype: draft.type,\n\t\t\tstatus: \"queued\",\n\t\t});\n\t\t// Hosts may leave optional fields `undefined`; drafts take strict JSON.\n\t\tconst value = copyJson(draft.type === \"write\" ? draft.entry : draft.content, {\n\t\t\tomitUndefinedProperties: true,\n\t\t});\n\t\tconst items = (boundary?.inbox ?? (await tx.doc(InboxDoc, conversationId))).items;\n\t\tif (draft.type === \"write\") items.push({ id, mode: \"write\", entry: value as JsonObject });\n\t\telse {\n\t\t\tconst mode = draft.whenBusy === \"steer\" ? \"steer\" : \"followUp\";\n\t\t\tconst content = value as JsonRepresentation<UserInput>;\n\t\t\tconst entry = draft.entry === undefined ? {} : { entry: pickInputEntry(draft.entry) };\n\t\t\titems.push({ id, mode, content, ...entry });\n\t\t}\n\t\tif (boundary === undefined) return id;\n\t\tconst { users } = await applyBoundary(tx, boundary, \"final\", now);\n\t\tif (users.length > 0) await startRun(tx, conversationId, live, users);\n\t\treturn id;\n\t}\n\tif (draft.type === \"write\") {\n\t\tif (isStale(boundary, draft.entry)) {\n\t\t\tconst stale = { status: \"unanswered\", reason: \"stale\" } as const;\n\t\t\treturn (await tx.createSubmission({ conversationId, ...requestId, type: \"write\", ...stale })).id;\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { conversationId, ...requestId, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn (await tx.createSubmission(write)).id;\n\t}\n\tconst entry = await appendInput(tx, conversationId, draft.content, draft.entry, now);\n\tconst input = { conversationId, ...requestId, type: \"input\", status: \"placed\", entry: entry.id } as const;\n\tconst { id } = await tx.createSubmission(input);\n\tawait startRun(tx, conversationId, live, [id]);\n\treturn id;\n}\n"]}
1
+ {"version":3,"file":"submissions.js","sourceRoot":"","sources":["../../src/harness/submissions.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Context, copyJson, type JsonRepresentation } from \"@earendil-works/chord\";\nimport { withTelemetry } from \"@earendil-works/chord/context\";\nimport {\n\tcreateTypedSpanStarter,\n\tNOOP_TELEMETRY_CONTEXT,\n\ttype TelemetryContext,\n\ttype TelemetrySpan,\n} from \"@earendil-works/pi-telemetry\";\nimport { ConversationBusy, ConversationIdle, ReadAfterWrite } from \"../errors.ts\";\nimport type { ObservedCommit, SessionImpl } from \"../session/session.ts\";\nimport type { ConversationId, JsonObject, SubmissionId, SubmissionRecord, Tx } from \"../types.ts\";\nimport { startRun } from \"./generation.ts\";\nimport {\n\tappendInput,\n\tapplyBoundary,\n\thasQueuedReset,\n\tInboxDoc,\n\tisDisplayOnly,\n\tisStale,\n\tpickInputEntry,\n\tprepareBoundary,\n\ttype QueueModes,\n\tremoveInboxItem,\n} from \"./inbox.ts\";\nimport { LiveDoc } from \"./live.ts\";\nimport { DURABLE_TELEMETRY_SCHEMA } from \"./telemetry.ts\";\nimport type { InputEntry, SettledSubmissionRecord, Submission, SubmissionDraft, UserInput } from \"./types.ts\";\nimport { closedError, Waiters } from \"./util.ts\";\n\ntype AbortResult = \"aborted\" | \"already_placed\" | \"settled\";\ntype Admission = { readonly id: SubmissionId; readonly status: \"queued\" | \"placed\" | \"done\" };\n\n/** Admission, waits, and withdrawal of the durable submissions of one Harness. */\nexport class Submissions {\n\treadonly #telemetry: TelemetryContext;\n\treadonly #session: SessionImpl;\n\treadonly #now: () => number;\n\t/** Read at each admission, on the Session line. */\n\treadonly #queueModes: () => QueueModes;\n\t/** Enable task scheduling; submitting or waiting asks for progress. */\n\treadonly #resume: () => void;\n\treadonly #waiters = new Waiters<SubmissionId, SettledSubmissionRecord>();\n\t#closed = false;\n\n\tconstructor(\n\t\tsession: SessionImpl,\n\t\tnow: () => number,\n\t\tqueueModes: () => QueueModes,\n\t\tresume: () => void,\n\t\ttelemetry: TelemetryContext = NOOP_TELEMETRY_CONTEXT,\n\t) {\n\t\tthis.#telemetry = telemetry;\n\t\tthis.#session = session;\n\t\tthis.#now = now;\n\t\tthis.#queueModes = queueModes;\n\t\tthis.#resume = resume;\n\t\tsession.followCommits((publication) => this.#observe(publication));\n\t\tsession.subscribeClose(() => {\n\t\t\tthis.#closed = true;\n\t\t\tthis.#waiters.rejectAll(closedError(this.#session));\n\t\t});\n\t}\n\n\t/** Admit a submission in one commit; see `admitSubmission()`. */\n\tasync submit(conversationId: ConversationId, draft: SubmissionDraft, context: Context): Promise<Submission> {\n\t\tconst { id } = await this.#traced(conversationId, draft, context, (span) =>\n\t\t\tthis.#session.commitWith(\n\t\t\t\t(tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span),\n\t\t\t\twithTelemetry(span, context),\n\t\t\t),\n\t\t);\n\t\treturn new SubmissionHandle(id, this);\n\t}\n\n\t/**\n\t * Admit a submission inside the caller's commit `tx`, with the rules of `submit()`. The admission is stored or lost\n\t * with that commit. It must come before the commit's first table write, another admission's included.\n\t */\n\tasync admit(tx: Tx, conversationId: ConversationId, draft: SubmissionDraft): Promise<SubmissionId> {\n\t\tif (!this.#session.ownsTransaction(tx)) throw new Error(\"The transaction belongs to another Session\");\n\t\t// Enforced on every path: admission reads tables only on some (request IDs, an idle boundary, a steer's trace).\n\t\tif (tx.hasTableWrite) throw new ReadAfterWrite(\"submit(tx, draft)\");\n\t\tconst admission = await this.#traced(conversationId, draft, tx.context, (span) =>\n\t\t\tadmitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span),\n\t\t);\n\t\treturn admission.id;\n\t}\n\n\t/** Run one admission in its `pi.durable.submit` span, asking for progress first, as the run it starts needs it. */\n\t#traced(\n\t\tconversationId: ConversationId,\n\t\tdraft: SubmissionDraft,\n\t\tcontext: Context,\n\t\tadmit: (span: TelemetrySpan) => Promise<Admission>,\n\t): Promise<Admission> {\n\t\tthis.#resume();\n\t\t// Inputs and continues start runs: root traces linked to their callers.\n\t\tconst startsRun = draft.type !== \"write\";\n\t\tconst parent = startsRun ? this.#telemetry : context.telemetry;\n\t\treturn createTypedSpanStarter(parent, [DURABLE_TELEMETRY_SCHEMA])(\n\t\t\t\"pi.durable.submit\",\n\t\t\t{\n\t\t\t\t\"submission.type\": draft.type,\n\t\t\t\t\"conversation.id\": conversationId,\n\t\t\t},\n\t\t\tasync (span) => {\n\t\t\t\tif (startsRun) span.addLink({ context: context.telemetry });\n\t\t\t\ttry {\n\t\t\t\t\tconst admission = await admit(span);\n\t\t\t\t\tspan.setAttributes({ \"submission.id\": admission.id, result: admission.status });\n\t\t\t\t\treturn admission;\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Error text may contain caller content. Record only the status.\n\t\t\t\t\tspan.setStatus({ status: \"error\" });\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\t/** Handle for an existing submission, or `undefined`. */\n\tasync get(id: SubmissionId, context: Context): Promise<Submission | undefined> {\n\t\tconst record = await this.#session.readOnLine((storage) => storage.submission(id, context));\n\t\treturn record === undefined ? undefined : new SubmissionHandle(record.id, this);\n\t}\n\n\tasync status(id: SubmissionId, context: Context): Promise<SubmissionRecord> {\n\t\tconst record = await this.#session.readOnLine((storage) => storage.submission(id, context));\n\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\treturn record;\n\t}\n\n\tasync wait(id: SubmissionId, context: Context): Promise<SettledSubmissionRecord> {\n\t\tthis.#resume();\n\t\t// Check and register on the line so no settling publication falls between them.\n\t\tconst found = await this.#session.readOnLine(async (storage) => {\n\t\t\tconst record = await storage.submission(id, context);\n\t\t\tif (record === undefined) throw new Error(`Submission ${id} does not exist`);\n\t\t\tif (isSettled(record)) return { promise: Promise.resolve(record) };\n\t\t\t// Close rejects registered waiters synchronously and may begin during the read.\n\t\t\tif (this.#closed) throw closedError(this.#session);\n\t\t\treturn { promise: this.#waiters.add(id, context) };\n\t\t});\n\t\treturn found.promise;\n\t}\n\n\t/** Withdraw a queued submission and remove its inbox item; placed inputs and settled submissions are reported. */\n\tabort(id: SubmissionId, context: Context, conversationId?: ConversationId): Promise<AbortResult | \"not_found\"> {\n\t\treturn this.#session.commitWith(async (tx) => {\n\t\t\tconst record = await tx.submission(id);\n\t\t\tif (record === undefined || (conversationId !== undefined && record.conversationId !== conversationId)) {\n\t\t\t\treturn \"not_found\";\n\t\t\t}\n\t\t\tif (record.status === \"queued\") {\n\t\t\t\ttx.settleSubmission(id, { status: \"unanswered\", reason: \"aborted\" });\n\t\t\t\tawait removeInboxItem(tx, record.conversationId, id);\n\t\t\t\treturn \"aborted\";\n\t\t\t}\n\t\t\treturn record.status === \"placed\" ? \"already_placed\" : \"settled\";\n\t\t}, context);\n\t}\n\n\t#observe(publication: ObservedCommit): void {\n\t\t// A commit held in memory changes documents only.\n\t\tif (publication.kind === \"memory\") return;\n\t\tfor (const change of publication.changes) {\n\t\t\tif (change.type !== \"submission\" || !isSettled(change.value)) continue;\n\t\t\tthis.#waiters.resolve(change.value.id, change.value);\n\t\t}\n\t}\n}\n\nclass SubmissionHandle implements Submission {\n\treadonly id: SubmissionId;\n\treadonly #submissions: Submissions;\n\n\tconstructor(id: SubmissionId, submissions: Submissions) {\n\t\tthis.id = id;\n\t\tthis.#submissions = submissions;\n\t}\n\n\tstatus(context: Context): Promise<SubmissionRecord> {\n\t\treturn this.#submissions.status(this.id, context);\n\t}\n\n\twait(context: Context): Promise<SettledSubmissionRecord> {\n\t\treturn this.#submissions.wait(this.id, context);\n\t}\n\n\tasync abort(context: Context): Promise<AbortResult> {\n\t\tconst result = await this.#submissions.abort(this.id, context);\n\t\tif (result === \"not_found\") throw new Error(`Submission ${this.id} does not exist`);\n\t\treturn result;\n\t}\n}\n\nfunction isSettled(record: SubmissionRecord): record is SettledSubmissionRecord {\n\treturn record.status === \"done\" || record.status === \"unanswered\";\n}\n\n/** Reject an input entry an untyped caller got wrong: its kind must be a non-empty string outside the `pi.` prefix. */\nfunction checkInputEntry(entry: InputEntry): void {\n\tconst { kind } = entry;\n\tif (typeof kind !== \"string\" || kind.length === 0 || kind.startsWith(\"pi.\")) {\n\t\tthrow new TypeError(\n\t\t\t`An input entry's kind must be a non-empty string not starting with \"pi.\", got ${String(kind)}`,\n\t\t);\n\t}\n}\n\n/**\n * Admit a submission inside a commit (spec §6); both `Conversation.submit()` forms and conversation-owned compactions\n * share it. A known request ID returns its existing submission without writing. A display-only write (only `kind` and\n * `data`) is appended and settled `done` at once, busy or not, as it changes nothing the model sees; only behind a\n * queued reset it queues, so it lands after the reset instead of before it in the context the reset ends. A busy\n * conversation queues anything else in `pi.inbox`, or rejects `whenBusy: \"reject\"` input and any continue with\n * `ConversationBusy`; an idle one rejects `whenIdle: \"reject\"` input with `ConversationIdle`. An idle continue places\n * queued items and starts a run with them and itself, placing no entry of its own. An idle conversation with queued\n * items queues it behind them and runs a final boundary. Otherwise idle input places its entry (`pi.user`, or the\n * input's own) and starts a run, and an idle write appends its entry and settles `done`, or `stale` when its head\n * reaches before the active range.\n */\nexport async function admitSubmission(\n\ttx: Tx,\n\tconversationId: ConversationId,\n\tdraft: SubmissionDraft,\n\tnow: number,\n\tqueueModes: QueueModes,\n\tspan?: TelemetrySpan,\n): Promise<Admission> {\n\tif (draft.type === \"input\" && draft.entry !== undefined) checkInputEntry(draft.entry);\n\tif (draft.requestId !== undefined) {\n\t\tconst existing = await tx.submissionByRequest(conversationId, draft.requestId);\n\t\tif (existing !== undefined) {\n\t\t\tif (existing.type !== draft.type) {\n\t\t\t\tthrow new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);\n\t\t\t}\n\t\t\treturn { id: existing.id, status: existing.status === \"unanswered\" ? \"done\" : existing.status };\n\t\t}\n\t}\n\tconst fields = { conversationId, requestId: draft.requestId, trace: span?.propagation?.inject(span) };\n\tif (\n\t\tdraft.type === \"write\" &&\n\t\tisDisplayOnly(draft.entry) &&\n\t\t!hasQueuedReset((await tx.doc(InboxDoc, conversationId)).items)\n\t) {\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { ...fields, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn { id: (await tx.createSubmission(write)).id, status: \"done\" };\n\t}\n\tconst live = await tx.doc(LiveDoc, conversationId);\n\tconst busy = live.run !== undefined;\n\tif (\n\t\tdraft.type === \"input\" &&\n\t\tdraft.whenBusy === \"steer\" &&\n\t\tlive.run !== undefined &&\n\t\tspan?.propagation !== undefined\n\t) {\n\t\tconst run = await tx.task(live.run.taskId);\n\t\tif (run?.trace !== undefined) span.addLink({ context: span.propagation.extract(run.trace) });\n\t}\n\tif (busy && draft.type === \"input\" && draft.whenBusy === \"reject\") throw new ConversationBusy(conversationId);\n\tif (!busy && draft.type === \"input\" && draft.whenIdle === \"reject\") throw new ConversationIdle(conversationId);\n\tif (draft.type === \"continue\") {\n\t\t// Never queued: whether a run can continue depends on how the current one ends. Rejected before any write.\n\t\tif (busy) throw new ConversationBusy(conversationId);\n\t\tconst boundary = await prepareBoundary(tx, conversationId, queueModes);\n\t\tconst { id } = await tx.createSubmission({ ...fields, type: \"continue\", status: \"placed\" });\n\t\t// Items an earlier failed run left queued (`afterFailedRun: \"keep\"`) are placed first and join the run. Its history\n\t\t// starts with the failed run's, so `afterRun` hooks see what that run did.\n\t\tconst { users, first } = await applyBoundary(tx, boundary, \"final\", now);\n\t\tawait startRun(tx, conversationId, live, { inputs: [...users, id], first: live.runFailure?.first ?? first });\n\t\treturn { id, status: \"placed\" };\n\t}\n\t// A boundary reads the table, so it is prepared before the first table write; a busy one needs none.\n\tconst boundary = busy ? undefined : await prepareBoundary(tx, conversationId, queueModes);\n\tif (boundary === undefined || boundary.inbox.items.length > 0) {\n\t\tconst { id } = await tx.createSubmission({\n\t\t\t...fields,\n\t\t\ttype: draft.type,\n\t\t\tstatus: \"queued\",\n\t\t});\n\t\t// Hosts may leave optional fields `undefined`; drafts take strict JSON.\n\t\tconst value = copyJson(draft.type === \"write\" ? draft.entry : draft.content, {\n\t\t\tomitUndefinedProperties: true,\n\t\t});\n\t\tconst items = (boundary?.inbox ?? (await tx.doc(InboxDoc, conversationId))).items;\n\t\tif (draft.type === \"write\") items.push({ id, mode: \"write\", entry: value as JsonObject });\n\t\telse {\n\t\t\tconst mode = draft.whenBusy === \"steer\" ? \"steer\" : \"followUp\";\n\t\t\tconst content = value as JsonRepresentation<UserInput>;\n\t\t\tconst entry = draft.entry === undefined ? {} : { entry: pickInputEntry(draft.entry) };\n\t\t\titems.push({ id, mode, content, ...entry });\n\t\t}\n\t\tif (boundary === undefined) return { id, status: \"queued\" };\n\t\tconst { users, first } = await applyBoundary(tx, boundary, \"final\", now);\n\t\tif (users.length > 0) await startRun(tx, conversationId, live, { inputs: users, first });\n\t\treturn { id, status: draft.type === \"write\" ? \"done\" : users.at(-1) === id ? \"placed\" : \"queued\" };\n\t}\n\tif (draft.type === \"write\") {\n\t\tif (isStale(boundary, draft.entry)) {\n\t\t\tconst stale = { status: \"unanswered\", reason: \"stale\" } as const;\n\t\t\treturn {\n\t\t\t\tid: (await tx.createSubmission({ ...fields, type: \"write\", ...stale })).id,\n\t\t\t\tstatus: \"done\",\n\t\t\t};\n\t\t}\n\t\tconst entry = await tx.appendEntry(conversationId, draft.entry);\n\t\tconst write = { ...fields, type: \"write\", status: \"done\", entry: entry.id } as const;\n\t\treturn { id: (await tx.createSubmission(write)).id, status: \"done\" };\n\t}\n\tconst entry = await appendInput(tx, conversationId, draft.content, draft.entry, now);\n\tconst input = { ...fields, type: \"input\", status: \"placed\", entry: entry.id } as const;\n\tconst { id } = await tx.createSubmission(input);\n\tawait startRun(tx, conversationId, live, { inputs: [id], first: entry.id });\n\treturn { id, status: \"placed\" };\n}\n"]}
@@ -1,7 +1,8 @@
1
- import { type AttachedReplicatedState, type Context, type JsonValue } from "@earendil-works/chord";
1
+ import { type Context, type JsonValue, type WatchHandle } from "@earendil-works/chord";
2
2
  import { type SessionImpl } from "../session/session.ts";
3
- import type { ConversationId, JoinPolicy, Storage, TaskId, TaskOutcome, WatchHandle } from "../types.ts";
4
- /** A live task's durable status without its checkpoint and outcome payloads (spec §9.5). */
3
+ import type { ConversationId, JoinPolicy, Observation, Observer, TaskId, TaskOutcome } from "../types.ts";
4
+ import { type BlockedReason, type BlockedSubject } from "./scheduler.ts";
5
+ /** A live task's durable status without its checkpoint and outcome payloads (spec §9.4). */
5
6
  export type TaskGraphState = {
6
7
  readonly status: "pending" | "running";
7
8
  readonly phase: string;
@@ -11,6 +12,12 @@ export type TaskGraphState = {
11
12
  readonly on: readonly TaskId[];
12
13
  readonly policy: JoinPolicy;
13
14
  }
15
+ /** Asleep until the Harness clock reaches `until`. */
16
+ | {
17
+ readonly status: "sleeping";
18
+ readonly phase: string;
19
+ readonly until: number;
20
+ }
14
21
  /** Outcome held until its ordinary owned work drains. */
15
22
  | {
16
23
  readonly status: "completing";
@@ -25,25 +32,38 @@ export type TaskGraphNode = {
25
32
  readonly background: boolean;
26
33
  readonly abortRequested: boolean;
27
34
  readonly state: TaskGraphState;
35
+ /**
36
+ * Why it cannot run here, when it cannot: no registered definition takes it (`missing_task`, `task_too_old`,
37
+ * `migration_failed`). Follows registry changes.
38
+ */
39
+ readonly blocked?: BlockedReason;
28
40
  /** Conversations this task owns, in ID order. */
29
41
  readonly conversations: readonly ConversationId[];
30
42
  };
31
- /** Every live task of the Session (spec §9.5). */
43
+ /** Every live task of the Session (spec §9.4). */
32
44
  export type TaskGraph = {
33
45
  /** Every live task, keyed by its decimal ID. */
34
46
  readonly tasks: Readonly<Record<string, TaskGraphNode>>;
35
47
  };
36
48
  export type TaskGraphWatch = WatchHandle<TaskGraph>;
49
+ /** What the graph asks the scheduler: a task's blocked reason, and when reasons may change without a commit. */
50
+ export type TaskGraphBlocking = {
51
+ readonly blocked: (record: BlockedSubject) => BlockedReason | undefined;
52
+ readonly subscribeBlocked: (listener: () => void) => () => void;
53
+ };
37
54
  /**
38
55
  * The Harness's task graph mount: built on the Session line by its first observer and dropped with its last. It
39
56
  * advances from the Session's commit publications, which are durable.
40
57
  */
41
58
  export declare class TaskGraphView {
42
59
  #private;
43
- constructor(session: SessionImpl, storage: Storage);
44
- /** A disposable read-only Chord state of the graph. */
45
- state(context: Context): Promise<AttachedReplicatedState<TaskGraph>>;
46
- /** A serialized exact-frame watch of the graph; cancelling `context` stops it. */
60
+ constructor(session: SessionImpl, blocking: TaskGraphBlocking);
61
+ /**
62
+ * Attach a synchronous observer of the graph (`Harness.observeTaskGraph()`), behind `guardObserver()`; `context`
63
+ * governs only the attachment.
64
+ */
65
+ observe(observer: Observer<TaskGraph>, context: Context): Promise<Observation<TaskGraph>>;
66
+ /** A serialized watch of the graph, an observer of its mount; aborting `context` ends it `aborted`. */
47
67
  watch(context: Context): Promise<TaskGraphWatch>;
48
68
  }
49
69
  //# sourceMappingURL=task-graph.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-graph.d.ts","sourceRoot":"","sources":["../../src/harness/task-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,uBAAuB,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,uBAAuB,CAAC;AAIpH,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAEX,cAAc,EACd,UAAU,EACV,OAAO,EACP,MAAM,EACN,WAAW,EAEX,WAAW,EACX,MAAM,aAAa,CAAC;AAGrB,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE;IACA,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC3B;AACH,yDAAyD;GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAEzF,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,CAAC;CAClD,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG;IACvB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;AASpD;;;GAGG;AACH,qBAAa,aAAa;;IAMzB,YAAY,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAgBjD;IAED,uDAAuD;IACjD,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,uBAAuB,CAAC,SAAS,CAAC,CAAC,CAWzE;IAED,kFAAkF;IAC5E,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAYrD;CAyCD"}
1
+ {"version":3,"file":"task-graph.d.ts","sourceRoot":"","sources":["../../src/harness/task-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAyB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG9G,OAAO,EAON,KAAK,WAAW,EAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACX,cAAc,EACd,UAAU,EACV,WAAW,EACX,QAAQ,EAER,MAAM,EACN,WAAW,EAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAkB,MAAM,gBAAgB,CAAC;AAGzF,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClE;IACA,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC3B;AACH,sDAAsD;GACpD;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AACjF,yDAAyD;GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAEzF,MAAM,MAAM,aAAa,GAAG;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,iDAAiD;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,cAAc,EAAE,CAAC;CAClD,CAAC;AAEF,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG;IACvB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;AAWpD,gHAAgH;AAChH,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,aAAa,GAAG,SAAS,CAAC;IACxE,QAAQ,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CAChE,CAAC;AAKF;;;GAGG;AACH,qBAAa,aAAa;;IAMzB,YAAY,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAoB5D;IAED;;;OAGG;IACG,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAY9F;IAED,uGAAuG;IACjG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAYrD;CAmED"}