@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,104 @@
1
+ import path from 'node:path';
2
+ import { COLLAB_RECOVERY_SCHEMA, applyRecovery, inspectRecovery, loadRecoveryRequest, planRecovery, } from '../../app/collab-recovery.js';
3
+ export const collaborationRecoveryUsage = 'pappra collab recovery inspect --task-root <abs> [--json]\n' +
4
+ 'pappra collab recovery <reconcile|lock-break> --task-root <abs> --request <abs request.json> [--apply] [--json]\n\n' +
5
+ 'Read-only recovery inspection or explicit recorded recovery. Reconcile resolves\n' +
6
+ 'one uncertainty (and optionally applies an existing state transition) atomically.\n' +
7
+ 'Lock-break archives one task write lock only after an operator stop assertion and\n' +
8
+ 'an exact inspected fingerprint. No native execution is queried or controlled.';
9
+ function invalid(output, options, errors) {
10
+ if (options.json) {
11
+ output.stdout(`${JSON.stringify({
12
+ schema: COLLAB_RECOVERY_SCHEMA,
13
+ ok: false,
14
+ status: 'invalid',
15
+ action: options.action,
16
+ errors,
17
+ })}\n`);
18
+ }
19
+ else {
20
+ output.stdout(`Recovery request invalid.\n`);
21
+ for (const error of errors)
22
+ output.stdout(` - ${error}\n`);
23
+ }
24
+ return 2;
25
+ }
26
+ function failure(output, options, value, exitCode) {
27
+ if (options.json) {
28
+ output.stdout(`${JSON.stringify({
29
+ schema: COLLAB_RECOVERY_SCHEMA,
30
+ ok: false,
31
+ status: exitCode === 2 ? 'invalid' : 'needs_input',
32
+ action: options.action,
33
+ code: value.code,
34
+ message: value.message,
35
+ nextAction: value.nextAction,
36
+ })}\n`);
37
+ }
38
+ else {
39
+ output.stdout(`Recovery needs input: ${value.message}\n`);
40
+ if (value.nextAction)
41
+ output.stdout(` ${value.nextAction}\n`);
42
+ }
43
+ return exitCode;
44
+ }
45
+ function emitInspect(value, output) {
46
+ const uncertainty = value.uncertainty;
47
+ const lock = value.lock;
48
+ output.stdout(`Recovery ${value.ok === true ? 'ready' : 'needs input'}: ${String(uncertainty.counts.open)} open uncertainty, ${String(uncertainty.counts.resolved)} resolved.\n`);
49
+ output.stdout(` lock: ${lock.held ? (lock.holder_process_alive ? 'held (holder alive)' : 'held (holder liveness unconfirmed)') : 'not held'}; transactions: ${String(lock.transaction_count)}; fingerprint: ${lock.fingerprint_status}\n`);
50
+ }
51
+ function emitHuman(value, action, output) {
52
+ if (value.status === 'planned' && value.applied === false) {
53
+ output.stdout(action === 'reconcile'
54
+ ? 'Reconcile plan validates the request and task namespace; nothing was written.\n'
55
+ : 'Lock-break plan validates the request and task namespace; nothing was archived.\n');
56
+ return;
57
+ }
58
+ if (action === 'reconcile') {
59
+ output.stdout(value.ok === true
60
+ ? `Reconcile applied: resolution recorded; state transition ${String(value.result?.state_transition ?? 'none')}.\n`
61
+ : `Reconcile refused: ${String(value.reason ?? 'unknown')}.\n`);
62
+ }
63
+ else if (value.ok === true) {
64
+ output.stdout(`Lock-break archived ${String(value.archived_lock ?? 'the task lock')}.\n`);
65
+ }
66
+ else {
67
+ output.stdout(`Lock-break refused: ${String(value.reason ?? 'unknown')}.\n`);
68
+ }
69
+ }
70
+ export async function runCollaborationRecoveryCommand(options, output) {
71
+ if (options.action === null)
72
+ return invalid(output, options, ['recovery requires an action.']);
73
+ if (options.taskRoot === null)
74
+ return invalid(output, options, ['--task-root is required.']);
75
+ if (!path.isAbsolute(options.taskRoot))
76
+ return invalid(output, options, ['--task-root must be absolute.']);
77
+ if (options.action === 'inspect') {
78
+ const result = await inspectRecovery(options.taskRoot);
79
+ if (!result.ok)
80
+ return failure(output, options, result, 1);
81
+ if (options.json)
82
+ output.stdout(`${JSON.stringify(result.value)}\n`);
83
+ else
84
+ emitInspect(result.value, output);
85
+ return result.value.ok === true ? 0 : 1;
86
+ }
87
+ if (options.requestFile === null)
88
+ return invalid(output, options, [`${options.action} requires --request.`]);
89
+ if (!path.isAbsolute(options.requestFile))
90
+ return invalid(output, options, ['--request must be absolute.']);
91
+ const loaded = loadRecoveryRequest(options.requestFile, options.action);
92
+ if (!loaded.ok)
93
+ return failure(output, options, loaded, 2);
94
+ const result = options.apply
95
+ ? await applyRecovery(options.taskRoot, loaded.value.request)
96
+ : await planRecovery(options.taskRoot, loaded.value.request);
97
+ if (!result.ok)
98
+ return failure(output, options, result, 1);
99
+ if (options.json)
100
+ output.stdout(`${JSON.stringify(result.value)}\n`);
101
+ else
102
+ emitHuman(result.value, options.action, output);
103
+ return result.value.ok === true ? 0 : 1;
104
+ }
@@ -0,0 +1,11 @@
1
+ import { type ResourceAction } from '../../app/collab-resources.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationResourcesUsage: string;
4
+ export interface CollaborationResourcesOptions {
5
+ readonly action: ResourceAction | null;
6
+ readonly taskRoot: string | null;
7
+ readonly requestFile: string | null;
8
+ readonly apply: boolean;
9
+ readonly json: boolean;
10
+ }
11
+ export declare function runCollaborationResourcesCommand(options: CollaborationResourcesOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,96 @@
1
+ import path from 'node:path';
2
+ import { COLLAB_RESOURCES_SCHEMA, applyResourceRequest, listTaskResources, loadResourceRequest, planResourceRequest, } from '../../app/collab-resources.js';
3
+ export const collaborationResourcesUsage = 'pappra collab resource <list|claim|release> --task-root <abs> [options]\n' +
4
+ ' list --task-root <abs> [--json]\n' +
5
+ ' claim --task-root <abs> --request <abs request.json> [--apply] [--json]\n' +
6
+ ' release --task-root <abs> --request <abs request.json> [--apply] [--json]\n\n' +
7
+ 'Read/plan is non-mutating. --apply invokes the existing cooperative claim or\n' +
8
+ 'release primitive and never fences OS side effects. Exit 0 success,\n' +
9
+ '1 conflict/uncertainty/core refusal, 2 invalid request/options.';
10
+ function invalid(output, options, errors) {
11
+ if (options.json) {
12
+ output.stdout(`${JSON.stringify({
13
+ schema: COLLAB_RESOURCES_SCHEMA,
14
+ ok: false,
15
+ status: 'invalid',
16
+ action: options.action,
17
+ errors,
18
+ })}\n`);
19
+ }
20
+ else {
21
+ output.stdout(`Resource request invalid.\n`);
22
+ for (const error of errors)
23
+ output.stdout(` - ${error}\n`);
24
+ }
25
+ return 2;
26
+ }
27
+ function failure(output, options, value, exitCode) {
28
+ if (options.json) {
29
+ output.stdout(`${JSON.stringify({
30
+ schema: COLLAB_RESOURCES_SCHEMA,
31
+ ok: false,
32
+ status: exitCode === 2 ? 'invalid' : 'needs_input',
33
+ action: options.action,
34
+ code: value.code,
35
+ message: value.message,
36
+ nextAction: value.nextAction,
37
+ })}\n`);
38
+ }
39
+ else {
40
+ output.stdout(`Resource operation needs input: ${value.message}\n`);
41
+ if (value.nextAction)
42
+ output.stdout(` ${value.nextAction}\n`);
43
+ }
44
+ return exitCode;
45
+ }
46
+ function emitHuman(value, action, output) {
47
+ if (action === 'list') {
48
+ const counts = value.counts;
49
+ output.stdout(`Domain resources: ${String(counts.tasks)} task(s), ${String(counts.claims)} claim(s), state ${String(value.state)}.\n`);
50
+ if (value.unreadable_tasks.length)
51
+ output.stdout(` unreadable tasks: ${String(value.unreadable_tasks.length)}\n`);
52
+ }
53
+ else if (value.applied === false) {
54
+ output.stdout(`Resource ${action} plan validated; nothing was persisted.\n`);
55
+ }
56
+ else {
57
+ output.stdout(`Resource ${action} ${value.ok === true ? 'applied' : 'refused'}: ${String(value.reason ?? 'completed')}.\n`);
58
+ }
59
+ }
60
+ export async function runCollaborationResourcesCommand(options, output) {
61
+ if (options.action === null)
62
+ return invalid(output, options, [
63
+ 'resource requires list, claim or release.',
64
+ ]);
65
+ if (options.taskRoot === null)
66
+ return invalid(output, options, ['--task-root is required.']);
67
+ if (!path.isAbsolute(options.taskRoot))
68
+ return invalid(output, options, ['--task-root must be absolute.']);
69
+ if (options.action === 'list') {
70
+ const result = await listTaskResources(options.taskRoot);
71
+ if (!result.ok)
72
+ return failure(output, options, result, 1);
73
+ if (options.json)
74
+ output.stdout(`${JSON.stringify(result.value)}\n`);
75
+ else
76
+ emitHuman(result.value, options.action, output);
77
+ return result.value.ok === true ? 0 : 1;
78
+ }
79
+ if (options.requestFile === null)
80
+ return invalid(output, options, [`${options.action} requires --request.`]);
81
+ if (!path.isAbsolute(options.requestFile))
82
+ return invalid(output, options, ['--request must be absolute.']);
83
+ const loaded = loadResourceRequest(options.requestFile, options.action);
84
+ if (!loaded.ok)
85
+ return failure(output, options, loaded, 2);
86
+ const result = options.apply
87
+ ? await applyResourceRequest(options.taskRoot, loaded.value.request)
88
+ : await planResourceRequest(options.taskRoot, loaded.value.request);
89
+ if (!result.ok)
90
+ return failure(output, options, result, 1);
91
+ if (options.json)
92
+ output.stdout(`${JSON.stringify(result.value)}\n`);
93
+ else
94
+ emitHuman(result.value, options.action, output);
95
+ return result.value.ok === true ? 0 : 1;
96
+ }
@@ -0,0 +1,9 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const collaborationRolePlanUsage: string;
3
+ export declare function runCollaborationRolePlanCommand(options: {
4
+ readonly action: string;
5
+ readonly requestFile: string | null;
6
+ readonly taskRoot: string | null;
7
+ readonly planFile: string | null;
8
+ readonly json: boolean;
9
+ }, output: CliOutput): Promise<number>;
@@ -0,0 +1,69 @@
1
+ import { readBoundedFile } from '../../app/bounded-file.js';
2
+ import { expandRolePlan, aggregateRolePlan, } from '../../app/collab-role-plan.js';
3
+ import { inspectWorkPlan } from '../../app/collab-work-plan.js';
4
+ import { canonicalJson } from '../../collab/envelope.js';
5
+ export const collaborationRolePlanUsage = 'pappra collab role-plan expand --request <abs role-plan.json> [--json]\n' +
6
+ 'pappra collab role-plan aggregate --request <abs role-plan.json> --task-root <abs> --config <abs expanded-plan.json> [--json]\n\n' +
7
+ 'Read-only writer/reviewer expansion and authoritative task-result aggregation.\n' +
8
+ 'Save the returned plan, then use collab plan/work-run for existing admission and dispatch.\n' +
9
+ 'Roles never grant authority; delivery never implies acceptance.';
10
+ function loadJson(file) {
11
+ if (file === null)
12
+ throw new Error('An absolute input file is required.');
13
+ const loaded = readBoundedFile(file, 512 * 1024);
14
+ if (!loaded.ok)
15
+ throw new Error(`Input refused: ${loaded.code}.`);
16
+ try {
17
+ return JSON.parse(loaded.text);
18
+ }
19
+ catch {
20
+ throw new Error('Input must be JSON.');
21
+ }
22
+ }
23
+ export async function runCollaborationRolePlanCommand(options, output) {
24
+ const emit = (value) => {
25
+ output.stdout(`${JSON.stringify(value, null, options.json ? undefined : 2)}\n`);
26
+ };
27
+ try {
28
+ if (options.action !== 'expand' && options.action !== 'aggregate')
29
+ throw new Error('role-plan accepts expand or aggregate.');
30
+ if (options.action === 'expand' &&
31
+ (options.taskRoot !== null || options.planFile !== null))
32
+ throw new Error('expand accepts only --request and --json.');
33
+ const expanded = expandRolePlan(loadJson(options.requestFile));
34
+ if (!expanded.ok) {
35
+ emit(expanded);
36
+ return 2;
37
+ }
38
+ if (options.action === 'expand') {
39
+ emit(expanded);
40
+ return 0;
41
+ }
42
+ if (options.taskRoot === null || options.planFile === null)
43
+ throw new Error('aggregate requires --task-root and --config.');
44
+ if (canonicalJson(loadJson(options.planFile)) !== canonicalJson(expanded.plan))
45
+ throw new Error('Persisted plan differs from the expanded role request.');
46
+ const report = await inspectWorkPlan({
47
+ taskRoot: options.taskRoot,
48
+ planFile: options.planFile,
49
+ });
50
+ const result = aggregateRolePlan(expanded, report.core ?? {
51
+ ok: false,
52
+ diagnostics: report.diagnostics.map((entry) => ({
53
+ ...entry,
54
+ node_id: null,
55
+ })),
56
+ });
57
+ emit(result);
58
+ return result.outcome === 'unknown' || result.outcome === 'missing' ? 1 : 0;
59
+ }
60
+ catch (error) {
61
+ emit({
62
+ ok: false,
63
+ status: 'invalid',
64
+ code: 'invalid_role_plan_request',
65
+ message: error instanceof Error ? error.message : 'Role plan request failed.',
66
+ });
67
+ return 2;
68
+ }
69
+ }
@@ -0,0 +1,11 @@
1
+ import { watchRoleOrchestration } from '../../app/collab-role-events.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationRoleRunUsage: string;
4
+ export declare function runCollaborationRoleRunCommand(options: {
5
+ readonly requestFile: string | null;
6
+ readonly apply: boolean;
7
+ readonly watch?: boolean;
8
+ readonly json: boolean;
9
+ }, output: CliOutput, deps?: {
10
+ readonly watch?: typeof watchRoleOrchestration;
11
+ }): Promise<number>;
@@ -0,0 +1,128 @@
1
+ import { loadRoleRunRequest, watchRoleOrchestration, } from '../../app/collab-role-events.js';
2
+ import { tickRoleOrchestration } from '../../app/collab-role-orchestration.js';
3
+ import { expandRolePlan } from '../../app/collab-role-plan.js';
4
+ import { inspectWorkPlan } from '../../app/collab-work-plan.js';
5
+ import { readBoundedFile } from '../../app/bounded-file.js';
6
+ import { canonicalJson } from '../../collab/envelope.js';
7
+ import { managedPiRepairDependencies } from '../../app/managed-pi-repair-stop.js';
8
+ export const collaborationRoleRunUsage = 'pappra collab role-run --request <abs role-orchestration.json> [--apply] [--watch] [--json]\n\n' +
9
+ 'Plan reads authoritative role/dependency state without effects. Apply handles one\n' +
10
+ 'bounded event tick, reserves before dispatch and never infers acceptance.\n' +
11
+ '--watch requires --apply and re-evaluates on relevant task/request/capability events.\n' +
12
+ 'Repeated or ambiguous effects are reconciled; rejected work requires an authorized repair attempt.';
13
+ const PUBLIC_ERRORS = new Set([
14
+ 'role_request_required',
15
+ 'role_request_invalid',
16
+ 'role_request_invalid_json',
17
+ 'role_request_path_not_absolute',
18
+ 'role_request_symlink',
19
+ 'role_request_not_regular',
20
+ 'role_request_too_large',
21
+ 'role_request_unreadable',
22
+ 'role_plan_file_mismatch',
23
+ 'watch_requires_apply',
24
+ 'role_event_request_path_not_absolute',
25
+ 'role_event_task_unavailable',
26
+ 'role_event_task_root_mismatch',
27
+ 'role_event_watch_initialization_failed',
28
+ ]);
29
+ function safeErrorCode(error) {
30
+ if (!(error instanceof Error))
31
+ return 'role_run_failed';
32
+ return PUBLIC_ERRORS.has(error.message) ? error.message : 'role_run_failed';
33
+ }
34
+ export async function runCollaborationRoleRunCommand(options, output, deps = {}) {
35
+ const emit = (value) => output.stdout(`${JSON.stringify(value, null, options.json ? undefined : 2)}\n`);
36
+ try {
37
+ if (options.watch && !options.apply)
38
+ throw new Error('watch_requires_apply');
39
+ if (!options.requestFile)
40
+ throw new Error('role_request_required');
41
+ if (options.watch) {
42
+ return await runWatch(options.requestFile, emit, deps.watch ?? watchRoleOrchestration);
43
+ }
44
+ const request = loadRoleRunRequest(options.requestFile);
45
+ if (!options.apply) {
46
+ const expanded = expandRolePlan(request.role_plan);
47
+ if (!expanded.ok) {
48
+ emit(expanded);
49
+ return 2;
50
+ }
51
+ const plan = readBoundedFile(request.execution.plan_file, 512 * 1024);
52
+ if (!plan.ok ||
53
+ canonicalJson(JSON.parse(plan.text)) !== canonicalJson(expanded.plan))
54
+ throw new Error('role_plan_file_mismatch');
55
+ const report = await inspectWorkPlan({
56
+ taskRoot: request.execution.task_root,
57
+ planFile: request.execution.plan_file,
58
+ });
59
+ emit({
60
+ schema: 'pappra/collab-role-orchestration-plan/1',
61
+ status: report.ok ? 'planned' : 'blocked',
62
+ effect: 'none',
63
+ inspection: report,
64
+ });
65
+ return report.ok ? 0 : 1;
66
+ }
67
+ const repair = managedPiRepairDependencies(request);
68
+ const report = await tickRoleOrchestration(request, repair ? { repair } : {});
69
+ emit(report);
70
+ return [
71
+ 'blocked',
72
+ 'reconciliation-required',
73
+ 'repair-required',
74
+ 'repair-exhausted',
75
+ 'budget-exhausted',
76
+ ].includes(report.status)
77
+ ? 1
78
+ : 0;
79
+ }
80
+ catch (error) {
81
+ emit({ ok: false, status: 'invalid', code: safeErrorCode(error) });
82
+ return 2;
83
+ }
84
+ }
85
+ async function runWatch(requestFile, emit, watch) {
86
+ emit({
87
+ schema: 'pappra/collab-role-orchestration-watch/1',
88
+ status: 'watching',
89
+ });
90
+ let resolveStop = null;
91
+ let stopped = false;
92
+ const stop = new Promise((resolve) => {
93
+ resolveStop = resolve;
94
+ });
95
+ const onSignal = (code) => () => {
96
+ if (stopped)
97
+ return;
98
+ stopped = true;
99
+ resolveStop?.(code);
100
+ };
101
+ const onInterrupt = onSignal(130);
102
+ const onTerminate = onSignal(143);
103
+ process.once('SIGINT', onInterrupt);
104
+ process.once('SIGTERM', onTerminate);
105
+ let watcher = null;
106
+ try {
107
+ watcher = await watch(requestFile, (result) => emit(result));
108
+ const signalCode = await stop;
109
+ const status = watcher.status();
110
+ emit({
111
+ schema: 'pappra/collab-role-orchestration-watch/1',
112
+ status: 'stopped',
113
+ result: status.result,
114
+ error: status.error,
115
+ });
116
+ return signalCode;
117
+ }
118
+ finally {
119
+ try {
120
+ if (watcher)
121
+ await watcher.close();
122
+ }
123
+ finally {
124
+ process.removeListener('SIGINT', onInterrupt);
125
+ process.removeListener('SIGTERM', onTerminate);
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,10 @@
1
+ import { type RolloverAction } from '../../app/collab-rollover.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationRolloverUsage: string;
4
+ export interface CollaborationRolloverOptions {
5
+ readonly action: RolloverAction;
6
+ readonly taskRoot: string | null;
7
+ readonly requestFile: string | null;
8
+ readonly json: boolean;
9
+ }
10
+ export declare function runCollaborationRolloverCommand(options: CollaborationRolloverOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,103 @@
1
+ import path from 'node:path';
2
+ import { COLLAB_ROLLOVER_REPORT_SCHEMA, inspectOrPlanRollover, loadRolloverRequest, } from '../../app/collab-rollover.js';
3
+ export const collaborationRolloverUsage = 'pappra collab rollover <inspect|plan> --task-root <abs> --request <abs request.json> [--json]\n\n' +
4
+ 'Read-only rollover inspection and planning against the authoritative task record\n' +
5
+ 'and one exact linked continuity handoff bundle. Nothing is claimed, transferred,\n' +
6
+ 'launched, archived, routed, notified or written, and no native query is made.\n\n' +
7
+ 'The request document is bounded (64 KiB) and separately versioned\n' +
8
+ '(schema pappra/collaboration-rollover-request/1). It names the absolute task root,\n' +
9
+ 'the exact bundle reference and digest, and either a recorded intent id or a\n' +
10
+ 'proposed intent. --task-root must equal the request task_root.\n\n' +
11
+ 'There is no apply action. A caller-supplied stop observation, exit code or\n' +
12
+ 'producer label is never authenticated native proof, so prepare-transfer stays\n' +
13
+ 'unavailable until an accepted host adapter produces quiescence evidence.\n\n' +
14
+ 'Exit 0 inspected (blocked steps included, plan_complete reports completion),\n' +
15
+ '1 the exact record or bundle cannot support the inspection, 2 invalid request.';
16
+ function emitFailure(output, options, kind, code, message, nextAction, details) {
17
+ if (options.json) {
18
+ output.stdout(`${JSON.stringify({
19
+ schema: COLLAB_ROLLOVER_REPORT_SCHEMA,
20
+ action: options.action,
21
+ ok: false,
22
+ kind,
23
+ code,
24
+ message,
25
+ next_action: nextAction,
26
+ task_root: options.taskRoot,
27
+ request: options.requestFile,
28
+ details,
29
+ limits: [
30
+ 'read_only_inspection',
31
+ 'no_apply_or_mutation',
32
+ 'host_stop_proof_unavailable',
33
+ 'native_launch_unavailable',
34
+ 'native_session_archive_unavailable',
35
+ 'routing_removal_pending',
36
+ ],
37
+ })}\n`);
38
+ }
39
+ else {
40
+ output.stdout(`Rollover ${options.action} rejected (${code}).\n`);
41
+ output.stdout(` ${message}\n`);
42
+ for (const detail of details)
43
+ output.stdout(` - ${detail}\n`);
44
+ if (nextAction !== null)
45
+ output.stdout(` next: ${nextAction}\n`);
46
+ }
47
+ return kind === 'invalid' ? 2 : 1;
48
+ }
49
+ function emitHuman(report, output) {
50
+ const intentLabel = report.intent.intent_id ?? '<unrecorded intent>';
51
+ output.stdout(`Rollover ${report.action} on task ${report.task_id} (revision ${report.state_revision}, epoch ${String(report.owner_epoch)}): intent ${intentLabel}.\n`);
52
+ output.stdout(` record: ${report.intent.found ? 'recorded intent' : 'proposed intent'}, handoff ${report.handoff.state ?? '<none>'}, attempt ${report.attempt?.state ?? '<none>'}\n`);
53
+ for (const claim of report.claims) {
54
+ output.stdout(` claim ${claim.claim_id}: holder ${claim.holder?.agent_id ?? '<none>'}, epoch ${String(claim.resource_epoch)} (expected ${claim.expected_resource_epoch})${claim.released_at === null ? '' : ', released'}\n`);
55
+ }
56
+ output.stdout(` bundle ${report.bundle.ref}: verified, context ${report.bundle.context_integrity}, association ${report.bundle.collaboration.matches_plan ? 'matches' : 'differs'}, execution ${String(report.bundle.execution_allowed)}\n`);
57
+ for (const step of report.steps) {
58
+ output.stdout(` ${step.step}: ${step.status}\n`);
59
+ for (const blocker of step.blockers)
60
+ output.stdout(` blocked by ${blocker.code}: ${blocker.detail}\n`);
61
+ }
62
+ if (report.drift.length > 0) {
63
+ output.stdout(' current-record drift:\n');
64
+ for (const blocker of report.drift)
65
+ output.stdout(` ${blocker.code}: ${blocker.detail}\n`);
66
+ }
67
+ output.stdout(` notify exclusion for the planned identities: ${report.notify_exclusion.effective}\n`);
68
+ if (report.evidence.requested.length > 0)
69
+ output.stdout(` evidence: ${report.evidence.supplied}/${report.evidence.requested.length} correlated envelope(s), ${report.evidence.raw_bytes} raw bytes\n`);
70
+ for (const entry of report.evidence.unreadable)
71
+ output.stdout(` unreadable ${entry.message_id}: ${entry.code}\n`);
72
+ output.stdout(` plan complete: ${String(report.plan_complete)} (host stop proof ${report.capabilities.host_stop_proof}, native launch ${report.capabilities.native_launch}, routing removal ${report.capabilities.routing_removal})\n`);
73
+ output.stdout(' read-only: no intent, claim, handoff, bundle, binding, notification or delivery file was written and nothing was applied.\n');
74
+ }
75
+ export async function runCollaborationRolloverCommand(options, output) {
76
+ const errors = [];
77
+ if (options.taskRoot === null)
78
+ errors.push('--task-root is required.');
79
+ else if (!path.isAbsolute(options.taskRoot))
80
+ errors.push('--task-root must be absolute.');
81
+ if (options.requestFile === null)
82
+ errors.push('--request is required.');
83
+ else if (!path.isAbsolute(options.requestFile))
84
+ errors.push('--request must be an absolute path to the request document.');
85
+ if (errors.length > 0)
86
+ return emitFailure(output, options, 'invalid', 'invalid_arguments', 'The rollover request is incomplete.', collaborationRolloverUsage, errors);
87
+ const loaded = loadRolloverRequest(options.requestFile);
88
+ if (loaded.ok === false)
89
+ return emitFailure(output, options, loaded.kind, loaded.code, loaded.message, loaded.nextAction, []);
90
+ const request = loaded.value;
91
+ if (options.action !== request.action)
92
+ return emitFailure(output, options, 'invalid', 'request_action_mismatch', `The command asks for ${options.action} but the request document declares ${request.action}.`, 'Use one action in both the command and the request document.', []);
93
+ if (path.resolve(request.task_root) !== path.resolve(options.taskRoot))
94
+ return emitFailure(output, options, 'invalid', 'task_root_mismatch', 'The request task_root is not the --task-root passed on the command line.', 'Use one absolute task root; the cwd is never used to infer it.', []);
95
+ const report = await inspectOrPlanRollover(request);
96
+ if (report.ok === false)
97
+ return emitFailure(output, options, report.kind, report.code, report.message, report.nextAction, []);
98
+ if (options.json)
99
+ output.stdout(`${JSON.stringify(report.value)}\n`);
100
+ else
101
+ emitHuman(report.value, output);
102
+ return 0;
103
+ }
@@ -0,0 +1,10 @@
1
+ import { type StateAction } from '../../app/collab-state.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationStateUsage: string;
4
+ export interface CollaborationStateOptions {
5
+ readonly action: StateAction | null;
6
+ readonly taskRoot: string | null;
7
+ readonly ownerEpoch: string | null;
8
+ readonly json: boolean;
9
+ }
10
+ export declare function runCollaborationStateCommand(options: CollaborationStateOptions, output: CliOutput): Promise<number>;
@@ -0,0 +1,96 @@
1
+ import path from 'node:path';
2
+ import { COLLAB_STATE_SCHEMA, checkTaskEpoch, doctorTaskState, showTaskState, } from '../../app/collab-state.js';
3
+ export const collaborationStateUsage = 'pappra collab state <show|doctor|epoch-check> --task-root <abs> [options]\n' +
4
+ ' show --task-root <abs> [--json]\n' +
5
+ ' doctor --task-root <abs> [--json]\n' +
6
+ ' epoch-check --task-root <abs> --owner-epoch <positive integer> [--json]\n\n' +
7
+ 'Read-only task-state projections over the existing record/lock/transaction\n' +
8
+ 'primitives. Nothing is repaired, released, restarted or launched. Exit 0 ready,\n' +
9
+ '1 needs_input/uncertainty, 2 invalid request/options.';
10
+ function invalid(output, options, errors) {
11
+ if (options.json) {
12
+ output.stdout(`${JSON.stringify({
13
+ schema: COLLAB_STATE_SCHEMA,
14
+ ok: false,
15
+ status: 'invalid',
16
+ action: options.action,
17
+ errors,
18
+ })}\n`);
19
+ }
20
+ else {
21
+ output.stdout(`State request invalid.\n`);
22
+ for (const error of errors)
23
+ output.stdout(` - ${error}\n`);
24
+ }
25
+ return 2;
26
+ }
27
+ function failure(output, options, value) {
28
+ if (options.json) {
29
+ output.stdout(`${JSON.stringify({
30
+ schema: COLLAB_STATE_SCHEMA,
31
+ ok: false,
32
+ status: 'needs_input',
33
+ action: options.action,
34
+ code: value.code,
35
+ message: value.message,
36
+ nextAction: value.nextAction,
37
+ })}\n`);
38
+ }
39
+ else {
40
+ output.stdout(`State needs input: ${value.message}\n`);
41
+ if (value.nextAction)
42
+ output.stdout(` ${value.nextAction}\n`);
43
+ }
44
+ return 1;
45
+ }
46
+ function emitHuman(value, action, output) {
47
+ if (action === 'show') {
48
+ output.stdout(`Task ${String(value.task_id)} revision ${String(value.state_revision)}.\n`);
49
+ output.stdout(` attempts: ${String(value.counts.attempts)}; claims: ${String(value.counts.claims)}; messages: ${String(value.messages)}\n`);
50
+ const lock = value.lock;
51
+ output.stdout(` lock: ${lock.held === true ? 'held' : 'not held'}; transactions: ${String(lock.transaction_count)}\n`);
52
+ }
53
+ else if (action === 'doctor') {
54
+ const findings = value.findings;
55
+ const counts = value.counts;
56
+ output.stdout(`Doctor ${value.ok === true ? 'ready' : 'needs input'}: ${String(counts.findings)} finding(s), ${String(counts.blocking)} blocking, ${String(counts.uncertain)} uncertain, ${String(counts.active)} active lock observation(s).\n`);
57
+ for (const finding of findings)
58
+ output.stdout(` - ${finding.severity}: ${finding.code}\n`);
59
+ }
60
+ else {
61
+ output.stdout(`Owner epoch ${value.ok === true ? 'matches' : 'does not match'}: expected ${String(value.expected)}, actual ${String(value.actual)}.\n`);
62
+ }
63
+ }
64
+ export async function runCollaborationStateCommand(options, output) {
65
+ if (options.action === null)
66
+ return invalid(output, options, [
67
+ 'state requires show, doctor or epoch-check.',
68
+ ]);
69
+ if (options.taskRoot === null)
70
+ return invalid(output, options, ['--task-root is required.']);
71
+ if (!path.isAbsolute(options.taskRoot))
72
+ return invalid(output, options, ['--task-root must be absolute.']);
73
+ let ownerEpoch = null;
74
+ if (options.action === 'epoch-check') {
75
+ if (options.ownerEpoch === null)
76
+ return invalid(output, options, ['epoch-check requires --owner-epoch.']);
77
+ const parsed = Number(options.ownerEpoch.trim());
78
+ if (!Number.isSafeInteger(parsed) || parsed <= 0)
79
+ return invalid(output, options, [
80
+ '--owner-epoch must be a positive integer.',
81
+ ]);
82
+ ownerEpoch = parsed;
83
+ }
84
+ const result = options.action === 'show'
85
+ ? await showTaskState(options.taskRoot)
86
+ : options.action === 'doctor'
87
+ ? await doctorTaskState(options.taskRoot)
88
+ : await checkTaskEpoch(options.taskRoot, ownerEpoch);
89
+ if (!result.ok)
90
+ return failure(output, options, result);
91
+ if (options.json)
92
+ output.stdout(`${JSON.stringify(result.value)}\n`);
93
+ else
94
+ emitHuman(result.value, options.action, output);
95
+ return result.value.ok === true ? 0 : 1;
96
+ }
@@ -0,0 +1,10 @@
1
+ import { type SessionTransitionAction, type SessionTransitionDependencies } from '../../app/collab-session-transition.js';
2
+ import type { CliOutput } from '../output.js';
3
+ export declare const collaborationTransitionUsage: string;
4
+ export interface CollaborationTransitionOptions {
5
+ readonly action: SessionTransitionAction | null;
6
+ readonly taskRoot: string | null;
7
+ readonly requestFile: string | null;
8
+ readonly json: boolean;
9
+ }
10
+ export declare function runCollaborationTransitionCommand(options: CollaborationTransitionOptions, output: CliOutput, dependencies?: SessionTransitionDependencies): Promise<number>;