@ouro.bot/cli 0.1.0-alpha.91 → 0.1.0-alpha.911

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 (709) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5769 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2997 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1254 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1564 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
  38. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  39. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  40. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  41. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  42. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  43. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  44. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  45. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  46. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +33 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  52. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  53. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  54. package/deploy/unraid/sanctuary.xml +30 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +250 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command-grants.js +93 -0
  59. package/dist/a2a/delegated-command.js +197 -0
  60. package/dist/a2a/delegation-stores.js +56 -0
  61. package/dist/a2a/did-resolution.js +93 -0
  62. package/dist/a2a/escalation-grants.js +84 -0
  63. package/dist/a2a/escalation-wiring.js +60 -0
  64. package/dist/a2a/identity.js +258 -0
  65. package/dist/a2a/inbound-share.js +110 -0
  66. package/dist/a2a/mission-result-wire.js +196 -0
  67. package/dist/a2a/onboarding.js +133 -0
  68. package/dist/a2a/operator-trust.js +382 -0
  69. package/dist/a2a/outbox-client.js +57 -0
  70. package/dist/a2a/outbox-store.js +188 -0
  71. package/dist/a2a/outbox-wire.js +95 -0
  72. package/dist/a2a/pin-store.js +132 -0
  73. package/dist/a2a/replay-grant-holders.js +33 -0
  74. package/dist/a2a/replay-harness.js +188 -0
  75. package/dist/a2a/resolution-proof.js +53 -0
  76. package/dist/a2a/sealed-chat.js +113 -0
  77. package/dist/a2a/seen-ledger.js +120 -0
  78. package/dist/a2a/server.js +771 -0
  79. package/dist/a2a/task-store.js +69 -0
  80. package/dist/a2a/transport.js +45 -0
  81. package/dist/a2a/trust-commands.js +203 -0
  82. package/dist/a2a/trusted-files.js +185 -0
  83. package/dist/a2a/types.js +3 -0
  84. package/dist/arc/attention-types.js +8 -0
  85. package/dist/arc/cares.js +360 -0
  86. package/dist/arc/episodes.js +118 -0
  87. package/dist/arc/evolution.js +490 -0
  88. package/dist/arc/flight-recorder.js +1034 -0
  89. package/dist/arc/intentions.js +134 -0
  90. package/dist/arc/json-store.js +117 -0
  91. package/dist/arc/obligations.js +386 -0
  92. package/dist/arc/packets.js +336 -0
  93. package/dist/arc/presence.js +185 -0
  94. package/dist/arc/task-lifecycle.js +57 -0
  95. package/dist/commerce/store.js +755 -0
  96. package/dist/commerce/types.js +3 -0
  97. package/dist/heart/active-work.js +798 -40
  98. package/dist/heart/agent-entry.js +252 -3
  99. package/dist/heart/approval-files.js +113 -0
  100. package/dist/heart/approval-store.js +960 -0
  101. package/dist/heart/attachments/image-normalize.js +194 -0
  102. package/dist/heart/attachments/materialize.js +97 -0
  103. package/dist/heart/attachments/originals.js +88 -0
  104. package/dist/heart/attachments/render.js +29 -0
  105. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  106. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  107. package/dist/heart/attachments/sources/index.js +18 -0
  108. package/dist/heart/attachments/sources/telegram.js +71 -0
  109. package/dist/heart/attachments/store.js +132 -0
  110. package/dist/heart/attachments/types.js +93 -0
  111. package/dist/heart/auth/auth-flow.js +495 -0
  112. package/dist/heart/autonomy-budget.js +478 -0
  113. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  114. package/dist/heart/awaiting/await-alert.js +152 -0
  115. package/dist/heart/awaiting/await-expiry.js +143 -0
  116. package/dist/heart/awaiting/await-loader.js +91 -0
  117. package/dist/heart/awaiting/await-parser.js +152 -0
  118. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  119. package/dist/heart/awaiting/await-scheduler.js +391 -0
  120. package/dist/heart/background-operations.js +281 -0
  121. package/dist/heart/bridges/manager.js +137 -17
  122. package/dist/heart/bridges/store.js +14 -2
  123. package/dist/heart/bundle-state.js +168 -0
  124. package/dist/heart/commitments.js +44 -18
  125. package/dist/heart/config-registry.js +331 -0
  126. package/dist/heart/config.js +174 -131
  127. package/dist/heart/context-loss-gauntlet.js +387 -0
  128. package/dist/heart/context-loss-sentinel.js +1159 -0
  129. package/dist/heart/core.js +2369 -579
  130. package/dist/heart/cross-chat-delivery.js +9 -22
  131. package/dist/heart/daemon/agent-config-check.js +451 -0
  132. package/dist/heart/daemon/agent-discovery.js +283 -3
  133. package/dist/heart/daemon/agent-home.js +319 -0
  134. package/dist/heart/daemon/agent-service.js +542 -0
  135. package/dist/heart/daemon/agentic-repair.js +547 -0
  136. package/dist/heart/daemon/await-private-wake.js +59 -0
  137. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  138. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  139. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  140. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  141. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  142. package/dist/heart/daemon/cadence.js +180 -0
  143. package/dist/heart/daemon/cli-defaults.js +876 -0
  144. package/dist/heart/daemon/cli-desk.js +322 -0
  145. package/dist/heart/daemon/cli-exec.js +9068 -0
  146. package/dist/heart/daemon/cli-help.js +735 -0
  147. package/dist/heart/daemon/cli-parse.js +3147 -0
  148. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  149. package/dist/heart/daemon/cli-render.js +819 -0
  150. package/dist/heart/daemon/cli-types.js +8 -0
  151. package/dist/heart/daemon/connect-bay.js +323 -0
  152. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  153. package/dist/heart/daemon/container-healthcheck.js +112 -0
  154. package/dist/heart/daemon/container-runtime.js +97 -0
  155. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  156. package/dist/heart/daemon/container-spec-auditor.js +235 -0
  157. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  158. package/dist/heart/daemon/daemon-cli.js +29 -2350
  159. package/dist/heart/daemon/daemon-entry.js +953 -11
  160. package/dist/heart/daemon/daemon-health.js +186 -0
  161. package/dist/heart/daemon/daemon-rollup.js +57 -0
  162. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  163. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  164. package/dist/heart/daemon/daemon.js +2084 -105
  165. package/dist/heart/daemon/dns-workflow.js +394 -0
  166. package/dist/heart/daemon/doctor-types.js +8 -0
  167. package/dist/heart/daemon/doctor.js +1755 -0
  168. package/dist/heart/daemon/freshness.js +345 -0
  169. package/dist/heart/daemon/habit-private-wake.js +61 -0
  170. package/dist/heart/daemon/health-monitor.js +154 -11
  171. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  172. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  173. package/dist/heart/daemon/http-health-probe.js +80 -0
  174. package/dist/heart/daemon/human-command-screens.js +234 -0
  175. package/dist/heart/daemon/human-readiness.js +114 -0
  176. package/dist/heart/daemon/inner-status.js +78 -0
  177. package/dist/heart/daemon/interactive-repair.js +394 -0
  178. package/dist/heart/daemon/launchd.js +37 -8
  179. package/dist/heart/daemon/log-tailer.js +79 -10
  180. package/dist/heart/daemon/logs-prune.js +132 -0
  181. package/dist/heart/daemon/mcp-canary.js +524 -0
  182. package/dist/heart/daemon/message-router.js +65 -5
  183. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  184. package/dist/heart/daemon/os-cron-deps.js +135 -0
  185. package/dist/heart/daemon/os-cron.js +22 -14
  186. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  187. package/dist/heart/daemon/ouro-entry.js +3 -1
  188. package/dist/heart/daemon/plugin-cli.js +432 -0
  189. package/dist/heart/daemon/process-manager.js +760 -61
  190. package/dist/heart/daemon/provider-discovery.js +137 -0
  191. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  192. package/dist/heart/daemon/prunable-bundle.js +144 -0
  193. package/dist/heart/daemon/pulse.js +511 -0
  194. package/dist/heart/daemon/readiness-repair.js +365 -0
  195. package/dist/heart/daemon/run-hooks.js +2 -0
  196. package/dist/heart/daemon/runtime-logging.js +47 -14
  197. package/dist/heart/daemon/runtime-metadata.js +2 -30
  198. package/dist/heart/daemon/runtime-mode.js +13 -2
  199. package/dist/heart/daemon/safe-mode.js +161 -0
  200. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  201. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  202. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  203. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  204. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  205. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  206. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  207. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  208. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1267 -0
  209. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  210. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  211. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  212. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  213. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  214. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  215. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  216. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  217. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  218. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  219. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  220. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  221. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  222. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  223. package/dist/heart/daemon/sense-manager.js +716 -48
  224. package/dist/heart/daemon/session-id-resolver.js +131 -0
  225. package/dist/heart/daemon/skill-management-installer.js +1 -1
  226. package/dist/heart/daemon/socket-client.js +180 -12
  227. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  228. package/dist/heart/daemon/startup-tui.js +339 -0
  229. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  230. package/dist/heart/daemon/task-scheduler.js +117 -39
  231. package/dist/heart/daemon/terminal-ui.js +499 -0
  232. package/dist/heart/daemon/thoughts.js +138 -54
  233. package/dist/heart/daemon/up-progress.js +366 -0
  234. package/dist/heart/daemon/vault-items.js +56 -0
  235. package/dist/heart/delegation.js +1 -4
  236. package/dist/heart/external-events/router.js +1516 -0
  237. package/dist/heart/failure-reports.js +336 -0
  238. package/dist/heart/file-lock.js +109 -0
  239. package/dist/heart/frontend-approval-runtime.js +506 -0
  240. package/dist/heart/frontend-journal.js +215 -0
  241. package/dist/heart/frontend-session-service.js +237 -0
  242. package/dist/heart/frontend-socket-client.js +164 -0
  243. package/dist/heart/frontend-socket.js +400 -0
  244. package/dist/heart/habits/habit-cancel.js +810 -0
  245. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  246. package/dist/heart/habits/habit-migration.js +194 -0
  247. package/dist/heart/habits/habit-parser.js +278 -0
  248. package/dist/heart/habits/habit-runtime-state.js +93 -0
  249. package/dist/heart/habits/habit-scheduler.js +653 -0
  250. package/dist/heart/habits/habit-session-summary.js +318 -0
  251. package/dist/heart/habits/habit-session.js +636 -0
  252. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  253. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  254. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  255. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  256. package/dist/heart/identity.js +199 -59
  257. package/dist/heart/kept-notes.js +289 -0
  258. package/dist/heart/kicks.js +1 -1
  259. package/dist/heart/machine-identity.js +175 -0
  260. package/dist/heart/mail-import-discovery.js +356 -0
  261. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  262. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  263. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  264. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  265. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  266. package/dist/heart/mailbox/mailbox-http.js +99 -0
  267. package/dist/heart/mailbox/mailbox-read.js +39 -0
  268. package/dist/heart/mailbox/mailbox-types.js +27 -0
  269. package/dist/heart/mailbox/mailbox-view.js +197 -0
  270. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  271. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  272. package/dist/heart/mailbox/readers/mail.js +375 -0
  273. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  274. package/dist/heart/mailbox/readers/sessions.js +231 -0
  275. package/dist/heart/mailbox/readers/shared.js +111 -0
  276. package/dist/heart/mcp/mcp-server.js +696 -0
  277. package/dist/heart/migrate-config.js +100 -0
  278. package/dist/heart/model-capabilities.js +11 -0
  279. package/dist/heart/orientation-frame.js +345 -0
  280. package/dist/heart/platform.js +81 -0
  281. package/dist/heart/primitives.js +1 -1
  282. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  283. package/dist/heart/private-runtime/index.js +18 -0
  284. package/dist/heart/private-runtime/ledger.js +221 -0
  285. package/dist/heart/private-runtime/policy.js +260 -0
  286. package/dist/heart/private-runtime/types.js +2 -0
  287. package/dist/heart/progress-story.js +1 -1
  288. package/dist/heart/provider-attempt.js +137 -0
  289. package/dist/heart/provider-binding-resolver.js +273 -0
  290. package/dist/heart/provider-credentials.js +449 -0
  291. package/dist/heart/provider-failover.js +311 -0
  292. package/dist/heart/provider-models.js +96 -0
  293. package/dist/heart/provider-ping.js +265 -0
  294. package/dist/heart/provider-readiness-cache.js +119 -0
  295. package/dist/heart/provider-visibility.js +188 -0
  296. package/dist/heart/providers/anthropic-token.js +131 -0
  297. package/dist/heart/providers/anthropic.js +173 -60
  298. package/dist/heart/providers/azure.js +23 -11
  299. package/dist/heart/providers/error-classification.js +127 -0
  300. package/dist/heart/providers/github-copilot.js +34 -38
  301. package/dist/heart/providers/minimax-vlm.js +189 -0
  302. package/dist/heart/providers/minimax.js +26 -8
  303. package/dist/heart/providers/openai-codex-token.js +349 -0
  304. package/dist/heart/providers/openai-codex.js +55 -40
  305. package/dist/heart/providers/openai-compatible.js +177 -0
  306. package/dist/heart/reply-style.js +52 -0
  307. package/dist/heart/run-ledger.js +247 -0
  308. package/dist/heart/runtime-capability-check.js +170 -0
  309. package/dist/heart/runtime-credentials.js +607 -0
  310. package/dist/heart/runtime-cwd.js +87 -0
  311. package/dist/heart/sense-truth.js +24 -4
  312. package/dist/heart/session-activity.js +92 -24
  313. package/dist/heart/session-events.js +1504 -0
  314. package/dist/heart/session-playback-cli-main.js +5 -0
  315. package/dist/heart/session-playback-cli.js +36 -0
  316. package/dist/heart/session-playback.js +231 -0
  317. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  318. package/dist/heart/session-redaction-repair.js +552 -0
  319. package/dist/heart/session-stats-cli-main.js +5 -0
  320. package/dist/heart/session-stats.js +183 -0
  321. package/dist/heart/session-transcript.js +133 -0
  322. package/dist/heart/shelf-claims.js +78 -0
  323. package/dist/heart/shepherd-config.js +113 -0
  324. package/dist/heart/source-grounding.js +297 -0
  325. package/dist/heart/start-of-turn-packet.js +372 -0
  326. package/dist/heart/steward-policy.js +656 -0
  327. package/dist/heart/streaming.js +604 -207
  328. package/dist/heart/structured-output.js +196 -0
  329. package/dist/heart/sync-classification.js +176 -0
  330. package/dist/heart/sync-health.js +152 -0
  331. package/dist/heart/sync.js +726 -0
  332. package/dist/heart/target-resolution.js +11 -7
  333. package/dist/heart/tempo.js +93 -0
  334. package/dist/heart/temporal-view.js +41 -0
  335. package/dist/heart/timeouts.js +101 -0
  336. package/dist/heart/tool-activity-callbacks.js +59 -0
  337. package/dist/heart/tool-approval.js +382 -0
  338. package/dist/heart/tool-description.js +155 -0
  339. package/dist/heart/tool-friction.js +55 -0
  340. package/dist/heart/tool-loop.js +206 -0
  341. package/dist/heart/turn-context.js +494 -0
  342. package/dist/heart/turn-execution-lease.js +30 -0
  343. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  344. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  345. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  346. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  347. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  348. package/dist/heart/versioning/release-sources.js +173 -0
  349. package/dist/heart/versioning/self-update-defaults.js +294 -0
  350. package/dist/heart/versioning/self-update.js +196 -0
  351. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  352. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  353. package/dist/heart/versioning/update-hooks.js +154 -0
  354. package/dist/heart/versioning/update-state.js +126 -0
  355. package/dist/heart/versioning/updater-launchd.js +150 -0
  356. package/dist/heart/versioning/version-intent.js +114 -0
  357. package/dist/heart/work-card.js +380 -0
  358. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  359. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  360. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  361. package/dist/mailbox-ui/index.html +16 -0
  362. package/dist/mailroom/attention.js +167 -0
  363. package/dist/mailroom/autonomy.js +209 -0
  364. package/dist/mailroom/blob-store.js +889 -0
  365. package/dist/mailroom/body-cache.js +61 -0
  366. package/dist/mailroom/cache-sync-cli.js +58 -0
  367. package/dist/mailroom/core.js +803 -0
  368. package/dist/mailroom/entry.js +160 -0
  369. package/dist/mailroom/file-store.js +568 -0
  370. package/dist/mailroom/hosted-cache-sync.js +384 -0
  371. package/dist/mailroom/mbox-import.js +393 -0
  372. package/dist/mailroom/migration.js +164 -0
  373. package/dist/mailroom/outbound.js +380 -0
  374. package/dist/mailroom/policy.js +263 -0
  375. package/dist/mailroom/reader.js +292 -0
  376. package/dist/mailroom/search-cache.js +513 -0
  377. package/dist/mailroom/search-relevance.js +319 -0
  378. package/dist/mailroom/smtp-ingress.js +176 -0
  379. package/dist/mailroom/source-state.js +176 -0
  380. package/dist/mailroom/thread.js +109 -0
  381. package/dist/mailroom/travel-extract.js +89 -0
  382. package/dist/mind/bundle-manifest.js +24 -2
  383. package/dist/mind/context.js +307 -139
  384. package/dist/mind/desk-section.js +362 -0
  385. package/dist/mind/diary-integrity.js +60 -0
  386. package/dist/mind/{memory.js → diary.js} +68 -77
  387. package/dist/mind/embedding-provider.js +60 -0
  388. package/dist/mind/file-state.js +179 -0
  389. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  390. package/dist/mind/obligation-steering.js +199 -3
  391. package/dist/mind/pending.js +36 -10
  392. package/dist/mind/prompt-budget.js +479 -0
  393. package/dist/mind/prompt-refresh.js +3 -2
  394. package/dist/mind/prompt.js +1085 -198
  395. package/dist/mind/provenance-trust.js +26 -0
  396. package/dist/mind/record-paths.js +312 -0
  397. package/dist/mind/scrutiny.js +173 -0
  398. package/dist/mind/session-transaction.js +564 -0
  399. package/dist/nerves/cli-logging.js +7 -1
  400. package/dist/nerves/coverage/audit-rules.js +15 -6
  401. package/dist/nerves/coverage/audit.js +28 -2
  402. package/dist/nerves/coverage/cli.js +1 -1
  403. package/dist/nerves/coverage/contract.js +5 -5
  404. package/dist/nerves/coverage/file-completeness.js +139 -5
  405. package/dist/nerves/coverage/run-artifacts.js +55 -35
  406. package/dist/nerves/coverage/source-scanner.js +4 -4
  407. package/dist/nerves/event-buffer.js +111 -0
  408. package/dist/nerves/index.js +293 -9
  409. package/dist/nerves/observation.js +20 -0
  410. package/dist/nerves/redact.js +79 -0
  411. package/dist/nerves/review/cli-main.js +5 -0
  412. package/dist/nerves/review/cli.js +156 -0
  413. package/dist/nerves/review/core.js +159 -0
  414. package/dist/nerves/runtime.js +17 -1
  415. package/dist/repertoire/ado-client.js +15 -56
  416. package/dist/repertoire/ado-semantic.js +16 -10
  417. package/dist/repertoire/api-client.js +97 -0
  418. package/dist/repertoire/bitwarden-store.js +1201 -0
  419. package/dist/repertoire/bundle-templates.js +71 -0
  420. package/dist/repertoire/bw-installer.js +231 -0
  421. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  422. package/dist/repertoire/coding/context-pack.js +331 -0
  423. package/dist/repertoire/coding/feedback.js +174 -32
  424. package/dist/repertoire/coding/index.js +15 -3
  425. package/dist/repertoire/coding/manager.js +159 -10
  426. package/dist/repertoire/coding/spawner.js +40 -11
  427. package/dist/repertoire/coding/tools.js +182 -18
  428. package/dist/repertoire/coding/workbench-client.js +272 -0
  429. package/dist/repertoire/coding/workbench-manager.js +346 -0
  430. package/dist/repertoire/commerce-errors.js +109 -0
  431. package/dist/repertoire/commerce-self-test.js +156 -0
  432. package/dist/repertoire/credential-access.js +183 -0
  433. package/dist/repertoire/desk/classifier.js +362 -0
  434. package/dist/repertoire/duffel-client.js +185 -0
  435. package/dist/repertoire/github-client.js +14 -55
  436. package/dist/repertoire/graph-client.js +11 -52
  437. package/dist/repertoire/guardrails.js +961 -19
  438. package/dist/repertoire/house-sweep.js +469 -0
  439. package/dist/repertoire/mcp-client.js +58 -5
  440. package/dist/repertoire/mcp-manager.js +427 -139
  441. package/dist/repertoire/mcp-tools.js +132 -0
  442. package/dist/repertoire/mcp-write-guard.js +46 -0
  443. package/dist/repertoire/plugin-mcp.js +175 -0
  444. package/dist/repertoire/plugins.js +253 -0
  445. package/dist/repertoire/relationship-authorization.js +322 -0
  446. package/dist/repertoire/sanctuary-container-policy.js +46 -0
  447. package/dist/repertoire/shell-sessions.js +134 -0
  448. package/dist/repertoire/skills.js +48 -4
  449. package/dist/repertoire/stripe-client.js +131 -0
  450. package/dist/repertoire/tool-arguments.js +182 -0
  451. package/dist/repertoire/tool-results.js +29 -0
  452. package/dist/repertoire/tools-a2a.js +699 -0
  453. package/dist/repertoire/tools-attachments.js +322 -0
  454. package/dist/repertoire/tools-awaiting.js +872 -0
  455. package/dist/repertoire/tools-base.js +81 -1168
  456. package/dist/repertoire/tools-bluebubbles.js +2 -0
  457. package/dist/repertoire/tools-bridge.js +144 -0
  458. package/dist/repertoire/tools-bundle.js +995 -0
  459. package/dist/repertoire/tools-commerce.js +253 -0
  460. package/dist/repertoire/tools-config.js +186 -0
  461. package/dist/repertoire/tools-continuity.js +575 -0
  462. package/dist/repertoire/tools-credential.js +383 -0
  463. package/dist/repertoire/tools-escalation.js +84 -0
  464. package/dist/repertoire/tools-evolution.js +527 -0
  465. package/dist/repertoire/tools-files.js +344 -0
  466. package/dist/repertoire/tools-flight.js +290 -0
  467. package/dist/repertoire/tools-flow.js +119 -0
  468. package/dist/repertoire/tools-github.js +3 -8
  469. package/dist/repertoire/tools-habits.js +103 -0
  470. package/dist/repertoire/tools-house-care.js +174 -0
  471. package/dist/repertoire/tools-mail.js +1828 -0
  472. package/dist/repertoire/tools-notes.js +496 -0
  473. package/dist/repertoire/tools-obligations.js +182 -0
  474. package/dist/repertoire/tools-orientation.js +31 -0
  475. package/dist/repertoire/tools-record.js +482 -0
  476. package/dist/repertoire/tools-rsvp.js +139 -0
  477. package/dist/repertoire/tools-runtime.js +238 -0
  478. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  479. package/dist/repertoire/tools-session.js +1133 -0
  480. package/dist/repertoire/tools-shell.js +149 -0
  481. package/dist/repertoire/tools-shepherd.js +180 -0
  482. package/dist/repertoire/tools-steward-policy.js +147 -0
  483. package/dist/repertoire/tools-stripe.js +224 -0
  484. package/dist/repertoire/tools-surface.js +369 -0
  485. package/dist/repertoire/tools-teams.js +12 -39
  486. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  487. package/dist/repertoire/tools-travel.js +125 -0
  488. package/dist/repertoire/tools-trip.js +982 -0
  489. package/dist/repertoire/tools-unraid.js +556 -0
  490. package/dist/repertoire/tools-user-profile.js +146 -0
  491. package/dist/repertoire/tools-vault.js +40 -0
  492. package/dist/repertoire/tools-voice-local.js +198 -0
  493. package/dist/repertoire/tools-voice.js +145 -0
  494. package/dist/repertoire/tools.js +514 -156
  495. package/dist/repertoire/travel-api-client.js +360 -0
  496. package/dist/repertoire/unraid-client.js +155 -0
  497. package/dist/repertoire/unraid-restart.js +339 -0
  498. package/dist/repertoire/user-profile.js +131 -0
  499. package/dist/repertoire/vault-setup.js +246 -0
  500. package/dist/repertoire/vault-unlock.js +686 -0
  501. package/dist/rsvp/aisleplanner-client.js +354 -0
  502. package/dist/rsvp/cli.js +926 -0
  503. package/dist/rsvp/config.js +327 -0
  504. package/dist/rsvp/cutover.js +433 -0
  505. package/dist/rsvp/diagnostics.js +232 -0
  506. package/dist/rsvp/diff-renderer.js +176 -0
  507. package/dist/rsvp/habit-policy.js +110 -0
  508. package/dist/rsvp/habit-stage.js +123 -0
  509. package/dist/rsvp/incident-bundle.js +97 -0
  510. package/dist/rsvp/migration.js +204 -0
  511. package/dist/rsvp/native-habit-runner.js +630 -0
  512. package/dist/rsvp/outbound-state.js +628 -0
  513. package/dist/rsvp/query.js +118 -0
  514. package/dist/rsvp/replay.js +233 -0
  515. package/dist/rsvp/snapshot.js +232 -0
  516. package/dist/rsvp/spend-ledger.js +175 -0
  517. package/dist/scripts/claude-code-hook.js +41 -0
  518. package/dist/scripts/claude-code-stop-hook.js +47 -0
  519. package/dist/senses/a2a-entry.js +132 -0
  520. package/dist/senses/acp-server.js +386 -0
  521. package/dist/senses/attention-queue.js +186 -0
  522. package/dist/senses/await-turn-message.js +65 -0
  523. package/dist/senses/bluebubbles/active-turns.js +216 -0
  524. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  525. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  526. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  527. package/dist/senses/bluebubbles/context-packet.js +207 -0
  528. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  529. package/dist/senses/bluebubbles/entry.js +90 -0
  530. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  531. package/dist/senses/bluebubbles/index.js +3841 -0
  532. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  533. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  534. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  535. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  536. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  537. package/dist/senses/bluebubbles/processed-log.js +133 -0
  538. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  539. package/dist/senses/bluebubbles/replay.js +284 -0
  540. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  541. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  542. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  543. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  544. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  545. package/dist/senses/cli/bracketed-paste.js +82 -0
  546. package/dist/senses/cli/image-paste.js +287 -0
  547. package/dist/senses/cli/image-ref-navigation.js +75 -0
  548. package/dist/senses/cli/ink-app.js +156 -0
  549. package/dist/senses/cli/inline-diff.js +64 -0
  550. package/dist/senses/cli/input-keys.js +174 -0
  551. package/dist/senses/cli/kill-ring.js +86 -0
  552. package/dist/senses/cli/message-list.js +51 -0
  553. package/dist/senses/cli/ouro-tui.js +607 -0
  554. package/dist/senses/cli/spinner-imperative.js +135 -0
  555. package/dist/senses/cli/spinner.js +101 -0
  556. package/dist/senses/cli/status-line.js +60 -0
  557. package/dist/senses/cli/streaming-markdown.js +526 -0
  558. package/dist/senses/cli/tool-display.js +85 -0
  559. package/dist/senses/cli/tool-render.js +85 -0
  560. package/dist/senses/cli/tui-store.js +241 -0
  561. package/dist/senses/cli/virtual-list.js +35 -0
  562. package/dist/senses/cli-entry.js +60 -8
  563. package/dist/senses/cli.js +601 -304
  564. package/dist/senses/commands.js +66 -3
  565. package/dist/senses/context-packet-ledger.js +371 -0
  566. package/dist/senses/context-packets.js +154 -0
  567. package/dist/senses/habit-lifecycle-guard.js +24 -0
  568. package/dist/senses/habit-turn-message.js +160 -0
  569. package/dist/senses/ingress-evidence.js +2 -0
  570. package/dist/senses/mail-entry.js +66 -0
  571. package/dist/senses/mail.js +524 -0
  572. package/dist/senses/pipeline.js +1136 -204
  573. package/dist/senses/private-runtime-worker.js +859 -0
  574. package/dist/senses/private-runtime.js +1627 -0
  575. package/dist/senses/proactive-content-guard.js +51 -0
  576. package/dist/senses/root-host-approval-port.js +345 -0
  577. package/dist/senses/root-host-approval-runtime.js +393 -0
  578. package/dist/senses/sanctuary-authority-resident.js +102 -0
  579. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  580. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  581. package/dist/senses/sanctuary-grounding.js +118 -0
  582. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  583. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  584. package/dist/senses/sanctuary-health-runner.js +104 -0
  585. package/dist/senses/sanctuary-health.js +422 -0
  586. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  587. package/dist/senses/sanctuary-interactive-control.js +410 -0
  588. package/dist/senses/sanctuary-media-catalog-contract.js +259 -0
  589. package/dist/senses/sanctuary-media-optimization.js +514 -0
  590. package/dist/senses/sanctuary-runtime.js +369 -0
  591. package/dist/senses/sanctuary-sab.js +85 -0
  592. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  593. package/dist/senses/shared-turn.js +793 -0
  594. package/dist/senses/shepherd/client.js +196 -0
  595. package/dist/senses/shepherd/cmux.js +332 -0
  596. package/dist/senses/shepherd/herdr.js +315 -0
  597. package/dist/senses/shepherd/host.js +14 -0
  598. package/dist/senses/shepherd/judge.js +124 -0
  599. package/dist/senses/shepherd/redact.js +37 -0
  600. package/dist/senses/shepherd/returns.js +79 -0
  601. package/dist/senses/shepherd/sense.js +288 -0
  602. package/dist/senses/shepherd-entry.js +78 -0
  603. package/dist/senses/surface-tool.js +109 -0
  604. package/dist/senses/teams-entry.js +60 -8
  605. package/dist/senses/teams.js +519 -218
  606. package/dist/senses/telegram-admission.js +718 -0
  607. package/dist/senses/telegram-approval-runtime.js +793 -0
  608. package/dist/senses/telegram-attachments.js +186 -0
  609. package/dist/senses/telegram-audit-ledger.js +220 -0
  610. package/dist/senses/telegram-authority-transport.js +231 -0
  611. package/dist/senses/telegram-client.js +1749 -0
  612. package/dist/senses/telegram-effect-adapter.js +900 -0
  613. package/dist/senses/telegram-entry.js +83 -0
  614. package/dist/senses/telegram-handoff.js +80 -0
  615. package/dist/senses/telegram.js +2405 -0
  616. package/dist/senses/trust-gate.js +104 -9
  617. package/dist/senses/voice/audio-playback.js +237 -0
  618. package/dist/senses/voice/audio-routing.js +119 -0
  619. package/dist/senses/voice/call-auth.js +250 -0
  620. package/dist/senses/voice/elevenlabs.js +202 -0
  621. package/dist/senses/voice/floor-control.js +431 -0
  622. package/dist/senses/voice/floor-controller.js +115 -0
  623. package/dist/senses/voice/golden-path.js +116 -0
  624. package/dist/senses/voice/index.js +29 -0
  625. package/dist/senses/voice/local-audio-control.js +344 -0
  626. package/dist/senses/voice/local-audio-devices.js +516 -0
  627. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  628. package/dist/senses/voice/local-audio-identity.js +103 -0
  629. package/dist/senses/voice/local-audio-join.js +325 -0
  630. package/dist/senses/voice/local-audio-mute.js +199 -0
  631. package/dist/senses/voice/local-audio-notify.js +121 -0
  632. package/dist/senses/voice/local-audio-prompts.js +116 -0
  633. package/dist/senses/voice/local-audio-transport.js +427 -0
  634. package/dist/senses/voice/local-audio.js +281 -0
  635. package/dist/senses/voice/local-media-stream.js +145 -0
  636. package/dist/senses/voice/meeting.js +113 -0
  637. package/dist/senses/voice/outbound.js +190 -0
  638. package/dist/senses/voice/phone.js +33 -0
  639. package/dist/senses/voice/playback.js +139 -0
  640. package/dist/senses/voice/process-guards.js +51 -0
  641. package/dist/senses/voice/realtime-eval.js +496 -0
  642. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  643. package/dist/senses/voice/realtime-trace.js +531 -0
  644. package/dist/senses/voice/transcript.js +70 -0
  645. package/dist/senses/voice/turn.js +191 -0
  646. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  647. package/dist/senses/voice/twilio-phone.js +5454 -0
  648. package/dist/senses/voice/types.js +2 -0
  649. package/dist/senses/voice/whisper.js +161 -0
  650. package/dist/senses/voice-entry.js +83 -0
  651. package/dist/senses/voice-realtime-eval-command.js +99 -0
  652. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  653. package/dist/senses/voice-twilio-entry.js +87 -0
  654. package/dist/trips/core.js +138 -0
  655. package/dist/trips/store.js +265 -0
  656. package/dist/util/frontmatter.js +69 -0
  657. package/npm-shrinkwrap.json +8100 -0
  658. package/package.json +74 -13
  659. package/skills/agent-commerce.md +113 -0
  660. package/skills/browser-navigation.md +117 -0
  661. package/skills/commerce-setup-guide.md +116 -0
  662. package/skills/commerce-setup.md +84 -0
  663. package/skills/configure-dev-tools.md +99 -0
  664. package/skills/travel-planning.md +138 -0
  665. package/dist/heart/daemon/auth-flow.js +0 -430
  666. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  667. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  668. package/dist/heart/daemon/update-hooks.js +0 -138
  669. package/dist/heart/obligations.js +0 -191
  670. package/dist/heart/safe-workspace.js +0 -362
  671. package/dist/heart/session-recall.js +0 -116
  672. package/dist/mind/friends/channel.js +0 -84
  673. package/dist/mind/friends/group-context.js +0 -144
  674. package/dist/mind/friends/resolver.js +0 -84
  675. package/dist/mind/friends/store-file.js +0 -190
  676. package/dist/mind/friends/store.js +0 -4
  677. package/dist/mind/friends/tokens.js +0 -26
  678. package/dist/mind/friends/trust-explanation.js +0 -74
  679. package/dist/mind/friends/types.js +0 -29
  680. package/dist/repertoire/tasks/board.js +0 -134
  681. package/dist/repertoire/tasks/index.js +0 -224
  682. package/dist/repertoire/tasks/lifecycle.js +0 -80
  683. package/dist/repertoire/tasks/middleware.js +0 -65
  684. package/dist/repertoire/tasks/parser.js +0 -173
  685. package/dist/repertoire/tasks/scanner.js +0 -132
  686. package/dist/repertoire/tasks/transitions.js +0 -144
  687. package/dist/senses/bluebubbles-entry.js +0 -13
  688. package/dist/senses/bluebubbles.js +0 -1181
  689. package/dist/senses/debug-activity.js +0 -154
  690. package/dist/senses/inner-dialog-worker.js +0 -90
  691. package/dist/senses/inner-dialog.js +0 -525
  692. package/subagents/README.md +0 -7
  693. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  694. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  695. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  696. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  697. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  698. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  699. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  700. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  701. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  702. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  703. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  704. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  705. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  706. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  707. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  708. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  709. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanctuaryInstallStateRequiredToolCalls = sanctuaryInstallStateRequiredToolCalls;
4
+ exports.sanctuaryVersionQuestionRequiredToolCalls = sanctuaryVersionQuestionRequiredToolCalls;
5
+ const runtime_1 = require("../nerves/runtime");
6
+ const TOOL_NAME = "sanctuary_get_install_state";
7
+ const REQUEST = /\b(?:use|run|call)\s+sanctuary_get_install_state\b/iu;
8
+ const NEGATED_REQUEST = /\b(?:do not|don't|dont|never|must not|should not|cannot|can't)\s+(?:(?:under|any|all|circumstances|whatsoever|ever|please|really|actually|immediately)\s+)*(?:use|run|call)\s+sanctuary_get_install_state\b|\bnot\s+to\s+(?:use|run|call)\s+sanctuary_get_install_state\b|\b(?:do not|don't|dont)\s+(?:(?:want|need|ask)\b(?:(?![.!?;,:]).){0,64}|(?:(?:under|any|all|circumstances|whatsoever|ever|please|really|actually|immediately)\s+)*(?:attempt|try|plan|intend)\s+(?:to\s+)?)(?:use|run|call)\s+sanctuary_get_install_state\b/giu;
9
+ const HISTORICAL_QUESTION = /\b(?:did|have|has)\s+(?:you\s+)?(?:use|run|call)\s+sanctuary_get_install_state\b[^.!?;:]*/giu;
10
+ const MISMATCH_CODES = new Set([
11
+ "managed_file_missing",
12
+ "managed_file_content",
13
+ "managed_file_mode",
14
+ "bundle_meta_missing",
15
+ "bundle_meta_field",
16
+ "bundle_meta_mode",
17
+ ]);
18
+ const REPAIR_ACTIONS = new Set([
19
+ "restart_from_verified_release",
20
+ "run_verified_update_recovery",
21
+ "roll_back_or_install_verified_release",
22
+ ]);
23
+ function parseInstallState(result) {
24
+ try {
25
+ const parsed = JSON.parse(result);
26
+ const data = parsed.ok === true && parsed.data && typeof parsed.data === "object" && !Array.isArray(parsed.data)
27
+ ? parsed.data
28
+ : undefined;
29
+ const repair = data?.repair && typeof data.repair === "object" && !Array.isArray(data.repair)
30
+ ? data.repair
31
+ : undefined;
32
+ if (!data
33
+ || typeof data.runtimePackageVersion !== "string" || data.runtimePackageVersion.length === 0
34
+ || typeof data.packagedBundleVersion !== "string" || data.packagedBundleVersion.length === 0
35
+ || !(typeof data.liveBundleVersion === "string" && data.liveBundleVersion.length > 0 || data.liveBundleVersion === null)
36
+ || !["exact", "mismatch"].includes(String(data.parity))
37
+ || !Array.isArray(data.mismatchCodes)
38
+ || !data.mismatchCodes.every((code) => typeof code === "string" && MISMATCH_CODES.has(code))
39
+ || !["absent", "rollback", "committing"].includes(String(data.journalState))
40
+ || typeof data.ready !== "boolean"
41
+ || !(repair?.actor === "none" && repair.action === "none"
42
+ || repair?.actor === "human-required" && typeof repair.action === "string" && REPAIR_ACTIONS.has(repair.action)))
43
+ return undefined;
44
+ return {
45
+ runtimePackageVersion: data.runtimePackageVersion,
46
+ packagedBundleVersion: data.packagedBundleVersion,
47
+ liveBundleVersion: data.liveBundleVersion,
48
+ parity: data.parity,
49
+ journalState: data.journalState,
50
+ ready: data.ready,
51
+ repairAction: repair.action,
52
+ };
53
+ }
54
+ catch {
55
+ return undefined;
56
+ }
57
+ }
58
+ function exactAnswerPattern(current) {
59
+ const value = (raw) => raw.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
60
+ const assignment = String.raw `\s*(?:(?:is)\s+|[:=]\s*)?`;
61
+ const separator = String.raw `\s*[,;]\s*`;
62
+ return new RegExp(String.raw `runtime(?: package)?(?: version)?${assignment}${value(current.runtimePackageVersion)}${separator}`
63
+ + String.raw `packaged(?: bundle)?(?: version)?${assignment}${value(current.packagedBundleVersion)}${separator}`
64
+ + String.raw `live(?: bundle)?(?: version)?${assignment}${value(current.liveBundleVersion ?? "null")}${separator}`
65
+ + String.raw `parity${assignment}${value(current.parity)}${separator}`
66
+ + String.raw `journal(?: state)?${assignment}${value(current.journalState)}${separator}`
67
+ + String.raw `ready(?: state)?${assignment}${value(String(current.ready))}${separator}`
68
+ + String.raw `repair(?: action)?${assignment}${value(current.repairAction)}(?=$|[\s,;.!?])`, "iu");
69
+ }
70
+ const RESIDUAL_INSTALL_STATE_CLAIM = /(?:^|[.!?;,]\s*)(?:(?:and|but|however|yet)\s+)*(?:(?:the\s+)?(?:runtime(?: package)?(?: version)?|packaged(?: bundle)?(?: version)?|live(?: bundle)?(?: version)?)\s*(?:(?:is)\s+|[:=]\s*)?(?=v?\d|unknown\b|null\b|missing\b|corrupt\b)|(?:the\s+)?installed package(?: version)?\b|(?:the\s+)?parity\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:exact|mismatch)\b)|(?:the\s+)?journal(?: state)?\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:absent|rollback|committing)\b)|(?:the\s+)?ready(?: state)?\s*(?:(?:is)\s+|[:=]\s*)?(?=(?:not\s+)?(?:true|false|ready)\b)|(?:the\s+)?repair(?: action)?\s*(?:(?:is)\s+|[:=]\s*)?(?=none\b|restart_from_verified_release\b|run_verified_update_recovery\b|roll_back_or_install_verified_release\b|required\b|needed\b)|(?:the\s+)?(?:install(?:ation)?|sanctuary|bundle|service|system|it)\s+(?:is(?:\s+not)?|isn't)\s+ready\b)/iu;
71
+ function sanctuaryInstallStateRequiredToolCalls(request, advertisedToolNames) {
72
+ const normalizedRequest = request.normalize("NFKC").replace(/[‘’]/gu, "'");
73
+ const negationRequest = normalizedRequest.replace(/,/gu, " ");
74
+ const affirmativeRequest = negationRequest
75
+ .replace(NEGATED_REQUEST, " ")
76
+ .replace(HISTORICAL_QUESTION, " ");
77
+ if (!advertisedToolNames.includes(TOOL_NAME)
78
+ || !REQUEST.test(affirmativeRequest))
79
+ return undefined;
80
+ let current;
81
+ const retryMessage = "Call sanctuary_get_install_state with empty arguments, then answer only from that fresh result.";
82
+ (0, runtime_1.emitNervesEvent)({
83
+ component: "senses",
84
+ event: "senses.sanctuary_install_state_required",
85
+ message: "explicit Sanctuary install-state request requires a fresh verified read",
86
+ meta: { requiredToolName: TOOL_NAME },
87
+ });
88
+ return {
89
+ names: [TOOL_NAME],
90
+ retryMessage,
91
+ requireSuccessfulResults: true,
92
+ validateRequiredToolResult: (name, result, args) => {
93
+ if (name !== TOOL_NAME || Object.keys(args).length !== 0)
94
+ return false;
95
+ current = parseInstallState(result);
96
+ return current !== undefined;
97
+ },
98
+ validateTerminalAnswer: (answer) => {
99
+ if (!current) {
100
+ return "Answer from the fresh install-state result and include its runtime package version, packaged bundle version, live bundle version, parity, journal state, ready state, and repair action.";
101
+ }
102
+ const normalizedAnswer = answer.normalize("NFKC").replace(/[‘’]/gu, "'").replace(/\*\*|`/gu, "");
103
+ const exactMatches = [...normalizedAnswer.matchAll(new RegExp(exactAnswerPattern(current).source, "giu"))];
104
+ if (exactMatches.length === 0) {
105
+ const currentValues = [
106
+ current.runtimePackageVersion,
107
+ current.packagedBundleVersion,
108
+ current.liveBundleVersion ?? "null",
109
+ current.parity,
110
+ current.journalState,
111
+ String(current.ready),
112
+ current.repairAction,
113
+ ];
114
+ return currentValues.every((value) => normalizedAnswer.includes(value))
115
+ ? "State each fresh install-state value exactly once in one compact answer."
116
+ : "Answer from the fresh install-state result and include its runtime package version, packaged bundle version, live bundle version, parity, journal state, ready state, and repair action.";
117
+ }
118
+ if (exactMatches.length !== 1)
119
+ return "State each fresh install-state value exactly once in one compact answer.";
120
+ const match = exactMatches[0];
121
+ const residual = normalizedAnswer.replace(match[0], " ").trim();
122
+ if (RESIDUAL_INSTALL_STATE_CLAIM.test(residual))
123
+ return "State each fresh install-state value exactly once in one compact answer.";
124
+ return undefined;
125
+ },
126
+ };
127
+ }
128
+ const VERSION_QUESTION = /\b(?:what|which)(?:'s|\s+is)?\s+(?:your\s+|the\s+)?(?:current\s+|live\s+|installed\s+|running\s+)?version\b|\bversion\s+(?:are|r)\s+(?:you|u)\b|\bwhat\s+(?:are\s+you|you're)\s+(?:on|running)\b|\bare\s+you\s+(?:on|running)\s+(?:the\s+)?(?:latest|newest|new|current)\b/iu;
129
+ const VERSION_CLAIM = /\bv?\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*)?\b/gu;
130
+ /**
131
+ * A natural question about the Butler's own version must be answered from a fresh
132
+ * install-state read. After an upgrade the Butler once answered "Just checked the live
133
+ * state: 0.1.0-alpha.841" from earlier conversation while it was running 845, with no
134
+ * tool call at all. Unlike the explicit install-state contract, the wording stays free:
135
+ * only the version it states is checked against the read.
136
+ */
137
+ function sanctuaryVersionQuestionRequiredToolCalls(request, advertisedToolNames) {
138
+ const normalizedRequest = request.normalize("NFKC").replace(/[‘’]/gu, "'");
139
+ if (!advertisedToolNames.includes(TOOL_NAME) || REQUEST.test(normalizedRequest) || !VERSION_QUESTION.test(normalizedRequest))
140
+ return undefined;
141
+ let current;
142
+ (0, runtime_1.emitNervesEvent)({
143
+ component: "senses",
144
+ event: "senses.sanctuary_version_question_required",
145
+ message: "a question about the running version requires a fresh install-state read",
146
+ meta: { requiredToolName: TOOL_NAME },
147
+ });
148
+ return {
149
+ names: [TOOL_NAME],
150
+ retryMessage: "Call sanctuary_get_install_state with empty arguments now, then state the version from that fresh result, not from earlier conversation.",
151
+ requireSuccessfulResults: true,
152
+ validateRequiredToolResult: (name, result, args) => {
153
+ if (name !== TOOL_NAME || Object.keys(args).length !== 0)
154
+ return false;
155
+ current = parseInstallState(result);
156
+ return current !== undefined;
157
+ },
158
+ validateTerminalAnswer: (answer) => {
159
+ if (!current)
160
+ return "Call sanctuary_get_install_state and state the version from that fresh result.";
161
+ const known = new Set([current.runtimePackageVersion, current.packagedBundleVersion, ...(current.liveBundleVersion ? [current.liveBundleVersion] : [])].map((version) => version.replace(/^v/u, "")));
162
+ const claimed = [...answer.normalize("NFKC").matchAll(VERSION_CLAIM)].map((match) => match[0].replace(/^v/u, ""));
163
+ if (claimed.length === 0)
164
+ return `State the running version from the fresh result: ${current.runtimePackageVersion}.`;
165
+ const stale = claimed.filter((version) => !known.has(version));
166
+ return stale.length === 0 ? undefined : `The fresh install-state result says ${current.runtimePackageVersion}; do not state ${stale.join(", ")} as the current version.`;
167
+ },
168
+ };
169
+ }
@@ -0,0 +1,410 @@
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.proveSanctuaryAttemptedRecoveryWithoutRetry = proveSanctuaryAttemptedRecoveryWithoutRetry;
37
+ exports.executeSanctuaryInteractiveEngine = executeSanctuaryInteractiveEngine;
38
+ exports.createSanctuaryInteractiveControl = createSanctuaryInteractiveControl;
39
+ exports.sanctuaryInteractiveControlReady = sanctuaryInteractiveControlReady;
40
+ const node_crypto_1 = require("node:crypto");
41
+ const node_fs_1 = require("node:fs");
42
+ const node_net_1 = require("node:net");
43
+ const path = __importStar(require("node:path"));
44
+ const approval_store_1 = require("../heart/approval-store");
45
+ const tool_approval_1 = require("../heart/tool-approval");
46
+ const runtime_1 = require("../nerves/runtime");
47
+ const telegram_client_1 = require("./telegram-client");
48
+ const SHA256 = /^[0-9a-f]{64}$/u;
49
+ const MAX_CONTROL_REQUEST = 16 * 1024;
50
+ function object(value, label) {
51
+ if (!value || typeof value !== "object" || Array.isArray(value))
52
+ throw new Error(`${label} must be an object`);
53
+ return value;
54
+ }
55
+ function exactKeys(value, keys, label) {
56
+ if (JSON.stringify(Object.keys(value).sort()) !== JSON.stringify([...keys].sort()))
57
+ throw new Error(`${label} shape is invalid`);
58
+ }
59
+ function sha256(value) {
60
+ return (0, node_crypto_1.createHash)("sha256").update(value, "utf8").digest("hex");
61
+ }
62
+ function exactApproval(projections) {
63
+ const matches = projections.filter(({ approval }) => approval.toolName === "unraid_restart_container" && approval.arguments.container === "calibre-web");
64
+ if (matches.length !== 1)
65
+ throw new Error("interactive production approval is absent or ambiguous");
66
+ return matches[0];
67
+ }
68
+ function exactPending(records, approvalId) {
69
+ const validCallback = (value) => typeof value === "string" && Buffer.byteLength(value) >= 1 && Buffer.byteLength(value) <= 64;
70
+ const matches = records.filter((record) => record.approvalId === approvalId && record.deliveryState === "bound" && record.messageId !== null
71
+ && validCallback(record.approveCallbackData) && validCallback(record.denyCallbackData));
72
+ if (matches.length !== 1)
73
+ throw new Error("interactive production pending approval is absent or ambiguous");
74
+ return matches[0];
75
+ }
76
+ function exactTerminalTombstone(records, approvalId) {
77
+ const validCallback = (value) => typeof value === "string" && Buffer.byteLength(value) >= 1 && Buffer.byteLength(value) <= 64;
78
+ const matches = records.filter((record) => record.approvalId === approvalId && record.deliveryState === "terminal_tombstone" && record.messageId !== null
79
+ && validCallback(record.approveCallbackData) && validCallback(record.denyCallbackData)
80
+ && record.expiryObservation?.schemaVersion === "telegram-approval-expiry-observation-v1"
81
+ && record.expiryObservation.deadlineAt === record.expiresAt && Number.isSafeInteger(record.expiryObservation.observedAt)
82
+ && record.expiryObservation.observedAt >= record.expiresAt && typeof record.expiryObservation.evidenceMac === "string" && SHA256.test(record.expiryObservation.evidenceMac)
83
+ && Number.isSafeInteger(record.terminalizedAt) && Number(record.terminalizedAt) >= record.expiryObservation.observedAt);
84
+ if (matches.length !== 1)
85
+ throw new Error("interactive production terminal tombstone is absent or ambiguous");
86
+ return matches[0];
87
+ }
88
+ function pendingDigest(record) {
89
+ return sha256(JSON.stringify({ approvalId: record.approvalId, messageId: record.messageId, deliveryState: record.deliveryState, approveCallbackData: record.approveCallbackData, denyCallbackData: record.denyCallbackData, expiresAt: record.expiresAt }));
90
+ }
91
+ function proveSanctuaryAttemptedRecoveryWithoutRetry(agentRoot, scenarioHandleDigest, approval) {
92
+ if (!SHA256.test(scenarioHandleDigest))
93
+ throw new Error("attempted recovery scenario is invalid");
94
+ const databaseRoot = path.join(agentRoot, "state", "acceptance", "attempted-recovery-probes");
95
+ (0, node_fs_1.mkdirSync)(databaseRoot, { recursive: true, mode: 0o700 });
96
+ const databasePath = path.join(databaseRoot, `${scenarioHandleDigest}.sqlite`);
97
+ if ((0, node_fs_1.existsSync)(databasePath))
98
+ throw new Error("attempted recovery proof requires inspect-before-retry");
99
+ const instant = new Date("2026-08-21T00:00:00.000Z");
100
+ const first = (0, approval_store_1.openApprovalStore)({ databasePath, now: () => instant });
101
+ const ownerId = "acceptance-attempted-recovery";
102
+ const toolCallId = `acceptance-${approval.toolCallId}`;
103
+ const frozenAssistantMessage = structuredClone(approval.frozenAssistantMessage);
104
+ const toolCalls = frozenAssistantMessage.tool_calls;
105
+ if (!Array.isArray(toolCalls) || toolCalls.length !== 1 || !toolCalls[0] || typeof toolCalls[0] !== "object" || Array.isArray(toolCalls[0])) {
106
+ first.close();
107
+ throw new Error("attempted recovery frozen tool call is invalid");
108
+ }
109
+ toolCalls[0].id = toolCallId;
110
+ const prepared = first.prepare({
111
+ toolCallId, toolName: approval.toolName, arguments: approval.arguments,
112
+ schemaDigest: approval.schemaDigest, toolDigest: approval.toolDigest, policyDigest: approval.policyDigest, policyId: approval.policyId,
113
+ sessionKey: "acceptance:attempted-recovery", sessionPath: path.join(databaseRoot, `${scenarioHandleDigest}.session.json`),
114
+ baseSessionRevision: approval.baseSessionRevision, checkpointDigest: approval.checkpointDigest,
115
+ requesterId: "acceptance-probe", transport: "telegram", transportUserId: "acceptance-probe", transportChatId: "acceptance-probe",
116
+ expiresAt: "2099-01-01T00:00:00.000Z", frozenAssistantMessage,
117
+ });
118
+ first.activate({ approvalId: prepared.record.approvalId, checkpointDigest: prepared.record.checkpointDigest, suspendedSessionRevision: approval.suspendedSessionRevision });
119
+ first.bindPrompt({ approvalId: prepared.record.approvalId, transport: "telegram", transportChatId: "acceptance-probe", transportMessageId: "acceptance-message" });
120
+ const claimed = first.decide({
121
+ approvalId: prepared.record.approvalId, decisionToken: prepared.decisionToken, decision: "approve", requesterId: "acceptance-probe",
122
+ transport: "telegram", transportUserId: "acceptance-probe", transportChatId: "acceptance-probe", transportMessageId: "acceptance-message",
123
+ sessionKey: "acceptance:attempted-recovery", ownerId,
124
+ });
125
+ const attempted = first.markAttempted({ approvalId: claimed.approvalId, ownerId, epoch: claimed.epoch });
126
+ first.close();
127
+ const attemptedRecordDigest = sha256(JSON.stringify(attempted));
128
+ const reopened = (0, approval_store_1.openApprovalStore)({ databasePath, now: () => instant });
129
+ const durableAttempted = reopened.read(attempted.approvalId);
130
+ if (!durableAttempted || durableAttempted.state !== "attempted") {
131
+ reopened.close();
132
+ throw new Error("attempted recovery record was not durable across reopen");
133
+ }
134
+ const recovered = (0, tool_approval_1.recoverAttemptedApproval)({ approvalStore: reopened, approvalId: durableAttempted.approvalId });
135
+ let retryCount = 0;
136
+ try {
137
+ (0, tool_approval_1.recoverAttemptedApproval)({ approvalStore: reopened, approvalId: durableAttempted.approvalId });
138
+ retryCount += 1;
139
+ }
140
+ catch { /* expected */ }
141
+ reopened.close();
142
+ return { observed: recovered.state === "attempted_indeterminate", retryCount, reopened: true, attemptedRecordDigest, recoveredRecordDigest: sha256(JSON.stringify(recovered)) };
143
+ }
144
+ async function executeSanctuaryInteractiveEngine(raw, deps) {
145
+ const payload = object(raw, "interactive runtime payload");
146
+ exactKeys(payload, ["operation", "label", "scenarioHandleDigest"], "interactive runtime payload");
147
+ const operation = payload.operation;
148
+ const label = payload.label;
149
+ const scenarioHandleDigest = payload.scenarioHandleDigest;
150
+ if (typeof scenarioHandleDigest !== "string" || !SHA256.test(scenarioHandleDigest)
151
+ || !["unit-16k-timeout-stale", "unit-16l-duplicate-callback", "unit-16m-restart-continuation"].includes(label)
152
+ || !["drive_timeout_stale", "drive_duplicate_callbacks", "prepare_restart_continuation", "reconcile_restart_continuation"].includes(String(operation))
153
+ || (operation === "drive_timeout_stale") !== (label === "unit-16k-timeout-stale")
154
+ || (operation === "drive_duplicate_callbacks") !== (label === "unit-16l-duplicate-callback"))
155
+ throw new Error("interactive runtime operation binding is invalid");
156
+ const before = exactApproval(deps.readApprovals(scenarioHandleDigest));
157
+ if (!before.approval.suspendedSessionRevision)
158
+ throw new Error("interactive production approval checkpoint is unavailable");
159
+ if (operation === "drive_timeout_stale") {
160
+ if (before.approval.state === "proposed") {
161
+ exactPending(deps.readPending(), before.approval.approvalId);
162
+ return { state: "waiting" };
163
+ }
164
+ if (before.approval.state !== "expired" || before.approval.epoch !== 0)
165
+ throw new Error("timeout stale approval is not expired without a claim");
166
+ const captured = exactTerminalTombstone(deps.readPending(), before.approval.approvalId);
167
+ const session = await deps.createSession();
168
+ try {
169
+ const queryId = (0, node_crypto_1.randomBytes)(18).toString("base64url");
170
+ const result = await session.handle({ callbackData: captured.approveCallbackData, queryId, messageId: captured.messageId });
171
+ const after = exactApproval(deps.readApprovals(scenarioHandleDigest));
172
+ const promptTerminal = !session.pendingApprovalIds().includes(before.approval.approvalId);
173
+ if (!result.handled || result.accepted || result.reason !== "stale_callback" || after.approval.state !== "expired" || after.approval.epoch !== 0 || !promptTerminal) {
174
+ throw new Error("timeout stale callback proof failed");
175
+ }
176
+ return {
177
+ schemaVersion: "sanctuary-timeout-stale-driver-receipt-v1", phase: "complete", label, scenarioHandleDigest,
178
+ approvalIdDigest: sha256(before.approval.approvalId), checkpointDigest: before.approval.checkpointDigest,
179
+ suspendedSessionRevisionDigest: sha256(before.approval.suspendedSessionRevision), approvalEpochBefore: before.approval.epoch,
180
+ callbackAttempts: 1, distinctQueryCount: 1, callbackDataDigest: sha256(captured.approveCallbackData),
181
+ settledCount: 1, claimCount: 0, mutationCount: 0, staleAcknowledged: true, promptTerminal,
182
+ };
183
+ }
184
+ finally {
185
+ session.close();
186
+ }
187
+ }
188
+ if (before.approval.state !== "proposed")
189
+ throw new Error("interactive production approval is not currently proposed");
190
+ const pending = exactPending(deps.readPending(), before.approval.approvalId);
191
+ const common = { approvalIdDigest: sha256(before.approval.approvalId), checkpointDigest: before.approval.checkpointDigest, suspendedSessionRevisionDigest: sha256(before.approval.suspendedSessionRevision), approvalEpochBefore: before.approval.epoch };
192
+ if (operation === "prepare_restart_continuation") {
193
+ const recovery = deps.proveIndeterminateRecovery(before.approval, scenarioHandleDigest);
194
+ if (!recovery.observed || recovery.retryCount !== 0 || !recovery.reopened
195
+ || !SHA256.test(recovery.attemptedRecordDigest) || !SHA256.test(recovery.recoveredRecordDigest)
196
+ || recovery.attemptedRecordDigest === recovery.recoveredRecordDigest)
197
+ throw new Error("isolated attempted recovery proof failed");
198
+ return {
199
+ schemaVersion: "sanctuary-interactive-driver-receipt-v2", phase: "prepared", label, scenarioHandleDigest, ...common,
200
+ pendingDigestBefore: pendingDigest(pending), indeterminateRecoveryObserved: true,
201
+ attemptedRecoveryReopened: true, attemptedRecordDigest: recovery.attemptedRecordDigest, recoveredRecordDigest: recovery.recoveredRecordDigest,
202
+ };
203
+ }
204
+ const session = await deps.createSession();
205
+ try {
206
+ if (operation === "drive_duplicate_callbacks") {
207
+ const queryIds = [(0, node_crypto_1.randomBytes)(18).toString("base64url"), (0, node_crypto_1.randomBytes)(18).toString("base64url")];
208
+ let arrivals = 0;
209
+ let release;
210
+ const barrier = new Promise((resolve) => { release = resolve; });
211
+ const invoke = async (queryId) => { arrivals += 1; if (arrivals === 2)
212
+ release(); await barrier; return session.handle({ callbackData: pending.approveCallbackData, queryId, messageId: pending.messageId }); };
213
+ const results = await Promise.all(queryIds.map(invoke));
214
+ const after = exactApproval(deps.readApprovals(scenarioHandleDigest));
215
+ const stale = await session.handle({ callbackData: pending.approveCallbackData, queryId: (0, node_crypto_1.randomBytes)(18).toString("base64url"), messageId: pending.messageId });
216
+ return { schemaVersion: "sanctuary-interactive-driver-receipt-v2", phase: "complete", label, scenarioHandleDigest, ...common, callbackAttempts: 2, distinctQueryCount: new Set(queryIds).size, callbackDataDigest: sha256(pending.approveCallbackData), barrierObserved: arrivals === 2, settledCount: results.filter(({ handled }) => handled).length, claimCount: after.approval.epoch === before.approval.epoch + 1 ? 1 : 0, mutationCount: after.approval.state === "succeeded" ? 1 : 0, staleReplayAttempts: 1, staleReplaySettled: stale.handled, staleReplayMutationCount: 0, promptTerminal: !session.pendingApprovalIds().includes(before.approval.approvalId), writeCredentialObserved: deps.writeCredentialObserved() };
217
+ }
218
+ const result = await session.handle({ callbackData: pending.approveCallbackData, queryId: (0, node_crypto_1.randomBytes)(18).toString("base64url"), messageId: pending.messageId });
219
+ const after = exactApproval(deps.readApprovals(scenarioHandleDigest));
220
+ if (!after.continuation || after.approval.state !== "succeeded")
221
+ throw new Error("restart continuation did not complete");
222
+ return { approvalEpochAfterRestart: before.approval.epoch, continuationEpochAfter: after.continuation.continuationEpoch, pendingDigestAfter: pendingDigest(pending), pendingRestored: true, callbackAttempts: 1, mutationCount: result.accepted ? 1 : 0, indeterminateRetryCount: 0 };
223
+ }
224
+ finally {
225
+ session.close();
226
+ }
227
+ }
228
+ function createSanctuaryInteractiveControl(options) {
229
+ const socketPath = path.join(options.agentRoot, "state", "acceptance", "telegram-control.sock");
230
+ const runRequest = options.runRequest ?? (async (operation) => operation());
231
+ let server;
232
+ let endpoint;
233
+ let startPromise;
234
+ let stopPromise;
235
+ let updateId = 2_100_000_000;
236
+ const readEndpoint = () => (0, node_fs_1.lstatSync)(socketPath, { bigint: true, throwIfNoEntry: false });
237
+ // Socket mtime, unlike ctime, survives permission-only changes.
238
+ const matches = (observed, current) => current !== undefined && current.isSocket() && current.dev === observed.dev && current.ino === observed.ino
239
+ && current.birthtimeNs === observed.birthtimeNs && current.mtimeNs === observed.mtimeNs;
240
+ const stopListener = async () => {
241
+ const active = server;
242
+ if (!active)
243
+ return;
244
+ if (active.listening) {
245
+ const current = readEndpoint();
246
+ // Native Server.close() also unlinks its pathname, so ownership must precede it.
247
+ if (current && (!endpoint || !matches(endpoint, current)))
248
+ throw new Error("Sanctuary interactive control socket ownership was replaced");
249
+ await new Promise((resolve, reject) => active.close((error) => error ? reject(error) : resolve()));
250
+ }
251
+ server = undefined;
252
+ endpoint = undefined;
253
+ };
254
+ return {
255
+ socketPath,
256
+ start() {
257
+ if (startPromise)
258
+ return startPromise;
259
+ const previousStop = stopPromise;
260
+ stopPromise = undefined;
261
+ const starting = (async () => {
262
+ if (previousStop)
263
+ await previousStop;
264
+ if (server) {
265
+ if (endpoint && matches(endpoint, readEndpoint()))
266
+ return;
267
+ await stopListener();
268
+ }
269
+ (0, node_fs_1.mkdirSync)(path.dirname(socketPath), { recursive: true, mode: 0o700 });
270
+ const previous = readEndpoint();
271
+ if (previous) {
272
+ if (!previous.isSocket())
273
+ throw new Error("Sanctuary interactive control endpoint is not a socket");
274
+ await new Promise((resolve, reject) => {
275
+ const socket = (0, node_net_1.createConnection)(socketPath);
276
+ const finish = (error) => { socket.destroy(); if (error)
277
+ reject(error);
278
+ else
279
+ resolve(); };
280
+ socket.setTimeout(1_000, () => finish(new Error("Sanctuary interactive control ownership probe timed out")));
281
+ socket.once("connect", () => finish(new Error("Sanctuary interactive control endpoint has another live listener")));
282
+ socket.once("error", (error) => finish(error.code === "ECONNREFUSED" ? undefined : error));
283
+ });
284
+ const current = readEndpoint();
285
+ if (!matches(previous, current) || current.ctimeNs !== previous.ctimeNs)
286
+ throw new Error("Sanctuary interactive control endpoint was replaced during the ownership probe");
287
+ (0, node_fs_1.unlinkSync)(socketPath);
288
+ }
289
+ server = (0, node_net_1.createServer)({ allowHalfOpen: true }, (connection) => {
290
+ let raw = "";
291
+ connection.setEncoding("utf8");
292
+ connection.on("error", () => undefined);
293
+ connection.on("data", (chunk) => { raw += chunk; if (Buffer.byteLength(raw) > MAX_CONTROL_REQUEST)
294
+ connection.destroy(); });
295
+ connection.on("end", () => {
296
+ void runRequest(async () => {
297
+ try {
298
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_interactive_control_request", message: "Sanctuary interactive control request received", meta: { bytes: Buffer.byteLength(raw) } });
299
+ const parsed = object(JSON.parse(raw), "interactive control request");
300
+ if (parsed.operation === "interactive_runtime_ready") {
301
+ exactKeys(parsed, ["operation", "label", "scenarioHandleDigest"], "interactive readiness request");
302
+ if (parsed.label !== "unit-16m-restart-continuation" || typeof parsed.scenarioHandleDigest !== "string" || !SHA256.test(parsed.scenarioHandleDigest))
303
+ throw new Error("interactive readiness binding is invalid");
304
+ connection.end(`${JSON.stringify({ ok: true, result: { ready: true } })}\n`);
305
+ return;
306
+ }
307
+ const result = await executeSanctuaryInteractiveEngine(parsed, {
308
+ agentRoot: options.agentRoot,
309
+ readApprovals: (digest) => (0, approval_store_1.readApprovalsByScenarioHandleDigest)(path.join(options.agentRoot, "state", "approvals", "approvals.sqlite"), digest),
310
+ readPending: () => new telegram_client_1.FileTelegramPendingApprovalStore(path.join(options.agentRoot, "state", "approvals", "telegram-pending.json")).load(),
311
+ createSession: async () => ({
312
+ handle: ({ callbackData, queryId, messageId }) => runRequest(() => options.transport.handleUpdate({
313
+ update_id: updateId++,
314
+ callback_query: {
315
+ id: queryId,
316
+ from: { id: Number(options.authorizedUserId) },
317
+ data: callbackData,
318
+ message: {
319
+ message_id: Number(messageId),
320
+ chat: { id: Number(options.authorizedChatId) },
321
+ },
322
+ },
323
+ })),
324
+ pendingApprovalIds: () => options.transport.listPendingDeliveries().map(({ approvalId }) => approvalId),
325
+ close: () => undefined,
326
+ }),
327
+ proveIndeterminateRecovery: (approval, digest) => proveSanctuaryAttemptedRecoveryWithoutRetry(options.agentRoot, digest, approval),
328
+ writeCredentialObserved: () => /credential|api[_-]?key|token|secret/iu.test(raw),
329
+ });
330
+ connection.end(`${JSON.stringify({ ok: true, result })}\n`);
331
+ }
332
+ catch {
333
+ connection.end(`${JSON.stringify({ ok: false, error: "interactive runtime operation failed" })}\n`);
334
+ }
335
+ }).catch(() => { if (!connection.destroyed)
336
+ connection.end(`${JSON.stringify({ ok: false, error: "interactive runtime operation failed" })}\n`); });
337
+ });
338
+ });
339
+ const active = server;
340
+ try {
341
+ await new Promise((resolve, reject) => {
342
+ const onError = (error) => { active.off("listening", onListening); reject(error); };
343
+ const onListening = () => {
344
+ active.off("error", onError);
345
+ try {
346
+ if (!endpoint || !matches(endpoint, readEndpoint()))
347
+ throw new Error("Sanctuary interactive control socket ownership was replaced during startup");
348
+ resolve();
349
+ }
350
+ catch (error) {
351
+ reject(error);
352
+ }
353
+ };
354
+ active.once("error", onError);
355
+ active.once("listening", onListening);
356
+ try {
357
+ active.listen(socketPath);
358
+ if (active.listening) {
359
+ endpoint = readEndpoint();
360
+ if (!endpoint?.isSocket())
361
+ throw new Error("Sanctuary interactive control startup ownership is unproven");
362
+ (0, node_fs_1.chmodSync)(socketPath, 0o600);
363
+ endpoint = readEndpoint();
364
+ }
365
+ }
366
+ catch (error) {
367
+ active.off("error", onError);
368
+ onError(error);
369
+ }
370
+ });
371
+ }
372
+ catch (error) {
373
+ try {
374
+ await stopListener();
375
+ }
376
+ catch (cleanupError) {
377
+ throw new AggregateError([error, cleanupError], "Sanctuary interactive control startup and ownership cleanup failed");
378
+ }
379
+ throw error;
380
+ }
381
+ })().finally(() => { if (startPromise === starting)
382
+ startPromise = undefined; });
383
+ startPromise = starting;
384
+ return starting;
385
+ },
386
+ stop() {
387
+ if (stopPromise)
388
+ return stopPromise;
389
+ const starting = startPromise;
390
+ startPromise = undefined;
391
+ const stopping = (async () => {
392
+ if (starting)
393
+ await starting;
394
+ await stopListener();
395
+ })().finally(() => { if (stopPromise === stopping)
396
+ stopPromise = undefined; });
397
+ stopPromise = stopping;
398
+ return stopping;
399
+ },
400
+ };
401
+ }
402
+ async function sanctuaryInteractiveControlReady(socketPath, timeoutMs = 1_000) {
403
+ return new Promise((resolve) => {
404
+ const socket = (0, node_net_1.createConnection)(socketPath);
405
+ const finish = (ready) => { socket.destroy(); resolve(ready); };
406
+ socket.setTimeout(timeoutMs, () => finish(false));
407
+ socket.once("connect", () => finish(true));
408
+ socket.once("error", () => finish(false));
409
+ });
410
+ }