@phyzess/pappra 0.1.0-beta.13 → 0.1.0-beta.18

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 (357) hide show
  1. package/README.md +134 -15
  2. package/assets/integrations/skills/pappra/SKILL.md +28 -7
  3. package/assets/integrations/skills/pappra/references/collaboration.md +633 -0
  4. package/assets/integrations/skills/pappra/references/environment.md +360 -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.d.ts +221 -0
  62. package/dist/app/collab-session-transition.js +3334 -0
  63. package/dist/app/collab-state.d.ts +7 -0
  64. package/dist/app/collab-state.js +162 -0
  65. package/dist/app/collab-task-store.d.ts +22 -0
  66. package/dist/app/collab-task-store.js +204 -0
  67. package/dist/app/collab-work-execution.d.ts +127 -0
  68. package/dist/app/collab-work-execution.js +1027 -0
  69. package/dist/app/collab-work-plan.d.ts +87 -0
  70. package/dist/app/collab-work-plan.js +437 -0
  71. package/dist/app/collaboration.d.ts +8 -2
  72. package/dist/app/collaboration.js +101 -12
  73. package/dist/app/doctor.js +108 -5
  74. package/dist/app/host-mcp.js +34 -8
  75. package/dist/app/host-probe.js +4 -4
  76. package/dist/app/init.d.ts +58 -4
  77. package/dist/app/init.js +768 -155
  78. package/dist/app/managed-pi-bootstrap-admission.d.ts +14 -0
  79. package/dist/app/managed-pi-bootstrap-admission.js +104 -0
  80. package/dist/app/managed-pi-bootstrap-refresh.d.ts +10 -0
  81. package/dist/app/managed-pi-bootstrap-refresh.js +78 -0
  82. package/dist/app/managed-pi-delivery.d.ts +8 -0
  83. package/dist/app/managed-pi-delivery.js +110 -0
  84. package/dist/app/managed-pi-handoff-receiver.d.ts +15 -0
  85. package/dist/app/managed-pi-handoff-receiver.js +263 -0
  86. package/dist/app/managed-pi-handoff-reference.d.ts +3 -0
  87. package/dist/app/managed-pi-handoff-reference.js +60 -0
  88. package/dist/app/managed-pi-herdr.d.ts +21 -0
  89. package/dist/app/managed-pi-herdr.js +185 -0
  90. package/dist/app/managed-pi-initial-admission.d.ts +28 -0
  91. package/dist/app/managed-pi-initial-admission.js +416 -0
  92. package/dist/app/managed-pi-initial-launch.d.ts +5 -0
  93. package/dist/app/managed-pi-initial-launch.js +61 -0
  94. package/dist/app/managed-pi-native-observation.d.ts +36 -0
  95. package/dist/app/managed-pi-native-observation.js +191 -0
  96. package/dist/app/managed-pi-readiness.d.ts +29 -0
  97. package/dist/app/managed-pi-readiness.js +288 -0
  98. package/dist/app/managed-pi-repair-stop.d.ts +21 -0
  99. package/dist/app/managed-pi-repair-stop.js +371 -0
  100. package/dist/app/managed-pi-resume-admission.d.ts +32 -0
  101. package/dist/app/managed-pi-resume-admission.js +618 -0
  102. package/dist/app/managed-pi-retirement.d.ts +28 -0
  103. package/dist/app/managed-pi-retirement.js +112 -0
  104. package/dist/app/managed-pi-sdk-control.d.ts +7 -0
  105. package/dist/app/managed-pi-sdk-control.js +169 -0
  106. package/dist/app/managed-pi-sdk-runtime.d.ts +3 -0
  107. package/dist/app/managed-pi-sdk-runtime.js +483 -0
  108. package/dist/app/managed-pi-source-admission.d.ts +14 -0
  109. package/dist/app/managed-pi-source-admission.js +323 -0
  110. package/dist/app/managed-pi-transition-host.d.ts +36 -0
  111. package/dist/app/managed-pi-transition-host.js +292 -0
  112. package/dist/app/managed-pi.d.ts +54 -0
  113. package/dist/app/managed-pi.js +248 -0
  114. package/dist/app/shell-readiness.d.ts +66 -0
  115. package/dist/app/shell-readiness.js +368 -0
  116. package/dist/app/task-pin.d.ts +2 -23
  117. package/dist/app/task-pin.js +2 -113
  118. package/dist/cli/commands/collaboration-binding.d.ts +13 -0
  119. package/dist/cli/commands/collaboration-binding.js +118 -0
  120. package/dist/cli/commands/collaboration-bootstrap.d.ts +10 -0
  121. package/dist/cli/commands/collaboration-bootstrap.js +84 -0
  122. package/dist/cli/commands/collaboration-capabilities.d.ts +13 -0
  123. package/dist/cli/commands/collaboration-capabilities.js +127 -0
  124. package/dist/cli/commands/collaboration-handoff.d.ts +13 -0
  125. package/dist/cli/commands/collaboration-handoff.js +102 -0
  126. package/dist/cli/commands/collaboration-message.d.ts +17 -0
  127. package/dist/cli/commands/collaboration-message.js +177 -0
  128. package/dist/cli/commands/collaboration-plan.d.ts +8 -0
  129. package/dist/cli/commands/collaboration-plan.js +108 -0
  130. package/dist/cli/commands/collaboration-preflight.d.ts +10 -0
  131. package/dist/cli/commands/collaboration-preflight.js +167 -0
  132. package/dist/cli/commands/collaboration-recovery-run.d.ts +46 -0
  133. package/dist/cli/commands/collaboration-recovery-run.js +224 -0
  134. package/dist/cli/commands/collaboration-recovery.d.ts +11 -0
  135. package/dist/cli/commands/collaboration-recovery.js +104 -0
  136. package/dist/cli/commands/collaboration-resources.d.ts +11 -0
  137. package/dist/cli/commands/collaboration-resources.js +96 -0
  138. package/dist/cli/commands/collaboration-role-plan.d.ts +9 -0
  139. package/dist/cli/commands/collaboration-role-plan.js +69 -0
  140. package/dist/cli/commands/collaboration-role-run.d.ts +11 -0
  141. package/dist/cli/commands/collaboration-role-run.js +128 -0
  142. package/dist/cli/commands/collaboration-rollover.d.ts +10 -0
  143. package/dist/cli/commands/collaboration-rollover.js +103 -0
  144. package/dist/cli/commands/collaboration-state.d.ts +10 -0
  145. package/dist/cli/commands/collaboration-state.js +96 -0
  146. package/dist/cli/commands/collaboration-transition.d.ts +10 -0
  147. package/dist/cli/commands/collaboration-transition.js +75 -0
  148. package/dist/cli/commands/collaboration-work-run.d.ts +34 -0
  149. package/dist/cli/commands/collaboration-work-run.js +178 -0
  150. package/dist/cli/commands/collaboration.d.ts +4 -0
  151. package/dist/cli/commands/collaboration.js +39 -4
  152. package/dist/cli/commands/continuity.js +2 -6
  153. package/dist/cli/commands/docs.d.ts +2 -0
  154. package/dist/cli/commands/docs.js +89 -15
  155. package/dist/cli/commands/host.d.ts +7 -1
  156. package/dist/cli/commands/host.js +122 -7
  157. package/dist/cli/commands/init.d.ts +20 -3
  158. package/dist/cli/commands/init.js +897 -232
  159. package/dist/cli/commands/mcp.d.ts +1 -0
  160. package/dist/cli/commands/mcp.js +11 -5
  161. package/dist/cli/commands/repair.d.ts +12 -0
  162. package/dist/cli/commands/repair.js +41 -0
  163. package/dist/cli/commands/runtime.d.ts +1 -1
  164. package/dist/cli/commands/runtime.js +139 -38
  165. package/dist/cli/commands/session.d.ts +7 -0
  166. package/dist/cli/commands/session.js +82 -0
  167. package/dist/cli/commands/task.js +19 -5
  168. package/dist/cli/run.js +866 -24
  169. package/dist/code/identity.d.ts +7 -0
  170. package/dist/code/identity.js +7 -3
  171. package/dist/code/registration.js +7 -0
  172. package/dist/code/service.d.ts +9 -0
  173. package/dist/code/service.js +16 -3
  174. package/dist/code/text.js +19 -7
  175. package/dist/collab/admission.d.ts +91 -66
  176. package/dist/collab/admission.js +21 -6
  177. package/dist/collab/canonical.d.ts +1 -1
  178. package/dist/collab/canonical.js +44 -3
  179. package/dist/collab/envelope.d.ts +2 -2
  180. package/dist/collab/envelope.js +12 -12
  181. package/dist/collab/first-work.d.ts +3 -0
  182. package/dist/collab/first-work.js +15 -0
  183. package/dist/collab/handoff.d.ts +16 -0
  184. package/dist/collab/handoff.js +39 -5
  185. package/dist/collab/index.d.ts +97 -1
  186. package/dist/collab/index.js +9 -1
  187. package/dist/collab/messages.js +126 -3
  188. package/dist/collab/persisted-messages.d.ts +123 -0
  189. package/dist/collab/persisted-messages.js +496 -0
  190. package/dist/collab/preflight.d.ts +1 -1
  191. package/dist/collab/resources.d.ts +13 -3
  192. package/dist/collab/resources.js +37 -6
  193. package/dist/collab/rollover.d.ts +311 -0
  194. package/dist/collab/rollover.js +1024 -0
  195. package/dist/collab/store.d.ts +1 -0
  196. package/dist/collab/store.js +1 -4
  197. package/dist/collab/types.d.ts +2 -354
  198. package/dist/collab/validation.d.ts +2 -10
  199. package/dist/collab/validation.js +2 -303
  200. package/dist/collab/work-plan.d.ts +105 -0
  201. package/dist/collab/work-plan.js +843 -0
  202. package/dist/continuity/context.d.ts +11 -2
  203. package/dist/continuity/context.js +100 -13
  204. package/dist/continuity/handoff-bundle.d.ts +296 -0
  205. package/dist/continuity/handoff-bundle.js +477 -0
  206. package/dist/continuity/index.d.ts +2 -0
  207. package/dist/continuity/index.js +1 -0
  208. package/dist/continuity/paths.js +10 -2
  209. package/dist/continuity/service.js +91 -15
  210. package/dist/continuity/task-pin.d.ts +24 -0
  211. package/dist/continuity/task-pin.js +590 -0
  212. package/dist/doctor.d.ts +1 -0
  213. package/dist/doctor.js +6 -0
  214. package/dist/experimental/index.d.ts +13 -0
  215. package/dist/experimental/index.js +25 -0
  216. package/dist/experimental/pi.d.ts +4 -0
  217. package/dist/experimental/pi.js +12 -0
  218. package/dist/hosts/claude/native.js +1 -1
  219. package/dist/hosts/codex/native.js +1 -1
  220. package/dist/hosts/codex/protocol.js +1 -1
  221. package/dist/hosts/integration/bootstrap-config.d.ts +58 -0
  222. package/dist/hosts/integration/bootstrap-config.js +254 -0
  223. package/dist/hosts/integration/bundle-export.d.ts +44 -0
  224. package/dist/hosts/integration/bundle-export.js +366 -3
  225. package/dist/hosts/integration/bundle.js +3 -0
  226. package/dist/hosts/integration/hook.js +36 -9
  227. package/dist/hosts/integration/pappra-bootstrap-extension.mjs +80 -0
  228. package/dist/hosts/integration/pappra-extension-runtime.mjs +59 -24631
  229. package/dist/hosts/integration/pappra-hook.mjs +61 -24749
  230. package/dist/hosts/integration/pappra-recovery-extension.mjs +259 -0
  231. package/dist/hosts/integration/pappra-session-transition-extension.mjs +276 -0
  232. package/dist/hosts/integration/pi-bootstrap-extension.d.ts +36 -0
  233. package/dist/hosts/integration/pi-bootstrap-extension.js +101 -0
  234. package/dist/hosts/integration/pi-bootstrap-guard.d.ts +125 -0
  235. package/dist/hosts/integration/pi-bootstrap-guard.js +438 -0
  236. package/dist/hosts/integration/pi-bootstrap-runtime.d.ts +63 -0
  237. package/dist/hosts/integration/pi-bootstrap-runtime.js +223 -0
  238. package/dist/hosts/integration/pi-native-events.d.ts +112 -0
  239. package/dist/hosts/integration/pi-native-events.js +348 -0
  240. package/dist/hosts/integration/pi-rollover-extension.d.ts +166 -0
  241. package/dist/hosts/integration/pi-rollover-extension.js +431 -0
  242. package/dist/hosts/integration/recovery-config.d.ts +48 -0
  243. package/dist/hosts/integration/recovery-config.js +117 -0
  244. package/dist/hosts/integration/service.d.ts +6 -1
  245. package/dist/hosts/integration/service.js +485 -35
  246. package/dist/hosts/integration/support.d.ts +7 -0
  247. package/dist/hosts/integration/support.js +9 -1
  248. package/dist/hosts/integration/templates.d.ts +3 -0
  249. package/dist/hosts/integration/templates.js +26 -3
  250. package/dist/hosts/pi/managed-host-identity.d.ts +2 -0
  251. package/dist/hosts/pi/managed-host-identity.js +40 -0
  252. package/dist/hosts/pi/managed-provider-diagnostics.d.ts +6 -0
  253. package/dist/hosts/pi/managed-provider-diagnostics.js +184 -0
  254. package/dist/hosts/pi/managed-sdk-session.d.ts +335 -0
  255. package/dist/hosts/pi/managed-sdk-session.js +1639 -0
  256. package/dist/hosts/pi/managed-session-extension.d.ts +20 -0
  257. package/dist/hosts/pi/managed-session-extension.js +84 -0
  258. package/dist/hosts/pi/managed-session.d.ts +177 -0
  259. package/dist/hosts/pi/managed-session.js +1557 -0
  260. package/dist/hosts/pi/protocol.js +1 -1
  261. package/dist/hosts/pi/query-result.js +1 -1
  262. package/dist/hosts/pi/resume-capability.d.ts +41 -0
  263. package/dist/hosts/pi/resume-capability.js +33 -0
  264. package/dist/hosts/pi/rpc.d.ts +182 -134
  265. package/dist/hosts/pi/rpc.js +230 -37
  266. package/dist/hosts/pilot.d.ts +97 -74
  267. package/dist/hosts/pilot.js +5 -1
  268. package/dist/hosts/version.d.ts +3 -0
  269. package/dist/hosts/version.js +18 -0
  270. package/dist/index.d.ts +0 -1
  271. package/dist/index.js +0 -1
  272. package/dist/infra/bounded-file.d.ts +19 -0
  273. package/dist/infra/bounded-file.js +66 -0
  274. package/dist/infra/fs.js +10 -2
  275. package/dist/infra/git.d.ts +29 -0
  276. package/dist/infra/git.js +45 -9
  277. package/dist/infra/json-property.d.ts +2 -0
  278. package/dist/infra/json-property.js +69 -0
  279. package/dist/infra/json.d.ts +4 -0
  280. package/dist/infra/json.js +24 -0
  281. package/dist/infra/owned-process-group.js +1 -1
  282. package/dist/infra/private-lock.d.ts +16 -0
  283. package/dist/infra/private-lock.js +148 -0
  284. package/dist/infra/private-state.d.ts +7 -0
  285. package/dist/infra/private-state.js +146 -0
  286. package/dist/infra/process-identity.d.ts +12 -0
  287. package/dist/infra/process-identity.js +142 -0
  288. package/dist/infra/validation.d.ts +5 -0
  289. package/dist/infra/validation.js +15 -0
  290. package/dist/init.d.ts +1 -0
  291. package/dist/init.js +6 -0
  292. package/dist/install/apply.d.ts +9 -1
  293. package/dist/install/apply.js +176 -12
  294. package/dist/install/dependencies.d.ts +38 -0
  295. package/dist/install/dependencies.js +282 -0
  296. package/dist/install/ownership.js +30 -1
  297. package/dist/install/references.d.ts +31 -0
  298. package/dist/install/references.js +208 -0
  299. package/dist/install/repair.d.ts +37 -0
  300. package/dist/install/repair.js +798 -0
  301. package/dist/install/reset-local.d.ts +16 -0
  302. package/dist/install/reset-local.js +304 -0
  303. package/dist/install/rollback.d.ts +3 -0
  304. package/dist/install/rollback.js +9 -3
  305. package/dist/install/runtime.d.ts +10 -6
  306. package/dist/install/runtime.js +299 -59
  307. package/dist/install/source-fingerprint.d.ts +2 -0
  308. package/dist/install/source-fingerprint.js +103 -0
  309. package/dist/knowledge/catalog.d.ts +1 -0
  310. package/dist/knowledge/catalog.js +143 -10
  311. package/dist/knowledge/journal.js +17 -7
  312. package/dist/knowledge/paths.js +2 -1
  313. package/dist/knowledge/refs.js +4 -0
  314. package/dist/knowledge/register-batch.d.ts +4 -0
  315. package/dist/knowledge/register-batch.js +225 -0
  316. package/dist/knowledge/relocate.d.ts +5 -0
  317. package/dist/knowledge/relocate.js +92 -0
  318. package/dist/knowledge/scan.js +103 -47
  319. package/dist/knowledge/service.d.ts +3 -0
  320. package/dist/knowledge/service.js +33 -1
  321. package/dist/knowledge/write.d.ts +4 -1
  322. package/dist/knowledge/write.js +1 -1
  323. package/dist/mcp/server.d.ts +4 -2
  324. package/dist/mcp/server.js +87 -136
  325. package/dist/schemas/collaboration-state-validation.d.ts +6 -0
  326. package/dist/schemas/collaboration-state-validation.js +342 -0
  327. package/dist/schemas/collaboration-state.d.ts +436 -0
  328. package/dist/schemas/collaboration-state.js +1 -0
  329. package/dist/schemas/collaboration.d.ts +335 -0
  330. package/dist/schemas/collaboration.js +272 -0
  331. package/dist/schemas/continuity.d.ts +8 -0
  332. package/dist/schemas/continuity.js +13 -3
  333. package/dist/schemas/doctor.d.ts +1 -0
  334. package/dist/schemas/doctor.js +1 -0
  335. package/dist/schemas/document.d.ts +61 -0
  336. package/dist/schemas/document.js +9 -0
  337. package/dist/schemas/errors.d.ts +1 -0
  338. package/dist/schemas/errors.js +1 -0
  339. package/dist/schemas/host.d.ts +24 -0
  340. package/dist/schemas/host.js +19 -0
  341. package/dist/schemas/install.d.ts +8 -2
  342. package/dist/schemas/install.js +11 -1
  343. package/dist/schemas/managed-pi-execution.d.ts +16 -0
  344. package/dist/schemas/managed-pi-execution.js +2 -0
  345. package/dist/schemas/outcome.d.ts +9 -5
  346. package/dist/workspace/config-file.js +1 -3
  347. package/dist/workspace/documents.js +12 -2
  348. package/dist/workspace/repositories.d.ts +7 -0
  349. package/dist/workspace/repositories.js +14 -5
  350. package/package.json +35 -35
  351. package/skills/pappra/SKILL.md +28 -7
  352. package/skills/pappra/references/collaboration.md +633 -0
  353. package/skills/pappra/references/environment.md +360 -0
  354. package/skills/pappra/references/hosts.md +20 -0
  355. package/skills/pappra/references/operations.md +36 -5
  356. package/dist/app/collab-from.d.ts +0 -35
  357. package/dist/app/collab-from.js +0 -84
package/dist/cli/run.js CHANGED
@@ -8,9 +8,27 @@ import { doctorUsage, runDoctorCommand } from './commands/doctor.js';
8
8
  import { docsUsage, runDocsCommand } from './commands/docs.js';
9
9
  import { checkpointUsage, resumeUsage, runCheckpointCommand, runResumeCommand, } from './commands/continuity.js';
10
10
  import { codeUsage, runCodeCommand } from './commands/code.js';
11
- import { collaborationUsage, runCollaborationCommand, } from './commands/collaboration.js';
11
+ import { collaborationCommandLine, collaborationUsage, runCollaborationCommand, } from './commands/collaboration.js';
12
+ import { collaborationMessageUsage, runCollaborationMessageCommand, } from './commands/collaboration-message.js';
13
+ import { collaborationPreflightUsage, runCollaborationPreflightCommand, } from './commands/collaboration-preflight.js';
14
+ import { collaborationCapabilitiesUsage, runCollaborationCapabilitiesCommand, } from './commands/collaboration-capabilities.js';
15
+ import { collaborationStateUsage, runCollaborationStateCommand, } from './commands/collaboration-state.js';
16
+ import { collaborationResourcesUsage, runCollaborationResourcesCommand, } from './commands/collaboration-resources.js';
17
+ import { collaborationHandoffUsage, runCollaborationHandoffCommand, } from './commands/collaboration-handoff.js';
18
+ import { collaborationRecoveryUsage, runCollaborationRecoveryCommand, } from './commands/collaboration-recovery.js';
19
+ import { collaborationRecoveryRunUsage, parseCollaborationRecoveryRunArgs, runCollaborationRecoveryRunCommand, } from './commands/collaboration-recovery-run.js';
20
+ import { collaborationWorkRunUsage, parseCollaborationWorkRunArgs, runCollaborationWorkRunCommand, } from './commands/collaboration-work-run.js';
21
+ import { collaborationBindingUsage, runCollaborationBindingCommand, } from './commands/collaboration-binding.js';
22
+ import { collaborationPlanUsage, runCollaborationPlanCommand, } from './commands/collaboration-plan.js';
23
+ import { collaborationRolloverUsage, runCollaborationRolloverCommand, } from './commands/collaboration-rollover.js';
24
+ import { collaborationBootstrapUsage, runCollaborationBootstrapCommand, } from './commands/collaboration-bootstrap.js';
25
+ import { collaborationTransitionUsage, runCollaborationTransitionCommand, } from './commands/collaboration-transition.js';
12
26
  import { hostUsage, runHostCommand } from './commands/host.js';
27
+ import { sessionUsage, runSessionCommand } from './commands/session.js';
28
+ import { collaborationRoleRunUsage, runCollaborationRoleRunCommand, } from './commands/collaboration-role-run.js';
29
+ import { collaborationRolePlanUsage, runCollaborationRolePlanCommand, } from './commands/collaboration-role-plan.js';
13
30
  import { runtimeUsage, runRuntimeCommand } from './commands/runtime.js';
31
+ import { repairUsage, runRepairCommand } from './commands/repair.js';
14
32
  import { hostNameSchema } from '../schemas/host.js';
15
33
  function parseOptions(args) {
16
34
  const { values, positionals } = parseArgs({
@@ -19,10 +37,13 @@ function parseOptions(args) {
19
37
  help: { type: 'boolean', short: 'h' },
20
38
  version: { type: 'boolean', short: 'v' },
21
39
  json: { type: 'boolean' },
40
+ live: { type: 'boolean' },
22
41
  config: { type: 'string' },
23
42
  apply: { type: 'boolean' },
43
+ watch: { type: 'boolean' },
24
44
  yes: { type: 'boolean', short: 'y' },
25
45
  'no-runtime': { type: 'boolean' },
46
+ 'allow-workspace-writes': { type: 'boolean' },
26
47
  reconfigure: { type: 'boolean' },
27
48
  hosts: { type: 'string' },
28
49
  'apply-host': { type: 'boolean' },
@@ -32,6 +53,9 @@ function parseOptions(args) {
32
53
  from: { type: 'string' },
33
54
  tarball: { type: 'string' },
34
55
  out: { type: 'string' },
56
+ 'bootstrap-config': { type: 'string' },
57
+ 'recovery-config': { type: 'string' },
58
+ 'transition-extension': { type: 'boolean' },
35
59
  mode: { type: 'string' },
36
60
  marketplace: { type: 'boolean' },
37
61
  scope: { type: 'string' },
@@ -43,6 +67,9 @@ function parseOptions(args) {
43
67
  'runtime-tarball': { type: 'string' },
44
68
  'runtime-version': { type: 'string' },
45
69
  root: { type: 'string' },
70
+ 'task-id': { type: 'string' },
71
+ record: { type: 'string' },
72
+ roots: { type: 'string' },
46
73
  'include-private': { type: 'boolean' },
47
74
  'include-archived': { type: 'boolean' },
48
75
  task: { type: 'string' },
@@ -73,7 +100,25 @@ function parseOptions(args) {
73
100
  prepared: { type: 'string' },
74
101
  capabilities: { type: 'string' },
75
102
  controller: { type: 'string' },
103
+ 'rpc-request-timeout-ms': { type: 'string' },
104
+ 'rpc-operation-timeout-ms': { type: 'string' },
76
105
  'domain-root': { type: 'string' },
106
+ 'task-root': { type: 'string' },
107
+ message: { type: 'string' },
108
+ 'message-id': { type: 'string' },
109
+ binding: { type: 'string' },
110
+ retry: { type: 'boolean' },
111
+ 'caller-pane': { type: 'string' },
112
+ assignment: { type: 'string' },
113
+ 'max-age-minutes': { type: 'string' },
114
+ harness: { type: 'string' },
115
+ template: { type: 'string' },
116
+ execution: { type: 'string' },
117
+ events: { type: 'string' },
118
+ request: { type: 'string' },
119
+ 'owner-epoch': { type: 'string' },
120
+ 'subtask-id': { type: 'string' },
121
+ attempt: { type: 'string' },
77
122
  },
78
123
  allowPositionals: true,
79
124
  strict: true,
@@ -102,7 +147,7 @@ function parseOptions(args) {
102
147
  };
103
148
  }
104
149
  if (command === 'docs') {
105
- if (positionals.length > 3) {
150
+ if (positionals.length > (positionals[1] === 'relocate' ? 4 : 3)) {
106
151
  throw new Error('Unknown command; docs accepts one action and one argument.');
107
152
  }
108
153
  return {
@@ -111,6 +156,7 @@ function parseOptions(args) {
111
156
  command,
112
157
  docsAction: positionals[1] ?? null,
113
158
  docsArgument: positionals[2] ?? null,
159
+ docsTarget: positionals[3] ?? null,
114
160
  hostAction: null,
115
161
  hostSubAction: null,
116
162
  collaborationAction: null,
@@ -197,8 +243,24 @@ function parseOptions(args) {
197
243
  };
198
244
  }
199
245
  if (command === 'collab') {
200
- if (positionals.length > 2) {
201
- throw new Error('collab accepts one action: prepare, run, or query.');
246
+ // `collab message <action>` is the only two-level form; the action string carries
247
+ // both segments so callers keep one parsed field.
248
+ if (positionals.length > 3 ||
249
+ (positionals.length === 3 &&
250
+ positionals[1] !== 'transition' &&
251
+ positionals[1] !== 'bootstrap' &&
252
+ positionals[1] !== 'plan' &&
253
+ positionals[1] !== 'role-plan' &&
254
+ positionals[1] !== 'message' &&
255
+ !(positionals[1] === 'capabilities' && positionals[2] === 'derive') &&
256
+ !((positionals[1] === 'state' ||
257
+ positionals[1] === 'resource' ||
258
+ positionals[1] === 'handoff' ||
259
+ positionals[1] === 'recovery' ||
260
+ positionals[1] === 'binding' ||
261
+ positionals[1] === 'rollover') &&
262
+ positionals[2] !== undefined))) {
263
+ throw new Error('collab accepts prepare, run, work-run, query, preflight, plan, bootstrap, rollover <inspect|plan>, transition <plan|apply>, message <send|list|read|notify>, capabilities derive, state <show|doctor|epoch-check>, resource <list|claim|release>, handoff <inventory|begin|stopped|rebind|transfer|confirm|complete|abort|release-dispatch>, recovery <inspect|reconcile|lock-break>, recovery-run, or binding <list|resolve|bind|unbind>.');
202
264
  }
203
265
  return {
204
266
  values,
@@ -208,7 +270,7 @@ function parseOptions(args) {
208
270
  codeAction: null,
209
271
  hostAction: null,
210
272
  hostSubAction: null,
211
- collaborationAction: positionals[1] ?? null,
273
+ collaborationAction: positionals[1] === undefined ? null : positionals.slice(1).join(':'),
212
274
  resumeTaskId: null,
213
275
  runtimeAction: null,
214
276
  taskAction: null,
@@ -262,21 +324,99 @@ function hasContinuityOptions(values, includeSession = true) {
262
324
  }
263
325
  const globalUsage = 'pappra [--help | --version] [--json]\n' +
264
326
  'pappra task <pin|unpin|show> [taskId] [--auto-resume] [--json]\n' +
265
- 'pappra mcp [--root <dir>] [--help]\n' +
327
+ 'pappra mcp [--root <dir>] [--allow-workspace-writes] [--help]\n' +
266
328
  'pappra onboard [--root <dir>] [--config <file>] [--hosts <list>] [--yes]\n' +
267
329
  ' [--apply-host] [--dry-run] [--print-handoff] [--json]\n' +
268
330
  'pappra init [--config <file> | --yes] [--apply] [--json] [--print-choices]\n' +
269
331
  ' [--install-runtime (--runtime-tarball <file> | --runtime-version <version>)]\n' +
270
332
  'pappra doctor [--root <path>] [--json]\n' +
271
- 'pappra docs <list|check|archive> [options]\n' +
333
+ 'pappra repair [--root <path>] [--runtime-version <v>] [--install-id <uuid>] [--apply] [--json]\n' +
334
+ 'pappra docs <list|check|archive|scan|relocate|forget> [options]\n' +
272
335
  'pappra checkpoint --task <id> [options] [--json]\n' +
273
336
  'pappra resume <taskId> [--session <id>] [--json]\n' +
274
337
  'pappra code <status|prepare|query> --repo <id> [options] [--json]\n' +
275
- 'pappra host <detect|describe|plan|install|verify> --host <name> [options] [--json]\n' +
276
- 'pappra runtime <install|status|verify|remove> [options] [--json]\n' +
277
- 'pappra collab <prepare|run|query> [options]';
338
+ 'pappra host <detect|describe|probe|plan|install|verify|uninstall|bundle|mcp> --host <name> [options] [--json]\n' +
339
+ 'pappra runtime <install|status|verify|remove|gc> [options] [--json]\n' +
340
+ 'pappra session <plan|start|status|fence|stop> --config <abs managed-pi.json> [--json]\n' +
341
+ `${collaborationCommandLine}`;
278
342
  export async function runCli(args, output) {
279
343
  const jsonRequested = args.includes('--json');
344
+ if (args[0] === 'repair') {
345
+ try {
346
+ const parsedRepair = parseArgs({
347
+ args: [...args.slice(1)],
348
+ options: {
349
+ root: { type: 'string' },
350
+ 'runtime-version': { type: 'string' },
351
+ 'install-id': { type: 'string' },
352
+ apply: { type: 'boolean' },
353
+ 'quarantine-unowned-locks': { type: 'boolean' },
354
+ 'reset-local': { type: 'boolean' },
355
+ 'all-writers-stopped': { type: 'boolean' },
356
+ json: { type: 'boolean' },
357
+ help: { type: 'boolean', short: 'h' },
358
+ },
359
+ allowPositionals: false,
360
+ strict: true,
361
+ });
362
+ if (['--root', '--runtime-version', '--install-id'].some((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
363
+ .length > 1))
364
+ throw new Error('Repair options must not be repeated.');
365
+ if (parsedRepair.values.help) {
366
+ output.stdout(repairUsage);
367
+ return 0;
368
+ }
369
+ return runRepairCommand({
370
+ root: parsedRepair.values.root ?? process.cwd(),
371
+ ...(parsedRepair.values['runtime-version'] === undefined
372
+ ? {}
373
+ : { runtimeVersion: parsedRepair.values['runtime-version'] }),
374
+ ...(parsedRepair.values['install-id'] === undefined
375
+ ? {}
376
+ : { installId: parsedRepair.values['install-id'] }),
377
+ apply: parsedRepair.values.apply === true,
378
+ quarantineUnownedLocks: parsedRepair.values['quarantine-unowned-locks'] === true,
379
+ resetLocal: parsedRepair.values['reset-local'] === true,
380
+ allWritersStopped: parsedRepair.values['all-writers-stopped'] === true,
381
+ json: parsedRepair.values.json === true,
382
+ }, output);
383
+ }
384
+ catch (error) {
385
+ failure(output, jsonRequested, 'invalid_arguments', error);
386
+ return 2;
387
+ }
388
+ }
389
+ if (args[0] === 'session') {
390
+ try {
391
+ const parsedSession = parseArgs({
392
+ args: [...args.slice(1)],
393
+ options: {
394
+ config: { type: 'string' },
395
+ json: { type: 'boolean' },
396
+ help: { type: 'boolean', short: 'h' },
397
+ },
398
+ allowPositionals: true,
399
+ strict: true,
400
+ });
401
+ if (parsedSession.values.help) {
402
+ output.stdout(`${sessionUsage}\n`);
403
+ return 0;
404
+ }
405
+ if (parsedSession.positionals.length !== 1 ||
406
+ args.filter((arg) => arg === '--config' || arg.startsWith('--config='))
407
+ .length > 1)
408
+ throw new Error(sessionUsage);
409
+ return runSessionCommand({
410
+ action: parsedSession.positionals[0],
411
+ config: parsedSession.values.config ?? null,
412
+ json: parsedSession.values.json ?? false,
413
+ }, output);
414
+ }
415
+ catch (error) {
416
+ failure(output, jsonRequested, 'invalid_arguments', error);
417
+ return 2;
418
+ }
419
+ }
280
420
  let parsed;
281
421
  try {
282
422
  parsed = parseOptions(args);
@@ -287,7 +427,61 @@ export async function runCli(args, output) {
287
427
  }
288
428
  const { values, command, docsAction, docsArgument, codeAction, hostAction, collaborationAction, resumeTaskId, runtimeAction, hostSubAction, taskAction, taskArgument, } = parsed;
289
429
  const json = values.json === true;
430
+ if (values['allow-workspace-writes'] === true && command !== 'mcp') {
431
+ failure(output, json, 'invalid_arguments', '--allow-workspace-writes is a trusted MCP server startup option only.');
432
+ return 2;
433
+ }
290
434
  const applyRequested = values.apply === true;
435
+ if (command === 'collab' && collaborationAction === 'role-run') {
436
+ const allowed = new Set(['request', 'apply', 'watch', 'json', 'help']);
437
+ const invalid = Object.entries(values).some(([key, value]) => value !== undefined && !allowed.has(key));
438
+ const duplicates = args.filter((arg) => arg === '--request' || arg.startsWith('--request='))
439
+ .length > 1;
440
+ if (invalid || duplicates) {
441
+ failure(output, json, 'invalid_arguments', collaborationRoleRunUsage);
442
+ return 2;
443
+ }
444
+ if (values.help) {
445
+ output.stdout(`${collaborationRoleRunUsage}\n`);
446
+ return 0;
447
+ }
448
+ return runCollaborationRoleRunCommand({
449
+ requestFile: values.request ?? null,
450
+ apply: applyRequested,
451
+ watch: values.watch === true,
452
+ json,
453
+ }, output);
454
+ }
455
+ if (values.watch !== undefined) {
456
+ failure(output, json, 'invalid_arguments', '--watch is supported only by collab role-run.');
457
+ return 2;
458
+ }
459
+ if (command === 'collab' && collaborationAction?.startsWith('role-plan')) {
460
+ const allowed = new Set(['request', 'task-root', 'config', 'json', 'help']);
461
+ const extra = Object.entries(values).filter(([key, value]) => value !== undefined && !allowed.has(key));
462
+ const duplicate = ['--request', '--task-root', '--config'].some((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
463
+ .length > 1);
464
+ if (extra.length || duplicate) {
465
+ failure(output, json, 'invalid_arguments', collaborationRolePlanUsage);
466
+ return 2;
467
+ }
468
+ if (values.help) {
469
+ output.stdout(`${collaborationRolePlanUsage}\n`);
470
+ return 0;
471
+ }
472
+ return runCollaborationRolePlanCommand({
473
+ action: collaborationAction.slice('role-plan:'.length),
474
+ requestFile: values.request ?? null,
475
+ taskRoot: values['task-root'] ?? null,
476
+ planFile: values.config ?? null,
477
+ json,
478
+ }, output);
479
+ }
480
+ if (values.live === true &&
481
+ !(command === 'collab' && collaborationAction === 'capabilities:derive')) {
482
+ failure(output, json, 'invalid_arguments', '--live is only valid for collab capabilities derive.');
483
+ return 2;
484
+ }
291
485
  if (command !== 'init' &&
292
486
  (values['no-interactive'] === true ||
293
487
  values['print-choices'] === true ||
@@ -312,6 +506,18 @@ export async function runCli(args, output) {
312
506
  failure(output, json, 'invalid_arguments', '--hosts, --apply-host, --dry-run and --print-handoff are only valid for onboard.');
313
507
  return 2;
314
508
  }
509
+ if (command !== 'host' && values['bootstrap-config'] !== undefined) {
510
+ failure(output, json, 'invalid_arguments', '--bootstrap-config is only valid for host bundle.');
511
+ return 2;
512
+ }
513
+ if (command !== 'host' && values['recovery-config'] !== undefined) {
514
+ failure(output, json, 'invalid_arguments', '--recovery-config is only valid for host bundle.');
515
+ return 2;
516
+ }
517
+ if (command !== 'host' && values['transition-extension'] === true) {
518
+ failure(output, json, 'invalid_arguments', '--transition-extension is only valid for host bundle.');
519
+ return 2;
520
+ }
315
521
  if (command !== 'host' && values.out !== undefined) {
316
522
  failure(output, json, 'invalid_arguments', '--out is only valid for host.');
317
523
  return 2;
@@ -351,6 +557,25 @@ export async function runCli(args, output) {
351
557
  failure(output, json, 'invalid_arguments', '--from, --tarball, --bind and --force are only valid for runtime.');
352
558
  return 2;
353
559
  }
560
+ const rpcRequestTimeout = values['rpc-request-timeout-ms'];
561
+ const rpcOperationTimeout = values['rpc-operation-timeout-ms'];
562
+ for (const [name, value, maximum] of [
563
+ ['rpc-request-timeout-ms', rpcRequestTimeout, 60_000],
564
+ ['rpc-operation-timeout-ms', rpcOperationTimeout, 86_400_000],
565
+ ]) {
566
+ if (value === undefined)
567
+ continue;
568
+ if (command !== 'collab' ||
569
+ collaborationAction !== 'run' ||
570
+ values.controller !== 'pi-rpc' ||
571
+ !/^[0-9]+$/.test(value) ||
572
+ !Number.isSafeInteger(Number(value)) ||
573
+ Number(value) < 1 ||
574
+ Number(value) > maximum) {
575
+ failure(output, json, 'invalid_arguments', `--${name} requires collab run --controller pi-rpc and an integer from 1 to ${maximum}.`);
576
+ return 2;
577
+ }
578
+ }
354
579
  let info;
355
580
  try {
356
581
  info = getPackageInfo();
@@ -367,16 +592,564 @@ export async function runCli(args, output) {
367
592
  output.stdout(json ? `${JSON.stringify(info)}\n` : `${info.version}\n`);
368
593
  return 0;
369
594
  }
595
+ if (command !== 'collab' &&
596
+ (values['task-root'] !== undefined ||
597
+ values.message !== undefined ||
598
+ values['message-id'] !== undefined ||
599
+ values.binding !== undefined ||
600
+ values.retry === true ||
601
+ values['caller-pane'] !== undefined ||
602
+ values.assignment !== undefined ||
603
+ values['max-age-minutes'] !== undefined ||
604
+ values.harness !== undefined ||
605
+ values.template !== undefined ||
606
+ values.execution !== undefined ||
607
+ values.events !== undefined ||
608
+ values.request !== undefined ||
609
+ values['owner-epoch'] !== undefined ||
610
+ values['subtask-id'] !== undefined ||
611
+ values.attempt !== undefined ||
612
+ values['task-id'] !== undefined ||
613
+ values.record !== undefined ||
614
+ values.roots !== undefined)) {
615
+ failure(output, json, 'invalid_arguments', '--task-root, --message, --message-id, --binding, --retry, --caller-pane, --assignment, --max-age-minutes, --harness, --template, --execution, --events, --request, --owner-epoch, --subtask-id, --attempt, --task-id, --record and --roots are only valid for collab.');
616
+ return 2;
617
+ }
370
618
  if (command === 'collab') {
371
619
  if (values.help) {
620
+ const usage = collaborationAction === 'recovery-run'
621
+ ? collaborationRecoveryRunUsage
622
+ : collaborationAction === 'work-run'
623
+ ? collaborationWorkRunUsage
624
+ : collaborationAction === 'transition' ||
625
+ collaborationAction?.startsWith('transition:') === true
626
+ ? collaborationTransitionUsage
627
+ : collaborationAction === 'bootstrap' ||
628
+ collaborationAction?.startsWith('bootstrap:') === true
629
+ ? collaborationBootstrapUsage
630
+ : collaborationAction === 'message' ||
631
+ collaborationAction?.startsWith('message:') === true
632
+ ? collaborationMessageUsage
633
+ : collaborationAction?.startsWith('capabilities:') === true
634
+ ? collaborationCapabilitiesUsage
635
+ : collaborationAction?.startsWith('state:') === true
636
+ ? collaborationStateUsage
637
+ : collaborationAction?.startsWith('resource:') === true
638
+ ? collaborationResourcesUsage
639
+ : collaborationAction?.startsWith('handoff:') === true
640
+ ? collaborationHandoffUsage
641
+ : collaborationAction?.startsWith('recovery:') ===
642
+ true
643
+ ? collaborationRecoveryUsage
644
+ : collaborationAction?.startsWith('binding:') ===
645
+ true
646
+ ? collaborationBindingUsage
647
+ : collaborationAction === 'plan'
648
+ ? collaborationPlanUsage
649
+ : collaborationAction?.startsWith('rollover:') === true ||
650
+ collaborationAction === 'rollover'
651
+ ? collaborationRolloverUsage
652
+ : collaborationAction === 'preflight'
653
+ ? collaborationPreflightUsage
654
+ : collaborationUsage;
372
655
  if (json) {
373
- output.stdout(`${JSON.stringify({ ...info, commands: ['collab'], usage: collaborationUsage })}\n`);
656
+ output.stdout(`${JSON.stringify({ ...info, commands: ['collab'], usage })}\n`);
374
657
  }
375
658
  else {
376
- output.stdout(collaborationUsage);
659
+ output.stdout(usage);
377
660
  }
378
661
  return 0;
379
662
  }
663
+ if (collaborationAction === 'work-run') {
664
+ const allowed = new Set(['request', 'apply', 'json']);
665
+ const extra = Object.entries(values)
666
+ .filter(([, value]) => value !== undefined)
667
+ .map(([key]) => key)
668
+ .filter((key) => !allowed.has(key));
669
+ const parsedWork = parseCollaborationWorkRunArgs(args.slice(2));
670
+ if (extra.length || parsedWork.errors.length) {
671
+ failure(output, json, 'invalid_arguments', `collab work-run accepts only --request, --apply and --json.${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}${parsedWork.errors.length ? ` ${parsedWork.errors.join(' ')}` : ''}\n${collaborationWorkRunUsage}`);
672
+ return 2;
673
+ }
674
+ return runCollaborationWorkRunCommand({ ...parsedWork.options, json }, output);
675
+ }
676
+ if (collaborationAction === 'recovery-run') {
677
+ const allowed = new Set(['request', 'apply', 'json']);
678
+ const extra = Object.entries(values)
679
+ .filter(([, value]) => value !== undefined)
680
+ .map(([key]) => key)
681
+ .filter((key) => !allowed.has(key));
682
+ const parsedRecovery = parseCollaborationRecoveryRunArgs(args.slice(2));
683
+ if (extra.length || parsedRecovery.errors.length) {
684
+ failure(output, json, 'invalid_arguments', `collab recovery-run accepts only --request, --apply and --json.${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}${parsedRecovery.errors.length ? ` ${parsedRecovery.errors.join(' ')}` : ''}\n${collaborationRecoveryRunUsage}`);
685
+ return 2;
686
+ }
687
+ return runCollaborationRecoveryRunCommand({ ...parsedRecovery.options, json }, output);
688
+ }
689
+ if (collaborationAction === 'capabilities:derive') {
690
+ const duplicate = [
691
+ '--live',
692
+ '--harness',
693
+ '--assignment',
694
+ '--template',
695
+ '--execution',
696
+ '--session',
697
+ '--events',
698
+ ].filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
699
+ .length > 1);
700
+ if (duplicate.length) {
701
+ failure(output, json, 'invalid_arguments', `collab capabilities derive rejects duplicate option(s): ${duplicate.join(', ')}.\n${collaborationCapabilitiesUsage}`);
702
+ return 2;
703
+ }
704
+ const allowed = new Set([
705
+ 'live',
706
+ 'assignment',
707
+ 'harness',
708
+ 'template',
709
+ 'execution',
710
+ 'session',
711
+ 'events',
712
+ 'json',
713
+ ]);
714
+ const extra = Object.entries(values)
715
+ .filter(([, value]) => value !== undefined)
716
+ .map(([key]) => key)
717
+ .filter((key) => !allowed.has(key));
718
+ if (extra.length) {
719
+ failure(output, json, 'invalid_arguments', `collab capabilities derive accepts only its own options: ${extra.join(', ')}.\n${collaborationCapabilitiesUsage}`);
720
+ return 2;
721
+ }
722
+ return runCollaborationCapabilitiesCommand({
723
+ harness: values.harness ?? null,
724
+ assignmentFile: values.assignment ?? null,
725
+ templateFile: values.template ?? null,
726
+ executionFile: values.execution ?? null,
727
+ sessionFile: values.session ?? null,
728
+ eventsFile: values.events ?? null,
729
+ live: values.live ?? false,
730
+ json,
731
+ }, output);
732
+ }
733
+ if (collaborationAction?.startsWith('state:')) {
734
+ const selected = collaborationAction.slice('state:'.length);
735
+ const stateAction = selected === 'show' ||
736
+ selected === 'doctor' ||
737
+ selected === 'epoch-check'
738
+ ? selected
739
+ : null;
740
+ const stateFlags = stateAction === 'epoch-check'
741
+ ? ['--task-root', '--owner-epoch']
742
+ : ['--task-root'];
743
+ const duplicate = stateFlags.filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
744
+ .length > 1);
745
+ const allowed = new Set([
746
+ 'task-root',
747
+ 'json',
748
+ ...(stateAction === 'epoch-check' ? ['owner-epoch'] : []),
749
+ ]);
750
+ const extra = Object.entries(values)
751
+ .filter(([, value]) => value !== undefined)
752
+ .map(([key]) => key)
753
+ .filter((key) => !allowed.has(key));
754
+ if (stateAction === null || duplicate.length || extra.length) {
755
+ failure(output, json, 'invalid_arguments', `collab state accepts only show/doctor/epoch-check and their own options.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationStateUsage}`);
756
+ return 2;
757
+ }
758
+ return runCollaborationStateCommand({
759
+ action: stateAction,
760
+ taskRoot: values['task-root'] ?? null,
761
+ ownerEpoch: values['owner-epoch'] ?? null,
762
+ json,
763
+ }, output);
764
+ }
765
+ if (collaborationAction?.startsWith('resource:')) {
766
+ const selected = collaborationAction.slice('resource:'.length);
767
+ const resourceAction = selected === 'list' || selected === 'claim' || selected === 'release'
768
+ ? selected
769
+ : null;
770
+ const resourceFlags = resourceAction === 'list'
771
+ ? ['--task-root']
772
+ : ['--task-root', '--request'];
773
+ const duplicate = resourceFlags.filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
774
+ .length > 1);
775
+ const allowed = new Set([
776
+ 'task-root',
777
+ 'json',
778
+ ...(resourceAction === 'list' ? [] : ['request', 'apply']),
779
+ ]);
780
+ const extra = Object.entries(values)
781
+ .filter(([, value]) => value !== undefined)
782
+ .map(([key]) => key)
783
+ .filter((key) => !allowed.has(key));
784
+ if (resourceAction === null || duplicate.length || extra.length) {
785
+ failure(output, json, 'invalid_arguments', `collab resource accepts only list/claim/release and their own options.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationResourcesUsage}`);
786
+ return 2;
787
+ }
788
+ return runCollaborationResourcesCommand({
789
+ action: resourceAction,
790
+ taskRoot: values['task-root'] ?? null,
791
+ requestFile: values.request ?? null,
792
+ apply: values.apply === true,
793
+ json,
794
+ }, output);
795
+ }
796
+ if (collaborationAction?.startsWith('handoff:')) {
797
+ const selected = collaborationAction.slice('handoff:'.length);
798
+ const handoffAction = selected === 'inventory' ||
799
+ selected === 'begin' ||
800
+ selected === 'stopped' ||
801
+ selected === 'rebind' ||
802
+ selected === 'transfer' ||
803
+ selected === 'confirm' ||
804
+ selected === 'complete' ||
805
+ selected === 'abort' ||
806
+ selected === 'release-dispatch'
807
+ ? selected
808
+ : null;
809
+ const duplicateFlags = handoffAction === 'inventory'
810
+ ? ['--task-root', '--subtask-id', '--attempt']
811
+ : ['--task-root', '--request'];
812
+ const duplicate = duplicateFlags.filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
813
+ .length > 1);
814
+ const allowed = new Set([
815
+ 'task-root',
816
+ 'json',
817
+ ...(handoffAction === 'inventory'
818
+ ? ['subtask-id', 'attempt']
819
+ : ['request', 'apply']),
820
+ ]);
821
+ const extra = Object.entries(values)
822
+ .filter(([, value]) => value !== undefined)
823
+ .map(([key]) => key)
824
+ .filter((key) => !allowed.has(key));
825
+ if (handoffAction === null || duplicate.length || extra.length) {
826
+ failure(output, json, 'invalid_arguments', `collab handoff accepts only inventory or a handoff mutation action and their own options.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationHandoffUsage}`);
827
+ return 2;
828
+ }
829
+ return runCollaborationHandoffCommand({
830
+ action: handoffAction,
831
+ taskRoot: values['task-root'] ?? null,
832
+ requestFile: values.request ?? null,
833
+ subtaskId: values['subtask-id'] ?? null,
834
+ attempt: values.attempt ?? null,
835
+ apply: values.apply === true,
836
+ json,
837
+ }, output);
838
+ }
839
+ if (collaborationAction?.startsWith('recovery:')) {
840
+ const selected = collaborationAction.slice('recovery:'.length);
841
+ const recoveryAction = selected === 'inspect' ||
842
+ selected === 'reconcile' ||
843
+ selected === 'lock-break'
844
+ ? selected
845
+ : null;
846
+ const duplicateFlags = recoveryAction === 'inspect'
847
+ ? ['--task-root']
848
+ : ['--task-root', '--request'];
849
+ const duplicate = duplicateFlags.filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
850
+ .length > 1);
851
+ const allowed = new Set([
852
+ 'task-root',
853
+ 'json',
854
+ ...(recoveryAction === 'inspect' ? [] : ['request', 'apply']),
855
+ ]);
856
+ const extra = Object.entries(values)
857
+ .filter(([, value]) => value !== undefined)
858
+ .map(([key]) => key)
859
+ .filter((key) => !allowed.has(key));
860
+ if (recoveryAction === null || duplicate.length || extra.length) {
861
+ failure(output, json, 'invalid_arguments', `collab recovery accepts only inspect/reconcile/lock-break and their own options.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationRecoveryUsage}`);
862
+ return 2;
863
+ }
864
+ return runCollaborationRecoveryCommand({
865
+ action: recoveryAction,
866
+ taskRoot: values['task-root'] ?? null,
867
+ requestFile: values.request ?? null,
868
+ apply: values.apply === true,
869
+ json,
870
+ }, output);
871
+ }
872
+ if (collaborationAction?.startsWith('binding:')) {
873
+ const selected = collaborationAction.slice('binding:'.length);
874
+ const bindingAction = selected === 'list' ||
875
+ selected === 'resolve' ||
876
+ selected === 'bind' ||
877
+ selected === 'unbind'
878
+ ? selected
879
+ : null;
880
+ const allowedFlags = bindingAction === 'list'
881
+ ? ['root']
882
+ : bindingAction === 'resolve'
883
+ ? ['task-id', 'root', 'roots']
884
+ : bindingAction === 'bind'
885
+ ? ['task-id', 'record', 'root', 'apply']
886
+ : bindingAction === 'unbind'
887
+ ? ['task-id', 'root', 'apply']
888
+ : [];
889
+ const duplicate = allowedFlags.filter((flag) => args.filter((arg) => arg === `--${flag}` || arg.startsWith(`--${flag}=`)).length > 1);
890
+ const allowed = new Set([...allowedFlags, 'json']);
891
+ const extra = Object.entries(values)
892
+ .filter(([, value]) => value !== undefined)
893
+ .map(([key]) => key)
894
+ .filter((key) => !allowed.has(key));
895
+ const missing = bindingAction === null
896
+ ? []
897
+ : [
898
+ ...(bindingAction === 'resolve' ||
899
+ bindingAction === 'bind' ||
900
+ bindingAction === 'unbind'
901
+ ? ['task-id']
902
+ : []),
903
+ ...(bindingAction === 'bind' ? ['record'] : []),
904
+ ].filter((flag) => values[flag] === undefined ||
905
+ values[flag] === null);
906
+ if (bindingAction === null ||
907
+ duplicate.length ||
908
+ extra.length ||
909
+ missing.length) {
910
+ failure(output, json, 'invalid_arguments', `collab binding accepts only list/resolve/bind/unbind and their own options.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}${missing.length ? ` Missing: ${missing.join(', ')}.` : ''}\n${collaborationBindingUsage}`);
911
+ return 2;
912
+ }
913
+ return runCollaborationBindingCommand({
914
+ action: bindingAction,
915
+ root: values.root ?? null,
916
+ taskId: values['task-id'] ?? null,
917
+ record: values.record ?? null,
918
+ roots: values.roots ?? null,
919
+ apply: values.apply === true,
920
+ json,
921
+ }, output);
922
+ }
923
+ if (collaborationAction === 'transition' ||
924
+ collaborationAction?.startsWith('transition:') === true) {
925
+ const selected = collaborationAction === 'transition'
926
+ ? null
927
+ : collaborationAction.slice('transition:'.length);
928
+ const transitionAction = selected === 'plan' || selected === 'apply' ? selected : null;
929
+ const duplicate = ['--task-root', '--request'].filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
930
+ .length > 1);
931
+ const allowed = new Set(['task-root', 'request', 'json']);
932
+ const extra = Object.entries(values)
933
+ .filter(([, value]) => value !== undefined)
934
+ .map(([key]) => key)
935
+ .filter((key) => !allowed.has(key));
936
+ if (transitionAction === null || duplicate.length || extra.length) {
937
+ failure(output, json, 'invalid_arguments', `collab transition accepts only plan|apply with --task-root, --request and --json.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}${transitionAction === null ? ' Missing: plan or apply.' : ''}\n${collaborationTransitionUsage}`);
938
+ return 2;
939
+ }
940
+ return runCollaborationTransitionCommand({
941
+ action: transitionAction,
942
+ taskRoot: values['task-root'] ?? null,
943
+ requestFile: values.request ?? null,
944
+ json,
945
+ }, output);
946
+ }
947
+ if (collaborationAction?.startsWith('rollover:') ||
948
+ collaborationAction === 'rollover') {
949
+ const selected = collaborationAction === 'rollover'
950
+ ? null
951
+ : collaborationAction.slice('rollover:'.length);
952
+ const rolloverAction = selected === 'inspect' || selected === 'plan' ? selected : null;
953
+ const duplicate = ['--task-root', '--request'].filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
954
+ .length > 1);
955
+ const allowed = new Set(['task-root', 'request', 'json']);
956
+ const extra = Object.entries(values)
957
+ .filter(([, value]) => value !== undefined)
958
+ .map(([key]) => key)
959
+ .filter((key) => !allowed.has(key));
960
+ if (rolloverAction === null || duplicate.length || extra.length) {
961
+ failure(output, json, 'invalid_arguments', `collab rollover accepts only inspect or plan with --task-root, --request and --json.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}${rolloverAction === null ? ' Missing: inspect or plan.' : ''}\n${collaborationRolloverUsage}`);
962
+ return 2;
963
+ }
964
+ return runCollaborationRolloverCommand({
965
+ action: rolloverAction,
966
+ taskRoot: values['task-root'] ?? null,
967
+ requestFile: values.request ?? null,
968
+ json,
969
+ }, output);
970
+ }
971
+ if (collaborationAction === 'plan') {
972
+ // `plan` is the only collab action that reads --config: the plan document is an
973
+ // explicit bounded file, not a global flag other commands silently accept.
974
+ const duplicate = ['--task-root', '--config'].filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
975
+ .length > 1);
976
+ const allowed = new Set(['task-root', 'config', 'json']);
977
+ const extra = Object.entries(values)
978
+ .filter(([, value]) => value !== undefined)
979
+ .map(([key]) => key)
980
+ .filter((key) => !allowed.has(key));
981
+ if (duplicate.length || extra.length) {
982
+ failure(output, json, 'invalid_arguments', `collab plan accepts only --task-root, --config and --json.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationPlanUsage}`);
983
+ return 2;
984
+ }
985
+ return runCollaborationPlanCommand({
986
+ taskRoot: values['task-root'] ?? null,
987
+ planFile: values.config ?? null,
988
+ json,
989
+ }, output);
990
+ }
991
+ if (collaborationAction === 'bootstrap' ||
992
+ collaborationAction?.startsWith('bootstrap:') === true) {
993
+ const selected = collaborationAction === 'bootstrap'
994
+ ? null
995
+ : collaborationAction.slice('bootstrap:'.length);
996
+ const action = selected === 'plan' || selected === 'apply' ? selected : null;
997
+ const duplicate = ['--task-root', '--request'].filter((flag) => args.filter((arg) => arg === flag || arg.startsWith(`${flag}=`))
998
+ .length > 1);
999
+ const allowed = new Set(['task-root', 'request', 'json']);
1000
+ const extra = Object.entries(values)
1001
+ .filter(([, value]) => value !== undefined)
1002
+ .map(([key]) => key)
1003
+ .filter((key) => !allowed.has(key));
1004
+ if (action === null || duplicate.length || extra.length) {
1005
+ failure(output, json, 'invalid_arguments', `collab bootstrap requires plan|apply and only --task-root, --request and --json.${duplicate.length ? ` Duplicate: ${duplicate.join(', ')}.` : ''}${extra.length ? ` Unexpected: ${extra.join(', ')}.` : ''}\n${collaborationBootstrapUsage}`);
1006
+ return 2;
1007
+ }
1008
+ return runCollaborationBootstrapCommand({
1009
+ action,
1010
+ taskRoot: values['task-root'] ?? null,
1011
+ requestFile: values.request ?? null,
1012
+ json,
1013
+ }, output);
1014
+ }
1015
+ if (collaborationAction === 'preflight') {
1016
+ if (values.version ||
1017
+ values.config !== undefined ||
1018
+ values['install-runtime'] === true ||
1019
+ values['runtime-tarball'] !== undefined ||
1020
+ values['runtime-version'] !== undefined ||
1021
+ values.root !== undefined ||
1022
+ values.goal !== undefined ||
1023
+ values.prepared !== undefined ||
1024
+ values.controller !== undefined ||
1025
+ values['domain-root'] !== undefined ||
1026
+ values['task-root'] !== undefined ||
1027
+ values.message !== undefined ||
1028
+ values['message-id'] !== undefined ||
1029
+ values.binding !== undefined ||
1030
+ values.retry === true ||
1031
+ values['caller-pane'] !== undefined ||
1032
+ values.session !== undefined ||
1033
+ values.harness !== undefined ||
1034
+ values.template !== undefined ||
1035
+ values.execution !== undefined ||
1036
+ values.events !== undefined ||
1037
+ values.request !== undefined ||
1038
+ values['owner-epoch'] !== undefined ||
1039
+ values['subtask-id'] !== undefined ||
1040
+ values.attempt !== undefined ||
1041
+ values['task-id'] !== undefined ||
1042
+ values.record !== undefined ||
1043
+ values.roots !== undefined ||
1044
+ values.apply === true ||
1045
+ values['include-private'] === true ||
1046
+ values['include-archived'] === true ||
1047
+ hasContinuityOptions(values)) {
1048
+ failure(output, json, 'invalid_arguments', `collab preflight accepts only its own options.\n${collaborationPreflightUsage}`);
1049
+ return 2;
1050
+ }
1051
+ return runCollaborationPreflightCommand({
1052
+ cwd: process.cwd(),
1053
+ assignmentFile: values.assignment ?? null,
1054
+ capabilitiesFile: values.capabilities ?? null,
1055
+ maxAgeMinutes: values['max-age-minutes'] ?? null,
1056
+ json,
1057
+ }, output);
1058
+ }
1059
+ const separator = collaborationAction?.indexOf(':') ?? -1;
1060
+ if (separator >= 0) {
1061
+ const group = collaborationAction?.slice(0, separator) ?? '';
1062
+ const selected = collaborationAction?.slice(separator + 1) ?? '';
1063
+ const messageAction = group === 'message' &&
1064
+ (selected === 'send' ||
1065
+ selected === 'list' ||
1066
+ selected === 'read' ||
1067
+ selected === 'notify')
1068
+ ? selected
1069
+ : null;
1070
+ const provided = new Set();
1071
+ if (values.message !== undefined)
1072
+ provided.add('message');
1073
+ if (values['message-id'] !== undefined)
1074
+ provided.add('message-id');
1075
+ if (values.binding !== undefined)
1076
+ provided.add('binding');
1077
+ if (values.limit !== undefined)
1078
+ provided.add('limit');
1079
+ if (values.apply === true)
1080
+ provided.add('apply');
1081
+ if (values.retry === true)
1082
+ provided.add('retry');
1083
+ if (values['caller-pane'] !== undefined)
1084
+ provided.add('caller-pane');
1085
+ const allowedByAction = {
1086
+ send: new Set(['message', 'apply']),
1087
+ list: new Set(['limit']),
1088
+ read: new Set(['message-id']),
1089
+ notify: new Set([
1090
+ 'message-id',
1091
+ 'binding',
1092
+ 'apply',
1093
+ 'retry',
1094
+ 'caller-pane',
1095
+ ]),
1096
+ };
1097
+ const requiredByAction = {
1098
+ send: ['message'],
1099
+ list: [],
1100
+ read: ['message-id'],
1101
+ notify: ['message-id', 'binding'],
1102
+ };
1103
+ const actionFlagsValid = messageAction !== null &&
1104
+ [...provided].every((flag) => allowedByAction[messageAction].has(flag)) &&
1105
+ requiredByAction[messageAction].every((flag) => provided.has(flag));
1106
+ if (messageAction === null ||
1107
+ !actionFlagsValid ||
1108
+ values.version ||
1109
+ values.config !== undefined ||
1110
+ values['install-runtime'] === true ||
1111
+ values['runtime-tarball'] !== undefined ||
1112
+ values['runtime-version'] !== undefined ||
1113
+ values.root !== undefined ||
1114
+ values.goal !== undefined ||
1115
+ values.prepared !== undefined ||
1116
+ values.capabilities !== undefined ||
1117
+ values.controller !== undefined ||
1118
+ values['domain-root'] !== undefined ||
1119
+ values.assignment !== undefined ||
1120
+ values['max-age-minutes'] !== undefined ||
1121
+ values.session !== undefined ||
1122
+ values.harness !== undefined ||
1123
+ values.template !== undefined ||
1124
+ values.execution !== undefined ||
1125
+ values.events !== undefined ||
1126
+ values.request !== undefined ||
1127
+ values['owner-epoch'] !== undefined ||
1128
+ values['subtask-id'] !== undefined ||
1129
+ values.attempt !== undefined ||
1130
+ values['task-id'] !== undefined ||
1131
+ values.record !== undefined ||
1132
+ values.roots !== undefined ||
1133
+ values['include-private'] === true ||
1134
+ values['include-archived'] === true ||
1135
+ hasContinuityOptions(values)) {
1136
+ failure(output, json, 'invalid_arguments', `collab message requires send/list/read/notify with only its own options.\n${collaborationMessageUsage}`);
1137
+ return 2;
1138
+ }
1139
+ return runCollaborationMessageCommand({
1140
+ cwd: process.cwd(),
1141
+ action: messageAction,
1142
+ json,
1143
+ taskRoot: values['task-root'] ?? null,
1144
+ messageFile: values.message ?? null,
1145
+ messageId: values['message-id'] ?? null,
1146
+ bindingFile: values.binding ?? null,
1147
+ apply: values.apply === true,
1148
+ retry: values.retry === true,
1149
+ limit: values.limit ?? null,
1150
+ callerPane: values['caller-pane'] ?? null,
1151
+ }, output);
1152
+ }
380
1153
  const action = collaborationAction === 'prepare' ||
381
1154
  collaborationAction === 'run' ||
382
1155
  collaborationAction === 'query'
@@ -390,6 +1163,26 @@ export async function runCli(args, output) {
390
1163
  values['runtime-version'] !== undefined ||
391
1164
  values.root !== undefined ||
392
1165
  values['include-private'] === true ||
1166
+ values['task-root'] !== undefined ||
1167
+ values.message !== undefined ||
1168
+ values['message-id'] !== undefined ||
1169
+ values.binding !== undefined ||
1170
+ values.retry === true ||
1171
+ values['caller-pane'] !== undefined ||
1172
+ values.assignment !== undefined ||
1173
+ values['max-age-minutes'] !== undefined ||
1174
+ values.session !== undefined ||
1175
+ values.harness !== undefined ||
1176
+ values.template !== undefined ||
1177
+ values.execution !== undefined ||
1178
+ values.events !== undefined ||
1179
+ values.request !== undefined ||
1180
+ values['owner-epoch'] !== undefined ||
1181
+ values['subtask-id'] !== undefined ||
1182
+ values.attempt !== undefined ||
1183
+ values['task-id'] !== undefined ||
1184
+ values.record !== undefined ||
1185
+ values.roots !== undefined ||
393
1186
  values['include-archived'] === true ||
394
1187
  hasContinuityOptions(values)) {
395
1188
  failure(output, json, 'invalid_arguments', 'collab requires prepare/run/query and only collab options.');
@@ -404,6 +1197,12 @@ export async function runCli(args, output) {
404
1197
  capabilitiesFile: values.capabilities ?? null,
405
1198
  controller: values.controller ?? null,
406
1199
  domainRoot: values['domain-root'] ?? null,
1200
+ ...(rpcRequestTimeout === undefined
1201
+ ? {}
1202
+ : { rpcRequestTimeoutMs: Number(rpcRequestTimeout) }),
1203
+ ...(rpcOperationTimeout === undefined
1204
+ ? {}
1205
+ : { rpcOperationTimeoutMs: Number(rpcOperationTimeout) }),
407
1206
  }, output);
408
1207
  }
409
1208
  if (command === 'docs') {
@@ -414,7 +1213,7 @@ export async function runCli(args, output) {
414
1213
  values['runtime-version'] !== undefined ||
415
1214
  values.root !== undefined ||
416
1215
  hasContinuityOptions(values)) {
417
- failure(output, json, 'invalid_arguments', 'docs only accepts list/check/archive/scan, --include-private, --include-archived, --apply (scan only), --help, and --json.');
1216
+ failure(output, json, 'invalid_arguments', 'docs accepts list/check/archive/scan/relocate/forget, --include-private, --include-archived, --apply, --help, and --json.');
418
1217
  return 2;
419
1218
  }
420
1219
  if (values.help) {
@@ -430,6 +1229,8 @@ export async function runCli(args, output) {
430
1229
  cwd: process.cwd(),
431
1230
  action: docsAction,
432
1231
  argument: docsArgument,
1232
+ targetPath: 'docsTarget' in parsed ? parsed.docsTarget : null,
1233
+ scope: values.scope ?? null,
433
1234
  json,
434
1235
  includePrivate: values['include-private'] === true,
435
1236
  includeArchived: values['include-archived'] === true,
@@ -524,7 +1325,7 @@ export async function runCli(args, output) {
524
1325
  values.rebuild === true ||
525
1326
  values.host !== undefined ||
526
1327
  hasContinuityOptions(values)) {
527
- failure(output, json, 'invalid_arguments', 'mcp accepts only --root, --help, and --json.');
1328
+ failure(output, json, 'invalid_arguments', 'mcp accepts --root, --allow-workspace-writes, --help, and --json.');
528
1329
  return 2;
529
1330
  }
530
1331
  if (values.help) {
@@ -540,7 +1341,12 @@ export async function runCli(args, output) {
540
1341
  failure(output, json, 'invalid_arguments', '--version cannot be combined with mcp.');
541
1342
  return 2;
542
1343
  }
543
- return runMcpCommand({ cwd: process.cwd(), root: values.root ?? null, json }, output);
1344
+ return runMcpCommand({
1345
+ cwd: process.cwd(),
1346
+ root: values.root ?? null,
1347
+ json,
1348
+ allowWorkspaceWrites: values['allow-workspace-writes'] === true,
1349
+ }, output);
544
1350
  }
545
1351
  if (command === 'onboard') {
546
1352
  if (values.apply === true ||
@@ -648,13 +1454,14 @@ export async function runCli(args, output) {
648
1454
  values.query !== undefined ||
649
1455
  values.kind !== undefined ||
650
1456
  hasContinuityOptions(values)) {
651
- failure(output, json, 'invalid_arguments', 'runtime accepts only --from, --tarball, --version, --apply, --bind, --force, --help, and --json.');
1457
+ failure(output, json, 'invalid_arguments', 'runtime accepts only --from, --tarball, --runtime-version, --apply, --bind, --force, --help, and --json.');
652
1458
  return 2;
653
1459
  }
654
1460
  const action = runtimeAction === 'install' ||
655
1461
  runtimeAction === 'status' ||
656
1462
  runtimeAction === 'verify' ||
657
- runtimeAction === 'remove'
1463
+ runtimeAction === 'remove' ||
1464
+ runtimeAction === 'gc'
658
1465
  ? runtimeAction
659
1466
  : null;
660
1467
  return runRuntimeCommand({
@@ -847,6 +1654,7 @@ export async function runCli(args, output) {
847
1654
  'describe',
848
1655
  'plan',
849
1656
  'install',
1657
+ 'uninstall',
850
1658
  'verify',
851
1659
  'bundle',
852
1660
  'mcp',
@@ -855,6 +1663,10 @@ export async function runCli(args, output) {
855
1663
  const action = allowedActions.find((item) => item === hostAction) ?? null;
856
1664
  const parsedHost = hostNameSchema.safeParse(values.host);
857
1665
  const host = parsedHost.success ? parsedHost.data : null;
1666
+ const duplicatedBootstrapConfig = args.filter((arg) => arg === '--bootstrap-config' || arg.startsWith('--bootstrap-config=')).length > 1;
1667
+ const duplicatedRecoveryConfig = args.filter((arg) => arg === '--recovery-config' || arg.startsWith('--recovery-config=')).length > 1;
1668
+ const duplicatedTransitionExtension = args.filter((arg) => arg === '--transition-extension' ||
1669
+ arg.startsWith('--transition-extension=')).length > 1;
858
1670
  const invalid = values.version ||
859
1671
  values.config !== undefined ||
860
1672
  values['install-runtime'] === true ||
@@ -870,15 +1682,42 @@ export async function runCli(args, output) {
870
1682
  values['max-bytes'] !== undefined ||
871
1683
  values.rebuild === true ||
872
1684
  hasContinuityOptions(values) ||
873
- (values.apply === true && action !== 'install' && action !== 'mcp') ||
1685
+ (values.apply === true &&
1686
+ action !== 'install' &&
1687
+ action !== 'uninstall' &&
1688
+ action !== 'mcp') ||
874
1689
  (values.mode !== undefined && action !== 'install') ||
875
1690
  (values.marketplace === true && action !== 'bundle') ||
1691
+ (values['bootstrap-config'] !== undefined &&
1692
+ (action !== 'bundle' ||
1693
+ values.marketplace === true ||
1694
+ values.mode !== undefined ||
1695
+ values.apply === true ||
1696
+ values['recovery-config'] !== undefined ||
1697
+ values['transition-extension'] === true)) ||
1698
+ (values['recovery-config'] !== undefined &&
1699
+ (action !== 'bundle' ||
1700
+ host !== 'pi' ||
1701
+ values.marketplace === true ||
1702
+ values.mode !== undefined ||
1703
+ values.apply === true)) ||
1704
+ (values['transition-extension'] === true &&
1705
+ (action !== 'bundle' ||
1706
+ host !== 'pi' ||
1707
+ values.marketplace === true ||
1708
+ values.mode !== undefined ||
1709
+ values.apply === true ||
1710
+ values['bootstrap-config'] !== undefined)) ||
876
1711
  (values.scope !== undefined &&
877
1712
  action !== 'plan' &&
878
1713
  action !== 'install' &&
1714
+ action !== 'uninstall' &&
879
1715
  action !== 'verify') ||
880
1716
  (values['host-root'] !== undefined && action === null) ||
881
- (values['host-version'] !== undefined && action === null);
1717
+ (values['host-version'] !== undefined && action === null) ||
1718
+ duplicatedBootstrapConfig ||
1719
+ duplicatedRecoveryConfig ||
1720
+ duplicatedTransitionExtension;
882
1721
  if (values.help) {
883
1722
  if (json) {
884
1723
  output.stdout(`${JSON.stringify({ ...info, commands: ['host'], usage: hostUsage })}\n`);
@@ -889,7 +1728,7 @@ export async function runCli(args, output) {
889
1728
  return 0;
890
1729
  }
891
1730
  if (action === null || host === null || invalid) {
892
- failure(output, json, 'invalid_arguments', 'host requires detect/describe/plan/install/verify/bundle, --host, and action-compatible options.');
1731
+ failure(output, json, 'invalid_arguments', 'host requires detect/describe/probe/plan/install/verify/uninstall/bundle/mcp, --host, and action-compatible options.');
893
1732
  return 2;
894
1733
  }
895
1734
  return runHostCommand({
@@ -906,6 +1745,9 @@ export async function runCli(args, output) {
906
1745
  mode: values.mode === 'project-settings' || values.mode === 'plugin'
907
1746
  ? values.mode
908
1747
  : null,
1748
+ bootstrapConfig: values['bootstrap-config'] ?? null,
1749
+ recoveryConfig: values['recovery-config'] ?? null,
1750
+ transitionExtension: values['transition-extension'] === true,
909
1751
  marketplace: values.marketplace === true,
910
1752
  scope: values.scope === 'project' || values.scope === 'user'
911
1753
  ? values.scope
@@ -930,16 +1772,16 @@ export async function runCli(args, output) {
930
1772
  }
931
1773
  if (values.help) {
932
1774
  if (json) {
933
- output.stdout(`${JSON.stringify({ ...info, usage: globalUsage, commands: ['init', 'doctor', 'docs', 'checkpoint', 'resume', 'code', 'host', 'collab'] })}\n`);
1775
+ output.stdout(`${JSON.stringify({ ...info, usage: globalUsage, commands: ['init', 'onboard', 'doctor', 'repair', 'docs', 'checkpoint', 'resume', 'code', 'host', 'runtime', 'task', 'mcp', 'collab', 'session'] })}\n`);
934
1776
  }
935
1777
  else {
936
- output.stdout(`${info.name} ${info.version}\n${info.description}\n\nUsage:\n ${globalUsage.replaceAll('\n', '\n ')}\n\nOptions:\n -h, --help Show help\n -v, --version Show version\n --json Output JSON\n\nCommands:\n init Plan workspace initialization\n doctor Read-only workspace and installation diagnostics\n docs List, check, and archive registered documents\n`);
937
- output.stdout(' checkpoint Save a private task checkpoint\n resume Read a bounded recovery packet without starting an agent\n code Inspect or prepare selected code intelligence\n host Detect, plan, install, or verify a selected host integration\n collab Prepare, run, or query a bounded collaboration goal\n');
1778
+ output.stdout(`${info.name} ${info.version}\n${info.description}\n\nUsage:\n ${globalUsage.replaceAll('\n', '\n ')}\n\nOptions:\n -h, --help Show help\n -v, --version Show version\n --json Output JSON\n\nCommands:\n init Plan workspace initialization\n onboard Discover and connect supported hosts\n doctor Read-only workspace and installation diagnostics\n repair Inspect and repair interrupted state\n docs Scan, relocate, forget and inspect knowledge\n runtime Install, verify and remove durable runtimes\n task Select a private task and auto-resume preference\n mcp Serve workspace tools over stdio\n`);
1779
+ output.stdout(' checkpoint Save a private task checkpoint\n resume Read a bounded recovery packet without starting an agent\n code Inspect or prepare selected code intelligence\n host Detect, plan, install, or verify a selected host integration\n collab Prepare, run, query, message, preflight, state, recovery and bindings\n session Launch and control an owned visible native Pi session\n');
938
1780
  }
939
1781
  return 0;
940
1782
  }
941
1783
  if (json) {
942
- output.stdout(`${JSON.stringify({ ...info, usage: globalUsage, commands: ['init', 'doctor', 'docs', 'checkpoint', 'resume', 'code', 'host', 'collab'] })}\n`);
1784
+ output.stdout(`${JSON.stringify({ ...info, usage: globalUsage, commands: ['init', 'onboard', 'doctor', 'repair', 'docs', 'checkpoint', 'resume', 'code', 'host', 'runtime', 'task', 'mcp', 'collab', 'session'] })}\n`);
943
1785
  }
944
1786
  else {
945
1787
  output.stdout(`${info.name} ${info.version}\n${info.description}\n\nUsage:\n ${globalUsage}\n\nRun pappra --help for all options.\n`);