@ouro.bot/cli 0.1.0-alpha.80 → 0.1.0-alpha.801

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 (613) 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/changelog.json +5123 -16
  15. package/deploy/unraid/Dockerfile +48 -0
  16. package/deploy/unraid/README.txt +3012 -0
  17. package/deploy/unraid/audit-container-spec.sh +4 -0
  18. package/deploy/unraid/container-runtime.json +1 -0
  19. package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
  20. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  21. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  22. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  23. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  24. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  25. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  26. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  27. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  28. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  29. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  30. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  31. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  32. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2030 -0
  33. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  34. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  35. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  36. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  37. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  38. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  39. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  40. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  41. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +11 -0
  43. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +11 -0
  45. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  46. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  47. package/deploy/unraid/sanctuary.xml +27 -0
  48. package/dist/a2a/card.js +57 -0
  49. package/dist/a2a/client.js +180 -0
  50. package/dist/a2a/config.js +50 -0
  51. package/dist/a2a/delegation-stores.js +56 -0
  52. package/dist/a2a/did-resolution.js +93 -0
  53. package/dist/a2a/identity.js +170 -0
  54. package/dist/a2a/inbound-share.js +107 -0
  55. package/dist/a2a/mission-result-wire.js +196 -0
  56. package/dist/a2a/onboarding.js +115 -0
  57. package/dist/a2a/pin-store.js +132 -0
  58. package/dist/a2a/seen-ledger.js +120 -0
  59. package/dist/a2a/server.js +604 -0
  60. package/dist/a2a/task-store.js +69 -0
  61. package/dist/a2a/transport.js +45 -0
  62. package/dist/a2a/types.js +3 -0
  63. package/dist/arc/attention-types.js +8 -0
  64. package/dist/arc/cares.js +360 -0
  65. package/dist/arc/episodes.js +118 -0
  66. package/dist/arc/evolution.js +490 -0
  67. package/dist/arc/flight-recorder.js +1034 -0
  68. package/dist/arc/intentions.js +134 -0
  69. package/dist/arc/json-store.js +117 -0
  70. package/dist/arc/obligations.js +386 -0
  71. package/dist/arc/packets.js +336 -0
  72. package/dist/arc/presence.js +185 -0
  73. package/dist/arc/task-lifecycle.js +57 -0
  74. package/dist/commerce/store.js +755 -0
  75. package/dist/commerce/types.js +3 -0
  76. package/dist/heart/active-work.js +820 -29
  77. package/dist/heart/agent-entry.js +252 -3
  78. package/dist/heart/approval-files.js +113 -0
  79. package/dist/heart/approval-store.js +950 -0
  80. package/dist/heart/attachments/image-normalize.js +194 -0
  81. package/dist/heart/attachments/materialize.js +97 -0
  82. package/dist/heart/attachments/originals.js +88 -0
  83. package/dist/heart/attachments/render.js +29 -0
  84. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  85. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  86. package/dist/heart/attachments/sources/index.js +18 -0
  87. package/dist/heart/attachments/sources/telegram.js +71 -0
  88. package/dist/heart/attachments/store.js +132 -0
  89. package/dist/heart/attachments/types.js +93 -0
  90. package/dist/heart/auth/auth-flow.js +495 -0
  91. package/dist/heart/autonomy-budget.js +478 -0
  92. package/dist/heart/awaiting/await-alert.js +148 -0
  93. package/dist/heart/awaiting/await-expiry.js +143 -0
  94. package/dist/heart/awaiting/await-loader.js +91 -0
  95. package/dist/heart/awaiting/await-parser.js +149 -0
  96. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  97. package/dist/heart/awaiting/await-scheduler.js +382 -0
  98. package/dist/heart/background-operations.js +281 -0
  99. package/dist/heart/bridges/manager.js +137 -17
  100. package/dist/heart/bridges/store.js +14 -2
  101. package/dist/heart/bundle-state.js +168 -0
  102. package/dist/heart/commitments.js +64 -18
  103. package/dist/heart/config-registry.js +331 -0
  104. package/dist/heart/config.js +142 -129
  105. package/dist/heart/context-loss-gauntlet.js +387 -0
  106. package/dist/heart/context-loss-sentinel.js +1157 -0
  107. package/dist/heart/core.js +2132 -572
  108. package/dist/heart/cross-chat-delivery.js +9 -22
  109. package/dist/heart/daemon/agent-config-check.js +451 -0
  110. package/dist/heart/daemon/agent-discovery.js +185 -3
  111. package/dist/heart/daemon/agent-service.js +542 -0
  112. package/dist/heart/daemon/agentic-repair.js +547 -0
  113. package/dist/heart/daemon/await-private-wake.js +59 -0
  114. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  115. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  116. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  117. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  118. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  119. package/dist/heart/daemon/cadence.js +180 -0
  120. package/dist/heart/daemon/cli-defaults.js +836 -0
  121. package/dist/heart/daemon/cli-desk.js +322 -0
  122. package/dist/heart/daemon/cli-exec.js +8730 -0
  123. package/dist/heart/daemon/cli-help.js +710 -0
  124. package/dist/heart/daemon/cli-parse.js +2719 -0
  125. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  126. package/dist/heart/daemon/cli-render.js +777 -0
  127. package/dist/heart/daemon/cli-types.js +8 -0
  128. package/dist/heart/daemon/connect-bay.js +323 -0
  129. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  130. package/dist/heart/daemon/container-healthcheck.js +112 -0
  131. package/dist/heart/daemon/container-runtime.js +97 -0
  132. package/dist/heart/daemon/container-spec-auditor-main.js +170 -0
  133. package/dist/heart/daemon/container-spec-auditor.js +236 -0
  134. package/dist/heart/daemon/daemon-bootstrap-startup.js +107 -0
  135. package/dist/heart/daemon/daemon-cli.js +29 -2284
  136. package/dist/heart/daemon/daemon-entry.js +920 -11
  137. package/dist/heart/daemon/daemon-health.js +186 -0
  138. package/dist/heart/daemon/daemon-rollup.js +57 -0
  139. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  140. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  141. package/dist/heart/daemon/daemon.js +2010 -88
  142. package/dist/heart/daemon/dns-workflow.js +394 -0
  143. package/dist/heart/daemon/doctor-types.js +8 -0
  144. package/dist/heart/daemon/doctor.js +1755 -0
  145. package/dist/heart/daemon/freshness.js +345 -0
  146. package/dist/heart/daemon/habit-private-wake.js +61 -0
  147. package/dist/heart/daemon/health-monitor.js +142 -11
  148. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  149. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  150. package/dist/heart/daemon/http-health-probe.js +80 -0
  151. package/dist/heart/daemon/human-command-screens.js +234 -0
  152. package/dist/heart/daemon/human-readiness.js +114 -0
  153. package/dist/heart/daemon/inner-status.js +78 -0
  154. package/dist/heart/daemon/interactive-repair.js +394 -0
  155. package/dist/heart/daemon/launchd.js +37 -8
  156. package/dist/heart/daemon/log-tailer.js +79 -10
  157. package/dist/heart/daemon/logs-prune.js +132 -0
  158. package/dist/heart/daemon/mcp-canary.js +524 -0
  159. package/dist/heart/daemon/message-router.js +65 -5
  160. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  161. package/dist/heart/daemon/os-cron-deps.js +135 -0
  162. package/dist/heart/daemon/os-cron.js +22 -14
  163. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  164. package/dist/heart/daemon/ouro-entry.js +3 -1
  165. package/dist/heart/daemon/plugin-cli.js +432 -0
  166. package/dist/heart/daemon/process-manager.js +733 -61
  167. package/dist/heart/daemon/provider-discovery.js +137 -0
  168. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  169. package/dist/heart/daemon/prunable-bundle.js +144 -0
  170. package/dist/heart/daemon/pulse.js +511 -0
  171. package/dist/heart/daemon/readiness-repair.js +365 -0
  172. package/dist/heart/daemon/run-hooks.js +2 -0
  173. package/dist/heart/daemon/runtime-logging.js +47 -14
  174. package/dist/heart/daemon/runtime-metadata.js +2 -30
  175. package/dist/heart/daemon/runtime-mode.js +13 -2
  176. package/dist/heart/daemon/safe-mode.js +161 -0
  177. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2609 -0
  178. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1866 -0
  179. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  180. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +976 -0
  181. package/dist/heart/daemon/sanctuary-bundle-migration.js +728 -0
  182. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  183. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  184. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  185. package/dist/heart/daemon/sense-manager.js +689 -48
  186. package/dist/heart/daemon/session-id-resolver.js +131 -0
  187. package/dist/heart/daemon/skill-management-installer.js +1 -1
  188. package/dist/heart/daemon/socket-client.js +180 -12
  189. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  190. package/dist/heart/daemon/startup-tui.js +339 -0
  191. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  192. package/dist/heart/daemon/task-scheduler.js +117 -39
  193. package/dist/heart/daemon/terminal-ui.js +499 -0
  194. package/dist/heart/daemon/thoughts.js +138 -54
  195. package/dist/heart/daemon/up-progress.js +366 -0
  196. package/dist/heart/daemon/vault-items.js +56 -0
  197. package/dist/heart/delegation.js +1 -4
  198. package/dist/heart/external-events/router.js +1414 -0
  199. package/dist/heart/habits/habit-cancel.js +810 -0
  200. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  201. package/dist/heart/habits/habit-migration.js +194 -0
  202. package/dist/heart/habits/habit-parser.js +278 -0
  203. package/dist/heart/habits/habit-runtime-state.js +93 -0
  204. package/dist/heart/habits/habit-scheduler.js +653 -0
  205. package/dist/heart/habits/habit-session-summary.js +318 -0
  206. package/dist/heart/habits/habit-session.js +636 -0
  207. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  208. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  209. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  210. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  211. package/dist/heart/identity.js +184 -59
  212. package/dist/heart/kept-notes.js +289 -0
  213. package/dist/heart/kicks.js +1 -1
  214. package/dist/heart/machine-identity.js +161 -0
  215. package/dist/heart/mail-import-discovery.js +353 -0
  216. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  217. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  218. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  219. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  220. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  221. package/dist/heart/mailbox/mailbox-http.js +99 -0
  222. package/dist/heart/mailbox/mailbox-read.js +39 -0
  223. package/dist/heart/mailbox/mailbox-types.js +27 -0
  224. package/dist/heart/mailbox/mailbox-view.js +197 -0
  225. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  226. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  227. package/dist/heart/mailbox/readers/mail.js +375 -0
  228. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  229. package/dist/heart/mailbox/readers/sessions.js +232 -0
  230. package/dist/heart/mailbox/readers/shared.js +111 -0
  231. package/dist/heart/mcp/mcp-server.js +696 -0
  232. package/dist/heart/migrate-config.js +100 -0
  233. package/dist/heart/model-capabilities.js +11 -0
  234. package/dist/heart/orientation-frame.js +345 -0
  235. package/dist/heart/platform.js +81 -0
  236. package/dist/heart/primitives.js +1 -1
  237. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  238. package/dist/heart/private-runtime/index.js +18 -0
  239. package/dist/heart/private-runtime/ledger.js +221 -0
  240. package/dist/heart/private-runtime/policy.js +252 -0
  241. package/dist/heart/private-runtime/types.js +2 -0
  242. package/dist/heart/progress-story.js +1 -1
  243. package/dist/heart/provider-attempt.js +137 -0
  244. package/dist/heart/provider-binding-resolver.js +273 -0
  245. package/dist/heart/provider-credentials.js +449 -0
  246. package/dist/heart/provider-failover.js +311 -0
  247. package/dist/heart/provider-models.js +96 -0
  248. package/dist/heart/provider-ping.js +265 -0
  249. package/dist/heart/provider-readiness-cache.js +119 -0
  250. package/dist/heart/provider-visibility.js +188 -0
  251. package/dist/heart/providers/anthropic-token.js +131 -0
  252. package/dist/heart/providers/anthropic.js +173 -60
  253. package/dist/heart/providers/azure.js +23 -11
  254. package/dist/heart/providers/error-classification.js +127 -0
  255. package/dist/heart/providers/github-copilot.js +34 -38
  256. package/dist/heart/providers/minimax-vlm.js +189 -0
  257. package/dist/heart/providers/minimax.js +26 -8
  258. package/dist/heart/providers/openai-codex-token.js +349 -0
  259. package/dist/heart/providers/openai-codex.js +55 -40
  260. package/dist/heart/providers/openai-compatible.js +177 -0
  261. package/dist/heart/run-ledger.js +247 -0
  262. package/dist/heart/runtime-capability-check.js +170 -0
  263. package/dist/heart/runtime-credentials.js +607 -0
  264. package/dist/heart/runtime-cwd.js +87 -0
  265. package/dist/heart/sense-truth.js +22 -4
  266. package/dist/heart/session-activity.js +90 -24
  267. package/dist/heart/session-events.js +1318 -0
  268. package/dist/heart/session-playback-cli-main.js +5 -0
  269. package/dist/heart/session-playback-cli.js +36 -0
  270. package/dist/heart/session-playback.js +231 -0
  271. package/dist/heart/session-stats-cli-main.js +5 -0
  272. package/dist/heart/session-stats.js +182 -0
  273. package/dist/heart/session-transcript.js +133 -0
  274. package/dist/heart/start-of-turn-packet.js +372 -0
  275. package/dist/heart/steward-policy.js +302 -0
  276. package/dist/heart/streaming.js +604 -207
  277. package/dist/heart/structured-output.js +196 -0
  278. package/dist/heart/sync-classification.js +176 -0
  279. package/dist/heart/sync.js +449 -0
  280. package/dist/heart/target-resolution.js +11 -7
  281. package/dist/heart/tempo.js +93 -0
  282. package/dist/heart/temporal-view.js +41 -0
  283. package/dist/heart/timeouts.js +101 -0
  284. package/dist/heart/tool-activity-callbacks.js +59 -0
  285. package/dist/heart/tool-approval.js +342 -0
  286. package/dist/heart/tool-description.js +155 -0
  287. package/dist/heart/tool-friction.js +55 -0
  288. package/dist/heart/tool-loop.js +200 -0
  289. package/dist/heart/turn-context.js +481 -0
  290. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  291. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  292. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  293. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  294. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  295. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  296. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  297. package/dist/heart/versioning/update-hooks.js +154 -0
  298. package/dist/heart/versioning/version-intent.js +114 -0
  299. package/dist/heart/work-card.js +380 -0
  300. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  301. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  302. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  303. package/dist/mailbox-ui/index.html +16 -0
  304. package/dist/mailroom/attention.js +167 -0
  305. package/dist/mailroom/autonomy.js +209 -0
  306. package/dist/mailroom/blob-store.js +889 -0
  307. package/dist/mailroom/body-cache.js +61 -0
  308. package/dist/mailroom/cache-sync-cli.js +58 -0
  309. package/dist/mailroom/core.js +803 -0
  310. package/dist/mailroom/entry.js +160 -0
  311. package/dist/mailroom/file-store.js +568 -0
  312. package/dist/mailroom/hosted-cache-sync.js +384 -0
  313. package/dist/mailroom/mbox-import.js +393 -0
  314. package/dist/mailroom/migration.js +164 -0
  315. package/dist/mailroom/outbound.js +380 -0
  316. package/dist/mailroom/policy.js +263 -0
  317. package/dist/mailroom/reader.js +292 -0
  318. package/dist/mailroom/search-cache.js +513 -0
  319. package/dist/mailroom/search-relevance.js +319 -0
  320. package/dist/mailroom/smtp-ingress.js +176 -0
  321. package/dist/mailroom/source-state.js +176 -0
  322. package/dist/mailroom/thread.js +109 -0
  323. package/dist/mailroom/travel-extract.js +89 -0
  324. package/dist/mind/bundle-manifest.js +24 -2
  325. package/dist/mind/context.js +278 -111
  326. package/dist/mind/desk-section.js +362 -0
  327. package/dist/mind/diary-integrity.js +60 -0
  328. package/dist/mind/{memory.js → diary.js} +68 -77
  329. package/dist/mind/embedding-provider.js +60 -0
  330. package/dist/mind/file-state.js +179 -0
  331. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  332. package/dist/mind/obligation-steering.js +227 -0
  333. package/dist/mind/pending.js +34 -8
  334. package/dist/mind/prompt-budget.js +479 -0
  335. package/dist/mind/prompt-refresh.js +3 -2
  336. package/dist/mind/prompt.js +1056 -187
  337. package/dist/mind/provenance-trust.js +26 -0
  338. package/dist/mind/record-paths.js +312 -0
  339. package/dist/mind/scrutiny.js +173 -0
  340. package/dist/mind/session-transaction.js +415 -0
  341. package/dist/nerves/cli-logging.js +7 -1
  342. package/dist/nerves/coverage/audit-rules.js +15 -6
  343. package/dist/nerves/coverage/audit.js +28 -2
  344. package/dist/nerves/coverage/cli.js +1 -1
  345. package/dist/nerves/coverage/contract.js +5 -5
  346. package/dist/nerves/coverage/file-completeness.js +139 -5
  347. package/dist/nerves/coverage/run-artifacts.js +55 -35
  348. package/dist/nerves/coverage/source-scanner.js +4 -4
  349. package/dist/nerves/event-buffer.js +111 -0
  350. package/dist/nerves/index.js +293 -9
  351. package/dist/nerves/observation.js +20 -0
  352. package/dist/nerves/redact.js +79 -0
  353. package/dist/nerves/review/cli-main.js +5 -0
  354. package/dist/nerves/review/cli.js +156 -0
  355. package/dist/nerves/review/core.js +159 -0
  356. package/dist/nerves/runtime.js +17 -1
  357. package/dist/repertoire/ado-client.js +15 -56
  358. package/dist/repertoire/ado-semantic.js +16 -10
  359. package/dist/repertoire/api-client.js +97 -0
  360. package/dist/repertoire/bitwarden-store.js +1045 -0
  361. package/dist/repertoire/bundle-templates.js +71 -0
  362. package/dist/repertoire/bw-installer.js +180 -0
  363. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  364. package/dist/repertoire/coding/context-pack.js +331 -0
  365. package/dist/repertoire/coding/feedback.js +218 -30
  366. package/dist/repertoire/coding/index.js +15 -3
  367. package/dist/repertoire/coding/manager.js +166 -10
  368. package/dist/repertoire/coding/spawner.js +58 -11
  369. package/dist/repertoire/coding/tools.js +242 -14
  370. package/dist/repertoire/coding/workbench-client.js +272 -0
  371. package/dist/repertoire/coding/workbench-manager.js +346 -0
  372. package/dist/repertoire/commerce-errors.js +109 -0
  373. package/dist/repertoire/commerce-self-test.js +156 -0
  374. package/dist/repertoire/credential-access.js +178 -0
  375. package/dist/repertoire/desk/classifier.js +362 -0
  376. package/dist/repertoire/duffel-client.js +185 -0
  377. package/dist/repertoire/github-client.js +14 -55
  378. package/dist/repertoire/graph-client.js +11 -52
  379. package/dist/repertoire/guardrails.js +811 -18
  380. package/dist/repertoire/mcp-client.js +44 -3
  381. package/dist/repertoire/mcp-manager.js +259 -20
  382. package/dist/repertoire/mcp-tools.js +83 -0
  383. package/dist/repertoire/plugin-mcp.js +175 -0
  384. package/dist/repertoire/plugins.js +253 -0
  385. package/dist/repertoire/relationship-authorization.js +194 -0
  386. package/dist/repertoire/shell-sessions.js +133 -0
  387. package/dist/repertoire/skills.js +48 -4
  388. package/dist/repertoire/stripe-client.js +131 -0
  389. package/dist/repertoire/tool-arguments.js +148 -0
  390. package/dist/repertoire/tool-results.js +29 -0
  391. package/dist/repertoire/tools-a2a.js +699 -0
  392. package/dist/repertoire/tools-attachments.js +322 -0
  393. package/dist/repertoire/tools-awaiting.js +575 -0
  394. package/dist/repertoire/tools-base.js +82 -1139
  395. package/dist/repertoire/tools-bluebubbles.js +2 -0
  396. package/dist/repertoire/tools-bridge.js +144 -0
  397. package/dist/repertoire/tools-bundle.js +993 -0
  398. package/dist/repertoire/tools-commerce.js +253 -0
  399. package/dist/repertoire/tools-config.js +186 -0
  400. package/dist/repertoire/tools-continuity.js +575 -0
  401. package/dist/repertoire/tools-credential.js +383 -0
  402. package/dist/repertoire/tools-evolution.js +527 -0
  403. package/dist/repertoire/tools-files.js +344 -0
  404. package/dist/repertoire/tools-flight.js +290 -0
  405. package/dist/repertoire/tools-flow.js +119 -0
  406. package/dist/repertoire/tools-github.js +3 -8
  407. package/dist/repertoire/tools-habits.js +103 -0
  408. package/dist/repertoire/tools-mail.js +1828 -0
  409. package/dist/repertoire/tools-notes.js +485 -0
  410. package/dist/repertoire/tools-obligations.js +182 -0
  411. package/dist/repertoire/tools-orientation.js +31 -0
  412. package/dist/repertoire/tools-record.js +482 -0
  413. package/dist/repertoire/tools-rsvp.js +139 -0
  414. package/dist/repertoire/tools-runtime.js +150 -0
  415. package/dist/repertoire/tools-session.js +1108 -0
  416. package/dist/repertoire/tools-shell.js +133 -0
  417. package/dist/repertoire/tools-steward-policy.js +95 -0
  418. package/dist/repertoire/tools-stripe.js +224 -0
  419. package/dist/repertoire/tools-surface.js +369 -0
  420. package/dist/repertoire/tools-teams.js +12 -39
  421. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  422. package/dist/repertoire/tools-travel.js +125 -0
  423. package/dist/repertoire/tools-trip.js +982 -0
  424. package/dist/repertoire/tools-unraid.js +484 -0
  425. package/dist/repertoire/tools-user-profile.js +146 -0
  426. package/dist/repertoire/tools-vault.js +40 -0
  427. package/dist/repertoire/tools-voice.js +145 -0
  428. package/dist/repertoire/tools.js +377 -80
  429. package/dist/repertoire/travel-api-client.js +360 -0
  430. package/dist/repertoire/unraid-client.js +155 -0
  431. package/dist/repertoire/unraid-restart.js +212 -0
  432. package/dist/repertoire/user-profile.js +131 -0
  433. package/dist/repertoire/vault-setup.js +246 -0
  434. package/dist/repertoire/vault-unlock.js +628 -0
  435. package/dist/rsvp/aisleplanner-client.js +354 -0
  436. package/dist/rsvp/cli.js +926 -0
  437. package/dist/rsvp/config.js +327 -0
  438. package/dist/rsvp/cutover.js +433 -0
  439. package/dist/rsvp/diagnostics.js +232 -0
  440. package/dist/rsvp/diff-renderer.js +176 -0
  441. package/dist/rsvp/habit-policy.js +110 -0
  442. package/dist/rsvp/habit-stage.js +123 -0
  443. package/dist/rsvp/incident-bundle.js +97 -0
  444. package/dist/rsvp/migration.js +204 -0
  445. package/dist/rsvp/native-habit-runner.js +630 -0
  446. package/dist/rsvp/outbound-state.js +628 -0
  447. package/dist/rsvp/query.js +118 -0
  448. package/dist/rsvp/replay.js +233 -0
  449. package/dist/rsvp/snapshot.js +232 -0
  450. package/dist/rsvp/spend-ledger.js +175 -0
  451. package/dist/scripts/claude-code-hook.js +41 -0
  452. package/dist/scripts/claude-code-stop-hook.js +47 -0
  453. package/dist/senses/a2a-entry.js +115 -0
  454. package/dist/senses/attention-queue.js +186 -0
  455. package/dist/senses/await-turn-message.js +58 -0
  456. package/dist/senses/bluebubbles/active-turns.js +216 -0
  457. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  458. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  459. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  460. package/dist/senses/bluebubbles/context-packet.js +207 -0
  461. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  462. package/dist/senses/bluebubbles/entry.js +90 -0
  463. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  464. package/dist/senses/bluebubbles/index.js +3839 -0
  465. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  466. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  467. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  468. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  469. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  470. package/dist/senses/bluebubbles/processed-log.js +133 -0
  471. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  472. package/dist/senses/bluebubbles/replay.js +284 -0
  473. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  474. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  475. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  476. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  477. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  478. package/dist/senses/cli/bracketed-paste.js +82 -0
  479. package/dist/senses/cli/image-paste.js +287 -0
  480. package/dist/senses/cli/image-ref-navigation.js +75 -0
  481. package/dist/senses/cli/ink-app.js +156 -0
  482. package/dist/senses/cli/inline-diff.js +64 -0
  483. package/dist/senses/cli/input-keys.js +174 -0
  484. package/dist/senses/cli/kill-ring.js +86 -0
  485. package/dist/senses/cli/message-list.js +51 -0
  486. package/dist/senses/cli/ouro-tui.js +607 -0
  487. package/dist/senses/cli/spinner-imperative.js +135 -0
  488. package/dist/senses/cli/spinner.js +101 -0
  489. package/dist/senses/cli/status-line.js +60 -0
  490. package/dist/senses/cli/streaming-markdown.js +526 -0
  491. package/dist/senses/cli/tool-display.js +85 -0
  492. package/dist/senses/cli/tool-render.js +85 -0
  493. package/dist/senses/cli/tui-store.js +241 -0
  494. package/dist/senses/cli/virtual-list.js +35 -0
  495. package/dist/senses/cli-entry.js +60 -8
  496. package/dist/senses/cli.js +600 -317
  497. package/dist/senses/commands.js +66 -3
  498. package/dist/senses/context-packet-ledger.js +371 -0
  499. package/dist/senses/context-packets.js +154 -0
  500. package/dist/senses/habit-lifecycle-guard.js +24 -0
  501. package/dist/senses/habit-turn-message.js +160 -0
  502. package/dist/senses/ingress-evidence.js +2 -0
  503. package/dist/senses/mail-entry.js +66 -0
  504. package/dist/senses/mail.js +524 -0
  505. package/dist/senses/pipeline.js +1110 -204
  506. package/dist/senses/private-runtime-worker.js +859 -0
  507. package/dist/senses/private-runtime.js +1496 -0
  508. package/dist/senses/proactive-content-guard.js +51 -0
  509. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  510. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  511. package/dist/senses/sanctuary-grounding.js +118 -0
  512. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  513. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  514. package/dist/senses/sanctuary-health-runner.js +101 -0
  515. package/dist/senses/sanctuary-health.js +408 -0
  516. package/dist/senses/sanctuary-interactive-control.js +306 -0
  517. package/dist/senses/sanctuary-media-catalog-contract.js +235 -0
  518. package/dist/senses/sanctuary-media-optimization.js +514 -0
  519. package/dist/senses/sanctuary-runtime.js +338 -0
  520. package/dist/senses/sanctuary-sab.js +85 -0
  521. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  522. package/dist/senses/shared-turn.js +571 -0
  523. package/dist/senses/surface-tool.js +109 -0
  524. package/dist/senses/teams-entry.js +60 -8
  525. package/dist/senses/teams.js +515 -217
  526. package/dist/senses/telegram-admission.js +711 -0
  527. package/dist/senses/telegram-approval-runtime.js +566 -0
  528. package/dist/senses/telegram-attachments.js +182 -0
  529. package/dist/senses/telegram-audit-ledger.js +220 -0
  530. package/dist/senses/telegram-client.js +1677 -0
  531. package/dist/senses/telegram-effect-adapter.js +859 -0
  532. package/dist/senses/telegram-entry.js +83 -0
  533. package/dist/senses/telegram.js +2031 -0
  534. package/dist/senses/trust-gate.js +104 -9
  535. package/dist/senses/voice/audio-playback.js +237 -0
  536. package/dist/senses/voice/audio-routing.js +119 -0
  537. package/dist/senses/voice/elevenlabs.js +202 -0
  538. package/dist/senses/voice/floor-control.js +431 -0
  539. package/dist/senses/voice/floor-controller.js +115 -0
  540. package/dist/senses/voice/golden-path.js +116 -0
  541. package/dist/senses/voice/index.js +29 -0
  542. package/dist/senses/voice/meeting.js +113 -0
  543. package/dist/senses/voice/outbound.js +190 -0
  544. package/dist/senses/voice/phone.js +33 -0
  545. package/dist/senses/voice/playback.js +139 -0
  546. package/dist/senses/voice/realtime-eval.js +496 -0
  547. package/dist/senses/voice/realtime-trace.js +531 -0
  548. package/dist/senses/voice/transcript.js +70 -0
  549. package/dist/senses/voice/turn.js +191 -0
  550. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  551. package/dist/senses/voice/twilio-phone.js +5081 -0
  552. package/dist/senses/voice/types.js +2 -0
  553. package/dist/senses/voice/whisper.js +161 -0
  554. package/dist/senses/voice-entry.js +81 -0
  555. package/dist/senses/voice-realtime-eval-command.js +99 -0
  556. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  557. package/dist/senses/voice-twilio-entry.js +87 -0
  558. package/dist/trips/core.js +138 -0
  559. package/dist/trips/store.js +265 -0
  560. package/dist/util/frontmatter.js +69 -0
  561. package/npm-shrinkwrap.json +8144 -0
  562. package/package.json +72 -13
  563. package/skills/agent-commerce.md +113 -0
  564. package/skills/browser-navigation.md +117 -0
  565. package/skills/commerce-setup-guide.md +116 -0
  566. package/skills/commerce-setup.md +84 -0
  567. package/skills/configure-dev-tools.md +99 -0
  568. package/skills/travel-planning.md +138 -0
  569. package/dist/heart/daemon/auth-flow.js +0 -430
  570. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  571. package/dist/heart/daemon/ouro-version-manager.js +0 -164
  572. package/dist/heart/daemon/update-hooks.js +0 -138
  573. package/dist/heart/obligations.js +0 -141
  574. package/dist/heart/safe-workspace.js +0 -228
  575. package/dist/heart/session-recall.js +0 -116
  576. package/dist/mind/friends/channel.js +0 -84
  577. package/dist/mind/friends/group-context.js +0 -144
  578. package/dist/mind/friends/resolver.js +0 -84
  579. package/dist/mind/friends/store-file.js +0 -190
  580. package/dist/mind/friends/store.js +0 -4
  581. package/dist/mind/friends/tokens.js +0 -26
  582. package/dist/mind/friends/trust-explanation.js +0 -74
  583. package/dist/mind/friends/types.js +0 -29
  584. package/dist/repertoire/tasks/board.js +0 -134
  585. package/dist/repertoire/tasks/index.js +0 -224
  586. package/dist/repertoire/tasks/lifecycle.js +0 -80
  587. package/dist/repertoire/tasks/middleware.js +0 -65
  588. package/dist/repertoire/tasks/parser.js +0 -173
  589. package/dist/repertoire/tasks/scanner.js +0 -132
  590. package/dist/repertoire/tasks/transitions.js +0 -144
  591. package/dist/senses/bluebubbles-entry.js +0 -13
  592. package/dist/senses/bluebubbles.js +0 -1181
  593. package/dist/senses/debug-activity.js +0 -154
  594. package/dist/senses/inner-dialog-worker.js +0 -90
  595. package/dist/senses/inner-dialog.js +0 -525
  596. package/subagents/README.md +0 -7
  597. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  598. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  599. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  600. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  601. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  602. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  603. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  604. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  605. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  606. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  607. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  608. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  609. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  610. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  611. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  612. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  613. /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
+ }