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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/README.md +133 -14
  2. package/assets/integrations/skills/pappra/SKILL.md +56 -7
  3. package/assets/integrations/skills/pappra/references/collaboration.md +646 -0
  4. package/assets/integrations/skills/pappra/references/environment.md +367 -0
  5. package/assets/integrations/skills/pappra/references/hosts.md +20 -0
  6. package/assets/integrations/skills/pappra/references/operations.md +36 -5
  7. package/dist/adapters/pi/recovery-extension.d.ts +65 -0
  8. package/dist/adapters/pi/recovery-extension.js +238 -0
  9. package/dist/adapters/pi/session-transition-extension.d.ts +30 -0
  10. package/dist/adapters/pi/session-transition-extension.js +265 -0
  11. package/dist/app/automatic-handoff-events.d.ts +26 -0
  12. package/dist/app/automatic-handoff-events.js +134 -0
  13. package/dist/app/bounded-file.d.ts +2 -0
  14. package/dist/app/bounded-file.js +2 -0
  15. package/dist/app/capability-evidence/claude.d.ts +37 -0
  16. package/dist/app/capability-evidence/claude.js +206 -0
  17. package/dist/app/capability-evidence/codex.d.ts +35 -0
  18. package/dist/app/capability-evidence/codex.js +193 -0
  19. package/dist/app/capability-evidence/index.d.ts +33 -0
  20. package/dist/app/capability-evidence/index.js +117 -0
  21. package/dist/app/capability-evidence/pi.d.ts +73 -0
  22. package/dist/app/capability-evidence/pi.js +669 -0
  23. package/dist/app/capability-evidence/shared.d.ts +69 -0
  24. package/dist/app/capability-evidence/shared.js +195 -0
  25. package/dist/app/collab-auto-handoff.d.ts +55 -0
  26. package/dist/app/collab-auto-handoff.js +384 -0
  27. package/dist/app/collab-bindings.d.ts +57 -0
  28. package/dist/app/collab-bindings.js +1006 -0
  29. package/dist/app/collab-bootstrap-transport.d.ts +163 -0
  30. package/dist/app/collab-bootstrap-transport.js +769 -0
  31. package/dist/app/collab-bootstrap.d.ts +137 -0
  32. package/dist/app/collab-bootstrap.js +3455 -0
  33. package/dist/app/collab-handoff.d.ts +12 -0
  34. package/dist/app/collab-handoff.js +511 -0
  35. package/dist/app/collab-messages.d.ts +2 -0
  36. package/dist/app/collab-messages.js +2 -0
  37. package/dist/app/collab-notify.d.ts +156 -0
  38. package/dist/app/collab-notify.js +1208 -0
  39. package/dist/app/collab-preflight.d.ts +34 -0
  40. package/dist/app/collab-preflight.js +96 -0
  41. package/dist/app/collab-recovery-executor.d.ts +161 -0
  42. package/dist/app/collab-recovery-executor.js +1153 -0
  43. package/dist/app/collab-recovery-projection.d.ts +103 -0
  44. package/dist/app/collab-recovery-projection.js +659 -0
  45. package/dist/app/collab-recovery.d.ts +25 -0
  46. package/dist/app/collab-recovery.js +429 -0
  47. package/dist/app/collab-resources.d.ts +16 -0
  48. package/dist/app/collab-resources.js +278 -0
  49. package/dist/app/collab-role-events.d.ts +22 -0
  50. package/dist/app/collab-role-events.js +329 -0
  51. package/dist/app/collab-role-orchestration.d.ts +53 -0
  52. package/dist/app/collab-role-orchestration.js +601 -0
  53. package/dist/app/collab-role-plan.d.ts +81 -0
  54. package/dist/app/collab-role-plan.js +504 -0
  55. package/dist/app/collab-role-repair.d.ts +109 -0
  56. package/dist/app/collab-role-repair.js +821 -0
  57. package/dist/app/collab-rollover.d.ts +263 -0
  58. package/dist/app/collab-rollover.js +1112 -0
  59. package/dist/app/collab-route.d.ts +64 -0
  60. package/dist/app/collab-route.js +240 -0
  61. package/dist/app/collab-session-transition-request.d.ts +50 -0
  62. package/dist/app/collab-session-transition-request.js +339 -0
  63. package/dist/app/collab-session-transition-validation.d.ts +19 -0
  64. package/dist/app/collab-session-transition-validation.js +44 -0
  65. package/dist/app/collab-session-transition.d.ts +181 -0
  66. package/dist/app/collab-session-transition.js +2970 -0
  67. package/dist/app/collab-state.d.ts +7 -0
  68. package/dist/app/collab-state.js +162 -0
  69. package/dist/app/collab-task-store.d.ts +22 -0
  70. package/dist/app/collab-task-store.js +204 -0
  71. package/dist/app/collab-work-execution.d.ts +127 -0
  72. package/dist/app/collab-work-execution.js +1027 -0
  73. package/dist/app/collab-work-plan.d.ts +87 -0
  74. package/dist/app/collab-work-plan.js +437 -0
  75. package/dist/app/collaboration.d.ts +8 -2
  76. package/dist/app/collaboration.js +101 -12
  77. package/dist/app/doctor.js +104 -3
  78. package/dist/app/host-mcp.js +34 -8
  79. package/dist/app/host-probe.js +4 -4
  80. package/dist/app/init.d.ts +58 -4
  81. package/dist/app/init.js +768 -155
  82. package/dist/app/managed-pi-bootstrap-admission.d.ts +14 -0
  83. package/dist/app/managed-pi-bootstrap-admission.js +104 -0
  84. package/dist/app/managed-pi-bootstrap-refresh.d.ts +10 -0
  85. package/dist/app/managed-pi-bootstrap-refresh.js +78 -0
  86. package/dist/app/managed-pi-delivery.d.ts +8 -0
  87. package/dist/app/managed-pi-delivery.js +110 -0
  88. package/dist/app/managed-pi-handoff-receiver.d.ts +15 -0
  89. package/dist/app/managed-pi-handoff-receiver.js +263 -0
  90. package/dist/app/managed-pi-handoff-reference.d.ts +3 -0
  91. package/dist/app/managed-pi-handoff-reference.js +60 -0
  92. package/dist/app/managed-pi-herdr.d.ts +21 -0
  93. package/dist/app/managed-pi-herdr.js +185 -0
  94. package/dist/app/managed-pi-initial-admission.d.ts +28 -0
  95. package/dist/app/managed-pi-initial-admission.js +416 -0
  96. package/dist/app/managed-pi-initial-launch.d.ts +5 -0
  97. package/dist/app/managed-pi-initial-launch.js +61 -0
  98. package/dist/app/managed-pi-native-observation.d.ts +36 -0
  99. package/dist/app/managed-pi-native-observation.js +191 -0
  100. package/dist/app/managed-pi-readiness.d.ts +29 -0
  101. package/dist/app/managed-pi-readiness.js +288 -0
  102. package/dist/app/managed-pi-repair-stop.d.ts +21 -0
  103. package/dist/app/managed-pi-repair-stop.js +371 -0
  104. package/dist/app/managed-pi-resume-admission.d.ts +32 -0
  105. package/dist/app/managed-pi-resume-admission.js +618 -0
  106. package/dist/app/managed-pi-retirement.d.ts +28 -0
  107. package/dist/app/managed-pi-retirement.js +112 -0
  108. package/dist/app/managed-pi-sdk-control.d.ts +7 -0
  109. package/dist/app/managed-pi-sdk-control.js +169 -0
  110. package/dist/app/managed-pi-sdk-runtime.d.ts +3 -0
  111. package/dist/app/managed-pi-sdk-runtime.js +483 -0
  112. package/dist/app/managed-pi-source-admission.d.ts +14 -0
  113. package/dist/app/managed-pi-source-admission.js +323 -0
  114. package/dist/app/managed-pi-transition-host.d.ts +36 -0
  115. package/dist/app/managed-pi-transition-host.js +292 -0
  116. package/dist/app/managed-pi.d.ts +54 -0
  117. package/dist/app/managed-pi.js +248 -0
  118. package/dist/app/shell-readiness.d.ts +66 -0
  119. package/dist/app/shell-readiness.js +368 -0
  120. package/dist/app/task-pin.d.ts +2 -23
  121. package/dist/app/task-pin.js +2 -113
  122. package/dist/cli/collaboration-router.d.ts +17 -0
  123. package/dist/cli/collaboration-router.js +604 -0
  124. package/dist/cli/commands/collaboration-binding.d.ts +13 -0
  125. package/dist/cli/commands/collaboration-binding.js +118 -0
  126. package/dist/cli/commands/collaboration-bootstrap.d.ts +10 -0
  127. package/dist/cli/commands/collaboration-bootstrap.js +84 -0
  128. package/dist/cli/commands/collaboration-capabilities.d.ts +13 -0
  129. package/dist/cli/commands/collaboration-capabilities.js +127 -0
  130. package/dist/cli/commands/collaboration-handoff.d.ts +13 -0
  131. package/dist/cli/commands/collaboration-handoff.js +102 -0
  132. package/dist/cli/commands/collaboration-message.d.ts +17 -0
  133. package/dist/cli/commands/collaboration-message.js +177 -0
  134. package/dist/cli/commands/collaboration-plan.d.ts +8 -0
  135. package/dist/cli/commands/collaboration-plan.js +108 -0
  136. package/dist/cli/commands/collaboration-preflight.d.ts +10 -0
  137. package/dist/cli/commands/collaboration-preflight.js +167 -0
  138. package/dist/cli/commands/collaboration-recovery-run.d.ts +46 -0
  139. package/dist/cli/commands/collaboration-recovery-run.js +224 -0
  140. package/dist/cli/commands/collaboration-recovery.d.ts +11 -0
  141. package/dist/cli/commands/collaboration-recovery.js +104 -0
  142. package/dist/cli/commands/collaboration-resources.d.ts +11 -0
  143. package/dist/cli/commands/collaboration-resources.js +96 -0
  144. package/dist/cli/commands/collaboration-role-plan.d.ts +9 -0
  145. package/dist/cli/commands/collaboration-role-plan.js +69 -0
  146. package/dist/cli/commands/collaboration-role-run.d.ts +11 -0
  147. package/dist/cli/commands/collaboration-role-run.js +128 -0
  148. package/dist/cli/commands/collaboration-rollover.d.ts +10 -0
  149. package/dist/cli/commands/collaboration-rollover.js +103 -0
  150. package/dist/cli/commands/collaboration-state.d.ts +10 -0
  151. package/dist/cli/commands/collaboration-state.js +96 -0
  152. package/dist/cli/commands/collaboration-transition.d.ts +10 -0
  153. package/dist/cli/commands/collaboration-transition.js +75 -0
  154. package/dist/cli/commands/collaboration-work-run.d.ts +34 -0
  155. package/dist/cli/commands/collaboration-work-run.js +178 -0
  156. package/dist/cli/commands/collaboration.d.ts +4 -0
  157. package/dist/cli/commands/collaboration.js +39 -4
  158. package/dist/cli/commands/continuity.js +2 -6
  159. package/dist/cli/commands/docs.d.ts +2 -0
  160. package/dist/cli/commands/docs.js +89 -15
  161. package/dist/cli/commands/host.d.ts +7 -1
  162. package/dist/cli/commands/host.js +122 -7
  163. package/dist/cli/commands/init.d.ts +20 -3
  164. package/dist/cli/commands/init.js +897 -232
  165. package/dist/cli/commands/mcp.d.ts +1 -0
  166. package/dist/cli/commands/mcp.js +11 -5
  167. package/dist/cli/commands/repair.d.ts +12 -0
  168. package/dist/cli/commands/repair.js +41 -0
  169. package/dist/cli/commands/runtime.d.ts +1 -1
  170. package/dist/cli/commands/runtime.js +139 -38
  171. package/dist/cli/commands/session.d.ts +7 -0
  172. package/dist/cli/commands/session.js +82 -0
  173. package/dist/cli/commands/task.js +19 -5
  174. package/dist/cli/options.d.ts +806 -0
  175. package/dist/cli/options.js +293 -0
  176. package/dist/cli/run.js +280 -310
  177. package/dist/code/identity.d.ts +7 -0
  178. package/dist/code/identity.js +7 -3
  179. package/dist/code/registration.js +7 -0
  180. package/dist/code/service.d.ts +9 -0
  181. package/dist/code/service.js +16 -3
  182. package/dist/code/text.js +19 -7
  183. package/dist/collab/admission.d.ts +91 -66
  184. package/dist/collab/admission.js +21 -6
  185. package/dist/collab/canonical.d.ts +1 -1
  186. package/dist/collab/canonical.js +44 -3
  187. package/dist/collab/envelope.d.ts +2 -2
  188. package/dist/collab/envelope.js +12 -12
  189. package/dist/collab/first-work.d.ts +3 -0
  190. package/dist/collab/first-work.js +15 -0
  191. package/dist/collab/handoff.d.ts +16 -0
  192. package/dist/collab/handoff.js +39 -5
  193. package/dist/collab/index.d.ts +97 -1
  194. package/dist/collab/index.js +9 -1
  195. package/dist/collab/messages.js +126 -3
  196. package/dist/collab/persisted-messages.d.ts +123 -0
  197. package/dist/collab/persisted-messages.js +496 -0
  198. package/dist/collab/preflight.d.ts +1 -1
  199. package/dist/collab/resources.d.ts +13 -3
  200. package/dist/collab/resources.js +37 -6
  201. package/dist/collab/rollover.d.ts +311 -0
  202. package/dist/collab/rollover.js +1024 -0
  203. package/dist/collab/store.d.ts +1 -0
  204. package/dist/collab/store.js +1 -4
  205. package/dist/collab/types.d.ts +2 -354
  206. package/dist/collab/validation.d.ts +2 -10
  207. package/dist/collab/validation.js +2 -303
  208. package/dist/collab/work-plan.d.ts +105 -0
  209. package/dist/collab/work-plan.js +843 -0
  210. package/dist/continuity/context.d.ts +11 -2
  211. package/dist/continuity/context.js +100 -13
  212. package/dist/continuity/handoff-bundle.d.ts +296 -0
  213. package/dist/continuity/handoff-bundle.js +477 -0
  214. package/dist/continuity/index.d.ts +2 -0
  215. package/dist/continuity/index.js +1 -0
  216. package/dist/continuity/paths.js +10 -2
  217. package/dist/continuity/service.js +91 -15
  218. package/dist/continuity/task-pin.d.ts +24 -0
  219. package/dist/continuity/task-pin.js +590 -0
  220. package/dist/doctor.d.ts +1 -0
  221. package/dist/doctor.js +6 -0
  222. package/dist/experimental/index.d.ts +13 -0
  223. package/dist/experimental/index.js +25 -0
  224. package/dist/experimental/pi.d.ts +4 -0
  225. package/dist/experimental/pi.js +12 -0
  226. package/dist/hosts/claude/native.js +1 -1
  227. package/dist/hosts/codex/native.js +1 -1
  228. package/dist/hosts/codex/protocol.js +1 -1
  229. package/dist/hosts/integration/bootstrap-config.d.ts +58 -0
  230. package/dist/hosts/integration/bootstrap-config.js +254 -0
  231. package/dist/hosts/integration/bundle-export.d.ts +44 -0
  232. package/dist/hosts/integration/bundle-export.js +366 -3
  233. package/dist/hosts/integration/bundle.js +3 -0
  234. package/dist/hosts/integration/hook.js +36 -9
  235. package/dist/hosts/integration/pappra-bootstrap-extension.mjs +80 -0
  236. package/dist/hosts/integration/pappra-extension-runtime.mjs +59 -24631
  237. package/dist/hosts/integration/pappra-hook.mjs +61 -24749
  238. package/dist/hosts/integration/pappra-recovery-extension.mjs +259 -0
  239. package/dist/hosts/integration/pappra-session-transition-extension.mjs +276 -0
  240. package/dist/hosts/integration/pi-bootstrap-extension.d.ts +36 -0
  241. package/dist/hosts/integration/pi-bootstrap-extension.js +101 -0
  242. package/dist/hosts/integration/pi-bootstrap-guard.d.ts +125 -0
  243. package/dist/hosts/integration/pi-bootstrap-guard.js +438 -0
  244. package/dist/hosts/integration/pi-bootstrap-runtime.d.ts +63 -0
  245. package/dist/hosts/integration/pi-bootstrap-runtime.js +223 -0
  246. package/dist/hosts/integration/pi-native-events.d.ts +112 -0
  247. package/dist/hosts/integration/pi-native-events.js +348 -0
  248. package/dist/hosts/integration/pi-rollover-extension.d.ts +166 -0
  249. package/dist/hosts/integration/pi-rollover-extension.js +431 -0
  250. package/dist/hosts/integration/recovery-config.d.ts +48 -0
  251. package/dist/hosts/integration/recovery-config.js +117 -0
  252. package/dist/hosts/integration/service.d.ts +6 -1
  253. package/dist/hosts/integration/service.js +485 -35
  254. package/dist/hosts/integration/support.d.ts +7 -0
  255. package/dist/hosts/integration/support.js +9 -1
  256. package/dist/hosts/integration/templates.d.ts +3 -0
  257. package/dist/hosts/integration/templates.js +26 -3
  258. package/dist/hosts/pi/managed-host-identity.d.ts +2 -0
  259. package/dist/hosts/pi/managed-host-identity.js +40 -0
  260. package/dist/hosts/pi/managed-provider-diagnostics.d.ts +6 -0
  261. package/dist/hosts/pi/managed-provider-diagnostics.js +184 -0
  262. package/dist/hosts/pi/managed-sdk-session.d.ts +335 -0
  263. package/dist/hosts/pi/managed-sdk-session.js +1639 -0
  264. package/dist/hosts/pi/managed-session-extension.d.ts +20 -0
  265. package/dist/hosts/pi/managed-session-extension.js +84 -0
  266. package/dist/hosts/pi/managed-session.d.ts +177 -0
  267. package/dist/hosts/pi/managed-session.js +1557 -0
  268. package/dist/hosts/pi/protocol.js +1 -1
  269. package/dist/hosts/pi/query-result.js +1 -1
  270. package/dist/hosts/pi/resume-capability.d.ts +41 -0
  271. package/dist/hosts/pi/resume-capability.js +33 -0
  272. package/dist/hosts/pi/rpc.d.ts +182 -134
  273. package/dist/hosts/pi/rpc.js +230 -37
  274. package/dist/hosts/pilot.d.ts +90 -67
  275. package/dist/hosts/pilot.js +5 -1
  276. package/dist/hosts/version.d.ts +3 -0
  277. package/dist/hosts/version.js +18 -0
  278. package/dist/index.d.ts +0 -1
  279. package/dist/index.js +0 -1
  280. package/dist/infra/bounded-file.d.ts +19 -0
  281. package/dist/infra/bounded-file.js +66 -0
  282. package/dist/infra/fs.js +10 -2
  283. package/dist/infra/git.d.ts +29 -0
  284. package/dist/infra/git.js +45 -9
  285. package/dist/infra/json-property.d.ts +2 -0
  286. package/dist/infra/json-property.js +69 -0
  287. package/dist/infra/json.d.ts +4 -0
  288. package/dist/infra/json.js +24 -0
  289. package/dist/infra/owned-process-group.js +1 -1
  290. package/dist/infra/private-lock.d.ts +16 -0
  291. package/dist/infra/private-lock.js +148 -0
  292. package/dist/infra/private-state.d.ts +7 -0
  293. package/dist/infra/private-state.js +146 -0
  294. package/dist/infra/process-identity.d.ts +12 -0
  295. package/dist/infra/process-identity.js +142 -0
  296. package/dist/infra/validation.d.ts +5 -0
  297. package/dist/infra/validation.js +15 -0
  298. package/dist/init.d.ts +1 -0
  299. package/dist/init.js +6 -0
  300. package/dist/install/apply.d.ts +9 -1
  301. package/dist/install/apply.js +176 -12
  302. package/dist/install/dependencies.d.ts +38 -0
  303. package/dist/install/dependencies.js +282 -0
  304. package/dist/install/ownership.js +30 -1
  305. package/dist/install/references.d.ts +31 -0
  306. package/dist/install/references.js +208 -0
  307. package/dist/install/repair.d.ts +37 -0
  308. package/dist/install/repair.js +798 -0
  309. package/dist/install/reset-local.d.ts +16 -0
  310. package/dist/install/reset-local.js +304 -0
  311. package/dist/install/rollback.d.ts +3 -0
  312. package/dist/install/rollback.js +9 -3
  313. package/dist/install/runtime.d.ts +10 -6
  314. package/dist/install/runtime.js +299 -59
  315. package/dist/install/source-fingerprint.d.ts +2 -0
  316. package/dist/install/source-fingerprint.js +103 -0
  317. package/dist/knowledge/catalog.d.ts +1 -0
  318. package/dist/knowledge/catalog.js +143 -10
  319. package/dist/knowledge/journal.js +17 -7
  320. package/dist/knowledge/paths.js +2 -1
  321. package/dist/knowledge/refs.js +4 -0
  322. package/dist/knowledge/register-batch.d.ts +4 -0
  323. package/dist/knowledge/register-batch.js +225 -0
  324. package/dist/knowledge/relocate.d.ts +5 -0
  325. package/dist/knowledge/relocate.js +92 -0
  326. package/dist/knowledge/scan.js +103 -47
  327. package/dist/knowledge/service.d.ts +3 -0
  328. package/dist/knowledge/service.js +33 -1
  329. package/dist/knowledge/write.d.ts +4 -1
  330. package/dist/knowledge/write.js +1 -1
  331. package/dist/mcp/server.d.ts +4 -2
  332. package/dist/mcp/server.js +87 -136
  333. package/dist/schemas/collaboration-state-validation.d.ts +6 -0
  334. package/dist/schemas/collaboration-state-validation.js +342 -0
  335. package/dist/schemas/collaboration-state.d.ts +436 -0
  336. package/dist/schemas/collaboration-state.js +1 -0
  337. package/dist/schemas/collaboration.d.ts +335 -0
  338. package/dist/schemas/collaboration.js +272 -0
  339. package/dist/schemas/continuity.d.ts +8 -0
  340. package/dist/schemas/continuity.js +13 -3
  341. package/dist/schemas/doctor.d.ts +1 -0
  342. package/dist/schemas/doctor.js +1 -0
  343. package/dist/schemas/document.d.ts +61 -0
  344. package/dist/schemas/document.js +9 -0
  345. package/dist/schemas/errors.d.ts +1 -0
  346. package/dist/schemas/errors.js +1 -0
  347. package/dist/schemas/host.d.ts +24 -0
  348. package/dist/schemas/host.js +19 -0
  349. package/dist/schemas/install.d.ts +8 -2
  350. package/dist/schemas/install.js +11 -1
  351. package/dist/schemas/managed-pi-execution.d.ts +16 -0
  352. package/dist/schemas/managed-pi-execution.js +2 -0
  353. package/dist/schemas/outcome.d.ts +9 -5
  354. package/dist/workspace/config-file.js +1 -3
  355. package/dist/workspace/documents.js +12 -2
  356. package/dist/workspace/repositories.d.ts +7 -0
  357. package/dist/workspace/repositories.js +14 -5
  358. package/package.json +37 -35
  359. package/skills/pappra/SKILL.md +56 -7
  360. package/skills/pappra/references/collaboration.md +646 -0
  361. package/skills/pappra/references/environment.md +367 -0
  362. package/skills/pappra/references/hosts.md +20 -0
  363. package/skills/pappra/references/operations.md +36 -5
  364. package/dist/app/collab-from.d.ts +0 -35
  365. package/dist/app/collab-from.js +0 -84
@@ -0,0 +1,368 @@
1
+ export const SHELL_READINESS_BUDGET_MS = 10_000;
2
+ export const SHELL_READINESS_INTERVAL_MS = 100;
3
+ export const SHELL_READINESS_MAX_SAMPLES = 100;
4
+ const MAX_CAPTURED_PROCESSES = 8;
5
+ const SHELL_NAMES = new Set([
6
+ 'sh',
7
+ 'bash',
8
+ 'dash',
9
+ 'zsh',
10
+ 'fish',
11
+ 'ksh',
12
+ 'mksh',
13
+ 'csh',
14
+ 'tcsh',
15
+ 'elvish',
16
+ 'xonsh',
17
+ 'nu',
18
+ 'pwsh',
19
+ 'powershell',
20
+ 'cmd',
21
+ ]);
22
+ const AGENT_NAMES = new Set([
23
+ 'pi',
24
+ 'codex',
25
+ 'claude',
26
+ 'gemini',
27
+ 'cursor',
28
+ 'devin',
29
+ 'agy',
30
+ 'cline',
31
+ 'omp',
32
+ 'opencode',
33
+ 'copilot',
34
+ 'kimi',
35
+ 'kiro',
36
+ 'droid',
37
+ 'amp',
38
+ 'grok',
39
+ 'hermes',
40
+ 'kilo',
41
+ 'qodercli',
42
+ 'qwen',
43
+ 'letta',
44
+ 'maki',
45
+ 'muse',
46
+ ]);
47
+ function normalizedName(value) {
48
+ const tail = value.split(/[\\/]/).at(-1) ?? value;
49
+ return tail
50
+ .replace(/^-+/, '')
51
+ .replace(/\.exe$/i, '')
52
+ .toLowerCase();
53
+ }
54
+ function validNumber(value) {
55
+ return value !== null && Number.isSafeInteger(value) && value > 0;
56
+ }
57
+ function identityCode(pane, expected) {
58
+ if (pane.paneId !== expected.paneId)
59
+ return 'pane_id_mismatch';
60
+ if (pane.workspaceId !== expected.workspaceId)
61
+ return 'workspace_id_mismatch';
62
+ if (pane.terminalId !== expected.terminalId)
63
+ return 'terminal_id_mismatch';
64
+ if (pane.cwd === null)
65
+ return 'pane_cwd_missing';
66
+ return pane.cwd === expected.cwd ? null : 'pane_cwd_mismatch';
67
+ }
68
+ function sampleProcessFacts(processInfo) {
69
+ if (!Array.isArray(processInfo.foregroundProcesses))
70
+ return {
71
+ processes: [],
72
+ truncated: 0,
73
+ error: 'foreground_processes_malformed',
74
+ };
75
+ const processes = [];
76
+ for (const process of processInfo.foregroundProcesses) {
77
+ if (!validNumber(process.pid) ||
78
+ typeof process.name !== 'string' ||
79
+ process.name.length === 0)
80
+ return {
81
+ processes: [],
82
+ truncated: 0,
83
+ error: 'foreground_process_fact_malformed',
84
+ };
85
+ processes.push({ pid: process.pid, name: normalizedName(process.name) });
86
+ }
87
+ return {
88
+ processes: processes.slice(0, MAX_CAPTURED_PROCESSES),
89
+ truncated: Math.max(0, processes.length - MAX_CAPTURED_PROCESSES),
90
+ error: null,
91
+ };
92
+ }
93
+ function classifyProcessInfo(processInfo) {
94
+ const shellPid = processInfo.shellPid;
95
+ const group = processInfo.foregroundProcessGroupId;
96
+ const facts = sampleProcessFacts(processInfo);
97
+ const stateBase = {
98
+ shellPid: validNumber(shellPid) ? shellPid : null,
99
+ group: validNumber(group) ? group : null,
100
+ shellName: null,
101
+ processes: facts.processes,
102
+ processesTruncated: facts.truncated,
103
+ };
104
+ if (shellPid !== null && !validNumber(shellPid))
105
+ return { ...stateBase, state: 'failed', code: 'shell_pid_malformed' };
106
+ if (group !== null && !validNumber(group))
107
+ return {
108
+ ...stateBase,
109
+ state: 'failed',
110
+ code: 'foreground_group_malformed',
111
+ };
112
+ if (facts.error !== null)
113
+ return { ...stateBase, state: 'failed', code: facts.error };
114
+ if (shellPid === null)
115
+ return { ...stateBase, state: 'unknown', code: 'shell_pid_missing' };
116
+ if (group === null)
117
+ return { ...stateBase, state: 'unknown', code: 'foreground_group_missing' };
118
+ if (group !== shellPid)
119
+ return {
120
+ ...stateBase,
121
+ state: 'not_ready',
122
+ code: 'foreground_group_not_shell',
123
+ };
124
+ if (processInfo.foregroundProcesses.length === 0)
125
+ return {
126
+ ...stateBase,
127
+ state: 'unknown',
128
+ code: 'foreground_processes_empty',
129
+ };
130
+ if (processInfo.foregroundProcesses.some((process) => process.pid !== shellPid)) {
131
+ const agent = facts.processes.find((process) => AGENT_NAMES.has(process.name));
132
+ return agent === undefined
133
+ ? { ...stateBase, state: 'not_ready', code: 'extra_foreground_process' }
134
+ : { ...stateBase, state: 'failed', code: `existing_agent:${agent.name}` };
135
+ }
136
+ const shellName = facts.processes[0]?.name ?? null;
137
+ if (shellName === null || !SHELL_NAMES.has(shellName))
138
+ return {
139
+ ...stateBase,
140
+ state: 'not_ready',
141
+ code: 'unrecognized_shell',
142
+ shellName,
143
+ };
144
+ return {
145
+ ...stateBase,
146
+ state: 'ready',
147
+ code: null,
148
+ shellName,
149
+ };
150
+ }
151
+ /**
152
+ * Verifies the installed Herdr available-shell predicate for one already owned pane.
153
+ * Process readiness is bounded local polling in the caller's single apply operation;
154
+ * it is not an event signal, a model wakeup, or an agent-completion wait.
155
+ */
156
+ export async function verifyAvailableShell(ops, identity, options = {}) {
157
+ const clock = options.clock ?? Date.now;
158
+ const sleeper = options.sleeper ??
159
+ ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
160
+ const shouldAbort = options.shouldAbort ?? (() => false);
161
+ const budgetMs = options.budgetMs ?? SHELL_READINESS_BUDGET_MS;
162
+ const intervalMs = options.intervalMs ?? SHELL_READINESS_INTERVAL_MS;
163
+ const maxSamples = options.maxSamples ?? SHELL_READINESS_MAX_SAMPLES;
164
+ if (!Number.isSafeInteger(budgetMs) ||
165
+ budgetMs < 1 ||
166
+ budgetMs > SHELL_READINESS_BUDGET_MS)
167
+ return immediateFailure(identity, 'budget_invalid');
168
+ if (!Number.isSafeInteger(intervalMs) ||
169
+ intervalMs < 1 ||
170
+ intervalMs > SHELL_READINESS_INTERVAL_MS)
171
+ return immediateFailure(identity, 'interval_invalid');
172
+ if (!Number.isSafeInteger(maxSamples) ||
173
+ maxSamples < 1 ||
174
+ maxSamples > SHELL_READINESS_MAX_SAMPLES)
175
+ return immediateFailure(identity, 'sample_limit_invalid');
176
+ const started = clock();
177
+ const deadline = started + budgetMs;
178
+ let attempts = 0;
179
+ let pinnedShellPid = null;
180
+ let latest = null;
181
+ const samples = [];
182
+ const result = (state, code, pane) => ({
183
+ status: state,
184
+ code,
185
+ evidence: {
186
+ state,
187
+ code,
188
+ attempts,
189
+ elapsed_ms: Math.max(0, clock() - started),
190
+ pane_id: pane.paneId,
191
+ workspace_id: pane.workspaceId,
192
+ terminal_id: pane.terminalId,
193
+ cwd: pane.cwd,
194
+ shell_pid: pinnedShellPid ?? latest?.shell_pid ?? null,
195
+ foreground_process_group_id: latest?.foreground_process_group_id ?? null,
196
+ shell_name: latest?.shell_name ?? null,
197
+ last_state: latest?.state ?? 'not_observed',
198
+ last_code: latest?.code ?? null,
199
+ limits: {
200
+ budget_ms: budgetMs,
201
+ interval_ms: intervalMs,
202
+ max_samples: maxSamples,
203
+ samples_truncated: Math.max(0, attempts - samples.length),
204
+ },
205
+ samples: [...samples],
206
+ },
207
+ });
208
+ const recordSample = (sample) => {
209
+ latest = sample;
210
+ if (samples.length < maxSamples)
211
+ samples.push(sample);
212
+ };
213
+ const terminal = (state, code) => result(state, code, identity);
214
+ const checkAbort = () => shouldAbort() ? terminal('aborted', 'abort_requested') : null;
215
+ const checkDeadline = (code) => clock() >= deadline ? terminal('timeout', code) : null;
216
+ const initialAbort = checkAbort();
217
+ if (initialAbort !== null)
218
+ return initialAbort;
219
+ const beforeDeadline = checkDeadline('deadline_before_identity');
220
+ if (beforeDeadline !== null)
221
+ return beforeDeadline;
222
+ const initial = await ops.paneGet(identity.paneId, Math.max(1, deadline - clock()));
223
+ const afterInitialAbort = checkAbort();
224
+ if (afterInitialAbort !== null)
225
+ return afterInitialAbort;
226
+ const afterInitialDeadline = checkDeadline('deadline_after_initial_identity');
227
+ if (afterInitialDeadline !== null)
228
+ return afterInitialDeadline;
229
+ if (!initial.ok)
230
+ return terminal(initial.status === 'unknown' ? 'unknown' : 'failed', `initial_identity:${initial.code}`);
231
+ const initialIdentity = identityCode(initial.value, identity);
232
+ if (initialIdentity !== null)
233
+ return terminal('failed', initialIdentity);
234
+ if (initial.value.agent !== null)
235
+ return terminal('failed', 'existing_agent');
236
+ for (;;) {
237
+ const beforeAbort = checkAbort();
238
+ if (beforeAbort !== null)
239
+ return beforeAbort;
240
+ const beforeSampleDeadline = checkDeadline('deadline_before_process_info');
241
+ if (beforeSampleDeadline !== null)
242
+ return beforeSampleDeadline;
243
+ if (attempts >= maxSamples)
244
+ return terminal('timeout', 'sample_limit_reached');
245
+ attempts += 1;
246
+ const sampleStart = clock();
247
+ const snapshot = await ops.paneProcessInfo(identity.paneId, Math.max(1, deadline - clock()));
248
+ const afterSampleAbort = checkAbort();
249
+ if (afterSampleAbort !== null)
250
+ return afterSampleAbort;
251
+ const afterSampleDeadline = checkDeadline('deadline_after_process_info');
252
+ if (afterSampleDeadline !== null)
253
+ return afterSampleDeadline;
254
+ if (!snapshot.ok) {
255
+ const status = snapshot.status === 'unknown' ? 'unknown' : 'failed';
256
+ recordSample({
257
+ elapsed_ms: Math.max(0, sampleStart - started),
258
+ state: status === 'unknown' ? 'unknown' : 'failed',
259
+ code: snapshot.code,
260
+ shell_pid: pinnedShellPid,
261
+ foreground_process_group_id: null,
262
+ shell_name: null,
263
+ foreground_processes: [],
264
+ processes_truncated: 0,
265
+ });
266
+ return terminal(status, `process_info:${snapshot.code}`);
267
+ }
268
+ const processInfo = snapshot.value;
269
+ if (processInfo.paneId !== identity.paneId)
270
+ return terminal('failed', 'pane_id_mismatch');
271
+ const classified = classifyProcessInfo(processInfo);
272
+ if (classified.shellPid !== null) {
273
+ if (pinnedShellPid === null)
274
+ pinnedShellPid = classified.shellPid;
275
+ else if (pinnedShellPid !== classified.shellPid) {
276
+ recordSample({
277
+ elapsed_ms: Math.max(0, sampleStart - started),
278
+ state: 'failed',
279
+ code: 'shell_incarnation_drift',
280
+ shell_pid: classified.shellPid,
281
+ foreground_process_group_id: classified.group,
282
+ shell_name: classified.shellName,
283
+ foreground_processes: classified.processes,
284
+ processes_truncated: classified.processesTruncated,
285
+ });
286
+ return terminal('failed', 'shell_incarnation_drift');
287
+ }
288
+ }
289
+ const sample = {
290
+ elapsed_ms: Math.max(0, sampleStart - started),
291
+ state: classified.state,
292
+ code: classified.code,
293
+ shell_pid: classified.shellPid,
294
+ foreground_process_group_id: classified.group,
295
+ shell_name: classified.shellName,
296
+ foreground_processes: classified.processes,
297
+ processes_truncated: classified.processesTruncated,
298
+ };
299
+ recordSample(sample);
300
+ if (classified.state === 'failed')
301
+ return terminal('failed', classified.code ?? 'process_facts_invalid');
302
+ if (classified.state === 'ready') {
303
+ const beforeFinalAbort = checkAbort();
304
+ if (beforeFinalAbort !== null)
305
+ return beforeFinalAbort;
306
+ const beforeFinalDeadline = checkDeadline('deadline_before_final_identity');
307
+ if (beforeFinalDeadline !== null)
308
+ return beforeFinalDeadline;
309
+ const finalIdentity = await ops.paneGet(identity.paneId, Math.max(1, deadline - clock()));
310
+ const afterFinalAbort = checkAbort();
311
+ if (afterFinalAbort !== null)
312
+ return afterFinalAbort;
313
+ const afterFinalDeadline = checkDeadline('deadline_after_final_identity');
314
+ if (afterFinalDeadline !== null)
315
+ return afterFinalDeadline;
316
+ if (!finalIdentity.ok)
317
+ return terminal(finalIdentity.status === 'unknown' ? 'unknown' : 'failed', `final_identity:${finalIdentity.code}`);
318
+ const finalCode = identityCode(finalIdentity.value, identity);
319
+ if (finalCode !== null)
320
+ return terminal('failed', finalCode);
321
+ if (finalIdentity.value.agent !== null)
322
+ return terminal('failed', 'agent_appeared_before_start');
323
+ return result('ready', null, identity);
324
+ }
325
+ if (attempts >= maxSamples)
326
+ return terminal('timeout', 'sample_limit_reached');
327
+ const remaining = deadline - clock();
328
+ if (remaining <= 0)
329
+ return terminal('timeout', classified.state === 'unknown'
330
+ ? 'deadline_unknown'
331
+ : 'deadline_not_ready');
332
+ await sleeper(Math.min(intervalMs, remaining));
333
+ const afterSleepAbort = checkAbort();
334
+ if (afterSleepAbort !== null)
335
+ return afterSleepAbort;
336
+ const afterSleepDeadline = checkDeadline('deadline_after_wait');
337
+ if (afterSleepDeadline !== null)
338
+ return afterSleepDeadline;
339
+ }
340
+ }
341
+ function immediateFailure(identity, code) {
342
+ return {
343
+ status: 'failed',
344
+ code,
345
+ evidence: {
346
+ state: 'failed',
347
+ code,
348
+ attempts: 0,
349
+ elapsed_ms: 0,
350
+ pane_id: identity.paneId,
351
+ workspace_id: identity.workspaceId,
352
+ terminal_id: identity.terminalId,
353
+ cwd: identity.cwd,
354
+ shell_pid: null,
355
+ foreground_process_group_id: null,
356
+ shell_name: null,
357
+ last_state: 'not_observed',
358
+ last_code: null,
359
+ limits: {
360
+ budget_ms: 0,
361
+ interval_ms: 0,
362
+ max_samples: 0,
363
+ samples_truncated: 0,
364
+ },
365
+ samples: [],
366
+ },
367
+ };
368
+ }
@@ -1,23 +1,2 @@
1
- export declare const TASK_PIN_SCHEMA = "pappra/task-pin/1";
2
- export interface TaskPin {
3
- readonly schema: typeof TASK_PIN_SCHEMA;
4
- readonly taskId: string;
5
- readonly pinnedAt: string;
6
- }
7
- export interface TaskPinFailure {
8
- readonly ok: false;
9
- readonly message: string;
10
- }
11
- export declare function readTaskPin(root: string): Promise<TaskPin | null>;
12
- export declare function pinTask(root: string, taskId: string): Promise<TaskPin | TaskPinFailure>;
13
- export declare function unpinTask(root: string): Promise<{
14
- ok: true;
15
- }>;
16
- /**
17
- * Toggles the workspace-level auto-resume switch. The hook only injects a resume
18
- * packet when this switch is on and a task pin exists; neither is inferred.
19
- */
20
- export declare function setAutoResume(root: string, enabled: boolean): Promise<{
21
- ok: true;
22
- } | TaskPinFailure>;
23
- export declare function readAutoResume(root: string): Promise<boolean>;
1
+ /** Workspace task selection is a continuity capability. */
2
+ export * from '../continuity/task-pin.js';
@@ -1,113 +1,2 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
3
- import { dirname, join } from 'node:path';
4
- import { readTextFileBounded } from '../infra/fs.js';
5
- import { workspaceConfigSchema } from '../schemas/workspace.js';
6
- export const TASK_PIN_SCHEMA = 'pappra/task-pin/1';
7
- const TASK_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
8
- function pinPath(root) {
9
- return join(root, '.pappra', 'local', 'current-task');
10
- }
11
- export async function readTaskPin(root) {
12
- const read = await readTextFileBounded(pinPath(root), 64 * 1024);
13
- if (!read.ok)
14
- return null;
15
- try {
16
- const value = JSON.parse(read.value.text);
17
- if (typeof value !== 'object' ||
18
- value === null ||
19
- !('schema' in value) ||
20
- value.schema !== TASK_PIN_SCHEMA ||
21
- !('taskId' in value) ||
22
- typeof value.taskId !== 'string' ||
23
- !TASK_ID.test(value.taskId)) {
24
- return null;
25
- }
26
- return value;
27
- }
28
- catch {
29
- return null;
30
- }
31
- }
32
- export async function pinTask(root, taskId) {
33
- if (!TASK_ID.test(taskId)) {
34
- return {
35
- ok: false,
36
- message: 'task id must be a short identifier (letters, digits, dot, dash, underscore).',
37
- };
38
- }
39
- const pin = {
40
- schema: TASK_PIN_SCHEMA,
41
- taskId,
42
- pinnedAt: new Date().toISOString(),
43
- };
44
- const target = pinPath(root);
45
- await mkdir(dirname(target), { recursive: true, mode: 0o700 });
46
- const temporary = `${target}.tmp-${randomUUID()}`;
47
- await writeFile(temporary, `${JSON.stringify(pin, null, 2)}\n`, {
48
- mode: 0o600,
49
- });
50
- await rename(temporary, target);
51
- return pin;
52
- }
53
- export async function unpinTask(root) {
54
- const target = pinPath(root);
55
- const { rm } = await import('node:fs/promises');
56
- await rm(target, { force: true });
57
- return { ok: true };
58
- }
59
- /**
60
- * Toggles the workspace-level auto-resume switch. The hook only injects a resume
61
- * packet when this switch is on and a task pin exists; neither is inferred.
62
- */
63
- export async function setAutoResume(root, enabled) {
64
- const configPath = join(root, '.pappra', 'workspace.json');
65
- const read = await readTextFileBounded(configPath, 1024 * 1024);
66
- if (!read.ok) {
67
- return { ok: false, message: read.message };
68
- }
69
- let raw;
70
- try {
71
- raw = JSON.parse(read.value.text);
72
- }
73
- catch (error) {
74
- return {
75
- ok: false,
76
- message: `workspace.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,
77
- };
78
- }
79
- const parsed = workspaceConfigSchema.safeParse({
80
- ...(typeof raw === 'object' && raw !== null ? raw : {}),
81
- continuity: { autoResume: enabled },
82
- });
83
- if (!parsed.success) {
84
- return {
85
- ok: false,
86
- message: `workspace.json rejected the continuity switch: ${parsed.error.issues[0]?.message ?? 'invalid'}`,
87
- };
88
- }
89
- const backup = join(root, '.pappra', 'local', 'backups', `task-pin-${randomUUID()}`, 'workspace.json');
90
- await mkdir(dirname(backup), { recursive: true, mode: 0o700 });
91
- await writeFile(backup, read.value.text, { mode: 0o600 });
92
- const temporary = `${configPath}.tmp-${randomUUID()}`;
93
- await writeFile(temporary, `${JSON.stringify(parsed.data, null, 2)}\n`);
94
- await rename(temporary, configPath);
95
- return { ok: true };
96
- }
97
- export async function readAutoResume(root) {
98
- const read = await readFile(join(root, '.pappra', 'workspace.json'), 'utf8');
99
- try {
100
- const raw = JSON.parse(read);
101
- if (typeof raw !== 'object' || raw === null || !('continuity' in raw)) {
102
- return false;
103
- }
104
- const continuity = raw.continuity;
105
- return (typeof continuity === 'object' &&
106
- continuity !== null &&
107
- 'autoResume' in continuity &&
108
- continuity.autoResume === true);
109
- }
110
- catch {
111
- return false;
112
- }
113
- }
1
+ /** Workspace task selection is a continuity capability. */
2
+ export * from '../continuity/task-pin.js';
@@ -0,0 +1,17 @@
1
+ import type { CliOutput } from './output.js';
2
+ import { type CliValues } from './options.js';
3
+ import type { getPackageInfo } from '../package-info.js';
4
+ /** Everything the collaboration router needs from one parsed command line. */
5
+ export interface CollaborationRouteRequest {
6
+ readonly values: CliValues;
7
+ /** The resolved `collab` action, e.g. `message:send` or `role-run`. */
8
+ readonly action: string | null;
9
+ /** Raw argv, for duplicate-flag detection the parser cannot observe. */
10
+ readonly args: readonly string[];
11
+ readonly info: ReturnType<typeof getPackageInfo>;
12
+ readonly rpcRequestTimeout: string | undefined;
13
+ readonly rpcOperationTimeout: string | undefined;
14
+ readonly output: CliOutput;
15
+ readonly json: boolean;
16
+ }
17
+ export declare function routeCollaboration(request: CollaborationRouteRequest): Promise<number>;