@scotthuang/agent-knock-knock 0.12.11 → 0.12.13

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 (344) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +43 -30
  3. package/dist/src/approval-policy.d.ts +11 -2
  4. package/dist/src/approval-policy.js +33 -7
  5. package/dist/src/approval-policy.js.map +1 -1
  6. package/dist/src/callback-cli-adapter.d.ts +47 -0
  7. package/dist/src/callback-cli-adapter.js +156 -0
  8. package/dist/src/callback-cli-adapter.js.map +1 -0
  9. package/dist/src/callback-outbox-policy.d.ts +95 -0
  10. package/dist/src/callback-outbox-policy.js +149 -0
  11. package/dist/src/callback-outbox-policy.js.map +1 -0
  12. package/dist/src/callback-outbox-service.d.ts +247 -0
  13. package/dist/src/callback-outbox-service.js +1053 -0
  14. package/dist/src/callback-outbox-service.js.map +1 -0
  15. package/dist/src/callback-outbox-settlement.d.ts +54 -0
  16. package/dist/src/callback-outbox-settlement.js +241 -0
  17. package/dist/src/callback-outbox-settlement.js.map +1 -0
  18. package/dist/src/canonical-json.d.ts +1 -0
  19. package/dist/src/canonical-json.js +14 -0
  20. package/dist/src/canonical-json.js.map +1 -0
  21. package/dist/src/claude-lifecycle-compatibility.js +15 -0
  22. package/dist/src/claude-lifecycle-compatibility.js.map +1 -1
  23. package/dist/src/claude-local-transcript-provider.d.ts +82 -1
  24. package/dist/src/claude-local-transcript-provider.js +873 -23
  25. package/dist/src/claude-local-transcript-provider.js.map +1 -1
  26. package/dist/src/cli-command-runtime.d.ts +14 -0
  27. package/dist/src/cli-command-runtime.js +164 -0
  28. package/dist/src/cli-command-runtime.js.map +1 -0
  29. package/dist/src/cli-core.d.ts +4 -42
  30. package/dist/src/cli-core.js +958 -28684
  31. package/dist/src/cli-core.js.map +1 -1
  32. package/dist/src/cli-runtime-context.d.ts +57 -0
  33. package/dist/src/cli-runtime-context.js +118 -0
  34. package/dist/src/cli-runtime-context.js.map +1 -0
  35. package/dist/src/codex-lifecycle-compatibility.js +2 -1
  36. package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
  37. package/dist/src/codex-local-session-provider.d.ts +18 -0
  38. package/dist/src/codex-local-session-provider.js +67 -0
  39. package/dist/src/codex-local-session-provider.js.map +1 -1
  40. package/dist/src/codex-session-provider.js +1 -3
  41. package/dist/src/codex-session-provider.js.map +1 -1
  42. package/dist/src/conversation-trace.d.ts +30 -0
  43. package/dist/src/conversation-trace.js +185 -0
  44. package/dist/src/conversation-trace.js.map +1 -0
  45. package/dist/src/deferred-foreground-application-service.d.ts +84 -0
  46. package/dist/src/deferred-foreground-application-service.js +742 -0
  47. package/dist/src/deferred-foreground-application-service.js.map +1 -0
  48. package/dist/src/deferred-foreground-authority-cli-adapter.d.ts +78 -0
  49. package/dist/src/deferred-foreground-authority-cli-adapter.js +795 -0
  50. package/dist/src/deferred-foreground-authority-cli-adapter.js.map +1 -0
  51. package/dist/src/deferred-foreground-boundary.d.ts +61 -0
  52. package/dist/src/deferred-foreground-boundary.js +2 -0
  53. package/dist/src/deferred-foreground-boundary.js.map +1 -0
  54. package/dist/src/deferred-foreground-capability.d.ts +4 -0
  55. package/dist/src/deferred-foreground-capability.js +184 -0
  56. package/dist/src/deferred-foreground-capability.js.map +1 -0
  57. package/dist/src/deferred-foreground-preparation-cli-adapter.d.ts +53 -0
  58. package/dist/src/deferred-foreground-preparation-cli-adapter.js +210 -0
  59. package/dist/src/deferred-foreground-preparation-cli-adapter.js.map +1 -0
  60. package/dist/src/deferred-foreground-preparation-service.d.ts +72 -0
  61. package/dist/src/deferred-foreground-preparation-service.js +179 -0
  62. package/dist/src/deferred-foreground-preparation-service.js.map +1 -0
  63. package/dist/src/deferred-foreground-recovery-cli-adapter.d.ts +139 -0
  64. package/dist/src/deferred-foreground-recovery-cli-adapter.js +1125 -0
  65. package/dist/src/deferred-foreground-recovery-cli-adapter.js.map +1 -0
  66. package/dist/src/deferred-foreground-recovery-service.d.ts +48 -0
  67. package/dist/src/deferred-foreground-recovery-service.js +91 -0
  68. package/dist/src/deferred-foreground-recovery-service.js.map +1 -0
  69. package/dist/src/deferred-foreground-transfer-policy.d.ts +2 -0
  70. package/dist/src/deferred-foreground-transfer-policy.js +10 -0
  71. package/dist/src/deferred-foreground-transfer-policy.js.map +1 -0
  72. package/dist/src/deferred-foreground-transfer.js +46 -105
  73. package/dist/src/deferred-foreground-transfer.js.map +1 -1
  74. package/dist/src/doctor-capabilities.d.ts +9 -0
  75. package/dist/src/doctor-capabilities.js +22 -0
  76. package/dist/src/doctor-capabilities.js.map +1 -1
  77. package/dist/src/durable-json-file.d.ts +22 -0
  78. package/dist/src/durable-json-file.js +127 -0
  79. package/dist/src/durable-json-file.js.map +1 -0
  80. package/dist/src/file-lock-cli-adapter.d.ts +43 -0
  81. package/dist/src/file-lock-cli-adapter.js +150 -0
  82. package/dist/src/file-lock-cli-adapter.js.map +1 -0
  83. package/dist/src/herdr-terminal-control-provider.js +1 -3
  84. package/dist/src/herdr-terminal-control-provider.js.map +1 -1
  85. package/dist/src/install-doctor-command-adapter.d.ts +17 -0
  86. package/dist/src/install-doctor-command-adapter.js +225 -0
  87. package/dist/src/install-doctor-command-adapter.js.map +1 -0
  88. package/dist/src/live-lifecycle-evidence.js +76 -46
  89. package/dist/src/live-lifecycle-evidence.js.map +1 -1
  90. package/dist/src/live-lifecycle-smoke.js +74 -50
  91. package/dist/src/live-lifecycle-smoke.js.map +1 -1
  92. package/dist/src/managed-session.d.ts +2 -0
  93. package/dist/src/managed-session.js +24 -0
  94. package/dist/src/managed-session.js.map +1 -1
  95. package/dist/src/managed-turn-recovery-service.d.ts +86 -0
  96. package/dist/src/managed-turn-recovery-service.js +145 -0
  97. package/dist/src/managed-turn-recovery-service.js.map +1 -0
  98. package/dist/src/mutation-transaction.d.ts +48 -0
  99. package/dist/src/mutation-transaction.js +73 -0
  100. package/dist/src/mutation-transaction.js.map +1 -0
  101. package/dist/src/native-thread-lifecycle-cli-adapter.d.ts +154 -0
  102. package/dist/src/native-thread-lifecycle-cli-adapter.js +786 -0
  103. package/dist/src/native-thread-lifecycle-cli-adapter.js.map +1 -0
  104. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.d.ts +25 -0
  105. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js +50 -0
  106. package/dist/src/native-thread-lifecycle-ledger-cli-adapter.js.map +1 -0
  107. package/dist/src/native-thread-lifecycle-query-service.d.ts +75 -0
  108. package/dist/src/native-thread-lifecycle-query-service.js +297 -0
  109. package/dist/src/native-thread-lifecycle-query-service.js.map +1 -0
  110. package/dist/src/native-thread-lifecycle-recovery-adapter.d.ts +45 -0
  111. package/dist/src/native-thread-lifecycle-recovery-adapter.js +154 -0
  112. package/dist/src/native-thread-lifecycle-recovery-adapter.js.map +1 -0
  113. package/dist/src/native-thread-lifecycle-recovery-service.d.ts +211 -0
  114. package/dist/src/native-thread-lifecycle-recovery-service.js +1093 -0
  115. package/dist/src/native-thread-lifecycle-recovery-service.js.map +1 -0
  116. package/dist/src/native-thread-resume-snapshot-policy.d.ts +73 -0
  117. package/dist/src/native-thread-resume-snapshot-policy.js +218 -0
  118. package/dist/src/native-thread-resume-snapshot-policy.js.map +1 -0
  119. package/dist/src/native-thread-resume-snapshot.d.ts +3 -61
  120. package/dist/src/native-thread-resume-snapshot.js +2 -143
  121. package/dist/src/native-thread-resume-snapshot.js.map +1 -1
  122. package/dist/src/native-thread-transition-application.d.ts +147 -0
  123. package/dist/src/native-thread-transition-application.js +974 -0
  124. package/dist/src/native-thread-transition-application.js.map +1 -0
  125. package/dist/src/native-thread-transition-policy.d.ts +127 -0
  126. package/dist/src/native-thread-transition-policy.js +154 -0
  127. package/dist/src/native-thread-transition-policy.js.map +1 -0
  128. package/dist/src/native-thread-transition-resource-adapter.d.ts +12 -0
  129. package/dist/src/native-thread-transition-resource-adapter.js +44 -0
  130. package/dist/src/native-thread-transition-resource-adapter.js.map +1 -0
  131. package/dist/src/native-thread-transition-settlement-service.d.ts +94 -0
  132. package/dist/src/native-thread-transition-settlement-service.js +134 -0
  133. package/dist/src/native-thread-transition-settlement-service.js.map +1 -0
  134. package/dist/src/native-thread-transition-verification-adapter.d.ts +62 -0
  135. package/dist/src/native-thread-transition-verification-adapter.js +451 -0
  136. package/dist/src/native-thread-transition-verification-adapter.js.map +1 -0
  137. package/dist/src/openclaw-callback-transport.d.ts +69 -0
  138. package/dist/src/openclaw-callback-transport.js +583 -0
  139. package/dist/src/openclaw-callback-transport.js.map +1 -0
  140. package/dist/src/openclaw-plugin-callback-adapter.d.ts +1 -0
  141. package/dist/src/openclaw-plugin-callback-adapter.js +423 -0
  142. package/dist/src/openclaw-plugin-callback-adapter.js.map +1 -0
  143. package/dist/src/openclaw-plugin-command-adapter.d.ts +16 -0
  144. package/dist/src/openclaw-plugin-command-adapter.js +1868 -0
  145. package/dist/src/openclaw-plugin-command-adapter.js.map +1 -0
  146. package/dist/src/openclaw-plugin-helpers.d.ts +27 -4
  147. package/dist/src/openclaw-plugin-helpers.js +356 -81
  148. package/dist/src/openclaw-plugin-helpers.js.map +1 -1
  149. package/dist/src/openclaw-plugin-schemas.d.ts +358 -0
  150. package/dist/src/openclaw-plugin-schemas.js +366 -0
  151. package/dist/src/openclaw-plugin-schemas.js.map +1 -0
  152. package/dist/src/openclaw-plugin-supervisor.d.ts +6 -0
  153. package/dist/src/openclaw-plugin-supervisor.js +123 -0
  154. package/dist/src/openclaw-plugin-supervisor.js.map +1 -0
  155. package/dist/src/openclaw-plugin.js +7 -2212
  156. package/dist/src/openclaw-plugin.js.map +1 -1
  157. package/dist/src/openclaw-private-authority-offers.d.ts +22 -0
  158. package/dist/src/openclaw-private-authority-offers.js +177 -0
  159. package/dist/src/openclaw-private-authority-offers.js.map +1 -0
  160. package/dist/src/protocol.d.ts +5 -0
  161. package/dist/src/protocol.js +59 -3
  162. package/dist/src/protocol.js.map +1 -1
  163. package/dist/src/session-store.d.ts +1 -0
  164. package/dist/src/session-store.js +84 -106
  165. package/dist/src/session-store.js.map +1 -1
  166. package/dist/src/store.d.ts +1 -0
  167. package/dist/src/store.js +5 -2
  168. package/dist/src/store.js.map +1 -1
  169. package/dist/src/terminal-acceptance-application-service.d.ts +65 -0
  170. package/dist/src/terminal-acceptance-application-service.js +63 -0
  171. package/dist/src/terminal-acceptance-application-service.js.map +1 -0
  172. package/dist/src/terminal-acceptance-cli-adapter.d.ts +210 -0
  173. package/dist/src/terminal-acceptance-cli-adapter.js +957 -0
  174. package/dist/src/terminal-acceptance-cli-adapter.js.map +1 -0
  175. package/dist/src/terminal-action-projection.d.ts +309 -0
  176. package/dist/src/terminal-action-projection.js +376 -0
  177. package/dist/src/terminal-action-projection.js.map +1 -0
  178. package/dist/src/terminal-agent-bridge.d.ts +3 -0
  179. package/dist/src/terminal-agent-bridge.js +29 -8
  180. package/dist/src/terminal-agent-bridge.js.map +1 -1
  181. package/dist/src/terminal-authority-policy.d.ts +141 -0
  182. package/dist/src/terminal-authority-policy.js +367 -0
  183. package/dist/src/terminal-authority-policy.js.map +1 -0
  184. package/dist/src/terminal-binding-authority.d.ts +118 -0
  185. package/dist/src/terminal-binding-authority.js +245 -0
  186. package/dist/src/terminal-binding-authority.js.map +1 -0
  187. package/dist/src/terminal-binding-reconciliation-service.d.ts +75 -0
  188. package/dist/src/terminal-binding-reconciliation-service.js +73 -0
  189. package/dist/src/terminal-binding-reconciliation-service.js.map +1 -0
  190. package/dist/src/terminal-command-cli-adapter.d.ts +380 -0
  191. package/dist/src/terminal-command-cli-adapter.js +3288 -0
  192. package/dist/src/terminal-command-cli-adapter.js.map +1 -0
  193. package/dist/src/terminal-control-ref.d.ts +4 -0
  194. package/dist/src/terminal-control-ref.js +11 -8
  195. package/dist/src/terminal-control-ref.js.map +1 -1
  196. package/dist/src/terminal-delegate-cli-adapter.d.ts +41 -0
  197. package/dist/src/terminal-delegate-cli-adapter.js +242 -0
  198. package/dist/src/terminal-delegate-cli-adapter.js.map +1 -0
  199. package/dist/src/terminal-dispatch-abort.d.ts +22 -0
  200. package/dist/src/terminal-dispatch-abort.js +30 -0
  201. package/dist/src/terminal-dispatch-abort.js.map +1 -0
  202. package/dist/src/terminal-dispatch-application.d.ts +115 -0
  203. package/dist/src/terminal-dispatch-application.js +478 -0
  204. package/dist/src/terminal-dispatch-application.js.map +1 -0
  205. package/dist/src/terminal-dispatch-capability.d.ts +63 -0
  206. package/dist/src/terminal-dispatch-capability.js +133 -0
  207. package/dist/src/terminal-dispatch-capability.js.map +1 -0
  208. package/dist/src/terminal-dispatch-completion-cli-adapter.d.ts +22 -0
  209. package/dist/src/terminal-dispatch-completion-cli-adapter.js +96 -0
  210. package/dist/src/terminal-dispatch-completion-cli-adapter.js.map +1 -0
  211. package/dist/src/terminal-dispatch-composition.d.ts +79 -0
  212. package/dist/src/terminal-dispatch-composition.js +2 -0
  213. package/dist/src/terminal-dispatch-composition.js.map +1 -0
  214. package/dist/src/terminal-dispatch-execution.d.ts +290 -0
  215. package/dist/src/terminal-dispatch-execution.js +916 -0
  216. package/dist/src/terminal-dispatch-execution.js.map +1 -0
  217. package/dist/src/terminal-dispatch-ledger-codec.d.ts +110 -0
  218. package/dist/src/terminal-dispatch-ledger-codec.js +399 -0
  219. package/dist/src/terminal-dispatch-ledger-codec.js.map +1 -0
  220. package/dist/src/terminal-dispatch-policy.d.ts +93 -0
  221. package/dist/src/terminal-dispatch-policy.js +122 -0
  222. package/dist/src/terminal-dispatch-policy.js.map +1 -0
  223. package/dist/src/terminal-dispatch-presenter.d.ts +65 -0
  224. package/dist/src/terminal-dispatch-presenter.js +258 -0
  225. package/dist/src/terminal-dispatch-presenter.js.map +1 -0
  226. package/dist/src/terminal-dispatch-receipt.d.ts +79 -0
  227. package/dist/src/terminal-dispatch-receipt.js +314 -0
  228. package/dist/src/terminal-dispatch-receipt.js.map +1 -0
  229. package/dist/src/terminal-dispatch-recovery-cli-adapter.d.ts +132 -0
  230. package/dist/src/terminal-dispatch-recovery-cli-adapter.js +1330 -0
  231. package/dist/src/terminal-dispatch-recovery-cli-adapter.js.map +1 -0
  232. package/dist/src/terminal-dispatch-recovery-service.d.ts +271 -0
  233. package/dist/src/terminal-dispatch-recovery-service.js +374 -0
  234. package/dist/src/terminal-dispatch-recovery-service.js.map +1 -0
  235. package/dist/src/terminal-dispatch-repository-cli-adapter.d.ts +35 -0
  236. package/dist/src/terminal-dispatch-repository-cli-adapter.js +483 -0
  237. package/dist/src/terminal-dispatch-repository-cli-adapter.js.map +1 -0
  238. package/dist/src/terminal-handoff-application-service.d.ts +7 -0
  239. package/dist/src/terminal-handoff-application-service.js +18 -0
  240. package/dist/src/terminal-handoff-application-service.js.map +1 -0
  241. package/dist/src/terminal-handoff-cli-adapter.d.ts +229 -0
  242. package/dist/src/terminal-handoff-cli-adapter.js +1389 -0
  243. package/dist/src/terminal-handoff-cli-adapter.js.map +1 -0
  244. package/dist/src/terminal-handoff-facts.d.ts +12 -0
  245. package/dist/src/terminal-handoff-facts.js +16 -0
  246. package/dist/src/terminal-handoff-facts.js.map +1 -0
  247. package/dist/src/terminal-identity-authority-cli-adapter.d.ts +318 -0
  248. package/dist/src/terminal-identity-authority-cli-adapter.js +1072 -0
  249. package/dist/src/terminal-identity-authority-cli-adapter.js.map +1 -0
  250. package/dist/src/terminal-identity-authority-service.d.ts +48 -0
  251. package/dist/src/terminal-identity-authority-service.js +45 -0
  252. package/dist/src/terminal-identity-authority-service.js.map +1 -0
  253. package/dist/src/terminal-list-cli-adapter.d.ts +274 -0
  254. package/dist/src/terminal-list-cli-adapter.js +2444 -0
  255. package/dist/src/terminal-list-cli-adapter.js.map +1 -0
  256. package/dist/src/terminal-list-renderer.d.ts +34 -0
  257. package/dist/src/terminal-list-renderer.js +643 -0
  258. package/dist/src/terminal-list-renderer.js.map +1 -0
  259. package/dist/src/terminal-maintenance-cli-adapter.d.ts +102 -0
  260. package/dist/src/terminal-maintenance-cli-adapter.js +1059 -0
  261. package/dist/src/terminal-maintenance-cli-adapter.js.map +1 -0
  262. package/dist/src/terminal-monitor-application-service.d.ts +275 -0
  263. package/dist/src/terminal-monitor-application-service.js +982 -0
  264. package/dist/src/terminal-monitor-application-service.js.map +1 -0
  265. package/dist/src/terminal-monitor-cli-adapter.d.ts +130 -0
  266. package/dist/src/terminal-monitor-cli-adapter.js +442 -0
  267. package/dist/src/terminal-monitor-cli-adapter.js.map +1 -0
  268. package/dist/src/terminal-monitor-decision-policy.d.ts +98 -0
  269. package/dist/src/terminal-monitor-decision-policy.js +246 -0
  270. package/dist/src/terminal-monitor-decision-policy.js.map +1 -0
  271. package/dist/src/terminal-monitor-launch-plan.d.ts +45 -0
  272. package/dist/src/terminal-monitor-launch-plan.js +94 -0
  273. package/dist/src/terminal-monitor-launch-plan.js.map +1 -0
  274. package/dist/src/terminal-monitor-ownership-policy.d.ts +31 -0
  275. package/dist/src/terminal-monitor-ownership-policy.js +64 -0
  276. package/dist/src/terminal-monitor-ownership-policy.js.map +1 -0
  277. package/dist/src/terminal-monitor-poll-policy.d.ts +48 -0
  278. package/dist/src/terminal-monitor-poll-policy.js +67 -0
  279. package/dist/src/terminal-monitor-poll-policy.js.map +1 -0
  280. package/dist/src/terminal-monitor-reconciliation-eligibility.d.ts +53 -0
  281. package/dist/src/terminal-monitor-reconciliation-eligibility.js +114 -0
  282. package/dist/src/terminal-monitor-reconciliation-eligibility.js.map +1 -0
  283. package/dist/src/terminal-monitor-state-cli-adapter.d.ts +106 -0
  284. package/dist/src/terminal-monitor-state-cli-adapter.js +1492 -0
  285. package/dist/src/terminal-monitor-state-cli-adapter.js.map +1 -0
  286. package/dist/src/terminal-monitor-state-reconciliation-service.d.ts +87 -0
  287. package/dist/src/terminal-monitor-state-reconciliation-service.js +106 -0
  288. package/dist/src/terminal-monitor-state-reconciliation-service.js.map +1 -0
  289. package/dist/src/terminal-monitor-supervision-cli-adapter.d.ts +122 -0
  290. package/dist/src/terminal-monitor-supervision-cli-adapter.js +685 -0
  291. package/dist/src/terminal-monitor-supervision-cli-adapter.js.map +1 -0
  292. package/dist/src/terminal-process-facts.d.ts +2 -0
  293. package/dist/src/terminal-process-facts.js +19 -0
  294. package/dist/src/terminal-process-facts.js.map +1 -0
  295. package/dist/src/terminal-process-source.d.ts +6 -4
  296. package/dist/src/terminal-process-source.js +25 -20
  297. package/dist/src/terminal-process-source.js.map +1 -1
  298. package/dist/src/terminal-runtime-cli-adapter.d.ts +80 -0
  299. package/dist/src/terminal-runtime-cli-adapter.js +488 -0
  300. package/dist/src/terminal-runtime-cli-adapter.js.map +1 -0
  301. package/dist/src/terminal-scoped-approval-authority.d.ts +62 -0
  302. package/dist/src/terminal-scoped-approval-authority.js +281 -0
  303. package/dist/src/terminal-scoped-approval-authority.js.map +1 -0
  304. package/dist/src/terminal-selector-projection-service.d.ts +26 -0
  305. package/dist/src/terminal-selector-projection-service.js +81 -0
  306. package/dist/src/terminal-selector-projection-service.js.map +1 -0
  307. package/dist/src/terminal-status-cli-adapter.d.ts +126 -0
  308. package/dist/src/terminal-status-cli-adapter.js +577 -0
  309. package/dist/src/terminal-status-cli-adapter.js.map +1 -0
  310. package/dist/src/terminal-status-facts.d.ts +56 -0
  311. package/dist/src/terminal-status-facts.js +199 -0
  312. package/dist/src/terminal-status-facts.js.map +1 -0
  313. package/dist/src/terminal-submission-acceptance.d.ts +62 -145
  314. package/dist/src/terminal-submission-acceptance.js +555 -222
  315. package/dist/src/terminal-submission-acceptance.js.map +1 -1
  316. package/dist/src/terminal-submission-facts.d.ts +123 -0
  317. package/dist/src/terminal-submission-facts.js +205 -0
  318. package/dist/src/terminal-submission-facts.js.map +1 -0
  319. package/dist/src/terminal-turn-binding-authority-cli-adapter.d.ts +14 -0
  320. package/dist/src/terminal-turn-binding-authority-cli-adapter.js +90 -0
  321. package/dist/src/terminal-turn-binding-authority-cli-adapter.js.map +1 -0
  322. package/dist/src/terminal-watch-callback-cli-adapter.d.ts +20 -0
  323. package/dist/src/terminal-watch-callback-cli-adapter.js +55 -0
  324. package/dist/src/terminal-watch-callback-cli-adapter.js.map +1 -0
  325. package/dist/src/terminal-watch-cli-adapter.d.ts +64 -0
  326. package/dist/src/terminal-watch-cli-adapter.js +508 -0
  327. package/dist/src/terminal-watch-cli-adapter.js.map +1 -0
  328. package/dist/src/terminal-watch-service.d.ts +97 -0
  329. package/dist/src/terminal-watch-service.js +714 -0
  330. package/dist/src/terminal-watch-service.js.map +1 -0
  331. package/dist/src/terminal-watch-store.d.ts +149 -0
  332. package/dist/src/terminal-watch-store.js +861 -0
  333. package/dist/src/terminal-watch-store.js.map +1 -0
  334. package/dist/src/value-guards.d.ts +4 -0
  335. package/dist/src/value-guards.js +12 -0
  336. package/dist/src/value-guards.js.map +1 -0
  337. package/dist/src/verified-dead-agent-policy.d.ts +192 -0
  338. package/dist/src/verified-dead-agent-policy.js +262 -0
  339. package/dist/src/verified-dead-agent-policy.js.map +1 -0
  340. package/docs/quickstart-herdr.md +8 -0
  341. package/docs/quickstart-tmux.md +33 -6
  342. package/openclaw.plugin.json +11 -3
  343. package/package.json +3 -1
  344. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +58 -40
@@ -0,0 +1,974 @@
1
+ import path from "node:path";
2
+ import { createManagedSessionId, createNativeThreadTransitionId, isExactNativeThreadId, managedSessionBindingToken, managedSessionRevision, nativeThreadTransitionRevision, nativeThreadCommandFingerprint, terminalBindingFrom } from "./managed-session.js";
3
+ import { assertRestorableOriginSessionRelationship as assertRestorableOriginSessionRelationshipFromQuery, requireRestorableLifecycleOrigin as requireRestorableLifecycleOriginFromQuery, resumableNativeThreadCandidates, revalidateNativeThreadCandidate as revalidateNativeThreadCandidateFromQuery } from "./native-thread-lifecycle-query-service.js";
4
+ import { decideResumeCandidateEligibility, decideResumeTargetSession, prepareNativeThreadTransition, reduceNativeThreadTransitionPhase } from "./native-thread-transition-policy.js";
5
+ import { settleFailedNativeThreadTransition, settleVerifiedNativeThreadTransition } from "./native-thread-transition-settlement-service.js";
6
+ import { reconcileLifecycleDispatchLedger as reconcileLifecycleDispatchLedgerService, recoverLifecycleFenceBeforeMutation as recoverLifecycleFenceBeforeMutationService } from "./native-thread-lifecycle-recovery-service.js";
7
+ import { createNativeThreadLifecycleRecoveryProbeAdapter, lifecycleRecoveryRuntime, lifecycleRecoveryTerminalFacts } from "./native-thread-lifecycle-recovery-adapter.js";
8
+ import { nativeThreadTransitionResourceBoundOperation } from "./native-thread-transition-resource-adapter.js";
9
+ import { assertResumedNativeThreadMatchesCandidate as assertResumedCodexRolloutMatchesCandidate, nativeThreadCandidateFileIdentity as codexCandidateFileIdentity, prepareNativeThreadVerification, verifyNativeThreadTransition as verifyNativeThreadTransitionWithRuntime } from "./native-thread-transition-verification-adapter.js";
10
+ import { resolveNativeThreadResumeSelection } from "./native-thread-resume-snapshot.js";
11
+ import { assertResumeSnapshotActionFingerprint, assertResumeSnapshotCandidates, assertResumeSnapshotMatchesTerminal, assertResumeSnapshotNotExpired } from "./native-thread-resume-snapshot-policy.js";
12
+ import { commitVerifiedLifecycleTransition, listNativeThreadTransitions, loadManagedSession, loadNativeThreadTransition, saveManagedSession, saveNativeThreadTransition, tryLoadManagedSession } from "./session-store.js";
13
+ import { TerminalInputNotStartedError } from "./terminal-agent-bridge.js";
14
+ import { codexCompanionsExcludingPreferred, nativeIdentityMatchesCodexPreMaterialization, terminalControlAliasMatches, terminalControlsShareIncarnation } from "./terminal-authority-policy.js";
15
+ import { nativeThreadLifecycleLedger as lifecycleLedger, terminalDispatchLedgerLooksLifecycle } from "./terminal-dispatch-ledger-codec.js";
16
+ import { reconcileTerminalBinding } from "./terminal-binding-reconciliation-service.js";
17
+ import { withCanonicalMutationLocks } from "./mutation-transaction.js";
18
+ import { isSessionSendBlockingStatus, isTerminalDispatchOwnerReleasedStatus, turnIdForConversation } from "./protocol.js";
19
+ import { nonBlankString as stringValue } from "./value-guards.js";
20
+ function createNativeThreadTransitionBindings(ports) {
21
+ const { now: cliNow, nowMs: cliNowMs, pid: cliPid, cwd: cliCwd, sleep: cliSleep, exit: cliExit, log: runtimeLog, print: printJson, summarizeError: textSummary } = ports.runtime;
22
+ const cliEnv = () => new Proxy({}, {
23
+ get: (_target, property) => ports.runtime.env(String(property))
24
+ });
25
+ const nativeThreadLifecycleFacade = ports.lifecycle.facade;
26
+ const assertNativeThreadHasExclusiveOwnership = (input) => nativeThreadLifecycleFacade.assertExclusive(input);
27
+ const resolveLifecycleTerminal = nativeThreadLifecycleFacade.resolveLifecycleTerminal;
28
+ const nativeThreadLifecycleQueryPorts = nativeThreadLifecycleFacade.queryPorts;
29
+ const currentLifecycleSnapshot = nativeThreadLifecycleFacade.currentSnapshot;
30
+ const lifecycleBindingTokens = nativeThreadLifecycleFacade.lifecycleBindingTokens;
31
+ const assertSameNativeInspectionTerminal = nativeThreadLifecycleFacade.assertSameInspectionTerminal;
32
+ const storeDirFromOptions = ports.state.storeDir;
33
+ const terminalBridgeRuntimeDir = ports.state.runtimeDir;
34
+ const loadTerminalBridgeDispatchLedger = ports.state.loadLedger;
35
+ const reconcilePreparedTerminalDispatchLedger = ports.state.reconcilePrepared;
36
+ const resolveTerminalDispatchLedgerPaneIncarnation = ports.state.reconcileIncarnation;
37
+ const terminalDispatchRecordMatchesControl = ports.state.recordMatchesControl;
38
+ const saveLifecycleTerminalDispatchLedger = ports.state.lifecycleLedger.save;
39
+ const loadTerminalDispatchLedgerOwner = (ledger) => {
40
+ const status = ports.state.ordinaryOwnerStatus(ledger);
41
+ return status ? { status } : undefined;
42
+ };
43
+ const terminalListCliFacade = {
44
+ terminalIncarnationBlockingTurns: ports.state.blockingTurns,
45
+ terminalDispatchOwnership: ports.state.dispatchOwnership,
46
+ managedSessionHasUnresolvedNativeTransition: ports.state.hasUnresolvedTransition
47
+ };
48
+ const managedTurnsForSession = ports.state.managedTurns;
49
+ const terminalWriterMutationLocks = ports.mutation.locks;
50
+ const mutationManagedSessions = {
51
+ load: ports.mutation.loadSession,
52
+ save: ports.mutation.saveSession
53
+ };
54
+ const authenticateLifecycleRecoveryResources = ports.mutation.authenticate;
55
+ const createTerminalAgentBridge = (options) => ports.lifecycle.runtime(options).createBridge();
56
+ const loadClaudeAgentRows = (options, settings) => ports.lifecycle.runtime(options).loadClaudeAgentRows(settings);
57
+ const agentVersionForRunningProcess = (agent, pid, options) => ports.lifecycle.runtime(options)
58
+ .agentVersionForRunningProcess(agent, pid);
59
+ const terminalRuntimeForLiveIdentity = ports.lifecycle.runtimeForIdentity;
60
+ const resolveCurrentNativeAgentSessionIdentity = ports.lifecycle.resolveIdentity;
61
+ const assertCodexComposerReadyForAutomatedInput = ports.lifecycle.assertComposerReady;
62
+ const exactLifecycleProcessIdentity = ports.lifecycle.exactIdentity;
63
+ const managedSessionClaimsResolvedTerminal = ports.authority.sessionClaimsTerminal;
64
+ const managedBindingConflictKindForResolvedTerminal = ports.authority.conflictKind;
65
+ const managedSessionOwnerIsConclusivelyInactive = ports.authority.ownerIsInactive;
66
+ const observedExternalHandoffIdentity = ports.authority.observeExternal;
67
+ const recoverDeferredCodexForegroundTransferWhileWriterLease = ports.authority.recoverDeferred;
68
+ const codexKnownRootSetForLifecycleTransition = ports.authority.knownRoots;
69
+ const codexProcessBirthForLifecycle = ports.authority.codexProcessBirth;
70
+ const isProcessAlive = ports.authority.processAlive;
71
+ const matchesConfiguredWorkspace = ports.authority.workspaceMatches;
72
+ return Object.freeze({
73
+ cliNow, cliNowMs, cliPid, cliCwd, cliSleep, cliExit,
74
+ runtimeLog, printJson, textSummary, cliEnv,
75
+ nativeThreadLifecycleFacade, assertNativeThreadHasExclusiveOwnership,
76
+ resolveLifecycleTerminal, nativeThreadLifecycleQueryPorts,
77
+ currentLifecycleSnapshot, lifecycleBindingTokens,
78
+ assertSameNativeInspectionTerminal, storeDirFromOptions,
79
+ terminalBridgeRuntimeDir, loadTerminalBridgeDispatchLedger,
80
+ reconcilePreparedTerminalDispatchLedger,
81
+ resolveTerminalDispatchLedgerPaneIncarnation,
82
+ terminalDispatchRecordMatchesControl,
83
+ saveLifecycleTerminalDispatchLedger, loadTerminalDispatchLedgerOwner,
84
+ terminalListCliFacade, managedTurnsForSession,
85
+ terminalWriterMutationLocks, mutationManagedSessions,
86
+ authenticateLifecycleRecoveryResources, createTerminalAgentBridge,
87
+ loadClaudeAgentRows, agentVersionForRunningProcess,
88
+ terminalRuntimeForLiveIdentity,
89
+ resolveCurrentNativeAgentSessionIdentity,
90
+ assertCodexComposerReadyForAutomatedInput,
91
+ exactLifecycleProcessIdentity, managedSessionClaimsResolvedTerminal,
92
+ managedBindingConflictKindForResolvedTerminal,
93
+ managedSessionOwnerIsConclusivelyInactive,
94
+ observedExternalHandoffIdentity,
95
+ recoverDeferredCodexForegroundTransferWhileWriterLease,
96
+ codexKnownRootSetForLifecycleTransition,
97
+ codexProcessBirthForLifecycle, isProcessAlive,
98
+ matchesConfiguredWorkspace
99
+ });
100
+ }
101
+ function required(value, message) {
102
+ if (value === undefined || value === "")
103
+ throw new Error(message);
104
+ return value;
105
+ }
106
+ function positiveSafeInteger(value, optionName) {
107
+ if (typeof value !== "string" || !/^[1-9][0-9]*$/u.test(value)) {
108
+ throw new Error(`${optionName} must be a positive integer`);
109
+ }
110
+ const parsed = Number(value);
111
+ if (!Number.isSafeInteger(parsed)) {
112
+ throw new Error(`${optionName} must be a positive safe integer`);
113
+ }
114
+ return parsed;
115
+ }
116
+ function bindingTerminalFacts(terminal) {
117
+ return Object.freeze({
118
+ conversationId: terminal.conversationId,
119
+ agent: terminal.agent,
120
+ pid: terminal.pid,
121
+ terminalControl: terminal.terminalControl
122
+ });
123
+ }
124
+ export function createNativeThreadTransitionApplication(ports) {
125
+ const bindings = createNativeThreadTransitionBindings(ports);
126
+ let commands;
127
+ let recovery;
128
+ const runTransition = (options, operation) => runNativeThreadTransition(bindings, commands, recovery, options, operation);
129
+ commands = createNativeThreadTransitionCommandApplication(bindings, runTransition, (...args) => recovery.recoverBeforeMutation(...args));
130
+ recovery = createNativeThreadTransitionRecoveryApplication(bindings, commands.assertTargetExclusive);
131
+ return Object.freeze({
132
+ runNewThread: commands.runNewThread,
133
+ runResumeThread: commands.runResumeThread,
134
+ runReconcileBinding: commands.runReconcileBinding,
135
+ verificationPorts: commands.verificationPorts,
136
+ assertTerminalReady: commands.assertTerminalReady,
137
+ recoverBeforeMutation: recovery.recoverBeforeMutation,
138
+ reconcileLedger: recovery.reconcileLedger
139
+ });
140
+ }
141
+ function createNativeThreadTransitionCommandApplication(bindings, runTransition, recoverBeforeMutation) {
142
+ const { cliNow, cliCwd, cliSleep, runtimeLog, printJson, assertNativeThreadHasExclusiveOwnership, resolveLifecycleTerminal, lifecycleBindingTokens, storeDirFromOptions, terminalBridgeRuntimeDir, loadTerminalBridgeDispatchLedger, reconcilePreparedTerminalDispatchLedger, resolveTerminalDispatchLedgerPaneIncarnation, loadTerminalDispatchLedgerOwner, terminalListCliFacade, managedTurnsForSession, terminalWriterMutationLocks, mutationManagedSessions, createTerminalAgentBridge, loadClaudeAgentRows, agentVersionForRunningProcess, terminalRuntimeForLiveIdentity, resolveCurrentNativeAgentSessionIdentity, managedSessionClaimsResolvedTerminal, managedBindingConflictKindForResolvedTerminal } = bindings;
143
+ function assertTerminalLifecycleReady({ options, terminal, terminalStatus }) {
144
+ if (terminalStatus.reachable !== true ||
145
+ terminalStatus.activity_state !== "idle" ||
146
+ terminalStatus.approval_state.blocked === true) {
147
+ throw new Error(`terminal ${terminal.terminalControl.target} is not at a verified idle prompt ` +
148
+ `(${terminalStatus.activity_state}: ${terminalStatus.activity_reason})`);
149
+ }
150
+ const blockers = terminalListCliFacade.terminalIncarnationBlockingTurns(storeDirFromOptions(options), terminal.terminalControl);
151
+ if (blockers.length > 0) {
152
+ throw new Error(`terminal ${terminal.terminalControl.target} still has unresolved Turn ` +
153
+ `${turnIdForConversation(blockers[0])} (${blockers[0].status})`);
154
+ }
155
+ const ledger = resolveTerminalDispatchLedgerPaneIncarnation(terminal.terminalControl, reconcilePreparedTerminalDispatchLedger(terminal.terminalControl, loadTerminalBridgeDispatchLedger(terminal.terminalControl)));
156
+ if (terminalDispatchLedgerLooksLifecycle(ledger) &&
157
+ ledger?.status !== "resolved") {
158
+ throw new Error(`terminal ${terminal.terminalControl.target} has unresolved lifecycle ` +
159
+ `transition ${stringValue(ledger?.transition_id) ?? "with invalid identity"}`);
160
+ }
161
+ if (ledger &&
162
+ [
163
+ "prepared",
164
+ "text_injected",
165
+ "enter_dispatched",
166
+ "dispatching",
167
+ "not_accepted",
168
+ "uncertain"
169
+ ].includes(String(ledger.status))) {
170
+ throw new Error(`terminal ${terminal.terminalControl.target} has an unresolved ` +
171
+ `${String(ledger.kind ?? "turn")} operation (${String(ledger.status)})`);
172
+ }
173
+ if (ledger && ["submitted", "agent_accepted"].includes(String(ledger.status))) {
174
+ const owner = loadTerminalDispatchLedgerOwner(ledger);
175
+ if (!owner || !isTerminalDispatchOwnerReleasedStatus(owner.status)) {
176
+ throw new Error(`terminal ${terminal.terminalControl.target} still has a submitted operation`);
177
+ }
178
+ }
179
+ }
180
+ function nativeThreadVerificationAdapterPorts(options, terminal) {
181
+ return {
182
+ createBridge: () => createTerminalAgentBridge(options),
183
+ loadClaudeAgentRows: () => loadClaudeAgentRows(options, { required: true }),
184
+ runningVersion: () => agentVersionForRunningProcess(terminal.agent, terminal.pid, options),
185
+ runtimeForIdentity: (identity) => terminalRuntimeForLiveIdentity({ terminal, identity }),
186
+ emptyRuntime: () => terminalRuntimeForLiveIdentity({
187
+ terminal,
188
+ expectedEmptyNativeSession: true
189
+ }),
190
+ physicalRuntime: () => terminalRuntimeForLiveIdentity({
191
+ terminal,
192
+ physicalOnly: true
193
+ }),
194
+ resolveIdentity: (preferredSessionId, allowedCompanionIdentity, allowedAdditionalIdentities) => resolveCurrentNativeAgentSessionIdentity({
195
+ options,
196
+ agent: terminal.agent,
197
+ pid: terminal.pid,
198
+ cwd: terminal.terminalControl.currentPath,
199
+ preferredSessionId,
200
+ allowedCompanionIdentity,
201
+ allowedAdditionalIdentities: [...allowedAdditionalIdentities]
202
+ }),
203
+ sleep: cliSleep
204
+ };
205
+ }
206
+ async function assertLifecycleTargetHasExclusiveOwnership({ options, terminal, transition, storeDir }) {
207
+ const afterBinding = transition.after_binding;
208
+ const nativeThreadId = afterBinding?.native_thread_id;
209
+ if (!afterBinding ||
210
+ !nativeThreadId ||
211
+ !isExactNativeThreadId(nativeThreadId) ||
212
+ afterBinding.native_process.pid !== terminal.pid ||
213
+ !terminalControlAliasMatches(afterBinding.terminal_id, afterBinding.terminal_control, terminal.conversationId, terminal.terminalControl)) {
214
+ throw new Error("cannot exclude the current lifecycle process without an exact after_binding");
215
+ }
216
+ await assertNativeThreadHasExclusiveOwnership({
217
+ options,
218
+ agent: transition.agent,
219
+ currentPid: terminal.pid,
220
+ nativeThreadId,
221
+ storeDir,
222
+ terminalControl: terminal.terminalControl,
223
+ excludedManagedSessionId: transition.target_session_id
224
+ });
225
+ }
226
+ async function runNewThread(options) {
227
+ const requireRestorableOrigin = options.requireRestorableOrigin;
228
+ if (requireRestorableOrigin !== undefined &&
229
+ requireRestorableOrigin !== true) {
230
+ throw new Error("--require-restorable-origin does not take a value");
231
+ }
232
+ return runTransition(options, {
233
+ kind: "new_thread",
234
+ requireRestorableOrigin: requireRestorableOrigin === true
235
+ });
236
+ }
237
+ async function runResumeThread(options) {
238
+ const exactNativeThreadId = stringValue(options.nativeThread ?? options.nativeThreadId);
239
+ const hasSnapshotSelection = Boolean(options.selectionSnapshot ||
240
+ options.selectionNumber ||
241
+ options.selectionShortId ||
242
+ options.selectionHandle);
243
+ if (exactNativeThreadId && hasSnapshotSelection) {
244
+ throw new Error("--native-thread cannot be combined with a snapshot-bound selection");
245
+ }
246
+ if (exactNativeThreadId) {
247
+ if (!isExactNativeThreadId(exactNativeThreadId)) {
248
+ throw new Error("--native-thread must be a complete native thread UUID");
249
+ }
250
+ return runTransition(options, {
251
+ kind: "resume_thread",
252
+ nativeThreadId: exactNativeThreadId.toLowerCase()
253
+ });
254
+ }
255
+ if (!hasSnapshotSelection) {
256
+ throw new Error("--native-thread or a snapshot-bound resume selection is required");
257
+ }
258
+ const terminal = await resolveLifecycleTerminal(options);
259
+ const storeDir = storeDirFromOptions(options);
260
+ const selectionScope = required(stringValue(options.selectionScope), "--selection-scope is required for snapshot-bound resume");
261
+ const rawSelectionNumber = options.selectionNumber;
262
+ const selectionNumber = rawSelectionNumber === undefined
263
+ ? undefined
264
+ : positiveSafeInteger(rawSelectionNumber, "--selection-number");
265
+ const selection = resolveNativeThreadResumeSelection({
266
+ runtimeDir: terminalBridgeRuntimeDir(),
267
+ storeDir,
268
+ terminalId: terminal.conversationId,
269
+ selectionScope,
270
+ snapshotId: stringValue(options.selectionSnapshot),
271
+ selectionNumber,
272
+ shortId: stringValue(options.selectionShortId),
273
+ selectionHandle: stringValue(options.selectionHandle)
274
+ });
275
+ assertResumeSnapshotMatchesTerminal(selection.snapshot, terminal, cliCwd);
276
+ assertResumeSnapshotActionFingerprint(selection.snapshot, loadTerminalBridgeDispatchLedger(terminal.terminalControl));
277
+ const selectedOptions = {
278
+ ...options,
279
+ expectedBindingToken: selection.snapshot.expected_binding_token,
280
+ candidateToken: selection.row.candidate_token
281
+ };
282
+ return runTransition(selectedOptions, {
283
+ kind: "resume_thread",
284
+ nativeThreadId: selection.row.native_thread_id.toLowerCase(),
285
+ selectionSnapshot: selection.snapshot
286
+ });
287
+ }
288
+ async function runReconcileBinding(options) {
289
+ const initiallyResolved = await resolveLifecycleTerminal(options);
290
+ const resolvedByFacts = new WeakMap();
291
+ const remember = (terminal) => {
292
+ const facts = bindingTerminalFacts(terminal);
293
+ resolvedByFacts.set(facts, terminal);
294
+ return facts;
295
+ };
296
+ const fullTerminal = (facts) => required(resolvedByFacts.get(facts), "binding reconciliation terminal capability is unavailable");
297
+ const initialFacts = remember(initiallyResolved);
298
+ const storeDir = storeDirFromOptions(options);
299
+ const conflictingSessionId = required(stringValue(options.conflictingSession ?? options.conflictingSessionId), "--conflicting-session is required");
300
+ const expectedSessionRevision = positiveSafeInteger(required(stringValue(options.expectedSessionRevision ?? options.sessionRevision), "--expected-session-revision is required"), "--expected-session-revision");
301
+ const expectedBindingToken = required(stringValue(options.expectedBindingToken), "--expected-binding-token is required");
302
+ const expectedTerminalToken = required(stringValue(options.expectedTerminalToken), "--expected-terminal-token is required");
303
+ return reconcileTerminalBinding({
304
+ initialTerminal: initialFacts,
305
+ conflictingSessionId,
306
+ expectedSessionRevision,
307
+ expectedBindingToken,
308
+ expectedTerminalToken
309
+ }, {
310
+ transaction: {
311
+ locks: terminalWriterMutationLocks(storeDir, initiallyResolved.terminalControl),
312
+ recover: (scopes, resources, terminal) => recoverBeforeMutation(scopes, resources, options, fullTerminal(terminal)),
313
+ loadSession: mutationManagedSessions.load,
314
+ saveSession: mutationManagedSessions.save
315
+ },
316
+ terminal: {
317
+ resolve: async () => remember(await resolveLifecycleTerminal(options)),
318
+ sameIncarnation: terminalControlsShareIncarnation,
319
+ identity: (facts) => resolveCurrentNativeAgentSessionIdentity({
320
+ options,
321
+ agent: facts.agent,
322
+ pid: facts.pid,
323
+ cwd: facts.terminalControl.currentPath
324
+ }),
325
+ prepareStatus: () => {
326
+ const bridge = createTerminalAgentBridge(options);
327
+ return async (facts) => {
328
+ const terminal = fullTerminal(facts);
329
+ const status = await bridge.status(terminal.agent, terminal.terminalControl, {
330
+ runtime: terminalRuntimeForLiveIdentity({
331
+ terminal,
332
+ physicalOnly: true
333
+ })
334
+ });
335
+ return Object.freeze({
336
+ reachable: status.reachable,
337
+ activity_state: status.activity_state,
338
+ activity_reason: status.activity_reason,
339
+ approval_state: Object.freeze({
340
+ blocked: status.approval_state.blocked
341
+ })
342
+ });
343
+ };
344
+ },
345
+ assertReady: (facts, terminalStatus) => assertTerminalLifecycleReady({
346
+ options,
347
+ terminal: fullTerminal(facts),
348
+ terminalStatus
349
+ })
350
+ },
351
+ authority: {
352
+ dispatchIsFree: (terminalControl) => terminalListCliFacade.terminalDispatchOwnership(terminalControl).state === "none",
353
+ sessionClaimsTerminal: managedSessionClaimsResolvedTerminal,
354
+ terminalTokenMatches: (terminal, identity, token) => lifecycleBindingTokens({
355
+ terminal: fullTerminal(terminal),
356
+ identity
357
+ }).includes(token),
358
+ hasUnresolvedTransition: (session) => terminalListCliFacade.managedSessionHasUnresolvedNativeTransition(storeDir, session),
359
+ blockingTurn: (sessionId) => {
360
+ const blocker = managedTurnsForSession(storeDir, sessionId)
361
+ .find((turn) => isSessionSendBlockingStatus(turn.status));
362
+ return blocker
363
+ ? { turnId: turnIdForConversation(blocker), status: blocker.status }
364
+ : undefined;
365
+ },
366
+ conflictKind: (session, terminal, identity) => managedBindingConflictKindForResolvedTerminal({
367
+ storeDir,
368
+ session,
369
+ terminal: fullTerminal(terminal),
370
+ identity
371
+ })
372
+ },
373
+ now: () => cliNow().toISOString(),
374
+ present: (result) => {
375
+ runtimeLog("info", "managed_binding_reconciled", {
376
+ terminal_id: result.terminal.conversationId,
377
+ terminal_target: result.terminal.terminalControl.target,
378
+ session_id: result.detached.session_id,
379
+ binding_id: result.detached.binding?.binding_id,
380
+ previous_revision: expectedSessionRevision,
381
+ revision: result.detached.revision,
382
+ conflict_kind: result.conflictKind,
383
+ terminal_input_sent: false
384
+ });
385
+ printJson({
386
+ status: "reconciled",
387
+ outcome: "detached_conflicting_binding",
388
+ conflict_kind: result.conflictKind,
389
+ terminal_id: result.terminal.conversationId,
390
+ session_id: result.detached.session_id,
391
+ binding_id: result.detached.binding?.binding_id,
392
+ session_revision: result.detached.revision,
393
+ terminal_input_sent: false,
394
+ turn_created: false,
395
+ refresh_required: true
396
+ });
397
+ }
398
+ });
399
+ }
400
+ return Object.freeze({
401
+ runNewThread, runResumeThread, runReconcileBinding,
402
+ verificationPorts: nativeThreadVerificationAdapterPorts,
403
+ assertTerminalReady: assertTerminalLifecycleReady,
404
+ assertTargetExclusive: assertLifecycleTargetHasExclusiveOwnership
405
+ });
406
+ }
407
+ function createNativeThreadTransitionRecoveryApplication(bindings, assertTargetExclusive) {
408
+ const { cliNow, cliSleep, terminalRuntimeForLiveIdentity, resolveCurrentNativeAgentSessionIdentity, assertNativeThreadHasExclusiveOwnership, assertSameNativeInspectionTerminal, authenticateLifecycleRecoveryResources, createTerminalAgentBridge, loadClaudeAgentRows, loadTerminalBridgeDispatchLedger, saveLifecycleTerminalDispatchLedger, observedExternalHandoffIdentity, recoverDeferredCodexForegroundTransferWhileWriterLease, codexKnownRootSetForLifecycleTransition, codexProcessBirthForLifecycle, isProcessAlive, matchesConfiguredWorkspace, terminalDispatchRecordMatchesControl, agentVersionForRunningProcess, exactLifecycleProcessIdentity } = bindings;
409
+ async function freshLifecycleRecoveryTerminal(scopes, resources, options, capturedTerminal) {
410
+ const active = authenticateLifecycleRecoveryResources(scopes, resources);
411
+ const terminal = await createTerminalAgentBridge(options).resolveStoredTerminal(capturedTerminal.agent, capturedTerminal.pid, active.terminalControl, { pid: capturedTerminal.pid });
412
+ assertSameNativeInspectionTerminal(capturedTerminal, terminal, "while waiting for lifecycle recovery");
413
+ if (!terminalControlsShareIncarnation(active.terminalControl, terminal.terminalControl)) {
414
+ throw new Error("terminal process incarnation changed while waiting for lifecycle recovery");
415
+ }
416
+ return { terminal, storeDir: active.storeDir };
417
+ }
418
+ function nativeThreadLifecycleRecoveryPorts({ options, terminal, storeDir }) {
419
+ const scoped = (operation) => nativeThreadTransitionResourceBoundOperation({
420
+ freshTerminal: terminal.terminalControl,
421
+ capturedStoreDir: storeDir
422
+ }, operation);
423
+ const scopedStore = (operation) => scoped((_freshControl, canonicalStoreDir, ...args) => operation(canonicalStoreDir, ...args));
424
+ const freshTerminal = (freshControl) => ({
425
+ ...terminal,
426
+ terminalControl: freshControl
427
+ });
428
+ const canonicalOptions = (canonicalStoreDir) => Object.freeze({ ...options, storeDir: canonicalStoreDir });
429
+ const deferredRecoveryRoute = scoped((freshControl, canonicalStoreDir) => ({ freshControl, canonicalStoreDir }));
430
+ const recoveryProbe = createNativeThreadLifecycleRecoveryProbeAdapter({
431
+ agent: terminal.agent,
432
+ lifecycle: terminal.adapter,
433
+ createBridge: (canonicalStoreDir) => createTerminalAgentBridge(canonicalOptions(canonicalStoreDir)),
434
+ runtime: (freshControl, context) => lifecycleRecoveryRuntime(terminalRuntimeForLiveIdentity({
435
+ terminal: freshTerminal(freshControl),
436
+ expectedEmptyNativeSession: context.kind === "codex_recovery",
437
+ physicalOnly: context.kind === "physical"
438
+ }), context),
439
+ loadClaudeRows: (canonicalStoreDir) => loadClaudeAgentRows(canonicalOptions(canonicalStoreDir), { required: true })
440
+ });
441
+ const ledgerDocument = (freshControl, canonicalStoreDir, transition, phase) => lifecycleLedger(transition, canonicalStoreDir, phase.phase === "rebuild"
442
+ ? { ...phase, control: freshControl }
443
+ : phase);
444
+ return {
445
+ authority: {
446
+ bind: scoped((freshControl) => ({ terminalControl: freshControl }))
447
+ },
448
+ persistence: {
449
+ listNativeThreadTransitions: scopedStore(listNativeThreadTransitions),
450
+ loadManagedSession: scopedStore(loadManagedSession),
451
+ tryLoadManagedSession: scopedStore(tryLoadManagedSession),
452
+ loadNativeThreadTransition: scopedStore(loadNativeThreadTransition),
453
+ saveManagedSession: scopedStore(saveManagedSession),
454
+ saveNativeThreadTransition: scopedStore(saveNativeThreadTransition),
455
+ commitVerified: scopedStore(commitVerifiedLifecycleTransition),
456
+ loadLedger: scoped((freshControl) => loadTerminalBridgeDispatchLedger(freshControl)),
457
+ buildLedger: scoped((freshControl, canonicalStoreDir, transition, phase) => ledgerDocument(freshControl, canonicalStoreDir, transition, phase)),
458
+ saveLedger: scoped((freshControl, canonicalStoreDir, transition, phase, expectation) => {
459
+ const ledger = ledgerDocument(freshControl, canonicalStoreDir, transition, phase);
460
+ if (ledger.store_dir !== canonicalStoreDir) {
461
+ throw new Error("lifecycle recovery ledger Store differs from its writer capability");
462
+ }
463
+ saveLifecycleTerminalDispatchLedger(freshControl, ledger, expectation);
464
+ }),
465
+ saveFailClosedLedger: scoped((freshControl, _canonicalStoreDir, ledger, transitionId, now, reason) => saveLifecycleTerminalDispatchLedger(freshControl, {
466
+ ...ledger,
467
+ kind: "lifecycle",
468
+ generation_id: transitionId,
469
+ transition_id: transitionId,
470
+ status: "uncertain",
471
+ uncertain_at: now,
472
+ reason: reason.slice(0, 2000)
473
+ }, { expectedTransitionId: transitionId }))
474
+ },
475
+ terminal: {
476
+ recoverDeferred: (scopes, resources) => {
477
+ const route = deferredRecoveryRoute(scopes, resources);
478
+ return recoverDeferredCodexForegroundTransferWhileWriterLease({
479
+ options: canonicalOptions(route.canonicalStoreDir),
480
+ terminal: freshTerminal(route.freshControl),
481
+ storeDir: route.canonicalStoreDir,
482
+ scopes,
483
+ resources
484
+ });
485
+ },
486
+ sameTerminalIncarnation: scoped((freshControl, _storeDir, right) => terminalControlsShareIncarnation(freshControl, right)),
487
+ aliasMatches: scoped((freshControl, _storeDir, storedTerminalId, storedControl, currentTerminalId) => terminalControlAliasMatches(storedTerminalId, storedControl, currentTerminalId, freshControl)),
488
+ workspaceMatches: scoped((freshControl, _storeDir, expected) => matchesConfiguredWorkspace(expected, freshControl.currentPath)),
489
+ resolveIdentity: scoped((freshControl, canonicalStoreDir, preferredSessionId, companions) => resolveCurrentNativeAgentSessionIdentity({
490
+ options: canonicalOptions(canonicalStoreDir),
491
+ agent: terminal.agent,
492
+ pid: terminal.pid,
493
+ cwd: freshControl.currentPath,
494
+ preferredSessionId,
495
+ allowedCompanionIdentity: companions.primary,
496
+ allowedAdditionalIdentities: companions.additional
497
+ })),
498
+ observeExternalHandoff: scoped((freshControl, canonicalStoreDir, sourceSession, resolvedIdentity) => observedExternalHandoffIdentity({
499
+ options: canonicalOptions(canonicalStoreDir),
500
+ terminal: freshTerminal(freshControl),
501
+ sourceSession,
502
+ resolvedIdentity
503
+ }).then((observed) => observed.identity)),
504
+ assertExclusive: scoped((freshControl, canonicalStoreDir, nativeThreadId, excludedManagedSessionId) => assertNativeThreadHasExclusiveOwnership({
505
+ options: canonicalOptions(canonicalStoreDir),
506
+ agent: terminal.agent,
507
+ currentPid: terminal.pid,
508
+ nativeThreadId,
509
+ storeDir: canonicalStoreDir,
510
+ terminalControl: freshControl,
511
+ excludedManagedSessionId
512
+ })),
513
+ assertTargetExclusive: scoped((freshControl, canonicalStoreDir, transition) => assertTargetExclusive({
514
+ options: canonicalOptions(canonicalStoreDir),
515
+ terminal: freshTerminal(freshControl),
516
+ transition,
517
+ storeDir: canonicalStoreDir
518
+ })),
519
+ exactIdentity: scoped((freshControl, _storeDir, identity) => exactLifecycleProcessIdentity(freshTerminal(freshControl), identity)),
520
+ isProcessAlive: scoped((_freshControl, _storeDir, pid) => isProcessAlive(pid)),
521
+ recordedStoreMatches: scoped((_freshControl, canonicalStoreDir, recordedStoreDir) => path.resolve(recordedStoreDir) === canonicalStoreDir),
522
+ recordMatchesControl: scoped((freshControl, _storeDir, ledger) => terminalDispatchRecordMatchesControl(ledger, freshControl)),
523
+ runningVersion: scoped((_freshControl, canonicalStoreDir) => agentVersionForRunningProcess(terminal.agent, terminal.pid, canonicalOptions(canonicalStoreDir))),
524
+ probeThreadLifecycle: scoped((_freshControl, _storeDir, version) => recoveryProbe.probe(version)),
525
+ planThreadLifecycle: scoped((_freshControl, _storeDir, operation, facts) => recoveryProbe.plan(operation, facts)),
526
+ observeThreadLifecycle: scoped((freshControl, canonicalStoreDir, request) => recoveryProbe.observe(freshControl, canonicalStoreDir, request)),
527
+ prepareProbeBridge: scoped((_freshControl, canonicalStoreDir) => recoveryProbe.prepare(canonicalStoreDir)),
528
+ status: scoped((freshControl, _storeDir, context, scrollbackLines) => recoveryProbe.status(freshControl, context, scrollbackLines)),
529
+ clearInputLine: scoped((freshControl, _storeDir, context) => recoveryProbe.clearInputLine(freshControl, context)),
530
+ submitCodexStatusProbe: scoped((freshControl, _storeDir, version, context) => recoveryProbe.submitCodexStatusProbe(freshControl, version, context)),
531
+ assertResumedCodexCandidate: scoped((_freshControl, _storeDir, identity, expected) => assertResumedCodexRolloutMatchesCandidate(identity, expected)),
532
+ codexKnownRoots: scoped((freshControl, canonicalStoreDir, transition) => codexKnownRootSetForLifecycleTransition({
533
+ storeDir: canonicalStoreDir,
534
+ terminal: freshTerminal(freshControl),
535
+ transition
536
+ })),
537
+ codexCompanionsExcludingPreferred: scoped((_freshControl, _storeDir, roots, preferredSessionId) => codexCompanionsExcludingPreferred(roots, preferredSessionId)),
538
+ codexProcessBirth: scoped(() => codexProcessBirthForLifecycle(terminal.pid)),
539
+ nativeIdentityMatches: scoped((_freshControl, _storeDir, identity, expected) => nativeIdentityMatchesCodexPreMaterialization(identity, expected))
540
+ },
541
+ runtime: {
542
+ now: cliNow,
543
+ sleep: cliSleep
544
+ }
545
+ };
546
+ }
547
+ async function recoverLifecycleFenceBeforeMutationScoped(scopes, resources, options, capturedTerminal) {
548
+ const fresh = await freshLifecycleRecoveryTerminal(scopes, resources, options, capturedTerminal);
549
+ const serviceTerminal = lifecycleRecoveryTerminalFacts(fresh.terminal);
550
+ await recoverLifecycleFenceBeforeMutationService({ terminal: serviceTerminal }, scopes, resources, nativeThreadLifecycleRecoveryPorts({
551
+ options,
552
+ terminal: fresh.terminal,
553
+ storeDir: fresh.storeDir
554
+ }));
555
+ }
556
+ async function reconcileLifecycleDispatchLedgerScoped(scopes, resources, options, capturedTerminal, ledger, authority = { kind: "automatic" }) {
557
+ const fresh = await freshLifecycleRecoveryTerminal(scopes, resources, options, capturedTerminal);
558
+ const serviceTerminal = lifecycleRecoveryTerminalFacts(fresh.terminal);
559
+ return reconcileLifecycleDispatchLedgerService({ terminal: serviceTerminal, ledger, authority }, scopes, resources, nativeThreadLifecycleRecoveryPorts({
560
+ options,
561
+ terminal: fresh.terminal,
562
+ storeDir: fresh.storeDir
563
+ }));
564
+ }
565
+ return Object.freeze({
566
+ recoverBeforeMutation: recoverLifecycleFenceBeforeMutationScoped,
567
+ reconcileLedger: reconcileLifecycleDispatchLedgerScoped
568
+ });
569
+ }
570
+ function nativeThreadTransitionSettlementPorts(bindings, assertTargetExclusive, { options, operation, terminal, storeDir, targetSession, targetSessionId, sourceBefore, beforeIdentity, verificationPorts }) {
571
+ const { saveLifecycleTerminalDispatchLedger, exactLifecycleProcessIdentity, cliCwd, cliNow, cliEnv, cliExit, textSummary, printJson } = bindings;
572
+ const scoped = (operation) => nativeThreadTransitionResourceBoundOperation({
573
+ freshTerminal: terminal.terminalControl,
574
+ capturedStoreDir: storeDir
575
+ }, operation);
576
+ return {
577
+ persistence: {
578
+ saveLedger: scoped((freshTerminal, canonicalStoreDir, value, phase, expectation) => {
579
+ const ledger = lifecycleLedger(value, canonicalStoreDir, phase);
580
+ if (ledger.store_dir !== canonicalStoreDir) {
581
+ throw new Error("lifecycle dispatch ledger Store differs from its writer capability");
582
+ }
583
+ saveLifecycleTerminalDispatchLedger(freshTerminal, ledger, expectation);
584
+ }),
585
+ loadTransition: scoped((_freshTerminal, canonicalStoreDir, id) => loadNativeThreadTransition(canonicalStoreDir, id)),
586
+ saveTransition: scoped((_freshTerminal, canonicalStoreDir, value, expectation) => saveNativeThreadTransition(canonicalStoreDir, value, expectation)),
587
+ saveSession: scoped((_freshTerminal, canonicalStoreDir, value, expectation) => saveManagedSession(canonicalStoreDir, value, expectation)),
588
+ commitVerified: scoped((_freshTerminal, canonicalStoreDir, value, verifiedAt) => commitVerifiedLifecycleTransition(canonicalStoreDir, value, verifiedAt))
589
+ },
590
+ effects: {
591
+ finalizeIdentity: (observed, durableTransition, verifiedAt) => {
592
+ const identity = exactLifecycleProcessIdentity(terminal, observed);
593
+ if (terminal.agent === "codex" &&
594
+ operation.kind === "resume_thread") {
595
+ assertResumedCodexRolloutMatchesCandidate(identity, durableTransition.target_candidate_file_identity);
596
+ }
597
+ return {
598
+ identity,
599
+ binding: terminalBindingFrom({
600
+ terminalId: terminal.conversationId,
601
+ terminalControl: terminal.terminalControl,
602
+ pid: terminal.pid,
603
+ nativeThreadId: identity.sessionId,
604
+ processUuid: identity.processUuid,
605
+ processBirth: identity.processBirth,
606
+ rollout: identity.rollout,
607
+ evidence: identity.evidence,
608
+ generation: (targetSession?.binding?.generation ?? 0) + 1,
609
+ now: verifiedAt
610
+ })
611
+ };
612
+ },
613
+ assertTargetOwnership: scoped((_freshTerminal, canonicalStoreDir, durableTransition) => assertTargetExclusive({
614
+ options,
615
+ terminal,
616
+ transition: durableTransition,
617
+ storeDir: canonicalStoreDir
618
+ })),
619
+ targetConflictWorkspace: () => terminal.terminalControl.currentPath ?? cliCwd()
620
+ },
621
+ runtime: {
622
+ now: cliNow,
623
+ crashAfterVerified: () => {
624
+ if (cliEnv().AKK_TEST_EXIT_AFTER_LIFECYCLE_VERIFIED === "1") {
625
+ cliExit(87);
626
+ }
627
+ },
628
+ injectTargetConflict: () => cliEnv().AKK_TEST_INJECT_LIFECYCLE_TARGET_CONFLICT === "1",
629
+ errorProvesInputNotStarted: (error) => error instanceof TerminalInputNotStartedError,
630
+ summarizeError: textSummary
631
+ },
632
+ verification: scoped((_freshTerminal, _canonicalStoreDir, request) => verifyNativeThreadTransitionWithRuntime(request, terminal, verificationPorts)),
633
+ present: (result) => {
634
+ if (result.status === "committed") {
635
+ printJson({
636
+ status: "committed",
637
+ transition_id: result.transition.transition_id,
638
+ operation: operation.kind,
639
+ terminal_id: terminal.conversationId,
640
+ previous_session_id: sourceBefore?.session_id ?? null,
641
+ session_id: targetSessionId,
642
+ previous_native_thread_id: beforeIdentity.sessionId ??
643
+ sourceBefore?.binding?.native_thread_id ??
644
+ null,
645
+ native_thread_id: result.identity.sessionId,
646
+ binding_id: result.binding.binding_id,
647
+ binding_generation: result.binding.generation,
648
+ binding_token: managedSessionBindingToken(result.committedTarget),
649
+ turn_created: false
650
+ });
651
+ return;
652
+ }
653
+ printJson({
654
+ status: result.status,
655
+ transition_id: result.transitionId,
656
+ operation: operation.kind,
657
+ terminal_id: terminal.conversationId,
658
+ do_not_retry: true,
659
+ turn_created: false,
660
+ reason: result.reason
661
+ });
662
+ }
663
+ };
664
+ }
665
+ async function runNativeThreadTransition(bindings, commands, recovery, options, operation) {
666
+ const { resolveLifecycleTerminal, storeDirFromOptions, terminalWriterMutationLocks, cliNowMs, cliCwd, loadTerminalBridgeDispatchLedger, currentLifecycleSnapshot, nativeThreadLifecycleFacade, nativeThreadLifecycleQueryPorts, assertNativeThreadHasExclusiveOwnership, assertCodexComposerReadyForAutomatedInput, cliNow, cliPid, saveLifecycleTerminalDispatchLedger, managedTurnsForSession, managedSessionOwnerIsConclusivelyInactive, printJson, cliEnv, cliExit, exactLifecycleProcessIdentity } = bindings;
667
+ const initiallyResolved = await resolveLifecycleTerminal(options);
668
+ const storeDir = storeDirFromOptions(options);
669
+ return withCanonicalMutationLocks(terminalWriterMutationLocks(storeDir, initiallyResolved.terminalControl), async (scopes, resources) => {
670
+ const terminal = await resolveLifecycleTerminal(options);
671
+ if (terminal.pid !== initiallyResolved.pid ||
672
+ !terminalControlsShareIncarnation(terminal.terminalControl, initiallyResolved.terminalControl)) {
673
+ throw new Error("terminal identity changed while waiting for lifecycle control; refresh list");
674
+ }
675
+ if (operation.kind === "resume_thread" && operation.selectionSnapshot) {
676
+ assertResumeSnapshotNotExpired(operation.selectionSnapshot, cliNowMs);
677
+ assertResumeSnapshotMatchesTerminal(operation.selectionSnapshot, terminal, cliCwd);
678
+ assertResumeSnapshotActionFingerprint(operation.selectionSnapshot, loadTerminalBridgeDispatchLedger(terminal.terminalControl));
679
+ }
680
+ await recovery.recoverBeforeMutation(scopes, resources, options, terminal);
681
+ if (operation.kind === "resume_thread" && operation.selectionSnapshot) {
682
+ // Recovery may resolve or otherwise rewrite a durable dispatch fence.
683
+ // A snapshot created before that mutation is stale even when the
684
+ // binding and candidate files themselves did not change.
685
+ assertResumeSnapshotActionFingerprint(operation.selectionSnapshot, loadTerminalBridgeDispatchLedger(terminal.terminalControl));
686
+ }
687
+ const snapshot = await currentLifecycleSnapshot(options, terminal, { materialize: true });
688
+ const expectedToken = required(stringValue(options.expectedBindingToken), "--expected-binding-token is required");
689
+ const verificationPorts = commands.verificationPorts(options, terminal);
690
+ const selectionSnapshot = operation.kind === "resume_thread"
691
+ ? operation.selectionSnapshot
692
+ : undefined;
693
+ const preparedVerification = await prepareNativeThreadVerification({
694
+ operation,
695
+ expectedBindingToken: expectedToken,
696
+ bindingTokens: snapshot.bindingTokens,
697
+ capabilities: snapshot.capabilities,
698
+ beforeIdentity: snapshot.identity,
699
+ physicalBeforeIdentity: snapshot.runtimeIdentity,
700
+ allowedCompanionIdentity: snapshot.codexCompanions.primary,
701
+ allowedAdditionalIdentities: snapshot.codexCompanions.additional
702
+ }, terminal, {
703
+ ...verificationPorts,
704
+ plan: () => nativeThreadLifecycleFacade.agentAdapter(options, terminal.agent).planThreadLifecycle?.(operation, snapshot.capabilities),
705
+ assertReady: (status) => commands.assertTerminalReady({ options, terminal, terminalStatus: status }),
706
+ ...(selectionSnapshot
707
+ ? {
708
+ revalidateSelectionSnapshot: async () => {
709
+ const candidates = await resumableNativeThreadCandidates({
710
+ terminal,
711
+ currentIdentity: snapshot.identity
712
+ }, nativeThreadLifecycleQueryPorts(options));
713
+ assertResumeSnapshotCandidates(selectionSnapshot, candidates);
714
+ }
715
+ }
716
+ : {}),
717
+ finalizeIdentity: (identity) => exactLifecycleProcessIdentity(terminal, identity)
718
+ });
719
+ const { bridge, plan, beforeIdentity, beforeRuntime } = preparedVerification;
720
+ const restorableOriginCandidateToken = operation.kind === "new_thread" &&
721
+ operation.requireRestorableOrigin
722
+ ? await requireRestorableLifecycleOriginFromQuery({
723
+ terminal,
724
+ currentIdentity: beforeIdentity,
725
+ currentSession: snapshot.session,
726
+ agentVersion: required(stringValue(snapshot.version), "restorable origin requires the exact running agent version")
727
+ }, nativeThreadLifecycleQueryPorts({ ...options, storeDir }))
728
+ : undefined;
729
+ let candidates = [];
730
+ let targetSession;
731
+ let resumeCandidateToken;
732
+ if (operation.kind === "resume_thread") {
733
+ const expectedCandidateToken = required(stringValue(options.candidateToken), "--candidate-token is required");
734
+ if (beforeIdentity.sessionId === operation.nativeThreadId) {
735
+ printJson({
736
+ status: "already_active",
737
+ no_op: true,
738
+ terminal_id: terminal.conversationId,
739
+ session_id: snapshot.session?.session_id ?? null,
740
+ native_thread_id: operation.nativeThreadId,
741
+ binding_token: snapshot.bindingToken
742
+ });
743
+ return;
744
+ }
745
+ candidates = await resumableNativeThreadCandidates({
746
+ terminal,
747
+ currentIdentity: beforeIdentity
748
+ }, nativeThreadLifecycleQueryPorts(options));
749
+ if (operation.selectionSnapshot) {
750
+ // The Codex identity probe and other readiness checks above are
751
+ // asynchronous. Rebind the whole displayed snapshot, not only its
752
+ // selected UUID, after those checks and before any lifecycle state
753
+ // is persisted.
754
+ assertResumeSnapshotCandidates(operation.selectionSnapshot, candidates);
755
+ }
756
+ const candidate = candidates.find((entry) => entry.native_thread_id === operation.nativeThreadId);
757
+ const candidateDecision = decideResumeCandidateEligibility({
758
+ candidate,
759
+ expectedCandidateToken
760
+ });
761
+ if (candidateDecision.action === "reject") {
762
+ throw new Error(candidateDecision.reason === "candidate_not_found"
763
+ ? `native thread ${operation.nativeThreadId} is not a verified same-workspace candidate`
764
+ : candidateDecision.reason === "candidate_not_resumable"
765
+ ? `native thread ${operation.nativeThreadId} cannot be resumed: ` +
766
+ `${candidate?.unavailable_reason ?? "unavailable"}`
767
+ : "resume candidate changed after it was listed; refresh resumable threads and retry");
768
+ }
769
+ const eligibleCandidate = candidateDecision.candidate;
770
+ resumeCandidateToken = await revalidateNativeThreadCandidateFromQuery({
771
+ terminal,
772
+ nativeThreadId: operation.nativeThreadId,
773
+ encodedToken: expectedCandidateToken,
774
+ agentVersion: snapshot.version
775
+ }, nativeThreadLifecycleQueryPorts(options));
776
+ if (eligibleCandidate.managed_session_id) {
777
+ targetSession = tryLoadManagedSession(storeDir, eligibleCandidate.managed_session_id);
778
+ const targetBlockers = managedTurnsForSession(storeDir, eligibleCandidate.managed_session_id).filter((turn) => isSessionSendBlockingStatus(turn.status));
779
+ const targetDecision = decideResumeTargetSession({
780
+ hasUnresolvedTurn: targetBlockers.length > 0,
781
+ loadedSession: targetSession,
782
+ boundOwnerConclusivelyInactive: Boolean(targetBlockers.length === 0 && targetSession?.status === "bound" &&
783
+ managedSessionOwnerIsConclusivelyInactive({
784
+ session: targetSession,
785
+ terminal,
786
+ identity: beforeIdentity
787
+ }))
788
+ });
789
+ if (targetDecision.action === "reject" &&
790
+ targetDecision.reason === "unresolved_turn") {
791
+ throw new Error(`target Session ${eligibleCandidate.managed_session_id} has unresolved Turn ` +
792
+ `${turnIdForConversation(targetBlockers[0])}`);
793
+ }
794
+ if (targetDecision.action === "reject") {
795
+ throw new Error(`target Session ${eligibleCandidate.managed_session_id} is still bound to a live or unverifiable process`);
796
+ }
797
+ if (targetDecision.action === "detach_stale_binding" &&
798
+ targetSession) {
799
+ const detachedAt = cliNow().toISOString();
800
+ targetSession = saveManagedSession(storeDir, {
801
+ ...targetSession,
802
+ status: "detached",
803
+ detached_at: detachedAt,
804
+ updated_at: detachedAt
805
+ }, { expectedRevision: managedSessionRevision(targetSession) });
806
+ }
807
+ }
808
+ }
809
+ const now = cliNow();
810
+ const transitionId = createNativeThreadTransitionId();
811
+ const targetSessionId = targetSession?.session_id ??
812
+ createManagedSessionId(now);
813
+ const sourceBefore = snapshot.session;
814
+ const previousLedger = loadTerminalBridgeDispatchLedger(terminal.terminalControl);
815
+ let transition = prepareNativeThreadTransition({
816
+ transitionId,
817
+ operation,
818
+ terminalId: terminal.conversationId,
819
+ agent: terminal.agent,
820
+ workspace: terminal.terminalControl.currentPath ?? cliCwd(),
821
+ source: sourceBefore
822
+ ? {
823
+ state: sourceBefore,
824
+ revision: managedSessionRevision(sourceBefore)
825
+ }
826
+ : undefined,
827
+ targetSessionId,
828
+ target: targetSession
829
+ ? {
830
+ state: targetSession,
831
+ revision: managedSessionRevision(targetSession)
832
+ }
833
+ : undefined,
834
+ candidateFileIdentity: terminal.agent === "codex" && operation.kind === "resume_thread"
835
+ ? codexCandidateFileIdentity(resumeCandidateToken)
836
+ : undefined,
837
+ beforeIdentity,
838
+ beforeProcessUuid: beforeIdentity.processUuid,
839
+ beforeBinding: snapshot.session?.binding,
840
+ adapterVersion: snapshot.version,
841
+ commandFingerprint: nativeThreadCommandFingerprint(JSON.stringify(plan.steps)),
842
+ dispatcherPid: cliPid(),
843
+ preparedAt: now.toISOString()
844
+ });
845
+ transition = saveNativeThreadTransition(storeDir, transition, {
846
+ expectedRevision: null
847
+ });
848
+ saveLifecycleTerminalDispatchLedger(terminal.terminalControl, lifecycleLedger(transition, storeDir, { phase: "command_prepared", previous: previousLedger }), {
849
+ expectedTransitionId: null
850
+ });
851
+ const settlementPorts = nativeThreadTransitionSettlementPorts(bindings, commands.assertTargetExclusive, {
852
+ options,
853
+ operation,
854
+ terminal,
855
+ storeDir,
856
+ targetSession,
857
+ targetSessionId,
858
+ sourceBefore,
859
+ beforeIdentity,
860
+ verificationPorts
861
+ });
862
+ let inputStarted = false;
863
+ let sourceTransitioning;
864
+ try {
865
+ if (cliEnv().AKK_TEST_EXIT_AFTER_LIFECYCLE_PREPARED === "1") {
866
+ cliExit(86);
867
+ }
868
+ if (sourceBefore) {
869
+ sourceTransitioning = saveManagedSession(storeDir, {
870
+ ...sourceBefore,
871
+ status: "transitioning",
872
+ last_transition_id: transitionId,
873
+ updated_at: now.toISOString()
874
+ }, { expectedRevision: managedSessionRevision(sourceBefore) });
875
+ }
876
+ const dispatchingAt = cliNow().toISOString();
877
+ transition = reduceNativeThreadTransitionPhase(transition, {
878
+ type: "dispatch_started",
879
+ at: dispatchingAt
880
+ });
881
+ transition = saveNativeThreadTransition(storeDir, transition, {
882
+ expectedRevision: nativeThreadTransitionRevision(transition)
883
+ });
884
+ saveLifecycleTerminalDispatchLedger(terminal.terminalControl, lifecycleLedger(transition, storeDir, { phase: "command_dispatching", previous: previousLedger }), {
885
+ expectedTransitionId: transitionId,
886
+ expectedStatus: "prepared"
887
+ });
888
+ const transitionStep = plan.steps.find((step) => step.kind === "transition");
889
+ if (!transitionStep || transitionStep.effect !== "thread_transition") {
890
+ throw new Error("the adapter lifecycle plan has no exact transition step");
891
+ }
892
+ if (restorableOriginCandidateToken) {
893
+ assertRestorableOriginSessionRelationshipFromQuery({
894
+ agent: terminal.agent,
895
+ nativeThreadId: beforeIdentity.sessionId.toLowerCase(),
896
+ currentSession: snapshot.session
897
+ }, nativeThreadLifecycleQueryPorts({ ...options, storeDir }));
898
+ await assertNativeThreadHasExclusiveOwnership({
899
+ options,
900
+ agent: terminal.agent,
901
+ currentPid: terminal.pid,
902
+ nativeThreadId: beforeIdentity.sessionId.toLowerCase(),
903
+ storeDir,
904
+ terminalControl: terminal.terminalControl,
905
+ excludedManagedSessionId: snapshot.session?.session_id
906
+ });
907
+ await revalidateNativeThreadCandidateFromQuery({
908
+ terminal,
909
+ nativeThreadId: beforeIdentity.sessionId.toLowerCase(),
910
+ encodedToken: restorableOriginCandidateToken,
911
+ agentVersion: required(stringValue(snapshot.version), "restorable origin requires the exact running agent version")
912
+ }, nativeThreadLifecycleQueryPorts({ ...options, storeDir }));
913
+ }
914
+ if (terminal.agent === "codex") {
915
+ // Candidate discovery and ownership revalidation can take long
916
+ // enough for a human to start typing after the /status probe. Keep
917
+ // this check immediately adjacent to the terminal mutation.
918
+ try {
919
+ await assertCodexComposerReadyForAutomatedInput({
920
+ options,
921
+ terminalControl: terminal.terminalControl
922
+ });
923
+ }
924
+ catch (error) {
925
+ throw new TerminalInputNotStartedError(error instanceof Error ? error.message : String(error), { cause: error });
926
+ }
927
+ }
928
+ if (operation.kind === "resume_thread" && operation.selectionSnapshot) {
929
+ assertResumeSnapshotNotExpired(operation.selectionSnapshot, cliNowMs);
930
+ }
931
+ await bridge.send(terminal.agent, terminal.terminalControl, transitionStep.command, {
932
+ runtime: beforeRuntime,
933
+ onTransportStage(event) {
934
+ if (event.stage === "text_injected") {
935
+ inputStarted = true;
936
+ }
937
+ }
938
+ });
939
+ const submittedAt = cliNow().toISOString();
940
+ transition = reduceNativeThreadTransitionPhase(transition, {
941
+ type: "submission_recorded",
942
+ at: submittedAt
943
+ });
944
+ transition = saveNativeThreadTransition(storeDir, transition, {
945
+ expectedRevision: nativeThreadTransitionRevision(transition)
946
+ });
947
+ saveLifecycleTerminalDispatchLedger(terminal.terminalControl, lifecycleLedger(transition, storeDir, { phase: "command_submitted", previous: previousLedger }), {
948
+ expectedTransitionId: transitionId,
949
+ expectedStatus: "dispatching"
950
+ });
951
+ await settleVerifiedNativeThreadTransition({
952
+ transition,
953
+ verification: {
954
+ operation,
955
+ plan,
956
+ beforeIdentity,
957
+ physicalBeforeIdentity: snapshot.runtimeIdentity,
958
+ allowedCompanionIdentity: snapshot.codexCompanions.primary,
959
+ allowedAdditionalIdentities: snapshot.codexCompanions.additional,
960
+ initialScreenDigest: preparedVerification.initialScreenDigest
961
+ }
962
+ }, scopes, resources, settlementPorts);
963
+ }
964
+ catch (error) {
965
+ await settleFailedNativeThreadTransition({
966
+ transitionId,
967
+ inputStarted,
968
+ sourceBefore,
969
+ sourceTransitioning
970
+ }, error, scopes, resources, settlementPorts);
971
+ }
972
+ });
973
+ }
974
+ //# sourceMappingURL=native-thread-transition-application.js.map