@ouro.bot/cli 0.1.0-alpha.58 → 0.1.0-alpha.581

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 (404) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +3745 -0
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +140 -0
  15. package/dist/arc/episodes.js +117 -0
  16. package/dist/arc/intentions.js +133 -0
  17. package/dist/arc/json-store.js +117 -0
  18. package/dist/arc/obligations.js +237 -0
  19. package/dist/arc/packets.js +193 -0
  20. package/dist/arc/presence.js +185 -0
  21. package/dist/arc/task-lifecycle.js +65 -0
  22. package/dist/heart/active-work.js +837 -26
  23. package/dist/heart/agent-entry.js +69 -3
  24. package/dist/heart/attachments/image-normalize.js +194 -0
  25. package/dist/heart/attachments/materialize.js +97 -0
  26. package/dist/heart/attachments/originals.js +88 -0
  27. package/dist/heart/attachments/render.js +29 -0
  28. package/dist/heart/attachments/sources/adapter.js +2 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/background-operations.js +281 -0
  36. package/dist/heart/bundle-state.js +168 -0
  37. package/dist/heart/commitments.js +111 -0
  38. package/dist/heart/config-registry.js +322 -0
  39. package/dist/heart/config.js +114 -118
  40. package/dist/heart/core.js +909 -246
  41. package/dist/heart/cross-chat-delivery.js +3 -18
  42. package/dist/heart/daemon/agent-config-check.js +419 -0
  43. package/dist/heart/daemon/agent-discovery.js +102 -3
  44. package/dist/heart/daemon/agent-service.js +522 -0
  45. package/dist/heart/daemon/agentic-repair.js +547 -0
  46. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  47. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  48. package/dist/heart/daemon/cadence.js +70 -0
  49. package/dist/heart/daemon/cli-defaults.js +776 -0
  50. package/dist/heart/daemon/cli-exec.js +7559 -0
  51. package/dist/heart/daemon/cli-help.js +498 -0
  52. package/dist/heart/daemon/cli-parse.js +1592 -0
  53. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  54. package/dist/heart/daemon/cli-render.js +763 -0
  55. package/dist/heart/daemon/cli-types.js +8 -0
  56. package/dist/heart/daemon/connect-bay.js +323 -0
  57. package/dist/heart/daemon/daemon-cli.js +29 -1703
  58. package/dist/heart/daemon/daemon-entry.js +387 -2
  59. package/dist/heart/daemon/daemon-health.js +176 -0
  60. package/dist/heart/daemon/daemon-rollup.js +57 -0
  61. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  62. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  63. package/dist/heart/daemon/daemon.js +816 -71
  64. package/dist/heart/daemon/dns-workflow.js +394 -0
  65. package/dist/heart/daemon/doctor-types.js +8 -0
  66. package/dist/heart/daemon/doctor.js +873 -0
  67. package/dist/heart/daemon/health-monitor.js +122 -1
  68. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  69. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  70. package/dist/heart/daemon/http-health-probe.js +80 -0
  71. package/dist/heart/daemon/human-command-screens.js +234 -0
  72. package/dist/heart/daemon/human-readiness.js +114 -0
  73. package/dist/heart/daemon/inner-status.js +89 -0
  74. package/dist/heart/daemon/interactive-repair.js +394 -0
  75. package/dist/heart/daemon/launchd.js +37 -8
  76. package/dist/heart/daemon/log-tailer.js +82 -12
  77. package/dist/heart/daemon/logs-prune.js +110 -0
  78. package/dist/heart/daemon/mcp-canary.js +297 -0
  79. package/dist/heart/daemon/message-router.js +2 -2
  80. package/dist/heart/daemon/os-cron-deps.js +135 -0
  81. package/dist/heart/daemon/os-cron.js +14 -12
  82. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  83. package/dist/heart/daemon/ouro-entry.js +3 -1
  84. package/dist/heart/daemon/process-manager.js +375 -33
  85. package/dist/heart/daemon/provider-discovery.js +137 -0
  86. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  87. package/dist/heart/daemon/pulse.js +475 -0
  88. package/dist/heart/daemon/readiness-repair.js +365 -0
  89. package/dist/heart/daemon/run-hooks.js +2 -0
  90. package/dist/heart/daemon/runtime-logging.js +30 -6
  91. package/dist/heart/daemon/runtime-metadata.js +3 -31
  92. package/dist/heart/daemon/safe-mode.js +161 -0
  93. package/dist/heart/daemon/sense-manager.js +462 -38
  94. package/dist/heart/daemon/session-id-resolver.js +131 -0
  95. package/dist/heart/daemon/skill-management-installer.js +94 -0
  96. package/dist/heart/daemon/socket-client.js +158 -11
  97. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  98. package/dist/heart/daemon/startup-tui.js +330 -0
  99. package/dist/heart/daemon/task-scheduler.js +3 -25
  100. package/dist/heart/daemon/terminal-ui.js +499 -0
  101. package/dist/heart/daemon/thoughts.js +162 -17
  102. package/dist/heart/daemon/up-progress.js +366 -0
  103. package/dist/heart/daemon/vault-items.js +56 -0
  104. package/dist/heart/delegation.js +1 -1
  105. package/dist/heart/habits/habit-migration.js +189 -0
  106. package/dist/heart/habits/habit-parser.js +140 -0
  107. package/dist/heart/habits/habit-runtime-state.js +100 -0
  108. package/dist/heart/habits/habit-scheduler.js +372 -0
  109. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  110. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  111. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  112. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  113. package/dist/heart/identity.js +203 -57
  114. package/dist/heart/kept-notes.js +357 -0
  115. package/dist/heart/kicks.js +1 -1
  116. package/dist/heart/machine-identity.js +161 -0
  117. package/dist/heart/mail-import-discovery.js +353 -0
  118. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  119. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  120. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  121. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  122. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  123. package/dist/heart/mailbox/mailbox-http.js +99 -0
  124. package/dist/heart/mailbox/mailbox-read.js +31 -0
  125. package/dist/heart/mailbox/mailbox-types.js +27 -0
  126. package/dist/heart/mailbox/mailbox-view.js +195 -0
  127. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  128. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  129. package/dist/heart/mailbox/readers/mail.js +362 -0
  130. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  131. package/dist/heart/mailbox/readers/sessions.js +232 -0
  132. package/dist/heart/mailbox/readers/shared.js +111 -0
  133. package/dist/heart/mcp/mcp-server.js +656 -0
  134. package/dist/heart/migrate-config.js +100 -0
  135. package/dist/heart/model-capabilities.js +19 -0
  136. package/dist/heart/platform.js +81 -0
  137. package/dist/heart/provider-attempt.js +134 -0
  138. package/dist/heart/provider-binding-resolver.js +267 -0
  139. package/dist/heart/provider-credentials.js +425 -0
  140. package/dist/heart/provider-failover.js +301 -0
  141. package/dist/heart/provider-models.js +81 -0
  142. package/dist/heart/provider-ping.js +262 -0
  143. package/dist/heart/provider-readiness-cache.js +40 -0
  144. package/dist/heart/provider-visibility.js +188 -0
  145. package/dist/heart/providers/anthropic-token.js +131 -0
  146. package/dist/heart/providers/anthropic.js +139 -52
  147. package/dist/heart/providers/azure.js +97 -13
  148. package/dist/heart/providers/error-classification.js +127 -0
  149. package/dist/heart/providers/github-copilot.js +145 -0
  150. package/dist/heart/providers/minimax-vlm.js +189 -0
  151. package/dist/heart/providers/minimax.js +26 -8
  152. package/dist/heart/providers/openai-codex.js +55 -40
  153. package/dist/heart/runtime-capability-check.js +170 -0
  154. package/dist/heart/runtime-credentials.js +367 -0
  155. package/dist/heart/runtime-cwd.js +87 -0
  156. package/dist/heart/sense-truth.js +13 -4
  157. package/dist/heart/session-activity.js +43 -22
  158. package/dist/heart/session-events.js +1149 -0
  159. package/dist/heart/session-playback-cli-main.js +5 -0
  160. package/dist/heart/session-playback-cli.js +36 -0
  161. package/dist/heart/session-playback.js +231 -0
  162. package/dist/heart/session-stats-cli-main.js +5 -0
  163. package/dist/heart/session-stats.js +182 -0
  164. package/dist/heart/session-transcript.js +243 -0
  165. package/dist/heart/start-of-turn-packet.js +345 -0
  166. package/dist/heart/streaming.js +44 -27
  167. package/dist/heart/sync-classification.js +176 -0
  168. package/dist/heart/sync.js +449 -0
  169. package/dist/heart/target-resolution.js +9 -5
  170. package/dist/heart/tempo.js +93 -0
  171. package/dist/heart/temporal-view.js +41 -0
  172. package/dist/heart/timeouts.js +101 -0
  173. package/dist/heart/tool-activity-callbacks.js +59 -0
  174. package/dist/heart/tool-description.js +143 -0
  175. package/dist/heart/tool-friction.js +55 -0
  176. package/dist/heart/tool-loop.js +200 -0
  177. package/dist/heart/turn-context.js +421 -0
  178. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  179. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  180. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  181. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  182. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  183. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  184. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  185. package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
  186. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  187. package/dist/mailbox-ui/index.html +15 -0
  188. package/dist/mailroom/attention.js +167 -0
  189. package/dist/mailroom/autonomy.js +209 -0
  190. package/dist/mailroom/blob-store.js +674 -0
  191. package/dist/mailroom/body-cache.js +61 -0
  192. package/dist/mailroom/core.js +720 -0
  193. package/dist/mailroom/entry.js +160 -0
  194. package/dist/mailroom/file-store.js +430 -0
  195. package/dist/mailroom/mbox-import.js +383 -0
  196. package/dist/mailroom/outbound.js +380 -0
  197. package/dist/mailroom/policy.js +263 -0
  198. package/dist/mailroom/reader.js +233 -0
  199. package/dist/mailroom/search-cache.js +256 -0
  200. package/dist/mailroom/search-relevance.js +319 -0
  201. package/dist/mailroom/smtp-ingress.js +176 -0
  202. package/dist/mailroom/source-state.js +176 -0
  203. package/dist/mailroom/thread.js +109 -0
  204. package/dist/mailroom/travel-extract.js +89 -0
  205. package/dist/mind/bundle-manifest.js +7 -1
  206. package/dist/mind/context.js +165 -101
  207. package/dist/mind/diary-integrity.js +60 -0
  208. package/dist/mind/{memory.js → diary.js} +62 -75
  209. package/dist/mind/embedding-provider.js +60 -0
  210. package/dist/mind/file-state.js +179 -0
  211. package/dist/mind/friends/channel.js +39 -0
  212. package/dist/mind/friends/resolver.js +54 -2
  213. package/dist/mind/friends/store-file.js +39 -3
  214. package/dist/mind/friends/types.js +2 -2
  215. package/dist/mind/journal-index.js +161 -0
  216. package/dist/mind/note-search.js +268 -0
  217. package/dist/mind/obligation-steering.js +221 -0
  218. package/dist/mind/pending.js +4 -0
  219. package/dist/mind/prompt-refresh.js +3 -2
  220. package/dist/mind/prompt.js +1039 -135
  221. package/dist/mind/provenance-trust.js +26 -0
  222. package/dist/mind/scrutiny.js +173 -0
  223. package/dist/nerves/cli-logging.js +7 -1
  224. package/dist/nerves/coverage/audit-rules.js +15 -6
  225. package/dist/nerves/coverage/audit.js +28 -2
  226. package/dist/nerves/coverage/cli.js +1 -1
  227. package/dist/nerves/coverage/contract.js +5 -5
  228. package/dist/nerves/coverage/file-completeness.js +129 -5
  229. package/dist/nerves/coverage/run-artifacts.js +1 -1
  230. package/dist/nerves/event-buffer.js +111 -0
  231. package/dist/nerves/index.js +224 -4
  232. package/dist/nerves/observation.js +20 -0
  233. package/dist/nerves/redact.js +79 -0
  234. package/dist/nerves/review/cli-main.js +5 -0
  235. package/dist/nerves/review/cli.js +156 -0
  236. package/dist/nerves/review/core.js +152 -0
  237. package/dist/nerves/runtime.js +5 -1
  238. package/dist/repertoire/ado-client.js +15 -56
  239. package/dist/repertoire/ado-semantic.js +11 -10
  240. package/dist/repertoire/api-client.js +97 -0
  241. package/dist/repertoire/bitwarden-store.js +997 -0
  242. package/dist/repertoire/bundle-templates.js +72 -0
  243. package/dist/repertoire/bw-installer.js +180 -0
  244. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  245. package/dist/repertoire/coding/context-pack.js +330 -0
  246. package/dist/repertoire/coding/feedback.js +197 -30
  247. package/dist/repertoire/coding/manager.js +158 -9
  248. package/dist/repertoire/coding/spawner.js +55 -9
  249. package/dist/repertoire/coding/tools.js +170 -7
  250. package/dist/repertoire/commerce-errors.js +109 -0
  251. package/dist/repertoire/commerce-self-test.js +156 -0
  252. package/dist/repertoire/credential-access.js +178 -0
  253. package/dist/repertoire/duffel-client.js +185 -0
  254. package/dist/repertoire/github-client.js +14 -55
  255. package/dist/repertoire/graph-client.js +11 -52
  256. package/dist/repertoire/guardrails.js +396 -0
  257. package/dist/repertoire/mcp-client.js +295 -0
  258. package/dist/repertoire/mcp-manager.js +362 -0
  259. package/dist/repertoire/mcp-tools.js +63 -0
  260. package/dist/repertoire/shell-sessions.js +133 -0
  261. package/dist/repertoire/skills.js +15 -24
  262. package/dist/repertoire/stripe-client.js +131 -0
  263. package/dist/repertoire/tasks/board.js +31 -5
  264. package/dist/repertoire/tasks/fix.js +182 -0
  265. package/dist/repertoire/tasks/index.js +16 -4
  266. package/dist/repertoire/tasks/lifecycle.js +2 -2
  267. package/dist/repertoire/tasks/parser.js +3 -2
  268. package/dist/repertoire/tasks/scanner.js +194 -37
  269. package/dist/repertoire/tasks/transitions.js +16 -78
  270. package/dist/repertoire/tool-results.js +29 -0
  271. package/dist/repertoire/tools-attachments.js +317 -0
  272. package/dist/repertoire/tools-base.js +47 -1075
  273. package/dist/repertoire/tools-bluebubbles.js +1 -0
  274. package/dist/repertoire/tools-bridge.js +142 -0
  275. package/dist/repertoire/tools-bundle.js +984 -0
  276. package/dist/repertoire/tools-config.js +185 -0
  277. package/dist/repertoire/tools-continuity.js +248 -0
  278. package/dist/repertoire/tools-credential.js +381 -0
  279. package/dist/repertoire/tools-files.js +342 -0
  280. package/dist/repertoire/tools-flight.js +224 -0
  281. package/dist/repertoire/tools-flow.js +119 -0
  282. package/dist/repertoire/tools-github.js +1 -7
  283. package/dist/repertoire/tools-mail.js +1857 -0
  284. package/dist/repertoire/tools-notes.js +421 -0
  285. package/dist/repertoire/tools-session.js +809 -0
  286. package/dist/repertoire/tools-shell.js +120 -0
  287. package/dist/repertoire/tools-stripe.js +180 -0
  288. package/dist/repertoire/tools-surface.js +345 -0
  289. package/dist/repertoire/tools-teams.js +9 -39
  290. package/dist/repertoire/tools-travel.js +125 -0
  291. package/dist/repertoire/tools-trip.js +604 -0
  292. package/dist/repertoire/tools-user-profile.js +144 -0
  293. package/dist/repertoire/tools-vault.js +40 -0
  294. package/dist/repertoire/tools-voice.js +144 -0
  295. package/dist/repertoire/tools.js +115 -103
  296. package/dist/repertoire/travel-api-client.js +360 -0
  297. package/dist/repertoire/user-profile.js +131 -0
  298. package/dist/repertoire/vault-setup.js +246 -0
  299. package/dist/repertoire/vault-unlock.js +594 -0
  300. package/dist/scripts/claude-code-hook.js +41 -0
  301. package/dist/scripts/claude-code-stop-hook.js +47 -0
  302. package/dist/senses/attention-queue.js +116 -0
  303. package/dist/senses/bluebubbles/active-turns.js +216 -0
  304. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  305. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  306. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  307. package/dist/senses/bluebubbles/entry.js +77 -0
  308. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  309. package/dist/senses/bluebubbles/index.js +2420 -0
  310. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  311. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  312. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  313. package/dist/senses/bluebubbles/processed-log.js +133 -0
  314. package/dist/senses/bluebubbles/replay.js +137 -0
  315. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  316. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  317. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +100 -0
  337. package/dist/senses/cli.js +516 -204
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +654 -181
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +392 -0
  347. package/dist/senses/surface-tool.js +70 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/senses/voice/audio-playback.js +237 -0
  352. package/dist/senses/voice/audio-routing.js +119 -0
  353. package/dist/senses/voice/elevenlabs.js +202 -0
  354. package/dist/senses/voice/golden-path.js +116 -0
  355. package/dist/senses/voice/index.js +28 -0
  356. package/dist/senses/voice/meeting.js +113 -0
  357. package/dist/senses/voice/outbound.js +190 -0
  358. package/dist/senses/voice/phone.js +33 -0
  359. package/dist/senses/voice/playback.js +139 -0
  360. package/dist/senses/voice/transcript.js +70 -0
  361. package/dist/senses/voice/turn.js +191 -0
  362. package/dist/senses/voice/twilio-phone-runtime.js +755 -0
  363. package/dist/senses/voice/twilio-phone.js +4484 -0
  364. package/dist/senses/voice/types.js +2 -0
  365. package/dist/senses/voice/whisper.js +161 -0
  366. package/dist/senses/voice-entry.js +81 -0
  367. package/dist/senses/voice-twilio-entry.js +87 -0
  368. package/dist/trips/core.js +138 -0
  369. package/dist/trips/store.js +265 -0
  370. package/package.json +40 -7
  371. package/skills/agent-commerce.md +106 -0
  372. package/skills/browser-navigation.md +117 -0
  373. package/skills/commerce-setup-guide.md +116 -0
  374. package/skills/commerce-setup.md +84 -0
  375. package/skills/configure-dev-tools.md +99 -0
  376. package/skills/travel-planning.md +138 -0
  377. package/dist/heart/daemon/auth-flow.js +0 -351
  378. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  379. package/dist/heart/daemon/subagent-installer.js +0 -166
  380. package/dist/heart/session-recall.js +0 -116
  381. package/dist/mind/associative-recall.js +0 -209
  382. package/dist/senses/bluebubbles-entry.js +0 -13
  383. package/dist/senses/bluebubbles.js +0 -1177
  384. package/dist/senses/debug-activity.js +0 -148
  385. package/subagents/README.md +0 -86
  386. package/subagents/work-doer.md +0 -237
  387. package/subagents/work-merger.md +0 -618
  388. package/subagents/work-planner.md +0 -390
  389. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  390. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  391. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  392. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  393. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  394. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  395. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  396. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  397. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  398. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  399. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  400. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  401. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  402. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  403. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  404. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,161 @@
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.parseWhisperCppTranscriptJson = parseWhisperCppTranscriptJson;
37
+ exports.createNodeWhisperCppProcessRunner = createNodeWhisperCppProcessRunner;
38
+ exports.createWhisperCppTranscriber = createWhisperCppTranscriber;
39
+ const fs = __importStar(require("fs/promises"));
40
+ const os = __importStar(require("os"));
41
+ const path = __importStar(require("path"));
42
+ const child_process_1 = require("child_process");
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ const transcript_1 = require("./transcript");
45
+ function parseWhisperCppTranscriptJson(raw) {
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(raw);
49
+ }
50
+ catch (error) {
51
+ throw new Error(`invalid whisper.cpp JSON: ${String(error)}`);
52
+ }
53
+ const text = typeof parsed.text === "string"
54
+ ? parsed.text.trim()
55
+ : Array.isArray(parsed.transcription)
56
+ ? parsed.transcription
57
+ .map((entry) => typeof entry.text === "string" ? entry.text.trim() : "")
58
+ .filter(Boolean)
59
+ .join(" ")
60
+ .trim()
61
+ : "";
62
+ if (!text) {
63
+ throw new Error("empty whisper.cpp transcript");
64
+ }
65
+ return text;
66
+ }
67
+ async function defaultMakeTempDir() {
68
+ return fs.mkdtemp(path.join(os.tmpdir(), "ouro-voice-whisper-"));
69
+ }
70
+ async function defaultRemoveDir(dir) {
71
+ await fs.rm(dir, { recursive: true, force: true });
72
+ }
73
+ function createNodeWhisperCppProcessRunner() {
74
+ return (command, args, options) => new Promise((resolve, reject) => {
75
+ const child = (0, child_process_1.spawn)(command, args, { stdio: ["ignore", "pipe", "pipe"] });
76
+ const stdout = [];
77
+ const stderr = [];
78
+ const timer = setTimeout(() => {
79
+ child.kill("SIGTERM");
80
+ reject(new Error(`command timed out after ${options.timeoutMs}ms`));
81
+ }, options.timeoutMs);
82
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
83
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
84
+ child.on("error", (error) => {
85
+ clearTimeout(timer);
86
+ reject(error);
87
+ });
88
+ child.on("close", (exitCode) => {
89
+ clearTimeout(timer);
90
+ resolve({
91
+ stdout: Buffer.concat(stdout).toString("utf8"),
92
+ stderr: Buffer.concat(stderr).toString("utf8"),
93
+ exitCode: exitCode ?? 0,
94
+ });
95
+ });
96
+ });
97
+ }
98
+ function createWhisperCppTranscriber(options) {
99
+ const timeoutMs = options.timeoutMs ?? 120_000;
100
+ const readFile = options.readFile ?? fs.readFile;
101
+ const makeTempDir = options.makeTempDir ?? defaultMakeTempDir;
102
+ const removeDir = options.removeDir ?? defaultRemoveDir;
103
+ const processRunner = options.processRunner ?? createNodeWhisperCppProcessRunner();
104
+ return {
105
+ async transcribe(request) {
106
+ const workDir = await makeTempDir();
107
+ const outputBase = path.join(workDir, "transcript");
108
+ const args = [
109
+ "-m",
110
+ options.modelPath,
111
+ "-f",
112
+ request.audioPath,
113
+ "-oj",
114
+ "-of",
115
+ outputBase,
116
+ ...(request.language ? ["-l", request.language] : []),
117
+ ];
118
+ (0, runtime_1.emitNervesEvent)({
119
+ component: "senses",
120
+ event: "senses.voice_stt_start",
121
+ message: "starting Whisper.cpp transcription",
122
+ meta: { utteranceId: request.utteranceId, audioPath: request.audioPath },
123
+ });
124
+ try {
125
+ const result = await processRunner(options.whisperCliPath, args, { timeoutMs });
126
+ if (typeof result.exitCode === "number" && result.exitCode !== 0) {
127
+ throw new Error(`exit ${result.exitCode}${result.stderr ? `: ${result.stderr}` : ""}`);
128
+ }
129
+ const raw = await readFile(`${outputBase}.json`, "utf8");
130
+ const text = parseWhisperCppTranscriptJson(raw);
131
+ const transcript = (0, transcript_1.buildVoiceTranscript)({
132
+ utteranceId: request.utteranceId,
133
+ text,
134
+ audioPath: request.audioPath,
135
+ language: request.language,
136
+ source: "whisper.cpp",
137
+ });
138
+ (0, runtime_1.emitNervesEvent)({
139
+ component: "senses",
140
+ event: "senses.voice_stt_end",
141
+ message: "finished Whisper.cpp transcription",
142
+ meta: { utteranceId: request.utteranceId, length: transcript.text.length },
143
+ });
144
+ return transcript;
145
+ }
146
+ catch (error) {
147
+ (0, runtime_1.emitNervesEvent)({
148
+ level: "error",
149
+ component: "senses",
150
+ event: "senses.voice_stt_error",
151
+ message: "Whisper.cpp transcription failed",
152
+ meta: { utteranceId: request.utteranceId, error: error instanceof Error ? error.message : String(error) },
153
+ });
154
+ throw new Error(`whisper.cpp transcription failed: ${error instanceof Error ? error.message : String(error)}`);
155
+ }
156
+ finally {
157
+ await removeDir(workDir);
158
+ }
159
+ },
160
+ };
161
+ }
@@ -0,0 +1,81 @@
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
+ const agentArgIndex = process.argv.indexOf("--agent");
37
+ const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
38
+ if (!agentName) {
39
+ // eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
40
+ console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/voice-entry.js --agent ouroboros");
41
+ process.exit(1);
42
+ }
43
+ const runtime_logging_1 = require("../heart/daemon/runtime-logging");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ (0, runtime_logging_1.configureDaemonRuntimeLogger)("voice");
46
+ (0, runtime_1.emitNervesEvent)({
47
+ component: "senses",
48
+ event: "senses.entry_boot",
49
+ message: "booting Voice entrypoint",
50
+ meta: { entry: "voice", agentName },
51
+ });
52
+ Promise.resolve().then(() => __importStar(require("./voice/twilio-phone-runtime"))).then(async ({ agentScopedTwilioPhoneBasePath, startConfiguredTwilioPhoneTransport, }) => {
53
+ const twilioPhone = await startConfiguredTwilioPhoneTransport({
54
+ agentName,
55
+ defaultBasePath: agentScopedTwilioPhoneBasePath(agentName),
56
+ });
57
+ (0, runtime_1.emitNervesEvent)({
58
+ component: "senses",
59
+ event: "senses.voice_entry_ready",
60
+ message: "Voice entrypoint is ready for managed voice turns",
61
+ meta: {
62
+ entry: "voice",
63
+ agentName,
64
+ twilioPhone: twilioPhone.status,
65
+ webhookUrl: twilioPhone.status === "started" ? twilioPhone.settings.webhookUrl : undefined,
66
+ },
67
+ });
68
+ setInterval(() => undefined, 60_000);
69
+ })
70
+ .catch((error) => {
71
+ (0, runtime_1.emitNervesEvent)({
72
+ level: "error",
73
+ component: "senses",
74
+ event: "senses.entry_error",
75
+ message: "Voice entrypoint failed",
76
+ meta: { entry: "voice", agentName, error: error instanceof Error ? error.message : String(error) },
77
+ });
78
+ // eslint-disable-next-line no-console -- fatal startup guard for sense process
79
+ console.error(error instanceof Error ? error.message : String(error));
80
+ process.exit(1);
81
+ });
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function readRequiredAgentName() {
4
+ const agentArgIndex = process.argv.indexOf("--agent");
5
+ const value = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
6
+ if (value)
7
+ return value;
8
+ process.stderr.write("Missing required --agent <name> argument.\nUsage: node dist/senses/voice-twilio-entry.js --agent ouroboros --public-url https://<tunnel>\n");
9
+ process.exit(1);
10
+ }
11
+ const agentName = readRequiredAgentName();
12
+ const runtime_logging_1 = require("../heart/daemon/runtime-logging");
13
+ const runtime_1 = require("../nerves/runtime");
14
+ const voice_1 = require("./voice");
15
+ function argValue(name) {
16
+ const index = process.argv.indexOf(name);
17
+ if (index < 0)
18
+ return undefined;
19
+ const value = process.argv[index + 1];
20
+ return value && !value.startsWith("--") ? value : undefined;
21
+ }
22
+ function numberArg(name) {
23
+ const raw = argValue(name);
24
+ if (!raw)
25
+ return undefined;
26
+ const parsed = Number(raw);
27
+ if (!Number.isFinite(parsed))
28
+ throw new Error(`${name} must be a number`);
29
+ return parsed;
30
+ }
31
+ function standaloneOverrides() {
32
+ return {
33
+ publicBaseUrl: argValue("--public-url"),
34
+ basePath: argValue("--base-path"),
35
+ port: numberArg("--port"),
36
+ host: argValue("--host"),
37
+ outputDir: argValue("--output-dir"),
38
+ defaultFriendId: argValue("--friend"),
39
+ elevenLabsVoiceId: argValue("--elevenlabs-voice-id"),
40
+ whisperCliPath: argValue("--whisper-cli-path"),
41
+ whisperModelPath: argValue("--whisper-model-path"),
42
+ recordTimeoutSeconds: numberArg("--record-timeout"),
43
+ recordMaxLengthSeconds: numberArg("--record-max-length"),
44
+ greetingPrebufferMs: numberArg("--greeting-prebuffer-ms"),
45
+ transportMode: argValue("--transport-mode"),
46
+ playbackMode: argValue("--playback-mode"),
47
+ };
48
+ }
49
+ function writeReadyInstructions(localUrl, publicBaseUrl, webhookUrl) {
50
+ process.stdout.write([
51
+ "Twilio phone voice bridge ready.",
52
+ `local: ${localUrl}`,
53
+ `public: ${publicBaseUrl}`,
54
+ `Twilio Voice webhook: POST ${webhookUrl}`,
55
+ "",
56
+ ].join("\n"));
57
+ }
58
+ (0, runtime_logging_1.configureDaemonRuntimeLogger)("voice");
59
+ (0, runtime_1.emitNervesEvent)({
60
+ component: "senses",
61
+ event: "senses.entry_boot",
62
+ message: "booting Twilio Voice entrypoint",
63
+ meta: { entry: "voice-twilio", agentName },
64
+ });
65
+ async function main() {
66
+ const transport = await (0, voice_1.startConfiguredTwilioPhoneTransport)({
67
+ agentName,
68
+ overrides: standaloneOverrides(),
69
+ defaultBasePath: voice_1.TWILIO_PHONE_WEBHOOK_BASE_PATH,
70
+ requirePublicUrl: true,
71
+ });
72
+ if (transport.status !== "started") {
73
+ throw new Error(`Twilio phone voice transport did not start: ${transport.reason}`);
74
+ }
75
+ writeReadyInstructions(transport.bridge.localUrl, transport.settings.publicBaseUrl, transport.settings.webhookUrl);
76
+ }
77
+ main().catch((error) => {
78
+ (0, runtime_1.emitNervesEvent)({
79
+ level: "error",
80
+ component: "senses",
81
+ event: "senses.entry_error",
82
+ message: "Twilio Voice entrypoint failed",
83
+ meta: { entry: "voice-twilio", agentName, error: error instanceof Error ? error.message : String(error) },
84
+ });
85
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
86
+ process.exit(1);
87
+ });
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ // Harness-side trip ledger primitive.
3
+ //
4
+ // Mirrors the substrate's @ouro/work-protocol/src/trip.ts contract (vendored
5
+ // the same way mailroom/core.ts vendors mail). Slugger's framing: today,
6
+ // doc-edits-from-mail keep falling back on freeform parsing because there is
7
+ // no structured object between "mail body" and "travel doc". TripRecord +
8
+ // TripLeg are that object — every leg fact carries non-optional provenance
9
+ // (TripEvidence with discoveryMethod) so the ledger can be audited cleanly
10
+ // and reasoned about under conflict.
11
+ //
12
+ // Per-agent ledger keypair design: in v1 each agent has ONE ledger keypair.
13
+ // All TripRecord blobs are encrypted with that key. Cross-trip sharing
14
+ // (handing one trip's facts to another party without their owning the whole
15
+ // ledger) is a follow-on; it would shard to per-trip keys, which the
16
+ // substrate's TripLedgerRegistry can already represent.
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.generateTripKeyPair = generateTripKeyPair;
52
+ exports.encryptTripRecord = encryptTripRecord;
53
+ exports.decryptTripRecord = decryptTripRecord;
54
+ exports.newTripId = newTripId;
55
+ exports.newLegId = newLegId;
56
+ exports.newTripLedgerRecord = newTripLedgerRecord;
57
+ const crypto = __importStar(require("node:crypto"));
58
+ // ── Helpers: keys + crypto ─────────────────────────────────────────
59
+ function safeLabel(label) {
60
+ return label.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
61
+ }
62
+ function generateTripKeyPair(label) {
63
+ const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
64
+ modulusLength: 2048,
65
+ publicKeyEncoding: { type: "spki", format: "pem" },
66
+ privateKeyEncoding: { type: "pkcs8", format: "pem" },
67
+ });
68
+ const slug = safeLabel(label) || "ledger";
69
+ const fingerprint = crypto.createHash("sha256").update(publicKey).digest("hex").slice(0, 16);
70
+ return {
71
+ keyId: `trip_${slug}_${fingerprint}`,
72
+ publicKeyPem: publicKey,
73
+ privateKeyPem: privateKey,
74
+ };
75
+ }
76
+ function encryptTripRecord(trip, publicKeyPem, keyId) {
77
+ const contentKey = crypto.randomBytes(32);
78
+ const iv = crypto.randomBytes(12);
79
+ const cipher = crypto.createCipheriv("aes-256-gcm", contentKey, iv);
80
+ const ciphertext = Buffer.concat([cipher.update(Buffer.from(JSON.stringify(trip), "utf-8")), cipher.final()]);
81
+ const authTag = cipher.getAuthTag();
82
+ const wrappedKey = crypto.publicEncrypt({ key: publicKeyPem, oaepHash: "sha256" }, contentKey);
83
+ return {
84
+ algorithm: "RSA-OAEP-SHA256+A256GCM",
85
+ keyId,
86
+ wrappedKey: wrappedKey.toString("base64"),
87
+ iv: iv.toString("base64"),
88
+ authTag: authTag.toString("base64"),
89
+ ciphertext: ciphertext.toString("base64"),
90
+ };
91
+ }
92
+ function decryptTripRecord(payload, privateKeyPem) {
93
+ const contentKey = crypto.privateDecrypt({
94
+ key: privateKeyPem,
95
+ oaepHash: "sha256",
96
+ }, Buffer.from(payload.wrappedKey, "base64"));
97
+ const decipher = crypto.createDecipheriv("aes-256-gcm", contentKey, Buffer.from(payload.iv, "base64"));
98
+ decipher.setAuthTag(Buffer.from(payload.authTag, "base64"));
99
+ const plaintext = Buffer.concat([
100
+ decipher.update(Buffer.from(payload.ciphertext, "base64")),
101
+ decipher.final(),
102
+ ]);
103
+ return JSON.parse(plaintext.toString("utf-8"));
104
+ }
105
+ // ── Helpers: deterministic ids ─────────────────────────────────────
106
+ function newTripId(agentId, name, createdAt) {
107
+ const fingerprint = crypto.createHash("sha256")
108
+ .update(`${agentId}\n${name}\n${createdAt}`)
109
+ .digest("hex")
110
+ .slice(0, 16);
111
+ const slug = safeLabel(name) || "trip";
112
+ return `trip_${slug}_${fingerprint}`;
113
+ }
114
+ function newLegId(input) {
115
+ const distinguish = input.vendor || input.confirmationCode || crypto.randomUUID();
116
+ const fingerprint = crypto.createHash("sha256")
117
+ .update(`${input.tripId}\n${input.kind}\n${distinguish}\n${input.createdAt}`)
118
+ .digest("hex")
119
+ .slice(0, 16);
120
+ return `leg_${input.kind}_${fingerprint}`;
121
+ }
122
+ // ── Ledger record helpers ──────────────────────────────────────────
123
+ function newTripLedgerRecord(input) {
124
+ const now = (input.now ?? (() => new Date().toISOString()))();
125
+ const keypair = generateTripKeyPair(input.label ?? input.agentId);
126
+ const ledgerId = `ledger_${safeLabel(input.agentId) || "agent"}_${crypto.createHash("sha256").update(`${input.agentId}\n${now}\n${keypair.keyId}`).digest("hex").slice(0, 16)}`;
127
+ return {
128
+ ledger: {
129
+ schemaVersion: 1,
130
+ agentId: input.agentId,
131
+ ledgerId,
132
+ keyId: keypair.keyId,
133
+ publicKeyPem: keypair.publicKeyPem,
134
+ createdAt: now,
135
+ },
136
+ keypair,
137
+ };
138
+ }