@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831

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 (647) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5308 -16
  16. package/deploy/unraid/Dockerfile +54 -0
  17. package/deploy/unraid/README.txt +2983 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  34. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  35. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
  36. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  37. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  38. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  39. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  40. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  41. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  42. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
  43. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
  49. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  50. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
  51. package/deploy/unraid/sanctuary.xml +28 -0
  52. package/dist/a2a/card.js +57 -0
  53. package/dist/a2a/client.js +180 -0
  54. package/dist/a2a/config.js +50 -0
  55. package/dist/a2a/delegation-stores.js +56 -0
  56. package/dist/a2a/did-resolution.js +93 -0
  57. package/dist/a2a/identity.js +170 -0
  58. package/dist/a2a/inbound-share.js +107 -0
  59. package/dist/a2a/mission-result-wire.js +196 -0
  60. package/dist/a2a/onboarding.js +115 -0
  61. package/dist/a2a/pin-store.js +132 -0
  62. package/dist/a2a/seen-ledger.js +120 -0
  63. package/dist/a2a/server.js +604 -0
  64. package/dist/a2a/task-store.js +69 -0
  65. package/dist/a2a/transport.js +45 -0
  66. package/dist/a2a/types.js +3 -0
  67. package/dist/arc/attention-types.js +8 -0
  68. package/dist/arc/cares.js +360 -0
  69. package/dist/arc/episodes.js +118 -0
  70. package/dist/arc/evolution.js +490 -0
  71. package/dist/arc/flight-recorder.js +1034 -0
  72. package/dist/arc/intentions.js +134 -0
  73. package/dist/arc/json-store.js +117 -0
  74. package/dist/arc/obligations.js +386 -0
  75. package/dist/arc/packets.js +336 -0
  76. package/dist/arc/presence.js +185 -0
  77. package/dist/arc/task-lifecycle.js +57 -0
  78. package/dist/commerce/store.js +755 -0
  79. package/dist/commerce/types.js +3 -0
  80. package/dist/heart/active-work.js +798 -40
  81. package/dist/heart/agent-entry.js +252 -3
  82. package/dist/heart/approval-files.js +113 -0
  83. package/dist/heart/approval-store.js +960 -0
  84. package/dist/heart/attachments/image-normalize.js +194 -0
  85. package/dist/heart/attachments/materialize.js +97 -0
  86. package/dist/heart/attachments/originals.js +88 -0
  87. package/dist/heart/attachments/render.js +29 -0
  88. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  89. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  90. package/dist/heart/attachments/sources/index.js +18 -0
  91. package/dist/heart/attachments/sources/telegram.js +71 -0
  92. package/dist/heart/attachments/store.js +132 -0
  93. package/dist/heart/attachments/types.js +93 -0
  94. package/dist/heart/auth/auth-flow.js +495 -0
  95. package/dist/heart/autonomy-budget.js +478 -0
  96. package/dist/heart/awaiting/await-alert.js +148 -0
  97. package/dist/heart/awaiting/await-expiry.js +143 -0
  98. package/dist/heart/awaiting/await-loader.js +91 -0
  99. package/dist/heart/awaiting/await-parser.js +149 -0
  100. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  101. package/dist/heart/awaiting/await-scheduler.js +382 -0
  102. package/dist/heart/background-operations.js +281 -0
  103. package/dist/heart/bridges/manager.js +137 -17
  104. package/dist/heart/bridges/store.js +14 -2
  105. package/dist/heart/bundle-state.js +168 -0
  106. package/dist/heart/commitments.js +44 -18
  107. package/dist/heart/config-registry.js +331 -0
  108. package/dist/heart/config.js +174 -131
  109. package/dist/heart/context-loss-gauntlet.js +387 -0
  110. package/dist/heart/context-loss-sentinel.js +1157 -0
  111. package/dist/heart/core.js +2169 -581
  112. package/dist/heart/cross-chat-delivery.js +9 -22
  113. package/dist/heart/daemon/agent-config-check.js +451 -0
  114. package/dist/heart/daemon/agent-discovery.js +185 -3
  115. package/dist/heart/daemon/agent-service.js +542 -0
  116. package/dist/heart/daemon/agentic-repair.js +547 -0
  117. package/dist/heart/daemon/await-private-wake.js +59 -0
  118. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  119. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  120. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  121. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  122. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  123. package/dist/heart/daemon/cadence.js +180 -0
  124. package/dist/heart/daemon/cli-defaults.js +854 -0
  125. package/dist/heart/daemon/cli-desk.js +322 -0
  126. package/dist/heart/daemon/cli-exec.js +8822 -0
  127. package/dist/heart/daemon/cli-help.js +716 -0
  128. package/dist/heart/daemon/cli-parse.js +2771 -0
  129. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  130. package/dist/heart/daemon/cli-render.js +777 -0
  131. package/dist/heart/daemon/cli-types.js +8 -0
  132. package/dist/heart/daemon/connect-bay.js +323 -0
  133. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  134. package/dist/heart/daemon/container-healthcheck.js +112 -0
  135. package/dist/heart/daemon/container-runtime.js +97 -0
  136. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  137. package/dist/heart/daemon/container-spec-auditor.js +229 -0
  138. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  139. package/dist/heart/daemon/daemon-cli.js +29 -2349
  140. package/dist/heart/daemon/daemon-entry.js +930 -11
  141. package/dist/heart/daemon/daemon-health.js +186 -0
  142. package/dist/heart/daemon/daemon-rollup.js +57 -0
  143. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  144. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  145. package/dist/heart/daemon/daemon.js +2084 -105
  146. package/dist/heart/daemon/dns-workflow.js +394 -0
  147. package/dist/heart/daemon/doctor-types.js +8 -0
  148. package/dist/heart/daemon/doctor.js +1755 -0
  149. package/dist/heart/daemon/freshness.js +345 -0
  150. package/dist/heart/daemon/habit-private-wake.js +61 -0
  151. package/dist/heart/daemon/health-monitor.js +142 -11
  152. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  153. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  154. package/dist/heart/daemon/http-health-probe.js +80 -0
  155. package/dist/heart/daemon/human-command-screens.js +234 -0
  156. package/dist/heart/daemon/human-readiness.js +114 -0
  157. package/dist/heart/daemon/inner-status.js +78 -0
  158. package/dist/heart/daemon/interactive-repair.js +394 -0
  159. package/dist/heart/daemon/launchd.js +37 -8
  160. package/dist/heart/daemon/log-tailer.js +79 -10
  161. package/dist/heart/daemon/logs-prune.js +132 -0
  162. package/dist/heart/daemon/mcp-canary.js +524 -0
  163. package/dist/heart/daemon/message-router.js +65 -5
  164. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  165. package/dist/heart/daemon/os-cron-deps.js +135 -0
  166. package/dist/heart/daemon/os-cron.js +22 -14
  167. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  168. package/dist/heart/daemon/ouro-entry.js +3 -1
  169. package/dist/heart/daemon/plugin-cli.js +432 -0
  170. package/dist/heart/daemon/process-manager.js +733 -61
  171. package/dist/heart/daemon/provider-discovery.js +137 -0
  172. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  173. package/dist/heart/daemon/prunable-bundle.js +144 -0
  174. package/dist/heart/daemon/pulse.js +511 -0
  175. package/dist/heart/daemon/readiness-repair.js +365 -0
  176. package/dist/heart/daemon/run-hooks.js +2 -0
  177. package/dist/heart/daemon/runtime-logging.js +47 -14
  178. package/dist/heart/daemon/runtime-metadata.js +2 -30
  179. package/dist/heart/daemon/runtime-mode.js +13 -2
  180. package/dist/heart/daemon/safe-mode.js +161 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  184. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  185. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  186. package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
  187. package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
  188. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  189. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
  190. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  191. package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
  192. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  193. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
  194. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  195. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  196. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  197. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  198. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  199. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  200. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  201. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
  202. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  203. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
  204. package/dist/heart/daemon/sense-manager.js +699 -48
  205. package/dist/heart/daemon/session-id-resolver.js +131 -0
  206. package/dist/heart/daemon/skill-management-installer.js +1 -1
  207. package/dist/heart/daemon/socket-client.js +180 -12
  208. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  209. package/dist/heart/daemon/startup-tui.js +339 -0
  210. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  211. package/dist/heart/daemon/task-scheduler.js +117 -39
  212. package/dist/heart/daemon/terminal-ui.js +499 -0
  213. package/dist/heart/daemon/thoughts.js +138 -54
  214. package/dist/heart/daemon/up-progress.js +366 -0
  215. package/dist/heart/daemon/vault-items.js +56 -0
  216. package/dist/heart/delegation.js +1 -4
  217. package/dist/heart/external-events/router.js +1430 -0
  218. package/dist/heart/frontend-approval-runtime.js +506 -0
  219. package/dist/heart/frontend-journal.js +215 -0
  220. package/dist/heart/frontend-session-service.js +237 -0
  221. package/dist/heart/frontend-socket-client.js +164 -0
  222. package/dist/heart/frontend-socket.js +400 -0
  223. package/dist/heart/habits/habit-cancel.js +810 -0
  224. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  225. package/dist/heart/habits/habit-migration.js +194 -0
  226. package/dist/heart/habits/habit-parser.js +278 -0
  227. package/dist/heart/habits/habit-runtime-state.js +93 -0
  228. package/dist/heart/habits/habit-scheduler.js +653 -0
  229. package/dist/heart/habits/habit-session-summary.js +318 -0
  230. package/dist/heart/habits/habit-session.js +636 -0
  231. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  232. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  233. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  234. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  235. package/dist/heart/identity.js +196 -59
  236. package/dist/heart/kept-notes.js +289 -0
  237. package/dist/heart/kicks.js +1 -1
  238. package/dist/heart/machine-identity.js +161 -0
  239. package/dist/heart/mail-import-discovery.js +356 -0
  240. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  241. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  242. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  243. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  244. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  245. package/dist/heart/mailbox/mailbox-http.js +99 -0
  246. package/dist/heart/mailbox/mailbox-read.js +39 -0
  247. package/dist/heart/mailbox/mailbox-types.js +27 -0
  248. package/dist/heart/mailbox/mailbox-view.js +197 -0
  249. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  250. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  251. package/dist/heart/mailbox/readers/mail.js +375 -0
  252. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  253. package/dist/heart/mailbox/readers/sessions.js +231 -0
  254. package/dist/heart/mailbox/readers/shared.js +111 -0
  255. package/dist/heart/mcp/mcp-server.js +696 -0
  256. package/dist/heart/migrate-config.js +100 -0
  257. package/dist/heart/model-capabilities.js +11 -0
  258. package/dist/heart/orientation-frame.js +345 -0
  259. package/dist/heart/platform.js +81 -0
  260. package/dist/heart/primitives.js +1 -1
  261. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  262. package/dist/heart/private-runtime/index.js +18 -0
  263. package/dist/heart/private-runtime/ledger.js +221 -0
  264. package/dist/heart/private-runtime/policy.js +252 -0
  265. package/dist/heart/private-runtime/types.js +2 -0
  266. package/dist/heart/progress-story.js +1 -1
  267. package/dist/heart/provider-attempt.js +137 -0
  268. package/dist/heart/provider-binding-resolver.js +273 -0
  269. package/dist/heart/provider-credentials.js +449 -0
  270. package/dist/heart/provider-failover.js +311 -0
  271. package/dist/heart/provider-models.js +96 -0
  272. package/dist/heart/provider-ping.js +265 -0
  273. package/dist/heart/provider-readiness-cache.js +119 -0
  274. package/dist/heart/provider-visibility.js +188 -0
  275. package/dist/heart/providers/anthropic-token.js +131 -0
  276. package/dist/heart/providers/anthropic.js +173 -60
  277. package/dist/heart/providers/azure.js +23 -11
  278. package/dist/heart/providers/error-classification.js +127 -0
  279. package/dist/heart/providers/github-copilot.js +34 -38
  280. package/dist/heart/providers/minimax-vlm.js +189 -0
  281. package/dist/heart/providers/minimax.js +26 -8
  282. package/dist/heart/providers/openai-codex-token.js +349 -0
  283. package/dist/heart/providers/openai-codex.js +55 -40
  284. package/dist/heart/providers/openai-compatible.js +177 -0
  285. package/dist/heart/run-ledger.js +247 -0
  286. package/dist/heart/runtime-capability-check.js +170 -0
  287. package/dist/heart/runtime-credentials.js +607 -0
  288. package/dist/heart/runtime-cwd.js +87 -0
  289. package/dist/heart/sense-truth.js +22 -4
  290. package/dist/heart/session-activity.js +92 -24
  291. package/dist/heart/session-events.js +1504 -0
  292. package/dist/heart/session-playback-cli-main.js +5 -0
  293. package/dist/heart/session-playback-cli.js +36 -0
  294. package/dist/heart/session-playback.js +231 -0
  295. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  296. package/dist/heart/session-redaction-repair.js +552 -0
  297. package/dist/heart/session-stats-cli-main.js +5 -0
  298. package/dist/heart/session-stats.js +183 -0
  299. package/dist/heart/session-transcript.js +133 -0
  300. package/dist/heart/start-of-turn-packet.js +372 -0
  301. package/dist/heart/steward-policy.js +618 -0
  302. package/dist/heart/streaming.js +604 -207
  303. package/dist/heart/structured-output.js +196 -0
  304. package/dist/heart/sync-classification.js +176 -0
  305. package/dist/heart/sync.js +449 -0
  306. package/dist/heart/target-resolution.js +11 -7
  307. package/dist/heart/tempo.js +93 -0
  308. package/dist/heart/temporal-view.js +41 -0
  309. package/dist/heart/timeouts.js +101 -0
  310. package/dist/heart/tool-activity-callbacks.js +59 -0
  311. package/dist/heart/tool-approval.js +382 -0
  312. package/dist/heart/tool-description.js +155 -0
  313. package/dist/heart/tool-friction.js +55 -0
  314. package/dist/heart/tool-loop.js +200 -0
  315. package/dist/heart/turn-context.js +482 -0
  316. package/dist/heart/turn-execution-lease.js +30 -0
  317. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  318. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  319. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  320. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  321. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  322. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  323. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  324. package/dist/heart/versioning/update-hooks.js +154 -0
  325. package/dist/heart/versioning/version-intent.js +114 -0
  326. package/dist/heart/work-card.js +380 -0
  327. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  328. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  329. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  330. package/dist/mailbox-ui/index.html +16 -0
  331. package/dist/mailroom/attention.js +167 -0
  332. package/dist/mailroom/autonomy.js +209 -0
  333. package/dist/mailroom/blob-store.js +889 -0
  334. package/dist/mailroom/body-cache.js +61 -0
  335. package/dist/mailroom/cache-sync-cli.js +58 -0
  336. package/dist/mailroom/core.js +803 -0
  337. package/dist/mailroom/entry.js +160 -0
  338. package/dist/mailroom/file-store.js +568 -0
  339. package/dist/mailroom/hosted-cache-sync.js +384 -0
  340. package/dist/mailroom/mbox-import.js +393 -0
  341. package/dist/mailroom/migration.js +164 -0
  342. package/dist/mailroom/outbound.js +380 -0
  343. package/dist/mailroom/policy.js +263 -0
  344. package/dist/mailroom/reader.js +292 -0
  345. package/dist/mailroom/search-cache.js +513 -0
  346. package/dist/mailroom/search-relevance.js +319 -0
  347. package/dist/mailroom/smtp-ingress.js +176 -0
  348. package/dist/mailroom/source-state.js +176 -0
  349. package/dist/mailroom/thread.js +109 -0
  350. package/dist/mailroom/travel-extract.js +89 -0
  351. package/dist/mind/bundle-manifest.js +24 -2
  352. package/dist/mind/context.js +309 -111
  353. package/dist/mind/desk-section.js +362 -0
  354. package/dist/mind/diary-integrity.js +60 -0
  355. package/dist/mind/{memory.js → diary.js} +68 -77
  356. package/dist/mind/embedding-provider.js +60 -0
  357. package/dist/mind/file-state.js +179 -0
  358. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  359. package/dist/mind/obligation-steering.js +199 -3
  360. package/dist/mind/pending.js +36 -10
  361. package/dist/mind/prompt-budget.js +479 -0
  362. package/dist/mind/prompt-refresh.js +3 -2
  363. package/dist/mind/prompt.js +1050 -189
  364. package/dist/mind/provenance-trust.js +26 -0
  365. package/dist/mind/record-paths.js +312 -0
  366. package/dist/mind/scrutiny.js +173 -0
  367. package/dist/mind/session-transaction.js +564 -0
  368. package/dist/nerves/cli-logging.js +7 -1
  369. package/dist/nerves/coverage/audit-rules.js +15 -6
  370. package/dist/nerves/coverage/audit.js +28 -2
  371. package/dist/nerves/coverage/cli.js +1 -1
  372. package/dist/nerves/coverage/contract.js +5 -5
  373. package/dist/nerves/coverage/file-completeness.js +139 -5
  374. package/dist/nerves/coverage/run-artifacts.js +55 -35
  375. package/dist/nerves/coverage/source-scanner.js +4 -4
  376. package/dist/nerves/event-buffer.js +111 -0
  377. package/dist/nerves/index.js +293 -9
  378. package/dist/nerves/observation.js +20 -0
  379. package/dist/nerves/redact.js +79 -0
  380. package/dist/nerves/review/cli-main.js +5 -0
  381. package/dist/nerves/review/cli.js +156 -0
  382. package/dist/nerves/review/core.js +159 -0
  383. package/dist/nerves/runtime.js +17 -1
  384. package/dist/repertoire/ado-client.js +15 -56
  385. package/dist/repertoire/ado-semantic.js +16 -10
  386. package/dist/repertoire/api-client.js +97 -0
  387. package/dist/repertoire/bitwarden-store.js +1045 -0
  388. package/dist/repertoire/bundle-templates.js +71 -0
  389. package/dist/repertoire/bw-installer.js +180 -0
  390. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  391. package/dist/repertoire/coding/context-pack.js +331 -0
  392. package/dist/repertoire/coding/feedback.js +174 -32
  393. package/dist/repertoire/coding/index.js +15 -3
  394. package/dist/repertoire/coding/manager.js +159 -10
  395. package/dist/repertoire/coding/spawner.js +58 -11
  396. package/dist/repertoire/coding/tools.js +221 -15
  397. package/dist/repertoire/coding/workbench-client.js +272 -0
  398. package/dist/repertoire/coding/workbench-manager.js +346 -0
  399. package/dist/repertoire/commerce-errors.js +109 -0
  400. package/dist/repertoire/commerce-self-test.js +156 -0
  401. package/dist/repertoire/credential-access.js +178 -0
  402. package/dist/repertoire/desk/classifier.js +362 -0
  403. package/dist/repertoire/duffel-client.js +185 -0
  404. package/dist/repertoire/github-client.js +14 -55
  405. package/dist/repertoire/graph-client.js +11 -52
  406. package/dist/repertoire/guardrails.js +811 -18
  407. package/dist/repertoire/mcp-client.js +44 -3
  408. package/dist/repertoire/mcp-manager.js +427 -139
  409. package/dist/repertoire/mcp-tools.js +124 -0
  410. package/dist/repertoire/plugin-mcp.js +175 -0
  411. package/dist/repertoire/plugins.js +253 -0
  412. package/dist/repertoire/relationship-authorization.js +322 -0
  413. package/dist/repertoire/shell-sessions.js +134 -0
  414. package/dist/repertoire/skills.js +48 -4
  415. package/dist/repertoire/stripe-client.js +131 -0
  416. package/dist/repertoire/tool-arguments.js +170 -0
  417. package/dist/repertoire/tool-results.js +29 -0
  418. package/dist/repertoire/tools-a2a.js +699 -0
  419. package/dist/repertoire/tools-attachments.js +322 -0
  420. package/dist/repertoire/tools-awaiting.js +575 -0
  421. package/dist/repertoire/tools-base.js +77 -1138
  422. package/dist/repertoire/tools-bluebubbles.js +2 -0
  423. package/dist/repertoire/tools-bridge.js +144 -0
  424. package/dist/repertoire/tools-bundle.js +993 -0
  425. package/dist/repertoire/tools-commerce.js +253 -0
  426. package/dist/repertoire/tools-config.js +186 -0
  427. package/dist/repertoire/tools-continuity.js +575 -0
  428. package/dist/repertoire/tools-credential.js +383 -0
  429. package/dist/repertoire/tools-evolution.js +527 -0
  430. package/dist/repertoire/tools-files.js +344 -0
  431. package/dist/repertoire/tools-flight.js +290 -0
  432. package/dist/repertoire/tools-flow.js +119 -0
  433. package/dist/repertoire/tools-github.js +3 -8
  434. package/dist/repertoire/tools-habits.js +103 -0
  435. package/dist/repertoire/tools-mail.js +1828 -0
  436. package/dist/repertoire/tools-notes.js +485 -0
  437. package/dist/repertoire/tools-obligations.js +182 -0
  438. package/dist/repertoire/tools-orientation.js +31 -0
  439. package/dist/repertoire/tools-record.js +482 -0
  440. package/dist/repertoire/tools-rsvp.js +139 -0
  441. package/dist/repertoire/tools-runtime.js +150 -0
  442. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  443. package/dist/repertoire/tools-session.js +1133 -0
  444. package/dist/repertoire/tools-shell.js +149 -0
  445. package/dist/repertoire/tools-steward-policy.js +119 -0
  446. package/dist/repertoire/tools-stripe.js +224 -0
  447. package/dist/repertoire/tools-surface.js +369 -0
  448. package/dist/repertoire/tools-teams.js +12 -39
  449. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  450. package/dist/repertoire/tools-travel.js +125 -0
  451. package/dist/repertoire/tools-trip.js +982 -0
  452. package/dist/repertoire/tools-unraid.js +531 -0
  453. package/dist/repertoire/tools-user-profile.js +146 -0
  454. package/dist/repertoire/tools-vault.js +40 -0
  455. package/dist/repertoire/tools-voice.js +145 -0
  456. package/dist/repertoire/tools.js +494 -148
  457. package/dist/repertoire/travel-api-client.js +360 -0
  458. package/dist/repertoire/unraid-client.js +155 -0
  459. package/dist/repertoire/unraid-restart.js +339 -0
  460. package/dist/repertoire/user-profile.js +131 -0
  461. package/dist/repertoire/vault-setup.js +246 -0
  462. package/dist/repertoire/vault-unlock.js +628 -0
  463. package/dist/rsvp/aisleplanner-client.js +354 -0
  464. package/dist/rsvp/cli.js +926 -0
  465. package/dist/rsvp/config.js +327 -0
  466. package/dist/rsvp/cutover.js +433 -0
  467. package/dist/rsvp/diagnostics.js +232 -0
  468. package/dist/rsvp/diff-renderer.js +176 -0
  469. package/dist/rsvp/habit-policy.js +110 -0
  470. package/dist/rsvp/habit-stage.js +123 -0
  471. package/dist/rsvp/incident-bundle.js +97 -0
  472. package/dist/rsvp/migration.js +204 -0
  473. package/dist/rsvp/native-habit-runner.js +630 -0
  474. package/dist/rsvp/outbound-state.js +628 -0
  475. package/dist/rsvp/query.js +118 -0
  476. package/dist/rsvp/replay.js +233 -0
  477. package/dist/rsvp/snapshot.js +232 -0
  478. package/dist/rsvp/spend-ledger.js +175 -0
  479. package/dist/scripts/claude-code-hook.js +41 -0
  480. package/dist/scripts/claude-code-stop-hook.js +47 -0
  481. package/dist/senses/a2a-entry.js +115 -0
  482. package/dist/senses/acp-server.js +386 -0
  483. package/dist/senses/attention-queue.js +186 -0
  484. package/dist/senses/await-turn-message.js +58 -0
  485. package/dist/senses/bluebubbles/active-turns.js +216 -0
  486. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  487. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  488. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  489. package/dist/senses/bluebubbles/context-packet.js +207 -0
  490. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  491. package/dist/senses/bluebubbles/entry.js +90 -0
  492. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  493. package/dist/senses/bluebubbles/index.js +3841 -0
  494. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  495. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  496. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  497. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  498. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  499. package/dist/senses/bluebubbles/processed-log.js +133 -0
  500. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  501. package/dist/senses/bluebubbles/replay.js +284 -0
  502. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  503. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  504. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  505. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  506. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  507. package/dist/senses/cli/bracketed-paste.js +82 -0
  508. package/dist/senses/cli/image-paste.js +287 -0
  509. package/dist/senses/cli/image-ref-navigation.js +75 -0
  510. package/dist/senses/cli/ink-app.js +156 -0
  511. package/dist/senses/cli/inline-diff.js +64 -0
  512. package/dist/senses/cli/input-keys.js +174 -0
  513. package/dist/senses/cli/kill-ring.js +86 -0
  514. package/dist/senses/cli/message-list.js +51 -0
  515. package/dist/senses/cli/ouro-tui.js +607 -0
  516. package/dist/senses/cli/spinner-imperative.js +135 -0
  517. package/dist/senses/cli/spinner.js +101 -0
  518. package/dist/senses/cli/status-line.js +60 -0
  519. package/dist/senses/cli/streaming-markdown.js +526 -0
  520. package/dist/senses/cli/tool-display.js +85 -0
  521. package/dist/senses/cli/tool-render.js +85 -0
  522. package/dist/senses/cli/tui-store.js +241 -0
  523. package/dist/senses/cli/virtual-list.js +35 -0
  524. package/dist/senses/cli-entry.js +60 -8
  525. package/dist/senses/cli.js +604 -320
  526. package/dist/senses/commands.js +66 -3
  527. package/dist/senses/context-packet-ledger.js +371 -0
  528. package/dist/senses/context-packets.js +154 -0
  529. package/dist/senses/habit-lifecycle-guard.js +24 -0
  530. package/dist/senses/habit-turn-message.js +160 -0
  531. package/dist/senses/ingress-evidence.js +2 -0
  532. package/dist/senses/mail-entry.js +66 -0
  533. package/dist/senses/mail.js +524 -0
  534. package/dist/senses/pipeline.js +1115 -204
  535. package/dist/senses/private-runtime-worker.js +859 -0
  536. package/dist/senses/private-runtime.js +1517 -0
  537. package/dist/senses/proactive-content-guard.js +51 -0
  538. package/dist/senses/root-host-approval-port.js +345 -0
  539. package/dist/senses/root-host-approval-runtime.js +393 -0
  540. package/dist/senses/sanctuary-authority-resident.js +102 -0
  541. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  542. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  543. package/dist/senses/sanctuary-grounding.js +118 -0
  544. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  545. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  546. package/dist/senses/sanctuary-health-runner.js +100 -0
  547. package/dist/senses/sanctuary-health.js +408 -0
  548. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  549. package/dist/senses/sanctuary-interactive-control.js +410 -0
  550. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  551. package/dist/senses/sanctuary-media-optimization.js +514 -0
  552. package/dist/senses/sanctuary-runtime.js +340 -0
  553. package/dist/senses/sanctuary-sab.js +85 -0
  554. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  555. package/dist/senses/shared-turn.js +772 -0
  556. package/dist/senses/surface-tool.js +109 -0
  557. package/dist/senses/teams-entry.js +60 -8
  558. package/dist/senses/teams.js +519 -218
  559. package/dist/senses/telegram-admission.js +718 -0
  560. package/dist/senses/telegram-approval-runtime.js +793 -0
  561. package/dist/senses/telegram-attachments.js +186 -0
  562. package/dist/senses/telegram-audit-ledger.js +220 -0
  563. package/dist/senses/telegram-authority-transport.js +231 -0
  564. package/dist/senses/telegram-client.js +1749 -0
  565. package/dist/senses/telegram-effect-adapter.js +896 -0
  566. package/dist/senses/telegram-entry.js +83 -0
  567. package/dist/senses/telegram.js +2324 -0
  568. package/dist/senses/trust-gate.js +104 -9
  569. package/dist/senses/voice/audio-playback.js +237 -0
  570. package/dist/senses/voice/audio-routing.js +119 -0
  571. package/dist/senses/voice/elevenlabs.js +202 -0
  572. package/dist/senses/voice/floor-control.js +431 -0
  573. package/dist/senses/voice/floor-controller.js +115 -0
  574. package/dist/senses/voice/golden-path.js +116 -0
  575. package/dist/senses/voice/index.js +29 -0
  576. package/dist/senses/voice/meeting.js +113 -0
  577. package/dist/senses/voice/outbound.js +190 -0
  578. package/dist/senses/voice/phone.js +33 -0
  579. package/dist/senses/voice/playback.js +139 -0
  580. package/dist/senses/voice/realtime-eval.js +496 -0
  581. package/dist/senses/voice/realtime-trace.js +531 -0
  582. package/dist/senses/voice/transcript.js +70 -0
  583. package/dist/senses/voice/turn.js +191 -0
  584. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  585. package/dist/senses/voice/twilio-phone.js +5031 -0
  586. package/dist/senses/voice/types.js +2 -0
  587. package/dist/senses/voice/whisper.js +161 -0
  588. package/dist/senses/voice-entry.js +81 -0
  589. package/dist/senses/voice-realtime-eval-command.js +99 -0
  590. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  591. package/dist/senses/voice-twilio-entry.js +87 -0
  592. package/dist/trips/core.js +138 -0
  593. package/dist/trips/store.js +265 -0
  594. package/dist/util/frontmatter.js +69 -0
  595. package/npm-shrinkwrap.json +8138 -0
  596. package/package.json +72 -13
  597. package/skills/agent-commerce.md +113 -0
  598. package/skills/browser-navigation.md +117 -0
  599. package/skills/commerce-setup-guide.md +116 -0
  600. package/skills/commerce-setup.md +84 -0
  601. package/skills/configure-dev-tools.md +99 -0
  602. package/skills/travel-planning.md +138 -0
  603. package/dist/heart/daemon/auth-flow.js +0 -430
  604. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  605. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  606. package/dist/heart/daemon/update-hooks.js +0 -138
  607. package/dist/heart/obligations.js +0 -191
  608. package/dist/heart/safe-workspace.js +0 -228
  609. package/dist/heart/session-recall.js +0 -116
  610. package/dist/mind/friends/channel.js +0 -84
  611. package/dist/mind/friends/group-context.js +0 -144
  612. package/dist/mind/friends/resolver.js +0 -84
  613. package/dist/mind/friends/store-file.js +0 -190
  614. package/dist/mind/friends/store.js +0 -4
  615. package/dist/mind/friends/tokens.js +0 -26
  616. package/dist/mind/friends/trust-explanation.js +0 -74
  617. package/dist/mind/friends/types.js +0 -29
  618. package/dist/repertoire/tasks/board.js +0 -134
  619. package/dist/repertoire/tasks/index.js +0 -224
  620. package/dist/repertoire/tasks/lifecycle.js +0 -80
  621. package/dist/repertoire/tasks/middleware.js +0 -65
  622. package/dist/repertoire/tasks/parser.js +0 -173
  623. package/dist/repertoire/tasks/scanner.js +0 -132
  624. package/dist/repertoire/tasks/transitions.js +0 -144
  625. package/dist/senses/bluebubbles-entry.js +0 -13
  626. package/dist/senses/bluebubbles.js +0 -1181
  627. package/dist/senses/debug-activity.js +0 -154
  628. package/dist/senses/inner-dialog-worker.js +0 -90
  629. package/dist/senses/inner-dialog.js +0 -525
  630. package/subagents/README.md +0 -7
  631. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  632. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  633. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  634. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  635. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  636. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  637. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  638. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  639. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  640. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  641. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  642. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  643. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  644. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  645. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  646. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  647. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stringifyBlueBubblesHealthError = stringifyBlueBubblesHealthError;
4
+ exports.redactBlueBubblesHealthDetailForNerves = redactBlueBubblesHealthDetailForNerves;
5
+ exports.formatBlueBubblesHealthcheckFailure = formatBlueBubblesHealthcheckFailure;
6
+ exports.probeBlueBubblesHealth = probeBlueBubblesHealth;
7
+ const runtime_1 = require("../../nerves/runtime");
8
+ const error_classification_1 = require("../providers/error-classification");
9
+ function buildBlueBubblesApiUrl(baseUrl, endpoint, password) {
10
+ const root = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
11
+ const url = new URL(endpoint.replace(/^\//, ""), root);
12
+ url.searchParams.set("password", password);
13
+ return url.toString();
14
+ }
15
+ function stringifyBlueBubblesHealthError(error) {
16
+ if (error instanceof Error) {
17
+ const message = error.message.trim();
18
+ if (message)
19
+ return message;
20
+ return error.name || "unknown";
21
+ }
22
+ const value = String(error).trim();
23
+ return value || "unknown";
24
+ }
25
+ function redactBlueBubblesHealthDetailForNerves(detail) {
26
+ return detail
27
+ .replace(/\bbluebubbles\.password\b/gi, "bluebubbles credential")
28
+ .replace(/\bpassword\b/gi, "credential");
29
+ }
30
+ function blueBubblesHealthStatus(error) {
31
+ return error instanceof Error && typeof error.status === "number"
32
+ ? error.status
33
+ : null;
34
+ }
35
+ function blueBubblesHealthClassification(error) {
36
+ return error instanceof Error ? (0, error_classification_1.classifyHttpError)(error) : "unknown";
37
+ }
38
+ function formatBlueBubblesHealthcheckFailure(serverUrlInput, error) {
39
+ const serverUrl = serverUrlInput.trim() || "configured BlueBubbles server";
40
+ const rawReason = stringifyBlueBubblesHealthError(error);
41
+ const status = blueBubblesHealthStatus(error);
42
+ if (!(error instanceof Error)) {
43
+ return `BlueBubbles health check failed at ${serverUrl}. Check \`bluebubbles.serverUrl\`, confirm the BlueBubbles app/API is running, and inspect daemon logs. Raw error: ${rawReason}`;
44
+ }
45
+ switch (blueBubblesHealthClassification(error)) {
46
+ case "network-error":
47
+ return `Cannot reach BlueBubbles at ${serverUrl}. Check \`bluebubbles.serverUrl\`, confirm the BlueBubbles app/API is running, and verify this machine can reach it. Raw error: ${rawReason}`;
48
+ case "auth-failure":
49
+ return `BlueBubbles auth failed at ${serverUrl} (HTTP ${status}). Check this machine's BlueBubbles attachment with \`ouro connect bluebubbles --agent <agent>\` and confirm the server accepts the password. Raw error: ${rawReason}`;
50
+ case "server-error":
51
+ return `BlueBubbles upstream returned HTTP ${status} at ${serverUrl}. Check the BlueBubbles app/server logs and confirm the upstream API is healthy. Raw error: ${rawReason}`;
52
+ default:
53
+ return `BlueBubbles health check failed at ${serverUrl}${status === null ? "" : ` (HTTP ${status})`}. Check \`bluebubbles.serverUrl\`, the BlueBubbles server configuration, and daemon logs. Raw error: ${rawReason}`;
54
+ }
55
+ }
56
+ async function probeBlueBubblesHealth(input) {
57
+ try {
58
+ const url = buildBlueBubblesApiUrl(input.serverUrl, "/api/v1/message/count", input.password);
59
+ const response = await input.fetchImpl(url, {
60
+ method: "GET",
61
+ signal: AbortSignal.timeout(input.requestTimeoutMs),
62
+ });
63
+ if (!response.ok) {
64
+ const errorText = await response.text().catch(() => "");
65
+ const error = new Error(errorText || "unknown");
66
+ error.status = response.status;
67
+ throw error;
68
+ }
69
+ (0, runtime_1.emitNervesEvent)({
70
+ component: "daemon",
71
+ event: "daemon.bluebubbles_health_probe_checked",
72
+ message: "checked bluebubbles upstream health",
73
+ meta: {
74
+ serverUrl: input.serverUrl,
75
+ ok: true,
76
+ status: response.status,
77
+ },
78
+ });
79
+ return {
80
+ ok: true,
81
+ detail: "upstream reachable",
82
+ reason: null,
83
+ status: response.status,
84
+ classification: null,
85
+ };
86
+ }
87
+ catch (error) {
88
+ const detail = formatBlueBubblesHealthcheckFailure(input.serverUrl, error);
89
+ const reason = stringifyBlueBubblesHealthError(error);
90
+ const status = blueBubblesHealthStatus(error);
91
+ const classification = blueBubblesHealthClassification(error);
92
+ (0, runtime_1.emitNervesEvent)({
93
+ level: "warn",
94
+ component: "daemon",
95
+ event: "daemon.bluebubbles_health_probe_checked",
96
+ message: "checked bluebubbles upstream health",
97
+ meta: {
98
+ serverUrl: input.serverUrl,
99
+ ok: false,
100
+ status,
101
+ reason,
102
+ classification,
103
+ detail: redactBlueBubblesHealthDetailForNerves(detail),
104
+ },
105
+ });
106
+ return {
107
+ ok: false,
108
+ detail,
109
+ reason,
110
+ status,
111
+ classification,
112
+ };
113
+ }
114
+ }
115
+ /* v8 ignore start -- module load observability event */
116
+ (0, runtime_1.emitNervesEvent)({
117
+ component: "daemon",
118
+ event: "daemon.bluebubbles_health_diagnostics_loaded",
119
+ message: "bluebubbles health diagnostics loaded",
120
+ meta: {},
121
+ });
122
+ /* v8 ignore stop */
@@ -0,0 +1,433 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BLUEBUBBLES_HOST_RECEIPTS_DIRECTORY = exports.BLUEBUBBLES_HOST_REQUESTS_DIRECTORY = exports.BLUEBUBBLES_HOST_SHARED_HELPER = exports.BLUEBUBBLES_HOST_SHARED_ROOT = exports.BLUEBUBBLES_HOST_FRESHNESS_MS = exports.BLUEBUBBLES_HOST_HELPER_VERSION = exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION = void 0;
37
+ exports.installBlueBubblesHostSharedHelper = installBlueBubblesHostSharedHelper;
38
+ exports.blueBubblesHostAttemptPath = blueBubblesHostAttemptPath;
39
+ exports.requestCrossUserBlueBubblesHostAction = requestCrossUserBlueBubblesHostAction;
40
+ exports.validateBlueBubblesHostHelperRequest = validateBlueBubblesHostHelperRequest;
41
+ exports.publishBlueBubblesHostReceipt = publishBlueBubblesHostReceipt;
42
+ exports.collectCrossUserBlueBubblesHostAction = collectCrossUserBlueBubblesHostAction;
43
+ const crypto_1 = require("crypto");
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const runtime_1 = require("../../nerves/runtime");
47
+ const bluebubbles_host_1 = require("./bluebubbles-host");
48
+ exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION = 1;
49
+ exports.BLUEBUBBLES_HOST_HELPER_VERSION = 1;
50
+ exports.BLUEBUBBLES_HOST_FRESHNESS_MS = 300_000;
51
+ exports.BLUEBUBBLES_HOST_SHARED_ROOT = "/Users/Shared/Ouro";
52
+ exports.BLUEBUBBLES_HOST_SHARED_HELPER = `${exports.BLUEBUBBLES_HOST_SHARED_ROOT}/bluebubbles-host`;
53
+ exports.BLUEBUBBLES_HOST_REQUESTS_DIRECTORY = `${exports.BLUEBUBBLES_HOST_SHARED_ROOT}/bluebubbles-host-requests`;
54
+ exports.BLUEBUBBLES_HOST_RECEIPTS_DIRECTORY = `${exports.BLUEBUBBLES_HOST_SHARED_ROOT}/bluebubbles-host-receipts`;
55
+ function protocolDeps(overrides = {}) {
56
+ return {
57
+ now: Date.now,
58
+ randomBytes: crypto_1.randomBytes,
59
+ currentUid: () => process.getuid?.() ?? 0,
60
+ expectedHelperBytes: () => fs.readFileSync(path.resolve(__dirname, "../../../assets/bluebubbles-host")),
61
+ existsSync: fs.existsSync,
62
+ readFileSync: fs.readFileSync,
63
+ mkdirSync: fs.mkdirSync,
64
+ chmodSync: fs.chmodSync,
65
+ writeFileSync: fs.writeFileSync,
66
+ linkSync: fs.linkSync,
67
+ unlinkSync: fs.unlinkSync,
68
+ renameSync: fs.renameSync,
69
+ lstatSync: fs.lstatSync,
70
+ ...overrides,
71
+ };
72
+ }
73
+ function sharedPaths(sharedRoot) {
74
+ return {
75
+ helper: path.join(sharedRoot, "bluebubbles-host"),
76
+ requests: path.join(sharedRoot, "bluebubbles-host-requests"),
77
+ receipts: path.join(sharedRoot, "bluebubbles-host-receipts"),
78
+ };
79
+ }
80
+ function fileMode(deps, filePath) {
81
+ return deps.existsSync(filePath) ? deps.lstatSync(filePath).mode & 0o7777 : null;
82
+ }
83
+ function validateManagedPath(deps, filePath, label, kind, expectedUid) {
84
+ const stat = deps.lstatSync(filePath);
85
+ if (stat.isSymbolicLink?.())
86
+ throw new Error(`${label} must not be a symbolic link`);
87
+ if (kind === "directory" && stat.isDirectory?.() !== true)
88
+ throw new Error(`${label} must be a directory`);
89
+ if (kind === "file" && stat.isFile?.() !== true)
90
+ throw new Error(`${label} must be a regular file`);
91
+ if (stat.uid !== expectedUid)
92
+ throw new Error(`${label} must be owned by uid ${expectedUid}`);
93
+ }
94
+ function ensureDirectory(deps, directoryPath, mode, label, expectedUid) {
95
+ const priorMode = fileMode(deps, directoryPath);
96
+ if (priorMode !== null)
97
+ validateManagedPath(deps, directoryPath, label, "directory", expectedUid);
98
+ if (priorMode === null)
99
+ deps.mkdirSync(directoryPath, { recursive: true, mode });
100
+ validateManagedPath(deps, directoryPath, label, "directory", expectedUid);
101
+ deps.chmodSync(directoryPath, mode);
102
+ return priorMode !== mode;
103
+ }
104
+ function writeAtomicReplacement(deps, filePath, content, mode) {
105
+ const temporaryPath = `${filePath}.${process.pid}.tmp`;
106
+ try {
107
+ deps.writeFileSync(temporaryPath, content, { mode, flag: "wx" });
108
+ deps.chmodSync(temporaryPath, mode);
109
+ deps.renameSync(temporaryPath, filePath);
110
+ deps.chmodSync(filePath, mode);
111
+ }
112
+ catch (error) {
113
+ if (deps.existsSync(temporaryPath))
114
+ deps.unlinkSync(temporaryPath);
115
+ throw error;
116
+ }
117
+ }
118
+ function isAlreadyExists(error) {
119
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
120
+ }
121
+ function publishNoClobberJson(deps, filePath, value, mode, token, label) {
122
+ const temporaryPath = `${filePath}.${token}.tmp`;
123
+ try {
124
+ deps.writeFileSync(temporaryPath, `${JSON.stringify(value, null, 2)}\n`, {
125
+ encoding: "utf8",
126
+ mode,
127
+ flag: "wx",
128
+ });
129
+ deps.chmodSync(temporaryPath, mode);
130
+ deps.linkSync(temporaryPath, filePath);
131
+ deps.chmodSync(filePath, mode);
132
+ }
133
+ catch (error) {
134
+ if (isAlreadyExists(error))
135
+ throw new Error(`${label} already exists`);
136
+ throw error;
137
+ }
138
+ finally {
139
+ if (deps.existsSync(temporaryPath))
140
+ deps.unlinkSync(temporaryPath);
141
+ }
142
+ }
143
+ function readJson(deps, filePath, label) {
144
+ try {
145
+ return JSON.parse(deps.readFileSync(filePath).toString("utf8"));
146
+ }
147
+ catch (error) {
148
+ const detail = error instanceof Error ? error.message : String(error);
149
+ throw new Error(`${label} is invalid: ${detail}`);
150
+ }
151
+ }
152
+ function parseTime(value, label) {
153
+ const parsed = Date.parse(value);
154
+ if (!Number.isFinite(parsed))
155
+ throw new Error(`${label} is invalid`);
156
+ return parsed;
157
+ }
158
+ function validateUsername(username) {
159
+ if (!/^[A-Za-z_][A-Za-z0-9._-]*$/.test(username)) {
160
+ throw new Error("invalid BlueBubbles host username");
161
+ }
162
+ }
163
+ function validateUid(uid) {
164
+ if (!Number.isInteger(uid) || uid < 500)
165
+ throw new Error("BlueBubbles host uid must be at least 500");
166
+ }
167
+ function validateAction(action) {
168
+ if (!["install", "status", "repair", "remove"].includes(action)) {
169
+ throw new Error("unsupported host action");
170
+ }
171
+ }
172
+ function validateRequestShape(request) {
173
+ if (request.schemaVersion !== exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION) {
174
+ throw new Error("unsupported request schema");
175
+ }
176
+ if (request.helperVersion !== exports.BLUEBUBBLES_HOST_HELPER_VERSION) {
177
+ throw new Error("unsupported helper version");
178
+ }
179
+ validateUsername(request.username);
180
+ validateUid(request.uid);
181
+ validateAction(request.action);
182
+ if (!/^[0-9a-f]{64}$/.test(request.nonce))
183
+ throw new Error("invalid request nonce");
184
+ if (request.requestId !== `${request.uid}-${request.nonce}`)
185
+ throw new Error("request id does not match uid and nonce");
186
+ const requestedAtMs = parseTime(request.requestedAt, "request timestamp");
187
+ const expiresAtMs = parseTime(request.expiresAt, "request expiry");
188
+ if (expiresAtMs - requestedAtMs > exports.BLUEBUBBLES_HOST_FRESHNESS_MS) {
189
+ throw new Error("request freshness window exceeds 300000 ms");
190
+ }
191
+ return { requestedAtMs, expiresAtMs };
192
+ }
193
+ function installBlueBubblesHostSharedHelper(input, overrides = {}) {
194
+ const deps = protocolDeps(overrides);
195
+ const root = input.sharedRoot ?? exports.BLUEBUBBLES_HOST_SHARED_ROOT;
196
+ const paths = sharedPaths(root);
197
+ const asset = deps.readFileSync(input.assetPath);
198
+ const expectedUid = deps.currentUid();
199
+ let changed = false;
200
+ changed = ensureDirectory(deps, root, 0o755, "shared root", expectedUid) || changed;
201
+ changed = ensureDirectory(deps, paths.requests, 0o755, "shared request directory", expectedUid) || changed;
202
+ changed = ensureDirectory(deps, paths.receipts, 0o1777, "shared receipt directory", expectedUid) || changed;
203
+ if (deps.existsSync(paths.helper))
204
+ validateManagedPath(deps, paths.helper, "shared helper", "file", expectedUid);
205
+ const helperCurrent = deps.existsSync(paths.helper) && deps.readFileSync(paths.helper).equals(asset);
206
+ const helperModeCurrent = fileMode(deps, paths.helper) === 0o755;
207
+ if (!helperCurrent) {
208
+ writeAtomicReplacement(deps, paths.helper, asset, 0o755);
209
+ changed = true;
210
+ }
211
+ else {
212
+ deps.chmodSync(paths.helper, 0o755);
213
+ changed = !helperModeCurrent || changed;
214
+ }
215
+ validateManagedPath(deps, paths.helper, "shared helper", "file", expectedUid);
216
+ (0, runtime_1.emitNervesEvent)({
217
+ component: "daemon",
218
+ event: "daemon.bluebubbles_host_helper_installed",
219
+ message: "installed shared BlueBubbles host helper state",
220
+ meta: { changed, helperPath: paths.helper },
221
+ });
222
+ return { changed, helperPath: paths.helper };
223
+ }
224
+ function blueBubblesHostAttemptPath(originHomeDir, requestId) {
225
+ return path.join(originHomeDir, ".ouro-cli", "bluebubbles-host", "attempts", `${requestId}.json`);
226
+ }
227
+ function requestCrossUserBlueBubblesHostAction(input, overrides = {}) {
228
+ const deps = protocolDeps(overrides);
229
+ validateUsername(input.username);
230
+ validateUid(input.uid);
231
+ validateAction(input.action);
232
+ if (!path.isAbsolute(input.targetHomeDir))
233
+ throw new Error("target home must be absolute");
234
+ if (!deps.existsSync(input.targetHomeDir))
235
+ throw new Error(`target home does not exist: ${input.targetHomeDir}`);
236
+ validateManagedPath(deps, input.targetHomeDir, "target home", "directory", input.uid);
237
+ const nonceBytes = deps.randomBytes(32);
238
+ if (nonceBytes.length !== 32)
239
+ throw new Error("BlueBubbles host nonce source must return 32 bytes");
240
+ const nonce = nonceBytes.toString("hex");
241
+ const requestId = `${input.uid}-${nonce}`;
242
+ const requestedAtMs = deps.now();
243
+ const request = {
244
+ schemaVersion: exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION,
245
+ helperVersion: exports.BLUEBUBBLES_HOST_HELPER_VERSION,
246
+ requestId,
247
+ nonce,
248
+ action: input.action,
249
+ username: input.username,
250
+ uid: input.uid,
251
+ requestedAt: new Date(requestedAtMs).toISOString(),
252
+ expiresAt: new Date(requestedAtMs + exports.BLUEBUBBLES_HOST_FRESHNESS_MS).toISOString(),
253
+ };
254
+ const root = input.sharedRoot ?? exports.BLUEBUBBLES_HOST_SHARED_ROOT;
255
+ const paths = sharedPaths(root);
256
+ const expectedUid = deps.currentUid();
257
+ validateManagedPath(deps, root, "shared root", "directory", expectedUid);
258
+ validateManagedPath(deps, paths.requests, "shared request directory", "directory", expectedUid);
259
+ validateManagedPath(deps, paths.helper, "shared helper", "file", expectedUid);
260
+ if (fileMode(deps, root) !== 0o755)
261
+ throw new Error("shared root mode must be 0755");
262
+ if (fileMode(deps, paths.requests) !== 0o755)
263
+ throw new Error("shared request directory mode must be 0755");
264
+ if (fileMode(deps, paths.helper) !== 0o755)
265
+ throw new Error("shared helper mode must be 0755");
266
+ if (!deps.readFileSync(paths.helper).equals(deps.expectedHelperBytes())) {
267
+ throw new Error("shared helper bytes do not match the packaged helper");
268
+ }
269
+ const requestPath = path.join(paths.requests, `${requestId}.json`);
270
+ const attemptPath = blueBubblesHostAttemptPath(input.originHomeDir, requestId);
271
+ const attempt = {
272
+ schemaVersion: exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION,
273
+ status: "pending",
274
+ request,
275
+ targetHomeDir: input.targetHomeDir,
276
+ };
277
+ deps.mkdirSync(path.dirname(attemptPath), { recursive: true, mode: 0o700 });
278
+ deps.chmodSync(path.dirname(attemptPath), 0o700);
279
+ publishNoClobberJson(deps, attemptPath, attempt, 0o600, nonce, "attempt");
280
+ try {
281
+ publishNoClobberJson(deps, requestPath, request, 0o444, nonce, "request");
282
+ }
283
+ catch (error) {
284
+ deps.unlinkSync(attemptPath);
285
+ throw error;
286
+ }
287
+ const result = {
288
+ classification: "human-required",
289
+ requestId,
290
+ requestPath,
291
+ helperCommand: `${paths.helper} --request ${requestPath}`,
292
+ collectCommand: `ouro bluebubbles host collect --request-id ${requestId}`,
293
+ };
294
+ (0, runtime_1.emitNervesEvent)({
295
+ component: "daemon",
296
+ event: "daemon.bluebubbles_host_handoff_created",
297
+ message: "created nonce-bound cross-user BlueBubbles host handoff",
298
+ meta: { requestId, uid: input.uid, action: input.action },
299
+ });
300
+ return result;
301
+ }
302
+ function validateBlueBubblesHostHelperRequest(input) {
303
+ const { requestedAtMs, expiresAtMs } = validateRequestShape(input.request);
304
+ if (input.currentUsername !== input.request.username)
305
+ throw new Error("target username mismatch");
306
+ if (input.currentUid !== input.request.uid)
307
+ throw new Error("target uid mismatch");
308
+ if (!input.launchdDomainAvailable) {
309
+ throw new Error(`logged-in gui/${input.request.uid} session is unavailable`);
310
+ }
311
+ if (requestedAtMs > input.nowMs)
312
+ throw new Error("request timestamp is in the future");
313
+ if (input.nowMs > expiresAtMs)
314
+ throw new Error("request expired");
315
+ return { request: input.request, launchdDomain: `gui/${input.request.uid}` };
316
+ }
317
+ function publishBlueBubblesHostReceipt(receipt, input = {}, overrides = {}) {
318
+ const deps = protocolDeps(overrides);
319
+ if (!/^\d+-[0-9a-f]{64}$/.test(receipt.requestId))
320
+ throw new Error("invalid BlueBubbles host receipt request id");
321
+ const root = input.sharedRoot ?? exports.BLUEBUBBLES_HOST_SHARED_ROOT;
322
+ const receiptPath = path.join(sharedPaths(root).receipts, `${receipt.requestId}.json`);
323
+ publishNoClobberJson(deps, receiptPath, receipt, 0o444, receipt.nonce, "receipt");
324
+ return receiptPath;
325
+ }
326
+ function expectedPlistPath(targetHomeDir) {
327
+ return path.join(targetHomeDir, "Library", "LaunchAgents", `${bluebubbles_host_1.BLUEBUBBLES_LAUNCH_AGENT_LABEL}.plist`);
328
+ }
329
+ function requireReceiptMatch(request, targetHomeDir, receipt) {
330
+ const exactFields = [
331
+ "schemaVersion",
332
+ "helperVersion",
333
+ "requestId",
334
+ "nonce",
335
+ "action",
336
+ "username",
337
+ "uid",
338
+ "requestedAt",
339
+ "expiresAt",
340
+ ];
341
+ for (const field of exactFields) {
342
+ if (receipt[field] !== request[field])
343
+ throw new Error(`receipt ${field} does not match request`);
344
+ }
345
+ if (receipt.appPath !== bluebubbles_host_1.BLUEBUBBLES_APP_PATH)
346
+ throw new Error("receipt app path does not match");
347
+ if (receipt.plistPath !== expectedPlistPath(targetHomeDir))
348
+ throw new Error("receipt plist path does not match");
349
+ if (receipt.launchAgentLabel !== bluebubbles_host_1.BLUEBUBBLES_LAUNCH_AGENT_LABEL) {
350
+ throw new Error("receipt launch agent label does not match");
351
+ }
352
+ if (receipt.launchdDomain !== `gui/${request.uid}`)
353
+ throw new Error("receipt launchd domain does not match");
354
+ if (receipt.result !== "verified" && receipt.result !== "failed")
355
+ throw new Error("receipt result is invalid");
356
+ if (typeof receipt.detail !== "string" || receipt.detail.length === 0)
357
+ throw new Error("receipt detail is invalid");
358
+ const verifiedAtMs = parseTime(receipt.verifiedAt, "receipt verification timestamp");
359
+ const requestedAtMs = parseTime(request.requestedAt, "request timestamp");
360
+ const expiresAtMs = parseTime(request.expiresAt, "request expiry");
361
+ if (verifiedAtMs < requestedAtMs || verifiedAtMs > expiresAtMs) {
362
+ throw new Error("receipt verification is outside request freshness");
363
+ }
364
+ }
365
+ function collectCrossUserBlueBubblesHostAction(input, overrides = {}) {
366
+ const deps = protocolDeps(overrides);
367
+ if (!/^\d+-[0-9a-f]{64}$/.test(input.requestId))
368
+ throw new Error("invalid BlueBubbles host request id");
369
+ const attemptPath = blueBubblesHostAttemptPath(input.originHomeDir, input.requestId);
370
+ if (!deps.existsSync(attemptPath))
371
+ throw new Error("BlueBubbles host attempt is missing");
372
+ const attempt = readJson(deps, attemptPath, "BlueBubbles host attempt");
373
+ if (attempt.schemaVersion !== exports.BLUEBUBBLES_HOST_PROTOCOL_SCHEMA_VERSION) {
374
+ throw new Error("BlueBubbles host attempt state is invalid");
375
+ }
376
+ const request = attempt.request;
377
+ validateRequestShape(request);
378
+ if (request.requestId !== input.requestId)
379
+ throw new Error("attempt request id does not match collection request");
380
+ if (typeof attempt.targetHomeDir !== "string" || !path.isAbsolute(attempt.targetHomeDir)) {
381
+ throw new Error("BlueBubbles host attempt target home is invalid");
382
+ }
383
+ if (attempt.status === "collected" && attempt.collection) {
384
+ if (attempt.collection.requestId !== request.requestId || attempt.collection.status !== "collected") {
385
+ throw new Error("stored collection request id does not match");
386
+ }
387
+ requireReceiptMatch(request, attempt.targetHomeDir, attempt.collection.receipt);
388
+ const expectedDetail = attempt.collection.receipt.result === "verified"
389
+ ? `launchd verified at ${attempt.collection.receipt.verifiedAt}; current service state requires a fresh helper run`
390
+ : `launchd helper reported failure at ${attempt.collection.receipt.verifiedAt}; current service state requires a fresh helper run`;
391
+ if (attempt.collection.detail !== expectedDetail)
392
+ throw new Error("stored collection detail does not match receipt");
393
+ return attempt.collection;
394
+ }
395
+ if (attempt.status !== "pending")
396
+ throw new Error("BlueBubbles host attempt state is invalid");
397
+ const root = input.sharedRoot ?? exports.BLUEBUBBLES_HOST_SHARED_ROOT;
398
+ const paths = sharedPaths(root);
399
+ const expectedUid = deps.currentUid();
400
+ validateManagedPath(deps, root, "shared root", "directory", expectedUid);
401
+ validateManagedPath(deps, paths.receipts, "shared receipt directory", "directory", expectedUid);
402
+ const receiptPath = path.join(paths.receipts, `${input.requestId}.json`);
403
+ if (!deps.existsSync(receiptPath))
404
+ throw new Error("BlueBubbles host receipt is missing");
405
+ const receiptStat = deps.lstatSync(receiptPath);
406
+ if (receiptStat.isSymbolicLink?.())
407
+ throw new Error("BlueBubbles host receipt must not be a symbolic link");
408
+ if (receiptStat.isFile?.() !== true)
409
+ throw new Error("BlueBubbles host receipt must be a regular file");
410
+ if (receiptStat.uid !== request.uid)
411
+ throw new Error(`receipt owner uid ${receiptStat.uid} does not match target uid ${request.uid}`);
412
+ if ((receiptStat.mode & 0o7777) !== 0o444)
413
+ throw new Error("BlueBubbles host receipt mode must be 0444");
414
+ const receipt = readJson(deps, receiptPath, "BlueBubbles host receipt");
415
+ requireReceiptMatch(request, attempt.targetHomeDir, receipt);
416
+ const detail = receipt.result === "verified"
417
+ ? `launchd verified at ${receipt.verifiedAt}; current service state requires a fresh helper run`
418
+ : `launchd helper reported failure at ${receipt.verifiedAt}; current service state requires a fresh helper run`;
419
+ const collection = {
420
+ requestId: request.requestId,
421
+ status: "collected",
422
+ detail,
423
+ receipt,
424
+ };
425
+ writeAtomicReplacement(deps, attemptPath, `${JSON.stringify({ ...attempt, status: "collected", collection }, null, 2)}\n`, 0o600);
426
+ (0, runtime_1.emitNervesEvent)({
427
+ component: "daemon",
428
+ event: "daemon.bluebubbles_host_receipt_collected",
429
+ message: "collected ownership-bound BlueBubbles host receipt",
430
+ meta: { requestId: request.requestId, uid: request.uid, result: receipt.result },
431
+ });
432
+ return collection;
433
+ }