@united-workforce/cli 0.3.0 → 0.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 (319) hide show
  1. package/README.md +45 -11
  2. package/dist/.build-fingerprint +1 -0
  3. package/dist/__tests__/adapter-json-roundtrip.test.js +17 -7
  4. package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
  5. package/dist/__tests__/agent-resolution-llm-free.test.d.ts +2 -0
  6. package/dist/__tests__/agent-resolution-llm-free.test.d.ts.map +1 -0
  7. package/dist/__tests__/agent-resolution-llm-free.test.js +30 -0
  8. package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -0
  9. package/dist/__tests__/build-step-entry.test.d.ts +2 -0
  10. package/dist/__tests__/build-step-entry.test.d.ts.map +1 -0
  11. package/dist/__tests__/build-step-entry.test.js +173 -0
  12. package/dist/__tests__/build-step-entry.test.js.map +1 -0
  13. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts +2 -0
  14. package/dist/__tests__/clear-thread-failed-attempts.test.d.ts.map +1 -0
  15. package/dist/__tests__/clear-thread-failed-attempts.test.js +93 -0
  16. package/dist/__tests__/clear-thread-failed-attempts.test.js.map +1 -0
  17. package/dist/__tests__/concurrency.test.d.ts +2 -0
  18. package/dist/__tests__/concurrency.test.d.ts.map +1 -0
  19. package/dist/__tests__/concurrency.test.js +196 -0
  20. package/dist/__tests__/concurrency.test.js.map +1 -0
  21. package/dist/__tests__/config.test.js +26 -302
  22. package/dist/__tests__/config.test.js.map +1 -1
  23. package/dist/__tests__/current-role.test.js +7 -6
  24. package/dist/__tests__/current-role.test.js.map +1 -1
  25. package/dist/__tests__/e2e-mock-agent.test.js +43 -30
  26. package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
  27. package/dist/__tests__/format-text-default.test.d.ts +2 -0
  28. package/dist/__tests__/format-text-default.test.d.ts.map +1 -0
  29. package/dist/__tests__/format-text-default.test.js +43 -0
  30. package/dist/__tests__/format-text-default.test.js.map +1 -0
  31. package/dist/__tests__/format-text-registry.test.d.ts +2 -0
  32. package/dist/__tests__/format-text-registry.test.d.ts.map +1 -0
  33. package/dist/__tests__/format-text-registry.test.js +158 -0
  34. package/dist/__tests__/format-text-registry.test.js.map +1 -0
  35. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts +2 -0
  36. package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts.map +1 -0
  37. package/dist/__tests__/issue-180-workflow-ref-removed.test.js +40 -0
  38. package/dist/__tests__/issue-180-workflow-ref-removed.test.js.map +1 -0
  39. package/dist/__tests__/log-text-renderer.test.d.ts +2 -0
  40. package/dist/__tests__/log-text-renderer.test.d.ts.map +1 -0
  41. package/dist/__tests__/log-text-renderer.test.js +265 -0
  42. package/dist/__tests__/log-text-renderer.test.js.map +1 -0
  43. package/dist/__tests__/moderator-evaluate.test.js +9 -50
  44. package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
  45. package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts +2 -0
  46. package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts.map +1 -0
  47. package/dist/__tests__/output-mapper-thread-list-startedat.test.js +102 -0
  48. package/dist/__tests__/output-mapper-thread-list-startedat.test.js.map +1 -0
  49. package/dist/__tests__/output-mapper-workflow-add.test.d.ts +2 -0
  50. package/dist/__tests__/output-mapper-workflow-add.test.d.ts.map +1 -0
  51. package/dist/__tests__/output-mapper-workflow-add.test.js +22 -0
  52. package/dist/__tests__/output-mapper-workflow-add.test.js.map +1 -0
  53. package/dist/__tests__/pid-recycling.test.d.ts +2 -0
  54. package/dist/__tests__/pid-recycling.test.d.ts.map +1 -0
  55. package/dist/__tests__/pid-recycling.test.js +273 -0
  56. package/dist/__tests__/pid-recycling.test.js.map +1 -0
  57. package/dist/__tests__/prompt.test.js +365 -2
  58. package/dist/__tests__/prompt.test.js.map +1 -1
  59. package/dist/__tests__/resolve-head-hash.test.js +12 -4
  60. package/dist/__tests__/resolve-head-hash.test.js.map +1 -1
  61. package/dist/__tests__/setup-agent-discovery.test.js +21 -30
  62. package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
  63. package/dist/__tests__/setup-complexity.test.js +2 -168
  64. package/dist/__tests__/setup-complexity.test.js.map +1 -1
  65. package/dist/__tests__/setup-no-llm.test.d.ts +2 -0
  66. package/dist/__tests__/setup-no-llm.test.d.ts.map +1 -0
  67. package/dist/__tests__/setup-no-llm.test.js +52 -0
  68. package/dist/__tests__/setup-no-llm.test.js.map +1 -0
  69. package/dist/__tests__/solve-issue-tea-worktree.test.js +27 -28
  70. package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -1
  71. package/dist/__tests__/step-ask.test.d.ts +2 -0
  72. package/dist/__tests__/step-ask.test.d.ts.map +1 -0
  73. package/dist/__tests__/step-ask.test.js +507 -0
  74. package/dist/__tests__/step-ask.test.js.map +1 -0
  75. package/dist/__tests__/step-show-json.test.js +1 -0
  76. package/dist/__tests__/step-show-json.test.js.map +1 -1
  77. package/dist/__tests__/step-timing.test.js +2 -0
  78. package/dist/__tests__/step-timing.test.js.map +1 -1
  79. package/dist/__tests__/store-global-cas.test.js +2 -2
  80. package/dist/__tests__/store-global-cas.test.js.map +1 -1
  81. package/dist/__tests__/store-unified-threads.test.js +28 -26
  82. package/dist/__tests__/store-unified-threads.test.js.map +1 -1
  83. package/dist/__tests__/thread-cancel-status.test.js +25 -19
  84. package/dist/__tests__/thread-cancel-status.test.js.map +1 -1
  85. package/dist/__tests__/thread-cancel-text-renderer.test.d.ts +2 -0
  86. package/dist/__tests__/thread-cancel-text-renderer.test.d.ts.map +1 -0
  87. package/dist/__tests__/thread-cancel-text-renderer.test.js +110 -0
  88. package/dist/__tests__/thread-cancel-text-renderer.test.js.map +1 -0
  89. package/dist/__tests__/thread-list-filters.test.js +354 -17
  90. package/dist/__tests__/thread-list-filters.test.js.map +1 -1
  91. package/dist/__tests__/thread-list-template-ms-date.test.d.ts +2 -0
  92. package/dist/__tests__/thread-list-template-ms-date.test.d.ts.map +1 -0
  93. package/dist/__tests__/thread-list-template-ms-date.test.js +102 -0
  94. package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -0
  95. package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts +2 -0
  96. package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts.map +1 -0
  97. package/dist/__tests__/thread-list-workflow-corrupt.test.js +157 -0
  98. package/dist/__tests__/thread-list-workflow-corrupt.test.js.map +1 -0
  99. package/dist/__tests__/thread-poke.test.d.ts +2 -0
  100. package/dist/__tests__/thread-poke.test.d.ts.map +1 -0
  101. package/dist/__tests__/thread-poke.test.js +422 -0
  102. package/dist/__tests__/thread-poke.test.js.map +1 -0
  103. package/dist/__tests__/thread-read-xml-tags.test.js +10 -9
  104. package/dist/__tests__/thread-read-xml-tags.test.js.map +1 -1
  105. package/dist/__tests__/thread-resume.test.js +21 -15
  106. package/dist/__tests__/thread-resume.test.js.map +1 -1
  107. package/dist/__tests__/thread-show-status.test.js +17 -28
  108. package/dist/__tests__/thread-show-status.test.js.map +1 -1
  109. package/dist/__tests__/thread-start-cwd-cli.test.js +15 -3
  110. package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -1
  111. package/dist/__tests__/thread-stop-text-renderer.test.d.ts +2 -0
  112. package/dist/__tests__/thread-stop-text-renderer.test.d.ts.map +1 -0
  113. package/dist/__tests__/thread-stop-text-renderer.test.js +148 -0
  114. package/dist/__tests__/thread-stop-text-renderer.test.js.map +1 -0
  115. package/dist/__tests__/thread-suspend-step.test.js +13 -16
  116. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  117. package/dist/__tests__/thread-suspended-display.test.js +10 -22
  118. package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
  119. package/dist/__tests__/thread-test-helpers.d.ts +7 -0
  120. package/dist/__tests__/thread-test-helpers.d.ts.map +1 -1
  121. package/dist/__tests__/thread-test-helpers.js +13 -0
  122. package/dist/__tests__/thread-test-helpers.js.map +1 -1
  123. package/dist/__tests__/thread.test.js +15 -13
  124. package/dist/__tests__/thread.test.js.map +1 -1
  125. package/dist/__tests__/validate-semantic.test.js +105 -23
  126. package/dist/__tests__/validate-semantic.test.js.map +1 -1
  127. package/dist/__tests__/workflow-list-recursive.test.d.ts +2 -0
  128. package/dist/__tests__/workflow-list-recursive.test.d.ts.map +1 -0
  129. package/dist/__tests__/workflow-list-recursive.test.js +286 -0
  130. package/dist/__tests__/workflow-list-recursive.test.js.map +1 -0
  131. package/dist/__tests__/workflow-resolution.test.js +46 -28
  132. package/dist/__tests__/workflow-resolution.test.js.map +1 -1
  133. package/dist/__tests__/workflow-show-resolution.test.d.ts +2 -0
  134. package/dist/__tests__/workflow-show-resolution.test.d.ts.map +1 -0
  135. package/dist/__tests__/workflow-show-resolution.test.js +213 -0
  136. package/dist/__tests__/workflow-show-resolution.test.js.map +1 -0
  137. package/dist/__tests__/workflow-validate.test.d.ts +2 -0
  138. package/dist/__tests__/workflow-validate.test.d.ts.map +1 -0
  139. package/dist/__tests__/workflow-validate.test.js +707 -0
  140. package/dist/__tests__/workflow-validate.test.js.map +1 -0
  141. package/dist/__tests__/write-envelope.test.d.ts +2 -0
  142. package/dist/__tests__/write-envelope.test.d.ts.map +1 -0
  143. package/dist/__tests__/write-envelope.test.js +201 -0
  144. package/dist/__tests__/write-envelope.test.js.map +1 -0
  145. package/dist/background/background.d.ts +22 -1
  146. package/dist/background/background.d.ts.map +1 -1
  147. package/dist/background/background.js +83 -6
  148. package/dist/background/background.js.map +1 -1
  149. package/dist/background/index.d.ts +1 -1
  150. package/dist/background/index.d.ts.map +1 -1
  151. package/dist/background/index.js +1 -1
  152. package/dist/background/index.js.map +1 -1
  153. package/dist/background/types.d.ts +1 -0
  154. package/dist/background/types.d.ts.map +1 -1
  155. package/dist/cli.js +120 -62
  156. package/dist/cli.js.map +1 -1
  157. package/dist/commands/config.d.ts +3 -1
  158. package/dist/commands/config.d.ts.map +1 -1
  159. package/dist/commands/config.js +17 -31
  160. package/dist/commands/config.js.map +1 -1
  161. package/dist/commands/prompt.d.ts.map +1 -1
  162. package/dist/commands/prompt.js +57 -31
  163. package/dist/commands/prompt.js.map +1 -1
  164. package/dist/commands/setup.d.ts +12 -39
  165. package/dist/commands/setup.d.ts.map +1 -1
  166. package/dist/commands/setup.js +72 -303
  167. package/dist/commands/setup.js.map +1 -1
  168. package/dist/commands/step.d.ts +44 -1
  169. package/dist/commands/step.d.ts.map +1 -1
  170. package/dist/commands/step.js +255 -11
  171. package/dist/commands/step.js.map +1 -1
  172. package/dist/commands/thread.d.ts +16 -3
  173. package/dist/commands/thread.d.ts.map +1 -1
  174. package/dist/commands/thread.js +423 -142
  175. package/dist/commands/thread.js.map +1 -1
  176. package/dist/commands/workflow.d.ts +9 -1
  177. package/dist/commands/workflow.d.ts.map +1 -1
  178. package/dist/commands/workflow.js +126 -6
  179. package/dist/commands/workflow.js.map +1 -1
  180. package/dist/concurrency/concurrency.d.ts +34 -0
  181. package/dist/concurrency/concurrency.d.ts.map +1 -0
  182. package/dist/concurrency/concurrency.js +216 -0
  183. package/dist/concurrency/concurrency.js.map +1 -0
  184. package/dist/concurrency/index.d.ts +3 -0
  185. package/dist/concurrency/index.d.ts.map +1 -0
  186. package/dist/concurrency/index.js +2 -0
  187. package/dist/concurrency/index.js.map +1 -0
  188. package/dist/concurrency/types.d.ts +19 -0
  189. package/dist/concurrency/types.d.ts.map +1 -0
  190. package/dist/concurrency/types.js +2 -0
  191. package/dist/concurrency/types.js.map +1 -0
  192. package/dist/format.d.ts +69 -2
  193. package/dist/format.d.ts.map +1 -1
  194. package/dist/format.js +198 -1
  195. package/dist/format.js.map +1 -1
  196. package/dist/moderator/__tests__/evaluate.test.js +31 -17
  197. package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
  198. package/dist/moderator/evaluate.d.ts.map +1 -1
  199. package/dist/moderator/evaluate.js +4 -16
  200. package/dist/moderator/evaluate.js.map +1 -1
  201. package/dist/moderator/index.d.ts +1 -2
  202. package/dist/moderator/index.d.ts.map +1 -1
  203. package/dist/moderator/index.js +0 -1
  204. package/dist/moderator/index.js.map +1 -1
  205. package/dist/moderator/types.d.ts +6 -10
  206. package/dist/moderator/types.d.ts.map +1 -1
  207. package/dist/moderator/types.js +1 -3
  208. package/dist/moderator/types.js.map +1 -1
  209. package/dist/output-mappers.d.ts +122 -0
  210. package/dist/output-mappers.d.ts.map +1 -0
  211. package/dist/output-mappers.js +134 -0
  212. package/dist/output-mappers.js.map +1 -0
  213. package/dist/schemas.d.ts +6 -1
  214. package/dist/schemas.d.ts.map +1 -1
  215. package/dist/schemas.js +34 -5
  216. package/dist/schemas.js.map +1 -1
  217. package/dist/store.d.ts +28 -9
  218. package/dist/store.d.ts.map +1 -1
  219. package/dist/store.js +75 -16
  220. package/dist/store.js.map +1 -1
  221. package/dist/text-renderers.d.ts +30 -0
  222. package/dist/text-renderers.d.ts.map +1 -0
  223. package/dist/text-renderers.js +251 -0
  224. package/dist/text-renderers.js.map +1 -0
  225. package/dist/validate-semantic.d.ts.map +1 -1
  226. package/dist/validate-semantic.js +95 -61
  227. package/dist/validate-semantic.js.map +1 -1
  228. package/dist/validate.d.ts +6 -0
  229. package/dist/validate.d.ts.map +1 -1
  230. package/dist/validate.js +24 -0
  231. package/dist/validate.js.map +1 -1
  232. package/examples/brainstorm.yaml +130 -0
  233. package/examples/debate.yaml +169 -0
  234. package/examples/socratic-questioning.yaml +112 -0
  235. package/package.json +9 -10
  236. package/src/__tests__/adapter-json-roundtrip.test.ts +16 -7
  237. package/src/__tests__/agent-resolution-llm-free.test.ts +39 -0
  238. package/src/__tests__/build-step-entry.test.ts +203 -0
  239. package/src/__tests__/clear-thread-failed-attempts.test.ts +122 -0
  240. package/src/__tests__/concurrency.test.ts +266 -0
  241. package/src/__tests__/config.test.ts +33 -321
  242. package/src/__tests__/current-role.test.ts +7 -6
  243. package/src/__tests__/e2e-mock-agent.test.ts +65 -30
  244. package/src/__tests__/fixtures/e2e-count.workflow.yaml +1 -0
  245. package/src/__tests__/fixtures/e2e-linear.workflow.yaml +1 -0
  246. package/src/__tests__/fixtures/{e2e-mustache.workflow.yaml → e2e-liquid.workflow.yaml} +3 -2
  247. package/src/__tests__/fixtures/e2e-loop.workflow.yaml +1 -0
  248. package/src/__tests__/fixtures/e2e-suspend.mock.yaml +2 -2
  249. package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +6 -10
  250. package/src/__tests__/format-text-default.test.ts +49 -0
  251. package/src/__tests__/format-text-registry.test.ts +173 -0
  252. package/src/__tests__/issue-180-workflow-ref-removed.test.ts +43 -0
  253. package/src/__tests__/log-text-renderer.test.ts +294 -0
  254. package/src/__tests__/moderator-evaluate.test.ts +9 -52
  255. package/src/__tests__/output-mapper-thread-list-startedat.test.ts +124 -0
  256. package/src/__tests__/output-mapper-workflow-add.test.ts +24 -0
  257. package/src/__tests__/pid-recycling.test.ts +329 -0
  258. package/src/__tests__/prompt.test.ts +443 -2
  259. package/src/__tests__/resolve-head-hash.test.ts +11 -4
  260. package/src/__tests__/setup-agent-discovery.test.ts +26 -51
  261. package/src/__tests__/setup-complexity.test.ts +1 -203
  262. package/src/__tests__/setup-no-llm.test.ts +68 -0
  263. package/src/__tests__/solve-issue-tea-worktree.test.ts +27 -31
  264. package/src/__tests__/step-ask.test.ts +677 -0
  265. package/src/__tests__/step-show-json.test.ts +1 -0
  266. package/src/__tests__/step-timing.test.ts +2 -0
  267. package/src/__tests__/store-global-cas.test.ts +2 -2
  268. package/src/__tests__/store-unified-threads.test.ts +30 -27
  269. package/src/__tests__/thread-cancel-status.test.ts +27 -20
  270. package/src/__tests__/thread-cancel-text-renderer.test.ts +125 -0
  271. package/src/__tests__/thread-list-filters.test.ts +443 -17
  272. package/src/__tests__/thread-list-template-ms-date.test.ts +110 -0
  273. package/src/__tests__/thread-list-workflow-corrupt.test.ts +198 -0
  274. package/src/__tests__/thread-poke.test.ts +554 -0
  275. package/src/__tests__/thread-read-xml-tags.test.ts +9 -11
  276. package/src/__tests__/thread-resume.test.ts +20 -15
  277. package/src/__tests__/thread-show-status.test.ts +17 -29
  278. package/src/__tests__/thread-start-cwd-cli.test.ts +15 -3
  279. package/src/__tests__/thread-stop-text-renderer.test.ts +168 -0
  280. package/src/__tests__/thread-suspend-step.test.ts +13 -16
  281. package/src/__tests__/thread-suspended-display.test.ts +10 -22
  282. package/src/__tests__/thread-test-helpers.ts +15 -1
  283. package/src/__tests__/thread.test.ts +14 -14
  284. package/src/__tests__/validate-semantic.test.ts +118 -33
  285. package/src/__tests__/workflow-list-recursive.test.ts +370 -0
  286. package/src/__tests__/workflow-resolution.test.ts +48 -29
  287. package/src/__tests__/workflow-show-resolution.test.ts +286 -0
  288. package/src/__tests__/workflow-validate.test.ts +828 -0
  289. package/src/__tests__/write-envelope.test.ts +257 -0
  290. package/src/background/background.ts +88 -6
  291. package/src/background/index.ts +2 -0
  292. package/src/background/types.ts +1 -0
  293. package/src/cli.ts +184 -77
  294. package/src/commands/config.ts +16 -33
  295. package/src/commands/prompt.ts +57 -31
  296. package/src/commands/setup.ts +80 -358
  297. package/src/commands/step.ts +339 -12
  298. package/src/commands/thread.ts +511 -171
  299. package/src/commands/workflow.ts +155 -4
  300. package/src/concurrency/concurrency.ts +245 -0
  301. package/src/concurrency/index.ts +10 -0
  302. package/src/concurrency/types.ts +19 -0
  303. package/src/format.ts +282 -2
  304. package/src/moderator/__tests__/evaluate.test.ts +34 -17
  305. package/src/moderator/evaluate.ts +5 -17
  306. package/src/moderator/index.ts +1 -6
  307. package/src/moderator/types.ts +6 -14
  308. package/src/output-mappers.ts +254 -0
  309. package/src/schemas.ts +51 -5
  310. package/src/store.ts +86 -20
  311. package/src/text-renderers.ts +355 -0
  312. package/src/validate-semantic.ts +125 -73
  313. package/src/validate.ts +27 -0
  314. package/dist/__tests__/setup-validate.test.d.ts +0 -2
  315. package/dist/__tests__/setup-validate.test.d.ts.map +0 -1
  316. package/dist/__tests__/setup-validate.test.js +0 -108
  317. package/dist/__tests__/setup-validate.test.js.map +0 -1
  318. package/src/__tests__/setup-validate.test.ts +0 -148
  319. /package/src/__tests__/fixtures/{e2e-mustache.mock.yaml → e2e-liquid.mock.yaml} +0 -0
@@ -0,0 +1,273 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { generateUlid } from "@united-workforce/util";
5
+ import { afterEach, beforeEach, describe, expect, test } from "vitest";
6
+ import { createMarker, getProcessStartTime, isMarkerValid, isThreadRunning, listRunningThreads, readMarker, } from "../background/index.js";
7
+ import { makeUwfStore } from "./thread-test-helpers.js";
8
+ // ── helpers ───────────────────────────────────────────────────────────────────
9
+ async function createTestWorkflow(uwf) {
10
+ const workflowPayload = {
11
+ name: "test-workflow",
12
+ roles: {
13
+ role1: {
14
+ goal: "test goal",
15
+ outputSchema: { type: "object", properties: {} },
16
+ },
17
+ },
18
+ graph: { start: "role1" },
19
+ conditions: {},
20
+ };
21
+ return await uwf.store.cas.put(uwf.schemas.workflow, workflowPayload);
22
+ }
23
+ // ── test setup ────────────────────────────────────────────────────────────────
24
+ let tmpDir;
25
+ let savedOcasHome;
26
+ beforeEach(async () => {
27
+ savedOcasHome = process.env.OCAS_HOME;
28
+ tmpDir = await mkdtemp(join(tmpdir(), "pid-recycling-test-"));
29
+ });
30
+ afterEach(async () => {
31
+ if (savedOcasHome === undefined) {
32
+ delete process.env.OCAS_HOME;
33
+ }
34
+ else {
35
+ process.env.OCAS_HOME = savedOcasHome;
36
+ }
37
+ await rm(tmpDir, { recursive: true, force: true });
38
+ });
39
+ // ── Spec: thread-marker-process-identity ──────────────────────────────────────
40
+ describe("marker records process start time", () => {
41
+ test("createMarker stores processStartTime in marker file", async () => {
42
+ const uwf = await makeUwfStore(tmpDir);
43
+ const workflowHash = await createTestWorkflow(uwf);
44
+ const threadId = generateUlid(Date.now());
45
+ const processStartTime = getProcessStartTime(process.pid);
46
+ await createMarker(tmpDir, {
47
+ thread: threadId,
48
+ workflow: workflowHash,
49
+ pid: process.pid,
50
+ startedAt: Date.now(),
51
+ processStartTime,
52
+ });
53
+ const marker = await readMarker(tmpDir, threadId);
54
+ expect(marker).not.toBeNull();
55
+ expect(marker.pid).toBe(process.pid);
56
+ expect(marker.processStartTime).toBe(processStartTime);
57
+ });
58
+ test("processStartTime is number on Linux when /proc is available", async () => {
59
+ const startTime = getProcessStartTime(process.pid);
60
+ // On Linux, this should be a number (clock ticks since boot)
61
+ // On non-Linux, it may be null
62
+ if (process.platform === "linux") {
63
+ expect(typeof startTime).toBe("number");
64
+ expect(startTime).toBeGreaterThan(0);
65
+ }
66
+ else {
67
+ // On non-Linux, null is acceptable
68
+ expect(startTime === null || typeof startTime === "number").toBe(true);
69
+ }
70
+ });
71
+ test("getProcessStartTime returns null for non-existent PID", () => {
72
+ // PID 99999999 is unlikely to exist
73
+ const startTime = getProcessStartTime(99999999);
74
+ expect(startTime).toBeNull();
75
+ });
76
+ });
77
+ // ── Spec: thread-marker-valid-process-still-blocked ───────────────────────────
78
+ describe("valid marker still blocks execution", () => {
79
+ test("isMarkerValid returns true when PID alive and processStartTime matches", () => {
80
+ const processStartTime = getProcessStartTime(process.pid);
81
+ const marker = {
82
+ thread: "test-thread",
83
+ workflow: "test-workflow",
84
+ pid: process.pid,
85
+ startedAt: Date.now(),
86
+ processStartTime,
87
+ };
88
+ const valid = isMarkerValid(marker);
89
+ expect(valid).toBe(true);
90
+ });
91
+ test("isThreadRunning returns marker when PID alive and processStartTime matches", async () => {
92
+ const uwf = await makeUwfStore(tmpDir);
93
+ const workflowHash = await createTestWorkflow(uwf);
94
+ const threadId = generateUlid(Date.now());
95
+ const processStartTime = getProcessStartTime(process.pid);
96
+ await createMarker(tmpDir, {
97
+ thread: threadId,
98
+ workflow: workflowHash,
99
+ pid: process.pid,
100
+ startedAt: Date.now(),
101
+ processStartTime,
102
+ });
103
+ const result = await isThreadRunning(tmpDir, threadId);
104
+ expect(result).not.toBeNull();
105
+ expect(result.pid).toBe(process.pid);
106
+ });
107
+ });
108
+ // ── Spec: thread-exec-stale-marker-recovery ───────────────────────────────────
109
+ describe("stale marker recovery on exec", () => {
110
+ test("isMarkerValid returns false when processStartTime does not match", () => {
111
+ // Create a marker with a mismatched processStartTime
112
+ const marker = {
113
+ thread: "test-thread",
114
+ workflow: "test-workflow",
115
+ pid: process.pid, // PID is alive (it's our own process)
116
+ startedAt: Date.now(),
117
+ processStartTime: 1, // Deliberately wrong start time
118
+ };
119
+ const valid = isMarkerValid(marker);
120
+ expect(valid).toBe(false);
121
+ });
122
+ test("isThreadRunning deletes stale marker and returns null when processStartTime mismatches", async () => {
123
+ const uwf = await makeUwfStore(tmpDir);
124
+ const workflowHash = await createTestWorkflow(uwf);
125
+ const threadId = generateUlid(Date.now());
126
+ // Write a marker with a deliberately wrong processStartTime
127
+ await createMarker(tmpDir, {
128
+ thread: threadId,
129
+ workflow: workflowHash,
130
+ pid: process.pid, // alive process
131
+ startedAt: Date.now(),
132
+ processStartTime: 1, // wrong start time - simulates PID recycling
133
+ });
134
+ // isThreadRunning should detect the stale marker and clean it up
135
+ const result = await isThreadRunning(tmpDir, threadId);
136
+ expect(result).toBeNull();
137
+ // Verify marker file was deleted
138
+ const markerAfter = await readMarker(tmpDir, threadId);
139
+ expect(markerAfter).toBeNull();
140
+ });
141
+ test("isMarkerValid returns false when PID is not alive (regardless of processStartTime)", () => {
142
+ const marker = {
143
+ thread: "test-thread",
144
+ workflow: "test-workflow",
145
+ pid: 99999999, // non-existent PID
146
+ startedAt: Date.now(),
147
+ processStartTime: 12345,
148
+ };
149
+ const valid = isMarkerValid(marker);
150
+ expect(valid).toBe(false);
151
+ });
152
+ });
153
+ // ── Spec: thread-list-stale-marker-cleanup ────────────────────────────────────
154
+ describe("thread list filters stale markers", () => {
155
+ test("listRunningThreads excludes threads with mismatched processStartTime", async () => {
156
+ const uwf = await makeUwfStore(tmpDir);
157
+ const workflowHash = await createTestWorkflow(uwf);
158
+ // T1: stale marker (PID alive, but wrong processStartTime)
159
+ const threadId1 = generateUlid(Date.now());
160
+ await createMarker(tmpDir, {
161
+ thread: threadId1,
162
+ workflow: workflowHash,
163
+ pid: process.pid,
164
+ startedAt: Date.now(),
165
+ processStartTime: 1, // wrong — simulates PID recycling
166
+ });
167
+ // T2: valid marker (PID alive, correct processStartTime)
168
+ const threadId2 = generateUlid(Date.now() + 1);
169
+ const correctStartTime = getProcessStartTime(process.pid);
170
+ await createMarker(tmpDir, {
171
+ thread: threadId2,
172
+ workflow: workflowHash,
173
+ pid: process.pid,
174
+ startedAt: Date.now(),
175
+ processStartTime: correctStartTime,
176
+ });
177
+ const running = await listRunningThreads(tmpDir);
178
+ // Only T2 should be listed
179
+ expect(running.length).toBe(1);
180
+ expect(running[0].thread).toBe(threadId2);
181
+ // T1's marker should have been deleted
182
+ const markerT1 = await readMarker(tmpDir, threadId1);
183
+ expect(markerT1).toBeNull();
184
+ });
185
+ test("listRunningThreads deletes marker when PID is dead", async () => {
186
+ const uwf = await makeUwfStore(tmpDir);
187
+ const workflowHash = await createTestWorkflow(uwf);
188
+ const threadId = generateUlid(Date.now());
189
+ // Marker with a non-existent PID
190
+ await createMarker(tmpDir, {
191
+ thread: threadId,
192
+ workflow: workflowHash,
193
+ pid: 99999999,
194
+ startedAt: Date.now(),
195
+ processStartTime: 12345,
196
+ });
197
+ const running = await listRunningThreads(tmpDir);
198
+ expect(running.length).toBe(0);
199
+ // Marker should be deleted
200
+ const markerAfter = await readMarker(tmpDir, threadId);
201
+ expect(markerAfter).toBeNull();
202
+ });
203
+ });
204
+ // ── Spec: thread-stop-validates-process-identity ──────────────────────────────
205
+ describe("thread stop validates process identity", () => {
206
+ test("isMarkerValid returns false for recycled PID (PID alive, wrong start time)", () => {
207
+ // Simulate: marker says processStartTime=100, but actual process started at a different time
208
+ const marker = {
209
+ thread: "test-thread",
210
+ workflow: "test-workflow",
211
+ pid: process.pid, // alive
212
+ startedAt: Date.now(),
213
+ processStartTime: 1, // wrong — this PID was recycled
214
+ };
215
+ expect(isMarkerValid(marker)).toBe(false);
216
+ });
217
+ });
218
+ // ── Spec: thread-cancel-validates-process-identity ────────────────────────────
219
+ describe("thread cancel validates process identity", () => {
220
+ test("isMarkerValid correctly identifies stale markers for cancel scenario", () => {
221
+ const marker = {
222
+ thread: "test-thread",
223
+ workflow: "test-workflow",
224
+ pid: process.pid, // alive
225
+ startedAt: Date.now(),
226
+ processStartTime: 1, // wrong — this is a recycled PID
227
+ };
228
+ expect(isMarkerValid(marker)).toBe(false);
229
+ });
230
+ });
231
+ // ── Legacy marker compatibility ───────────────────────────────────────────────
232
+ describe("backward compatibility with old markers", () => {
233
+ test("marker without processStartTime field is treated as stale when PID alive", async () => {
234
+ const uwf = await makeUwfStore(tmpDir);
235
+ const workflowHash = await createTestWorkflow(uwf);
236
+ const threadId = generateUlid(Date.now());
237
+ // Simulate an old-format marker (no processStartTime field)
238
+ const runningDir = join(tmpDir, "running");
239
+ await mkdir(runningDir, { recursive: true });
240
+ const markerPath = join(runningDir, `${threadId}.json`);
241
+ const oldMarker = {
242
+ thread: threadId,
243
+ workflow: workflowHash,
244
+ pid: process.pid,
245
+ startedAt: Date.now(),
246
+ // No processStartTime field
247
+ };
248
+ await writeFile(markerPath, JSON.stringify(oldMarker, null, 2), "utf8");
249
+ // Reading the marker should work (null processStartTime)
250
+ const marker = await readMarker(tmpDir, threadId);
251
+ expect(marker).not.toBeNull();
252
+ expect(marker.processStartTime).toBeNull();
253
+ // isMarkerValid should still accept it gracefully (null means can't verify — fallback to PID check only)
254
+ // But since we can't verify identity, we treat it as potentially stale
255
+ // The spec says: on non-Linux, processStartTime is null — same behavior
256
+ // When processStartTime is null in marker AND we can't read /proc (or it's null from getProcessStartTime too),
257
+ // we fall back to the PID-alive-only check for backward compat
258
+ const valid = isMarkerValid(marker);
259
+ // With null processStartTime in the marker, we can't verify identity,
260
+ // but the PID IS alive. For backward compat, this should be treated as valid
261
+ // (the new getProcessStartTime returns a real number on Linux, null if unavailable)
262
+ if (process.platform === "linux") {
263
+ // On Linux where we CAN get the actual start time but the marker has null,
264
+ // we cannot confirm identity — treat as potentially stale
265
+ // However for backward compat during transition, null in marker = skip identity check
266
+ expect(valid).toBe(true);
267
+ }
268
+ else {
269
+ expect(valid).toBe(true);
270
+ }
271
+ });
272
+ });
273
+ //# sourceMappingURL=pid-recycling.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pid-recycling.test.js","sourceRoot":"","sources":["../../src/__tests__/pid-recycling.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEvE,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,UAAU,GACX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,iFAAiF;AAEjF,KAAK,UAAU,kBAAkB,CAAC,GAAa;IAC7C,MAAM,eAAe,GAAG;QACtB,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,WAAW;gBACjB,YAAY,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE;aAC1D;SACF;QACD,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;QACzB,UAAU,EAAE,EAAE;KACf,CAAC;IACF,OAAO,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AACxE,CAAC;AAED,iFAAiF;AAEjF,IAAI,MAAc,CAAC;AACnB,IAAI,aAAiC,CAAC;AAEtC,UAAU,CAAC,KAAK,IAAI,EAAE;IACpB,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IACtC,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,aAAa,CAAC;IACxC,CAAC;IACD,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,IAAI,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QAEtD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE1D,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,MAAO,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnD,6DAA6D;QAC7D,+BAA+B;QAC/B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,mCAAmC;YACnC,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;QACjE,oCAAoC;QACpC,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAChD,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,IAAI,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAClF,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,aAAyB;YACjC,QAAQ,EAAE,eAAyB;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB;SACjB,CAAC;QAEF,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QACtD,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE1D,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB;SACjB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC5E,qDAAqD;QACrD,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,aAAyB;YACjC,QAAQ,EAAE,eAAyB;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,sCAAsC;YACxD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,CAAC,EAAE,gCAAgC;SACtD,CAAC;QAEF,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,wFAAwF,EAAE,KAAK,IAAI,EAAE;QACxG,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QAEtD,4DAA4D;QAC5D,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,gBAAgB;YAClC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,CAAC,EAAE,6CAA6C;SACnE,CAAC,CAAC;QAEH,iEAAiE;QACjE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE1B,iCAAiC;QACjC,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oFAAoF,EAAE,GAAG,EAAE;QAC9F,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,aAAyB;YACjC,QAAQ,EAAE,eAAyB;YACnC,GAAG,EAAE,QAAQ,EAAE,mBAAmB;YAClC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,KAAK;SACxB,CAAC;QAEF,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAEnD,2DAA2D;QAC3D,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QACvD,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,CAAC,EAAE,kCAAkC;SACxD,CAAC,CAAC;QAEH,yDAAyD;QACzD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAa,CAAC;QAC3D,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1D,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,gBAAgB;SACnC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEjD,2BAA2B;QAC3B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE3C,uCAAuC;QACvC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QAEtD,iCAAiC;QACjC,MAAM,YAAY,CAAC,MAAM,EAAE;YACzB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,QAAQ;YACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,KAAK;SACxB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE/B,2BAA2B;QAC3B,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,IAAI,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACtF,6FAA6F;QAC7F,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,aAAyB;YACjC,QAAQ,EAAE,eAAyB;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ;YAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,CAAC,EAAE,gCAAgC;SACtD,CAAC;QAEF,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,IAAI,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAChF,MAAM,MAAM,GAAkB;YAC5B,MAAM,EAAE,aAAyB;YACjC,QAAQ,EAAE,eAAyB;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ;YAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,gBAAgB,EAAE,CAAC,EAAE,iCAAiC;SACvD,CAAC;QAEF,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,IAAI,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAa,CAAC;QAEtD,4DAA4D;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,QAAQ,OAAO,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG;YAChB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,YAAY;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,4BAA4B;SAC7B,CAAC;QACF,MAAM,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAExE,yDAAyD;QACzD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,MAAO,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC;QAE5C,yGAAyG;QACzG,uEAAuE;QACvE,wEAAwE;QACxE,+GAA+G;QAC/G,+DAA+D;QAC/D,MAAM,KAAK,GAAG,aAAa,CAAC,MAAO,CAAC,CAAC;QACrC,sEAAsE;QACtE,6EAA6E;QAC7E,oFAAoF;QACpF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,2EAA2E;YAC3E,0DAA0D;YAC1D,sFAAsF;YACtF,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}