clinkx 0.2.3 → 1.0.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 (574) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +10 -0
  3. package/README.md +113 -18
  4. package/clinkx-workflows/dist/allowed-roots.d.ts +1 -0
  5. package/clinkx-workflows/dist/allowed-roots.js +5 -0
  6. package/clinkx-workflows/dist/allowed-roots.js.map +1 -0
  7. package/clinkx-workflows/dist/artifacts.d.ts +20 -1
  8. package/clinkx-workflows/dist/artifacts.js +38 -9
  9. package/clinkx-workflows/dist/artifacts.js.map +1 -1
  10. package/clinkx-workflows/dist/backend.d.ts +4 -0
  11. package/clinkx-workflows/dist/citation-check.d.ts +40 -0
  12. package/clinkx-workflows/dist/citation-check.js +348 -0
  13. package/clinkx-workflows/dist/citation-check.js.map +1 -0
  14. package/clinkx-workflows/dist/clink-client.d.ts +2 -1
  15. package/clinkx-workflows/dist/clink-client.js +17 -4
  16. package/clinkx-workflows/dist/clink-client.js.map +1 -1
  17. package/clinkx-workflows/dist/config.d.ts +145 -16
  18. package/clinkx-workflows/dist/config.js +384 -26
  19. package/clinkx-workflows/dist/config.js.map +1 -1
  20. package/clinkx-workflows/dist/contained-file.d.ts +172 -0
  21. package/clinkx-workflows/dist/contained-file.js +483 -0
  22. package/clinkx-workflows/dist/contained-file.js.map +1 -0
  23. package/clinkx-workflows/dist/context-builder-lifecycle-contract.d.ts +416 -0
  24. package/clinkx-workflows/dist/context-builder-lifecycle-contract.js +328 -0
  25. package/clinkx-workflows/dist/context-builder-lifecycle-contract.js.map +1 -0
  26. package/clinkx-workflows/dist/context-builder-lifecycle-router.d.ts +24 -0
  27. package/clinkx-workflows/dist/context-builder-lifecycle-router.js +39 -0
  28. package/clinkx-workflows/dist/context-builder-lifecycle-router.js.map +1 -0
  29. package/clinkx-workflows/dist/context-cache-key.d.ts +53 -0
  30. package/clinkx-workflows/dist/context-cache-key.js +91 -0
  31. package/clinkx-workflows/dist/context-cache-key.js.map +1 -0
  32. package/clinkx-workflows/dist/context-mode-resolver.d.ts +27 -0
  33. package/clinkx-workflows/dist/context-mode-resolver.js +126 -0
  34. package/clinkx-workflows/dist/context-mode-resolver.js.map +1 -0
  35. package/clinkx-workflows/dist/context-preflight.d.ts +184 -0
  36. package/clinkx-workflows/dist/context-preflight.js +91 -0
  37. package/clinkx-workflows/dist/context-preflight.js.map +1 -0
  38. package/clinkx-workflows/dist/council-expander.d.ts +1 -1
  39. package/clinkx-workflows/dist/council-expander.js +2 -1
  40. package/clinkx-workflows/dist/council-expander.js.map +1 -1
  41. package/clinkx-workflows/dist/dashboard/activity-contract.d.ts +165 -0
  42. package/clinkx-workflows/dist/dashboard/activity-contract.js +105 -0
  43. package/clinkx-workflows/dist/dashboard/activity-contract.js.map +1 -0
  44. package/clinkx-workflows/dist/dashboard/activity-lease.d.ts +25 -0
  45. package/clinkx-workflows/dist/dashboard/activity-lease.js +34 -0
  46. package/clinkx-workflows/dist/dashboard/activity-lease.js.map +1 -0
  47. package/clinkx-workflows/dist/dashboard/activity-reader.d.ts +86 -0
  48. package/clinkx-workflows/dist/dashboard/activity-reader.js +480 -0
  49. package/clinkx-workflows/dist/dashboard/activity-reader.js.map +1 -0
  50. package/clinkx-workflows/dist/dashboard/api-routes.d.ts +36 -0
  51. package/clinkx-workflows/dist/dashboard/api-routes.js +1047 -0
  52. package/clinkx-workflows/dist/dashboard/api-routes.js.map +1 -0
  53. package/clinkx-workflows/dist/dashboard/artifact-index.d.ts +37 -0
  54. package/clinkx-workflows/dist/dashboard/artifact-index.js +145 -0
  55. package/clinkx-workflows/dist/dashboard/artifact-index.js.map +1 -0
  56. package/clinkx-workflows/dist/dashboard/auth/challenge-store.d.ts +31 -0
  57. package/clinkx-workflows/dist/dashboard/auth/challenge-store.js +65 -0
  58. package/clinkx-workflows/dist/dashboard/auth/challenge-store.js.map +1 -0
  59. package/clinkx-workflows/dist/dashboard/auth/controller.d.ts +26 -0
  60. package/clinkx-workflows/dist/dashboard/auth/controller.js +596 -0
  61. package/clinkx-workflows/dist/dashboard/auth/controller.js.map +1 -0
  62. package/clinkx-workflows/dist/dashboard/auth/credential-store.d.ts +60 -0
  63. package/clinkx-workflows/dist/dashboard/auth/credential-store.js +776 -0
  64. package/clinkx-workflows/dist/dashboard/auth/credential-store.js.map +1 -0
  65. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.d.ts +9 -0
  66. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js +44 -0
  67. package/clinkx-workflows/dist/dashboard/auth/enrollment-gate.js.map +1 -0
  68. package/clinkx-workflows/dist/dashboard/auth/session-store.d.ts +17 -0
  69. package/clinkx-workflows/dist/dashboard/auth/session-store.js +77 -0
  70. package/clinkx-workflows/dist/dashboard/auth/session-store.js.map +1 -0
  71. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.d.ts +25 -0
  72. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js +71 -0
  73. package/clinkx-workflows/dist/dashboard/auth/webauthn-service.js.map +1 -0
  74. package/clinkx-workflows/dist/dashboard/context-run-liveness.d.ts +37 -0
  75. package/clinkx-workflows/dist/dashboard/context-run-liveness.js +49 -0
  76. package/clinkx-workflows/dist/dashboard/context-run-liveness.js.map +1 -0
  77. package/clinkx-workflows/dist/dashboard/context-run-reader.d.ts +222 -0
  78. package/clinkx-workflows/dist/dashboard/context-run-reader.js +1178 -0
  79. package/clinkx-workflows/dist/dashboard/context-run-reader.js.map +1 -0
  80. package/clinkx-workflows/dist/dashboard/contracts.d.ts +8936 -0
  81. package/clinkx-workflows/dist/dashboard/contracts.js +1157 -0
  82. package/clinkx-workflows/dist/dashboard/contracts.js.map +1 -0
  83. package/clinkx-workflows/dist/dashboard/generation.d.ts +14 -0
  84. package/clinkx-workflows/dist/dashboard/generation.js +41 -0
  85. package/clinkx-workflows/dist/dashboard/generation.js.map +1 -0
  86. package/clinkx-workflows/dist/dashboard/index.d.ts +28 -0
  87. package/clinkx-workflows/dist/dashboard/index.js +16 -0
  88. package/clinkx-workflows/dist/dashboard/index.js.map +1 -0
  89. package/clinkx-workflows/dist/dashboard/lazy-content.d.ts +101 -0
  90. package/clinkx-workflows/dist/dashboard/lazy-content.js +748 -0
  91. package/clinkx-workflows/dist/dashboard/lazy-content.js.map +1 -0
  92. package/clinkx-workflows/dist/dashboard/progress-report-contract.d.ts +303 -0
  93. package/clinkx-workflows/dist/dashboard/progress-report-contract.js +221 -0
  94. package/clinkx-workflows/dist/dashboard/progress-report-contract.js.map +1 -0
  95. package/clinkx-workflows/dist/dashboard/progress-report-reader.d.ts +50 -0
  96. package/clinkx-workflows/dist/dashboard/progress-report-reader.js +581 -0
  97. package/clinkx-workflows/dist/dashboard/progress-report-reader.js.map +1 -0
  98. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.d.ts +89 -0
  99. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js +71 -0
  100. package/clinkx-workflows/dist/dashboard/progress-report-status-overlay.js.map +1 -0
  101. package/clinkx-workflows/dist/dashboard/progress-report-status-store.d.ts +28 -0
  102. package/clinkx-workflows/dist/dashboard/progress-report-status-store.js +110 -0
  103. package/clinkx-workflows/dist/dashboard/progress-report-status-store.js.map +1 -0
  104. package/clinkx-workflows/dist/dashboard/read-model.d.ts +86 -0
  105. package/clinkx-workflows/dist/dashboard/read-model.js +440 -0
  106. package/clinkx-workflows/dist/dashboard/read-model.js.map +1 -0
  107. package/clinkx-workflows/dist/dashboard/request-admission.d.ts +31 -0
  108. package/clinkx-workflows/dist/dashboard/request-admission.js +126 -0
  109. package/clinkx-workflows/dist/dashboard/request-admission.js.map +1 -0
  110. package/clinkx-workflows/dist/dashboard/scanner.d.ts +75 -0
  111. package/clinkx-workflows/dist/dashboard/scanner.js +1110 -0
  112. package/clinkx-workflows/dist/dashboard/scanner.js.map +1 -0
  113. package/clinkx-workflows/dist/dashboard/server-factory.d.ts +50 -0
  114. package/clinkx-workflows/dist/dashboard/server-factory.js +431 -0
  115. package/clinkx-workflows/dist/dashboard/server-factory.js.map +1 -0
  116. package/clinkx-workflows/dist/dashboard/session-log-contract.d.ts +2611 -0
  117. package/clinkx-workflows/dist/dashboard/session-log-contract.js +480 -0
  118. package/clinkx-workflows/dist/dashboard/session-log-contract.js.map +1 -0
  119. package/clinkx-workflows/dist/dashboard/session-log-identity.d.ts +21 -0
  120. package/clinkx-workflows/dist/dashboard/session-log-identity.js +101 -0
  121. package/clinkx-workflows/dist/dashboard/session-log-identity.js.map +1 -0
  122. package/clinkx-workflows/dist/dashboard/session-log-journal.d.ts +43 -0
  123. package/clinkx-workflows/dist/dashboard/session-log-journal.js +522 -0
  124. package/clinkx-workflows/dist/dashboard/session-log-journal.js.map +1 -0
  125. package/clinkx-workflows/dist/dashboard/session-log-reader.d.ts +61 -0
  126. package/clinkx-workflows/dist/dashboard/session-log-reader.js +378 -0
  127. package/clinkx-workflows/dist/dashboard/session-log-reader.js.map +1 -0
  128. package/clinkx-workflows/dist/dashboard/session-log-redaction.d.ts +6 -0
  129. package/clinkx-workflows/dist/dashboard/session-log-redaction.js +367 -0
  130. package/clinkx-workflows/dist/dashboard/session-log-redaction.js.map +1 -0
  131. package/clinkx-workflows/dist/dashboard/session-log-retention.d.ts +23 -0
  132. package/clinkx-workflows/dist/dashboard/session-log-retention.js +212 -0
  133. package/clinkx-workflows/dist/dashboard/session-log-retention.js.map +1 -0
  134. package/clinkx-workflows/dist/dashboard/static-responses.d.ts +10 -0
  135. package/clinkx-workflows/dist/dashboard/static-responses.js +94 -0
  136. package/clinkx-workflows/dist/dashboard/static-responses.js.map +1 -0
  137. package/clinkx-workflows/dist/dashboard/worker-lock-observer.d.ts +28 -0
  138. package/clinkx-workflows/dist/dashboard/worker-lock-observer.js +241 -0
  139. package/clinkx-workflows/dist/dashboard/worker-lock-observer.js.map +1 -0
  140. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  141. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  142. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  143. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  144. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  145. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  146. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  147. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  148. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  149. package/clinkx-workflows/dist/dashboard-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  150. package/clinkx-workflows/dist/dashboard-ui/assets/index-DOkMXTfB.js +25 -0
  151. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  152. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  153. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  154. package/clinkx-workflows/dist/dashboard-ui/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  155. package/clinkx-workflows/dist/dashboard-ui/assets/style-ChJsn0KD.css +1 -0
  156. package/clinkx-workflows/dist/dashboard-ui/contracts/council-plan-review-input-v1.json +158 -0
  157. package/clinkx-workflows/dist/dashboard-ui/index.html +15 -0
  158. package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Mono-OFL.txt +93 -0
  159. package/clinkx-workflows/dist/dashboard-ui/licenses/IBM-Plex-Sans-OFL.txt +93 -0
  160. package/clinkx-workflows/dist/dashboard-ui/licenses/JetBrains-Mono-OFL.txt +93 -0
  161. package/clinkx-workflows/dist/dashboard-ui/licenses/NOTICE.md +32 -0
  162. package/clinkx-workflows/dist/dashboard-ui/theme-init.js +8 -0
  163. package/clinkx-workflows/dist/definition-normalizer.d.ts +19 -0
  164. package/clinkx-workflows/dist/definition-normalizer.js.map +1 -1
  165. package/clinkx-workflows/dist/delegate-validate.d.ts +78 -0
  166. package/clinkx-workflows/dist/delegate-validate.js +97 -0
  167. package/clinkx-workflows/dist/delegate-validate.js.map +1 -0
  168. package/clinkx-workflows/dist/engine.d.ts +141 -0
  169. package/clinkx-workflows/dist/engine.js +882 -28
  170. package/clinkx-workflows/dist/engine.js.map +1 -1
  171. package/clinkx-workflows/dist/errors.d.ts +2 -0
  172. package/clinkx-workflows/dist/errors.js.map +1 -1
  173. package/clinkx-workflows/dist/fingerprint.d.ts +1 -1
  174. package/clinkx-workflows/dist/fingerprint.js +1 -1
  175. package/clinkx-workflows/dist/index.d.ts +19 -0
  176. package/clinkx-workflows/dist/index.js +15 -0
  177. package/clinkx-workflows/dist/index.js.map +1 -1
  178. package/clinkx-workflows/dist/loader.d.ts +9 -3
  179. package/clinkx-workflows/dist/loader.js +92 -21
  180. package/clinkx-workflows/dist/loader.js.map +1 -1
  181. package/clinkx-workflows/dist/plan-review/admission.d.ts +160 -0
  182. package/clinkx-workflows/dist/plan-review/admission.js +290 -0
  183. package/clinkx-workflows/dist/plan-review/admission.js.map +1 -0
  184. package/clinkx-workflows/dist/plan-review/context-policy.d.ts +55 -0
  185. package/clinkx-workflows/dist/plan-review/context-policy.js +146 -0
  186. package/clinkx-workflows/dist/plan-review/context-policy.js.map +1 -0
  187. package/clinkx-workflows/dist/plan-review/contract.d.ts +763 -0
  188. package/clinkx-workflows/dist/plan-review/contract.js +289 -0
  189. package/clinkx-workflows/dist/plan-review/contract.js.map +1 -0
  190. package/clinkx-workflows/dist/plan-review/digest.d.ts +68 -0
  191. package/clinkx-workflows/dist/plan-review/digest.js +241 -0
  192. package/clinkx-workflows/dist/plan-review/digest.js.map +1 -0
  193. package/clinkx-workflows/dist/plan-review/discovery.d.ts +45 -0
  194. package/clinkx-workflows/dist/plan-review/discovery.js +36 -0
  195. package/clinkx-workflows/dist/plan-review/discovery.js.map +1 -0
  196. package/clinkx-workflows/dist/plan-review/execution-contract.d.ts +298 -0
  197. package/clinkx-workflows/dist/plan-review/execution-contract.js +194 -0
  198. package/clinkx-workflows/dist/plan-review/execution-contract.js.map +1 -0
  199. package/clinkx-workflows/dist/plan-review/expander.d.ts +48 -0
  200. package/clinkx-workflows/dist/plan-review/expander.js +243 -0
  201. package/clinkx-workflows/dist/plan-review/expander.js.map +1 -0
  202. package/clinkx-workflows/dist/plan-review/projector.d.ts +126 -0
  203. package/clinkx-workflows/dist/plan-review/projector.js +437 -0
  204. package/clinkx-workflows/dist/plan-review/projector.js.map +1 -0
  205. package/clinkx-workflows/dist/plan-review/publication.d.ts +95 -0
  206. package/clinkx-workflows/dist/plan-review/publication.js +182 -0
  207. package/clinkx-workflows/dist/plan-review/publication.js.map +1 -0
  208. package/clinkx-workflows/dist/plan-review/ranking-reducer.d.ts +34 -0
  209. package/clinkx-workflows/dist/plan-review/ranking-reducer.js +139 -0
  210. package/clinkx-workflows/dist/plan-review/ranking-reducer.js.map +1 -0
  211. package/clinkx-workflows/dist/plan-review/resume.d.ts +38 -0
  212. package/clinkx-workflows/dist/plan-review/resume.js +122 -0
  213. package/clinkx-workflows/dist/plan-review/resume.js.map +1 -0
  214. package/clinkx-workflows/dist/plan-review/rubric.d.ts +7 -0
  215. package/clinkx-workflows/dist/plan-review/rubric.js +24 -0
  216. package/clinkx-workflows/dist/plan-review/rubric.js.map +1 -0
  217. package/clinkx-workflows/dist/plan-review/run-state.d.ts +398 -0
  218. package/clinkx-workflows/dist/plan-review/run-state.js +183 -0
  219. package/clinkx-workflows/dist/plan-review/run-state.js.map +1 -0
  220. package/clinkx-workflows/dist/plan-review/runtime-policy.d.ts +74 -0
  221. package/clinkx-workflows/dist/plan-review/runtime-policy.js +186 -0
  222. package/clinkx-workflows/dist/plan-review/runtime-policy.js.map +1 -0
  223. package/clinkx-workflows/dist/plan-review/snapshot.d.ts +81 -0
  224. package/clinkx-workflows/dist/plan-review/snapshot.js +170 -0
  225. package/clinkx-workflows/dist/plan-review/snapshot.js.map +1 -0
  226. package/clinkx-workflows/dist/plan-review/stage-error.d.ts +19 -0
  227. package/clinkx-workflows/dist/plan-review/stage-error.js +20 -0
  228. package/clinkx-workflows/dist/plan-review/stage-error.js.map +1 -0
  229. package/clinkx-workflows/dist/post-processors/index.d.ts +20 -0
  230. package/clinkx-workflows/dist/post-processors/index.js +21 -0
  231. package/clinkx-workflows/dist/post-processors/index.js.map +1 -0
  232. package/clinkx-workflows/dist/prompt-budget.d.ts +7 -0
  233. package/clinkx-workflows/dist/prompt-budget.js +7 -1
  234. package/clinkx-workflows/dist/prompt-budget.js.map +1 -1
  235. package/clinkx-workflows/dist/reducers/index.js +2 -0
  236. package/clinkx-workflows/dist/reducers/index.js.map +1 -1
  237. package/clinkx-workflows/dist/run-lock-heartbeat.d.ts +2 -0
  238. package/clinkx-workflows/dist/run-lock-heartbeat.js +3 -0
  239. package/clinkx-workflows/dist/run-lock-heartbeat.js.map +1 -0
  240. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.d.ts +34 -0
  241. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js +74 -0
  242. package/clinkx-workflows/dist/run-summary/cards/council-plan-review.js.map +1 -0
  243. package/clinkx-workflows/dist/run-summary/cards/index.js +5 -0
  244. package/clinkx-workflows/dist/run-summary/cards/index.js.map +1 -1
  245. package/clinkx-workflows/dist/run-summary.d.ts +13 -0
  246. package/clinkx-workflows/dist/run-summary.js +29 -1
  247. package/clinkx-workflows/dist/run-summary.js.map +1 -1
  248. package/clinkx-workflows/dist/schema.d.ts +76 -21
  249. package/clinkx-workflows/dist/schema.js +10 -1
  250. package/clinkx-workflows/dist/schema.js.map +1 -1
  251. package/clinkx-workflows/dist/seed-terms.d.ts +30 -0
  252. package/clinkx-workflows/dist/seed-terms.js +176 -0
  253. package/clinkx-workflows/dist/seed-terms.js.map +1 -0
  254. package/clinkx-workflows/dist/server.d.ts +5 -2
  255. package/clinkx-workflows/dist/server.js +82 -52
  256. package/clinkx-workflows/dist/server.js.map +1 -1
  257. package/clinkx-workflows/dist/shutdown.d.ts +18 -20
  258. package/clinkx-workflows/dist/shutdown.js +43 -61
  259. package/clinkx-workflows/dist/shutdown.js.map +1 -1
  260. package/clinkx-workflows/dist/state-schema.d.ts +38 -0
  261. package/clinkx-workflows/dist/state.d.ts +170 -3
  262. package/clinkx-workflows/dist/state.js +1275 -28
  263. package/clinkx-workflows/dist/state.js.map +1 -1
  264. package/clinkx-workflows/dist/transport.d.ts +15 -0
  265. package/clinkx-workflows/dist/transport.js +19 -10
  266. package/clinkx-workflows/dist/transport.js.map +1 -1
  267. package/clinkx-workflows/dist/types.d.ts +14 -2
  268. package/clinkx-workflows/dist/validators/council.d.ts +318 -85
  269. package/clinkx-workflows/dist/validators/council.js +52 -13
  270. package/clinkx-workflows/dist/validators/council.js.map +1 -1
  271. package/clinkx-workflows/dist/validators/index.d.ts +1 -0
  272. package/clinkx-workflows/dist/validators/index.js +3 -0
  273. package/clinkx-workflows/dist/validators/index.js.map +1 -1
  274. package/clinkx-workflows/dist/validators/plan-review.d.ts +398 -0
  275. package/clinkx-workflows/dist/validators/plan-review.js +316 -0
  276. package/clinkx-workflows/dist/validators/plan-review.js.map +1 -0
  277. package/clinkx-workflows/dist/workflow-receipt.js +188 -4
  278. package/clinkx-workflows/dist/workflow-receipt.js.map +1 -1
  279. package/clinkx-workflows/dist/workflow-tools.d.ts +48 -3
  280. package/clinkx-workflows/dist/workflow-tools.js +1402 -59
  281. package/clinkx-workflows/dist/workflow-tools.js.map +1 -1
  282. package/clinkx-workflows/dist/workspace-signature.d.ts +16 -0
  283. package/clinkx-workflows/dist/workspace-signature.js +388 -0
  284. package/clinkx-workflows/dist/workspace-signature.js.map +1 -0
  285. package/clinkx-workflows/templates/council/answer-specialist.txt +2 -1
  286. package/clinkx-workflows/templates/council/code-review-chairman.txt +13 -0
  287. package/clinkx-workflows/templates/council/code-review-cross-reviewer.txt +4 -1
  288. package/clinkx-workflows/templates/council/code-review-reviewer.txt +19 -3
  289. package/clinkx-workflows/templates/council/debug-debugger.txt +2 -1
  290. package/clinkx-workflows/templates/council/discover-analyst.txt +2 -1
  291. package/clinkx-workflows/templates/council/member.txt +2 -1
  292. package/clinkx-workflows/templates/council/plan-review-chairman.txt +68 -0
  293. package/clinkx-workflows/templates/council/plan-review-cross-reviewer.txt +51 -0
  294. package/clinkx-workflows/templates/council/plan-review-reviewer.txt +60 -0
  295. package/clinkx-workflows/templates/plan-review/chairman.txt +48 -0
  296. package/clinkx-workflows/templates/plan-review/cross-review.txt +52 -0
  297. package/clinkx-workflows/templates/plan-review/ranking.txt +16 -0
  298. package/clinkx-workflows/templates/plan-review/reviewer.txt +57 -0
  299. package/clinkx-workflows/workflows/council-answer.yaml +97 -8
  300. package/clinkx-workflows/workflows/council-code-review.yaml +103 -8
  301. package/clinkx-workflows/workflows/council-debug.yaml +97 -8
  302. package/clinkx-workflows/workflows/council-default.yaml +97 -8
  303. package/clinkx-workflows/workflows/council-discover.yaml +97 -8
  304. package/clinkx-workflows/workflows/council-plan-review.yaml +250 -0
  305. package/clinkx-workflows/workflows/plan-review-receipts.yaml +230 -0
  306. package/conf/adapters/agy.json +49 -0
  307. package/conf/adapters/claude.json +5 -0
  308. package/conf/adapters/codex-app-server.json +44 -0
  309. package/conf/adapters/codex.json +7 -2
  310. package/conf/adapters/glm.json +5 -0
  311. package/conf/adapters/grok.json +60 -0
  312. package/conf/adapters/hapi/agy.json +52 -0
  313. package/conf/adapters/hapi/claude.json +5 -0
  314. package/conf/adapters/hapi/codex.json +7 -2
  315. package/conf/adapters/hapi/glm.json +5 -0
  316. package/conf/prompts/json-codereviewer.txt +1 -0
  317. package/conf/prompts/json.txt +1 -0
  318. package/dist/activity-journal.d.ts +42 -0
  319. package/dist/activity-journal.js +381 -0
  320. package/dist/activity-journal.js.map +1 -0
  321. package/dist/allowed-roots.d.ts +53 -0
  322. package/dist/allowed-roots.js +216 -0
  323. package/dist/allowed-roots.js.map +1 -0
  324. package/dist/codex/activity-session-log.d.ts +14 -0
  325. package/dist/codex/activity-session-log.js +206 -0
  326. package/dist/codex/activity-session-log.js.map +1 -0
  327. package/dist/codex/agent-tools.d.ts +23 -0
  328. package/dist/codex/agent-tools.js +1270 -0
  329. package/dist/codex/agent-tools.js.map +1 -0
  330. package/dist/codex/app-server-client.d.ts +76 -0
  331. package/dist/codex/app-server-client.js +582 -0
  332. package/dist/codex/app-server-client.js.map +1 -0
  333. package/dist/codex/app-server-registry.d.ts +389 -0
  334. package/dist/codex/app-server-registry.js +1407 -0
  335. package/dist/codex/app-server-registry.js.map +1 -0
  336. package/dist/codex/client-types.d.ts +109 -0
  337. package/dist/codex/client-types.js +2 -0
  338. package/dist/codex/client-types.js.map +1 -0
  339. package/dist/codex/protocol.d.ts +5375 -0
  340. package/dist/codex/protocol.js +614 -0
  341. package/dist/codex/protocol.js.map +1 -0
  342. package/dist/codex/session.d.ts +263 -0
  343. package/dist/codex/session.js +466 -0
  344. package/dist/codex/session.js.map +1 -0
  345. package/dist/config.d.ts +185 -19
  346. package/dist/config.js +82 -16
  347. package/dist/config.js.map +1 -1
  348. package/dist/context-builder/anchors.d.ts +12 -0
  349. package/dist/context-builder/anchors.js +22 -0
  350. package/dist/context-builder/anchors.js.map +1 -0
  351. package/dist/context-builder/bundle.d.ts +109 -0
  352. package/dist/context-builder/bundle.js +1498 -0
  353. package/dist/context-builder/bundle.js.map +1 -0
  354. package/dist/context-builder/codemap.d.ts +22 -0
  355. package/dist/context-builder/codemap.js +675 -0
  356. package/dist/context-builder/codemap.js.map +1 -0
  357. package/dist/context-builder/config.d.ts +61 -0
  358. package/dist/context-builder/config.js +216 -0
  359. package/dist/context-builder/config.js.map +1 -0
  360. package/dist/context-builder/context-run-catalog.d.ts +17 -0
  361. package/dist/context-builder/context-run-catalog.js +99 -0
  362. package/dist/context-builder/context-run-catalog.js.map +1 -0
  363. package/dist/context-builder/delegate-packet.d.ts +219 -0
  364. package/dist/context-builder/delegate-packet.js +1190 -0
  365. package/dist/context-builder/delegate-packet.js.map +1 -0
  366. package/dist/context-builder/delegate-reconstruction.d.ts +13 -0
  367. package/dist/context-builder/delegate-reconstruction.js +220 -0
  368. package/dist/context-builder/delegate-reconstruction.js.map +1 -0
  369. package/dist/context-builder/delegate-validation.d.ts +27 -0
  370. package/dist/context-builder/delegate-validation.js +479 -0
  371. package/dist/context-builder/delegate-validation.js.map +1 -0
  372. package/dist/context-builder/delegate.d.ts +26 -0
  373. package/dist/context-builder/delegate.js +134 -0
  374. package/dist/context-builder/delegate.js.map +1 -0
  375. package/dist/context-builder/diagnostics.d.ts +36 -0
  376. package/dist/context-builder/diagnostics.js +107 -0
  377. package/dist/context-builder/diagnostics.js.map +1 -0
  378. package/dist/context-builder/discovery.d.ts +146 -0
  379. package/dist/context-builder/discovery.js +2129 -0
  380. package/dist/context-builder/discovery.js.map +1 -0
  381. package/dist/context-builder/globs.d.ts +14 -0
  382. package/dist/context-builder/globs.js +175 -0
  383. package/dist/context-builder/globs.js.map +1 -0
  384. package/dist/context-builder/handler.d.ts +41 -0
  385. package/dist/context-builder/handler.js +2590 -0
  386. package/dist/context-builder/handler.js.map +1 -0
  387. package/dist/context-builder/lifecycle-contract.d.ts +424 -0
  388. package/dist/context-builder/lifecycle-contract.js +523 -0
  389. package/dist/context-builder/lifecycle-contract.js.map +1 -0
  390. package/dist/context-builder/lifecycle-journal.d.ts +62 -0
  391. package/dist/context-builder/lifecycle-journal.js +88 -0
  392. package/dist/context-builder/lifecycle-journal.js.map +1 -0
  393. package/dist/context-builder/lifecycle-observer.d.ts +102 -0
  394. package/dist/context-builder/lifecycle-observer.js +258 -0
  395. package/dist/context-builder/lifecycle-observer.js.map +1 -0
  396. package/dist/context-builder/lifecycle-reconcile.d.ts +32 -0
  397. package/dist/context-builder/lifecycle-reconcile.js +191 -0
  398. package/dist/context-builder/lifecycle-reconcile.js.map +1 -0
  399. package/dist/context-builder/lifecycle-recovery.d.ts +2 -0
  400. package/dist/context-builder/lifecycle-recovery.js +14 -0
  401. package/dist/context-builder/lifecycle-recovery.js.map +1 -0
  402. package/dist/context-builder/path-signals.d.ts +7 -0
  403. package/dist/context-builder/path-signals.js +70 -0
  404. package/dist/context-builder/path-signals.js.map +1 -0
  405. package/dist/context-builder/paths.d.ts +30 -0
  406. package/dist/context-builder/paths.js +153 -0
  407. package/dist/context-builder/paths.js.map +1 -0
  408. package/dist/context-builder/progress.d.ts +17 -0
  409. package/dist/context-builder/progress.js +93 -0
  410. package/dist/context-builder/progress.js.map +1 -0
  411. package/dist/context-builder/receipt.d.ts +91 -0
  412. package/dist/context-builder/receipt.js +180 -0
  413. package/dist/context-builder/receipt.js.map +1 -0
  414. package/dist/context-builder/refine-handler.d.ts +14 -0
  415. package/dist/context-builder/refine-handler.js +790 -0
  416. package/dist/context-builder/refine-handler.js.map +1 -0
  417. package/dist/context-builder/review-coverage.d.ts +84 -0
  418. package/dist/context-builder/review-coverage.js +437 -0
  419. package/dist/context-builder/review-coverage.js.map +1 -0
  420. package/dist/context-builder/run-id.d.ts +7 -0
  421. package/dist/context-builder/run-id.js +31 -0
  422. package/dist/context-builder/run-id.js.map +1 -0
  423. package/dist/context-builder/schema.d.ts +669 -0
  424. package/dist/context-builder/schema.js +399 -0
  425. package/dist/context-builder/schema.js.map +1 -0
  426. package/dist/context-builder/secrets.d.ts +41 -0
  427. package/dist/context-builder/secrets.js +1651 -0
  428. package/dist/context-builder/secrets.js.map +1 -0
  429. package/dist/context-builder/selection.d.ts +56 -0
  430. package/dist/context-builder/selection.js +1111 -0
  431. package/dist/context-builder/selection.js.map +1 -0
  432. package/dist/context-builder/session-log-identity.d.ts +1 -0
  433. package/dist/context-builder/session-log-identity.js +66 -0
  434. package/dist/context-builder/session-log-identity.js.map +1 -0
  435. package/dist/context-builder/slice-range-math.d.ts +16 -0
  436. package/dist/context-builder/slice-range-math.js +137 -0
  437. package/dist/context-builder/slice-range-math.js.map +1 -0
  438. package/dist/context-builder/status.d.ts +66 -0
  439. package/dist/context-builder/status.js +160 -0
  440. package/dist/context-builder/status.js.map +1 -0
  441. package/dist/context-builder/storage.d.ts +118 -0
  442. package/dist/context-builder/storage.js +1003 -0
  443. package/dist/context-builder/storage.js.map +1 -0
  444. package/dist/context-builder/token-estimate.d.ts +19 -0
  445. package/dist/context-builder/token-estimate.js +90 -0
  446. package/dist/context-builder/token-estimate.js.map +1 -0
  447. package/dist/context-builder/versions.d.ts +29 -0
  448. package/dist/context-builder/versions.js +30 -0
  449. package/dist/context-builder/versions.js.map +1 -0
  450. package/dist/context-builder/workflow-runner.d.ts +69 -0
  451. package/dist/context-builder/workflow-runner.js +1051 -0
  452. package/dist/context-builder/workflow-runner.js.map +1 -0
  453. package/dist/context-builder/write-watchdog.d.ts +14 -0
  454. package/dist/context-builder/write-watchdog.js +38 -0
  455. package/dist/context-builder/write-watchdog.js.map +1 -0
  456. package/dist/dashboard-adapter-catalog.d.ts +9 -0
  457. package/dist/dashboard-adapter-catalog.js +46 -0
  458. package/dist/dashboard-adapter-catalog.js.map +1 -0
  459. package/dist/dashboard-cli.d.ts +79 -0
  460. package/dist/dashboard-cli.js +585 -0
  461. package/dist/dashboard-cli.js.map +1 -0
  462. package/dist/dashboard-companion/client.d.ts +36 -0
  463. package/dist/dashboard-companion/client.js +210 -0
  464. package/dist/dashboard-companion/client.js.map +1 -0
  465. package/dist/dashboard-companion/config.d.ts +8 -0
  466. package/dist/dashboard-companion/config.js +52 -0
  467. package/dist/dashboard-companion/config.js.map +1 -0
  468. package/dist/dashboard-companion/http-proxy.d.ts +10 -0
  469. package/dist/dashboard-companion/http-proxy.js +234 -0
  470. package/dist/dashboard-companion/http-proxy.js.map +1 -0
  471. package/dist/dashboard-companion/protocol.d.ts +80 -0
  472. package/dist/dashboard-companion/protocol.js +455 -0
  473. package/dist/dashboard-companion/protocol.js.map +1 -0
  474. package/dist/dashboard-companion/standalone-assets.d.ts +12 -0
  475. package/dist/dashboard-companion/standalone-assets.js +72 -0
  476. package/dist/dashboard-companion/standalone-assets.js.map +1 -0
  477. package/dist/dashboard-companion/standalone-entry.d.ts +1 -0
  478. package/dist/dashboard-companion/standalone-entry.js +17 -0
  479. package/dist/dashboard-companion/standalone-entry.js.map +1 -0
  480. package/dist/dashboard-gateway/config.d.ts +9 -0
  481. package/dist/dashboard-gateway/config.js +44 -0
  482. package/dist/dashboard-gateway/config.js.map +1 -0
  483. package/dist/dashboard-gateway/index.d.ts +11 -0
  484. package/dist/dashboard-gateway/index.js +755 -0
  485. package/dist/dashboard-gateway/index.js.map +1 -0
  486. package/dist/dashboard-gateway/main.d.ts +1 -0
  487. package/dist/dashboard-gateway/main.js +25 -0
  488. package/dist/dashboard-gateway/main.js.map +1 -0
  489. package/dist/dashboard-pairing-token.d.ts +1 -0
  490. package/dist/dashboard-pairing-token.js +5 -0
  491. package/dist/dashboard-pairing-token.js.map +1 -0
  492. package/dist/elaris/client.d.ts +73 -0
  493. package/dist/elaris/client.js +825 -0
  494. package/dist/elaris/client.js.map +1 -0
  495. package/dist/elaris/config.d.ts +18 -0
  496. package/dist/elaris/config.js +75 -0
  497. package/dist/elaris/config.js.map +1 -0
  498. package/dist/elaris/errors.d.ts +41 -0
  499. package/dist/elaris/errors.js +205 -0
  500. package/dist/elaris/errors.js.map +1 -0
  501. package/dist/elaris/github-repo.d.ts +18 -0
  502. package/dist/elaris/github-repo.js +89 -0
  503. package/dist/elaris/github-repo.js.map +1 -0
  504. package/dist/elaris/index.d.ts +10 -0
  505. package/dist/elaris/index.js +11 -0
  506. package/dist/elaris/index.js.map +1 -0
  507. package/dist/elaris/redact.d.ts +89 -0
  508. package/dist/elaris/redact.js +423 -0
  509. package/dist/elaris/redact.js.map +1 -0
  510. package/dist/elaris/run-id.d.ts +5 -0
  511. package/dist/elaris/run-id.js +20 -0
  512. package/dist/elaris/run-id.js.map +1 -0
  513. package/dist/elaris/status.d.ts +45 -0
  514. package/dist/elaris/status.js +122 -0
  515. package/dist/elaris/status.js.map +1 -0
  516. package/dist/elaris/tool-schemas.d.ts +314 -0
  517. package/dist/elaris/tool-schemas.js +208 -0
  518. package/dist/elaris/tool-schemas.js.map +1 -0
  519. package/dist/elaris/tools.d.ts +73 -0
  520. package/dist/elaris/tools.js +1065 -0
  521. package/dist/elaris/tools.js.map +1 -0
  522. package/dist/elaris/types.d.ts +1541 -0
  523. package/dist/elaris/types.js +252 -0
  524. package/dist/elaris/types.js.map +1 -0
  525. package/dist/errors.d.ts +16 -0
  526. package/dist/errors.js +19 -0
  527. package/dist/errors.js.map +1 -1
  528. package/dist/handler.d.ts +4 -0
  529. package/dist/handler.js +10 -1
  530. package/dist/handler.js.map +1 -1
  531. package/dist/index.d.ts +2 -1
  532. package/dist/index.js +13 -3
  533. package/dist/index.js.map +1 -1
  534. package/dist/local-clink-backend.d.ts +3 -0
  535. package/dist/local-clink-backend.js +4 -0
  536. package/dist/local-clink-backend.js.map +1 -1
  537. package/dist/package-info.d.ts +2 -0
  538. package/dist/package-info.js +18 -0
  539. package/dist/package-info.js.map +1 -0
  540. package/dist/parsers/codex-jsonl.js +48 -3
  541. package/dist/parsers/codex-jsonl.js.map +1 -1
  542. package/dist/parsers/extract.d.ts +10 -1
  543. package/dist/parsers/extract.js +11 -3
  544. package/dist/parsers/extract.js.map +1 -1
  545. package/dist/paths.d.ts +8 -0
  546. package/dist/paths.js +31 -43
  547. package/dist/paths.js.map +1 -1
  548. package/dist/pipeline.d.ts +51 -3
  549. package/dist/pipeline.js +264 -47
  550. package/dist/pipeline.js.map +1 -1
  551. package/dist/run-dir.d.ts +24 -0
  552. package/dist/run-dir.js +201 -2
  553. package/dist/run-dir.js.map +1 -1
  554. package/dist/runner.d.ts +13 -0
  555. package/dist/runner.js +184 -15
  556. package/dist/runner.js.map +1 -1
  557. package/dist/safety.d.ts +4 -4
  558. package/dist/safety.js +4 -4
  559. package/dist/schema.d.ts +7 -7
  560. package/dist/server.d.ts +2 -0
  561. package/dist/server.js +396 -24
  562. package/dist/server.js.map +1 -1
  563. package/dist/session-log-stream.d.ts +18 -0
  564. package/dist/session-log-stream.js +319 -0
  565. package/dist/session-log-stream.js.map +1 -0
  566. package/package.json +47 -5
  567. package/conf/adapters/gemini.json +0 -44
  568. package/conf/adapters/hapi/gemini.json +0 -47
  569. package/dist/artifacts.d.ts +0 -9
  570. package/dist/artifacts.js +0 -24
  571. package/dist/artifacts.js.map +0 -1
  572. package/dist/parsers/gemini-json.d.ts +0 -2
  573. package/dist/parsers/gemini-json.js +0 -72
  574. package/dist/parsers/gemini-json.js.map +0 -1
@@ -0,0 +1,381 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { chmod, mkdir, open, readFile, readdir, rename, rm, stat, } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { ACTIVITY_RESULT_FILENAME, ACTIVITY_STATE_FILENAME, ActivityIdSchema, ActivityStateV1Schema, DEFAULT_ACTIVITY_HEARTBEAT_INTERVAL_MS, DEFAULT_ACTIVITY_MAX_AGE_MS, DEFAULT_MAX_ACTIVITY_ENTRIES, DEFAULT_MAX_ACTIVITY_RESULT_BYTES, DEFAULT_MAX_ACTIVITY_TOTAL_BYTES, MAX_ACTIVITY_STATE_BYTES, } from "../clinkx-workflows/dist/dashboard/activity-contract.js";
5
+ import { createDashboardActivityReader } from "../clinkx-workflows/dist/dashboard/activity-reader.js";
6
+ import { removeSessionLogGeneration } from "../clinkx-workflows/dist/dashboard/session-log-retention.js";
7
+ import { createSessionLogGeneration, readSessionLogGeneration, } from "../clinkx-workflows/dist/dashboard/session-log-identity.js";
8
+ import { logger } from "./logger.js";
9
+ export { ACTIVITY_RESULT_FILENAME, ACTIVITY_STATE_FILENAME, ActivityIdSchema, ActivityKindSchema, ActivityOutcomeKindSchema, ActivityPhaseSchema, ActivityResultReferenceSchema, ActivityStateV1Schema, ActivityTerminalStatusSchema, DEFAULT_ACTIVITY_HEARTBEAT_INTERVAL_MS, DEFAULT_ACTIVITY_MAX_AGE_MS, DEFAULT_MAX_ACTIVITY_ENTRIES, DEFAULT_MAX_ACTIVITY_RESULT_BYTES, DEFAULT_MAX_ACTIVITY_TOTAL_BYTES, MAX_ACTIVITY_STATE_BYTES, } from "../clinkx-workflows/dist/dashboard/activity-contract.js";
10
+ export const ACTIVITY_RETAIN_RESULT_ENV = "CLINKX_DASHBOARD_ACTIVITY_RETAIN_RESULT";
11
+ const SESSION_LOG_GENERATION_FILE_BYTES = 44;
12
+ const NOOP_OBSERVATION = Object.freeze({
13
+ async transition() { },
14
+ async complete() { },
15
+ });
16
+ async function writeFileAtomic(filePath, content) {
17
+ const temporaryPath = `${filePath}.${randomUUID()}.tmp`;
18
+ const handle = await open(temporaryPath, "wx", 0o600);
19
+ try {
20
+ await handle.writeFile(content);
21
+ await handle.sync();
22
+ await handle.close();
23
+ await rename(temporaryPath, filePath);
24
+ await chmod(filePath, 0o600);
25
+ }
26
+ catch (error) {
27
+ await handle.close().catch(() => undefined);
28
+ await rm(temporaryPath, { force: true }).catch(() => undefined);
29
+ throw error;
30
+ }
31
+ }
32
+ function serializedState(state) {
33
+ const serialized = `${JSON.stringify(ActivityStateV1Schema.parse(state), null, 2)}\n`;
34
+ if (Buffer.byteLength(serialized, "utf8") > MAX_ACTIVITY_STATE_BYTES) {
35
+ throw new Error("activity state exceeds the producer byte cap");
36
+ }
37
+ return serialized;
38
+ }
39
+ async function pruneActivities(rootDir, sessionLogRootDir, activityIdentityReader, now, maxAgeMs, maxEntries, maxTotalBytes, reservedBytes) {
40
+ const entries = await readdir(rootDir, { withFileTypes: true });
41
+ await Promise.all(entries.map(async (entry) => {
42
+ if (!entry.isDirectory() || !ActivityIdSchema.safeParse(entry.name).success) {
43
+ return;
44
+ }
45
+ const activityDir = join(rootDir, entry.name);
46
+ try {
47
+ const parsed = ActivityStateV1Schema.safeParse(JSON.parse(await readFile(join(activityDir, ACTIVITY_STATE_FILENAME), "utf8")));
48
+ if (!parsed.success ||
49
+ parsed.data.phase !== "terminal" ||
50
+ parsed.data.completedAt === undefined) {
51
+ return;
52
+ }
53
+ if (now.getTime() - Date.parse(parsed.data.completedAt) > maxAgeMs) {
54
+ await pruneActivityDirectory({
55
+ rootDir,
56
+ sessionLogRootDir,
57
+ activityId: entry.name,
58
+ activityDir,
59
+ activityIdentityReader,
60
+ });
61
+ }
62
+ }
63
+ catch (error) {
64
+ if (error.code !== "ENOENT") {
65
+ logger.debug({
66
+ activity_id: entry.name,
67
+ err: error instanceof Error ? error.message : String(error),
68
+ }, "activity journal could not inspect a retention candidate");
69
+ }
70
+ }
71
+ }));
72
+ const survivors = await readdir(rootDir, { withFileTypes: true });
73
+ const terminal = [];
74
+ let totalBytes = 0;
75
+ for (const entry of survivors) {
76
+ if (!entry.isDirectory())
77
+ continue;
78
+ const activityDir = join(rootDir, entry.name);
79
+ let activityBytes = 0;
80
+ try {
81
+ for (const child of await readdir(activityDir, { withFileTypes: true })) {
82
+ if (!child.isFile())
83
+ continue;
84
+ activityBytes += (await stat(join(activityDir, child.name))).size;
85
+ }
86
+ }
87
+ catch {
88
+ // A concurrent terminal update is reconciled at the next admission.
89
+ }
90
+ totalBytes += activityBytes;
91
+ if (!ActivityIdSchema.safeParse(entry.name).success)
92
+ continue;
93
+ try {
94
+ const parsed = ActivityStateV1Schema.safeParse(JSON.parse(await readFile(join(activityDir, ACTIVITY_STATE_FILENAME), "utf8")));
95
+ if (parsed.success &&
96
+ parsed.data.phase === "terminal" &&
97
+ parsed.data.completedAt !== undefined) {
98
+ terminal.push({
99
+ activityId: entry.name,
100
+ path: activityDir,
101
+ completedAtMs: Date.parse(parsed.data.completedAt),
102
+ bytes: activityBytes,
103
+ });
104
+ }
105
+ }
106
+ catch {
107
+ // Unreadable entries are not producer-owned retention candidates.
108
+ }
109
+ }
110
+ terminal.sort((left, right) => left.completedAtMs - right.completedAtMs);
111
+ let entryCount = survivors.filter((entry) => entry.isDirectory()).length;
112
+ while (entryCount >= maxEntries && terminal.length > 0) {
113
+ const victim = terminal.shift();
114
+ if (await pruneActivityDirectory({
115
+ rootDir,
116
+ sessionLogRootDir,
117
+ activityId: victim.activityId,
118
+ activityDir: victim.path,
119
+ activityIdentityReader,
120
+ })) {
121
+ entryCount -= 1;
122
+ totalBytes -= victim.bytes;
123
+ }
124
+ }
125
+ while (totalBytes + reservedBytes > maxTotalBytes &&
126
+ terminal.length > 0) {
127
+ const victim = terminal.shift();
128
+ if (await pruneActivityDirectory({
129
+ rootDir,
130
+ sessionLogRootDir,
131
+ activityId: victim.activityId,
132
+ activityDir: victim.path,
133
+ activityIdentityReader,
134
+ })) {
135
+ entryCount -= 1;
136
+ totalBytes -= victim.bytes;
137
+ }
138
+ }
139
+ return entryCount < maxEntries && totalBytes + reservedBytes <= maxTotalBytes;
140
+ }
141
+ async function pruneActivityDirectory(input) {
142
+ const identity = await input.activityIdentityReader.resolveCurrent(input.rootDir, input.activityId);
143
+ if (identity.kind !== "resolved") {
144
+ logger.debug({ activity_id: input.activityId }, "activity retention skipped because exact generation was unavailable");
145
+ return false;
146
+ }
147
+ const sessionLogIdentity = await readSessionLogGeneration(input.activityDir);
148
+ const sessionLogGeneration = sessionLogIdentity.kind === "available"
149
+ ? sessionLogIdentity.sessionLogGeneration
150
+ : sessionLogIdentity.kind === "legacy"
151
+ ? identity.activityGeneration
152
+ : undefined;
153
+ await rm(input.activityDir, { recursive: true, force: true });
154
+ if (sessionLogGeneration === undefined) {
155
+ logger.warn({ activity_id: input.activityId }, "activity parent pruned but portable session-log identity was unsafe");
156
+ return true;
157
+ }
158
+ try {
159
+ const cleanup = await removeSessionLogGeneration({
160
+ rootDir: input.sessionLogRootDir,
161
+ family: "activity",
162
+ generation: sessionLogGeneration,
163
+ });
164
+ if (cleanup.kind === "unsafe" || cleanup.kind === "unavailable") {
165
+ logger.warn({ activity_id: input.activityId, cleanup: cleanup.kind }, "activity parent pruned but exact session-log cleanup was unavailable");
166
+ }
167
+ }
168
+ catch {
169
+ logger.warn({ activity_id: input.activityId }, "activity parent pruned but exact session-log cleanup failed");
170
+ }
171
+ return true;
172
+ }
173
+ function truncateUtf8(text, maxBytes) {
174
+ const source = Buffer.from(text, "utf8");
175
+ if (source.byteLength <= maxBytes) {
176
+ return { bytes: source, truncated: false };
177
+ }
178
+ const decoder = new TextDecoder("utf-8", { fatal: true });
179
+ let end = maxBytes;
180
+ while (end > 0) {
181
+ const candidate = source.subarray(0, end);
182
+ try {
183
+ decoder.decode(candidate);
184
+ return { bytes: candidate, truncated: true };
185
+ }
186
+ catch {
187
+ end -= 1;
188
+ }
189
+ }
190
+ return { bytes: Buffer.alloc(0), truncated: true };
191
+ }
192
+ class FileActivityObservation {
193
+ activityDir;
194
+ options;
195
+ identity;
196
+ state;
197
+ writeChain = Promise.resolve();
198
+ terminal = false;
199
+ heartbeat;
200
+ constructor(activityDir, options, initialState, identity) {
201
+ this.activityDir = activityDir;
202
+ this.options = options;
203
+ this.identity = identity;
204
+ this.state = initialState;
205
+ if (options.heartbeatIntervalMs > 0) {
206
+ this.heartbeat = setInterval(() => {
207
+ void this.enqueue(async () => {
208
+ if (this.terminal)
209
+ return;
210
+ const timestamp = this.options.now().toISOString();
211
+ this.state = {
212
+ ...this.state,
213
+ stateUpdatedAt: timestamp,
214
+ leaseUpdatedAt: timestamp,
215
+ };
216
+ await this.persistState();
217
+ });
218
+ }, options.heartbeatIntervalMs);
219
+ this.heartbeat.unref();
220
+ }
221
+ }
222
+ async transition(phase) {
223
+ await this.enqueue(async () => {
224
+ if (this.terminal)
225
+ return;
226
+ const timestamp = this.options.now().toISOString();
227
+ this.state = {
228
+ ...this.state,
229
+ phase,
230
+ stateUpdatedAt: timestamp,
231
+ leaseUpdatedAt: timestamp,
232
+ };
233
+ await this.persistState();
234
+ });
235
+ }
236
+ async complete(completion) {
237
+ await this.enqueue(async () => {
238
+ if (this.terminal)
239
+ return;
240
+ this.terminal = true;
241
+ if (this.heartbeat !== undefined) {
242
+ clearInterval(this.heartbeat);
243
+ this.heartbeat = undefined;
244
+ }
245
+ let result;
246
+ try {
247
+ result = await this.persistResult(completion.resultText);
248
+ }
249
+ catch (error) {
250
+ logger.warn({
251
+ activity_id: this.state.activityId,
252
+ err: error instanceof Error ? error.message : String(error),
253
+ }, "activity result persistence failed; committing terminal metadata without content");
254
+ }
255
+ const timestamp = this.options.now().toISOString();
256
+ this.state = {
257
+ ...this.state,
258
+ phase: "terminal",
259
+ status: completion.status,
260
+ stateUpdatedAt: timestamp,
261
+ completedAt: timestamp,
262
+ outcome: { kind: completion.outcomeKind },
263
+ ...(result === undefined ? {} : { result }),
264
+ };
265
+ await this.persistState();
266
+ });
267
+ }
268
+ async enqueue(task) {
269
+ const next = this.writeChain.then(task, task).catch((error) => {
270
+ logger.warn({
271
+ activity_id: this.state.activityId,
272
+ err: error instanceof Error ? error.message : String(error),
273
+ }, "activity journal write failed; clink execution remains authoritative");
274
+ });
275
+ this.writeChain = next;
276
+ await next;
277
+ }
278
+ async persistResult(resultText) {
279
+ if (!this.options.retainResult || resultText === undefined)
280
+ return undefined;
281
+ const { bytes, truncated } = truncateUtf8(resultText, this.options.maxResultBytes);
282
+ await writeFileAtomic(join(this.activityDir, ACTIVITY_RESULT_FILENAME), bytes);
283
+ return {
284
+ path: ACTIVITY_RESULT_FILENAME,
285
+ bytes: bytes.byteLength,
286
+ sha256: createHash("sha256").update(bytes).digest("hex"),
287
+ truncated,
288
+ };
289
+ }
290
+ async persistState() {
291
+ await writeFileAtomic(join(this.activityDir, ACTIVITY_STATE_FILENAME), serializedState(this.state));
292
+ }
293
+ }
294
+ export function createActivityJournal(options) {
295
+ const activityIdentityReader = createDashboardActivityReader();
296
+ const sessionLogRootDir = options.sessionLogRootDir ??
297
+ join(options.rootDir, "..", "session-logs");
298
+ const now = options.now ?? (() => new Date());
299
+ const maxResultBytes = Number.isSafeInteger(options.maxResultBytes) &&
300
+ (options.maxResultBytes ?? 0) > 0
301
+ ? Math.min(options.maxResultBytes, DEFAULT_MAX_ACTIVITY_RESULT_BYTES)
302
+ : DEFAULT_MAX_ACTIVITY_RESULT_BYTES;
303
+ const normalized = {
304
+ retainResult: options.retainResult ?? false,
305
+ maxResultBytes,
306
+ heartbeatIntervalMs: options.heartbeatIntervalMs ?? DEFAULT_ACTIVITY_HEARTBEAT_INTERVAL_MS,
307
+ now,
308
+ };
309
+ const maxAgeMs = options.maxAgeMs ?? DEFAULT_ACTIVITY_MAX_AGE_MS;
310
+ const maxEntries = options.maxEntries ?? DEFAULT_MAX_ACTIVITY_ENTRIES;
311
+ const maxTotalBytes = options.maxTotalBytes ?? DEFAULT_MAX_ACTIVITY_TOTAL_BYTES;
312
+ const reservedBytes = MAX_ACTIVITY_STATE_BYTES +
313
+ SESSION_LOG_GENERATION_FILE_BYTES +
314
+ (normalized.retainResult ? normalized.maxResultBytes : 0);
315
+ let admissionChain = Promise.resolve();
316
+ async function beginOne(input) {
317
+ try {
318
+ const parsed = ActivityIdSchema.parse(input.activityId);
319
+ await mkdir(options.rootDir, { recursive: true, mode: 0o700 });
320
+ await chmod(options.rootDir, 0o700);
321
+ try {
322
+ const admitted = await pruneActivities(options.rootDir, sessionLogRootDir, activityIdentityReader, now(), maxAgeMs, maxEntries, maxTotalBytes, reservedBytes);
323
+ if (!admitted) {
324
+ logger.warn({ activity_id: input.activityId }, "activity journal capacity is occupied by live or unreadable records; observation disabled");
325
+ return NOOP_OBSERVATION;
326
+ }
327
+ }
328
+ catch (error) {
329
+ logger.warn({
330
+ activity_id: input.activityId,
331
+ err: error instanceof Error ? error.message : String(error),
332
+ }, "activity journal pruning failed; observation disabled");
333
+ return NOOP_OBSERVATION;
334
+ }
335
+ const activityDir = join(options.rootDir, parsed);
336
+ await mkdir(activityDir, { mode: 0o700 });
337
+ await chmod(activityDir, 0o700);
338
+ const sessionLogGeneration = await createSessionLogGeneration(activityDir);
339
+ const timestamp = now().toISOString();
340
+ const initialState = ActivityStateV1Schema.parse({
341
+ schemaVersion: "clinkx-dashboard-activity-v1",
342
+ activityId: parsed,
343
+ kind: input.kind,
344
+ phase: "resolving",
345
+ status: "running",
346
+ adapter: input.adapter,
347
+ role: input.role,
348
+ startedAt: timestamp,
349
+ stateUpdatedAt: timestamp,
350
+ leaseUpdatedAt: timestamp,
351
+ ...(input.projectFolders === undefined || input.projectFolders.length === 0
352
+ ? {}
353
+ : { projectFolders: [...input.projectFolders] }),
354
+ });
355
+ await writeFileAtomic(join(activityDir, ACTIVITY_STATE_FILENAME), serializedState(initialState));
356
+ const identity = await activityIdentityReader.resolveCurrent(options.rootDir, parsed);
357
+ if (identity.kind !== "resolved") {
358
+ throw new Error("activity journal directory identity unavailable");
359
+ }
360
+ return new FileActivityObservation(activityDir, normalized, initialState, Object.freeze({
361
+ activityId: parsed,
362
+ activityGeneration: sessionLogGeneration,
363
+ }));
364
+ }
365
+ catch (error) {
366
+ logger.warn({
367
+ activity_id: input.activityId,
368
+ err: error instanceof Error ? error.message : String(error),
369
+ }, "activity journal start failed; clink execution remains authoritative");
370
+ return NOOP_OBSERVATION;
371
+ }
372
+ }
373
+ return {
374
+ begin(input) {
375
+ const next = admissionChain.then(() => beginOne(input), () => beginOne(input));
376
+ admissionChain = next.then(() => undefined, () => undefined);
377
+ return next;
378
+ },
379
+ };
380
+ }
381
+ //# sourceMappingURL=activity-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-journal.js","sourceRoot":"","sources":["../src/activity-journal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ export type AllowedRootsOptions = {
2
+ env?: NodeJS.ProcessEnv;
3
+ cwd?: string;
4
+ rejectBroadRoots?: boolean;
5
+ requireExisting?: boolean;
6
+ includeArtifactOnly?: boolean;
7
+ };
8
+ export declare function parseAllowedRootsEnv(options?: AllowedRootsOptions): string[];
9
+ export declare function serializeAllowedRoots(roots: readonly string[]): string;
10
+ export declare function appendAllowedRootsToEnv(rootsToAppend: readonly string[], options?: AllowedRootsOptions): string;
11
+ /**
12
+ * Encode `root` as an artifact-only `CLINKX_ALLOWED_ROOTS` entry by appending a
13
+ * trailing `/.` (or `\.` on Windows) marker.
14
+ *
15
+ * An artifact-only entry grants a root for child process I/O and artifact
16
+ * writes (e.g. state/run dirs producers emit), but MUST NEVER be treated as a
17
+ * `context_builder` SOURCE root: the `context_builder` source-root validators
18
+ * skip marked entries so curated bundles can never select from a write/output
19
+ * root. The marker is an env-string convention only — strip it with
20
+ * {@link stripArtifactOnlyMarker} before any `path.resolve`/`realpathSync`, or
21
+ * the canonicalized path silently loses the `/.` and re-enters source roots
22
+ * (the "realpath-strip trap").
23
+ */
24
+ export declare function artifactOnlyEnvEntry(root: string): string;
25
+ /**
26
+ * Return true when `entry` is an artifact-only `CLINKX_ALLOWED_ROOTS` entry
27
+ * (ends with the `/.` or `\.` marker). Source-root validators use this to skip
28
+ * artifact-only entries; consumers that need the real directory must call
29
+ * {@link stripArtifactOnlyMarker} first. The check is purely lexical and does
30
+ * not touch the filesystem.
31
+ */
32
+ export declare function isArtifactOnlyAllowedRootEntry(entry: string): boolean;
33
+ /**
34
+ * Remove the trailing artifact-only `/.` / `\.` marker, returning the real
35
+ * directory path the entry refers to. No-op for unmarked entries. Filesystem
36
+ * roots are preserved (`/.` -> `/`, `C:\.` -> `C:\`). Always call this before
37
+ * resolving/realpath'ing a marked entry to avoid the realpath-strip trap noted
38
+ * on {@link artifactOnlyEnvEntry}.
39
+ */
40
+ export declare function stripArtifactOnlyMarker(entry: string): string;
41
+ /**
42
+ * Append `rootsToAppend` to `CLINKX_ALLOWED_ROOTS` as artifact-only entries
43
+ * ({@link artifactOnlyEnvEntry}). Used by producers to widen the child's
44
+ * write/artifact boundary without widening the `context_builder` source
45
+ * surface: appended roots are usable as child I/O / artifact-write roots but
46
+ * never as a context_builder source root. Broad/filesystem roots are rejected,
47
+ * and entries already present (marked or not) are de-duplicated by resolved
48
+ * path.
49
+ */
50
+ export declare function appendArtifactOnlyRootsToEnv(rootsToAppend: readonly string[], options?: AllowedRootsOptions): string;
51
+ export declare function isPathWithinAllowedRoots(resolvedPath: string, roots: readonly string[]): boolean;
52
+ export declare function isSamePathOrDescendant(child: string, parent: string): boolean;
53
+ export declare function isFilesystemRoot(resolved: string): boolean;
@@ -0,0 +1,216 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { InvalidParamsError } from "./errors.js";
4
+ const ALLOWED_ROOTS_ENV = "CLINKX_ALLOWED_ROOTS";
5
+ export function parseAllowedRootsEnv(options = {}) {
6
+ const env = options.env ?? process.env;
7
+ const cwd = options.cwd ?? process.cwd();
8
+ const raw = rawAllowedRoots(env[ALLOWED_ROOTS_ENV], cwd);
9
+ const roots = [];
10
+ const seen = new Set();
11
+ for (const entry of raw) {
12
+ if (options.includeArtifactOnly === false &&
13
+ isArtifactOnlyAllowedRootEntry(entry)) {
14
+ continue;
15
+ }
16
+ const resolved = resolveAllowedRoot(isArtifactOnlyAllowedRootEntry(entry)
17
+ ? stripArtifactOnlyMarker(entry)
18
+ : entry, {
19
+ cwd,
20
+ requireExisting: options.requireExisting ?? false,
21
+ });
22
+ if (options.rejectBroadRoots === true) {
23
+ rejectBroadAllowedRoot(resolved);
24
+ }
25
+ if (!seen.has(resolved)) {
26
+ seen.add(resolved);
27
+ roots.push(resolved);
28
+ }
29
+ }
30
+ return roots;
31
+ }
32
+ export function serializeAllowedRoots(roots) {
33
+ return roots.join(",");
34
+ }
35
+ export function appendAllowedRootsToEnv(rootsToAppend, options = {}) {
36
+ const env = options.env ?? process.env;
37
+ const cwd = options.cwd ?? process.cwd();
38
+ const parseOptions = { env, cwd };
39
+ if (options.rejectBroadRoots !== undefined) {
40
+ parseOptions.rejectBroadRoots = options.rejectBroadRoots;
41
+ }
42
+ if (options.requireExisting !== undefined) {
43
+ parseOptions.requireExisting = options.requireExisting;
44
+ }
45
+ if (options.includeArtifactOnly !== undefined) {
46
+ parseOptions.includeArtifactOnly = options.includeArtifactOnly;
47
+ }
48
+ const roots = normalizeAllowedRootEntriesForAppend(parseOptions);
49
+ const seen = new Set(roots
50
+ .filter((root) => !isArtifactOnlyAllowedRootEntry(root))
51
+ .map((root) => resolveAllowedRootBestEffort(root, cwd)));
52
+ for (const root of rootsToAppend) {
53
+ const resolved = resolveAllowedRoot(root, {
54
+ cwd,
55
+ requireExisting: options.requireExisting ?? true,
56
+ });
57
+ if (options.rejectBroadRoots === true) {
58
+ rejectBroadAllowedRoot(resolved);
59
+ }
60
+ if (!seen.has(resolved)) {
61
+ seen.add(resolved);
62
+ roots.push(resolved);
63
+ }
64
+ }
65
+ const serialized = serializeAllowedRoots(roots);
66
+ env[ALLOWED_ROOTS_ENV] = serialized;
67
+ return serialized;
68
+ }
69
+ /**
70
+ * Encode `root` as an artifact-only `CLINKX_ALLOWED_ROOTS` entry by appending a
71
+ * trailing `/.` (or `\.` on Windows) marker.
72
+ *
73
+ * An artifact-only entry grants a root for child process I/O and artifact
74
+ * writes (e.g. state/run dirs producers emit), but MUST NEVER be treated as a
75
+ * `context_builder` SOURCE root: the `context_builder` source-root validators
76
+ * skip marked entries so curated bundles can never select from a write/output
77
+ * root. The marker is an env-string convention only — strip it with
78
+ * {@link stripArtifactOnlyMarker} before any `path.resolve`/`realpathSync`, or
79
+ * the canonicalized path silently loses the `/.` and re-enters source roots
80
+ * (the "realpath-strip trap").
81
+ */
82
+ export function artifactOnlyEnvEntry(root) {
83
+ return root.endsWith(path.sep) ? `${root}.` : `${root}${path.sep}.`;
84
+ }
85
+ /**
86
+ * Return true when `entry` is an artifact-only `CLINKX_ALLOWED_ROOTS` entry
87
+ * (ends with the `/.` or `\.` marker). Source-root validators use this to skip
88
+ * artifact-only entries; consumers that need the real directory must call
89
+ * {@link stripArtifactOnlyMarker} first. The check is purely lexical and does
90
+ * not touch the filesystem.
91
+ */
92
+ export function isArtifactOnlyAllowedRootEntry(entry) {
93
+ return entry.endsWith("/.") || entry.endsWith("\\.");
94
+ }
95
+ /**
96
+ * Remove the trailing artifact-only `/.` / `\.` marker, returning the real
97
+ * directory path the entry refers to. No-op for unmarked entries. Filesystem
98
+ * roots are preserved (`/.` -> `/`, `C:\.` -> `C:\`). Always call this before
99
+ * resolving/realpath'ing a marked entry to avoid the realpath-strip trap noted
100
+ * on {@link artifactOnlyEnvEntry}.
101
+ */
102
+ export function stripArtifactOnlyMarker(entry) {
103
+ if (!isArtifactOnlyAllowedRootEntry(entry)) {
104
+ return entry;
105
+ }
106
+ const stripped = entry.slice(0, -2);
107
+ if (stripped === "") {
108
+ return entry.endsWith("/.") ? "/" : "\\";
109
+ }
110
+ if (entry.endsWith("\\.") && stripped.endsWith(":")) {
111
+ return `${stripped}\\`;
112
+ }
113
+ return stripped;
114
+ }
115
+ /**
116
+ * Append `rootsToAppend` to `CLINKX_ALLOWED_ROOTS` as artifact-only entries
117
+ * ({@link artifactOnlyEnvEntry}). Used by producers to widen the child's
118
+ * write/artifact boundary without widening the `context_builder` source
119
+ * surface: appended roots are usable as child I/O / artifact-write roots but
120
+ * never as a context_builder source root. Broad/filesystem roots are rejected,
121
+ * and entries already present (marked or not) are de-duplicated by resolved
122
+ * path.
123
+ */
124
+ export function appendArtifactOnlyRootsToEnv(rootsToAppend, options = {}) {
125
+ const env = options.env ?? process.env;
126
+ const cwd = options.cwd ?? process.cwd();
127
+ const entries = rawAllowedRoots(env[ALLOWED_ROOTS_ENV], cwd);
128
+ const seen = new Set(entries.map((entry) => resolveAllowedRootBestEffort(isArtifactOnlyAllowedRootEntry(entry)
129
+ ? stripArtifactOnlyMarker(entry)
130
+ : entry, cwd)));
131
+ for (const root of rootsToAppend) {
132
+ const resolved = resolveAllowedRoot(root, {
133
+ cwd,
134
+ requireExisting: options.requireExisting ?? true,
135
+ });
136
+ rejectBroadAllowedRoot(resolved);
137
+ if (!seen.has(resolved)) {
138
+ seen.add(resolved);
139
+ entries.push(artifactOnlyEnvEntry(resolved));
140
+ }
141
+ }
142
+ const serialized = serializeAllowedRoots(entries);
143
+ env[ALLOWED_ROOTS_ENV] = serialized;
144
+ return serialized;
145
+ }
146
+ export function isPathWithinAllowedRoots(resolvedPath, roots) {
147
+ return roots.some((root) => isSamePathOrDescendant(resolvedPath, root));
148
+ }
149
+ export function isSamePathOrDescendant(child, parent) {
150
+ const relation = path.relative(parent, child);
151
+ return relation === "" || (!relation.startsWith("..") && !path.isAbsolute(relation));
152
+ }
153
+ export function isFilesystemRoot(resolved) {
154
+ return resolved === path.parse(resolved).root;
155
+ }
156
+ function rawAllowedRoots(envValue, cwd) {
157
+ if (envValue != null && envValue.length > 0) {
158
+ return envValue
159
+ .split(",")
160
+ .map((root) => root.trim())
161
+ .filter((root) => root.length > 0);
162
+ }
163
+ return [cwd];
164
+ }
165
+ function resolveAllowedRoot(root, input) {
166
+ const lexical = path.resolve(input.cwd, root);
167
+ try {
168
+ return fs.realpathSync(lexical);
169
+ }
170
+ catch {
171
+ if (input.requireExisting) {
172
+ throw new InvalidParamsError(`Allowed root does not exist or is not accessible: ${root}`);
173
+ }
174
+ return lexical;
175
+ }
176
+ }
177
+ function resolveAllowedRootBestEffort(root, cwd) {
178
+ const lexical = path.resolve(cwd, root);
179
+ try {
180
+ return fs.realpathSync(lexical);
181
+ }
182
+ catch {
183
+ return lexical;
184
+ }
185
+ }
186
+ function normalizeAllowedRootEntriesForAppend(options) {
187
+ const raw = rawAllowedRoots(options.env[ALLOWED_ROOTS_ENV], options.cwd);
188
+ const roots = [];
189
+ const seen = new Set();
190
+ for (const entry of raw) {
191
+ if (isArtifactOnlyAllowedRootEntry(entry)) {
192
+ if (options.includeArtifactOnly !== false) {
193
+ roots.push(entry);
194
+ }
195
+ continue;
196
+ }
197
+ const resolved = resolveAllowedRoot(entry, {
198
+ cwd: options.cwd,
199
+ requireExisting: options.requireExisting ?? false,
200
+ });
201
+ if (options.rejectBroadRoots === true) {
202
+ rejectBroadAllowedRoot(resolved);
203
+ }
204
+ if (!seen.has(resolved)) {
205
+ seen.add(resolved);
206
+ roots.push(resolved);
207
+ }
208
+ }
209
+ return roots;
210
+ }
211
+ function rejectBroadAllowedRoot(root) {
212
+ if (isFilesystemRoot(root)) {
213
+ throw new InvalidParamsError(`Allowed root must not be a filesystem root: ${root}`);
214
+ }
215
+ }
216
+ //# sourceMappingURL=allowed-roots.js.map