@ouro.bot/cli 0.1.0-alpha.78 → 0.1.0-alpha.781

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 (608) 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 +5000 -17
  15. package/deploy/unraid/Dockerfile +48 -0
  16. package/deploy/unraid/README.txt +2523 -0
  17. package/deploy/unraid/audit-container-spec.sh +4 -0
  18. package/deploy/unraid/container-runtime.json +1 -0
  19. package/deploy/unraid/migrate-sanctuary-bundle.mjs +21 -0
  20. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  21. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  22. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  23. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  24. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  25. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  26. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  27. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  28. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  29. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  30. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2030 -0
  31. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  32. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  33. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  34. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  35. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  36. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  37. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  38. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  39. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  40. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +9 -0
  41. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +9 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +10 -0
  43. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  44. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  45. package/deploy/unraid/sanctuary.xml +27 -0
  46. package/dist/a2a/card.js +57 -0
  47. package/dist/a2a/client.js +180 -0
  48. package/dist/a2a/config.js +50 -0
  49. package/dist/a2a/delegation-stores.js +56 -0
  50. package/dist/a2a/did-resolution.js +93 -0
  51. package/dist/a2a/identity.js +170 -0
  52. package/dist/a2a/inbound-share.js +107 -0
  53. package/dist/a2a/mission-result-wire.js +196 -0
  54. package/dist/a2a/onboarding.js +115 -0
  55. package/dist/a2a/pin-store.js +132 -0
  56. package/dist/a2a/seen-ledger.js +120 -0
  57. package/dist/a2a/server.js +604 -0
  58. package/dist/a2a/task-store.js +69 -0
  59. package/dist/a2a/transport.js +45 -0
  60. package/dist/a2a/types.js +3 -0
  61. package/dist/arc/attention-types.js +8 -0
  62. package/dist/arc/cares.js +360 -0
  63. package/dist/arc/episodes.js +118 -0
  64. package/dist/arc/evolution.js +490 -0
  65. package/dist/arc/flight-recorder.js +1034 -0
  66. package/dist/arc/intentions.js +134 -0
  67. package/dist/arc/json-store.js +117 -0
  68. package/dist/arc/obligations.js +386 -0
  69. package/dist/arc/packets.js +336 -0
  70. package/dist/arc/presence.js +185 -0
  71. package/dist/arc/task-lifecycle.js +57 -0
  72. package/dist/commerce/store.js +755 -0
  73. package/dist/commerce/types.js +3 -0
  74. package/dist/heart/active-work.js +820 -29
  75. package/dist/heart/agent-entry.js +253 -3
  76. package/dist/heart/approval-files.js +113 -0
  77. package/dist/heart/approval-store.js +950 -0
  78. package/dist/heart/attachments/image-normalize.js +194 -0
  79. package/dist/heart/attachments/materialize.js +97 -0
  80. package/dist/heart/attachments/originals.js +88 -0
  81. package/dist/heart/attachments/render.js +29 -0
  82. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  83. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  84. package/dist/heart/attachments/sources/index.js +18 -0
  85. package/dist/heart/attachments/sources/telegram.js +71 -0
  86. package/dist/heart/attachments/store.js +132 -0
  87. package/dist/heart/attachments/types.js +93 -0
  88. package/dist/heart/auth/auth-flow.js +495 -0
  89. package/dist/heart/autonomy-budget.js +478 -0
  90. package/dist/heart/awaiting/await-alert.js +148 -0
  91. package/dist/heart/awaiting/await-expiry.js +143 -0
  92. package/dist/heart/awaiting/await-loader.js +91 -0
  93. package/dist/heart/awaiting/await-parser.js +149 -0
  94. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  95. package/dist/heart/awaiting/await-scheduler.js +382 -0
  96. package/dist/heart/background-operations.js +281 -0
  97. package/dist/heart/bridges/manager.js +137 -17
  98. package/dist/heart/bridges/store.js +14 -2
  99. package/dist/heart/bundle-state.js +168 -0
  100. package/dist/heart/commitments.js +64 -18
  101. package/dist/heart/config-registry.js +331 -0
  102. package/dist/heart/config.js +128 -129
  103. package/dist/heart/context-loss-gauntlet.js +387 -0
  104. package/dist/heart/context-loss-sentinel.js +1157 -0
  105. package/dist/heart/core.js +2014 -469
  106. package/dist/heart/cross-chat-delivery.js +9 -22
  107. package/dist/heart/daemon/agent-config-check.js +451 -0
  108. package/dist/heart/daemon/agent-discovery.js +185 -3
  109. package/dist/heart/daemon/agent-service.js +542 -0
  110. package/dist/heart/daemon/agentic-repair.js +547 -0
  111. package/dist/heart/daemon/await-private-wake.js +59 -0
  112. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  113. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  114. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  115. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  116. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  117. package/dist/heart/daemon/cadence.js +180 -0
  118. package/dist/heart/daemon/cli-defaults.js +836 -0
  119. package/dist/heart/daemon/cli-desk.js +322 -0
  120. package/dist/heart/daemon/cli-exec.js +8730 -0
  121. package/dist/heart/daemon/cli-help.js +710 -0
  122. package/dist/heart/daemon/cli-parse.js +2719 -0
  123. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  124. package/dist/heart/daemon/cli-render.js +777 -0
  125. package/dist/heart/daemon/cli-types.js +8 -0
  126. package/dist/heart/daemon/connect-bay.js +323 -0
  127. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  128. package/dist/heart/daemon/container-healthcheck.js +96 -0
  129. package/dist/heart/daemon/container-runtime.js +97 -0
  130. package/dist/heart/daemon/container-spec-auditor-main.js +160 -0
  131. package/dist/heart/daemon/container-spec-auditor.js +176 -0
  132. package/dist/heart/daemon/daemon-bootstrap-startup.js +77 -0
  133. package/dist/heart/daemon/daemon-cli.js +29 -2181
  134. package/dist/heart/daemon/daemon-entry.js +907 -10
  135. package/dist/heart/daemon/daemon-health.js +186 -0
  136. package/dist/heart/daemon/daemon-rollup.js +57 -0
  137. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  138. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  139. package/dist/heart/daemon/daemon.js +1988 -88
  140. package/dist/heart/daemon/dns-workflow.js +394 -0
  141. package/dist/heart/daemon/doctor-types.js +8 -0
  142. package/dist/heart/daemon/doctor.js +1755 -0
  143. package/dist/heart/daemon/freshness.js +345 -0
  144. package/dist/heart/daemon/habit-private-wake.js +61 -0
  145. package/dist/heart/daemon/health-monitor.js +142 -11
  146. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  147. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  148. package/dist/heart/daemon/http-health-probe.js +80 -0
  149. package/dist/heart/daemon/human-command-screens.js +234 -0
  150. package/dist/heart/daemon/human-readiness.js +114 -0
  151. package/dist/heart/daemon/inner-status.js +78 -0
  152. package/dist/heart/daemon/interactive-repair.js +394 -0
  153. package/dist/heart/daemon/launchd.js +37 -8
  154. package/dist/heart/daemon/log-tailer.js +79 -10
  155. package/dist/heart/daemon/logs-prune.js +132 -0
  156. package/dist/heart/daemon/mcp-canary.js +524 -0
  157. package/dist/heart/daemon/message-router.js +45 -5
  158. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  159. package/dist/heart/daemon/os-cron-deps.js +135 -0
  160. package/dist/heart/daemon/os-cron.js +22 -14
  161. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  162. package/dist/heart/daemon/ouro-entry.js +3 -1
  163. package/dist/heart/daemon/plugin-cli.js +432 -0
  164. package/dist/heart/daemon/process-manager.js +733 -61
  165. package/dist/heart/daemon/provider-discovery.js +137 -0
  166. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  167. package/dist/heart/daemon/prunable-bundle.js +144 -0
  168. package/dist/heart/daemon/pulse.js +511 -0
  169. package/dist/heart/daemon/readiness-repair.js +365 -0
  170. package/dist/heart/daemon/run-hooks.js +2 -0
  171. package/dist/heart/daemon/runtime-logging.js +47 -14
  172. package/dist/heart/daemon/runtime-metadata.js +2 -30
  173. package/dist/heart/daemon/runtime-mode.js +13 -2
  174. package/dist/heart/daemon/safe-mode.js +161 -0
  175. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2609 -0
  176. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1866 -0
  177. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  178. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +976 -0
  179. package/dist/heart/daemon/sanctuary-bundle-migration.js +398 -0
  180. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  181. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  182. package/dist/heart/daemon/sense-manager.js +689 -48
  183. package/dist/heart/daemon/session-id-resolver.js +131 -0
  184. package/dist/heart/daemon/skill-management-installer.js +1 -1
  185. package/dist/heart/daemon/socket-client.js +180 -12
  186. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  187. package/dist/heart/daemon/startup-tui.js +339 -0
  188. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  189. package/dist/heart/daemon/task-scheduler.js +117 -39
  190. package/dist/heart/daemon/terminal-ui.js +499 -0
  191. package/dist/heart/daemon/thoughts.js +138 -54
  192. package/dist/heart/daemon/up-progress.js +366 -0
  193. package/dist/heart/daemon/vault-items.js +56 -0
  194. package/dist/heart/delegation.js +1 -4
  195. package/dist/heart/external-events/router.js +1414 -0
  196. package/dist/heart/habits/habit-cancel.js +810 -0
  197. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  198. package/dist/heart/habits/habit-migration.js +194 -0
  199. package/dist/heart/habits/habit-parser.js +278 -0
  200. package/dist/heart/habits/habit-runtime-state.js +93 -0
  201. package/dist/heart/habits/habit-scheduler.js +653 -0
  202. package/dist/heart/habits/habit-session-summary.js +318 -0
  203. package/dist/heart/habits/habit-session.js +636 -0
  204. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  205. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  206. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  207. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  208. package/dist/heart/identity.js +184 -59
  209. package/dist/heart/kept-notes.js +289 -0
  210. package/dist/heart/kicks.js +1 -1
  211. package/dist/heart/machine-identity.js +161 -0
  212. package/dist/heart/mail-import-discovery.js +353 -0
  213. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  214. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  215. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  216. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  217. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  218. package/dist/heart/mailbox/mailbox-http.js +99 -0
  219. package/dist/heart/mailbox/mailbox-read.js +39 -0
  220. package/dist/heart/mailbox/mailbox-types.js +27 -0
  221. package/dist/heart/mailbox/mailbox-view.js +197 -0
  222. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  223. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  224. package/dist/heart/mailbox/readers/mail.js +375 -0
  225. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  226. package/dist/heart/mailbox/readers/sessions.js +232 -0
  227. package/dist/heart/mailbox/readers/shared.js +111 -0
  228. package/dist/heart/mcp/mcp-server.js +696 -0
  229. package/dist/heart/migrate-config.js +100 -0
  230. package/dist/heart/model-capabilities.js +11 -0
  231. package/dist/heart/orientation-frame.js +345 -0
  232. package/dist/heart/platform.js +81 -0
  233. package/dist/heart/primitives.js +1 -1
  234. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  235. package/dist/heart/private-runtime/index.js +18 -0
  236. package/dist/heart/private-runtime/ledger.js +221 -0
  237. package/dist/heart/private-runtime/policy.js +228 -0
  238. package/dist/heart/private-runtime/types.js +2 -0
  239. package/dist/heart/progress-story.js +1 -1
  240. package/dist/heart/provider-attempt.js +137 -0
  241. package/dist/heart/provider-binding-resolver.js +273 -0
  242. package/dist/heart/provider-credentials.js +449 -0
  243. package/dist/heart/provider-failover.js +311 -0
  244. package/dist/heart/provider-models.js +96 -0
  245. package/dist/heart/provider-ping.js +265 -0
  246. package/dist/heart/provider-readiness-cache.js +119 -0
  247. package/dist/heart/provider-visibility.js +188 -0
  248. package/dist/heart/providers/anthropic-token.js +131 -0
  249. package/dist/heart/providers/anthropic.js +173 -60
  250. package/dist/heart/providers/azure.js +23 -11
  251. package/dist/heart/providers/error-classification.js +127 -0
  252. package/dist/heart/providers/github-copilot.js +34 -38
  253. package/dist/heart/providers/minimax-vlm.js +189 -0
  254. package/dist/heart/providers/minimax.js +26 -8
  255. package/dist/heart/providers/openai-codex-token.js +349 -0
  256. package/dist/heart/providers/openai-codex.js +55 -40
  257. package/dist/heart/providers/openai-compatible.js +177 -0
  258. package/dist/heart/run-ledger.js +247 -0
  259. package/dist/heart/runtime-capability-check.js +170 -0
  260. package/dist/heart/runtime-credentials.js +607 -0
  261. package/dist/heart/runtime-cwd.js +87 -0
  262. package/dist/heart/sense-truth.js +22 -4
  263. package/dist/heart/session-activity.js +90 -24
  264. package/dist/heart/session-events.js +1318 -0
  265. package/dist/heart/session-playback-cli-main.js +5 -0
  266. package/dist/heart/session-playback-cli.js +36 -0
  267. package/dist/heart/session-playback.js +231 -0
  268. package/dist/heart/session-stats-cli-main.js +5 -0
  269. package/dist/heart/session-stats.js +182 -0
  270. package/dist/heart/session-transcript.js +133 -0
  271. package/dist/heart/start-of-turn-packet.js +372 -0
  272. package/dist/heart/steward-policy.js +302 -0
  273. package/dist/heart/streaming.js +604 -207
  274. package/dist/heart/structured-output.js +196 -0
  275. package/dist/heart/sync-classification.js +176 -0
  276. package/dist/heart/sync.js +449 -0
  277. package/dist/heart/target-resolution.js +11 -7
  278. package/dist/heart/tempo.js +93 -0
  279. package/dist/heart/temporal-view.js +41 -0
  280. package/dist/heart/timeouts.js +101 -0
  281. package/dist/heart/tool-activity-callbacks.js +59 -0
  282. package/dist/heart/tool-approval.js +342 -0
  283. package/dist/heart/tool-description.js +155 -0
  284. package/dist/heart/tool-friction.js +55 -0
  285. package/dist/heart/tool-loop.js +200 -0
  286. package/dist/heart/turn-context.js +481 -0
  287. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  288. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  289. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  290. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  291. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  292. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  293. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  294. package/dist/heart/versioning/update-hooks.js +154 -0
  295. package/dist/heart/versioning/version-intent.js +114 -0
  296. package/dist/heart/work-card.js +380 -0
  297. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  298. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  299. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  300. package/dist/mailbox-ui/index.html +16 -0
  301. package/dist/mailroom/attention.js +167 -0
  302. package/dist/mailroom/autonomy.js +209 -0
  303. package/dist/mailroom/blob-store.js +889 -0
  304. package/dist/mailroom/body-cache.js +61 -0
  305. package/dist/mailroom/cache-sync-cli.js +58 -0
  306. package/dist/mailroom/core.js +803 -0
  307. package/dist/mailroom/entry.js +160 -0
  308. package/dist/mailroom/file-store.js +568 -0
  309. package/dist/mailroom/hosted-cache-sync.js +384 -0
  310. package/dist/mailroom/mbox-import.js +393 -0
  311. package/dist/mailroom/migration.js +164 -0
  312. package/dist/mailroom/outbound.js +380 -0
  313. package/dist/mailroom/policy.js +263 -0
  314. package/dist/mailroom/reader.js +292 -0
  315. package/dist/mailroom/search-cache.js +513 -0
  316. package/dist/mailroom/search-relevance.js +319 -0
  317. package/dist/mailroom/smtp-ingress.js +176 -0
  318. package/dist/mailroom/source-state.js +176 -0
  319. package/dist/mailroom/thread.js +109 -0
  320. package/dist/mailroom/travel-extract.js +89 -0
  321. package/dist/mind/bundle-manifest.js +24 -2
  322. package/dist/mind/context.js +278 -111
  323. package/dist/mind/desk-section.js +362 -0
  324. package/dist/mind/diary-integrity.js +60 -0
  325. package/dist/mind/{memory.js → diary.js} +68 -77
  326. package/dist/mind/embedding-provider.js +60 -0
  327. package/dist/mind/file-state.js +179 -0
  328. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  329. package/dist/mind/obligation-steering.js +227 -0
  330. package/dist/mind/pending.js +34 -8
  331. package/dist/mind/prompt-budget.js +479 -0
  332. package/dist/mind/prompt-refresh.js +3 -2
  333. package/dist/mind/prompt.js +1058 -187
  334. package/dist/mind/provenance-trust.js +26 -0
  335. package/dist/mind/record-paths.js +312 -0
  336. package/dist/mind/scrutiny.js +173 -0
  337. package/dist/mind/session-transaction.js +415 -0
  338. package/dist/nerves/cli-logging.js +7 -1
  339. package/dist/nerves/coverage/audit-rules.js +15 -6
  340. package/dist/nerves/coverage/audit.js +28 -2
  341. package/dist/nerves/coverage/cli.js +1 -1
  342. package/dist/nerves/coverage/contract.js +5 -5
  343. package/dist/nerves/coverage/file-completeness.js +139 -5
  344. package/dist/nerves/coverage/run-artifacts.js +55 -35
  345. package/dist/nerves/coverage/source-scanner.js +4 -4
  346. package/dist/nerves/event-buffer.js +111 -0
  347. package/dist/nerves/index.js +293 -9
  348. package/dist/nerves/observation.js +20 -0
  349. package/dist/nerves/redact.js +79 -0
  350. package/dist/nerves/review/cli-main.js +5 -0
  351. package/dist/nerves/review/cli.js +156 -0
  352. package/dist/nerves/review/core.js +159 -0
  353. package/dist/nerves/runtime.js +17 -1
  354. package/dist/repertoire/ado-client.js +15 -56
  355. package/dist/repertoire/ado-semantic.js +16 -10
  356. package/dist/repertoire/api-client.js +97 -0
  357. package/dist/repertoire/bitwarden-store.js +1045 -0
  358. package/dist/repertoire/bundle-templates.js +71 -0
  359. package/dist/repertoire/bw-installer.js +180 -0
  360. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  361. package/dist/repertoire/coding/context-pack.js +331 -0
  362. package/dist/repertoire/coding/feedback.js +218 -30
  363. package/dist/repertoire/coding/index.js +15 -3
  364. package/dist/repertoire/coding/manager.js +166 -10
  365. package/dist/repertoire/coding/spawner.js +58 -11
  366. package/dist/repertoire/coding/tools.js +242 -14
  367. package/dist/repertoire/coding/workbench-client.js +272 -0
  368. package/dist/repertoire/coding/workbench-manager.js +346 -0
  369. package/dist/repertoire/commerce-errors.js +109 -0
  370. package/dist/repertoire/commerce-self-test.js +156 -0
  371. package/dist/repertoire/credential-access.js +178 -0
  372. package/dist/repertoire/desk/classifier.js +362 -0
  373. package/dist/repertoire/duffel-client.js +185 -0
  374. package/dist/repertoire/github-client.js +14 -55
  375. package/dist/repertoire/graph-client.js +11 -52
  376. package/dist/repertoire/guardrails.js +813 -18
  377. package/dist/repertoire/mcp-client.js +44 -3
  378. package/dist/repertoire/mcp-manager.js +259 -20
  379. package/dist/repertoire/mcp-tools.js +83 -0
  380. package/dist/repertoire/plugin-mcp.js +175 -0
  381. package/dist/repertoire/plugins.js +253 -0
  382. package/dist/repertoire/relationship-authorization.js +194 -0
  383. package/dist/repertoire/shell-sessions.js +133 -0
  384. package/dist/repertoire/skills.js +48 -4
  385. package/dist/repertoire/stripe-client.js +131 -0
  386. package/dist/repertoire/tool-arguments.js +148 -0
  387. package/dist/repertoire/tool-results.js +29 -0
  388. package/dist/repertoire/tools-a2a.js +699 -0
  389. package/dist/repertoire/tools-attachments.js +322 -0
  390. package/dist/repertoire/tools-awaiting.js +575 -0
  391. package/dist/repertoire/tools-base.js +82 -1139
  392. package/dist/repertoire/tools-bluebubbles.js +2 -0
  393. package/dist/repertoire/tools-bridge.js +144 -0
  394. package/dist/repertoire/tools-bundle.js +993 -0
  395. package/dist/repertoire/tools-commerce.js +253 -0
  396. package/dist/repertoire/tools-config.js +186 -0
  397. package/dist/repertoire/tools-continuity.js +575 -0
  398. package/dist/repertoire/tools-credential.js +383 -0
  399. package/dist/repertoire/tools-evolution.js +527 -0
  400. package/dist/repertoire/tools-files.js +344 -0
  401. package/dist/repertoire/tools-flight.js +290 -0
  402. package/dist/repertoire/tools-flow.js +119 -0
  403. package/dist/repertoire/tools-github.js +3 -8
  404. package/dist/repertoire/tools-habits.js +103 -0
  405. package/dist/repertoire/tools-mail.js +1828 -0
  406. package/dist/repertoire/tools-notes.js +485 -0
  407. package/dist/repertoire/tools-obligations.js +182 -0
  408. package/dist/repertoire/tools-orientation.js +31 -0
  409. package/dist/repertoire/tools-record.js +482 -0
  410. package/dist/repertoire/tools-rsvp.js +139 -0
  411. package/dist/repertoire/tools-runtime.js +150 -0
  412. package/dist/repertoire/tools-session.js +1096 -0
  413. package/dist/repertoire/tools-shell.js +133 -0
  414. package/dist/repertoire/tools-steward-policy.js +95 -0
  415. package/dist/repertoire/tools-stripe.js +224 -0
  416. package/dist/repertoire/tools-surface.js +355 -0
  417. package/dist/repertoire/tools-teams.js +12 -39
  418. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  419. package/dist/repertoire/tools-travel.js +125 -0
  420. package/dist/repertoire/tools-trip.js +982 -0
  421. package/dist/repertoire/tools-unraid.js +459 -0
  422. package/dist/repertoire/tools-user-profile.js +146 -0
  423. package/dist/repertoire/tools-vault.js +40 -0
  424. package/dist/repertoire/tools-voice.js +145 -0
  425. package/dist/repertoire/tools.js +377 -80
  426. package/dist/repertoire/travel-api-client.js +360 -0
  427. package/dist/repertoire/unraid-client.js +155 -0
  428. package/dist/repertoire/unraid-restart.js +212 -0
  429. package/dist/repertoire/user-profile.js +131 -0
  430. package/dist/repertoire/vault-setup.js +246 -0
  431. package/dist/repertoire/vault-unlock.js +628 -0
  432. package/dist/rsvp/aisleplanner-client.js +354 -0
  433. package/dist/rsvp/cli.js +926 -0
  434. package/dist/rsvp/config.js +327 -0
  435. package/dist/rsvp/cutover.js +433 -0
  436. package/dist/rsvp/diagnostics.js +232 -0
  437. package/dist/rsvp/diff-renderer.js +176 -0
  438. package/dist/rsvp/habit-policy.js +110 -0
  439. package/dist/rsvp/habit-stage.js +123 -0
  440. package/dist/rsvp/incident-bundle.js +97 -0
  441. package/dist/rsvp/migration.js +204 -0
  442. package/dist/rsvp/native-habit-runner.js +630 -0
  443. package/dist/rsvp/outbound-state.js +628 -0
  444. package/dist/rsvp/query.js +118 -0
  445. package/dist/rsvp/replay.js +233 -0
  446. package/dist/rsvp/snapshot.js +232 -0
  447. package/dist/rsvp/spend-ledger.js +175 -0
  448. package/dist/scripts/claude-code-hook.js +41 -0
  449. package/dist/scripts/claude-code-stop-hook.js +47 -0
  450. package/dist/senses/a2a-entry.js +115 -0
  451. package/dist/senses/attention-queue.js +186 -0
  452. package/dist/senses/await-turn-message.js +58 -0
  453. package/dist/senses/bluebubbles/active-turns.js +216 -0
  454. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  455. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  456. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  457. package/dist/senses/bluebubbles/context-packet.js +207 -0
  458. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  459. package/dist/senses/bluebubbles/entry.js +90 -0
  460. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  461. package/dist/senses/bluebubbles/index.js +3839 -0
  462. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  463. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  464. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  465. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  466. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  467. package/dist/senses/bluebubbles/processed-log.js +133 -0
  468. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  469. package/dist/senses/bluebubbles/replay.js +284 -0
  470. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  471. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  472. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  473. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  474. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  475. package/dist/senses/cli/bracketed-paste.js +82 -0
  476. package/dist/senses/cli/image-paste.js +287 -0
  477. package/dist/senses/cli/image-ref-navigation.js +75 -0
  478. package/dist/senses/cli/ink-app.js +156 -0
  479. package/dist/senses/cli/inline-diff.js +64 -0
  480. package/dist/senses/cli/input-keys.js +174 -0
  481. package/dist/senses/cli/kill-ring.js +86 -0
  482. package/dist/senses/cli/message-list.js +51 -0
  483. package/dist/senses/cli/ouro-tui.js +607 -0
  484. package/dist/senses/cli/spinner-imperative.js +135 -0
  485. package/dist/senses/cli/spinner.js +101 -0
  486. package/dist/senses/cli/status-line.js +60 -0
  487. package/dist/senses/cli/streaming-markdown.js +526 -0
  488. package/dist/senses/cli/tool-display.js +85 -0
  489. package/dist/senses/cli/tool-render.js +85 -0
  490. package/dist/senses/cli/tui-store.js +241 -0
  491. package/dist/senses/cli/virtual-list.js +35 -0
  492. package/dist/senses/cli-entry.js +60 -8
  493. package/dist/senses/cli.js +600 -317
  494. package/dist/senses/commands.js +66 -3
  495. package/dist/senses/context-packet-ledger.js +371 -0
  496. package/dist/senses/context-packets.js +154 -0
  497. package/dist/senses/habit-lifecycle-guard.js +24 -0
  498. package/dist/senses/habit-turn-message.js +160 -0
  499. package/dist/senses/ingress-evidence.js +2 -0
  500. package/dist/senses/mail-entry.js +66 -0
  501. package/dist/senses/mail.js +524 -0
  502. package/dist/senses/pipeline.js +1081 -204
  503. package/dist/senses/private-runtime-worker.js +859 -0
  504. package/dist/senses/private-runtime.js +1496 -0
  505. package/dist/senses/proactive-content-guard.js +51 -0
  506. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  507. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  508. package/dist/senses/sanctuary-grounding.js +118 -0
  509. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  510. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  511. package/dist/senses/sanctuary-health-runner.js +101 -0
  512. package/dist/senses/sanctuary-health.js +408 -0
  513. package/dist/senses/sanctuary-interactive-control.js +306 -0
  514. package/dist/senses/sanctuary-media-optimization.js +436 -0
  515. package/dist/senses/sanctuary-runtime.js +330 -0
  516. package/dist/senses/sanctuary-sab.js +85 -0
  517. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  518. package/dist/senses/shared-turn.js +488 -0
  519. package/dist/senses/surface-tool.js +109 -0
  520. package/dist/senses/teams-entry.js +60 -8
  521. package/dist/senses/teams.js +515 -217
  522. package/dist/senses/telegram-admission.js +711 -0
  523. package/dist/senses/telegram-approval-runtime.js +566 -0
  524. package/dist/senses/telegram-attachments.js +182 -0
  525. package/dist/senses/telegram-audit-ledger.js +220 -0
  526. package/dist/senses/telegram-client.js +1676 -0
  527. package/dist/senses/telegram-effect-adapter.js +796 -0
  528. package/dist/senses/telegram-entry.js +83 -0
  529. package/dist/senses/telegram.js +2018 -0
  530. package/dist/senses/trust-gate.js +104 -9
  531. package/dist/senses/voice/audio-playback.js +237 -0
  532. package/dist/senses/voice/audio-routing.js +119 -0
  533. package/dist/senses/voice/elevenlabs.js +202 -0
  534. package/dist/senses/voice/floor-control.js +431 -0
  535. package/dist/senses/voice/floor-controller.js +115 -0
  536. package/dist/senses/voice/golden-path.js +116 -0
  537. package/dist/senses/voice/index.js +29 -0
  538. package/dist/senses/voice/meeting.js +113 -0
  539. package/dist/senses/voice/outbound.js +190 -0
  540. package/dist/senses/voice/phone.js +33 -0
  541. package/dist/senses/voice/playback.js +139 -0
  542. package/dist/senses/voice/realtime-eval.js +496 -0
  543. package/dist/senses/voice/realtime-trace.js +531 -0
  544. package/dist/senses/voice/transcript.js +70 -0
  545. package/dist/senses/voice/turn.js +191 -0
  546. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  547. package/dist/senses/voice/twilio-phone.js +5081 -0
  548. package/dist/senses/voice/types.js +2 -0
  549. package/dist/senses/voice/whisper.js +161 -0
  550. package/dist/senses/voice-entry.js +81 -0
  551. package/dist/senses/voice-realtime-eval-command.js +99 -0
  552. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  553. package/dist/senses/voice-twilio-entry.js +87 -0
  554. package/dist/trips/core.js +138 -0
  555. package/dist/trips/store.js +265 -0
  556. package/dist/util/frontmatter.js +69 -0
  557. package/npm-shrinkwrap.json +8144 -0
  558. package/package.json +72 -13
  559. package/skills/agent-commerce.md +113 -0
  560. package/skills/browser-navigation.md +117 -0
  561. package/skills/commerce-setup-guide.md +116 -0
  562. package/skills/commerce-setup.md +84 -0
  563. package/skills/configure-dev-tools.md +99 -0
  564. package/skills/travel-planning.md +138 -0
  565. package/dist/heart/daemon/auth-flow.js +0 -430
  566. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  567. package/dist/heart/daemon/update-hooks.js +0 -138
  568. package/dist/heart/obligations.js +0 -141
  569. package/dist/heart/safe-workspace.js +0 -228
  570. package/dist/heart/session-recall.js +0 -116
  571. package/dist/mind/friends/channel.js +0 -84
  572. package/dist/mind/friends/group-context.js +0 -144
  573. package/dist/mind/friends/resolver.js +0 -84
  574. package/dist/mind/friends/store-file.js +0 -190
  575. package/dist/mind/friends/store.js +0 -4
  576. package/dist/mind/friends/tokens.js +0 -26
  577. package/dist/mind/friends/trust-explanation.js +0 -74
  578. package/dist/mind/friends/types.js +0 -29
  579. package/dist/repertoire/tasks/board.js +0 -134
  580. package/dist/repertoire/tasks/index.js +0 -224
  581. package/dist/repertoire/tasks/lifecycle.js +0 -80
  582. package/dist/repertoire/tasks/middleware.js +0 -65
  583. package/dist/repertoire/tasks/parser.js +0 -173
  584. package/dist/repertoire/tasks/scanner.js +0 -132
  585. package/dist/repertoire/tasks/transitions.js +0 -144
  586. package/dist/senses/bluebubbles-entry.js +0 -13
  587. package/dist/senses/bluebubbles.js +0 -1181
  588. package/dist/senses/debug-activity.js +0 -154
  589. package/dist/senses/inner-dialog-worker.js +0 -90
  590. package/dist/senses/inner-dialog.js +0 -525
  591. package/subagents/README.md +0 -7
  592. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  593. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  594. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  595. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  596. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  597. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  598. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  599. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  600. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  601. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  602. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  603. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  604. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  605. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  606. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  607. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  608. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SANCTUARY_BUNDLE_ROLLBACK_FILE = exports.SANCTUARY_PACKAGE_MANAGED_FILES = void 0;
37
+ exports.inspectSanctuaryPackageManagedBundleRollback = inspectSanctuaryPackageManagedBundleRollback;
38
+ exports.rollbackSanctuaryPackageManagedBundle = rollbackSanctuaryPackageManagedBundle;
39
+ exports.commitSanctuaryPackageManagedBundle = commitSanctuaryPackageManagedBundle;
40
+ exports.migrateSanctuaryPackageManagedBundle = migrateSanctuaryPackageManagedBundle;
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const node_crypto_1 = require("node:crypto");
44
+ const runtime_1 = require("../../nerves/runtime");
45
+ const steward_policy_1 = require("../steward-policy");
46
+ exports.SANCTUARY_PACKAGE_MANAGED_FILES = [
47
+ "provider-readiness.json",
48
+ "tool-profiles.json",
49
+ "habits/sanctuary-health.md",
50
+ "psyche/ASPIRATIONS.md",
51
+ "psyche/IDENTITY.md",
52
+ "psyche/LORE.md",
53
+ "psyche/SOUL.md",
54
+ "psyche/TACIT.md",
55
+ ];
56
+ exports.SANCTUARY_BUNDLE_ROLLBACK_FILE = ".sanctuary-package-managed-rollback.json";
57
+ const SANCTUARY_BUNDLE_COMMITTING_FILE = `${exports.SANCTUARY_BUNDLE_ROLLBACK_FILE}.committing`;
58
+ const BUNDLE_META_VERSION_FIELDS = ["runtimeVersion", "bundleSchemaVersion", "lastUpdated"];
59
+ function readObject(filePath) {
60
+ const value = JSON.parse(fs.readFileSync(filePath, "utf8"));
61
+ if (!value || typeof value !== "object" || Array.isArray(value))
62
+ throw new Error(`${path.basename(filePath)} must contain an object`);
63
+ return value;
64
+ }
65
+ function requirePlainFile(filePath, label) {
66
+ let stat;
67
+ try {
68
+ stat = fs.lstatSync(filePath);
69
+ }
70
+ catch {
71
+ throw new Error(`${label} is missing`);
72
+ }
73
+ if (stat.isSymbolicLink())
74
+ throw new Error(`${label} must not be a symlink`);
75
+ if (!stat.isFile())
76
+ throw new Error(`${label} must be a regular file`);
77
+ }
78
+ function ensureSafeParent(agentRoot, relative) {
79
+ let current = agentRoot;
80
+ for (const segment of path.dirname(relative).split(path.sep).filter((value) => value !== ".")) {
81
+ current = path.join(current, segment);
82
+ if (!fs.existsSync(current))
83
+ fs.mkdirSync(current, { mode: 0o700 });
84
+ }
85
+ }
86
+ function validateDestination(agentRoot, relative) {
87
+ let current = agentRoot;
88
+ for (const segment of relative.split(path.sep)) {
89
+ current = path.join(current, segment);
90
+ let stat;
91
+ try {
92
+ stat = fs.lstatSync(current);
93
+ }
94
+ catch {
95
+ return;
96
+ }
97
+ if (stat.isSymbolicLink())
98
+ throw new Error(`package-managed destination must not be a symlink: ${relative}`);
99
+ if (current !== path.join(agentRoot, relative) && !stat.isDirectory())
100
+ throw new Error(`package-managed destination parent must be a directory: ${relative}`);
101
+ if (current === path.join(agentRoot, relative) && !stat.isFile())
102
+ throw new Error(`package-managed destination must be a regular file: ${relative}`);
103
+ }
104
+ }
105
+ function writeAtomic(filePath, content) {
106
+ const stagingDirectory = fs.mkdtempSync(`${filePath}.package-migration.`);
107
+ const temporary = path.join(stagingDirectory, "value");
108
+ try {
109
+ const fd = fs.openSync(temporary, "wx", 0o600);
110
+ try {
111
+ fs.writeFileSync(fd, content);
112
+ fs.fsyncSync(fd);
113
+ }
114
+ finally {
115
+ fs.closeSync(fd);
116
+ }
117
+ fs.renameSync(temporary, filePath);
118
+ }
119
+ finally {
120
+ fs.rmSync(temporary, { force: true });
121
+ fs.rmdirSync(stagingDirectory);
122
+ }
123
+ fs.chmodSync(filePath, 0o600);
124
+ const directory = fs.openSync(path.dirname(filePath), fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
125
+ try {
126
+ fs.fsyncSync(directory);
127
+ }
128
+ finally {
129
+ fs.closeSync(directory);
130
+ }
131
+ }
132
+ function cleanupInterruptedWrites(filePath) {
133
+ const parent = path.dirname(filePath);
134
+ const prefix = `${path.basename(filePath)}.package-migration.`;
135
+ if (!fs.existsSync(parent))
136
+ return;
137
+ for (const name of fs.readdirSync(parent)) {
138
+ if (!name.startsWith(prefix))
139
+ continue;
140
+ const stagingDirectory = path.join(parent, name);
141
+ const stagingStat = fs.lstatSync(stagingDirectory);
142
+ if (stagingStat.isSymbolicLink() || !stagingStat.isDirectory())
143
+ throw new Error(`interrupted package migration stage is invalid: ${name}`);
144
+ const entries = fs.readdirSync(stagingDirectory);
145
+ if (entries.some((entry) => entry !== "value"))
146
+ throw new Error(`interrupted package migration stage contains unexpected entries: ${name}`);
147
+ const temporary = path.join(stagingDirectory, "value");
148
+ if (fs.existsSync(temporary)) {
149
+ const temporaryStat = fs.lstatSync(temporary);
150
+ if (temporaryStat.isSymbolicLink() || !temporaryStat.isFile())
151
+ throw new Error(`interrupted package migration value is invalid: ${name}`);
152
+ fs.unlinkSync(temporary);
153
+ }
154
+ fs.rmdirSync(stagingDirectory);
155
+ }
156
+ }
157
+ const SNAPSHOT_RELATIVES = [...exports.SANCTUARY_PACKAGE_MANAGED_FILES, "bundle-meta.json"];
158
+ function snapshotDirectoryRelatives() {
159
+ const directories = new Set();
160
+ for (const relative of SNAPSHOT_RELATIVES) {
161
+ let directory = path.dirname(relative);
162
+ while (directory !== ".") {
163
+ directories.add(directory);
164
+ directory = path.dirname(directory);
165
+ }
166
+ }
167
+ return [...directories].sort((left, right) => left.length - right.length);
168
+ }
169
+ function captureMigrationSnapshot(agentRoot) {
170
+ const files = SNAPSHOT_RELATIVES.map((relative) => {
171
+ const filePath = path.join(agentRoot, relative);
172
+ if (!fs.existsSync(filePath))
173
+ return { path: filePath, content: null, mode: null };
174
+ const stat = fs.lstatSync(filePath);
175
+ return { path: filePath, content: fs.readFileSync(filePath), mode: stat.mode & 0o777 };
176
+ });
177
+ const directories = snapshotDirectoryRelatives().map((relative) => {
178
+ const directory = path.join(agentRoot, relative);
179
+ if (!fs.existsSync(directory))
180
+ return { path: directory, mode: null };
181
+ const stat = fs.lstatSync(directory);
182
+ return { path: directory, mode: stat.mode & 0o777 };
183
+ });
184
+ return { files, directories };
185
+ }
186
+ function rollbackPath(agentRoot) {
187
+ return path.join(agentRoot, exports.SANCTUARY_BUNDLE_ROLLBACK_FILE);
188
+ }
189
+ function durableSnapshot(agentRoot, snapshot, rollbackImageId, targetImageId) {
190
+ const payload = {
191
+ schemaVersion: 1,
192
+ rollbackImageId,
193
+ targetImageId,
194
+ files: snapshot.files.map((file) => ({ relative: path.relative(agentRoot, file.path), contentBase64: file.content?.toString("base64") ?? null, mode: file.mode })),
195
+ directories: snapshot.directories.map((directory) => ({ relative: path.relative(agentRoot, directory.path), mode: directory.mode })),
196
+ };
197
+ return { ...payload, snapshotDigest: (0, node_crypto_1.createHash)("sha256").update(JSON.stringify(payload)).digest("hex") };
198
+ }
199
+ function readDurableRecord(agentRoot) {
200
+ const candidates = [rollbackPath(agentRoot), path.join(agentRoot, SANCTUARY_BUNDLE_COMMITTING_FILE)].filter((candidate) => fs.existsSync(candidate));
201
+ if (candidates.length === 0)
202
+ return null;
203
+ if (candidates.length !== 1)
204
+ throw new Error("Sanctuary bundle rollback record state is ambiguous");
205
+ const [filePath] = candidates;
206
+ const stat = fs.lstatSync(filePath);
207
+ if (stat.isSymbolicLink())
208
+ throw new Error("Sanctuary bundle rollback record must not be a symlink");
209
+ if (!stat.isFile() || (stat.mode & 0o777) !== 0o600)
210
+ throw new Error("Sanctuary bundle rollback record must be a mode-0600 regular file");
211
+ let value;
212
+ try {
213
+ value = JSON.parse(fs.readFileSync(filePath, "utf8"));
214
+ }
215
+ catch {
216
+ throw new Error("Sanctuary bundle rollback record is invalid JSON");
217
+ }
218
+ if (!value || typeof value !== "object" || Array.isArray(value))
219
+ throw new Error("Sanctuary bundle rollback record is invalid");
220
+ const record = value;
221
+ if (record.schemaVersion !== 1 || typeof record.rollbackImageId !== "string" || !/^sha256:[0-9a-f]{64}$/u.test(record.rollbackImageId) || typeof record.targetImageId !== "string" || !/^sha256:[0-9a-f]{64}$/u.test(record.targetImageId) || record.targetImageId === record.rollbackImageId || typeof record.snapshotDigest !== "string" || !/^[0-9a-f]{64}$/u.test(record.snapshotDigest) || !Array.isArray(record.files) || !Array.isArray(record.directories))
222
+ throw new Error("Sanctuary bundle rollback record is invalid");
223
+ const fileRelatives = record.files.map((file) => file?.relative);
224
+ const directoryRelatives = record.directories.map((directory) => directory?.relative);
225
+ const expectedDirectories = snapshotDirectoryRelatives();
226
+ if (JSON.stringify(fileRelatives) !== JSON.stringify(SNAPSHOT_RELATIVES) || JSON.stringify(directoryRelatives) !== JSON.stringify(expectedDirectories))
227
+ throw new Error("Sanctuary bundle rollback record paths are invalid");
228
+ for (const relative of SNAPSHOT_RELATIVES)
229
+ validateDestination(agentRoot, relative);
230
+ const validMode = (mode) => mode === null || (Number.isInteger(mode) && mode >= 0 && mode <= 0o777);
231
+ const files = record.files.map((file) => {
232
+ if (!file || typeof file.relative !== "string" || !validMode(file.mode) || (file.contentBase64 !== null && typeof file.contentBase64 !== "string") || (file.contentBase64 === null) !== (file.mode === null))
233
+ throw new Error("Sanctuary bundle rollback record file is invalid");
234
+ const content = file.contentBase64 === null ? null : Buffer.from(file.contentBase64, "base64");
235
+ if (file.contentBase64 !== null && (!content || content.toString("base64") !== file.contentBase64))
236
+ throw new Error("Sanctuary bundle rollback record content is invalid");
237
+ return { path: path.join(agentRoot, file.relative), content, mode: file.mode };
238
+ });
239
+ const directories = record.directories.map((directory) => {
240
+ if (!directory || typeof directory.relative !== "string" || !validMode(directory.mode))
241
+ throw new Error("Sanctuary bundle rollback record directory is invalid");
242
+ return { path: path.join(agentRoot, directory.relative), mode: directory.mode };
243
+ });
244
+ const payload = { schemaVersion: record.schemaVersion, rollbackImageId: record.rollbackImageId, targetImageId: record.targetImageId, files: record.files, directories: record.directories };
245
+ if ((0, node_crypto_1.createHash)("sha256").update(JSON.stringify(payload)).digest("hex") !== record.snapshotDigest)
246
+ throw new Error("Sanctuary bundle rollback record digest is invalid");
247
+ return { snapshot: { files, directories }, rollbackImageId: record.rollbackImageId, targetImageId: record.targetImageId, filePath, state: filePath === rollbackPath(agentRoot) ? "rollback" : "committing" };
248
+ }
249
+ function removeRollbackRecord(agentRoot, filePath) {
250
+ fs.unlinkSync(filePath);
251
+ const root = fs.openSync(agentRoot, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
252
+ try {
253
+ fs.fsyncSync(root);
254
+ }
255
+ finally {
256
+ fs.closeSync(root);
257
+ }
258
+ }
259
+ function validateAgentRoot(agentRoot) {
260
+ if (!path.isAbsolute(agentRoot))
261
+ throw new Error("agent root must be an absolute path");
262
+ const stat = fs.lstatSync(agentRoot);
263
+ if (stat.isSymbolicLink() || !stat.isDirectory())
264
+ throw new Error("agent root must be a real directory");
265
+ }
266
+ function inspectSanctuaryPackageManagedBundleRollback(agentRoot) {
267
+ validateAgentRoot(agentRoot);
268
+ const record = readDurableRecord(agentRoot);
269
+ return record ? { rollbackImageId: record.rollbackImageId, targetImageId: record.targetImageId, state: record.state } : null;
270
+ }
271
+ function rollbackSanctuaryPackageManagedBundle(agentRoot, options = {}) {
272
+ validateAgentRoot(agentRoot);
273
+ const record = readDurableRecord(agentRoot);
274
+ if (!record)
275
+ return false;
276
+ if (record.state === "committing")
277
+ throw new Error("Sanctuary bundle commit is pending and cannot be rolled back");
278
+ restoreMigrationSnapshot(record.snapshot);
279
+ if (!options.retainRecord)
280
+ removeRollbackRecord(agentRoot, record.filePath);
281
+ return true;
282
+ }
283
+ function commitSanctuaryPackageManagedBundle(agentRoot) {
284
+ validateAgentRoot(agentRoot);
285
+ const record = readDurableRecord(agentRoot);
286
+ if (!record)
287
+ return false;
288
+ const committingPath = path.join(agentRoot, SANCTUARY_BUNDLE_COMMITTING_FILE);
289
+ if (record.filePath !== committingPath) {
290
+ fs.renameSync(record.filePath, committingPath);
291
+ const root = fs.openSync(agentRoot, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
292
+ try {
293
+ fs.fsyncSync(root);
294
+ }
295
+ finally {
296
+ fs.closeSync(root);
297
+ }
298
+ }
299
+ removeRollbackRecord(agentRoot, committingPath);
300
+ return true;
301
+ }
302
+ function restoreMigrationSnapshot(snapshot) {
303
+ for (const file of snapshot.files) {
304
+ cleanupInterruptedWrites(file.path);
305
+ if (file.content === null) {
306
+ fs.rmSync(file.path, { force: true });
307
+ }
308
+ else {
309
+ writeAtomic(file.path, file.content);
310
+ fs.chmodSync(file.path, file.mode);
311
+ }
312
+ }
313
+ for (const directory of [...snapshot.directories].reverse()) {
314
+ if (directory.mode === null) {
315
+ if (!fs.existsSync(directory.path))
316
+ continue;
317
+ if (fs.readdirSync(directory.path).length === 0)
318
+ fs.rmdirSync(directory.path);
319
+ }
320
+ else {
321
+ fs.chmodSync(directory.path, directory.mode);
322
+ }
323
+ }
324
+ }
325
+ function migrateSanctuaryPackageManagedBundle(input) {
326
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_bundle_migration_start", message: "starting Sanctuary package-managed bundle migration", meta: { agentRoot: input.agentRoot } });
327
+ let snapshot = null;
328
+ try {
329
+ if (!path.isAbsolute(input.packageRoot) || !path.isAbsolute(input.agentRoot) || input.packageRoot === input.agentRoot)
330
+ throw new Error("package and agent roots must be distinct absolute paths");
331
+ const packageStat = fs.lstatSync(input.packageRoot);
332
+ const agentStat = fs.lstatSync(input.agentRoot);
333
+ if (packageStat.isSymbolicLink() || !packageStat.isDirectory())
334
+ throw new Error("package root must be a real directory");
335
+ if (agentStat.isSymbolicLink() || !agentStat.isDirectory())
336
+ throw new Error("agent root must be a real directory");
337
+ if (input.retainRollback && (!input.rollbackImageId || !/^sha256:[0-9a-f]{64}$/u.test(input.rollbackImageId) || !input.targetImageId || !/^sha256:[0-9a-f]{64}$/u.test(input.targetImageId) || input.targetImageId === input.rollbackImageId))
338
+ throw new Error("retained rollback requires distinct exact rollback and target image IDs");
339
+ const existingRollback = rollbackPath(input.agentRoot);
340
+ if (readDurableRecord(input.agentRoot))
341
+ throw new Error("Sanctuary bundle rollback is pending; rollback or commit it before another migration");
342
+ for (const relative of exports.SANCTUARY_PACKAGE_MANAGED_FILES) {
343
+ requirePlainFile(path.join(input.packageRoot, relative), `package-managed source ${relative}`);
344
+ validateDestination(input.agentRoot, relative);
345
+ }
346
+ requirePlainFile(path.join(input.packageRoot, "bundle-meta.json"), "packaged bundle-meta.json");
347
+ validateDestination(input.agentRoot, "bundle-meta.json");
348
+ const packagedMeta = readObject(path.join(input.packageRoot, "bundle-meta.json"));
349
+ for (const field of BUNDLE_META_VERSION_FIELDS)
350
+ if (!(field in packagedMeta))
351
+ throw new Error(`packaged bundle-meta.json is missing ${field}`);
352
+ const packagedPolicy = (0, steward_policy_1.readStewardPolicy)(input.packageRoot);
353
+ if (Object.keys(packagedPolicy.routineActionGrants).length > 0) {
354
+ throw new Error("packaged steward policy must not carry routine action grants; authorize them through an authenticated owner session");
355
+ }
356
+ snapshot = captureMigrationSnapshot(input.agentRoot);
357
+ if (input.retainRollback) {
358
+ cleanupInterruptedWrites(existingRollback);
359
+ writeAtomic(existingRollback, `${JSON.stringify(durableSnapshot(input.agentRoot, snapshot, input.rollbackImageId, input.targetImageId))}\n`);
360
+ }
361
+ let managedFilesUpdated = 0;
362
+ for (const relative of exports.SANCTUARY_PACKAGE_MANAGED_FILES) {
363
+ const source = fs.readFileSync(path.join(input.packageRoot, relative), "utf8");
364
+ const destination = path.join(input.agentRoot, relative);
365
+ ensureSafeParent(input.agentRoot, relative);
366
+ if (fs.existsSync(destination) && fs.readFileSync(destination, "utf8") === source && (fs.statSync(destination).mode & 0o777) === 0o600)
367
+ continue;
368
+ writeAtomic(destination, source);
369
+ managedFilesUpdated += 1;
370
+ }
371
+ const metaPath = path.join(input.agentRoot, "bundle-meta.json");
372
+ const currentMeta = fs.existsSync(metaPath) ? readObject(metaPath) : {};
373
+ const nextMeta = { ...currentMeta };
374
+ for (const field of BUNDLE_META_VERSION_FIELDS)
375
+ nextMeta[field] = packagedMeta[field];
376
+ const nextMetaText = `${JSON.stringify(nextMeta, null, 2)}\n`;
377
+ if (!fs.existsSync(metaPath) || fs.readFileSync(metaPath, "utf8") !== nextMetaText)
378
+ writeAtomic(metaPath, nextMetaText);
379
+ const result = { managedFilesUpdated };
380
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_bundle_migration_end", message: "completed Sanctuary package-managed bundle migration", meta: result });
381
+ return result;
382
+ }
383
+ catch (error) {
384
+ let failure = error;
385
+ if (snapshot) {
386
+ try {
387
+ restoreMigrationSnapshot(snapshot);
388
+ if (fs.existsSync(rollbackPath(input.agentRoot)))
389
+ removeRollbackRecord(input.agentRoot, rollbackPath(input.agentRoot));
390
+ }
391
+ catch (restoreError) {
392
+ failure = new AggregateError([error, restoreError], "Sanctuary bundle migration and rollback both failed");
393
+ }
394
+ }
395
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_bundle_migration_error", level: "error", message: "Sanctuary package-managed bundle migration failed", meta: { error: String(failure), agentRoot: input.agentRoot } });
396
+ throw failure;
397
+ }
398
+ }
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readSanctuaryHealthCursor = readSanctuaryHealthCursor;
37
+ exports.durableExclusiveJson = durableExclusiveJson;
38
+ exports.consumeSanctuarySchedulerFire = consumeSanctuarySchedulerFire;
39
+ exports.publishSanctuarySchedulerReceipt = publishSanctuarySchedulerReceipt;
40
+ exports.sanctuarySchedulerLivenessReceiptMac = sanctuarySchedulerLivenessReceiptMac;
41
+ exports.verifySanctuarySchedulerLivenessReceiptMac = verifySanctuarySchedulerLivenessReceiptMac;
42
+ exports.recordSanctuarySchedulerLivenessReceipt = recordSanctuarySchedulerLivenessReceipt;
43
+ const node_crypto_1 = require("node:crypto");
44
+ const fs = __importStar(require("node:fs"));
45
+ const path = __importStar(require("node:path"));
46
+ const runtime_1 = require("../../nerves/runtime");
47
+ const SHA256 = /^[0-9a-f]{64}$/u;
48
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
49
+ const CRONTAB_PATH = "/home/ouro/.ouro-cli/scheduler/sanctuary.crontab";
50
+ const COMMAND = "/usr/local/bin/node /opt/ouro/dist/heart/daemon/ouro-entry.js poke sanctuary --habit sanctuary-health --trigger cron";
51
+ function readSanctuaryHealthCursor(agentRoot) {
52
+ const state = JSON.parse(fs.readFileSync(path.join(agentRoot, "state", "health", "sanctuary-health.json"), "utf8"));
53
+ if (!Array.isArray(state.sweepReceipts) || !Array.isArray(state.deliveredReceipts))
54
+ throw new Error("Sanctuary health cursor state is invalid");
55
+ return { sweepCount: state.sweepReceipts.length, deliveryCount: state.deliveredReceipts.length };
56
+ }
57
+ function fsyncDirectory(directory, deps) {
58
+ const descriptor = deps.openSync(directory, fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
59
+ try {
60
+ deps.fsyncSync(descriptor);
61
+ }
62
+ finally {
63
+ deps.closeSync(descriptor);
64
+ }
65
+ }
66
+ function ensureDurableDirectory(directory, deps) {
67
+ try {
68
+ deps.mkdirSync(directory, { mode: 0o700 });
69
+ }
70
+ catch (error) {
71
+ const code = error.code;
72
+ if (code === "EEXIST") {
73
+ fsyncDirectory(directory, deps);
74
+ fsyncDirectory(path.dirname(directory), deps);
75
+ return;
76
+ }
77
+ if (code !== "ENOENT")
78
+ throw error;
79
+ const parent = path.dirname(directory);
80
+ if (parent === directory)
81
+ throw error;
82
+ ensureDurableDirectory(parent, deps);
83
+ try {
84
+ deps.mkdirSync(directory, { mode: 0o700 });
85
+ }
86
+ catch (retryError) {
87
+ if (retryError.code !== "EEXIST")
88
+ throw retryError;
89
+ }
90
+ }
91
+ fsyncDirectory(directory, deps);
92
+ fsyncDirectory(path.dirname(directory), deps);
93
+ }
94
+ function durableExclusiveJson(filePath, value, deps = fs) {
95
+ const directory = path.dirname(filePath);
96
+ ensureDurableDirectory(directory, deps);
97
+ const temporary = `${filePath}.tmp-${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
98
+ let handle = null;
99
+ try {
100
+ handle = deps.openSync(temporary, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY | fs.constants.O_NOFOLLOW, 0o600);
101
+ deps.writeFileSync(handle, `${JSON.stringify(value)}\n`, "utf8");
102
+ deps.fsyncSync(handle);
103
+ deps.closeSync(handle);
104
+ handle = null;
105
+ deps.linkSync(temporary, filePath);
106
+ fsyncDirectory(directory, deps);
107
+ }
108
+ finally {
109
+ if (handle !== null)
110
+ deps.closeSync(handle);
111
+ try {
112
+ deps.unlinkSync(temporary);
113
+ }
114
+ catch (error) {
115
+ if (error.code !== "ENOENT")
116
+ throw error;
117
+ }
118
+ finally {
119
+ fsyncDirectory(directory, deps);
120
+ }
121
+ }
122
+ }
123
+ function consumeSanctuarySchedulerFire(agentRoot, origin) {
124
+ if (!UUID.test(origin.schedulerRunId) || origin.occurrenceId !== `cron:${origin.slot}`)
125
+ throw new Error("Sanctuary scheduler fire claim is invalid");
126
+ const claimId = (0, node_crypto_1.createHash)("sha256").update(`sanctuary\0sanctuary-health\0${origin.slot}\0${origin.occurrenceId}`).digest("hex");
127
+ const claimPath = path.join(agentRoot, "state", "scheduler", "sanctuary-fire-claims", `${claimId}.json`);
128
+ try {
129
+ durableExclusiveJson(claimPath, { schemaVersion: "sanctuary-scheduler-fire-claim-v1", ...origin });
130
+ }
131
+ catch (error) {
132
+ if (error.code === "EEXIST") {
133
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "daemon", event: "daemon.sanctuary_scheduler_fire_rejected", message: "Rejected replayed Sanctuary scheduler fire", meta: { occurrenceId: origin.occurrenceId, schedulerRunId: origin.schedulerRunId } });
134
+ throw new Error("Sanctuary scheduler fire replay rejected");
135
+ }
136
+ throw error;
137
+ }
138
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_scheduler_fire_consumed", message: "Consumed Sanctuary scheduler fire before execution", meta: { occurrenceId: origin.occurrenceId, schedulerRunId: origin.schedulerRunId } });
139
+ }
140
+ function publishSanctuarySchedulerReceipt(filePath, value, deps = fs) {
141
+ try {
142
+ durableExclusiveJson(filePath, value, deps);
143
+ }
144
+ catch (error) {
145
+ if (error.code === "EEXIST")
146
+ throw new Error("Sanctuary scheduler liveness receipt already exists");
147
+ throw error;
148
+ }
149
+ }
150
+ function unsignedReceipt(value) {
151
+ return Object.fromEntries(Object.entries(value).filter(([key]) => key !== "receiptMac"));
152
+ }
153
+ function sanctuarySchedulerLivenessReceiptMac(identityKey, value) {
154
+ return (0, node_crypto_1.createHmac)("sha256", identityKey).update(`sanctuary-scheduler-liveness-receipt-v2\0${JSON.stringify(unsignedReceipt(value))}`).digest("hex");
155
+ }
156
+ function verifySanctuarySchedulerLivenessReceiptMac(identityKey, value) {
157
+ const observed = value.receiptMac;
158
+ if (typeof observed !== "string" || !SHA256.test(observed))
159
+ return false;
160
+ return (0, node_crypto_1.timingSafeEqual)(Buffer.from(observed, "hex"), Buffer.from(sanctuarySchedulerLivenessReceiptMac(identityKey, value), "hex"));
161
+ }
162
+ function validateSupervisor(snapshot) {
163
+ const manifest = snapshot.manifest;
164
+ if (snapshot.schemaVersion !== "supercronic-supervisor-snapshot-v1" || snapshot.daemonPid !== process.pid
165
+ || snapshot.childCount !== 1 || snapshot.healthy !== true || !Number.isSafeInteger(snapshot.childPid) || snapshot.childPid <= 1
166
+ || snapshot.binaryPath !== "/usr/local/bin/supercronic" || snapshot.crontabPath !== CRONTAB_PATH
167
+ || JSON.stringify(snapshot.args) !== JSON.stringify(["-split-logs", "-inotify", CRONTAB_PATH])
168
+ || snapshot.namespace !== "habit:sanctuary" || manifest.length !== 1
169
+ || manifest[0]?.id !== "sanctuary:sanctuary-health" || manifest[0].agent !== "sanctuary"
170
+ || manifest[0].taskId !== "sanctuary-health" || manifest[0].schedule !== "*/15 * * * *"
171
+ || manifest[0].taskPath !== "/home/ouro/AgentBundles/sanctuary.ouro/habits/sanctuary-health.md"
172
+ || manifest[0].command !== COMMAND || !snapshot.renderedCrontab.includes(`# ouro:habit:sanctuary:sanctuary:sanctuary-health\n*/15 * * * * ${COMMAND}\n`)) {
173
+ throw new Error("Sanctuary scheduler supervisor attestation is invalid");
174
+ }
175
+ }
176
+ function recordSanctuarySchedulerLivenessReceipt(input) {
177
+ if (input.trigger !== "cron")
178
+ throw new Error("Sanctuary scheduler liveness requires cron provenance");
179
+ if (input.scenario.label !== "unit-16f-cron-fingerprint" || !SHA256.test(input.scenario.scenarioHandleDigest))
180
+ throw new Error("Sanctuary scheduler liveness scenario is invalid");
181
+ if (input.occurrenceId.length === 0 || !UUID.test(input.runnerId))
182
+ throw new Error("Sanctuary scheduler liveness runner provenance is invalid");
183
+ if (!/^[A-Za-z0-9_-]{43}$/u.test(input.identityKey) || input.schedulerOrigin.parentPid !== input.supervisor.childPid
184
+ || input.schedulerOrigin.scenarioHandleDigest !== input.scenario.scenarioHandleDigest || input.occurrenceId !== input.schedulerOrigin.occurrenceId
185
+ || input.occurrenceId !== `cron:${input.schedulerOrigin.slot}`
186
+ || !UUID.test(input.schedulerOrigin.schedulerRunId)
187
+ || input.schedulerOrigin.slot.length === 0 || !SHA256.test(input.schedulerOrigin.proofMac))
188
+ throw new Error("Sanctuary scheduler liveness authenticated origin is invalid");
189
+ if (input.providerInvocationCount !== 0 || input.privateTurnCount !== 0)
190
+ throw new Error("Sanctuary scheduler liveness performed paid work");
191
+ validateSupervisor(input.supervisor);
192
+ const statePath = path.join(input.agentRoot, "state", "health", "sanctuary-health.json");
193
+ const state = JSON.parse(fs.readFileSync(statePath, "utf8"));
194
+ if (!Array.isArray(state.sweepReceipts) || !Array.isArray(state.deliveredReceipts))
195
+ throw new Error("Sanctuary scheduler liveness state is invalid");
196
+ const after = { sweepCount: state.sweepReceipts.length, deliveryCount: state.deliveredReceipts.length };
197
+ const matching = state.sweepReceipts.slice(input.before.sweepCount).filter((row) => row.scenarioHandleDigest === input.scenario.scenarioHandleDigest);
198
+ const sweep = matching[0];
199
+ if (after.sweepCount - input.before.sweepCount !== 1 || matching.length !== 1 || !sweep
200
+ || after.deliveryCount - input.before.deliveryCount !== 0 || sweep.opened !== 0 || sweep.recovered !== 0 || sweep.digestDue !== false || sweep.deliveryId !== undefined) {
201
+ throw new Error("Sanctuary scheduler liveness requires exactly one unchanged sweep");
202
+ }
203
+ const unsigned = {
204
+ schemaVersion: "sanctuary-scheduler-liveness-receipt-v1",
205
+ label: "unit-16f-cron-fingerprint",
206
+ scenarioHandleDigest: input.scenario.scenarioHandleDigest,
207
+ trigger: "cron",
208
+ occurrenceId: input.occurrenceId,
209
+ runnerId: input.runnerId,
210
+ recordedAt: (input.now ?? (() => new Date()))().toISOString(),
211
+ before: input.before,
212
+ after,
213
+ sweepDelta: 1,
214
+ deliveryDelta: 0,
215
+ providerInvocationCount: 0,
216
+ privateTurnCount: 0,
217
+ sweep: { recordDigest: (0, node_crypto_1.createHash)("sha256").update(JSON.stringify(sweep)).digest("hex"), opened: 0, recovered: 0, digestDue: false, deliveryId: null },
218
+ supervisor: input.supervisor,
219
+ schedulerOrigin: input.schedulerOrigin,
220
+ nonReplay: true,
221
+ };
222
+ const receipt = { ...unsigned, receiptMac: sanctuarySchedulerLivenessReceiptMac(input.identityKey, unsigned) };
223
+ const receiptPath = path.join(input.agentRoot, "state", "acceptance", "scheduler-liveness-receipts", `${input.scenario.scenarioHandleDigest}.json`);
224
+ publishSanctuarySchedulerReceipt(receiptPath, receipt);
225
+ (0, runtime_1.emitNervesEvent)({ component: "daemon", event: "daemon.sanctuary_scheduler_liveness", message: "Scheduler-origin Sanctuary health sweep attested", meta: { scenarioHandleDigest: input.scenario.scenarioHandleDigest, occurrenceId: input.occurrenceId, runnerId: input.runnerId } });
226
+ return receipt;
227
+ }