@ouro.bot/cli 0.1.0-alpha.56 → 0.1.0-alpha.560

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 (392) 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 +3596 -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 +58 -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 +913 -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 +7457 -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 -1698
  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 +796 -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 +826 -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 +67 -16
  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 +389 -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 +683 -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 +139 -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 +389 -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 +1011 -123
  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 +963 -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 +750 -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 +243 -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.js +108 -100
  295. package/dist/repertoire/travel-api-client.js +360 -0
  296. package/dist/repertoire/user-profile.js +131 -0
  297. package/dist/repertoire/vault-setup.js +246 -0
  298. package/dist/repertoire/vault-unlock.js +594 -0
  299. package/dist/scripts/claude-code-hook.js +41 -0
  300. package/dist/scripts/claude-code-stop-hook.js +47 -0
  301. package/dist/senses/attention-queue.js +116 -0
  302. package/dist/senses/bluebubbles/active-turns.js +216 -0
  303. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  304. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  305. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  306. package/dist/senses/bluebubbles/entry.js +77 -0
  307. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  308. package/dist/senses/bluebubbles/index.js +2305 -0
  309. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  310. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  311. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  312. package/dist/senses/bluebubbles/processed-log.js +133 -0
  313. package/dist/senses/bluebubbles/replay.js +137 -0
  314. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  315. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  316. package/dist/senses/cli/bracketed-paste.js +82 -0
  317. package/dist/senses/cli/image-paste.js +287 -0
  318. package/dist/senses/cli/image-ref-navigation.js +75 -0
  319. package/dist/senses/cli/ink-app.js +156 -0
  320. package/dist/senses/cli/inline-diff.js +64 -0
  321. package/dist/senses/cli/input-keys.js +174 -0
  322. package/dist/senses/cli/kill-ring.js +86 -0
  323. package/dist/senses/cli/message-list.js +51 -0
  324. package/dist/senses/cli/ouro-tui.js +607 -0
  325. package/dist/senses/cli/spinner-imperative.js +135 -0
  326. package/dist/senses/cli/spinner.js +101 -0
  327. package/dist/senses/cli/status-line.js +60 -0
  328. package/dist/senses/cli/streaming-markdown.js +526 -0
  329. package/dist/senses/cli/tool-display.js +85 -0
  330. package/dist/senses/cli/tool-render.js +85 -0
  331. package/dist/senses/cli/tui-store.js +240 -0
  332. package/dist/senses/cli/virtual-list.js +35 -0
  333. package/dist/senses/cli-entry.js +60 -8
  334. package/dist/senses/cli-layout.js +187 -0
  335. package/dist/senses/cli.js +520 -209
  336. package/dist/senses/commands.js +66 -3
  337. package/dist/senses/habit-turn-message.js +108 -0
  338. package/dist/senses/inner-dialog-worker.js +175 -21
  339. package/dist/senses/inner-dialog.js +330 -27
  340. package/dist/senses/mail-entry.js +66 -0
  341. package/dist/senses/mail.js +379 -0
  342. package/dist/senses/pipeline.js +549 -181
  343. package/dist/senses/proactive-content-guard.js +51 -0
  344. package/dist/senses/shared-turn.js +248 -0
  345. package/dist/senses/surface-tool.js +68 -0
  346. package/dist/senses/teams-entry.js +60 -8
  347. package/dist/senses/teams.js +387 -98
  348. package/dist/senses/trust-gate.js +100 -5
  349. package/dist/senses/voice/elevenlabs.js +125 -0
  350. package/dist/senses/voice/index.js +22 -0
  351. package/dist/senses/voice/transcript.js +70 -0
  352. package/dist/senses/voice/turn.js +85 -0
  353. package/dist/senses/voice/types.js +2 -0
  354. package/dist/senses/voice/whisper.js +133 -0
  355. package/dist/senses/voice-entry.js +80 -0
  356. package/dist/trips/core.js +138 -0
  357. package/dist/trips/store.js +146 -0
  358. package/package.json +38 -7
  359. package/skills/agent-commerce.md +106 -0
  360. package/skills/browser-navigation.md +117 -0
  361. package/skills/commerce-setup-guide.md +116 -0
  362. package/skills/commerce-setup.md +84 -0
  363. package/skills/configure-dev-tools.md +101 -0
  364. package/skills/travel-planning.md +138 -0
  365. package/dist/heart/daemon/auth-flow.js +0 -351
  366. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  367. package/dist/heart/daemon/subagent-installer.js +0 -166
  368. package/dist/heart/session-recall.js +0 -116
  369. package/dist/mind/associative-recall.js +0 -209
  370. package/dist/senses/bluebubbles-entry.js +0 -13
  371. package/dist/senses/bluebubbles.js +0 -1177
  372. package/dist/senses/debug-activity.js +0 -148
  373. package/subagents/README.md +0 -86
  374. package/subagents/work-doer.md +0 -237
  375. package/subagents/work-merger.md +0 -618
  376. package/subagents/work-planner.md +0 -390
  377. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  378. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  379. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  380. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  381. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  382. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  383. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  384. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  385. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  386. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  387. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  388. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  389. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  390. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  391. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  392. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -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
+ }
@@ -0,0 +1,146 @@
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.TripNotFoundError = void 0;
37
+ exports.ensureAgentTripLedger = ensureAgentTripLedger;
38
+ exports.readAgentTripKeypair = readAgentTripKeypair;
39
+ exports.upsertTripRecord = upsertTripRecord;
40
+ exports.readTripRecord = readTripRecord;
41
+ exports.listTripIds = listTripIds;
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const identity_1 = require("../heart/identity");
45
+ const runtime_1 = require("../nerves/runtime");
46
+ const core_1 = require("./core");
47
+ function tripsRoot(agentName) {
48
+ return path.join((0, identity_1.getAgentRoot)(agentName), "state", "trips");
49
+ }
50
+ function ledgerPath(agentName) {
51
+ return path.join(tripsRoot(agentName), "ledger.json");
52
+ }
53
+ function recordsDir(agentName) {
54
+ return path.join(tripsRoot(agentName), "records");
55
+ }
56
+ function recordPath(agentName, tripId) {
57
+ return path.join(recordsDir(agentName), `${tripId}.json`);
58
+ }
59
+ function readJsonFile(filePath) {
60
+ if (!fs.existsSync(filePath))
61
+ return null;
62
+ return JSON.parse(fs.readFileSync(filePath, "utf-8"));
63
+ }
64
+ function writeJsonAtomic(filePath, value) {
65
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
66
+ const tmp = `${filePath}.tmp`;
67
+ fs.writeFileSync(tmp, JSON.stringify(value, null, 2), "utf-8");
68
+ fs.renameSync(tmp, filePath);
69
+ }
70
+ class TripNotFoundError extends Error {
71
+ statusCode = 404;
72
+ constructor(input) {
73
+ super(`trip not found: agent=${input.agentName} trip=${input.tripId}`);
74
+ }
75
+ }
76
+ exports.TripNotFoundError = TripNotFoundError;
77
+ /**
78
+ * Idempotent — if the agent already has a ledger on disk, return it; otherwise
79
+ * generate a fresh keypair and persist both halves.
80
+ */
81
+ function ensureAgentTripLedger(input) {
82
+ const existing = readJsonFile(ledgerPath(input.agentName));
83
+ if (existing) {
84
+ return { ledger: existing.ledger, added: false };
85
+ }
86
+ const created = (0, core_1.newTripLedgerRecord)({
87
+ agentId: input.agentName,
88
+ ...(input.label ? { label: input.label } : {}),
89
+ ...(input.now ? { now: input.now } : {}),
90
+ });
91
+ const stored = {
92
+ schemaVersion: 1,
93
+ ledger: created.ledger,
94
+ privateKeyPem: created.keypair.privateKeyPem,
95
+ };
96
+ writeJsonAtomic(ledgerPath(input.agentName), stored);
97
+ (0, runtime_1.emitNervesEvent)({
98
+ component: "trips",
99
+ event: "trips.ledger_created",
100
+ message: "agent trip ledger keypair created",
101
+ meta: { agentId: input.agentName, ledgerId: created.ledger.ledgerId, keyId: created.ledger.keyId },
102
+ });
103
+ return { ledger: created.ledger, added: true };
104
+ }
105
+ function readLedgerOrThrow(agentName) {
106
+ const stored = readJsonFile(ledgerPath(agentName));
107
+ if (!stored) {
108
+ throw new Error(`no trip ledger for agent ${agentName} — call ensureAgentTripLedger first`);
109
+ }
110
+ return stored;
111
+ }
112
+ function readAgentTripKeypair(agentName) {
113
+ const stored = readLedgerOrThrow(agentName);
114
+ return {
115
+ keyId: stored.ledger.keyId,
116
+ publicKeyPem: stored.ledger.publicKeyPem,
117
+ privateKeyPem: stored.privateKeyPem,
118
+ };
119
+ }
120
+ function upsertTripRecord(agentName, trip) {
121
+ const stored = readLedgerOrThrow(agentName);
122
+ const payload = (0, core_1.encryptTripRecord)(trip, stored.ledger.publicKeyPem, stored.ledger.keyId);
123
+ writeJsonAtomic(recordPath(agentName, trip.tripId), payload);
124
+ (0, runtime_1.emitNervesEvent)({
125
+ component: "trips",
126
+ event: "trips.record_upserted",
127
+ message: "trip record upserted",
128
+ meta: { agentId: agentName, tripId: trip.tripId, legCount: trip.legs.length, status: trip.status },
129
+ });
130
+ }
131
+ function readTripRecord(agentName, tripId) {
132
+ const payload = readJsonFile(recordPath(agentName, tripId));
133
+ if (!payload)
134
+ throw new TripNotFoundError({ agentName, tripId });
135
+ const stored = readLedgerOrThrow(agentName);
136
+ return (0, core_1.decryptTripRecord)(payload, stored.privateKeyPem);
137
+ }
138
+ function listTripIds(agentName) {
139
+ const dir = recordsDir(agentName);
140
+ if (!fs.existsSync(dir))
141
+ return [];
142
+ return fs.readdirSync(dir)
143
+ .filter((entry) => entry.endsWith(".json"))
144
+ .map((entry) => entry.slice(0, -".json".length))
145
+ .sort();
146
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.56",
3
+ "version": "0.1.0-alpha.560",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",
@@ -9,8 +9,9 @@
9
9
  },
10
10
  "files": [
11
11
  "dist/",
12
- "AdoptionSpecialist.ouro/",
13
- "subagents/",
12
+ "SerpentGuide.ouro/",
13
+ "RepairGuide.ouro/",
14
+ "skills/",
14
15
  "assets/",
15
16
  "changelog.json"
16
17
  ],
@@ -19,36 +20,66 @@
19
20
  "./runOuroCli": "./dist/heart/daemon/daemon-cli.js"
20
21
  },
21
22
  "scripts": {
22
- "dev": "tsc && node dist/senses/cli-entry.js --agent ouroboros",
23
+ "dev": "tsc && node dist/heart/daemon/ouro-bot-entry.js dev",
24
+ "cli": "tsc && node dist/senses/cli-entry.js",
23
25
  "daemon": "tsc && node dist/heart/daemon/daemon-entry.js",
24
26
  "ouro": "tsc && node dist/heart/daemon/ouro-entry.js",
25
27
  "teams": "tsc && node dist/senses/teams-entry.js --agent ouroboros",
26
- "bluebubbles": "tsc && node dist/senses/bluebubbles-entry.js --agent ouroboros",
28
+ "bluebubbles": "tsc && node dist/senses/bluebubbles/entry.js --agent ouroboros",
27
29
  "test": "vitest run",
30
+ "test:integration": "npm run build && vitest run --config vitest.integration.config.ts",
31
+ "test:e2e:package": "npm run build && node scripts/package-e2e.cjs",
32
+ "test:e2e:real-smoke": "npm run build && node scripts/nightly-real-smoke.cjs",
33
+ "typecheck:mailbox-ui": "tsc --noEmit -p packages/mailbox-ui/tsconfig.json",
34
+ "test:mailbox-ui": "npm test --prefix packages/mailbox-ui",
28
35
  "test:coverage:vitest": "vitest run --coverage",
29
36
  "test:coverage": "node scripts/run-coverage-gate.cjs",
30
- "build": "tsc",
37
+ "build": "node scripts/clean-dist.cjs && tsc && (cd packages/mailbox-ui && npm install --ignore-scripts 2>/dev/null && npm run build && cd ../.. && node scripts/copy-mailbox-ui.cjs) || echo 'mailbox-ui build skipped'",
31
38
  "lint": "eslint src/",
39
+ "release:preflight": "node scripts/release-preflight.cjs",
40
+ "release:smoke": "node scripts/release-smoke.cjs",
32
41
  "audit:nerves": "npm run build && node dist/nerves/coverage/cli-main.js"
33
42
  },
34
43
  "dependencies": {
35
44
  "@anthropic-ai/sdk": "^0.78.0",
45
+ "@azure/identity": "^4.13.0",
46
+ "@azure/storage-blob": "^12.31.0",
47
+ "@microsoft/teams.api": "2.0.5",
36
48
  "@microsoft/teams.apps": "^2.0.5",
49
+ "@microsoft/teams.cards": "2.0.5",
50
+ "@microsoft/teams.common": "2.0.5",
37
51
  "@microsoft/teams.dev": "^2.0.5",
52
+ "@microsoft/teams.graph": "2.0.5",
53
+ "@types/react": "^17.0.91",
38
54
  "fast-glob": "^3.3.3",
55
+ "ink": "^3.2.0",
56
+ "mailparser": "^3.9.8",
39
57
  "openai": "^6.27.0",
40
- "semver": "^7.7.4"
58
+ "react": "^17.0.2",
59
+ "semver": "^7.7.4",
60
+ "smtp-server": "^3.18.4",
61
+ "stripe": "^22.0.0"
41
62
  },
42
63
  "repository": {
43
64
  "type": "git",
44
65
  "url": "https://github.com/ouroborosbot/ouroboros"
45
66
  },
46
67
  "devDependencies": {
68
+ "@testing-library/react": "^16.3.2",
69
+ "@types/mailparser": "^3.4.6",
47
70
  "@types/semver": "^7.7.1",
71
+ "@types/smtp-server": "^3.5.13",
48
72
  "@vitest/coverage-v8": "^4.0.18",
49
73
  "eslint": "^10.0.2",
74
+ "jsdom": "^29.0.2",
50
75
  "typescript": "^5.7.0",
51
76
  "typescript-eslint": "^8.56.1",
52
77
  "vitest": "^4.0.18"
78
+ },
79
+ "overrides": {
80
+ "@testing-library/react": {
81
+ "react": "$react",
82
+ "@types/react": "$@types/react"
83
+ }
53
84
  }
54
85
  }
@@ -0,0 +1,106 @@
1
+ # Agent Commerce Skill
2
+
3
+ How to book, purchase, and pay for things on behalf of humans.
4
+
5
+ ## Three Patterns
6
+
7
+ ### Pattern A: API (Structured, Preferred)
8
+
9
+ For services with direct API access: Duffel flights, LiteAPI hotels.
10
+
11
+ 1. Search using the API tool (`flight_search`, LiteAPI MCP)
12
+ 2. Present options to the human with prices and details
13
+ 3. Human approves a specific option and price
14
+ 4. Book using the API tool with passenger data from `user_profile_get`
15
+ 5. Create a single-use virtual card via `stripe_create_card`
16
+ 6. Complete payment through the API
17
+ 7. Deactivate the card via `stripe_deactivate_card`
18
+ 8. Confirm booking to the human
19
+
20
+ **Key tools**: `flight_search`, `flight_book`, `flight_cancel`, `user_profile_get`, `user_profile_store`, `stripe_create_card`, `stripe_deactivate_card`, `stripe_list_cards`
21
+
22
+ ### Pattern B: Browser (Best-Effort)
23
+
24
+ For sites without API access, use browser automation via Playwright MCP.
25
+
26
+ 1. Navigate to the booking site
27
+ 2. Search for the requested service
28
+ 3. Fill forms using data from `user_profile_get`
29
+ 4. Use a virtual card from `stripe_create_card` for payment
30
+ 5. If blocked by anti-bot measures, fall back to Pattern C
31
+ 6. Complete and confirm the booking
32
+
33
+ **Limitations**: Browser automation is fragile. Sites may block, layouts change, CAPTCHAs appear. Always have Pattern C as fallback.
34
+
35
+ ### Pattern C: Link-Only (Primary for Hostile Sites)
36
+
37
+ For sites that block automation or require complex human interaction.
38
+
39
+ 1. Research the best options using browser tools or API tools
40
+ 2. Prepare a curated link with pre-filled parameters where possible
41
+ 3. Send the link to the human with a summary of what to book
42
+ 4. Human completes the booking in their own browser
43
+
44
+ **When to use**: Always use Pattern C as the primary approach for sites known to block automation (most airline direct sites, hotel chains, rental car sites). Pattern B is best-effort, not reliable.
45
+
46
+ ## Payment autonomy Levels
47
+
48
+ - **Level 0**: No autonomous payments. Agent researches, human pays manually.
49
+ - **Level 1**: Agent creates virtual cards, human approves each transaction explicitly.
50
+ - **Level 2**: Agent can book pre-approved items (within budget, approved categories) without per-transaction approval.
51
+ - **Level 3**: Full delegation with spending limits. Agent manages a budget and books as needed.
52
+
53
+ Default is Level 1. Level changes require explicit human approval.
54
+
55
+ ## Error Handling
56
+
57
+ ### Price Change Guard
58
+ Before completing a booking, verify the final price matches the approved price within 5%. If the price changed more than 5%, stop and report to the human. Never pay a price the human didn't approve.
59
+
60
+ ### Partial Failure Reporting
61
+ When booking involves multiple services (e.g., flight + hotel), each service may succeed or fail independently — this is a partial failure scenario. Report the status of each service separately. **Never auto-cancel a successful booking because a related booking failed.** Let the human decide.
62
+
63
+ Example: "Flight SFO-JFK booked (confirmation: ABC123). Hotel booking failed: no availability for those dates. Would you like me to search for alternative hotels?"
64
+
65
+ ### Refund Flow
66
+ If a booking fails after card creation:
67
+ 1. Deactivate the virtual card immediately
68
+ 2. Report the failure to the human
69
+ 3. If a charge was made, note it for the human to follow up with the provider
70
+
71
+ ## CAPTCHA Handling
72
+
73
+ When a CAPTCHA appears during browser automation (Pattern B):
74
+ 1. Take a screenshot and send it to the human
75
+ 2. Explain what page you're on and what you were trying to do
76
+ 3. Ask the human to solve the CAPTCHA in their own browser
77
+ 4. Switch to Pattern C (link-only) for this transaction
78
+
79
+ Never attempt to solve CAPTCHAs programmatically.
80
+
81
+ ## Card Number Isolation
82
+
83
+ Card numbers must NEVER appear in:
84
+ - Tool return values shown to the model
85
+ - Nerves events or logs
86
+ - Chat messages to the human
87
+ - Any stored state or written notes
88
+
89
+ The only place card numbers exist is inside the Stripe client's internal payment flow functions, scoped to a single function call. The model only ever sees card IDs and last-4 digits.
90
+
91
+ ## Profile Data Usage
92
+
93
+ Access profile data only when needed for the current transaction:
94
+ - `user_profile_get` to retrieve specific fields (never dump full profile)
95
+ - Passport data only for international bookings
96
+ - Loyalty program numbers only when booking with that program
97
+ - Emergency contact only when the booking service requires it
98
+
99
+ ## Self-Test
100
+
101
+ Before first use, run the commerce self-test to verify all services are configured:
102
+ - Stripe: creates and deactivates a test virtual card
103
+ - Duffel: runs a test flight search
104
+ - LiteAPI: verifies API key in vault
105
+
106
+ Report results to the human with actionable next steps for any failures.
@@ -0,0 +1,117 @@
1
+ # Browser Navigation Skill
2
+
3
+ When to use browser tools and how to navigate effectively.
4
+
5
+ ## When to Use Browser Tools
6
+
7
+ Use browser navigation when:
8
+ - The target site has no API (e.g., Airbnb, VRBO, travel blogs)
9
+ - Content is dynamic or requires JavaScript rendering
10
+ - Login-required pages need session-based access
11
+ - You need to verify visual content (screenshots, layouts)
12
+ - Price comparison requires real-time scraping
13
+
14
+ Do NOT use browser tools when:
15
+ - A dedicated API or MCP server exists (prefer `weather_lookup`, Duffel MCP, etc.)
16
+ - The data is available via a public JSON endpoint
17
+ - The task can be completed with `web_search`
18
+
19
+ ## Stealth Browsing Best Practices
20
+
21
+ The `@playwright/mcp` server is configured with realistic user-agent and viewport settings. To avoid detection on travel sites:
22
+
23
+ - **Add delays between navigations**: Wait 2-5 seconds between page loads. Never hammer requests in rapid succession.
24
+ - **Vary timing**: Use random delays rather than fixed intervals (e.g., 2-5s, not exactly 3s every time).
25
+ - **Avoid predictable patterns**: Don't navigate the same path repeatedly in short succession.
26
+ - **Use realistic scroll behavior**: Scroll gradually through pages rather than jumping to specific elements.
27
+ - **Respect robots.txt**: Check for rate limits and crawling restrictions.
28
+
29
+ ## Navigation Workflow
30
+
31
+ Follow this pattern for every page interaction:
32
+
33
+ 1. **Navigate**: Use `browser_navigate` to load the page
34
+ 2. **Wait**: Allow the page to fully load (use `browser_wait` if needed)
35
+ 3. **Snapshot**: Take a `browser_snapshot` to understand the page structure
36
+ 4. **Extract**: Parse the accessibility tree for relevant data
37
+ 5. **Screenshot** (optional): Use `browser_screenshot` for visual confirmation
38
+
39
+ ## Form Filling Patterns
40
+
41
+ ### Login Flows
42
+ 1. Navigate to the login page
43
+ 2. Take a snapshot to identify form fields
44
+ 3. Use `browser_type` for username/password fields
45
+ 4. Use `browser_click` to submit
46
+ 5. Wait for redirect, then verify login succeeded via snapshot
47
+ 6. NEVER hardcode credentials -- use `credential_get` to retrieve login info
48
+
49
+ ### Sign-up Flows
50
+ 1. Use `credential_generate_password` to mint a strong password for the target domain
51
+ 2. Fill the signup form with that password
52
+ 3. If the site rejects the password policy, generate a new one that matches the site rules
53
+ 4. Once the site accepts the exact password, call `credential_store` immediately
54
+ 5. Do not claim a new credential is saved until `credential_store` succeeds
55
+
56
+ ### Search Forms (Hotels, Flights, Rentals)
57
+ 1. Navigate to the search page
58
+ 2. Snapshot to identify input fields
59
+ 3. Fill location/date fields with `browser_type`
60
+ 4. Select options with `browser_select_option` or `browser_click`
61
+ 5. Submit the search
62
+ 6. Wait for results to load (travel sites often have loading animations)
63
+ 7. Snapshot the results page to extract listings
64
+
65
+ ### Booking Forms
66
+ 1. **ALWAYS confirm with the user before proceeding to payment**
67
+ 2. Fill traveler information
68
+ 3. Use stored credentials for payment (via `credential_get` -- NEVER type raw card numbers)
69
+ 4. Screenshot the final review page for user confirmation
70
+ 5. Only click "Book" / "Confirm" after explicit user approval
71
+
72
+ ## Anti-Bot Detection Avoidance
73
+
74
+ The stealth configuration handles most fingerprinting automatically. Additionally:
75
+
76
+ - **Don't access detection endpoints**: Avoid URLs containing "captcha", "challenge", "verify"
77
+ - **Handle CAPTCHAs**: If you encounter a CAPTCHA, pause and inform the user. Do not attempt automated solving.
78
+ - **Rotate viewport sizes occasionally**: Use different viewport sizes across sessions
79
+ - **Maintain cookies**: Use persistent `user-data-dir` to appear as a returning user
80
+ - **Avoid headless tells**: The user-agent is set to a real browser string
81
+
82
+ ## Travel Site Patterns
83
+
84
+ ### Airbnb / VRBO
85
+ 1. Search by location + check-in/check-out dates + guests
86
+ 2. Results load dynamically -- scroll to load more listings
87
+ 3. Extract: title, price per night, total price, rating, number of reviews
88
+ 4. For detailed info, click into each listing and snapshot
89
+ 5. Compare top 3-5 options
90
+
91
+ ### Hotel Sites (Booking.com, Hotels.com)
92
+ 1. Search by destination + dates + guests + rooms
93
+ 2. Filter by price range, star rating, amenities
94
+ 3. Extract: name, price, location, rating, key amenities
95
+ 4. Check cancellation policies (important for travel planning)
96
+
97
+ ### Flight Comparison
98
+ 1. Prefer Duffel MCP for flight search (structured API data)
99
+ 2. Use browser only if Duffel doesn't cover the airline
100
+ 3. Google Flights is useful for price comparison but requires careful navigation
101
+
102
+ ## Error Handling
103
+
104
+ - **Page timeouts**: Retry once after 5 seconds. If still failing, inform the user.
105
+ - **CAPTCHAs**: Stop and ask the user to solve manually.
106
+ - **Stale elements**: Re-snapshot the page and retry the interaction.
107
+ - **Blocked/403**: The site may have detected automation. Wait 30 seconds and try with a different approach (e.g., direct URL instead of navigation).
108
+ - **Session expired**: Re-login using stored credentials.
109
+
110
+ ## Human Confirmation Gates
111
+
112
+ **ALWAYS** confirm with the user before:
113
+ - Any booking or payment action
114
+ - Entering personal information (name, address, phone)
115
+ - Agreeing to terms of service
116
+ - Subscribing to any service
117
+ - Any action that creates a financial obligation