@openrig/cli 0.1.12 → 0.2.0

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 (518) hide show
  1. package/daemon/assets/openrig-activity-hook-relay.cjs +104 -0
  2. package/daemon/dist/adapters/claude-code-adapter.d.ts +14 -6
  3. package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
  4. package/daemon/dist/adapters/claude-code-adapter.js +183 -65
  5. package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
  6. package/daemon/dist/adapters/claude-resume.d.ts +5 -0
  7. package/daemon/dist/adapters/claude-resume.d.ts.map +1 -1
  8. package/daemon/dist/adapters/claude-resume.js +13 -0
  9. package/daemon/dist/adapters/claude-resume.js.map +1 -1
  10. package/daemon/dist/adapters/codex-resume.d.ts +8 -1
  11. package/daemon/dist/adapters/codex-resume.d.ts.map +1 -1
  12. package/daemon/dist/adapters/codex-resume.js +74 -5
  13. package/daemon/dist/adapters/codex-resume.js.map +1 -1
  14. package/daemon/dist/adapters/codex-runtime-adapter.d.ts +9 -5
  15. package/daemon/dist/adapters/codex-runtime-adapter.d.ts.map +1 -1
  16. package/daemon/dist/adapters/codex-runtime-adapter.js +255 -28
  17. package/daemon/dist/adapters/codex-runtime-adapter.js.map +1 -1
  18. package/daemon/dist/adapters/terminal-adapter.d.ts +2 -1
  19. package/daemon/dist/adapters/terminal-adapter.d.ts.map +1 -1
  20. package/daemon/dist/adapters/terminal-adapter.js +7 -1
  21. package/daemon/dist/adapters/terminal-adapter.js.map +1 -1
  22. package/daemon/dist/adapters/tmux.d.ts.map +1 -1
  23. package/daemon/dist/adapters/tmux.js +53 -5
  24. package/daemon/dist/adapters/tmux.js.map +1 -1
  25. package/daemon/dist/db/migrations/021_seat_handover_observability.d.ts +3 -0
  26. package/daemon/dist/db/migrations/021_seat_handover_observability.d.ts.map +1 -0
  27. package/daemon/dist/db/migrations/021_seat_handover_observability.js +11 -0
  28. package/daemon/dist/db/migrations/021_seat_handover_observability.js.map +1 -0
  29. package/daemon/dist/db/migrations/022_node_codex_config_profile.d.ts +3 -0
  30. package/daemon/dist/db/migrations/022_node_codex_config_profile.d.ts.map +1 -0
  31. package/daemon/dist/db/migrations/022_node_codex_config_profile.js +7 -0
  32. package/daemon/dist/db/migrations/022_node_codex_config_profile.js.map +1 -0
  33. package/daemon/dist/db/migrations/023_stream_items.d.ts +16 -0
  34. package/daemon/dist/db/migrations/023_stream_items.d.ts.map +1 -0
  35. package/daemon/dist/db/migrations/023_stream_items.js +37 -0
  36. package/daemon/dist/db/migrations/023_stream_items.js.map +1 -0
  37. package/daemon/dist/db/migrations/024_queue_items.d.ts +19 -0
  38. package/daemon/dist/db/migrations/024_queue_items.d.ts.map +1 -0
  39. package/daemon/dist/db/migrations/024_queue_items.js +52 -0
  40. package/daemon/dist/db/migrations/024_queue_items.js.map +1 -0
  41. package/daemon/dist/db/migrations/025_queue_transitions.d.ts +13 -0
  42. package/daemon/dist/db/migrations/025_queue_transitions.d.ts.map +1 -0
  43. package/daemon/dist/db/migrations/025_queue_transitions.js +28 -0
  44. package/daemon/dist/db/migrations/025_queue_transitions.js.map +1 -0
  45. package/daemon/dist/db/migrations/026_inbox_entries.d.ts +14 -0
  46. package/daemon/dist/db/migrations/026_inbox_entries.d.ts.map +1 -0
  47. package/daemon/dist/db/migrations/026_inbox_entries.js +35 -0
  48. package/daemon/dist/db/migrations/026_inbox_entries.js.map +1 -0
  49. package/daemon/dist/db/migrations/027_outbox_entries.d.ts +12 -0
  50. package/daemon/dist/db/migrations/027_outbox_entries.d.ts.map +1 -0
  51. package/daemon/dist/db/migrations/027_outbox_entries.js +30 -0
  52. package/daemon/dist/db/migrations/027_outbox_entries.js.map +1 -0
  53. package/daemon/dist/db/migrations/028_project_classifications.d.ts +26 -0
  54. package/daemon/dist/db/migrations/028_project_classifications.d.ts.map +1 -0
  55. package/daemon/dist/db/migrations/028_project_classifications.js +44 -0
  56. package/daemon/dist/db/migrations/028_project_classifications.js.map +1 -0
  57. package/daemon/dist/db/migrations/029_classifier_leases.d.ts +22 -0
  58. package/daemon/dist/db/migrations/029_classifier_leases.d.ts.map +1 -0
  59. package/daemon/dist/db/migrations/029_classifier_leases.js +41 -0
  60. package/daemon/dist/db/migrations/029_classifier_leases.js.map +1 -0
  61. package/daemon/dist/db/migrations/030_views_custom.d.ts +15 -0
  62. package/daemon/dist/db/migrations/030_views_custom.d.ts.map +1 -0
  63. package/daemon/dist/db/migrations/030_views_custom.js +27 -0
  64. package/daemon/dist/db/migrations/030_views_custom.js.map +1 -0
  65. package/daemon/dist/db/migrations/031_watchdog_jobs.d.ts +34 -0
  66. package/daemon/dist/db/migrations/031_watchdog_jobs.d.ts.map +1 -0
  67. package/daemon/dist/db/migrations/031_watchdog_jobs.js +59 -0
  68. package/daemon/dist/db/migrations/031_watchdog_jobs.js.map +1 -0
  69. package/daemon/dist/db/migrations/032_watchdog_history.d.ts +28 -0
  70. package/daemon/dist/db/migrations/032_watchdog_history.d.ts.map +1 -0
  71. package/daemon/dist/db/migrations/032_watchdog_history.js +46 -0
  72. package/daemon/dist/db/migrations/032_watchdog_history.js.map +1 -0
  73. package/daemon/dist/db/migrations/033_workflow_specs.d.ts +30 -0
  74. package/daemon/dist/db/migrations/033_workflow_specs.d.ts.map +1 -0
  75. package/daemon/dist/db/migrations/033_workflow_specs.js +50 -0
  76. package/daemon/dist/db/migrations/033_workflow_specs.js.map +1 -0
  77. package/daemon/dist/db/migrations/034_workflow_instances.d.ts +42 -0
  78. package/daemon/dist/db/migrations/034_workflow_instances.d.ts.map +1 -0
  79. package/daemon/dist/db/migrations/034_workflow_instances.js +63 -0
  80. package/daemon/dist/db/migrations/034_workflow_instances.js.map +1 -0
  81. package/daemon/dist/db/migrations/035_workflow_step_trails.d.ts +29 -0
  82. package/daemon/dist/db/migrations/035_workflow_step_trails.d.ts.map +1 -0
  83. package/daemon/dist/db/migrations/035_workflow_step_trails.js +48 -0
  84. package/daemon/dist/db/migrations/035_workflow_step_trails.js.map +1 -0
  85. package/daemon/dist/db/migrations/036_watchdog_policy_enum_extension.d.ts +35 -0
  86. package/daemon/dist/db/migrations/036_watchdog_policy_enum_extension.d.ts.map +1 -0
  87. package/daemon/dist/db/migrations/036_watchdog_policy_enum_extension.js +43 -0
  88. package/daemon/dist/db/migrations/036_watchdog_policy_enum_extension.js.map +1 -0
  89. package/daemon/dist/domain/agent-activity-store.d.ts +42 -0
  90. package/daemon/dist/domain/agent-activity-store.d.ts.map +1 -0
  91. package/daemon/dist/domain/agent-activity-store.js +177 -0
  92. package/daemon/dist/domain/agent-activity-store.js.map +1 -0
  93. package/daemon/dist/domain/agent-manifest.d.ts.map +1 -1
  94. package/daemon/dist/domain/agent-manifest.js +3 -0
  95. package/daemon/dist/domain/agent-manifest.js.map +1 -1
  96. package/daemon/dist/domain/agent-starter-resolver.d.ts +100 -0
  97. package/daemon/dist/domain/agent-starter-resolver.d.ts.map +1 -0
  98. package/daemon/dist/domain/agent-starter-resolver.js +200 -0
  99. package/daemon/dist/domain/agent-starter-resolver.js.map +1 -0
  100. package/daemon/dist/domain/classifier-lease-manager.d.ts +130 -0
  101. package/daemon/dist/domain/classifier-lease-manager.d.ts.map +1 -0
  102. package/daemon/dist/domain/classifier-lease-manager.js +285 -0
  103. package/daemon/dist/domain/classifier-lease-manager.js.map +1 -0
  104. package/daemon/dist/domain/context-usage-store.d.ts +1 -1
  105. package/daemon/dist/domain/context-usage-store.js +1 -1
  106. package/daemon/dist/domain/context-usage-store.js.map +1 -1
  107. package/daemon/dist/domain/hot-potato-enforcer.d.ts +45 -0
  108. package/daemon/dist/domain/hot-potato-enforcer.d.ts.map +1 -0
  109. package/daemon/dist/domain/hot-potato-enforcer.js +94 -0
  110. package/daemon/dist/domain/hot-potato-enforcer.js.map +1 -0
  111. package/daemon/dist/domain/inbox-handler.d.ts +68 -0
  112. package/daemon/dist/domain/inbox-handler.d.ts.map +1 -0
  113. package/daemon/dist/domain/inbox-handler.js +177 -0
  114. package/daemon/dist/domain/inbox-handler.js.map +1 -0
  115. package/daemon/dist/domain/native-resume-probe.d.ts +1 -1
  116. package/daemon/dist/domain/native-resume-probe.d.ts.map +1 -1
  117. package/daemon/dist/domain/native-resume-probe.js +67 -0
  118. package/daemon/dist/domain/native-resume-probe.js.map +1 -1
  119. package/daemon/dist/domain/node-inventory.d.ts +29 -1
  120. package/daemon/dist/domain/node-inventory.d.ts.map +1 -1
  121. package/daemon/dist/domain/node-inventory.js +160 -38
  122. package/daemon/dist/domain/node-inventory.js.map +1 -1
  123. package/daemon/dist/domain/node-launcher.d.ts +2 -0
  124. package/daemon/dist/domain/node-launcher.d.ts.map +1 -1
  125. package/daemon/dist/domain/node-launcher.js +14 -2
  126. package/daemon/dist/domain/node-launcher.js.map +1 -1
  127. package/daemon/dist/domain/outbox-handler.d.ts +48 -0
  128. package/daemon/dist/domain/outbox-handler.d.ts.map +1 -0
  129. package/daemon/dist/domain/outbox-handler.js +106 -0
  130. package/daemon/dist/domain/outbox-handler.js.map +1 -0
  131. package/daemon/dist/domain/policies/artifact-pool-helpers.d.ts +64 -0
  132. package/daemon/dist/domain/policies/artifact-pool-helpers.d.ts.map +1 -0
  133. package/daemon/dist/domain/policies/artifact-pool-helpers.js +226 -0
  134. package/daemon/dist/domain/policies/artifact-pool-helpers.js.map +1 -0
  135. package/daemon/dist/domain/policies/artifact-pool-ready.d.ts +3 -0
  136. package/daemon/dist/domain/policies/artifact-pool-ready.d.ts.map +1 -0
  137. package/daemon/dist/domain/policies/artifact-pool-ready.js +41 -0
  138. package/daemon/dist/domain/policies/artifact-pool-ready.js.map +1 -0
  139. package/daemon/dist/domain/policies/edge-artifact-required.d.ts +3 -0
  140. package/daemon/dist/domain/policies/edge-artifact-required.d.ts.map +1 -0
  141. package/daemon/dist/domain/policies/edge-artifact-required.js +90 -0
  142. package/daemon/dist/domain/policies/edge-artifact-required.js.map +1 -0
  143. package/daemon/dist/domain/policies/periodic-reminder.d.ts +3 -0
  144. package/daemon/dist/domain/policies/periodic-reminder.d.ts.map +1 -0
  145. package/daemon/dist/domain/policies/periodic-reminder.js +30 -0
  146. package/daemon/dist/domain/policies/periodic-reminder.js.map +1 -0
  147. package/daemon/dist/domain/policies/types.d.ts +51 -0
  148. package/daemon/dist/domain/policies/types.d.ts.map +1 -0
  149. package/daemon/dist/domain/policies/types.js +9 -0
  150. package/daemon/dist/domain/policies/types.js.map +1 -0
  151. package/daemon/dist/domain/policies/workflow-keepalive.d.ts +7 -0
  152. package/daemon/dist/domain/policies/workflow-keepalive.d.ts.map +1 -0
  153. package/daemon/dist/domain/policies/workflow-keepalive.js +123 -0
  154. package/daemon/dist/domain/policies/workflow-keepalive.js.map +1 -0
  155. package/daemon/dist/domain/project-classifier.d.ts +75 -0
  156. package/daemon/dist/domain/project-classifier.d.ts.map +1 -0
  157. package/daemon/dist/domain/project-classifier.js +132 -0
  158. package/daemon/dist/domain/project-classifier.js.map +1 -0
  159. package/daemon/dist/domain/projection-planner.d.ts +1 -0
  160. package/daemon/dist/domain/projection-planner.d.ts.map +1 -1
  161. package/daemon/dist/domain/projection-planner.js +3 -0
  162. package/daemon/dist/domain/projection-planner.js.map +1 -1
  163. package/daemon/dist/domain/ps-projection.d.ts +31 -0
  164. package/daemon/dist/domain/ps-projection.d.ts.map +1 -1
  165. package/daemon/dist/domain/ps-projection.js +38 -0
  166. package/daemon/dist/domain/ps-projection.js.map +1 -1
  167. package/daemon/dist/domain/queue-repository.d.ts +322 -0
  168. package/daemon/dist/domain/queue-repository.d.ts.map +1 -0
  169. package/daemon/dist/domain/queue-repository.js +686 -0
  170. package/daemon/dist/domain/queue-repository.js.map +1 -0
  171. package/daemon/dist/domain/queue-transition-log.d.ts +38 -0
  172. package/daemon/dist/domain/queue-transition-log.d.ts.map +1 -0
  173. package/daemon/dist/domain/queue-transition-log.js +52 -0
  174. package/daemon/dist/domain/queue-transition-log.js.map +1 -0
  175. package/daemon/dist/domain/restore-check-service.d.ts +203 -0
  176. package/daemon/dist/domain/restore-check-service.d.ts.map +1 -0
  177. package/daemon/dist/domain/restore-check-service.js +1047 -0
  178. package/daemon/dist/domain/restore-check-service.js.map +1 -0
  179. package/daemon/dist/domain/restore-orchestrator.d.ts +49 -3
  180. package/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
  181. package/daemon/dist/domain/restore-orchestrator.js +460 -62
  182. package/daemon/dist/domain/restore-orchestrator.js.map +1 -1
  183. package/daemon/dist/domain/rig-expansion-service.d.ts.map +1 -1
  184. package/daemon/dist/domain/rig-expansion-service.js +13 -0
  185. package/daemon/dist/domain/rig-expansion-service.js.map +1 -1
  186. package/daemon/dist/domain/rig-repository.d.ts +17 -1
  187. package/daemon/dist/domain/rig-repository.d.ts.map +1 -1
  188. package/daemon/dist/domain/rig-repository.js +63 -5
  189. package/daemon/dist/domain/rig-repository.js.map +1 -1
  190. package/daemon/dist/domain/rigspec-codec.d.ts.map +1 -1
  191. package/daemon/dist/domain/rigspec-codec.js +13 -0
  192. package/daemon/dist/domain/rigspec-codec.js.map +1 -1
  193. package/daemon/dist/domain/rigspec-exporter.d.ts.map +1 -1
  194. package/daemon/dist/domain/rigspec-exporter.js +2 -0
  195. package/daemon/dist/domain/rigspec-exporter.js.map +1 -1
  196. package/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
  197. package/daemon/dist/domain/rigspec-instantiator.js +61 -1
  198. package/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
  199. package/daemon/dist/domain/rigspec-schema.d.ts.map +1 -1
  200. package/daemon/dist/domain/rigspec-schema.js +196 -0
  201. package/daemon/dist/domain/rigspec-schema.js.map +1 -1
  202. package/daemon/dist/domain/runtime-adapter.d.ts +27 -2
  203. package/daemon/dist/domain/runtime-adapter.d.ts.map +1 -1
  204. package/daemon/dist/domain/runtime-adapter.js +5 -0
  205. package/daemon/dist/domain/runtime-adapter.js.map +1 -1
  206. package/daemon/dist/domain/seat-handover-planner.d.ts +84 -0
  207. package/daemon/dist/domain/seat-handover-planner.d.ts.map +1 -0
  208. package/daemon/dist/domain/seat-handover-planner.js +188 -0
  209. package/daemon/dist/domain/seat-handover-planner.js.map +1 -0
  210. package/daemon/dist/domain/seat-handover-service.d.ts +104 -0
  211. package/daemon/dist/domain/seat-handover-service.d.ts.map +1 -0
  212. package/daemon/dist/domain/seat-handover-service.js +343 -0
  213. package/daemon/dist/domain/seat-handover-service.js.map +1 -0
  214. package/daemon/dist/domain/seat-status-service.d.ts +50 -0
  215. package/daemon/dist/domain/seat-status-service.d.ts.map +1 -0
  216. package/daemon/dist/domain/seat-status-service.js +66 -0
  217. package/daemon/dist/domain/seat-status-service.js.map +1 -0
  218. package/daemon/dist/domain/session-source-rebuild-resolver.d.ts +53 -0
  219. package/daemon/dist/domain/session-source-rebuild-resolver.d.ts.map +1 -0
  220. package/daemon/dist/domain/session-source-rebuild-resolver.js +59 -0
  221. package/daemon/dist/domain/session-source-rebuild-resolver.js.map +1 -0
  222. package/daemon/dist/domain/session-transport.d.ts +30 -0
  223. package/daemon/dist/domain/session-transport.d.ts.map +1 -1
  224. package/daemon/dist/domain/session-transport.js +322 -12
  225. package/daemon/dist/domain/session-transport.js.map +1 -1
  226. package/daemon/dist/domain/snapshot-repository.d.ts +18 -0
  227. package/daemon/dist/domain/snapshot-repository.d.ts.map +1 -1
  228. package/daemon/dist/domain/snapshot-repository.js +77 -0
  229. package/daemon/dist/domain/snapshot-repository.js.map +1 -1
  230. package/daemon/dist/domain/startup-orchestrator.d.ts +22 -3
  231. package/daemon/dist/domain/startup-orchestrator.d.ts.map +1 -1
  232. package/daemon/dist/domain/startup-orchestrator.js +31 -5
  233. package/daemon/dist/domain/startup-orchestrator.js.map +1 -1
  234. package/daemon/dist/domain/stream-store.d.ts +56 -0
  235. package/daemon/dist/domain/stream-store.d.ts.map +1 -0
  236. package/daemon/dist/domain/stream-store.js +108 -0
  237. package/daemon/dist/domain/stream-store.js.map +1 -0
  238. package/daemon/dist/domain/transcript-redaction.d.ts +13 -0
  239. package/daemon/dist/domain/transcript-redaction.d.ts.map +1 -0
  240. package/daemon/dist/domain/transcript-redaction.js +34 -0
  241. package/daemon/dist/domain/transcript-redaction.js.map +1 -0
  242. package/daemon/dist/domain/transcript-store.d.ts +15 -0
  243. package/daemon/dist/domain/transcript-store.d.ts.map +1 -1
  244. package/daemon/dist/domain/transcript-store.js +57 -1
  245. package/daemon/dist/domain/transcript-store.js.map +1 -1
  246. package/daemon/dist/domain/types.d.ts +316 -3
  247. package/daemon/dist/domain/types.d.ts.map +1 -1
  248. package/daemon/dist/domain/view-event-bridge.d.ts +12 -0
  249. package/daemon/dist/domain/view-event-bridge.d.ts.map +1 -0
  250. package/daemon/dist/domain/view-event-bridge.js +92 -0
  251. package/daemon/dist/domain/view-event-bridge.js.map +1 -0
  252. package/daemon/dist/domain/view-projector.d.ts +83 -0
  253. package/daemon/dist/domain/view-projector.d.ts.map +1 -0
  254. package/daemon/dist/domain/view-projector.js +296 -0
  255. package/daemon/dist/domain/view-projector.js.map +1 -0
  256. package/daemon/dist/domain/watchdog-history-log.d.ts +49 -0
  257. package/daemon/dist/domain/watchdog-history-log.d.ts.map +1 -0
  258. package/daemon/dist/domain/watchdog-history-log.js +67 -0
  259. package/daemon/dist/domain/watchdog-history-log.js.map +1 -0
  260. package/daemon/dist/domain/watchdog-jobs-repository.d.ts +81 -0
  261. package/daemon/dist/domain/watchdog-jobs-repository.d.ts.map +1 -0
  262. package/daemon/dist/domain/watchdog-jobs-repository.js +164 -0
  263. package/daemon/dist/domain/watchdog-jobs-repository.js.map +1 -0
  264. package/daemon/dist/domain/watchdog-policy-engine.d.ts +92 -0
  265. package/daemon/dist/domain/watchdog-policy-engine.d.ts.map +1 -0
  266. package/daemon/dist/domain/watchdog-policy-engine.js +442 -0
  267. package/daemon/dist/domain/watchdog-policy-engine.js.map +1 -0
  268. package/daemon/dist/domain/watchdog-scheduler.d.ts +76 -0
  269. package/daemon/dist/domain/watchdog-scheduler.d.ts.map +1 -0
  270. package/daemon/dist/domain/watchdog-scheduler.js +112 -0
  271. package/daemon/dist/domain/watchdog-scheduler.js.map +1 -0
  272. package/daemon/dist/domain/workflow-instance-store.d.ts +46 -0
  273. package/daemon/dist/domain/workflow-instance-store.d.ts.map +1 -0
  274. package/daemon/dist/domain/workflow-instance-store.js +116 -0
  275. package/daemon/dist/domain/workflow-instance-store.js.map +1 -0
  276. package/daemon/dist/domain/workflow-projector.d.ts +64 -0
  277. package/daemon/dist/domain/workflow-projector.d.ts.map +1 -0
  278. package/daemon/dist/domain/workflow-projector.js +424 -0
  279. package/daemon/dist/domain/workflow-projector.js.map +1 -0
  280. package/daemon/dist/domain/workflow-runtime.d.ts +63 -0
  281. package/daemon/dist/domain/workflow-runtime.d.ts.map +1 -0
  282. package/daemon/dist/domain/workflow-runtime.js +150 -0
  283. package/daemon/dist/domain/workflow-runtime.js.map +1 -0
  284. package/daemon/dist/domain/workflow-spec-cache.d.ts +35 -0
  285. package/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -0
  286. package/daemon/dist/domain/workflow-spec-cache.js +171 -0
  287. package/daemon/dist/domain/workflow-spec-cache.js.map +1 -0
  288. package/daemon/dist/domain/workflow-step-trail-log.d.ts +27 -0
  289. package/daemon/dist/domain/workflow-step-trail-log.d.ts.map +1 -0
  290. package/daemon/dist/domain/workflow-step-trail-log.js +73 -0
  291. package/daemon/dist/domain/workflow-step-trail-log.js.map +1 -0
  292. package/daemon/dist/domain/workflow-types.d.ts +108 -0
  293. package/daemon/dist/domain/workflow-types.d.ts.map +1 -0
  294. package/daemon/dist/domain/workflow-types.js +11 -0
  295. package/daemon/dist/domain/workflow-types.js.map +1 -0
  296. package/daemon/dist/domain/workflow-validator.d.ts +31 -0
  297. package/daemon/dist/domain/workflow-validator.d.ts.map +1 -0
  298. package/daemon/dist/domain/workflow-validator.js +115 -0
  299. package/daemon/dist/domain/workflow-validator.js.map +1 -0
  300. package/daemon/dist/index.d.ts.map +1 -1
  301. package/daemon/dist/index.js +21 -2
  302. package/daemon/dist/index.js.map +1 -1
  303. package/daemon/dist/routes/activity.d.ts +3 -0
  304. package/daemon/dist/routes/activity.d.ts.map +1 -0
  305. package/daemon/dist/routes/activity.js +47 -0
  306. package/daemon/dist/routes/activity.js.map +1 -0
  307. package/daemon/dist/routes/projects.d.ts +12 -0
  308. package/daemon/dist/routes/projects.d.ts.map +1 -0
  309. package/daemon/dist/routes/projects.js +178 -0
  310. package/daemon/dist/routes/projects.js.map +1 -0
  311. package/daemon/dist/routes/queue.d.ts +10 -0
  312. package/daemon/dist/routes/queue.d.ts.map +1 -0
  313. package/daemon/dist/routes/queue.js +374 -0
  314. package/daemon/dist/routes/queue.js.map +1 -0
  315. package/daemon/dist/routes/restore-check.d.ts +3 -0
  316. package/daemon/dist/routes/restore-check.d.ts.map +1 -0
  317. package/daemon/dist/routes/restore-check.js +200 -0
  318. package/daemon/dist/routes/restore-check.js.map +1 -0
  319. package/daemon/dist/routes/rigs.d.ts.map +1 -1
  320. package/daemon/dist/routes/rigs.js +60 -4
  321. package/daemon/dist/routes/rigs.js.map +1 -1
  322. package/daemon/dist/routes/seat.d.ts +3 -0
  323. package/daemon/dist/routes/seat.d.ts.map +1 -0
  324. package/daemon/dist/routes/seat.js +69 -0
  325. package/daemon/dist/routes/seat.js.map +1 -0
  326. package/daemon/dist/routes/sessions.d.ts.map +1 -1
  327. package/daemon/dist/routes/sessions.js +25 -4
  328. package/daemon/dist/routes/sessions.js.map +1 -1
  329. package/daemon/dist/routes/snapshots.js +66 -29
  330. package/daemon/dist/routes/snapshots.js.map +1 -1
  331. package/daemon/dist/routes/stream.d.ts +9 -0
  332. package/daemon/dist/routes/stream.d.ts.map +1 -0
  333. package/daemon/dist/routes/stream.js +119 -0
  334. package/daemon/dist/routes/stream.js.map +1 -0
  335. package/daemon/dist/routes/transcripts.d.ts.map +1 -1
  336. package/daemon/dist/routes/transcripts.js +38 -0
  337. package/daemon/dist/routes/transcripts.js.map +1 -1
  338. package/daemon/dist/routes/transport.d.ts.map +1 -1
  339. package/daemon/dist/routes/transport.js +21 -0
  340. package/daemon/dist/routes/transport.js.map +1 -1
  341. package/daemon/dist/routes/up.js +24 -3
  342. package/daemon/dist/routes/up.js.map +1 -1
  343. package/daemon/dist/routes/views.d.ts +13 -0
  344. package/daemon/dist/routes/views.d.ts.map +1 -0
  345. package/daemon/dist/routes/views.js +120 -0
  346. package/daemon/dist/routes/views.js.map +1 -0
  347. package/daemon/dist/routes/watchdog.d.ts +18 -0
  348. package/daemon/dist/routes/watchdog.d.ts.map +1 -0
  349. package/daemon/dist/routes/watchdog.js +148 -0
  350. package/daemon/dist/routes/watchdog.js.map +1 -0
  351. package/daemon/dist/routes/workflow.d.ts +20 -0
  352. package/daemon/dist/routes/workflow.d.ts.map +1 -0
  353. package/daemon/dist/routes/workflow.js +184 -0
  354. package/daemon/dist/routes/workflow.js.map +1 -0
  355. package/daemon/dist/server.d.ts +30 -0
  356. package/daemon/dist/server.d.ts.map +1 -1
  357. package/daemon/dist/server.js +33 -0
  358. package/daemon/dist/server.js.map +1 -1
  359. package/daemon/dist/startup.d.ts.map +1 -1
  360. package/daemon/dist/startup.js +202 -8
  361. package/daemon/dist/startup.js.map +1 -1
  362. package/daemon/docs/reference/agent-spec.md +12 -5
  363. package/daemon/docs/reference/agent-startup-guide.md +9 -9
  364. package/daemon/specs/agents/apps/vault-specialist/agent.yaml +1 -1
  365. package/daemon/specs/agents/design/product-designer/agent.yaml +1 -1
  366. package/daemon/specs/agents/development/implementer/agent.yaml +1 -1
  367. package/daemon/specs/agents/development/qa/agent.yaml +1 -1
  368. package/daemon/specs/agents/orchestration/orchestrator/agent.yaml +1 -1
  369. package/daemon/specs/agents/product-management/pm/agent.yaml +4 -0
  370. package/daemon/specs/agents/research/analyst/agent.yaml +1 -1
  371. package/daemon/specs/agents/research/synthesizer/agent.yaml +1 -1
  372. package/daemon/specs/agents/review/independent-reviewer/agent.yaml +1 -1
  373. package/daemon/specs/agents/shared/agent.yaml +17 -0
  374. package/daemon/specs/agents/shared/runtime/claude-mcp.fragment.json +12 -0
  375. package/daemon/specs/agents/shared/runtime/claude-settings.fragment.json +16 -0
  376. package/daemon/specs/agents/shared/runtime/codex-config.fragment.toml +5 -0
  377. package/daemon/specs/agents/shared/skills/claude-compact-in-place/SKILL.md +100 -0
  378. package/daemon/specs/agents/shared/skills/core/openrig-operator/SKILL.md +110 -0
  379. package/daemon/specs/agents/shared/skills/core/openrig-user/SKILL.md +44 -1
  380. package/daemon/specs/agents/shared/skills/mental-model-ha/SKILL.md +3 -0
  381. package/daemon/specs/agents/shared/skills/pods/orchestration-team/SKILL.md +3 -0
  382. package/daemon/specs/agents/shared/skills/rig-architect/SKILL.md +11 -1
  383. package/dist/bin-wrapper.js +0 -0
  384. package/dist/commands/capture.d.ts +7 -1
  385. package/dist/commands/capture.d.ts.map +1 -1
  386. package/dist/commands/capture.js +59 -1
  387. package/dist/commands/capture.js.map +1 -1
  388. package/dist/commands/compact-plan.d.ts +9 -0
  389. package/dist/commands/compact-plan.d.ts.map +1 -0
  390. package/dist/commands/compact-plan.js +354 -0
  391. package/dist/commands/compact-plan.js.map +1 -0
  392. package/dist/commands/context.d.ts +9 -0
  393. package/dist/commands/context.d.ts.map +1 -0
  394. package/dist/commands/context.js +220 -0
  395. package/dist/commands/context.js.map +1 -0
  396. package/dist/commands/expand.d.ts.map +1 -1
  397. package/dist/commands/expand.js +15 -4
  398. package/dist/commands/expand.js.map +1 -1
  399. package/dist/commands/heartbeat.d.ts +99 -0
  400. package/dist/commands/heartbeat.d.ts.map +1 -0
  401. package/dist/commands/heartbeat.js +393 -0
  402. package/dist/commands/heartbeat.js.map +1 -0
  403. package/dist/commands/project.d.ts +14 -0
  404. package/dist/commands/project.d.ts.map +1 -0
  405. package/dist/commands/project.js +157 -0
  406. package/dist/commands/project.js.map +1 -0
  407. package/dist/commands/ps.d.ts +20 -3
  408. package/dist/commands/ps.d.ts.map +1 -1
  409. package/dist/commands/ps.js +455 -33
  410. package/dist/commands/ps.js.map +1 -1
  411. package/dist/commands/queue.d.ts +16 -0
  412. package/dist/commands/queue.d.ts.map +1 -0
  413. package/dist/commands/queue.js +401 -0
  414. package/dist/commands/queue.js.map +1 -0
  415. package/dist/commands/restore-check.d.ts +9 -0
  416. package/dist/commands/restore-check.d.ts.map +1 -0
  417. package/dist/commands/restore-check.js +234 -0
  418. package/dist/commands/restore-check.js.map +1 -0
  419. package/dist/commands/restore-packet.d.ts +9 -0
  420. package/dist/commands/restore-packet.d.ts.map +1 -0
  421. package/dist/commands/restore-packet.js +383 -0
  422. package/dist/commands/restore-packet.js.map +1 -0
  423. package/dist/commands/restore.d.ts.map +1 -1
  424. package/dist/commands/restore.js +44 -1
  425. package/dist/commands/restore.js.map +1 -1
  426. package/dist/commands/seat.d.ts +5 -0
  427. package/dist/commands/seat.d.ts.map +1 -0
  428. package/dist/commands/seat.js +170 -0
  429. package/dist/commands/seat.js.map +1 -0
  430. package/dist/commands/send.d.ts +12 -1
  431. package/dist/commands/send.d.ts.map +1 -1
  432. package/dist/commands/send.js +93 -5
  433. package/dist/commands/send.js.map +1 -1
  434. package/dist/commands/setup.js +3 -3
  435. package/dist/commands/setup.js.map +1 -1
  436. package/dist/commands/specs.d.ts.map +1 -1
  437. package/dist/commands/specs.js +99 -16
  438. package/dist/commands/specs.js.map +1 -1
  439. package/dist/commands/stream.d.ts +12 -0
  440. package/dist/commands/stream.d.ts.map +1 -0
  441. package/dist/commands/stream.js +111 -0
  442. package/dist/commands/stream.js.map +1 -0
  443. package/dist/commands/up.d.ts.map +1 -1
  444. package/dist/commands/up.js +63 -3
  445. package/dist/commands/up.js.map +1 -1
  446. package/dist/commands/view.d.ts +12 -0
  447. package/dist/commands/view.d.ts.map +1 -0
  448. package/dist/commands/view.js +82 -0
  449. package/dist/commands/view.js.map +1 -0
  450. package/dist/commands/watchdog.d.ts +15 -0
  451. package/dist/commands/watchdog.d.ts.map +1 -0
  452. package/dist/commands/watchdog.js +120 -0
  453. package/dist/commands/watchdog.js.map +1 -0
  454. package/dist/commands/whoami.d.ts +8 -1
  455. package/dist/commands/whoami.d.ts.map +1 -1
  456. package/dist/commands/whoami.js +60 -1
  457. package/dist/commands/whoami.js.map +1 -1
  458. package/dist/commands/workflow.d.ts +17 -0
  459. package/dist/commands/workflow.d.ts.map +1 -0
  460. package/dist/commands/workflow.js +138 -0
  461. package/dist/commands/workflow.js.map +1 -0
  462. package/dist/cross-host-cli-helpers.d.ts +12 -0
  463. package/dist/cross-host-cli-helpers.d.ts.map +1 -0
  464. package/dist/cross-host-cli-helpers.js +48 -0
  465. package/dist/cross-host-cli-helpers.js.map +1 -0
  466. package/dist/cross-host-executor.d.ts +84 -0
  467. package/dist/cross-host-executor.d.ts.map +1 -0
  468. package/dist/cross-host-executor.js +138 -0
  469. package/dist/cross-host-executor.js.map +1 -0
  470. package/dist/host-registry.d.ts +50 -0
  471. package/dist/host-registry.d.ts.map +1 -0
  472. package/dist/host-registry.js +116 -0
  473. package/dist/host-registry.js.map +1 -0
  474. package/dist/index.d.ts +20 -0
  475. package/dist/index.d.ts.map +1 -1
  476. package/dist/index.js +24 -0
  477. package/dist/index.js.map +1 -1
  478. package/dist/mcp-server.d.ts.map +1 -1
  479. package/dist/mcp-server.js +22 -2
  480. package/dist/mcp-server.js.map +1 -1
  481. package/dist/restore-packet/claude-transcript-parser.d.ts +12 -0
  482. package/dist/restore-packet/claude-transcript-parser.d.ts.map +1 -0
  483. package/dist/restore-packet/claude-transcript-parser.js +221 -0
  484. package/dist/restore-packet/claude-transcript-parser.js.map +1 -0
  485. package/dist/restore-packet/codex-jsonl-parser.d.ts +11 -0
  486. package/dist/restore-packet/codex-jsonl-parser.d.ts.map +1 -0
  487. package/dist/restore-packet/codex-jsonl-parser.js +159 -0
  488. package/dist/restore-packet/codex-jsonl-parser.js.map +1 -0
  489. package/dist/restore-packet/omitted-records.d.ts +60 -0
  490. package/dist/restore-packet/omitted-records.d.ts.map +1 -0
  491. package/dist/restore-packet/omitted-records.js +116 -0
  492. package/dist/restore-packet/omitted-records.js.map +1 -0
  493. package/dist/restore-packet/packet-writer.d.ts +59 -0
  494. package/dist/restore-packet/packet-writer.d.ts.map +1 -0
  495. package/dist/restore-packet/packet-writer.js +224 -0
  496. package/dist/restore-packet/packet-writer.js.map +1 -0
  497. package/dist/restore-packet/redaction.d.ts +30 -0
  498. package/dist/restore-packet/redaction.d.ts.map +1 -0
  499. package/dist/restore-packet/redaction.js +71 -0
  500. package/dist/restore-packet/redaction.js.map +1 -0
  501. package/dist/restore-packet/runtime-detect.d.ts +19 -0
  502. package/dist/restore-packet/runtime-detect.d.ts.map +1 -0
  503. package/dist/restore-packet/runtime-detect.js +81 -0
  504. package/dist/restore-packet/runtime-detect.js.map +1 -0
  505. package/dist/restore-packet/schema-validator.d.ts +13 -0
  506. package/dist/restore-packet/schema-validator.d.ts.map +1 -0
  507. package/dist/restore-packet/schema-validator.js +245 -0
  508. package/dist/restore-packet/schema-validator.js.map +1 -0
  509. package/dist/restore-packet/types.d.ts +76 -0
  510. package/dist/restore-packet/types.d.ts.map +1 -0
  511. package/dist/restore-packet/types.js +15 -0
  512. package/dist/restore-packet/types.js.map +1 -0
  513. package/dist/schemas/restore-summary.schema.json +98 -0
  514. package/package.json +10 -3
  515. package/scripts/check-abi.mjs +123 -0
  516. package/ui/dist/assets/{index-DlMH-REm.css → index-Dec25siz.css} +1 -1
  517. package/ui/dist/assets/{index-Ccd-jwRN.js → index-GNYaWmBj.js} +2 -2
  518. package/ui/dist/index.html +2 -2
@@ -0,0 +1,1047 @@
1
+ import { accessSync, constants } from "node:fs";
2
+ import { isAbsolute, join, relative } from "node:path";
3
+ import { getCompatibleOpenRigPath } from "../openrig-compat.js";
4
+ // --- Service ---
5
+ const DAEMON_HEALTHY_PATTERN = /^Daemon running\b/m;
6
+ const CLAUDE_SESSION_START_COMPACT_COMMAND = "/Users/wrandom/code/substrate/shared-docs/control-plane/services/claude-hooks/bin/session-start-compact-context.sh";
7
+ const CLAUDE_USER_PROMPT_SUBMIT_COMMAND = "/Users/wrandom/code/substrate/shared-docs/control-plane/services/claude-hooks/bin/userpromptsubmit-queue-attention.sh";
8
+ const CLAUDE_HOOK_FRAGMENT_PATH = "/Users/wrandom/code/substrate/shared-docs/control-plane/services/claude-hooks/config/settings.fragment.json";
9
+ export class RestoreCheckService {
10
+ deps;
11
+ constructor(deps) {
12
+ this.deps = deps;
13
+ }
14
+ check(opts) {
15
+ const checks = [];
16
+ const rigRollupInputs = [];
17
+ const recoveryRigInputs = [];
18
+ // Host-level checks — daemon probe throw produces unknown (not not_restorable).
19
+ // Daemon definitely-down (healthy=false, negative text) is red/not_restorable.
20
+ // Daemon probe exception (socket unavailable, etc.) is unknown.
21
+ const daemonCheck = this.checkDaemonReachable();
22
+ if (daemonCheck === null) {
23
+ // Probe threw — state is uninspectable
24
+ return this.buildUnknown([
25
+ { check: "daemon.reachable", status: "red", evidence: "Daemon health probe failed (unable to determine state)", remediation: "Start the daemon with: rig daemon start",
26
+ remediationSafe: false },
27
+ ]);
28
+ }
29
+ checks.push(daemonCheck);
30
+ checks.push(this.checkStateDirWritable());
31
+ const hostInfraCheck = this.checkHostInfraDeclaration();
32
+ checks.push(hostInfraCheck.check);
33
+ // Get rigs — probe error produces unknown, not not_restorable
34
+ let rigs;
35
+ try {
36
+ rigs = this.deps.listRigs();
37
+ }
38
+ catch (err) {
39
+ return this.buildUnknown([
40
+ ...checks,
41
+ { check: "probe.error", status: "red", evidence: `Failed to list rigs: ${err instanceof Error ? err.message : String(err)}`, remediation: "Check daemon status with: rig daemon status", remediationSafe: true },
42
+ ]);
43
+ }
44
+ if (opts.rig) {
45
+ rigs = rigs.filter((r) => r.name === opts.rig);
46
+ if (rigs.length === 0) {
47
+ return this.buildResult([
48
+ ...checks,
49
+ { check: `rig.${opts.rig}.exists`, status: "red", evidence: `Rig "${opts.rig}" not found`, remediation: "List rigs with: rig ps", remediationSafe: true },
50
+ ], [], hostInfraCheck.hostInfra);
51
+ }
52
+ }
53
+ // Per-rig checks
54
+ for (const rig of rigs) {
55
+ const rigChecks = [];
56
+ const snapshotCheck = this.checkSnapshot(rig);
57
+ checks.push(snapshotCheck);
58
+ rigChecks.push(snapshotCheck);
59
+ // Rig spec/root check
60
+ const specCheck = this.checkSpecPresent(rig);
61
+ checks.push(specCheck);
62
+ rigChecks.push(specCheck);
63
+ // Per-seat checks — probe error produces unknown, not not_restorable
64
+ let nodes;
65
+ try {
66
+ nodes = this.deps.getNodeInventory(rig.rigId);
67
+ }
68
+ catch (err) {
69
+ return this.buildUnknown([
70
+ ...checks,
71
+ { check: "probe.error", status: "red", evidence: `Failed to get node inventory for ${rig.name}: ${err instanceof Error ? err.message : String(err)}`, remediation: "Check daemon status" },
72
+ ]);
73
+ }
74
+ for (const node of nodes) {
75
+ const readinessCheck = this.checkSeatReadiness(node);
76
+ checks.push(readinessCheck);
77
+ rigChecks.push(readinessCheck);
78
+ const startupContextCheck = this.checkStartupContext(node);
79
+ if ("unknownChecks" in startupContextCheck) {
80
+ return this.buildUnknown([
81
+ ...checks,
82
+ ...startupContextCheck.unknownChecks,
83
+ ]);
84
+ }
85
+ checks.push(startupContextCheck.check);
86
+ rigChecks.push(startupContextCheck.check);
87
+ const transcriptCheck = this.checkTranscript(rig.name, node);
88
+ checks.push(transcriptCheck);
89
+ rigChecks.push(transcriptCheck);
90
+ const resumeCheck = this.checkResumePath(node);
91
+ checks.push(resumeCheck);
92
+ rigChecks.push(resumeCheck);
93
+ if (!opts.noQueue) {
94
+ const queueCheck = this.checkQueueFile(rig.name, node);
95
+ checks.push(queueCheck);
96
+ rigChecks.push(queueCheck);
97
+ }
98
+ if (!opts.noHooks) {
99
+ const hooksCheck = this.checkHooks(node);
100
+ checks.push(hooksCheck);
101
+ rigChecks.push(hooksCheck);
102
+ }
103
+ }
104
+ rigRollupInputs.push({ rig, nodes, checks: rigChecks });
105
+ }
106
+ const rigRollups = rigRollupInputs.map((input) => this.buildRigRollup(input));
107
+ for (const rollup of rigRollups) {
108
+ const latestSnapshot = this.inspectLatestSnapshot(rollup.rigId);
109
+ recoveryRigInputs.push({
110
+ rigId: rollup.rigId,
111
+ rigName: rollup.rigName,
112
+ expectedNodes: rollup.expectedNodes,
113
+ runningReadyNodes: rollup.runningReadyNodes,
114
+ blockingChecks: rollup.blockingChecks,
115
+ latestSnapshot: latestSnapshot.snapshot,
116
+ snapshotLookupError: latestSnapshot.error,
117
+ });
118
+ }
119
+ return this.buildResult(checks, rigRollups, hostInfraCheck.hostInfra, recoveryRigInputs);
120
+ }
121
+ /** Returns CheckEntry on success/definite-down; null on probe exception
122
+ * (uninspectable state → caller should produce verdict: unknown). */
123
+ checkDaemonReachable() {
124
+ try {
125
+ const probe = this.deps.probeDaemonHealth();
126
+ // Anchored positive match: only "Daemon running" at line start is green.
127
+ // Anything else (including "Daemon not running", empty output, or text
128
+ // that contains "running" non-anchored) is red. This preserves the
129
+ // reviewer fix from prototype 0e2af8d.
130
+ if (probe.healthy && DAEMON_HEALTHY_PATTERN.test(probe.evidence)) {
131
+ return { check: "daemon.reachable", status: "green", evidence: probe.evidence, remediation: "" };
132
+ }
133
+ return {
134
+ check: "daemon.reachable", status: "red",
135
+ evidence: probe.evidence || "Daemon health probe returned non-positive result",
136
+ remediation: "Start the daemon with: rig daemon start",
137
+ remediationSafe: false,
138
+ };
139
+ }
140
+ catch {
141
+ // Probe threw — return null to signal uninspectable state
142
+ return null;
143
+ }
144
+ }
145
+ checkStateDirWritable() {
146
+ const stateDir = getCompatibleOpenRigPath("");
147
+ try {
148
+ // Non-mutating permission probe — no file creation/deletion.
149
+ // accessSync throws if the directory is not writable.
150
+ accessSync(stateDir, constants.W_OK);
151
+ return { check: "host.state-dir-writable", status: "green", evidence: `${stateDir} is writable`, remediation: "" };
152
+ }
153
+ catch {
154
+ return {
155
+ check: "host.state-dir-writable", status: "red",
156
+ evidence: `${stateDir} is not writable`,
157
+ remediation: `Fix permissions: chmod u+w ${stateDir}`,
158
+ remediationSafe: false,
159
+ };
160
+ }
161
+ }
162
+ checkHostInfraDeclaration() {
163
+ const declarationPath = getCompatibleOpenRigPath("host-infra.json");
164
+ const check = "host.bootstrap-autostart.declaration";
165
+ try {
166
+ if (!this.deps.exists(declarationPath)) {
167
+ const evidence = `Host infra declaration missing at ${declarationPath}`;
168
+ return {
169
+ check: {
170
+ check,
171
+ status: "yellow",
172
+ evidence,
173
+ remediation: `Create host infra declaration at ${declarationPath}`,
174
+ remediationSafe: false,
175
+ },
176
+ hostInfra: {
177
+ status: "not_declared",
178
+ evidence,
179
+ },
180
+ };
181
+ }
182
+ let raw;
183
+ try {
184
+ raw = this.deps.readFile(declarationPath);
185
+ }
186
+ catch (err) {
187
+ const evidence = `Host infra declaration inspection failed at ${declarationPath}: ${err instanceof Error ? err.message : String(err)}`;
188
+ return {
189
+ check: {
190
+ check,
191
+ status: "yellow",
192
+ evidence,
193
+ remediation: `Inspect or fix host infra declaration at ${declarationPath}`,
194
+ remediationSafe: false,
195
+ },
196
+ hostInfra: {
197
+ status: "unknown",
198
+ evidence,
199
+ },
200
+ };
201
+ }
202
+ let parsed;
203
+ try {
204
+ parsed = JSON.parse(raw);
205
+ }
206
+ catch (err) {
207
+ const evidence = `Host infra declaration JSON parse failed at ${declarationPath}: ${err instanceof Error ? err.message : String(err)}`;
208
+ return {
209
+ check: {
210
+ check,
211
+ status: "yellow",
212
+ evidence,
213
+ remediation: `Fix host infra declaration JSON at ${declarationPath}`,
214
+ remediationSafe: false,
215
+ },
216
+ hostInfra: {
217
+ status: "not_declared",
218
+ evidence,
219
+ },
220
+ };
221
+ }
222
+ const validation = this.validateHostInfraDeclaration(parsed);
223
+ if (validation.errors.length > 0) {
224
+ const evidence = `Invalid host infra declaration at ${declarationPath}: missing/invalid ${validation.errors.join(", ")}`;
225
+ return {
226
+ check: {
227
+ check,
228
+ status: "yellow",
229
+ evidence,
230
+ remediation: `Fix host infra declaration shape at ${declarationPath}`,
231
+ remediationSafe: false,
232
+ },
233
+ hostInfra: {
234
+ status: "not_declared",
235
+ evidence,
236
+ },
237
+ };
238
+ }
239
+ if (validation.schemaVersion === 2 && validation.evidenceProblems.length > 0) {
240
+ const evidence = `Host infra declaration at ${declarationPath} declared with insufficient evidence paths; ${validation.evidenceProblems.join("; ")}`;
241
+ return {
242
+ check: {
243
+ check,
244
+ status: "yellow",
245
+ evidence,
246
+ remediation: `Add or repair host infra evidence path(s): ${validation.evidenceProblems.join("; ")}`,
247
+ remediationSafe: false,
248
+ },
249
+ hostInfra: {
250
+ status: "declared",
251
+ evidence,
252
+ },
253
+ };
254
+ }
255
+ const evidence = validation.schemaVersion === 2
256
+ ? `Host infra declaration at ${declarationPath} declared, evidence paths present, not autostart verified; daemonBootstrap mechanism=${validation.mechanism}; requiredSupportingInfra=${validation.requiredSupportingInfra}; evidencePaths=${validation.evidencePaths.join(", ")}`
257
+ : `Host infra declaration at ${declarationPath} declared, not verified; daemonBootstrap mechanism=${validation.mechanism}; requiredSupportingInfra=${validation.requiredSupportingInfra}`;
258
+ return {
259
+ check: {
260
+ check,
261
+ status: "green",
262
+ evidence,
263
+ remediation: "",
264
+ },
265
+ hostInfra: {
266
+ status: "declared",
267
+ evidence,
268
+ },
269
+ };
270
+ }
271
+ catch (err) {
272
+ const evidence = `Host infra declaration inspection failed at ${declarationPath}: ${err instanceof Error ? err.message : String(err)}`;
273
+ return {
274
+ check: {
275
+ check,
276
+ status: "yellow",
277
+ evidence,
278
+ remediation: `Inspect or fix host infra declaration at ${declarationPath}`,
279
+ remediationSafe: false,
280
+ },
281
+ hostInfra: {
282
+ status: "unknown",
283
+ evidence,
284
+ },
285
+ };
286
+ }
287
+ }
288
+ validateHostInfraDeclaration(value) {
289
+ const errors = [];
290
+ const evidencePaths = [];
291
+ const evidenceProblems = [];
292
+ const obj = isRecord(value) ? value : null;
293
+ if (obj === null) {
294
+ return {
295
+ errors: ["schemaVersion", "daemonBootstrap.mechanism", "supportingInfra"],
296
+ schemaVersion: null,
297
+ mechanism: "unknown",
298
+ requiredSupportingInfra: 0,
299
+ evidencePaths,
300
+ evidenceProblems,
301
+ };
302
+ }
303
+ const schemaVersion = obj["schemaVersion"] === 1 || obj["schemaVersion"] === 2
304
+ ? obj["schemaVersion"]
305
+ : null;
306
+ if (schemaVersion === null) {
307
+ errors.push("schemaVersion");
308
+ }
309
+ const daemonBootstrap = isRecord(obj["daemonBootstrap"]) ? obj["daemonBootstrap"] : null;
310
+ const mechanism = daemonBootstrap && typeof daemonBootstrap["mechanism"] === "string"
311
+ ? daemonBootstrap["mechanism"].trim()
312
+ : "";
313
+ if (!mechanism) {
314
+ errors.push("daemonBootstrap.mechanism");
315
+ }
316
+ if (daemonBootstrap?.["declared"] !== true) {
317
+ errors.push("daemonBootstrap.declared");
318
+ }
319
+ const supportingInfra = Array.isArray(obj["supportingInfra"]) ? obj["supportingInfra"] : null;
320
+ if (!supportingInfra) {
321
+ errors.push("supportingInfra");
322
+ }
323
+ const requiredSupportingInfra = supportingInfra
324
+ ? supportingInfra.filter((entry) => isRecord(entry) && entry["required"] === true).length
325
+ : 0;
326
+ if (schemaVersion === 2 && errors.length === 0) {
327
+ this.collectRequiredEvidencePaths("daemonBootstrap.evidencePaths", daemonBootstrap?.["evidencePaths"], evidencePaths, evidenceProblems);
328
+ supportingInfra?.forEach((entry, index) => {
329
+ if (!isRecord(entry) || entry["required"] !== true)
330
+ return;
331
+ const id = typeof entry["id"] === "string" && entry["id"].trim()
332
+ ? entry["id"].trim()
333
+ : String(index);
334
+ this.collectRequiredEvidencePaths(`supportingInfra[${id}].evidencePaths`, entry["evidencePaths"], evidencePaths, evidenceProblems);
335
+ });
336
+ }
337
+ return {
338
+ errors,
339
+ schemaVersion,
340
+ mechanism: mechanism || "unknown",
341
+ requiredSupportingInfra,
342
+ evidencePaths,
343
+ evidenceProblems,
344
+ };
345
+ }
346
+ collectRequiredEvidencePaths(label, value, evidencePaths, evidenceProblems) {
347
+ if (!Array.isArray(value) || value.length === 0) {
348
+ evidenceProblems.push(`${label} missing or empty`);
349
+ return;
350
+ }
351
+ for (const candidate of value) {
352
+ if (typeof candidate !== "string" || candidate.trim() === "") {
353
+ evidenceProblems.push(`${label} contains invalid evidence path ${String(candidate)}`);
354
+ continue;
355
+ }
356
+ const resolved = this.resolveHostInfraEvidencePath(candidate.trim());
357
+ if ("error" in resolved) {
358
+ evidenceProblems.push(`${label} invalid evidence path ${candidate}: ${resolved.error}`);
359
+ continue;
360
+ }
361
+ const resolvedPath = resolved.path;
362
+ evidencePaths.push(resolvedPath);
363
+ if (!this.deps.exists(resolvedPath)) {
364
+ evidenceProblems.push(`${label} missing evidence path ${resolvedPath}`);
365
+ }
366
+ }
367
+ }
368
+ resolveHostInfraEvidencePath(rawPath) {
369
+ const openRigPrefix = "${OPENRIG_HOME}/";
370
+ const hasTraversal = rawPath.split(/[\\/]+/).includes("..");
371
+ if (rawPath.startsWith(openRigPrefix)) {
372
+ const relativePath = rawPath.slice(openRigPrefix.length);
373
+ if (!relativePath || isAbsolute(relativePath) || hasTraversal) {
374
+ return { error: "path traversal or empty OPENRIG_HOME-relative path rejected" };
375
+ }
376
+ const openRigHome = getCompatibleOpenRigPath("");
377
+ const resolved = join(openRigHome, relativePath);
378
+ const relativeToHome = relative(openRigHome, resolved);
379
+ if (relativeToHome.startsWith("..") || isAbsolute(relativeToHome)) {
380
+ return { error: "path traversal outside OPENRIG_HOME rejected" };
381
+ }
382
+ return { path: resolved };
383
+ }
384
+ if (!isAbsolute(rawPath)) {
385
+ return { error: "plain relative evidence paths are rejected; use absolute or ${OPENRIG_HOME}/..." };
386
+ }
387
+ if (hasTraversal) {
388
+ return { error: "path traversal evidence paths are rejected" };
389
+ }
390
+ return { path: rawPath };
391
+ }
392
+ checkSnapshot(rig) {
393
+ try {
394
+ const has = this.deps.hasSnapshot(rig.rigId);
395
+ if (has) {
396
+ return { check: `rig.${rig.name}.snapshot`, status: "green", evidence: "Snapshot available", remediation: "" };
397
+ }
398
+ return {
399
+ check: `rig.${rig.name}.snapshot`, status: "yellow",
400
+ evidence: "No snapshot found (first-boot or adopted rig)",
401
+ remediation: "Create a snapshot with: rig snapshot <rigId>",
402
+ remediationSafe: false,
403
+ };
404
+ }
405
+ catch {
406
+ return { check: `rig.${rig.name}.snapshot`, status: "yellow", evidence: "Could not check snapshots", remediation: "" };
407
+ }
408
+ }
409
+ checkTranscript(rigName, node) {
410
+ const session = node.canonicalSessionName ?? node.logicalId;
411
+ const check = `seat.${session}.transcript`;
412
+ // Terminal/infrastructure nodes are exempt from transcript checks
413
+ if (node.nodeKind === "infrastructure") {
414
+ return { check, status: "green", evidence: "Terminal/infrastructure node — transcript exempt", remediation: "" };
415
+ }
416
+ const transcriptPath = join(getCompatibleOpenRigPath("transcripts"), rigName, `${session}.log`);
417
+ if (this.deps.exists(transcriptPath)) {
418
+ return { check, status: "green", evidence: `Transcript exists at ${transcriptPath}`, remediation: "" };
419
+ }
420
+ return {
421
+ check, status: "yellow",
422
+ evidence: `Transcript missing: ${transcriptPath}`,
423
+ remediation: "Transcript will be created on next session launch",
424
+ remediationSafe: true,
425
+ };
426
+ }
427
+ checkSeatReadiness(node) {
428
+ const session = node.canonicalSessionName ?? node.logicalId;
429
+ const check = `seat.${session}.readiness`;
430
+ if (!node.canonicalSessionName) {
431
+ return {
432
+ check,
433
+ status: "red",
434
+ evidence: "Missing canonical session identity",
435
+ remediation: "Restore or relaunch the seat so it has a canonical session identity",
436
+ remediationSafe: false,
437
+ };
438
+ }
439
+ if (node.sessionStatus !== "running" || node.startupStatus !== "ready") {
440
+ const latestError = node.latestError ? ` latestError=${node.latestError}` : "";
441
+ return {
442
+ check,
443
+ status: "red",
444
+ evidence: `Seat not running/ready: sessionStatus=${node.sessionStatus ?? "unknown"} startupStatus=${node.startupStatus ?? "unknown"}${latestError}`,
445
+ remediation: "Restore or relaunch the seat, then rerun rig restore-check",
446
+ remediationSafe: false,
447
+ };
448
+ }
449
+ return {
450
+ check,
451
+ status: "green",
452
+ evidence: `Seat running and ready: ${node.canonicalSessionName}`,
453
+ remediation: "",
454
+ };
455
+ }
456
+ checkResumePath(node) {
457
+ const session = node.canonicalSessionName ?? node.logicalId;
458
+ if (node.tmuxAttachCommand) {
459
+ return { check: `seat.${session}.resume-path`, status: "green", evidence: node.tmuxAttachCommand, remediation: "" };
460
+ }
461
+ return {
462
+ check: `seat.${session}.resume-path`, status: "yellow",
463
+ evidence: "No attach command available",
464
+ remediation: "Session will be created fresh on restore",
465
+ remediationSafe: true,
466
+ };
467
+ }
468
+ checkStartupContext(node) {
469
+ const session = node.canonicalSessionName ?? node.logicalId;
470
+ const check = `seat.${session}.startup-context`;
471
+ const runningReady = node.sessionStatus === "running" && node.startupStatus === "ready";
472
+ if (!node.nodeId) {
473
+ return {
474
+ check: this.buildStartupContextAvailabilityCheck(check, runningReady, `Startup context cannot be inspected because node id is missing for ${session}`),
475
+ };
476
+ }
477
+ const probe = this.deps.getStartupContext(node.nodeId);
478
+ switch (probe.status) {
479
+ case "probe_error":
480
+ return {
481
+ unknownChecks: [{
482
+ check: "probe.error",
483
+ status: "red",
484
+ evidence: `Failed to inspect startup context for ${session}: ${probe.evidence}`,
485
+ remediation: "Check daemon logs with: rig daemon logs",
486
+ remediationSafe: true,
487
+ }],
488
+ };
489
+ case "missing":
490
+ case "malformed":
491
+ return {
492
+ check: this.buildStartupContextAvailabilityCheck(check, runningReady, probe.evidence),
493
+ };
494
+ case "ok":
495
+ break;
496
+ }
497
+ const startupContext = probe;
498
+ const missingRequired = startupContext.resolvedStartupFiles.filter((file) => file.required && !this.deps.exists(file.absolutePath));
499
+ const missingOptional = startupContext.resolvedStartupFiles.filter((file) => !file.required && !this.deps.exists(file.absolutePath));
500
+ const missingProjectionEntries = startupContext.projectionEntries.filter((entry) => !this.deps.exists(entry.absolutePath));
501
+ if (missingRequired.length === 0 && missingOptional.length === 0 && missingProjectionEntries.length === 0) {
502
+ const detailParts = [];
503
+ if (startupContext.resolvedStartupFiles.length > 0) {
504
+ detailParts.push(`resolved startup files present: ${startupContext.resolvedStartupFiles.map((file) => file.absolutePath).join(", ")}`);
505
+ }
506
+ if (startupContext.projectionEntries.length > 0) {
507
+ detailParts.push(`projection source paths present: ${startupContext.projectionEntries.map((entry) => entry.absolutePath).join(", ")}`);
508
+ }
509
+ if (detailParts.length === 0) {
510
+ detailParts.push("no persisted startup files or projection source paths declared");
511
+ }
512
+ return {
513
+ check: {
514
+ check,
515
+ status: "green",
516
+ evidence: `Startup context present for node ${node.nodeId}; ${detailParts.join("; ")}`,
517
+ remediation: "",
518
+ },
519
+ };
520
+ }
521
+ const evidenceParts = [];
522
+ if (missingRequired.length > 0) {
523
+ evidenceParts.push(`missing required startup file(s): ${missingRequired.map((file) => file.absolutePath).join(", ")}`);
524
+ }
525
+ if (missingOptional.length > 0) {
526
+ evidenceParts.push(`missing optional startup file(s): ${missingOptional.map((file) => file.absolutePath).join(", ")}`);
527
+ }
528
+ if (missingProjectionEntries.length > 0) {
529
+ evidenceParts.push(`missing projection source path(s): ${missingProjectionEntries.map((entry) => entry.absolutePath).join(", ")}`);
530
+ }
531
+ const status = missingRequired.length > 0 && !runningReady ? "red" : "yellow";
532
+ return {
533
+ check: {
534
+ check,
535
+ status,
536
+ evidence: `Startup context present for node ${node.nodeId}, but replay inputs are incomplete: ${evidenceParts.join("; ")}`,
537
+ remediation: `Restore or recreate the missing startup inputs from the rig or agent spec before trusting replay: ${[
538
+ ...missingRequired.map((file) => file.absolutePath),
539
+ ...missingOptional.map((file) => file.absolutePath),
540
+ ...missingProjectionEntries.map((entry) => entry.absolutePath),
541
+ ].join(", ")}`,
542
+ remediationSafe: false,
543
+ },
544
+ };
545
+ }
546
+ buildStartupContextAvailabilityCheck(check, runningReady, evidence) {
547
+ return {
548
+ check,
549
+ status: runningReady ? "yellow" : "red",
550
+ evidence,
551
+ remediation: "Recreate the seat startup context from the rig or agent spec before trusting replay inputs",
552
+ remediationSafe: false,
553
+ };
554
+ }
555
+ checkQueueFile(rigName, node) {
556
+ const session = node.canonicalSessionName ?? node.logicalId;
557
+ const check = `seat.${session}.queue-file`;
558
+ // Derive queue file path from pod/member
559
+ const podName = node.podNamespace ?? (node.logicalId.includes(".") ? node.logicalId.split(".")[0] : null);
560
+ const memberName = node.logicalId.includes(".") ? node.logicalId.split(".").slice(1).join(".") : node.logicalId;
561
+ if (!podName) {
562
+ return { check, status: "yellow", evidence: "Cannot derive queue path (no pod namespace)", remediation: "" };
563
+ }
564
+ const substrateRoot = this.deps.substrateRoot ?? join(process.env["HOME"] ?? "~", "code", "substrate", "shared-docs");
565
+ const queuePath = join(substrateRoot, "rigs", rigName, "state", podName, `${memberName}.queue.md`);
566
+ if (this.deps.exists(queuePath)) {
567
+ return { check, status: "green", evidence: `Queue file exists at ${queuePath}`, remediation: "" };
568
+ }
569
+ return {
570
+ check, status: "yellow",
571
+ evidence: `Queue file missing: ${queuePath}`,
572
+ remediation: "Create queue file per attention-queue convention",
573
+ remediationSafe: false,
574
+ };
575
+ }
576
+ checkHooks(node) {
577
+ const session = node.canonicalSessionName ?? node.logicalId;
578
+ if (node.nodeKind !== "agent") {
579
+ return {
580
+ check: `seat.${session}.hooks`, status: "green",
581
+ evidence: "Infrastructure/terminal node; Claude Code hook inspection not applicable",
582
+ remediation: "",
583
+ };
584
+ }
585
+ if (node.runtime !== "claude-code") {
586
+ return {
587
+ check: `seat.${session}.hooks`, status: "green",
588
+ evidence: `${node.runtime ?? "non-Claude"} seat; Claude Code hook inspection not applicable`,
589
+ remediation: "",
590
+ };
591
+ }
592
+ const candidates = this.getClaudeSettingsCandidates(node);
593
+ const searchedPaths = candidates.map((candidate) => candidate.path);
594
+ const cwdUnavailable = !node.cwd;
595
+ const inspections = [];
596
+ const malformed = [];
597
+ for (const candidate of candidates) {
598
+ if (!this.deps.exists(candidate.path))
599
+ continue;
600
+ let parsed;
601
+ try {
602
+ parsed = JSON.parse(this.deps.readFile(candidate.path));
603
+ }
604
+ catch (err) {
605
+ malformed.push(`${candidate.path}: ${err instanceof Error ? err.message : String(err)}`);
606
+ continue;
607
+ }
608
+ inspections.push({
609
+ path: candidate.path,
610
+ hasSessionStartCompact: this.hasClaudeCommandHook(parsed, "SessionStart", CLAUDE_SESSION_START_COMPACT_COMMAND, "compact"),
611
+ hasUserPromptSubmit: this.hasClaudeCommandHook(parsed, "UserPromptSubmit", CLAUDE_USER_PROMPT_SUBMIT_COMMAND),
612
+ });
613
+ }
614
+ if (malformed.length > 0) {
615
+ return {
616
+ check: `seat.${session}.hooks`, status: "yellow",
617
+ evidence: `Malformed applicable Claude settings file(s): ${malformed.join("; ")}. Claude hook configuration could not be trusted until the malformed applicable settings file is fixed. Searched settings paths: ${searchedPaths.join(", ")}`,
618
+ remediation: `Fix Claude settings JSON before trusting hook readiness: ${malformed.map((entry) => entry.split(":")[0]).join(", ")}`,
619
+ remediationSafe: false,
620
+ };
621
+ }
622
+ const sessionStartPaths = inspections
623
+ .filter((inspection) => inspection.hasSessionStartCompact)
624
+ .map((inspection) => inspection.path);
625
+ const userPromptSubmitPaths = inspections
626
+ .filter((inspection) => inspection.hasUserPromptSubmit)
627
+ .map((inspection) => inspection.path);
628
+ const hasSessionStart = sessionStartPaths.length > 0;
629
+ const hasUserPromptSubmit = userPromptSubmitPaths.length > 0;
630
+ if (hasSessionStart && hasUserPromptSubmit) {
631
+ return {
632
+ check: `seat.${session}.hooks`, status: "green",
633
+ evidence: `Claude Code hook configuration present, not hook-execution verified; SessionStart matcher compact command found in ${sessionStartPaths.join(", ")}; UserPromptSubmit command found in ${userPromptSubmitPaths.join(", ")}. Searched settings paths: ${searchedPaths.join(", ")}`,
634
+ remediation: "",
635
+ };
636
+ }
637
+ const missing = [];
638
+ if (!hasSessionStart) {
639
+ missing.push(`SessionStart matcher compact command ${CLAUDE_SESSION_START_COMPACT_COMMAND}`);
640
+ }
641
+ if (!hasUserPromptSubmit) {
642
+ missing.push(`UserPromptSubmit command ${CLAUDE_USER_PROMPT_SUBMIT_COMMAND}`);
643
+ }
644
+ const inspected = inspections.length > 0
645
+ ? `Existing settings inspected: ${inspections.map((inspection) => inspection.path).join(", ")}.`
646
+ : "No existing Claude settings files were found.";
647
+ const cwdEvidence = cwdUnavailable
648
+ ? " project settings were not inspected because cwd is unavailable."
649
+ : "";
650
+ return {
651
+ check: `seat.${session}.hooks`, status: "yellow",
652
+ evidence: `Claude Code hook configuration missing required entries: ${missing.join("; ")}. Searched settings paths: ${searchedPaths.join(", ")}. ${inspected}${cwdEvidence}`,
653
+ remediation: `Merge required Claude hook entries from ${CLAUDE_HOOK_FRAGMENT_PATH} into host-global or project Claude settings`,
654
+ remediationSafe: false,
655
+ };
656
+ }
657
+ getClaudeSettingsCandidates(node) {
658
+ const home = process.env["HOME"] ?? "~";
659
+ const candidates = [{
660
+ path: join(home, ".claude", "settings.json"),
661
+ scope: "host-global",
662
+ }];
663
+ if (node.cwd) {
664
+ candidates.push({
665
+ path: join(node.cwd, ".claude", "settings.json"),
666
+ scope: "project",
667
+ });
668
+ candidates.push({
669
+ path: join(node.cwd, ".claude", "settings.local.json"),
670
+ scope: "project-local",
671
+ });
672
+ }
673
+ return candidates;
674
+ }
675
+ hasClaudeCommandHook(settings, eventName, requiredCommand, requiredMatcher) {
676
+ if (!isRecord(settings) || !isRecord(settings["hooks"]))
677
+ return false;
678
+ const eventEntries = settings["hooks"][eventName];
679
+ if (!Array.isArray(eventEntries))
680
+ return false;
681
+ return eventEntries.some((entry) => {
682
+ if (!isRecord(entry))
683
+ return false;
684
+ if (requiredMatcher !== undefined && entry["matcher"] !== requiredMatcher)
685
+ return false;
686
+ const hooks = entry["hooks"];
687
+ if (!Array.isArray(hooks))
688
+ return false;
689
+ return hooks.some((hook) => isRecord(hook) && hook["command"] === requiredCommand);
690
+ });
691
+ }
692
+ checkSpecPresent(rig) {
693
+ const substrateRoot = this.deps.substrateRoot ?? join(process.env["HOME"] ?? "~", "code", "substrate", "shared-docs");
694
+ const rigRoot = join(substrateRoot, "rigs", rig.name);
695
+ const rigYaml = join(rigRoot, "rig.yaml");
696
+ if (!this.deps.exists(rigRoot)) {
697
+ return {
698
+ check: `rig.${rig.name}.spec-present`, status: "red",
699
+ evidence: `Rig root missing: ${rigRoot}`,
700
+ remediation: `Create the rig root directory at ${rigRoot} with a rig.yaml spec`,
701
+ remediationSafe: false,
702
+ };
703
+ }
704
+ if (!this.deps.exists(rigYaml)) {
705
+ return {
706
+ check: `rig.${rig.name}.spec-present`, status: "yellow",
707
+ evidence: `Rig root exists but rig.yaml missing: ${rigYaml}`,
708
+ remediation: `Add a rig.yaml spec to ${rigRoot}`,
709
+ remediationSafe: false,
710
+ };
711
+ }
712
+ return { check: `rig.${rig.name}.spec-present`, status: "green", evidence: `Spec present at ${rigYaml}`, remediation: "" };
713
+ }
714
+ inspectLatestSnapshot(rigId) {
715
+ if (!this.deps.getLatestSnapshot) {
716
+ return { snapshot: null };
717
+ }
718
+ try {
719
+ const snapshot = this.deps.getLatestSnapshot(rigId);
720
+ if (!snapshot)
721
+ return { snapshot: null };
722
+ return { snapshot: { id: snapshot.id, kind: snapshot.kind } };
723
+ }
724
+ catch (err) {
725
+ return {
726
+ snapshot: null,
727
+ error: `Latest snapshot lookup failed: ${err instanceof Error ? err.message : String(err)}`,
728
+ };
729
+ }
730
+ }
731
+ buildResult(checks, rigs, hostInfra, recoveryInputs = []) {
732
+ const red = checks.filter((c) => c.status === "red").length;
733
+ const yellow = checks.filter((c) => c.status === "yellow").length;
734
+ const green = checks.filter((c) => c.status === "green").length;
735
+ let verdict;
736
+ if (red > 0) {
737
+ verdict = "not_restorable";
738
+ }
739
+ else if (yellow > 0) {
740
+ verdict = "restorable_with_caveats";
741
+ }
742
+ else {
743
+ verdict = "restorable";
744
+ }
745
+ const repairPacket = this.buildRepairPacket(checks, verdict);
746
+ const recovery = this.buildRecovery(verdict, checks, recoveryInputs);
747
+ return this.withAssertion({ verdict, counts: { red, yellow, green }, checks, repairPacket, recovery }, rigs, hostInfra);
748
+ }
749
+ /** Probe error produces verdict=unknown (not not_restorable) so operators
750
+ * can distinguish "definitely broken" from "checker couldn't inspect." */
751
+ buildUnknown(checks) {
752
+ const red = checks.filter((c) => c.status === "red").length;
753
+ const yellow = checks.filter((c) => c.status === "yellow").length;
754
+ const green = checks.filter((c) => c.status === "green").length;
755
+ const repairPacket = this.buildRepairPacket(checks, "unknown");
756
+ const evidence = checks.find((check) => check.status === "red")?.evidence
757
+ ?? "Restore-check state could not be inspected";
758
+ return this.withAssertion({
759
+ verdict: "unknown",
760
+ counts: { red, yellow, green },
761
+ checks,
762
+ repairPacket,
763
+ recovery: {
764
+ status: "unknown",
765
+ summary: "Recovery status could not be inspected because restore-check state is unknown.",
766
+ actions: [],
767
+ blocked: [],
768
+ unknown: [{ scope: "host", reason: evidence }],
769
+ },
770
+ }, []);
771
+ }
772
+ withAssertion(result, rigs, hostInfra) {
773
+ const blockingRigCount = rigs.filter((rig) => rig.blockedNodes > 0 || rig.blockingChecks.length > 0).length;
774
+ const caveatRigCount = rigs.filter((rig) => rig.blockedNodes === 0 && rig.blockingChecks.length === 0 && (rig.caveatNodes > 0 || rig.caveatChecks.length > 0)).length;
775
+ const unknownRigCount = rigs.filter((rig) => rig.status === "unknown").length;
776
+ let readinessStatus;
777
+ let reason;
778
+ if (result.verdict === "unknown") {
779
+ readinessStatus = "unknown";
780
+ reason = "unknown_probe_state";
781
+ }
782
+ else if (result.counts.red > 0) {
783
+ readinessStatus = "not_ready";
784
+ reason = "blockers_present";
785
+ }
786
+ else if (result.counts.yellow > 0) {
787
+ readinessStatus = "ready_with_caveats";
788
+ reason = "caveats_present";
789
+ }
790
+ else {
791
+ readinessStatus = "ready";
792
+ reason = hostInfra?.status === "declared"
793
+ ? "all_observable_checks_green_host_infra_declared_not_verified"
794
+ : "all_observable_checks_green";
795
+ }
796
+ // Continuity is always not_proven in v1 — no code path can produce "proven"
797
+ const continuity = {
798
+ status: "not_proven",
799
+ evidence: "Strict same-session/provider-context resume is not verified by restore-check v1. Observable readiness is verified.",
800
+ provenCapabilities: this.computeProvenCapabilities(result.checks),
801
+ unprovenCapabilities: [
802
+ "provider_session_resume",
803
+ "context_window_preservation",
804
+ "interrupted_work_functional_resume",
805
+ ],
806
+ };
807
+ return {
808
+ ...result,
809
+ readiness: {
810
+ status: readinessStatus,
811
+ reason,
812
+ blockingRigCount,
813
+ caveatRigCount,
814
+ unknownRigCount,
815
+ },
816
+ continuity,
817
+ rigs,
818
+ hostInfra: result.verdict === "unknown"
819
+ ? {
820
+ status: "unknown",
821
+ evidence: "Host bootstrap/autostart source could not be inspected because restore-check state is unknown",
822
+ }
823
+ : (hostInfra ?? {
824
+ status: "not_inspected",
825
+ evidence: "No host bootstrap/autostart source inspected by v0; readiness only covers observable daemon, rig, and seat checks",
826
+ }),
827
+ recovery: result.recovery,
828
+ };
829
+ }
830
+ /** Derive proven capabilities from green checks for the continuity block. */
831
+ computeProvenCapabilities(checks) {
832
+ const proven = [];
833
+ if (checks.some((c) => c.check === "daemon.reachable" && c.status === "green"))
834
+ proven.push("daemon_reachable");
835
+ if (checks.some((c) => c.check.endsWith(".transcript") && c.status === "green"))
836
+ proven.push("transcript_readable");
837
+ if (checks.some((c) => c.check.endsWith(".spec-present") && c.status === "green"))
838
+ proven.push("spec_present");
839
+ if (checks.some((c) => c.check.endsWith(".queue-file") && c.status === "green"))
840
+ proven.push("queue_file_present");
841
+ if (checks.some((c) => c.check.endsWith(".resume-path") && c.status === "green"))
842
+ proven.push("seat_identity_resolvable");
843
+ return proven;
844
+ }
845
+ buildRecovery(verdict, checks, recoveryInputs) {
846
+ if (verdict === "unknown") {
847
+ const evidence = checks.find((check) => check.status === "red")?.evidence
848
+ ?? "Restore-check state could not be inspected";
849
+ return {
850
+ status: "unknown",
851
+ summary: "Recovery status could not be inspected because restore-check state is unknown.",
852
+ actions: [],
853
+ blocked: [],
854
+ unknown: [{ scope: "host", reason: evidence }],
855
+ };
856
+ }
857
+ if (recoveryInputs.length === 0) {
858
+ const firstRed = checks.find((check) => check.status === "red");
859
+ if (firstRed) {
860
+ return {
861
+ status: "blocked",
862
+ summary: "No exact recovery action is known in v0 because restore-check found blockers outside runnable rig inventory.",
863
+ actions: [],
864
+ blocked: [{ scope: "host", reason: firstRed.evidence }],
865
+ unknown: [],
866
+ };
867
+ }
868
+ return {
869
+ status: "not_needed",
870
+ summary: "All observable rigs are already running/ready; no recovery action needed.",
871
+ actions: [],
872
+ blocked: [],
873
+ unknown: [],
874
+ };
875
+ }
876
+ const allReady = recoveryInputs.every((input) => input.runningReadyNodes === input.expectedNodes);
877
+ if (allReady) {
878
+ return {
879
+ status: "not_needed",
880
+ summary: "All observable rigs are already running/ready; no recovery action needed.",
881
+ actions: [],
882
+ blocked: [],
883
+ unknown: [],
884
+ };
885
+ }
886
+ const actions = [];
887
+ const blocked = [];
888
+ const unknown = [];
889
+ for (const input of recoveryInputs) {
890
+ if (input.runningReadyNodes === input.expectedNodes)
891
+ continue;
892
+ if (input.snapshotLookupError) {
893
+ unknown.push({
894
+ scope: "rig",
895
+ rigId: input.rigId,
896
+ rigName: input.rigName,
897
+ reason: input.snapshotLookupError,
898
+ });
899
+ continue;
900
+ }
901
+ const restoreInputBlockers = input.blockingChecks.filter((check) => this.classifyRecoveryBlockingCheck(check) === "restore_input");
902
+ if (restoreInputBlockers.length > 0) {
903
+ blocked.push({
904
+ scope: "rig",
905
+ rigId: input.rigId,
906
+ rigName: input.rigName,
907
+ reason: `No exact recovery action is known in v0 because restore-input blockers remain: ${restoreInputBlockers.map((check) => check.evidence).join("; ")}`,
908
+ });
909
+ continue;
910
+ }
911
+ if (input.latestSnapshot) {
912
+ actions.push({
913
+ scope: "rig",
914
+ rigId: input.rigId,
915
+ rigName: input.rigName,
916
+ action: "restore_from_latest_snapshot",
917
+ command: `rig restore ${input.latestSnapshot.id} --rig ${input.rigId}`,
918
+ reason: "Rig has a latest snapshot and one or more seats are not running/ready.",
919
+ safe: false,
920
+ blocking: true,
921
+ });
922
+ continue;
923
+ }
924
+ blocked.push({
925
+ scope: "rig",
926
+ rigId: input.rigId,
927
+ rigName: input.rigName,
928
+ reason: "No exact recovery action is known in v0 because latest snapshot input is missing.",
929
+ });
930
+ }
931
+ const status = unknown.length > 0
932
+ ? "unknown"
933
+ : actions.length > 0
934
+ ? "actionable"
935
+ : blocked.length > 0
936
+ ? "blocked"
937
+ : "not_needed";
938
+ return {
939
+ status,
940
+ summary: this.buildRecoverySummary(status, actions, blocked, unknown),
941
+ actions,
942
+ blocked,
943
+ unknown,
944
+ };
945
+ }
946
+ classifyRecoveryBlockingCheck(check) {
947
+ if (check.status !== "red")
948
+ return "other";
949
+ if (check.check.startsWith("seat.") && check.check.endsWith(".readiness")) {
950
+ if (check.evidence.includes("Missing canonical session identity")) {
951
+ return "restore_input";
952
+ }
953
+ return "runtime";
954
+ }
955
+ if (check.check.startsWith("seat.") && check.check.endsWith(".startup-context")) {
956
+ return "restore_input";
957
+ }
958
+ return "other";
959
+ }
960
+ buildRecoverySummary(status, actions, blocked, unknown) {
961
+ if (status === "not_needed") {
962
+ return "All observable rigs are already running/ready; no recovery action needed.";
963
+ }
964
+ if (status === "unknown") {
965
+ return `Recovery status could not be inspected completely; ${actions.length} actionable, ${blocked.length} blocked, ${unknown.length} unknown.`;
966
+ }
967
+ if (status === "actionable") {
968
+ return `${actions.length} ${pluralize(actions.length, "rig")} can be recovered by known OpenRig command; ${blocked.length} ${pluralize(blocked.length, "rig")} blocked; ${unknown.length} unknown.`;
969
+ }
970
+ return `${blocked.length} ${pluralize(blocked.length, "rig")} blocked; ${actions.length} actionable; ${unknown.length} unknown.`;
971
+ }
972
+ buildRigRollup(input) {
973
+ const blockingChecks = input.checks.filter((check) => check.status === "red");
974
+ const caveatChecks = input.checks.filter((check) => check.status === "yellow");
975
+ const expectedNodes = input.nodes.length;
976
+ let runningReadyNodes = 0;
977
+ let blockedNodes = 0;
978
+ let caveatNodes = 0;
979
+ for (const node of input.nodes) {
980
+ const session = node.canonicalSessionName ?? node.logicalId;
981
+ const nodeChecks = input.checks.filter((check) => check.check.startsWith(`seat.${session}.`));
982
+ const hasBlocking = nodeChecks.some((check) => check.status === "red");
983
+ const hasCaveat = nodeChecks.some((check) => check.status === "yellow");
984
+ if (node.canonicalSessionName && node.sessionStatus === "running" && node.startupStatus === "ready") {
985
+ runningReadyNodes += 1;
986
+ }
987
+ if (hasBlocking)
988
+ blockedNodes += 1;
989
+ else if (hasCaveat)
990
+ caveatNodes += 1;
991
+ }
992
+ let verdict;
993
+ let status;
994
+ if (blockingChecks.length > 0) {
995
+ verdict = "not_restorable";
996
+ status = "not_ready";
997
+ }
998
+ else if (caveatChecks.length > 0) {
999
+ verdict = "restorable_with_caveats";
1000
+ status = "ready_with_caveats";
1001
+ }
1002
+ else {
1003
+ verdict = "restorable";
1004
+ status = "ready";
1005
+ }
1006
+ return {
1007
+ rigId: input.rig.rigId,
1008
+ rigName: input.rig.name,
1009
+ status,
1010
+ verdict,
1011
+ expectedNodes,
1012
+ runningReadyNodes,
1013
+ blockedNodes,
1014
+ caveatNodes,
1015
+ blockingChecks,
1016
+ caveatChecks,
1017
+ };
1018
+ }
1019
+ /** Generate ordered repair steps from non-green checks with remediation.
1020
+ * null when all green (restorable — nothing to repair).
1021
+ * Blockers (red) first in check order, then caveats (yellow). */
1022
+ buildRepairPacket(checks, verdict) {
1023
+ if (verdict === "restorable")
1024
+ return null;
1025
+ // Blockers first, then caveats, preserving original check order within each group
1026
+ const blockers = checks.filter((c) => c.status === "red" && c.remediation);
1027
+ const caveats = checks.filter((c) => c.status === "yellow" && c.remediation);
1028
+ const ordered = [...blockers, ...caveats];
1029
+ if (ordered.length === 0)
1030
+ return null;
1031
+ let step = 0;
1032
+ return ordered.map((c) => ({
1033
+ step: ++step,
1034
+ command: c.remediation,
1035
+ rationale: c.evidence,
1036
+ safe: c.remediationSafe === true, // conservative: default false unless explicitly marked safe
1037
+ blocking: c.status === "red",
1038
+ }));
1039
+ }
1040
+ }
1041
+ function isRecord(value) {
1042
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1043
+ }
1044
+ function pluralize(count, noun) {
1045
+ return count === 1 ? noun : `${noun}s`;
1046
+ }
1047
+ //# sourceMappingURL=restore-check-service.js.map