@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (647) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5308 -16
  16. package/deploy/unraid/Dockerfile +54 -0
  17. package/deploy/unraid/README.txt +2983 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  34. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  35. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
  36. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  37. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  38. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  39. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  40. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  41. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  42. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
  43. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
  49. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  50. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
  51. package/deploy/unraid/sanctuary.xml +28 -0
  52. package/dist/a2a/card.js +57 -0
  53. package/dist/a2a/client.js +180 -0
  54. package/dist/a2a/config.js +50 -0
  55. package/dist/a2a/delegation-stores.js +56 -0
  56. package/dist/a2a/did-resolution.js +93 -0
  57. package/dist/a2a/identity.js +170 -0
  58. package/dist/a2a/inbound-share.js +107 -0
  59. package/dist/a2a/mission-result-wire.js +196 -0
  60. package/dist/a2a/onboarding.js +115 -0
  61. package/dist/a2a/pin-store.js +132 -0
  62. package/dist/a2a/seen-ledger.js +120 -0
  63. package/dist/a2a/server.js +604 -0
  64. package/dist/a2a/task-store.js +69 -0
  65. package/dist/a2a/transport.js +45 -0
  66. package/dist/a2a/types.js +3 -0
  67. package/dist/arc/attention-types.js +8 -0
  68. package/dist/arc/cares.js +360 -0
  69. package/dist/arc/episodes.js +118 -0
  70. package/dist/arc/evolution.js +490 -0
  71. package/dist/arc/flight-recorder.js +1034 -0
  72. package/dist/arc/intentions.js +134 -0
  73. package/dist/arc/json-store.js +117 -0
  74. package/dist/arc/obligations.js +386 -0
  75. package/dist/arc/packets.js +336 -0
  76. package/dist/arc/presence.js +185 -0
  77. package/dist/arc/task-lifecycle.js +57 -0
  78. package/dist/commerce/store.js +755 -0
  79. package/dist/commerce/types.js +3 -0
  80. package/dist/heart/active-work.js +798 -40
  81. package/dist/heart/agent-entry.js +252 -3
  82. package/dist/heart/approval-files.js +113 -0
  83. package/dist/heart/approval-store.js +960 -0
  84. package/dist/heart/attachments/image-normalize.js +194 -0
  85. package/dist/heart/attachments/materialize.js +97 -0
  86. package/dist/heart/attachments/originals.js +88 -0
  87. package/dist/heart/attachments/render.js +29 -0
  88. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  89. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  90. package/dist/heart/attachments/sources/index.js +18 -0
  91. package/dist/heart/attachments/sources/telegram.js +71 -0
  92. package/dist/heart/attachments/store.js +132 -0
  93. package/dist/heart/attachments/types.js +93 -0
  94. package/dist/heart/auth/auth-flow.js +495 -0
  95. package/dist/heart/autonomy-budget.js +478 -0
  96. package/dist/heart/awaiting/await-alert.js +148 -0
  97. package/dist/heart/awaiting/await-expiry.js +143 -0
  98. package/dist/heart/awaiting/await-loader.js +91 -0
  99. package/dist/heart/awaiting/await-parser.js +149 -0
  100. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  101. package/dist/heart/awaiting/await-scheduler.js +382 -0
  102. package/dist/heart/background-operations.js +281 -0
  103. package/dist/heart/bridges/manager.js +137 -17
  104. package/dist/heart/bridges/store.js +14 -2
  105. package/dist/heart/bundle-state.js +168 -0
  106. package/dist/heart/commitments.js +44 -18
  107. package/dist/heart/config-registry.js +331 -0
  108. package/dist/heart/config.js +174 -131
  109. package/dist/heart/context-loss-gauntlet.js +387 -0
  110. package/dist/heart/context-loss-sentinel.js +1157 -0
  111. package/dist/heart/core.js +2169 -581
  112. package/dist/heart/cross-chat-delivery.js +9 -22
  113. package/dist/heart/daemon/agent-config-check.js +451 -0
  114. package/dist/heart/daemon/agent-discovery.js +185 -3
  115. package/dist/heart/daemon/agent-service.js +542 -0
  116. package/dist/heart/daemon/agentic-repair.js +547 -0
  117. package/dist/heart/daemon/await-private-wake.js +59 -0
  118. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  119. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  120. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  121. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  122. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  123. package/dist/heart/daemon/cadence.js +180 -0
  124. package/dist/heart/daemon/cli-defaults.js +854 -0
  125. package/dist/heart/daemon/cli-desk.js +322 -0
  126. package/dist/heart/daemon/cli-exec.js +8822 -0
  127. package/dist/heart/daemon/cli-help.js +716 -0
  128. package/dist/heart/daemon/cli-parse.js +2771 -0
  129. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  130. package/dist/heart/daemon/cli-render.js +777 -0
  131. package/dist/heart/daemon/cli-types.js +8 -0
  132. package/dist/heart/daemon/connect-bay.js +323 -0
  133. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  134. package/dist/heart/daemon/container-healthcheck.js +112 -0
  135. package/dist/heart/daemon/container-runtime.js +97 -0
  136. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  137. package/dist/heart/daemon/container-spec-auditor.js +229 -0
  138. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  139. package/dist/heart/daemon/daemon-cli.js +29 -2349
  140. package/dist/heart/daemon/daemon-entry.js +930 -11
  141. package/dist/heart/daemon/daemon-health.js +186 -0
  142. package/dist/heart/daemon/daemon-rollup.js +57 -0
  143. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  144. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  145. package/dist/heart/daemon/daemon.js +2084 -105
  146. package/dist/heart/daemon/dns-workflow.js +394 -0
  147. package/dist/heart/daemon/doctor-types.js +8 -0
  148. package/dist/heart/daemon/doctor.js +1755 -0
  149. package/dist/heart/daemon/freshness.js +345 -0
  150. package/dist/heart/daemon/habit-private-wake.js +61 -0
  151. package/dist/heart/daemon/health-monitor.js +142 -11
  152. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  153. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  154. package/dist/heart/daemon/http-health-probe.js +80 -0
  155. package/dist/heart/daemon/human-command-screens.js +234 -0
  156. package/dist/heart/daemon/human-readiness.js +114 -0
  157. package/dist/heart/daemon/inner-status.js +78 -0
  158. package/dist/heart/daemon/interactive-repair.js +394 -0
  159. package/dist/heart/daemon/launchd.js +37 -8
  160. package/dist/heart/daemon/log-tailer.js +79 -10
  161. package/dist/heart/daemon/logs-prune.js +132 -0
  162. package/dist/heart/daemon/mcp-canary.js +524 -0
  163. package/dist/heart/daemon/message-router.js +65 -5
  164. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  165. package/dist/heart/daemon/os-cron-deps.js +135 -0
  166. package/dist/heart/daemon/os-cron.js +22 -14
  167. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  168. package/dist/heart/daemon/ouro-entry.js +3 -1
  169. package/dist/heart/daemon/plugin-cli.js +432 -0
  170. package/dist/heart/daemon/process-manager.js +733 -61
  171. package/dist/heart/daemon/provider-discovery.js +137 -0
  172. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  173. package/dist/heart/daemon/prunable-bundle.js +144 -0
  174. package/dist/heart/daemon/pulse.js +511 -0
  175. package/dist/heart/daemon/readiness-repair.js +365 -0
  176. package/dist/heart/daemon/run-hooks.js +2 -0
  177. package/dist/heart/daemon/runtime-logging.js +47 -14
  178. package/dist/heart/daemon/runtime-metadata.js +2 -30
  179. package/dist/heart/daemon/runtime-mode.js +13 -2
  180. package/dist/heart/daemon/safe-mode.js +161 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  184. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  185. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  186. package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
  187. package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
  188. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  189. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
  190. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  191. package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
  192. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  193. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
  194. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  195. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  196. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  197. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  198. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  199. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  200. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  201. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
  202. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  203. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
  204. package/dist/heart/daemon/sense-manager.js +699 -48
  205. package/dist/heart/daemon/session-id-resolver.js +131 -0
  206. package/dist/heart/daemon/skill-management-installer.js +1 -1
  207. package/dist/heart/daemon/socket-client.js +180 -12
  208. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  209. package/dist/heart/daemon/startup-tui.js +339 -0
  210. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  211. package/dist/heart/daemon/task-scheduler.js +117 -39
  212. package/dist/heart/daemon/terminal-ui.js +499 -0
  213. package/dist/heart/daemon/thoughts.js +138 -54
  214. package/dist/heart/daemon/up-progress.js +366 -0
  215. package/dist/heart/daemon/vault-items.js +56 -0
  216. package/dist/heart/delegation.js +1 -4
  217. package/dist/heart/external-events/router.js +1430 -0
  218. package/dist/heart/frontend-approval-runtime.js +506 -0
  219. package/dist/heart/frontend-journal.js +215 -0
  220. package/dist/heart/frontend-session-service.js +237 -0
  221. package/dist/heart/frontend-socket-client.js +164 -0
  222. package/dist/heart/frontend-socket.js +400 -0
  223. package/dist/heart/habits/habit-cancel.js +810 -0
  224. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  225. package/dist/heart/habits/habit-migration.js +194 -0
  226. package/dist/heart/habits/habit-parser.js +278 -0
  227. package/dist/heart/habits/habit-runtime-state.js +93 -0
  228. package/dist/heart/habits/habit-scheduler.js +653 -0
  229. package/dist/heart/habits/habit-session-summary.js +318 -0
  230. package/dist/heart/habits/habit-session.js +636 -0
  231. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  232. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  233. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  234. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  235. package/dist/heart/identity.js +196 -59
  236. package/dist/heart/kept-notes.js +289 -0
  237. package/dist/heart/kicks.js +1 -1
  238. package/dist/heart/machine-identity.js +161 -0
  239. package/dist/heart/mail-import-discovery.js +356 -0
  240. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  241. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  242. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  243. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  244. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  245. package/dist/heart/mailbox/mailbox-http.js +99 -0
  246. package/dist/heart/mailbox/mailbox-read.js +39 -0
  247. package/dist/heart/mailbox/mailbox-types.js +27 -0
  248. package/dist/heart/mailbox/mailbox-view.js +197 -0
  249. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  250. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  251. package/dist/heart/mailbox/readers/mail.js +375 -0
  252. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  253. package/dist/heart/mailbox/readers/sessions.js +231 -0
  254. package/dist/heart/mailbox/readers/shared.js +111 -0
  255. package/dist/heart/mcp/mcp-server.js +696 -0
  256. package/dist/heart/migrate-config.js +100 -0
  257. package/dist/heart/model-capabilities.js +11 -0
  258. package/dist/heart/orientation-frame.js +345 -0
  259. package/dist/heart/platform.js +81 -0
  260. package/dist/heart/primitives.js +1 -1
  261. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  262. package/dist/heart/private-runtime/index.js +18 -0
  263. package/dist/heart/private-runtime/ledger.js +221 -0
  264. package/dist/heart/private-runtime/policy.js +252 -0
  265. package/dist/heart/private-runtime/types.js +2 -0
  266. package/dist/heart/progress-story.js +1 -1
  267. package/dist/heart/provider-attempt.js +137 -0
  268. package/dist/heart/provider-binding-resolver.js +273 -0
  269. package/dist/heart/provider-credentials.js +449 -0
  270. package/dist/heart/provider-failover.js +311 -0
  271. package/dist/heart/provider-models.js +96 -0
  272. package/dist/heart/provider-ping.js +265 -0
  273. package/dist/heart/provider-readiness-cache.js +119 -0
  274. package/dist/heart/provider-visibility.js +188 -0
  275. package/dist/heart/providers/anthropic-token.js +131 -0
  276. package/dist/heart/providers/anthropic.js +173 -60
  277. package/dist/heart/providers/azure.js +23 -11
  278. package/dist/heart/providers/error-classification.js +127 -0
  279. package/dist/heart/providers/github-copilot.js +34 -38
  280. package/dist/heart/providers/minimax-vlm.js +189 -0
  281. package/dist/heart/providers/minimax.js +26 -8
  282. package/dist/heart/providers/openai-codex-token.js +349 -0
  283. package/dist/heart/providers/openai-codex.js +55 -40
  284. package/dist/heart/providers/openai-compatible.js +177 -0
  285. package/dist/heart/run-ledger.js +247 -0
  286. package/dist/heart/runtime-capability-check.js +170 -0
  287. package/dist/heart/runtime-credentials.js +607 -0
  288. package/dist/heart/runtime-cwd.js +87 -0
  289. package/dist/heart/sense-truth.js +22 -4
  290. package/dist/heart/session-activity.js +92 -24
  291. package/dist/heart/session-events.js +1504 -0
  292. package/dist/heart/session-playback-cli-main.js +5 -0
  293. package/dist/heart/session-playback-cli.js +36 -0
  294. package/dist/heart/session-playback.js +231 -0
  295. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  296. package/dist/heart/session-redaction-repair.js +552 -0
  297. package/dist/heart/session-stats-cli-main.js +5 -0
  298. package/dist/heart/session-stats.js +183 -0
  299. package/dist/heart/session-transcript.js +133 -0
  300. package/dist/heart/start-of-turn-packet.js +372 -0
  301. package/dist/heart/steward-policy.js +618 -0
  302. package/dist/heart/streaming.js +604 -207
  303. package/dist/heart/structured-output.js +196 -0
  304. package/dist/heart/sync-classification.js +176 -0
  305. package/dist/heart/sync.js +449 -0
  306. package/dist/heart/target-resolution.js +11 -7
  307. package/dist/heart/tempo.js +93 -0
  308. package/dist/heart/temporal-view.js +41 -0
  309. package/dist/heart/timeouts.js +101 -0
  310. package/dist/heart/tool-activity-callbacks.js +59 -0
  311. package/dist/heart/tool-approval.js +382 -0
  312. package/dist/heart/tool-description.js +155 -0
  313. package/dist/heart/tool-friction.js +55 -0
  314. package/dist/heart/tool-loop.js +200 -0
  315. package/dist/heart/turn-context.js +482 -0
  316. package/dist/heart/turn-execution-lease.js +30 -0
  317. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  318. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  319. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  320. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  321. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  322. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  323. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  324. package/dist/heart/versioning/update-hooks.js +154 -0
  325. package/dist/heart/versioning/version-intent.js +114 -0
  326. package/dist/heart/work-card.js +380 -0
  327. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  328. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  329. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  330. package/dist/mailbox-ui/index.html +16 -0
  331. package/dist/mailroom/attention.js +167 -0
  332. package/dist/mailroom/autonomy.js +209 -0
  333. package/dist/mailroom/blob-store.js +889 -0
  334. package/dist/mailroom/body-cache.js +61 -0
  335. package/dist/mailroom/cache-sync-cli.js +58 -0
  336. package/dist/mailroom/core.js +803 -0
  337. package/dist/mailroom/entry.js +160 -0
  338. package/dist/mailroom/file-store.js +568 -0
  339. package/dist/mailroom/hosted-cache-sync.js +384 -0
  340. package/dist/mailroom/mbox-import.js +393 -0
  341. package/dist/mailroom/migration.js +164 -0
  342. package/dist/mailroom/outbound.js +380 -0
  343. package/dist/mailroom/policy.js +263 -0
  344. package/dist/mailroom/reader.js +292 -0
  345. package/dist/mailroom/search-cache.js +513 -0
  346. package/dist/mailroom/search-relevance.js +319 -0
  347. package/dist/mailroom/smtp-ingress.js +176 -0
  348. package/dist/mailroom/source-state.js +176 -0
  349. package/dist/mailroom/thread.js +109 -0
  350. package/dist/mailroom/travel-extract.js +89 -0
  351. package/dist/mind/bundle-manifest.js +24 -2
  352. package/dist/mind/context.js +309 -111
  353. package/dist/mind/desk-section.js +362 -0
  354. package/dist/mind/diary-integrity.js +60 -0
  355. package/dist/mind/{memory.js → diary.js} +68 -77
  356. package/dist/mind/embedding-provider.js +60 -0
  357. package/dist/mind/file-state.js +179 -0
  358. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  359. package/dist/mind/obligation-steering.js +199 -3
  360. package/dist/mind/pending.js +36 -10
  361. package/dist/mind/prompt-budget.js +479 -0
  362. package/dist/mind/prompt-refresh.js +3 -2
  363. package/dist/mind/prompt.js +1050 -189
  364. package/dist/mind/provenance-trust.js +26 -0
  365. package/dist/mind/record-paths.js +312 -0
  366. package/dist/mind/scrutiny.js +173 -0
  367. package/dist/mind/session-transaction.js +564 -0
  368. package/dist/nerves/cli-logging.js +7 -1
  369. package/dist/nerves/coverage/audit-rules.js +15 -6
  370. package/dist/nerves/coverage/audit.js +28 -2
  371. package/dist/nerves/coverage/cli.js +1 -1
  372. package/dist/nerves/coverage/contract.js +5 -5
  373. package/dist/nerves/coverage/file-completeness.js +139 -5
  374. package/dist/nerves/coverage/run-artifacts.js +55 -35
  375. package/dist/nerves/coverage/source-scanner.js +4 -4
  376. package/dist/nerves/event-buffer.js +111 -0
  377. package/dist/nerves/index.js +293 -9
  378. package/dist/nerves/observation.js +20 -0
  379. package/dist/nerves/redact.js +79 -0
  380. package/dist/nerves/review/cli-main.js +5 -0
  381. package/dist/nerves/review/cli.js +156 -0
  382. package/dist/nerves/review/core.js +159 -0
  383. package/dist/nerves/runtime.js +17 -1
  384. package/dist/repertoire/ado-client.js +15 -56
  385. package/dist/repertoire/ado-semantic.js +16 -10
  386. package/dist/repertoire/api-client.js +97 -0
  387. package/dist/repertoire/bitwarden-store.js +1045 -0
  388. package/dist/repertoire/bundle-templates.js +71 -0
  389. package/dist/repertoire/bw-installer.js +180 -0
  390. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  391. package/dist/repertoire/coding/context-pack.js +331 -0
  392. package/dist/repertoire/coding/feedback.js +174 -32
  393. package/dist/repertoire/coding/index.js +15 -3
  394. package/dist/repertoire/coding/manager.js +159 -10
  395. package/dist/repertoire/coding/spawner.js +58 -11
  396. package/dist/repertoire/coding/tools.js +221 -15
  397. package/dist/repertoire/coding/workbench-client.js +272 -0
  398. package/dist/repertoire/coding/workbench-manager.js +346 -0
  399. package/dist/repertoire/commerce-errors.js +109 -0
  400. package/dist/repertoire/commerce-self-test.js +156 -0
  401. package/dist/repertoire/credential-access.js +178 -0
  402. package/dist/repertoire/desk/classifier.js +362 -0
  403. package/dist/repertoire/duffel-client.js +185 -0
  404. package/dist/repertoire/github-client.js +14 -55
  405. package/dist/repertoire/graph-client.js +11 -52
  406. package/dist/repertoire/guardrails.js +811 -18
  407. package/dist/repertoire/mcp-client.js +44 -3
  408. package/dist/repertoire/mcp-manager.js +427 -139
  409. package/dist/repertoire/mcp-tools.js +124 -0
  410. package/dist/repertoire/plugin-mcp.js +175 -0
  411. package/dist/repertoire/plugins.js +253 -0
  412. package/dist/repertoire/relationship-authorization.js +322 -0
  413. package/dist/repertoire/shell-sessions.js +134 -0
  414. package/dist/repertoire/skills.js +48 -4
  415. package/dist/repertoire/stripe-client.js +131 -0
  416. package/dist/repertoire/tool-arguments.js +170 -0
  417. package/dist/repertoire/tool-results.js +29 -0
  418. package/dist/repertoire/tools-a2a.js +699 -0
  419. package/dist/repertoire/tools-attachments.js +322 -0
  420. package/dist/repertoire/tools-awaiting.js +575 -0
  421. package/dist/repertoire/tools-base.js +77 -1138
  422. package/dist/repertoire/tools-bluebubbles.js +2 -0
  423. package/dist/repertoire/tools-bridge.js +144 -0
  424. package/dist/repertoire/tools-bundle.js +993 -0
  425. package/dist/repertoire/tools-commerce.js +253 -0
  426. package/dist/repertoire/tools-config.js +186 -0
  427. package/dist/repertoire/tools-continuity.js +575 -0
  428. package/dist/repertoire/tools-credential.js +383 -0
  429. package/dist/repertoire/tools-evolution.js +527 -0
  430. package/dist/repertoire/tools-files.js +344 -0
  431. package/dist/repertoire/tools-flight.js +290 -0
  432. package/dist/repertoire/tools-flow.js +119 -0
  433. package/dist/repertoire/tools-github.js +3 -8
  434. package/dist/repertoire/tools-habits.js +103 -0
  435. package/dist/repertoire/tools-mail.js +1828 -0
  436. package/dist/repertoire/tools-notes.js +485 -0
  437. package/dist/repertoire/tools-obligations.js +182 -0
  438. package/dist/repertoire/tools-orientation.js +31 -0
  439. package/dist/repertoire/tools-record.js +482 -0
  440. package/dist/repertoire/tools-rsvp.js +139 -0
  441. package/dist/repertoire/tools-runtime.js +150 -0
  442. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  443. package/dist/repertoire/tools-session.js +1133 -0
  444. package/dist/repertoire/tools-shell.js +149 -0
  445. package/dist/repertoire/tools-steward-policy.js +119 -0
  446. package/dist/repertoire/tools-stripe.js +224 -0
  447. package/dist/repertoire/tools-surface.js +369 -0
  448. package/dist/repertoire/tools-teams.js +12 -39
  449. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  450. package/dist/repertoire/tools-travel.js +125 -0
  451. package/dist/repertoire/tools-trip.js +982 -0
  452. package/dist/repertoire/tools-unraid.js +531 -0
  453. package/dist/repertoire/tools-user-profile.js +146 -0
  454. package/dist/repertoire/tools-vault.js +40 -0
  455. package/dist/repertoire/tools-voice.js +145 -0
  456. package/dist/repertoire/tools.js +494 -148
  457. package/dist/repertoire/travel-api-client.js +360 -0
  458. package/dist/repertoire/unraid-client.js +155 -0
  459. package/dist/repertoire/unraid-restart.js +339 -0
  460. package/dist/repertoire/user-profile.js +131 -0
  461. package/dist/repertoire/vault-setup.js +246 -0
  462. package/dist/repertoire/vault-unlock.js +628 -0
  463. package/dist/rsvp/aisleplanner-client.js +354 -0
  464. package/dist/rsvp/cli.js +926 -0
  465. package/dist/rsvp/config.js +327 -0
  466. package/dist/rsvp/cutover.js +433 -0
  467. package/dist/rsvp/diagnostics.js +232 -0
  468. package/dist/rsvp/diff-renderer.js +176 -0
  469. package/dist/rsvp/habit-policy.js +110 -0
  470. package/dist/rsvp/habit-stage.js +123 -0
  471. package/dist/rsvp/incident-bundle.js +97 -0
  472. package/dist/rsvp/migration.js +204 -0
  473. package/dist/rsvp/native-habit-runner.js +630 -0
  474. package/dist/rsvp/outbound-state.js +628 -0
  475. package/dist/rsvp/query.js +118 -0
  476. package/dist/rsvp/replay.js +233 -0
  477. package/dist/rsvp/snapshot.js +232 -0
  478. package/dist/rsvp/spend-ledger.js +175 -0
  479. package/dist/scripts/claude-code-hook.js +41 -0
  480. package/dist/scripts/claude-code-stop-hook.js +47 -0
  481. package/dist/senses/a2a-entry.js +115 -0
  482. package/dist/senses/acp-server.js +386 -0
  483. package/dist/senses/attention-queue.js +186 -0
  484. package/dist/senses/await-turn-message.js +58 -0
  485. package/dist/senses/bluebubbles/active-turns.js +216 -0
  486. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  487. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  488. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  489. package/dist/senses/bluebubbles/context-packet.js +207 -0
  490. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  491. package/dist/senses/bluebubbles/entry.js +90 -0
  492. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  493. package/dist/senses/bluebubbles/index.js +3841 -0
  494. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  495. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  496. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  497. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  498. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  499. package/dist/senses/bluebubbles/processed-log.js +133 -0
  500. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  501. package/dist/senses/bluebubbles/replay.js +284 -0
  502. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  503. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  504. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  505. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  506. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  507. package/dist/senses/cli/bracketed-paste.js +82 -0
  508. package/dist/senses/cli/image-paste.js +287 -0
  509. package/dist/senses/cli/image-ref-navigation.js +75 -0
  510. package/dist/senses/cli/ink-app.js +156 -0
  511. package/dist/senses/cli/inline-diff.js +64 -0
  512. package/dist/senses/cli/input-keys.js +174 -0
  513. package/dist/senses/cli/kill-ring.js +86 -0
  514. package/dist/senses/cli/message-list.js +51 -0
  515. package/dist/senses/cli/ouro-tui.js +607 -0
  516. package/dist/senses/cli/spinner-imperative.js +135 -0
  517. package/dist/senses/cli/spinner.js +101 -0
  518. package/dist/senses/cli/status-line.js +60 -0
  519. package/dist/senses/cli/streaming-markdown.js +526 -0
  520. package/dist/senses/cli/tool-display.js +85 -0
  521. package/dist/senses/cli/tool-render.js +85 -0
  522. package/dist/senses/cli/tui-store.js +241 -0
  523. package/dist/senses/cli/virtual-list.js +35 -0
  524. package/dist/senses/cli-entry.js +60 -8
  525. package/dist/senses/cli.js +604 -320
  526. package/dist/senses/commands.js +66 -3
  527. package/dist/senses/context-packet-ledger.js +371 -0
  528. package/dist/senses/context-packets.js +154 -0
  529. package/dist/senses/habit-lifecycle-guard.js +24 -0
  530. package/dist/senses/habit-turn-message.js +160 -0
  531. package/dist/senses/ingress-evidence.js +2 -0
  532. package/dist/senses/mail-entry.js +66 -0
  533. package/dist/senses/mail.js +524 -0
  534. package/dist/senses/pipeline.js +1115 -204
  535. package/dist/senses/private-runtime-worker.js +859 -0
  536. package/dist/senses/private-runtime.js +1517 -0
  537. package/dist/senses/proactive-content-guard.js +51 -0
  538. package/dist/senses/root-host-approval-port.js +345 -0
  539. package/dist/senses/root-host-approval-runtime.js +393 -0
  540. package/dist/senses/sanctuary-authority-resident.js +102 -0
  541. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  542. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  543. package/dist/senses/sanctuary-grounding.js +118 -0
  544. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  545. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  546. package/dist/senses/sanctuary-health-runner.js +100 -0
  547. package/dist/senses/sanctuary-health.js +408 -0
  548. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  549. package/dist/senses/sanctuary-interactive-control.js +410 -0
  550. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  551. package/dist/senses/sanctuary-media-optimization.js +514 -0
  552. package/dist/senses/sanctuary-runtime.js +340 -0
  553. package/dist/senses/sanctuary-sab.js +85 -0
  554. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  555. package/dist/senses/shared-turn.js +772 -0
  556. package/dist/senses/surface-tool.js +109 -0
  557. package/dist/senses/teams-entry.js +60 -8
  558. package/dist/senses/teams.js +519 -218
  559. package/dist/senses/telegram-admission.js +718 -0
  560. package/dist/senses/telegram-approval-runtime.js +793 -0
  561. package/dist/senses/telegram-attachments.js +186 -0
  562. package/dist/senses/telegram-audit-ledger.js +220 -0
  563. package/dist/senses/telegram-authority-transport.js +231 -0
  564. package/dist/senses/telegram-client.js +1749 -0
  565. package/dist/senses/telegram-effect-adapter.js +896 -0
  566. package/dist/senses/telegram-entry.js +83 -0
  567. package/dist/senses/telegram.js +2324 -0
  568. package/dist/senses/trust-gate.js +104 -9
  569. package/dist/senses/voice/audio-playback.js +237 -0
  570. package/dist/senses/voice/audio-routing.js +119 -0
  571. package/dist/senses/voice/elevenlabs.js +202 -0
  572. package/dist/senses/voice/floor-control.js +431 -0
  573. package/dist/senses/voice/floor-controller.js +115 -0
  574. package/dist/senses/voice/golden-path.js +116 -0
  575. package/dist/senses/voice/index.js +29 -0
  576. package/dist/senses/voice/meeting.js +113 -0
  577. package/dist/senses/voice/outbound.js +190 -0
  578. package/dist/senses/voice/phone.js +33 -0
  579. package/dist/senses/voice/playback.js +139 -0
  580. package/dist/senses/voice/realtime-eval.js +496 -0
  581. package/dist/senses/voice/realtime-trace.js +531 -0
  582. package/dist/senses/voice/transcript.js +70 -0
  583. package/dist/senses/voice/turn.js +191 -0
  584. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  585. package/dist/senses/voice/twilio-phone.js +5031 -0
  586. package/dist/senses/voice/types.js +2 -0
  587. package/dist/senses/voice/whisper.js +161 -0
  588. package/dist/senses/voice-entry.js +81 -0
  589. package/dist/senses/voice-realtime-eval-command.js +99 -0
  590. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  591. package/dist/senses/voice-twilio-entry.js +87 -0
  592. package/dist/trips/core.js +138 -0
  593. package/dist/trips/store.js +265 -0
  594. package/dist/util/frontmatter.js +69 -0
  595. package/npm-shrinkwrap.json +8138 -0
  596. package/package.json +72 -13
  597. package/skills/agent-commerce.md +113 -0
  598. package/skills/browser-navigation.md +117 -0
  599. package/skills/commerce-setup-guide.md +116 -0
  600. package/skills/commerce-setup.md +84 -0
  601. package/skills/configure-dev-tools.md +99 -0
  602. package/skills/travel-planning.md +138 -0
  603. package/dist/heart/daemon/auth-flow.js +0 -430
  604. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  605. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  606. package/dist/heart/daemon/update-hooks.js +0 -138
  607. package/dist/heart/obligations.js +0 -191
  608. package/dist/heart/safe-workspace.js +0 -228
  609. package/dist/heart/session-recall.js +0 -116
  610. package/dist/mind/friends/channel.js +0 -84
  611. package/dist/mind/friends/group-context.js +0 -144
  612. package/dist/mind/friends/resolver.js +0 -84
  613. package/dist/mind/friends/store-file.js +0 -190
  614. package/dist/mind/friends/store.js +0 -4
  615. package/dist/mind/friends/tokens.js +0 -26
  616. package/dist/mind/friends/trust-explanation.js +0 -74
  617. package/dist/mind/friends/types.js +0 -29
  618. package/dist/repertoire/tasks/board.js +0 -134
  619. package/dist/repertoire/tasks/index.js +0 -224
  620. package/dist/repertoire/tasks/lifecycle.js +0 -80
  621. package/dist/repertoire/tasks/middleware.js +0 -65
  622. package/dist/repertoire/tasks/parser.js +0 -173
  623. package/dist/repertoire/tasks/scanner.js +0 -132
  624. package/dist/repertoire/tasks/transitions.js +0 -144
  625. package/dist/senses/bluebubbles-entry.js +0 -13
  626. package/dist/senses/bluebubbles.js +0 -1181
  627. package/dist/senses/debug-activity.js +0 -154
  628. package/dist/senses/inner-dialog-worker.js +0 -90
  629. package/dist/senses/inner-dialog.js +0 -525
  630. package/subagents/README.md +0 -7
  631. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  632. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  633. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  634. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  635. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  636. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  637. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  638. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  639. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  640. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  641. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  642. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  643. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  644. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  645. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  646. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  647. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,960 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ApprovalStoreError = void 0;
40
+ exports.canonicalApprovalArguments = canonicalApprovalArguments;
41
+ exports.parseApprovalRecord = parseApprovalRecord;
42
+ exports.openApprovalStore = openApprovalStore;
43
+ exports.readApprovalsByScenarioHandleDigest = readApprovalsByScenarioHandleDigest;
44
+ const node_crypto_1 = require("node:crypto");
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("node:path"));
47
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
48
+ const runtime_1 = require("../nerves/runtime");
49
+ class ApprovalStoreError extends Error {
50
+ code;
51
+ constructor(code, message = code) {
52
+ super(message);
53
+ this.name = "ApprovalStoreError";
54
+ this.code = code;
55
+ }
56
+ }
57
+ exports.ApprovalStoreError = ApprovalStoreError;
58
+ const HASH = /^[a-f0-9]{64}$/;
59
+ const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
60
+ const RECORD_KEYS = [
61
+ "approvalId", "state", "toolCallId", "toolName", "arguments", "argumentDigest", "schemaDigest",
62
+ "toolDigest", "policyDigest", "policyId", "sessionKey", "sessionPath", "baseSessionRevision",
63
+ "suspendedSessionRevision", "checkpointDigest", "requesterId", "transport", "transportUserId",
64
+ "transportChatId", "transportMessageId", "decisionTokenDigest", "expiresAt", "createdAt", "updatedAt",
65
+ "ownerId", "epoch", "attemptedAt", "result", "reason", "frozenAssistantMessage",
66
+ ];
67
+ const STATES = new Set([
68
+ "preparing", "awaiting_prompt_binding", "proposed", "claimed", "attempted", "succeeded", "failed",
69
+ "attempted_indeterminate", "denied", "expired", "drifted", "session_head_changed", "abandoned_before_attempt",
70
+ ]);
71
+ const ATTEMPT_TERMINALS = new Set(["succeeded", "failed", "attempted_indeterminate"]);
72
+ function fail(code) {
73
+ throw new ApprovalStoreError(code);
74
+ }
75
+ function isObject(value) {
76
+ return typeof value === "object" && value !== null && !Array.isArray(value);
77
+ }
78
+ function isTimestamp(value) {
79
+ return typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
80
+ }
81
+ function isNonEmpty(value) {
82
+ return typeof value === "string" && value.length > 0;
83
+ }
84
+ function processIsAlive(pid) {
85
+ try {
86
+ process.kill(pid, 0);
87
+ return true;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ function assertJsonValue(value) {
94
+ if (value === null || typeof value === "string" || typeof value === "boolean")
95
+ return;
96
+ if (typeof value === "number" && Number.isFinite(value))
97
+ return;
98
+ if (Array.isArray(value)) {
99
+ for (const item of value)
100
+ assertJsonValue(item);
101
+ return;
102
+ }
103
+ if (isObject(value)) {
104
+ for (const item of Object.values(value))
105
+ assertJsonValue(item);
106
+ return;
107
+ }
108
+ fail("invalid_json_value");
109
+ }
110
+ function canonicalize(value) {
111
+ if (value === null || typeof value !== "object")
112
+ return JSON.stringify(value);
113
+ if (Array.isArray(value))
114
+ return `[${value.map(canonicalize).join(",")}]`;
115
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalize(value[key])}`).join(",")}}`;
116
+ }
117
+ function sha256(value) {
118
+ return (0, node_crypto_1.createHash)("sha256").update(value, "utf8").digest("hex");
119
+ }
120
+ function canonicalApprovalArguments(value) {
121
+ if (!isObject(value))
122
+ fail("arguments_not_object");
123
+ assertJsonValue(value);
124
+ const canonical = canonicalize(value);
125
+ return { canonical, digest: sha256(canonical) };
126
+ }
127
+ function hasExactKeys(value) {
128
+ const actual = Object.keys(value).sort();
129
+ const expected = [...RECORD_KEYS, ...("ownerBinding" in value ? ["ownerBinding"] : [])].sort();
130
+ return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
131
+ }
132
+ function validOwnerBinding(value) {
133
+ return isObject(value) && Object.keys(value).length === 5
134
+ && ["friendId", "requestId", "sessionEventId", "sessionKey"].every((key) => isNonEmpty(value[key]) && value[key] === value[key].trim())
135
+ && typeof value.profileVersion === "number" && Number.isSafeInteger(value.profileVersion) && value.profileVersion > 0;
136
+ }
137
+ function validStateShape(record) {
138
+ const hasOwner = isNonEmpty(record.ownerId);
139
+ const hasAttempt = isTimestamp(record.attemptedAt);
140
+ const hasSuspension = typeof record.suspendedSessionRevision === "string"
141
+ && HASH.test(record.suspendedSessionRevision);
142
+ const hasPromptBinding = isNonEmpty(record.transportMessageId);
143
+ const hasValidOwnershipEpoch = hasOwner ? record.epoch > 0 : record.epoch === 0;
144
+ if (record.state === "preparing") {
145
+ return record.suspendedSessionRevision === null && record.transportMessageId === null
146
+ && !hasOwner && record.epoch === 0 && !hasAttempt && record.result === null && record.reason === null;
147
+ }
148
+ if (record.state === "awaiting_prompt_binding") {
149
+ return hasSuspension && record.transportMessageId === null
150
+ && !hasOwner && record.epoch === 0 && !hasAttempt && record.result === null && record.reason === null;
151
+ }
152
+ if (record.state === "proposed") {
153
+ return hasSuspension && hasPromptBinding
154
+ && !hasOwner && record.epoch === 0 && !hasAttempt && record.result === null && record.reason === null;
155
+ }
156
+ if (record.state === "claimed") {
157
+ return hasSuspension && hasPromptBinding && hasOwner && record.epoch > 0
158
+ && !hasAttempt && record.result === null && record.reason === null;
159
+ }
160
+ if (record.state === "attempted") {
161
+ return hasSuspension && hasPromptBinding && hasOwner && record.epoch > 0
162
+ && hasAttempt && record.result === null && record.reason === null;
163
+ }
164
+ if (ATTEMPT_TERMINALS.has(record.state)) {
165
+ return hasSuspension && hasPromptBinding && hasOwner && record.epoch > 0
166
+ && hasAttempt && isNonEmpty(record.result) && record.reason === null;
167
+ }
168
+ if (record.state === "abandoned_before_attempt") {
169
+ const validPreparingRecovery = !hasOwner && record.epoch === 0
170
+ && record.suspendedSessionRevision === null && record.transportMessageId === null;
171
+ const validPromptBindingRecovery = !hasOwner && record.epoch === 0
172
+ && hasSuspension && record.transportMessageId === null;
173
+ const validClaimRecovery = hasOwner && record.epoch > 0 && hasSuspension && hasPromptBinding;
174
+ return (validPreparingRecovery || validPromptBindingRecovery || validClaimRecovery)
175
+ && !hasAttempt && record.result === null && isNonEmpty(record.reason);
176
+ }
177
+ if (record.state === "drifted") {
178
+ const validPreparingRecovery = !hasOwner && record.epoch === 0
179
+ && record.suspendedSessionRevision === null && record.transportMessageId === null;
180
+ const validPostCheckpoint = !hasOwner && record.epoch === 0 && hasSuspension
181
+ && (hasPromptBinding || record.transportMessageId === null);
182
+ const validPostClaim = hasOwner && record.epoch > 0 && hasSuspension && hasPromptBinding;
183
+ return (validPreparingRecovery || validPostCheckpoint || validPostClaim)
184
+ && !hasAttempt && record.result === null && isNonEmpty(record.reason);
185
+ }
186
+ if (record.state === "denied") {
187
+ return hasValidOwnershipEpoch && hasSuspension && hasPromptBinding
188
+ && !hasAttempt && record.result === null && record.reason === null;
189
+ }
190
+ if (record.state === "expired") {
191
+ return !hasOwner && record.epoch === 0 && hasSuspension
192
+ && (hasPromptBinding || record.transportMessageId === null)
193
+ && !hasAttempt && record.result === null && record.reason === null;
194
+ }
195
+ if (record.state === "session_head_changed") {
196
+ return hasValidOwnershipEpoch && hasSuspension && hasPromptBinding
197
+ && !hasAttempt && record.result === null && isNonEmpty(record.reason);
198
+ }
199
+ return false;
200
+ }
201
+ function parseApprovalRecord(value) {
202
+ if (!isObject(value) || !hasExactKeys(value))
203
+ fail("corrupt_record");
204
+ if ("ownerBinding" in value && !validOwnerBinding(value.ownerBinding))
205
+ fail("corrupt_record");
206
+ const record = value;
207
+ if (!UUID.test(record.approvalId))
208
+ fail("corrupt_record");
209
+ for (const field of [
210
+ "toolCallId", "toolName", "policyId", "sessionKey", "sessionPath", "requesterId", "transport",
211
+ "transportUserId", "transportChatId",
212
+ ])
213
+ if (!isNonEmpty(record[field]))
214
+ fail("corrupt_record");
215
+ for (const field of [
216
+ "argumentDigest", "schemaDigest", "toolDigest", "policyDigest", "baseSessionRevision", "checkpointDigest",
217
+ "decisionTokenDigest",
218
+ ])
219
+ if (typeof record[field] !== "string" || !HASH.test(record[field]))
220
+ fail("corrupt_record");
221
+ if (!isObject(record.arguments) || !isObject(record.frozenAssistantMessage))
222
+ fail("corrupt_record");
223
+ assertJsonValue(record.arguments);
224
+ assertJsonValue(record.frozenAssistantMessage);
225
+ if (canonicalApprovalArguments(record.arguments).digest !== record.argumentDigest)
226
+ fail("corrupt_record");
227
+ if (!isTimestamp(record.expiresAt) || !isTimestamp(record.createdAt) || !isTimestamp(record.updatedAt))
228
+ fail("corrupt_record");
229
+ if (record.ownerId !== null && !isNonEmpty(record.ownerId))
230
+ fail("corrupt_record");
231
+ if (record.attemptedAt !== null && !isTimestamp(record.attemptedAt))
232
+ fail("corrupt_record");
233
+ if (record.reason !== null && !isNonEmpty(record.reason))
234
+ fail("corrupt_record");
235
+ if (record.result !== null && !isNonEmpty(record.result))
236
+ fail("corrupt_record");
237
+ if (record.transportMessageId !== null && !isNonEmpty(record.transportMessageId))
238
+ fail("corrupt_record");
239
+ if (record.suspendedSessionRevision !== null
240
+ && (typeof record.suspendedSessionRevision !== "string" || !HASH.test(record.suspendedSessionRevision)))
241
+ fail("corrupt_record");
242
+ if (!Number.isInteger(record.epoch) || record.epoch < 0 || !validStateShape(record) || !STATES.has(record.state))
243
+ fail("corrupt_record");
244
+ return structuredClone(record);
245
+ }
246
+ function assertHash(value, code) {
247
+ if (!HASH.test(value))
248
+ fail(code);
249
+ }
250
+ function assertPrepareInput(input) {
251
+ if (input.ownerBinding !== undefined && !validOwnerBinding(input.ownerBinding))
252
+ fail("invalid_proposal");
253
+ for (const value of [input.toolCallId, input.toolName, input.policyId, input.sessionKey, input.sessionPath,
254
+ input.requesterId, input.transport, input.transportUserId, input.transportChatId]) {
255
+ if (!isNonEmpty(value))
256
+ fail("invalid_proposal");
257
+ }
258
+ for (const value of [input.schemaDigest, input.toolDigest, input.policyDigest, input.baseSessionRevision, input.checkpointDigest]) {
259
+ assertHash(value, "invalid_proposal");
260
+ }
261
+ if (!isTimestamp(input.expiresAt) || !isObject(input.arguments) || !isObject(input.frozenAssistantMessage))
262
+ fail("invalid_proposal");
263
+ assertJsonValue(input.arguments);
264
+ assertJsonValue(input.frozenAssistantMessage);
265
+ }
266
+ function tokenMatches(token, digest) {
267
+ const actual = Buffer.from(sha256(token), "hex");
268
+ const expected = Buffer.from(digest, "hex");
269
+ return actual.length === expected.length && (0, node_crypto_1.timingSafeEqual)(actual, expected);
270
+ }
271
+ function sameDecisionBinding(record, input) {
272
+ return tokenMatches(input.decisionToken, record.decisionTokenDigest)
273
+ && input.requesterId === record.requesterId
274
+ && input.transport === record.transport
275
+ && input.transportUserId === record.transportUserId
276
+ && input.transportChatId === record.transportChatId
277
+ && input.transportMessageId === record.transportMessageId
278
+ && input.sessionKey === record.sessionKey;
279
+ }
280
+ function operationErrorMeta(operation, error) {
281
+ return {
282
+ operation,
283
+ outcome: "error",
284
+ code: error instanceof ApprovalStoreError ? error.code : "unexpected_error",
285
+ };
286
+ }
287
+ function observePrepare(operation) {
288
+ try {
289
+ const result = operation();
290
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_prepare", message: "approval store prepare completed", meta: { operation: "prepare", outcome: "success" } });
291
+ return result;
292
+ }
293
+ catch (error) {
294
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_prepare", message: "approval store prepare failed", meta: operationErrorMeta("prepare", error) });
295
+ throw error;
296
+ }
297
+ }
298
+ function observeActivate(operation) {
299
+ try {
300
+ const result = operation();
301
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_activate", message: "approval store activation completed", meta: { operation: "activate", outcome: "success" } });
302
+ return result;
303
+ }
304
+ catch (error) {
305
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_activate", message: "approval store activation failed", meta: operationErrorMeta("activate", error) });
306
+ throw error;
307
+ }
308
+ }
309
+ function observeBindPrompt(operation) {
310
+ try {
311
+ const result = operation();
312
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_bind_prompt", message: "approval prompt binding completed", meta: { operation: "bind_prompt", outcome: "success" } });
313
+ return result;
314
+ }
315
+ catch (error) {
316
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_bind_prompt", message: "approval prompt binding failed", meta: operationErrorMeta("bind_prompt", error) });
317
+ throw error;
318
+ }
319
+ }
320
+ function observeDecide(operation) {
321
+ try {
322
+ const result = operation();
323
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_decide", message: "approval decision completed", meta: { operation: "decide", outcome: "success" } });
324
+ return result;
325
+ }
326
+ catch (error) {
327
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_decide", message: "approval decision failed", meta: operationErrorMeta("decide", error) });
328
+ throw error;
329
+ }
330
+ }
331
+ function observeExpire(operation) {
332
+ try {
333
+ const result = operation();
334
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_expire", message: "approval expiry completed", meta: { operation: "expire", outcome: "success" } });
335
+ return result;
336
+ }
337
+ catch (error) {
338
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_expire", message: "approval expiry failed", meta: operationErrorMeta("expire", error) });
339
+ throw error;
340
+ }
341
+ }
342
+ function observeMarkAttempted(operation) {
343
+ try {
344
+ const result = operation();
345
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_mark_attempted", message: "approval attempt marker completed", meta: { operation: "mark_attempted", outcome: "success" } });
346
+ return result;
347
+ }
348
+ catch (error) {
349
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_mark_attempted", message: "approval attempt marker failed", meta: operationErrorMeta("mark_attempted", error) });
350
+ throw error;
351
+ }
352
+ }
353
+ function observeTerminalizeBeforeAttempt(operation) {
354
+ try {
355
+ const result = operation();
356
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_terminalize_before_attempt", message: "approval pre-attempt terminalization completed", meta: { operation: "terminalize_before_attempt", outcome: "success" } });
357
+ return result;
358
+ }
359
+ catch (error) {
360
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_terminalize_before_attempt", message: "approval pre-attempt terminalization failed", meta: operationErrorMeta("terminalize_before_attempt", error) });
361
+ throw error;
362
+ }
363
+ }
364
+ function observeAbandonBeforeAttempt(operation) {
365
+ try {
366
+ const result = operation();
367
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_abandon_before_attempt", message: "approval abandonment completed", meta: { operation: "abandon_before_attempt", outcome: "success" } });
368
+ return result;
369
+ }
370
+ catch (error) {
371
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_abandon_before_attempt", message: "approval abandonment failed", meta: operationErrorMeta("abandon_before_attempt", error) });
372
+ throw error;
373
+ }
374
+ }
375
+ function observeComplete(operation) {
376
+ try {
377
+ const result = operation();
378
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_complete", message: "approval completion completed", meta: { operation: "complete", outcome: "success" } });
379
+ return result;
380
+ }
381
+ catch (error) {
382
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_complete", message: "approval completion failed", meta: operationErrorMeta("complete", error) });
383
+ throw error;
384
+ }
385
+ }
386
+ function observeClaimContinuation(operation) {
387
+ try {
388
+ const result = operation();
389
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_claim_continuation", message: "approval continuation claim completed", meta: { operation: "claim_continuation", outcome: "success" } });
390
+ return result;
391
+ }
392
+ catch (error) {
393
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_claim_continuation", message: "approval continuation claim failed", meta: operationErrorMeta("claim_continuation", error) });
394
+ throw error;
395
+ }
396
+ }
397
+ function observeCompleteContinuation(operation) {
398
+ try {
399
+ const result = operation();
400
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_complete_continuation", message: "approval continuation completion completed", meta: { operation: "complete_continuation", outcome: "success" } });
401
+ return result;
402
+ }
403
+ catch (error) {
404
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_complete_continuation", message: "approval continuation completion failed", meta: operationErrorMeta("complete_continuation", error) });
405
+ throw error;
406
+ }
407
+ }
408
+ function observeMaterializeContinuation(operation) {
409
+ try {
410
+ const result = operation();
411
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_materialize_continuation", message: "approval continuation materialization completed", meta: { operation: "materialize_continuation", outcome: "success" } });
412
+ return result;
413
+ }
414
+ catch (error) {
415
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_materialize_continuation", message: "approval continuation materialization failed", meta: operationErrorMeta("materialize_continuation", error) });
416
+ throw error;
417
+ }
418
+ }
419
+ function observeAttemptContinuation(operation) {
420
+ try {
421
+ const result = operation();
422
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_attempt_continuation", message: "approval continuation attempt completed", meta: { operation: "attempt_continuation", outcome: "success" } });
423
+ return result;
424
+ }
425
+ catch (error) {
426
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_attempt_continuation", message: "approval continuation attempt failed", meta: operationErrorMeta("attempt_continuation", error) });
427
+ throw error;
428
+ }
429
+ }
430
+ function observeRead(operation) {
431
+ try {
432
+ const result = operation();
433
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_read", message: "approval store read completed", meta: { operation: "read", outcome: "success" } });
434
+ return result;
435
+ }
436
+ catch (error) {
437
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_read", message: "approval store read failed", meta: operationErrorMeta("read", error) });
438
+ throw error;
439
+ }
440
+ }
441
+ function observeListPreparing(operation) {
442
+ try {
443
+ const result = operation();
444
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_list_preparing", message: "preparing approval listing completed", meta: { operation: "list_preparing", outcome: "success" } });
445
+ return result;
446
+ }
447
+ catch (error) {
448
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_list_preparing", message: "preparing approval listing failed", meta: operationErrorMeta("list_preparing", error) });
449
+ throw error;
450
+ }
451
+ }
452
+ function observeRecoverPreparing(operation) {
453
+ try {
454
+ const result = operation();
455
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_recover_preparing", message: "preparing approval recovery completed", meta: { operation: "recover_preparing", outcome: "success" } });
456
+ return result;
457
+ }
458
+ catch (error) {
459
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_recover_preparing", message: "preparing approval recovery failed", meta: operationErrorMeta("recover_preparing", error) });
460
+ throw error;
461
+ }
462
+ }
463
+ function observeClose(operation) {
464
+ try {
465
+ const result = operation();
466
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.store_close", message: "approval store close completed", meta: { operation: "close", outcome: "success" } });
467
+ return result;
468
+ }
469
+ catch (error) {
470
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "heart", event: "approval.store_close", message: "approval store close failed", meta: operationErrorMeta("close", error) });
471
+ throw error;
472
+ }
473
+ }
474
+ function openApprovalStore(options) {
475
+ fs.mkdirSync(path.dirname(options.databasePath), { recursive: true });
476
+ const database = new better_sqlite3_1.default(options.databasePath);
477
+ database.pragma("journal_mode = WAL");
478
+ database.pragma("busy_timeout = 5000");
479
+ database.exec(`
480
+ CREATE TABLE IF NOT EXISTS approval_actions (
481
+ approval_id TEXT PRIMARY KEY,
482
+ state TEXT NOT NULL,
483
+ epoch INTEGER NOT NULL,
484
+ record_json TEXT NOT NULL
485
+ )
486
+ ;
487
+ CREATE TABLE IF NOT EXISTS approval_continuations (
488
+ approval_id TEXT PRIMARY KEY,
489
+ owner_id TEXT NOT NULL,
490
+ owner_pid INTEGER NOT NULL,
491
+ epoch INTEGER NOT NULL,
492
+ state TEXT NOT NULL,
493
+ claimed_at TEXT NOT NULL,
494
+ materialized_at TEXT,
495
+ attempted_at TEXT,
496
+ continued_at TEXT
497
+ )
498
+ ;
499
+ CREATE TABLE IF NOT EXISTS approval_acceptance_scenarios (
500
+ approval_id TEXT PRIMARY KEY,
501
+ scenario_handle_digest TEXT NOT NULL,
502
+ FOREIGN KEY (approval_id) REFERENCES approval_actions(approval_id)
503
+ )
504
+ ;
505
+ CREATE INDEX IF NOT EXISTS approval_acceptance_scenario_digest
506
+ ON approval_acceptance_scenarios (scenario_handle_digest)
507
+ `);
508
+ const now = options.now ?? (() => new Date());
509
+ const randomUUID = options.randomUUID ?? node_crypto_1.randomUUID;
510
+ const randomBytes = options.randomBytes ?? node_crypto_1.randomBytes;
511
+ const rawRead = (approvalId) => {
512
+ const row = database.prepare("SELECT record_json FROM approval_actions WHERE approval_id = ?")
513
+ .get(approvalId);
514
+ if (!row)
515
+ return null;
516
+ try {
517
+ return parseApprovalRecord(JSON.parse(row.record_json));
518
+ }
519
+ catch (error) {
520
+ if (error instanceof ApprovalStoreError)
521
+ throw error;
522
+ fail("corrupt_record");
523
+ }
524
+ };
525
+ const insert = (record, scenarioHandleDigest) => {
526
+ const transaction = database.transaction(() => {
527
+ database.prepare("INSERT INTO approval_actions (approval_id, state, epoch, record_json) VALUES (?, ?, ?, ?)")
528
+ .run(record.approvalId, record.state, record.epoch, JSON.stringify(record));
529
+ if (scenarioHandleDigest)
530
+ database.prepare("INSERT INTO approval_acceptance_scenarios (approval_id, scenario_handle_digest) VALUES (?, ?)")
531
+ .run(record.approvalId, scenarioHandleDigest);
532
+ });
533
+ transaction();
534
+ if (scenarioHandleDigest)
535
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.acceptance_transition", message: "acceptance-bound approval transitioned", meta: { approvalId: record.approvalId, scenarioHandleDigest, toolName: record.toolName, argumentDigest: record.argumentDigest, state: record.state } });
536
+ };
537
+ const acceptanceDigest = (approvalId) => {
538
+ const row = database.prepare("SELECT scenario_handle_digest FROM approval_acceptance_scenarios WHERE approval_id = ?")
539
+ .get(approvalId);
540
+ return row?.scenario_handle_digest ?? null;
541
+ };
542
+ const cas = (previous, next) => {
543
+ const changed = database.prepare(`
544
+ UPDATE approval_actions SET state = ?, epoch = ?, record_json = ?
545
+ WHERE approval_id = ? AND state = ? AND epoch = ? AND record_json = ?
546
+ `).run(next.state, next.epoch, JSON.stringify(next), previous.approvalId, previous.state, previous.epoch, JSON.stringify(previous));
547
+ if (changed.changes !== 1)
548
+ fail("transition_conflict");
549
+ const scenarioHandleDigest = acceptanceDigest(next.approvalId);
550
+ if (scenarioHandleDigest)
551
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.acceptance_transition", message: "acceptance-bound approval transitioned", meta: { approvalId: next.approvalId, scenarioHandleDigest, toolName: next.toolName, argumentDigest: next.argumentDigest, state: next.state } });
552
+ return structuredClone(next);
553
+ };
554
+ const requireRecord = (approvalId) => rawRead(approvalId) ?? fail("approval_not_found");
555
+ const timestamp = () => now().toISOString();
556
+ const readContinuationRow = (approvalId) => database.prepare(`
557
+ SELECT owner_id, owner_pid, epoch, state, claimed_at, materialized_at, attempted_at, continued_at
558
+ FROM approval_continuations WHERE approval_id = ?
559
+ `).get(approvalId);
560
+ const combineContinuation = (approval, row) => ({
561
+ ...approval,
562
+ continuationOwnerId: row.owner_id,
563
+ continuationOwnerPid: row.owner_pid,
564
+ continuationEpoch: row.epoch,
565
+ continuationState: row.state,
566
+ continuationClaimedAt: row.claimed_at,
567
+ continuationMaterializedAt: row.materialized_at,
568
+ continuationAttemptedAt: row.attempted_at,
569
+ continuedAt: row.continued_at,
570
+ });
571
+ const transitionContinuation = (input, from, to, timestampColumn) => {
572
+ const approval = requireRecord(input.approvalId);
573
+ const changed = database.prepare(`
574
+ UPDATE approval_continuations SET state = ?, ${timestampColumn} = ?
575
+ WHERE approval_id = ? AND owner_id = ? AND epoch = ? AND state = ?
576
+ `).run(to, timestamp(), input.approvalId, input.ownerId, input.epoch, from);
577
+ if (changed.changes !== 1)
578
+ fail(`continuation_${to}_not_eligible`);
579
+ const scenarioHandleDigest = acceptanceDigest(input.approvalId);
580
+ if (scenarioHandleDigest)
581
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.acceptance_continuation_transition", message: "acceptance-bound approval continuation transitioned", meta: { approvalId: approval.approvalId, scenarioHandleDigest, toolName: approval.toolName, argumentDigest: approval.argumentDigest, state: to } });
582
+ return combineContinuation(approval, readContinuationRow(input.approvalId));
583
+ };
584
+ return {
585
+ prepare(input) {
586
+ return observePrepare(() => {
587
+ assertPrepareInput(input);
588
+ const approvalId = randomUUID();
589
+ if (!UUID.test(approvalId))
590
+ fail("invalid_approval_id");
591
+ const tokenBytes = randomBytes(32);
592
+ if (tokenBytes.length !== 32)
593
+ fail("invalid_token_entropy");
594
+ const decisionToken = tokenBytes.toString("base64url");
595
+ const createdAt = timestamp();
596
+ const record = {
597
+ approvalId,
598
+ state: "preparing",
599
+ toolCallId: input.toolCallId,
600
+ toolName: input.toolName,
601
+ arguments: structuredClone(input.arguments),
602
+ argumentDigest: canonicalApprovalArguments(input.arguments).digest,
603
+ schemaDigest: input.schemaDigest,
604
+ toolDigest: input.toolDigest,
605
+ policyDigest: input.policyDigest,
606
+ policyId: input.policyId,
607
+ sessionKey: input.sessionKey,
608
+ sessionPath: input.sessionPath,
609
+ baseSessionRevision: input.baseSessionRevision,
610
+ suspendedSessionRevision: null,
611
+ checkpointDigest: input.checkpointDigest,
612
+ requesterId: input.requesterId,
613
+ transport: input.transport,
614
+ transportUserId: input.transportUserId,
615
+ transportChatId: input.transportChatId,
616
+ transportMessageId: null,
617
+ decisionTokenDigest: sha256(decisionToken),
618
+ expiresAt: input.expiresAt,
619
+ createdAt,
620
+ updatedAt: createdAt,
621
+ ownerId: null,
622
+ epoch: 0,
623
+ attemptedAt: null,
624
+ result: null,
625
+ reason: null,
626
+ frozenAssistantMessage: structuredClone(input.frozenAssistantMessage),
627
+ ...(input.ownerBinding ? { ownerBinding: structuredClone(input.ownerBinding) } : {}),
628
+ };
629
+ if (input.scenarioHandleDigest !== undefined)
630
+ assertHash(input.scenarioHandleDigest, "invalid_proposal");
631
+ insert(parseApprovalRecord(record), input.scenarioHandleDigest);
632
+ return { record: structuredClone(record), decisionToken };
633
+ });
634
+ },
635
+ activate(input) {
636
+ return observeActivate(() => {
637
+ const previous = requireRecord(input.approvalId);
638
+ if (previous.state !== "preparing" || input.checkpointDigest !== previous.checkpointDigest)
639
+ fail("invalid_activation");
640
+ assertHash(input.suspendedSessionRevision, "invalid_activation");
641
+ return cas(previous, { ...previous, state: "awaiting_prompt_binding", suspendedSessionRevision: input.suspendedSessionRevision, updatedAt: timestamp() });
642
+ });
643
+ },
644
+ bindPrompt(input) {
645
+ return observeBindPrompt(() => {
646
+ const previous = requireRecord(input.approvalId);
647
+ if (previous.state !== "awaiting_prompt_binding" || input.transport !== previous.transport
648
+ || input.transportChatId !== previous.transportChatId || !isNonEmpty(input.transportMessageId)
649
+ || (input.expiresAt !== undefined && !isTimestamp(input.expiresAt)))
650
+ fail("invalid_prompt_binding");
651
+ return cas(previous, { ...previous, state: "proposed", transportMessageId: input.transportMessageId, expiresAt: input.expiresAt ?? previous.expiresAt, updatedAt: timestamp() });
652
+ });
653
+ },
654
+ abandonPromptBinding(input) {
655
+ return observeAbandonBeforeAttempt(() => {
656
+ const previous = requireRecord(input.approvalId);
657
+ if (previous.state === "abandoned_before_attempt" && previous.ownerId === null
658
+ && previous.epoch === 0 && previous.reason === input.reason)
659
+ return previous;
660
+ if (previous.state !== "awaiting_prompt_binding" || !isNonEmpty(input.reason))
661
+ fail("prompt_abandon_not_eligible");
662
+ return cas(previous, {
663
+ ...previous,
664
+ state: "abandoned_before_attempt",
665
+ reason: input.reason,
666
+ updatedAt: timestamp(),
667
+ });
668
+ });
669
+ },
670
+ decide(input) {
671
+ return observeDecide(() => {
672
+ const previous = requireRecord(input.approvalId);
673
+ const decisionAt = input.decisionAt ?? now().getTime();
674
+ if (!Number.isSafeInteger(decisionAt))
675
+ fail("invalid_decision_time");
676
+ if (!sameDecisionBinding(previous, input))
677
+ fail("decision_binding_mismatch");
678
+ if (previous.state === "denied" && input.decision === "deny")
679
+ return previous;
680
+ if (previous.state !== "proposed")
681
+ fail("decision_not_eligible");
682
+ if (decisionAt >= Date.parse(previous.expiresAt)) {
683
+ return cas(previous, { ...previous, state: "expired", updatedAt: timestamp() });
684
+ }
685
+ if (input.decision === "deny") {
686
+ return cas(previous, { ...previous, state: "denied", updatedAt: timestamp() });
687
+ }
688
+ if (!isNonEmpty(input.ownerId))
689
+ fail("invalid_owner");
690
+ options.hooks?.beforeClaimCas?.();
691
+ if ((input.decisionAt ?? now().getTime()) >= Date.parse(previous.expiresAt)) {
692
+ return cas(previous, { ...previous, state: "expired", updatedAt: timestamp() });
693
+ }
694
+ return cas(previous, { ...previous, state: "claimed", ownerId: input.ownerId, epoch: previous.epoch + 1, updatedAt: timestamp() });
695
+ });
696
+ },
697
+ expire(input) {
698
+ return observeExpire(() => {
699
+ const previous = requireRecord(input.approvalId);
700
+ if (previous.state === "expired")
701
+ return previous;
702
+ if ((previous.state !== "proposed" && previous.state !== "awaiting_prompt_binding")
703
+ || now().getTime() < Date.parse(previous.expiresAt))
704
+ fail("expiry_not_eligible");
705
+ return cas(previous, { ...previous, state: "expired", updatedAt: timestamp() });
706
+ });
707
+ },
708
+ markAttempted(input) {
709
+ return observeMarkAttempted(() => {
710
+ const previous = requireRecord(input.approvalId);
711
+ if (previous.state !== "claimed" || previous.ownerId !== input.ownerId || previous.epoch !== input.epoch)
712
+ fail("attempt_not_eligible");
713
+ options.hooks?.beforeAttemptCas?.();
714
+ return cas(previous, { ...previous, state: "attempted", attemptedAt: timestamp(), updatedAt: timestamp() });
715
+ });
716
+ },
717
+ terminalizeBeforeAttempt(input) {
718
+ return observeTerminalizeBeforeAttempt(() => {
719
+ const previous = requireRecord(input.approvalId);
720
+ if (previous.state !== "claimed" || previous.ownerId !== input.ownerId || previous.epoch !== input.epoch
721
+ || (input.state !== "drifted" && input.state !== "session_head_changed") || !isNonEmpty(input.reason)) {
722
+ fail("pre_attempt_terminalization_not_eligible");
723
+ }
724
+ return cas(previous, { ...previous, state: input.state, reason: input.reason, updatedAt: timestamp() });
725
+ });
726
+ },
727
+ abandonBeforeAttempt(input) {
728
+ return observeAbandonBeforeAttempt(() => {
729
+ const previous = requireRecord(input.approvalId);
730
+ if (previous.state === "abandoned_before_attempt" && previous.ownerId === input.ownerId
731
+ && previous.epoch === input.epoch && previous.reason === input.reason)
732
+ return previous;
733
+ if (previous.state !== "claimed" || previous.ownerId !== input.ownerId || previous.epoch !== input.epoch
734
+ || !isNonEmpty(input.reason))
735
+ fail("abandon_not_eligible");
736
+ return cas(previous, { ...previous, state: "abandoned_before_attempt", reason: input.reason, updatedAt: timestamp() });
737
+ });
738
+ },
739
+ complete(input) {
740
+ return observeComplete(() => {
741
+ const previous = requireRecord(input.approvalId);
742
+ if (ATTEMPT_TERMINALS.has(previous.state)) {
743
+ if (previous.state === input.state && previous.ownerId === input.ownerId && previous.epoch === input.epoch
744
+ && previous.result === input.result)
745
+ return previous;
746
+ fail("completion_conflict");
747
+ }
748
+ if (previous.state !== "attempted" || previous.ownerId !== input.ownerId || previous.epoch !== input.epoch
749
+ || !ATTEMPT_TERMINALS.has(input.state) || !isNonEmpty(input.result))
750
+ fail("completion_not_eligible");
751
+ return cas(previous, { ...previous, state: input.state, result: input.result, updatedAt: timestamp() });
752
+ });
753
+ },
754
+ listPreparing() {
755
+ return observeListPreparing(() => {
756
+ const rows = database.prepare("SELECT record_json FROM approval_actions WHERE state = ? ORDER BY approval_id")
757
+ .all("preparing");
758
+ return rows.map((row) => {
759
+ try {
760
+ return parseApprovalRecord(JSON.parse(row.record_json));
761
+ }
762
+ catch (error) {
763
+ if (error instanceof ApprovalStoreError)
764
+ throw error;
765
+ return fail("corrupt_record");
766
+ }
767
+ });
768
+ });
769
+ },
770
+ recoverPreparing(input) {
771
+ return observeRecoverPreparing(() => {
772
+ const previous = requireRecord(input.approvalId);
773
+ if (!isNonEmpty(input.reason))
774
+ fail("recovery_not_eligible");
775
+ if (previous.state === input.state && previous.ownerId === null && previous.epoch === 0
776
+ && previous.attemptedAt === null && previous.reason === input.reason)
777
+ return previous;
778
+ if (previous.state !== "preparing")
779
+ fail("recovery_not_eligible");
780
+ return cas(previous, { ...previous, state: input.state, reason: input.reason, updatedAt: timestamp() });
781
+ });
782
+ },
783
+ claimContinuation(input) {
784
+ return observeClaimContinuation(() => {
785
+ if (!isNonEmpty(input.ownerId))
786
+ fail("invalid_continuation_owner");
787
+ const approval = requireRecord(input.approvalId);
788
+ if (!["succeeded", "failed", "denied", "expired", "drifted", "session_head_changed", "abandoned_before_attempt", "attempted_indeterminate"].includes(approval.state)) {
789
+ fail("continuation_not_eligible");
790
+ }
791
+ const ownerPid = input.ownerPid ?? process.pid;
792
+ const claimedAt = timestamp();
793
+ const inserted = database.prepare(`
794
+ INSERT OR IGNORE INTO approval_continuations
795
+ (approval_id, owner_id, owner_pid, epoch, state, claimed_at, materialized_at, attempted_at, continued_at)
796
+ VALUES (?, ?, ?, 1, 'claimed', ?, NULL, NULL, NULL)
797
+ `).run(input.approvalId, input.ownerId, ownerPid, claimedAt);
798
+ let row = readContinuationRow(input.approvalId);
799
+ let claimed = inserted.changes === 1;
800
+ let interruptedAfterAttempt = false;
801
+ if (!claimed && (row.state === "claimed" || row.state === "materialized") && !processIsAlive(row.owner_pid)) {
802
+ const reclaimed = database.prepare(`
803
+ UPDATE approval_continuations
804
+ SET owner_id = ?, owner_pid = ?, epoch = epoch + 1, claimed_at = ?
805
+ WHERE approval_id = ? AND owner_id = ? AND owner_pid = ? AND epoch = ? AND state = ?
806
+ `).run(input.ownerId, ownerPid, claimedAt, input.approvalId, row.owner_id, row.owner_pid, row.epoch, row.state);
807
+ claimed = reclaimed.changes === 1;
808
+ row = readContinuationRow(input.approvalId);
809
+ }
810
+ if (!claimed && row.state === "attempted" && !processIsAlive(row.owner_pid)) {
811
+ const terminalized = database.prepare(`
812
+ UPDATE approval_continuations
813
+ SET owner_id = ?, owner_pid = ?, epoch = epoch + 1, state = 'completed', claimed_at = ?, continued_at = ?
814
+ WHERE approval_id = ? AND owner_id = ? AND owner_pid = ? AND epoch = ? AND state = 'attempted'
815
+ `).run(input.ownerId, ownerPid, claimedAt, claimedAt, input.approvalId, row.owner_id, row.owner_pid, row.epoch);
816
+ interruptedAfterAttempt = terminalized.changes === 1;
817
+ row = readContinuationRow(input.approvalId);
818
+ }
819
+ const scenarioHandleDigest = acceptanceDigest(input.approvalId);
820
+ if (scenarioHandleDigest)
821
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.acceptance_continuation_transition", message: "acceptance-bound approval continuation transitioned", meta: { approvalId: approval.approvalId, scenarioHandleDigest, toolName: approval.toolName, argumentDigest: approval.argumentDigest, state: row.state } });
822
+ return {
823
+ claimed,
824
+ interruptedAfterAttempt,
825
+ record: combineContinuation(approval, row),
826
+ };
827
+ });
828
+ },
829
+ markContinuationMaterialized(input) {
830
+ return observeMaterializeContinuation(() => transitionContinuation(input, "claimed", "materialized", "materialized_at"));
831
+ },
832
+ markContinuationAttempted(input) {
833
+ return observeAttemptContinuation(() => transitionContinuation(input, "materialized", "attempted", "attempted_at"));
834
+ },
835
+ completeContinuation(input) {
836
+ return observeCompleteContinuation(() => {
837
+ const approval = requireRecord(input.approvalId);
838
+ const completedAt = timestamp();
839
+ const changed = database.prepare(`
840
+ UPDATE approval_continuations SET state = 'completed', continued_at = ?
841
+ WHERE approval_id = ? AND owner_id = ? AND epoch = ?
842
+ AND state IN ('materialized', 'attempted') AND continued_at IS NULL
843
+ `).run(completedAt, input.approvalId, input.ownerId, input.epoch);
844
+ if (changed.changes !== 1)
845
+ fail("continuation_completion_not_eligible");
846
+ const scenarioHandleDigest = acceptanceDigest(input.approvalId);
847
+ if (scenarioHandleDigest)
848
+ (0, runtime_1.emitNervesEvent)({ component: "heart", event: "approval.acceptance_continuation_transition", message: "acceptance-bound approval continuation transitioned", meta: { approvalId: approval.approvalId, scenarioHandleDigest, toolName: approval.toolName, argumentDigest: approval.argumentDigest, state: "completed" } });
849
+ return combineContinuation(approval, readContinuationRow(input.approvalId));
850
+ });
851
+ },
852
+ read(approvalId) { return observeRead(() => rawRead(approvalId)); },
853
+ readByScenarioHandleDigest(scenarioHandleDigest) {
854
+ assertHash(scenarioHandleDigest, "invalid_scenario_handle_digest");
855
+ const rows = database.prepare(`
856
+ SELECT a.record_json
857
+ FROM approval_actions a
858
+ INNER JOIN approval_acceptance_scenarios s ON s.approval_id = a.approval_id
859
+ WHERE s.scenario_handle_digest = ?
860
+ ORDER BY a.approval_id
861
+ `).all(scenarioHandleDigest);
862
+ return rows.map((row) => parseApprovalRecord(JSON.parse(row.record_json)));
863
+ },
864
+ listTelegramIdentitySubjects() {
865
+ const subjects = new Set();
866
+ const add = (value) => {
867
+ if (/^tg_[A-Za-z0-9_-]{43}$/u.test(value))
868
+ subjects.add(value);
869
+ };
870
+ const rows = database.prepare("SELECT record_json FROM approval_actions ORDER BY approval_id")
871
+ .all();
872
+ for (const row of rows) {
873
+ const record = parseApprovalRecord(JSON.parse(row.record_json));
874
+ if (record.transport !== "telegram")
875
+ continue;
876
+ add(record.requesterId);
877
+ add(record.transportUserId);
878
+ add(record.transportChatId);
879
+ if (record.sessionKey.startsWith("telegram:"))
880
+ add(record.sessionKey.slice("telegram:".length));
881
+ for (const match of record.sessionPath.matchAll(/tg_[A-Za-z0-9_-]{43}/gu))
882
+ add(match[0]);
883
+ }
884
+ return [...subjects].sort();
885
+ },
886
+ migrateTelegramIdentity(input) {
887
+ if (!isNonEmpty(input.legacyUserId) || !isNonEmpty(input.legacyChatId) || !/^tg_[A-Za-z0-9_-]{43}$/u.test(input.subject)) {
888
+ fail("invalid_telegram_identity_migration");
889
+ }
890
+ const rows = database.prepare("SELECT approval_id, record_json FROM approval_actions ORDER BY approval_id")
891
+ .all();
892
+ const migrate = database.transaction(() => {
893
+ let migrated = 0;
894
+ for (const row of rows) {
895
+ const previous = parseApprovalRecord(JSON.parse(row.record_json));
896
+ if (previous.transport !== "telegram")
897
+ continue;
898
+ const next = {
899
+ ...previous,
900
+ sessionKey: previous.sessionKey === `telegram:${input.legacyChatId}` ? `telegram:${input.subject}` : previous.sessionKey,
901
+ sessionPath: previous.sessionPath
902
+ .replace(`telegram-user:${input.legacyUserId}`, `telegram-user:${input.subject}`)
903
+ .replace(`telegram_${input.legacyChatId}.json`, `telegram_${input.subject}.json`),
904
+ requesterId: previous.requesterId === input.legacyUserId ? input.subject : previous.requesterId,
905
+ transportUserId: previous.transportUserId === input.legacyUserId ? input.subject : previous.transportUserId,
906
+ transportChatId: previous.transportChatId === input.legacyChatId ? input.subject : previous.transportChatId,
907
+ transportMessageId: previous.transportMessageId && !previous.transportMessageId.startsWith("tgm_")
908
+ ? `tgm_${(0, node_crypto_1.createHmac)("sha256", input.subject).update(`message:${previous.transportMessageId}`, "utf8").digest("base64url")}`
909
+ : previous.transportMessageId,
910
+ };
911
+ const nextJson = JSON.stringify(parseApprovalRecord(next));
912
+ if (nextJson === row.record_json)
913
+ continue;
914
+ const changed = database.prepare("UPDATE approval_actions SET record_json = ? WHERE approval_id = ? AND record_json = ?")
915
+ .run(nextJson, row.approval_id, row.record_json);
916
+ if (changed.changes !== 1)
917
+ fail("telegram_identity_migration_conflict");
918
+ migrated += 1;
919
+ }
920
+ return migrated;
921
+ });
922
+ const migrated = migrate();
923
+ if (migrated > 0)
924
+ database.exec("VACUUM");
925
+ return migrated;
926
+ },
927
+ close() {
928
+ return observeClose(() => {
929
+ options.hooks?.beforeClose?.();
930
+ database.close();
931
+ });
932
+ },
933
+ };
934
+ }
935
+ function readApprovalsByScenarioHandleDigest(databasePath, scenarioHandleDigest) {
936
+ assertHash(scenarioHandleDigest, "invalid_scenario_handle_digest");
937
+ const database = new better_sqlite3_1.default(databasePath, { readonly: true, fileMustExist: true });
938
+ try {
939
+ const rows = database.prepare(`
940
+ SELECT a.record_json, c.owner_id, c.owner_pid, c.epoch AS continuation_epoch, c.state AS continuation_state,
941
+ c.claimed_at, c.materialized_at, c.attempted_at AS continuation_attempted_at, c.continued_at
942
+ FROM approval_actions a
943
+ INNER JOIN approval_acceptance_scenarios s ON s.approval_id = a.approval_id
944
+ LEFT JOIN approval_continuations c ON c.approval_id = a.approval_id
945
+ WHERE s.scenario_handle_digest = ?
946
+ ORDER BY a.approval_id
947
+ `).all(scenarioHandleDigest);
948
+ return rows.map((row) => ({
949
+ approval: parseApprovalRecord(JSON.parse(row.record_json)),
950
+ continuation: row.continuation_state === null ? null : {
951
+ continuationOwnerId: row.owner_id, continuationOwnerPid: row.owner_pid, continuationEpoch: row.continuation_epoch,
952
+ continuationState: row.continuation_state, continuationClaimedAt: row.claimed_at, continuationMaterializedAt: row.materialized_at,
953
+ continuationAttemptedAt: row.continuation_attempted_at, continuedAt: row.continued_at,
954
+ },
955
+ }));
956
+ }
957
+ finally {
958
+ database.close();
959
+ }
960
+ }