@ouro.bot/cli 0.1.0-alpha.55 → 0.1.0-alpha.551

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 (386) hide show
  1. package/README.md +133 -19
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-bootstrap-drift.md +54 -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/changelog.json +3561 -0
  14. package/dist/arc/attention-types.js +8 -0
  15. package/dist/arc/cares.js +140 -0
  16. package/dist/arc/episodes.js +117 -0
  17. package/dist/arc/intentions.js +133 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +237 -0
  20. package/dist/arc/packets.js +193 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +65 -0
  23. package/dist/heart/active-work.js +837 -26
  24. package/dist/heart/agent-entry.js +58 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -0
  29. package/dist/heart/attachments/sources/adapter.js +2 -0
  30. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  31. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  32. package/dist/heart/attachments/sources/index.js +16 -0
  33. package/dist/heart/attachments/store.js +103 -0
  34. package/dist/heart/attachments/types.js +93 -0
  35. package/dist/heart/auth/auth-flow.js +479 -0
  36. package/dist/heart/background-operations.js +281 -0
  37. package/dist/heart/bundle-state.js +168 -0
  38. package/dist/heart/commitments.js +111 -0
  39. package/dist/heart/config-registry.js +304 -0
  40. package/dist/heart/config.js +114 -118
  41. package/dist/heart/core.js +925 -246
  42. package/dist/heart/cross-chat-delivery.js +3 -18
  43. package/dist/heart/daemon/agent-config-check.js +512 -0
  44. package/dist/heart/daemon/agent-discovery.js +102 -3
  45. package/dist/heart/daemon/agent-service.js +522 -0
  46. package/dist/heart/daemon/agentic-repair.js +554 -0
  47. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  48. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  49. package/dist/heart/daemon/cadence.js +70 -0
  50. package/dist/heart/daemon/cli-defaults.js +665 -0
  51. package/dist/heart/daemon/cli-exec.js +7565 -0
  52. package/dist/heart/daemon/cli-help.js +498 -0
  53. package/dist/heart/daemon/cli-parse.js +1590 -0
  54. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  55. package/dist/heart/daemon/cli-render.js +775 -0
  56. package/dist/heart/daemon/cli-types.js +8 -0
  57. package/dist/heart/daemon/connect-bay.js +323 -0
  58. package/dist/heart/daemon/daemon-cli.js +29 -1672
  59. package/dist/heart/daemon/daemon-entry.js +417 -2
  60. package/dist/heart/daemon/daemon-health.js +183 -0
  61. package/dist/heart/daemon/daemon-rollup.js +58 -0
  62. package/dist/heart/daemon/daemon-runtime-sync.js +87 -13
  63. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  64. package/dist/heart/daemon/daemon.js +796 -71
  65. package/dist/heart/daemon/dns-workflow.js +394 -0
  66. package/dist/heart/daemon/doctor-types.js +8 -0
  67. package/dist/heart/daemon/doctor.js +844 -0
  68. package/dist/heart/daemon/drift-detection.js +146 -0
  69. package/dist/heart/daemon/health-monitor.js +122 -1
  70. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  71. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  72. package/dist/heart/daemon/http-health-probe.js +80 -0
  73. package/dist/heart/daemon/human-command-screens.js +234 -0
  74. package/dist/heart/daemon/human-readiness.js +114 -0
  75. package/dist/heart/daemon/inner-status.js +102 -0
  76. package/dist/heart/daemon/interactive-repair.js +394 -0
  77. package/dist/heart/daemon/launchd.js +37 -8
  78. package/dist/heart/daemon/log-tailer.js +82 -12
  79. package/dist/heart/daemon/logs-prune.js +110 -0
  80. package/dist/heart/daemon/mcp-canary.js +297 -0
  81. package/dist/heart/daemon/message-router.js +2 -2
  82. package/dist/heart/daemon/os-cron-deps.js +135 -0
  83. package/dist/heart/daemon/os-cron.js +14 -12
  84. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  85. package/dist/heart/daemon/ouro-entry.js +3 -1
  86. package/dist/heart/daemon/process-manager.js +375 -33
  87. package/dist/heart/daemon/provider-discovery.js +137 -0
  88. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  89. package/dist/heart/daemon/pulse.js +475 -0
  90. package/dist/heart/daemon/readiness-repair.js +365 -0
  91. package/dist/heart/daemon/run-hooks.js +2 -0
  92. package/dist/heart/daemon/runtime-logging.js +67 -16
  93. package/dist/heart/daemon/runtime-metadata.js +3 -31
  94. package/dist/heart/daemon/safe-mode.js +161 -0
  95. package/dist/heart/daemon/sense-manager.js +353 -38
  96. package/dist/heart/daemon/session-id-resolver.js +131 -0
  97. package/dist/heart/daemon/skill-management-installer.js +94 -0
  98. package/dist/heart/daemon/socket-client.js +158 -11
  99. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  100. package/dist/heart/daemon/startup-tui.js +330 -0
  101. package/dist/heart/daemon/task-scheduler.js +3 -25
  102. package/dist/heart/daemon/terminal-ui.js +499 -0
  103. package/dist/heart/daemon/thoughts.js +162 -17
  104. package/dist/heart/daemon/up-progress.js +366 -0
  105. package/dist/heart/daemon/vault-items.js +56 -0
  106. package/dist/heart/delegation.js +1 -1
  107. package/dist/heart/habits/habit-migration.js +189 -0
  108. package/dist/heart/habits/habit-parser.js +140 -0
  109. package/dist/heart/habits/habit-runtime-state.js +100 -0
  110. package/dist/heart/habits/habit-scheduler.js +372 -0
  111. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  112. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  113. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  114. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  115. package/dist/heart/identity.js +200 -51
  116. package/dist/heart/kept-notes.js +357 -0
  117. package/dist/heart/kicks.js +1 -1
  118. package/dist/heart/machine-identity.js +161 -0
  119. package/dist/heart/mail-import-discovery.js +353 -0
  120. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  121. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  122. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  123. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  124. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  125. package/dist/heart/mailbox/mailbox-http.js +99 -0
  126. package/dist/heart/mailbox/mailbox-read.js +31 -0
  127. package/dist/heart/mailbox/mailbox-types.js +27 -0
  128. package/dist/heart/mailbox/mailbox-view.js +195 -0
  129. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  130. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  131. package/dist/heart/mailbox/readers/mail.js +362 -0
  132. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  133. package/dist/heart/mailbox/readers/sessions.js +232 -0
  134. package/dist/heart/mailbox/readers/shared.js +111 -0
  135. package/dist/heart/mcp/mcp-server.js +683 -0
  136. package/dist/heart/migrate-config.js +100 -0
  137. package/dist/heart/model-capabilities.js +19 -0
  138. package/dist/heart/platform.js +81 -0
  139. package/dist/heart/provider-attempt.js +134 -0
  140. package/dist/heart/provider-binding-resolver.js +255 -0
  141. package/dist/heart/provider-credentials.js +425 -0
  142. package/dist/heart/provider-failover.js +301 -0
  143. package/dist/heart/provider-models.js +81 -0
  144. package/dist/heart/provider-ping.js +262 -0
  145. package/dist/heart/provider-state.js +216 -0
  146. package/dist/heart/provider-visibility.js +188 -0
  147. package/dist/heart/providers/anthropic-token.js +131 -0
  148. package/dist/heart/providers/anthropic.js +139 -52
  149. package/dist/heart/providers/azure.js +97 -13
  150. package/dist/heart/providers/error-classification.js +127 -0
  151. package/dist/heart/providers/github-copilot.js +145 -0
  152. package/dist/heart/providers/minimax-vlm.js +189 -0
  153. package/dist/heart/providers/minimax.js +26 -8
  154. package/dist/heart/providers/openai-codex.js +55 -40
  155. package/dist/heart/runtime-capability-check.js +170 -0
  156. package/dist/heart/runtime-credentials.js +367 -0
  157. package/dist/heart/runtime-cwd.js +87 -0
  158. package/dist/heart/sense-truth.js +11 -4
  159. package/dist/heart/session-activity.js +43 -22
  160. package/dist/heart/session-events.js +1149 -0
  161. package/dist/heart/session-playback-cli-main.js +5 -0
  162. package/dist/heart/session-playback-cli.js +36 -0
  163. package/dist/heart/session-playback.js +231 -0
  164. package/dist/heart/session-stats-cli-main.js +5 -0
  165. package/dist/heart/session-stats.js +182 -0
  166. package/dist/heart/session-transcript.js +243 -0
  167. package/dist/heart/start-of-turn-packet.js +345 -0
  168. package/dist/heart/streaming.js +44 -27
  169. package/dist/heart/sync-classification.js +176 -0
  170. package/dist/heart/sync.js +449 -0
  171. package/dist/heart/target-resolution.js +9 -5
  172. package/dist/heart/tempo.js +93 -0
  173. package/dist/heart/temporal-view.js +41 -0
  174. package/dist/heart/timeouts.js +101 -0
  175. package/dist/heart/tool-activity-callbacks.js +59 -0
  176. package/dist/heart/tool-description.js +139 -0
  177. package/dist/heart/tool-friction.js +55 -0
  178. package/dist/heart/tool-loop.js +200 -0
  179. package/dist/heart/turn-context.js +381 -0
  180. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  181. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  182. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  183. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  184. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  185. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  186. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  187. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  188. package/dist/mailbox-ui/assets/index-Cm51CY9W.js +61 -0
  189. package/dist/mailbox-ui/index.html +15 -0
  190. package/dist/mailroom/attention.js +167 -0
  191. package/dist/mailroom/autonomy.js +209 -0
  192. package/dist/mailroom/blob-store.js +674 -0
  193. package/dist/mailroom/body-cache.js +61 -0
  194. package/dist/mailroom/core.js +720 -0
  195. package/dist/mailroom/entry.js +160 -0
  196. package/dist/mailroom/file-store.js +430 -0
  197. package/dist/mailroom/mbox-import.js +383 -0
  198. package/dist/mailroom/outbound.js +380 -0
  199. package/dist/mailroom/policy.js +263 -0
  200. package/dist/mailroom/reader.js +233 -0
  201. package/dist/mailroom/search-cache.js +256 -0
  202. package/dist/mailroom/search-relevance.js +319 -0
  203. package/dist/mailroom/smtp-ingress.js +176 -0
  204. package/dist/mailroom/source-state.js +176 -0
  205. package/dist/mailroom/thread.js +109 -0
  206. package/dist/mailroom/travel-extract.js +89 -0
  207. package/dist/mind/bundle-manifest.js +7 -1
  208. package/dist/mind/context.js +165 -101
  209. package/dist/mind/diary-integrity.js +60 -0
  210. package/dist/mind/{memory.js → diary.js} +62 -75
  211. package/dist/mind/embedding-provider.js +60 -0
  212. package/dist/mind/file-state.js +179 -0
  213. package/dist/mind/friends/channel.js +30 -0
  214. package/dist/mind/friends/resolver.js +54 -2
  215. package/dist/mind/friends/store-file.js +39 -3
  216. package/dist/mind/friends/types.js +2 -2
  217. package/dist/mind/journal-index.js +161 -0
  218. package/dist/mind/note-search.js +268 -0
  219. package/dist/mind/obligation-steering.js +221 -0
  220. package/dist/mind/pending.js +4 -0
  221. package/dist/mind/prompt-refresh.js +3 -2
  222. package/dist/mind/prompt.js +995 -123
  223. package/dist/mind/provenance-trust.js +26 -0
  224. package/dist/mind/scrutiny.js +173 -0
  225. package/dist/nerves/cli-logging.js +7 -1
  226. package/dist/nerves/coverage/audit-rules.js +15 -6
  227. package/dist/nerves/coverage/audit.js +28 -2
  228. package/dist/nerves/coverage/cli.js +1 -1
  229. package/dist/nerves/coverage/contract.js +5 -5
  230. package/dist/nerves/coverage/file-completeness.js +139 -5
  231. package/dist/nerves/coverage/run-artifacts.js +1 -1
  232. package/dist/nerves/event-buffer.js +111 -0
  233. package/dist/nerves/index.js +224 -4
  234. package/dist/nerves/observation.js +20 -0
  235. package/dist/nerves/redact.js +79 -0
  236. package/dist/nerves/review/cli-main.js +5 -0
  237. package/dist/nerves/review/cli.js +156 -0
  238. package/dist/nerves/review/core.js +152 -0
  239. package/dist/nerves/runtime.js +5 -1
  240. package/dist/repertoire/ado-client.js +15 -56
  241. package/dist/repertoire/ado-semantic.js +11 -10
  242. package/dist/repertoire/api-client.js +97 -0
  243. package/dist/repertoire/bitwarden-store.js +816 -0
  244. package/dist/repertoire/bundle-templates.js +72 -0
  245. package/dist/repertoire/bw-installer.js +180 -0
  246. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  247. package/dist/repertoire/coding/context-pack.js +330 -0
  248. package/dist/repertoire/coding/feedback.js +197 -30
  249. package/dist/repertoire/coding/manager.js +158 -9
  250. package/dist/repertoire/coding/spawner.js +55 -9
  251. package/dist/repertoire/coding/tools.js +170 -7
  252. package/dist/repertoire/commerce-errors.js +109 -0
  253. package/dist/repertoire/commerce-self-test.js +156 -0
  254. package/dist/repertoire/credential-access.js +111 -0
  255. package/dist/repertoire/duffel-client.js +185 -0
  256. package/dist/repertoire/github-client.js +14 -55
  257. package/dist/repertoire/graph-client.js +11 -52
  258. package/dist/repertoire/guardrails.js +396 -0
  259. package/dist/repertoire/mcp-client.js +295 -0
  260. package/dist/repertoire/mcp-manager.js +362 -0
  261. package/dist/repertoire/mcp-tools.js +63 -0
  262. package/dist/repertoire/shell-sessions.js +133 -0
  263. package/dist/repertoire/skills.js +15 -24
  264. package/dist/repertoire/stripe-client.js +131 -0
  265. package/dist/repertoire/tasks/board.js +31 -5
  266. package/dist/repertoire/tasks/fix.js +182 -0
  267. package/dist/repertoire/tasks/index.js +16 -4
  268. package/dist/repertoire/tasks/lifecycle.js +2 -2
  269. package/dist/repertoire/tasks/parser.js +3 -2
  270. package/dist/repertoire/tasks/scanner.js +194 -37
  271. package/dist/repertoire/tasks/transitions.js +16 -78
  272. package/dist/repertoire/tool-results.js +29 -0
  273. package/dist/repertoire/tools-attachments.js +317 -0
  274. package/dist/repertoire/tools-base.js +47 -1075
  275. package/dist/repertoire/tools-bluebubbles.js +1 -0
  276. package/dist/repertoire/tools-bridge.js +142 -0
  277. package/dist/repertoire/tools-bundle.js +984 -0
  278. package/dist/repertoire/tools-config.js +185 -0
  279. package/dist/repertoire/tools-continuity.js +248 -0
  280. package/dist/repertoire/tools-credential.js +381 -0
  281. package/dist/repertoire/tools-files.js +342 -0
  282. package/dist/repertoire/tools-flight.js +224 -0
  283. package/dist/repertoire/tools-flow.js +119 -0
  284. package/dist/repertoire/tools-github.js +1 -7
  285. package/dist/repertoire/tools-mail.js +1857 -0
  286. package/dist/repertoire/tools-notes.js +421 -0
  287. package/dist/repertoire/tools-session.js +750 -0
  288. package/dist/repertoire/tools-shell.js +120 -0
  289. package/dist/repertoire/tools-stripe.js +180 -0
  290. package/dist/repertoire/tools-surface.js +243 -0
  291. package/dist/repertoire/tools-teams.js +9 -39
  292. package/dist/repertoire/tools-travel.js +125 -0
  293. package/dist/repertoire/tools-trip.js +604 -0
  294. package/dist/repertoire/tools-user-profile.js +144 -0
  295. package/dist/repertoire/tools-vault.js +40 -0
  296. package/dist/repertoire/tools.js +108 -100
  297. package/dist/repertoire/travel-api-client.js +360 -0
  298. package/dist/repertoire/user-profile.js +131 -0
  299. package/dist/repertoire/vault-setup.js +246 -0
  300. package/dist/repertoire/vault-unlock.js +561 -0
  301. package/dist/scripts/claude-code-hook.js +41 -0
  302. package/dist/scripts/claude-code-stop-hook.js +47 -0
  303. package/dist/senses/attention-queue.js +116 -0
  304. package/dist/senses/bluebubbles/active-turns.js +216 -0
  305. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  306. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  307. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  308. package/dist/senses/bluebubbles/entry.js +77 -0
  309. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  310. package/dist/senses/bluebubbles/index.js +2305 -0
  311. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  312. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  313. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  314. package/dist/senses/bluebubbles/processed-log.js +133 -0
  315. package/dist/senses/bluebubbles/replay.js +137 -0
  316. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  317. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +187 -0
  337. package/dist/senses/cli.js +520 -209
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +569 -182
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +248 -0
  347. package/dist/senses/surface-tool.js +68 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/trips/core.js +138 -0
  352. package/dist/trips/store.js +146 -0
  353. package/package.json +38 -7
  354. package/skills/agent-commerce.md +106 -0
  355. package/skills/browser-navigation.md +117 -0
  356. package/skills/commerce-setup-guide.md +116 -0
  357. package/skills/commerce-setup.md +84 -0
  358. package/skills/configure-dev-tools.md +101 -0
  359. package/skills/travel-planning.md +138 -0
  360. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  361. package/dist/heart/daemon/subagent-installer.js +0 -166
  362. package/dist/heart/session-recall.js +0 -116
  363. package/dist/mind/associative-recall.js +0 -209
  364. package/dist/senses/bluebubbles-entry.js +0 -13
  365. package/dist/senses/bluebubbles.js +0 -1177
  366. package/dist/senses/debug-activity.js +0 -148
  367. package/subagents/README.md +0 -86
  368. package/subagents/work-doer.md +0 -237
  369. package/subagents/work-merger.md +0 -618
  370. package/subagents/work-planner.md +0 -390
  371. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  372. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  373. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  374. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  375. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  376. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  377. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  378. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  379. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  380. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  381. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  382. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  383. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  384. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  385. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  386. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,380 @@
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.parseAcsEmailDeliveryReportEvent = void 0;
37
+ exports.createAcsEmailProviderClient = createAcsEmailProviderClient;
38
+ exports.resolveOutboundProviderClient = resolveOutboundProviderClient;
39
+ exports.resolveOutboundTransport = resolveOutboundTransport;
40
+ exports.createMailDraft = createMailDraft;
41
+ exports.confirmMailDraftSend = confirmMailDraftSend;
42
+ exports.listMailOutboundRecords = listMailOutboundRecords;
43
+ exports.reconcileOutboundDeliveryEvent = reconcileOutboundDeliveryEvent;
44
+ const crypto = __importStar(require("node:crypto"));
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("node:path"));
47
+ const runtime_1 = require("../nerves/runtime");
48
+ const autonomy_1 = require("./autonomy");
49
+ const core_1 = require("./core");
50
+ Object.defineProperty(exports, "parseAcsEmailDeliveryReportEvent", { enumerable: true, get: function () { return core_1.parseAcsEmailDeliveryReportEvent; } });
51
+ function isRecord(value) {
52
+ return !!value && typeof value === "object" && !Array.isArray(value);
53
+ }
54
+ function textField(value, key) {
55
+ const raw = value[key];
56
+ return typeof raw === "string" ? raw.trim() : "";
57
+ }
58
+ function credentialFields(value) {
59
+ if (!isRecord(value))
60
+ return undefined;
61
+ const accessKey = textField(value, "accessKey");
62
+ const connectionString = textField(value, "connectionString");
63
+ const fields = {
64
+ ...(accessKey ? { accessKey } : {}),
65
+ ...(connectionString ? { connectionString } : {}),
66
+ };
67
+ return Object.keys(fields).length > 0 ? fields : undefined;
68
+ }
69
+ function normalizeList(values) {
70
+ return values
71
+ .map((value) => value.trim())
72
+ .filter(Boolean)
73
+ .map(core_1.normalizeMailAddress);
74
+ }
75
+ function contentHash(body) {
76
+ return crypto.createHash("sha256").update(body, "utf-8").digest("base64");
77
+ }
78
+ function hmacSignature(input) {
79
+ const stringToSign = `${input.method}\n${input.pathAndQuery}\n${input.date};${input.host};${input.contentHash}`;
80
+ return crypto.createHmac("sha256", Buffer.from(input.accessKey, "base64")).update(stringToSign, "utf-8").digest("base64");
81
+ }
82
+ function recipientObjects(addresses) {
83
+ return addresses.map((address) => ({ address }));
84
+ }
85
+ function providerMessageIdFromOperationLocation(operationLocation) {
86
+ const match = operationLocation.match(/\/operations\/([^?/#]+)/);
87
+ return match?.[1] ?? "";
88
+ }
89
+ function createAcsEmailProviderClient(input) {
90
+ const endpoint = input.endpoint.replace(/\/+$/, "");
91
+ const fetchImpl = input.fetch ?? fetch;
92
+ return {
93
+ async submit(submitInput) {
94
+ const url = new URL(`${endpoint}/emails:send?api-version=2025-09-01`);
95
+ const senderAddress = submitInput.transport.senderAddress ?? submitInput.draft.from;
96
+ const body = JSON.stringify({
97
+ senderAddress,
98
+ recipients: {
99
+ to: recipientObjects(submitInput.draft.to),
100
+ cc: recipientObjects(submitInput.draft.cc),
101
+ bcc: recipientObjects(submitInput.draft.bcc),
102
+ },
103
+ content: {
104
+ subject: submitInput.draft.subject,
105
+ plainText: submitInput.draft.text,
106
+ },
107
+ });
108
+ const date = (input.now ?? (() => new Date()))().toUTCString();
109
+ const hash = contentHash(body);
110
+ const signature = hmacSignature({
111
+ method: "POST",
112
+ pathAndQuery: `${url.pathname}${url.search}`,
113
+ date,
114
+ host: url.host,
115
+ contentHash: hash,
116
+ accessKey: input.accessKey,
117
+ });
118
+ const response = await fetchImpl(url.toString(), {
119
+ method: "POST",
120
+ headers: {
121
+ "content-type": "application/json",
122
+ "x-ms-date": date,
123
+ "x-ms-content-sha256": hash,
124
+ authorization: `HMAC-SHA256 SignedHeaders=x-ms-date;host;x-ms-content-sha256&Signature=${signature}`,
125
+ },
126
+ body,
127
+ });
128
+ const operationLocation = response.headers.get("operation-location") ?? undefined;
129
+ const providerRequestId = response.headers.get("x-ms-request-id") ?? undefined;
130
+ const payload = await response.json().catch(() => ({}));
131
+ if (!response.ok) {
132
+ const reason = typeof payload.error?.message === "string" ? payload.error.message : `HTTP ${response.status}`;
133
+ throw new Error(`ACS outbound send failed: ${reason}`);
134
+ }
135
+ const providerMessageId = typeof payload.id === "string"
136
+ ? payload.id
137
+ : operationLocation
138
+ ? providerMessageIdFromOperationLocation(operationLocation)
139
+ : "";
140
+ if (!providerMessageId)
141
+ throw new Error("ACS outbound send did not return an operation id");
142
+ return {
143
+ provider: "azure-communication-services",
144
+ providerMessageId,
145
+ ...(operationLocation ? { operationLocation } : {}),
146
+ ...(providerRequestId ? { providerRequestId } : {}),
147
+ submittedAt: submitInput.submittedAt,
148
+ };
149
+ },
150
+ };
151
+ }
152
+ async function resolveOutboundProviderClient(transport, reader, options = {}) {
153
+ if (transport.kind !== "azure-communication-services")
154
+ return undefined;
155
+ const credentialItem = transport.credentialItem?.trim();
156
+ if (!credentialItem) {
157
+ throw new Error("outbound Azure Communication Services transport is missing credentialItem");
158
+ }
159
+ const accessKeyField = transport.credentialFields?.accessKey?.trim() || "accessKey";
160
+ const accessKey = (await reader.readSecretField(credentialItem, accessKeyField)).trim();
161
+ if (!accessKey) {
162
+ throw new Error(`outbound Azure Communication Services required secret field ${accessKeyField} is blank`);
163
+ }
164
+ return createAcsEmailProviderClient({
165
+ endpoint: transport.endpoint,
166
+ accessKey,
167
+ ...(options.fetch ? { fetch: options.fetch } : {}),
168
+ ...(options.now ? { now: options.now } : {}),
169
+ });
170
+ }
171
+ function draftId() {
172
+ return `draft_${crypto.randomBytes(12).toString("hex")}`;
173
+ }
174
+ function ensureRecipients(to) {
175
+ if (to.length === 0)
176
+ throw new Error("at least one recipient is required");
177
+ }
178
+ function resolveOutboundTransport(config) {
179
+ const outbound = isRecord(config) && isRecord(config.outbound) ? config.outbound : null;
180
+ if (!outbound) {
181
+ throw new Error("outbound mail transport is not configured; human-required: set mailroom.outbound before confirmed sends");
182
+ }
183
+ const transport = textField(outbound, "transport");
184
+ if (transport === "local-sink") {
185
+ const sinkPath = textField(outbound, "sinkPath");
186
+ if (!sinkPath)
187
+ throw new Error("outbound local-sink transport is missing sinkPath");
188
+ return { kind: "local-sink", sinkPath };
189
+ }
190
+ if (transport === "azure-communication-services") {
191
+ if ("credentialItemNoteQuery" in outbound || "noteQuery" in outbound || "notes" in outbound) {
192
+ throw new Error("outbound provider binding must not infer credentials from vault notes");
193
+ }
194
+ const endpoint = textField(outbound, "endpoint");
195
+ if (!endpoint)
196
+ throw new Error("outbound Azure Communication Services transport is missing endpoint");
197
+ const senderAddress = textField(outbound, "senderAddress");
198
+ const credentialItem = textField(outbound, "credentialItem");
199
+ const fields = credentialFields(outbound.credentialFields);
200
+ return {
201
+ kind: "azure-communication-services",
202
+ endpoint,
203
+ ...(senderAddress ? { senderAddress } : {}),
204
+ ...(credentialItem ? { credentialItem } : {}),
205
+ ...(fields ? { credentialFields: fields } : {}),
206
+ };
207
+ }
208
+ throw new Error("outbound mail transport is not configured; human-required: choose local-sink or azure-communication-services");
209
+ }
210
+ async function createMailDraft(input) {
211
+ const now = (input.now ?? (() => new Date()))().toISOString();
212
+ const to = normalizeList(input.to);
213
+ ensureRecipients(to);
214
+ const record = {
215
+ schemaVersion: 1,
216
+ id: draftId(),
217
+ agentId: input.agentId,
218
+ status: "draft",
219
+ mailboxRole: "agent-native-mailbox",
220
+ sendAuthority: "agent-native",
221
+ ownerEmail: null,
222
+ source: null,
223
+ from: (0, core_1.normalizeMailAddress)(input.from),
224
+ to,
225
+ cc: normalizeList(input.cc ?? []),
226
+ bcc: normalizeList(input.bcc ?? []),
227
+ subject: input.subject.trim(),
228
+ text: input.text,
229
+ actor: input.actor,
230
+ reason: input.reason,
231
+ createdAt: now,
232
+ updatedAt: now,
233
+ };
234
+ await input.store.upsertMailOutbound(record);
235
+ (0, runtime_1.emitNervesEvent)({
236
+ component: "senses",
237
+ event: "senses.mail_draft_created",
238
+ message: "mail draft created",
239
+ meta: { agentId: record.agentId, id: record.id, toCount: record.to.length },
240
+ });
241
+ return record;
242
+ }
243
+ function appendLocalSink(transport, record, sentAt) {
244
+ fs.mkdirSync(path.dirname(transport.sinkPath), { recursive: true });
245
+ const transportMessageId = `local_${crypto.randomBytes(10).toString("hex")}`;
246
+ fs.appendFileSync(transport.sinkPath, `${JSON.stringify({
247
+ schemaVersion: 1,
248
+ transportMessageId,
249
+ draftId: record.id,
250
+ agentId: record.agentId,
251
+ from: record.from,
252
+ to: record.to,
253
+ cc: record.cc,
254
+ bcc: record.bcc,
255
+ subject: record.subject,
256
+ text: record.text,
257
+ sendMode: record.sendMode,
258
+ policyId: record.policyDecision?.policyId ?? null,
259
+ sentAt,
260
+ })}\n`, "utf-8");
261
+ return transportMessageId;
262
+ }
263
+ function transportSend(transport, record, sentAt) {
264
+ return appendLocalSink(transport, record, sentAt);
265
+ }
266
+ async function confirmMailDraftSend(input) {
267
+ const draft = await input.store.getMailOutbound(input.draftId);
268
+ if (!draft || draft.agentId !== input.agentId)
269
+ throw new Error(`No draft found for ${input.draftId}`);
270
+ if (draft.status !== "draft")
271
+ throw new Error(`Draft ${input.draftId} is already ${draft.status}`);
272
+ const sentAt = (input.now ?? (() => new Date()))().toISOString();
273
+ const recentOutbound = await input.store.listMailOutbound(input.agentId);
274
+ const policyDecision = input.autonomous
275
+ ? (() => {
276
+ if (!input.autonomyPolicy) {
277
+ throw new Error("Autonomous mail sending requires an enabled native-agent policy");
278
+ }
279
+ const decision = (0, autonomy_1.evaluateNativeMailSendPolicy)({
280
+ policy: input.autonomyPolicy,
281
+ draft,
282
+ recentOutbound,
283
+ now: new Date(sentAt),
284
+ });
285
+ if (!decision.allowed) {
286
+ if (decision.mode === "confirmation-required") {
287
+ throw new Error(`Autonomous mail send ${decision.code} requires confirmation=CONFIRM_SEND: ${decision.reason}`);
288
+ }
289
+ throw new Error(`${decision.code}: ${decision.reason}`);
290
+ }
291
+ return decision;
292
+ })()
293
+ : (() => {
294
+ if (input.confirmation !== "CONFIRM_SEND") {
295
+ throw new Error("mail_send requires confirmation=CONFIRM_SEND before any outbound mail leaves the agent");
296
+ }
297
+ return (0, autonomy_1.buildConfirmedMailSendDecision)({
298
+ draft,
299
+ policy: input.autonomyPolicy,
300
+ now: new Date(sentAt),
301
+ });
302
+ })();
303
+ const pendingSent = {
304
+ ...draft,
305
+ status: input.transport.kind === "local-sink" ? "sent" : "submitted",
306
+ actor: input.actor,
307
+ reason: input.reason,
308
+ updatedAt: sentAt,
309
+ sendMode: input.autonomous ? "autonomous" : "confirmed",
310
+ policyDecision,
311
+ sentAt,
312
+ };
313
+ if (input.transport.kind === "azure-communication-services") {
314
+ if (!input.providerClient) {
315
+ throw new Error("Azure Communication Services outbound send is configured but not enabled on this machine; human-required setup is still needed");
316
+ }
317
+ const submission = await input.providerClient.submit({
318
+ draft: pendingSent,
319
+ transport: input.transport,
320
+ submittedAt: sentAt,
321
+ });
322
+ const submitted = {
323
+ ...(0, core_1.buildMailProviderSubmission)({
324
+ draft: pendingSent,
325
+ provider: submission.provider,
326
+ providerMessageId: submission.providerMessageId,
327
+ submittedAt: submission.submittedAt ?? sentAt,
328
+ ...(submission.operationLocation ? { operationLocation: submission.operationLocation } : {}),
329
+ ...(submission.providerRequestId ? { providerRequestId: submission.providerRequestId } : {}),
330
+ }),
331
+ transport: input.transport.kind,
332
+ };
333
+ await input.store.upsertMailOutbound(submitted);
334
+ (0, runtime_1.emitNervesEvent)({
335
+ component: "senses",
336
+ event: "senses.mail_draft_submitted",
337
+ message: "mail draft submitted to outbound provider",
338
+ meta: { agentId: submitted.agentId, id: submitted.id, provider: submitted.provider, providerMessageId: submitted.providerMessageId },
339
+ });
340
+ return submitted;
341
+ }
342
+ const transportMessageId = transportSend(input.transport, pendingSent, sentAt);
343
+ const sent = {
344
+ ...pendingSent,
345
+ transport: input.transport.kind,
346
+ transportMessageId,
347
+ };
348
+ await input.store.upsertMailOutbound(sent);
349
+ (0, runtime_1.emitNervesEvent)({
350
+ component: "senses",
351
+ event: "senses.mail_draft_sent",
352
+ message: "mail draft sent",
353
+ meta: { agentId: sent.agentId, id: sent.id, transport: sent.transport },
354
+ });
355
+ return sent;
356
+ }
357
+ function listMailOutboundRecords(store, agentId) {
358
+ return store.listMailOutbound(agentId);
359
+ }
360
+ async function reconcileOutboundDeliveryEvent(input) {
361
+ const records = await input.store.listMailOutbound(input.agentId);
362
+ const outbound = records.find((record) => record.providerMessageId === input.event.providerMessageId);
363
+ if (!outbound)
364
+ throw new Error(`No outbound record found for provider message ${input.event.providerMessageId}`);
365
+ const updated = (0, core_1.reconcileMailDeliveryEvent)({ outbound, event: input.event });
366
+ await input.store.upsertMailOutbound(updated);
367
+ (0, runtime_1.emitNervesEvent)({
368
+ component: "senses",
369
+ event: "senses.mail_delivery_event_reconciled",
370
+ message: "mail delivery event reconciled",
371
+ meta: {
372
+ agentId: updated.agentId,
373
+ id: updated.id,
374
+ provider: input.event.provider,
375
+ providerEventId: input.event.providerEventId,
376
+ outcome: input.event.outcome,
377
+ },
378
+ });
379
+ return updated;
380
+ }
@@ -0,0 +1,263 @@
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.buildSenderPolicy = buildSenderPolicy;
37
+ exports.classifyResolvedMailPlacement = classifyResolvedMailPlacement;
38
+ exports.classifyMailPlacement = classifyMailPlacement;
39
+ exports.listPendingScreenerCandidates = listPendingScreenerCandidates;
40
+ exports.applyMailDecision = applyMailDecision;
41
+ const crypto = __importStar(require("node:crypto"));
42
+ const runtime_1 = require("../nerves/runtime");
43
+ const core_1 = require("./core");
44
+ function stableJson(value) {
45
+ /* v8 ignore next -- current sender-policy IDs are built from object/scalar fields; array support is defensive. @preserve */
46
+ if (Array.isArray(value))
47
+ return `[${value.map(stableJson).join(",")}]`;
48
+ if (value && typeof value === "object") {
49
+ const record = value;
50
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(",")}}`;
51
+ }
52
+ return JSON.stringify(value);
53
+ }
54
+ function policyId(input) {
55
+ return `policy_${crypto.createHash("sha256").update(stableJson({
56
+ agentId: input.agentId.toLowerCase(),
57
+ scope: input.scope,
58
+ match: normalizeMatch(input.match),
59
+ action: input.action,
60
+ reason: input.reason,
61
+ })).digest("hex").slice(0, 16)}`;
62
+ }
63
+ function normalizeSender(sender) {
64
+ try {
65
+ return (0, core_1.normalizeMailAddress)(sender);
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ function senderDomain(sender) {
72
+ if (!sender)
73
+ return null;
74
+ /* v8 ignore next -- normalizeMailAddress guarantees a domain for non-null senders. @preserve */
75
+ return sender.split("@")[1]?.toLowerCase() ?? null;
76
+ }
77
+ function normalizeMatch(match) {
78
+ if (match.kind === "email")
79
+ return { kind: "email", value: (0, core_1.normalizeMailAddress)(match.value) };
80
+ return { kind: match.kind, value: match.value.trim().toLowerCase() };
81
+ }
82
+ function authenticationFailed(authentication) {
83
+ if (!authentication)
84
+ return false;
85
+ return authentication.dmarc === "fail" || (authentication.spf === "fail" &&
86
+ authentication.dkim === "fail");
87
+ }
88
+ function scopeMatches(policy, resolved) {
89
+ if (policy.scope === "all")
90
+ return true;
91
+ if (policy.scope === resolved.compartmentKind)
92
+ return true;
93
+ if (policy.scope.startsWith("source:"))
94
+ return resolved.source?.toLowerCase() === policy.scope.slice("source:".length);
95
+ return false;
96
+ }
97
+ function policyMatches(policy, resolved, sender) {
98
+ if (policy.agentId !== resolved.agentId || !scopeMatches(policy, resolved))
99
+ return false;
100
+ const match = normalizeMatch(policy.match);
101
+ if (match.kind === "email")
102
+ return sender === match.value;
103
+ if (match.kind === "domain")
104
+ return senderDomain(sender) === match.value;
105
+ if (match.kind === "source")
106
+ return resolved.source?.toLowerCase() === match.value;
107
+ return false;
108
+ }
109
+ function classificationForPolicy(policy) {
110
+ const placement = policy.action === "allow"
111
+ ? "imbox"
112
+ : policy.action === "discard"
113
+ ? "discarded"
114
+ : "quarantine";
115
+ return {
116
+ placement,
117
+ candidate: false,
118
+ trustReason: `sender policy ${policy.action} ${policy.match.kind} ${normalizeMatch(policy.match).value}`,
119
+ };
120
+ }
121
+ function buildSenderPolicy(input) {
122
+ const policy = {
123
+ schemaVersion: 1,
124
+ policyId: policyId(input),
125
+ agentId: input.agentId.toLowerCase(),
126
+ scope: input.scope,
127
+ match: normalizeMatch(input.match),
128
+ action: input.action,
129
+ actor: input.actor,
130
+ reason: input.reason,
131
+ createdAt: (input.now ?? new Date()).toISOString(),
132
+ };
133
+ (0, runtime_1.emitNervesEvent)({
134
+ component: "senses",
135
+ event: "senses.mail_sender_policy_built",
136
+ message: "mail sender policy built",
137
+ meta: { agentId: policy.agentId, action: policy.action, scope: policy.scope, matchKind: policy.match.kind },
138
+ });
139
+ return policy;
140
+ }
141
+ function classifyResolvedMailPlacement(input) {
142
+ if (authenticationFailed(input.authentication)) {
143
+ const classification = {
144
+ placement: "quarantine",
145
+ candidate: false,
146
+ trustReason: "mail authentication failed",
147
+ authentication: input.authentication,
148
+ };
149
+ (0, runtime_1.emitNervesEvent)({
150
+ component: "senses",
151
+ event: "senses.mail_classified",
152
+ message: "mail classified by authentication failure",
153
+ meta: { agentId: input.resolved.agentId, placement: classification.placement },
154
+ });
155
+ return classification;
156
+ }
157
+ const sender = normalizeSender(input.sender);
158
+ const policy = input.registry.senderPolicies?.find((entry) => policyMatches(entry, input.resolved, sender));
159
+ if (policy) {
160
+ const classification = classificationForPolicy(policy);
161
+ (0, runtime_1.emitNervesEvent)({
162
+ component: "senses",
163
+ event: "senses.mail_classified",
164
+ message: "mail classified by sender policy",
165
+ meta: { agentId: input.resolved.agentId, placement: classification.placement, policyId: policy.policyId },
166
+ });
167
+ return classification;
168
+ }
169
+ const placement = input.resolved.defaultPlacement;
170
+ const classification = {
171
+ placement,
172
+ candidate: placement === "screener",
173
+ trustReason: input.resolved.compartmentKind === "delegated"
174
+ ? `delegated source grant ${input.resolved.source ?? input.resolved.compartmentId}`
175
+ : placement === "imbox"
176
+ ? "screened-in native agent mailbox"
177
+ : "native agent mailbox default screener",
178
+ ...(input.authentication ? { authentication: input.authentication } : {}),
179
+ };
180
+ (0, runtime_1.emitNervesEvent)({
181
+ component: "senses",
182
+ event: "senses.mail_classified",
183
+ message: "mail classified by default placement",
184
+ meta: { agentId: input.resolved.agentId, placement: classification.placement, candidate: classification.candidate },
185
+ });
186
+ return classification;
187
+ }
188
+ function classifyMailPlacement(input) {
189
+ const resolved = (0, core_1.resolveMailAddress)(input.registry, input.recipient);
190
+ if (!resolved)
191
+ throw new Error(`Cannot classify unknown mail recipient ${input.recipient}`);
192
+ return classifyResolvedMailPlacement({
193
+ registry: input.registry,
194
+ resolved,
195
+ sender: input.sender,
196
+ ...(input.authentication ? { authentication: input.authentication } : {}),
197
+ });
198
+ }
199
+ function decisionPlacement(action) {
200
+ if (action === "discard")
201
+ return "discarded";
202
+ if (action === "quarantine")
203
+ return "quarantine";
204
+ return "imbox";
205
+ }
206
+ function candidateStatus(action) {
207
+ if (action === "discard")
208
+ return "discarded";
209
+ if (action === "quarantine")
210
+ return "quarantined";
211
+ if (action === "restore")
212
+ return "restored";
213
+ return "allowed";
214
+ }
215
+ async function listPendingScreenerCandidates(store, agentId) {
216
+ const candidates = await store.listScreenerCandidates({ agentId, status: "pending" });
217
+ (0, runtime_1.emitNervesEvent)({
218
+ component: "senses",
219
+ event: "senses.mail_pending_screener_candidates_listed",
220
+ message: "pending mail screener candidates listed",
221
+ meta: { agentId, count: candidates.length },
222
+ });
223
+ return candidates;
224
+ }
225
+ async function applyMailDecision(input) {
226
+ const message = await input.store.getMessage(input.messageId);
227
+ if (!message || message.agentId !== input.agentId) {
228
+ throw new Error(`No mail message ${input.messageId} for ${input.agentId}`);
229
+ }
230
+ const candidate = (await input.store.listScreenerCandidates({ agentId: input.agentId }))
231
+ .find((entry) => entry.messageId === input.messageId);
232
+ const nextPlacement = decisionPlacement(input.action);
233
+ const decision = await input.store.recordMailDecision({
234
+ agentId: input.agentId,
235
+ messageId: input.messageId,
236
+ ...(candidate ? { candidateId: candidate.id } : {}),
237
+ action: input.action,
238
+ actor: input.actor,
239
+ reason: input.reason,
240
+ previousPlacement: message.placement,
241
+ nextPlacement,
242
+ ...(candidate?.senderEmail ? { senderEmail: candidate.senderEmail } : {}),
243
+ ...(input.friendId ? { friendId: input.friendId } : {}),
244
+ ...(input.now ? { createdAt: input.now.toISOString() } : {}),
245
+ });
246
+ await input.store.updateMessagePlacement(input.messageId, nextPlacement);
247
+ if (candidate) {
248
+ await input.store.updateScreenerCandidate({
249
+ ...candidate,
250
+ placement: nextPlacement,
251
+ status: candidateStatus(input.action),
252
+ lastSeenAt: decision.createdAt,
253
+ resolvedByDecisionId: decision.id,
254
+ });
255
+ }
256
+ (0, runtime_1.emitNervesEvent)({
257
+ component: "senses",
258
+ event: "senses.mail_decision_applied",
259
+ message: "mail decision applied",
260
+ meta: { agentId: input.agentId, messageId: input.messageId, action: input.action, nextPlacement },
261
+ });
262
+ return decision;
263
+ }