@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,594 @@
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.vaultUnlockReplaceRecoverFix = vaultUnlockReplaceRecoverFix;
37
+ exports.credentialVaultNotConfiguredError = credentialVaultNotConfiguredError;
38
+ exports.isCredentialVaultNotConfiguredError = isCredentialVaultNotConfiguredError;
39
+ exports.vaultCreateRecoverFix = vaultCreateRecoverFix;
40
+ exports.promptConfirmedVaultUnlockSecret = promptConfirmedVaultUnlockSecret;
41
+ exports.resolveVaultUnlockStore = resolveVaultUnlockStore;
42
+ exports.noteVaultUnlockSelfHeal = noteVaultUnlockSelfHeal;
43
+ exports.clearVaultUnlockSecret = clearVaultUnlockSecret;
44
+ exports.readVaultUnlockSecret = readVaultUnlockSecret;
45
+ exports.storeVaultUnlockSecret = storeVaultUnlockSecret;
46
+ exports.getVaultUnlockStatus = getVaultUnlockStatus;
47
+ const node_child_process_1 = require("node:child_process");
48
+ const crypto = __importStar(require("node:crypto"));
49
+ const fs = __importStar(require("node:fs"));
50
+ const os = __importStar(require("node:os"));
51
+ const path = __importStar(require("node:path"));
52
+ const runtime_1 = require("../nerves/runtime");
53
+ const identity_1 = require("../heart/identity");
54
+ const VAULT_UNLOCK_SERVICE = "ouro.vault";
55
+ const CREDENTIAL_VAULT_NOT_CONFIGURED_PREFIX = "credential vault is not configured in ";
56
+ const PLAINTEXT_UNLOCK_DIR = path.join(".ouro-cli", "vault-unlock");
57
+ const WINDOWS_DPAPI_UNLOCK_DIR = path.join(".ouro-cli", "vault-unlock-dpapi");
58
+ const SUPPORTED_STORES = ["auto", "macos-keychain", "windows-dpapi", "linux-secret-service", "plaintext-file"];
59
+ function platform(deps) {
60
+ return deps.platform ?? process.platform;
61
+ }
62
+ function spawnSync(deps) {
63
+ return deps.spawnSync ?? node_child_process_1.spawnSync;
64
+ }
65
+ function homeDir(deps) {
66
+ return deps.homeDir ?? os.homedir();
67
+ }
68
+ function vaultKey(config) {
69
+ return `${config.serverUrl}:${config.email}`;
70
+ }
71
+ function vaultLabel(config) {
72
+ return `${config.email} at ${config.serverUrl}`;
73
+ }
74
+ function canonicalizeVaultUnlockConfig(config) {
75
+ return {
76
+ ...config,
77
+ serverUrl: (0, identity_1.normalizeVaultServerUrl)(config.serverUrl),
78
+ };
79
+ }
80
+ function vaultConfigCandidates(config) {
81
+ const canonical = canonicalizeVaultUnlockConfig(config);
82
+ return (0, identity_1.getVaultServerUrlCandidates)(config.serverUrl).map((serverUrl) => ({
83
+ ...canonical,
84
+ serverUrl,
85
+ }));
86
+ }
87
+ function exactVaultConfig(config) {
88
+ return {
89
+ ...config,
90
+ serverUrl: config.serverUrl.trim().replace(/\/+$/, ""),
91
+ };
92
+ }
93
+ function plaintextUnlockPath(config, deps) {
94
+ const digest = crypto.createHash("sha256").update(vaultKey(config)).digest("hex").slice(0, 24);
95
+ return path.join(homeDir(deps), PLAINTEXT_UNLOCK_DIR, `${digest}.secret`);
96
+ }
97
+ function windowsDpapiUnlockPath(config, deps) {
98
+ const digest = crypto.createHash("sha256").update(vaultKey(config)).digest("hex").slice(0, 24);
99
+ const localAppData = process.env.LOCALAPPDATA;
100
+ const baseDir = localAppData && platform(deps) === "win32"
101
+ ? path.join(localAppData, "Ouro")
102
+ : path.join(homeDir(deps), WINDOWS_DPAPI_UNLOCK_DIR);
103
+ return path.join(baseDir, "vault-unlock", `${digest}.dpapi`);
104
+ }
105
+ function commandExists(command, deps) {
106
+ const result = spawnSync(deps)(command, ["--version"], { encoding: "utf8" });
107
+ const code = result.error?.code;
108
+ return code !== "ENOENT";
109
+ }
110
+ function missingSecureStoreMessage(config) {
111
+ const agentPart = config.agentName ? ` for ${config.agentName}` : "";
112
+ return [
113
+ `No supported secure local secret store was found on this machine${agentPart}.`,
114
+ "",
115
+ `Ouro knows the credential vault is ${vaultLabel(config)}, but it cannot cache the vault unlock secret here yet.`,
116
+ "",
117
+ "On macOS, Ouro uses Keychain automatically.",
118
+ "On Windows, Ouro uses a CurrentUser DPAPI-encrypted local file automatically.",
119
+ "On Linux/WSL, install and configure Secret Service/libsecret, or choose the explicit plaintext fallback on a trusted machine.",
120
+ "",
121
+ config.agentName
122
+ ? `Run \`ouro vault unlock --agent ${config.agentName} --store plaintext-file\` to store the vault unlock secret in a chmod 0600 local file.`
123
+ : "Run `ouro vault unlock --store plaintext-file` to store the vault unlock secret in a chmod 0600 local file.",
124
+ ].join("\n");
125
+ }
126
+ function vaultUnlockReplaceRecoverFix(agentName, _nextStep) {
127
+ return `Run 'ouro vault unlock --agent ${agentName}' or 'ouro vault replace --agent ${agentName}' if the secret is lost.`;
128
+ }
129
+ function credentialVaultNotConfiguredError(agentName, configPath) {
130
+ return (`${CREDENTIAL_VAULT_NOT_CONFIGURED_PREFIX}${configPath}. ` +
131
+ `Run 'ouro vault create --agent ${agentName}' to create this agent's vault before loading or storing credentials.`);
132
+ }
133
+ function isCredentialVaultNotConfiguredError(message) {
134
+ return message.includes(CREDENTIAL_VAULT_NOT_CONFIGURED_PREFIX);
135
+ }
136
+ function vaultCreateRecoverFix(agentName, _nextStep) {
137
+ return `Run 'ouro vault create --agent ${agentName}' to set up this agent's vault.`;
138
+ }
139
+ function vaultUnlockSecretStrengthIssues(secret) {
140
+ const issues = [];
141
+ if (secret.length < 8)
142
+ issues.push("at least 8 characters");
143
+ if (!/[a-z]/.test(secret))
144
+ issues.push("a lowercase letter");
145
+ if (!/[A-Z]/.test(secret))
146
+ issues.push("an uppercase letter");
147
+ if (!/[0-9]/.test(secret))
148
+ issues.push("a number");
149
+ if (!/[^A-Za-z0-9]/.test(secret))
150
+ issues.push("a special character");
151
+ return issues;
152
+ }
153
+ async function promptConfirmedVaultUnlockSecret(input) {
154
+ const secret = (await input.promptSecret(input.question)).trim();
155
+ if (!secret) {
156
+ throw new Error(input.emptyError);
157
+ }
158
+ const issues = vaultUnlockSecretStrengthIssues(secret);
159
+ if (issues.length > 0) {
160
+ throw new Error(`vault unlock secret is too weak: add ${issues.join(", ")}. Use at least 8 characters with uppercase and lowercase letters, one number, and one special character.`);
161
+ }
162
+ const confirmation = (await input.promptSecret(input.confirmQuestion)).trim();
163
+ if (secret !== confirmation) {
164
+ throw new Error("vault unlock secrets did not match. Re-run the command and enter the same secret twice.");
165
+ }
166
+ return secret;
167
+ }
168
+ function lostUnlockSecretGuidance(config) {
169
+ if (!config.agentName) {
170
+ return "If nobody saved that unlock secret, run `ouro vault replace --agent <agent>` to create a new empty vault and re-enter credentials. If you do have a local JSON credential export, run `ouro vault recover --agent <agent> --from <json>` to import it.";
171
+ }
172
+ return [
173
+ `If nobody saved that unlock secret, run \`ouro vault replace --agent ${config.agentName}\` to create a new empty vault and re-enter credentials.`,
174
+ `If you do have a local JSON credential export, run \`ouro vault recover --agent ${config.agentName} --from <json>\` to import it.`,
175
+ ].join(" ");
176
+ }
177
+ function lockedMessage(config, store) {
178
+ const agentPart = config.agentName ? ` for ${config.agentName}` : "";
179
+ const command = config.agentName
180
+ ? `ouro vault unlock --agent ${config.agentName}${store.kind === "plaintext-file" ? " --store plaintext-file" : ""}`
181
+ : `ouro vault unlock${store.kind === "plaintext-file" ? " --store plaintext-file" : ""}`;
182
+ return [
183
+ `Ouro credential vault is locked on this machine${agentPart}.`,
184
+ "",
185
+ `Vault: ${vaultLabel(config)}`,
186
+ `Local unlock store: ${store.kind} (${store.location})`,
187
+ "",
188
+ "Provider credentials are still stored in the agent vault.",
189
+ "This computer does not currently have usable local unlock material for that vault.",
190
+ "This can happen on a new computer, after a local profile or hostname migration, or if the local unlock entry was removed.",
191
+ "",
192
+ `Run \`${command}\` and enter the saved agent vault unlock secret from the human/operator who controls that vault.`,
193
+ lostUnlockSecretGuidance(config),
194
+ ].join("\n");
195
+ }
196
+ function validateStoreKind(store) {
197
+ const requested = store ?? "auto";
198
+ if (!SUPPORTED_STORES.includes(requested)) {
199
+ throw new Error(`unknown vault unlock store '${requested}'. Use auto|macos-keychain|windows-dpapi|linux-secret-service|plaintext-file.`);
200
+ }
201
+ return requested;
202
+ }
203
+ function resolveVaultUnlockStore(config, deps = {}) {
204
+ const canonicalConfig = canonicalizeVaultUnlockConfig(config);
205
+ const requested = validateStoreKind(deps.store);
206
+ const currentPlatform = platform(deps);
207
+ if (requested === "macos-keychain") {
208
+ if (currentPlatform !== "darwin") {
209
+ throw new Error(`macos-keychain unlock store is only available on macOS; this machine is ${currentPlatform}.`);
210
+ }
211
+ return { kind: "macos-keychain", secure: true, location: "macOS Keychain" };
212
+ }
213
+ if (requested === "linux-secret-service") {
214
+ if (currentPlatform !== "linux") {
215
+ throw new Error(`linux-secret-service unlock store is only available on Linux/WSL; this machine is ${currentPlatform}.`);
216
+ }
217
+ if (!commandExists("secret-tool", deps)) {
218
+ throw new Error("linux-secret-service unlock store requires the `secret-tool` command from libsecret.");
219
+ }
220
+ return { kind: "linux-secret-service", secure: true, location: "Secret Service via secret-tool" };
221
+ }
222
+ if (requested === "windows-dpapi") {
223
+ if (currentPlatform !== "win32") {
224
+ throw new Error(`windows-dpapi unlock store is only available on Windows; this machine is ${currentPlatform}.`);
225
+ }
226
+ return { kind: "windows-dpapi", secure: true, location: windowsDpapiUnlockPath(canonicalConfig, deps) };
227
+ }
228
+ if (requested === "plaintext-file") {
229
+ return { kind: "plaintext-file", secure: false, location: plaintextUnlockPath(canonicalConfig, deps) };
230
+ }
231
+ if (currentPlatform === "darwin") {
232
+ return { kind: "macos-keychain", secure: true, location: "macOS Keychain" };
233
+ }
234
+ if (currentPlatform === "win32") {
235
+ return { kind: "windows-dpapi", secure: true, location: windowsDpapiUnlockPath(canonicalConfig, deps) };
236
+ }
237
+ if (currentPlatform === "linux" && commandExists("secret-tool", deps)) {
238
+ return { kind: "linux-secret-service", secure: true, location: "Secret Service via secret-tool" };
239
+ }
240
+ throw new Error(missingSecureStoreMessage(canonicalConfig));
241
+ }
242
+ function readFromMacosKeychainExact(accountKey, deps) {
243
+ const result = spawnSync(deps)("security", [
244
+ "find-generic-password",
245
+ "-s",
246
+ VAULT_UNLOCK_SERVICE,
247
+ "-a",
248
+ accountKey,
249
+ "-w",
250
+ ], { encoding: "utf8" });
251
+ const secret = typeof result.stdout === "string" ? result.stdout.trim() : "";
252
+ if (result.status === 0) {
253
+ return secret || null;
254
+ }
255
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
256
+ const error = result.error instanceof Error ? result.error.message : "";
257
+ const detail = stderr || error;
258
+ if (!detail || /could not be found in the keychain/i.test(detail)) {
259
+ return null;
260
+ }
261
+ throw new Error(`failed to read vault unlock secret from macOS Keychain: ${detail}`);
262
+ }
263
+ function noteVaultUnlockSelfHeal(config, storeKind, sourceServerUrl) {
264
+ (0, runtime_1.emitNervesEvent)({
265
+ component: "repertoire",
266
+ event: "repertoire.vault_unlock_self_healed",
267
+ message: "rewrote local unlock material using canonical vault coordinates",
268
+ meta: {
269
+ store: storeKind,
270
+ email: config.email,
271
+ sourceServerUrl,
272
+ targetServerUrl: config.serverUrl,
273
+ },
274
+ });
275
+ }
276
+ function readFromMacosKeychain(config, deps) {
277
+ const candidates = vaultConfigCandidates(config);
278
+ for (const candidate of candidates) {
279
+ const secret = readFromMacosKeychainExact(vaultKey(candidate), deps);
280
+ if (secret) {
281
+ return { secret, source: exactVaultConfig(candidate) };
282
+ }
283
+ }
284
+ return null;
285
+ }
286
+ function writeToMacosKeychain(config, secret, deps) {
287
+ const result = spawnSync(deps)("security", [
288
+ "add-generic-password",
289
+ "-U",
290
+ "-s",
291
+ VAULT_UNLOCK_SERVICE,
292
+ "-a",
293
+ vaultKey(config),
294
+ "-w",
295
+ secret,
296
+ ], { encoding: "utf8" });
297
+ if (result.status !== 0) {
298
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
299
+ throw new Error(`failed to store vault unlock secret in macOS Keychain${stderr ? `: ${stderr}` : ""}`);
300
+ }
301
+ }
302
+ function readFromLinuxSecretServiceExact(accountKey, deps) {
303
+ const result = spawnSync(deps)("secret-tool", [
304
+ "lookup",
305
+ "service",
306
+ VAULT_UNLOCK_SERVICE,
307
+ "account",
308
+ accountKey,
309
+ ], { encoding: "utf8" });
310
+ const secret = typeof result.stdout === "string" ? result.stdout.trim() : "";
311
+ if (result.status === 0) {
312
+ return secret || null;
313
+ }
314
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
315
+ const error = result.error instanceof Error ? result.error.message : "";
316
+ const detail = stderr || error;
317
+ if (!detail || /not found/i.test(detail)) {
318
+ return null;
319
+ }
320
+ throw new Error(`failed to read vault unlock secret from Linux Secret Service: ${detail}`);
321
+ }
322
+ function readFromLinuxSecretService(config, deps) {
323
+ const candidates = vaultConfigCandidates(config);
324
+ for (const candidate of candidates) {
325
+ const secret = readFromLinuxSecretServiceExact(vaultKey(candidate), deps);
326
+ if (secret) {
327
+ return { secret, source: exactVaultConfig(candidate) };
328
+ }
329
+ }
330
+ return null;
331
+ }
332
+ function writeToLinuxSecretService(config, secret, deps) {
333
+ const result = spawnSync(deps)("secret-tool", [
334
+ "store",
335
+ "--label",
336
+ `Ouro credential vault ${vaultLabel(config)}`,
337
+ "service",
338
+ VAULT_UNLOCK_SERVICE,
339
+ "account",
340
+ vaultKey(config),
341
+ ], { encoding: "utf8", input: secret });
342
+ if (result.status !== 0) {
343
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
344
+ throw new Error(`failed to store vault unlock secret in Linux Secret Service${stderr ? `: ${stderr}` : ""}`);
345
+ }
346
+ }
347
+ function runWindowsDpapi(mode, payload, deps) {
348
+ const script = `
349
+ $ErrorActionPreference = "Stop"
350
+ $inputJson = [Console]::In.ReadToEnd()
351
+ $payload = $inputJson | ConvertFrom-Json
352
+ Add-Type -AssemblyName System.Security
353
+ if ($payload.mode -eq "protect") {
354
+ $bytes = [Text.Encoding]::UTF8.GetBytes([string]$payload.secret)
355
+ $protected = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
356
+ [Console]::Out.Write([Convert]::ToBase64String($protected))
357
+ } elseif ($payload.mode -eq "unprotect") {
358
+ $protected = [Convert]::FromBase64String([string]$payload.ciphertext)
359
+ $bytes = [Security.Cryptography.ProtectedData]::Unprotect($protected, $null, [Security.Cryptography.DataProtectionScope]::CurrentUser)
360
+ [Console]::Out.Write([Text.Encoding]::UTF8.GetString($bytes))
361
+ } else {
362
+ throw "unknown DPAPI mode"
363
+ }
364
+ `;
365
+ const result = spawnSync(deps)("powershell.exe", [
366
+ "-NoProfile",
367
+ "-NonInteractive",
368
+ "-ExecutionPolicy",
369
+ "Bypass",
370
+ "-Command",
371
+ script,
372
+ ], {
373
+ encoding: "utf8",
374
+ input: JSON.stringify({ mode, ...payload }),
375
+ });
376
+ if (result.status !== 0) {
377
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
378
+ const error = result.error instanceof Error ? result.error.message : stderr;
379
+ throw new Error(`Windows DPAPI ${mode} failed${error ? `: ${error}` : ""}`);
380
+ }
381
+ return typeof result.stdout === "string" ? result.stdout : "";
382
+ }
383
+ function readFromWindowsDpapiExact(config, deps) {
384
+ const filePath = windowsDpapiUnlockPath(config, deps);
385
+ if (!fs.existsSync(filePath))
386
+ return null;
387
+ const ciphertext = fs.readFileSync(filePath, "utf8").trim();
388
+ if (!ciphertext)
389
+ return null;
390
+ const secret = runWindowsDpapi("unprotect", { ciphertext }, deps).trim();
391
+ return secret || null;
392
+ }
393
+ function readFromWindowsDpapi(config, deps) {
394
+ const candidates = vaultConfigCandidates(config);
395
+ for (const candidate of candidates) {
396
+ const secret = readFromWindowsDpapiExact(candidate, deps);
397
+ if (secret) {
398
+ return { secret, source: exactVaultConfig(candidate) };
399
+ }
400
+ }
401
+ return null;
402
+ }
403
+ function writeToWindowsDpapi(config, secret, deps) {
404
+ const filePath = windowsDpapiUnlockPath(config, deps);
405
+ const ciphertext = runWindowsDpapi("protect", { secret }, deps).trim();
406
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
407
+ fs.writeFileSync(filePath, `${ciphertext}\n`, "utf8");
408
+ }
409
+ function readFromPlaintextFileExact(config, deps) {
410
+ const filePath = plaintextUnlockPath(config, deps);
411
+ if (!fs.existsSync(filePath))
412
+ return null;
413
+ if (platform(deps) !== "win32") {
414
+ const mode = fs.statSync(filePath).mode & 0o777;
415
+ if ((mode & 0o077) !== 0) {
416
+ throw new Error(`refusing to read plaintext vault unlock file at ${filePath} because permissions are too broad; run chmod 600 ${filePath}`);
417
+ }
418
+ }
419
+ const secret = fs.readFileSync(filePath, "utf8").trim();
420
+ return secret || null;
421
+ }
422
+ function readFromPlaintextFile(config, deps) {
423
+ const candidates = vaultConfigCandidates(config);
424
+ for (const candidate of candidates) {
425
+ const secret = readFromPlaintextFileExact(candidate, deps);
426
+ if (secret) {
427
+ return { secret, source: exactVaultConfig(candidate) };
428
+ }
429
+ }
430
+ return null;
431
+ }
432
+ function writeToPlaintextFile(config, secret, deps) {
433
+ const filePath = plaintextUnlockPath(config, deps);
434
+ fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
435
+ fs.writeFileSync(filePath, secret, { encoding: "utf8", mode: 0o600 });
436
+ if (platform(deps) !== "win32") {
437
+ fs.chmodSync(path.dirname(filePath), 0o700);
438
+ fs.chmodSync(filePath, 0o600);
439
+ }
440
+ }
441
+ function readFromStore(config, store, deps) {
442
+ if (store.kind === "macos-keychain")
443
+ return readFromMacosKeychain(config, deps);
444
+ if (store.kind === "windows-dpapi")
445
+ return readFromWindowsDpapi(config, deps);
446
+ if (store.kind === "linux-secret-service")
447
+ return readFromLinuxSecretService(config, deps);
448
+ return readFromPlaintextFile(config, deps);
449
+ }
450
+ function writeToStore(config, store, secret, deps) {
451
+ if (store.kind === "macos-keychain") {
452
+ writeToMacosKeychain(config, secret, deps);
453
+ return;
454
+ }
455
+ if (store.kind === "linux-secret-service") {
456
+ writeToLinuxSecretService(config, secret, deps);
457
+ return;
458
+ }
459
+ if (store.kind === "windows-dpapi") {
460
+ writeToWindowsDpapi(config, secret, deps);
461
+ return;
462
+ }
463
+ writeToPlaintextFile(config, secret, deps);
464
+ }
465
+ function deleteFromMacosKeychainExact(config, deps) {
466
+ const result = spawnSync(deps)("security", [
467
+ "delete-generic-password",
468
+ "-s",
469
+ VAULT_UNLOCK_SERVICE,
470
+ "-a",
471
+ vaultKey(config),
472
+ ], { encoding: "utf8" });
473
+ if (result.status === 0)
474
+ return true;
475
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
476
+ const error = result.error instanceof Error ? result.error.message : "";
477
+ const detail = stderr || error;
478
+ if (!detail || /could not be found in the keychain/i.test(detail))
479
+ return false;
480
+ throw new Error(`failed to clear vault unlock secret from macOS Keychain: ${detail}`);
481
+ }
482
+ function deleteFromLinuxSecretServiceExact(config, deps) {
483
+ const result = spawnSync(deps)("secret-tool", [
484
+ "clear",
485
+ "service",
486
+ VAULT_UNLOCK_SERVICE,
487
+ "account",
488
+ vaultKey(config),
489
+ ], { encoding: "utf8" });
490
+ if (result.status === 0)
491
+ return true;
492
+ const stderr = typeof result.stderr === "string" ? result.stderr.trim() : "";
493
+ const error = result.error instanceof Error ? result.error.message : "";
494
+ const detail = stderr || error;
495
+ if (!detail || /not found/i.test(detail))
496
+ return false;
497
+ throw new Error(`failed to clear vault unlock secret from Linux Secret Service: ${detail}`);
498
+ }
499
+ function deleteFromWindowsDpapiExact(config, deps) {
500
+ const filePath = windowsDpapiUnlockPath(config, deps);
501
+ const existed = fs.existsSync(filePath);
502
+ fs.rmSync(filePath, { force: true });
503
+ return existed;
504
+ }
505
+ function deleteFromPlaintextFileExact(config, deps) {
506
+ const filePath = plaintextUnlockPath(config, deps);
507
+ const existed = fs.existsSync(filePath);
508
+ fs.rmSync(filePath, { force: true });
509
+ return existed;
510
+ }
511
+ function deleteFromStoreExact(config, store, deps) {
512
+ if (store.kind === "macos-keychain")
513
+ return deleteFromMacosKeychainExact(config, deps);
514
+ if (store.kind === "linux-secret-service")
515
+ return deleteFromLinuxSecretServiceExact(config, deps);
516
+ if (store.kind === "windows-dpapi")
517
+ return deleteFromWindowsDpapiExact(config, deps);
518
+ return deleteFromPlaintextFileExact(config, deps);
519
+ }
520
+ function clearVaultUnlockSecret(config, deps = {}) {
521
+ const canonicalConfig = canonicalizeVaultUnlockConfig(config);
522
+ const store = resolveVaultUnlockStore(canonicalConfig, deps);
523
+ const deletedAccounts = new Set();
524
+ let deleted = false;
525
+ for (const candidate of vaultConfigCandidates(config)) {
526
+ const exactCandidate = exactVaultConfig(candidate);
527
+ const key = vaultKey(exactCandidate);
528
+ if (deletedAccounts.has(key))
529
+ continue;
530
+ deletedAccounts.add(key);
531
+ deleted = deleteFromStoreExact(exactCandidate, store, deps) || deleted;
532
+ }
533
+ (0, runtime_1.emitNervesEvent)({
534
+ component: "repertoire",
535
+ event: "repertoire.vault_unlock_cleared",
536
+ message: "cleared local vault unlock material",
537
+ meta: { store: store.kind, secure: store.secure, hasAgentName: !!config.agentName, deleted },
538
+ });
539
+ return store;
540
+ }
541
+ function readVaultUnlockSecret(config, deps = {}) {
542
+ const canonicalConfig = canonicalizeVaultUnlockConfig(config);
543
+ const store = resolveVaultUnlockStore(canonicalConfig, deps);
544
+ const loaded = readFromStore(canonicalConfig, store, deps);
545
+ if (!loaded) {
546
+ throw new Error(lockedMessage(canonicalConfig, store));
547
+ }
548
+ (0, runtime_1.emitNervesEvent)({
549
+ component: "repertoire",
550
+ event: "repertoire.vault_unlock_loaded",
551
+ message: "loaded vault unlock material from local store",
552
+ meta: { store: store.kind, secure: store.secure, hasAgentName: !!config.agentName, sourceServerUrl: loaded.source.serverUrl },
553
+ });
554
+ return { secret: loaded.secret, store, source: loaded.source };
555
+ }
556
+ function storeVaultUnlockSecret(config, secret, deps = {}) {
557
+ const canonicalConfig = canonicalizeVaultUnlockConfig(config);
558
+ const trimmed = secret.trim();
559
+ if (!trimmed) {
560
+ throw new Error("vault unlock secret is required");
561
+ }
562
+ const store = resolveVaultUnlockStore(canonicalConfig, deps);
563
+ writeToStore(canonicalConfig, store, trimmed, deps);
564
+ (0, runtime_1.emitNervesEvent)({
565
+ component: "repertoire",
566
+ event: "repertoire.vault_unlock_stored",
567
+ message: "stored vault unlock material in local store",
568
+ meta: { store: store.kind, secure: store.secure, hasAgentName: !!config.agentName },
569
+ });
570
+ return store;
571
+ }
572
+ function getVaultUnlockStatus(config, deps = {}) {
573
+ try {
574
+ const canonicalConfig = canonicalizeVaultUnlockConfig(config);
575
+ const store = resolveVaultUnlockStore(canonicalConfig, deps);
576
+ const stored = !!readFromStore(canonicalConfig, store, deps);
577
+ return {
578
+ configured: true,
579
+ stored,
580
+ store,
581
+ fix: stored
582
+ ? "Vault unlock secret is available on this machine."
583
+ : lockedMessage(canonicalConfig, store),
584
+ };
585
+ }
586
+ catch (error) {
587
+ return {
588
+ configured: false,
589
+ stored: false,
590
+ error: error instanceof Error ? error.message : String(error),
591
+ fix: error instanceof Error ? error.message : String(error),
592
+ };
593
+ }
594
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ // Claude Code lifecycle hook handler.
3
+ // Receives events from Claude Code's hooks system (SessionStart, Stop, PostToolUse)
4
+ // and forwards them to the Ouroboros daemon for agent awareness.
5
+ //
6
+ // This module exports handleHookEvent for testability.
7
+ // The actual hook scripts (scripts/claude-code-hook.js) read stdin and call this.
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.handleHookEvent = handleHookEvent;
10
+ const socket_client_1 = require("../heart/daemon/socket-client");
11
+ const runtime_1 = require("../nerves/runtime");
12
+ /**
13
+ * Handle a Claude Code lifecycle hook event.
14
+ * Sends the event to the daemon and always exits 0 (hooks must not block the IDE).
15
+ */
16
+ async function handleHookEvent(hookEvent) {
17
+ (0, runtime_1.emitNervesEvent)({
18
+ component: "daemon",
19
+ event: "daemon.hook_event_received",
20
+ message: "claude code hook event received",
21
+ meta: { hookEvent: hookEvent.event, sessionId: hookEvent.sessionId },
22
+ });
23
+ try {
24
+ await (0, socket_client_1.sendDaemonCommand)(socket_client_1.DEFAULT_DAEMON_SOCKET_PATH, {
25
+ kind: "hook.event",
26
+ event: hookEvent.event,
27
+ sessionId: hookEvent.sessionId,
28
+ toolName: hookEvent.toolName,
29
+ });
30
+ }
31
+ catch {
32
+ // Daemon unavailable — silently ignore. Hooks must not block.
33
+ (0, runtime_1.emitNervesEvent)({
34
+ component: "daemon",
35
+ event: "daemon.hook_event_daemon_unavailable",
36
+ message: "daemon unavailable for hook event",
37
+ meta: { hookEvent: hookEvent.event },
38
+ });
39
+ }
40
+ return { exitCode: 0 };
41
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ // Claude Code stop hook — checks the agent's pending queue and returns
3
+ // any messages as additionalContext for injection into the next turn.
4
+ //
5
+ // This is how the agent can proactively communicate back to the dev tool user:
6
+ // the agent surfaces a message to the pending queue, and the stop hook picks
7
+ // it up and injects it as context in the Claude Code session.
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.handleStopHook = handleStopHook;
10
+ const pending_1 = require("../mind/pending");
11
+ const runtime_1 = require("../nerves/runtime");
12
+ /**
13
+ * Check the pending queue for messages from the agent to this dev tool session.
14
+ * Returns accumulated message text as additionalContext.
15
+ */
16
+ async function handleStopHook(input) {
17
+ (0, runtime_1.emitNervesEvent)({
18
+ component: "daemon",
19
+ event: "daemon.stop_hook_check_start",
20
+ message: "checking pending queue for stop hook",
21
+ meta: { agentName: input.agentName, friendId: input.friendId, sessionId: input.sessionId },
22
+ });
23
+ try {
24
+ const pendingDir = (0, pending_1.getPendingDir)(input.agentName, input.friendId, "mcp", input.sessionId);
25
+ const pending = (0, pending_1.drainPending)(pendingDir);
26
+ if (pending.length === 0) {
27
+ return { additionalContext: "" };
28
+ }
29
+ const text = pending.map((m) => m.content).join("\n\n---\n\n");
30
+ (0, runtime_1.emitNervesEvent)({
31
+ component: "daemon",
32
+ event: "daemon.stop_hook_check_end",
33
+ message: "pending messages found for stop hook",
34
+ meta: { agentName: input.agentName, count: pending.length },
35
+ });
36
+ return { additionalContext: text };
37
+ }
38
+ catch {
39
+ (0, runtime_1.emitNervesEvent)({
40
+ component: "daemon",
41
+ event: "daemon.stop_hook_check_error",
42
+ message: "error checking pending queue in stop hook",
43
+ meta: { agentName: input.agentName },
44
+ });
45
+ return { additionalContext: "" };
46
+ }
47
+ }