@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.920

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 (716) 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 +5819 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2997 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1254 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1564 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
  38. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  39. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  40. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  41. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  42. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  43. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  44. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  45. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  46. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +33 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  52. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  53. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  54. package/deploy/unraid/sanctuary.xml +30 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +250 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command-grants.js +93 -0
  59. package/dist/a2a/delegated-command.js +197 -0
  60. package/dist/a2a/delegation-stores.js +56 -0
  61. package/dist/a2a/did-resolution.js +93 -0
  62. package/dist/a2a/escalation-grants.js +84 -0
  63. package/dist/a2a/escalation-wiring.js +60 -0
  64. package/dist/a2a/identity.js +258 -0
  65. package/dist/a2a/inbound-share.js +110 -0
  66. package/dist/a2a/mission-result-wire.js +196 -0
  67. package/dist/a2a/onboarding.js +133 -0
  68. package/dist/a2a/operator-trust.js +382 -0
  69. package/dist/a2a/outbox-client.js +57 -0
  70. package/dist/a2a/outbox-store.js +188 -0
  71. package/dist/a2a/outbox-wire.js +95 -0
  72. package/dist/a2a/pin-store.js +132 -0
  73. package/dist/a2a/replay-grant-holders.js +33 -0
  74. package/dist/a2a/replay-harness.js +188 -0
  75. package/dist/a2a/resolution-proof.js +53 -0
  76. package/dist/a2a/sealed-chat.js +113 -0
  77. package/dist/a2a/seen-ledger.js +120 -0
  78. package/dist/a2a/server.js +771 -0
  79. package/dist/a2a/task-store.js +69 -0
  80. package/dist/a2a/transport.js +45 -0
  81. package/dist/a2a/trust-commands.js +203 -0
  82. package/dist/a2a/trusted-files.js +185 -0
  83. package/dist/a2a/types.js +3 -0
  84. package/dist/arc/attention-types.js +8 -0
  85. package/dist/arc/cares.js +360 -0
  86. package/dist/arc/episodes.js +118 -0
  87. package/dist/arc/evolution.js +490 -0
  88. package/dist/arc/flight-recorder.js +1034 -0
  89. package/dist/arc/intentions.js +134 -0
  90. package/dist/arc/json-store.js +117 -0
  91. package/dist/arc/obligations.js +386 -0
  92. package/dist/arc/packets.js +336 -0
  93. package/dist/arc/presence.js +185 -0
  94. package/dist/arc/task-lifecycle.js +57 -0
  95. package/dist/commerce/store.js +755 -0
  96. package/dist/commerce/types.js +3 -0
  97. package/dist/heart/active-work.js +798 -40
  98. package/dist/heart/agent-entry.js +252 -3
  99. package/dist/heart/approval-files.js +113 -0
  100. package/dist/heart/approval-store.js +960 -0
  101. package/dist/heart/attachments/image-normalize.js +194 -0
  102. package/dist/heart/attachments/materialize.js +97 -0
  103. package/dist/heart/attachments/originals.js +88 -0
  104. package/dist/heart/attachments/render.js +29 -0
  105. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  106. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  107. package/dist/heart/attachments/sources/index.js +18 -0
  108. package/dist/heart/attachments/sources/telegram.js +71 -0
  109. package/dist/heart/attachments/store.js +132 -0
  110. package/dist/heart/attachments/types.js +93 -0
  111. package/dist/heart/auth/auth-flow.js +495 -0
  112. package/dist/heart/autonomy-budget.js +478 -0
  113. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  114. package/dist/heart/awaiting/await-alert.js +152 -0
  115. package/dist/heart/awaiting/await-expiry.js +143 -0
  116. package/dist/heart/awaiting/await-loader.js +91 -0
  117. package/dist/heart/awaiting/await-parser.js +152 -0
  118. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  119. package/dist/heart/awaiting/await-scheduler.js +391 -0
  120. package/dist/heart/background-operations.js +281 -0
  121. package/dist/heart/bluebubbles-host-account.js +78 -0
  122. package/dist/heart/bridges/manager.js +137 -17
  123. package/dist/heart/bridges/store.js +14 -2
  124. package/dist/heart/bundle-state.js +168 -0
  125. package/dist/heart/commitments.js +44 -18
  126. package/dist/heart/config-registry.js +331 -0
  127. package/dist/heart/config.js +174 -131
  128. package/dist/heart/context-loss-gauntlet.js +387 -0
  129. package/dist/heart/context-loss-sentinel.js +1159 -0
  130. package/dist/heart/core.js +2364 -578
  131. package/dist/heart/cross-chat-delivery.js +9 -22
  132. package/dist/heart/daemon/agent-config-check.js +451 -0
  133. package/dist/heart/daemon/agent-discovery.js +283 -3
  134. package/dist/heart/daemon/agent-home.js +319 -0
  135. package/dist/heart/daemon/agent-service.js +542 -0
  136. package/dist/heart/daemon/agentic-repair.js +547 -0
  137. package/dist/heart/daemon/await-private-wake.js +59 -0
  138. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  139. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  140. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  141. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  142. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  143. package/dist/heart/daemon/cadence.js +180 -0
  144. package/dist/heart/daemon/cli-arg-redaction.js +26 -0
  145. package/dist/heart/daemon/cli-defaults.js +876 -0
  146. package/dist/heart/daemon/cli-desk.js +322 -0
  147. package/dist/heart/daemon/cli-exec.js +9199 -0
  148. package/dist/heart/daemon/cli-help.js +735 -0
  149. package/dist/heart/daemon/cli-parse.js +3211 -0
  150. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  151. package/dist/heart/daemon/cli-render.js +819 -0
  152. package/dist/heart/daemon/cli-types.js +8 -0
  153. package/dist/heart/daemon/connect-bay.js +323 -0
  154. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  155. package/dist/heart/daemon/container-healthcheck.js +112 -0
  156. package/dist/heart/daemon/container-runtime.js +97 -0
  157. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  158. package/dist/heart/daemon/container-spec-auditor.js +235 -0
  159. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  160. package/dist/heart/daemon/daemon-cli.js +29 -2350
  161. package/dist/heart/daemon/daemon-entry.js +953 -11
  162. package/dist/heart/daemon/daemon-health.js +186 -0
  163. package/dist/heart/daemon/daemon-rollup.js +57 -0
  164. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  165. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  166. package/dist/heart/daemon/daemon.js +2084 -105
  167. package/dist/heart/daemon/dns-workflow.js +394 -0
  168. package/dist/heart/daemon/doctor-types.js +8 -0
  169. package/dist/heart/daemon/doctor.js +1766 -0
  170. package/dist/heart/daemon/freshness.js +345 -0
  171. package/dist/heart/daemon/habit-private-wake.js +61 -0
  172. package/dist/heart/daemon/health-monitor.js +154 -11
  173. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  174. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  175. package/dist/heart/daemon/http-health-probe.js +80 -0
  176. package/dist/heart/daemon/human-command-screens.js +234 -0
  177. package/dist/heart/daemon/human-readiness.js +114 -0
  178. package/dist/heart/daemon/inner-status.js +78 -0
  179. package/dist/heart/daemon/interactive-repair.js +394 -0
  180. package/dist/heart/daemon/launchd.js +37 -8
  181. package/dist/heart/daemon/log-tailer.js +79 -10
  182. package/dist/heart/daemon/logs-prune.js +132 -0
  183. package/dist/heart/daemon/mcp-canary.js +524 -0
  184. package/dist/heart/daemon/message-router.js +65 -5
  185. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  186. package/dist/heart/daemon/os-cron-deps.js +135 -0
  187. package/dist/heart/daemon/os-cron.js +22 -14
  188. package/dist/heart/daemon/ouro-bot-entry.js +6 -3
  189. package/dist/heart/daemon/ouro-entry.js +5 -2
  190. package/dist/heart/daemon/plugin-cli.js +432 -0
  191. package/dist/heart/daemon/process-manager.js +760 -61
  192. package/dist/heart/daemon/provider-discovery.js +137 -0
  193. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  194. package/dist/heart/daemon/prunable-bundle.js +144 -0
  195. package/dist/heart/daemon/pulse.js +511 -0
  196. package/dist/heart/daemon/readiness-repair.js +365 -0
  197. package/dist/heart/daemon/run-hooks.js +2 -0
  198. package/dist/heart/daemon/runtime-logging.js +47 -14
  199. package/dist/heart/daemon/runtime-metadata.js +2 -30
  200. package/dist/heart/daemon/runtime-mode.js +13 -2
  201. package/dist/heart/daemon/safe-mode.js +161 -0
  202. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  203. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  204. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  205. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  206. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  207. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  208. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  209. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  210. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1267 -0
  211. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  212. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  213. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  214. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  215. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  216. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  217. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  218. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  219. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  220. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  221. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  222. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  223. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  224. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  225. package/dist/heart/daemon/sense-manager.js +733 -48
  226. package/dist/heart/daemon/session-id-resolver.js +131 -0
  227. package/dist/heart/daemon/skill-management-installer.js +1 -1
  228. package/dist/heart/daemon/socket-client.js +180 -12
  229. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  230. package/dist/heart/daemon/startup-tui.js +339 -0
  231. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  232. package/dist/heart/daemon/task-scheduler.js +117 -39
  233. package/dist/heart/daemon/terminal-ui.js +503 -0
  234. package/dist/heart/daemon/thoughts.js +138 -54
  235. package/dist/heart/daemon/up-progress.js +366 -0
  236. package/dist/heart/daemon/vault-items.js +56 -0
  237. package/dist/heart/delegation.js +1 -4
  238. package/dist/heart/external-events/router.js +1516 -0
  239. package/dist/heart/failure-reports.js +336 -0
  240. package/dist/heart/file-lock.js +109 -0
  241. package/dist/heart/frontend-approval-runtime.js +506 -0
  242. package/dist/heart/frontend-journal.js +215 -0
  243. package/dist/heart/frontend-session-service.js +237 -0
  244. package/dist/heart/frontend-socket-client.js +164 -0
  245. package/dist/heart/frontend-socket.js +400 -0
  246. package/dist/heart/habits/habit-cancel.js +810 -0
  247. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  248. package/dist/heart/habits/habit-migration.js +194 -0
  249. package/dist/heart/habits/habit-parser.js +278 -0
  250. package/dist/heart/habits/habit-runtime-state.js +93 -0
  251. package/dist/heart/habits/habit-scheduler.js +653 -0
  252. package/dist/heart/habits/habit-session-summary.js +318 -0
  253. package/dist/heart/habits/habit-session.js +636 -0
  254. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  255. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  256. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  257. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  258. package/dist/heart/identity.js +230 -59
  259. package/dist/heart/kept-notes.js +289 -0
  260. package/dist/heart/kicks.js +1 -1
  261. package/dist/heart/machine-identity.js +175 -0
  262. package/dist/heart/mail-import-discovery.js +356 -0
  263. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  264. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  265. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  266. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  267. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  268. package/dist/heart/mailbox/mailbox-http.js +99 -0
  269. package/dist/heart/mailbox/mailbox-read.js +39 -0
  270. package/dist/heart/mailbox/mailbox-types.js +27 -0
  271. package/dist/heart/mailbox/mailbox-view.js +197 -0
  272. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  273. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  274. package/dist/heart/mailbox/readers/mail.js +375 -0
  275. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  276. package/dist/heart/mailbox/readers/sessions.js +231 -0
  277. package/dist/heart/mailbox/readers/shared.js +111 -0
  278. package/dist/heart/mcp/mcp-server.js +696 -0
  279. package/dist/heart/migrate-config.js +100 -0
  280. package/dist/heart/model-capabilities.js +83 -16
  281. package/dist/heart/orientation-frame.js +345 -0
  282. package/dist/heart/platform.js +81 -0
  283. package/dist/heart/primitives.js +1 -1
  284. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  285. package/dist/heart/private-runtime/index.js +18 -0
  286. package/dist/heart/private-runtime/ledger.js +221 -0
  287. package/dist/heart/private-runtime/policy.js +260 -0
  288. package/dist/heart/private-runtime/types.js +2 -0
  289. package/dist/heart/progress-story.js +1 -1
  290. package/dist/heart/provider-attempt.js +137 -0
  291. package/dist/heart/provider-binding-resolver.js +273 -0
  292. package/dist/heart/provider-credentials.js +449 -0
  293. package/dist/heart/provider-failover.js +311 -0
  294. package/dist/heart/provider-models.js +96 -0
  295. package/dist/heart/provider-ping.js +265 -0
  296. package/dist/heart/provider-readiness-cache.js +119 -0
  297. package/dist/heart/provider-visibility.js +188 -0
  298. package/dist/heart/providers/anthropic-token.js +131 -0
  299. package/dist/heart/providers/anthropic.js +173 -60
  300. package/dist/heart/providers/azure.js +23 -11
  301. package/dist/heart/providers/error-classification.js +127 -0
  302. package/dist/heart/providers/github-copilot.js +38 -39
  303. package/dist/heart/providers/minimax-vlm.js +189 -0
  304. package/dist/heart/providers/minimax.js +26 -8
  305. package/dist/heart/providers/openai-codex-token.js +349 -0
  306. package/dist/heart/providers/openai-codex.js +55 -40
  307. package/dist/heart/providers/openai-compatible.js +177 -0
  308. package/dist/heart/reply-style.js +52 -0
  309. package/dist/heart/run-ledger.js +247 -0
  310. package/dist/heart/runtime-capability-check.js +170 -0
  311. package/dist/heart/runtime-credentials.js +607 -0
  312. package/dist/heart/runtime-cwd.js +87 -0
  313. package/dist/heart/sense-truth.js +24 -4
  314. package/dist/heart/session-activity.js +92 -24
  315. package/dist/heart/session-events.js +1504 -0
  316. package/dist/heart/session-playback-cli-main.js +5 -0
  317. package/dist/heart/session-playback-cli.js +36 -0
  318. package/dist/heart/session-playback.js +231 -0
  319. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  320. package/dist/heart/session-redaction-repair.js +552 -0
  321. package/dist/heart/session-stats-cli-main.js +5 -0
  322. package/dist/heart/session-stats.js +183 -0
  323. package/dist/heart/session-transcript.js +133 -0
  324. package/dist/heart/shelf-claims.js +78 -0
  325. package/dist/heart/shepherd-config.js +113 -0
  326. package/dist/heart/source-grounding.js +297 -0
  327. package/dist/heart/start-of-turn-packet.js +372 -0
  328. package/dist/heart/steward-policy.js +656 -0
  329. package/dist/heart/streaming.js +609 -207
  330. package/dist/heart/structured-output.js +196 -0
  331. package/dist/heart/sync-classification.js +176 -0
  332. package/dist/heart/sync-health.js +152 -0
  333. package/dist/heart/sync.js +726 -0
  334. package/dist/heart/target-resolution.js +11 -7
  335. package/dist/heart/tempo.js +93 -0
  336. package/dist/heart/temporal-view.js +41 -0
  337. package/dist/heart/timeouts.js +101 -0
  338. package/dist/heart/tool-activity-callbacks.js +59 -0
  339. package/dist/heart/tool-approval.js +382 -0
  340. package/dist/heart/tool-description.js +155 -0
  341. package/dist/heart/tool-friction.js +55 -0
  342. package/dist/heart/tool-loop.js +206 -0
  343. package/dist/heart/turn-context.js +496 -0
  344. package/dist/heart/turn-execution-lease.js +30 -0
  345. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  346. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
  347. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  348. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  349. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  350. package/dist/heart/versioning/release-sources.js +173 -0
  351. package/dist/heart/versioning/self-update-defaults.js +294 -0
  352. package/dist/heart/versioning/self-update.js +196 -0
  353. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  354. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  355. package/dist/heart/versioning/update-hooks.js +154 -0
  356. package/dist/heart/versioning/update-state.js +126 -0
  357. package/dist/heart/versioning/updater-launchd.js +150 -0
  358. package/dist/heart/versioning/version-intent.js +114 -0
  359. package/dist/heart/work-card.js +380 -0
  360. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  361. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  362. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  363. package/dist/mailbox-ui/index.html +16 -0
  364. package/dist/mailroom/attention.js +167 -0
  365. package/dist/mailroom/autonomy.js +209 -0
  366. package/dist/mailroom/blob-store.js +889 -0
  367. package/dist/mailroom/body-cache.js +61 -0
  368. package/dist/mailroom/cache-sync-cli.js +58 -0
  369. package/dist/mailroom/core.js +803 -0
  370. package/dist/mailroom/entry.js +160 -0
  371. package/dist/mailroom/file-store.js +568 -0
  372. package/dist/mailroom/hosted-cache-sync.js +384 -0
  373. package/dist/mailroom/mbox-import.js +393 -0
  374. package/dist/mailroom/migration.js +164 -0
  375. package/dist/mailroom/outbound.js +380 -0
  376. package/dist/mailroom/policy.js +263 -0
  377. package/dist/mailroom/reader.js +292 -0
  378. package/dist/mailroom/search-cache.js +513 -0
  379. package/dist/mailroom/search-relevance.js +319 -0
  380. package/dist/mailroom/smtp-ingress.js +176 -0
  381. package/dist/mailroom/source-state.js +176 -0
  382. package/dist/mailroom/thread.js +109 -0
  383. package/dist/mailroom/travel-extract.js +89 -0
  384. package/dist/mind/bundle-manifest.js +24 -2
  385. package/dist/mind/context.js +307 -139
  386. package/dist/mind/desk-section.js +362 -0
  387. package/dist/mind/diary-integrity.js +60 -0
  388. package/dist/mind/{memory.js → diary.js} +68 -77
  389. package/dist/mind/embedding-provider.js +60 -0
  390. package/dist/mind/file-state.js +179 -0
  391. package/dist/mind/friend-link-codes.js +209 -0
  392. package/dist/mind/friend-merge.js +330 -0
  393. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  394. package/dist/mind/obligation-steering.js +199 -3
  395. package/dist/mind/pending.js +36 -10
  396. package/dist/mind/prompt-budget.js +479 -0
  397. package/dist/mind/prompt-refresh.js +3 -2
  398. package/dist/mind/prompt.js +1085 -198
  399. package/dist/mind/provenance-trust.js +26 -0
  400. package/dist/mind/record-paths.js +312 -0
  401. package/dist/mind/scrutiny.js +173 -0
  402. package/dist/mind/session-transaction.js +564 -0
  403. package/dist/nerves/cli-logging.js +7 -1
  404. package/dist/nerves/coverage/audit-rules.js +15 -6
  405. package/dist/nerves/coverage/audit.js +28 -2
  406. package/dist/nerves/coverage/cli.js +1 -1
  407. package/dist/nerves/coverage/contract.js +5 -5
  408. package/dist/nerves/coverage/file-completeness.js +139 -5
  409. package/dist/nerves/coverage/run-artifacts.js +55 -35
  410. package/dist/nerves/coverage/source-scanner.js +4 -4
  411. package/dist/nerves/event-buffer.js +111 -0
  412. package/dist/nerves/index.js +293 -9
  413. package/dist/nerves/observation.js +20 -0
  414. package/dist/nerves/redact.js +79 -0
  415. package/dist/nerves/review/cli-main.js +5 -0
  416. package/dist/nerves/review/cli.js +156 -0
  417. package/dist/nerves/review/core.js +159 -0
  418. package/dist/nerves/runtime.js +17 -1
  419. package/dist/repertoire/ado-client.js +15 -56
  420. package/dist/repertoire/ado-semantic.js +16 -10
  421. package/dist/repertoire/api-client.js +97 -0
  422. package/dist/repertoire/bitwarden-store.js +1201 -0
  423. package/dist/repertoire/bundle-templates.js +71 -0
  424. package/dist/repertoire/bw-installer.js +231 -0
  425. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  426. package/dist/repertoire/coding/context-pack.js +331 -0
  427. package/dist/repertoire/coding/feedback.js +174 -32
  428. package/dist/repertoire/coding/index.js +15 -3
  429. package/dist/repertoire/coding/manager.js +159 -10
  430. package/dist/repertoire/coding/spawner.js +40 -11
  431. package/dist/repertoire/coding/tools.js +182 -18
  432. package/dist/repertoire/coding/workbench-client.js +272 -0
  433. package/dist/repertoire/coding/workbench-manager.js +346 -0
  434. package/dist/repertoire/commerce-errors.js +109 -0
  435. package/dist/repertoire/commerce-self-test.js +156 -0
  436. package/dist/repertoire/credential-access.js +183 -0
  437. package/dist/repertoire/desk/classifier.js +362 -0
  438. package/dist/repertoire/duffel-client.js +185 -0
  439. package/dist/repertoire/github-client.js +14 -55
  440. package/dist/repertoire/graph-client.js +11 -52
  441. package/dist/repertoire/guardrails.js +968 -20
  442. package/dist/repertoire/house-sweep.js +469 -0
  443. package/dist/repertoire/mcp-client.js +58 -5
  444. package/dist/repertoire/mcp-manager.js +427 -139
  445. package/dist/repertoire/mcp-tools.js +132 -0
  446. package/dist/repertoire/mcp-write-guard.js +46 -0
  447. package/dist/repertoire/plugin-mcp.js +175 -0
  448. package/dist/repertoire/plugins.js +253 -0
  449. package/dist/repertoire/relationship-authorization.js +322 -0
  450. package/dist/repertoire/sanctuary-container-policy.js +46 -0
  451. package/dist/repertoire/shell-sessions.js +134 -0
  452. package/dist/repertoire/skills.js +48 -4
  453. package/dist/repertoire/stripe-client.js +131 -0
  454. package/dist/repertoire/tool-arguments.js +182 -0
  455. package/dist/repertoire/tool-results.js +29 -0
  456. package/dist/repertoire/tools-a2a.js +699 -0
  457. package/dist/repertoire/tools-attachments.js +322 -0
  458. package/dist/repertoire/tools-awaiting.js +872 -0
  459. package/dist/repertoire/tools-base.js +83 -1168
  460. package/dist/repertoire/tools-bluebubbles.js +2 -0
  461. package/dist/repertoire/tools-bridge.js +144 -0
  462. package/dist/repertoire/tools-bundle.js +995 -0
  463. package/dist/repertoire/tools-commerce.js +253 -0
  464. package/dist/repertoire/tools-config.js +186 -0
  465. package/dist/repertoire/tools-continuity.js +575 -0
  466. package/dist/repertoire/tools-credential.js +383 -0
  467. package/dist/repertoire/tools-escalation.js +84 -0
  468. package/dist/repertoire/tools-evolution.js +527 -0
  469. package/dist/repertoire/tools-files.js +344 -0
  470. package/dist/repertoire/tools-flight.js +290 -0
  471. package/dist/repertoire/tools-flow.js +119 -0
  472. package/dist/repertoire/tools-friend-link.js +57 -0
  473. package/dist/repertoire/tools-github.js +3 -8
  474. package/dist/repertoire/tools-habits.js +103 -0
  475. package/dist/repertoire/tools-house-care.js +174 -0
  476. package/dist/repertoire/tools-mail.js +1828 -0
  477. package/dist/repertoire/tools-notes.js +496 -0
  478. package/dist/repertoire/tools-obligations.js +182 -0
  479. package/dist/repertoire/tools-orientation.js +31 -0
  480. package/dist/repertoire/tools-record.js +482 -0
  481. package/dist/repertoire/tools-rsvp.js +139 -0
  482. package/dist/repertoire/tools-runtime.js +238 -0
  483. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  484. package/dist/repertoire/tools-session.js +1133 -0
  485. package/dist/repertoire/tools-shell.js +149 -0
  486. package/dist/repertoire/tools-shepherd.js +262 -0
  487. package/dist/repertoire/tools-steward-policy.js +147 -0
  488. package/dist/repertoire/tools-stripe.js +224 -0
  489. package/dist/repertoire/tools-surface.js +369 -0
  490. package/dist/repertoire/tools-teams.js +12 -39
  491. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  492. package/dist/repertoire/tools-travel.js +125 -0
  493. package/dist/repertoire/tools-trip.js +982 -0
  494. package/dist/repertoire/tools-unraid.js +556 -0
  495. package/dist/repertoire/tools-user-profile.js +146 -0
  496. package/dist/repertoire/tools-vault.js +40 -0
  497. package/dist/repertoire/tools-voice-local.js +198 -0
  498. package/dist/repertoire/tools-voice.js +145 -0
  499. package/dist/repertoire/tools.js +514 -156
  500. package/dist/repertoire/travel-api-client.js +360 -0
  501. package/dist/repertoire/unraid-client.js +155 -0
  502. package/dist/repertoire/unraid-restart.js +339 -0
  503. package/dist/repertoire/user-profile.js +131 -0
  504. package/dist/repertoire/vault-setup.js +246 -0
  505. package/dist/repertoire/vault-unlock.js +686 -0
  506. package/dist/rsvp/aisleplanner-client.js +354 -0
  507. package/dist/rsvp/cli.js +936 -0
  508. package/dist/rsvp/config.js +327 -0
  509. package/dist/rsvp/cutover.js +433 -0
  510. package/dist/rsvp/diagnostics.js +232 -0
  511. package/dist/rsvp/diff-renderer.js +176 -0
  512. package/dist/rsvp/habit-policy.js +110 -0
  513. package/dist/rsvp/habit-stage.js +123 -0
  514. package/dist/rsvp/incident-bundle.js +97 -0
  515. package/dist/rsvp/migration.js +204 -0
  516. package/dist/rsvp/native-habit-runner.js +630 -0
  517. package/dist/rsvp/outbound-state.js +628 -0
  518. package/dist/rsvp/query.js +118 -0
  519. package/dist/rsvp/replay.js +233 -0
  520. package/dist/rsvp/snapshot.js +232 -0
  521. package/dist/rsvp/spend-ledger.js +175 -0
  522. package/dist/scripts/claude-code-hook.js +41 -0
  523. package/dist/scripts/claude-code-stop-hook.js +47 -0
  524. package/dist/senses/a2a-entry.js +132 -0
  525. package/dist/senses/acp-server.js +386 -0
  526. package/dist/senses/attention-queue.js +186 -0
  527. package/dist/senses/await-turn-message.js +65 -0
  528. package/dist/senses/bluebubbles/active-turns.js +216 -0
  529. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  530. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  531. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +379 -41
  532. package/dist/senses/bluebubbles/context-packet.js +207 -0
  533. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  534. package/dist/senses/bluebubbles/entry.js +90 -0
  535. package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
  536. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  537. package/dist/senses/bluebubbles/index.js +3878 -0
  538. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  539. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  540. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  541. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  542. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  543. package/dist/senses/bluebubbles/processed-log.js +133 -0
  544. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  545. package/dist/senses/bluebubbles/replay.js +284 -0
  546. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  547. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  548. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  549. package/dist/senses/bluebubbles/webhook-registration.js +257 -0
  550. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  551. package/dist/senses/cli/bracketed-paste.js +82 -0
  552. package/dist/senses/cli/image-paste.js +287 -0
  553. package/dist/senses/cli/image-ref-navigation.js +75 -0
  554. package/dist/senses/cli/ink-app.js +156 -0
  555. package/dist/senses/cli/inline-diff.js +64 -0
  556. package/dist/senses/cli/input-keys.js +174 -0
  557. package/dist/senses/cli/kill-ring.js +86 -0
  558. package/dist/senses/cli/message-list.js +51 -0
  559. package/dist/senses/cli/ouro-tui.js +607 -0
  560. package/dist/senses/cli/spinner-imperative.js +135 -0
  561. package/dist/senses/cli/spinner.js +101 -0
  562. package/dist/senses/cli/status-line.js +60 -0
  563. package/dist/senses/cli/streaming-markdown.js +526 -0
  564. package/dist/senses/cli/tool-display.js +85 -0
  565. package/dist/senses/cli/tool-render.js +85 -0
  566. package/dist/senses/cli/tui-store.js +241 -0
  567. package/dist/senses/cli/virtual-list.js +35 -0
  568. package/dist/senses/cli-entry.js +60 -8
  569. package/dist/senses/cli.js +601 -304
  570. package/dist/senses/commands.js +66 -3
  571. package/dist/senses/context-packet-ledger.js +371 -0
  572. package/dist/senses/context-packets.js +154 -0
  573. package/dist/senses/habit-lifecycle-guard.js +24 -0
  574. package/dist/senses/habit-turn-message.js +160 -0
  575. package/dist/senses/ingress-evidence.js +2 -0
  576. package/dist/senses/mail-entry.js +66 -0
  577. package/dist/senses/mail.js +524 -0
  578. package/dist/senses/pipeline.js +1158 -204
  579. package/dist/senses/private-runtime-worker.js +859 -0
  580. package/dist/senses/private-runtime.js +1627 -0
  581. package/dist/senses/proactive-content-guard.js +51 -0
  582. package/dist/senses/root-host-approval-port.js +345 -0
  583. package/dist/senses/root-host-approval-runtime.js +393 -0
  584. package/dist/senses/sanctuary-authority-resident.js +102 -0
  585. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  586. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  587. package/dist/senses/sanctuary-grounding.js +118 -0
  588. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  589. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  590. package/dist/senses/sanctuary-health-runner.js +104 -0
  591. package/dist/senses/sanctuary-health.js +422 -0
  592. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  593. package/dist/senses/sanctuary-interactive-control.js +410 -0
  594. package/dist/senses/sanctuary-media-catalog-contract.js +259 -0
  595. package/dist/senses/sanctuary-media-optimization.js +514 -0
  596. package/dist/senses/sanctuary-runtime.js +369 -0
  597. package/dist/senses/sanctuary-sab.js +85 -0
  598. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  599. package/dist/senses/shared-turn.js +793 -0
  600. package/dist/senses/shepherd/client.js +196 -0
  601. package/dist/senses/shepherd/cmux.js +344 -0
  602. package/dist/senses/shepherd/herdr.js +315 -0
  603. package/dist/senses/shepherd/host.js +14 -0
  604. package/dist/senses/shepherd/judge.js +137 -0
  605. package/dist/senses/shepherd/owner-notice.js +245 -0
  606. package/dist/senses/shepherd/redact.js +66 -0
  607. package/dist/senses/shepherd/returns.js +79 -0
  608. package/dist/senses/shepherd/sense.js +309 -0
  609. package/dist/senses/shepherd-entry.js +78 -0
  610. package/dist/senses/surface-tool.js +109 -0
  611. package/dist/senses/teams-entry.js +68 -8
  612. package/dist/senses/teams.js +598 -233
  613. package/dist/senses/telegram-admission.js +718 -0
  614. package/dist/senses/telegram-approval-runtime.js +793 -0
  615. package/dist/senses/telegram-attachments.js +186 -0
  616. package/dist/senses/telegram-audit-ledger.js +220 -0
  617. package/dist/senses/telegram-authority-transport.js +231 -0
  618. package/dist/senses/telegram-client.js +1749 -0
  619. package/dist/senses/telegram-effect-adapter.js +900 -0
  620. package/dist/senses/telegram-entry.js +83 -0
  621. package/dist/senses/telegram-handoff.js +80 -0
  622. package/dist/senses/telegram.js +2405 -0
  623. package/dist/senses/trust-gate.js +104 -9
  624. package/dist/senses/voice/audio-playback.js +237 -0
  625. package/dist/senses/voice/audio-routing.js +119 -0
  626. package/dist/senses/voice/call-auth.js +250 -0
  627. package/dist/senses/voice/elevenlabs.js +202 -0
  628. package/dist/senses/voice/floor-control.js +431 -0
  629. package/dist/senses/voice/floor-controller.js +115 -0
  630. package/dist/senses/voice/golden-path.js +116 -0
  631. package/dist/senses/voice/index.js +29 -0
  632. package/dist/senses/voice/local-audio-control.js +344 -0
  633. package/dist/senses/voice/local-audio-devices.js +516 -0
  634. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  635. package/dist/senses/voice/local-audio-identity.js +103 -0
  636. package/dist/senses/voice/local-audio-join.js +325 -0
  637. package/dist/senses/voice/local-audio-mute.js +199 -0
  638. package/dist/senses/voice/local-audio-notify.js +121 -0
  639. package/dist/senses/voice/local-audio-prompts.js +116 -0
  640. package/dist/senses/voice/local-audio-transport.js +427 -0
  641. package/dist/senses/voice/local-audio.js +281 -0
  642. package/dist/senses/voice/local-media-stream.js +145 -0
  643. package/dist/senses/voice/meeting.js +113 -0
  644. package/dist/senses/voice/outbound.js +190 -0
  645. package/dist/senses/voice/phone.js +33 -0
  646. package/dist/senses/voice/playback.js +139 -0
  647. package/dist/senses/voice/process-guards.js +51 -0
  648. package/dist/senses/voice/realtime-eval.js +496 -0
  649. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  650. package/dist/senses/voice/realtime-trace.js +531 -0
  651. package/dist/senses/voice/transcript.js +70 -0
  652. package/dist/senses/voice/turn.js +191 -0
  653. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  654. package/dist/senses/voice/twilio-phone.js +5454 -0
  655. package/dist/senses/voice/types.js +2 -0
  656. package/dist/senses/voice/whisper.js +161 -0
  657. package/dist/senses/voice-entry.js +83 -0
  658. package/dist/senses/voice-realtime-eval-command.js +99 -0
  659. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  660. package/dist/senses/voice-twilio-entry.js +87 -0
  661. package/dist/trips/core.js +138 -0
  662. package/dist/trips/store.js +265 -0
  663. package/dist/util/frontmatter.js +69 -0
  664. package/npm-shrinkwrap.json +8100 -0
  665. package/package.json +74 -13
  666. package/skills/agent-commerce.md +113 -0
  667. package/skills/browser-navigation.md +117 -0
  668. package/skills/commerce-setup-guide.md +116 -0
  669. package/skills/commerce-setup.md +84 -0
  670. package/skills/configure-dev-tools.md +99 -0
  671. package/skills/travel-planning.md +138 -0
  672. package/dist/heart/daemon/auth-flow.js +0 -430
  673. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  674. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  675. package/dist/heart/daemon/update-hooks.js +0 -138
  676. package/dist/heart/obligations.js +0 -191
  677. package/dist/heart/safe-workspace.js +0 -362
  678. package/dist/heart/session-recall.js +0 -116
  679. package/dist/mind/friends/channel.js +0 -84
  680. package/dist/mind/friends/group-context.js +0 -144
  681. package/dist/mind/friends/resolver.js +0 -84
  682. package/dist/mind/friends/store-file.js +0 -190
  683. package/dist/mind/friends/store.js +0 -4
  684. package/dist/mind/friends/tokens.js +0 -26
  685. package/dist/mind/friends/trust-explanation.js +0 -74
  686. package/dist/mind/friends/types.js +0 -29
  687. package/dist/repertoire/tasks/board.js +0 -134
  688. package/dist/repertoire/tasks/index.js +0 -224
  689. package/dist/repertoire/tasks/lifecycle.js +0 -80
  690. package/dist/repertoire/tasks/middleware.js +0 -65
  691. package/dist/repertoire/tasks/parser.js +0 -173
  692. package/dist/repertoire/tasks/scanner.js +0 -132
  693. package/dist/repertoire/tasks/transitions.js +0 -144
  694. package/dist/senses/bluebubbles-entry.js +0 -13
  695. package/dist/senses/bluebubbles.js +0 -1181
  696. package/dist/senses/debug-activity.js +0 -154
  697. package/dist/senses/inner-dialog-worker.js +0 -90
  698. package/dist/senses/inner-dialog.js +0 -525
  699. package/subagents/README.md +0 -7
  700. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  701. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  702. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  703. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  704. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  705. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  706. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  707. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  708. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  709. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  710. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  711. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  712. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  713. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  714. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  715. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  716. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OUTBOX_ERROR_INVALID = exports.OUTBOX_ERROR_REFUSED = exports.OUTBOX_METHODS = void 0;
4
+ exports.isOutboxMethod = isOutboxMethod;
5
+ exports.encodeOutboxCommand = encodeOutboxCommand;
6
+ exports.parseOutboxCommand = parseOutboxCommand;
7
+ exports.handleOutboxCommand = handleOutboxCommand;
8
+ const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
9
+ const escalation_grants_1 = require("./escalation-grants");
10
+ const resolution_proof_1 = require("./resolution-proof");
11
+ const outbox_store_1 = require("./outbox-store");
12
+ const failure_reports_1 = require("../heart/failure-reports");
13
+ const runtime_1 = require("../nerves/runtime");
14
+ /**
15
+ * The outbox methods ride the same sealed, signed chat envelope as `a2a message`: the request is a `message` whose
16
+ * signed text is `{"ouro":"a2a-method","method":...,"params":...}`, posted under the JSON-RPC method of the same name.
17
+ * The server verifies the sender exactly as it does for a chat (unseal, pinned key, signature, replay guard, friend
18
+ * record), requires the signed method to equal the JSON-RPC method, and then decides access itself from the verified
19
+ * friend record. A sender can only ever name its own outbox: no parameter selects another peer's.
20
+ *
21
+ * outbox/list { since?: string, limit?: number } -> { entries, nextCursor, more } any active friend, own outbox
22
+ * outbox/ack { ids: string[] } -> { acked, unknown } any active friend, own outbox
23
+ * report/resolve { id, version, note, resolvedAt, proof } -> { id, status: "resolved" } escalation holders, own reports
24
+ */
25
+ exports.OUTBOX_METHODS = ["outbox/list", "outbox/ack", "report/resolve"];
26
+ exports.OUTBOX_ERROR_REFUSED = -32003;
27
+ exports.OUTBOX_ERROR_INVALID = -32602;
28
+ const MAX_ACK_IDS = 100;
29
+ function isOutboxMethod(method) {
30
+ return typeof method === "string" && exports.OUTBOX_METHODS.includes(method);
31
+ }
32
+ function encodeOutboxCommand(method, params) {
33
+ return JSON.stringify({ ouro: "a2a-method", method, params });
34
+ }
35
+ function parseOutboxCommand(text) {
36
+ let parsed;
37
+ try {
38
+ parsed = JSON.parse(text);
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
44
+ return null;
45
+ const command = parsed;
46
+ if (command.ouro !== "a2a-method" || !isOutboxMethod(command.method))
47
+ return null;
48
+ const params = command.params === undefined ? {} : command.params;
49
+ if (!params || typeof params !== "object" || Array.isArray(params))
50
+ return null;
51
+ return { method: command.method, params: params };
52
+ }
53
+ const refuse = (message) => ({ ok: false, code: exports.OUTBOX_ERROR_REFUSED, message });
54
+ const invalid = (message) => ({ ok: false, code: exports.OUTBOX_ERROR_INVALID, message });
55
+ /** Runs one verified outbox command for `friend`. `friend` must be the record found by the signed sender DID. */
56
+ async function handleOutboxCommand(input) {
57
+ const { agentRoot, friend, method, params } = input;
58
+ if (!friend || friend.admissionState !== "active") {
59
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_outbox_refused", message: "refused an outbox call from a peer that is not an active friend", meta: { method, friendId: friend?.id ?? null } });
60
+ return refuse("only an active friend can use its outbox");
61
+ }
62
+ const outbox = new outbox_store_1.FileOutboxStore(agentRoot);
63
+ if (method === "outbox/list") {
64
+ const { since, limit } = params;
65
+ if (since !== undefined && typeof since !== "string")
66
+ return invalid("since must be a string cursor");
67
+ if (limit !== undefined && (typeof limit !== "number" || !Number.isFinite(limit)))
68
+ return invalid("limit must be a number");
69
+ return { ok: true, result: { ...outbox.list(friend.id, { ...(since !== undefined ? { since } : {}), ...(limit !== undefined ? { limit: Math.min(limit, outbox_store_1.OUTBOX_LIST_MAX_LIMIT) } : {}) }) } };
70
+ }
71
+ if (method === "outbox/ack") {
72
+ const { ids } = params;
73
+ if (!Array.isArray(ids) || ids.length === 0 || ids.length > MAX_ACK_IDS || ids.some((id) => typeof id !== "string"))
74
+ return invalid(`ids must be 1 to ${MAX_ACK_IDS} strings`);
75
+ return { ok: true, result: { ...outbox.ack(friend.id, ids) } };
76
+ }
77
+ if (!(0, escalation_grants_1.holdsEscalation)(agentRoot, friend, input.now)) {
78
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_report_resolve_refused", message: "refused report/resolve from a peer without the escalation grant", meta: { friendId: friend.id } });
79
+ return refuse("report/resolve needs the escalation grant");
80
+ }
81
+ const { id, version, note, resolvedAt, proof } = params;
82
+ if (typeof id !== "string" || typeof version !== "string" || typeof note !== "string" || typeof resolvedAt !== "string")
83
+ return invalid("id, version, note and resolvedAt must be strings");
84
+ // The key is the DID the operator pinned in the root-owned grant, never the friend record; and the A2A-verified caller must be that same DID.
85
+ const holderDid = (0, escalation_grants_1.pinnedHolderDid)(agentRoot, friend.id, input.now);
86
+ if (!holderDid || input.verifiedDid !== holderDid) {
87
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_report_resolve_refused", message: "refused report/resolve from a caller whose verified DID is not the pinned holder DID", meta: { friendId: friend.id } });
88
+ return refuse("report not resolved: the caller is not the pinned escalation holder");
89
+ }
90
+ const checked = (0, resolution_proof_1.verifyResolution)({ sodium: await (0, a2a_client_1.ready)(), claim: { reportId: id, version, note, resolvedAt }, proof, holderDid });
91
+ if (!checked.ok)
92
+ return refuse(`report not resolved: the resolution is not signed by your key (${checked.reason})`);
93
+ const resolved = await (0, failure_reports_1.resolveFailureReport)(agentRoot, { id, version, note, byFriendId: friend.id, resolvedAt, proof }, input.now);
94
+ return resolved.ok ? { ok: true, result: { id: resolved.id, status: resolved.status } } : refuse(`report not resolved: ${resolved.reason}`);
95
+ }
@@ -0,0 +1,132 @@
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.FileA2APinStore = void 0;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const node_crypto_1 = require("node:crypto");
40
+ const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
41
+ const runtime_1 = require("../nerves/runtime");
42
+ function pinFileName(fromAgentId) {
43
+ return `${(0, node_crypto_1.createHash)("sha256").update(fromAgentId).digest("hex")}.json`;
44
+ }
45
+ class FileA2APinStore {
46
+ dir;
47
+ cache = new Map();
48
+ constructor(agentRoot) {
49
+ this.dir = path.join(agentRoot, "state", "a2a", "pins");
50
+ fs.mkdirSync(this.dir, { recursive: true });
51
+ this.loadExisting();
52
+ (0, runtime_1.emitNervesEvent)({
53
+ component: "channels",
54
+ event: "channel.a2a_pin_store_init",
55
+ message: "initialized durable A2A pin store",
56
+ meta: { dir: this.dir, pins: this.cache.size },
57
+ });
58
+ }
59
+ get size() {
60
+ return this.cache.size;
61
+ }
62
+ get(fromAgentId) {
63
+ if (!fromAgentId)
64
+ return undefined;
65
+ const pinned = this.cache.get(fromAgentId);
66
+ if (!pinned)
67
+ return undefined;
68
+ (0, runtime_1.emitNervesEvent)({
69
+ component: "channels",
70
+ event: "channel.a2a_pin_hit",
71
+ message: "A2A pin hit",
72
+ meta: { fromAgentId, did: pinned.did },
73
+ });
74
+ return pinned;
75
+ }
76
+ set(fromAgentId, pinned) {
77
+ // An empty-string DID is never a matchable key (security: it can never index a
78
+ // pin). Stay inert rather than writing an unkeyed pin file.
79
+ if (!fromAgentId)
80
+ return;
81
+ const existed = this.cache.has(fromAgentId);
82
+ // Faithfully persist the pinned identity's DID (which may differ from
83
+ // fromAgentId after a rotation), not fromAgentId itself.
84
+ const stored = {
85
+ fromAgentId,
86
+ did: pinned.did,
87
+ pinnedKey: (0, a2a_client_1.base58btcEncode)(pinned.ed25519Pub),
88
+ };
89
+ fs.writeFileSync(path.join(this.dir, pinFileName(fromAgentId)), `${JSON.stringify(stored, null, 2)}\n`, "utf-8");
90
+ this.cache.set(fromAgentId, { did: pinned.did, ed25519Pub: pinned.ed25519Pub });
91
+ (0, runtime_1.emitNervesEvent)({
92
+ component: "channels",
93
+ event: "channel.a2a_pin_set",
94
+ message: "set durable A2A pin",
95
+ meta: { fromAgentId, did: pinned.did, rotated: existed },
96
+ });
97
+ }
98
+ /** Reload every persisted pin from disk into the in-memory cache (the restart
99
+ * replay). Corrupt/undecodable files are skipped so one bad file can never
100
+ * wedge the store. */
101
+ loadExisting() {
102
+ let entries;
103
+ try {
104
+ entries = fs.readdirSync(this.dir);
105
+ }
106
+ catch {
107
+ /* v8 ignore next -- the constructor mkdirSync's the dir before this runs; unreadable dir is unreachable in practice @preserve */
108
+ return;
109
+ }
110
+ for (const name of entries) {
111
+ if (!name.endsWith(".json"))
112
+ continue;
113
+ let stored;
114
+ try {
115
+ stored = JSON.parse(fs.readFileSync(path.join(this.dir, name), "utf-8"));
116
+ }
117
+ catch {
118
+ continue;
119
+ }
120
+ // `fromAgentId` is the cache key; fall back to `did` for any pre-rotation
121
+ // file written before the key/did split (back-compat).
122
+ const key = stored.fromAgentId ?? stored.did;
123
+ if (!key || !stored.did || !stored.pinnedKey)
124
+ continue;
125
+ const ed25519Pub = (0, a2a_client_1.base58btcDecode)(stored.pinnedKey);
126
+ if (!ed25519Pub)
127
+ continue;
128
+ this.cache.set(key, { did: stored.did, ed25519Pub });
129
+ }
130
+ }
131
+ }
132
+ exports.FileA2APinStore = FileA2APinStore;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REPLAY_GRANT_HOLDERS_FILE = void 0;
4
+ exports.isReplayGrantHolder = isReplayGrantHolder;
5
+ const runtime_1 = require("../nerves/runtime");
6
+ const operator_trust_1 = require("./operator-trust");
7
+ /**
8
+ * The friends the replay gate provisioned as replay peers, kept by the gate itself as root inside the operator trust directory
9
+ * (`replay-identities.json`, `{ schemaVersion: 1, grants: { <friend id>: { who, name, did } } }`). A grant for one of them must
10
+ * carry an expiry (and so must every grant when this file is present but cannot be trusted), so a permanent grant can never be left behind by a replay run. This list is the authority for that rule: the
11
+ * bundle's own replay registry and a grant's free-text source are the agent's to edit and decide nothing here.
12
+ */
13
+ exports.REPLAY_GRANT_HOLDERS_FILE = "replay-identities.json";
14
+ function validHolder(value) {
15
+ if (!value || typeof value !== "object" || Array.isArray(value))
16
+ return false;
17
+ const holder = value;
18
+ return typeof holder.who === "string" && typeof holder.name === "string" && typeof holder.did === "string";
19
+ }
20
+ /**
21
+ * True when a grant with no expiry for this friend must be refused. That is the case for a friend the list names, for an entry in the list
22
+ * that is malformed (its id is read from the file but its content is not trusted), and for every friend when the list is present but
23
+ * untrusted or malformed: a list the Butler cannot rely on must never let a permanent replay grant through. A list that does not exist
24
+ * yet (no replay gate has run) names nobody.
25
+ */
26
+ function isReplayGrantHolder(agentRoot, friendId) {
27
+ const view = (0, operator_trust_1.readGrantFile)(agentRoot, exports.REPLAY_GRANT_HOLDERS_FILE, validHolder);
28
+ if (view.state === "untrusted") {
29
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_replay_list_untrusted", message: "the replay list is present but cannot be trusted, so no grant without an expiry is honoured", meta: { file: exports.REPLAY_GRANT_HOLDERS_FILE } });
30
+ return true;
31
+ }
32
+ return Object.prototype.hasOwnProperty.call(view.grants, friendId) || view.ignored.includes(friendId);
33
+ }
@@ -0,0 +1,188 @@
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.REPLAY_WINDOW_MAX_MS = void 0;
37
+ exports.replayWindowPath = replayWindowPath;
38
+ exports.replaySinkPath = replaySinkPath;
39
+ exports.replayIdentitiesPath = replayIdentitiesPath;
40
+ exports.isReplayIdentity = isReplayIdentity;
41
+ exports.isReplayWindowOpen = isReplayWindowOpen;
42
+ exports.isAnyReplayWindowOpen = isAnyReplayWindowOpen;
43
+ exports.appendReplayNotice = appendReplayNotice;
44
+ exports.replayNoticeRecorded = replayNoticeRecorded;
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("path"));
47
+ const runtime_1 = require("../nerves/runtime");
48
+ /**
49
+ * The replay gate drives the Butler over its real A2A path to check its behaviour after an upgrade. Every delegated
50
+ * command and every A2A-filed await would otherwise post to the owner's Telegram chat. While the host's gate holds a
51
+ * replay window open for a peer, those notices are appended to a local sink instead.
52
+ *
53
+ * The window narrows where a notice goes, never whether a command is authorized: the grant, family trust, sole owner
54
+ * and notify-before-run checks are unchanged, and "notify" means "the sink write succeeded". The window file lives
55
+ * under the bundle's state directory, is written by the host's gate and cleared when its run ends, and every entry
56
+ * expires on its own (and is ignored if it claims to last longer than the cap).
57
+ */
58
+ exports.REPLAY_WINDOW_MAX_MS = 2 * 60 * 60 * 1000;
59
+ function replayDir(agentRoot) {
60
+ return path.join(agentRoot, "state", "replay");
61
+ }
62
+ function replayWindowPath(agentRoot) {
63
+ return path.join(replayDir(agentRoot), "window.json");
64
+ }
65
+ function replaySinkPath(agentRoot) {
66
+ return path.join(replayDir(agentRoot), "notices.ndjson");
67
+ }
68
+ /** Permanent registry of replay identities, written by the host's provisioning and never cleared. */
69
+ function replayIdentitiesPath(agentRoot) {
70
+ return path.join(replayDir(agentRoot), "identities.json");
71
+ }
72
+ function listsFriend(file, friendId) {
73
+ let parsed;
74
+ try {
75
+ parsed = JSON.parse(fs.readFileSync(file, "utf8"));
76
+ }
77
+ catch (error) {
78
+ // A missing file lists nobody; a file that exists but cannot be read or parsed fails closed.
79
+ return error.code !== "ENOENT";
80
+ }
81
+ const friends = parsed?.friends;
82
+ return !!friends && typeof friends === "object" && Object.hasOwn(friends, friendId);
83
+ }
84
+ /**
85
+ * True when `friendId` is a replay identity: listed in the permanent registry, or holding any window entry (open or
86
+ * expired). Unlike the window check this needs no trusted-owner proof, because the marker only ever restricts: forging
87
+ * an entry can block a friend from writing owner policy, never grant anything. Owner policy writes refuse these identities.
88
+ */
89
+ function isReplayIdentity(agentRoot, friendId) {
90
+ return listsFriend(replayIdentitiesPath(agentRoot), friendId) || listsFriend(replayWindowPath(agentRoot), friendId);
91
+ }
92
+ /** A root-controlled directory: a real directory (no symlink), owned by the trusted uid, writable by neither group nor other. */
93
+ function isTrustedDirectory(target, trustedUid) {
94
+ try {
95
+ const stat = fs.lstatSync(target);
96
+ return stat.isDirectory() && !stat.isSymbolicLink() && stat.uid === trustedUid && (stat.mode & 0o022) === 0;
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ /**
103
+ * Reads the window file only if the file actually opened is trusted. The path is opened once with O_NOFOLLOW, then the
104
+ * descriptor itself is checked (regular file, trusted owner, not group- or other-writable) and read, so a rename loop on
105
+ * the Butler's own state directory cannot swap a different file in between the check and the read. Any error is "no window".
106
+ */
107
+ function readTrustedWindow(file, trustedUid) {
108
+ let fd;
109
+ try {
110
+ fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
111
+ const stat = fs.fstatSync(fd);
112
+ if (!stat.isFile() || stat.uid !== trustedUid || (stat.mode & 0o022) !== 0)
113
+ return undefined;
114
+ return JSON.parse(fs.readFileSync(fd, "utf8"));
115
+ }
116
+ catch {
117
+ return undefined;
118
+ }
119
+ finally {
120
+ if (fd !== undefined)
121
+ fs.closeSync(fd);
122
+ }
123
+ }
124
+ /**
125
+ * True only when the window file lists `friendId` with an expiry that is in the future and within the cap. Any unreadable or malformed file means "closed".
126
+ * The state directory is the Butler's own, so it could swap in a directory and window of its own making: only a replay
127
+ * directory and window file that root owns, and nobody else can write, count; anything else fails toward Telegram.
128
+ */
129
+ const windowEntryOpen = (entry, now) => {
130
+ const expiresAt = typeof entry?.expiresAt === "string"
131
+ ? Date.parse(entry.expiresAt)
132
+ : Number.NaN;
133
+ return Number.isFinite(expiresAt) && expiresAt > now && expiresAt <= now + exports.REPLAY_WINDOW_MAX_MS;
134
+ };
135
+ function isReplayWindowOpen(agentRoot, friendId, now = Date.now(), trustedUid = 0) {
136
+ if (!isTrustedDirectory(replayDir(agentRoot), trustedUid))
137
+ return false;
138
+ const parsed = readTrustedWindow(replayWindowPath(agentRoot), trustedUid);
139
+ const friends = parsed?.friends;
140
+ if (!friends || typeof friends !== "object")
141
+ return false;
142
+ return windowEntryOpen(friends[friendId], now);
143
+ }
144
+ /** True while any friend's replay window is open: the gate is running, and background work should stay out of its way. Same trust rules as `isReplayWindowOpen`. */
145
+ function isAnyReplayWindowOpen(agentRoot, now = Date.now(), trustedUid = 0) {
146
+ if (!isTrustedDirectory(replayDir(agentRoot), trustedUid))
147
+ return false;
148
+ const parsed = readTrustedWindow(replayWindowPath(agentRoot), trustedUid);
149
+ const friends = parsed?.friends;
150
+ if (!friends || typeof friends !== "object")
151
+ return false;
152
+ return Object.values(friends).some((entry) => windowEntryOpen(entry, now));
153
+ }
154
+ /** Appends one notice to the sink, once per notice id and friend (a retry after a crash adds nothing); throws when it cannot be written, so the caller refuses exactly as a failed Telegram send does. */
155
+ function appendReplayNotice(agentRoot, notice, now = Date.now()) {
156
+ if (replayNoticeRecorded(agentRoot, notice.noticeId, notice.friendId))
157
+ return;
158
+ fs.mkdirSync(replayDir(agentRoot), { recursive: true });
159
+ const line = JSON.stringify({ at: new Date(now).toISOString(), ...notice });
160
+ fs.appendFileSync(replaySinkPath(agentRoot), `${line}\n`, { mode: 0o600 });
161
+ (0, runtime_1.emitNervesEvent)({
162
+ component: "senses",
163
+ event: "senses.a2a_replay_notice_sunk",
164
+ message: "wrote an owner notice to the replay sink instead of Telegram",
165
+ meta: { noticeId: notice.noticeId, friendId: notice.friendId },
166
+ });
167
+ }
168
+ /** True when the sink holds a notice with this id for this friend (a missing sink is "no"). The sink is Butler-writable: callers must also require a trusted window. */
169
+ function replayNoticeRecorded(agentRoot, noticeId, friendId) {
170
+ let raw;
171
+ try {
172
+ raw = fs.readFileSync(replaySinkPath(agentRoot), "utf8");
173
+ }
174
+ catch {
175
+ return false;
176
+ }
177
+ return raw.split("\n").some((line) => {
178
+ if (!line)
179
+ return false;
180
+ try {
181
+ const entry = JSON.parse(line);
182
+ return entry.noticeId === noticeId && entry.friendId === friendId;
183
+ }
184
+ catch {
185
+ return false;
186
+ }
187
+ });
188
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.signResolution = signResolution;
4
+ exports.friendDid = friendDid;
5
+ exports.verifyResolution = verifyResolution;
6
+ const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
7
+ const friends_1 = require("@ouro.bot/friends");
8
+ const runtime_1 = require("../nerves/runtime");
9
+ /**
10
+ * The proof that an escalation holder, and nobody who can write the Butler's files, said a failure report is fixed.
11
+ * The holder signs `{reportId, version, note, resolvedAt}` with its DID key (canonical JSON, detached Ed25519), and
12
+ * the Butler keeps the signature next to the resolution. The holder's private key never leaves the holder's machine,
13
+ * so a forged report file cannot carry a valid one.
14
+ */
15
+ const PURPOSE = "ouro.report-resolve.v1";
16
+ function envelopeOf(claim) {
17
+ return { purpose: PURPOSE, reportId: claim.reportId, version: claim.version, note: claim.note, resolvedAt: claim.resolvedAt };
18
+ }
19
+ function signResolution(input) {
20
+ const { claim } = input;
21
+ return (0, a2a_client_1.signEnvelope)({
22
+ sodium: input.sodium,
23
+ envelope: envelopeOf(claim),
24
+ signerEd25519Priv: input.identity.ed25519Priv,
25
+ signerDid: input.identity.did,
26
+ signerKeyId: input.identity.keyId,
27
+ });
28
+ }
29
+ /** The DID a friend record names. Used only by the operator command that pins it into the grant; never to verify a resolution. */
30
+ function friendDid(friend) {
31
+ return (0, friends_1.resolveAgentIdentity)(friend.agentMeta).did ?? null;
32
+ }
33
+ function verifyResolution(input) {
34
+ const fail = (reason) => {
35
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.a2a_resolution_proof_rejected", message: "rejected a report resolution without a valid holder signature", meta: { reportId: input.claim.reportId, reason } });
36
+ return { ok: false, reason };
37
+ };
38
+ const proof = input.proof;
39
+ if (!proof || typeof proof !== "object" || Array.isArray(proof))
40
+ return fail("no_proof");
41
+ if (!input.holderDid)
42
+ return fail("no_holder_did");
43
+ const parsed = (0, a2a_client_1.parseDidKey)(input.holderDid);
44
+ if (!parsed || proof.signerDid !== input.holderDid)
45
+ return fail("wrong_signer");
46
+ const valid = (0, a2a_client_1.verifyEnvelopeSignature)({
47
+ sodium: input.sodium,
48
+ envelope: envelopeOf(input.claim),
49
+ proof: proof,
50
+ signerEd25519Pub: parsed.ed25519Pub,
51
+ });
52
+ return valid ? { ok: true } : fail("bad_signature");
53
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMPTY_CHAT_REPLY = void 0;
4
+ exports.sealChatMessage = sealChatMessage;
5
+ exports.openChatMessage = openChatMessage;
6
+ /**
7
+ * Sealed agent-to-agent chat over A2A (friends `message` kind).
8
+ *
9
+ * Both directions use the same primitive: the text is signed by the sender and
10
+ * sealed to the recipient inside ONE friends DataPart, so a message is confidential
11
+ * and tamper-evident over any transport (tailnet, LAN, relay). The network is a
12
+ * pipe, not the lock.
13
+ *
14
+ * - `sealChatMessage` builds the single-DataPart A2A message for a recipient whose
15
+ * Ed25519 key the sender already trusts (a pinned DID, or a did:key card).
16
+ * - `openChatMessage` opens one through the SAME `receiveShare` pipeline every
17
+ * friends kind uses (unseal, sender binding, pinned-key signature, replay guard,
18
+ * trust floor), pinned to the sender the opener expects. There is no second,
19
+ * hand-rolled verification path.
20
+ */
21
+ const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
22
+ const friends_1 = require("@ouro.bot/friends");
23
+ const runtime_1 = require("../nerves/runtime");
24
+ /** What an agent replies when its turn produced no text; sealed like any reply. */
25
+ exports.EMPTY_CHAT_REPLY = "(no reply)";
26
+ /** Seal `text` from `from` to the recipient as a single friends DataPart. Returns
27
+ * the harness-shaped A2A message; callers add role/messageId/contextId. */
28
+ function sealChatMessage(input) {
29
+ const text = input.text.trim() === "" ? exports.EMPTY_CHAT_REPLY : input.text.slice(0, friends_1.MAX_MESSAGE_TEXT_CHARS);
30
+ const prepared = (0, friends_1.prepareMessage)({
31
+ fromAgentId: input.from.did,
32
+ text,
33
+ ...(input.conversationId !== undefined ? { conversationId: input.conversationId } : {}),
34
+ ...(input.onBehalfOf ? { onBehalfOf: input.onBehalfOf } : {}),
35
+ });
36
+ /* v8 ignore next -- the text is normalized above and the sender DID comes from a real identity @preserve */
37
+ if (!prepared.ok)
38
+ throw new Error(`cannot prepare chat message: ${prepared.status}`);
39
+ const sealed = (0, a2a_client_1.sealEnvelope)({
40
+ sodium: input.sodium,
41
+ envelope: prepared.envelope,
42
+ friendsKind: "message",
43
+ fromIdentity: input.from,
44
+ recipientDid: input.recipientDid,
45
+ recipientX25519Pub: (0, a2a_client_1.keyAgreementFromDidKey)({ sodium: input.sodium, ed25519Pub: input.recipientEd25519Pub }),
46
+ });
47
+ const wrapped = (0, a2a_client_1.wrapInDataPart)({ sealedEnvelope: sealed, recipientDid: input.recipientDid });
48
+ (0, runtime_1.emitNervesEvent)({
49
+ component: "channels",
50
+ event: "channel.a2a_chat_sealed",
51
+ message: "sealed an A2A chat message",
52
+ meta: { recipientDid: input.recipientDid, chars: text.length },
53
+ });
54
+ return { parts: wrapped.parts };
55
+ }
56
+ class MemorySeenLedger {
57
+ seen = new Set();
58
+ isSeen(nonce) { return this.seen.has(nonce); }
59
+ markSeen(nonce) { this.seen.add(nonce); }
60
+ }
61
+ /** A `message` receipt imports nothing, so the stores must never be reached. */
62
+ function unreachableStore(name) {
63
+ return new Proxy({}, { get() { throw new Error(`sealed chat must not touch the ${name}`); } });
64
+ }
65
+ /** Open a sealed chat message from an expected sender through `receiveShare`. */
66
+ async function openChatMessage(input) {
67
+ const pinStore = new a2a_client_1.MemoryPinStore();
68
+ (0, a2a_client_1.pinOnFirstContact)({ pinStore, fromAgentId: input.senderDid, did: input.senderDid, ed25519Pub: input.senderEd25519Pub });
69
+ const result = await (0, a2a_client_1.receiveShare)({
70
+ sodium: input.sodium,
71
+ store: unreachableStore("friend store"),
72
+ missionStore: unreachableStore("mission store"),
73
+ pinStore,
74
+ // Only the pre-pinned sender can verify: any other signer resolves to nothing.
75
+ didResolution: {
76
+ async resolveAndPin({ fromAgentId }) {
77
+ const pinned = pinStore.get(fromAgentId);
78
+ return pinned ? { ed25519Pub: pinned.ed25519Pub } : null;
79
+ },
80
+ },
81
+ seen: new MemorySeenLedger(),
82
+ a2aMessage: input.message,
83
+ recipientDid: input.self.did,
84
+ recipientIdentity: { x25519Priv: input.self.x25519Priv, x25519Pub: input.self.x25519Pub },
85
+ // The opener chose this sender; the signature, not this level, is the gate.
86
+ trustOfSource: "family",
87
+ });
88
+ if (result.state === "rejected") {
89
+ (0, runtime_1.emitNervesEvent)({
90
+ level: "warn",
91
+ component: "channels",
92
+ event: "channel.a2a_chat_open_rejected",
93
+ message: "refused a sealed A2A chat message",
94
+ meta: { senderDid: input.senderDid, reason: result.reason },
95
+ });
96
+ return { ok: false, reason: result.reason };
97
+ }
98
+ /* v8 ignore next -- any other kind reaches a store, and these stores throw: only a message can complete here @preserve */
99
+ if (result.friendsKind !== "message" || !result.message)
100
+ return { ok: false, reason: "not_a_message" };
101
+ (0, runtime_1.emitNervesEvent)({
102
+ component: "channels",
103
+ event: "channel.a2a_chat_opened",
104
+ message: "opened a verified A2A chat message",
105
+ meta: { senderDid: input.senderDid, chars: result.message.text.length },
106
+ });
107
+ return {
108
+ ok: true,
109
+ text: result.message.text,
110
+ ...(result.message.conversationId !== undefined ? { conversationId: result.message.conversationId } : {}),
111
+ issuedAt: result.message.issuedAt,
112
+ };
113
+ }