@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,774 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.registerSanctuaryHealthAcceptanceProbeProcess = registerSanctuaryHealthAcceptanceProbeProcess;
38
+ exports.createSanctuaryHealthAcceptanceProbeProcessHost = createSanctuaryHealthAcceptanceProbeProcessHost;
39
+ exports.createSanctuaryHealthAcceptanceProbeProcessDependencies = createSanctuaryHealthAcceptanceProbeProcessDependencies;
40
+ exports.stopSanctuaryHealthAcceptanceProbeProcess = stopSanctuaryHealthAcceptanceProbeProcess;
41
+ exports.exactLocalDailyBoundary = exactLocalDailyBoundary;
42
+ exports.createSanctuaryHealthAcceptanceLoopbackFixture = createSanctuaryHealthAcceptanceLoopbackFixture;
43
+ exports.createSanctuaryHealthAcceptanceProbeDependencies = createSanctuaryHealthAcceptanceProbeDependencies;
44
+ exports.runSanctuaryHealthAcceptanceProbe = runSanctuaryHealthAcceptanceProbe;
45
+ exports.finalizeSanctuaryHealthAcceptanceProbe = finalizeSanctuaryHealthAcceptanceProbe;
46
+ exports.recoverSanctuaryHealthAcceptanceProbe = recoverSanctuaryHealthAcceptanceProbe;
47
+ exports.createSanctuaryHealthAcceptanceProbeCliHost = createSanctuaryHealthAcceptanceProbeCliHost;
48
+ exports.runSanctuaryHealthAcceptanceProbeCli = runSanctuaryHealthAcceptanceProbeCli;
49
+ exports.createSanctuaryHealthAcceptanceProbeCliOutput = createSanctuaryHealthAcceptanceProbeCliOutput;
50
+ exports.startSanctuaryHealthAcceptanceProbeCli = startSanctuaryHealthAcceptanceProbeCli;
51
+ const node_crypto_1 = require("node:crypto");
52
+ const fs = __importStar(require("node:fs"));
53
+ const node_http_1 = require("node:http");
54
+ const os = __importStar(require("node:os"));
55
+ const path = __importStar(require("node:path"));
56
+ const identity_1 = require("../heart/identity");
57
+ const runtime_1 = require("../nerves/runtime");
58
+ const sanctuary_health_1 = require("./sanctuary-health");
59
+ const sanctuary_health_runner_1 = require("./sanctuary-health-runner");
60
+ const sanctuary_runtime_1 = require("./sanctuary-runtime");
61
+ const sanctuary_scheduler_liveness_1 = require("../heart/daemon/sanctuary-scheduler-liveness");
62
+ const telegram_1 = require("./telegram");
63
+ const SHA256 = /^[0-9a-f]{64}$/u;
64
+ const TARGET_ENDPOINT = "https://books.mendelow.cloud/";
65
+ const CRON_MARKER = "# ouro:habit:sanctuary:sanctuary:sanctuary-health";
66
+ const CRON_COMMAND = "*/15 * * * * /usr/local/bin/node /opt/ouro/dist/heart/daemon/ouro-entry.js poke sanctuary --habit sanctuary-health --trigger cron";
67
+ const PROCESS_ENTRY = "/opt/ouro/dist/senses/sanctuary-health-acceptance-probe-entry.js";
68
+ const LABELS = ["unit-16f-cron-fingerprint", "unit-16g-health-transition", "unit-16h-acceptance-delivery-probe"];
69
+ function digestBytes(value) {
70
+ return (0, node_crypto_1.createHash)("sha256").update(value).digest("hex");
71
+ }
72
+ function digestJson(value) {
73
+ return digestBytes(JSON.stringify(value));
74
+ }
75
+ function canonicalInput(input) {
76
+ if (!LABELS.includes(input.label) || ![input.scenarioHandleDigest, input.ownerImageDigest, input.ownerContainerDigest].every((value) => SHA256.test(value))) {
77
+ throw new Error("Sanctuary health acceptance probe input is invalid");
78
+ }
79
+ }
80
+ function atomicPrivateFile(filePath, contents) {
81
+ fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
82
+ fs.chmodSync(path.dirname(filePath), 0o700);
83
+ const temporary = `${filePath}.tmp-${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
84
+ try {
85
+ fs.writeFileSync(temporary, contents, { flag: "wx", mode: 0o600 });
86
+ const handle = fs.openSync(temporary, "r");
87
+ try {
88
+ fs.fsyncSync(handle);
89
+ }
90
+ finally {
91
+ fs.closeSync(handle);
92
+ }
93
+ fs.renameSync(temporary, filePath);
94
+ fs.chmodSync(filePath, 0o600);
95
+ const directory = fs.openSync(path.dirname(filePath), "r");
96
+ try {
97
+ fs.fsyncSync(directory);
98
+ }
99
+ finally {
100
+ fs.closeSync(directory);
101
+ }
102
+ }
103
+ finally {
104
+ if (fs.existsSync(temporary))
105
+ fs.unlinkSync(temporary);
106
+ }
107
+ }
108
+ function probeProcessPath(agentRoot, scenarioHandleDigest) {
109
+ return path.join(agentRoot, "state", "acceptance", "health-probe-processes", `${scenarioHandleDigest}.json`);
110
+ }
111
+ function processRecord(input, pid) {
112
+ return { schemaVersion: "sanctuary-health-probe-process-v1", pid, ...input };
113
+ }
114
+ function sameProcessRecord(value, input) {
115
+ return value.schemaVersion === "sanctuary-health-probe-process-v1" && Number.isSafeInteger(value.pid) && Number(value.pid) > 1
116
+ && value.label === input.label && value.scenarioHandleDigest === input.scenarioHandleDigest
117
+ && value.ownerImageDigest === input.ownerImageDigest && value.ownerContainerDigest === input.ownerContainerDigest;
118
+ }
119
+ function registerSanctuaryHealthAcceptanceProbeProcess(input, dependencies) {
120
+ canonicalInput(input);
121
+ if (!Number.isSafeInteger(dependencies.pid) || dependencies.pid <= 1)
122
+ throw new Error("Sanctuary health acceptance process pid is invalid");
123
+ atomicPrivateFile(probeProcessPath(dependencies.agentRoot, input.scenarioHandleDigest), `${JSON.stringify(processRecord(input, dependencies.pid))}\n`);
124
+ }
125
+ function unregisterSanctuaryHealthAcceptanceProbeProcess(input, agentRoot, pid) {
126
+ const marker = probeProcessPath(agentRoot, input.scenarioHandleDigest);
127
+ try {
128
+ const value = JSON.parse(fs.readFileSync(marker, "utf8"));
129
+ if (sameProcessRecord(value, input) && value.pid === pid)
130
+ fs.unlinkSync(marker);
131
+ }
132
+ catch (error) {
133
+ if (error.code !== "ENOENT")
134
+ throw error;
135
+ }
136
+ }
137
+ function createSanctuaryHealthAcceptanceProbeProcessHost(raw = {
138
+ readDirectory: fs.readdirSync,
139
+ kill: process.kill.bind(process),
140
+ readFile: fs.readFileSync,
141
+ setTimeout,
142
+ }) {
143
+ return {
144
+ listProcEntries: () => raw.readDirectory("/proc"),
145
+ kill: (pid, signal) => { raw.kill(pid, signal); },
146
+ readCommandLine: (pid) => raw.readFile(`/proc/${pid}/cmdline`, "utf8"),
147
+ sleep: (ms) => new Promise((resolve) => { raw.setTimeout(resolve, ms); }),
148
+ };
149
+ }
150
+ function createSanctuaryHealthAcceptanceProbeProcessDependencies(options = {}, host = createSanctuaryHealthAcceptanceProbeProcessHost()) {
151
+ const kill = options.kill ?? host.kill;
152
+ return {
153
+ agentRoot: options.agentRoot ?? (0, identity_1.getAgentRoot)("sanctuary"),
154
+ listPids: () => (options.listProcEntries?.() ?? host.listProcEntries()).filter((entry) => /^[0-9]+$/u.test(entry)).map(Number),
155
+ processAlive: (pid) => {
156
+ try {
157
+ kill(pid, 0);
158
+ return true;
159
+ }
160
+ catch (error) {
161
+ if (error.code === "ESRCH")
162
+ return false;
163
+ throw error;
164
+ }
165
+ },
166
+ readCommandLine: options.readCommandLine ?? host.readCommandLine,
167
+ signal: (pid, signal) => { kill(pid, signal); },
168
+ sleep: options.sleep ?? host.sleep,
169
+ };
170
+ }
171
+ function expectedProbeCommandLine(input) {
172
+ return [
173
+ "/usr/local/bin/node", PROCESS_ENTRY, "run",
174
+ "--label", input.label,
175
+ "--scenario", input.scenarioHandleDigest,
176
+ "--owner-image", input.ownerImageDigest,
177
+ "--owner-container", input.ownerContainerDigest,
178
+ ];
179
+ }
180
+ function parsedCommandLine(raw) {
181
+ const parts = raw.split("\0");
182
+ if (parts.at(-1) === "")
183
+ parts.pop();
184
+ return parts;
185
+ }
186
+ function probeProcessScan(input, dependencies) {
187
+ const expected = JSON.stringify(expectedProbeCommandLine(input));
188
+ const candidates = [];
189
+ const exact = [];
190
+ for (const pid of dependencies.listPids()) {
191
+ if (!dependencies.processAlive(pid))
192
+ continue;
193
+ let command;
194
+ try {
195
+ command = parsedCommandLine(dependencies.readCommandLine(pid));
196
+ }
197
+ catch (error) {
198
+ if (["ENOENT", "ESRCH"].includes(String(error.code)))
199
+ continue;
200
+ throw error;
201
+ }
202
+ if (command.includes(PROCESS_ENTRY) && command.includes("run") && command.includes(input.scenarioHandleDigest))
203
+ candidates.push(pid);
204
+ if (JSON.stringify(command) === expected)
205
+ exact.push(pid);
206
+ }
207
+ return { candidates, exact };
208
+ }
209
+ function exactProbeProcessAtPid(input, dependencies, pid) {
210
+ if (!dependencies.processAlive(pid))
211
+ return false;
212
+ try {
213
+ return JSON.stringify(parsedCommandLine(dependencies.readCommandLine(pid))) === JSON.stringify(expectedProbeCommandLine(input));
214
+ }
215
+ catch (error) {
216
+ if (["ENOENT", "ESRCH"].includes(String(error.code)))
217
+ return false;
218
+ throw error;
219
+ }
220
+ }
221
+ async function waitForExactProcessAbsent(input, pid, dependencies, timeoutMs) {
222
+ const deadline = Date.now() + timeoutMs;
223
+ while (exactProbeProcessAtPid(input, dependencies, pid) && Date.now() < deadline)
224
+ await dependencies.sleep(Math.min(50, Math.max(1, deadline - Date.now())));
225
+ return !exactProbeProcessAtPid(input, dependencies, pid);
226
+ }
227
+ async function stopSanctuaryHealthAcceptanceProbeProcess(input, dependencies = createSanctuaryHealthAcceptanceProbeProcessDependencies(), options = {}) {
228
+ canonicalInput(input);
229
+ const marker = probeProcessPath(dependencies.agentRoot, input.scenarioHandleDigest);
230
+ let markerPid = null;
231
+ try {
232
+ const value = JSON.parse(fs.readFileSync(marker, "utf8"));
233
+ if (!sameProcessRecord(value, input))
234
+ throw new Error("Sanctuary health acceptance process identity is invalid");
235
+ markerPid = value.pid;
236
+ }
237
+ catch (error) {
238
+ if (error.code !== "ENOENT")
239
+ throw error;
240
+ }
241
+ const scan = probeProcessScan(input, dependencies);
242
+ if (scan.candidates.length !== scan.exact.length)
243
+ throw new Error("Sanctuary health acceptance process identity is invalid");
244
+ const exactPids = scan.exact;
245
+ if (exactPids.length > 1)
246
+ throw new Error("Sanctuary health acceptance process identity is ambiguous");
247
+ if (markerPid !== null && dependencies.processAlive(markerPid) && exactPids[0] !== markerPid) {
248
+ throw new Error("Sanctuary health acceptance process identity is invalid");
249
+ }
250
+ if (markerPid !== null && !dependencies.processAlive(markerPid) && exactPids.length !== 0) {
251
+ throw new Error("Sanctuary health acceptance process identity is invalid");
252
+ }
253
+ const pid = markerPid !== null && dependencies.processAlive(markerPid) ? markerPid : exactPids[0] ?? null;
254
+ if (pid !== null) {
255
+ if (!exactProbeProcessAtPid(input, dependencies, pid))
256
+ throw new Error("Sanctuary health acceptance process identity is invalid");
257
+ dependencies.signal(pid, "SIGTERM");
258
+ if (!await waitForExactProcessAbsent(input, pid, dependencies, options.termGraceMs ?? 5_000)) {
259
+ if (!exactProbeProcessAtPid(input, dependencies, pid))
260
+ throw new Error("Sanctuary health acceptance process identity is invalid");
261
+ dependencies.signal(pid, "SIGKILL");
262
+ if (!await waitForExactProcessAbsent(input, pid, dependencies, options.killGraceMs ?? 5_000))
263
+ throw new Error("Sanctuary health acceptance process did not stop");
264
+ }
265
+ }
266
+ if (markerPid !== null)
267
+ unregisterSanctuaryHealthAcceptanceProbeProcess(input, dependencies.agentRoot, markerPid);
268
+ const finalScan = probeProcessScan(input, dependencies);
269
+ if (finalScan.candidates.length !== 0 || finalScan.exact.length !== 0 || fs.existsSync(marker))
270
+ throw new Error("Sanctuary health acceptance process absence was not verified");
271
+ return { stopped: pid !== null };
272
+ }
273
+ function snapshotState(statePath) {
274
+ try {
275
+ return { exists: true, bytes: fs.readFileSync(statePath).toString("base64") };
276
+ }
277
+ catch (error) {
278
+ if (error.code === "ENOENT")
279
+ return { exists: false, bytes: "" };
280
+ throw error;
281
+ }
282
+ }
283
+ function snapshotDigest(snapshot) {
284
+ return digestBytes(snapshot.exists ? Buffer.from(snapshot.bytes, "base64") : "sanctuary-health-state:absent");
285
+ }
286
+ function cursorFromSnapshot(snapshot) {
287
+ if (!snapshot.exists)
288
+ throw new Error("Sanctuary health acceptance observer state is absent");
289
+ const state = JSON.parse(Buffer.from(snapshot.bytes, "base64").toString("utf8"));
290
+ if (!Array.isArray(state.sweepReceipts) || !Array.isArray(state.deliveredReceipts))
291
+ throw new Error("Sanctuary health acceptance observer state is invalid");
292
+ return { sweepCount: state.sweepReceipts.length, deliveryCount: state.deliveredReceipts.length };
293
+ }
294
+ function restoreState(statePath, snapshot) {
295
+ if (!snapshot.exists) {
296
+ try {
297
+ fs.unlinkSync(statePath);
298
+ }
299
+ catch (error) {
300
+ if (error.code !== "ENOENT")
301
+ throw error;
302
+ }
303
+ return;
304
+ }
305
+ atomicPrivateFile(statePath, Buffer.from(snapshot.bytes, "base64").toString("utf8"));
306
+ }
307
+ function readHealthState(statePath, readFile) {
308
+ const value = JSON.parse(readFile ? readFile(statePath) : fs.readFileSync(statePath, "utf8"));
309
+ if (!value || typeof value !== "object" || Array.isArray(value.incidents) || !Array.isArray(value.sweepReceipts) || !Array.isArray(value.deliveredReceipts)) {
310
+ throw new Error("Sanctuary health acceptance working state is invalid");
311
+ }
312
+ return value;
313
+ }
314
+ function writeHealthState(statePath, state) {
315
+ atomicPrivateFile(statePath, `${JSON.stringify(state)}\n`);
316
+ }
317
+ function localParts(date) {
318
+ return Object.fromEntries(new Intl.DateTimeFormat("en-CA", {
319
+ timeZone: "America/Los_Angeles", year: "numeric", month: "2-digit", day: "2-digit",
320
+ hour: "2-digit", minute: "2-digit", second: "2-digit", hourCycle: "h23",
321
+ }).formatToParts(date).map((part) => [part.type, part.value]));
322
+ }
323
+ function localDay(date) {
324
+ const parts = localParts(date);
325
+ return `${parts.year}-${parts.month}-${parts.day}`;
326
+ }
327
+ function exactLocalDailyBoundary(reference) {
328
+ const parts = localParts(reference);
329
+ const desired = Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day), 9, 0, 0, 0);
330
+ let candidate = desired;
331
+ for (let attempt = 0; attempt < 3; attempt += 1) {
332
+ const observed = localParts(new Date(candidate));
333
+ const observedWall = Date.UTC(Number(observed.year), Number(observed.month) - 1, Number(observed.day), Number(observed.hour), Number(observed.minute), Number(observed.second), 0);
334
+ candidate += desired - observedWall;
335
+ }
336
+ const result = new Date(candidate);
337
+ const final = localParts(result);
338
+ if (final.year !== parts.year || final.month !== parts.month || final.day !== parts.day
339
+ || final.hour !== "09" || final.minute !== "00" || final.second !== "00" || result.getUTCMilliseconds() !== 0) {
340
+ throw new Error("Sanctuary daily boundary clock could not be resolved");
341
+ }
342
+ return result;
343
+ }
344
+ function canonicalCron(raw) {
345
+ const lines = raw.split(/\r?\n/u);
346
+ const marker = lines.indexOf(CRON_MARKER);
347
+ return marker >= 0 && lines[marker + 1] === CRON_COMMAND;
348
+ }
349
+ async function closeServer(server) {
350
+ await new Promise((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
351
+ }
352
+ async function createSanctuaryHealthAcceptanceLoopbackFixture(statuses, ambientFetch, createLoopbackServer = node_http_1.createServer) {
353
+ let cursor = 0;
354
+ const observed = [];
355
+ const server = createLoopbackServer((_request, response) => {
356
+ const status = statuses[cursor];
357
+ if (status === undefined) {
358
+ response.writeHead(500);
359
+ response.end();
360
+ return;
361
+ }
362
+ cursor += 1;
363
+ observed.push(status);
364
+ response.writeHead(status);
365
+ response.end();
366
+ });
367
+ await new Promise((resolve, reject) => {
368
+ server.once("error", reject);
369
+ server.listen(0, "127.0.0.1", () => { server.off("error", reject); resolve(); });
370
+ });
371
+ const address = server.address();
372
+ if (!address || typeof address === "string") {
373
+ await closeServer(server);
374
+ throw new Error("Sanctuary loopback fixture address is invalid");
375
+ }
376
+ const fixtureUrl = `http://127.0.0.1:${address.port}/health`;
377
+ const fixtureFetch = (async (input, init) => {
378
+ if (String(input) === TARGET_ENDPOINT)
379
+ return globalThis.fetch(fixtureUrl, { ...init, redirect: "manual" });
380
+ return ambientFetch(input, init);
381
+ });
382
+ return { fetch: fixtureFetch, server, observed };
383
+ }
384
+ function createSanctuaryHealthAcceptanceProbeDependencies(overrides = {}, schedulerWait = {}) {
385
+ const defaults = {
386
+ agentRoot: overrides.agentRoot ?? (0, identity_1.getAgentRoot)("sanctuary"),
387
+ runtimeRoot: overrides.runtimeRoot ?? path.join(os.homedir(), ".ouro-cli"),
388
+ ambientFetch: overrides.ambientFetch ?? fetch,
389
+ now: overrides.now ?? (() => new Date()),
390
+ runnerOptions: overrides.runnerOptions,
391
+ deferOwnerAttestation: overrides.deferOwnerAttestation ?? true,
392
+ identityKey: overrides.identityKey ?? telegram_1.readOrCreateTelegramIdentityKey,
393
+ waitForSchedulerReceipt: overrides.waitForSchedulerReceipt ?? (async (agentRoot, scenarioHandleDigest) => {
394
+ const receiptPath = path.join(agentRoot, "state", "acceptance", "scheduler-liveness-receipts", `${scenarioHandleDigest}.json`);
395
+ const deadline = Date.now() + (schedulerWait.timeoutMs ?? 16 * 60 * 1_000);
396
+ while (Date.now() <= deadline) {
397
+ try {
398
+ return JSON.parse(fs.readFileSync(receiptPath, "utf8"));
399
+ }
400
+ catch (error) {
401
+ if (error.code !== "ENOENT")
402
+ throw error;
403
+ }
404
+ await new Promise((resolve) => setTimeout(resolve, Math.min(schedulerWait.pollMs ?? 1_000, Math.max(1, deadline - Date.now()))));
405
+ }
406
+ throw new Error("Sanctuary scheduler liveness receipt timed out");
407
+ }),
408
+ toolContext: overrides.toolContext ?? (0, sanctuary_runtime_1.createSanctuaryToolContext)("sanctuary"),
409
+ acceptanceFs: overrides.acceptanceFs,
410
+ createLoopbackServer: overrides.createLoopbackServer,
411
+ };
412
+ return defaults;
413
+ }
414
+ function removeProbeWorkspace(workspace) {
415
+ const allowed = new Set(["checkpoint.json", "normalization.json", "snapshot.json", "verify.json"]);
416
+ const entries = fs.readdirSync(workspace, { withFileTypes: true });
417
+ if (entries.some((entry) => !entry.isFile() || !allowed.has(entry.name)))
418
+ throw new Error("Sanctuary health acceptance workspace contains unexpected entries");
419
+ for (const entry of entries)
420
+ fs.unlinkSync(path.join(workspace, entry.name));
421
+ fs.rmdirSync(workspace);
422
+ }
423
+ async function normalizeWorkingState(input) {
424
+ const temporaryState = path.join(input.workspace, "normalization.json");
425
+ const copyFile = input.deps.acceptanceFs?.copyFile ?? fs.copyFileSync;
426
+ try {
427
+ copyFile(input.statePath, temporaryState);
428
+ }
429
+ catch (error) {
430
+ if (error.code !== "ENOENT")
431
+ throw error;
432
+ }
433
+ const sweep = (0, sanctuary_health_1.createSanctuaryHealthSweep)({
434
+ toolContext: input.deps.toolContext,
435
+ statePath: temporaryState,
436
+ fetch: input.deps.ambientFetch,
437
+ now: () => input.effectiveNow,
438
+ acceptanceEventMeta: () => ({}),
439
+ });
440
+ await sweep();
441
+ const state = readHealthState(temporaryState, input.deps.acceptanceFs?.readFile);
442
+ state.outbox = null;
443
+ state.indeterminateDeliveries = [];
444
+ state.lastDigestDay = localDay(input.effectiveNow);
445
+ state.updatedAt = input.effectiveNow.toISOString();
446
+ writeHealthState(input.statePath, state);
447
+ const last = state.sweepReceipts.at(-1);
448
+ if (!last || typeof last.incidentDigest !== "string" || !SHA256.test(last.incidentDigest))
449
+ throw new Error("Sanctuary health normalization receipt is invalid");
450
+ return last.incidentDigest;
451
+ }
452
+ function phaseFromState(statePath, scenarioHandleDigest, ordinal, name, trigger, fixtureStatus) {
453
+ const state = readHealthState(statePath);
454
+ const sweep = state.sweepReceipts.filter((entry) => entry.scenarioHandleDigest === scenarioHandleDigest).at(-1);
455
+ if (!sweep || typeof sweep.opened !== "number" || typeof sweep.recovered !== "number" || typeof sweep.digestDue !== "boolean") {
456
+ throw new Error("Sanctuary health acceptance sweep receipt is missing");
457
+ }
458
+ const deliveryId = typeof sweep.deliveryId === "string" ? sweep.deliveryId : null;
459
+ const delivery = deliveryId ? state.deliveredReceipts.find((entry) => entry.deliveryId === deliveryId) : undefined;
460
+ const kind = delivery && ["transition", "digest", "transition_and_digest"].includes(String(delivery.kind))
461
+ ? delivery.kind : null;
462
+ if (deliveryId && !delivery)
463
+ throw new Error("Sanctuary health acceptance delivery receipt is missing");
464
+ return {
465
+ ordinal, name, trigger, fixtureStatus,
466
+ opened: sweep.opened, recovered: sweep.recovered, digestDue: sweep.digestDue,
467
+ deliveryKind: kind,
468
+ sweepReceiptDigest: digestJson(sweep),
469
+ deliveryReceiptDigest: delivery ? digestJson(delivery) : null,
470
+ };
471
+ }
472
+ async function verifyRealCheckEquivalent(input) {
473
+ const verifyState = path.join(input.workspace, "verify.json");
474
+ const copyFile = input.deps.acceptanceFs?.copyFile ?? fs.copyFileSync;
475
+ try {
476
+ copyFile(input.statePath, verifyState);
477
+ }
478
+ catch (error) {
479
+ if (error.code !== "ENOENT")
480
+ throw error;
481
+ }
482
+ const sweep = (0, sanctuary_health_1.createSanctuaryHealthSweep)({ toolContext: input.deps.toolContext, statePath: verifyState, fetch: input.deps.ambientFetch, now: () => input.effectiveNow });
483
+ await sweep();
484
+ const receipt = readHealthState(verifyState, input.deps.acceptanceFs?.readFile).sweepReceipts.at(-1);
485
+ return Boolean(receipt && receipt.incidentDigest === input.expectedIncidentDigest);
486
+ }
487
+ async function runSanctuaryHealthAcceptanceProbe(input, dependencies = createSanctuaryHealthAcceptanceProbeDependencies()) {
488
+ canonicalInput(input);
489
+ const statePath = path.join(dependencies.agentRoot, "state", "health", "sanctuary-health.json");
490
+ const acceptanceRoot = path.join(dependencies.agentRoot, "state", "acceptance");
491
+ const workspace = path.join(acceptanceRoot, "health-probe-workspaces", input.scenarioHandleDigest);
492
+ const snapshotPath = path.join(workspace, "snapshot.json");
493
+ const checkpointPath = path.join(workspace, "checkpoint.json");
494
+ const receiptPath = path.join(acceptanceRoot, "health-probe-receipts", `${input.scenarioHandleDigest}.json`);
495
+ const pendingPath = path.join(acceptanceRoot, "health-probe-pending", `${input.scenarioHandleDigest}.json`);
496
+ if (fs.existsSync(workspace) || fs.existsSync(receiptPath) || fs.existsSync(pendingPath))
497
+ throw new Error("Sanctuary health acceptance probe requires inspect-before-retry");
498
+ fs.mkdirSync(workspace, { recursive: true, mode: 0o700 });
499
+ fs.chmodSync(workspace, 0o700);
500
+ const snapshot = snapshotState(statePath);
501
+ const beforeStateDigest = snapshotDigest(snapshot);
502
+ atomicPrivateFile(snapshotPath, `${JSON.stringify(snapshot)}\n`);
503
+ atomicPrivateFile(checkpointPath, `${JSON.stringify({ schemaVersion: 1, ownerImageDigest: input.ownerImageDigest, ownerContainerDigest: input.ownerContainerDigest })}\n`);
504
+ const cronPath = path.join(dependencies.runtimeRoot, "scheduler", "sanctuary.crontab");
505
+ const cronBefore = fs.readFileSync(cronPath, "utf8");
506
+ const cronFingerprintBefore = digestBytes(cronBefore);
507
+ const cronRegisteredBefore = canonicalCron(cronBefore);
508
+ const effectiveNow = input.label === "unit-16h-acceptance-delivery-probe" ? exactLocalDailyBoundary(dependencies.now()) : dependencies.now();
509
+ let fixture;
510
+ let expectedIncidentDigest = "";
511
+ let realCheckEquivalent = false;
512
+ let restoredStateDigest = "";
513
+ let socketAbsent = true;
514
+ const phases = [];
515
+ let providerInvocationCount = 0;
516
+ let privateTurnCount = 0;
517
+ let schedulerReceipt = null;
518
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_acceptance_start", message: "Sanctuary health acceptance probe started", meta: { label: input.label, scenarioHandleDigest: input.scenarioHandleDigest } });
519
+ try {
520
+ if (input.label === "unit-16f-cron-fingerprint") {
521
+ const initialCursor = cursorFromSnapshot(snapshot);
522
+ schedulerReceipt = await dependencies.waitForSchedulerReceipt(dependencies.agentRoot, input.scenarioHandleDigest);
523
+ const identityKey = dependencies.identityKey(dependencies.agentRoot);
524
+ if (!(0, sanctuary_scheduler_liveness_1.verifySanctuarySchedulerLivenessReceiptMac)(identityKey, schedulerReceipt)
525
+ || schedulerReceipt.schemaVersion !== "sanctuary-scheduler-liveness-receipt-v1" || schedulerReceipt.label !== input.label
526
+ || schedulerReceipt.scenarioHandleDigest !== input.scenarioHandleDigest || schedulerReceipt.trigger !== "cron"
527
+ || schedulerReceipt.before.sweepCount !== initialCursor.sweepCount || schedulerReceipt.before.deliveryCount !== initialCursor.deliveryCount
528
+ || schedulerReceipt.sweepDelta !== 1 || schedulerReceipt.deliveryDelta !== 0 || schedulerReceipt.providerInvocationCount !== 0
529
+ || schedulerReceipt.privateTurnCount !== 0 || schedulerReceipt.nonReplay !== true
530
+ || schedulerReceipt.schedulerOrigin.scenarioHandleDigest !== input.scenarioHandleDigest
531
+ || schedulerReceipt.schedulerOrigin.occurrenceId !== schedulerReceipt.occurrenceId
532
+ || schedulerReceipt.occurrenceId !== `cron:${schedulerReceipt.schedulerOrigin.slot}`) {
533
+ throw new Error("Sanctuary scheduler liveness receipt is invalid");
534
+ }
535
+ phases.push(phaseFromState(statePath, input.scenarioHandleDigest, 1, "cron-unchanged", "cron", null));
536
+ realCheckEquivalent = true;
537
+ restoredStateDigest = snapshotDigest(snapshotState(statePath));
538
+ }
539
+ else
540
+ await (0, sanctuary_health_1.withSanctuaryHealthStateLease)(statePath, async (lease) => {
541
+ expectedIncidentDigest = await normalizeWorkingState({ workspace, statePath, deps: dependencies, effectiveNow });
542
+ if (input.label === "unit-16h-acceptance-delivery-probe") {
543
+ const state = readHealthState(statePath);
544
+ state.incidents[`endpoint:${TARGET_ENDPOINT}`] = { id: `endpoint:${TARGET_ENDPOINT}`, summary: `${TARGET_ENDPOINT} returned 503` };
545
+ state.lastDigestDay = localDay(new Date(effectiveNow.getTime() - 36 * 60 * 60 * 1_000));
546
+ writeHealthState(statePath, state);
547
+ }
548
+ const runPhase = async (name, trigger, fixtureStatus, fetchImpl, now) => {
549
+ const sweep = (0, sanctuary_health_1.createSanctuaryHealthSweep)({
550
+ toolContext: dependencies.toolContext, statePath, fetch: fetchImpl, now: () => now, lease,
551
+ acceptanceEventMeta: () => ({ scenarioHandleDigest: input.scenarioHandleDigest }),
552
+ });
553
+ await (0, sanctuary_health_runner_1.runSanctuaryHealthHabit)("sanctuary", {
554
+ ...dependencies.runnerOptions,
555
+ createSweep: () => sweep,
556
+ acceptanceMetrics: {
557
+ onPrivateTurnStart: () => { privateTurnCount += 1; },
558
+ onProviderInvocation: () => { providerInvocationCount += 1; },
559
+ },
560
+ });
561
+ phases.push(phaseFromState(statePath, input.scenarioHandleDigest, phases.length + 1, name, trigger, fixtureStatus));
562
+ };
563
+ if (input.label === "unit-16g-health-transition") {
564
+ await runPhase("live-baseline", "acceptance", null, dependencies.ambientFetch, effectiveNow);
565
+ await runPhase("live-repeat", "acceptance", null, dependencies.ambientFetch, effectiveNow);
566
+ fixture = await createSanctuaryHealthAcceptanceLoopbackFixture([503, 503, 200, 503], dependencies.ambientFetch, dependencies.createLoopbackServer);
567
+ for (const [name, status] of [["fixture-fail", 503], ["fixture-repeat", 503], ["fixture-recover", 200], ["fixture-refail", 503]]) {
568
+ await runPhase(name, "acceptance", status, fixture.fetch, effectiveNow);
569
+ }
570
+ }
571
+ else {
572
+ fixture = await createSanctuaryHealthAcceptanceLoopbackFixture([503, 503], dependencies.ambientFetch, dependencies.createLoopbackServer);
573
+ await runPhase("delivery-probe-first", "acceptance", 503, fixture.fetch, effectiveNow);
574
+ await runPhase("delivery-probe-repeat", "acceptance", 503, fixture.fetch, effectiveNow);
575
+ }
576
+ await closeServer(fixture.server);
577
+ socketAbsent = fixture.server.address() === null;
578
+ restoreState(statePath, snapshot);
579
+ realCheckEquivalent = await verifyRealCheckEquivalent({ workspace, statePath, deps: dependencies, effectiveNow, expectedIncidentDigest });
580
+ restoreState(statePath, snapshot);
581
+ restoredStateDigest = snapshotDigest(snapshotState(statePath));
582
+ });
583
+ const cronAfter = fs.readFileSync(cronPath, "utf8");
584
+ const cronFingerprintAfter = digestBytes(cronAfter);
585
+ const cronRegisteredAfter = canonicalCron(cronAfter);
586
+ const observedFixtureSequence = fixture?.observed ?? [];
587
+ removeProbeWorkspace(workspace);
588
+ const receipt = {
589
+ schemaVersion: "sanctuary-health-probe-receipt-v1",
590
+ label: input.label,
591
+ scenarioHandleDigest: input.scenarioHandleDigest,
592
+ ownerImageDigestBefore: input.ownerImageDigest,
593
+ ownerImageDigestAfter: input.ownerImageDigest,
594
+ ownerContainerDigestBefore: input.ownerContainerDigest,
595
+ ownerContainerDigestAfter: input.ownerContainerDigest,
596
+ beforeStateDigest,
597
+ restoredStateDigest,
598
+ cronFingerprintBefore,
599
+ cronFingerprintAfter,
600
+ cronRegisteredBefore,
601
+ cronRegisteredAfter,
602
+ cronDegradedBefore: !cronRegisteredBefore,
603
+ cronDegradedAfter: !cronRegisteredAfter,
604
+ fixtureSequenceDigest: digestJson(observedFixtureSequence),
605
+ clockMode: input.label === "unit-16h-acceptance-delivery-probe" ? "local-daily-boundary" : "ambient",
606
+ effectiveNow: effectiveNow.toISOString(),
607
+ phases,
608
+ providerInvocationCount,
609
+ privateTurnCount,
610
+ deliveryCount: phases.filter((phase) => phase.deliveryReceiptDigest !== null).length,
611
+ workspaceAbsent: !fs.existsSync(workspace),
612
+ socketAbsent,
613
+ snapshotAbsent: !fs.existsSync(snapshotPath),
614
+ realCheckEquivalent,
615
+ productionRestored: beforeStateDigest === restoredStateDigest && cronFingerprintBefore === cronFingerprintAfter
616
+ && cronRegisteredBefore && cronRegisteredAfter && socketAbsent && realCheckEquivalent,
617
+ schedulerReceipt,
618
+ acceptanceOnly: true,
619
+ productionScheduleChanged: false,
620
+ };
621
+ if (input.label === "unit-16f-cron-fingerprint")
622
+ receipt.productionRestored = cronFingerprintBefore === cronFingerprintAfter
623
+ && cronRegisteredBefore && cronRegisteredAfter && socketAbsent && realCheckEquivalent && schedulerReceipt !== null;
624
+ if (dependencies.deferOwnerAttestation) {
625
+ atomicPrivateFile(pendingPath, `${JSON.stringify({ schemaVersion: "sanctuary-health-probe-pending-v1", receipt })}\n`);
626
+ }
627
+ else {
628
+ atomicPrivateFile(receiptPath, `${JSON.stringify(receipt)}\n`);
629
+ }
630
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_acceptance_end", message: "Sanctuary health acceptance probe completed", meta: { label: input.label, scenarioHandleDigest: input.scenarioHandleDigest, phaseCount: phases.length } });
631
+ return receipt;
632
+ }
633
+ catch (error) {
634
+ try {
635
+ if (fixture?.server.listening)
636
+ await closeServer(fixture.server);
637
+ }
638
+ catch { /* restoration remains authoritative */ }
639
+ if (input.label !== "unit-16f-cron-fingerprint")
640
+ try {
641
+ restoreState(statePath, snapshot);
642
+ }
643
+ catch { /* recovery checkpoint remains for the fixed recovery operation */ }
644
+ try {
645
+ removeProbeWorkspace(workspace);
646
+ }
647
+ catch { /* retain checkpoint for recovery */ }
648
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "senses", event: "senses.sanctuary_health_acceptance_error", message: "Sanctuary health acceptance probe failed", meta: { label: input.label, scenarioHandleDigest: input.scenarioHandleDigest, error: error instanceof Error ? error.message : String(error) } });
649
+ throw error;
650
+ }
651
+ }
652
+ function finalizeSanctuaryHealthAcceptanceProbe(input, after, dependencies = { agentRoot: (0, identity_1.getAgentRoot)("sanctuary") }) {
653
+ canonicalInput(input);
654
+ if (!SHA256.test(after.ownerImageDigest) || !SHA256.test(after.ownerContainerDigest))
655
+ throw new Error("Sanctuary health acceptance final owner is invalid");
656
+ const acceptanceRoot = path.join(dependencies.agentRoot, "state", "acceptance");
657
+ const pendingPath = path.join(acceptanceRoot, "health-probe-pending", `${input.scenarioHandleDigest}.json`);
658
+ const receiptPath = path.join(acceptanceRoot, "health-probe-receipts", `${input.scenarioHandleDigest}.json`);
659
+ const envelope = JSON.parse(fs.readFileSync(pendingPath, "utf8"));
660
+ const pending = envelope.receipt;
661
+ if (envelope.schemaVersion !== "sanctuary-health-probe-pending-v1" || !pending
662
+ || pending.label !== input.label || pending.scenarioHandleDigest !== input.scenarioHandleDigest
663
+ || pending.ownerImageDigestBefore !== input.ownerImageDigest || pending.ownerContainerDigestBefore !== input.ownerContainerDigest) {
664
+ throw new Error("Sanctuary health acceptance pending receipt binding is invalid");
665
+ }
666
+ const ownerStable = after.ownerImageDigest === input.ownerImageDigest && after.ownerContainerDigest === input.ownerContainerDigest;
667
+ if (!ownerStable)
668
+ throw new Error("Sanctuary health acceptance owner drifted");
669
+ const receipt = {
670
+ ...pending,
671
+ ownerImageDigestAfter: after.ownerImageDigest,
672
+ ownerContainerDigestAfter: after.ownerContainerDigest,
673
+ productionRestored: pending.productionRestored && ownerStable,
674
+ };
675
+ atomicPrivateFile(receiptPath, `${JSON.stringify(receipt)}\n`);
676
+ fs.unlinkSync(pendingPath);
677
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_acceptance_attested", message: "Sanctuary health acceptance owner continuity was attested", meta: { label: input.label, scenarioHandleDigest: input.scenarioHandleDigest } });
678
+ return receipt;
679
+ }
680
+ async function recoverSanctuaryHealthAcceptanceProbe(input, dependencies = createSanctuaryHealthAcceptanceProbeDependencies()) {
681
+ canonicalInput(input);
682
+ const statePath = path.join(dependencies.agentRoot, "state", "health", "sanctuary-health.json");
683
+ const pendingPath = path.join(dependencies.agentRoot, "state", "acceptance", "health-probe-pending", `${input.scenarioHandleDigest}.json`);
684
+ const workspace = path.join(dependencies.agentRoot, "state", "acceptance", "health-probe-workspaces", input.scenarioHandleDigest);
685
+ if (!fs.existsSync(workspace)) {
686
+ if (!fs.existsSync(pendingPath))
687
+ return { recovered: false };
688
+ const envelope = JSON.parse(fs.readFileSync(pendingPath, "utf8"));
689
+ if (!envelope.receipt || envelope.receipt.label !== input.label || envelope.receipt.scenarioHandleDigest !== input.scenarioHandleDigest
690
+ || envelope.receipt.ownerImageDigestBefore !== input.ownerImageDigest || envelope.receipt.ownerContainerDigestBefore !== input.ownerContainerDigest) {
691
+ throw new Error("Sanctuary health acceptance pending recovery binding is invalid");
692
+ }
693
+ fs.unlinkSync(pendingPath);
694
+ return { recovered: true };
695
+ }
696
+ const checkpoint = JSON.parse(fs.readFileSync(path.join(workspace, "checkpoint.json"), "utf8"));
697
+ if (checkpoint.schemaVersion !== 1 || checkpoint.ownerImageDigest !== input.ownerImageDigest || checkpoint.ownerContainerDigest !== input.ownerContainerDigest) {
698
+ throw new Error("Sanctuary health acceptance recovery owner binding is invalid");
699
+ }
700
+ const snapshot = JSON.parse(fs.readFileSync(path.join(workspace, "snapshot.json"), "utf8"));
701
+ if (input.label !== "unit-16f-cron-fingerprint")
702
+ await (0, sanctuary_health_1.withSanctuaryHealthStateLease)(statePath, async () => restoreState(statePath, snapshot));
703
+ removeProbeWorkspace(workspace);
704
+ if (fs.existsSync(pendingPath))
705
+ fs.unlinkSync(pendingPath);
706
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_health_acceptance_recovered", message: "Sanctuary health acceptance probe state was restored", meta: { label: input.label, scenarioHandleDigest: input.scenarioHandleDigest } });
707
+ return { recovered: true };
708
+ }
709
+ function parseCli(argv) {
710
+ if ((argv.length !== 9 && argv.length !== 13) || (argv[0] !== "run" && argv[0] !== "stop" && argv[0] !== "recover" && argv[0] !== "finalize")
711
+ || argv[1] !== "--label" || argv[3] !== "--scenario" || argv[5] !== "--owner-image" || argv[7] !== "--owner-container") {
712
+ throw new Error("usage: sanctuary-health-acceptance-probe <run|stop|recover|finalize> --label <label> --scenario <digest> --owner-image <digest> --owner-container <digest> [--owner-image-after <digest> --owner-container-after <digest>]");
713
+ }
714
+ const input = { label: argv[2], scenarioHandleDigest: argv[4], ownerImageDigest: argv[6], ownerContainerDigest: argv[8] };
715
+ canonicalInput(input);
716
+ if (argv[0] === "finalize") {
717
+ if (argv.length !== 13 || argv[9] !== "--owner-image-after" || argv[11] !== "--owner-container-after")
718
+ throw new Error("Sanctuary health acceptance finalize coordinates are invalid");
719
+ return { mode: argv[0], input, after: { ownerImageDigest: argv[10], ownerContainerDigest: argv[12] } };
720
+ }
721
+ if (argv.length !== 9)
722
+ throw new Error("Sanctuary health acceptance probe coordinates are invalid");
723
+ return { mode: argv[0], input };
724
+ }
725
+ function createSanctuaryHealthAcceptanceProbeCliHost(target = process) {
726
+ return {
727
+ pid: target.pid,
728
+ once: (signal, listener) => { target.once(signal, listener); },
729
+ removeListener: (signal, listener) => { target.removeListener(signal, listener); },
730
+ signalSelf: (signal) => { target.kill(target.pid, signal); },
731
+ };
732
+ }
733
+ async function runSanctuaryHealthAcceptanceProbeCli(argv, options = {}) {
734
+ const { mode, input, after } = parseCli(argv);
735
+ const host = options.host ?? createSanctuaryHealthAcceptanceProbeCliHost();
736
+ if (mode === "stop")
737
+ return stopSanctuaryHealthAcceptanceProbeProcess(input, options.processDependencies);
738
+ if (mode === "recover")
739
+ return recoverSanctuaryHealthAcceptanceProbe(input, options.dependencies);
740
+ if (mode === "finalize")
741
+ return finalizeSanctuaryHealthAcceptanceProbe(input, after, options.dependencies);
742
+ const dependencies = options.dependencies ?? createSanctuaryHealthAcceptanceProbeDependencies();
743
+ registerSanctuaryHealthAcceptanceProbeProcess(input, { agentRoot: dependencies.agentRoot, pid: host.pid });
744
+ const interrupted = (signal) => {
745
+ unregisterSanctuaryHealthAcceptanceProbeProcess(input, dependencies.agentRoot, host.pid);
746
+ host.removeListener("SIGTERM", onTerm);
747
+ host.removeListener("SIGINT", onInterrupt);
748
+ host.signalSelf(signal);
749
+ };
750
+ const onTerm = () => interrupted("SIGTERM");
751
+ const onInterrupt = () => interrupted("SIGINT");
752
+ host.once("SIGTERM", onTerm);
753
+ host.once("SIGINT", onInterrupt);
754
+ try {
755
+ return await runSanctuaryHealthAcceptanceProbe(input, dependencies);
756
+ }
757
+ finally {
758
+ host.removeListener("SIGTERM", onTerm);
759
+ host.removeListener("SIGINT", onInterrupt);
760
+ unregisterSanctuaryHealthAcceptanceProbeProcess(input, dependencies.agentRoot, host.pid);
761
+ }
762
+ }
763
+ function createSanctuaryHealthAcceptanceProbeCliOutput(target = process) {
764
+ return {
765
+ writeError: (message) => { target.stderr.write(message); },
766
+ setExitCode: (code) => { target.exitCode = code; },
767
+ };
768
+ }
769
+ function startSanctuaryHealthAcceptanceProbeCli(argv, output, options = {}) {
770
+ void runSanctuaryHealthAcceptanceProbeCli(argv, options).catch((error) => {
771
+ output.writeError(`${error instanceof Error ? error.message : String(error)}\n`);
772
+ output.setExitCode(1);
773
+ });
774
+ }