@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
@@ -0,0 +1,7 @@
1
+ import { type TaskStoreFailure, type TaskStoreResult } from './collab-task-store.js';
2
+ export declare const COLLAB_STATE_SCHEMA = "pappra/collaboration-state/1";
3
+ export type StateAction = 'show' | 'doctor' | 'epoch-check';
4
+ export declare function showTaskState(taskRoot: string): Promise<TaskStoreResult<Record<string, unknown>>>;
5
+ export declare function doctorTaskState(taskRoot: string): Promise<TaskStoreResult<Record<string, unknown>>>;
6
+ export declare function checkTaskEpoch(taskRoot: string, ownerEpoch: number): Promise<TaskStoreResult<Record<string, unknown>>>;
7
+ export type { TaskStoreFailure };
@@ -0,0 +1,162 @@
1
+ import { checkOwnerEpoch } from '../collab/lifecycle.js';
2
+ import { activeClaims } from '../collab/resources.js';
3
+ import { doctor, readLock } from '../collab/store.js';
4
+ import { openTaskStore, } from './collab-task-store.js';
5
+ export const COLLAB_STATE_SCHEMA = 'pappra/collaboration-state/1';
6
+ const MAX_COLLECTION_ROWS = 50;
7
+ function limitRows(items) {
8
+ return {
9
+ rows: items.slice(0, MAX_COLLECTION_ROWS),
10
+ total: items.length,
11
+ truncated: items.length > MAX_COLLECTION_ROWS,
12
+ };
13
+ }
14
+ function lockSummary(taskRoot) {
15
+ const lock = readLock(taskRoot);
16
+ return {
17
+ held: lock.held,
18
+ holder: lock.held ? lock.holder : null,
19
+ holder_process_alive: lock.held ? lock.holder_process_alive : false,
20
+ transaction_count: lock.transaction_files?.length ?? 0,
21
+ };
22
+ }
23
+ export async function showTaskState(taskRoot) {
24
+ const opened = await openTaskStore(taskRoot);
25
+ if (!opened.ok)
26
+ return opened;
27
+ const { record, taskRoot: canonical } = opened.value;
28
+ const attempts = limitRows((record.attempts ?? []).map((item) => ({
29
+ subtask_id: item.subtask_id,
30
+ attempt: item.attempt,
31
+ state: item.state,
32
+ ownership: item.ownership ?? null,
33
+ native: item.native,
34
+ })));
35
+ const claims = limitRows(activeClaims(record));
36
+ const handoffs = limitRows((record.handoffs ?? []).map((item) => ({
37
+ handoff_id: item.handoff_id,
38
+ kind: item.kind,
39
+ state: item.state,
40
+ })));
41
+ const uncertainty = limitRows((record.uncertainty ?? [])
42
+ .filter((item) => !item.resolved_at)
43
+ .map((item) => ({
44
+ uncertainty_id: item.uncertainty_id,
45
+ kind: item.kind,
46
+ subtask_id: item.subtask_id,
47
+ attempt: item.attempt,
48
+ detail: item.detail,
49
+ })));
50
+ const results = limitRows((record.results ?? []).map((item) => ({
51
+ subtask_id: item.subtask_id,
52
+ attempt: item.attempt,
53
+ status: item.status,
54
+ classification: item.classification,
55
+ message_id: item.message_id,
56
+ })));
57
+ const lock = lockSummary(canonical);
58
+ return {
59
+ ok: true,
60
+ value: {
61
+ schema: COLLAB_STATE_SCHEMA,
62
+ ok: true,
63
+ action: 'show',
64
+ task_root: canonical,
65
+ task_id: record.task_id,
66
+ state_revision: record.state_revision,
67
+ coordinator: record.coordinator ?? null,
68
+ dispatch_frozen: record.dispatch_frozen === true,
69
+ attempts: attempts.rows,
70
+ messages: (record.messages ?? []).length,
71
+ claims: claims.rows,
72
+ handoffs: handoffs.rows,
73
+ open_uncertainty: uncertainty.rows,
74
+ results: results.rows,
75
+ lock,
76
+ counts: {
77
+ attempts: attempts.total,
78
+ messages: (record.messages ?? []).length,
79
+ claims: claims.total,
80
+ handoffs: handoffs.total,
81
+ open_uncertainty: uncertainty.total,
82
+ results: results.total,
83
+ },
84
+ truncated: {
85
+ attempts: attempts.truncated,
86
+ claims: claims.truncated,
87
+ handoffs: handoffs.truncated,
88
+ open_uncertainty: uncertainty.truncated,
89
+ results: results.truncated,
90
+ },
91
+ limits: ['reported_state_only', 'native_execution_not_queried'],
92
+ },
93
+ };
94
+ }
95
+ export async function doctorTaskState(taskRoot) {
96
+ const opened = await openTaskStore(taskRoot);
97
+ if (!opened.ok)
98
+ return opened;
99
+ const { taskRoot: canonical } = opened.value;
100
+ let report;
101
+ try {
102
+ report = doctor(canonical);
103
+ }
104
+ catch {
105
+ return {
106
+ ok: false,
107
+ code: 'task_state_unreadable',
108
+ message: 'The task state could not be diagnosed.',
109
+ nextAction: 'Inspect the task record, lock and transaction paths; nothing was repaired.',
110
+ };
111
+ }
112
+ const findings = limitRows(report.findings);
113
+ const blocking = report.findings.filter((finding) => finding.severity === 'invalid').length;
114
+ const uncertain = report.findings.filter((finding) => finding.severity === 'uncertain').length;
115
+ const active = report.findings.filter((finding) => finding.severity === 'active').length;
116
+ return {
117
+ ok: true,
118
+ value: {
119
+ schema: COLLAB_STATE_SCHEMA,
120
+ // A live lock observation is diagnostic but not a readiness failure.
121
+ // Unresolved uncertain evidence and invalid layout/records need input.
122
+ ok: blocking === 0 && uncertain === 0,
123
+ action: 'doctor',
124
+ task_root: report.task_root,
125
+ state_revision: report.state_revision,
126
+ findings: findings.rows,
127
+ counts: { findings: findings.total, blocking, uncertain, active },
128
+ truncated: findings.truncated,
129
+ lock: lockSummary(canonical),
130
+ limits: ['diagnostic_only', 'no_repair_or_lock_break'],
131
+ },
132
+ };
133
+ }
134
+ export async function checkTaskEpoch(taskRoot, ownerEpoch) {
135
+ const opened = await openTaskStore(taskRoot);
136
+ if (!opened.ok)
137
+ return opened;
138
+ const { record, taskRoot: canonical } = opened.value;
139
+ const result = checkOwnerEpoch(record, ownerEpoch);
140
+ const subtasks = limitRows((record.attempts ?? []).map((item) => ({
141
+ subtask_id: item.subtask_id,
142
+ attempt: item.attempt,
143
+ state: item.state,
144
+ })));
145
+ return {
146
+ ok: true,
147
+ value: {
148
+ schema: COLLAB_STATE_SCHEMA,
149
+ ok: result.ok,
150
+ action: 'epoch-check',
151
+ task_root: canonical,
152
+ owner_epoch: result.ok ? result.owner_epoch : null,
153
+ expected: record.coordinator?.owner_epoch ?? null,
154
+ actual: ownerEpoch,
155
+ reason: result.ok ? null : result.reason,
156
+ subtasks: subtasks.rows,
157
+ counts: { subtasks: subtasks.total },
158
+ truncated: subtasks.truncated,
159
+ limits: ['reported_epoch_only', 'no_authority_transition'],
160
+ },
161
+ };
162
+ }
@@ -0,0 +1,22 @@
1
+ import type { Outcome } from '../schemas/outcome.js';
2
+ import { type MessageServiceFailure, type OpenedMessageTask } from './collab-messages.js';
3
+ /**
4
+ * Task-store namespace proof for state and resource operations.
5
+ *
6
+ * The message namespace validator is authoritative for the domain/tasks/task
7
+ * root, task record and messages directory. This module additionally inspects
8
+ * the nested paths the new routes may read or mutate: the write lock and its
9
+ * transaction files, ledger, aborted/broken-lock directories, the resource
10
+ * domain lock, and neighboring task records used by domain-wide scans. Symlinks
11
+ * and special files in those paths are refused instead of being followed.
12
+ */
13
+ export type TaskStoreFailure = MessageServiceFailure;
14
+ export type TaskStoreResult<T> = Outcome<T, TaskStoreFailure>;
15
+ export type OpenedTaskStore = OpenedMessageTask;
16
+ export declare function openTaskStore(taskRoot: string): Promise<TaskStoreResult<OpenedTaskStore>>;
17
+ /** Revalidate namespace identity and nested state immediately before apply. */
18
+ export declare function assertTaskStoreCurrent(opened: OpenedTaskStore): Promise<TaskStoreFailure | null>;
19
+ /** Domain-wide scan validation for `resource list` and `claim`. */
20
+ export declare function validateDomainTaskState(domainRoot: string): TaskStoreFailure | null;
21
+ /** Mutation-path validation for `claim` (the domain lock is never followed). */
22
+ export declare function validateDomainMutationPaths(domainRoot: string): TaskStoreFailure | null;
@@ -0,0 +1,204 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { assertMessageTaskCurrent, openMessageTask, } from './collab-messages.js';
4
+ import { abortedDir, brokenLocksDir, ledgerPath, lockPath, } from '../collab/store.js';
5
+ import { isPathInside } from '../schemas/paths.js';
6
+ class UnsafeNestedState extends Error {
7
+ code;
8
+ nextAction;
9
+ constructor(code, message, nextAction) {
10
+ super(message);
11
+ this.code = code;
12
+ this.nextAction = nextAction;
13
+ this.name = 'UnsafeNestedState';
14
+ }
15
+ }
16
+ function failure(error) {
17
+ return {
18
+ ok: false,
19
+ code: error.code,
20
+ message: error.message,
21
+ nextAction: error.nextAction,
22
+ };
23
+ }
24
+ const MISSING = new Set(['ENOENT', 'ENOTDIR']);
25
+ function lstatOptional(file) {
26
+ try {
27
+ return fs.lstatSync(file);
28
+ }
29
+ catch (error) {
30
+ const code = typeof error === 'object' && error !== null && 'code' in error
31
+ ? String(error.code)
32
+ : null;
33
+ if (code !== null && MISSING.has(code))
34
+ return null;
35
+ throw new UnsafeNestedState('task_state_unreadable', `Cannot inspect nested task state: ${file}`, 'Inspect permissions and the path; nothing was mutated.');
36
+ }
37
+ }
38
+ function requireRealDirectory(file, base, code) {
39
+ const stats = lstatOptional(file);
40
+ if (stats === null)
41
+ return;
42
+ if (stats.isSymbolicLink() || !stats.isDirectory()) {
43
+ throw new UnsafeNestedState(code, `Nested task state is not a real directory: ${file}`, 'Restore a real directory; Pappra does not follow redirected state.');
44
+ }
45
+ const real = fs.realpathSync(file);
46
+ if (real !== file || !isPathInside(base, real)) {
47
+ throw new UnsafeNestedState(code, `Nested task state is redirected: ${file}`, 'Restore the real directory inside its task/domain root.');
48
+ }
49
+ }
50
+ function requireRealRegularFile(file, base, code, maxBytes) {
51
+ const stats = lstatOptional(file);
52
+ if (stats === null)
53
+ return;
54
+ if (stats.isSymbolicLink() || !stats.isFile()) {
55
+ throw new UnsafeNestedState(code, `Nested task state is not a regular file: ${file}`, 'Restore a regular file; Pappra does not follow redirected state.');
56
+ }
57
+ if (maxBytes !== undefined && stats.size > maxBytes) {
58
+ throw new UnsafeNestedState(code, `Nested task state exceeds the supported size: ${file}`, 'Inspect the oversized nested state; nothing was read or mutated.');
59
+ }
60
+ const real = fs.realpathSync(file);
61
+ if (real !== file || !isPathInside(base, real)) {
62
+ throw new UnsafeNestedState(code, `Nested task state is redirected: ${file}`, 'Restore the real file inside its task/domain root.');
63
+ }
64
+ }
65
+ function inspectLockDirectory(taskRoot) {
66
+ const directory = lockPath(taskRoot);
67
+ const stats = lstatOptional(directory);
68
+ if (stats === null)
69
+ return;
70
+ requireRealDirectory(directory, taskRoot, 'task_lock_unsafe');
71
+ for (const name of fs.readdirSync(directory)) {
72
+ requireRealRegularFile(path.join(directory, name), taskRoot, 'task_transaction_unsafe', 8 * 1024 * 1024);
73
+ }
74
+ }
75
+ function inspectTaskPrivateState(taskRoot) {
76
+ inspectLockDirectory(taskRoot);
77
+ requireRealDirectory(abortedDir(taskRoot), taskRoot, 'task_aborted_unsafe');
78
+ requireRealDirectory(brokenLocksDir(taskRoot), taskRoot, 'task_broken_locks_unsafe');
79
+ requireRealRegularFile(ledgerPath(taskRoot), taskRoot, 'task_ledger_unsafe');
80
+ }
81
+ function inspectDomainLock(domainRoot) {
82
+ const directory = path.join(domainRoot, '.domain.lock');
83
+ const stats = lstatOptional(directory);
84
+ if (stats === null)
85
+ return;
86
+ requireRealDirectory(directory, domainRoot, 'domain_lock_unsafe');
87
+ for (const name of fs.readdirSync(directory)) {
88
+ requireRealRegularFile(path.join(directory, name), domainRoot, 'domain_lock_unsafe', 1024 * 1024);
89
+ }
90
+ }
91
+ /**
92
+ * Validate the neighboring task roots/records read by a domain-wide resource
93
+ * scan. Missing or malformed regular records remain unreadable evidence for the
94
+ * core; a symlinked root or record is a namespace redirect and is refused.
95
+ */
96
+ function inspectDomainTasks(domainRoot) {
97
+ const tasksDirectory = path.join(domainRoot, 'tasks');
98
+ let names;
99
+ try {
100
+ names = fs.readdirSync(tasksDirectory).sort();
101
+ }
102
+ catch {
103
+ throw new UnsafeNestedState('task_state_unreadable', `Cannot inspect the domain tasks directory: ${tasksDirectory}`, 'Inspect permissions; nothing was mutated.');
104
+ }
105
+ for (const name of names) {
106
+ const taskRoot = path.join(tasksDirectory, name);
107
+ const stats = lstatOptional(taskRoot);
108
+ if (stats === null)
109
+ continue;
110
+ if (stats.isSymbolicLink()) {
111
+ throw new UnsafeNestedState('domain_state_redirected', `Neighboring task root is a symlink: ${taskRoot}`, 'Restore a real task root; Pappra does not follow redirected task state.');
112
+ }
113
+ if (!stats.isDirectory())
114
+ continue;
115
+ const realTask = fs.realpathSync(taskRoot);
116
+ if (realTask !== taskRoot || !isPathInside(tasksDirectory, realTask)) {
117
+ throw new UnsafeNestedState('domain_state_redirected', `Neighboring task root is redirected: ${taskRoot}`, 'Restore the real task root inside the domain.');
118
+ }
119
+ const record = path.join(taskRoot, 'task.json');
120
+ const recordStats = lstatOptional(record);
121
+ if (recordStats === null)
122
+ continue;
123
+ if (recordStats.isSymbolicLink() || !recordStats.isFile()) {
124
+ throw new UnsafeNestedState('domain_state_unsafe', `Neighboring task record is not a regular file: ${record}`, 'Restore a regular task record; redirected state is not scanned.');
125
+ }
126
+ const realRecord = fs.realpathSync(record);
127
+ if (realRecord !== record || !isPathInside(taskRoot, realRecord)) {
128
+ throw new UnsafeNestedState('domain_state_redirected', `Neighboring task record is redirected: ${record}`, 'Restore the real task record inside its task root.');
129
+ }
130
+ }
131
+ }
132
+ export async function openTaskStore(taskRoot) {
133
+ const opened = await openMessageTask(taskRoot);
134
+ if (!opened.ok)
135
+ return opened;
136
+ try {
137
+ inspectTaskPrivateState(opened.value.taskRoot);
138
+ }
139
+ catch (error) {
140
+ if (error instanceof UnsafeNestedState)
141
+ return failure(error);
142
+ return {
143
+ ok: false,
144
+ code: 'task_state_unreadable',
145
+ message: 'Nested task state could not be inspected.',
146
+ nextAction: 'Inspect the task lock, ledger and transaction paths; nothing was mutated.',
147
+ };
148
+ }
149
+ return opened;
150
+ }
151
+ /** Revalidate namespace identity and nested state immediately before apply. */
152
+ export async function assertTaskStoreCurrent(opened) {
153
+ const changed = await assertMessageTaskCurrent(opened);
154
+ if (changed !== null)
155
+ return changed;
156
+ try {
157
+ inspectTaskPrivateState(opened.taskRoot);
158
+ }
159
+ catch (error) {
160
+ if (error instanceof UnsafeNestedState)
161
+ return failure(error);
162
+ return {
163
+ ok: false,
164
+ code: 'task_state_unreadable',
165
+ message: 'Nested task state could not be inspected.',
166
+ nextAction: 'Inspect the task lock, ledger and transaction paths; nothing was mutated.',
167
+ };
168
+ }
169
+ return null;
170
+ }
171
+ /** Domain-wide scan validation for `resource list` and `claim`. */
172
+ export function validateDomainTaskState(domainRoot) {
173
+ try {
174
+ inspectDomainTasks(domainRoot);
175
+ }
176
+ catch (error) {
177
+ if (error instanceof UnsafeNestedState)
178
+ return failure(error);
179
+ return {
180
+ ok: false,
181
+ code: 'task_state_unreadable',
182
+ message: 'The domain task state could not be inspected.',
183
+ nextAction: 'Inspect the domain tasks directory and records; nothing was mutated.',
184
+ };
185
+ }
186
+ return null;
187
+ }
188
+ /** Mutation-path validation for `claim` (the domain lock is never followed). */
189
+ export function validateDomainMutationPaths(domainRoot) {
190
+ try {
191
+ inspectDomainLock(domainRoot);
192
+ }
193
+ catch (error) {
194
+ if (error instanceof UnsafeNestedState)
195
+ return failure(error);
196
+ return {
197
+ ok: false,
198
+ code: 'task_state_unreadable',
199
+ message: 'The domain lock path could not be inspected.',
200
+ nextAction: 'Inspect the domain lock directory; nothing was mutated.',
201
+ };
202
+ }
203
+ return null;
204
+ }
@@ -0,0 +1,127 @@
1
+ import { type HerdrTransport } from './collab-notify.js';
2
+ import type { Identity } from '../collab/types.js';
3
+ export declare const COLLAB_WORK_EXECUTION_SCHEMA = "pappra/collab-work-execution/1";
4
+ export interface WorkExecutionCardInput {
5
+ readonly assignment_id: string;
6
+ readonly capabilities_file: string;
7
+ }
8
+ export interface WorkExecutionRequest {
9
+ readonly task_root: string;
10
+ readonly plan_file: string;
11
+ readonly binding_file: string;
12
+ readonly caller: Identity & {
13
+ readonly cwd: string;
14
+ };
15
+ readonly caller_pane: string;
16
+ readonly capability_cards: readonly WorkExecutionCardInput[];
17
+ readonly max_concurrency?: number;
18
+ }
19
+ export interface WorkExecutionOptions {
20
+ readonly request: WorkExecutionRequest;
21
+ readonly apply: boolean;
22
+ }
23
+ export interface WorkExecutionDispatchRequest {
24
+ readonly taskRoot: string;
25
+ readonly messageId: string;
26
+ readonly bindingFile: string;
27
+ readonly callerPane: string;
28
+ readonly finalAuthorityCheck?: () => Promise<{
29
+ readonly ok: boolean;
30
+ readonly reason: string;
31
+ }>;
32
+ }
33
+ export interface WorkExecutionAdapter {
34
+ /** Read-only routing validation. It must never submit a notification. */
35
+ preflight(request: WorkExecutionDispatchRequest): Promise<WorkExecutionObservation>;
36
+ /** One notification attempt; unknown outcomes are never replayed by this layer. */
37
+ dispatch(request: WorkExecutionDispatchRequest): Promise<WorkExecutionObservation>;
38
+ }
39
+ export interface WorkExecutionObservation {
40
+ readonly ok: boolean;
41
+ readonly status: string;
42
+ readonly detail: string | null;
43
+ readonly delivery_path?: string | null;
44
+ readonly message_digest?: string | null;
45
+ readonly target_pane?: string | null;
46
+ }
47
+ export interface WorkExecutionNodeResult {
48
+ readonly node_id: string;
49
+ readonly role: string;
50
+ readonly assignment_id: string;
51
+ readonly attempt: number;
52
+ readonly input_revision: string;
53
+ readonly work_plan_status: string;
54
+ readonly execution_status: 'accepted' | 'awaiting_acceptance' | 'planned' | 'dispatched' | 'blocked' | 'reconciliation-required' | 'not-dispatchable';
55
+ readonly blockers: readonly string[];
56
+ readonly next_action: string | null;
57
+ readonly assignment: {
58
+ readonly ref: string | null;
59
+ readonly digest: string | null;
60
+ };
61
+ readonly capabilities: {
62
+ readonly ref: string | null;
63
+ readonly digest: string | null;
64
+ };
65
+ readonly intent_message_id: string | null;
66
+ readonly delivery: {
67
+ readonly status: string | null;
68
+ readonly message_digest: string | null;
69
+ readonly delivery_path: string | null;
70
+ readonly target_pane: string | null;
71
+ } | null;
72
+ readonly acceptance: 'accepted' | 'awaiting_acceptance' | 'rejected' | 'not-applicable';
73
+ }
74
+ export interface WorkExecutionReportPointer {
75
+ readonly node_id: string;
76
+ readonly assignment_id: string;
77
+ readonly attempt: number;
78
+ readonly status: string;
79
+ readonly message_id: string;
80
+ readonly digest: string;
81
+ readonly input_revision: string | null;
82
+ readonly evidence_ref: string | null;
83
+ readonly outputs: readonly {
84
+ readonly ref: string;
85
+ readonly digest: string;
86
+ }[];
87
+ }
88
+ export interface WorkExecutionReport {
89
+ readonly schema: typeof COLLAB_WORK_EXECUTION_SCHEMA;
90
+ readonly ok: boolean;
91
+ readonly status: 'planned' | 'applied' | 'blocked' | 'needs-reconciliation' | 'invalid';
92
+ readonly diagnostics: readonly string[];
93
+ readonly apply: boolean;
94
+ readonly task_root: string;
95
+ readonly task_id: string | null;
96
+ readonly plan: {
97
+ readonly ref: string;
98
+ readonly digest: string | null;
99
+ readonly plan_id: string | null;
100
+ readonly owner_epoch: number | null;
101
+ };
102
+ readonly concurrency: {
103
+ readonly limit: number;
104
+ readonly selected: number;
105
+ readonly actual_overlap: boolean;
106
+ };
107
+ readonly nodes: readonly WorkExecutionNodeResult[];
108
+ readonly reports: readonly WorkExecutionReportPointer[];
109
+ readonly acceptance: {
110
+ readonly accepted_nodes: readonly string[];
111
+ readonly awaiting_acceptance_nodes: readonly string[];
112
+ readonly rejected_nodes: readonly string[];
113
+ };
114
+ readonly limits: readonly string[];
115
+ }
116
+ export interface WorkExecutionHerdrAdapterOptions {
117
+ readonly transport?: HerdrTransport;
118
+ }
119
+ export declare function createHerdrWorkExecutionAdapter(options?: WorkExecutionHerdrAdapterOptions): WorkExecutionAdapter;
120
+ /**
121
+ * Applies one bounded batch of already assigned work. Plan mode is read-only. Apply
122
+ * persists a deterministic STATUS_QUERY intent with the existing message transaction before
123
+ * one visible notification attempt; duplicate intents are reconciliation-only.
124
+ */
125
+ export declare function runWorkExecution(options: WorkExecutionOptions, deps?: {
126
+ readonly adapter?: WorkExecutionAdapter;
127
+ }): Promise<WorkExecutionReport>;