@phyzess/pappra 0.1.0-beta.14 → 0.1.0-beta.19

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 (365) hide show
  1. package/README.md +133 -14
  2. package/assets/integrations/skills/pappra/SKILL.md +56 -7
  3. package/assets/integrations/skills/pappra/references/collaboration.md +646 -0
  4. package/assets/integrations/skills/pappra/references/environment.md +367 -0
  5. package/assets/integrations/skills/pappra/references/hosts.md +20 -0
  6. package/assets/integrations/skills/pappra/references/operations.md +36 -5
  7. package/dist/adapters/pi/recovery-extension.d.ts +65 -0
  8. package/dist/adapters/pi/recovery-extension.js +238 -0
  9. package/dist/adapters/pi/session-transition-extension.d.ts +30 -0
  10. package/dist/adapters/pi/session-transition-extension.js +265 -0
  11. package/dist/app/automatic-handoff-events.d.ts +26 -0
  12. package/dist/app/automatic-handoff-events.js +134 -0
  13. package/dist/app/bounded-file.d.ts +2 -0
  14. package/dist/app/bounded-file.js +2 -0
  15. package/dist/app/capability-evidence/claude.d.ts +37 -0
  16. package/dist/app/capability-evidence/claude.js +206 -0
  17. package/dist/app/capability-evidence/codex.d.ts +35 -0
  18. package/dist/app/capability-evidence/codex.js +193 -0
  19. package/dist/app/capability-evidence/index.d.ts +33 -0
  20. package/dist/app/capability-evidence/index.js +117 -0
  21. package/dist/app/capability-evidence/pi.d.ts +73 -0
  22. package/dist/app/capability-evidence/pi.js +669 -0
  23. package/dist/app/capability-evidence/shared.d.ts +69 -0
  24. package/dist/app/capability-evidence/shared.js +195 -0
  25. package/dist/app/collab-auto-handoff.d.ts +55 -0
  26. package/dist/app/collab-auto-handoff.js +384 -0
  27. package/dist/app/collab-bindings.d.ts +57 -0
  28. package/dist/app/collab-bindings.js +1006 -0
  29. package/dist/app/collab-bootstrap-transport.d.ts +163 -0
  30. package/dist/app/collab-bootstrap-transport.js +769 -0
  31. package/dist/app/collab-bootstrap.d.ts +137 -0
  32. package/dist/app/collab-bootstrap.js +3455 -0
  33. package/dist/app/collab-handoff.d.ts +12 -0
  34. package/dist/app/collab-handoff.js +511 -0
  35. package/dist/app/collab-messages.d.ts +2 -0
  36. package/dist/app/collab-messages.js +2 -0
  37. package/dist/app/collab-notify.d.ts +156 -0
  38. package/dist/app/collab-notify.js +1208 -0
  39. package/dist/app/collab-preflight.d.ts +34 -0
  40. package/dist/app/collab-preflight.js +96 -0
  41. package/dist/app/collab-recovery-executor.d.ts +161 -0
  42. package/dist/app/collab-recovery-executor.js +1153 -0
  43. package/dist/app/collab-recovery-projection.d.ts +103 -0
  44. package/dist/app/collab-recovery-projection.js +659 -0
  45. package/dist/app/collab-recovery.d.ts +25 -0
  46. package/dist/app/collab-recovery.js +429 -0
  47. package/dist/app/collab-resources.d.ts +16 -0
  48. package/dist/app/collab-resources.js +278 -0
  49. package/dist/app/collab-role-events.d.ts +22 -0
  50. package/dist/app/collab-role-events.js +329 -0
  51. package/dist/app/collab-role-orchestration.d.ts +53 -0
  52. package/dist/app/collab-role-orchestration.js +601 -0
  53. package/dist/app/collab-role-plan.d.ts +81 -0
  54. package/dist/app/collab-role-plan.js +504 -0
  55. package/dist/app/collab-role-repair.d.ts +109 -0
  56. package/dist/app/collab-role-repair.js +821 -0
  57. package/dist/app/collab-rollover.d.ts +263 -0
  58. package/dist/app/collab-rollover.js +1112 -0
  59. package/dist/app/collab-route.d.ts +64 -0
  60. package/dist/app/collab-route.js +240 -0
  61. package/dist/app/collab-session-transition-request.d.ts +50 -0
  62. package/dist/app/collab-session-transition-request.js +339 -0
  63. package/dist/app/collab-session-transition-validation.d.ts +19 -0
  64. package/dist/app/collab-session-transition-validation.js +44 -0
  65. package/dist/app/collab-session-transition.d.ts +181 -0
  66. package/dist/app/collab-session-transition.js +2970 -0
  67. package/dist/app/collab-state.d.ts +7 -0
  68. package/dist/app/collab-state.js +162 -0
  69. package/dist/app/collab-task-store.d.ts +22 -0
  70. package/dist/app/collab-task-store.js +204 -0
  71. package/dist/app/collab-work-execution.d.ts +127 -0
  72. package/dist/app/collab-work-execution.js +1027 -0
  73. package/dist/app/collab-work-plan.d.ts +87 -0
  74. package/dist/app/collab-work-plan.js +437 -0
  75. package/dist/app/collaboration.d.ts +8 -2
  76. package/dist/app/collaboration.js +101 -12
  77. package/dist/app/doctor.js +104 -3
  78. package/dist/app/host-mcp.js +34 -8
  79. package/dist/app/host-probe.js +4 -4
  80. package/dist/app/init.d.ts +58 -4
  81. package/dist/app/init.js +768 -155
  82. package/dist/app/managed-pi-bootstrap-admission.d.ts +14 -0
  83. package/dist/app/managed-pi-bootstrap-admission.js +104 -0
  84. package/dist/app/managed-pi-bootstrap-refresh.d.ts +10 -0
  85. package/dist/app/managed-pi-bootstrap-refresh.js +78 -0
  86. package/dist/app/managed-pi-delivery.d.ts +8 -0
  87. package/dist/app/managed-pi-delivery.js +110 -0
  88. package/dist/app/managed-pi-handoff-receiver.d.ts +15 -0
  89. package/dist/app/managed-pi-handoff-receiver.js +263 -0
  90. package/dist/app/managed-pi-handoff-reference.d.ts +3 -0
  91. package/dist/app/managed-pi-handoff-reference.js +60 -0
  92. package/dist/app/managed-pi-herdr.d.ts +21 -0
  93. package/dist/app/managed-pi-herdr.js +185 -0
  94. package/dist/app/managed-pi-initial-admission.d.ts +28 -0
  95. package/dist/app/managed-pi-initial-admission.js +416 -0
  96. package/dist/app/managed-pi-initial-launch.d.ts +5 -0
  97. package/dist/app/managed-pi-initial-launch.js +61 -0
  98. package/dist/app/managed-pi-native-observation.d.ts +36 -0
  99. package/dist/app/managed-pi-native-observation.js +191 -0
  100. package/dist/app/managed-pi-readiness.d.ts +29 -0
  101. package/dist/app/managed-pi-readiness.js +288 -0
  102. package/dist/app/managed-pi-repair-stop.d.ts +21 -0
  103. package/dist/app/managed-pi-repair-stop.js +371 -0
  104. package/dist/app/managed-pi-resume-admission.d.ts +32 -0
  105. package/dist/app/managed-pi-resume-admission.js +618 -0
  106. package/dist/app/managed-pi-retirement.d.ts +28 -0
  107. package/dist/app/managed-pi-retirement.js +112 -0
  108. package/dist/app/managed-pi-sdk-control.d.ts +7 -0
  109. package/dist/app/managed-pi-sdk-control.js +169 -0
  110. package/dist/app/managed-pi-sdk-runtime.d.ts +3 -0
  111. package/dist/app/managed-pi-sdk-runtime.js +483 -0
  112. package/dist/app/managed-pi-source-admission.d.ts +14 -0
  113. package/dist/app/managed-pi-source-admission.js +323 -0
  114. package/dist/app/managed-pi-transition-host.d.ts +36 -0
  115. package/dist/app/managed-pi-transition-host.js +292 -0
  116. package/dist/app/managed-pi.d.ts +54 -0
  117. package/dist/app/managed-pi.js +248 -0
  118. package/dist/app/shell-readiness.d.ts +66 -0
  119. package/dist/app/shell-readiness.js +368 -0
  120. package/dist/app/task-pin.d.ts +2 -23
  121. package/dist/app/task-pin.js +2 -113
  122. package/dist/cli/collaboration-router.d.ts +17 -0
  123. package/dist/cli/collaboration-router.js +604 -0
  124. package/dist/cli/commands/collaboration-binding.d.ts +13 -0
  125. package/dist/cli/commands/collaboration-binding.js +118 -0
  126. package/dist/cli/commands/collaboration-bootstrap.d.ts +10 -0
  127. package/dist/cli/commands/collaboration-bootstrap.js +84 -0
  128. package/dist/cli/commands/collaboration-capabilities.d.ts +13 -0
  129. package/dist/cli/commands/collaboration-capabilities.js +127 -0
  130. package/dist/cli/commands/collaboration-handoff.d.ts +13 -0
  131. package/dist/cli/commands/collaboration-handoff.js +102 -0
  132. package/dist/cli/commands/collaboration-message.d.ts +17 -0
  133. package/dist/cli/commands/collaboration-message.js +177 -0
  134. package/dist/cli/commands/collaboration-plan.d.ts +8 -0
  135. package/dist/cli/commands/collaboration-plan.js +108 -0
  136. package/dist/cli/commands/collaboration-preflight.d.ts +10 -0
  137. package/dist/cli/commands/collaboration-preflight.js +167 -0
  138. package/dist/cli/commands/collaboration-recovery-run.d.ts +46 -0
  139. package/dist/cli/commands/collaboration-recovery-run.js +224 -0
  140. package/dist/cli/commands/collaboration-recovery.d.ts +11 -0
  141. package/dist/cli/commands/collaboration-recovery.js +104 -0
  142. package/dist/cli/commands/collaboration-resources.d.ts +11 -0
  143. package/dist/cli/commands/collaboration-resources.js +96 -0
  144. package/dist/cli/commands/collaboration-role-plan.d.ts +9 -0
  145. package/dist/cli/commands/collaboration-role-plan.js +69 -0
  146. package/dist/cli/commands/collaboration-role-run.d.ts +11 -0
  147. package/dist/cli/commands/collaboration-role-run.js +128 -0
  148. package/dist/cli/commands/collaboration-rollover.d.ts +10 -0
  149. package/dist/cli/commands/collaboration-rollover.js +103 -0
  150. package/dist/cli/commands/collaboration-state.d.ts +10 -0
  151. package/dist/cli/commands/collaboration-state.js +96 -0
  152. package/dist/cli/commands/collaboration-transition.d.ts +10 -0
  153. package/dist/cli/commands/collaboration-transition.js +75 -0
  154. package/dist/cli/commands/collaboration-work-run.d.ts +34 -0
  155. package/dist/cli/commands/collaboration-work-run.js +178 -0
  156. package/dist/cli/commands/collaboration.d.ts +4 -0
  157. package/dist/cli/commands/collaboration.js +39 -4
  158. package/dist/cli/commands/continuity.js +2 -6
  159. package/dist/cli/commands/docs.d.ts +2 -0
  160. package/dist/cli/commands/docs.js +89 -15
  161. package/dist/cli/commands/host.d.ts +7 -1
  162. package/dist/cli/commands/host.js +122 -7
  163. package/dist/cli/commands/init.d.ts +20 -3
  164. package/dist/cli/commands/init.js +897 -232
  165. package/dist/cli/commands/mcp.d.ts +1 -0
  166. package/dist/cli/commands/mcp.js +11 -5
  167. package/dist/cli/commands/repair.d.ts +12 -0
  168. package/dist/cli/commands/repair.js +41 -0
  169. package/dist/cli/commands/runtime.d.ts +1 -1
  170. package/dist/cli/commands/runtime.js +139 -38
  171. package/dist/cli/commands/session.d.ts +7 -0
  172. package/dist/cli/commands/session.js +82 -0
  173. package/dist/cli/commands/task.js +19 -5
  174. package/dist/cli/options.d.ts +806 -0
  175. package/dist/cli/options.js +293 -0
  176. package/dist/cli/run.js +280 -310
  177. package/dist/code/identity.d.ts +7 -0
  178. package/dist/code/identity.js +7 -3
  179. package/dist/code/registration.js +7 -0
  180. package/dist/code/service.d.ts +9 -0
  181. package/dist/code/service.js +16 -3
  182. package/dist/code/text.js +19 -7
  183. package/dist/collab/admission.d.ts +91 -66
  184. package/dist/collab/admission.js +21 -6
  185. package/dist/collab/canonical.d.ts +1 -1
  186. package/dist/collab/canonical.js +44 -3
  187. package/dist/collab/envelope.d.ts +2 -2
  188. package/dist/collab/envelope.js +12 -12
  189. package/dist/collab/first-work.d.ts +3 -0
  190. package/dist/collab/first-work.js +15 -0
  191. package/dist/collab/handoff.d.ts +16 -0
  192. package/dist/collab/handoff.js +39 -5
  193. package/dist/collab/index.d.ts +97 -1
  194. package/dist/collab/index.js +9 -1
  195. package/dist/collab/messages.js +126 -3
  196. package/dist/collab/persisted-messages.d.ts +123 -0
  197. package/dist/collab/persisted-messages.js +496 -0
  198. package/dist/collab/preflight.d.ts +1 -1
  199. package/dist/collab/resources.d.ts +13 -3
  200. package/dist/collab/resources.js +37 -6
  201. package/dist/collab/rollover.d.ts +311 -0
  202. package/dist/collab/rollover.js +1024 -0
  203. package/dist/collab/store.d.ts +1 -0
  204. package/dist/collab/store.js +1 -4
  205. package/dist/collab/types.d.ts +2 -354
  206. package/dist/collab/validation.d.ts +2 -10
  207. package/dist/collab/validation.js +2 -303
  208. package/dist/collab/work-plan.d.ts +105 -0
  209. package/dist/collab/work-plan.js +843 -0
  210. package/dist/continuity/context.d.ts +11 -2
  211. package/dist/continuity/context.js +100 -13
  212. package/dist/continuity/handoff-bundle.d.ts +296 -0
  213. package/dist/continuity/handoff-bundle.js +477 -0
  214. package/dist/continuity/index.d.ts +2 -0
  215. package/dist/continuity/index.js +1 -0
  216. package/dist/continuity/paths.js +10 -2
  217. package/dist/continuity/service.js +91 -15
  218. package/dist/continuity/task-pin.d.ts +24 -0
  219. package/dist/continuity/task-pin.js +590 -0
  220. package/dist/doctor.d.ts +1 -0
  221. package/dist/doctor.js +6 -0
  222. package/dist/experimental/index.d.ts +13 -0
  223. package/dist/experimental/index.js +25 -0
  224. package/dist/experimental/pi.d.ts +4 -0
  225. package/dist/experimental/pi.js +12 -0
  226. package/dist/hosts/claude/native.js +1 -1
  227. package/dist/hosts/codex/native.js +1 -1
  228. package/dist/hosts/codex/protocol.js +1 -1
  229. package/dist/hosts/integration/bootstrap-config.d.ts +58 -0
  230. package/dist/hosts/integration/bootstrap-config.js +254 -0
  231. package/dist/hosts/integration/bundle-export.d.ts +44 -0
  232. package/dist/hosts/integration/bundle-export.js +366 -3
  233. package/dist/hosts/integration/bundle.js +3 -0
  234. package/dist/hosts/integration/hook.js +36 -9
  235. package/dist/hosts/integration/pappra-bootstrap-extension.mjs +80 -0
  236. package/dist/hosts/integration/pappra-extension-runtime.mjs +59 -24631
  237. package/dist/hosts/integration/pappra-hook.mjs +61 -24749
  238. package/dist/hosts/integration/pappra-recovery-extension.mjs +259 -0
  239. package/dist/hosts/integration/pappra-session-transition-extension.mjs +276 -0
  240. package/dist/hosts/integration/pi-bootstrap-extension.d.ts +36 -0
  241. package/dist/hosts/integration/pi-bootstrap-extension.js +101 -0
  242. package/dist/hosts/integration/pi-bootstrap-guard.d.ts +125 -0
  243. package/dist/hosts/integration/pi-bootstrap-guard.js +438 -0
  244. package/dist/hosts/integration/pi-bootstrap-runtime.d.ts +63 -0
  245. package/dist/hosts/integration/pi-bootstrap-runtime.js +223 -0
  246. package/dist/hosts/integration/pi-native-events.d.ts +112 -0
  247. package/dist/hosts/integration/pi-native-events.js +348 -0
  248. package/dist/hosts/integration/pi-rollover-extension.d.ts +166 -0
  249. package/dist/hosts/integration/pi-rollover-extension.js +431 -0
  250. package/dist/hosts/integration/recovery-config.d.ts +48 -0
  251. package/dist/hosts/integration/recovery-config.js +117 -0
  252. package/dist/hosts/integration/service.d.ts +6 -1
  253. package/dist/hosts/integration/service.js +485 -35
  254. package/dist/hosts/integration/support.d.ts +7 -0
  255. package/dist/hosts/integration/support.js +9 -1
  256. package/dist/hosts/integration/templates.d.ts +3 -0
  257. package/dist/hosts/integration/templates.js +26 -3
  258. package/dist/hosts/pi/managed-host-identity.d.ts +2 -0
  259. package/dist/hosts/pi/managed-host-identity.js +40 -0
  260. package/dist/hosts/pi/managed-provider-diagnostics.d.ts +6 -0
  261. package/dist/hosts/pi/managed-provider-diagnostics.js +184 -0
  262. package/dist/hosts/pi/managed-sdk-session.d.ts +335 -0
  263. package/dist/hosts/pi/managed-sdk-session.js +1639 -0
  264. package/dist/hosts/pi/managed-session-extension.d.ts +20 -0
  265. package/dist/hosts/pi/managed-session-extension.js +84 -0
  266. package/dist/hosts/pi/managed-session.d.ts +177 -0
  267. package/dist/hosts/pi/managed-session.js +1557 -0
  268. package/dist/hosts/pi/protocol.js +1 -1
  269. package/dist/hosts/pi/query-result.js +1 -1
  270. package/dist/hosts/pi/resume-capability.d.ts +41 -0
  271. package/dist/hosts/pi/resume-capability.js +33 -0
  272. package/dist/hosts/pi/rpc.d.ts +182 -134
  273. package/dist/hosts/pi/rpc.js +230 -37
  274. package/dist/hosts/pilot.d.ts +90 -67
  275. package/dist/hosts/pilot.js +5 -1
  276. package/dist/hosts/version.d.ts +3 -0
  277. package/dist/hosts/version.js +18 -0
  278. package/dist/index.d.ts +0 -1
  279. package/dist/index.js +0 -1
  280. package/dist/infra/bounded-file.d.ts +19 -0
  281. package/dist/infra/bounded-file.js +66 -0
  282. package/dist/infra/fs.js +10 -2
  283. package/dist/infra/git.d.ts +29 -0
  284. package/dist/infra/git.js +45 -9
  285. package/dist/infra/json-property.d.ts +2 -0
  286. package/dist/infra/json-property.js +69 -0
  287. package/dist/infra/json.d.ts +4 -0
  288. package/dist/infra/json.js +24 -0
  289. package/dist/infra/owned-process-group.js +1 -1
  290. package/dist/infra/private-lock.d.ts +16 -0
  291. package/dist/infra/private-lock.js +148 -0
  292. package/dist/infra/private-state.d.ts +7 -0
  293. package/dist/infra/private-state.js +146 -0
  294. package/dist/infra/process-identity.d.ts +12 -0
  295. package/dist/infra/process-identity.js +142 -0
  296. package/dist/infra/validation.d.ts +5 -0
  297. package/dist/infra/validation.js +15 -0
  298. package/dist/init.d.ts +1 -0
  299. package/dist/init.js +6 -0
  300. package/dist/install/apply.d.ts +9 -1
  301. package/dist/install/apply.js +176 -12
  302. package/dist/install/dependencies.d.ts +38 -0
  303. package/dist/install/dependencies.js +282 -0
  304. package/dist/install/ownership.js +30 -1
  305. package/dist/install/references.d.ts +31 -0
  306. package/dist/install/references.js +208 -0
  307. package/dist/install/repair.d.ts +37 -0
  308. package/dist/install/repair.js +798 -0
  309. package/dist/install/reset-local.d.ts +16 -0
  310. package/dist/install/reset-local.js +304 -0
  311. package/dist/install/rollback.d.ts +3 -0
  312. package/dist/install/rollback.js +9 -3
  313. package/dist/install/runtime.d.ts +10 -6
  314. package/dist/install/runtime.js +299 -59
  315. package/dist/install/source-fingerprint.d.ts +2 -0
  316. package/dist/install/source-fingerprint.js +103 -0
  317. package/dist/knowledge/catalog.d.ts +1 -0
  318. package/dist/knowledge/catalog.js +143 -10
  319. package/dist/knowledge/journal.js +17 -7
  320. package/dist/knowledge/paths.js +2 -1
  321. package/dist/knowledge/refs.js +4 -0
  322. package/dist/knowledge/register-batch.d.ts +4 -0
  323. package/dist/knowledge/register-batch.js +225 -0
  324. package/dist/knowledge/relocate.d.ts +5 -0
  325. package/dist/knowledge/relocate.js +92 -0
  326. package/dist/knowledge/scan.js +103 -47
  327. package/dist/knowledge/service.d.ts +3 -0
  328. package/dist/knowledge/service.js +33 -1
  329. package/dist/knowledge/write.d.ts +4 -1
  330. package/dist/knowledge/write.js +1 -1
  331. package/dist/mcp/server.d.ts +4 -2
  332. package/dist/mcp/server.js +87 -136
  333. package/dist/schemas/collaboration-state-validation.d.ts +6 -0
  334. package/dist/schemas/collaboration-state-validation.js +342 -0
  335. package/dist/schemas/collaboration-state.d.ts +436 -0
  336. package/dist/schemas/collaboration-state.js +1 -0
  337. package/dist/schemas/collaboration.d.ts +335 -0
  338. package/dist/schemas/collaboration.js +272 -0
  339. package/dist/schemas/continuity.d.ts +8 -0
  340. package/dist/schemas/continuity.js +13 -3
  341. package/dist/schemas/doctor.d.ts +1 -0
  342. package/dist/schemas/doctor.js +1 -0
  343. package/dist/schemas/document.d.ts +61 -0
  344. package/dist/schemas/document.js +9 -0
  345. package/dist/schemas/errors.d.ts +1 -0
  346. package/dist/schemas/errors.js +1 -0
  347. package/dist/schemas/host.d.ts +24 -0
  348. package/dist/schemas/host.js +19 -0
  349. package/dist/schemas/install.d.ts +8 -2
  350. package/dist/schemas/install.js +11 -1
  351. package/dist/schemas/managed-pi-execution.d.ts +16 -0
  352. package/dist/schemas/managed-pi-execution.js +2 -0
  353. package/dist/schemas/outcome.d.ts +9 -5
  354. package/dist/workspace/config-file.js +1 -3
  355. package/dist/workspace/documents.js +12 -2
  356. package/dist/workspace/repositories.d.ts +7 -0
  357. package/dist/workspace/repositories.js +14 -5
  358. package/package.json +37 -35
  359. package/skills/pappra/SKILL.md +56 -7
  360. package/skills/pappra/references/collaboration.md +646 -0
  361. package/skills/pappra/references/environment.md +367 -0
  362. package/skills/pappra/references/hosts.md +20 -0
  363. package/skills/pappra/references/operations.md +36 -5
  364. package/dist/app/collab-from.d.ts +0 -35
  365. package/dist/app/collab-from.js +0 -84
@@ -0,0 +1,8 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const collaborationPlanUsage: string;
3
+ export interface CollaborationPlanOptions {
4
+ readonly taskRoot: string | null;
5
+ readonly planFile: string | null;
6
+ readonly json: boolean;
7
+ }
8
+ export declare function runCollaborationPlanCommand(options: CollaborationPlanOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,108 @@
1
+ import path from 'node:path';
2
+ import { COLLAB_WORK_PLAN_REPORT_SCHEMA, inspectWorkPlan, } from '../../app/collab-work-plan.js';
3
+ export const collaborationPlanUsage = 'pappra collab plan --task-root <abs> --config <abs plan.json> [--json]\n\n' +
4
+ 'Read-only role and dependency evaluation of one persisted work-plan document\n' +
5
+ 'against the authoritative task record. Nothing is claimed, dispatched, launched,\n' +
6
+ 'refreshed or written, and no prompt, network call or model call is made.\n\n' +
7
+ 'Plan nodes correlate to the existing task protocol by\n' +
8
+ 'node.assignment_id == attempt.subtask_id; there is no second assignment registry.\n' +
9
+ 'A ready node is not authorization to run it.\n\n' +
10
+ 'Exit 0 evaluated snapshot (normal waiting and blocked nodes included),\n' +
11
+ '1 incomplete or unavailable authoritative evidence, 2 invalid request/plan.';
12
+ function invalid(output, options, errors) {
13
+ if (options.json) {
14
+ output.stdout(`${JSON.stringify({
15
+ schema: COLLAB_WORK_PLAN_REPORT_SCHEMA,
16
+ ok: false,
17
+ status: 'invalid',
18
+ task_root: options.taskRoot,
19
+ task_id: null,
20
+ plan: {
21
+ ref: options.planFile,
22
+ digest: null,
23
+ plan_id: null,
24
+ owner_epoch: null,
25
+ node_count: null,
26
+ },
27
+ stale: false,
28
+ summary: null,
29
+ nodes: [],
30
+ core: null,
31
+ evidence: {
32
+ registered_decisions: 0,
33
+ supplied: 0,
34
+ envelope_bytes: 0,
35
+ unreadable: [],
36
+ truncated: false,
37
+ },
38
+ diagnostics: errors.map((error) => ({
39
+ code: 'invalid_arguments',
40
+ detail: error,
41
+ next_action: collaborationPlanUsage,
42
+ })),
43
+ identity_mapping: 'plan.nodes[].assignment_id corresponds to the existing task subtask identity (record.attempts[].subtask_id); no separate assignment registry exists.',
44
+ limits: ['persisted_snapshot_only', 'not_an_authorization'],
45
+ })}\n`);
46
+ }
47
+ else {
48
+ output.stdout('Plan request invalid.\n');
49
+ for (const error of errors)
50
+ output.stdout(` - ${error}\n`);
51
+ output.stdout(`\n${collaborationPlanUsage}\n`);
52
+ }
53
+ return 2;
54
+ }
55
+ function emitHuman(report, output) {
56
+ const planLabel = report.plan.plan_id ?? '<unparsed plan>';
57
+ const taskLabel = report.task_id ?? '<unknown task>';
58
+ output.stdout(`Plan ${planLabel} on task ${taskLabel}: ${report.status}.\n`);
59
+ if (report.status === 'invalid') {
60
+ for (const entry of report.diagnostics)
61
+ output.stdout(` invalid: ${entry.code}: ${entry.detail}\n`);
62
+ return;
63
+ }
64
+ if (report.status === 'incomplete') {
65
+ for (const entry of report.diagnostics)
66
+ output.stdout(` incomplete: ${entry.code}: ${entry.detail}\n`);
67
+ }
68
+ if (report.stale) {
69
+ output.stdout(' note: the plan owner epoch is not the current epoch; every node is stale until it is rebuilt.\n');
70
+ }
71
+ const summary = report.summary;
72
+ if (summary !== null) {
73
+ output.stdout(` ready ${summary.ready}, running ${summary.running}, awaiting acceptance ${summary.awaiting_acceptance}, accepted ${summary.accepted}, blocked ${summary.blocked}\n`);
74
+ }
75
+ for (const node of report.nodes) {
76
+ output.stdout(` ${node.role} ${node.node_id} (assignment ${node.assignment_id}#${node.attempt}): ${node.status}\n`);
77
+ for (const blocker of node.blockers)
78
+ output.stdout(` blocked by ${blocker.code}: ${blocker.detail}\n`);
79
+ if (node.next_action !== null)
80
+ output.stdout(` next: ${node.next_action}\n`);
81
+ }
82
+ output.stdout(` evidence: ${report.evidence.supplied}/${report.evidence.registered_decisions} relevant decision envelope(s) read from ${report.evidence.relevant_reports} planned report(s), ${report.evidence.raw_bytes} raw bytes\n`);
83
+ output.stdout(' read-only: this evaluation is a persisted snapshot and grants no authority to run anything.\n');
84
+ }
85
+ export async function runCollaborationPlanCommand(options, output) {
86
+ const errors = [];
87
+ if (options.taskRoot === null)
88
+ errors.push('--task-root is required.');
89
+ else if (!path.isAbsolute(options.taskRoot))
90
+ errors.push('--task-root must be absolute.');
91
+ if (options.planFile === null)
92
+ errors.push('--config is required.');
93
+ else if (!path.isAbsolute(options.planFile))
94
+ errors.push('--config must be an absolute path to the plan document.');
95
+ if (errors.length > 0)
96
+ return invalid(output, options, errors);
97
+ const report = await inspectWorkPlan({
98
+ taskRoot: options.taskRoot,
99
+ planFile: options.planFile,
100
+ });
101
+ if (options.json)
102
+ output.stdout(`${JSON.stringify(report)}\n`);
103
+ else
104
+ emitHuman(report, output);
105
+ if (report.status === 'evaluated')
106
+ return 0;
107
+ return report.status === 'invalid' ? 2 : 1;
108
+ }
@@ -0,0 +1,10 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const collaborationPreflightUsage: string;
3
+ export interface CollaborationPreflightOptions {
4
+ readonly cwd: string;
5
+ readonly assignmentFile: string | null;
6
+ readonly capabilitiesFile: string | null;
7
+ readonly maxAgeMinutes: string | null;
8
+ readonly json: boolean;
9
+ }
10
+ export declare function runCollaborationPreflightCommand(options: CollaborationPreflightOptions, output: CliOutput): number;
@@ -0,0 +1,167 @@
1
+ import { runCollaborationPreflight, } from '../../app/collab-preflight.js';
2
+ export const collaborationPreflightUsage = 'pappra collab preflight --assignment <abs assignment.json> --capabilities <abs card.json> [--max-age-minutes <n>] [--json]\n\n' +
3
+ 'Read-only readiness check over the existing collaboration preflight. It reads the\n' +
4
+ 'two files and verifies pinned inputs/evidence; it never launches, claims, mutates\n' +
5
+ 'a task record or refreshes evidence. Exit 0 ready, 1 needs_input, 2 invalid.\n' +
6
+ 'Needs-input output groups recovery guidance for known blockers; JSON output is unchanged.';
7
+ function usageFailure(output, options, code, message) {
8
+ if (options.json) {
9
+ output.stdout(`${JSON.stringify({
10
+ schema: 'pappra/collaboration-preflight/1',
11
+ ok: false,
12
+ status: 'invalid',
13
+ errors: [message],
14
+ blockers: [],
15
+ warnings: [],
16
+ limits: [],
17
+ code,
18
+ })}\n`);
19
+ }
20
+ else {
21
+ output.stderr(`pappra collab preflight: ${message}\n`);
22
+ }
23
+ return 2;
24
+ }
25
+ function describeChecks(checks) {
26
+ return checks.map((check) => ` - ${check.code}${check.capability === undefined ? '' : ` (${check.capability})`}`);
27
+ }
28
+ const FRESHNESS_RECOVERY = 'Obtain fresh runtime evidence from the current receiving session and rerun preflight. Never retimestamp older evidence, and never revert a user-selected model or provider to recreate an earlier observation.';
29
+ const IDENTITY_RECOVERY = 'Supply evidence for the exact assignee identity, session, cwd and configuration. A model or provider difference alone is not an identity difference, and identity fields are not relabeled to match.';
30
+ const CAPABILITY_RECOVERY = 'Required capability readiness is not confirmed by this card: inspect the current runtime exposure and obtain actual current evidence for the required tool or skill, restoring or enabling it when it is in fact absent. Changing the requirement is an explicit scope decision for the coordinator, not a worker recovery step. Earlier successful tool use does not prove the current runtime still exposes it.';
31
+ /** Exact identity blockers emitted by the preflight core; unknown future codes get no remedy. */
32
+ const IDENTITY_BLOCKERS = new Set([
33
+ 'assignee_agent_id_mismatch',
34
+ 'assignee_session_id_mismatch',
35
+ 'assignee_harness_mismatch',
36
+ 'assignee_surface_mismatch',
37
+ 'assignee_configuration_id_mismatch',
38
+ 'assignee_cwd_mismatch',
39
+ ]);
40
+ /** Recovery guidance for concrete, known blockers. Unknown codes keep their code only. */
41
+ function recoveryFor(code) {
42
+ if (code === 'capabilities_stale')
43
+ return { group: 'freshness', action: FRESHNESS_RECOVERY };
44
+ if (code === 'capabilities_from_future')
45
+ return {
46
+ group: 'clock',
47
+ action: 'The evidence clock is ahead of this host clock: compare host and native timestamps and correct the clock or the evidence source. Do not edit timestamps to make evidence pass.',
48
+ };
49
+ if (code === 'runtime_capabilities_unconfirmed')
50
+ return {
51
+ group: 'evidence-level',
52
+ action: 'Derive a runtime card from actual native evidence for this session (pappra collab capabilities derive); a declared template is not runtime proof.',
53
+ };
54
+ if (code === 'required_capability_omitted_by_runner')
55
+ return { group: 'capabilities', action: CAPABILITY_RECOVERY };
56
+ if (code === 'native_evidence_changed' ||
57
+ code === 'native_evidence_unavailable')
58
+ return {
59
+ group: 'evidence-files',
60
+ action: 'The referenced native evidence changed or is unavailable: re-derive from the current native file instead of editing digests.',
61
+ };
62
+ if (code === 'input_changed' || code === 'input_unavailable')
63
+ return {
64
+ group: 'pinned-input',
65
+ action: 'A pinned input changed or is missing: obtain the current pinned input and update the assignment revision deliberately rather than rewriting a digest.',
66
+ };
67
+ if (code === 'tools_unavailable' || code === 'skills_unavailable')
68
+ return { group: 'capabilities', action: CAPABILITY_RECOVERY };
69
+ if (code === 'tools_evidence_unavailable' ||
70
+ code === 'skills_evidence_unavailable')
71
+ return {
72
+ group: 'capability-evidence',
73
+ action: 'A claimed capability has no usable evidence: re-derive the card so each capability references existing evidence.',
74
+ };
75
+ if (code === 'skill_version_mismatch' ||
76
+ code === 'skill_files_changed' ||
77
+ code === 'skill_files_unavailable')
78
+ return {
79
+ group: 'skill-bundle',
80
+ action: 'The required skill bundle differs from the pinned fingerprint or is unreadable: restore the pinned bundle or update the requirement deliberately.',
81
+ };
82
+ if (code === 'assignee_cwd_unavailable')
83
+ return {
84
+ group: 'identity',
85
+ action: 'The assigned cwd is unreadable from here: run readiness from a process that can read it. cwd is part of the identity.',
86
+ };
87
+ if (IDENTITY_BLOCKERS.has(code))
88
+ return { group: 'identity', action: IDENTITY_RECOVERY };
89
+ return null;
90
+ }
91
+ function recoveryLines(checks) {
92
+ const groups = new Map();
93
+ for (const check of checks) {
94
+ const guidance = recoveryFor(check.code);
95
+ if (guidance === null)
96
+ continue;
97
+ const existing = groups.get(guidance.group);
98
+ if (existing === undefined) {
99
+ groups.set(guidance.group, {
100
+ action: guidance.action,
101
+ codes: new Set([check.code]),
102
+ });
103
+ continue;
104
+ }
105
+ existing.codes.add(check.code);
106
+ }
107
+ return [...groups.entries()].map(([group, entry]) => ` ${group}: ${entry.action} (${[...entry.codes].join(', ')})`);
108
+ }
109
+ function emitHuman(report, output) {
110
+ if (report.status === 'ready') {
111
+ output.stdout(`Preflight ready${report.checked_at === undefined ? '' : ` at ${report.checked_at}`}.\n`);
112
+ }
113
+ else if (report.status === 'needs_input') {
114
+ output.stdout(`Preflight needs input: ${report.blockers.length} blocker(s).\n`);
115
+ for (const line of describeChecks(report.blockers))
116
+ output.stdout(`${line}\n`);
117
+ const recovery = recoveryLines(report.blockers);
118
+ if (recovery.length > 0) {
119
+ output.stdout('Recovery:\n');
120
+ for (const line of recovery)
121
+ output.stdout(`${line}\n`);
122
+ }
123
+ }
124
+ else {
125
+ output.stdout(`Preflight invalid: ${report.errors[0] ?? 'invalid input'}.\n`);
126
+ for (const error of report.errors.slice(1))
127
+ output.stdout(` - ${error}\n`);
128
+ }
129
+ if (report.warnings.length > 0) {
130
+ output.stdout(`Warnings: ${report.warnings.length}.\n`);
131
+ for (const line of describeChecks(report.warnings))
132
+ output.stdout(`${line}\n`);
133
+ }
134
+ if (report.limits.length > 0) {
135
+ output.stdout(`Limits: ${report.limits.join(', ')}.\n`);
136
+ }
137
+ }
138
+ export function runCollaborationPreflightCommand(options, output) {
139
+ if (options.assignmentFile === null) {
140
+ return usageFailure(output, options, 'assignment_required', 'preflight requires --assignment <abs assignment.json>.');
141
+ }
142
+ if (options.capabilitiesFile === null) {
143
+ return usageFailure(output, options, 'capabilities_required', 'preflight requires --capabilities <abs card.json>.');
144
+ }
145
+ let maxAgeMinutes;
146
+ if (options.maxAgeMinutes !== null) {
147
+ const parsed = Number(options.maxAgeMinutes.trim());
148
+ if (!Number.isFinite(parsed) || parsed <= 0) {
149
+ return usageFailure(output, options, 'max_age_invalid', '--max-age-minutes must be a positive finite number.');
150
+ }
151
+ maxAgeMinutes = parsed;
152
+ }
153
+ const report = runCollaborationPreflight({
154
+ assignmentFile: options.assignmentFile,
155
+ capabilitiesFile: options.capabilitiesFile,
156
+ ...(maxAgeMinutes === undefined ? {} : { maxAgeMinutes }),
157
+ });
158
+ if (options.json) {
159
+ output.stdout(`${JSON.stringify(report)}\n`);
160
+ }
161
+ else {
162
+ emitHuman(report, output);
163
+ }
164
+ if (report.status === 'ready')
165
+ return 0;
166
+ return report.status === 'needs_input' ? 1 : 2;
167
+ }
@@ -0,0 +1,46 @@
1
+ import { type RecoveryController } from '../../app/collab-recovery-executor.js';
2
+ import type { RecoveryPolicy } from '../../app/collab-recovery-projection.js';
3
+ import type { Identity } from '../../collab/types.js';
4
+ import type { CliOutput } from '../output.js';
5
+ export declare const COLLAB_RECOVERY_RUN_SCHEMA: 'pappra/collab-recovery-run/1';
6
+ export declare const collaborationRecoveryRunUsage: string;
7
+ /** Typed options for the handler; a parser rejects duplicate and unknown flags at the boundary. */
8
+ export interface CollaborationRecoveryRunOptions {
9
+ readonly requestFile: string | null;
10
+ readonly apply: boolean;
11
+ readonly json: boolean;
12
+ }
13
+ export interface CollaborationRecoveryRunParse {
14
+ readonly options: CollaborationRecoveryRunOptions;
15
+ readonly errors: readonly string[];
16
+ }
17
+ /** The request file supplied to the handler; mode is derived from the --apply flag, not the file. */
18
+ export interface RecoveryRunRequestFile {
19
+ readonly schema: 'pappra/collab-recovery-run-request/1';
20
+ readonly taskRoot: string;
21
+ readonly planFile: string;
22
+ readonly self: Identity;
23
+ readonly policy: RecoveryPolicy;
24
+ readonly expected?: {
25
+ readonly session_id: string;
26
+ readonly cwd?: string | null;
27
+ readonly binding_ref?: string | null;
28
+ readonly binding_digest?: string | null;
29
+ readonly pane_id?: string | null;
30
+ readonly harness?: string | null;
31
+ } | null;
32
+ readonly requestId: string;
33
+ readonly target?: {
34
+ readonly agent: string;
35
+ } | null;
36
+ }
37
+ /** Parse argv for the recovery-run command, rejecting duplicate and unknown options. */
38
+ export declare function parseCollaborationRecoveryRunArgs(argv: readonly string[]): CollaborationRecoveryRunParse;
39
+ /**
40
+ * Durable recovery execution handler, exported for the integration router. It builds a Herdr-backed
41
+ * controller only for an `--apply` request that names a target agent; a dry plan needs no controller
42
+ * and issues no effect.
43
+ */
44
+ export declare function runCollaborationRecoveryRunCommand(options: CollaborationRecoveryRunOptions, output: CliOutput, deps?: {
45
+ readonly controller?: RecoveryController;
46
+ }): Promise<number>;
@@ -0,0 +1,224 @@
1
+ import path from 'node:path';
2
+ import { readBoundedFile } from '../../app/bounded-file.js';
3
+ import { createHerdrRecoveryController, executeRecovery, } from '../../app/collab-recovery-executor.js';
4
+ export const COLLAB_RECOVERY_RUN_SCHEMA = 'pappra/collab-recovery-run/1';
5
+ const MAX_REQUEST_BYTES = 64 * 1024;
6
+ export const collaborationRecoveryRunUsage = 'pappra collab recovery-run --request <abs recovery-run.json> [--apply] [--json]\n\n' +
7
+ 'Durable recovery execution for a single task. Without --apply this is a strict dry\n' +
8
+ 'plan: it reads the current task and recommendation and writes nothing. With --apply,\n' +
9
+ 'the request must pin the exact session, cwd, harness, pane and bounded task-local\n' +
10
+ 'binding path/digest for the admitted current task participant; no identity or\n' +
11
+ 'participant fallback is accepted. The live target and current authority are rechecked\n' +
12
+ 'before prompting. It never spawns a session, overrides a model, installs anything or\n' +
13
+ 'auto-approves.';
14
+ /** Parse argv for the recovery-run command, rejecting duplicate and unknown options. */
15
+ export function parseCollaborationRecoveryRunArgs(argv) {
16
+ const errors = [];
17
+ let requestFile = null;
18
+ let apply = false;
19
+ let json = false;
20
+ let sawApply = false;
21
+ let sawJson = false;
22
+ for (let i = 0; i < argv.length; i += 1) {
23
+ const arg = argv[i];
24
+ if (arg === '--request') {
25
+ if (requestFile !== null)
26
+ errors.push('--request may be given only once.');
27
+ const value = argv[i + 1];
28
+ if (value === undefined || value.startsWith('--'))
29
+ errors.push('--request requires a value.');
30
+ else {
31
+ requestFile = value;
32
+ i += 1;
33
+ }
34
+ }
35
+ else if (arg === '--apply') {
36
+ if (sawApply)
37
+ errors.push('--apply may be given only once.');
38
+ sawApply = true;
39
+ apply = true;
40
+ }
41
+ else if (arg === '--json') {
42
+ if (sawJson)
43
+ errors.push('--json may be given only once.');
44
+ sawJson = true;
45
+ json = true;
46
+ }
47
+ else {
48
+ errors.push(`unknown option: ${String(arg)}`);
49
+ }
50
+ }
51
+ return { options: { requestFile, apply, json }, errors };
52
+ }
53
+ function isIdentity(value) {
54
+ return (typeof value === 'object' &&
55
+ value !== null &&
56
+ typeof value.agent_id === 'string' &&
57
+ typeof value.session_id === 'string' &&
58
+ (typeof value.harness === 'string' ||
59
+ value.harness === null));
60
+ }
61
+ function isPinnedExpected(value) {
62
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
63
+ return false;
64
+ const expected = value;
65
+ const keys = Object.keys(expected).sort();
66
+ return (keys.join('|') ===
67
+ 'binding_digest|binding_ref|cwd|harness|pane_id|session_id' &&
68
+ typeof expected.session_id === 'string' &&
69
+ expected.session_id.length > 0 &&
70
+ typeof expected.cwd === 'string' &&
71
+ path.isAbsolute(expected.cwd) &&
72
+ typeof expected.binding_ref === 'string' &&
73
+ path.isAbsolute(expected.binding_ref) &&
74
+ typeof expected.binding_digest === 'string' &&
75
+ /^sha256:[0-9a-f]{64}$/.test(expected.binding_digest) &&
76
+ typeof expected.pane_id === 'string' &&
77
+ /^[A-Za-z0-9]+:p[A-Za-z0-9]+$/.test(expected.pane_id) &&
78
+ typeof expected.harness === 'string' &&
79
+ expected.harness.length > 0);
80
+ }
81
+ function loadRequestFile(file) {
82
+ const read = readBoundedFile(file, MAX_REQUEST_BYTES);
83
+ if (!read.ok)
84
+ return { ok: false, error: `request file unreadable (${read.code}).` };
85
+ let parsed;
86
+ try {
87
+ parsed = JSON.parse(read.text);
88
+ }
89
+ catch {
90
+ return { ok: false, error: 'request file is not valid JSON.' };
91
+ }
92
+ if (typeof parsed !== 'object' || parsed === null)
93
+ return { ok: false, error: 'request must be an object.' };
94
+ const raw = parsed;
95
+ if (raw.schema !== 'pappra/collab-recovery-run-request/1')
96
+ return { ok: false, error: 'unsupported request schema.' };
97
+ if (typeof raw.taskRoot !== 'string' || !path.isAbsolute(raw.taskRoot))
98
+ return { ok: false, error: 'taskRoot must be an absolute path.' };
99
+ if (typeof raw.planFile !== 'string' || !path.isAbsolute(raw.planFile))
100
+ return { ok: false, error: 'planFile must be an absolute path.' };
101
+ if (!isIdentity(raw.self))
102
+ return { ok: false, error: 'self must be a valid identity.' };
103
+ const policy = raw.policy;
104
+ if (typeof policy !== 'object' ||
105
+ policy === null ||
106
+ (policy.role !== 'writer' &&
107
+ policy.role !== 'coordinator' &&
108
+ policy.role !== 'reviewer'))
109
+ return {
110
+ ok: false,
111
+ error: 'policy.role must be writer, coordinator or reviewer.',
112
+ };
113
+ if (typeof raw.requestId !== 'string' || raw.requestId.length === 0)
114
+ return { ok: false, error: 'requestId must be a non-empty string.' };
115
+ if (raw.expected !== undefined &&
116
+ raw.expected !== null &&
117
+ !isPinnedExpected(raw.expected))
118
+ return {
119
+ ok: false,
120
+ error: 'expected must pin session, cwd, harness, pane, binding_ref and binding_digest exactly.',
121
+ };
122
+ if (raw.target !== undefined &&
123
+ raw.target !== null &&
124
+ (typeof raw.target !== 'object' ||
125
+ Array.isArray(raw.target) ||
126
+ typeof raw.target.agent !== 'string' ||
127
+ !raw.target.agent))
128
+ return {
129
+ ok: false,
130
+ error: 'target.agent must be a non-empty Herdr agent name.',
131
+ };
132
+ return { ok: true, value: raw };
133
+ }
134
+ function invalid(output, options, errors) {
135
+ if (options.json)
136
+ output.stdout(`${JSON.stringify({ schema: COLLAB_RECOVERY_RUN_SCHEMA, ok: false, status: 'invalid', errors })}\n`);
137
+ else {
138
+ output.stdout('Recovery run request invalid.\n');
139
+ for (const error of errors)
140
+ output.stdout(` - ${error}\n`);
141
+ }
142
+ return 2;
143
+ }
144
+ /**
145
+ * Durable recovery execution handler, exported for the integration router. It builds a Herdr-backed
146
+ * controller only for an `--apply` request that names a target agent; a dry plan needs no controller
147
+ * and issues no effect.
148
+ */
149
+ export async function runCollaborationRecoveryRunCommand(options, output, deps = {}) {
150
+ if (options.requestFile === null)
151
+ return invalid(output, options, ['--request is required.']);
152
+ if (!path.isAbsolute(options.requestFile))
153
+ return invalid(output, options, ['--request must be absolute.']);
154
+ const loaded = loadRequestFile(options.requestFile);
155
+ if (!loaded.ok)
156
+ return invalid(output, options, [loaded.error]);
157
+ const request = loaded.value;
158
+ const mode = options.apply ? 'apply' : 'plan';
159
+ if (mode === 'apply' &&
160
+ (!isPinnedExpected(request.expected) ||
161
+ typeof request.target?.agent !== 'string' ||
162
+ request.target.agent.length === 0))
163
+ return invalid(output, options, [
164
+ 'apply requires a complete expected session/cwd/harness/pane plus a task-local binding_ref and binding_digest, and request.target.agent.',
165
+ ]);
166
+ let controller;
167
+ if (deps.controller)
168
+ controller = deps.controller;
169
+ else if (mode === 'apply') {
170
+ if (!request.target || typeof request.target.agent !== 'string')
171
+ return invalid(output, options, [
172
+ 'apply requires request.target.agent for the continuation wake.',
173
+ ]);
174
+ controller = createHerdrRecoveryController({ env: process.env }, { agent: request.target.agent });
175
+ }
176
+ else {
177
+ controller = {
178
+ id: 'recovery-plan-noop',
179
+ perform: async () => ({
180
+ disposition: 'unknown',
181
+ detail: 'plan mode issues no effect',
182
+ observation: 'none',
183
+ }),
184
+ };
185
+ }
186
+ const executorRequest = {
187
+ taskRoot: request.taskRoot,
188
+ planFile: request.planFile,
189
+ self: request.self,
190
+ policy: request.policy,
191
+ requestId: request.requestId,
192
+ mode,
193
+ ...(isPinnedExpected(request.expected)
194
+ ? {
195
+ expectedSession: {
196
+ session_id: request.expected.session_id,
197
+ cwd: request.expected.cwd,
198
+ binding_digest: request.expected.binding_digest,
199
+ binding_ref: request.expected.binding_ref,
200
+ target_agent: request.target?.agent ?? null,
201
+ pane_id: request.expected.pane_id,
202
+ harness: request.expected.harness,
203
+ },
204
+ }
205
+ : {}),
206
+ };
207
+ const result = await executeRecovery(executorRequest, { controller });
208
+ if (options.json) {
209
+ output.stdout(`${JSON.stringify({ schema: COLLAB_RECOVERY_RUN_SCHEMA, ok: result.ok, executor: result })}\n`);
210
+ }
211
+ else {
212
+ output.stdout(`Recovery ${mode}: ${result.status}${result.action ? ` (${result.action.kind} ${result.action.subtask_id ?? '-'})` : ''}.\n`);
213
+ for (const note of result.notes)
214
+ output.stdout(` - ${note}\n`);
215
+ if (result.reservation)
216
+ output.stdout(` reservation: ${result.reservation.created ? 'created' : 'existing'} ${result.reservation.key.slice(0, 12)} outcome=${result.reservation.outcome ?? 'none'}\n`);
217
+ }
218
+ // Exit success for a clean plan or a positively issued/deferred apply; block otherwise.
219
+ const good = result.status === 'planned' ||
220
+ result.status === 'applied' ||
221
+ result.status === 'deferred' ||
222
+ result.status === 'noop';
223
+ return good ? 0 : 1;
224
+ }
@@ -0,0 +1,11 @@
1
+ import { type RecoveryAction } from '../../app/collab-recovery.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationRecoveryUsage: string;
4
+ export interface CollaborationRecoveryOptions {
5
+ readonly action: RecoveryAction | null;
6
+ readonly taskRoot: string | null;
7
+ readonly requestFile: string | null;
8
+ readonly apply: boolean;
9
+ readonly json: boolean;
10
+ }
11
+ export declare function runCollaborationRecoveryCommand(options: CollaborationRecoveryOptions, output: CliOutput): Promise<number>;