@openrig/cli 0.5.8 → 0.5.9

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 (781) hide show
  1. package/daemon/assets/claude-statusline-context.cjs +1 -0
  2. package/daemon/assets/plugins/openrig-core/README.md +1 -1
  3. package/daemon/assets/plugins/openrig-core/skills/agent-operated-software/SKILL.md +92 -0
  4. package/daemon/assets/plugins/openrig-core/skills/agent-operated-workflows/SKILL.md +79 -0
  5. package/daemon/assets/plugins/openrig-core/skills/forming-an-openrig-mental-model/SKILL.md +2 -2
  6. package/daemon/assets/plugins/openrig-core/skills/openrig-skills/SKILL.md +4 -2
  7. package/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md +12 -16
  8. package/daemon/assets/plugins/openrig-core/skills/software-for-agents/SKILL.md +11 -179
  9. package/daemon/context-packs/onboarding-width/manifest.yaml +1 -1
  10. package/daemon/context-packs/onboarding-width/public-what-you-can-do.md +63 -19
  11. package/daemon/context-packs/skills/agent-operated-software/SKILL.md +92 -0
  12. package/daemon/context-packs/skills/agent-operated-software/manifest.yaml +10 -0
  13. package/daemon/context-packs/skills/agent-operated-workflows/SKILL.md +79 -0
  14. package/daemon/context-packs/skills/agent-operated-workflows/manifest.yaml +10 -0
  15. package/daemon/context-packs/skills/applying-a-permission-policy/manifest.yaml +1 -1
  16. package/daemon/context-packs/skills/claude-compaction-restore/manifest.yaml +1 -1
  17. package/daemon/context-packs/skills/core/agent-starters/manifest.yaml +1 -1
  18. package/daemon/context-packs/skills/core/agent-startup-and-context-ingestion/manifest.yaml +1 -1
  19. package/daemon/context-packs/skills/core/cross-host-rig-commands/manifest.yaml +1 -1
  20. package/daemon/context-packs/skills/core/human-in-the-loop/manifest.yaml +1 -1
  21. package/daemon/context-packs/skills/core/messaging-the-human/manifest.yaml +1 -1
  22. package/daemon/context-packs/skills/core/openrig-architect/manifest.yaml +1 -1
  23. package/daemon/context-packs/skills/core/openrig-cmux/manifest.yaml +1 -1
  24. package/daemon/context-packs/skills/core/openrig-herdr/manifest.yaml +1 -1
  25. package/daemon/context-packs/skills/core/openrig-skills/SKILL.md +4 -2
  26. package/daemon/context-packs/skills/core/openrig-skills/manifest.yaml +1 -1
  27. package/daemon/context-packs/skills/core/openrig-upgrade/SKILL.md +81 -0
  28. package/daemon/context-packs/skills/core/openrig-upgrade/manifest.yaml +3 -1
  29. package/daemon/context-packs/skills/core/openrig-upgrade/scripts/migrate-telemetry-state-0.5.9.mjs +1419 -0
  30. package/daemon/context-packs/skills/core/rig-bundles-and-shareable-artifacts/manifest.yaml +1 -1
  31. package/daemon/context-packs/skills/core/rig-lifecycle/manifest.yaml +1 -1
  32. package/daemon/context-packs/skills/core/session-source-fork/manifest.yaml +1 -1
  33. package/daemon/context-packs/skills/core/specification-system/manifest.yaml +1 -1
  34. package/daemon/context-packs/skills/core/topology-mutation-and-seat-management/manifest.yaml +1 -1
  35. package/daemon/context-packs/skills/core/watchdog/manifest.yaml +1 -1
  36. package/daemon/context-packs/skills/delegating-work/manifest.yaml +1 -1
  37. package/daemon/context-packs/skills/forming-an-openrig-mental-model/SKILL.md +2 -2
  38. package/daemon/context-packs/skills/forming-an-openrig-mental-model/manifest.yaml +1 -1
  39. package/daemon/context-packs/skills/loading-addressable-markdown/manifest.yaml +1 -1
  40. package/daemon/context-packs/skills/mission-slice-sop/manifest.yaml +1 -1
  41. package/daemon/context-packs/skills/openrig-operating-model/manifest.yaml +1 -1
  42. package/daemon/context-packs/skills/openrig-user/SKILL.md +12 -16
  43. package/daemon/context-packs/skills/openrig-user/manifest.yaml +1 -1
  44. package/daemon/context-packs/skills/orienting-to-an-inherited-seat/manifest.yaml +1 -1
  45. package/daemon/context-packs/skills/pm/backlog-capture/manifest.yaml +1 -1
  46. package/daemon/context-packs/skills/pm/context-builder/manifest.yaml +1 -1
  47. package/daemon/context-packs/skills/pm/exec-summary/manifest.yaml +1 -1
  48. package/daemon/context-packs/skills/pm/office-hours/manifest.yaml +1 -1
  49. package/daemon/context-packs/skills/pm/plan-review/manifest.yaml +1 -1
  50. package/daemon/context-packs/skills/pm/requirements-writer/manifest.yaml +1 -1
  51. package/daemon/context-packs/skills/pm/ui-mockup/manifest.yaml +1 -1
  52. package/daemon/context-packs/skills/pods/development-team/manifest.yaml +1 -1
  53. package/daemon/context-packs/skills/pods/orchestration-team/manifest.yaml +1 -1
  54. package/daemon/context-packs/skills/pods/oversight-team/manifest.yaml +1 -1
  55. package/daemon/context-packs/skills/pods/review-team/manifest.yaml +1 -1
  56. package/daemon/context-packs/skills/process/agent-browser/manifest.yaml +1 -1
  57. package/daemon/context-packs/skills/process/context-engineering/manifest.yaml +1 -1
  58. package/daemon/context-packs/skills/process/dogfood/manifest.yaml +1 -1
  59. package/daemon/context-packs/skills/process/frontend-design/manifest.yaml +1 -1
  60. package/daemon/context-packs/skills/process/systematic-debugging/manifest.yaml +1 -1
  61. package/daemon/context-packs/skills/process/test-driven-development/manifest.yaml +1 -1
  62. package/daemon/context-packs/skills/process/verification-before-completion/manifest.yaml +1 -1
  63. package/daemon/context-packs/skills/queue-handoff/manifest.yaml +1 -1
  64. package/daemon/context-packs/skills/refocusing/manifest.yaml +1 -1
  65. package/daemon/context-packs/skills/retiring-and-inheriting-a-seat/manifest.yaml +1 -1
  66. package/daemon/context-packs/skills/seat-continuity-and-handover/manifest.yaml +1 -1
  67. package/daemon/context-packs/skills/session-compaction-and-restore/manifest.yaml +1 -1
  68. package/daemon/context-packs/skills/software-for-agents/SKILL.md +11 -179
  69. package/daemon/context-packs/skills/software-for-agents/manifest.yaml +3 -3
  70. package/daemon/context-packs/world-example/manifest.yaml +1 -1
  71. package/daemon/context-packs/world-example/your-world.md +1 -1
  72. package/daemon/context-packs/world-public/build-your-world.md +19 -0
  73. package/daemon/context-packs/world-public/claims.yaml +5 -1
  74. package/daemon/context-packs/world-public/manifest.yaml +40 -1
  75. package/daemon/context-packs/world-public/verify-world.sh +25 -9
  76. package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
  77. package/daemon/dist/adapters/claude-code-adapter.js +4 -2
  78. package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
  79. package/daemon/dist/build-info.js +3 -3
  80. package/daemon/dist/db/all-migrations.d.ts +1 -1
  81. package/daemon/dist/db/all-migrations.d.ts.map +1 -1
  82. package/daemon/dist/db/all-migrations.js +3 -1
  83. package/daemon/dist/db/all-migrations.js.map +1 -1
  84. package/daemon/dist/db/migrations/046_seat_identity_verdicts.d.ts +8 -5
  85. package/daemon/dist/db/migrations/046_seat_identity_verdicts.d.ts.map +1 -1
  86. package/daemon/dist/db/migrations/046_seat_identity_verdicts.js +8 -5
  87. package/daemon/dist/db/migrations/046_seat_identity_verdicts.js.map +1 -1
  88. package/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.d.ts +8 -0
  89. package/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.d.ts.map +1 -0
  90. package/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.js +50 -0
  91. package/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.js.map +1 -0
  92. package/daemon/dist/domain/active-occupant.d.ts +6 -1
  93. package/daemon/dist/domain/active-occupant.d.ts.map +1 -1
  94. package/daemon/dist/domain/active-occupant.js +47 -0
  95. package/daemon/dist/domain/active-occupant.js.map +1 -1
  96. package/daemon/dist/domain/bootstrap-orchestrator.d.ts.map +1 -1
  97. package/daemon/dist/domain/bootstrap-orchestrator.js +8 -1
  98. package/daemon/dist/domain/bootstrap-orchestrator.js.map +1 -1
  99. package/daemon/dist/domain/bundle-context-packs-router.d.ts +3 -3
  100. package/daemon/dist/domain/bundle-context-packs-router.d.ts.map +1 -1
  101. package/daemon/dist/domain/bundle-skills-router.d.ts +3 -0
  102. package/daemon/dist/domain/bundle-skills-router.d.ts.map +1 -1
  103. package/daemon/dist/domain/bundle-skills-router.js +5 -1
  104. package/daemon/dist/domain/bundle-skills-router.js.map +1 -1
  105. package/daemon/dist/domain/claim-service.d.ts +2 -0
  106. package/daemon/dist/domain/claim-service.d.ts.map +1 -1
  107. package/daemon/dist/domain/claim-service.js +33 -12
  108. package/daemon/dist/domain/claim-service.js.map +1 -1
  109. package/daemon/dist/domain/context-packs/context-pack-library-service.d.ts.map +1 -1
  110. package/daemon/dist/domain/context-packs/context-pack-library-service.js +9 -1
  111. package/daemon/dist/domain/context-packs/context-pack-library-service.js.map +1 -1
  112. package/daemon/dist/domain/context-packs/context-pack-types.d.ts +25 -0
  113. package/daemon/dist/domain/context-packs/context-pack-types.d.ts.map +1 -1
  114. package/daemon/dist/domain/context-packs/context-pack-types.js +3 -1
  115. package/daemon/dist/domain/context-packs/context-pack-types.js.map +1 -1
  116. package/daemon/dist/domain/context-packs/manifest-parser.d.ts.map +1 -1
  117. package/daemon/dist/domain/context-packs/manifest-parser.js +143 -3
  118. package/daemon/dist/domain/context-packs/manifest-parser.js.map +1 -1
  119. package/daemon/dist/domain/context-packs/profile-composer.d.ts +22 -1
  120. package/daemon/dist/domain/context-packs/profile-composer.d.ts.map +1 -1
  121. package/daemon/dist/domain/context-packs/profile-composer.js +105 -40
  122. package/daemon/dist/domain/context-packs/profile-composer.js.map +1 -1
  123. package/daemon/dist/domain/context-usage-store.d.ts +4 -0
  124. package/daemon/dist/domain/context-usage-store.d.ts.map +1 -1
  125. package/daemon/dist/domain/context-usage-store.js +8 -4
  126. package/daemon/dist/domain/context-usage-store.js.map +1 -1
  127. package/daemon/dist/domain/crash-cart-conductor.d.ts +13 -0
  128. package/daemon/dist/domain/crash-cart-conductor.d.ts.map +1 -1
  129. package/daemon/dist/domain/crash-cart-conductor.js +3 -1
  130. package/daemon/dist/domain/crash-cart-conductor.js.map +1 -1
  131. package/daemon/dist/domain/execution-view.d.ts.map +1 -1
  132. package/daemon/dist/domain/execution-view.js +145 -16
  133. package/daemon/dist/domain/execution-view.js.map +1 -1
  134. package/daemon/dist/domain/instance-initialization.d.ts +25 -0
  135. package/daemon/dist/domain/instance-initialization.d.ts.map +1 -0
  136. package/daemon/dist/domain/instance-initialization.js +81 -0
  137. package/daemon/dist/domain/instance-initialization.js.map +1 -0
  138. package/daemon/dist/domain/lifecycle-manifest.d.ts +19 -0
  139. package/daemon/dist/domain/lifecycle-manifest.d.ts.map +1 -0
  140. package/daemon/dist/domain/lifecycle-manifest.js +73 -0
  141. package/daemon/dist/domain/lifecycle-manifest.js.map +1 -0
  142. package/daemon/dist/domain/model-divergence/current-generation-record.d.ts +36 -36
  143. package/daemon/dist/domain/model-divergence/current-generation-record.d.ts.map +1 -1
  144. package/daemon/dist/domain/model-divergence/current-generation-record.js +104 -135
  145. package/daemon/dist/domain/model-divergence/current-generation-record.js.map +1 -1
  146. package/daemon/dist/domain/native-process-lineage.d.ts +10 -0
  147. package/daemon/dist/domain/native-process-lineage.d.ts.map +1 -0
  148. package/daemon/dist/domain/native-process-lineage.js +86 -0
  149. package/daemon/dist/domain/native-process-lineage.js.map +1 -0
  150. package/daemon/dist/domain/native-resume-probe.js +12 -1
  151. package/daemon/dist/domain/native-resume-probe.js.map +1 -1
  152. package/daemon/dist/domain/node-inventory.d.ts +2 -0
  153. package/daemon/dist/domain/node-inventory.d.ts.map +1 -1
  154. package/daemon/dist/domain/node-inventory.js +3 -1
  155. package/daemon/dist/domain/node-inventory.js.map +1 -1
  156. package/daemon/dist/domain/node-launcher.d.ts +3 -0
  157. package/daemon/dist/domain/node-launcher.d.ts.map +1 -1
  158. package/daemon/dist/domain/node-launcher.js +21 -8
  159. package/daemon/dist/domain/node-launcher.js.map +1 -1
  160. package/daemon/dist/domain/pane-binding-observation.d.ts +22 -0
  161. package/daemon/dist/domain/pane-binding-observation.d.ts.map +1 -0
  162. package/daemon/dist/domain/pane-binding-observation.js +54 -0
  163. package/daemon/dist/domain/pane-binding-observation.js.map +1 -0
  164. package/daemon/dist/domain/policies/parked-owner-consumer.js +1 -1
  165. package/daemon/dist/domain/policies/parked-owner-consumer.js.map +1 -1
  166. package/daemon/dist/domain/policies/workflow-keepalive.d.ts.map +1 -1
  167. package/daemon/dist/domain/policies/workflow-keepalive.js +16 -2
  168. package/daemon/dist/domain/policies/workflow-keepalive.js.map +1 -1
  169. package/daemon/dist/domain/profile-resolver.d.ts +12 -0
  170. package/daemon/dist/domain/profile-resolver.d.ts.map +1 -1
  171. package/daemon/dist/domain/profile-resolver.js +60 -0
  172. package/daemon/dist/domain/profile-resolver.js.map +1 -1
  173. package/daemon/dist/domain/project-lifecycle-compiler.d.ts +35 -0
  174. package/daemon/dist/domain/project-lifecycle-compiler.d.ts.map +1 -0
  175. package/daemon/dist/domain/project-lifecycle-compiler.js +190 -0
  176. package/daemon/dist/domain/project-lifecycle-compiler.js.map +1 -0
  177. package/daemon/dist/domain/provider/claude-usage-reader.d.ts +1 -1
  178. package/daemon/dist/domain/provider/claude-usage-reader.d.ts.map +1 -1
  179. package/daemon/dist/domain/provider/claude-usage-reader.js +28 -18
  180. package/daemon/dist/domain/provider/claude-usage-reader.js.map +1 -1
  181. package/daemon/dist/domain/queue-repository.d.ts +5 -1
  182. package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
  183. package/daemon/dist/domain/queue-repository.js +6 -0
  184. package/daemon/dist/domain/queue-repository.js.map +1 -1
  185. package/daemon/dist/domain/queue-retention.d.ts +3 -4
  186. package/daemon/dist/domain/queue-retention.d.ts.map +1 -1
  187. package/daemon/dist/domain/queue-retention.js +5 -8
  188. package/daemon/dist/domain/queue-retention.js.map +1 -1
  189. package/daemon/dist/domain/queue-transition-log.d.ts +28 -0
  190. package/daemon/dist/domain/queue-transition-log.d.ts.map +1 -1
  191. package/daemon/dist/domain/queue-transition-log.js +124 -0
  192. package/daemon/dist/domain/queue-transition-log.js.map +1 -1
  193. package/daemon/dist/domain/restore-attempt-receipt.d.ts +34 -0
  194. package/daemon/dist/domain/restore-attempt-receipt.d.ts.map +1 -0
  195. package/daemon/dist/domain/restore-attempt-receipt.js +59 -0
  196. package/daemon/dist/domain/restore-attempt-receipt.js.map +1 -0
  197. package/daemon/dist/domain/restore-orchestrator.d.ts +57 -24
  198. package/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
  199. package/daemon/dist/domain/restore-orchestrator.js +152 -26
  200. package/daemon/dist/domain/restore-orchestrator.js.map +1 -1
  201. package/daemon/dist/domain/restore-topology.d.ts +14 -0
  202. package/daemon/dist/domain/restore-topology.d.ts.map +1 -0
  203. package/daemon/dist/domain/restore-topology.js +27 -0
  204. package/daemon/dist/domain/restore-topology.js.map +1 -0
  205. package/daemon/dist/domain/rig-lifecycle-service.d.ts.map +1 -1
  206. package/daemon/dist/domain/rig-lifecycle-service.js +9 -0
  207. package/daemon/dist/domain/rig-lifecycle-service.js.map +1 -1
  208. package/daemon/dist/domain/rigspec-instantiator.d.ts +19 -0
  209. package/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
  210. package/daemon/dist/domain/rigspec-instantiator.js +65 -1
  211. package/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
  212. package/daemon/dist/domain/rigspec-preflight.d.ts +8 -0
  213. package/daemon/dist/domain/rigspec-preflight.d.ts.map +1 -1
  214. package/daemon/dist/domain/rigspec-preflight.js +4 -0
  215. package/daemon/dist/domain/rigspec-preflight.js.map +1 -1
  216. package/daemon/dist/domain/seat-attention-reconciler.d.ts +23 -1
  217. package/daemon/dist/domain/seat-attention-reconciler.d.ts.map +1 -1
  218. package/daemon/dist/domain/seat-attention-reconciler.js +97 -46
  219. package/daemon/dist/domain/seat-attention-reconciler.js.map +1 -1
  220. package/daemon/dist/domain/seat-identity-reconciler.d.ts.map +1 -1
  221. package/daemon/dist/domain/seat-identity-reconciler.js +15 -6
  222. package/daemon/dist/domain/seat-identity-reconciler.js.map +1 -1
  223. package/daemon/dist/domain/seat-lifecycle-service.d.ts +47 -1
  224. package/daemon/dist/domain/seat-lifecycle-service.d.ts.map +1 -1
  225. package/daemon/dist/domain/seat-lifecycle-service.js +525 -29
  226. package/daemon/dist/domain/seat-lifecycle-service.js.map +1 -1
  227. package/daemon/dist/domain/session-registry.d.ts +8 -1
  228. package/daemon/dist/domain/session-registry.d.ts.map +1 -1
  229. package/daemon/dist/domain/session-registry.js +19 -0
  230. package/daemon/dist/domain/session-registry.js.map +1 -1
  231. package/daemon/dist/domain/skill-catalog.d.ts +81 -0
  232. package/daemon/dist/domain/skill-catalog.d.ts.map +1 -0
  233. package/daemon/dist/domain/skill-catalog.js +827 -0
  234. package/daemon/dist/domain/skill-catalog.js.map +1 -0
  235. package/daemon/dist/domain/skill-discovery.d.ts +3 -0
  236. package/daemon/dist/domain/skill-discovery.d.ts.map +1 -1
  237. package/daemon/dist/domain/skill-discovery.js +1 -1
  238. package/daemon/dist/domain/skill-discovery.js.map +1 -1
  239. package/daemon/dist/domain/snapshot-capture.d.ts +4 -1
  240. package/daemon/dist/domain/snapshot-capture.d.ts.map +1 -1
  241. package/daemon/dist/domain/snapshot-capture.js +38 -2
  242. package/daemon/dist/domain/snapshot-capture.js.map +1 -1
  243. package/daemon/dist/domain/snapshot-repository.d.ts +15 -1
  244. package/daemon/dist/domain/snapshot-repository.d.ts.map +1 -1
  245. package/daemon/dist/domain/snapshot-repository.js +103 -1
  246. package/daemon/dist/domain/snapshot-repository.js.map +1 -1
  247. package/daemon/dist/domain/startup-orchestrator.d.ts +2 -0
  248. package/daemon/dist/domain/startup-orchestrator.d.ts.map +1 -1
  249. package/daemon/dist/domain/startup-orchestrator.js +12 -0
  250. package/daemon/dist/domain/startup-orchestrator.js.map +1 -1
  251. package/daemon/dist/domain/system-world.d.ts +45 -0
  252. package/daemon/dist/domain/system-world.d.ts.map +1 -0
  253. package/daemon/dist/domain/system-world.js +123 -0
  254. package/daemon/dist/domain/system-world.js.map +1 -0
  255. package/daemon/dist/domain/telemetry-state-paths.d.ts +7 -0
  256. package/daemon/dist/domain/telemetry-state-paths.d.ts.map +1 -0
  257. package/daemon/dist/domain/telemetry-state-paths.js +20 -0
  258. package/daemon/dist/domain/telemetry-state-paths.js.map +1 -0
  259. package/daemon/dist/domain/types.d.ts +103 -4
  260. package/daemon/dist/domain/types.d.ts.map +1 -1
  261. package/daemon/dist/domain/types.js.map +1 -1
  262. package/daemon/dist/domain/user-settings/settings-store.d.ts +8 -3
  263. package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
  264. package/daemon/dist/domain/user-settings/settings-store.js +65 -29
  265. package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
  266. package/daemon/dist/domain/watchdog-policy-engine.d.ts +7 -23
  267. package/daemon/dist/domain/watchdog-policy-engine.d.ts.map +1 -1
  268. package/daemon/dist/domain/watchdog-policy-engine.js +44 -226
  269. package/daemon/dist/domain/watchdog-policy-engine.js.map +1 -1
  270. package/daemon/dist/domain/workflow-boot-sweep.d.ts.map +1 -1
  271. package/daemon/dist/domain/workflow-boot-sweep.js +20 -6
  272. package/daemon/dist/domain/workflow-boot-sweep.js.map +1 -1
  273. package/daemon/dist/domain/workflow-instance-store.d.ts +33 -1
  274. package/daemon/dist/domain/workflow-instance-store.d.ts.map +1 -1
  275. package/daemon/dist/domain/workflow-instance-store.js +127 -2
  276. package/daemon/dist/domain/workflow-instance-store.js.map +1 -1
  277. package/daemon/dist/domain/workflow-keepalive-arming.d.ts +7 -5
  278. package/daemon/dist/domain/workflow-keepalive-arming.d.ts.map +1 -1
  279. package/daemon/dist/domain/workflow-keepalive-arming.js +27 -16
  280. package/daemon/dist/domain/workflow-keepalive-arming.js.map +1 -1
  281. package/daemon/dist/domain/workflow-projector.d.ts +6 -2
  282. package/daemon/dist/domain/workflow-projector.d.ts.map +1 -1
  283. package/daemon/dist/domain/workflow-projector.js +271 -2
  284. package/daemon/dist/domain/workflow-projector.js.map +1 -1
  285. package/daemon/dist/domain/workflow-runtime.d.ts +62 -2
  286. package/daemon/dist/domain/workflow-runtime.d.ts.map +1 -1
  287. package/daemon/dist/domain/workflow-runtime.js +334 -18
  288. package/daemon/dist/domain/workflow-runtime.js.map +1 -1
  289. package/daemon/dist/domain/workflow-spec-cache.d.ts +9 -1
  290. package/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -1
  291. package/daemon/dist/domain/workflow-spec-cache.js +85 -0
  292. package/daemon/dist/domain/workflow-spec-cache.js.map +1 -1
  293. package/daemon/dist/domain/workflow-types.d.ts +38 -1
  294. package/daemon/dist/domain/workflow-types.d.ts.map +1 -1
  295. package/daemon/dist/domain/workflow-types.js.map +1 -1
  296. package/daemon/dist/domain/workflow-validator.d.ts.map +1 -1
  297. package/daemon/dist/domain/workflow-validator.js +20 -3
  298. package/daemon/dist/domain/workflow-validator.js.map +1 -1
  299. package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts +38 -9
  300. package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
  301. package/daemon/dist/domain/workspace/default-workspace-scaffold.js +93 -347
  302. package/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
  303. package/daemon/dist/index.d.ts.map +1 -1
  304. package/daemon/dist/index.js +13 -0
  305. package/daemon/dist/index.js.map +1 -1
  306. package/daemon/dist/instance-initialization-surface.d.ts +3 -0
  307. package/daemon/dist/instance-initialization-surface.d.ts.map +1 -0
  308. package/daemon/dist/instance-initialization-surface.js +3 -0
  309. package/daemon/dist/instance-initialization-surface.js.map +1 -0
  310. package/daemon/dist/project-lifecycle-surface.d.ts +3 -0
  311. package/daemon/dist/project-lifecycle-surface.d.ts.map +1 -0
  312. package/daemon/dist/project-lifecycle-surface.js +3 -0
  313. package/daemon/dist/project-lifecycle-surface.js.map +1 -0
  314. package/daemon/dist/routes/bundles.js +10 -9
  315. package/daemon/dist/routes/bundles.js.map +1 -1
  316. package/daemon/dist/routes/config.d.ts.map +1 -1
  317. package/daemon/dist/routes/config.js +27 -49
  318. package/daemon/dist/routes/config.js.map +1 -1
  319. package/daemon/dist/routes/context-packs.d.ts.map +1 -1
  320. package/daemon/dist/routes/context-packs.js +114 -16
  321. package/daemon/dist/routes/context-packs.js.map +1 -1
  322. package/daemon/dist/routes/crash-cart.js +3 -0
  323. package/daemon/dist/routes/crash-cart.js.map +1 -1
  324. package/daemon/dist/routes/queue.d.ts.map +1 -1
  325. package/daemon/dist/routes/queue.js +20 -0
  326. package/daemon/dist/routes/queue.js.map +1 -1
  327. package/daemon/dist/routes/rigs.js +12 -1
  328. package/daemon/dist/routes/rigs.js.map +1 -1
  329. package/daemon/dist/routes/rigspec.js +9 -2
  330. package/daemon/dist/routes/rigspec.js.map +1 -1
  331. package/daemon/dist/routes/seat.js +21 -1
  332. package/daemon/dist/routes/seat.js.map +1 -1
  333. package/daemon/dist/routes/sessions.js +16 -6
  334. package/daemon/dist/routes/sessions.js.map +1 -1
  335. package/daemon/dist/routes/snapshots.d.ts.map +1 -1
  336. package/daemon/dist/routes/snapshots.js +41 -3
  337. package/daemon/dist/routes/snapshots.js.map +1 -1
  338. package/daemon/dist/routes/up.js +12 -1
  339. package/daemon/dist/routes/up.js.map +1 -1
  340. package/daemon/dist/routes/watchdog.d.ts.map +1 -1
  341. package/daemon/dist/routes/watchdog.js +7 -6
  342. package/daemon/dist/routes/watchdog.js.map +1 -1
  343. package/daemon/dist/routes/workflow.d.ts.map +1 -1
  344. package/daemon/dist/routes/workflow.js +104 -39
  345. package/daemon/dist/routes/workflow.js.map +1 -1
  346. package/daemon/dist/server.d.ts +2 -0
  347. package/daemon/dist/server.d.ts.map +1 -1
  348. package/daemon/dist/server.js +1 -0
  349. package/daemon/dist/server.js.map +1 -1
  350. package/daemon/dist/skill-loadout-surface.d.ts +3 -0
  351. package/daemon/dist/skill-loadout-surface.d.ts.map +1 -0
  352. package/daemon/dist/skill-loadout-surface.js +2 -0
  353. package/daemon/dist/skill-loadout-surface.js.map +1 -0
  354. package/daemon/dist/startup.d.ts.map +1 -1
  355. package/daemon/dist/startup.js +72 -65
  356. package/daemon/dist/startup.js.map +1 -1
  357. package/daemon/dist/system-world-surface.d.ts +2 -0
  358. package/daemon/dist/system-world-surface.d.ts.map +1 -0
  359. package/daemon/dist/system-world-surface.js +2 -0
  360. package/daemon/dist/system-world-surface.js.map +1 -0
  361. package/daemon/docs/reference/getting-started.md +2 -1
  362. package/daemon/docs/reference/instance-layout.md +106 -0
  363. package/daemon/docs/reference/mission-install.md +12 -2
  364. package/daemon/docs/reference/project-workspace.md +66 -40
  365. package/daemon/specs/agents/shared/skills/core/openrig-skills/SKILL.md +4 -2
  366. package/daemon/specs/agents/shared/skills/core/openrig-upgrade/SKILL.md +81 -0
  367. package/daemon/specs/agents/shared/skills/core/openrig-upgrade/scripts/migrate-telemetry-state-0.5.9.mjs +1419 -0
  368. package/dist/build-info.js +3 -3
  369. package/dist/commands/config-init-workspace.d.ts +4 -23
  370. package/dist/commands/config-init-workspace.d.ts.map +1 -1
  371. package/dist/commands/config-init-workspace.js +14 -576
  372. package/dist/commands/config-init-workspace.js.map +1 -1
  373. package/dist/commands/config.d.ts.map +1 -1
  374. package/dist/commands/config.js +6 -4
  375. package/dist/commands/config.js.map +1 -1
  376. package/dist/commands/context.d.ts.map +1 -1
  377. package/dist/commands/context.js +114 -8
  378. package/dist/commands/context.js.map +1 -1
  379. package/dist/commands/daemon.d.ts.map +1 -1
  380. package/dist/commands/daemon.js +16 -0
  381. package/dist/commands/daemon.js.map +1 -1
  382. package/dist/commands/launch.d.ts.map +1 -1
  383. package/dist/commands/launch.js +51 -4
  384. package/dist/commands/launch.js.map +1 -1
  385. package/dist/commands/restore.d.ts.map +1 -1
  386. package/dist/commands/restore.js +43 -3
  387. package/dist/commands/restore.js.map +1 -1
  388. package/dist/commands/scope.d.ts.map +1 -1
  389. package/dist/commands/scope.js +169 -79
  390. package/dist/commands/scope.js.map +1 -1
  391. package/dist/commands/seat.d.ts.map +1 -1
  392. package/dist/commands/seat.js +30 -0
  393. package/dist/commands/seat.js.map +1 -1
  394. package/dist/commands/skill.d.ts.map +1 -1
  395. package/dist/commands/skill.js +61 -0
  396. package/dist/commands/skill.js.map +1 -1
  397. package/dist/commands/snapshot.d.ts.map +1 -1
  398. package/dist/commands/snapshot.js +4 -2
  399. package/dist/commands/snapshot.js.map +1 -1
  400. package/dist/commands/start.d.ts.map +1 -1
  401. package/dist/commands/start.js +3 -0
  402. package/dist/commands/start.js.map +1 -1
  403. package/dist/commands/up.d.ts.map +1 -1
  404. package/dist/commands/up.js +3 -0
  405. package/dist/commands/up.js.map +1 -1
  406. package/dist/commands/walk.d.ts.map +1 -1
  407. package/dist/commands/walk.js +3 -0
  408. package/dist/commands/walk.js.map +1 -1
  409. package/dist/commands/workflow-render.d.ts +31 -0
  410. package/dist/commands/workflow-render.d.ts.map +1 -1
  411. package/dist/commands/workflow-render.js +84 -6
  412. package/dist/commands/workflow-render.js.map +1 -1
  413. package/dist/commands/workflow.d.ts.map +1 -1
  414. package/dist/commands/workflow.js +96 -8
  415. package/dist/commands/workflow.js.map +1 -1
  416. package/dist/config-store.d.ts +9 -4
  417. package/dist/config-store.d.ts.map +1 -1
  418. package/dist/config-store.js +67 -30
  419. package/dist/config-store.js.map +1 -1
  420. package/dist/daemon-lifecycle.d.ts +8 -15
  421. package/dist/daemon-lifecycle.d.ts.map +1 -1
  422. package/dist/daemon-lifecycle.js +24 -31
  423. package/dist/daemon-lifecycle.js.map +1 -1
  424. package/dist/lib/scope/mission-composition.d.ts +16 -0
  425. package/dist/lib/scope/mission-composition.d.ts.map +1 -0
  426. package/dist/lib/scope/mission-composition.js +110 -0
  427. package/dist/lib/scope/mission-composition.js.map +1 -0
  428. package/dist/lib/scope/scope-fs.d.ts +5 -0
  429. package/dist/lib/scope/scope-fs.d.ts.map +1 -1
  430. package/dist/lib/scope/scope-fs.js +34 -4
  431. package/dist/lib/scope/scope-fs.js.map +1 -1
  432. package/dist/lib/work-install.d.ts +17 -0
  433. package/dist/lib/work-install.d.ts.map +1 -1
  434. package/dist/lib/work-install.js +49 -6
  435. package/dist/lib/work-install.js.map +1 -1
  436. package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
  437. package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.js +4 -2
  438. package/node_modules/@openrig/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
  439. package/node_modules/@openrig/daemon/dist/build-info.js +3 -3
  440. package/node_modules/@openrig/daemon/dist/db/all-migrations.d.ts +1 -1
  441. package/node_modules/@openrig/daemon/dist/db/all-migrations.d.ts.map +1 -1
  442. package/node_modules/@openrig/daemon/dist/db/all-migrations.js +3 -1
  443. package/node_modules/@openrig/daemon/dist/db/all-migrations.js.map +1 -1
  444. package/node_modules/@openrig/daemon/dist/db/migrations/046_seat_identity_verdicts.d.ts +8 -5
  445. package/node_modules/@openrig/daemon/dist/db/migrations/046_seat_identity_verdicts.d.ts.map +1 -1
  446. package/node_modules/@openrig/daemon/dist/db/migrations/046_seat_identity_verdicts.js +8 -5
  447. package/node_modules/@openrig/daemon/dist/db/migrations/046_seat_identity_verdicts.js.map +1 -1
  448. package/node_modules/@openrig/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.d.ts +8 -0
  449. package/node_modules/@openrig/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.d.ts.map +1 -0
  450. package/node_modules/@openrig/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.js +50 -0
  451. package/node_modules/@openrig/daemon/dist/db/migrations/079_workflow_lifecycle_parallel.js.map +1 -0
  452. package/node_modules/@openrig/daemon/dist/domain/active-occupant.d.ts +6 -1
  453. package/node_modules/@openrig/daemon/dist/domain/active-occupant.d.ts.map +1 -1
  454. package/node_modules/@openrig/daemon/dist/domain/active-occupant.js +47 -0
  455. package/node_modules/@openrig/daemon/dist/domain/active-occupant.js.map +1 -1
  456. package/node_modules/@openrig/daemon/dist/domain/bootstrap-orchestrator.d.ts.map +1 -1
  457. package/node_modules/@openrig/daemon/dist/domain/bootstrap-orchestrator.js +8 -1
  458. package/node_modules/@openrig/daemon/dist/domain/bootstrap-orchestrator.js.map +1 -1
  459. package/node_modules/@openrig/daemon/dist/domain/bundle-context-packs-router.d.ts +3 -3
  460. package/node_modules/@openrig/daemon/dist/domain/bundle-context-packs-router.d.ts.map +1 -1
  461. package/node_modules/@openrig/daemon/dist/domain/bundle-skills-router.d.ts +3 -0
  462. package/node_modules/@openrig/daemon/dist/domain/bundle-skills-router.d.ts.map +1 -1
  463. package/node_modules/@openrig/daemon/dist/domain/bundle-skills-router.js +5 -1
  464. package/node_modules/@openrig/daemon/dist/domain/bundle-skills-router.js.map +1 -1
  465. package/node_modules/@openrig/daemon/dist/domain/claim-service.d.ts +2 -0
  466. package/node_modules/@openrig/daemon/dist/domain/claim-service.d.ts.map +1 -1
  467. package/node_modules/@openrig/daemon/dist/domain/claim-service.js +33 -12
  468. package/node_modules/@openrig/daemon/dist/domain/claim-service.js.map +1 -1
  469. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-library-service.d.ts.map +1 -1
  470. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-library-service.js +9 -1
  471. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-library-service.js.map +1 -1
  472. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-types.d.ts +25 -0
  473. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-types.d.ts.map +1 -1
  474. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-types.js +3 -1
  475. package/node_modules/@openrig/daemon/dist/domain/context-packs/context-pack-types.js.map +1 -1
  476. package/node_modules/@openrig/daemon/dist/domain/context-packs/manifest-parser.d.ts.map +1 -1
  477. package/node_modules/@openrig/daemon/dist/domain/context-packs/manifest-parser.js +143 -3
  478. package/node_modules/@openrig/daemon/dist/domain/context-packs/manifest-parser.js.map +1 -1
  479. package/node_modules/@openrig/daemon/dist/domain/context-packs/profile-composer.d.ts +22 -1
  480. package/node_modules/@openrig/daemon/dist/domain/context-packs/profile-composer.d.ts.map +1 -1
  481. package/node_modules/@openrig/daemon/dist/domain/context-packs/profile-composer.js +105 -40
  482. package/node_modules/@openrig/daemon/dist/domain/context-packs/profile-composer.js.map +1 -1
  483. package/node_modules/@openrig/daemon/dist/domain/context-usage-store.d.ts +4 -0
  484. package/node_modules/@openrig/daemon/dist/domain/context-usage-store.d.ts.map +1 -1
  485. package/node_modules/@openrig/daemon/dist/domain/context-usage-store.js +8 -4
  486. package/node_modules/@openrig/daemon/dist/domain/context-usage-store.js.map +1 -1
  487. package/node_modules/@openrig/daemon/dist/domain/crash-cart-conductor.d.ts +13 -0
  488. package/node_modules/@openrig/daemon/dist/domain/crash-cart-conductor.d.ts.map +1 -1
  489. package/node_modules/@openrig/daemon/dist/domain/crash-cart-conductor.js +3 -1
  490. package/node_modules/@openrig/daemon/dist/domain/crash-cart-conductor.js.map +1 -1
  491. package/node_modules/@openrig/daemon/dist/domain/execution-view.d.ts.map +1 -1
  492. package/node_modules/@openrig/daemon/dist/domain/execution-view.js +145 -16
  493. package/node_modules/@openrig/daemon/dist/domain/execution-view.js.map +1 -1
  494. package/node_modules/@openrig/daemon/dist/domain/instance-initialization.d.ts +25 -0
  495. package/node_modules/@openrig/daemon/dist/domain/instance-initialization.d.ts.map +1 -0
  496. package/node_modules/@openrig/daemon/dist/domain/instance-initialization.js +81 -0
  497. package/node_modules/@openrig/daemon/dist/domain/instance-initialization.js.map +1 -0
  498. package/node_modules/@openrig/daemon/dist/domain/lifecycle-manifest.d.ts +19 -0
  499. package/node_modules/@openrig/daemon/dist/domain/lifecycle-manifest.d.ts.map +1 -0
  500. package/node_modules/@openrig/daemon/dist/domain/lifecycle-manifest.js +73 -0
  501. package/node_modules/@openrig/daemon/dist/domain/lifecycle-manifest.js.map +1 -0
  502. package/node_modules/@openrig/daemon/dist/domain/model-divergence/current-generation-record.d.ts +36 -36
  503. package/node_modules/@openrig/daemon/dist/domain/model-divergence/current-generation-record.d.ts.map +1 -1
  504. package/node_modules/@openrig/daemon/dist/domain/model-divergence/current-generation-record.js +104 -135
  505. package/node_modules/@openrig/daemon/dist/domain/model-divergence/current-generation-record.js.map +1 -1
  506. package/node_modules/@openrig/daemon/dist/domain/native-process-lineage.d.ts +10 -0
  507. package/node_modules/@openrig/daemon/dist/domain/native-process-lineage.d.ts.map +1 -0
  508. package/node_modules/@openrig/daemon/dist/domain/native-process-lineage.js +86 -0
  509. package/node_modules/@openrig/daemon/dist/domain/native-process-lineage.js.map +1 -0
  510. package/node_modules/@openrig/daemon/dist/domain/native-resume-probe.js +12 -1
  511. package/node_modules/@openrig/daemon/dist/domain/native-resume-probe.js.map +1 -1
  512. package/node_modules/@openrig/daemon/dist/domain/node-inventory.d.ts +2 -0
  513. package/node_modules/@openrig/daemon/dist/domain/node-inventory.d.ts.map +1 -1
  514. package/node_modules/@openrig/daemon/dist/domain/node-inventory.js +3 -1
  515. package/node_modules/@openrig/daemon/dist/domain/node-inventory.js.map +1 -1
  516. package/node_modules/@openrig/daemon/dist/domain/node-launcher.d.ts +3 -0
  517. package/node_modules/@openrig/daemon/dist/domain/node-launcher.d.ts.map +1 -1
  518. package/node_modules/@openrig/daemon/dist/domain/node-launcher.js +21 -8
  519. package/node_modules/@openrig/daemon/dist/domain/node-launcher.js.map +1 -1
  520. package/node_modules/@openrig/daemon/dist/domain/pane-binding-observation.d.ts +22 -0
  521. package/node_modules/@openrig/daemon/dist/domain/pane-binding-observation.d.ts.map +1 -0
  522. package/node_modules/@openrig/daemon/dist/domain/pane-binding-observation.js +54 -0
  523. package/node_modules/@openrig/daemon/dist/domain/pane-binding-observation.js.map +1 -0
  524. package/node_modules/@openrig/daemon/dist/domain/policies/parked-owner-consumer.js +1 -1
  525. package/node_modules/@openrig/daemon/dist/domain/policies/parked-owner-consumer.js.map +1 -1
  526. package/node_modules/@openrig/daemon/dist/domain/policies/workflow-keepalive.d.ts.map +1 -1
  527. package/node_modules/@openrig/daemon/dist/domain/policies/workflow-keepalive.js +16 -2
  528. package/node_modules/@openrig/daemon/dist/domain/policies/workflow-keepalive.js.map +1 -1
  529. package/node_modules/@openrig/daemon/dist/domain/profile-resolver.d.ts +12 -0
  530. package/node_modules/@openrig/daemon/dist/domain/profile-resolver.d.ts.map +1 -1
  531. package/node_modules/@openrig/daemon/dist/domain/profile-resolver.js +60 -0
  532. package/node_modules/@openrig/daemon/dist/domain/profile-resolver.js.map +1 -1
  533. package/node_modules/@openrig/daemon/dist/domain/project-lifecycle-compiler.d.ts +35 -0
  534. package/node_modules/@openrig/daemon/dist/domain/project-lifecycle-compiler.d.ts.map +1 -0
  535. package/node_modules/@openrig/daemon/dist/domain/project-lifecycle-compiler.js +190 -0
  536. package/node_modules/@openrig/daemon/dist/domain/project-lifecycle-compiler.js.map +1 -0
  537. package/node_modules/@openrig/daemon/dist/domain/provider/claude-usage-reader.d.ts +1 -1
  538. package/node_modules/@openrig/daemon/dist/domain/provider/claude-usage-reader.d.ts.map +1 -1
  539. package/node_modules/@openrig/daemon/dist/domain/provider/claude-usage-reader.js +28 -18
  540. package/node_modules/@openrig/daemon/dist/domain/provider/claude-usage-reader.js.map +1 -1
  541. package/node_modules/@openrig/daemon/dist/domain/queue-repository.d.ts +5 -1
  542. package/node_modules/@openrig/daemon/dist/domain/queue-repository.d.ts.map +1 -1
  543. package/node_modules/@openrig/daemon/dist/domain/queue-repository.js +6 -0
  544. package/node_modules/@openrig/daemon/dist/domain/queue-repository.js.map +1 -1
  545. package/node_modules/@openrig/daemon/dist/domain/queue-retention.d.ts +3 -4
  546. package/node_modules/@openrig/daemon/dist/domain/queue-retention.d.ts.map +1 -1
  547. package/node_modules/@openrig/daemon/dist/domain/queue-retention.js +5 -8
  548. package/node_modules/@openrig/daemon/dist/domain/queue-retention.js.map +1 -1
  549. package/node_modules/@openrig/daemon/dist/domain/queue-transition-log.d.ts +28 -0
  550. package/node_modules/@openrig/daemon/dist/domain/queue-transition-log.d.ts.map +1 -1
  551. package/node_modules/@openrig/daemon/dist/domain/queue-transition-log.js +124 -0
  552. package/node_modules/@openrig/daemon/dist/domain/queue-transition-log.js.map +1 -1
  553. package/node_modules/@openrig/daemon/dist/domain/restore-attempt-receipt.d.ts +34 -0
  554. package/node_modules/@openrig/daemon/dist/domain/restore-attempt-receipt.d.ts.map +1 -0
  555. package/node_modules/@openrig/daemon/dist/domain/restore-attempt-receipt.js +59 -0
  556. package/node_modules/@openrig/daemon/dist/domain/restore-attempt-receipt.js.map +1 -0
  557. package/node_modules/@openrig/daemon/dist/domain/restore-orchestrator.d.ts +57 -24
  558. package/node_modules/@openrig/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
  559. package/node_modules/@openrig/daemon/dist/domain/restore-orchestrator.js +152 -26
  560. package/node_modules/@openrig/daemon/dist/domain/restore-orchestrator.js.map +1 -1
  561. package/node_modules/@openrig/daemon/dist/domain/restore-topology.d.ts +14 -0
  562. package/node_modules/@openrig/daemon/dist/domain/restore-topology.d.ts.map +1 -0
  563. package/node_modules/@openrig/daemon/dist/domain/restore-topology.js +27 -0
  564. package/node_modules/@openrig/daemon/dist/domain/restore-topology.js.map +1 -0
  565. package/node_modules/@openrig/daemon/dist/domain/rig-lifecycle-service.d.ts.map +1 -1
  566. package/node_modules/@openrig/daemon/dist/domain/rig-lifecycle-service.js +9 -0
  567. package/node_modules/@openrig/daemon/dist/domain/rig-lifecycle-service.js.map +1 -1
  568. package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.d.ts +19 -0
  569. package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
  570. package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.js +65 -1
  571. package/node_modules/@openrig/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
  572. package/node_modules/@openrig/daemon/dist/domain/rigspec-preflight.d.ts +8 -0
  573. package/node_modules/@openrig/daemon/dist/domain/rigspec-preflight.d.ts.map +1 -1
  574. package/node_modules/@openrig/daemon/dist/domain/rigspec-preflight.js +4 -0
  575. package/node_modules/@openrig/daemon/dist/domain/rigspec-preflight.js.map +1 -1
  576. package/node_modules/@openrig/daemon/dist/domain/seat-attention-reconciler.d.ts +23 -1
  577. package/node_modules/@openrig/daemon/dist/domain/seat-attention-reconciler.d.ts.map +1 -1
  578. package/node_modules/@openrig/daemon/dist/domain/seat-attention-reconciler.js +97 -46
  579. package/node_modules/@openrig/daemon/dist/domain/seat-attention-reconciler.js.map +1 -1
  580. package/node_modules/@openrig/daemon/dist/domain/seat-identity-reconciler.d.ts.map +1 -1
  581. package/node_modules/@openrig/daemon/dist/domain/seat-identity-reconciler.js +15 -6
  582. package/node_modules/@openrig/daemon/dist/domain/seat-identity-reconciler.js.map +1 -1
  583. package/node_modules/@openrig/daemon/dist/domain/seat-lifecycle-service.d.ts +47 -1
  584. package/node_modules/@openrig/daemon/dist/domain/seat-lifecycle-service.d.ts.map +1 -1
  585. package/node_modules/@openrig/daemon/dist/domain/seat-lifecycle-service.js +525 -29
  586. package/node_modules/@openrig/daemon/dist/domain/seat-lifecycle-service.js.map +1 -1
  587. package/node_modules/@openrig/daemon/dist/domain/session-registry.d.ts +8 -1
  588. package/node_modules/@openrig/daemon/dist/domain/session-registry.d.ts.map +1 -1
  589. package/node_modules/@openrig/daemon/dist/domain/session-registry.js +19 -0
  590. package/node_modules/@openrig/daemon/dist/domain/session-registry.js.map +1 -1
  591. package/node_modules/@openrig/daemon/dist/domain/skill-catalog.d.ts +81 -0
  592. package/node_modules/@openrig/daemon/dist/domain/skill-catalog.d.ts.map +1 -0
  593. package/node_modules/@openrig/daemon/dist/domain/skill-catalog.js +827 -0
  594. package/node_modules/@openrig/daemon/dist/domain/skill-catalog.js.map +1 -0
  595. package/node_modules/@openrig/daemon/dist/domain/skill-discovery.d.ts +3 -0
  596. package/node_modules/@openrig/daemon/dist/domain/skill-discovery.d.ts.map +1 -1
  597. package/node_modules/@openrig/daemon/dist/domain/skill-discovery.js +1 -1
  598. package/node_modules/@openrig/daemon/dist/domain/skill-discovery.js.map +1 -1
  599. package/node_modules/@openrig/daemon/dist/domain/snapshot-capture.d.ts +4 -1
  600. package/node_modules/@openrig/daemon/dist/domain/snapshot-capture.d.ts.map +1 -1
  601. package/node_modules/@openrig/daemon/dist/domain/snapshot-capture.js +38 -2
  602. package/node_modules/@openrig/daemon/dist/domain/snapshot-capture.js.map +1 -1
  603. package/node_modules/@openrig/daemon/dist/domain/snapshot-repository.d.ts +15 -1
  604. package/node_modules/@openrig/daemon/dist/domain/snapshot-repository.d.ts.map +1 -1
  605. package/node_modules/@openrig/daemon/dist/domain/snapshot-repository.js +103 -1
  606. package/node_modules/@openrig/daemon/dist/domain/snapshot-repository.js.map +1 -1
  607. package/node_modules/@openrig/daemon/dist/domain/startup-orchestrator.d.ts +2 -0
  608. package/node_modules/@openrig/daemon/dist/domain/startup-orchestrator.d.ts.map +1 -1
  609. package/node_modules/@openrig/daemon/dist/domain/startup-orchestrator.js +12 -0
  610. package/node_modules/@openrig/daemon/dist/domain/startup-orchestrator.js.map +1 -1
  611. package/node_modules/@openrig/daemon/dist/domain/system-world.d.ts +45 -0
  612. package/node_modules/@openrig/daemon/dist/domain/system-world.d.ts.map +1 -0
  613. package/node_modules/@openrig/daemon/dist/domain/system-world.js +123 -0
  614. package/node_modules/@openrig/daemon/dist/domain/system-world.js.map +1 -0
  615. package/node_modules/@openrig/daemon/dist/domain/telemetry-state-paths.d.ts +7 -0
  616. package/node_modules/@openrig/daemon/dist/domain/telemetry-state-paths.d.ts.map +1 -0
  617. package/node_modules/@openrig/daemon/dist/domain/telemetry-state-paths.js +20 -0
  618. package/node_modules/@openrig/daemon/dist/domain/telemetry-state-paths.js.map +1 -0
  619. package/node_modules/@openrig/daemon/dist/domain/types.d.ts +103 -4
  620. package/node_modules/@openrig/daemon/dist/domain/types.d.ts.map +1 -1
  621. package/node_modules/@openrig/daemon/dist/domain/types.js.map +1 -1
  622. package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.d.ts +8 -3
  623. package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
  624. package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.js +65 -29
  625. package/node_modules/@openrig/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
  626. package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.d.ts +7 -23
  627. package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.d.ts.map +1 -1
  628. package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.js +44 -226
  629. package/node_modules/@openrig/daemon/dist/domain/watchdog-policy-engine.js.map +1 -1
  630. package/node_modules/@openrig/daemon/dist/domain/workflow-boot-sweep.d.ts.map +1 -1
  631. package/node_modules/@openrig/daemon/dist/domain/workflow-boot-sweep.js +20 -6
  632. package/node_modules/@openrig/daemon/dist/domain/workflow-boot-sweep.js.map +1 -1
  633. package/node_modules/@openrig/daemon/dist/domain/workflow-instance-store.d.ts +33 -1
  634. package/node_modules/@openrig/daemon/dist/domain/workflow-instance-store.d.ts.map +1 -1
  635. package/node_modules/@openrig/daemon/dist/domain/workflow-instance-store.js +127 -2
  636. package/node_modules/@openrig/daemon/dist/domain/workflow-instance-store.js.map +1 -1
  637. package/node_modules/@openrig/daemon/dist/domain/workflow-keepalive-arming.d.ts +7 -5
  638. package/node_modules/@openrig/daemon/dist/domain/workflow-keepalive-arming.d.ts.map +1 -1
  639. package/node_modules/@openrig/daemon/dist/domain/workflow-keepalive-arming.js +27 -16
  640. package/node_modules/@openrig/daemon/dist/domain/workflow-keepalive-arming.js.map +1 -1
  641. package/node_modules/@openrig/daemon/dist/domain/workflow-projector.d.ts +6 -2
  642. package/node_modules/@openrig/daemon/dist/domain/workflow-projector.d.ts.map +1 -1
  643. package/node_modules/@openrig/daemon/dist/domain/workflow-projector.js +271 -2
  644. package/node_modules/@openrig/daemon/dist/domain/workflow-projector.js.map +1 -1
  645. package/node_modules/@openrig/daemon/dist/domain/workflow-runtime.d.ts +62 -2
  646. package/node_modules/@openrig/daemon/dist/domain/workflow-runtime.d.ts.map +1 -1
  647. package/node_modules/@openrig/daemon/dist/domain/workflow-runtime.js +334 -18
  648. package/node_modules/@openrig/daemon/dist/domain/workflow-runtime.js.map +1 -1
  649. package/node_modules/@openrig/daemon/dist/domain/workflow-spec-cache.d.ts +9 -1
  650. package/node_modules/@openrig/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -1
  651. package/node_modules/@openrig/daemon/dist/domain/workflow-spec-cache.js +85 -0
  652. package/node_modules/@openrig/daemon/dist/domain/workflow-spec-cache.js.map +1 -1
  653. package/node_modules/@openrig/daemon/dist/domain/workflow-types.d.ts +38 -1
  654. package/node_modules/@openrig/daemon/dist/domain/workflow-types.d.ts.map +1 -1
  655. package/node_modules/@openrig/daemon/dist/domain/workflow-types.js.map +1 -1
  656. package/node_modules/@openrig/daemon/dist/domain/workflow-validator.d.ts.map +1 -1
  657. package/node_modules/@openrig/daemon/dist/domain/workflow-validator.js +20 -3
  658. package/node_modules/@openrig/daemon/dist/domain/workflow-validator.js.map +1 -1
  659. package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts +38 -9
  660. package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
  661. package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.js +93 -347
  662. package/node_modules/@openrig/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
  663. package/node_modules/@openrig/daemon/dist/index.d.ts.map +1 -1
  664. package/node_modules/@openrig/daemon/dist/index.js +13 -0
  665. package/node_modules/@openrig/daemon/dist/index.js.map +1 -1
  666. package/node_modules/@openrig/daemon/dist/instance-initialization-surface.d.ts +3 -0
  667. package/node_modules/@openrig/daemon/dist/instance-initialization-surface.d.ts.map +1 -0
  668. package/node_modules/@openrig/daemon/dist/instance-initialization-surface.js +3 -0
  669. package/node_modules/@openrig/daemon/dist/instance-initialization-surface.js.map +1 -0
  670. package/node_modules/@openrig/daemon/dist/project-lifecycle-surface.d.ts +3 -0
  671. package/node_modules/@openrig/daemon/dist/project-lifecycle-surface.d.ts.map +1 -0
  672. package/node_modules/@openrig/daemon/dist/project-lifecycle-surface.js +3 -0
  673. package/node_modules/@openrig/daemon/dist/project-lifecycle-surface.js.map +1 -0
  674. package/node_modules/@openrig/daemon/dist/routes/bundles.js +10 -9
  675. package/node_modules/@openrig/daemon/dist/routes/bundles.js.map +1 -1
  676. package/node_modules/@openrig/daemon/dist/routes/config.d.ts.map +1 -1
  677. package/node_modules/@openrig/daemon/dist/routes/config.js +27 -49
  678. package/node_modules/@openrig/daemon/dist/routes/config.js.map +1 -1
  679. package/node_modules/@openrig/daemon/dist/routes/context-packs.d.ts.map +1 -1
  680. package/node_modules/@openrig/daemon/dist/routes/context-packs.js +114 -16
  681. package/node_modules/@openrig/daemon/dist/routes/context-packs.js.map +1 -1
  682. package/node_modules/@openrig/daemon/dist/routes/crash-cart.js +3 -0
  683. package/node_modules/@openrig/daemon/dist/routes/crash-cart.js.map +1 -1
  684. package/node_modules/@openrig/daemon/dist/routes/queue.d.ts.map +1 -1
  685. package/node_modules/@openrig/daemon/dist/routes/queue.js +20 -0
  686. package/node_modules/@openrig/daemon/dist/routes/queue.js.map +1 -1
  687. package/node_modules/@openrig/daemon/dist/routes/rigs.js +12 -1
  688. package/node_modules/@openrig/daemon/dist/routes/rigs.js.map +1 -1
  689. package/node_modules/@openrig/daemon/dist/routes/rigspec.js +9 -2
  690. package/node_modules/@openrig/daemon/dist/routes/rigspec.js.map +1 -1
  691. package/node_modules/@openrig/daemon/dist/routes/seat.js +21 -1
  692. package/node_modules/@openrig/daemon/dist/routes/seat.js.map +1 -1
  693. package/node_modules/@openrig/daemon/dist/routes/sessions.js +16 -6
  694. package/node_modules/@openrig/daemon/dist/routes/sessions.js.map +1 -1
  695. package/node_modules/@openrig/daemon/dist/routes/snapshots.d.ts.map +1 -1
  696. package/node_modules/@openrig/daemon/dist/routes/snapshots.js +41 -3
  697. package/node_modules/@openrig/daemon/dist/routes/snapshots.js.map +1 -1
  698. package/node_modules/@openrig/daemon/dist/routes/up.js +12 -1
  699. package/node_modules/@openrig/daemon/dist/routes/up.js.map +1 -1
  700. package/node_modules/@openrig/daemon/dist/routes/watchdog.d.ts.map +1 -1
  701. package/node_modules/@openrig/daemon/dist/routes/watchdog.js +7 -6
  702. package/node_modules/@openrig/daemon/dist/routes/watchdog.js.map +1 -1
  703. package/node_modules/@openrig/daemon/dist/routes/workflow.d.ts.map +1 -1
  704. package/node_modules/@openrig/daemon/dist/routes/workflow.js +104 -39
  705. package/node_modules/@openrig/daemon/dist/routes/workflow.js.map +1 -1
  706. package/node_modules/@openrig/daemon/dist/server.d.ts +2 -0
  707. package/node_modules/@openrig/daemon/dist/server.d.ts.map +1 -1
  708. package/node_modules/@openrig/daemon/dist/server.js +1 -0
  709. package/node_modules/@openrig/daemon/dist/server.js.map +1 -1
  710. package/node_modules/@openrig/daemon/dist/skill-loadout-surface.d.ts +3 -0
  711. package/node_modules/@openrig/daemon/dist/skill-loadout-surface.d.ts.map +1 -0
  712. package/node_modules/@openrig/daemon/dist/skill-loadout-surface.js +2 -0
  713. package/node_modules/@openrig/daemon/dist/skill-loadout-surface.js.map +1 -0
  714. package/node_modules/@openrig/daemon/dist/startup.d.ts.map +1 -1
  715. package/node_modules/@openrig/daemon/dist/startup.js +72 -65
  716. package/node_modules/@openrig/daemon/dist/startup.js.map +1 -1
  717. package/node_modules/@openrig/daemon/dist/system-world-surface.d.ts +2 -0
  718. package/node_modules/@openrig/daemon/dist/system-world-surface.d.ts.map +1 -0
  719. package/node_modules/@openrig/daemon/dist/system-world-surface.js +2 -0
  720. package/node_modules/@openrig/daemon/dist/system-world-surface.js.map +1 -0
  721. package/node_modules/@openrig/daemon/package.json +17 -1
  722. package/package.json +1 -1
  723. package/tui/dist/commands/registry.d.ts.map +1 -1
  724. package/tui/dist/commands/registry.js +10 -1
  725. package/tui/dist/commands/registry.js.map +1 -1
  726. package/tui/dist/daemon-client.d.ts +11 -0
  727. package/tui/dist/daemon-client.d.ts.map +1 -1
  728. package/tui/dist/daemon-client.js +15 -0
  729. package/tui/dist/daemon-client.js.map +1 -1
  730. package/tui/dist/demo-data.d.ts.map +1 -1
  731. package/tui/dist/demo-data.js +65 -9
  732. package/tui/dist/demo-data.js.map +1 -1
  733. package/tui/dist/detail.d.ts +9 -0
  734. package/tui/dist/detail.d.ts.map +1 -1
  735. package/tui/dist/detail.js.map +1 -1
  736. package/tui/dist/execution/execution-model.d.ts +8 -2
  737. package/tui/dist/execution/execution-model.d.ts.map +1 -1
  738. package/tui/dist/execution/execution-model.js +482 -119
  739. package/tui/dist/execution/execution-model.js.map +1 -1
  740. package/tui/dist/hydrate.d.ts +3 -2
  741. package/tui/dist/hydrate.d.ts.map +1 -1
  742. package/tui/dist/hydrate.js +66 -8
  743. package/tui/dist/hydrate.js.map +1 -1
  744. package/tui/dist/input.d.ts +6 -1
  745. package/tui/dist/input.d.ts.map +1 -1
  746. package/tui/dist/input.js +20 -10
  747. package/tui/dist/input.js.map +1 -1
  748. package/tui/dist/main.js +39 -8
  749. package/tui/dist/main.js.map +1 -1
  750. package/tui/dist/navigator.d.ts.map +1 -1
  751. package/tui/dist/navigator.js +10 -6
  752. package/tui/dist/navigator.js.map +1 -1
  753. package/tui/dist/render.d.ts.map +1 -1
  754. package/tui/dist/render.js +596 -155
  755. package/tui/dist/render.js.map +1 -1
  756. package/tui/dist/scopes/scopes-model.d.ts +14 -8
  757. package/tui/dist/scopes/scopes-model.d.ts.map +1 -1
  758. package/tui/dist/scopes/scopes-model.js +218 -46
  759. package/tui/dist/scopes/scopes-model.js.map +1 -1
  760. package/tui/dist/socket-server.d.ts +13 -0
  761. package/tui/dist/socket-server.d.ts.map +1 -1
  762. package/tui/dist/socket-server.js +24 -0
  763. package/tui/dist/socket-server.js.map +1 -1
  764. package/tui/dist/state.d.ts.map +1 -1
  765. package/tui/dist/state.js +20 -6
  766. package/tui/dist/state.js.map +1 -1
  767. package/tui/dist/stylize.d.ts.map +1 -1
  768. package/tui/dist/stylize.js +22 -28
  769. package/tui/dist/stylize.js.map +1 -1
  770. package/tui/dist/theme.d.ts +1 -1
  771. package/tui/dist/theme.d.ts.map +1 -1
  772. package/tui/dist/theme.js +5 -4
  773. package/tui/dist/theme.js.map +1 -1
  774. package/tui/dist/types.d.ts +97 -1
  775. package/tui/dist/types.d.ts.map +1 -1
  776. package/tui/dist/visual-layout.d.ts +6 -0
  777. package/tui/dist/visual-layout.d.ts.map +1 -0
  778. package/tui/dist/visual-layout.js +8 -0
  779. package/tui/dist/visual-layout.js.map +1 -0
  780. package/ui/dist/assets/{index-B_wqzP0D.js → index-wyX378xb.js} +15 -15
  781. package/ui/dist/index.html +1 -1
@@ -0,0 +1,1419 @@
1
+ #!/usr/bin/env node
2
+
3
+ import crypto from "node:crypto";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+
8
+ const SCHEMA = "openrig-telemetry-state-migration/v1";
9
+ const rig = process.env.OPENRIG_RIG_BIN || "rig";
10
+ const HELP = `Usage: migrate-telemetry-state-0.5.9.mjs [options]
11
+
12
+ No phase flag runs the read-only plan.
13
+ This tool performs one bounded operation selected by the user agent. It does not
14
+ install, start, stop, or otherwise orchestrate an OpenRig upgrade.
15
+
16
+ Options:
17
+ --home <path> OpenRig home to inspect or migrate
18
+ --apply-state Prepare canonical roots, recovery, and compatibility config
19
+ --verify Verify real paired canonical telemetry after activation
20
+ --apply-library Finalize by non-destructive verified library copy
21
+ --rollback <preimage> Reverse only helper-owned preparation/finalizer effects
22
+ --preimage <path> Protected recovery material created by apply-state
23
+ --verification <path> Successful verification receipt required by the finalizer
24
+ -h, --help Show this help without inspecting the instance
25
+ `;
26
+ const DEFAULT_SYSTEM_WORLD = `schema: openrig.system-world/v0alpha1
27
+ id: openrig-default
28
+ version: "0.5.9"
29
+ context:
30
+ - ref: onboarding-width
31
+ - ref: world-public
32
+ profiles:
33
+ claude: guided
34
+ codex: codex-coverage
35
+ skills: []
36
+ `;
37
+
38
+ function parseArguments(argv) {
39
+ const valueOptions = new Set(["--home", "--preimage", "--verification", "--rollback"]);
40
+ const phaseOptions = new Set(["--apply-state", "--verify", "--apply-library"]);
41
+ const values = new Map();
42
+ const phases = new Set();
43
+ for (let index = 0; index < argv.length; index += 1) {
44
+ const option = argv[index];
45
+ if (phaseOptions.has(option)) {
46
+ phases.add(option);
47
+ continue;
48
+ }
49
+ if (valueOptions.has(option)) {
50
+ const value = argv[index + 1];
51
+ if (value === undefined || value.startsWith("-")) {
52
+ return { issue: issue("value_required", null, `${option} requires a value`, { option }) };
53
+ }
54
+ values.set(option, value);
55
+ index += 1;
56
+ continue;
57
+ }
58
+ return { issue: issue("unknown_option", null, "run --help for supported options", { option }) };
59
+ }
60
+ return { values, phases };
61
+ }
62
+
63
+ function sha256(bytes) {
64
+ return crypto.createHash("sha256").update(bytes).digest("hex");
65
+ }
66
+
67
+ function emit(report, status = 0) {
68
+ const stream = status === 0 ? process.stdout : process.stderr;
69
+ stream.write(`${JSON.stringify(report, null, 2)}\n`);
70
+ process.exit(status);
71
+ }
72
+
73
+ function issue(code, pathValue, next, extra = {}) {
74
+ return { code, ...(pathValue ? { path: pathValue } : {}), ...extra, next };
75
+ }
76
+
77
+ function readJson(filePath) {
78
+ try {
79
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
80
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ function lstatOrNull(pathValue) {
87
+ try {
88
+ return fs.lstatSync(pathValue);
89
+ } catch (error) {
90
+ if (error.code === "ENOENT" || error.code === "ENOTDIR") return null;
91
+ throw error;
92
+ }
93
+ }
94
+
95
+ function treeSnapshot(root, ignored = new Set()) {
96
+ const rootStat = lstatOrNull(root);
97
+ if (!rootStat) return { digest: null, rootIdentity: null, entries: [] };
98
+ if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
99
+ throw new Error(`library root is not a real directory: ${root}`);
100
+ }
101
+ const rows = [];
102
+ const entries = [];
103
+ const visit = (directory, prefix = "") => {
104
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
105
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
106
+ const absolute = path.join(directory, entry.name);
107
+ if (ignored.has(relative)) continue;
108
+ const current = fs.lstatSync(absolute);
109
+ const mode = current.mode & 0o777;
110
+ if (current.isSymbolicLink()) {
111
+ const linkTargetBase64 = fs.readlinkSync(absolute, { encoding: "buffer" }).toString("base64");
112
+ const afterRead = fs.lstatSync(absolute);
113
+ if (!afterRead.isSymbolicLink()
114
+ || afterRead.dev !== current.dev
115
+ || afterRead.ino !== current.ino
116
+ || (afterRead.mode & 0o777) !== mode) {
117
+ throw new Error(`symlink changed while being inventoried: ${absolute}`);
118
+ }
119
+ entries.push({
120
+ path: relative,
121
+ type: "symlink",
122
+ mode,
123
+ linkTargetBase64,
124
+ identity: { dev: String(current.dev), ino: String(current.ino) },
125
+ });
126
+ rows.push(`${relative}\0symlink\0${mode}\0${linkTargetBase64}`);
127
+ } else if (current.isDirectory()) {
128
+ entries.push({ path: relative, type: "directory", mode });
129
+ rows.push(`${relative}\0directory\0${mode}`);
130
+ visit(absolute, relative);
131
+ } else if (current.isFile()) {
132
+ const digest = sha256(fs.readFileSync(absolute));
133
+ entries.push({ path: relative, type: "file", mode, sha256: digest });
134
+ // Preserve the pre-symlink regular-file serialization byte-for-byte.
135
+ rows.push(`${relative}\0${mode}\0${digest}`);
136
+ } else {
137
+ throw new Error(`unsupported library entry is not supported: ${absolute}`);
138
+ }
139
+ }
140
+ };
141
+ visit(root);
142
+ return {
143
+ digest: sha256(rows.join("\n")),
144
+ rootIdentity: { dev: String(rootStat.dev), ino: String(rootStat.ino) },
145
+ entries,
146
+ };
147
+ }
148
+
149
+ function treeDigest(root, ignored = new Set()) {
150
+ return treeSnapshot(root, ignored).digest;
151
+ }
152
+
153
+ function librarySourceDrift(sourcePath, message) {
154
+ const drift = new Error(`context library changed after inventory: ${sourcePath}: ${message}`);
155
+ drift.migrationIssueCode = "library_source_drift";
156
+ drift.migrationPath = sourcePath;
157
+ return drift;
158
+ }
159
+
160
+ function assertTreeSnapshot(root, expected, ignored = new Set()) {
161
+ let current;
162
+ try {
163
+ current = treeSnapshot(root, ignored);
164
+ } catch (error) {
165
+ throw librarySourceDrift(root, error.message);
166
+ }
167
+ const rootIdentityChanged = expected.rootIdentity !== null && (
168
+ current.rootIdentity?.dev !== expected.rootIdentity.dev
169
+ || current.rootIdentity?.ino !== expected.rootIdentity.ino
170
+ );
171
+ if (current.digest !== expected.digest || rootIdentityChanged) {
172
+ throw librarySourceDrift(root, "tree digest or root identity no longer matches");
173
+ }
174
+ const currentLinks = new Map(current.entries
175
+ .filter((entry) => entry.type === "symlink")
176
+ .map((entry) => [entry.path, entry]));
177
+ for (const link of expected.entries.filter((entry) => entry.type === "symlink")) {
178
+ const observed = currentLinks.get(link.path);
179
+ if (!observed
180
+ || observed.mode !== link.mode
181
+ || observed.linkTargetBase64 !== link.linkTargetBase64
182
+ || observed.identity.dev !== link.identity.dev
183
+ || observed.identity.ino !== link.identity.ino) {
184
+ throw librarySourceDrift(path.join(root, link.path), "symlink payload, type, mode, or inode no longer matches");
185
+ }
186
+ }
187
+ return current;
188
+ }
189
+
190
+ function regularFileSnapshot(filePath) {
191
+ const before = lstatOrNull(filePath);
192
+ if (!before) throw new Error(`managed file is missing: ${filePath}`);
193
+ if (!before.isFile() || before.isSymbolicLink()) {
194
+ throw new Error(`managed path is not a regular file: ${filePath}`);
195
+ }
196
+ const mode = before.mode & 0o777;
197
+ const digest = sha256(fs.readFileSync(filePath));
198
+ const after = fs.lstatSync(filePath);
199
+ if (!after.isFile()
200
+ || after.isSymbolicLink()
201
+ || after.dev !== before.dev
202
+ || after.ino !== before.ino
203
+ || (after.mode & 0o777) !== mode) {
204
+ throw new Error(`managed file changed while being inventoried: ${filePath}`);
205
+ }
206
+ return {
207
+ type: "file",
208
+ mode,
209
+ sha256: digest,
210
+ identity: { dev: String(before.dev), ino: String(before.ino) },
211
+ };
212
+ }
213
+
214
+ function assertRegularFileSnapshot(filePath, expected) {
215
+ if (!expected) throw new Error(`managed file has no recorded identity: ${filePath}`);
216
+ const current = regularFileSnapshot(filePath);
217
+ if (current.type !== expected.type
218
+ || current.mode !== expected.mode
219
+ || current.sha256 !== expected.sha256
220
+ || current.identity.dev !== expected.identity?.dev
221
+ || current.identity.ino !== expected.identity?.ino) {
222
+ throw new Error(`managed file identity no longer matches: ${filePath}`);
223
+ }
224
+ return current;
225
+ }
226
+
227
+ function readLibraryConfig(home, issues) {
228
+ const configPath = path.join(home, "config.json");
229
+ const configExists = fs.existsSync(configPath);
230
+ const config = configExists ? readJson(configPath) : {};
231
+ if (!config) {
232
+ issues.push(issue("config_invalid", configPath, "repair config.json before migrating the context library"));
233
+ return null;
234
+ }
235
+ const context = config.context === undefined ? {} : config.context;
236
+ if (!context || typeof context !== "object" || Array.isArray(context)) {
237
+ issues.push(issue("config_invalid", configPath, "make config.context an object before migrating the context library"));
238
+ return null;
239
+ }
240
+ if (context.packsRoot !== undefined && (typeof context.packsRoot !== "string" || context.packsRoot.length === 0)) {
241
+ issues.push(issue("config_invalid", configPath, "make context.packsRoot a non-empty path or remove it before migration"));
242
+ return null;
243
+ }
244
+ if (context.root !== undefined && (typeof context.root !== "string" || context.root.length === 0)) {
245
+ issues.push(issue("config_invalid", configPath, "make context.root a non-empty path or remove it before migration"));
246
+ return null;
247
+ }
248
+ const defaultLegacyRoot = path.join(home, "context-packs");
249
+ const configuredLegacyRoot = context.packsRoot
250
+ ? path.resolve(context.packsRoot)
251
+ : context.root
252
+ ? path.resolve(context.root)
253
+ : defaultLegacyRoot;
254
+ if (context.packsRoot !== undefined && context.root !== undefined
255
+ && path.resolve(context.packsRoot) !== path.resolve(context.root)) {
256
+ issues.push(issue("context_root_conflict", configPath, "choose the one context library that must stay authoritative during activation", {
257
+ legacyRoot: path.resolve(context.packsRoot),
258
+ configuredRoot: path.resolve(context.root),
259
+ }));
260
+ return null;
261
+ }
262
+ const targetRoot = configuredLegacyRoot === defaultLegacyRoot ? path.join(home, "context") : configuredLegacyRoot;
263
+ const activationContext = { ...context, root: configuredLegacyRoot };
264
+ delete activationContext.packsRoot;
265
+ const finalContext = { ...context, root: targetRoot };
266
+ delete finalContext.packsRoot;
267
+ if (context.systemWorld === undefined) {
268
+ activationContext.systemWorld = path.join(home, "context", "system", "system-world.yaml");
269
+ if (targetRoot !== path.join(home, "context")) finalContext.systemWorld = activationContext.systemWorld;
270
+ }
271
+ const activationConfig = { ...config, context: activationContext };
272
+ const finalConfig = { ...config, context: finalContext };
273
+ return {
274
+ configPath,
275
+ configExists,
276
+ originalConfig: configExists ? fs.readFileSync(configPath) : null,
277
+ activationConfig: Buffer.from(`${JSON.stringify(activationConfig, null, 2)}\n`),
278
+ finalConfig: Buffer.from(`${JSON.stringify(finalConfig, null, 2)}\n`),
279
+ sourceRoot: configuredLegacyRoot,
280
+ targetRoot,
281
+ };
282
+ }
283
+
284
+ function systemWorldPlan(home, issues) {
285
+ const directory = path.join(home, "context", "system");
286
+ const filePath = path.join(directory, "system-world.yaml");
287
+ const file = lstatOrNull(filePath);
288
+ if (file && (!file.isFile() || file.isSymbolicLink())) {
289
+ issues.push(issue("system_world_conflict", filePath, "preserve the opaque entry and select the intended System World before preparation"));
290
+ return null;
291
+ }
292
+ if (file && sha256(fs.readFileSync(filePath)) !== sha256(DEFAULT_SYSTEM_WORLD)) {
293
+ issues.push(issue("system_world_conflict", filePath, "preserve the operator-owned System World and explicitly reconcile it before preparation"));
294
+ return null;
295
+ }
296
+ const directoryStat = lstatOrNull(directory);
297
+ if (directoryStat && (!directoryStat.isDirectory() || directoryStat.isSymbolicLink())) {
298
+ issues.push(issue("system_world_conflict", directory, "preserve the opaque entry and select the intended System World directory before preparation"));
299
+ return null;
300
+ }
301
+ if (directoryStat) {
302
+ const foreign = fs.readdirSync(directory).filter((name) => name !== "system-world.yaml");
303
+ if (foreign.length > 0) {
304
+ issues.push(issue("system_world_conflict", path.join(directory, foreign[0]), "preserve the additional content and reconcile the reserved System World directory before preparation"));
305
+ return null;
306
+ }
307
+ }
308
+ return { directory, filePath, existed: Boolean(file) };
309
+ }
310
+
311
+ function inventoryClaudeSeats(issues) {
312
+ const result = spawnSync(rig, ["ps", "--nodes", "-A", "--json", "--full"], { encoding: "utf8" });
313
+ if (result.status !== 0) {
314
+ issues.push(issue(
315
+ "inventory_unavailable",
316
+ null,
317
+ `run ${rig} ps --nodes -A --json --full and restore daemon inventory before retrying`,
318
+ { diagnostic: result.stderr?.trim() || result.stdout?.trim() || "command produced no diagnostic" },
319
+ ));
320
+ return [];
321
+ }
322
+
323
+ try {
324
+ const parsed = JSON.parse(result.stdout);
325
+ const entries = Array.isArray(parsed) ? parsed : parsed.entries;
326
+ if (!Array.isArray(entries) || parsed.truncated === true) throw new Error("inventory is missing or truncated");
327
+ return entries.filter((entry) => entry.runtime === "claude-code" && entry.sessionStatus === "running");
328
+ } catch (error) {
329
+ issues.push(issue("inventory_unavailable", null, "obtain one complete untruncated node inventory before retrying", {
330
+ diagnostic: error.message,
331
+ }));
332
+ return [];
333
+ }
334
+ }
335
+
336
+ function targetIssue(target) {
337
+ let cursor = target;
338
+ while (!fs.existsSync(cursor)) {
339
+ const parent = path.dirname(cursor);
340
+ if (parent === cursor) break;
341
+ cursor = parent;
342
+ }
343
+ if (fs.existsSync(cursor) && !fs.statSync(cursor).isDirectory()) {
344
+ return issue("unwriteable_target", target, "replace the non-directory ancestor or choose the correct OpenRig home before apply", {
345
+ blockingPath: cursor,
346
+ });
347
+ }
348
+ if (!fs.existsSync(target)) return null;
349
+ if (!fs.statSync(target).isDirectory()) {
350
+ return issue("unwriteable_target", target, "preserve the non-directory target and repair the path before apply");
351
+ }
352
+ return null;
353
+ }
354
+
355
+ function scanLegacy(directory, kind, destination, issues, managedEmptyDirectories = [], allowedDirectories = []) {
356
+ if (!fs.existsSync(directory)) return [];
357
+ if (!fs.statSync(directory).isDirectory()) {
358
+ issues.push(issue("foreign_file", directory, "preserve the path and identify the real legacy telemetry directory"));
359
+ return [];
360
+ }
361
+
362
+ const files = [];
363
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
364
+ const source = path.join(directory, entry.name);
365
+ if (entry.isFile() && entry.name.endsWith(".json.tmp")) continue;
366
+ if (kind === "context" && entry.name === "system" && entry.isDirectory()) {
367
+ if (fs.readdirSync(source).length === 0) {
368
+ managedEmptyDirectories.push(source);
369
+ continue;
370
+ }
371
+ if (allowedDirectories.includes(source)) continue;
372
+ }
373
+ if (!entry.isFile() || !entry.name.endsWith(".json")) {
374
+ issues.push(issue("foreign_file", source, "classify or archive the non-telemetry entry before applying this bounded migration"));
375
+ continue;
376
+ }
377
+ const parsed = readJson(source);
378
+ const identity = kind === "context" ? parsed?.session_name : parsed?.seatSession;
379
+ const timestamp = kind === "context" ? parsed?.sampled_at : parsed?.asOf;
380
+ if (typeof identity !== "string" || identity.length === 0
381
+ || typeof timestamp !== "string" || Number.isNaN(Date.parse(timestamp))) {
382
+ issues.push(issue("malformed_sidecar", source, `repair or archive the malformed ${kind} sidecar before apply`));
383
+ continue;
384
+ }
385
+ files.push({
386
+ kind,
387
+ source,
388
+ destination: path.join(destination, entry.name),
389
+ sessionName: identity,
390
+ bytes: fs.readFileSync(source),
391
+ mode: fs.statSync(source).mode & 0o777,
392
+ });
393
+ }
394
+ return files;
395
+ }
396
+
397
+ function buildPlan(home) {
398
+ const issues = [];
399
+ const managedEmptyDirectories = [];
400
+ const roots = {
401
+ legacyContext: path.join(home, "context"),
402
+ legacyProvider: path.join(home, "provider-usage"),
403
+ contextUsage: path.join(home, "state", "context-usage"),
404
+ providerUsage: path.join(home, "state", "provider-usage"),
405
+ };
406
+ for (const target of [roots.contextUsage, roots.providerUsage]) {
407
+ const found = targetIssue(target);
408
+ if (found) issues.push(found);
409
+ }
410
+ const systemWorld = systemWorldPlan(home, issues);
411
+ const allowedContextDirectories = systemWorld && lstatOrNull(systemWorld.directory)
412
+ ? [systemWorld.directory]
413
+ : [];
414
+ const telemetry = [
415
+ ...scanLegacy(roots.legacyContext, "context", roots.contextUsage, issues, managedEmptyDirectories, allowedContextDirectories),
416
+ ...scanLegacy(roots.legacyProvider, "provider", roots.providerUsage, issues),
417
+ ];
418
+ inventoryClaudeSeats(issues);
419
+ const library = readLibraryConfig(home, issues);
420
+ if (library && fs.existsSync(library.sourceRoot) && !fs.statSync(library.sourceRoot).isDirectory()) {
421
+ issues.push(issue("library_source_invalid", library.sourceRoot, "preserve the path and identify the real legacy context library"));
422
+ }
423
+ return { roots, telemetry, library, systemWorld, managedEmptyDirectories, issues };
424
+ }
425
+
426
+ function publicPlan(home, plan) {
427
+ return {
428
+ schema: SCHEMA,
429
+ generatedAt: new Date().toISOString(),
430
+ home,
431
+ phase: "plan",
432
+ applied: false,
433
+ complete: plan.issues.length === 0,
434
+ roots: plan.roots,
435
+ actions: [
436
+ { decision: "prepare-directory", path: plan.roots.contextUsage },
437
+ { decision: "prepare-directory", path: plan.roots.providerUsage },
438
+ ...plan.telemetry.map((item) => ({ decision: "preserve-legacy-fallback", kind: item.kind, path: item.source, sha256: sha256(item.bytes) })),
439
+ ...(plan.systemWorld ? [{ decision: plan.systemWorld.existed ? "preserve-system-world" : "install-system-world", path: plan.systemWorld.filePath }] : []),
440
+ ...(plan.library ? [{
441
+ decision: "pin-library-during-activation",
442
+ from: plan.library.sourceRoot,
443
+ to: plan.library.sourceRoot,
444
+ finalizer: plan.library.sourceRoot === plan.library.targetRoot ? "verify-in-place" : "copy-after-verification",
445
+ finalizerTarget: plan.library.targetRoot,
446
+ }] : []),
447
+ ],
448
+ issues: plan.issues,
449
+ next: plan.issues.length === 0
450
+ ? "after the user agent approves this installation-specific plan, choose an unused --preimage path and run --apply-state"
451
+ : "resolve every issue; plan mode changed nothing",
452
+ };
453
+ }
454
+
455
+ function atomicWrite(destination, bytes, mode) {
456
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
457
+ const temporary = `${destination}.openrig-telemetry-${process.pid}-${crypto.randomBytes(4).toString("hex")}`;
458
+ try {
459
+ fs.writeFileSync(temporary, bytes, { flag: "wx", mode });
460
+ fs.chmodSync(temporary, mode);
461
+ fs.renameSync(temporary, destination);
462
+ } finally {
463
+ fs.rmSync(temporary, { force: true });
464
+ }
465
+ }
466
+
467
+ function storePreimage(preimage, records) {
468
+ if (fs.existsSync(preimage)) {
469
+ emit({ schema: SCHEMA, phase: "apply-state", ok: false, issues: [issue(
470
+ "preimage_exists",
471
+ preimage,
472
+ "choose a new preimage path; this helper never overwrites one",
473
+ )] }, 1);
474
+ }
475
+ fs.mkdirSync(preimage, { recursive: true });
476
+ const files = records.map((record, index) => {
477
+ const digest = sha256(record.bytes);
478
+ const storedAs = path.join("files", `${String(index).padStart(4, "0")}-${digest}`);
479
+ const storedPath = path.join(preimage, storedAs);
480
+ fs.mkdirSync(path.dirname(storedPath), { recursive: true });
481
+ fs.writeFileSync(storedPath, record.bytes, { flag: "wx", mode: record.mode });
482
+ return { ...record.public, storedAs, sha256: digest, mode: record.mode };
483
+ });
484
+ return files;
485
+ }
486
+
487
+ function loadManifest(preimage, home, phase) {
488
+ const manifestPath = path.join(preimage, "manifest.json");
489
+ const manifest = readJson(manifestPath);
490
+ if (manifest?.schema !== SCHEMA || manifest.home !== home || !Array.isArray(manifest.files)) {
491
+ emit({ schema: SCHEMA, phase, ok: false, issues: [issue(
492
+ "preimage_manifest_mismatch",
493
+ manifestPath,
494
+ "use the exact preimage emitted by this home's apply-state receipt",
495
+ )] }, 1);
496
+ }
497
+ return manifest;
498
+ }
499
+
500
+ function validatePreimage(preimage, manifest) {
501
+ const issues = [];
502
+ for (const file of manifest.files) {
503
+ const storedPath = path.resolve(preimage, file.storedAs);
504
+ if (!storedPath.startsWith(`${path.resolve(preimage)}${path.sep}`) || !fs.existsSync(storedPath)
505
+ || sha256(fs.readFileSync(storedPath)) !== file.sha256) {
506
+ issues.push(issue("preimage_mismatch", storedPath, "restore the byte-matching preimage before rollback", {
507
+ originalPath: file.originalPath,
508
+ }));
509
+ }
510
+ }
511
+ return issues;
512
+ }
513
+
514
+ function contextFilenameForSession(home, preimage, manifest, sessionName) {
515
+ const preservedSource = manifest.files.find((file) => {
516
+ if (file.kind !== "context-source") return false;
517
+ return readJson(path.join(preimage, file.storedAs))?.session_name === sessionName;
518
+ });
519
+ if (preservedSource) return path.basename(preservedSource.originalPath);
520
+
521
+ const directory = path.join(home, "state", "context-usage");
522
+ if (!fs.existsSync(directory) || !fs.statSync(directory).isDirectory()) return null;
523
+ return fs.readdirSync(directory, { withFileTypes: true })
524
+ .find((entry) => entry.isFile() && readJson(path.join(directory, entry.name))?.session_name === sessionName)?.name ?? null;
525
+ }
526
+
527
+ function applyState(home, preimage) {
528
+ if (!preimage) {
529
+ emit({ schema: SCHEMA, phase: "apply-state", ok: false, issues: [issue(
530
+ "preimage_required",
531
+ null,
532
+ "pass --preimage with a new path under a protected backup root",
533
+ )] }, 1);
534
+ }
535
+ const plan = buildPlan(home);
536
+ if (plan.issues.length > 0) emit({ ...publicPlan(home, plan), phase: "apply-state", ok: false }, 1);
537
+
538
+ const records = [
539
+ ...plan.telemetry.map((item) => ({
540
+ bytes: item.bytes,
541
+ mode: item.mode,
542
+ public: { kind: `${item.kind}-source`, originalPath: item.source },
543
+ })),
544
+ ...(plan.library?.originalConfig ? [{
545
+ bytes: plan.library.originalConfig,
546
+ mode: fs.statSync(plan.library.configPath).mode & 0o777,
547
+ public: { kind: "config", originalPath: plan.library.configPath },
548
+ }] : []),
549
+ ];
550
+ const files = storePreimage(preimage, records);
551
+ const manifestPath = path.join(preimage, "manifest.json");
552
+ const prepared = {
553
+ schema: SCHEMA,
554
+ home,
555
+ status: "prepared",
556
+ createdAt: new Date().toISOString(),
557
+ files,
558
+ stateDirectories: [plan.roots.contextUsage, plan.roots.providerUsage].map((directory) => ({
559
+ path: directory,
560
+ existed: Boolean(lstatOrNull(directory)),
561
+ })),
562
+ managedEmptyDirectories: plan.managedEmptyDirectories,
563
+ systemWorld: plan.systemWorld ? {
564
+ path: plan.systemWorld.filePath,
565
+ existed: plan.systemWorld.existed,
566
+ sha256: sha256(DEFAULT_SYSTEM_WORLD),
567
+ mode: 0o644,
568
+ } : null,
569
+ libraryPlan: plan.library ? {
570
+ configPath: plan.library.configPath,
571
+ configExisted: plan.library.configExists,
572
+ sourceRoot: plan.library.sourceRoot,
573
+ targetRoot: plan.library.targetRoot,
574
+ activationConfigBase64: plan.library.activationConfig.toString("base64"),
575
+ activationConfigSha256: sha256(plan.library.activationConfig),
576
+ finalConfigBase64: plan.library.finalConfig.toString("base64"),
577
+ finalConfigSha256: sha256(plan.library.finalConfig),
578
+ } : null,
579
+ };
580
+ fs.writeFileSync(manifestPath, `${JSON.stringify(prepared, null, 2)}\n`, { flag: "wx" });
581
+
582
+ try {
583
+ fs.mkdirSync(plan.roots.contextUsage, { recursive: true });
584
+ fs.mkdirSync(plan.roots.providerUsage, { recursive: true });
585
+ if (plan.systemWorld && !plan.systemWorld.existed) {
586
+ atomicWrite(plan.systemWorld.filePath, Buffer.from(DEFAULT_SYSTEM_WORLD), 0o644);
587
+ }
588
+ if (plan.library) {
589
+ const configMode = plan.library.configExists ? fs.statSync(plan.library.configPath).mode & 0o777 : 0o600;
590
+ if (plan.library.configExists && sha256(fs.readFileSync(plan.library.configPath)) !== sha256(plan.library.originalConfig)) {
591
+ throw new Error(`config changed during preparation: ${plan.library.configPath}`);
592
+ }
593
+ atomicWrite(plan.library.configPath, plan.library.activationConfig, configMode);
594
+ }
595
+ } catch (error) {
596
+ emit({
597
+ schema: SCHEMA,
598
+ phase: "apply-state",
599
+ ok: false,
600
+ applied: false,
601
+ complete: false,
602
+ preimage,
603
+ issues: [issue("unwriteable_target", null, "inspect the preserved preimage and partial target state; resolve before retrying", {
604
+ diagnostic: error.message,
605
+ })],
606
+ }, 1);
607
+ }
608
+
609
+ const appliedAt = new Date().toISOString();
610
+ atomicWrite(manifestPath, Buffer.from(`${JSON.stringify({ ...prepared, status: "applied", appliedAt }, null, 2)}\n`), 0o600);
611
+ emit({
612
+ schema: SCHEMA,
613
+ generatedAt: appliedAt,
614
+ home,
615
+ phase: "apply-state",
616
+ applied: true,
617
+ complete: false,
618
+ preimage,
619
+ preparedDirectories: [plan.roots.contextUsage, plan.roots.providerUsage],
620
+ preservedLegacy: plan.telemetry.map((item) => item.source),
621
+ configuredContextRoot: plan.library?.sourceRoot ?? null,
622
+ issues: [],
623
+ next: "the user agent may now activate the exact target runtime; prove canonical-only writes and canonical-first/legacy-fallback reads, then run --verify with this --preimage",
624
+ });
625
+ }
626
+
627
+ function sampleTime(filePath, identityKey, timeKey, expectedSession, issues) {
628
+ const parsed = readJson(filePath);
629
+ if (!parsed) {
630
+ if (fs.existsSync(filePath)) issues.push(issue("malformed_sidecar", filePath, "repair the malformed sidecar and obtain a fresh sample"));
631
+ return null;
632
+ }
633
+ if (parsed[identityKey] !== expectedSession || typeof parsed[timeKey] !== "string") {
634
+ issues.push(issue("malformed_sidecar", filePath, "repair the sidecar identity or timestamp and obtain a fresh sample"));
635
+ return null;
636
+ }
637
+ const time = Date.parse(parsed[timeKey]);
638
+ if (Number.isNaN(time)) {
639
+ issues.push(issue("malformed_sidecar", filePath, "repair the sidecar timestamp and obtain a fresh sample"));
640
+ return null;
641
+ }
642
+ return time;
643
+ }
644
+
645
+ function managedSystemWorldState(home, manifest, issues, expectedArtifact = undefined) {
646
+ if (manifest.systemWorld) {
647
+ const expected = manifest.systemWorld;
648
+ const filePath = expected.path;
649
+ const current = lstatOrNull(filePath);
650
+ if (!current?.isFile() || current.isSymbolicLink()
651
+ || sha256(fs.readFileSync(filePath)) !== expected.sha256
652
+ || (current.mode & 0o777) !== expected.mode) {
653
+ issues.push(issue("system_world_conflict", filePath, "preserve the changed System World and restore the exact prepared artifact before continuing"));
654
+ return { directories: [path.dirname(filePath)], artifact: null };
655
+ }
656
+ const foreign = fs.readdirSync(path.dirname(filePath)).filter((name) => name !== path.basename(filePath));
657
+ if (foreign.length > 0) {
658
+ issues.push(issue("system_world_conflict", path.join(path.dirname(filePath), foreign[0]), "preserve the additional content and reconcile the reserved System World directory before continuing"));
659
+ }
660
+ const artifact = { path: filePath, sha256: expected.sha256, mode: expected.mode };
661
+ if (expectedArtifact !== undefined && (
662
+ expectedArtifact === null
663
+ || expectedArtifact.path !== artifact.path
664
+ || expectedArtifact.sha256 !== artifact.sha256
665
+ || expectedArtifact.mode !== artifact.mode
666
+ )) {
667
+ issues.push(issue("destination_drift", filePath, "preserve the changed System World and rerun verification from the exact migration state"));
668
+ }
669
+ return { directories: [path.dirname(filePath)], artifact };
670
+ }
671
+ const directory = path.join(home, "context", "system");
672
+ const systemWorldPath = path.join(directory, "system-world.yaml");
673
+ const directories = manifest.managedEmptyDirectories ?? [];
674
+ if (!Array.isArray(directories) || directories.length > 1 || directories.some((entry) => entry !== directory)) {
675
+ issues.push(issue("preimage_manifest_mismatch", directory, "use the exact preimage emitted by this helper"));
676
+ return { directories: [], artifact: null };
677
+ }
678
+ if (directories.length === 0) {
679
+ if (expectedArtifact !== undefined && expectedArtifact !== null) {
680
+ issues.push(issue("verification_receipt_invalid", systemWorldPath, "rerun --verify against this exact home and preimage"));
681
+ }
682
+ return { directories, artifact: null };
683
+ }
684
+ if (!fs.existsSync(directory) || !fs.lstatSync(directory).isDirectory() || fs.lstatSync(directory).isSymbolicLink()) {
685
+ issues.push(issue("system_world_conflict", directory, "start the exact target daemon and require only its canonical default System World before retrying"));
686
+ return { directories, artifact: null };
687
+ }
688
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
689
+ if (entries.length !== 1 || entries[0].name !== "system-world.yaml" || !entries[0].isFile() || entries[0].isSymbolicLink()) {
690
+ issues.push(issue("system_world_conflict", directory, "preserve the differing or additional System World content and reconcile it manually"));
691
+ return { directories, artifact: null };
692
+ }
693
+ const bytes = fs.readFileSync(systemWorldPath);
694
+ const artifact = {
695
+ path: systemWorldPath,
696
+ sha256: sha256(bytes),
697
+ mode: fs.statSync(systemWorldPath).mode & 0o777,
698
+ };
699
+ if (artifact.sha256 !== sha256(DEFAULT_SYSTEM_WORLD)) {
700
+ issues.push(issue("system_world_conflict", systemWorldPath, "preserve the differing System World and reconcile it manually"));
701
+ }
702
+ if (expectedArtifact !== undefined && (
703
+ expectedArtifact === null
704
+ || expectedArtifact.path !== artifact.path
705
+ || expectedArtifact.sha256 !== artifact.sha256
706
+ || expectedArtifact.mode !== artifact.mode
707
+ )) {
708
+ issues.push(issue("destination_drift", systemWorldPath, "preserve the changed System World and rerun verification from the exact migration state"));
709
+ }
710
+ return { directories, artifact };
711
+ }
712
+
713
+ function telemetryPair(home, preimage, manifest, sessionName, issues) {
714
+ const filename = contextFilenameForSession(home, preimage, manifest, sessionName);
715
+ if (!filename) return null;
716
+ const contextPath = path.join(home, "state", "context-usage", filename);
717
+ const providerPath = path.join(home, "state", "provider-usage", filename);
718
+ const contextAt = sampleTime(contextPath, "session_name", "sampled_at", sessionName, issues);
719
+ const providerAt = sampleTime(providerPath, "seatSession", "asOf", sessionName, issues);
720
+ if (contextAt === null || providerAt === null) return null;
721
+ return {
722
+ sessionName,
723
+ contextPath,
724
+ providerPath,
725
+ contextAt,
726
+ providerAt,
727
+ sampledAt: new Date(Math.min(contextAt, providerAt)).toISOString(),
728
+ };
729
+ }
730
+
731
+ function legacyTails(manifest, telemetry, appliedAt, issues) {
732
+ const originalByPath = new Map(manifest.files
733
+ .filter((file) => file.kind === "context-source" || file.kind === "provider-source")
734
+ .map((file) => [file.originalPath, file]));
735
+ const currentPaths = new Set(telemetry.map((file) => file.source));
736
+ for (const original of originalByPath.values()) {
737
+ if (!currentPaths.has(original.originalPath)) {
738
+ issues.push(issue("legacy_source_drift", original.originalPath, "restore the preimage-bound legacy sidecar and rerun verification"));
739
+ }
740
+ }
741
+ const tails = [];
742
+ for (const file of telemetry) {
743
+ const original = originalByPath.get(file.source);
744
+ const currentSha256 = sha256(file.bytes);
745
+ if (original && original.sha256 === currentSha256 && original.mode === file.mode) continue;
746
+ const current = readJson(file.source);
747
+ const timeKey = file.kind === "context" ? "sampled_at" : "asOf";
748
+ const identityKey = file.kind === "context" ? "session_name" : "seatSession";
749
+ const observedAt = Date.parse(current?.[timeKey]);
750
+ if (Number.isNaN(observedAt) || observedAt <= appliedAt) {
751
+ issues.push(issue("legacy_source_drift", file.source, "preserve the changed legacy sidecar and rerun the migration from a fresh preimage"));
752
+ continue;
753
+ }
754
+ tails.push({
755
+ kind: file.kind,
756
+ originalPath: file.source,
757
+ sessionName: current[identityKey],
758
+ observedAt: current[timeKey],
759
+ sha256: currentSha256,
760
+ mode: file.mode,
761
+ });
762
+ }
763
+ return tails;
764
+ }
765
+
766
+ function requireTailConvergence(tails, samples, issues) {
767
+ for (const tail of tails) {
768
+ const sample = samples.get(tail.sessionName);
769
+ const observedAt = Date.parse(tail.observedAt);
770
+ if (!sample || sample.contextAt <= observedAt || sample.providerAt <= observedAt) {
771
+ issues.push(issue("legacy_writer_active", tail.originalPath, "obtain newer samples for the named seat at both new state roots, or replace the process if legacy writes continue", {
772
+ sessionName: tail.sessionName,
773
+ observedAt: tail.observedAt,
774
+ ...(sample ? {
775
+ contextObservedAt: new Date(sample.contextAt).toISOString(),
776
+ providerObservedAt: new Date(sample.providerAt).toISOString(),
777
+ } : {}),
778
+ }));
779
+ }
780
+ }
781
+ }
782
+
783
+ function verify(home, preimage) {
784
+ if (!preimage) {
785
+ emit({ schema: SCHEMA, phase: "verify", ok: false, issues: [issue("preimage_required", null, "pass the apply-state --preimage path")] }, 1);
786
+ }
787
+ const manifest = loadManifest(preimage, home, "verify");
788
+ const issues = validatePreimage(preimage, manifest);
789
+ if (manifest.status !== "applied" || typeof manifest.appliedAt !== "string") {
790
+ issues.push(issue("preimage_manifest_mismatch", path.join(preimage, "manifest.json"), "use a completed apply-state preimage"));
791
+ }
792
+ const appliedAt = Date.parse(manifest.appliedAt);
793
+ const systemWorld = managedSystemWorldState(home, manifest, issues);
794
+ const legacyTelemetry = [
795
+ ...scanLegacy(path.join(home, "context"), "context", path.join(home, "state", "context-usage"), issues, [], systemWorld.directories),
796
+ ...scanLegacy(path.join(home, "provider-usage"), "provider", path.join(home, "state", "provider-usage"), issues),
797
+ ];
798
+ const tails = legacyTails(manifest, legacyTelemetry, appliedAt, issues);
799
+ const seats = inventoryClaudeSeats(issues);
800
+ const sampleSessions = new Set(tails.map((tail) => tail.sessionName));
801
+ for (const seat of seats) {
802
+ const sessionName = seat.canonicalSessionName || seat.sessionName;
803
+ if (typeof sessionName === "string") sampleSessions.add(sessionName);
804
+ }
805
+ const samples = new Map();
806
+ const freshSamples = [];
807
+ for (const sessionName of sampleSessions) {
808
+ const sample = telemetryPair(home, preimage, manifest, sessionName, issues);
809
+ if (sample) {
810
+ samples.set(sessionName, sample);
811
+ if (sample.contextAt > appliedAt && sample.providerAt > appliedAt) {
812
+ const { contextAt: _contextAt, providerAt: _providerAt, ...publicSample } = sample;
813
+ freshSamples.push(publicSample);
814
+ }
815
+ }
816
+ }
817
+ requireTailConvergence(tails, samples, issues);
818
+ if (freshSamples.length === 0) {
819
+ issues.push(issue("missing_fresh_sample", path.join(home, "state", "context-usage"), "obtain one post-apply Claude sample at both new telemetry roots before declaring migration complete"));
820
+ }
821
+
822
+ const report = {
823
+ schema: SCHEMA,
824
+ generatedAt: new Date().toISOString(),
825
+ home,
826
+ phase: "verify",
827
+ verified: issues.length === 0,
828
+ complete: issues.length === 0,
829
+ preimage,
830
+ preimageManifestSha256: sha256(fs.readFileSync(path.join(preimage, "manifest.json"))),
831
+ managedSystemWorld: systemWorld.artifact,
832
+ freshSamples,
833
+ legacyTails: tails,
834
+ issues,
835
+ next: issues.length === 0 ? "canonical telemetry adoption is verified" : "resolve the named incomplete state and rerun verify",
836
+ };
837
+ emit(report, issues.length === 0 ? 0 : 1);
838
+ }
839
+
840
+ function verificationReceipt(home, preimage, verificationPath) {
841
+ if (!verificationPath) return { issue: issue("verification_receipt_required", null, "capture a successful --verify JSON receipt and pass it with --verification") };
842
+ const receipt = readJson(verificationPath);
843
+ const manifestPath = path.join(preimage, "manifest.json");
844
+ const manifest = readJson(manifestPath);
845
+ const expectsSystemWorld = Boolean(manifest?.systemWorld)
846
+ || (Array.isArray(manifest?.managedEmptyDirectories) && manifest.managedEmptyDirectories.length === 1);
847
+ const valid = receipt?.schema === SCHEMA
848
+ && receipt.phase === "verify"
849
+ && receipt.verified === true
850
+ && receipt.complete === true
851
+ && typeof receipt.home === "string"
852
+ && typeof receipt.preimage === "string"
853
+ && path.resolve(receipt.home) === home
854
+ && path.resolve(receipt.preimage) === path.resolve(preimage)
855
+ && receipt.preimageManifestSha256 === sha256(fs.readFileSync(manifestPath))
856
+ && Array.isArray(receipt.legacyTails)
857
+ && receipt.legacyTails.every((tail) => (tail?.kind === "context" || tail?.kind === "provider")
858
+ && typeof tail.originalPath === "string"
859
+ && typeof tail.sessionName === "string"
860
+ && typeof tail.observedAt === "string"
861
+ && typeof tail.sha256 === "string"
862
+ && Number.isInteger(tail.mode))
863
+ && (expectsSystemWorld
864
+ ? receipt.managedSystemWorld && typeof receipt.managedSystemWorld.path === "string"
865
+ && typeof receipt.managedSystemWorld.sha256 === "string"
866
+ && Number.isInteger(receipt.managedSystemWorld.mode)
867
+ : receipt.managedSystemWorld === null);
868
+ return valid
869
+ ? { receipt }
870
+ : { issue: issue("verification_receipt_invalid", verificationPath, "rerun --verify against this exact home and preimage, capture its JSON, then retry") };
871
+ }
872
+
873
+ function validateLegacySources(preimage, manifest, root, kind, issues, allowedEntries = [], verifiedTails = []) {
874
+ const files = manifest.files.filter((file) => file.kind === kind && path.dirname(file.originalPath) === root);
875
+ const telemetryKind = kind === "context-source" ? "context" : "provider";
876
+ const tails = verifiedTails.filter((tail) => tail.kind === telemetryKind && path.dirname(tail.originalPath) === root);
877
+ const expectedByPath = new Map(files.map((file) => [file.originalPath, file]));
878
+ for (const tail of tails) expectedByPath.set(tail.originalPath, tail);
879
+ const allowed = new Set([...expectedByPath.keys()].map((filePath) => path.basename(filePath)));
880
+ const allowedEntrySet = new Set(allowedEntries);
881
+ if (!fs.existsSync(root)) {
882
+ for (const file of expectedByPath.values()) {
883
+ issues.push(issue("legacy_source_drift", file.originalPath, "restore the verified legacy telemetry source before migrating the library"));
884
+ }
885
+ return [...expectedByPath.values()];
886
+ }
887
+ if (!fs.statSync(root).isDirectory()) {
888
+ issues.push(issue("legacy_source_drift", root, "restore the verified legacy telemetry directory before migrating the library"));
889
+ return files;
890
+ }
891
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
892
+ if (entry.isFile() && entry.name.endsWith(".json.tmp")) continue;
893
+ if (allowedEntrySet.has(path.join(root, entry.name))) continue;
894
+ if (!entry.isFile() || !allowed.has(entry.name)) {
895
+ issues.push(issue("legacy_source_drift", path.join(root, entry.name), "classify the new legacy-root entry and obtain a fresh verification receipt before finalization"));
896
+ }
897
+ }
898
+ for (const file of expectedByPath.values()) {
899
+ const sourceKind = fs.existsSync(file.originalPath) ? fs.lstatSync(file.originalPath) : null;
900
+ if (!sourceKind?.isFile() || sourceKind.isSymbolicLink()
901
+ || sha256(fs.readFileSync(file.originalPath)) !== file.sha256
902
+ || (sourceKind.mode & 0o777) !== file.mode) {
903
+ issues.push(issue("legacy_source_drift", file.originalPath, "rerun apply-state and verify; a legacy telemetry source changed after the receipt"));
904
+ }
905
+ }
906
+ return [...expectedByPath.values()];
907
+ }
908
+
909
+ function legacySourceDrift(sourcePath, error) {
910
+ const drift = new Error(`legacy source changed after verification: ${sourcePath}: ${error.message}`);
911
+ drift.migrationIssueCode = "legacy_source_drift";
912
+ drift.migrationPath = sourcePath;
913
+ return drift;
914
+ }
915
+
916
+ function assertLegacySourcesStillVerified(home, preimage, manifest, allowedContextEntries, verifiedTails) {
917
+ const issues = [];
918
+ validateLegacySources(
919
+ preimage,
920
+ manifest,
921
+ path.join(home, "context"),
922
+ "context-source",
923
+ issues,
924
+ allowedContextEntries,
925
+ verifiedTails,
926
+ );
927
+ validateLegacySources(
928
+ preimage,
929
+ manifest,
930
+ path.join(home, "provider-usage"),
931
+ "provider-source",
932
+ issues,
933
+ [],
934
+ verifiedTails,
935
+ );
936
+ if (issues.length > 0) {
937
+ const first = issues[0];
938
+ throw legacySourceDrift(first.path ?? home, new Error(first.code));
939
+ }
940
+ }
941
+
942
+ function decodePlannedBytes(encoded, digest) {
943
+ const bytes = Buffer.from(encoded ?? "", "base64");
944
+ if (!encoded || sha256(bytes) !== digest) throw new Error("manifest-planned bytes do not match their digest");
945
+ return bytes;
946
+ }
947
+
948
+ function entrySnapshot(entryPath) {
949
+ const stat = fs.lstatSync(entryPath);
950
+ const mode = stat.mode & 0o777;
951
+ if (stat.isSymbolicLink()) {
952
+ return {
953
+ type: "symlink",
954
+ mode,
955
+ linkTargetBase64: fs.readlinkSync(entryPath, { encoding: "buffer" }).toString("base64"),
956
+ identity: { dev: String(stat.dev), ino: String(stat.ino) },
957
+ };
958
+ }
959
+ if (stat.isFile()) {
960
+ return {
961
+ type: "file",
962
+ mode,
963
+ sha256: sha256(fs.readFileSync(entryPath)),
964
+ identity: { dev: String(stat.dev), ino: String(stat.ino) },
965
+ };
966
+ }
967
+ if (stat.isDirectory()) {
968
+ return { type: "directory", mode, tree: treeSnapshot(entryPath) };
969
+ }
970
+ throw new Error(`unsupported library entry is not supported: ${entryPath}`);
971
+ }
972
+
973
+ function copyEntryOpaque(source, destination) {
974
+ const stat = fs.lstatSync(source);
975
+ if (stat.isSymbolicLink()) {
976
+ fs.symlinkSync(fs.readlinkSync(source), destination);
977
+ return;
978
+ }
979
+ if (stat.isFile()) {
980
+ fs.copyFileSync(source, destination, fs.constants.COPYFILE_EXCL);
981
+ fs.chmodSync(destination, stat.mode & 0o777);
982
+ return;
983
+ }
984
+ if (stat.isDirectory()) {
985
+ fs.mkdirSync(destination, { mode: stat.mode & 0o777 });
986
+ for (const name of fs.readdirSync(source).sort((left, right) => left.localeCompare(right))) {
987
+ copyEntryOpaque(path.join(source, name), path.join(destination, name));
988
+ }
989
+ fs.chmodSync(destination, stat.mode & 0o777);
990
+ return;
991
+ }
992
+ throw new Error(`unsupported library entry is not supported: ${source}`);
993
+ }
994
+
995
+ function semanticEntrySnapshot(snapshot) {
996
+ if (snapshot.type !== "directory") {
997
+ const { identity: _identity, ...semantic } = snapshot;
998
+ return semantic;
999
+ }
1000
+ return {
1001
+ type: snapshot.type,
1002
+ mode: snapshot.mode,
1003
+ digest: snapshot.tree.digest,
1004
+ entries: snapshot.tree.entries.map((entry) => {
1005
+ const { identity: _identity, ...semantic } = entry;
1006
+ return semantic;
1007
+ }),
1008
+ };
1009
+ }
1010
+
1011
+ function assertEntrySnapshot(entryPath, expected, requireIdentity = true) {
1012
+ const current = entrySnapshot(entryPath);
1013
+ if (JSON.stringify(semanticEntrySnapshot(current)) !== JSON.stringify(semanticEntrySnapshot(expected))) {
1014
+ throw new Error(`entry bytes, type, link payload, or mode changed: ${entryPath}`);
1015
+ }
1016
+ if (!requireIdentity) return current;
1017
+ if (expected.type === "directory") {
1018
+ if (current.tree.rootIdentity?.dev !== expected.tree.rootIdentity?.dev
1019
+ || current.tree.rootIdentity?.ino !== expected.tree.rootIdentity?.ino) {
1020
+ throw new Error(`entry identity changed: ${entryPath}`);
1021
+ }
1022
+ const currentLinks = new Map(current.tree.entries.filter((entry) => entry.type === "symlink").map((entry) => [entry.path, entry.identity]));
1023
+ for (const link of expected.tree.entries.filter((entry) => entry.type === "symlink")) {
1024
+ const identity = currentLinks.get(link.path);
1025
+ if (identity?.dev !== link.identity?.dev || identity?.ino !== link.identity?.ino) {
1026
+ throw new Error(`symlink identity changed: ${path.join(entryPath, link.path)}`);
1027
+ }
1028
+ }
1029
+ } else if (current.identity.dev !== expected.identity.dev || current.identity.ino !== expected.identity.ino) {
1030
+ throw new Error(`entry identity changed: ${entryPath}`);
1031
+ }
1032
+ return current;
1033
+ }
1034
+
1035
+ function libraryPlanFromManifest(manifest, home, issues) {
1036
+ const plan = manifest.libraryPlan;
1037
+ try {
1038
+ if (!plan
1039
+ || typeof plan.configPath !== "string"
1040
+ || typeof plan.sourceRoot !== "string"
1041
+ || typeof plan.targetRoot !== "string"
1042
+ || typeof plan.configExisted !== "boolean") throw new Error("library plan is absent or malformed");
1043
+ const activationConfig = decodePlannedBytes(plan.activationConfigBase64, plan.activationConfigSha256);
1044
+ const finalConfig = decodePlannedBytes(plan.finalConfigBase64, plan.finalConfigSha256);
1045
+ if (path.resolve(plan.configPath) !== path.join(home, "config.json")) throw new Error("config path does not match this home");
1046
+ return { ...plan, activationConfig, finalConfig };
1047
+ } catch (error) {
1048
+ issues.push(issue("preimage_manifest_mismatch", path.join(home, "config.json"), "use the exact preparation receipt for this home", {
1049
+ diagnostic: error.message,
1050
+ }));
1051
+ return null;
1052
+ }
1053
+ }
1054
+
1055
+ function applyLibrary(home, preimage, verificationPath) {
1056
+ if (!preimage) {
1057
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, issues: [issue("preimage_required", null, "pass the apply-state --preimage path")] }, 1);
1058
+ }
1059
+ const manifest = loadManifest(preimage, home, "apply-library");
1060
+ const issues = validatePreimage(preimage, manifest);
1061
+ if (manifest.status !== "applied") {
1062
+ issues.push(issue("preimage_manifest_mismatch", path.join(preimage, "manifest.json"), "the finalizer requires one completed preparation receipt"));
1063
+ }
1064
+ const receipt = verificationReceipt(home, preimage, verificationPath);
1065
+ if (receipt.issue) issues.push(receipt.issue);
1066
+ const verifiedTails = receipt.receipt?.legacyTails ?? [];
1067
+ const systemWorld = managedSystemWorldState(home, manifest, issues, receipt.receipt?.managedSystemWorld);
1068
+ const tailSamples = new Map();
1069
+ for (const sessionName of new Set(verifiedTails.map((tail) => tail.sessionName))) {
1070
+ const sample = telemetryPair(home, preimage, manifest, sessionName, issues);
1071
+ if (sample) tailSamples.set(sessionName, sample);
1072
+ }
1073
+ requireTailConvergence(verifiedTails, tailSamples, issues);
1074
+ const library = libraryPlanFromManifest(manifest, home, issues);
1075
+ validateLegacySources(
1076
+ preimage,
1077
+ manifest,
1078
+ path.join(home, "context"),
1079
+ "context-source",
1080
+ issues,
1081
+ systemWorld.directories,
1082
+ verifiedTails,
1083
+ );
1084
+ validateLegacySources(
1085
+ preimage,
1086
+ manifest,
1087
+ path.join(home, "provider-usage"),
1088
+ "provider-source",
1089
+ issues,
1090
+ [],
1091
+ verifiedTails,
1092
+ );
1093
+ if (library) {
1094
+ const currentConfigSha = fs.existsSync(library.configPath) ? sha256(fs.readFileSync(library.configPath)) : null;
1095
+ if (currentConfigSha !== library.activationConfigSha256) {
1096
+ issues.push(issue("config_drift", library.configPath, "preserve the changed config and prepare a fresh migration receipt before finalization"));
1097
+ }
1098
+ }
1099
+ if (issues.length > 0 || !library) {
1100
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues }, 1);
1101
+ }
1102
+
1103
+ let sourceTreeSnapshot;
1104
+ try {
1105
+ sourceTreeSnapshot = treeSnapshot(library.sourceRoot);
1106
+ } catch (error) {
1107
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1108
+ "library_source_invalid",
1109
+ library.sourceRoot,
1110
+ "preserve the unsupported entry and extend the bounded migration before retrying",
1111
+ { diagnostic: error.message },
1112
+ )] }, 1);
1113
+ }
1114
+ const systemEntry = sourceTreeSnapshot.entries.find((entry) => entry.path === "system");
1115
+ const systemWorldEntry = sourceTreeSnapshot.entries.find((entry) => entry.path === "system/system-world.yaml");
1116
+ if (systemEntry?.type === "symlink" || systemWorldEntry?.type === "symlink") {
1117
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1118
+ "system_world_conflict",
1119
+ path.join(library.sourceRoot, "system"),
1120
+ "preserve the opaque entry at the reserved System World path and reconcile it before migration",
1121
+ )] }, 1);
1122
+ }
1123
+ const sourceSystemWorld = path.join(library.sourceRoot, "system", "system-world.yaml");
1124
+ const sourceSystemEntries = systemEntry?.type === "directory"
1125
+ ? sourceTreeSnapshot.entries.filter((entry) => entry.path === "system" || entry.path.startsWith("system/"))
1126
+ : [];
1127
+ const sourceSystemWorldIsDefault = systemWorldEntry?.type === "file"
1128
+ && sha256(fs.readFileSync(sourceSystemWorld)) === sha256(DEFAULT_SYSTEM_WORLD)
1129
+ && sourceSystemEntries.length === 2;
1130
+ if (systemEntry && !sourceSystemWorldIsDefault) {
1131
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1132
+ "system_world_conflict",
1133
+ path.join(library.sourceRoot, "system"),
1134
+ "preserve the legacy library's reserved system entry and explicitly reconcile it before finalization",
1135
+ )] }, 1);
1136
+ }
1137
+
1138
+ try {
1139
+ assertTreeSnapshot(library.sourceRoot, sourceTreeSnapshot);
1140
+ } catch (error) {
1141
+ const libraryDrift = error.migrationIssueCode === "library_source_drift";
1142
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1143
+ libraryDrift ? "library_source_drift" : "preimage_mismatch",
1144
+ libraryDrift ? error.migrationPath : preimage,
1145
+ libraryDrift
1146
+ ? "preserve the changed context library and rerun from a fresh inventory"
1147
+ : "restore a writeable byte-matching preimage before finalization",
1148
+ { diagnostic: error.message },
1149
+ )] }, 1);
1150
+ }
1151
+
1152
+ const targetStat = lstatOrNull(library.targetRoot);
1153
+ if (targetStat && (!targetStat.isDirectory() || targetStat.isSymbolicLink())) {
1154
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1155
+ "library_target_conflict",
1156
+ library.targetRoot,
1157
+ "preserve the opaque target and select the intended canonical context root before finalization",
1158
+ )] }, 1);
1159
+ }
1160
+ const sourceTopLevel = sourceTreeSnapshot.digest === null
1161
+ ? []
1162
+ : fs.readdirSync(library.sourceRoot, { withFileTypes: true })
1163
+ .map((entry) => entry.name)
1164
+ .filter((name) => name !== "system")
1165
+ .sort((left, right) => left.localeCompare(right));
1166
+ if (library.sourceRoot !== library.targetRoot) {
1167
+ for (const name of sourceTopLevel) {
1168
+ const destination = path.join(library.targetRoot, name);
1169
+ if (lstatOrNull(destination)) {
1170
+ emit({ schema: SCHEMA, phase: "apply-library", ok: false, applied: false, complete: false, issues: [issue(
1171
+ "library_target_conflict",
1172
+ destination,
1173
+ "preserve both entries and reconcile the collision before finalization; no existing target is overwritten",
1174
+ )] }, 1);
1175
+ }
1176
+ }
1177
+ }
1178
+
1179
+ const prepared = {
1180
+ ...manifest,
1181
+ status: "finalizer-prepared",
1182
+ library: {
1183
+ sourceRoot: library.sourceRoot,
1184
+ targetRoot: library.targetRoot,
1185
+ sourceTreeDigest: sourceTreeSnapshot.digest,
1186
+ sourceTreeRootIdentity: sourceTreeSnapshot.rootIdentity,
1187
+ sourceTreeInventory: sourceTreeSnapshot.entries,
1188
+ skippedMatchingSourceSystemWorld: sourceSystemWorldIsDefault,
1189
+ configExisted: library.configExisted,
1190
+ activationConfigSha256: library.activationConfigSha256,
1191
+ finalConfigSha256: library.finalConfigSha256,
1192
+ copiedRoots: [],
1193
+ },
1194
+ };
1195
+ const manifestPath = path.join(preimage, "manifest.json");
1196
+ atomicWrite(manifestPath, Buffer.from(`${JSON.stringify(prepared, null, 2)}\n`), 0o600);
1197
+
1198
+ try {
1199
+ assertTreeSnapshot(library.sourceRoot, sourceTreeSnapshot);
1200
+ fs.mkdirSync(library.targetRoot, { recursive: true });
1201
+ const copiedRoots = [];
1202
+ if (library.sourceRoot !== library.targetRoot) {
1203
+ for (const name of sourceTopLevel) {
1204
+ const source = path.join(library.sourceRoot, name);
1205
+ const destination = path.join(library.targetRoot, name);
1206
+ assertTreeSnapshot(library.sourceRoot, sourceTreeSnapshot);
1207
+ const sourceEntry = entrySnapshot(source);
1208
+ copiedRoots.push({ name, snapshot: sourceEntry });
1209
+ atomicWrite(manifestPath, Buffer.from(`${JSON.stringify({
1210
+ ...prepared,
1211
+ status: "finalizer-copying",
1212
+ library: { ...prepared.library, copiedRoots },
1213
+ }, null, 2)}\n`), 0o600);
1214
+ copyEntryOpaque(source, destination);
1215
+ const destinationEntry = assertEntrySnapshot(destination, sourceEntry, false);
1216
+ copiedRoots[copiedRoots.length - 1] = { name, snapshot: destinationEntry };
1217
+ atomicWrite(manifestPath, Buffer.from(`${JSON.stringify({
1218
+ ...prepared,
1219
+ status: "finalizer-copying",
1220
+ library: { ...prepared.library, copiedRoots },
1221
+ }, null, 2)}\n`), 0o600);
1222
+ }
1223
+ }
1224
+ assertTreeSnapshot(library.sourceRoot, sourceTreeSnapshot);
1225
+ assertLegacySourcesStillVerified(
1226
+ home,
1227
+ preimage,
1228
+ manifest,
1229
+ [...systemWorld.directories, ...copiedRoots.map((entry) => path.join(library.targetRoot, entry.name))],
1230
+ verifiedTails,
1231
+ );
1232
+ if (sha256(fs.readFileSync(library.configPath)) !== library.activationConfigSha256) {
1233
+ throw new Error(`config changed during finalization: ${library.configPath}`);
1234
+ }
1235
+ if (library.activationConfigSha256 !== library.finalConfigSha256) {
1236
+ atomicWrite(library.configPath, library.finalConfig, fs.statSync(library.configPath).mode & 0o777);
1237
+ }
1238
+ const appliedAt = new Date().toISOString();
1239
+ const completed = {
1240
+ ...prepared,
1241
+ status: "finalizer-applied",
1242
+ library: {
1243
+ ...prepared.library,
1244
+ copiedRoots,
1245
+ targetTreeDigest: treeDigest(library.targetRoot),
1246
+ appliedConfigSha256: sha256(fs.readFileSync(library.configPath)),
1247
+ appliedAt,
1248
+ },
1249
+ };
1250
+ atomicWrite(manifestPath, Buffer.from(`${JSON.stringify(completed, null, 2)}\n`), 0o600);
1251
+ emit({
1252
+ schema: SCHEMA,
1253
+ generatedAt: appliedAt,
1254
+ home,
1255
+ phase: "apply-library",
1256
+ applied: true,
1257
+ complete: true,
1258
+ preimage,
1259
+ operation: "non-destructive-finalizer",
1260
+ sourceRoot: library.sourceRoot,
1261
+ contextRoot: library.targetRoot,
1262
+ systemWorldPath: systemWorld.artifact?.path ?? null,
1263
+ copied: copiedRoots.map((entry) => path.join(library.targetRoot, entry.name)),
1264
+ preservedRecovery: [library.sourceRoot, path.join(home, "context"), path.join(home, "provider-usage")],
1265
+ issues: [],
1266
+ next: "inspect the copied library, effective context root, System World provenance, and representative fresh-seat behavior; keep the legacy sources until separately retired",
1267
+ });
1268
+ } catch (error) {
1269
+ const sourceDrift = error.migrationIssueCode === "legacy_source_drift";
1270
+ const libraryDrift = error.migrationIssueCode === "library_source_drift";
1271
+ emit({
1272
+ schema: SCHEMA,
1273
+ phase: "apply-library",
1274
+ ok: false,
1275
+ applied: false,
1276
+ complete: false,
1277
+ preimage,
1278
+ issues: [issue(
1279
+ sourceDrift ? "legacy_source_drift" : libraryDrift ? "library_source_drift" : "library_apply_incomplete",
1280
+ sourceDrift || libraryDrift ? error.migrationPath : null,
1281
+ libraryDrift
1282
+ ? "preserve the changed context library and run --rollback with this preimage before retrying"
1283
+ : sourceDrift
1284
+ ? "preserve the changed legacy telemetry source and obtain a fresh verification receipt"
1285
+ : "run --rollback with this preimage before retrying; copied roots remain recorded and the source was not removed",
1286
+ { diagnostic: error.message },
1287
+ )],
1288
+ }, 1);
1289
+ }
1290
+ }
1291
+
1292
+ function rollback(home, preimage) {
1293
+ const manifest = loadManifest(preimage, home, "rollback");
1294
+ const issues = validatePreimage(preimage, manifest);
1295
+ const libraryPlan = libraryPlanFromManifest(manifest, home, issues);
1296
+ const configRecord = manifest.files.find((file) => file.kind === "config");
1297
+ const copiedRoots = Array.isArray(manifest.library?.copiedRoots) ? manifest.library.copiedRoots : [];
1298
+ const restored = [];
1299
+ const alreadyOriginal = [];
1300
+
1301
+ if (libraryPlan) {
1302
+ const configExists = fs.existsSync(libraryPlan.configPath);
1303
+ const currentConfigSha = configExists ? sha256(fs.readFileSync(libraryPlan.configPath)) : null;
1304
+ const originalSha = configRecord?.sha256 ?? null;
1305
+ const accepted = new Set([originalSha, libraryPlan.activationConfigSha256, libraryPlan.finalConfigSha256].filter(Boolean));
1306
+ if (currentConfigSha === originalSha || (!libraryPlan.configExisted && currentConfigSha === null)) {
1307
+ alreadyOriginal.push(libraryPlan.configPath);
1308
+ } else if (currentConfigSha === null || !accepted.has(currentConfigSha)) {
1309
+ issues.push(issue("destination_drift", libraryPlan.configPath, "preserve the changed config and decide its recovery before rollback"));
1310
+ }
1311
+ }
1312
+
1313
+ for (const copied of copiedRoots) {
1314
+ const destination = libraryPlan ? path.join(libraryPlan.targetRoot, copied.name) : null;
1315
+ if (!destination || copied.name.includes(path.sep) || copied.name === "." || copied.name === "..") {
1316
+ issues.push(issue("preimage_manifest_mismatch", destination, "use the exact preparation receipt for this home"));
1317
+ continue;
1318
+ }
1319
+ if (!lstatOrNull(destination)) {
1320
+ alreadyOriginal.push(destination);
1321
+ continue;
1322
+ }
1323
+ try {
1324
+ assertEntrySnapshot(destination, copied.snapshot, true);
1325
+ } catch (error) {
1326
+ issues.push(issue("destination_drift", destination, "preserve the changed copied library entry and reconcile it before rollback", {
1327
+ diagnostic: error.message,
1328
+ }));
1329
+ }
1330
+ }
1331
+
1332
+ const systemWorld = manifest.systemWorld;
1333
+ if (systemWorld && !systemWorld.existed && lstatOrNull(systemWorld.path)) {
1334
+ const current = lstatOrNull(systemWorld.path);
1335
+ if (!current?.isFile() || current.isSymbolicLink()
1336
+ || sha256(fs.readFileSync(systemWorld.path)) !== systemWorld.sha256
1337
+ || (current.mode & 0o777) !== systemWorld.mode) {
1338
+ issues.push(issue("destination_drift", systemWorld.path, "preserve the changed System World and reconcile it before rollback"));
1339
+ }
1340
+ }
1341
+
1342
+ if (issues.length > 0) {
1343
+ emit({ schema: SCHEMA, phase: "rollback", rolledBack: false, complete: false, preimage, restored: [], alreadyOriginal, issues }, 1);
1344
+ }
1345
+
1346
+ for (const copied of [...copiedRoots].reverse()) {
1347
+ const destination = path.join(libraryPlan.targetRoot, copied.name);
1348
+ if (lstatOrNull(destination)) {
1349
+ fs.rmSync(destination, { recursive: true, force: false });
1350
+ restored.push(destination);
1351
+ }
1352
+ }
1353
+ if (libraryPlan) {
1354
+ if (libraryPlan.configExisted && configRecord) {
1355
+ const original = fs.readFileSync(path.join(preimage, configRecord.storedAs));
1356
+ if (!fs.existsSync(libraryPlan.configPath) || sha256(fs.readFileSync(libraryPlan.configPath)) !== configRecord.sha256) {
1357
+ atomicWrite(libraryPlan.configPath, original, configRecord.mode);
1358
+ restored.push(libraryPlan.configPath);
1359
+ }
1360
+ } else if (fs.existsSync(libraryPlan.configPath)) {
1361
+ fs.rmSync(libraryPlan.configPath);
1362
+ restored.push(libraryPlan.configPath);
1363
+ }
1364
+ }
1365
+ if (systemWorld && !systemWorld.existed && lstatOrNull(systemWorld.path)) {
1366
+ fs.rmSync(systemWorld.path);
1367
+ restored.push(systemWorld.path);
1368
+ const directory = path.dirname(systemWorld.path);
1369
+ if (fs.readdirSync(directory).length === 0) fs.rmdirSync(directory);
1370
+ }
1371
+ for (const directory of [...(manifest.stateDirectories ?? [])].reverse()) {
1372
+ if (!directory.existed && lstatOrNull(directory.path)?.isDirectory() && fs.readdirSync(directory.path).length === 0) {
1373
+ fs.rmdirSync(directory.path);
1374
+ restored.push(directory.path);
1375
+ }
1376
+ }
1377
+ emit({
1378
+ schema: SCHEMA,
1379
+ generatedAt: new Date().toISOString(),
1380
+ home,
1381
+ phase: "rollback",
1382
+ rolledBack: true,
1383
+ complete: true,
1384
+ preimage,
1385
+ restored,
1386
+ alreadyOriginal,
1387
+ preservedLegacy: [path.join(home, "context"), path.join(home, "provider-usage"), libraryPlan?.sourceRoot].filter(Boolean),
1388
+ issues: [],
1389
+ next: "helper-owned preparation and finalizer effects are reversed; legacy sources and unrelated canonical state remain untouched",
1390
+ });
1391
+ }
1392
+
1393
+ const argv = process.argv.slice(2);
1394
+ if (argv.includes("--help") || argv.includes("-h")) {
1395
+ process.stdout.write(HELP);
1396
+ process.exit(0);
1397
+ }
1398
+ const parsed = parseArguments(argv);
1399
+ if (parsed.issue) {
1400
+ emit({ schema: SCHEMA, phase: "input", ok: false, issues: [parsed.issue] }, 1);
1401
+ }
1402
+ const homeArg = parsed.values.get("--home") || process.env.OPENRIG_HOME;
1403
+ if (!homeArg) {
1404
+ emit({ schema: SCHEMA, phase: "input", ok: false, issues: [issue("home_required", null, "pass --home or set OPENRIG_HOME")] }, 1);
1405
+ }
1406
+ const home = path.resolve(homeArg);
1407
+ const apply = parsed.phases.has("--apply-state");
1408
+ const verifyFlag = parsed.phases.has("--verify");
1409
+ const applyLibraryFlag = parsed.phases.has("--apply-library");
1410
+ const rollbackArg = parsed.values.get("--rollback");
1411
+ if ([apply, verifyFlag, applyLibraryFlag, Boolean(rollbackArg)].filter(Boolean).length > 1) {
1412
+ emit({ schema: SCHEMA, phase: "input", ok: false, issues: [issue("phase_conflict", null, "choose exactly one of --apply-state, --verify, --apply-library, or --rollback")] }, 1);
1413
+ }
1414
+
1415
+ if (apply) applyState(home, parsed.values.get("--preimage"));
1416
+ if (verifyFlag) verify(home, parsed.values.get("--preimage"));
1417
+ if (applyLibraryFlag) applyLibrary(home, parsed.values.get("--preimage"), parsed.values.get("--verification"));
1418
+ if (rollbackArg) rollback(home, path.resolve(rollbackArg));
1419
+ emit(publicPlan(home, buildPlan(home)));