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

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 (396) 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 +3604 -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 +251 -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/audio-routing.js +119 -0
  350. package/dist/senses/voice/elevenlabs.js +178 -0
  351. package/dist/senses/voice/golden-path.js +116 -0
  352. package/dist/senses/voice/index.js +26 -0
  353. package/dist/senses/voice/meeting.js +113 -0
  354. package/dist/senses/voice/playback.js +139 -0
  355. package/dist/senses/voice/transcript.js +70 -0
  356. package/dist/senses/voice/turn.js +85 -0
  357. package/dist/senses/voice/types.js +2 -0
  358. package/dist/senses/voice/whisper.js +161 -0
  359. package/dist/senses/voice-entry.js +80 -0
  360. package/dist/trips/core.js +138 -0
  361. package/dist/trips/store.js +146 -0
  362. package/package.json +38 -7
  363. package/skills/agent-commerce.md +106 -0
  364. package/skills/browser-navigation.md +117 -0
  365. package/skills/commerce-setup-guide.md +116 -0
  366. package/skills/commerce-setup.md +84 -0
  367. package/skills/configure-dev-tools.md +101 -0
  368. package/skills/travel-planning.md +138 -0
  369. package/dist/heart/daemon/auth-flow.js +0 -351
  370. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  371. package/dist/heart/daemon/subagent-installer.js +0 -166
  372. package/dist/heart/session-recall.js +0 -116
  373. package/dist/mind/associative-recall.js +0 -209
  374. package/dist/senses/bluebubbles-entry.js +0 -13
  375. package/dist/senses/bluebubbles.js +0 -1177
  376. package/dist/senses/debug-activity.js +0 -148
  377. package/subagents/README.md +0 -86
  378. package/subagents/work-doer.md +0 -237
  379. package/subagents/work-merger.md +0 -618
  380. package/subagents/work-planner.md +0 -390
  381. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  382. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  383. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  384. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  385. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  386. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  387. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  388. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  389. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  390. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  391. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  392. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  393. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  394. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  395. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  396. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -41,6 +41,9 @@ exports.readTaskFile = readTaskFile;
41
41
  exports.buildTaskTriggeredMessage = buildTaskTriggeredMessage;
42
42
  exports.deriveResumeCheckpoint = deriveResumeCheckpoint;
43
43
  exports.innerDialogSessionPath = innerDialogSessionPath;
44
+ exports.enrichDelegatedFromWithBridge = enrichDelegatedFromWithBridge;
45
+ exports.routeDelegatedCompletion = routeDelegatedCompletion;
46
+ exports.buildParseErrorNudge = buildParseErrorNudge;
44
47
  exports.runInnerDialogTurn = runInnerDialogTurn;
45
48
  const fs = __importStar(require("fs"));
46
49
  const path = __importStar(require("path"));
@@ -49,8 +52,13 @@ const core_1 = require("../heart/core");
49
52
  const identity_1 = require("../heart/identity");
50
53
  const context_1 = require("../mind/context");
51
54
  const prompt_1 = require("../mind/prompt");
55
+ const mcp_manager_1 = require("../repertoire/mcp-manager");
56
+ const tools_1 = require("../repertoire/tools");
52
57
  const bundle_manifest_1 = require("../mind/bundle-manifest");
53
58
  const pending_1 = require("../mind/pending");
59
+ const obligations_1 = require("../arc/obligations");
60
+ const attention_queue_1 = require("./attention-queue");
61
+ const packets_1 = require("../arc/packets");
54
62
  const channel_1 = require("../mind/friends/channel");
55
63
  const trust_gate_1 = require("./trust-gate");
56
64
  const tokens_1 = require("../mind/friends/tokens");
@@ -60,6 +68,12 @@ const runtime_1 = require("../nerves/runtime");
60
68
  const manager_1 = require("../heart/bridges/manager");
61
69
  const session_activity_1 = require("../heart/session-activity");
62
70
  const bluebubbles_1 = require("./bluebubbles");
71
+ const habit_turn_message_1 = require("./habit-turn-message");
72
+ const journal_index_1 = require("../mind/journal-index");
73
+ const habit_parser_1 = require("../heart/habits/habit-parser");
74
+ const habit_runtime_state_1 = require("../heart/habits/habit-runtime-state");
75
+ const cadence_1 = require("../heart/daemon/cadence");
76
+ const daemon_health_1 = require("../heart/daemon/daemon-health");
63
77
  const DEFAULT_INNER_DIALOG_INSTINCTS = [
64
78
  {
65
79
  id: "heartbeat_checkin",
@@ -98,23 +112,31 @@ function buildNonCanonicalCleanupNudge(nonCanonicalPaths) {
98
112
  }
99
113
  return [
100
114
  "## canonical cleanup nudge",
101
- "I found non-canonical files in my bundle. I should distill anything valuable into your memory system and remove these files.",
115
+ "I found non-canonical files in my bundle. I should distill anything valuable into my diary and remove these files.",
102
116
  ...listed,
103
117
  ].join("\n");
104
118
  }
119
+ function displayCheckpoint(checkpoint) {
120
+ const trimmed = checkpoint?.trim();
121
+ if (!trimmed || trimmed === "no prior checkpoint recorded") {
122
+ return undefined;
123
+ }
124
+ return trimmed;
125
+ }
105
126
  function buildInstinctUserMessage(instincts, _reason, state) {
106
127
  const active = instincts.find((instinct) => instinct.enabled !== false) ?? DEFAULT_INNER_DIALOG_INSTINCTS[0];
107
- const checkpoint = state.checkpoint?.trim();
128
+ const checkpoint = displayCheckpoint(state.checkpoint);
108
129
  const lines = [active.prompt];
109
130
  if (checkpoint) {
110
- lines.push(`\nlast i remember: ${checkpoint}`);
131
+ lines.push(`\nlast checkpoint: ${checkpoint}`);
111
132
  }
112
133
  return lines.join("\n");
113
134
  }
114
135
  function readTaskFile(agentRoot, taskId) {
115
- // Task files live in collection subdirectories (one-shots, ongoing, habits).
136
+ // Task files live in collection subdirectories (one-shots, ongoing).
116
137
  // Try each collection, then fall back to root tasks/ for legacy layout.
117
- const collections = ["one-shots", "ongoing", "habits", ""];
138
+ // Habits are no longer in tasks/ — they live at bundle root habits/.
139
+ const collections = ["one-shots", "ongoing", ""];
118
140
  for (const collection of collections) {
119
141
  try {
120
142
  return fs.readFileSync(path.join(agentRoot, "tasks", collection, `${taskId}.md`), "utf8").trim();
@@ -133,8 +155,9 @@ function buildTaskTriggeredMessage(taskId, taskContent, checkpoint) {
133
155
  else {
134
156
  lines.push("", `## task: ${taskId}`, "(task file not found)");
135
157
  }
136
- if (checkpoint) {
137
- lines.push("", `last i remember: ${checkpoint}`);
158
+ const renderedCheckpoint = displayCheckpoint(checkpoint);
159
+ if (renderedCheckpoint) {
160
+ lines.push("", `last checkpoint: ${renderedCheckpoint}`);
138
161
  }
139
162
  return lines.join("\n");
140
163
  }
@@ -164,19 +187,17 @@ function deriveResumeCheckpoint(messages) {
164
187
  const assistantText = contentToText(lastAssistant.content);
165
188
  if (!assistantText)
166
189
  return "no prior checkpoint recorded";
167
- const explicitCheckpoint = assistantText
190
+ const cleanedLines = assistantText
168
191
  .split("\n")
169
- .map((line) => line.trim())
192
+ .map((line) => line.replace(/<\/?think>/gi, "").trim())
193
+ .filter((line) => line.length > 0);
194
+ const explicitCheckpoint = cleanedLines
170
195
  .find((line) => /^checkpoint\s*:/i.test(line));
171
196
  if (explicitCheckpoint) {
172
197
  const parsed = explicitCheckpoint.replace(/^checkpoint\s*:\s*/i, "").trim();
173
198
  return parsed || "no prior checkpoint recorded";
174
199
  }
175
- const firstLine = assistantText
176
- .split("\n")
177
- .map((line) => line.trim())
178
- .find((line) => line.length > 0);
179
- /* v8 ignore next -- unreachable: contentToText().trim() guarantees a non-empty line @preserve */
200
+ const firstLine = cleanedLines[0];
180
201
  if (!firstLine)
181
202
  return "no prior checkpoint recorded";
182
203
  if (firstLine.length <= 220)
@@ -247,6 +268,7 @@ function writeInnerDialogRuntimeState(sessionFilePath, state) {
247
268
  });
248
269
  }
249
270
  }
271
+ /* v8 ignore start -- routing helpers: called from routing functions which are integration paths @preserve */
250
272
  function writePendingEnvelope(pendingDir, message) {
251
273
  fs.mkdirSync(pendingDir, { recursive: true });
252
274
  const fileName = `${message.timestamp}-${Math.random().toString(36).slice(2, 10)}.json`;
@@ -258,6 +280,8 @@ function sessionMatchesActivity(activity, session) {
258
280
  && activity.channel === session.channel
259
281
  && activity.key === session.key;
260
282
  }
283
+ /* v8 ignore stop */
284
+ /* v8 ignore start -- routing: delivery now inline via surface tool; routing functions preserved for reuse @preserve */
261
285
  function resolveBridgePreferredSession(delegatedFrom, sessionActivity) {
262
286
  if (!delegatedFrom.bridgeId)
263
287
  return null;
@@ -277,15 +301,82 @@ async function tryDeliverDelegatedCompletion(target, outboundEnvelope) {
277
301
  friendId: target.friendId,
278
302
  sessionKey: target.key,
279
303
  text: outboundEnvelope.content,
304
+ intent: "explicit_cross_chat",
280
305
  });
281
306
  return result.delivered;
282
307
  }
308
+ function enrichDelegatedFromWithBridge(delegatedFrom) {
309
+ if (delegatedFrom.bridgeId) {
310
+ return delegatedFrom;
311
+ }
312
+ const bridgeManager = (0, manager_1.createBridgeManager)();
313
+ const originBridges = bridgeManager.findBridgesForSession({
314
+ friendId: delegatedFrom.friendId,
315
+ channel: delegatedFrom.channel,
316
+ key: delegatedFrom.key,
317
+ });
318
+ const activeBridge = originBridges.find((b) => b.lifecycle === "active");
319
+ if (activeBridge) {
320
+ return { ...delegatedFrom, bridgeId: activeBridge.id };
321
+ }
322
+ return delegatedFrom;
323
+ }
324
+ function advanceObligationQuietly(agentName, obligationId, update) {
325
+ if (!obligationId)
326
+ return;
327
+ try {
328
+ (0, obligations_1.advanceReturnObligation)(agentName, obligationId, update);
329
+ /* v8 ignore start -- best-effort: obligation fs errors must never block return routing @preserve */
330
+ }
331
+ catch {
332
+ // swallowed
333
+ }
334
+ /* v8 ignore stop */
335
+ }
283
336
  async function routeDelegatedCompletion(agentRoot, agentName, completion, drainedPending, timestamp) {
284
337
  const delegated = (drainedPending ?? []).find((message) => message.delegatedFrom);
285
338
  if (!delegated?.delegatedFrom || !completion?.answer?.trim()) {
286
339
  return;
287
340
  }
288
- const delegatedFrom = delegated.delegatedFrom;
341
+ const delegatedFrom = enrichDelegatedFromWithBridge(delegated.delegatedFrom);
342
+ const obligationId = delegated.obligationId;
343
+ // Advance any inner return obligations from queued -> running (they were drained this turn).
344
+ // drainedPending is guaranteed non-null here (we found delegated above).
345
+ for (const msg of drainedPending) {
346
+ if (msg.obligationId) {
347
+ advanceObligationQuietly(agentName, msg.obligationId, {
348
+ status: "running",
349
+ startedAt: timestamp,
350
+ });
351
+ }
352
+ }
353
+ if (delegated.obligationStatus === "pending") {
354
+ // Fulfill the persistent obligation in the store
355
+ try {
356
+ const pending = (0, obligations_1.findPendingObligationForOrigin)(agentRoot, {
357
+ friendId: delegatedFrom.friendId,
358
+ channel: delegatedFrom.channel,
359
+ key: delegatedFrom.key,
360
+ });
361
+ /* v8 ignore next 2 -- obligation fulfillment tested via obligations.test.ts; integration requires real disk state @preserve */
362
+ if (pending) {
363
+ (0, obligations_1.fulfillObligation)(agentRoot, pending.id);
364
+ }
365
+ }
366
+ catch {
367
+ /* v8 ignore next -- defensive: obligation store read failure should not break delivery @preserve */
368
+ }
369
+ (0, runtime_1.emitNervesEvent)({
370
+ event: "senses.obligation_fulfilled",
371
+ component: "senses",
372
+ message: "obligation fulfilled via delegated completion",
373
+ meta: {
374
+ friendId: delegatedFrom.friendId,
375
+ channel: delegatedFrom.channel,
376
+ key: delegatedFrom.key,
377
+ },
378
+ });
379
+ }
289
380
  const outboundEnvelope = {
290
381
  from: agentName,
291
382
  friendId: delegatedFrom.friendId,
@@ -294,36 +385,62 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
294
385
  content: completion.answer.trim(),
295
386
  timestamp,
296
387
  delegatedFrom,
388
+ ...(obligationId ? { obligationId } : {}),
297
389
  };
298
390
  const sessionActivity = (0, session_activity_1.listSessionActivity)({
299
391
  sessionsDir: path.join(agentRoot, "state", "sessions"),
300
392
  friendsDir: path.join(agentRoot, "friends"),
301
393
  agentName,
302
394
  });
395
+ // Priority 1: Bridge-preferred session (if delegation was within a bridge).
303
396
  const bridgeTarget = resolveBridgePreferredSession(delegatedFrom, sessionActivity);
304
397
  if (bridgeTarget) {
305
398
  if (await tryDeliverDelegatedCompletion(bridgeTarget, outboundEnvelope)) {
399
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
306
400
  return;
307
401
  }
308
402
  writePendingEnvelope((0, pending_1.getPendingDir)(agentName, bridgeTarget.friendId, bridgeTarget.channel, bridgeTarget.key), outboundEnvelope);
403
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
309
404
  return;
310
405
  }
311
- const freshest = (0, session_activity_1.findFreshestFriendSession)({
406
+ // Priority 1.5: Direct return to originating session (ponder without bridge).
407
+ // When delegatedFrom has specific channel+key, route directly there instead of searching for freshest.
408
+ if (delegatedFrom.channel && delegatedFrom.key && delegatedFrom.channel !== "inner") {
409
+ const directTarget = sessionActivity.find((a) => a.friendId === delegatedFrom.friendId && a.channel === delegatedFrom.channel && a.key === delegatedFrom.key);
410
+ if (directTarget) {
411
+ if (await tryDeliverDelegatedCompletion(directTarget, outboundEnvelope)) {
412
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
413
+ return;
414
+ }
415
+ }
416
+ // Even if session isn't in activity list (might have ended), queue to its pending dir
417
+ writePendingEnvelope((0, pending_1.getPendingDir)(agentName, delegatedFrom.friendId, delegatedFrom.channel, delegatedFrom.key), outboundEnvelope);
418
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
419
+ return;
420
+ }
421
+ // Priority 2: Freshest active friend session.
422
+ // For BB, prefer DM sessions (;-;) over group chats (;+;) — proactive outreach should never land in groups.
423
+ const allFriendSessions = (0, session_activity_1.listSessionActivity)({
312
424
  sessionsDir: path.join(agentRoot, "state", "sessions"),
313
425
  friendsDir: path.join(agentRoot, "friends"),
314
426
  agentName,
315
- friendId: delegatedFrom.friendId,
316
- activeOnly: true,
317
- });
318
- if (freshest && freshest.channel !== "inner") {
427
+ }).filter((s) => s.friendId === delegatedFrom.friendId && s.channel !== "inner");
428
+ const bbDm = allFriendSessions.find((s) => s.channel === "bluebubbles" && s.key.includes(";-;"));
429
+ const freshest = bbDm ?? allFriendSessions.find((s) => s.channel !== "bluebubbles" || s.key.includes(";-;")) ?? allFriendSessions[0];
430
+ if (freshest) {
319
431
  if (await tryDeliverDelegatedCompletion(freshest, outboundEnvelope)) {
432
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
320
433
  return;
321
434
  }
322
435
  writePendingEnvelope((0, pending_1.getPendingDir)(agentName, freshest.friendId, freshest.channel, freshest.key), outboundEnvelope);
436
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
323
437
  return;
324
438
  }
439
+ // Priority 3: Deferred return queue.
325
440
  writePendingEnvelope((0, pending_1.getDeferredReturnDir)(agentName, delegatedFrom.friendId), outboundEnvelope);
441
+ advanceObligationQuietly(agentName, obligationId, { status: "deferred", returnedAt: timestamp, returnTarget: "deferred" });
326
442
  }
443
+ /* v8 ignore stop */
327
444
  // Self-referencing friend record for inner dialog (agent talking to itself).
328
445
  // No real friend to resolve -- this satisfies the pipeline's friend resolver contract.
329
446
  function createSelfFriend(agentName) {
@@ -350,12 +467,59 @@ function createNoOpFriendStore() {
350
467
  findByExternalId: async () => null,
351
468
  };
352
469
  }
470
+ function buildParseErrorNudge(parseErrors) {
471
+ if (parseErrors.length === 0)
472
+ return "";
473
+ const lines = parseErrors.map((e) => `I noticed my habit file \`${e.file}\` has invalid frontmatter — I should fix it. (${e.error})`);
474
+ return lines.join("\n");
475
+ }
476
+ function buildAlsoDueLine(agentRoot, currentHabitName, now) {
477
+ const habitsDir = path.join(agentRoot, "habits");
478
+ let files;
479
+ try {
480
+ files = fs.readdirSync(habitsDir);
481
+ }
482
+ catch {
483
+ return "";
484
+ }
485
+ const nowMs = now().getTime();
486
+ const alsoDue = [];
487
+ for (const file of files) {
488
+ if (!file.endsWith(".md"))
489
+ continue;
490
+ const stem = file.replace(/\.md$/, "");
491
+ if (stem === currentHabitName)
492
+ continue;
493
+ try {
494
+ const content = fs.readFileSync(path.join(habitsDir, file), "utf-8");
495
+ const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(content, path.join(habitsDir, file)));
496
+ if (habit.status !== "active" || !habit.cadence)
497
+ continue;
498
+ const cadenceMs = (0, cadence_1.parseCadenceToMs)(habit.cadence);
499
+ if (cadenceMs === null)
500
+ continue;
501
+ if (habit.lastRun === null) {
502
+ alsoDue.push(stem);
503
+ continue;
504
+ }
505
+ const lastRunMs = new Date(habit.lastRun).getTime();
506
+ if (nowMs - lastRunMs >= cadenceMs) {
507
+ alsoDue.push(stem);
508
+ }
509
+ }
510
+ catch {
511
+ // skip unreadable habits
512
+ }
513
+ }
514
+ if (alsoDue.length === 0)
515
+ return "";
516
+ return `also due: ${alsoDue.join(", ")}`;
517
+ }
353
518
  async function runInnerDialogTurn(options) {
354
519
  const now = options?.now ?? (() => new Date());
355
- const reason = options?.reason ?? "heartbeat";
520
+ const reason = options?.reason ?? "instinct";
356
521
  const sessionFilePath = innerDialogSessionPath();
357
522
  const agentName = (0, identity_1.getAgentName)();
358
- const agentRoot = (0, identity_1.getAgentRoot)();
359
523
  writeInnerDialogRuntimeState(sessionFilePath, {
360
524
  status: "running",
361
525
  reason,
@@ -372,6 +536,8 @@ async function runInnerDialogTurn(options) {
372
536
  };
373
537
  // ── Adapter concern: build user message ──────────────────────────
374
538
  let userContent;
539
+ let habitTools;
540
+ let habitParsedSuccessfully = false;
375
541
  if (existingMessages.length === 0) {
376
542
  // Fresh session: bootstrap message with non-canonical cleanup nudge
377
543
  const aspirations = readAspirations((0, identity_1.getAgentRoot)());
@@ -391,6 +557,74 @@ async function runInnerDialogTurn(options) {
391
557
  const taskContent = readTaskFile((0, identity_1.getAgentRoot)(), options.taskId);
392
558
  userContent = buildTaskTriggeredMessage(options.taskId, taskContent, state.checkpoint);
393
559
  }
560
+ else if (reason === "habit" && options?.habitName) {
561
+ const agentRoot = (0, identity_1.getAgentRoot)();
562
+ const habitName = options.habitName;
563
+ const habitFilePath = path.join(agentRoot, "habits", `${habitName}.md`);
564
+ // Read and parse the habit file
565
+ let habitBody;
566
+ let habitTitle = habitName;
567
+ let habitLastRun = null;
568
+ try {
569
+ const habitContent = fs.readFileSync(habitFilePath, "utf-8");
570
+ const parsed = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(habitContent, habitFilePath));
571
+ habitBody = parsed.body || undefined;
572
+ habitTitle = parsed.title || habitName;
573
+ habitLastRun = parsed.lastRun;
574
+ habitTools = parsed.tools;
575
+ }
576
+ catch {
577
+ // Habit file missing or unreadable
578
+ }
579
+ // If the habit file couldn't be read at all (no body, no title parsed), error message
580
+ if (habitBody === undefined && habitTitle === habitName) {
581
+ userContent = `habit "${habitName}" could not be read (file not found or unreadable). check habits/${habitName}.md exists.`;
582
+ }
583
+ else {
584
+ habitParsedSuccessfully = true;
585
+ // Unified path: gather context for ALL habits (heartbeat included)
586
+ const obligations = (0, obligations_1.listActiveReturnObligations)(agentName);
587
+ const nowMs = now().getTime();
588
+ const staleObligations = obligations.map((o) => ({
589
+ friendName: o.origin.friendId,
590
+ content: o.delegatedContent,
591
+ stalenessMs: nowMs - o.createdAt,
592
+ }));
593
+ const alsoDue = buildAlsoDueLine(agentRoot, habitName, now);
594
+ // Degraded state (best-effort: never crash)
595
+ let degradedComponents = [];
596
+ try {
597
+ const health = (0, daemon_health_1.readHealth)((0, daemon_health_1.getDefaultHealthPath)());
598
+ if (health && health.degraded.length > 0) {
599
+ degradedComponents = health.degraded.map((d) => ({ component: d.component, reason: d.reason }));
600
+ }
601
+ }
602
+ catch {
603
+ // Best-effort: missing file or parse error -> empty array, no crash
604
+ }
605
+ userContent = (0, habit_turn_message_1.buildHabitTurnMessage)({
606
+ habitName,
607
+ habitTitle,
608
+ habitBody,
609
+ lastRun: habitLastRun,
610
+ checkpoint: displayCheckpoint(state.checkpoint),
611
+ alsoDue: alsoDue || undefined,
612
+ staleObligations,
613
+ parseErrors: options?.parseErrors ?? [],
614
+ degradedComponents,
615
+ now,
616
+ });
617
+ // Piggyback journal embedding indexing (best-effort, fire-and-forget)
618
+ const journalDir = path.join(agentRoot, "journal");
619
+ /* v8 ignore start -- journal indexing piggyback: embedding provider may not be available; tested via journal-index unit tests @preserve */
620
+ void (0, journal_index_1.indexJournalFiles)(journalDir, path.join(journalDir, ".index.json"), {
621
+ embed: async () => [],
622
+ }).catch(() => {
623
+ // swallowed: indexing failure must never block habit turn
624
+ });
625
+ /* v8 ignore stop */
626
+ }
627
+ }
394
628
  else {
395
629
  userContent = buildInstinctUserMessage(instincts, reason, state);
396
630
  }
@@ -401,15 +635,43 @@ async function runInnerDialogTurn(options) {
401
635
  const pendingDir = (0, pending_1.getInnerDialogPendingDir)(agentName);
402
636
  const selfFriend = createSelfFriend(agentName);
403
637
  const selfContext = { friend: selfFriend, channel: innerCapabilities };
638
+ const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
639
+ // ── Habit tool enforcement ───────────────────────────────────────
640
+ let habitToolsResolved;
641
+ if (habitTools !== undefined) {
642
+ const fullTools = (0, tools_1.getToolsForChannel)(innerCapabilities);
643
+ habitToolsResolved = fullTools.filter((t) => habitTools.includes(t.function.name));
644
+ (0, runtime_1.emitNervesEvent)({
645
+ event: "habit.tools_restricted",
646
+ component: "senses",
647
+ message: "habit running with restricted tools",
648
+ meta: {
649
+ habitName: options?.habitName,
650
+ declared: habitTools,
651
+ resolved: habitToolsResolved.map((t) => t.function.name),
652
+ },
653
+ });
654
+ }
655
+ else if (reason === "habit" && options?.habitName && habitParsedSuccessfully) {
656
+ (0, runtime_1.emitNervesEvent)({
657
+ event: "habit.tools_unrestricted",
658
+ component: "senses",
659
+ message: "habit running with full tool repertoire",
660
+ meta: { habitName: options.habitName },
661
+ });
662
+ }
404
663
  const sessionLoader = {
405
664
  loadOrCreate: async () => {
406
665
  if (existingMessages.length > 0) {
407
- return { messages: existingMessages, sessionPath: sessionFilePath };
666
+ return {
667
+ messages: existingMessages,
668
+ sessionPath: sessionFilePath,
669
+ };
408
670
  }
409
671
  // Fresh session: build system prompt
410
672
  const systemPrompt = await (0, prompt_1.buildSystem)("inner", { toolChoiceRequired: true });
411
673
  return {
412
- messages: [{ role: "system", content: systemPrompt }],
674
+ messages: [{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(systemPrompt) }],
413
675
  sessionPath: sessionFilePath,
414
676
  };
415
677
  },
@@ -417,6 +679,8 @@ async function runInnerDialogTurn(options) {
417
679
  // ── Call shared pipeline ──────────────────────────────────────────
418
680
  const callbacks = createInnerDialogCallbacks();
419
681
  const traceId = (0, nerves_1.createTraceId)();
682
+ // Attention queue: built when pending messages are drained, shared with tool context
683
+ let attentionQueue = [];
420
684
  const result = await (0, pipeline_1.handleInboundTurn)({
421
685
  channel: "inner",
422
686
  sessionKey: "dialog",
@@ -431,16 +695,55 @@ async function runInnerDialogTurn(options) {
431
695
  enforceTrustGate: trust_gate_1.enforceTrustGate,
432
696
  drainPending: pending_1.drainPending,
433
697
  runAgent: core_1.runAgent,
434
- postTurn: context_1.postTurn,
698
+ postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
699
+ const prepared = (0, context_1.postTurnTrim)(turnMessages, usage, hooks);
700
+ (0, context_1.deferPostTurnPersist)(sessionPathArg, prepared, usage, state);
701
+ },
435
702
  accumulateFriendTokens: tokens_1.accumulateFriendTokens,
436
703
  signal: options?.signal,
704
+ /* v8 ignore start -- attention queue: callback invoked by pipeline during pending drain; tested via attention-queue unit tests @preserve */
705
+ onPendingDrained: (drained) => {
706
+ const outstandingObligations = (0, obligations_1.listActiveReturnObligations)(agentName);
707
+ attentionQueue = (0, attention_queue_1.buildAttentionQueue)({
708
+ drainedPending: drained,
709
+ outstandingObligations,
710
+ friendNameResolver: (friendId) => {
711
+ try {
712
+ const raw = fs.readFileSync(path.join((0, identity_1.getAgentRoot)(agentName), "friends", friendId + ".json"), "utf-8");
713
+ const parsed = JSON.parse(raw);
714
+ return typeof parsed.name === "string" ? parsed.name : null;
715
+ }
716
+ catch {
717
+ return null;
718
+ }
719
+ },
720
+ packetResolver: (packetId) => {
721
+ try {
722
+ return (0, packets_1.readPonderPacket)((0, identity_1.getAgentRoot)(agentName), packetId);
723
+ }
724
+ catch {
725
+ return null;
726
+ }
727
+ },
728
+ });
729
+ const summary = (0, attention_queue_1.buildAttentionQueueSummary)(attentionQueue);
730
+ return summary ? [summary] : [];
731
+ },
732
+ /* v8 ignore stop */
437
733
  runAgentOptions: {
438
734
  traceId,
439
735
  toolChoiceRequired: true,
440
- skipConfirmation: true,
736
+ mcpManager,
737
+ ...(habitToolsResolved !== undefined && { tools: habitToolsResolved }),
738
+ toolContext: {
739
+ signin: async () => undefined,
740
+ delegatedOrigins: attentionQueue,
741
+ },
441
742
  },
442
743
  });
443
- await routeDelegatedCompletion(agentRoot, agentName, result.completion, result.drainedPending, now().getTime());
744
+ // Post-turn routeDelegatedCompletion removed: delivery is now inline via surface tool.
745
+ // settle in inner dialog produces no CompletionMetadata, so routeDelegatedCompletion
746
+ // would be a no-op. The routing infrastructure is reused by the surface handler.
444
747
  const resultMessages = result.messages ?? [];
445
748
  const assistantPreview = extractAssistantPreview(resultMessages);
446
749
  const toolCalls = extractToolCallNames(resultMessages);
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const agentArgIndex = process.argv.indexOf("--agent");
37
+ const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
38
+ if (!agentName) {
39
+ // eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
40
+ console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/mail-entry.js --agent ouroboros");
41
+ process.exit(1);
42
+ }
43
+ const runtime_logging_1 = require("../heart/daemon/runtime-logging");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ (0, runtime_logging_1.configureDaemonRuntimeLogger)("mail");
46
+ (0, runtime_1.emitNervesEvent)({
47
+ component: "senses",
48
+ event: "senses.entry_boot",
49
+ message: "booting Mail entrypoint",
50
+ meta: { entry: "mail", agentName },
51
+ });
52
+ Promise.resolve().then(() => __importStar(require("./mail"))).then(async ({ startMailSenseApp }) => {
53
+ await startMailSenseApp({ agentName });
54
+ })
55
+ .catch((error) => {
56
+ (0, runtime_1.emitNervesEvent)({
57
+ level: "error",
58
+ component: "senses",
59
+ event: "senses.entry_error",
60
+ message: "Mail entrypoint failed",
61
+ meta: { entry: "mail", agentName, error: error instanceof Error ? error.message : String(error) },
62
+ });
63
+ // eslint-disable-next-line no-console -- fatal startup guard for sense process
64
+ console.error(error instanceof Error ? error.message : String(error));
65
+ process.exit(1);
66
+ });