@ouro.bot/cli 0.1.0-alpha.88 → 0.1.0-alpha.880

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 (669) 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 +5601 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2995 -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 +1197 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1127 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2085 -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 +27 -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 +29 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +238 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command.js +151 -0
  59. package/dist/a2a/delegation-stores.js +56 -0
  60. package/dist/a2a/did-resolution.js +93 -0
  61. package/dist/a2a/escalation-grants.js +122 -0
  62. package/dist/a2a/escalation-wiring.js +60 -0
  63. package/dist/a2a/identity.js +204 -0
  64. package/dist/a2a/inbound-share.js +110 -0
  65. package/dist/a2a/mission-result-wire.js +196 -0
  66. package/dist/a2a/onboarding.js +133 -0
  67. package/dist/a2a/outbox-client.js +57 -0
  68. package/dist/a2a/outbox-store.js +188 -0
  69. package/dist/a2a/outbox-wire.js +95 -0
  70. package/dist/a2a/pin-store.js +132 -0
  71. package/dist/a2a/replay-harness.js +175 -0
  72. package/dist/a2a/resolution-proof.js +53 -0
  73. package/dist/a2a/sealed-chat.js +113 -0
  74. package/dist/a2a/seen-ledger.js +120 -0
  75. package/dist/a2a/server.js +766 -0
  76. package/dist/a2a/task-store.js +69 -0
  77. package/dist/a2a/transport.js +45 -0
  78. package/dist/a2a/trusted-files.js +98 -0
  79. package/dist/a2a/types.js +3 -0
  80. package/dist/arc/attention-types.js +8 -0
  81. package/dist/arc/cares.js +360 -0
  82. package/dist/arc/episodes.js +118 -0
  83. package/dist/arc/evolution.js +490 -0
  84. package/dist/arc/flight-recorder.js +1034 -0
  85. package/dist/arc/intentions.js +134 -0
  86. package/dist/arc/json-store.js +117 -0
  87. package/dist/arc/obligations.js +386 -0
  88. package/dist/arc/packets.js +336 -0
  89. package/dist/arc/presence.js +185 -0
  90. package/dist/arc/task-lifecycle.js +57 -0
  91. package/dist/commerce/store.js +755 -0
  92. package/dist/commerce/types.js +3 -0
  93. package/dist/heart/active-work.js +798 -40
  94. package/dist/heart/agent-entry.js +252 -3
  95. package/dist/heart/approval-files.js +113 -0
  96. package/dist/heart/approval-store.js +960 -0
  97. package/dist/heart/attachments/image-normalize.js +194 -0
  98. package/dist/heart/attachments/materialize.js +97 -0
  99. package/dist/heart/attachments/originals.js +88 -0
  100. package/dist/heart/attachments/render.js +29 -0
  101. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  102. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  103. package/dist/heart/attachments/sources/index.js +18 -0
  104. package/dist/heart/attachments/sources/telegram.js +71 -0
  105. package/dist/heart/attachments/store.js +132 -0
  106. package/dist/heart/attachments/types.js +93 -0
  107. package/dist/heart/auth/auth-flow.js +495 -0
  108. package/dist/heart/autonomy-budget.js +478 -0
  109. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  110. package/dist/heart/awaiting/await-alert.js +152 -0
  111. package/dist/heart/awaiting/await-expiry.js +143 -0
  112. package/dist/heart/awaiting/await-loader.js +91 -0
  113. package/dist/heart/awaiting/await-parser.js +152 -0
  114. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  115. package/dist/heart/awaiting/await-scheduler.js +382 -0
  116. package/dist/heart/background-operations.js +281 -0
  117. package/dist/heart/bridges/manager.js +137 -17
  118. package/dist/heart/bridges/store.js +14 -2
  119. package/dist/heart/bundle-state.js +168 -0
  120. package/dist/heart/commitments.js +44 -18
  121. package/dist/heart/config-registry.js +331 -0
  122. package/dist/heart/config.js +174 -131
  123. package/dist/heart/context-loss-gauntlet.js +387 -0
  124. package/dist/heart/context-loss-sentinel.js +1157 -0
  125. package/dist/heart/core.js +2286 -580
  126. package/dist/heart/cross-chat-delivery.js +9 -22
  127. package/dist/heart/daemon/agent-config-check.js +451 -0
  128. package/dist/heart/daemon/agent-discovery.js +185 -3
  129. package/dist/heart/daemon/agent-service.js +542 -0
  130. package/dist/heart/daemon/agentic-repair.js +547 -0
  131. package/dist/heart/daemon/await-private-wake.js +59 -0
  132. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  133. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  134. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  135. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  136. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  137. package/dist/heart/daemon/cadence.js +180 -0
  138. package/dist/heart/daemon/cli-defaults.js +854 -0
  139. package/dist/heart/daemon/cli-desk.js +322 -0
  140. package/dist/heart/daemon/cli-exec.js +8951 -0
  141. package/dist/heart/daemon/cli-help.js +716 -0
  142. package/dist/heart/daemon/cli-parse.js +2941 -0
  143. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  144. package/dist/heart/daemon/cli-render.js +777 -0
  145. package/dist/heart/daemon/cli-types.js +8 -0
  146. package/dist/heart/daemon/connect-bay.js +323 -0
  147. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  148. package/dist/heart/daemon/container-healthcheck.js +112 -0
  149. package/dist/heart/daemon/container-runtime.js +97 -0
  150. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  151. package/dist/heart/daemon/container-spec-auditor.js +232 -0
  152. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  153. package/dist/heart/daemon/daemon-cli.js +29 -2349
  154. package/dist/heart/daemon/daemon-entry.js +932 -11
  155. package/dist/heart/daemon/daemon-health.js +186 -0
  156. package/dist/heart/daemon/daemon-rollup.js +57 -0
  157. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  158. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  159. package/dist/heart/daemon/daemon.js +2084 -105
  160. package/dist/heart/daemon/dns-workflow.js +394 -0
  161. package/dist/heart/daemon/doctor-types.js +8 -0
  162. package/dist/heart/daemon/doctor.js +1755 -0
  163. package/dist/heart/daemon/freshness.js +345 -0
  164. package/dist/heart/daemon/habit-private-wake.js +61 -0
  165. package/dist/heart/daemon/health-monitor.js +142 -11
  166. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  167. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  168. package/dist/heart/daemon/http-health-probe.js +80 -0
  169. package/dist/heart/daemon/human-command-screens.js +234 -0
  170. package/dist/heart/daemon/human-readiness.js +114 -0
  171. package/dist/heart/daemon/inner-status.js +78 -0
  172. package/dist/heart/daemon/interactive-repair.js +394 -0
  173. package/dist/heart/daemon/launchd.js +37 -8
  174. package/dist/heart/daemon/log-tailer.js +79 -10
  175. package/dist/heart/daemon/logs-prune.js +132 -0
  176. package/dist/heart/daemon/mcp-canary.js +524 -0
  177. package/dist/heart/daemon/message-router.js +65 -5
  178. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  179. package/dist/heart/daemon/os-cron-deps.js +135 -0
  180. package/dist/heart/daemon/os-cron.js +22 -14
  181. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  182. package/dist/heart/daemon/ouro-entry.js +3 -1
  183. package/dist/heart/daemon/plugin-cli.js +432 -0
  184. package/dist/heart/daemon/process-manager.js +733 -61
  185. package/dist/heart/daemon/provider-discovery.js +137 -0
  186. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  187. package/dist/heart/daemon/prunable-bundle.js +144 -0
  188. package/dist/heart/daemon/pulse.js +511 -0
  189. package/dist/heart/daemon/readiness-repair.js +365 -0
  190. package/dist/heart/daemon/run-hooks.js +2 -0
  191. package/dist/heart/daemon/runtime-logging.js +47 -14
  192. package/dist/heart/daemon/runtime-metadata.js +2 -30
  193. package/dist/heart/daemon/runtime-mode.js +13 -2
  194. package/dist/heart/daemon/safe-mode.js +161 -0
  195. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  196. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  197. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  198. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  199. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  200. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  201. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  202. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  203. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1310 -0
  204. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  205. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  206. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  207. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  208. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  209. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  210. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  211. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  212. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  213. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  214. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  215. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  216. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  217. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  218. package/dist/heart/daemon/sense-manager.js +699 -48
  219. package/dist/heart/daemon/session-id-resolver.js +131 -0
  220. package/dist/heart/daemon/skill-management-installer.js +1 -1
  221. package/dist/heart/daemon/socket-client.js +180 -12
  222. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  223. package/dist/heart/daemon/startup-tui.js +339 -0
  224. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  225. package/dist/heart/daemon/task-scheduler.js +117 -39
  226. package/dist/heart/daemon/terminal-ui.js +499 -0
  227. package/dist/heart/daemon/thoughts.js +138 -54
  228. package/dist/heart/daemon/up-progress.js +366 -0
  229. package/dist/heart/daemon/vault-items.js +56 -0
  230. package/dist/heart/delegation.js +1 -4
  231. package/dist/heart/external-events/router.js +1516 -0
  232. package/dist/heart/failure-reports.js +335 -0
  233. package/dist/heart/file-lock.js +109 -0
  234. package/dist/heart/frontend-approval-runtime.js +506 -0
  235. package/dist/heart/frontend-journal.js +215 -0
  236. package/dist/heart/frontend-session-service.js +237 -0
  237. package/dist/heart/frontend-socket-client.js +164 -0
  238. package/dist/heart/frontend-socket.js +400 -0
  239. package/dist/heart/habits/habit-cancel.js +810 -0
  240. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  241. package/dist/heart/habits/habit-migration.js +194 -0
  242. package/dist/heart/habits/habit-parser.js +278 -0
  243. package/dist/heart/habits/habit-runtime-state.js +93 -0
  244. package/dist/heart/habits/habit-scheduler.js +653 -0
  245. package/dist/heart/habits/habit-session-summary.js +318 -0
  246. package/dist/heart/habits/habit-session.js +636 -0
  247. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  248. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  249. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  250. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  251. package/dist/heart/identity.js +196 -59
  252. package/dist/heart/kept-notes.js +289 -0
  253. package/dist/heart/kicks.js +1 -1
  254. package/dist/heart/machine-identity.js +161 -0
  255. package/dist/heart/mail-import-discovery.js +356 -0
  256. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  257. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  258. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  259. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  260. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  261. package/dist/heart/mailbox/mailbox-http.js +99 -0
  262. package/dist/heart/mailbox/mailbox-read.js +39 -0
  263. package/dist/heart/mailbox/mailbox-types.js +27 -0
  264. package/dist/heart/mailbox/mailbox-view.js +197 -0
  265. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  266. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  267. package/dist/heart/mailbox/readers/mail.js +375 -0
  268. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  269. package/dist/heart/mailbox/readers/sessions.js +231 -0
  270. package/dist/heart/mailbox/readers/shared.js +111 -0
  271. package/dist/heart/mcp/mcp-server.js +696 -0
  272. package/dist/heart/migrate-config.js +100 -0
  273. package/dist/heart/model-capabilities.js +11 -0
  274. package/dist/heart/orientation-frame.js +345 -0
  275. package/dist/heart/platform.js +81 -0
  276. package/dist/heart/primitives.js +1 -1
  277. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  278. package/dist/heart/private-runtime/index.js +18 -0
  279. package/dist/heart/private-runtime/ledger.js +221 -0
  280. package/dist/heart/private-runtime/policy.js +252 -0
  281. package/dist/heart/private-runtime/types.js +2 -0
  282. package/dist/heart/progress-story.js +1 -1
  283. package/dist/heart/provider-attempt.js +137 -0
  284. package/dist/heart/provider-binding-resolver.js +273 -0
  285. package/dist/heart/provider-credentials.js +449 -0
  286. package/dist/heart/provider-failover.js +311 -0
  287. package/dist/heart/provider-models.js +96 -0
  288. package/dist/heart/provider-ping.js +265 -0
  289. package/dist/heart/provider-readiness-cache.js +119 -0
  290. package/dist/heart/provider-visibility.js +188 -0
  291. package/dist/heart/providers/anthropic-token.js +131 -0
  292. package/dist/heart/providers/anthropic.js +173 -60
  293. package/dist/heart/providers/azure.js +23 -11
  294. package/dist/heart/providers/error-classification.js +127 -0
  295. package/dist/heart/providers/github-copilot.js +34 -38
  296. package/dist/heart/providers/minimax-vlm.js +189 -0
  297. package/dist/heart/providers/minimax.js +26 -8
  298. package/dist/heart/providers/openai-codex-token.js +349 -0
  299. package/dist/heart/providers/openai-codex.js +55 -40
  300. package/dist/heart/providers/openai-compatible.js +177 -0
  301. package/dist/heart/reply-style.js +56 -0
  302. package/dist/heart/run-ledger.js +247 -0
  303. package/dist/heart/runtime-capability-check.js +170 -0
  304. package/dist/heart/runtime-credentials.js +607 -0
  305. package/dist/heart/runtime-cwd.js +87 -0
  306. package/dist/heart/sense-truth.js +22 -4
  307. package/dist/heart/session-activity.js +92 -24
  308. package/dist/heart/session-events.js +1504 -0
  309. package/dist/heart/session-playback-cli-main.js +5 -0
  310. package/dist/heart/session-playback-cli.js +36 -0
  311. package/dist/heart/session-playback.js +231 -0
  312. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  313. package/dist/heart/session-redaction-repair.js +552 -0
  314. package/dist/heart/session-stats-cli-main.js +5 -0
  315. package/dist/heart/session-stats.js +183 -0
  316. package/dist/heart/session-transcript.js +133 -0
  317. package/dist/heart/source-grounding.js +194 -0
  318. package/dist/heart/start-of-turn-packet.js +372 -0
  319. package/dist/heart/steward-policy.js +656 -0
  320. package/dist/heart/streaming.js +604 -207
  321. package/dist/heart/structured-output.js +196 -0
  322. package/dist/heart/sync-classification.js +176 -0
  323. package/dist/heart/sync.js +505 -0
  324. package/dist/heart/target-resolution.js +11 -7
  325. package/dist/heart/tempo.js +93 -0
  326. package/dist/heart/temporal-view.js +41 -0
  327. package/dist/heart/timeouts.js +101 -0
  328. package/dist/heart/tool-activity-callbacks.js +59 -0
  329. package/dist/heart/tool-approval.js +382 -0
  330. package/dist/heart/tool-description.js +155 -0
  331. package/dist/heart/tool-friction.js +55 -0
  332. package/dist/heart/tool-loop.js +206 -0
  333. package/dist/heart/turn-context.js +487 -0
  334. package/dist/heart/turn-execution-lease.js +30 -0
  335. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  336. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  337. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  338. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  339. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  340. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  341. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  342. package/dist/heart/versioning/update-hooks.js +154 -0
  343. package/dist/heart/versioning/version-intent.js +114 -0
  344. package/dist/heart/work-card.js +380 -0
  345. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  346. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  347. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  348. package/dist/mailbox-ui/index.html +16 -0
  349. package/dist/mailroom/attention.js +167 -0
  350. package/dist/mailroom/autonomy.js +209 -0
  351. package/dist/mailroom/blob-store.js +889 -0
  352. package/dist/mailroom/body-cache.js +61 -0
  353. package/dist/mailroom/cache-sync-cli.js +58 -0
  354. package/dist/mailroom/core.js +803 -0
  355. package/dist/mailroom/entry.js +160 -0
  356. package/dist/mailroom/file-store.js +568 -0
  357. package/dist/mailroom/hosted-cache-sync.js +384 -0
  358. package/dist/mailroom/mbox-import.js +393 -0
  359. package/dist/mailroom/migration.js +164 -0
  360. package/dist/mailroom/outbound.js +380 -0
  361. package/dist/mailroom/policy.js +263 -0
  362. package/dist/mailroom/reader.js +292 -0
  363. package/dist/mailroom/search-cache.js +513 -0
  364. package/dist/mailroom/search-relevance.js +319 -0
  365. package/dist/mailroom/smtp-ingress.js +176 -0
  366. package/dist/mailroom/source-state.js +176 -0
  367. package/dist/mailroom/thread.js +109 -0
  368. package/dist/mailroom/travel-extract.js +89 -0
  369. package/dist/mind/bundle-manifest.js +24 -2
  370. package/dist/mind/context.js +307 -139
  371. package/dist/mind/desk-section.js +362 -0
  372. package/dist/mind/diary-integrity.js +60 -0
  373. package/dist/mind/{memory.js → diary.js} +68 -77
  374. package/dist/mind/embedding-provider.js +60 -0
  375. package/dist/mind/file-state.js +179 -0
  376. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  377. package/dist/mind/obligation-steering.js +199 -3
  378. package/dist/mind/pending.js +36 -10
  379. package/dist/mind/prompt-budget.js +479 -0
  380. package/dist/mind/prompt-refresh.js +3 -2
  381. package/dist/mind/prompt.js +1048 -198
  382. package/dist/mind/provenance-trust.js +26 -0
  383. package/dist/mind/record-paths.js +312 -0
  384. package/dist/mind/scrutiny.js +173 -0
  385. package/dist/mind/session-transaction.js +564 -0
  386. package/dist/nerves/cli-logging.js +7 -1
  387. package/dist/nerves/coverage/audit-rules.js +15 -6
  388. package/dist/nerves/coverage/audit.js +28 -2
  389. package/dist/nerves/coverage/cli.js +1 -1
  390. package/dist/nerves/coverage/contract.js +5 -5
  391. package/dist/nerves/coverage/file-completeness.js +139 -5
  392. package/dist/nerves/coverage/run-artifacts.js +55 -35
  393. package/dist/nerves/coverage/source-scanner.js +4 -4
  394. package/dist/nerves/event-buffer.js +111 -0
  395. package/dist/nerves/index.js +293 -9
  396. package/dist/nerves/observation.js +20 -0
  397. package/dist/nerves/redact.js +79 -0
  398. package/dist/nerves/review/cli-main.js +5 -0
  399. package/dist/nerves/review/cli.js +156 -0
  400. package/dist/nerves/review/core.js +159 -0
  401. package/dist/nerves/runtime.js +17 -1
  402. package/dist/repertoire/ado-client.js +15 -56
  403. package/dist/repertoire/ado-semantic.js +16 -10
  404. package/dist/repertoire/api-client.js +97 -0
  405. package/dist/repertoire/bitwarden-store.js +1045 -0
  406. package/dist/repertoire/bundle-templates.js +71 -0
  407. package/dist/repertoire/bw-installer.js +180 -0
  408. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  409. package/dist/repertoire/coding/context-pack.js +331 -0
  410. package/dist/repertoire/coding/feedback.js +174 -32
  411. package/dist/repertoire/coding/index.js +15 -3
  412. package/dist/repertoire/coding/manager.js +159 -10
  413. package/dist/repertoire/coding/spawner.js +58 -11
  414. package/dist/repertoire/coding/tools.js +221 -15
  415. package/dist/repertoire/coding/workbench-client.js +272 -0
  416. package/dist/repertoire/coding/workbench-manager.js +346 -0
  417. package/dist/repertoire/commerce-errors.js +109 -0
  418. package/dist/repertoire/commerce-self-test.js +156 -0
  419. package/dist/repertoire/credential-access.js +178 -0
  420. package/dist/repertoire/desk/classifier.js +362 -0
  421. package/dist/repertoire/duffel-client.js +185 -0
  422. package/dist/repertoire/github-client.js +14 -55
  423. package/dist/repertoire/graph-client.js +11 -52
  424. package/dist/repertoire/guardrails.js +873 -19
  425. package/dist/repertoire/house-sweep.js +466 -0
  426. package/dist/repertoire/mcp-client.js +58 -5
  427. package/dist/repertoire/mcp-manager.js +427 -139
  428. package/dist/repertoire/mcp-tools.js +132 -0
  429. package/dist/repertoire/mcp-write-guard.js +46 -0
  430. package/dist/repertoire/plugin-mcp.js +175 -0
  431. package/dist/repertoire/plugins.js +253 -0
  432. package/dist/repertoire/relationship-authorization.js +322 -0
  433. package/dist/repertoire/shell-sessions.js +134 -0
  434. package/dist/repertoire/skills.js +48 -4
  435. package/dist/repertoire/stripe-client.js +131 -0
  436. package/dist/repertoire/tool-arguments.js +182 -0
  437. package/dist/repertoire/tool-results.js +29 -0
  438. package/dist/repertoire/tools-a2a.js +699 -0
  439. package/dist/repertoire/tools-attachments.js +322 -0
  440. package/dist/repertoire/tools-awaiting.js +870 -0
  441. package/dist/repertoire/tools-base.js +79 -1168
  442. package/dist/repertoire/tools-bluebubbles.js +2 -0
  443. package/dist/repertoire/tools-bridge.js +144 -0
  444. package/dist/repertoire/tools-bundle.js +993 -0
  445. package/dist/repertoire/tools-commerce.js +253 -0
  446. package/dist/repertoire/tools-config.js +186 -0
  447. package/dist/repertoire/tools-continuity.js +575 -0
  448. package/dist/repertoire/tools-credential.js +383 -0
  449. package/dist/repertoire/tools-escalation.js +84 -0
  450. package/dist/repertoire/tools-evolution.js +527 -0
  451. package/dist/repertoire/tools-files.js +344 -0
  452. package/dist/repertoire/tools-flight.js +290 -0
  453. package/dist/repertoire/tools-flow.js +119 -0
  454. package/dist/repertoire/tools-github.js +3 -8
  455. package/dist/repertoire/tools-habits.js +103 -0
  456. package/dist/repertoire/tools-house-care.js +138 -0
  457. package/dist/repertoire/tools-mail.js +1828 -0
  458. package/dist/repertoire/tools-notes.js +496 -0
  459. package/dist/repertoire/tools-obligations.js +182 -0
  460. package/dist/repertoire/tools-orientation.js +31 -0
  461. package/dist/repertoire/tools-record.js +482 -0
  462. package/dist/repertoire/tools-rsvp.js +139 -0
  463. package/dist/repertoire/tools-runtime.js +238 -0
  464. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  465. package/dist/repertoire/tools-session.js +1133 -0
  466. package/dist/repertoire/tools-shell.js +149 -0
  467. package/dist/repertoire/tools-steward-policy.js +147 -0
  468. package/dist/repertoire/tools-stripe.js +224 -0
  469. package/dist/repertoire/tools-surface.js +369 -0
  470. package/dist/repertoire/tools-teams.js +12 -39
  471. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  472. package/dist/repertoire/tools-travel.js +125 -0
  473. package/dist/repertoire/tools-trip.js +982 -0
  474. package/dist/repertoire/tools-unraid.js +556 -0
  475. package/dist/repertoire/tools-user-profile.js +146 -0
  476. package/dist/repertoire/tools-vault.js +40 -0
  477. package/dist/repertoire/tools-voice.js +145 -0
  478. package/dist/repertoire/tools.js +509 -156
  479. package/dist/repertoire/travel-api-client.js +360 -0
  480. package/dist/repertoire/unraid-client.js +155 -0
  481. package/dist/repertoire/unraid-restart.js +339 -0
  482. package/dist/repertoire/user-profile.js +131 -0
  483. package/dist/repertoire/vault-setup.js +246 -0
  484. package/dist/repertoire/vault-unlock.js +628 -0
  485. package/dist/rsvp/aisleplanner-client.js +354 -0
  486. package/dist/rsvp/cli.js +926 -0
  487. package/dist/rsvp/config.js +327 -0
  488. package/dist/rsvp/cutover.js +433 -0
  489. package/dist/rsvp/diagnostics.js +232 -0
  490. package/dist/rsvp/diff-renderer.js +176 -0
  491. package/dist/rsvp/habit-policy.js +110 -0
  492. package/dist/rsvp/habit-stage.js +123 -0
  493. package/dist/rsvp/incident-bundle.js +97 -0
  494. package/dist/rsvp/migration.js +204 -0
  495. package/dist/rsvp/native-habit-runner.js +630 -0
  496. package/dist/rsvp/outbound-state.js +628 -0
  497. package/dist/rsvp/query.js +118 -0
  498. package/dist/rsvp/replay.js +233 -0
  499. package/dist/rsvp/snapshot.js +232 -0
  500. package/dist/rsvp/spend-ledger.js +175 -0
  501. package/dist/scripts/claude-code-hook.js +41 -0
  502. package/dist/scripts/claude-code-stop-hook.js +47 -0
  503. package/dist/senses/a2a-entry.js +131 -0
  504. package/dist/senses/acp-server.js +386 -0
  505. package/dist/senses/attention-queue.js +186 -0
  506. package/dist/senses/await-turn-message.js +65 -0
  507. package/dist/senses/bluebubbles/active-turns.js +216 -0
  508. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  509. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  510. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  511. package/dist/senses/bluebubbles/context-packet.js +207 -0
  512. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  513. package/dist/senses/bluebubbles/entry.js +90 -0
  514. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  515. package/dist/senses/bluebubbles/index.js +3841 -0
  516. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  517. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  518. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  519. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  520. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  521. package/dist/senses/bluebubbles/processed-log.js +133 -0
  522. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  523. package/dist/senses/bluebubbles/replay.js +284 -0
  524. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  525. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  526. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  527. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  528. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  529. package/dist/senses/cli/bracketed-paste.js +82 -0
  530. package/dist/senses/cli/image-paste.js +287 -0
  531. package/dist/senses/cli/image-ref-navigation.js +75 -0
  532. package/dist/senses/cli/ink-app.js +156 -0
  533. package/dist/senses/cli/inline-diff.js +64 -0
  534. package/dist/senses/cli/input-keys.js +174 -0
  535. package/dist/senses/cli/kill-ring.js +86 -0
  536. package/dist/senses/cli/message-list.js +51 -0
  537. package/dist/senses/cli/ouro-tui.js +607 -0
  538. package/dist/senses/cli/spinner-imperative.js +135 -0
  539. package/dist/senses/cli/spinner.js +101 -0
  540. package/dist/senses/cli/status-line.js +60 -0
  541. package/dist/senses/cli/streaming-markdown.js +526 -0
  542. package/dist/senses/cli/tool-display.js +85 -0
  543. package/dist/senses/cli/tool-render.js +85 -0
  544. package/dist/senses/cli/tui-store.js +241 -0
  545. package/dist/senses/cli/virtual-list.js +35 -0
  546. package/dist/senses/cli-entry.js +60 -8
  547. package/dist/senses/cli.js +601 -304
  548. package/dist/senses/commands.js +66 -3
  549. package/dist/senses/context-packet-ledger.js +371 -0
  550. package/dist/senses/context-packets.js +154 -0
  551. package/dist/senses/habit-lifecycle-guard.js +24 -0
  552. package/dist/senses/habit-turn-message.js +160 -0
  553. package/dist/senses/ingress-evidence.js +2 -0
  554. package/dist/senses/mail-entry.js +66 -0
  555. package/dist/senses/mail.js +524 -0
  556. package/dist/senses/pipeline.js +1115 -204
  557. package/dist/senses/private-runtime-worker.js +859 -0
  558. package/dist/senses/private-runtime.js +1619 -0
  559. package/dist/senses/proactive-content-guard.js +51 -0
  560. package/dist/senses/root-host-approval-port.js +345 -0
  561. package/dist/senses/root-host-approval-runtime.js +393 -0
  562. package/dist/senses/sanctuary-authority-resident.js +102 -0
  563. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  564. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  565. package/dist/senses/sanctuary-grounding.js +118 -0
  566. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  567. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  568. package/dist/senses/sanctuary-health-runner.js +104 -0
  569. package/dist/senses/sanctuary-health.js +422 -0
  570. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  571. package/dist/senses/sanctuary-interactive-control.js +410 -0
  572. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  573. package/dist/senses/sanctuary-media-optimization.js +514 -0
  574. package/dist/senses/sanctuary-runtime.js +347 -0
  575. package/dist/senses/sanctuary-sab.js +85 -0
  576. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  577. package/dist/senses/shared-turn.js +789 -0
  578. package/dist/senses/surface-tool.js +109 -0
  579. package/dist/senses/teams-entry.js +60 -8
  580. package/dist/senses/teams.js +519 -218
  581. package/dist/senses/telegram-admission.js +718 -0
  582. package/dist/senses/telegram-approval-runtime.js +793 -0
  583. package/dist/senses/telegram-attachments.js +186 -0
  584. package/dist/senses/telegram-audit-ledger.js +220 -0
  585. package/dist/senses/telegram-authority-transport.js +231 -0
  586. package/dist/senses/telegram-client.js +1749 -0
  587. package/dist/senses/telegram-effect-adapter.js +900 -0
  588. package/dist/senses/telegram-entry.js +83 -0
  589. package/dist/senses/telegram.js +2349 -0
  590. package/dist/senses/trust-gate.js +104 -9
  591. package/dist/senses/voice/audio-playback.js +237 -0
  592. package/dist/senses/voice/audio-routing.js +119 -0
  593. package/dist/senses/voice/elevenlabs.js +202 -0
  594. package/dist/senses/voice/floor-control.js +431 -0
  595. package/dist/senses/voice/floor-controller.js +115 -0
  596. package/dist/senses/voice/golden-path.js +116 -0
  597. package/dist/senses/voice/index.js +29 -0
  598. package/dist/senses/voice/meeting.js +113 -0
  599. package/dist/senses/voice/outbound.js +190 -0
  600. package/dist/senses/voice/phone.js +33 -0
  601. package/dist/senses/voice/playback.js +139 -0
  602. package/dist/senses/voice/realtime-eval.js +496 -0
  603. package/dist/senses/voice/realtime-trace.js +531 -0
  604. package/dist/senses/voice/transcript.js +70 -0
  605. package/dist/senses/voice/turn.js +191 -0
  606. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  607. package/dist/senses/voice/twilio-phone.js +5031 -0
  608. package/dist/senses/voice/types.js +2 -0
  609. package/dist/senses/voice/whisper.js +161 -0
  610. package/dist/senses/voice-entry.js +81 -0
  611. package/dist/senses/voice-realtime-eval-command.js +99 -0
  612. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  613. package/dist/senses/voice-twilio-entry.js +87 -0
  614. package/dist/trips/core.js +138 -0
  615. package/dist/trips/store.js +265 -0
  616. package/dist/util/frontmatter.js +69 -0
  617. package/npm-shrinkwrap.json +8100 -0
  618. package/package.json +73 -13
  619. package/skills/agent-commerce.md +113 -0
  620. package/skills/browser-navigation.md +117 -0
  621. package/skills/commerce-setup-guide.md +116 -0
  622. package/skills/commerce-setup.md +84 -0
  623. package/skills/configure-dev-tools.md +99 -0
  624. package/skills/travel-planning.md +138 -0
  625. package/dist/heart/daemon/auth-flow.js +0 -430
  626. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  627. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  628. package/dist/heart/daemon/update-hooks.js +0 -138
  629. package/dist/heart/obligations.js +0 -191
  630. package/dist/heart/safe-workspace.js +0 -362
  631. package/dist/heart/session-recall.js +0 -116
  632. package/dist/mind/friends/channel.js +0 -84
  633. package/dist/mind/friends/group-context.js +0 -144
  634. package/dist/mind/friends/resolver.js +0 -84
  635. package/dist/mind/friends/store-file.js +0 -190
  636. package/dist/mind/friends/store.js +0 -4
  637. package/dist/mind/friends/tokens.js +0 -26
  638. package/dist/mind/friends/trust-explanation.js +0 -74
  639. package/dist/mind/friends/types.js +0 -29
  640. package/dist/repertoire/tasks/board.js +0 -134
  641. package/dist/repertoire/tasks/index.js +0 -224
  642. package/dist/repertoire/tasks/lifecycle.js +0 -80
  643. package/dist/repertoire/tasks/middleware.js +0 -65
  644. package/dist/repertoire/tasks/parser.js +0 -173
  645. package/dist/repertoire/tasks/scanner.js +0 -132
  646. package/dist/repertoire/tasks/transitions.js +0 -144
  647. package/dist/senses/bluebubbles-entry.js +0 -13
  648. package/dist/senses/bluebubbles.js +0 -1181
  649. package/dist/senses/debug-activity.js +0 -154
  650. package/dist/senses/inner-dialog-worker.js +0 -90
  651. package/dist/senses/inner-dialog.js +0 -525
  652. package/subagents/README.md +0 -7
  653. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  654. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  655. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  656. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  657. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  658. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  659. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  660. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  661. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  662. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  663. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  664. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  665. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  666. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  667. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  668. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  669. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -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,175 @@
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.appendReplayNotice = appendReplayNotice;
43
+ exports.replayNoticeRecorded = replayNoticeRecorded;
44
+ const fs = __importStar(require("node:fs"));
45
+ const path = __importStar(require("path"));
46
+ const runtime_1 = require("../nerves/runtime");
47
+ /**
48
+ * The replay gate drives the Butler over its real A2A path to check its behaviour after an upgrade. Every delegated
49
+ * command and every A2A-filed await would otherwise post to the owner's Telegram chat. While the host's gate holds a
50
+ * replay window open for a peer, those notices are appended to a local sink instead.
51
+ *
52
+ * The window narrows where a notice goes, never whether a command is authorized: the grant, family trust, sole owner
53
+ * and notify-before-run checks are unchanged, and "notify" means "the sink write succeeded". The window file lives
54
+ * under the bundle's state directory, is written by the host's gate and cleared when its run ends, and every entry
55
+ * expires on its own (and is ignored if it claims to last longer than the cap).
56
+ */
57
+ exports.REPLAY_WINDOW_MAX_MS = 2 * 60 * 60 * 1000;
58
+ function replayDir(agentRoot) {
59
+ return path.join(agentRoot, "state", "replay");
60
+ }
61
+ function replayWindowPath(agentRoot) {
62
+ return path.join(replayDir(agentRoot), "window.json");
63
+ }
64
+ function replaySinkPath(agentRoot) {
65
+ return path.join(replayDir(agentRoot), "notices.ndjson");
66
+ }
67
+ /** Permanent registry of replay identities, written by the host's provisioning and never cleared. */
68
+ function replayIdentitiesPath(agentRoot) {
69
+ return path.join(replayDir(agentRoot), "identities.json");
70
+ }
71
+ function listsFriend(file, friendId) {
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(fs.readFileSync(file, "utf8"));
75
+ }
76
+ catch (error) {
77
+ // A missing file lists nobody; a file that exists but cannot be read or parsed fails closed.
78
+ return error.code !== "ENOENT";
79
+ }
80
+ const friends = parsed?.friends;
81
+ return !!friends && typeof friends === "object" && Object.hasOwn(friends, friendId);
82
+ }
83
+ /**
84
+ * True when `friendId` is a replay identity: listed in the permanent registry, or holding any window entry (open or
85
+ * expired). Unlike the window check this needs no trusted-owner proof, because the marker only ever restricts: forging
86
+ * an entry can block a friend from writing owner policy, never grant anything. Owner policy writes refuse these identities.
87
+ */
88
+ function isReplayIdentity(agentRoot, friendId) {
89
+ return listsFriend(replayIdentitiesPath(agentRoot), friendId) || listsFriend(replayWindowPath(agentRoot), friendId);
90
+ }
91
+ /** A root-controlled directory: a real directory (no symlink), owned by the trusted uid, writable by neither group nor other. */
92
+ function isTrustedDirectory(target, trustedUid) {
93
+ try {
94
+ const stat = fs.lstatSync(target);
95
+ return stat.isDirectory() && !stat.isSymbolicLink() && stat.uid === trustedUid && (stat.mode & 0o022) === 0;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * Reads the window file only if the file actually opened is trusted. The path is opened once with O_NOFOLLOW, then the
103
+ * descriptor itself is checked (regular file, trusted owner, not group- or other-writable) and read, so a rename loop on
104
+ * the Butler's own state directory cannot swap a different file in between the check and the read. Any error is "no window".
105
+ */
106
+ function readTrustedWindow(file, trustedUid) {
107
+ let fd;
108
+ try {
109
+ fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
110
+ const stat = fs.fstatSync(fd);
111
+ if (!stat.isFile() || stat.uid !== trustedUid || (stat.mode & 0o022) !== 0)
112
+ return undefined;
113
+ return JSON.parse(fs.readFileSync(fd, "utf8"));
114
+ }
115
+ catch {
116
+ return undefined;
117
+ }
118
+ finally {
119
+ if (fd !== undefined)
120
+ fs.closeSync(fd);
121
+ }
122
+ }
123
+ /**
124
+ * 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".
125
+ * The state directory is the Butler's own, so it could swap in a directory and window of its own making: only a replay
126
+ * directory and window file that root owns, and nobody else can write, count; anything else fails toward Telegram.
127
+ */
128
+ function isReplayWindowOpen(agentRoot, friendId, now = Date.now(), trustedUid = 0) {
129
+ if (!isTrustedDirectory(replayDir(agentRoot), trustedUid))
130
+ return false;
131
+ const parsed = readTrustedWindow(replayWindowPath(agentRoot), trustedUid);
132
+ const friends = parsed?.friends;
133
+ if (!friends || typeof friends !== "object")
134
+ return false;
135
+ const entry = friends[friendId];
136
+ const expiresAt = typeof entry?.expiresAt === "string"
137
+ ? Date.parse(entry.expiresAt)
138
+ : Number.NaN;
139
+ return Number.isFinite(expiresAt) && expiresAt > now && expiresAt <= now + exports.REPLAY_WINDOW_MAX_MS;
140
+ }
141
+ /** 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. */
142
+ function appendReplayNotice(agentRoot, notice, now = Date.now()) {
143
+ if (replayNoticeRecorded(agentRoot, notice.noticeId, notice.friendId))
144
+ return;
145
+ fs.mkdirSync(replayDir(agentRoot), { recursive: true });
146
+ const line = JSON.stringify({ at: new Date(now).toISOString(), ...notice });
147
+ fs.appendFileSync(replaySinkPath(agentRoot), `${line}\n`, { mode: 0o600 });
148
+ (0, runtime_1.emitNervesEvent)({
149
+ component: "senses",
150
+ event: "senses.a2a_replay_notice_sunk",
151
+ message: "wrote an owner notice to the replay sink instead of Telegram",
152
+ meta: { noticeId: notice.noticeId, friendId: notice.friendId },
153
+ });
154
+ }
155
+ /** 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. */
156
+ function replayNoticeRecorded(agentRoot, noticeId, friendId) {
157
+ let raw;
158
+ try {
159
+ raw = fs.readFileSync(replaySinkPath(agentRoot), "utf8");
160
+ }
161
+ catch {
162
+ return false;
163
+ }
164
+ return raw.split("\n").some((line) => {
165
+ if (!line)
166
+ return false;
167
+ try {
168
+ const entry = JSON.parse(line);
169
+ return entry.noticeId === noticeId && entry.friendId === friendId;
170
+ }
171
+ catch {
172
+ return false;
173
+ }
174
+ });
175
+ }
@@ -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
+ }
@@ -0,0 +1,120 @@
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.FileA2ASeenLedger = 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 runtime_1 = require("../nerves/runtime");
41
+ function nonceFileName(nonce) {
42
+ return `${(0, node_crypto_1.createHash)("sha256").update(nonce).digest("hex")}.json`;
43
+ }
44
+ class FileA2ASeenLedger {
45
+ dir;
46
+ cache = new Set();
47
+ constructor(agentRoot) {
48
+ this.dir = path.join(agentRoot, "state", "a2a", "seen");
49
+ fs.mkdirSync(this.dir, { recursive: true });
50
+ this.loadExisting();
51
+ (0, runtime_1.emitNervesEvent)({
52
+ component: "channels",
53
+ event: "channel.a2a_seen_ledger_init",
54
+ message: "initialized durable A2A seen ledger",
55
+ meta: { dir: this.dir, seen: this.cache.size },
56
+ });
57
+ }
58
+ get size() {
59
+ return this.cache.size;
60
+ }
61
+ isSeen(nonce) {
62
+ if (!nonce)
63
+ return false;
64
+ const seen = this.cache.has(nonce);
65
+ if (seen) {
66
+ // A nonce we already processed is arriving again — for a seal nonce this is
67
+ // a replay. Loud security signal.
68
+ (0, runtime_1.emitNervesEvent)({
69
+ component: "channels",
70
+ event: "channel.a2a_replay_rejected",
71
+ message: "A2A replay rejected (nonce already seen)",
72
+ meta: { nonceHash: nonceFileName(nonce).slice(0, 16) },
73
+ });
74
+ }
75
+ return seen;
76
+ }
77
+ markSeen(nonce) {
78
+ // An empty-string nonce is never a matchable key — stay inert.
79
+ if (!nonce)
80
+ return;
81
+ if (this.cache.has(nonce))
82
+ return;
83
+ fs.writeFileSync(path.join(this.dir, nonceFileName(nonce)), `${JSON.stringify({ nonce, markedAt: new Date().toISOString() }, null, 2)}\n`, "utf-8");
84
+ this.cache.add(nonce);
85
+ (0, runtime_1.emitNervesEvent)({
86
+ component: "channels",
87
+ event: "channel.a2a_seen_marked",
88
+ message: "marked A2A seal nonce as seen (first sight)",
89
+ meta: { nonceHash: nonceFileName(nonce).slice(0, 16) },
90
+ });
91
+ }
92
+ /** Reload every persisted nonce from disk into the in-memory set (the restart
93
+ * replay defense). Corrupt/unreadable artifacts are skipped so one bad file can
94
+ * never reopen the replay window for the rest. */
95
+ loadExisting() {
96
+ let entries;
97
+ try {
98
+ entries = fs.readdirSync(this.dir);
99
+ }
100
+ catch {
101
+ /* v8 ignore next -- the constructor mkdirSync's the dir before this runs; unreadable dir is unreachable in practice @preserve */
102
+ return;
103
+ }
104
+ for (const name of entries) {
105
+ if (!name.endsWith(".json"))
106
+ continue;
107
+ let record;
108
+ try {
109
+ record = JSON.parse(fs.readFileSync(path.join(this.dir, name), "utf-8"));
110
+ }
111
+ catch {
112
+ continue;
113
+ }
114
+ if (typeof record.nonce === "string" && record.nonce.length > 0) {
115
+ this.cache.add(record.nonce);
116
+ }
117
+ }
118
+ }
119
+ }
120
+ exports.FileA2ASeenLedger = FileA2ASeenLedger;