@blxzer/pactile 0.6.0-beta.2 → 0.6.0-beta.5

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 (704) hide show
  1. package/README.md +93 -84
  2. package/README.zh-CN.md +90 -81
  3. package/dist/bin/compat-warning.d.ts +2 -0
  4. package/dist/bin/compat-warning.d.ts.map +1 -0
  5. package/dist/bin/compat-warning.js +8 -0
  6. package/dist/bin/compat-warning.js.map +1 -0
  7. package/dist/bin/cstl.d.ts +3 -0
  8. package/dist/bin/cstl.d.ts.map +1 -0
  9. package/{bin → dist/bin}/cstl.js +2 -3
  10. package/dist/bin/cstl.js.map +1 -0
  11. package/dist/bin/pactile.d.ts +3 -0
  12. package/dist/bin/pactile.d.ts.map +1 -0
  13. package/dist/bin/pactile.js +4 -0
  14. package/dist/bin/pactile.js.map +1 -0
  15. package/dist/cli/index.d.ts.map +1 -1
  16. package/dist/cli/index.js +77 -17
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/commands/capability.d.ts +3 -0
  19. package/dist/commands/capability.d.ts.map +1 -0
  20. package/dist/commands/capability.js +129 -0
  21. package/dist/commands/capability.js.map +1 -0
  22. package/dist/commands/codex.d.ts.map +1 -1
  23. package/dist/commands/codex.js +54 -6
  24. package/dist/commands/codex.js.map +1 -1
  25. package/dist/commands/context.d.ts +2 -0
  26. package/dist/commands/context.d.ts.map +1 -1
  27. package/dist/commands/context.js +367 -41
  28. package/dist/commands/context.js.map +1 -1
  29. package/dist/commands/detach.d.ts.map +1 -1
  30. package/dist/commands/detach.js +5 -4
  31. package/dist/commands/detach.js.map +1 -1
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +615 -259
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/legacy-task.d.ts +3 -0
  36. package/dist/commands/legacy-task.d.ts.map +1 -0
  37. package/dist/commands/legacy-task.js +295 -0
  38. package/dist/commands/legacy-task.js.map +1 -0
  39. package/dist/commands/pi.d.ts +3 -2
  40. package/dist/commands/pi.d.ts.map +1 -1
  41. package/dist/commands/pi.js +333 -10
  42. package/dist/commands/pi.js.map +1 -1
  43. package/dist/commands/session.d.ts.map +1 -1
  44. package/dist/commands/session.js +148 -24
  45. package/dist/commands/session.js.map +1 -1
  46. package/dist/commands/task-schedule.d.ts +17 -0
  47. package/dist/commands/task-schedule.d.ts.map +1 -0
  48. package/dist/commands/task-schedule.js +395 -0
  49. package/dist/commands/task-schedule.js.map +1 -0
  50. package/dist/commands/task-verify-plan.d.ts +3 -0
  51. package/dist/commands/task-verify-plan.d.ts.map +1 -0
  52. package/dist/commands/task-verify-plan.js +503 -0
  53. package/dist/commands/task-verify-plan.js.map +1 -0
  54. package/dist/commands/task-worktree-close.d.ts +4 -0
  55. package/dist/commands/task-worktree-close.d.ts.map +1 -0
  56. package/dist/commands/task-worktree-close.js +81 -0
  57. package/dist/commands/task-worktree-close.js.map +1 -0
  58. package/dist/commands/task.d.ts +3 -0
  59. package/dist/commands/task.d.ts.map +1 -1
  60. package/dist/commands/task.js +1373 -184
  61. package/dist/commands/task.js.map +1 -1
  62. package/dist/commands/tile-selection.d.ts +3 -0
  63. package/dist/commands/tile-selection.d.ts.map +1 -0
  64. package/dist/commands/tile-selection.js +174 -0
  65. package/dist/commands/tile-selection.js.map +1 -0
  66. package/dist/commands/update.d.ts +1 -1
  67. package/dist/commands/update.d.ts.map +1 -1
  68. package/dist/commands/update.js +80 -55
  69. package/dist/commands/update.js.map +1 -1
  70. package/dist/commands/worktree.d.ts +4 -0
  71. package/dist/commands/worktree.d.ts.map +1 -0
  72. package/dist/commands/worktree.js +198 -0
  73. package/dist/commands/worktree.js.map +1 -0
  74. package/dist/configurators/shared.js +1 -1
  75. package/dist/configurators/shared.js.map +1 -1
  76. package/dist/core/compat/environment.d.ts +0 -1
  77. package/dist/core/compat/environment.d.ts.map +1 -1
  78. package/dist/core/compat/environment.js +1 -9
  79. package/dist/core/compat/environment.js.map +1 -1
  80. package/dist/core/pactile/bounded-capabilities.d.ts +127 -0
  81. package/dist/core/pactile/bounded-capabilities.d.ts.map +1 -0
  82. package/dist/core/pactile/bounded-capabilities.js +188 -0
  83. package/dist/core/pactile/bounded-capabilities.js.map +1 -0
  84. package/dist/core/pactile/index.d.ts +1 -0
  85. package/dist/core/pactile/index.d.ts.map +1 -1
  86. package/dist/core/pactile/index.js +1 -0
  87. package/dist/core/pactile/index.js.map +1 -1
  88. package/dist/core/task/index.d.ts +4 -2
  89. package/dist/core/task/index.d.ts.map +1 -1
  90. package/dist/core/task/index.js +2 -1
  91. package/dist/core/task/index.js.map +1 -1
  92. package/dist/core/task/kernel-cli.d.ts +14 -1
  93. package/dist/core/task/kernel-cli.d.ts.map +1 -1
  94. package/dist/core/task/kernel-cli.js +128 -0
  95. package/dist/core/task/kernel-cli.js.map +1 -1
  96. package/dist/core/task/kernel-contract.d.ts +6 -3
  97. package/dist/core/task/kernel-contract.d.ts.map +1 -1
  98. package/dist/core/task/kernel-contract.js +71 -23
  99. package/dist/core/task/kernel-contract.js.map +1 -1
  100. package/dist/core/task/kernel-store.d.ts +6 -0
  101. package/dist/core/task/kernel-store.d.ts.map +1 -1
  102. package/dist/core/task/kernel-store.js +54 -2
  103. package/dist/core/task/kernel-store.js.map +1 -1
  104. package/dist/core/task/legacy-task-migration-reader.d.ts +137 -0
  105. package/dist/core/task/legacy-task-migration-reader.d.ts.map +1 -0
  106. package/dist/core/task/legacy-task-migration-reader.js +512 -0
  107. package/dist/core/task/legacy-task-migration-reader.js.map +1 -0
  108. package/dist/core/task/legacy-task-migration.d.ts +105 -0
  109. package/dist/core/task/legacy-task-migration.d.ts.map +1 -0
  110. package/dist/core/task/legacy-task-migration.js +562 -0
  111. package/dist/core/task/legacy-task-migration.js.map +1 -0
  112. package/dist/core/task/legacy-task-overlay-durable-io.d.ts +18 -0
  113. package/dist/core/task/legacy-task-overlay-durable-io.d.ts.map +1 -0
  114. package/dist/core/task/legacy-task-overlay-durable-io.js +66 -0
  115. package/dist/core/task/legacy-task-overlay-durable-io.js.map +1 -0
  116. package/dist/core/task/legacy-task-reconciliation-reader.d.ts +26 -0
  117. package/dist/core/task/legacy-task-reconciliation-reader.d.ts.map +1 -0
  118. package/dist/core/task/legacy-task-reconciliation-reader.js +324 -0
  119. package/dist/core/task/legacy-task-reconciliation-reader.js.map +1 -0
  120. package/dist/core/task/legacy-task-v2-import.d.ts +67 -0
  121. package/dist/core/task/legacy-task-v2-import.d.ts.map +1 -0
  122. package/dist/core/task/legacy-task-v2-import.js +1046 -0
  123. package/dist/core/task/legacy-task-v2-import.js.map +1 -0
  124. package/dist/core/task/project-file-observer.d.ts +46 -0
  125. package/dist/core/task/project-file-observer.d.ts.map +1 -0
  126. package/dist/core/task/project-file-observer.js +618 -0
  127. package/dist/core/task/project-file-observer.js.map +1 -0
  128. package/dist/core/task/start-authority.d.ts +14 -0
  129. package/dist/core/task/start-authority.d.ts.map +1 -0
  130. package/dist/core/task/start-authority.js +146 -0
  131. package/dist/core/task/start-authority.js.map +1 -0
  132. package/dist/core/task/strategy.d.ts +24 -0
  133. package/dist/core/task/strategy.d.ts.map +1 -0
  134. package/dist/core/task/strategy.js +136 -0
  135. package/dist/core/task/strategy.js.map +1 -0
  136. package/dist/core/task/task-candidate-observer.d.ts +111 -0
  137. package/dist/core/task/task-candidate-observer.d.ts.map +1 -0
  138. package/dist/core/task/task-candidate-observer.js +762 -0
  139. package/dist/core/task/task-candidate-observer.js.map +1 -0
  140. package/dist/core/task/task-kernel-close.d.ts +5 -0
  141. package/dist/core/task/task-kernel-close.d.ts.map +1 -0
  142. package/dist/core/task/task-kernel-close.js +367 -0
  143. package/dist/core/task/task-kernel-close.js.map +1 -0
  144. package/dist/core/task/task-kernel-dependencies.d.ts +3 -0
  145. package/dist/core/task/task-kernel-dependencies.d.ts.map +1 -0
  146. package/dist/core/task/task-kernel-dependencies.js +24 -0
  147. package/dist/core/task/task-kernel-dependencies.js.map +1 -0
  148. package/dist/core/task/task-kernel-host.d.ts +5 -0
  149. package/dist/core/task/task-kernel-host.d.ts.map +1 -0
  150. package/dist/core/task/task-kernel-host.js +136 -0
  151. package/dist/core/task/task-kernel-host.js.map +1 -0
  152. package/dist/core/task/task-kernel-paths.d.ts +19 -0
  153. package/dist/core/task/task-kernel-paths.d.ts.map +1 -0
  154. package/dist/core/task/task-kernel-paths.js +237 -0
  155. package/dist/core/task/task-kernel-paths.js.map +1 -0
  156. package/dist/core/task/task-kernel-reviews.d.ts +3 -0
  157. package/dist/core/task/task-kernel-reviews.d.ts.map +1 -0
  158. package/dist/core/task/task-kernel-reviews.js +100 -0
  159. package/dist/core/task/task-kernel-reviews.js.map +1 -0
  160. package/dist/core/task/task-kernel-runs.d.ts +5 -0
  161. package/dist/core/task/task-kernel-runs.d.ts.map +1 -0
  162. package/dist/core/task/task-kernel-runs.js +196 -0
  163. package/dist/core/task/task-kernel-runs.js.map +1 -0
  164. package/dist/core/task/task-kernel-schema.d.ts +29 -0
  165. package/dist/core/task/task-kernel-schema.d.ts.map +1 -0
  166. package/dist/core/task/task-kernel-schema.js +1169 -0
  167. package/dist/core/task/task-kernel-schema.js.map +1 -0
  168. package/dist/core/task/task-kernel-store-v2.d.ts +33 -0
  169. package/dist/core/task/task-kernel-store-v2.d.ts.map +1 -0
  170. package/dist/core/task/task-kernel-store-v2.js +574 -0
  171. package/dist/core/task/task-kernel-store-v2.js.map +1 -0
  172. package/dist/core/task/task-kernel-types.d.ts +585 -0
  173. package/dist/core/task/task-kernel-types.d.ts.map +1 -0
  174. package/dist/core/task/task-kernel-types.js +31 -0
  175. package/dist/core/task/task-kernel-types.js.map +1 -0
  176. package/dist/core/task/task-kernel-workspaces.d.ts +10 -0
  177. package/dist/core/task/task-kernel-workspaces.d.ts.map +1 -0
  178. package/dist/core/task/task-kernel-workspaces.js +250 -0
  179. package/dist/core/task/task-kernel-workspaces.js.map +1 -0
  180. package/dist/core/task/task-kernel-write-set.d.ts +3 -0
  181. package/dist/core/task/task-kernel-write-set.d.ts.map +1 -0
  182. package/dist/core/task/task-kernel-write-set.js +12 -0
  183. package/dist/core/task/task-kernel-write-set.js.map +1 -0
  184. package/dist/core/task/task-kernel.d.ts +19 -0
  185. package/dist/core/task/task-kernel.d.ts.map +1 -0
  186. package/dist/core/task/task-kernel.js +17 -0
  187. package/dist/core/task/task-kernel.js.map +1 -0
  188. package/dist/core/task/task-pull-request-observer.d.ts +25 -0
  189. package/dist/core/task/task-pull-request-observer.d.ts.map +1 -0
  190. package/dist/core/task/task-pull-request-observer.js +187 -0
  191. package/dist/core/task/task-pull-request-observer.js.map +1 -0
  192. package/dist/core/task/task-review-evidence.d.ts +27 -0
  193. package/dist/core/task/task-review-evidence.d.ts.map +1 -0
  194. package/dist/core/task/task-review-evidence.js +383 -0
  195. package/dist/core/task/task-review-evidence.js.map +1 -0
  196. package/dist/migrations/index.d.ts +1 -1
  197. package/dist/migrations/index.d.ts.map +1 -1
  198. package/dist/migrations/index.js +5 -3
  199. package/dist/migrations/index.js.map +1 -1
  200. package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
  201. package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
  202. package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
  203. package/dist/pactile/artifacts/documents.d.ts +72 -0
  204. package/dist/pactile/artifacts/documents.d.ts.map +1 -0
  205. package/dist/pactile/artifacts/documents.js +406 -0
  206. package/dist/pactile/artifacts/documents.js.map +1 -0
  207. package/dist/pactile/artifacts/index.d.ts +6 -0
  208. package/dist/pactile/artifacts/index.d.ts.map +1 -0
  209. package/dist/pactile/artifacts/index.js +6 -0
  210. package/dist/pactile/artifacts/index.js.map +1 -0
  211. package/dist/pactile/artifacts/projection.d.ts +50 -0
  212. package/dist/pactile/artifacts/projection.d.ts.map +1 -0
  213. package/dist/pactile/artifacts/projection.js +139 -0
  214. package/dist/pactile/artifacts/projection.js.map +1 -0
  215. package/dist/pactile/artifacts/reader.d.ts +20 -0
  216. package/dist/pactile/artifacts/reader.d.ts.map +1 -0
  217. package/dist/pactile/artifacts/reader.js +559 -0
  218. package/dist/pactile/artifacts/reader.js.map +1 -0
  219. package/dist/pactile/artifacts/schema.d.ts +4 -0
  220. package/dist/pactile/artifacts/schema.d.ts.map +1 -0
  221. package/dist/pactile/artifacts/schema.js +217 -0
  222. package/dist/pactile/artifacts/schema.js.map +1 -0
  223. package/dist/pactile/artifacts/types.d.ts +66 -0
  224. package/dist/pactile/artifacts/types.d.ts.map +1 -0
  225. package/dist/pactile/artifacts/types.js +45 -0
  226. package/dist/pactile/artifacts/types.js.map +1 -0
  227. package/dist/pactile/capabilities/claim.d.ts +3 -0
  228. package/dist/pactile/capabilities/claim.d.ts.map +1 -0
  229. package/dist/pactile/capabilities/claim.js +97 -0
  230. package/dist/pactile/capabilities/claim.js.map +1 -0
  231. package/dist/pactile/capabilities/command.d.ts +6 -0
  232. package/dist/pactile/capabilities/command.d.ts.map +1 -0
  233. package/dist/pactile/capabilities/command.js +253 -0
  234. package/dist/pactile/capabilities/command.js.map +1 -0
  235. package/dist/pactile/capabilities/discover.d.ts +6 -0
  236. package/dist/pactile/capabilities/discover.d.ts.map +1 -0
  237. package/dist/pactile/capabilities/discover.js +48 -0
  238. package/dist/pactile/capabilities/discover.js.map +1 -0
  239. package/dist/pactile/capabilities/node.d.ts +15 -0
  240. package/dist/pactile/capabilities/node.d.ts.map +1 -0
  241. package/dist/pactile/capabilities/node.js +292 -0
  242. package/dist/pactile/capabilities/node.js.map +1 -0
  243. package/dist/pactile/capabilities/read.d.ts +6 -0
  244. package/dist/pactile/capabilities/read.d.ts.map +1 -0
  245. package/dist/pactile/capabilities/read.js +100 -0
  246. package/dist/pactile/capabilities/read.js.map +1 -0
  247. package/dist/pactile/capabilities/receipts.d.ts +17 -0
  248. package/dist/pactile/capabilities/receipts.d.ts.map +1 -0
  249. package/dist/pactile/capabilities/receipts.js +90 -0
  250. package/dist/pactile/capabilities/receipts.js.map +1 -0
  251. package/dist/pactile/capabilities/search.d.ts +6 -0
  252. package/dist/pactile/capabilities/search.d.ts.map +1 -0
  253. package/dist/pactile/capabilities/search.js +181 -0
  254. package/dist/pactile/capabilities/search.js.map +1 -0
  255. package/dist/pactile/capabilities/shared.d.ts +29 -0
  256. package/dist/pactile/capabilities/shared.d.ts.map +1 -0
  257. package/dist/pactile/capabilities/shared.js +134 -0
  258. package/dist/pactile/capabilities/shared.js.map +1 -0
  259. package/dist/pactile/capabilities/workspace.d.ts +19 -0
  260. package/dist/pactile/capabilities/workspace.d.ts.map +1 -0
  261. package/dist/pactile/capabilities/workspace.js +273 -0
  262. package/dist/pactile/capabilities/workspace.js.map +1 -0
  263. package/dist/pactile/codex/bridge.d.ts +105 -2
  264. package/dist/pactile/codex/bridge.d.ts.map +1 -1
  265. package/dist/pactile/codex/bridge.js +1266 -92
  266. package/dist/pactile/codex/bridge.js.map +1 -1
  267. package/dist/pactile/codex/dispatch-stop-proof.d.ts +43 -0
  268. package/dist/pactile/codex/dispatch-stop-proof.d.ts.map +1 -0
  269. package/dist/pactile/codex/dispatch-stop-proof.js +177 -0
  270. package/dist/pactile/codex/dispatch-stop-proof.js.map +1 -0
  271. package/dist/pactile/codex/host-stop.d.ts +47 -0
  272. package/dist/pactile/codex/host-stop.d.ts.map +1 -0
  273. package/dist/pactile/codex/host-stop.js +344 -0
  274. package/dist/pactile/codex/host-stop.js.map +1 -0
  275. package/dist/pactile/coordination/index.d.ts +4 -0
  276. package/dist/pactile/coordination/index.d.ts.map +1 -0
  277. package/dist/pactile/coordination/index.js +4 -0
  278. package/dist/pactile/coordination/index.js.map +1 -0
  279. package/dist/pactile/coordination/journal.d.ts +10 -0
  280. package/dist/pactile/coordination/journal.d.ts.map +1 -0
  281. package/dist/pactile/coordination/journal.js +255 -0
  282. package/dist/pactile/coordination/journal.js.map +1 -0
  283. package/dist/pactile/coordination/kernel-resume.d.ts +8 -0
  284. package/dist/pactile/coordination/kernel-resume.d.ts.map +1 -0
  285. package/dist/pactile/coordination/kernel-resume.js +87 -0
  286. package/dist/pactile/coordination/kernel-resume.js.map +1 -0
  287. package/dist/pactile/coordination/model.d.ts +553 -0
  288. package/dist/pactile/coordination/model.d.ts.map +1 -0
  289. package/dist/pactile/coordination/model.js +239 -0
  290. package/dist/pactile/coordination/model.js.map +1 -0
  291. package/dist/pactile/coordination/state.d.ts +46 -0
  292. package/dist/pactile/coordination/state.d.ts.map +1 -0
  293. package/dist/pactile/coordination/state.js +301 -0
  294. package/dist/pactile/coordination/state.js.map +1 -0
  295. package/dist/pactile/coordination/store.d.ts +94 -0
  296. package/dist/pactile/coordination/store.d.ts.map +1 -0
  297. package/dist/pactile/coordination/store.js +396 -0
  298. package/dist/pactile/coordination/store.js.map +1 -0
  299. package/dist/pactile/index.d.ts +7 -1
  300. package/dist/pactile/index.d.ts.map +1 -1
  301. package/dist/pactile/index.js +7 -1
  302. package/dist/pactile/index.js.map +1 -1
  303. package/dist/pactile/jev/contracts.d.ts +104 -0
  304. package/dist/pactile/jev/contracts.d.ts.map +1 -0
  305. package/dist/pactile/jev/contracts.js +53 -0
  306. package/dist/pactile/jev/contracts.js.map +1 -0
  307. package/dist/pactile/jev/decision.d.ts +58 -0
  308. package/dist/pactile/jev/decision.d.ts.map +1 -0
  309. package/dist/pactile/jev/decision.js +149 -0
  310. package/dist/pactile/jev/decision.js.map +1 -0
  311. package/dist/pactile/jev/http.d.ts +25 -0
  312. package/dist/pactile/jev/http.d.ts.map +1 -0
  313. package/dist/pactile/jev/http.js +234 -0
  314. package/dist/pactile/jev/http.js.map +1 -0
  315. package/dist/pactile/jev/index.d.ts +8 -0
  316. package/dist/pactile/jev/index.d.ts.map +1 -0
  317. package/dist/pactile/jev/index.js +4 -0
  318. package/dist/pactile/jev/index.js.map +1 -0
  319. package/dist/pactile/jev/outbound.d.ts +15 -0
  320. package/dist/pactile/jev/outbound.d.ts.map +1 -0
  321. package/dist/pactile/jev/outbound.js +264 -0
  322. package/dist/pactile/jev/outbound.js.map +1 -0
  323. package/dist/pactile/jev/project-policy.d.ts +10 -0
  324. package/dist/pactile/jev/project-policy.d.ts.map +1 -0
  325. package/dist/pactile/jev/project-policy.js +53 -0
  326. package/dist/pactile/jev/project-policy.js.map +1 -0
  327. package/dist/pactile/jev/response.d.ts +17 -0
  328. package/dist/pactile/jev/response.d.ts.map +1 -0
  329. package/dist/pactile/jev/response.js +280 -0
  330. package/dist/pactile/jev/response.js.map +1 -0
  331. package/dist/pactile/jev/scheduler-advice.d.ts +92 -0
  332. package/dist/pactile/jev/scheduler-advice.d.ts.map +1 -0
  333. package/dist/pactile/jev/scheduler-advice.js +323 -0
  334. package/dist/pactile/jev/scheduler-advice.js.map +1 -0
  335. package/dist/pactile/jev/transport.d.ts +6 -0
  336. package/dist/pactile/jev/transport.d.ts.map +1 -0
  337. package/dist/pactile/jev/transport.js +87 -0
  338. package/dist/pactile/jev/transport.js.map +1 -0
  339. package/dist/pactile/lifecycle/deferred-live.d.ts +17 -0
  340. package/dist/pactile/lifecycle/deferred-live.d.ts.map +1 -0
  341. package/dist/pactile/lifecycle/deferred-live.js +173 -0
  342. package/dist/pactile/lifecycle/deferred-live.js.map +1 -0
  343. package/dist/pactile/lifecycle/legacy-import.d.ts +1 -1
  344. package/dist/pactile/lifecycle/legacy-import.js +3 -3
  345. package/dist/pactile/lifecycle/legacy-import.js.map +1 -1
  346. package/dist/pactile/lifecycle/project-files.d.ts.map +1 -1
  347. package/dist/pactile/lifecycle/project-files.js +1 -0
  348. package/dist/pactile/lifecycle/project-files.js.map +1 -1
  349. package/dist/pactile/migration/legacy-task-batch-generation.d.ts +23 -0
  350. package/dist/pactile/migration/legacy-task-batch-generation.d.ts.map +1 -0
  351. package/dist/pactile/migration/legacy-task-batch-generation.js +102 -0
  352. package/dist/pactile/migration/legacy-task-batch-generation.js.map +1 -0
  353. package/dist/pactile/migration/legacy-task-batch-io.d.ts +9 -0
  354. package/dist/pactile/migration/legacy-task-batch-io.d.ts.map +1 -0
  355. package/dist/pactile/migration/legacy-task-batch-io.js +208 -0
  356. package/dist/pactile/migration/legacy-task-batch-io.js.map +1 -0
  357. package/dist/pactile/migration/legacy-task-batch-journal.d.ts +6 -0
  358. package/dist/pactile/migration/legacy-task-batch-journal.d.ts.map +1 -0
  359. package/dist/pactile/migration/legacy-task-batch-journal.js +121 -0
  360. package/dist/pactile/migration/legacy-task-batch-journal.js.map +1 -0
  361. package/dist/pactile/migration/legacy-task-batch-orchestrator.d.ts +18 -0
  362. package/dist/pactile/migration/legacy-task-batch-orchestrator.d.ts.map +1 -0
  363. package/dist/pactile/migration/legacy-task-batch-orchestrator.js +634 -0
  364. package/dist/pactile/migration/legacy-task-batch-orchestrator.js.map +1 -0
  365. package/dist/pactile/migration/legacy-task-batch-source.d.ts +8 -0
  366. package/dist/pactile/migration/legacy-task-batch-source.d.ts.map +1 -0
  367. package/dist/pactile/migration/legacy-task-batch-source.js +158 -0
  368. package/dist/pactile/migration/legacy-task-batch-source.js.map +1 -0
  369. package/dist/pactile/migration/legacy-task-batch-types.d.ts +127 -0
  370. package/dist/pactile/migration/legacy-task-batch-types.d.ts.map +1 -0
  371. package/dist/pactile/migration/legacy-task-batch-types.js +127 -0
  372. package/dist/pactile/migration/legacy-task-batch-types.js.map +1 -0
  373. package/dist/pactile/migration/legacy-task-batch.d.ts +3 -0
  374. package/dist/pactile/migration/legacy-task-batch.d.ts.map +1 -0
  375. package/dist/pactile/migration/legacy-task-batch.js +2 -0
  376. package/dist/pactile/migration/legacy-task-batch.js.map +1 -0
  377. package/dist/pactile/migration/legacy-task-held-source-reader.d.ts +27 -0
  378. package/dist/pactile/migration/legacy-task-held-source-reader.d.ts.map +1 -0
  379. package/dist/pactile/migration/legacy-task-held-source-reader.js +261 -0
  380. package/dist/pactile/migration/legacy-task-held-source-reader.js.map +1 -0
  381. package/dist/pactile/migration/legacy-task-reconciliation.d.ts +46 -0
  382. package/dist/pactile/migration/legacy-task-reconciliation.d.ts.map +1 -0
  383. package/dist/pactile/migration/legacy-task-reconciliation.js +589 -0
  384. package/dist/pactile/migration/legacy-task-reconciliation.js.map +1 -0
  385. package/dist/pactile/migration/legacy-task-update.d.ts +19 -0
  386. package/dist/pactile/migration/legacy-task-update.d.ts.map +1 -0
  387. package/dist/pactile/migration/legacy-task-update.js +164 -0
  388. package/dist/pactile/migration/legacy-task-update.js.map +1 -0
  389. package/dist/pactile/parallel/batch.d.ts +21 -2
  390. package/dist/pactile/parallel/batch.d.ts.map +1 -1
  391. package/dist/pactile/parallel/batch.js +271 -50
  392. package/dist/pactile/parallel/batch.js.map +1 -1
  393. package/dist/pactile/parallel/policy.d.ts +1 -1
  394. package/dist/pactile/parallel/policy.d.ts.map +1 -1
  395. package/dist/pactile/parallel/policy.js +130 -102
  396. package/dist/pactile/parallel/policy.js.map +1 -1
  397. package/dist/pactile/pi/bridge.d.ts +139 -2
  398. package/dist/pactile/pi/bridge.d.ts.map +1 -1
  399. package/dist/pactile/pi/bridge.js +1317 -106
  400. package/dist/pactile/pi/bridge.js.map +1 -1
  401. package/dist/pactile/pi/rpc.d.ts +23 -4
  402. package/dist/pactile/pi/rpc.d.ts.map +1 -1
  403. package/dist/pactile/pi/rpc.js +243 -42
  404. package/dist/pactile/pi/rpc.js.map +1 -1
  405. package/dist/pactile/pi/v2-dispatch.d.ts +113 -0
  406. package/dist/pactile/pi/v2-dispatch.d.ts.map +1 -0
  407. package/dist/pactile/pi/v2-dispatch.js +919 -0
  408. package/dist/pactile/pi/v2-dispatch.js.map +1 -0
  409. package/dist/pactile/projection/planner.js +1 -1
  410. package/dist/pactile/projection/planner.js.map +1 -1
  411. package/dist/pactile/registry.d.ts +63 -1
  412. package/dist/pactile/registry.d.ts.map +1 -1
  413. package/dist/pactile/registry.js +633 -4
  414. package/dist/pactile/registry.js.map +1 -1
  415. package/dist/pactile/retrieval/index.d.ts +1 -0
  416. package/dist/pactile/retrieval/index.d.ts.map +1 -1
  417. package/dist/pactile/retrieval/index.js +1 -0
  418. package/dist/pactile/retrieval/index.js.map +1 -1
  419. package/dist/pactile/retrieval/jev-planning.d.ts +28 -0
  420. package/dist/pactile/retrieval/jev-planning.d.ts.map +1 -0
  421. package/dist/pactile/retrieval/jev-planning.js +96 -0
  422. package/dist/pactile/retrieval/jev-planning.js.map +1 -0
  423. package/dist/pactile/review/contract.d.ts +232 -0
  424. package/dist/pactile/review/contract.d.ts.map +1 -0
  425. package/dist/pactile/review/contract.js +695 -0
  426. package/dist/pactile/review/contract.js.map +1 -0
  427. package/dist/pactile/review/escalation-artifacts.d.ts +41 -0
  428. package/dist/pactile/review/escalation-artifacts.d.ts.map +1 -0
  429. package/dist/pactile/review/escalation-artifacts.js +415 -0
  430. package/dist/pactile/review/escalation-artifacts.js.map +1 -0
  431. package/dist/pactile/review/escalation-contract.d.ts +115 -0
  432. package/dist/pactile/review/escalation-contract.d.ts.map +1 -0
  433. package/dist/pactile/review/escalation-contract.js +151 -0
  434. package/dist/pactile/review/escalation-contract.js.map +1 -0
  435. package/dist/pactile/review/escalation-finalize.d.ts +14 -0
  436. package/dist/pactile/review/escalation-finalize.d.ts.map +1 -0
  437. package/dist/pactile/review/escalation-finalize.js +319 -0
  438. package/dist/pactile/review/escalation-finalize.js.map +1 -0
  439. package/dist/pactile/review/escalation-reply.d.ts +10 -0
  440. package/dist/pactile/review/escalation-reply.d.ts.map +1 -0
  441. package/dist/pactile/review/escalation-reply.js +61 -0
  442. package/dist/pactile/review/escalation-reply.js.map +1 -0
  443. package/dist/pactile/review/escalation-transport.d.ts +32 -0
  444. package/dist/pactile/review/escalation-transport.d.ts.map +1 -0
  445. package/dist/pactile/review/escalation-transport.js +216 -0
  446. package/dist/pactile/review/escalation-transport.js.map +1 -0
  447. package/dist/pactile/review/escalation.d.ts +7 -0
  448. package/dist/pactile/review/escalation.d.ts.map +1 -0
  449. package/dist/pactile/review/escalation.js +6 -0
  450. package/dist/pactile/review/escalation.js.map +1 -0
  451. package/dist/pactile/review/evidence.d.ts +25 -0
  452. package/dist/pactile/review/evidence.d.ts.map +1 -0
  453. package/dist/pactile/review/evidence.js +58 -0
  454. package/dist/pactile/review/evidence.js.map +1 -0
  455. package/dist/pactile/review/jev-escalation-advice.d.ts +77 -0
  456. package/dist/pactile/review/jev-escalation-advice.d.ts.map +1 -0
  457. package/dist/pactile/review/jev-escalation-advice.js +358 -0
  458. package/dist/pactile/review/jev-escalation-advice.js.map +1 -0
  459. package/dist/pactile/scheduler/index.d.ts +6 -0
  460. package/dist/pactile/scheduler/index.d.ts.map +1 -0
  461. package/dist/pactile/scheduler/index.js +5 -0
  462. package/dist/pactile/scheduler/index.js.map +1 -0
  463. package/dist/pactile/scheduler/project-lease-store.d.ts +35 -0
  464. package/dist/pactile/scheduler/project-lease-store.d.ts.map +1 -0
  465. package/dist/pactile/scheduler/project-lease-store.js +189 -0
  466. package/dist/pactile/scheduler/project-lease-store.js.map +1 -0
  467. package/dist/pactile/scheduler/scheduler.d.ts +91 -0
  468. package/dist/pactile/scheduler/scheduler.d.ts.map +1 -0
  469. package/dist/pactile/scheduler/scheduler.js +589 -0
  470. package/dist/pactile/scheduler/scheduler.js.map +1 -0
  471. package/dist/pactile/scheduler/task-kernel-admission.d.ts +173 -0
  472. package/dist/pactile/scheduler/task-kernel-admission.d.ts.map +1 -0
  473. package/dist/pactile/scheduler/task-kernel-admission.js +1560 -0
  474. package/dist/pactile/scheduler/task-kernel-admission.js.map +1 -0
  475. package/dist/pactile/scheduler/task-kernel-wave-dispatch.d.ts +184 -0
  476. package/dist/pactile/scheduler/task-kernel-wave-dispatch.d.ts.map +1 -0
  477. package/dist/pactile/scheduler/task-kernel-wave-dispatch.js +952 -0
  478. package/dist/pactile/scheduler/task-kernel-wave-dispatch.js.map +1 -0
  479. package/dist/pactile/scheduler/task-map-scheduler.d.ts +116 -0
  480. package/dist/pactile/scheduler/task-map-scheduler.d.ts.map +1 -0
  481. package/dist/pactile/scheduler/task-map-scheduler.js +1448 -0
  482. package/dist/pactile/scheduler/task-map-scheduler.js.map +1 -0
  483. package/dist/pactile/scheduler/task-run-dispatch-state.d.ts +7 -0
  484. package/dist/pactile/scheduler/task-run-dispatch-state.d.ts.map +1 -0
  485. package/dist/pactile/scheduler/task-run-dispatch-state.js +69 -0
  486. package/dist/pactile/scheduler/task-run-dispatch-state.js.map +1 -0
  487. package/dist/pactile/task/authorization.d.ts +3 -0
  488. package/dist/pactile/task/authorization.d.ts.map +1 -0
  489. package/dist/pactile/task/authorization.js +43 -0
  490. package/dist/pactile/task/authorization.js.map +1 -0
  491. package/dist/pactile/task/creation.d.ts +22 -0
  492. package/dist/pactile/task/creation.d.ts.map +1 -0
  493. package/dist/pactile/task/creation.js +95 -0
  494. package/dist/pactile/task/creation.js.map +1 -0
  495. package/dist/pactile/task/guards.d.ts +1 -4
  496. package/dist/pactile/task/guards.d.ts.map +1 -1
  497. package/dist/pactile/task/guards.js +5 -57
  498. package/dist/pactile/task/guards.js.map +1 -1
  499. package/dist/pactile/task/session-jev-receipt.d.ts +58 -0
  500. package/dist/pactile/task/session-jev-receipt.d.ts.map +1 -0
  501. package/dist/pactile/task/session-jev-receipt.js +375 -0
  502. package/dist/pactile/task/session-jev-receipt.js.map +1 -0
  503. package/dist/pactile/task/session-jev.d.ts +7 -0
  504. package/dist/pactile/task/session-jev.d.ts.map +1 -0
  505. package/dist/pactile/task/session-jev.js +217 -0
  506. package/dist/pactile/task/session-jev.js.map +1 -0
  507. package/dist/pactile/task/session-pack.d.ts.map +1 -1
  508. package/dist/pactile/task/session-pack.js +155 -16
  509. package/dist/pactile/task/session-pack.js.map +1 -1
  510. package/dist/pactile/task/session-retrieval-jev-receipt.d.ts +49 -0
  511. package/dist/pactile/task/session-retrieval-jev-receipt.d.ts.map +1 -0
  512. package/dist/pactile/task/session-retrieval-jev-receipt.js +97 -0
  513. package/dist/pactile/task/session-retrieval-jev-receipt.js.map +1 -0
  514. package/dist/pactile/task/session-retrieval-jev.d.ts +8 -0
  515. package/dist/pactile/task/session-retrieval-jev.d.ts.map +1 -0
  516. package/dist/pactile/task/session-retrieval-jev.js +352 -0
  517. package/dist/pactile/task/session-retrieval-jev.js.map +1 -0
  518. package/dist/pactile/task/strategy.d.ts +1 -23
  519. package/dist/pactile/task/strategy.d.ts.map +1 -1
  520. package/dist/pactile/task/strategy.js +2 -135
  521. package/dist/pactile/task/strategy.js.map +1 -1
  522. package/dist/pactile/tiles/jev-selection.d.ts +44 -0
  523. package/dist/pactile/tiles/jev-selection.d.ts.map +1 -0
  524. package/dist/pactile/tiles/jev-selection.js +210 -0
  525. package/dist/pactile/tiles/jev-selection.js.map +1 -0
  526. package/dist/pactile/tiles/safe-yaml.d.ts +5 -1
  527. package/dist/pactile/tiles/safe-yaml.d.ts.map +1 -1
  528. package/dist/pactile/tiles/safe-yaml.js +8 -8
  529. package/dist/pactile/tiles/safe-yaml.js.map +1 -1
  530. package/dist/pactile/tiles/selection-receipts.d.ts +71 -0
  531. package/dist/pactile/tiles/selection-receipts.d.ts.map +1 -0
  532. package/dist/pactile/tiles/selection-receipts.js +319 -0
  533. package/dist/pactile/tiles/selection-receipts.js.map +1 -0
  534. package/dist/pactile/tiles/selection.d.ts +185 -0
  535. package/dist/pactile/tiles/selection.d.ts.map +1 -0
  536. package/dist/pactile/tiles/selection.js +985 -0
  537. package/dist/pactile/tiles/selection.js.map +1 -0
  538. package/dist/pactile/verification/git-observer.d.ts +3 -0
  539. package/dist/pactile/verification/git-observer.d.ts.map +1 -0
  540. package/dist/pactile/verification/git-observer.js +3 -0
  541. package/dist/pactile/verification/git-observer.js.map +1 -0
  542. package/dist/pactile/verification/index.d.ts +11 -0
  543. package/dist/pactile/verification/index.d.ts.map +1 -0
  544. package/dist/pactile/verification/index.js +6 -0
  545. package/dist/pactile/verification/index.js.map +1 -0
  546. package/dist/pactile/verification/jev-advice.d.ts +78 -0
  547. package/dist/pactile/verification/jev-advice.d.ts.map +1 -0
  548. package/dist/pactile/verification/jev-advice.js +397 -0
  549. package/dist/pactile/verification/jev-advice.js.map +1 -0
  550. package/dist/pactile/verification/planner.d.ts +15 -0
  551. package/dist/pactile/verification/planner.d.ts.map +1 -0
  552. package/dist/pactile/verification/planner.js +412 -0
  553. package/dist/pactile/verification/planner.js.map +1 -0
  554. package/dist/pactile/verification/receipt.d.ts +101 -0
  555. package/dist/pactile/verification/receipt.d.ts.map +1 -0
  556. package/dist/pactile/verification/receipt.js +400 -0
  557. package/dist/pactile/verification/receipt.js.map +1 -0
  558. package/dist/pactile/verification/types.d.ts +72 -0
  559. package/dist/pactile/verification/types.d.ts.map +1 -0
  560. package/dist/pactile/verification/types.js +21 -0
  561. package/dist/pactile/verification/types.js.map +1 -0
  562. package/dist/pactile/worktree/git-probe.d.ts +32 -0
  563. package/dist/pactile/worktree/git-probe.d.ts.map +1 -0
  564. package/dist/pactile/worktree/git-probe.js +336 -0
  565. package/dist/pactile/worktree/git-probe.js.map +1 -0
  566. package/dist/pactile/worktree/git-removal.d.ts +3 -0
  567. package/dist/pactile/worktree/git-removal.d.ts.map +1 -0
  568. package/dist/pactile/worktree/git-removal.js +11 -0
  569. package/dist/pactile/worktree/git-removal.js.map +1 -0
  570. package/dist/pactile/worktree/index.d.ts +2 -0
  571. package/dist/pactile/worktree/index.d.ts.map +1 -0
  572. package/dist/pactile/worktree/index.js +2 -0
  573. package/dist/pactile/worktree/index.js.map +1 -0
  574. package/dist/pactile/worktree/integration-evidence.d.ts +80 -0
  575. package/dist/pactile/worktree/integration-evidence.d.ts.map +1 -0
  576. package/dist/pactile/worktree/integration-evidence.js +166 -0
  577. package/dist/pactile/worktree/integration-evidence.js.map +1 -0
  578. package/dist/pactile/worktree/manager-core.d.ts +50 -0
  579. package/dist/pactile/worktree/manager-core.d.ts.map +1 -0
  580. package/dist/pactile/worktree/manager-core.js +359 -0
  581. package/dist/pactile/worktree/manager-core.js.map +1 -0
  582. package/dist/pactile/worktree/manager-provenance.d.ts +32 -0
  583. package/dist/pactile/worktree/manager-provenance.d.ts.map +1 -0
  584. package/dist/pactile/worktree/manager-provenance.js +409 -0
  585. package/dist/pactile/worktree/manager-provenance.js.map +1 -0
  586. package/dist/pactile/worktree/manager-types.d.ts +84 -0
  587. package/dist/pactile/worktree/manager-types.d.ts.map +1 -0
  588. package/dist/pactile/worktree/manager-types.js +11 -0
  589. package/dist/pactile/worktree/manager-types.js.map +1 -0
  590. package/dist/pactile/worktree/manager.d.ts +10 -0
  591. package/dist/pactile/worktree/manager.d.ts.map +1 -0
  592. package/dist/pactile/worktree/manager.js +6 -0
  593. package/dist/pactile/worktree/manager.js.map +1 -0
  594. package/dist/pactile/worktree/run-workspace-cleanup.d.ts +10 -0
  595. package/dist/pactile/worktree/run-workspace-cleanup.d.ts.map +1 -0
  596. package/dist/pactile/worktree/run-workspace-cleanup.js +695 -0
  597. package/dist/pactile/worktree/run-workspace-cleanup.js.map +1 -0
  598. package/dist/pactile/worktree/run-workspace-lifecycle.d.ts +65 -0
  599. package/dist/pactile/worktree/run-workspace-lifecycle.d.ts.map +1 -0
  600. package/dist/pactile/worktree/run-workspace-lifecycle.js +276 -0
  601. package/dist/pactile/worktree/run-workspace-lifecycle.js.map +1 -0
  602. package/dist/templates/common/bundled-skills/pactile-meta/references/customize-local/change-hooks.md +1 -1
  603. package/dist/templates/common/bundled-skills/pactile-meta/references/local-architecture/generated-files.md +1 -1
  604. package/dist/templates/common/bundled-skills/pactile-meta/references/platform-files/hooks-and-settings.md +1 -1
  605. package/dist/templates/common/bundled-skills/pactile-meta/references/platform-files/overview.md +1 -1
  606. package/dist/templates/common/bundled-skills/pactile-meta/references/platform-files/platform-map.md +1 -1
  607. package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +2 -0
  608. package/dist/templates/common/skills/brainstorm.md +19 -13
  609. package/dist/templates/markdown/agents.md +2 -2
  610. package/dist/templates/markdown/framework/execution-strategy.md.txt +1 -1
  611. package/dist/templates/markdown/framework/index.md.txt +1 -1
  612. package/dist/templates/markdown/framework/parallel-first-execution.md.txt +17 -105
  613. package/dist/templates/markdown/framework/prd-grill-frontier.md.txt +3 -3
  614. package/dist/templates/markdown/framework/release-boundary.md.txt +9 -10
  615. package/dist/templates/markdown/framework/retrieval-daily-guide.md.txt +1 -1
  616. package/dist/templates/pactile/CONTEXT.md +48 -36
  617. package/dist/templates/pactile/modules/approval-personal/contract.md +12 -24
  618. package/dist/templates/pactile/modules/close-basic/contract.md +15 -18
  619. package/dist/templates/pactile/modules/debug-recovery/contract.md +4 -4
  620. package/dist/templates/pactile/modules/define-basic/contract.md +15 -19
  621. package/dist/templates/pactile/modules/define-extended/contract.md +3 -3
  622. package/dist/templates/pactile/modules/execute-agent/contract.md +11 -19
  623. package/dist/templates/pactile/modules/intake-basic/contract.md +16 -13
  624. package/dist/templates/pactile/modules/verify-basic/contract.md +11 -20
  625. package/dist/templates/pactile/tasks/templates/release-execution/design.md +5 -5
  626. package/dist/templates/pactile/tasks/templates/release-readiness/design.md +6 -6
  627. package/dist/templates/pactile/tasks/templates/release-readiness/handoff-template.md +8 -2
  628. package/dist/templates/pactile/workflow.md +37 -41
  629. package/dist/templates/template-utils.d.ts +1 -2
  630. package/dist/templates/template-utils.d.ts.map +1 -1
  631. package/dist/templates/template-utils.js +2 -13
  632. package/dist/templates/template-utils.js.map +1 -1
  633. package/dist/types/ai-tools.d.ts +1 -1
  634. package/dist/types/ai-tools.js +1 -1
  635. package/dist/utils/manifest-prune.js +1 -1
  636. package/dist/utils/manifest-prune.js.map +1 -1
  637. package/dist/utils/p36-upgrade.d.ts +2 -2
  638. package/dist/utils/p36-upgrade.d.ts.map +1 -1
  639. package/dist/utils/p36-upgrade.js +2 -10
  640. package/dist/utils/p36-upgrade.js.map +1 -1
  641. package/dist/utils/post-update-smoke.js +1 -1
  642. package/dist/utils/post-update-smoke.js.map +1 -1
  643. package/dist/utils/readiness.d.ts +2 -2
  644. package/dist/utils/readiness.js +2 -2
  645. package/dist/utils/uninstall-scrubbers.js +1 -1
  646. package/dist/utils/workflow-dir.d.ts +1 -1
  647. package/dist/utils/workflow-dir.d.ts.map +1 -1
  648. package/dist/utils/workflow-dir.js +1 -1
  649. package/dist/utils/workflow-dir.js.map +1 -1
  650. package/package.json +42 -37
  651. package/CHANGELOG.md +0 -651
  652. package/bin/compat-warning.js +0 -11
  653. package/bin/pactile.js +0 -3
  654. package/bin/smart-search.js +0 -38
  655. package/dist/migrations/manifests/0.1.0.json +0 -9
  656. package/dist/migrations/manifests/0.1.1.json +0 -9
  657. package/dist/migrations/manifests/0.1.2.json +0 -9
  658. package/dist/migrations/manifests/0.1.3.json +0 -9
  659. package/dist/migrations/manifests/0.1.4.json +0 -9
  660. package/dist/migrations/manifests/0.2.1.json +0 -9
  661. package/dist/migrations/manifests/0.2.10.json +0 -374
  662. package/dist/migrations/manifests/0.2.2.json +0 -9
  663. package/dist/migrations/manifests/0.2.3.json +0 -9
  664. package/dist/migrations/manifests/0.2.4.json +0 -9
  665. package/dist/migrations/manifests/0.2.5.json +0 -9
  666. package/dist/migrations/manifests/0.2.6.json +0 -9
  667. package/dist/migrations/manifests/0.2.7.json +0 -9
  668. package/dist/migrations/manifests/0.2.8.json +0 -9
  669. package/dist/migrations/manifests/0.2.9.json +0 -9
  670. package/dist/migrations/manifests/0.3.0.json +0 -89
  671. package/dist/migrations/manifests/0.3.1.json +0 -32
  672. package/dist/migrations/manifests/0.3.2.json +0 -16
  673. package/dist/migrations/manifests/0.3.3.json +0 -9
  674. package/dist/migrations/manifests/0.3.4.json +0 -9
  675. package/dist/migrations/manifests/0.3.5.json +0 -9
  676. package/dist/migrations/manifests/0.3.6.json +0 -9
  677. package/dist/migrations/manifests/0.4.0.json +0 -9
  678. package/dist/migrations/manifests/0.4.1.json +0 -9
  679. package/dist/migrations/manifests/0.4.2.json +0 -9
  680. package/dist/migrations/manifests/0.4.3.json +0 -9
  681. package/dist/migrations/manifests/0.5.0-beta.0.json +0 -9
  682. package/dist/migrations/manifests/0.5.0-beta.1.json +0 -9
  683. package/dist/migrations/manifests/0.5.0-beta.2.json +0 -9
  684. package/dist/migrations/manifests/0.5.0-beta.3.json +0 -9
  685. package/dist/migrations/manifests/0.5.0-beta.4.json +0 -9
  686. package/dist/migrations/manifests/0.5.0-beta.5.json +0 -9
  687. package/dist/migrations/manifests/0.5.0.json +0 -9
  688. package/dist/pactile/compat/retired-alternate-client.d.ts +0 -42
  689. package/dist/pactile/compat/retired-alternate-client.d.ts.map +0 -1
  690. package/dist/pactile/compat/retired-alternate-client.js +0 -153
  691. package/dist/pactile/compat/retired-alternate-client.js.map +0 -1
  692. package/dist/pactile/compat/update-residue.d.ts +0 -4
  693. package/dist/pactile/compat/update-residue.d.ts.map +0 -1
  694. package/dist/pactile/compat/update-residue.js +0 -55
  695. package/dist/pactile/compat/update-residue.js.map +0 -1
  696. package/dist/utils/cursor-retrieval-env.d.ts +0 -17
  697. package/dist/utils/cursor-retrieval-env.d.ts.map +0 -1
  698. package/dist/utils/cursor-retrieval-env.js +0 -19
  699. package/dist/utils/cursor-retrieval-env.js.map +0 -1
  700. package/dist/utils/proxy.d.ts +0 -25
  701. package/dist/utils/proxy.d.ts.map +0 -1
  702. package/dist/utils/proxy.js +0 -60
  703. package/dist/utils/proxy.js.map +0 -1
  704. package/scripts/postinstall.js +0 -6
@@ -0,0 +1,1560 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fingerprintTaskValue, projectTaskKernelLifecycle, readTaskKernel, } from "../../core/task/index.js";
5
+ import { resolveTaskDirectoryById } from "../../core/task/task-kernel-paths.js";
6
+ import { resolveTaskDir } from "../task/session.js";
7
+ import { CoordinationError, readCoordinationSnapshot, } from "../coordination/index.js";
8
+ import { withCoordinationJournalLock } from "../coordination/journal.js";
9
+ import { readTaskKernelScheduleReceiptV1, } from "./task-map-scheduler.js";
10
+ import { listProjectWriteLeases, normalizeProjectWriteSet, projectActiveLeasePath, projectLeaseHistoryPath, projectWriteSetsConflict, withProjectSchedulerMutex, } from "./project-lease-store.js";
11
+ const ADMISSION_SCHEMA_VERSION = 1;
12
+ const STOP_PROOF_SCOPE = "task-kernel-v2-run-dispatch-stop";
13
+ const PI_RUN_OUTCOMES = [
14
+ "settled",
15
+ "needs_review",
16
+ "failed",
17
+ "cancelled",
18
+ "timed_out",
19
+ "interrupted",
20
+ ];
21
+ export function readPiRunSettlementSealV1(runRecord) {
22
+ const outcome = runRecord.outcome;
23
+ const toolErrors = runRecord.tool_errors;
24
+ const startedAt = runRecord.started_at;
25
+ const endedAt = runRecord.ended_at;
26
+ const elapsedMs = runRecord.elapsed_ms;
27
+ const resultFile = runRecord.result_file;
28
+ const resultSha256 = runRecord.result_sha256;
29
+ if (typeof outcome !== "string" ||
30
+ !PI_RUN_OUTCOMES.includes(outcome) ||
31
+ typeof toolErrors !== "number" ||
32
+ !Number.isSafeInteger(toolErrors) ||
33
+ toolErrors < 0 ||
34
+ typeof startedAt !== "string" ||
35
+ !Number.isFinite(Date.parse(startedAt)) ||
36
+ typeof endedAt !== "string" ||
37
+ !Number.isFinite(Date.parse(endedAt)) ||
38
+ typeof elapsedMs !== "number" ||
39
+ !Number.isSafeInteger(elapsedMs) ||
40
+ elapsedMs < 0 ||
41
+ (typeof resultFile !== "string" && resultFile !== null) ||
42
+ (typeof resultFile === "string" && !resultFile.trim()) ||
43
+ (typeof resultSha256 !== "string" && resultSha256 !== null) ||
44
+ (typeof resultSha256 === "string" && !/^[a-f0-9]{64}$/u.test(resultSha256)) ||
45
+ (resultFile === null) !== (resultSha256 === null)) {
46
+ return null;
47
+ }
48
+ return {
49
+ outcome,
50
+ tool_errors: toolErrors,
51
+ started_at: startedAt,
52
+ ended_at: endedAt,
53
+ elapsed_ms: elapsedMs,
54
+ result_file: resultFile,
55
+ result_sha256: resultSha256,
56
+ };
57
+ }
58
+ function relative(root, file) {
59
+ return path.relative(root, file).replaceAll("\\", "/");
60
+ }
61
+ function decisionFingerprint(base) {
62
+ return fingerprintTaskValue(base);
63
+ }
64
+ function persistDecisionReceipt(root, base) {
65
+ const fingerprint = decisionFingerprint(base);
66
+ const folder = path.join(root, ".pactile", ".runtime", "scheduler", "admissions");
67
+ const file = path.join(folder, `${fingerprint}.json`);
68
+ fs.mkdirSync(folder, { recursive: true });
69
+ if (fs.existsSync(file)) {
70
+ const value = JSON.parse(fs.readFileSync(file, "utf8"));
71
+ if (!value || typeof value !== "object" || Array.isArray(value))
72
+ throw new Error("Invalid Task Run admission receipt");
73
+ const receipt = value;
74
+ const { schemaVersion, scope, receiptFingerprint, createdAt: _createdAt, ...storedBase } = receipt;
75
+ if (schemaVersion !== ADMISSION_SCHEMA_VERSION ||
76
+ scope !== "task-kernel-v2-run-admission" ||
77
+ receiptFingerprint !== fingerprint ||
78
+ fingerprintTaskValue(storedBase) !== fingerprint) {
79
+ throw new Error("Task Run admission receipt fingerprint does not match its contents");
80
+ }
81
+ return { receipt, file };
82
+ }
83
+ const receipt = {
84
+ ...base,
85
+ schemaVersion: ADMISSION_SCHEMA_VERSION,
86
+ scope: "task-kernel-v2-run-admission",
87
+ receiptFingerprint: fingerprint,
88
+ createdAt: new Date().toISOString(),
89
+ };
90
+ const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
91
+ try {
92
+ fs.writeFileSync(temporary, `${JSON.stringify(receipt, null, 2)}\n`, {
93
+ flag: "wx",
94
+ mode: 0o600,
95
+ });
96
+ try {
97
+ fs.copyFileSync(temporary, file, fs.constants.COPYFILE_EXCL);
98
+ return { receipt, file };
99
+ }
100
+ catch (error) {
101
+ if (error.code !== "EEXIST")
102
+ throw error;
103
+ return persistDecisionReceipt(root, base);
104
+ }
105
+ }
106
+ finally {
107
+ fs.rmSync(temporary, { force: true });
108
+ }
109
+ }
110
+ function readTaskKernelScheduleReceipt(root, fingerprint) {
111
+ if (!/^[a-f0-9]{64}$/.test(fingerprint))
112
+ throw new Error("invalid-schedule-receipt-fingerprint");
113
+ try {
114
+ return readTaskKernelScheduleReceiptV1(root, fingerprint).receipt;
115
+ }
116
+ catch (error) {
117
+ const message = error instanceof Error ? error.message : String(error);
118
+ if (message.includes("fingerprint does not match"))
119
+ throw new Error("schedule-receipt-integrity-failed");
120
+ if (message.includes("not found"))
121
+ throw new Error("schedule-receipt-not-found");
122
+ throw new Error("invalid-schedule-receipt");
123
+ }
124
+ }
125
+ function lifecycleFor(receipt, taskId) {
126
+ return receipt.lifecycle.find((item) => item.taskId === taskId);
127
+ }
128
+ function nonEmptyAuthorization(run) {
129
+ return [
130
+ run.authorization.approvedBy,
131
+ run.authorization.approvedAt,
132
+ run.authorization.scope,
133
+ run.authorization.evidenceRef,
134
+ ].every((value) => typeof value === "string" && !!value.trim());
135
+ }
136
+ function readRunHost(run) {
137
+ if (!run.host)
138
+ return null;
139
+ const host = run.host;
140
+ return {
141
+ host: host.host,
142
+ role: host.role,
143
+ sessionId: host.sessionId,
144
+ threadId: host.threadId,
145
+ hostId: typeof host.hostId === "string"
146
+ ? host.hostId
147
+ : typeof host.host_id === "string"
148
+ ? host.host_id
149
+ : null,
150
+ contractFingerprint: host.contractFingerprint,
151
+ startRequestId: typeof host.startRequestId === "string"
152
+ ? host.startRequestId
153
+ : typeof host.start_request_id === "string"
154
+ ? host.start_request_id
155
+ : null,
156
+ processId: typeof host.processId === "number"
157
+ ? host.processId
158
+ : typeof host.process_id === "number"
159
+ ? host.process_id
160
+ : null,
161
+ };
162
+ }
163
+ function validOwner(value) {
164
+ if (!value || typeof value !== "object" || Array.isArray(value))
165
+ return false;
166
+ const owner = value;
167
+ return (typeof owner.host === "string" &&
168
+ !!owner.host.trim() &&
169
+ typeof owner.role === "string" &&
170
+ !!owner.role.trim() &&
171
+ (owner.sessionId === null || typeof owner.sessionId === "string") &&
172
+ (owner.threadId === null || typeof owner.threadId === "string") &&
173
+ (owner.hostId === null || typeof owner.hostId === "string") &&
174
+ (owner.contractFingerprint === undefined ||
175
+ owner.contractFingerprint === null ||
176
+ typeof owner.contractFingerprint === "string") &&
177
+ (owner.startRequestId === undefined ||
178
+ owner.startRequestId === null ||
179
+ typeof owner.startRequestId === "string") &&
180
+ (owner.processId === undefined ||
181
+ owner.processId === null ||
182
+ (typeof owner.processId === "number" &&
183
+ Number.isSafeInteger(owner.processId) &&
184
+ owner.processId > 0)));
185
+ }
186
+ function normalizeOwner(value) {
187
+ if (!validOwner(value))
188
+ return null;
189
+ return {
190
+ host: value.host,
191
+ role: value.role,
192
+ sessionId: value.sessionId,
193
+ threadId: value.threadId,
194
+ hostId: value.hostId,
195
+ contractFingerprint: value.contractFingerprint ?? null,
196
+ startRequestId: value.startRequestId ?? null,
197
+ processId: value.processId ?? null,
198
+ };
199
+ }
200
+ function sameOwner(left, right) {
201
+ return JSON.stringify(left) === JSON.stringify(right);
202
+ }
203
+ function ownersCompatible(left, right) {
204
+ return (left.host === right.host &&
205
+ left.role === right.role &&
206
+ left.sessionId === right.sessionId &&
207
+ left.threadId === right.threadId &&
208
+ left.hostId === right.hostId &&
209
+ (left.startRequestId === null ||
210
+ right.startRequestId === null ||
211
+ left.startRequestId === right.startRequestId) &&
212
+ (left.processId === null ||
213
+ right.processId === null ||
214
+ left.processId === right.processId) &&
215
+ (left.contractFingerprint === null ||
216
+ right.contractFingerprint === null ||
217
+ left.contractFingerprint === right.contractFingerprint));
218
+ }
219
+ function ownerCanBind(previous, next) {
220
+ const mayFill = (oldValue, newValue) => oldValue === null || oldValue === undefined || oldValue === newValue;
221
+ return (previous.host === next.host &&
222
+ previous.role === next.role &&
223
+ mayFill(previous.sessionId, next.sessionId) &&
224
+ mayFill(previous.threadId, next.threadId) &&
225
+ mayFill(previous.hostId, next.hostId) &&
226
+ mayFill(previous.startRequestId, next.startRequestId) &&
227
+ mayFill(previous.processId, next.processId) &&
228
+ (previous.contractFingerprint === null ||
229
+ previous.contractFingerprint === undefined ||
230
+ previous.contractFingerprint === next.contractFingerprint));
231
+ }
232
+ function runHostMatchesOwner(run, owner) {
233
+ const host = run.host;
234
+ if (!host)
235
+ return false;
236
+ const observed = readRunHost(run);
237
+ if (!observed)
238
+ return false;
239
+ if (observed.host !== owner.host ||
240
+ observed.role !== owner.role ||
241
+ observed.sessionId !== owner.sessionId ||
242
+ observed.threadId !== owner.threadId ||
243
+ observed.hostId !== owner.hostId ||
244
+ (owner.contractFingerprint !== null &&
245
+ owner.contractFingerprint !== undefined &&
246
+ observed.contractFingerprint !== owner.contractFingerprint))
247
+ return false;
248
+ if (owner.startRequestId && !host.requestRefs.includes(owner.startRequestId))
249
+ return false;
250
+ return (owner.processId === null ||
251
+ owner.processId === undefined ||
252
+ owner.processId > 0);
253
+ }
254
+ function taskRunOwnerMatches(run, owner) {
255
+ return runHostMatchesOwner(run, owner);
256
+ }
257
+ function projectFile(root, ref) {
258
+ if (typeof ref !== "string" || !ref.trim() || path.isAbsolute(ref)) {
259
+ throw new Error("project-relative receipt reference required");
260
+ }
261
+ const file = path.resolve(root, ref);
262
+ const relativeFile = path.relative(root, file);
263
+ if (!relativeFile ||
264
+ relativeFile.startsWith("..") ||
265
+ path.isAbsolute(relativeFile)) {
266
+ throw new Error("receipt reference must stay inside the project");
267
+ }
268
+ const realFile = fs.realpathSync(file);
269
+ const realRelative = path.relative(fs.realpathSync(root), realFile);
270
+ if (!realRelative ||
271
+ realRelative.startsWith("..") ||
272
+ path.isAbsolute(realRelative)) {
273
+ throw new Error("receipt reference must stay inside the project");
274
+ }
275
+ if (!fs.statSync(realFile).isFile())
276
+ throw new Error("receipt reference must be a file");
277
+ return realFile;
278
+ }
279
+ function asRecord(value, label) {
280
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
281
+ throw new Error(`${label} must be an object`);
282
+ }
283
+ return value;
284
+ }
285
+ function proofOwnerMatches(proof, expected) {
286
+ return (proof.host === expected.host &&
287
+ proof.role === expected.role &&
288
+ proof.session_id === expected.sessionId &&
289
+ proof.thread_id === expected.threadId &&
290
+ proof.host_id === expected.hostId &&
291
+ proof.start_request_id === (expected.startRequestId ?? null) &&
292
+ proof.process_id === (expected.processId ?? null));
293
+ }
294
+ function hasExactKeys(value, keys) {
295
+ const actual = Object.keys(value).sort();
296
+ const expected = [...keys].sort();
297
+ return (actual.length === expected.length &&
298
+ actual.every((key, index) => key === expected[index]));
299
+ }
300
+ function nonEmptyString(value) {
301
+ return typeof value === "string" && value.trim().length > 0;
302
+ }
303
+ function taskOrProjectFile(root, taskId, ref) {
304
+ if (!nonEmptyString(ref) || path.isAbsolute(ref))
305
+ throw new Error("task evidence reference must be project-relative");
306
+ try {
307
+ return projectFile(root, ref);
308
+ }
309
+ catch {
310
+ const taskDir = resolveTaskDir(root, taskId);
311
+ const candidate = path.resolve(taskDir, ref);
312
+ const taskRelative = path.relative(taskDir, candidate);
313
+ if (!taskRelative ||
314
+ taskRelative.startsWith("..") ||
315
+ path.isAbsolute(taskRelative))
316
+ throw new Error("task evidence reference must stay inside the Task directory");
317
+ const realFile = fs.realpathSync(candidate);
318
+ const realTaskDir = fs.realpathSync(taskDir);
319
+ const realRelative = path.relative(realTaskDir, realFile);
320
+ if (!realRelative ||
321
+ realRelative.startsWith("..") ||
322
+ path.isAbsolute(realRelative))
323
+ throw new Error("task evidence reference must stay inside the Task directory");
324
+ if (!fs.statSync(realFile).isFile())
325
+ throw new Error("task evidence reference must be a file");
326
+ return realFile;
327
+ }
328
+ }
329
+ function sameTaskOrProjectRef(root, taskId, left, rightFile) {
330
+ try {
331
+ return taskOrProjectFile(root, taskId, left) === fs.realpathSync(rightFile);
332
+ }
333
+ catch {
334
+ return false;
335
+ }
336
+ }
337
+ function hostResultRefsContainFile(root, taskId, refs, expectedFile) {
338
+ return refs.some((ref) => sameTaskOrProjectRef(root, taskId, ref, expectedFile));
339
+ }
340
+ function verifyCodexBridgeStopProof(proof, lease, request, nativeReceipt) {
341
+ const owner = lease.dispatch_owner;
342
+ if (proof.source !== "codex-bridge" ||
343
+ owner.host !== "codex-desktop" ||
344
+ (owner.startRequestId !== null && owner.startRequestId !== undefined) ||
345
+ (owner.processId !== null && owner.processId !== undefined) ||
346
+ proof.owner.start_request_id !== null ||
347
+ proof.owner.process_id !== null ||
348
+ request.dispatch_task_id !== lease.task_id ||
349
+ request.dispatch_run_id !== lease.run_id ||
350
+ request.dispatch_lease_id !== lease.id ||
351
+ request.schedule_receipt_fingerprint !==
352
+ lease.schedule_receipt_fingerprint ||
353
+ request.dispatch_admission_receipt_fingerprint !==
354
+ lease.admission_receipt_fingerprint ||
355
+ request.role !== owner.role ||
356
+ request.thread_id !== owner.threadId ||
357
+ request.host_id !== owner.hostId ||
358
+ (owner.contractFingerprint !== null &&
359
+ owner.contractFingerprint !== undefined &&
360
+ request.contract_fingerprint !== owner.contractFingerprint) ||
361
+ nativeReceipt.request_id !== request.request_id ||
362
+ nativeReceipt.request_fingerprint !== proof.request_fingerprint ||
363
+ nativeReceipt.task_id !== lease.task_id ||
364
+ nativeReceipt.run_id !== lease.run_id ||
365
+ nativeReceipt.tool !== request.tool ||
366
+ nativeReceipt.host_id !== owner.hostId ||
367
+ nativeReceipt.thread_id !== owner.threadId ||
368
+ nativeReceipt.evidence_level !== "desktop-native" ||
369
+ request.candidate_snapshot_id !== nativeReceipt.candidate_snapshot_id ||
370
+ request.candidate_fingerprint !== nativeReceipt.candidate_fingerprint ||
371
+ nativeReceipt.contract_stale !== false) {
372
+ throw new Error("dispatch-stop-proof-codex-identity-mismatch");
373
+ }
374
+ if (proof.disposition === "native-terminal") {
375
+ if (request.tool !== "wait_threads" ||
376
+ nativeReceipt.tool !== "wait_threads" ||
377
+ nativeReceipt.outcome !== "ok" ||
378
+ nativeReceipt.status !== "completed")
379
+ throw new Error("dispatch-stop-proof-not-native-terminal");
380
+ }
381
+ else if (proof.disposition === "not-created") {
382
+ if (request.tool !== "create_thread" ||
383
+ nativeReceipt.tool !== "create_thread" ||
384
+ nativeReceipt.outcome !== "failed" ||
385
+ nativeReceipt.thread_creation_state !== "not_created" ||
386
+ (nativeReceipt.thread_id !== null &&
387
+ nativeReceipt.thread_id !== undefined) ||
388
+ (nativeReceipt.client_thread_id !== null &&
389
+ nativeReceipt.client_thread_id !== undefined) ||
390
+ nativeReceipt.host_id !== null)
391
+ throw new Error("dispatch-stop-proof-not-confirmed-not-created");
392
+ if (owner.sessionId !== null ||
393
+ owner.threadId !== null ||
394
+ owner.hostId !== null ||
395
+ proof.owner.session_id !== null ||
396
+ proof.owner.thread_id !== null ||
397
+ proof.owner.host_id !== null)
398
+ throw new Error("dispatch-stop-proof-not-created-owner-mismatch");
399
+ }
400
+ else {
401
+ throw new Error("dispatch-stop-proof-invalid-disposition");
402
+ }
403
+ }
404
+ function verifyPiHostStopProof(root, proof, lease, startReceipt, runRecord, nativeReceipt, nativeReceiptFile) {
405
+ const owner = lease.dispatch_owner;
406
+ const stop = asRecord(nativeReceipt.process_stop_receipt, "Pi process stop receipt");
407
+ const runSettlementSeal = readPiRunSettlementSealV1(runRecord);
408
+ const processExit = asRecord(stop.processExit, "Pi process exit evidence");
409
+ if (!runSettlementSeal ||
410
+ typeof proof.native_run_settlement_fingerprint !== "string" ||
411
+ !/^[a-f0-9]{64}$/u.test(proof.native_run_settlement_fingerprint) ||
412
+ proof.native_run_settlement_fingerprint !==
413
+ fingerprintTaskValue(runSettlementSeal) ||
414
+ proof.source !== "pi-host" ||
415
+ proof.disposition !== "native-terminal" ||
416
+ owner.host !== "pi" ||
417
+ owner.role !== "implement" ||
418
+ owner.threadId !== null ||
419
+ owner.hostId !== null ||
420
+ !owner.startRequestId ||
421
+ !owner.processId ||
422
+ proof.owner.start_request_id !== owner.startRequestId ||
423
+ proof.owner.process_id !== owner.processId ||
424
+ startReceipt.schemaVersion !== 1 ||
425
+ startReceipt.source !== "pactile-pi-rpc" ||
426
+ startReceipt.taskId !== lease.task_id ||
427
+ startReceipt.taskRunId !== lease.run_id ||
428
+ !nonEmptyString(startReceipt.piRunId) ||
429
+ startReceipt.role !== "implement" ||
430
+ startReceipt.sessionId !== owner.sessionId ||
431
+ startReceipt.processId !== owner.processId ||
432
+ startReceipt.startRequestId !== owner.startRequestId ||
433
+ !nonEmptyString(startReceipt.progressEvidenceRef) ||
434
+ !nonEmptyString(startReceipt.evidenceRef) ||
435
+ runRecord.run_id !== startReceipt.piRunId ||
436
+ runRecord.task_id !== lease.task_id ||
437
+ runRecord.task_run_id !== lease.run_id ||
438
+ runRecord.role !== "implement" ||
439
+ runRecord.session_id !== owner.sessionId ||
440
+ runRecord.process_id !== owner.processId ||
441
+ runRecord.start_request_id !== owner.startRequestId ||
442
+ runRecord.progress_evidence_ref !== startReceipt.progressEvidenceRef ||
443
+ runRecord.settle_receipt_id !== stop.settleReceiptId ||
444
+ stop.schemaVersion !== 1 ||
445
+ stop.source !== "pactile-pi-rpc" ||
446
+ stop.assurance !== "manager-owned-child-exit" ||
447
+ stop.taskId !== lease.task_id ||
448
+ stop.taskRunId !== lease.run_id ||
449
+ stop.piRunId !== startReceipt.piRunId ||
450
+ stop.role !== "implement" ||
451
+ stop.sessionId !== owner.sessionId ||
452
+ stop.processId !== owner.processId ||
453
+ stop.startRequestId !== owner.startRequestId ||
454
+ !nonEmptyString(stop.settleReceiptId) ||
455
+ !["exited", "cancelled"].includes(String(stop.terminal)) ||
456
+ processExit.processId !== owner.processId ||
457
+ processExit.terminationVerified !== true ||
458
+ !nonEmptyString(processExit.exitObservedAt) ||
459
+ !nonEmptyString(stop.evidenceRef) ||
460
+ stop.evidenceRef !== startReceipt.evidenceRef ||
461
+ !nonEmptyString(stop.progressEvidenceRef) ||
462
+ stop.progressEvidenceRef !== startReceipt.progressEvidenceRef ||
463
+ !sameTaskOrProjectRef(root, lease.task_id, runRecord.host_start_receipt_ref, projectFile(root, proof.request_ref)) ||
464
+ !sameTaskOrProjectRef(root, lease.task_id, startReceipt.evidenceRef, nativeReceiptFile)) {
465
+ throw new Error("dispatch-stop-proof-pi-identity-mismatch");
466
+ }
467
+ }
468
+ function verifyStopProof(root, proofRef, lease) {
469
+ const proofFile = projectFile(root, proofRef);
470
+ const proof = asRecord(JSON.parse(fs.readFileSync(proofFile, "utf8")), "dispatch stop proof");
471
+ const { proof_fingerprint: storedProofFingerprint, ...proofBase } = proof;
472
+ const proofKeys = [
473
+ "schema_version",
474
+ "scope",
475
+ "proof_fingerprint",
476
+ "lease_id",
477
+ "task_id",
478
+ "run_id",
479
+ "schedule_receipt_fingerprint",
480
+ "admission_receipt_fingerprint",
481
+ "source",
482
+ "disposition",
483
+ "writer_exited",
484
+ "owner",
485
+ "request_ref",
486
+ "request_fingerprint",
487
+ "native_receipt_ref",
488
+ "native_receipt_fingerprint",
489
+ ];
490
+ if (proof.source === "pi-host")
491
+ proofKeys.push("native_run_settlement_fingerprint");
492
+ if (proof.schema_version !== 1 ||
493
+ proof.scope !== STOP_PROOF_SCOPE ||
494
+ !hasExactKeys(proof, proofKeys) ||
495
+ !hasExactKeys(proof.owner, [
496
+ "host",
497
+ "role",
498
+ "session_id",
499
+ "thread_id",
500
+ "host_id",
501
+ "start_request_id",
502
+ "process_id",
503
+ ]) ||
504
+ typeof storedProofFingerprint !== "string" ||
505
+ fingerprintTaskValue(proofBase) !== storedProofFingerprint ||
506
+ path.basename(proofFile) !== `${storedProofFingerprint}.json`) {
507
+ throw new Error("dispatch-stop-proof-integrity-failed");
508
+ }
509
+ if (proof.lease_id !== lease.id ||
510
+ proof.task_id !== lease.task_id ||
511
+ proof.run_id !== lease.run_id ||
512
+ proof.schedule_receipt_fingerprint !== lease.schedule_receipt_fingerprint ||
513
+ proof.admission_receipt_fingerprint !==
514
+ lease.admission_receipt_fingerprint ||
515
+ proof.writer_exited !== true ||
516
+ !proofOwnerMatches(proof.owner, lease.dispatch_owner)) {
517
+ throw new Error("dispatch-stop-proof-identity-mismatch");
518
+ }
519
+ const requestFile = projectFile(root, proof.request_ref);
520
+ const request = asRecord(JSON.parse(fs.readFileSync(requestFile, "utf8")), "dispatch request");
521
+ if (proof.source === "codex-bridge") {
522
+ const { request_fingerprint: storedRequestFingerprint, ...requestBase } = request;
523
+ if (typeof storedRequestFingerprint !== "string" ||
524
+ fingerprintTaskValue(requestBase) !== storedRequestFingerprint ||
525
+ storedRequestFingerprint !== proof.request_fingerprint ||
526
+ request.task_id !== lease.task_id ||
527
+ request.run_id !== lease.run_id)
528
+ throw new Error("dispatch-stop-proof-request-mismatch");
529
+ }
530
+ else if (proof.source === "pi-host") {
531
+ if (proof.disposition !== "native-terminal" ||
532
+ fingerprintTaskValue(request) !== proof.request_fingerprint)
533
+ throw new Error("dispatch-stop-proof-request-mismatch");
534
+ }
535
+ else {
536
+ throw new Error("dispatch-stop-proof-source-invalid");
537
+ }
538
+ const nativeReceiptFile = projectFile(root, proof.native_receipt_ref);
539
+ const nativeReceipt = asRecord(JSON.parse(fs.readFileSync(nativeReceiptFile, "utf8")), "native dispatch receipt");
540
+ if (proof.source === "codex-bridge") {
541
+ if (fingerprintTaskValue(nativeReceipt) !== proof.native_receipt_fingerprint)
542
+ throw new Error("dispatch-stop-proof-native-receipt-mismatch");
543
+ verifyCodexBridgeStopProof(proof, lease, request, nativeReceipt);
544
+ return {
545
+ disposition: proof.disposition,
546
+ proof,
547
+ nativeReceiptFile,
548
+ settlementEventRef: proof.disposition === "native-terminal" &&
549
+ nonEmptyString(nativeReceipt.request_id)
550
+ ? nativeReceipt.request_id
551
+ : null,
552
+ progressEvidenceRef: null,
553
+ startRequestId: null,
554
+ candidateSnapshotId: typeof nativeReceipt.candidate_snapshot_id === "string"
555
+ ? nativeReceipt.candidate_snapshot_id
556
+ : null,
557
+ candidateFingerprint: typeof nativeReceipt.candidate_fingerprint === "string"
558
+ ? nativeReceipt.candidate_fingerprint
559
+ : null,
560
+ };
561
+ }
562
+ else {
563
+ const startReceipt = request;
564
+ const runRecord = nativeReceipt;
565
+ const stop = asRecord(runRecord.process_stop_receipt, "Pi process stop receipt");
566
+ if (fingerprintTaskValue(stop) !== proof.native_receipt_fingerprint)
567
+ throw new Error("dispatch-stop-proof-native-receipt-mismatch");
568
+ verifyPiHostStopProof(root, proof, lease, startReceipt, runRecord, nativeReceipt, nativeReceiptFile);
569
+ return {
570
+ disposition: proof.disposition,
571
+ proof,
572
+ nativeReceiptFile,
573
+ settlementEventRef: nonEmptyString(stop.settleReceiptId)
574
+ ? stop.settleReceiptId
575
+ : null,
576
+ progressEvidenceRef: nonEmptyString(startReceipt.progressEvidenceRef)
577
+ ? startReceipt.progressEvidenceRef
578
+ : null,
579
+ startRequestId: nonEmptyString(startReceipt.startRequestId)
580
+ ? startReceipt.startRequestId
581
+ : null,
582
+ candidateSnapshotId: null,
583
+ candidateFingerprint: null,
584
+ };
585
+ }
586
+ }
587
+ function validateStopProofForActiveLease(root, request, lease) {
588
+ const reject = (reasonCode) => ({
589
+ valid: false,
590
+ reasonCode,
591
+ proof: null,
592
+ });
593
+ let admission;
594
+ try {
595
+ admission = readAdmissionReceipt(root, lease.admission_receipt_fingerprint);
596
+ }
597
+ catch {
598
+ return reject("dispatch-lease-receipt-invalid");
599
+ }
600
+ if (admission.receiptFingerprint !== lease.admission_receipt_fingerprint ||
601
+ admission.leaseId !== lease.id ||
602
+ admission.request.taskId !== request.taskId ||
603
+ admission.request.runId !== request.runId ||
604
+ admission.request.scheduleReceiptFingerprint !==
605
+ lease.schedule_receipt_fingerprint ||
606
+ !sameOwner(admission.owner, lease.admission_owner) ||
607
+ !Array.isArray(admission.writeSet) ||
608
+ fingerprintTaskValue(normalizeProjectWriteSet(admission.writeSet)) !==
609
+ fingerprintTaskValue(normalizeProjectWriteSet(lease.touches)))
610
+ return reject("dispatch-lease-receipt-mismatch");
611
+ try {
612
+ readTaskKernelScheduleReceipt(root, lease.schedule_receipt_fingerprint);
613
+ }
614
+ catch {
615
+ return reject("schedule-receipt-integrity-failed");
616
+ }
617
+ let kernel;
618
+ let run;
619
+ try {
620
+ const read = readTaskKernel({
621
+ root,
622
+ taskDir: resolveTaskDir(root, request.taskId),
623
+ });
624
+ if (read.kind !== "task-kernel-v2")
625
+ return reject("task-kernel-snapshot-invalid-or-missing");
626
+ if (read.kernel.identity.taskId !== request.taskId)
627
+ return reject("task-kernel-snapshot-invalid-or-missing");
628
+ const latest = read.kernel.runs.at(-1);
629
+ if (latest?.id !== request.runId || latest.taskId !== request.taskId)
630
+ return reject("task-run-id-mismatch");
631
+ kernel = read.kernel;
632
+ run = latest;
633
+ }
634
+ catch {
635
+ return reject("task-kernel-snapshot-invalid-or-missing");
636
+ }
637
+ let checkedProof;
638
+ try {
639
+ checkedProof = verifyStopProof(root, request.stopReceiptRef, lease);
640
+ }
641
+ catch (error) {
642
+ return reject(error instanceof Error ? error.message : "dispatch-stop-proof-invalid");
643
+ }
644
+ const currentWriteSet = normalizeProjectWriteSet([
645
+ ...run.writeSetSnapshot,
646
+ ...(run.workspace?.writeSet ?? []),
647
+ ]);
648
+ if (!writeSetCoveredByLease(currentWriteSet, lease.touches))
649
+ return reject("task-run-write-set-expanded");
650
+ if (checkedProof.disposition === "native-terminal") {
651
+ if (!run.host || !taskRunOwnerMatches(run, lease.dispatch_owner))
652
+ return reject("task-run-host-binding-mismatch");
653
+ const ownerBindingReason = verifyOwnerBinding(root, lease, kernel, run);
654
+ if (ownerBindingReason)
655
+ return reject(ownerBindingReason);
656
+ if ((run.candidateSnapshot?.id ?? null) !==
657
+ checkedProof.candidateSnapshotId ||
658
+ (run.candidateSnapshot?.fingerprint ?? null) !==
659
+ checkedProof.candidateFingerprint)
660
+ return reject("dispatch-stop-proof-candidate-mismatch");
661
+ if (!checkedProof.settlementEventRef ||
662
+ !run.host.eventRefs.includes(checkedProof.settlementEventRef) ||
663
+ !hostResultRefsContainFile(root, request.taskId, run.host.resultRefs, checkedProof.nativeReceiptFile))
664
+ return reject("task-run-host-settlement-refs-missing");
665
+ if (checkedProof.proof.source === "codex-bridge" &&
666
+ !run.host.requestRefs.length)
667
+ return reject("task-run-host-start-request-ref-missing");
668
+ if (checkedProof.proof.source === "pi-host" &&
669
+ (!checkedProof.startRequestId ||
670
+ !run.host.requestRefs.includes(checkedProof.startRequestId) ||
671
+ !checkedProof.progressEvidenceRef ||
672
+ !run.host.eventRefs.some((ref) => sameTaskOrProjectRef(root, request.taskId, ref, taskOrProjectFile(root, request.taskId, checkedProof.progressEvidenceRef)))))
673
+ return reject("task-run-host-start-evidence-refs-missing");
674
+ }
675
+ else if (run.host !== null ||
676
+ !["waiting", "running"].includes(run.state) ||
677
+ !sameOwner(lease.admission_owner, lease.dispatch_owner) ||
678
+ lease.owner_binding_receipt_fingerprint) {
679
+ return reject("not-created-run-state-mismatch");
680
+ }
681
+ if (checkedProof.proof.source === "pi-host" && run.candidateSnapshot !== null)
682
+ return reject("pi-stop-proof-candidate-must-follow-process-stop");
683
+ return { valid: true, reasonCode: null, proof: checkedProof.proof };
684
+ }
685
+ function inspectTaskRun(root, receipt, request, requirePlannedRevision) {
686
+ const reasons = [];
687
+ const snapshot = lifecycleFor(receipt, request.taskId);
688
+ const decision = receipt.plan.decisions.find((item) => item.taskId === request.taskId);
689
+ if (!receipt.candidateTaskIds.includes(request.taskId) ||
690
+ !snapshot ||
691
+ !decision ||
692
+ !["scheduled", "in-flight"].includes(decision.action)) {
693
+ return { checked: null, reasonCodes: ["task-not-admitted-by-plan"] };
694
+ }
695
+ const taskDir = resolveTaskDir(root, request.taskId);
696
+ const read = readTaskKernel({ root, taskDir });
697
+ if (read.kind !== "task-kernel-v2")
698
+ return { checked: null, reasonCodes: ["task-kernel-v2-required"] };
699
+ const kernel = read.kernel;
700
+ if (kernel.identity.taskId !== request.taskId)
701
+ return { checked: null, reasonCodes: ["task-identity-mismatch"] };
702
+ const expectedRevision = receipt.taskKernelRevisions[request.taskId];
703
+ if (expectedRevision !== snapshot.kernelRevision ||
704
+ (requirePlannedRevision && kernel.revision !== expectedRevision))
705
+ reasons.push("task-kernel-revision-changed");
706
+ const dependencyIds = [...kernel.definition.dependencies].sort();
707
+ if (JSON.stringify(dependencyIds) !==
708
+ JSON.stringify([...snapshot.dependencyTaskIds].sort()))
709
+ reasons.push("hard-dependencies-changed");
710
+ const run = kernel.runs.at(-1) ?? null;
711
+ if (!run)
712
+ return { checked: null, reasonCodes: [...reasons, "task-run-missing"] };
713
+ if (run.id !== request.runId || snapshot.runId !== request.runId)
714
+ reasons.push("task-run-id-mismatch");
715
+ if (run.taskId !== request.taskId)
716
+ reasons.push("task-run-identity-mismatch");
717
+ if (run.state !== "waiting" && run.state !== "running")
718
+ reasons.push("task-run-not-dispatchable");
719
+ const lifecycle = projectTaskKernelLifecycle(kernel);
720
+ if (!lifecycle.gateSnapshot.runStart.phaseAllowsRun ||
721
+ lifecycle.gateSnapshot.runStart.activeRunId !== run.id ||
722
+ kernel.condition === "blocked")
723
+ reasons.push("task-run-lifecycle-gate-closed");
724
+ if (!nonEmptyAuthorization(run))
725
+ reasons.push("task-run-authorization-missing");
726
+ const dependencyKernelRevisions = {};
727
+ for (const dependencyId of dependencyIds) {
728
+ const dependencyDir = resolveTaskDirectoryById(root, dependencyId);
729
+ if (!dependencyDir) {
730
+ dependencyKernelRevisions[dependencyId] = null;
731
+ reasons.push(`hard-dependency-missing-or-invalid:${dependencyId}`);
732
+ continue;
733
+ }
734
+ const dependency = readTaskKernel({ root, taskDir: dependencyDir });
735
+ if (dependency.kind !== "task-kernel-v2") {
736
+ dependencyKernelRevisions[dependencyId] = null;
737
+ reasons.push(`hard-dependency-not-v2-closed:${dependencyId}`);
738
+ continue;
739
+ }
740
+ dependencyKernelRevisions[dependencyId] = dependency.kernel.revision;
741
+ const projection = projectTaskKernelLifecycle(dependency.kernel);
742
+ if (!projection.closed || projection.outcome !== "completed")
743
+ reasons.push(`hard-dependency-not-closed:${dependencyId}`);
744
+ }
745
+ const writeInputs = [
746
+ ...run.writeSetSnapshot,
747
+ ...(run.workspace?.writeSet ?? []),
748
+ ];
749
+ const writeSet = normalizeProjectWriteSet(writeInputs);
750
+ const receiptWriteSet = normalizeProjectWriteSet(snapshot.writeSet);
751
+ if (JSON.stringify(writeSet) !== JSON.stringify(receiptWriteSet))
752
+ reasons.push("task-run-write-set-changed");
753
+ if (reasons.length)
754
+ return { checked: null, reasonCodes: [...new Set(reasons)] };
755
+ return {
756
+ checked: {
757
+ kernel,
758
+ run,
759
+ lifecycle: snapshot,
760
+ dependencyKernelRevisions,
761
+ writeSet,
762
+ },
763
+ reasonCodes: [],
764
+ };
765
+ }
766
+ function coordinationDispatchReason(root, taskId, kernel, run) {
767
+ let coordination;
768
+ try {
769
+ coordination = readCoordinationSnapshot(root);
770
+ }
771
+ catch {
772
+ return "coordination-state-unreadable";
773
+ }
774
+ if (coordination.blocked_tasks.some((block) => block.task_id === taskId))
775
+ return "coordination-task-blocked";
776
+ if (!kernel || !run)
777
+ return null;
778
+ const runEntryIndex = kernel.events.findIndex((event) => event.entityId === run.id &&
779
+ (event.type === "run.queued" || event.type === "run.started"));
780
+ const runEntry = kernel.events[runEntryIndex];
781
+ if (!runEntry)
782
+ return "task-run-start-event-missing";
783
+ const latestUnblock = [...coordination.events]
784
+ .reverse()
785
+ .find((event) => event.type === "task.unblocked" && event.task_id === taskId);
786
+ if (!latestUnblock)
787
+ return null;
788
+ const barrierRevision = latestUnblock.kernel_revision_at_unblock;
789
+ const barrierEventId = latestUnblock.kernel_event_id_at_unblock;
790
+ if (typeof barrierRevision !== "number" ||
791
+ typeof barrierEventId !== "string") {
792
+ return "coordination-unblock-kernel-barrier-missing";
793
+ }
794
+ const barrierIndex = kernel.events.findIndex((event) => event.id === barrierEventId);
795
+ const barrierEvent = kernel.events[barrierIndex];
796
+ if (barrierEvent?.revision !== barrierRevision || barrierIndex < 0) {
797
+ return "coordination-unblock-kernel-barrier-invalid";
798
+ }
799
+ if (runEntry.type === "run.started") {
800
+ return runEntryIndex > barrierIndex
801
+ ? null
802
+ : "coordination-running-run-requires-terminal-retry";
803
+ }
804
+ const resumeEntry = [...kernel.events]
805
+ .map((event, index) => ({ event, index }))
806
+ .reverse()
807
+ .find(({ event }) => event.type === "run.resumed" && event.entityId === run.id);
808
+ if (!resumeEntry || resumeEntry.index <= runEntryIndex)
809
+ return "coordination-unblock-requires-kernel-resume";
810
+ if (resumeEntry.index <= barrierIndex)
811
+ return "coordination-running-run-requires-terminal-retry";
812
+ if (runEntryIndex <= barrierIndex && latestUnblock.run_id !== run.id) {
813
+ return "coordination-unblock-kernel-barrier-mismatch";
814
+ }
815
+ const unblockEventIndex = coordination.events.findIndex((event) => event.event_id === latestUnblock.event_id);
816
+ const resumeAuthorization = [...coordination.events]
817
+ .reverse()
818
+ .find((event) => event.type === "run.resume-authorized" &&
819
+ event.task_id === taskId &&
820
+ event.run_id === run.id &&
821
+ event.unblock_event_id === latestUnblock.event_id);
822
+ const resumeAuthorizationIndex = resumeAuthorization
823
+ ? coordination.events.findIndex((event) => event.event_id === resumeAuthorization.event_id)
824
+ : -1;
825
+ if (!resumeAuthorization ||
826
+ resumeAuthorizationIndex <= unblockEventIndex ||
827
+ resumeAuthorization.kernel_revision !== resumeEntry.event.revision ||
828
+ resumeAuthorization.kernel_event_id !== resumeEntry.event.id) {
829
+ return "coordination-unblock-resume-authorization-missing";
830
+ }
831
+ return null;
832
+ }
833
+ function conflictAuthorization(receipt, taskId, prior) {
834
+ const priorTaskId = prior.task_id;
835
+ if (prior.owner_kind !== "task-kernel-v2-run" ||
836
+ !priorTaskId ||
837
+ prior.schedule_receipt_fingerprint !== receipt.receiptFingerprint)
838
+ return undefined;
839
+ return receipt.plan.waves
840
+ .find((wave) => wave.taskIds.includes(taskId) && wave.taskIds.includes(priorTaskId))
841
+ ?.conflictAuthorizations.find((authorization) => authorization.taskIds.includes(taskId) &&
842
+ authorization.taskIds.includes(priorTaskId));
843
+ }
844
+ function persistRejected(root, request, reasonCodes, taskKernelRevision, dependencyKernelRevisions = {}, writeSet = null, conflictingLeaseIds = []) {
845
+ const stored = persistDecisionReceipt(root, {
846
+ decision: "rejected",
847
+ request,
848
+ owner: normalizeOwner(request.owner),
849
+ reasonCodes,
850
+ taskKernelRevision,
851
+ dependencyKernelRevisions,
852
+ writeSet,
853
+ conflictingLeaseIds,
854
+ leaseId: null,
855
+ });
856
+ return {
857
+ permitted: false,
858
+ receipt: stored.receipt,
859
+ receiptFile: relative(root, stored.file),
860
+ };
861
+ }
862
+ /** Acquires a project-wide writer lease only for a currently authorized V2 Run. */
863
+ export function acquireTaskKernelRunDispatchV1(rootValue, request) {
864
+ const root = path.resolve(rootValue);
865
+ return withProjectSchedulerMutex(root, () => {
866
+ let schedule;
867
+ try {
868
+ schedule = readTaskKernelScheduleReceipt(root, request.scheduleReceiptFingerprint);
869
+ }
870
+ catch (error) {
871
+ const reason = error instanceof Error &&
872
+ error.message === "schedule-receipt-integrity-failed"
873
+ ? "schedule-receipt-integrity-failed"
874
+ : "schedule-receipt-invalid-or-missing";
875
+ return persistRejected(root, request, [reason], null);
876
+ }
877
+ let inspected;
878
+ try {
879
+ inspected = inspectTaskRun(root, schedule, request, true);
880
+ }
881
+ catch {
882
+ return persistRejected(root, request, ["task-kernel-snapshot-invalid-or-missing"], null);
883
+ }
884
+ if (!inspected.checked)
885
+ return persistRejected(root, request, inspected.reasonCodes, null);
886
+ const checked = inspected.checked;
887
+ try {
888
+ return withCoordinationJournalLock(root, () => {
889
+ const coordinationReason = coordinationDispatchReason(root, request.taskId, checked.kernel, checked.run);
890
+ if (coordinationReason) {
891
+ return persistRejected(root, request, [coordinationReason], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
892
+ }
893
+ const kernelOwner = readRunHost(checked.run);
894
+ const suppliedOwner = normalizeOwner(request.owner);
895
+ // Preserve adapter-observed process identity when the Kernel Host schema
896
+ // has not yet projected those fields; a null Kernel slot is not a claim.
897
+ const owner = suppliedOwner ?? kernelOwner;
898
+ if (!owner) {
899
+ return persistRejected(root, request, ["dispatch-owner-missing-or-invalid"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
900
+ }
901
+ if (kernelOwner &&
902
+ suppliedOwner &&
903
+ !ownersCompatible(kernelOwner, suppliedOwner)) {
904
+ return persistRejected(root, request, ["dispatch-owner-does-not-match-task-run"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
905
+ }
906
+ if (request.owner && !normalizeOwner(request.owner)) {
907
+ return persistRejected(root, request, ["dispatch-owner-missing-or-invalid"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
908
+ }
909
+ let active;
910
+ try {
911
+ active = listProjectWriteLeases(root);
912
+ }
913
+ catch {
914
+ return persistRejected(root, request, ["project-active-leases-unreadable"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
915
+ }
916
+ const sameRun = active.find(({ lease }) => lease.owner_kind === "task-kernel-v2-run" &&
917
+ lease.task_id === request.taskId &&
918
+ lease.run_id === request.runId);
919
+ if (sameRun)
920
+ return persistRejected(root, request, ["task-run-already-leased"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet, [sameRun.lease.id]);
921
+ const collisions = active.filter(({ lease }) => projectWriteSetsConflict(lease.touches, checked.writeSet));
922
+ const conflictingLeaseIds = [];
923
+ const missingIntegrationOwnerLeaseIds = [];
924
+ const authorizedConflicts = [];
925
+ for (const { lease } of collisions) {
926
+ const authorization = conflictAuthorization(schedule, request.taskId, lease);
927
+ if (!authorization)
928
+ conflictingLeaseIds.push(lease.id);
929
+ else if (!nonEmptyString(authorization.integrationOwner)) {
930
+ missingIntegrationOwnerLeaseIds.push(lease.id);
931
+ conflictingLeaseIds.push(lease.id);
932
+ }
933
+ else
934
+ authorizedConflicts.push(authorization);
935
+ }
936
+ if (conflictingLeaseIds.length) {
937
+ const reasonCodes = [
938
+ ...(conflictingLeaseIds.length >
939
+ missingIntegrationOwnerLeaseIds.length
940
+ ? ["project-write-set-conflict"]
941
+ : []),
942
+ ...(missingIntegrationOwnerLeaseIds.length
943
+ ? ["project-write-set-conflict-integration-owner-missing"]
944
+ : []),
945
+ ];
946
+ return persistRejected(root, request, reasonCodes, checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet, conflictingLeaseIds.sort());
947
+ }
948
+ const leaseId = randomUUID();
949
+ const decisionBase = {
950
+ decision: "permitted",
951
+ request,
952
+ owner,
953
+ reasonCodes: [
954
+ "planned-task-run-authorized",
955
+ "hard-dependencies-closed",
956
+ "project-write-set-reserved",
957
+ ],
958
+ taskKernelRevision: checked.kernel.revision,
959
+ dependencyKernelRevisions: checked.dependencyKernelRevisions,
960
+ writeSet: checked.writeSet,
961
+ conflictingLeaseIds: collisions.map(({ lease }) => lease.id).sort(),
962
+ leaseId,
963
+ };
964
+ const admissionFingerprint = decisionFingerprint(decisionBase);
965
+ const leaseFile = projectActiveLeasePath(root, leaseId);
966
+ const lease = {
967
+ schema_version: 1,
968
+ owner_kind: "task-kernel-v2-run",
969
+ id: leaseId,
970
+ pid: process.pid,
971
+ durable: true,
972
+ task_id: request.taskId,
973
+ run_id: request.runId,
974
+ schedule_receipt_fingerprint: schedule.receiptFingerprint,
975
+ admission_receipt_fingerprint: admissionFingerprint,
976
+ admission_owner: owner,
977
+ dispatch_owner: owner,
978
+ touches: checked.writeSet,
979
+ authorized_conflicts: authorizedConflicts,
980
+ source_kernel_revision: checked.kernel.revision,
981
+ created_at: new Date().toISOString(),
982
+ status: "active",
983
+ };
984
+ fs.mkdirSync(path.dirname(leaseFile), { recursive: true });
985
+ fs.writeFileSync(leaseFile, `${JSON.stringify(lease, null, 2)}\n`, {
986
+ flag: "wx",
987
+ mode: 0o600,
988
+ });
989
+ try {
990
+ const stored = persistDecisionReceipt(root, decisionBase);
991
+ return {
992
+ permitted: true,
993
+ receipt: stored.receipt,
994
+ receiptFile: relative(root, stored.file),
995
+ leaseId,
996
+ leaseFile: relative(root, leaseFile),
997
+ };
998
+ }
999
+ catch (error) {
1000
+ fs.rmSync(leaseFile, { force: true });
1001
+ throw error;
1002
+ }
1003
+ });
1004
+ }
1005
+ catch (error) {
1006
+ if (error instanceof CoordinationError) {
1007
+ return persistRejected(root, request, ["coordination-state-unreadable"], checked.kernel.revision, checked.dependencyKernelRevisions, checked.writeSet);
1008
+ }
1009
+ throw error;
1010
+ }
1011
+ });
1012
+ }
1013
+ function readAdmissionReceipt(root, fingerprint) {
1014
+ if (!/^[a-f0-9]{64}$/.test(fingerprint))
1015
+ throw new Error("invalid-admission-receipt-fingerprint");
1016
+ const file = path.join(root, ".pactile", ".runtime", "scheduler", "admissions", `${fingerprint}.json`);
1017
+ const value = JSON.parse(fs.readFileSync(file, "utf8"));
1018
+ if (!value || typeof value !== "object" || Array.isArray(value))
1019
+ throw new Error("invalid-admission-receipt");
1020
+ const receipt = value;
1021
+ const { schemaVersion, scope, receiptFingerprint, createdAt: _createdAt, ...base } = receipt;
1022
+ if (schemaVersion !== 1 ||
1023
+ scope !== "task-kernel-v2-run-admission" ||
1024
+ receiptFingerprint !== fingerprint ||
1025
+ fingerprintTaskValue(base) !== fingerprint ||
1026
+ receipt.decision !== "permitted")
1027
+ throw new Error("admission-receipt-integrity-failed");
1028
+ return receipt;
1029
+ }
1030
+ function ownerBindingReceiptPath(root, fingerprint) {
1031
+ if (!/^[a-f0-9]{64}$/.test(fingerprint))
1032
+ throw new Error("invalid-owner-binding-receipt-fingerprint");
1033
+ return path.join(root, ".pactile", ".runtime", "scheduler", "owner-bindings", `${fingerprint}.json`);
1034
+ }
1035
+ function readOwnerBindingReceipt(root, fingerprint) {
1036
+ const file = ownerBindingReceiptPath(root, fingerprint);
1037
+ const receipt = asRecord(JSON.parse(fs.readFileSync(file, "utf8")), "owner binding receipt");
1038
+ const { schemaVersion, scope, receiptFingerprint, createdAt: _createdAt, ...base } = receipt;
1039
+ if (schemaVersion !== 1 ||
1040
+ scope !== "task-kernel-v2-run-owner-binding" ||
1041
+ receiptFingerprint !== fingerprint ||
1042
+ fingerprintTaskValue(base) !== fingerprint) {
1043
+ throw new Error("owner-binding-receipt-integrity-failed");
1044
+ }
1045
+ return receipt;
1046
+ }
1047
+ function persistOwnerBindingReceipt(root, base) {
1048
+ const fingerprint = fingerprintTaskValue(base);
1049
+ const file = ownerBindingReceiptPath(root, fingerprint);
1050
+ fs.mkdirSync(path.dirname(file), { recursive: true });
1051
+ if (fs.existsSync(file))
1052
+ return { receipt: readOwnerBindingReceipt(root, fingerprint), file };
1053
+ const receipt = {
1054
+ ...base,
1055
+ schemaVersion: 1,
1056
+ scope: "task-kernel-v2-run-owner-binding",
1057
+ receiptFingerprint: fingerprint,
1058
+ createdAt: new Date().toISOString(),
1059
+ };
1060
+ fs.writeFileSync(file, `${JSON.stringify(receipt, null, 2)}\n`, {
1061
+ flag: "wx",
1062
+ mode: 0o600,
1063
+ });
1064
+ return { receipt, file };
1065
+ }
1066
+ function verifyOwnerBinding(root, lease, kernel, run) {
1067
+ if (!lease.owner_binding_receipt_fingerprint) {
1068
+ if (!sameOwner(lease.admission_owner, lease.dispatch_owner))
1069
+ return "owner-binding-receipt-required";
1070
+ return taskRunOwnerMatches(run, lease.dispatch_owner)
1071
+ ? null
1072
+ : "task-run-host-binding-mismatch";
1073
+ }
1074
+ let receipt;
1075
+ try {
1076
+ receipt = readOwnerBindingReceipt(root, lease.owner_binding_receipt_fingerprint);
1077
+ }
1078
+ catch {
1079
+ return "owner-binding-receipt-invalid";
1080
+ }
1081
+ const event = kernel.events.find((candidate) => candidate.type === "run.host-bound" &&
1082
+ candidate.entityId === run.id &&
1083
+ candidate.id === receipt.hostBoundEventId);
1084
+ if (receipt.leaseId !== lease.id ||
1085
+ receipt.taskId !== lease.task_id ||
1086
+ receipt.runId !== lease.run_id ||
1087
+ receipt.scheduleReceiptFingerprint !== lease.schedule_receipt_fingerprint ||
1088
+ receipt.admissionReceiptFingerprint !==
1089
+ lease.admission_receipt_fingerprint ||
1090
+ !sameOwner(receipt.fromOwner, lease.admission_owner) ||
1091
+ !sameOwner(receipt.owner, lease.dispatch_owner) ||
1092
+ event?.revision !== receipt.taskKernelRevision ||
1093
+ !taskRunOwnerMatches(run, lease.dispatch_owner)) {
1094
+ return "owner-binding-receipt-mismatch";
1095
+ }
1096
+ return null;
1097
+ }
1098
+ /** Binds a previously unknown native writer only after its Run records run.host-bound. */
1099
+ export function bindTaskKernelRunDispatchOwnerV1(rootValue, request) {
1100
+ const root = path.resolve(rootValue);
1101
+ return withProjectSchedulerMutex(root, () => {
1102
+ const denied = (reasonCode) => ({
1103
+ bound: false,
1104
+ reasonCode,
1105
+ leaseId: request.leaseId,
1106
+ receipt: null,
1107
+ receiptFile: null,
1108
+ });
1109
+ const leaseFile = projectActiveLeasePath(root, request.leaseId);
1110
+ if (!fs.existsSync(leaseFile))
1111
+ return denied("dispatch-lease-not-active");
1112
+ let lease;
1113
+ let admission;
1114
+ try {
1115
+ lease = JSON.parse(fs.readFileSync(leaseFile, "utf8"));
1116
+ if (lease.owner_kind !== "task-kernel-v2-run" ||
1117
+ lease.id !== request.leaseId ||
1118
+ lease.task_id !== request.taskId ||
1119
+ lease.run_id !== request.runId ||
1120
+ lease.status !== "active" ||
1121
+ !validOwner(lease.dispatch_owner) ||
1122
+ !validOwner(lease.admission_owner))
1123
+ return denied("dispatch-lease-identity-mismatch");
1124
+ admission = readAdmissionReceipt(root, lease.admission_receipt_fingerprint);
1125
+ if (admission.leaseId !== lease.id ||
1126
+ admission.request.taskId !== lease.task_id ||
1127
+ admission.request.runId !== lease.run_id ||
1128
+ admission.request.scheduleReceiptFingerprint !==
1129
+ lease.schedule_receipt_fingerprint ||
1130
+ !sameOwner(admission.owner, lease.admission_owner))
1131
+ return denied("dispatch-lease-receipt-mismatch");
1132
+ }
1133
+ catch {
1134
+ return denied("dispatch-lease-record-invalid");
1135
+ }
1136
+ const owner = normalizeOwner(request.owner);
1137
+ if (!owner)
1138
+ return denied("dispatch-owner-missing-or-invalid");
1139
+ if (!ownerCanBind(lease.dispatch_owner, owner))
1140
+ return denied("dispatch-owner-binding-not-monotonic");
1141
+ let schedule;
1142
+ try {
1143
+ schedule = readTaskKernelScheduleReceipt(root, lease.schedule_receipt_fingerprint);
1144
+ }
1145
+ catch {
1146
+ return denied("schedule-receipt-integrity-failed");
1147
+ }
1148
+ let inspected;
1149
+ try {
1150
+ inspected = inspectTaskRun(root, schedule, {
1151
+ scheduleReceiptFingerprint: lease.schedule_receipt_fingerprint,
1152
+ taskId: request.taskId,
1153
+ runId: request.runId,
1154
+ }, false);
1155
+ }
1156
+ catch {
1157
+ return denied("task-kernel-snapshot-invalid-or-missing");
1158
+ }
1159
+ if (!inspected.checked)
1160
+ return denied(inspected.reasonCodes[0] ?? "task-run-not-dispatchable");
1161
+ if (!runHostMatchesOwner(inspected.checked.run, owner))
1162
+ return denied("task-run-host-binding-mismatch");
1163
+ const hostBoundEvent = inspected.checked.kernel.events.find((event) => event.type === "run.host-bound" &&
1164
+ event.entityId === request.runId);
1165
+ if (!hostBoundEvent)
1166
+ return denied("task-run-host-bound-event-required");
1167
+ if (sameOwner(lease.dispatch_owner, owner)) {
1168
+ if (lease.owner_binding_receipt_fingerprint) {
1169
+ const reason = verifyOwnerBinding(root, lease, inspected.checked.kernel, inspected.checked.run);
1170
+ if (reason)
1171
+ return denied(reason);
1172
+ const receipt = readOwnerBindingReceipt(root, lease.owner_binding_receipt_fingerprint);
1173
+ return {
1174
+ bound: true,
1175
+ reasonCode: null,
1176
+ leaseId: lease.id,
1177
+ receipt,
1178
+ receiptFile: relative(root, ownerBindingReceiptPath(root, receipt.receiptFingerprint)),
1179
+ };
1180
+ }
1181
+ return {
1182
+ bound: true,
1183
+ reasonCode: null,
1184
+ leaseId: lease.id,
1185
+ receipt: null,
1186
+ receiptFile: null,
1187
+ };
1188
+ }
1189
+ if (lease.owner_binding_receipt_fingerprint) {
1190
+ return denied("dispatch-owner-already-bound");
1191
+ }
1192
+ const stored = persistOwnerBindingReceipt(root, {
1193
+ leaseId: lease.id,
1194
+ taskId: lease.task_id,
1195
+ runId: lease.run_id,
1196
+ scheduleReceiptFingerprint: lease.schedule_receipt_fingerprint,
1197
+ admissionReceiptFingerprint: lease.admission_receipt_fingerprint,
1198
+ fromOwner: lease.dispatch_owner,
1199
+ owner,
1200
+ hostBoundEventId: hostBoundEvent.id,
1201
+ taskKernelRevision: hostBoundEvent.revision,
1202
+ });
1203
+ const updated = {
1204
+ ...lease,
1205
+ dispatch_owner: owner,
1206
+ owner_binding_receipt_fingerprint: stored.receipt.receiptFingerprint,
1207
+ };
1208
+ fs.writeFileSync(leaseFile, `${JSON.stringify(updated, null, 2)}\n`, {
1209
+ mode: 0o600,
1210
+ });
1211
+ return {
1212
+ bound: true,
1213
+ reasonCode: null,
1214
+ leaseId: lease.id,
1215
+ receipt: stored.receipt,
1216
+ receiptFile: relative(root, stored.file),
1217
+ };
1218
+ });
1219
+ }
1220
+ function writeSetCoveredByLease(current, reserved) {
1221
+ return current.every((candidate) => reserved.some((held) => held === "*" || candidate === held || candidate.startsWith(`${held}/`)));
1222
+ }
1223
+ function sameProjectWriteSet(left, right) {
1224
+ if (!Array.isArray(left) ||
1225
+ !Array.isArray(right) ||
1226
+ !left.every((value) => typeof value === "string") ||
1227
+ !right.every((value) => typeof value === "string"))
1228
+ return false;
1229
+ try {
1230
+ return (JSON.stringify(normalizeProjectWriteSet(left)) ===
1231
+ JSON.stringify(normalizeProjectWriteSet(right)));
1232
+ }
1233
+ catch {
1234
+ return false;
1235
+ }
1236
+ }
1237
+ /** Revalidates an active lease for a follow-up send or wait operation. */
1238
+ export function assertTaskKernelRunDispatchLeaseV1(rootValue, request) {
1239
+ return assertTaskKernelRunDispatchLeaseInternal(rootValue, request, null);
1240
+ }
1241
+ /**
1242
+ * Revalidates a writer lease immediately before first spawn, while requiring
1243
+ * the Kernel Run to remain unbound until native process identity exists.
1244
+ */
1245
+ export function assertTaskKernelRunDispatchPreSpawnV1(rootValue, request) {
1246
+ const result = assertTaskKernelRunDispatchLeaseInternal(rootValue, {
1247
+ leaseId: request.leaseId,
1248
+ taskId: request.taskId,
1249
+ runId: request.runId,
1250
+ }, request);
1251
+ return { ...result, hostBound: result.asserted ? false : null };
1252
+ }
1253
+ function assertTaskKernelRunDispatchLeaseInternal(rootValue, request, preSpawn) {
1254
+ const root = path.resolve(rootValue);
1255
+ return withProjectSchedulerMutex(root, () => {
1256
+ const empty = (reasonCode) => ({
1257
+ asserted: false,
1258
+ reasonCode,
1259
+ leaseId: request.leaseId,
1260
+ taskId: request.taskId,
1261
+ runId: request.runId,
1262
+ scheduleReceiptFingerprint: null,
1263
+ writeSet: null,
1264
+ });
1265
+ const leaseFile = projectActiveLeasePath(root, request.leaseId);
1266
+ if (!fs.existsSync(leaseFile))
1267
+ return empty("dispatch-lease-not-active");
1268
+ let lease;
1269
+ let admission;
1270
+ try {
1271
+ lease = JSON.parse(fs.readFileSync(leaseFile, "utf8"));
1272
+ if (lease.owner_kind !== "task-kernel-v2-run" ||
1273
+ lease.id !== request.leaseId ||
1274
+ lease.task_id !== request.taskId ||
1275
+ lease.run_id !== request.runId ||
1276
+ lease.status !== "active" ||
1277
+ !validOwner(lease.dispatch_owner) ||
1278
+ !validOwner(lease.admission_owner))
1279
+ return empty("dispatch-lease-identity-mismatch");
1280
+ admission = readAdmissionReceipt(root, lease.admission_receipt_fingerprint);
1281
+ if (admission.leaseId !== request.leaseId ||
1282
+ admission.request.taskId !== request.taskId ||
1283
+ admission.request.runId !== request.runId ||
1284
+ admission.request.scheduleReceiptFingerprint !==
1285
+ lease.schedule_receipt_fingerprint ||
1286
+ !sameOwner(admission.owner, lease.admission_owner))
1287
+ return empty("dispatch-lease-receipt-mismatch");
1288
+ if (!sameProjectWriteSet(admission.writeSet, lease.touches))
1289
+ return empty("dispatch-lease-write-set-mismatch");
1290
+ }
1291
+ catch {
1292
+ return empty("dispatch-lease-record-invalid");
1293
+ }
1294
+ if (preSpawn) {
1295
+ const expectedOwner = normalizeOwner(preSpawn.owner);
1296
+ if (preSpawn.scheduleReceiptFingerprint !==
1297
+ lease.schedule_receipt_fingerprint)
1298
+ return empty("schedule-receipt-fingerprint-mismatch");
1299
+ if (!expectedOwner ||
1300
+ !sameOwner(expectedOwner, lease.admission_owner) ||
1301
+ !sameOwner(expectedOwner, lease.dispatch_owner))
1302
+ return empty("dispatch-lease-owner-mismatch");
1303
+ }
1304
+ let schedule;
1305
+ try {
1306
+ schedule = readTaskKernelScheduleReceipt(root, lease.schedule_receipt_fingerprint);
1307
+ }
1308
+ catch {
1309
+ return empty("schedule-receipt-integrity-failed");
1310
+ }
1311
+ let inspected;
1312
+ try {
1313
+ inspected = inspectTaskRun(root, schedule, {
1314
+ scheduleReceiptFingerprint: lease.schedule_receipt_fingerprint,
1315
+ taskId: request.taskId,
1316
+ runId: request.runId,
1317
+ }, false);
1318
+ }
1319
+ catch {
1320
+ return empty("task-kernel-snapshot-invalid-or-missing");
1321
+ }
1322
+ if (!inspected.checked) {
1323
+ if (!request.allowSettled)
1324
+ return empty(inspected.reasonCodes[0] ?? "task-run-not-dispatchable");
1325
+ let read;
1326
+ try {
1327
+ const taskDir = resolveTaskDir(root, request.taskId);
1328
+ read = readTaskKernel({ root, taskDir });
1329
+ }
1330
+ catch {
1331
+ return empty("task-kernel-snapshot-invalid-or-missing");
1332
+ }
1333
+ if (read.kind !== "task-kernel-v2" ||
1334
+ read.kernel.runs.at(-1)?.id !== request.runId)
1335
+ return empty("task-run-id-mismatch");
1336
+ const settledRun = read.kernel.runs.at(-1);
1337
+ if (!settledRun ||
1338
+ !["completed", "failed", "blocked"].includes(settledRun.state))
1339
+ return empty(inspected.reasonCodes[0] ?? "task-run-not-settled");
1340
+ const dependencies = [...read.kernel.definition.dependencies];
1341
+ for (const dependencyId of dependencies) {
1342
+ let dependency;
1343
+ try {
1344
+ const dependencyDir = resolveTaskDirectoryById(root, dependencyId);
1345
+ if (!dependencyDir)
1346
+ return empty(`hard-dependency-missing-or-invalid:${dependencyId}`);
1347
+ dependency = readTaskKernel({
1348
+ root,
1349
+ taskDir: dependencyDir,
1350
+ });
1351
+ }
1352
+ catch {
1353
+ return empty(`hard-dependency-missing-or-invalid:${dependencyId}`);
1354
+ }
1355
+ if (dependency.kind !== "task-kernel-v2")
1356
+ return empty(`hard-dependency-not-v2-closed:${dependencyId}`);
1357
+ const projection = projectTaskKernelLifecycle(dependency.kernel);
1358
+ if (!projection.closed || projection.outcome !== "completed")
1359
+ return empty(`hard-dependency-not-closed:${dependencyId}`);
1360
+ }
1361
+ const latestRun = read.kernel.runs.at(-1);
1362
+ if (!latestRun)
1363
+ return empty("task-run-missing");
1364
+ const ownerBindingReason = verifyOwnerBinding(root, lease, read.kernel, latestRun);
1365
+ if (ownerBindingReason)
1366
+ return empty(ownerBindingReason);
1367
+ const currentWriteSet = normalizeProjectWriteSet([
1368
+ ...latestRun.writeSetSnapshot,
1369
+ ...(latestRun.workspace?.writeSet ?? []),
1370
+ ]);
1371
+ if (!writeSetCoveredByLease(currentWriteSet, lease.touches))
1372
+ return empty("task-run-write-set-expanded");
1373
+ return {
1374
+ asserted: true,
1375
+ reasonCode: null,
1376
+ leaseId: lease.id,
1377
+ taskId: lease.task_id,
1378
+ runId: lease.run_id,
1379
+ scheduleReceiptFingerprint: lease.schedule_receipt_fingerprint,
1380
+ writeSet: lease.touches,
1381
+ };
1382
+ }
1383
+ const checked = inspected.checked;
1384
+ if (!checked)
1385
+ return empty("task-run-not-dispatchable");
1386
+ let coordinationReason;
1387
+ try {
1388
+ coordinationReason = withCoordinationJournalLock(root, () => coordinationDispatchReason(root, request.taskId, checked.kernel, checked.run));
1389
+ }
1390
+ catch (error) {
1391
+ if (error instanceof CoordinationError)
1392
+ return empty("coordination-state-unreadable");
1393
+ throw error;
1394
+ }
1395
+ if (coordinationReason)
1396
+ return empty(coordinationReason);
1397
+ if (!writeSetCoveredByLease(checked.writeSet, lease.touches))
1398
+ return empty("task-run-write-set-expanded");
1399
+ if (!sameProjectWriteSet(admission.writeSet, lease.touches))
1400
+ return empty("dispatch-lease-write-set-mismatch");
1401
+ if (preSpawn) {
1402
+ if (checked.run.host)
1403
+ return empty("task-run-host-already-bound");
1404
+ if (lease.owner_binding_receipt_fingerprint ||
1405
+ !sameOwner(lease.admission_owner, lease.dispatch_owner))
1406
+ return empty("owner-binding-receipt-required");
1407
+ const ownerBindingReason = verifyOwnerBinding(root, lease, checked.kernel, checked.run);
1408
+ if (ownerBindingReason &&
1409
+ ownerBindingReason !== "task-run-host-binding-mismatch")
1410
+ return empty(ownerBindingReason);
1411
+ }
1412
+ else {
1413
+ const ownerBindingReason = verifyOwnerBinding(root, lease, checked.kernel, checked.run);
1414
+ if (ownerBindingReason)
1415
+ return empty(ownerBindingReason);
1416
+ }
1417
+ return {
1418
+ asserted: true,
1419
+ reasonCode: null,
1420
+ leaseId: lease.id,
1421
+ taskId: lease.task_id,
1422
+ runId: lease.run_id,
1423
+ scheduleReceiptFingerprint: lease.schedule_receipt_fingerprint,
1424
+ writeSet: lease.touches,
1425
+ };
1426
+ });
1427
+ }
1428
+ /** Read-only proof gate, usable by host adapters before mutating the lease. */
1429
+ export function validateTaskKernelRunDispatchStopProofV1(rootValue, request) {
1430
+ const root = path.resolve(rootValue);
1431
+ return withProjectSchedulerMutex(root, () => {
1432
+ const leaseFile = projectActiveLeasePath(root, request.leaseId);
1433
+ if (!fs.existsSync(leaseFile))
1434
+ return {
1435
+ valid: false,
1436
+ reasonCode: "dispatch-lease-not-active",
1437
+ proof: null,
1438
+ };
1439
+ let lease;
1440
+ try {
1441
+ lease = JSON.parse(fs.readFileSync(leaseFile, "utf8"));
1442
+ }
1443
+ catch {
1444
+ return {
1445
+ valid: false,
1446
+ reasonCode: "dispatch-lease-record-invalid",
1447
+ proof: null,
1448
+ };
1449
+ }
1450
+ if (lease.owner_kind !== "task-kernel-v2-run" ||
1451
+ lease.id !== request.leaseId ||
1452
+ lease.task_id !== request.taskId ||
1453
+ lease.run_id !== request.runId ||
1454
+ lease.status !== "active" ||
1455
+ !validOwner(lease.admission_owner) ||
1456
+ !validOwner(lease.dispatch_owner))
1457
+ return {
1458
+ valid: false,
1459
+ reasonCode: "dispatch-lease-identity-mismatch",
1460
+ proof: null,
1461
+ };
1462
+ if (!nonEmptyString(request.stopReceiptRef))
1463
+ return {
1464
+ valid: false,
1465
+ reasonCode: "verified-stop-receipt-required",
1466
+ proof: null,
1467
+ };
1468
+ return validateStopProofForActiveLease(root, request, lease);
1469
+ });
1470
+ }
1471
+ /** Releases only after a caller has persisted its verified terminal stop receipt. */
1472
+ export function releaseTaskKernelRunDispatchV1(rootValue, request) {
1473
+ const root = path.resolve(rootValue);
1474
+ return withProjectSchedulerMutex(root, () => {
1475
+ const leaseFile = projectActiveLeasePath(root, request.leaseId);
1476
+ const historyFile = projectLeaseHistoryPath(root, request.leaseId);
1477
+ if (!fs.existsSync(leaseFile)) {
1478
+ const history = fs.existsSync(historyFile)
1479
+ ? relative(root, historyFile)
1480
+ : null;
1481
+ return {
1482
+ released: false,
1483
+ reasonCode: history
1484
+ ? "lease-already-released"
1485
+ : "dispatch-lease-not-found",
1486
+ leaseId: request.leaseId,
1487
+ receiptFile: history,
1488
+ };
1489
+ }
1490
+ let value;
1491
+ try {
1492
+ value = JSON.parse(fs.readFileSync(leaseFile, "utf8"));
1493
+ }
1494
+ catch {
1495
+ return {
1496
+ released: false,
1497
+ reasonCode: "dispatch-lease-record-invalid",
1498
+ leaseId: request.leaseId,
1499
+ receiptFile: null,
1500
+ };
1501
+ }
1502
+ if (value.owner_kind !== "task-kernel-v2-run" ||
1503
+ value.id !== request.leaseId ||
1504
+ value.task_id !== request.taskId ||
1505
+ value.run_id !== request.runId ||
1506
+ value.status !== "active" ||
1507
+ !validOwner(value.admission_owner) ||
1508
+ !validOwner(value.dispatch_owner))
1509
+ return {
1510
+ released: false,
1511
+ reasonCode: "dispatch-lease-identity-mismatch",
1512
+ leaseId: request.leaseId,
1513
+ receiptFile: null,
1514
+ };
1515
+ if (!nonEmptyString(request.stopReceiptRef))
1516
+ return {
1517
+ released: false,
1518
+ reasonCode: "verified-stop-receipt-required",
1519
+ leaseId: request.leaseId,
1520
+ receiptFile: null,
1521
+ };
1522
+ const validation = validateStopProofForActiveLease(root, request, value);
1523
+ if (!validation.valid)
1524
+ return {
1525
+ released: false,
1526
+ reasonCode: validation.reasonCode,
1527
+ leaseId: request.leaseId,
1528
+ receiptFile: null,
1529
+ };
1530
+ const proofFile = projectFile(root, request.stopReceiptRef);
1531
+ const history = {
1532
+ ...value,
1533
+ status: "released",
1534
+ released_at: new Date().toISOString(),
1535
+ stop_receipt_ref: relative(root, proofFile),
1536
+ stop_proof_fingerprint: validation.proof.proof_fingerprint,
1537
+ release_disposition: validation.proof.disposition,
1538
+ };
1539
+ fs.mkdirSync(path.dirname(historyFile), { recursive: true });
1540
+ if (fs.existsSync(historyFile))
1541
+ return {
1542
+ released: false,
1543
+ reasonCode: "lease-history-already-exists",
1544
+ leaseId: request.leaseId,
1545
+ receiptFile: relative(root, historyFile),
1546
+ };
1547
+ fs.writeFileSync(historyFile, `${JSON.stringify(history, null, 2)}\n`, {
1548
+ flag: "wx",
1549
+ mode: 0o600,
1550
+ });
1551
+ fs.rmSync(leaseFile, { force: true });
1552
+ return {
1553
+ released: true,
1554
+ reasonCode: null,
1555
+ leaseId: request.leaseId,
1556
+ receiptFile: relative(root, historyFile),
1557
+ };
1558
+ });
1559
+ }
1560
+ //# sourceMappingURL=task-kernel-admission.js.map