@ouro.bot/cli 0.1.0-alpha.48 → 0.1.0-alpha.480

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 (358) hide show
  1. package/README.md +132 -19
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +3061 -0
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +857 -0
  16. package/dist/heart/agent-entry.js +58 -3
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +426 -0
  28. package/dist/heart/background-operations.js +234 -0
  29. package/dist/heart/bridges/manager.js +358 -0
  30. package/dist/heart/bridges/state-machine.js +135 -0
  31. package/dist/heart/bridges/store.js +123 -0
  32. package/dist/heart/bundle-state.js +168 -0
  33. package/dist/heart/commitments.js +111 -0
  34. package/dist/heart/config-registry.js +304 -0
  35. package/dist/heart/config.js +110 -128
  36. package/dist/heart/core.js +745 -227
  37. package/dist/heart/cross-chat-delivery.js +131 -0
  38. package/dist/heart/daemon/agent-config-check.js +490 -0
  39. package/dist/heart/daemon/agent-discovery.js +79 -3
  40. package/dist/heart/daemon/agent-service.js +360 -0
  41. package/dist/heart/daemon/agentic-repair.js +216 -0
  42. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  43. package/dist/heart/daemon/cadence.js +70 -0
  44. package/dist/heart/daemon/cli-defaults.js +640 -0
  45. package/dist/heart/daemon/cli-exec.js +6933 -0
  46. package/dist/heart/daemon/cli-help.js +487 -0
  47. package/dist/heart/daemon/cli-parse.js +1527 -0
  48. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  49. package/dist/heart/daemon/cli-render.js +561 -0
  50. package/dist/heart/daemon/cli-types.js +8 -0
  51. package/dist/heart/daemon/connect-bay.js +323 -0
  52. package/dist/heart/daemon/daemon-cli.js +29 -1616
  53. package/dist/heart/daemon/daemon-entry.js +345 -3
  54. package/dist/heart/daemon/daemon-health.js +141 -0
  55. package/dist/heart/daemon/daemon-runtime-sync.js +190 -12
  56. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  57. package/dist/heart/daemon/daemon.js +677 -58
  58. package/dist/heart/daemon/dns-workflow.js +394 -0
  59. package/dist/heart/daemon/doctor-types.js +8 -0
  60. package/dist/heart/daemon/doctor.js +486 -0
  61. package/dist/heart/daemon/health-monitor.js +92 -1
  62. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  63. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  64. package/dist/heart/daemon/http-health-probe.js +80 -0
  65. package/dist/heart/daemon/human-command-screens.js +234 -0
  66. package/dist/heart/daemon/human-readiness.js +114 -0
  67. package/dist/heart/daemon/inner-status.js +89 -0
  68. package/dist/heart/daemon/interactive-repair.js +394 -0
  69. package/dist/heart/daemon/launchd.js +25 -5
  70. package/dist/heart/daemon/log-tailer.js +82 -12
  71. package/dist/heart/daemon/logs-prune.js +110 -0
  72. package/dist/heart/daemon/message-router.js +2 -2
  73. package/dist/heart/daemon/os-cron-deps.js +134 -0
  74. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  75. package/dist/heart/daemon/ouro-entry.js +3 -1
  76. package/dist/heart/daemon/process-manager.js +214 -0
  77. package/dist/heart/daemon/provider-discovery.js +137 -0
  78. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  79. package/dist/heart/daemon/pulse.js +475 -0
  80. package/dist/heart/daemon/readiness-repair.js +365 -0
  81. package/dist/heart/daemon/run-hooks.js +2 -0
  82. package/dist/heart/daemon/runtime-logging.js +67 -16
  83. package/dist/heart/daemon/runtime-metadata.js +73 -0
  84. package/dist/heart/daemon/runtime-mode.js +67 -0
  85. package/dist/heart/daemon/safe-mode.js +161 -0
  86. package/dist/heart/daemon/sense-manager.js +178 -37
  87. package/dist/heart/daemon/session-id-resolver.js +131 -0
  88. package/dist/heart/daemon/skill-management-installer.js +94 -0
  89. package/dist/heart/daemon/socket-client.js +109 -4
  90. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  91. package/dist/heart/daemon/startup-tui.js +264 -0
  92. package/dist/heart/daemon/task-scheduler.js +3 -25
  93. package/dist/heart/daemon/terminal-ui.js +499 -0
  94. package/dist/heart/daemon/thoughts.js +149 -10
  95. package/dist/heart/daemon/up-progress.js +366 -0
  96. package/dist/heart/daemon/vault-items.js +56 -0
  97. package/dist/heart/delegation.js +62 -0
  98. package/dist/heart/habits/habit-migration.js +189 -0
  99. package/dist/heart/habits/habit-parser.js +140 -0
  100. package/dist/heart/habits/habit-runtime-state.js +100 -0
  101. package/dist/heart/habits/habit-scheduler.js +372 -0
  102. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  103. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  104. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  105. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  106. package/dist/heart/identity.js +201 -66
  107. package/dist/heart/kept-notes.js +357 -0
  108. package/dist/heart/kicks.js +1 -1
  109. package/dist/heart/machine-identity.js +161 -0
  110. package/dist/heart/mcp/mcp-server.js +653 -0
  111. package/dist/heart/migrate-config.js +100 -0
  112. package/dist/heart/model-capabilities.js +59 -0
  113. package/dist/heart/outlook/outlook-http-hooks.js +66 -0
  114. package/dist/heart/outlook/outlook-http-response.js +7 -0
  115. package/dist/heart/outlook/outlook-http-routes.js +244 -0
  116. package/dist/heart/outlook/outlook-http-static.js +99 -0
  117. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  118. package/dist/heart/outlook/outlook-http.js +99 -0
  119. package/dist/heart/outlook/outlook-read.js +31 -0
  120. package/dist/heart/outlook/outlook-types.js +27 -0
  121. package/dist/heart/outlook/outlook-view.js +195 -0
  122. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  123. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  124. package/dist/heart/outlook/readers/mail.js +362 -0
  125. package/dist/heart/outlook/readers/runtime-readers.js +644 -0
  126. package/dist/heart/outlook/readers/sessions.js +232 -0
  127. package/dist/heart/outlook/readers/shared.js +111 -0
  128. package/dist/heart/platform.js +81 -0
  129. package/dist/heart/progress-story.js +42 -0
  130. package/dist/heart/provider-attempt.js +134 -0
  131. package/dist/heart/provider-binding-resolver.js +255 -0
  132. package/dist/heart/provider-credentials.js +424 -0
  133. package/dist/heart/provider-failover.js +266 -0
  134. package/dist/heart/provider-models.js +81 -0
  135. package/dist/heart/provider-ping.js +262 -0
  136. package/dist/heart/provider-state.js +216 -0
  137. package/dist/heart/provider-visibility.js +188 -0
  138. package/dist/heart/providers/anthropic-token.js +131 -0
  139. package/dist/heart/providers/anthropic.js +193 -55
  140. package/dist/heart/providers/azure.js +103 -12
  141. package/dist/heart/providers/error-classification.js +63 -0
  142. package/dist/heart/providers/github-copilot.js +145 -0
  143. package/dist/heart/providers/minimax-vlm.js +189 -0
  144. package/dist/heart/providers/minimax.js +29 -7
  145. package/dist/heart/providers/openai-codex.js +62 -38
  146. package/dist/heart/runtime-capability-check.js +170 -0
  147. package/dist/heart/runtime-credentials.js +260 -0
  148. package/dist/heart/sense-truth.js +11 -4
  149. package/dist/heart/session-activity.js +190 -0
  150. package/dist/heart/session-events.js +855 -0
  151. package/dist/heart/session-transcript.js +167 -0
  152. package/dist/heart/start-of-turn-packet.js +345 -0
  153. package/dist/heart/streaming.js +36 -27
  154. package/dist/heart/sync.js +332 -0
  155. package/dist/heart/target-resolution.js +127 -0
  156. package/dist/heart/tempo.js +93 -0
  157. package/dist/heart/temporal-view.js +41 -0
  158. package/dist/heart/tool-activity-callbacks.js +36 -0
  159. package/dist/heart/tool-description.js +135 -0
  160. package/dist/heart/tool-friction.js +55 -0
  161. package/dist/heart/tool-loop.js +200 -0
  162. package/dist/heart/turn-context.js +361 -0
  163. package/dist/heart/turn-coordinator.js +24 -1
  164. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  165. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  166. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  167. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  168. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  169. package/dist/heart/{daemon → versioning}/update-checker.js +5 -1
  170. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  171. package/dist/mailroom/attention.js +167 -0
  172. package/dist/mailroom/autonomy.js +209 -0
  173. package/dist/mailroom/blob-store.js +558 -0
  174. package/dist/mailroom/core.js +658 -0
  175. package/dist/mailroom/entry.js +160 -0
  176. package/dist/mailroom/file-store.js +400 -0
  177. package/dist/mailroom/mbox-import.js +341 -0
  178. package/dist/mailroom/outbound.js +380 -0
  179. package/dist/mailroom/policy.js +263 -0
  180. package/dist/mailroom/reader.js +197 -0
  181. package/dist/mailroom/smtp-ingress.js +176 -0
  182. package/dist/mailroom/source-state.js +176 -0
  183. package/dist/mailroom/travel-extract.js +89 -0
  184. package/dist/mind/bundle-manifest.js +7 -1
  185. package/dist/mind/context.js +132 -93
  186. package/dist/mind/diary-integrity.js +60 -0
  187. package/dist/mind/{memory.js → diary.js} +74 -93
  188. package/dist/mind/embedding-provider.js +60 -0
  189. package/dist/mind/file-state.js +179 -0
  190. package/dist/mind/friends/channel.js +30 -0
  191. package/dist/mind/friends/group-context.js +144 -0
  192. package/dist/mind/friends/resolver.js +38 -1
  193. package/dist/mind/friends/store-file.js +39 -3
  194. package/dist/mind/friends/trust-explanation.js +74 -0
  195. package/dist/mind/friends/types.js +2 -2
  196. package/dist/mind/journal-index.js +161 -0
  197. package/dist/mind/note-search.js +268 -0
  198. package/dist/mind/obligation-steering.js +221 -0
  199. package/dist/mind/pending.js +66 -7
  200. package/dist/mind/prompt-refresh.js +3 -2
  201. package/dist/mind/prompt.js +978 -169
  202. package/dist/mind/provenance-trust.js +26 -0
  203. package/dist/mind/scrutiny.js +173 -0
  204. package/dist/nerves/cli-logging.js +7 -1
  205. package/dist/nerves/coverage/audit-rules.js +15 -6
  206. package/dist/nerves/coverage/audit.js +28 -2
  207. package/dist/nerves/coverage/cli.js +1 -1
  208. package/dist/nerves/coverage/contract.js +5 -5
  209. package/dist/nerves/coverage/file-completeness.js +84 -5
  210. package/dist/nerves/coverage/run-artifacts.js +1 -1
  211. package/dist/nerves/event-buffer.js +111 -0
  212. package/dist/nerves/index.js +224 -4
  213. package/dist/nerves/observation.js +20 -0
  214. package/dist/nerves/redact.js +79 -0
  215. package/dist/nerves/runtime.js +5 -1
  216. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  217. package/dist/outlook-ui/assets/index-CPfhbn13.js +61 -0
  218. package/dist/outlook-ui/index.html +15 -0
  219. package/dist/repertoire/ado-client.js +15 -56
  220. package/dist/repertoire/ado-semantic.js +11 -10
  221. package/dist/repertoire/api-client.js +97 -0
  222. package/dist/repertoire/bitwarden-store.js +774 -0
  223. package/dist/repertoire/bundle-templates.js +72 -0
  224. package/dist/repertoire/bw-installer.js +180 -0
  225. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  226. package/dist/repertoire/coding/context-pack.js +330 -0
  227. package/dist/repertoire/coding/feedback.js +197 -30
  228. package/dist/repertoire/coding/manager.js +158 -9
  229. package/dist/repertoire/coding/spawner.js +55 -9
  230. package/dist/repertoire/coding/tools.js +170 -7
  231. package/dist/repertoire/commerce-errors.js +109 -0
  232. package/dist/repertoire/commerce-self-test.js +156 -0
  233. package/dist/repertoire/credential-access.js +111 -0
  234. package/dist/repertoire/duffel-client.js +185 -0
  235. package/dist/repertoire/github-client.js +14 -55
  236. package/dist/repertoire/graph-client.js +11 -52
  237. package/dist/repertoire/guardrails.js +396 -0
  238. package/dist/repertoire/mcp-client.js +255 -0
  239. package/dist/repertoire/mcp-manager.js +305 -0
  240. package/dist/repertoire/mcp-tools.js +63 -0
  241. package/dist/repertoire/shell-sessions.js +133 -0
  242. package/dist/repertoire/skills.js +15 -24
  243. package/dist/repertoire/stripe-client.js +131 -0
  244. package/dist/repertoire/tasks/board.js +43 -5
  245. package/dist/repertoire/tasks/fix.js +182 -0
  246. package/dist/repertoire/tasks/index.js +37 -4
  247. package/dist/repertoire/tasks/lifecycle.js +2 -2
  248. package/dist/repertoire/tasks/parser.js +3 -2
  249. package/dist/repertoire/tasks/scanner.js +194 -37
  250. package/dist/repertoire/tasks/transitions.js +16 -78
  251. package/dist/repertoire/tool-results.js +29 -0
  252. package/dist/repertoire/tools-attachments.js +317 -0
  253. package/dist/repertoire/tools-base.js +44 -740
  254. package/dist/repertoire/tools-bluebubbles.js +1 -0
  255. package/dist/repertoire/tools-bridge.js +141 -0
  256. package/dist/repertoire/tools-bundle.js +984 -0
  257. package/dist/repertoire/tools-config.js +185 -0
  258. package/dist/repertoire/tools-continuity.js +248 -0
  259. package/dist/repertoire/tools-credential.js +381 -0
  260. package/dist/repertoire/tools-files.js +342 -0
  261. package/dist/repertoire/tools-flight.js +224 -0
  262. package/dist/repertoire/tools-flow.js +105 -0
  263. package/dist/repertoire/tools-github.js +1 -7
  264. package/dist/repertoire/tools-mail.js +896 -0
  265. package/dist/repertoire/tools-notes.js +376 -0
  266. package/dist/repertoire/tools-session.js +746 -0
  267. package/dist/repertoire/tools-shell.js +120 -0
  268. package/dist/repertoire/tools-stripe.js +180 -0
  269. package/dist/repertoire/tools-surface.js +243 -0
  270. package/dist/repertoire/tools-teams.js +9 -39
  271. package/dist/repertoire/tools-travel.js +125 -0
  272. package/dist/repertoire/tools-user-profile.js +144 -0
  273. package/dist/repertoire/tools-vault.js +40 -0
  274. package/dist/repertoire/tools.js +144 -113
  275. package/dist/repertoire/travel-api-client.js +360 -0
  276. package/dist/repertoire/user-profile.js +131 -0
  277. package/dist/repertoire/vault-setup.js +246 -0
  278. package/dist/repertoire/vault-unlock.js +561 -0
  279. package/dist/scripts/claude-code-hook.js +41 -0
  280. package/dist/scripts/claude-code-stop-hook.js +47 -0
  281. package/dist/senses/attention-queue.js +116 -0
  282. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  283. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  284. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  285. package/dist/senses/bluebubbles/entry.js +73 -0
  286. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +7 -3
  287. package/dist/senses/{bluebubbles.js → bluebubbles/index.js} +705 -116
  288. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  289. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  290. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  291. package/dist/senses/bluebubbles/replay.js +129 -0
  292. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
  293. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  294. package/dist/senses/cli/bracketed-paste.js +82 -0
  295. package/dist/senses/cli/image-paste.js +287 -0
  296. package/dist/senses/cli/image-ref-navigation.js +75 -0
  297. package/dist/senses/cli/ink-app.js +156 -0
  298. package/dist/senses/cli/inline-diff.js +64 -0
  299. package/dist/senses/cli/input-keys.js +174 -0
  300. package/dist/senses/cli/kill-ring.js +86 -0
  301. package/dist/senses/cli/message-list.js +51 -0
  302. package/dist/senses/cli/ouro-tui.js +605 -0
  303. package/dist/senses/cli/spinner-imperative.js +135 -0
  304. package/dist/senses/cli/spinner.js +101 -0
  305. package/dist/senses/cli/status-line.js +60 -0
  306. package/dist/senses/cli/streaming-markdown.js +526 -0
  307. package/dist/senses/cli/tool-display.js +83 -0
  308. package/dist/senses/cli/tool-render.js +85 -0
  309. package/dist/senses/cli/tui-store.js +240 -0
  310. package/dist/senses/cli/virtual-list.js +35 -0
  311. package/dist/senses/cli-entry.js +60 -8
  312. package/dist/senses/cli-layout.js +187 -0
  313. package/dist/senses/cli.js +516 -211
  314. package/dist/senses/commands.js +66 -3
  315. package/dist/senses/habit-turn-message.js +108 -0
  316. package/dist/senses/inner-dialog-worker.js +97 -17
  317. package/dist/senses/inner-dialog.js +404 -14
  318. package/dist/senses/mail-entry.js +66 -0
  319. package/dist/senses/mail.js +232 -0
  320. package/dist/senses/pipeline.js +533 -72
  321. package/dist/senses/proactive-content-guard.js +51 -0
  322. package/dist/senses/shared-turn.js +205 -0
  323. package/dist/senses/surface-tool.js +68 -0
  324. package/dist/senses/teams-entry.js +60 -8
  325. package/dist/senses/teams.js +413 -163
  326. package/dist/senses/trust-gate.js +5 -5
  327. package/package.json +37 -7
  328. package/skills/agent-commerce.md +106 -0
  329. package/skills/browser-navigation.md +117 -0
  330. package/skills/commerce-setup-guide.md +116 -0
  331. package/skills/commerce-setup.md +84 -0
  332. package/skills/configure-dev-tools.md +101 -0
  333. package/skills/travel-planning.md +138 -0
  334. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  335. package/dist/heart/daemon/subagent-installer.js +0 -166
  336. package/dist/mind/associative-recall.js +0 -209
  337. package/dist/senses/bluebubbles-entry.js +0 -13
  338. package/dist/senses/debug-activity.js +0 -127
  339. package/subagents/README.md +0 -86
  340. package/subagents/work-doer.md +0 -237
  341. package/subagents/work-merger.md +0 -618
  342. package/subagents/work-planner.md +0 -390
  343. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  344. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  345. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  346. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  347. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  348. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  349. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  350. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  351. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  352. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  353. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  354. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  355. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  356. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  357. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  358. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,486 @@
1
+ "use strict";
2
+ /**
3
+ * System health check ("ouro doctor") — runs all diagnostic categories
4
+ * and aggregates results into a structured DoctorResult.
5
+ *
6
+ * Each category checker is isolated: if one throws, it produces a single
7
+ * "fail" check and the remaining categories still run.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.checkCliPath = checkCliPath;
11
+ exports.checkDaemon = checkDaemon;
12
+ exports.checkAgents = checkAgents;
13
+ exports.checkSenses = checkSenses;
14
+ exports.checkHabits = checkHabits;
15
+ exports.checkSecurity = checkSecurity;
16
+ exports.checkDisk = checkDisk;
17
+ exports.runDoctorChecks = runDoctorChecks;
18
+ const runtime_1 = require("../../nerves/runtime");
19
+ const bluebubbles_health_diagnostics_1 = require("./bluebubbles-health-diagnostics");
20
+ const ouro_path_installer_1 = require("../versioning/ouro-path-installer");
21
+ const runtime_credentials_1 = require("../runtime-credentials");
22
+ const machine_identity_1 = require("../machine-identity");
23
+ const DEFAULT_BLUEBUBBLES_REQUEST_TIMEOUT_MS = 30_000;
24
+ // ── Category checkers ──
25
+ function checkCliPath(deps) {
26
+ const resolution = (0, ouro_path_installer_1.diagnoseOuroPath)({
27
+ homeDir: deps.homedir,
28
+ envPath: deps.envPath ?? "",
29
+ existsSync: deps.existsSync,
30
+ readFileSync: (p) => deps.readFileSync(p),
31
+ });
32
+ const status = resolution.status === "ok"
33
+ ? "pass"
34
+ : resolution.status === "shadowed"
35
+ ? "fail"
36
+ : "warn";
37
+ return {
38
+ name: "CLI",
39
+ checks: [{
40
+ label: "ouro PATH resolution",
41
+ status,
42
+ detail: resolution.remediation
43
+ ? `${resolution.detail}; fix: ${resolution.remediation}`
44
+ : resolution.detail,
45
+ }],
46
+ };
47
+ }
48
+ async function checkDaemon(deps) {
49
+ const checks = [];
50
+ const socketExists = deps.existsSync(deps.socketPath);
51
+ checks.push({
52
+ label: "daemon socket exists",
53
+ status: socketExists ? "pass" : "fail",
54
+ detail: socketExists ? deps.socketPath : `not found at ${deps.socketPath}`,
55
+ });
56
+ if (socketExists) {
57
+ const alive = await deps.checkSocketAlive(deps.socketPath);
58
+ checks.push({
59
+ label: "daemon is responsive",
60
+ status: alive ? "pass" : "fail",
61
+ detail: alive ? "socket responded" : "socket exists but daemon unresponsive",
62
+ });
63
+ }
64
+ else {
65
+ checks.push({
66
+ label: "daemon is responsive",
67
+ status: "fail",
68
+ detail: "skipped — socket missing",
69
+ });
70
+ }
71
+ return { name: "Daemon", checks };
72
+ }
73
+ /** Discover all *.ouro directories under bundlesRoot. */
74
+ function discoverAgents(deps) {
75
+ if (!deps.existsSync(deps.bundlesRoot))
76
+ return [];
77
+ return deps.readdirSync(deps.bundlesRoot).filter((name) => name.endsWith(".ouro"));
78
+ }
79
+ function asRecord(value) {
80
+ return value && typeof value === "object" && !Array.isArray(value)
81
+ ? value
82
+ : null;
83
+ }
84
+ function textField(record, key) {
85
+ const value = record?.[key];
86
+ return typeof value === "string" ? value.trim() : "";
87
+ }
88
+ function numberField(record, key, fallback) {
89
+ const value = record?.[key];
90
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
91
+ }
92
+ function hasStringRecordValue(value) {
93
+ const record = asRecord(value);
94
+ return !!record && Object.values(record).some((entry) => typeof entry === "string" && entry.trim().length > 0);
95
+ }
96
+ function mailAutonomyDetail(mailroom) {
97
+ const policy = asRecord(mailroom?.autonomousSendPolicy);
98
+ const autonomy = policy?.enabled === true ? "autonomy enabled" : "autonomy disabled";
99
+ const killSwitch = policy?.killSwitch === true ? "kill switch on" : "kill switch off";
100
+ return `${autonomy}; ${killSwitch}`;
101
+ }
102
+ const SENSITIVE_CONFIG_KEYS = ["apiKey", "token", "secret", "password"];
103
+ function credentialKeyLeaks(raw) {
104
+ return SENSITIVE_CONFIG_KEYS.filter((key) => raw.includes(`"${key}"`));
105
+ }
106
+ function checkCredentialLeak(checks, label, raw) {
107
+ const found = credentialKeyLeaks(raw);
108
+ if (found.length > 0) {
109
+ checks.push({ label, status: "warn", detail: `contains credential-looking keys: ${found.join(", ")}` });
110
+ }
111
+ else {
112
+ checks.push({ label, status: "pass", detail: "no credential keys" });
113
+ }
114
+ }
115
+ function checkAgents(deps) {
116
+ const checks = [];
117
+ if (!deps.existsSync(deps.bundlesRoot)) {
118
+ checks.push({ label: "bundles directory", status: "fail", detail: `${deps.bundlesRoot} not found` });
119
+ return { name: "Agents", checks };
120
+ }
121
+ const agents = discoverAgents(deps);
122
+ if (agents.length === 0) {
123
+ checks.push({ label: "agent bundles", status: "warn", detail: "no *.ouro bundles found" });
124
+ return { name: "Agents", checks };
125
+ }
126
+ for (const agentDir of agents) {
127
+ const agentPath = `${deps.bundlesRoot}/${agentDir}`;
128
+ const configPath = `${agentPath}/agent.json`;
129
+ if (!deps.existsSync(configPath)) {
130
+ checks.push({ label: `${agentDir}/agent.json`, status: "fail", detail: "missing" });
131
+ continue;
132
+ }
133
+ let config;
134
+ try {
135
+ config = JSON.parse(deps.readFileSync(configPath));
136
+ }
137
+ catch {
138
+ checks.push({ label: `${agentDir}/agent.json`, status: "fail", detail: "unparseable JSON" });
139
+ continue;
140
+ }
141
+ const missing = [];
142
+ if (!config.version)
143
+ missing.push("version");
144
+ if (!config.humanFacing || typeof config.humanFacing !== "object") {
145
+ missing.push("humanFacing");
146
+ }
147
+ else {
148
+ const hf = config.humanFacing;
149
+ if (!hf.provider)
150
+ missing.push("humanFacing.provider");
151
+ if (!hf.model)
152
+ missing.push("humanFacing.model");
153
+ }
154
+ if (!config.agentFacing || typeof config.agentFacing !== "object") {
155
+ missing.push("agentFacing");
156
+ }
157
+ else {
158
+ const af = config.agentFacing;
159
+ if (!af.provider)
160
+ missing.push("agentFacing.provider");
161
+ if (!af.model)
162
+ missing.push("agentFacing.model");
163
+ }
164
+ if (missing.length > 0) {
165
+ checks.push({ label: `${agentDir}/agent.json`, status: "warn", detail: `missing fields: ${missing.join(", ")}` });
166
+ }
167
+ else {
168
+ checks.push({ label: `${agentDir}/agent.json`, status: "pass", detail: "valid" });
169
+ }
170
+ }
171
+ return { name: "Agents", checks };
172
+ }
173
+ async function checkSenses(deps) {
174
+ const checks = [];
175
+ const agents = discoverAgents(deps);
176
+ for (const agentDir of agents) {
177
+ const agentName = agentDir.replace(/\.ouro$/, "");
178
+ const configPath = `${deps.bundlesRoot}/${agentDir}/agent.json`;
179
+ if (!deps.existsSync(configPath))
180
+ continue;
181
+ let config;
182
+ try {
183
+ config = JSON.parse(deps.readFileSync(configPath));
184
+ }
185
+ catch {
186
+ checks.push({ label: `${agentDir} senses`, status: "fail", detail: "agent.json unparseable" });
187
+ continue;
188
+ }
189
+ if (!config.senses || typeof config.senses !== "object") {
190
+ checks.push({ label: `${agentDir} senses`, status: "warn", detail: "no senses config block" });
191
+ continue;
192
+ }
193
+ const senses = config.senses;
194
+ const senseNames = ["cli", "teams", "bluebubbles", "mail"];
195
+ for (const sense of senseNames) {
196
+ if (!(sense in senses))
197
+ continue;
198
+ const entry = senses[sense];
199
+ if (!entry || typeof entry !== "object") {
200
+ checks.push({ label: `${agentDir} ${sense}`, status: "fail", detail: "malformed sense entry" });
201
+ continue;
202
+ }
203
+ const senseObj = entry;
204
+ if (typeof senseObj.enabled !== "boolean") {
205
+ checks.push({ label: `${agentDir} ${sense}`, status: "warn", detail: "missing enabled boolean" });
206
+ }
207
+ else {
208
+ checks.push({
209
+ label: `${agentDir} ${sense}`,
210
+ status: "pass",
211
+ detail: senseObj.enabled ? "enabled" : "disabled",
212
+ });
213
+ }
214
+ if (sense === "bluebubbles" && senseObj.enabled === true) {
215
+ const machineId = (0, machine_identity_1.loadOrCreateMachineIdentity)({ homeDir: deps.homedir }).machineId;
216
+ const runtimeConfig = await (0, runtime_credentials_1.refreshMachineRuntimeCredentialConfig)(agentName, machineId, { preserveCachedOnFailure: true });
217
+ if (!runtimeConfig.ok) {
218
+ if (runtimeConfig.reason === "missing") {
219
+ checks.push({
220
+ label: `${agentDir} bluebubbles config`,
221
+ status: "pass",
222
+ detail: "not attached on this machine",
223
+ });
224
+ continue;
225
+ }
226
+ checks.push({
227
+ label: `${agentDir} bluebubbles config`,
228
+ status: "fail",
229
+ detail: `machine runtime config unavailable: ${runtimeConfig.error}`,
230
+ });
231
+ continue;
232
+ }
233
+ const bluebubbles = asRecord(runtimeConfig.config.bluebubbles);
234
+ const bluebubblesChannel = asRecord(runtimeConfig.config.bluebubblesChannel);
235
+ const serverUrl = textField(bluebubbles, "serverUrl");
236
+ const password = textField(bluebubbles, "password");
237
+ const missing = [];
238
+ if (!serverUrl)
239
+ missing.push("bluebubbles.serverUrl");
240
+ if (!password)
241
+ missing.push("bluebubbles.password");
242
+ if (missing.length > 0) {
243
+ checks.push({
244
+ label: `${agentDir} bluebubbles config`,
245
+ status: "fail",
246
+ detail: `missing ${missing.join("/")}`,
247
+ });
248
+ continue;
249
+ }
250
+ checks.push({
251
+ label: `${agentDir} bluebubbles config`,
252
+ status: "pass",
253
+ detail: serverUrl,
254
+ });
255
+ if (deps.fetchImpl) {
256
+ const probe = await (0, bluebubbles_health_diagnostics_1.probeBlueBubblesHealth)({
257
+ serverUrl,
258
+ password,
259
+ requestTimeoutMs: numberField(bluebubblesChannel, "requestTimeoutMs", DEFAULT_BLUEBUBBLES_REQUEST_TIMEOUT_MS),
260
+ fetchImpl: deps.fetchImpl,
261
+ });
262
+ checks.push({
263
+ label: `${agentDir} bluebubbles upstream`,
264
+ status: probe.ok ? "pass" : "fail",
265
+ detail: probe.detail,
266
+ });
267
+ }
268
+ }
269
+ if (sense === "mail" && senseObj.enabled === true) {
270
+ const runtimeConfig = await (0, runtime_credentials_1.refreshRuntimeCredentialConfig)(agentName, { preserveCachedOnFailure: true });
271
+ if (!runtimeConfig.ok) {
272
+ checks.push({
273
+ label: `${agentDir} mail config`,
274
+ status: "fail",
275
+ detail: `runtime config unavailable: ${runtimeConfig.error}`,
276
+ });
277
+ continue;
278
+ }
279
+ const mailroom = asRecord(runtimeConfig.config.mailroom);
280
+ const workSubstrate = asRecord(runtimeConfig.config.workSubstrate);
281
+ const mailboxAddress = textField(mailroom, "mailboxAddress");
282
+ const hosted = textField(workSubstrate, "mode") === "hosted";
283
+ const azureAccountUrl = textField(mailroom, "azureAccountUrl");
284
+ const azureContainer = textField(mailroom, "azureContainer") || "mailroom";
285
+ const missing = [];
286
+ if (!mailboxAddress)
287
+ missing.push("mailroom.mailboxAddress");
288
+ if (!hasStringRecordValue(mailroom?.privateKeys))
289
+ missing.push("mailroom.privateKeys");
290
+ if (hosted && !azureAccountUrl)
291
+ missing.push("mailroom.azureAccountUrl for hosted Blob reader");
292
+ if (missing.length > 0) {
293
+ checks.push({
294
+ label: `${agentDir} mail config`,
295
+ status: "fail",
296
+ detail: `missing ${missing.join("/")}`,
297
+ });
298
+ continue;
299
+ }
300
+ checks.push({
301
+ label: `${agentDir} mail config`,
302
+ status: "pass",
303
+ detail: [
304
+ mailboxAddress,
305
+ hosted ? `hosted azure-blob ${azureAccountUrl}/${azureContainer}` : "local file Mailroom",
306
+ mailAutonomyDetail(mailroom),
307
+ ].join("; "),
308
+ });
309
+ }
310
+ }
311
+ }
312
+ if (checks.length === 0) {
313
+ checks.push({ label: "senses", status: "warn", detail: "no agents with senses config found" });
314
+ }
315
+ return { name: "Senses", checks };
316
+ }
317
+ function checkHabits(deps) {
318
+ const checks = [];
319
+ const agents = discoverAgents(deps);
320
+ for (const agentDir of agents) {
321
+ const agentName = agentDir.replace(/\.ouro$/, "");
322
+ const habitsDir = `${deps.bundlesRoot}/${agentDir}/habits`;
323
+ if (!deps.existsSync(habitsDir)) {
324
+ checks.push({ label: `${agentDir} habits dir`, status: "warn", detail: "no habits directory" });
325
+ continue;
326
+ }
327
+ checks.push({ label: `${agentDir} habits dir`, status: "pass", detail: habitsDir });
328
+ // Check for launchd plists on macOS
329
+ const launchAgentsDir = `${deps.homedir}/Library/LaunchAgents`;
330
+ if (deps.existsSync(launchAgentsDir)) {
331
+ const plists = deps.readdirSync(launchAgentsDir).filter((f) => f.startsWith(`bot.ouro.${agentName}.`) && f.endsWith(".plist"));
332
+ if (plists.length > 0) {
333
+ checks.push({ label: `${agentDir} launchd plists`, status: "pass", detail: `${plists.length} plist(s)` });
334
+ }
335
+ else {
336
+ checks.push({ label: `${agentDir} launchd plists`, status: "fail", detail: "no matching plists in LaunchAgents" });
337
+ }
338
+ }
339
+ }
340
+ if (checks.length === 0) {
341
+ checks.push({ label: "habits", status: "warn", detail: "no agents found" });
342
+ }
343
+ return { name: "Habits", checks };
344
+ }
345
+ function checkSecurity(deps) {
346
+ const checks = [];
347
+ const agents = discoverAgents(deps);
348
+ for (const agentDir of agents) {
349
+ // Check agent.json for leaked credential keys
350
+ const configPath = `${deps.bundlesRoot}/${agentDir}/agent.json`;
351
+ if (deps.existsSync(configPath)) {
352
+ try {
353
+ const raw = deps.readFileSync(configPath);
354
+ const found = credentialKeyLeaks(raw);
355
+ if (found.length > 0) {
356
+ checks.push({ label: `${agentDir} credential leak`, status: "warn", detail: `agent.json contains keys: ${found.join(", ")}` });
357
+ }
358
+ else {
359
+ checks.push({ label: `${agentDir} credential leak`, status: "pass", detail: "no credential keys in agent.json" });
360
+ }
361
+ }
362
+ catch {
363
+ checks.push({ label: `${agentDir} credential leak`, status: "fail", detail: "could not read agent.json" });
364
+ }
365
+ }
366
+ const providerStatePath = `${deps.bundlesRoot}/${agentDir}/state/providers.json`;
367
+ if (deps.existsSync(providerStatePath)) {
368
+ try {
369
+ checkCredentialLeak(checks, `${agentDir} state/providers.json credential leak`, deps.readFileSync(providerStatePath));
370
+ }
371
+ catch {
372
+ checks.push({ label: `${agentDir} state/providers.json credential leak`, status: "fail", detail: "could not read state/providers.json" });
373
+ }
374
+ }
375
+ }
376
+ if (checks.length === 0) {
377
+ checks.push({ label: "security", status: "warn", detail: "no agents found" });
378
+ }
379
+ return { name: "Security", checks };
380
+ }
381
+ function checkDisk(deps) {
382
+ const checks = [];
383
+ const addLogSizeCheck = (labelPrefix, logsDir) => {
384
+ let totalSize = 0;
385
+ try {
386
+ const files = deps.readdirSync(logsDir);
387
+ for (const file of files) {
388
+ try {
389
+ const stat = deps.statSync(`${logsDir}/${file}`);
390
+ totalSize += stat.size;
391
+ }
392
+ catch {
393
+ // skip unreadable files
394
+ }
395
+ }
396
+ }
397
+ catch {
398
+ // readdirSync failure handled below
399
+ }
400
+ const sizeMB = totalSize / (1024 * 1024);
401
+ if (sizeMB > 500) {
402
+ checks.push({ label: `${labelPrefix} daemon log size`, status: "fail", detail: `${sizeMB.toFixed(1)}MB — exceeds 500MB limit` });
403
+ }
404
+ else if (sizeMB > 100) {
405
+ checks.push({ label: `${labelPrefix} daemon log size`, status: "warn", detail: `${sizeMB.toFixed(1)}MB — consider pruning with \`ouro logs prune\`` });
406
+ }
407
+ else {
408
+ checks.push({ label: `${labelPrefix} daemon log size`, status: "pass", detail: `${sizeMB.toFixed(1)}MB` });
409
+ }
410
+ };
411
+ const agents = discoverAgents(deps);
412
+ if (agents.length === 0) {
413
+ checks.push({ label: "daemon logs dir", status: "warn", detail: "no agent bundles found for bundle-local logs" });
414
+ }
415
+ for (const agentDir of agents) {
416
+ const logsDir = `${deps.bundlesRoot}/${agentDir}/state/daemon/logs`;
417
+ if (!deps.existsSync(logsDir)) {
418
+ checks.push({ label: `${agentDir} daemon logs dir`, status: "warn", detail: `${logsDir} not found` });
419
+ }
420
+ else {
421
+ addLogSizeCheck(agentDir, logsDir);
422
+ }
423
+ }
424
+ // Check AgentBundles root
425
+ if (deps.existsSync(deps.bundlesRoot)) {
426
+ checks.push({ label: "bundles root", status: "pass", detail: deps.bundlesRoot });
427
+ }
428
+ else {
429
+ checks.push({ label: "bundles root", status: "warn", detail: `${deps.bundlesRoot} not found` });
430
+ }
431
+ return { name: "Disk", checks };
432
+ }
433
+ // ── Orchestrator ──
434
+ function computeSummary(categories) {
435
+ let passed = 0;
436
+ let warnings = 0;
437
+ let failed = 0;
438
+ for (const cat of categories) {
439
+ for (const check of cat.checks) {
440
+ /* v8 ignore next 3 -- all three branches tested; v8 misreports compound if/else-if chain @preserve */
441
+ if (check.status === "pass")
442
+ passed++;
443
+ else if (check.status === "warn")
444
+ warnings++;
445
+ else
446
+ failed++;
447
+ }
448
+ }
449
+ return { passed, warnings, failed };
450
+ }
451
+ const CATEGORY_CHECKERS = [
452
+ { name: "CLI", fn: checkCliPath },
453
+ { name: "Daemon", fn: checkDaemon },
454
+ { name: "Agents", fn: checkAgents },
455
+ { name: "Senses", fn: checkSenses },
456
+ { name: "Habits", fn: checkHabits },
457
+ { name: "Security", fn: checkSecurity },
458
+ { name: "Disk", fn: checkDisk },
459
+ ];
460
+ async function runDoctorChecks(deps) {
461
+ const categories = [];
462
+ for (const checker of CATEGORY_CHECKERS) {
463
+ try {
464
+ const category = await Promise.resolve(checker.fn(deps));
465
+ categories.push(category);
466
+ }
467
+ catch (error) {
468
+ (0, runtime_1.emitNervesEvent)({
469
+ level: "warn",
470
+ component: "daemon",
471
+ event: "daemon.doctor_check_error",
472
+ message: `doctor check ${checker.name} failed`,
473
+ meta: { category: checker.name, error: error instanceof Error ? error.message : String(error) },
474
+ });
475
+ categories.push({
476
+ name: checker.name,
477
+ checks: [{
478
+ label: checker.name.toLowerCase(),
479
+ status: "fail",
480
+ detail: `check crashed: ${error instanceof Error ? error.message : String(error)}`,
481
+ }],
482
+ });
483
+ }
484
+ }
485
+ return { categories, summary: computeSummary(categories) };
486
+ }
@@ -7,22 +7,76 @@ class HealthMonitor {
7
7
  scheduler;
8
8
  alertSink;
9
9
  diskUsagePercent;
10
+ onCriticalAgent;
11
+ senseProbes;
12
+ senseProbeProvider;
13
+ intervalHandle = null;
10
14
  constructor(options) {
11
15
  this.processManager = options.processManager;
12
16
  this.scheduler = options.scheduler;
13
17
  this.alertSink = options.alertSink ?? (() => undefined);
14
18
  this.diskUsagePercent = options.diskUsagePercent ?? (() => 0);
19
+ this.onCriticalAgent = options.onCriticalAgent ?? (() => undefined);
20
+ this.senseProbes = options.senseProbes ?? [];
21
+ this.senseProbeProvider = options.senseProbeProvider ?? (() => []);
22
+ }
23
+ startPeriodicChecks(intervalMs) {
24
+ if (this.intervalHandle !== null)
25
+ return;
26
+ (0, runtime_1.emitNervesEvent)({
27
+ level: "info",
28
+ component: "daemon",
29
+ event: "daemon.health_check_scheduled",
30
+ message: "periodic health checks started",
31
+ meta: { intervalMs },
32
+ });
33
+ this.intervalHandle = setInterval(() => {
34
+ void this.runChecks();
35
+ }, intervalMs);
36
+ }
37
+ stopPeriodicChecks() {
38
+ if (this.intervalHandle === null)
39
+ return;
40
+ clearInterval(this.intervalHandle);
41
+ this.intervalHandle = null;
15
42
  }
16
43
  async runChecks() {
17
44
  const results = [];
18
45
  const snapshots = this.processManager.listAgentSnapshots();
19
46
  const unhealthy = snapshots.filter((snapshot) => snapshot.status !== "running");
20
47
  if (unhealthy.length > 0) {
48
+ const unhealthySummary = unhealthy.map((item) => {
49
+ const detail = [
50
+ item.errorReason ?? null,
51
+ item.fixHint ? `fix: ${item.fixHint}` : null,
52
+ ].filter((part) => part !== null).join("; ");
53
+ return detail.length > 0 ? `${item.name} (${detail})` : item.name;
54
+ }).join(", ");
21
55
  results.push({
22
56
  name: "agent-processes",
23
57
  status: "critical",
24
- message: `non-running agents: ${unhealthy.map((item) => item.name).join(", ")}`,
58
+ message: `non-running agents: ${unhealthySummary}`,
25
59
  });
60
+ for (const agent of unhealthy) {
61
+ try {
62
+ (0, runtime_1.emitNervesEvent)({
63
+ level: "warn",
64
+ component: "daemon",
65
+ event: "daemon.health_check_recovery_attempted",
66
+ message: "triggering recovery restart for non-running agent",
67
+ meta: {
68
+ agentName: agent.name,
69
+ agentStatus: agent.status,
70
+ errorReason: agent.errorReason ?? null,
71
+ fixHint: agent.fixHint ?? null,
72
+ },
73
+ });
74
+ this.onCriticalAgent(agent.name);
75
+ }
76
+ catch {
77
+ // Recovery is best-effort -- callback errors must not crash runChecks
78
+ }
79
+ }
26
80
  }
27
81
  else {
28
82
  results.push({ name: "agent-processes", status: "ok", message: "all managed agents running" });
@@ -61,6 +115,43 @@ class HealthMonitor {
61
115
  message: `disk usage healthy (${diskPercent}%)`,
62
116
  });
63
117
  }
118
+ const senseProbes = [...this.senseProbes];
119
+ try {
120
+ senseProbes.push(...this.senseProbeProvider());
121
+ }
122
+ catch (error) {
123
+ results.push({
124
+ name: "sense-probes",
125
+ status: "warn",
126
+ message: `sense probe discovery failed: ${error instanceof Error ? error.message : String(error)}`,
127
+ });
128
+ }
129
+ for (const probe of senseProbes) {
130
+ try {
131
+ const outcome = await probe.check();
132
+ if (outcome.ok) {
133
+ results.push({
134
+ name: `sense-probe:${probe.name}`,
135
+ status: "ok",
136
+ message: `${probe.name} healthy`,
137
+ });
138
+ }
139
+ else {
140
+ results.push({
141
+ name: `sense-probe:${probe.name}`,
142
+ status: "critical",
143
+ message: `${probe.name} failed: ${outcome.detail ?? "unknown"}`,
144
+ });
145
+ }
146
+ }
147
+ catch (error) {
148
+ results.push({
149
+ name: `sense-probe:${probe.name}`,
150
+ status: "critical",
151
+ message: `${probe.name} error: ${error instanceof Error ? error.message : String(error)}`,
152
+ });
153
+ }
154
+ }
64
155
  for (const result of results) {
65
156
  (0, runtime_1.emitNervesEvent)({
66
157
  level: result.status === "critical" ? "error" : result.status === "warn" ? "warn" : "info",
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agentConfigV2Hook = agentConfigV2Hook;
4
+ const runtime_1 = require("../../../nerves/runtime");
5
+ const migrate_config_1 = require("../../migrate-config");
6
+ async function agentConfigV2Hook(ctx) {
7
+ (0, runtime_1.emitNervesEvent)({
8
+ component: "daemon",
9
+ event: "daemon.agent_config_v2_hook_start",
10
+ message: "running agent-config-v2 update hook",
11
+ meta: { agentRoot: ctx.agentRoot, currentVersion: ctx.currentVersion },
12
+ });
13
+ try {
14
+ (0, migrate_config_1.migrateAgentConfigV1ToV2)(ctx.agentRoot);
15
+ }
16
+ catch (err) {
17
+ const errorMessage = err instanceof Error ? err.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(err);
18
+ (0, runtime_1.emitNervesEvent)({
19
+ component: "daemon",
20
+ event: "daemon.agent_config_v2_hook_error",
21
+ message: "agent-config-v2 hook migration failed",
22
+ meta: { agentRoot: ctx.agentRoot, error: errorMessage },
23
+ });
24
+ return { ok: false, error: errorMessage };
25
+ }
26
+ (0, runtime_1.emitNervesEvent)({
27
+ component: "daemon",
28
+ event: "daemon.agent_config_v2_hook_end",
29
+ message: "agent-config-v2 hook completed",
30
+ meta: { agentRoot: ctx.agentRoot },
31
+ });
32
+ return { ok: true };
33
+ }