@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
@@ -4,5 +4,6 @@ export interface McpCommandOptions {
4
4
  readonly cwd: string;
5
5
  readonly root: string | null;
6
6
  readonly json: boolean;
7
+ readonly allowWorkspaceWrites?: boolean;
7
8
  }
8
9
  export declare function runMcpCommand(options: McpCommandOptions, output: CliOutput): Promise<number>;
@@ -1,13 +1,19 @@
1
1
  import { runMcpServer } from '../../mcp/server.js';
2
- export const mcpUsage = 'pappra mcp [--root <dir>] [--json]\n\n' +
3
- 'Starts the Pappra MCP server on stdio for the selected workspace. The server exposes\n' +
4
- 'read-only tools (workspace_status, resume, docs_list, docs_check, code_status,\n' +
5
- 'code_query, runtime_status). stdout carries MCP JSON-RPC; use --help outside a host.';
2
+ export const mcpUsage = 'pappra mcp [--root <dir>] [--allow-workspace-writes] [--json]\n\n' +
3
+ 'Starts the Pappra MCP server on stdio for the selected workspace. stdout carries\n' +
4
+ 'MCP JSON-RPC; use --help outside a host.\n\n' +
5
+ 'Read-only tools: workspace_status, resume, docs_list, docs_check, code_status,\n' +
6
+ 'code_query, runtime_status.\n' +
7
+ 'The default server cannot mutate state, install code or launch agent/index work. A trusted host may\n' +
8
+ 'enable checkpoint/docs_scan and workspace-private collab_prepare at server startup\n' +
9
+ 'with --allow-workspace-writes; apply only selects preview versus execution.\n' +
10
+ 'runtime_install and code_prepare execution always require the authorized CLI.\n' +
11
+ 'collab_start returns cli_required and never launches, even with confirm: true.';
6
12
  export async function runMcpCommand(options, output) {
7
13
  const root = options.root ?? options.cwd;
8
14
  if (options.json) {
9
15
  output.stderr('pappra mcp: --json is not used; the server speaks MCP JSON-RPC on stdout.\n');
10
16
  }
11
- await runMcpServer(root);
17
+ await runMcpServer(root, options.allowWorkspaceWrites === true);
12
18
  return 0;
13
19
  }
@@ -0,0 +1,12 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const repairUsage: string;
3
+ export declare function runRepairCommand(options: {
4
+ readonly root: string;
5
+ readonly runtimeVersion?: string;
6
+ readonly installId?: string;
7
+ readonly apply: boolean;
8
+ readonly json: boolean;
9
+ readonly quarantineUnownedLocks?: boolean;
10
+ readonly resetLocal?: boolean;
11
+ readonly allWritersStopped?: boolean;
12
+ }, output: CliOutput): Promise<number>;
@@ -0,0 +1,41 @@
1
+ import { repairInstall } from '../../install/repair.js';
2
+ export const repairUsage = 'pappra repair [--root <workspace>] [--runtime-version <v>] [--install-id <uuid>] [--apply] [--quarantine-unowned-locks] [--reset-local --all-writers-stopped] [--json]\n' +
3
+ 'Preview incomplete install journals, or explicitly recover them with --apply.\n' +
4
+ 'Also inspect/recover provably dead knowledge and checkpoint writer locks.\n' +
5
+ 'Runtime recovery targets the machine data directory for the selected version.\n' +
6
+ 'Live/unknown lock owners and modified or unproven files are preserved.\n' +
7
+ '--quarantine-unowned-locks is an explicit operator assertion that ALL affected writers are stopped;\n' +
8
+ 'with --apply it moves unknown lock evidence into private quarantine without claiming owner death.\n' +
9
+ 'Never use this flag against a live or paused writer. Live verified owners are always refused.\n' +
10
+ '--reset-local explicitly archives all old private local state without migration; --apply also requires\n' +
11
+ '--all-writers-stopped. Existing bytes remain under ignored .pappra/local-archive; fresh init is separate.\n';
12
+ export async function runRepairCommand(options, output) {
13
+ const result = await repairInstall(options);
14
+ if (options.json)
15
+ output.stdout(`${JSON.stringify({ command: 'repair', ...result })}\n`);
16
+ else {
17
+ output.stdout(`State repair ${result.mode}: ${result.entries.length} incomplete install journal(s).\n`);
18
+ for (const entry of result.entries)
19
+ output.stdout(` ${entry.installId} ${entry.operation}: ${entry.status}\n`);
20
+ for (const file of result.locks)
21
+ output.stdout(`Writer lock: ${file}\n`);
22
+ for (const state of result.lockStates)
23
+ output.stdout(`Lock owner ${state.state}: ${state.file}\n`);
24
+ for (const file of result.preserved)
25
+ output.stdout(`Preserved unproven file: ${file}\n`);
26
+ for (const file of result.quarantined)
27
+ output.stdout(`Quarantined unowned lock evidence: ${file}\n`);
28
+ if (result.reset !== null)
29
+ output.stdout(`Local reset ${result.reset.status}; archive: ${result.reset.archive ?? '(none)'}\n`);
30
+ for (const file of result.repaired)
31
+ output.stdout(`Recovered: ${file}\n`);
32
+ for (const error of result.errors)
33
+ output.stderr(`pappra repair: ${error}\n`);
34
+ if (result.ok &&
35
+ result.mode === 'plan' &&
36
+ (result.entries.length > 0 || result.locks.length > 0)) {
37
+ output.stdout('Rerun with --apply to recover the listed install state.\n');
38
+ }
39
+ }
40
+ return result.ok ? 0 : 1;
41
+ }
@@ -2,7 +2,7 @@ import type { CliOutput } from '../output.js';
2
2
  export declare const runtimeUsage: string;
3
3
  export interface RuntimeCommandOptions {
4
4
  readonly cwd: string;
5
- readonly action: 'install' | 'status' | 'verify' | 'remove' | null;
5
+ readonly action: 'install' | 'status' | 'verify' | 'remove' | 'gc' | null;
6
6
  readonly json: boolean;
7
7
  readonly from: 'self' | 'tarball' | 'registry' | null;
8
8
  readonly tarball: string | null;
@@ -1,18 +1,23 @@
1
- import { resolve } from 'node:path';
1
+ import { join, resolve } from 'node:path';
2
+ import { readdir } from 'node:fs/promises';
3
+ import { inspectRuntimeReferences, runtimeBindingMatches, } from '../../install/references.js';
2
4
  import { getPackageInfo, getPackageRoot } from '../../package-info.js';
3
5
  import { inspectRuntimeState, inspectRuntimeStatePassive, installRuntime, removeRuntime, resolveUserDataDir, runtimePaths, } from '../../install/runtime.js';
4
6
  import { updateMachineRuntime } from '../../install/apply.js';
5
7
  import { inspectMachineConfig } from '../../workspace/config.js';
6
8
  import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
7
- export const runtimeUsage = 'pappra runtime <install|status|verify|remove> [options] [--json]\n' +
9
+ export const runtimeUsage = 'pappra runtime <install|status|verify|remove|gc> [options] [--json]\n' +
8
10
  ' install [--from self|tarball|registry] [--tarball <file>] [--runtime-version <v>]\n' +
9
11
  ' [--apply] [--bind]\n' +
10
12
  ' status\n' +
11
13
  ' verify [--runtime-version <v>]\n' +
12
- ' remove [--runtime-version <v>] --apply [--force]\n\n' +
14
+ ' remove [--runtime-version <v>] [--apply] [--force]\n' +
15
+ ' gc [--runtime-version <v>] [--apply] [--force]\n\n' +
13
16
  'Install keeps a durable copy of the package outside the checkout. --from self packs the\n' +
14
17
  'package that is currently executing, which is what makes an npx/dlx bootstrap survive\n' +
15
- 'cache eviction. Writes require --apply; --bind records the copy in machine.json.\n';
18
+ 'cache eviction. Writes require --apply; --bind records the copy in machine.json.\n' +
19
+ 'Only explicitly registered workspace roots are inspected; no home scan is performed.\n' +
20
+ '--force accepts unknown/unregistered coverage, but never bypasses a verified workspace binding.\n';
16
21
  async function inspectBinding(cwd) {
17
22
  const resolution = await resolveWorkspaceRoot({ startPath: cwd });
18
23
  if (resolution.root === null)
@@ -197,53 +202,147 @@ async function runVerify(options, output, binding) {
197
202
  async function runRemove(options, output, binding) {
198
203
  const version = options.version ?? binding?.runtime?.version ?? null;
199
204
  if (version === null) {
200
- output.stderr('pappra runtime remove: --version is required.\n');
205
+ const message = 'runtime remove requires --runtime-version.';
206
+ if (options.json)
207
+ output.stdout(`${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`);
208
+ else
209
+ output.stderr(`pappra: ${message}\n`);
201
210
  return 2;
202
211
  }
212
+ const dataDir = resolveUserDataDir();
213
+ const boundHere = await runtimeBindingMatches(dataDir, version, binding?.runtime);
214
+ const references = await inspectRuntimeReferences(dataDir, version);
203
215
  if (!options.apply) {
204
- output.stderr('pappra runtime remove: rerun with --apply to remove it.\n');
205
- return 2;
206
- }
207
- const boundHere = binding?.runtime?.version === version;
208
- if (boundHere && !options.force) {
209
- const message = 'machine.json still binds this runtime; pass --force to remove it anyway.';
210
- if (options.json) {
211
- output.stdout(`${JSON.stringify({
212
- ok: false,
213
- command: 'runtime',
214
- action: 'remove',
215
- version,
216
- message,
217
- })}\n`);
218
- }
219
- else {
220
- output.stderr(`pappra runtime remove: ${message}\n`);
221
- }
222
- return 1;
223
- }
224
- const removed = await removeRuntime({
225
- version,
226
- dataDir: resolveUserDataDir(),
227
- // The current workspace was already checked above; callers that need to
228
- // protect other checkouts pass --force only after checking them.
229
- activeReferences: [],
230
- });
231
- if (options.json) {
232
- output.stdout(`${JSON.stringify({
233
- ok: removed.ok,
216
+ const plan = {
217
+ ok: true,
234
218
  command: 'runtime',
235
219
  action: 'remove',
220
+ mode: 'plan',
236
221
  version,
237
- removed,
238
- machineBindingRetained: boundHere,
239
- })}\n`);
222
+ runtimeRoot: runtimePaths(version, dataDir).runtimeRoot,
223
+ references,
224
+ boundHere,
225
+ eligibleUnderForcePolicy: !boundHere && references.active.length === 0 && options.force,
226
+ nextAction: 'Use --apply after review. --force accepts unknown coverage only; active bindings are always retained.',
227
+ };
228
+ output.stdout(options.json
229
+ ? `${JSON.stringify(plan)}\n`
230
+ : `Runtime removal plan ${version}: ${boundHere || references.active.length > 0 ? 'referenced; retained' : 'global coverage unknown; explicit --force required'}.\n`);
231
+ return 0;
240
232
  }
233
+ const removed = await removeRuntime({
234
+ version,
235
+ dataDir,
236
+ ...(boundHere && binding !== null
237
+ ? { activeReferences: [binding.root] }
238
+ : {}),
239
+ forceUnknownReferences: options.force,
240
+ });
241
+ if (options.json)
242
+ output.stdout(`${JSON.stringify({ ok: removed.ok, command: 'runtime', action: 'remove', version, removed, references, machineBindingRetained: boundHere })}\n`);
241
243
  else {
242
244
  output.stdout(`Runtime ${version}: ${removed.status}\n`);
243
245
  printDiagnostics(output, removed.diagnostics);
244
246
  }
245
247
  return removed.ok ? 0 : 1;
246
248
  }
249
+ async function runGc(options, output, binding) {
250
+ if (options.version !== null &&
251
+ !/^[0-9A-Za-z][0-9A-Za-z0-9._+-]*$/.test(options.version)) {
252
+ const message = 'runtime gc requires an exact --runtime-version without path separators.';
253
+ output.stdout(options.json
254
+ ? `${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`
255
+ : `${message}\n`);
256
+ return 2;
257
+ }
258
+ if (options.from !== null || options.tarball !== null || options.bind) {
259
+ const message = 'runtime gc accepts only --runtime-version, --apply, --force and --json.';
260
+ if (options.json)
261
+ output.stdout(`${JSON.stringify({ ok: false, code: 'invalid_arguments', message })}\n`);
262
+ else
263
+ output.stderr(`${message}\n`);
264
+ return 2;
265
+ }
266
+ const dataDir = resolveUserDataDir();
267
+ let versions;
268
+ try {
269
+ const entries = await readdir(join(dataDir, 'runtimes'), {
270
+ withFileTypes: true,
271
+ });
272
+ versions = entries
273
+ .filter((entry) => entry.isDirectory() &&
274
+ /^[0-9A-Za-z][0-9A-Za-z0-9._+-]*$/.test(entry.name))
275
+ .map((entry) => entry.name)
276
+ .sort();
277
+ }
278
+ catch (error) {
279
+ if (error.code !== 'ENOENT') {
280
+ const report = {
281
+ ok: false,
282
+ command: 'runtime',
283
+ action: 'gc',
284
+ mode: options.apply ? 'apply' : 'plan',
285
+ message: 'Runtime directory is unreadable; nothing was removed.',
286
+ };
287
+ output.stdout(options.json ? `${JSON.stringify(report)}\n` : `${report.message}\n`);
288
+ return 1;
289
+ }
290
+ versions = [];
291
+ }
292
+ if (options.version !== null)
293
+ versions = versions.filter((version) => version === options.version);
294
+ if (versions.length > 256) {
295
+ const message = 'Runtime GC version limit exceeded; select one --runtime-version.';
296
+ output.stdout(options.json
297
+ ? `${JSON.stringify({ ok: false, command: 'runtime', action: 'gc', message })}\n`
298
+ : `${message}\n`);
299
+ return 1;
300
+ }
301
+ const entries = [];
302
+ let ok = true;
303
+ for (const version of versions) {
304
+ const references = await inspectRuntimeReferences(dataDir, version);
305
+ const boundHere = await runtimeBindingMatches(dataDir, version, binding?.runtime);
306
+ if (boundHere || references.active.length > 0) {
307
+ entries.push({
308
+ version,
309
+ status: 'retained',
310
+ reason: 'verified-workspace-reference',
311
+ references,
312
+ });
313
+ continue;
314
+ }
315
+ if (!options.apply) {
316
+ entries.push({
317
+ version,
318
+ status: options.force ? 'candidate' : 'unknown',
319
+ references,
320
+ });
321
+ continue;
322
+ }
323
+ const removed = await removeRuntime({
324
+ version,
325
+ dataDir,
326
+ forceUnknownReferences: options.force,
327
+ });
328
+ entries.push({ version, ...removed, references });
329
+ ok &&= removed.ok;
330
+ }
331
+ const report = {
332
+ ok,
333
+ command: 'runtime',
334
+ action: 'gc',
335
+ mode: options.apply ? 'apply' : 'plan',
336
+ dataDir,
337
+ coverage: 'registered-workspaces-only',
338
+ unregisteredCoverage: 'unknown',
339
+ entries,
340
+ };
341
+ output.stdout(options.json
342
+ ? `${JSON.stringify(report)}\n`
343
+ : `Runtime GC ${report.mode}: ${entries.map((entry) => `${String(entry['version'])}=${String(entry['status'])}`).join(', ') || 'no versions'}\n`);
344
+ return ok ? 0 : 1;
345
+ }
247
346
  export async function runRuntimeCommand(options, output) {
248
347
  if (options.action === null) {
249
348
  output.stderr(`${runtimeUsage}`);
@@ -259,5 +358,7 @@ export async function runRuntimeCommand(options, output) {
259
358
  return runVerify(options, output, binding);
260
359
  case 'remove':
261
360
  return runRemove(options, output, binding);
361
+ case 'gc':
362
+ return runGc(options, output, binding);
262
363
  }
263
364
  }
@@ -0,0 +1,7 @@
1
+ import type { CliOutput } from '../output.js';
2
+ export declare const sessionUsage: string;
3
+ export declare function runSessionCommand(options: {
4
+ readonly action: string;
5
+ readonly config: string | null;
6
+ readonly json: boolean;
7
+ }, output: CliOutput): Promise<number>;
@@ -0,0 +1,82 @@
1
+ import { readManagedPiRequest, planManagedPiSession, } from '../../app/managed-pi.js';
2
+ import { startManagedPiSession, requestManagedPiControl, } from '../../hosts/pi/managed-session.js';
3
+ import { watchManagedPiReadiness } from '../../app/managed-pi-readiness.js';
4
+ import { runManagedPiSdkRuntime } from '../../app/managed-pi-sdk-runtime.js';
5
+ export const sessionUsage = 'pappra session <plan|start|status|fence|stop> --config <abs managed-pi.json> [--json]\n\n' +
6
+ 'plan validates a launch request without effects. start requires a visible terminal,\n' +
7
+ 'launches native Pi TUI with OpenRouter and preserves daily configuration.\n' +
8
+ 'Ingress is journaled; exact-child exit is separate from transfer-safe quiescence.\n' +
9
+ 'status/fence/stop address only the private endpoint created by that launch.\n' +
10
+ 'No existing interactive session is adopted. start does not accept --json.';
11
+ export async function runSessionCommand(options, output) {
12
+ try {
13
+ if (options.config === null)
14
+ throw new Error('--config is required.');
15
+ const request = readManagedPiRequest(options.config);
16
+ if (options.action === 'status' ||
17
+ options.action === 'fence' ||
18
+ options.action === 'stop') {
19
+ const result = await requestManagedPiControl(`${request.journalPath}.control.json`, options.action === 'status' ? 'snapshot' : options.action);
20
+ output.stdout(`${JSON.stringify(result, null, options.json ? undefined : 2)}\n`);
21
+ if (options.action === 'stop') {
22
+ const exit = result.exit;
23
+ return result.ok === true &&
24
+ typeof exit === 'object' &&
25
+ exit !== null &&
26
+ 'status' in exit &&
27
+ (exit.status === 'exited' || exit.status === 'runtime_disposed')
28
+ ? 0
29
+ : 1;
30
+ }
31
+ return result.ok === true ? 0 : 1;
32
+ }
33
+ if (options.action === 'plan') {
34
+ output.stdout(`${JSON.stringify(planManagedPiSession(request), null, options.json ? undefined : 2)}\n`);
35
+ return 0;
36
+ }
37
+ if (options.action !== 'start')
38
+ throw new Error('session accepts plan, start, status, fence or stop.');
39
+ if (options.json)
40
+ throw new Error('Native TUI start does not accept --json.');
41
+ if (request.runtime === 'sdk') {
42
+ if (!process.stdin.isTTY || !process.stdout.isTTY)
43
+ throw new Error('SDK mode requires a visible native terminal.');
44
+ return await runManagedPiSdkRuntime(request);
45
+ }
46
+ const { schema: _schema, readiness, ...launch } = request;
47
+ const session = await startManagedPiSession(launch);
48
+ let publisher = null;
49
+ try {
50
+ if (readiness)
51
+ publisher = watchManagedPiReadiness(readiness, {
52
+ sessionId: session.identity.sessionId,
53
+ cwd: launch.cwd,
54
+ metadataFile: `${launch.journalPath}.pi-events.jsonl`,
55
+ });
56
+ }
57
+ catch {
58
+ // Readiness failure does not terminate an otherwise owned, visible session.
59
+ output.stderr('Readiness watcher could not start; task preflight remains required.\n');
60
+ }
61
+ const exit = await session.waitForExit().finally(() => publisher?.close());
62
+ if (exit.status === 'exited')
63
+ session.close();
64
+ if (exit.status !== 'exited') {
65
+ output.stderr('Managed Pi child exit is unknown; inspect retained controller evidence.\n');
66
+ return 1;
67
+ }
68
+ return exit.exitCode === 0 ? 0 : 1;
69
+ }
70
+ catch (error) {
71
+ const result = {
72
+ ok: false,
73
+ code: 'managed_pi_session_refused',
74
+ message: error instanceof Error ? error.message : 'Managed Pi session failed.',
75
+ };
76
+ if (options.json)
77
+ output.stdout(`${JSON.stringify(result)}\n`);
78
+ else
79
+ output.stderr(`${result.message}\n`);
80
+ return 2;
81
+ }
82
+ }
@@ -1,8 +1,10 @@
1
1
  import { resolveWorkspaceRoot } from '../../workspace/resolve.js';
2
2
  import { pinTask, readAutoResume, readTaskPin, setAutoResume, unpinTask, } from '../../app/task-pin.js';
3
+ import { loadWorkspaceConfig } from '../../workspace/config.js';
3
4
  export const taskUsage = 'pappra task <pin|unpin|show> [taskId] [--auto-resume] [--json]\n\n' +
4
5
  'pin records the current task in .pappra/local/current-task. Hooks inject a resume\n' +
5
- 'packet only when the workspace continuity.autoResume switch is on (--auto-resume).';
6
+ "packet only when this checkout's private auto-resume preference is on (--auto-resume).\n" +
7
+ 'The preference lives in .pappra/local/task-preferences.json and never rewrites workspace.json.';
6
8
  function failure(output, options, message) {
7
9
  if (options.json) {
8
10
  output.stdout(`${JSON.stringify({ ok: false, code: 'task_invalid', message })}\n`);
@@ -15,8 +17,17 @@ function failure(output, options, message) {
15
17
  export async function runTaskCommand(options, output) {
16
18
  const resolution = await resolveWorkspaceRoot({ startPath: options.cwd });
17
19
  const root = resolution.root;
18
- if (root === null) {
19
- return failure(output, options, 'task requires a registered Pappra workspace above the current directory.');
20
+ const mutating = options.action === 'pin' || options.action === 'unpin';
21
+ if (root === null || (mutating && resolution.state !== 'registered')) {
22
+ return failure(output, options, `task requires a registered Pappra workspace above the current directory (found: ${resolution.state}).`);
23
+ }
24
+ if (mutating) {
25
+ // An incomplete or unsafe registration can still report a root; mutations
26
+ // also require configuration this version can read.
27
+ const config = await loadWorkspaceConfig(root);
28
+ if (!config.ok) {
29
+ return failure(output, options, `workspace configuration is not usable: ${config.message}`);
30
+ }
20
31
  }
21
32
  if (options.action === 'pin') {
22
33
  if (options.taskId === null) {
@@ -29,7 +40,7 @@ export async function runTaskCommand(options, output) {
29
40
  if (options.autoResume) {
30
41
  const switched = await setAutoResume(root, true);
31
42
  if ('message' in switched) {
32
- return failure(output, options, switched.message);
43
+ return failure(output, options, `task ${pinned.taskId} is pinned, but autoResume was not enabled: ${switched.message}`);
33
44
  }
34
45
  }
35
46
  const report = {
@@ -44,7 +55,10 @@ export async function runTaskCommand(options, output) {
44
55
  return 0;
45
56
  }
46
57
  if (options.action === 'unpin') {
47
- await unpinTask(root);
58
+ const unpinned = await unpinTask(root);
59
+ if ('message' in unpinned) {
60
+ return failure(output, options, unpinned.message);
61
+ }
48
62
  const report = { ok: true, action: 'unpin' };
49
63
  output.stdout(options.json
50
64
  ? `${JSON.stringify(report)}\n`