@ouro.bot/cli 0.1.0-alpha.55 → 0.1.0-alpha.551

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 (386) hide show
  1. package/README.md +133 -19
  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-bootstrap-drift.md +54 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/changelog.json +3561 -0
  14. package/dist/arc/attention-types.js +8 -0
  15. package/dist/arc/cares.js +140 -0
  16. package/dist/arc/episodes.js +117 -0
  17. package/dist/arc/intentions.js +133 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +237 -0
  20. package/dist/arc/packets.js +193 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +65 -0
  23. package/dist/heart/active-work.js +837 -26
  24. package/dist/heart/agent-entry.js +58 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -0
  29. package/dist/heart/attachments/sources/adapter.js +2 -0
  30. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  31. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  32. package/dist/heart/attachments/sources/index.js +16 -0
  33. package/dist/heart/attachments/store.js +103 -0
  34. package/dist/heart/attachments/types.js +93 -0
  35. package/dist/heart/auth/auth-flow.js +479 -0
  36. package/dist/heart/background-operations.js +281 -0
  37. package/dist/heart/bundle-state.js +168 -0
  38. package/dist/heart/commitments.js +111 -0
  39. package/dist/heart/config-registry.js +304 -0
  40. package/dist/heart/config.js +114 -118
  41. package/dist/heart/core.js +925 -246
  42. package/dist/heart/cross-chat-delivery.js +3 -18
  43. package/dist/heart/daemon/agent-config-check.js +512 -0
  44. package/dist/heart/daemon/agent-discovery.js +102 -3
  45. package/dist/heart/daemon/agent-service.js +522 -0
  46. package/dist/heart/daemon/agentic-repair.js +554 -0
  47. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  48. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  49. package/dist/heart/daemon/cadence.js +70 -0
  50. package/dist/heart/daemon/cli-defaults.js +665 -0
  51. package/dist/heart/daemon/cli-exec.js +7565 -0
  52. package/dist/heart/daemon/cli-help.js +498 -0
  53. package/dist/heart/daemon/cli-parse.js +1590 -0
  54. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  55. package/dist/heart/daemon/cli-render.js +775 -0
  56. package/dist/heart/daemon/cli-types.js +8 -0
  57. package/dist/heart/daemon/connect-bay.js +323 -0
  58. package/dist/heart/daemon/daemon-cli.js +29 -1672
  59. package/dist/heart/daemon/daemon-entry.js +417 -2
  60. package/dist/heart/daemon/daemon-health.js +183 -0
  61. package/dist/heart/daemon/daemon-rollup.js +58 -0
  62. package/dist/heart/daemon/daemon-runtime-sync.js +87 -13
  63. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  64. package/dist/heart/daemon/daemon.js +796 -71
  65. package/dist/heart/daemon/dns-workflow.js +394 -0
  66. package/dist/heart/daemon/doctor-types.js +8 -0
  67. package/dist/heart/daemon/doctor.js +844 -0
  68. package/dist/heart/daemon/drift-detection.js +146 -0
  69. package/dist/heart/daemon/health-monitor.js +122 -1
  70. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  71. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  72. package/dist/heart/daemon/http-health-probe.js +80 -0
  73. package/dist/heart/daemon/human-command-screens.js +234 -0
  74. package/dist/heart/daemon/human-readiness.js +114 -0
  75. package/dist/heart/daemon/inner-status.js +102 -0
  76. package/dist/heart/daemon/interactive-repair.js +394 -0
  77. package/dist/heart/daemon/launchd.js +37 -8
  78. package/dist/heart/daemon/log-tailer.js +82 -12
  79. package/dist/heart/daemon/logs-prune.js +110 -0
  80. package/dist/heart/daemon/mcp-canary.js +297 -0
  81. package/dist/heart/daemon/message-router.js +2 -2
  82. package/dist/heart/daemon/os-cron-deps.js +135 -0
  83. package/dist/heart/daemon/os-cron.js +14 -12
  84. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  85. package/dist/heart/daemon/ouro-entry.js +3 -1
  86. package/dist/heart/daemon/process-manager.js +375 -33
  87. package/dist/heart/daemon/provider-discovery.js +137 -0
  88. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  89. package/dist/heart/daemon/pulse.js +475 -0
  90. package/dist/heart/daemon/readiness-repair.js +365 -0
  91. package/dist/heart/daemon/run-hooks.js +2 -0
  92. package/dist/heart/daemon/runtime-logging.js +67 -16
  93. package/dist/heart/daemon/runtime-metadata.js +3 -31
  94. package/dist/heart/daemon/safe-mode.js +161 -0
  95. package/dist/heart/daemon/sense-manager.js +353 -38
  96. package/dist/heart/daemon/session-id-resolver.js +131 -0
  97. package/dist/heart/daemon/skill-management-installer.js +94 -0
  98. package/dist/heart/daemon/socket-client.js +158 -11
  99. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  100. package/dist/heart/daemon/startup-tui.js +330 -0
  101. package/dist/heart/daemon/task-scheduler.js +3 -25
  102. package/dist/heart/daemon/terminal-ui.js +499 -0
  103. package/dist/heart/daemon/thoughts.js +162 -17
  104. package/dist/heart/daemon/up-progress.js +366 -0
  105. package/dist/heart/daemon/vault-items.js +56 -0
  106. package/dist/heart/delegation.js +1 -1
  107. package/dist/heart/habits/habit-migration.js +189 -0
  108. package/dist/heart/habits/habit-parser.js +140 -0
  109. package/dist/heart/habits/habit-runtime-state.js +100 -0
  110. package/dist/heart/habits/habit-scheduler.js +372 -0
  111. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  112. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  113. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  114. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  115. package/dist/heart/identity.js +200 -51
  116. package/dist/heart/kept-notes.js +357 -0
  117. package/dist/heart/kicks.js +1 -1
  118. package/dist/heart/machine-identity.js +161 -0
  119. package/dist/heart/mail-import-discovery.js +353 -0
  120. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  121. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  122. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  123. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  124. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  125. package/dist/heart/mailbox/mailbox-http.js +99 -0
  126. package/dist/heart/mailbox/mailbox-read.js +31 -0
  127. package/dist/heart/mailbox/mailbox-types.js +27 -0
  128. package/dist/heart/mailbox/mailbox-view.js +195 -0
  129. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  130. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  131. package/dist/heart/mailbox/readers/mail.js +362 -0
  132. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  133. package/dist/heart/mailbox/readers/sessions.js +232 -0
  134. package/dist/heart/mailbox/readers/shared.js +111 -0
  135. package/dist/heart/mcp/mcp-server.js +683 -0
  136. package/dist/heart/migrate-config.js +100 -0
  137. package/dist/heart/model-capabilities.js +19 -0
  138. package/dist/heart/platform.js +81 -0
  139. package/dist/heart/provider-attempt.js +134 -0
  140. package/dist/heart/provider-binding-resolver.js +255 -0
  141. package/dist/heart/provider-credentials.js +425 -0
  142. package/dist/heart/provider-failover.js +301 -0
  143. package/dist/heart/provider-models.js +81 -0
  144. package/dist/heart/provider-ping.js +262 -0
  145. package/dist/heart/provider-state.js +216 -0
  146. package/dist/heart/provider-visibility.js +188 -0
  147. package/dist/heart/providers/anthropic-token.js +131 -0
  148. package/dist/heart/providers/anthropic.js +139 -52
  149. package/dist/heart/providers/azure.js +97 -13
  150. package/dist/heart/providers/error-classification.js +127 -0
  151. package/dist/heart/providers/github-copilot.js +145 -0
  152. package/dist/heart/providers/minimax-vlm.js +189 -0
  153. package/dist/heart/providers/minimax.js +26 -8
  154. package/dist/heart/providers/openai-codex.js +55 -40
  155. package/dist/heart/runtime-capability-check.js +170 -0
  156. package/dist/heart/runtime-credentials.js +367 -0
  157. package/dist/heart/runtime-cwd.js +87 -0
  158. package/dist/heart/sense-truth.js +11 -4
  159. package/dist/heart/session-activity.js +43 -22
  160. package/dist/heart/session-events.js +1149 -0
  161. package/dist/heart/session-playback-cli-main.js +5 -0
  162. package/dist/heart/session-playback-cli.js +36 -0
  163. package/dist/heart/session-playback.js +231 -0
  164. package/dist/heart/session-stats-cli-main.js +5 -0
  165. package/dist/heart/session-stats.js +182 -0
  166. package/dist/heart/session-transcript.js +243 -0
  167. package/dist/heart/start-of-turn-packet.js +345 -0
  168. package/dist/heart/streaming.js +44 -27
  169. package/dist/heart/sync-classification.js +176 -0
  170. package/dist/heart/sync.js +449 -0
  171. package/dist/heart/target-resolution.js +9 -5
  172. package/dist/heart/tempo.js +93 -0
  173. package/dist/heart/temporal-view.js +41 -0
  174. package/dist/heart/timeouts.js +101 -0
  175. package/dist/heart/tool-activity-callbacks.js +59 -0
  176. package/dist/heart/tool-description.js +139 -0
  177. package/dist/heart/tool-friction.js +55 -0
  178. package/dist/heart/tool-loop.js +200 -0
  179. package/dist/heart/turn-context.js +381 -0
  180. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  181. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  182. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  183. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  184. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  185. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  186. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  187. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  188. package/dist/mailbox-ui/assets/index-Cm51CY9W.js +61 -0
  189. package/dist/mailbox-ui/index.html +15 -0
  190. package/dist/mailroom/attention.js +167 -0
  191. package/dist/mailroom/autonomy.js +209 -0
  192. package/dist/mailroom/blob-store.js +674 -0
  193. package/dist/mailroom/body-cache.js +61 -0
  194. package/dist/mailroom/core.js +720 -0
  195. package/dist/mailroom/entry.js +160 -0
  196. package/dist/mailroom/file-store.js +430 -0
  197. package/dist/mailroom/mbox-import.js +383 -0
  198. package/dist/mailroom/outbound.js +380 -0
  199. package/dist/mailroom/policy.js +263 -0
  200. package/dist/mailroom/reader.js +233 -0
  201. package/dist/mailroom/search-cache.js +256 -0
  202. package/dist/mailroom/search-relevance.js +319 -0
  203. package/dist/mailroom/smtp-ingress.js +176 -0
  204. package/dist/mailroom/source-state.js +176 -0
  205. package/dist/mailroom/thread.js +109 -0
  206. package/dist/mailroom/travel-extract.js +89 -0
  207. package/dist/mind/bundle-manifest.js +7 -1
  208. package/dist/mind/context.js +165 -101
  209. package/dist/mind/diary-integrity.js +60 -0
  210. package/dist/mind/{memory.js → diary.js} +62 -75
  211. package/dist/mind/embedding-provider.js +60 -0
  212. package/dist/mind/file-state.js +179 -0
  213. package/dist/mind/friends/channel.js +30 -0
  214. package/dist/mind/friends/resolver.js +54 -2
  215. package/dist/mind/friends/store-file.js +39 -3
  216. package/dist/mind/friends/types.js +2 -2
  217. package/dist/mind/journal-index.js +161 -0
  218. package/dist/mind/note-search.js +268 -0
  219. package/dist/mind/obligation-steering.js +221 -0
  220. package/dist/mind/pending.js +4 -0
  221. package/dist/mind/prompt-refresh.js +3 -2
  222. package/dist/mind/prompt.js +995 -123
  223. package/dist/mind/provenance-trust.js +26 -0
  224. package/dist/mind/scrutiny.js +173 -0
  225. package/dist/nerves/cli-logging.js +7 -1
  226. package/dist/nerves/coverage/audit-rules.js +15 -6
  227. package/dist/nerves/coverage/audit.js +28 -2
  228. package/dist/nerves/coverage/cli.js +1 -1
  229. package/dist/nerves/coverage/contract.js +5 -5
  230. package/dist/nerves/coverage/file-completeness.js +139 -5
  231. package/dist/nerves/coverage/run-artifacts.js +1 -1
  232. package/dist/nerves/event-buffer.js +111 -0
  233. package/dist/nerves/index.js +224 -4
  234. package/dist/nerves/observation.js +20 -0
  235. package/dist/nerves/redact.js +79 -0
  236. package/dist/nerves/review/cli-main.js +5 -0
  237. package/dist/nerves/review/cli.js +156 -0
  238. package/dist/nerves/review/core.js +152 -0
  239. package/dist/nerves/runtime.js +5 -1
  240. package/dist/repertoire/ado-client.js +15 -56
  241. package/dist/repertoire/ado-semantic.js +11 -10
  242. package/dist/repertoire/api-client.js +97 -0
  243. package/dist/repertoire/bitwarden-store.js +816 -0
  244. package/dist/repertoire/bundle-templates.js +72 -0
  245. package/dist/repertoire/bw-installer.js +180 -0
  246. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  247. package/dist/repertoire/coding/context-pack.js +330 -0
  248. package/dist/repertoire/coding/feedback.js +197 -30
  249. package/dist/repertoire/coding/manager.js +158 -9
  250. package/dist/repertoire/coding/spawner.js +55 -9
  251. package/dist/repertoire/coding/tools.js +170 -7
  252. package/dist/repertoire/commerce-errors.js +109 -0
  253. package/dist/repertoire/commerce-self-test.js +156 -0
  254. package/dist/repertoire/credential-access.js +111 -0
  255. package/dist/repertoire/duffel-client.js +185 -0
  256. package/dist/repertoire/github-client.js +14 -55
  257. package/dist/repertoire/graph-client.js +11 -52
  258. package/dist/repertoire/guardrails.js +396 -0
  259. package/dist/repertoire/mcp-client.js +295 -0
  260. package/dist/repertoire/mcp-manager.js +362 -0
  261. package/dist/repertoire/mcp-tools.js +63 -0
  262. package/dist/repertoire/shell-sessions.js +133 -0
  263. package/dist/repertoire/skills.js +15 -24
  264. package/dist/repertoire/stripe-client.js +131 -0
  265. package/dist/repertoire/tasks/board.js +31 -5
  266. package/dist/repertoire/tasks/fix.js +182 -0
  267. package/dist/repertoire/tasks/index.js +16 -4
  268. package/dist/repertoire/tasks/lifecycle.js +2 -2
  269. package/dist/repertoire/tasks/parser.js +3 -2
  270. package/dist/repertoire/tasks/scanner.js +194 -37
  271. package/dist/repertoire/tasks/transitions.js +16 -78
  272. package/dist/repertoire/tool-results.js +29 -0
  273. package/dist/repertoire/tools-attachments.js +317 -0
  274. package/dist/repertoire/tools-base.js +47 -1075
  275. package/dist/repertoire/tools-bluebubbles.js +1 -0
  276. package/dist/repertoire/tools-bridge.js +142 -0
  277. package/dist/repertoire/tools-bundle.js +984 -0
  278. package/dist/repertoire/tools-config.js +185 -0
  279. package/dist/repertoire/tools-continuity.js +248 -0
  280. package/dist/repertoire/tools-credential.js +381 -0
  281. package/dist/repertoire/tools-files.js +342 -0
  282. package/dist/repertoire/tools-flight.js +224 -0
  283. package/dist/repertoire/tools-flow.js +119 -0
  284. package/dist/repertoire/tools-github.js +1 -7
  285. package/dist/repertoire/tools-mail.js +1857 -0
  286. package/dist/repertoire/tools-notes.js +421 -0
  287. package/dist/repertoire/tools-session.js +750 -0
  288. package/dist/repertoire/tools-shell.js +120 -0
  289. package/dist/repertoire/tools-stripe.js +180 -0
  290. package/dist/repertoire/tools-surface.js +243 -0
  291. package/dist/repertoire/tools-teams.js +9 -39
  292. package/dist/repertoire/tools-travel.js +125 -0
  293. package/dist/repertoire/tools-trip.js +604 -0
  294. package/dist/repertoire/tools-user-profile.js +144 -0
  295. package/dist/repertoire/tools-vault.js +40 -0
  296. package/dist/repertoire/tools.js +108 -100
  297. package/dist/repertoire/travel-api-client.js +360 -0
  298. package/dist/repertoire/user-profile.js +131 -0
  299. package/dist/repertoire/vault-setup.js +246 -0
  300. package/dist/repertoire/vault-unlock.js +561 -0
  301. package/dist/scripts/claude-code-hook.js +41 -0
  302. package/dist/scripts/claude-code-stop-hook.js +47 -0
  303. package/dist/senses/attention-queue.js +116 -0
  304. package/dist/senses/bluebubbles/active-turns.js +216 -0
  305. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  306. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  307. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  308. package/dist/senses/bluebubbles/entry.js +77 -0
  309. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  310. package/dist/senses/bluebubbles/index.js +2305 -0
  311. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  312. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  313. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  314. package/dist/senses/bluebubbles/processed-log.js +133 -0
  315. package/dist/senses/bluebubbles/replay.js +137 -0
  316. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  317. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +187 -0
  337. package/dist/senses/cli.js +520 -209
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +569 -182
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +248 -0
  347. package/dist/senses/surface-tool.js +68 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/trips/core.js +138 -0
  352. package/dist/trips/store.js +146 -0
  353. package/package.json +38 -7
  354. package/skills/agent-commerce.md +106 -0
  355. package/skills/browser-navigation.md +117 -0
  356. package/skills/commerce-setup-guide.md +116 -0
  357. package/skills/commerce-setup.md +84 -0
  358. package/skills/configure-dev-tools.md +101 -0
  359. package/skills/travel-planning.md +138 -0
  360. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  361. package/dist/heart/daemon/subagent-installer.js +0 -166
  362. package/dist/heart/session-recall.js +0 -116
  363. package/dist/mind/associative-recall.js +0 -209
  364. package/dist/senses/bluebubbles-entry.js +0 -13
  365. package/dist/senses/bluebubbles.js +0 -1177
  366. package/dist/senses/debug-activity.js +0 -148
  367. package/subagents/README.md +0 -86
  368. package/subagents/work-doer.md +0 -237
  369. package/subagents/work-merger.md +0 -618
  370. package/subagents/work-planner.md +0 -390
  371. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  372. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  373. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  374. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  375. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  376. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  377. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  378. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  379. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  380. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  381. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  382. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  383. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  384. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  385. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  386. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,651 @@
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.readCodingDeep = readCodingDeep;
37
+ exports.readAttentionView = readAttentionView;
38
+ exports.readBridgeInventory = readBridgeInventory;
39
+ exports.readDaemonHealthDeep = readDaemonHealthDeep;
40
+ exports.readNotesView = readNotesView;
41
+ exports.readFriendView = readFriendView;
42
+ exports.readLogView = readLogView;
43
+ exports.readHabitView = readHabitView;
44
+ exports.readNeedsMeView = readNeedsMeView;
45
+ exports.readDeskPrefs = readDeskPrefs;
46
+ const fs = __importStar(require("fs"));
47
+ const path = __importStar(require("path"));
48
+ const runtime_1 = require("../../../nerves/runtime");
49
+ const habit_parser_1 = require("../../habits/habit-parser");
50
+ const habit_runtime_state_1 = require("../../habits/habit-runtime-state");
51
+ const identity_1 = require("../../identity");
52
+ const daemon_health_1 = require("../../daemon/daemon-health");
53
+ const shared_1 = require("./shared");
54
+ const agent_machine_1 = require("./agent-machine");
55
+ const sessions_1 = require("./sessions");
56
+ /* v8 ignore start — defensive parsing of on-disk JSON, fallback branches are safety nets */
57
+ function readCodingDeep(agentRoot) {
58
+ const stateFilePath = path.join(agentRoot, "state", "coding", "sessions.json");
59
+ if (!fs.existsSync(stateFilePath)) {
60
+ return { totalCount: 0, activeCount: 0, blockedCount: 0, items: [] };
61
+ }
62
+ let parsed;
63
+ try {
64
+ parsed = JSON.parse(fs.readFileSync(stateFilePath, "utf-8"));
65
+ }
66
+ catch {
67
+ return { totalCount: 0, activeCount: 0, blockedCount: 0, items: [] };
68
+ }
69
+ const items = Array.isArray(parsed.records)
70
+ ? parsed.records.flatMap((record) => {
71
+ const s = record?.session;
72
+ if (!s || typeof s.id !== "string" || typeof s.status !== "string")
73
+ return [];
74
+ const checkpoint = typeof s.checkpoint === "string" ? s.checkpoint
75
+ : typeof s.stderrTail === "string" && s.stderrTail.trim().length > 0 ? s.stderrTail.trim()
76
+ : typeof s.stdoutTail === "string" && s.stdoutTail.trim().length > 0 ? s.stdoutTail.trim()
77
+ : null;
78
+ const originSession = s.originSession;
79
+ const normalizedOrigin = originSession
80
+ && typeof originSession.friendId === "string"
81
+ && typeof originSession.channel === "string"
82
+ && typeof originSession.key === "string"
83
+ ? { friendId: originSession.friendId, channel: originSession.channel, key: originSession.key }
84
+ : null;
85
+ const failure = s.failure;
86
+ const normalizedFailure = failure && typeof failure === "object"
87
+ ? {
88
+ command: typeof failure.command === "string" ? failure.command : "",
89
+ args: Array.isArray(failure.args) ? failure.args.map(String) : [],
90
+ code: typeof failure.code === "number" ? failure.code : null,
91
+ signal: typeof failure.signal === "string" ? failure.signal : null,
92
+ stdoutTail: typeof failure.stdoutTail === "string" ? failure.stdoutTail : "",
93
+ stderrTail: typeof failure.stderrTail === "string" ? failure.stderrTail : "",
94
+ }
95
+ : null;
96
+ return [{
97
+ id: s.id,
98
+ runner: (typeof s.runner === "string" ? s.runner : "claude"),
99
+ status: s.status,
100
+ checkpoint,
101
+ taskRef: typeof s.taskRef === "string" ? s.taskRef : null,
102
+ workdir: typeof s.workdir === "string" ? s.workdir : "",
103
+ originSession: normalizedOrigin,
104
+ obligationId: typeof s.obligationId === "string" ? s.obligationId : null,
105
+ scopeFile: typeof s.scopeFile === "string" ? s.scopeFile : null,
106
+ stateFile: typeof s.stateFile === "string" ? s.stateFile : null,
107
+ artifactPath: typeof s.artifactPath === "string" ? s.artifactPath : null,
108
+ pid: typeof s.pid === "number" ? s.pid : null,
109
+ startedAt: typeof s.startedAt === "string" ? s.startedAt : "",
110
+ lastActivityAt: typeof s.lastActivityAt === "string" ? s.lastActivityAt : "",
111
+ endedAt: typeof s.endedAt === "string" ? s.endedAt : null,
112
+ restartCount: typeof s.restartCount === "number" ? s.restartCount : 0,
113
+ lastExitCode: typeof s.lastExitCode === "number" ? s.lastExitCode : null,
114
+ lastSignal: typeof s.lastSignal === "string" ? s.lastSignal : null,
115
+ stdoutTail: typeof s.stdoutTail === "string" ? s.stdoutTail : "",
116
+ stderrTail: typeof s.stderrTail === "string" ? s.stderrTail : "",
117
+ failure: normalizedFailure,
118
+ }];
119
+ })
120
+ : [];
121
+ return {
122
+ totalCount: items.length,
123
+ activeCount: items.filter((item) => shared_1.ACTIVE_CODING_STATUSES.has(item.status)).length,
124
+ blockedCount: items.filter((item) => shared_1.BLOCKED_CODING_STATUSES.has(item.status)).length,
125
+ items,
126
+ };
127
+ }
128
+ /* v8 ignore stop */
129
+ function scanPendingChannels(agentRoot) {
130
+ const pendingRoot = path.join(agentRoot, "state", "pending");
131
+ const channels = [];
132
+ for (const friendId of (0, shared_1.safeReaddir)(pendingRoot)) {
133
+ if (friendId === "self")
134
+ continue;
135
+ const friendDir = path.join(pendingRoot, friendId);
136
+ if (!(0, shared_1.safeIsDirectory)(friendDir))
137
+ continue;
138
+ for (const channel of (0, shared_1.safeReaddir)(friendDir)) {
139
+ const channelDir = path.join(friendDir, channel);
140
+ if (!(0, shared_1.safeIsDirectory)(channelDir))
141
+ continue;
142
+ for (const key of (0, shared_1.safeReaddir)(channelDir)) {
143
+ const keyDir = path.join(channelDir, key);
144
+ if (!(0, shared_1.safeIsDirectory)(keyDir))
145
+ continue;
146
+ const files = (0, shared_1.safeReaddir)(keyDir).filter((f) => f.endsWith(".json") || f.endsWith(".json.processing"));
147
+ if (files.length > 0) {
148
+ channels.push({ friendId, channel, key, messageCount: files.length });
149
+ }
150
+ }
151
+ }
152
+ }
153
+ return channels;
154
+ }
155
+ function readPendingMessagesNonDestructive(pendingDir) {
156
+ const files = (0, shared_1.safeReaddir)(pendingDir).filter((f) => f.endsWith(".json") || f.endsWith(".json.processing"));
157
+ const messages = [];
158
+ for (const file of files.sort()) {
159
+ try {
160
+ const raw = fs.readFileSync(path.join(pendingDir, file), "utf-8");
161
+ messages.push(JSON.parse(raw));
162
+ }
163
+ catch {
164
+ // skip unparseable pending messages
165
+ }
166
+ }
167
+ return messages;
168
+ }
169
+ function readAttentionView(agentName, options = {}) {
170
+ const bundlesRoot = options.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
171
+ const agentRoot = path.join(bundlesRoot, `${agentName}.ouro`);
172
+ const friendsDir = path.join(agentRoot, "friends");
173
+ const pendingChannels = scanPendingChannels(agentRoot);
174
+ const queueItems = [];
175
+ const pendingRoot = path.join(agentRoot, "state", "pending");
176
+ for (const pending of pendingChannels) {
177
+ const pendingDir = path.join(pendingRoot, pending.friendId, pending.channel, pending.key);
178
+ const messages = readPendingMessagesNonDestructive(pendingDir);
179
+ for (const msg of messages) {
180
+ const delegatedFrom = msg.delegatedFrom;
181
+ queueItems.push({
182
+ id: typeof msg.timestamp === "number" ? `${msg.timestamp}-${pending.friendId}` : `pending-${Date.now()}`,
183
+ friendId: pending.friendId,
184
+ friendName: (0, shared_1.resolveFriendName)(friendsDir, pending.friendId),
185
+ channel: pending.channel,
186
+ key: pending.key,
187
+ bridgeId: delegatedFrom && typeof delegatedFrom.bridgeId === "string" ? delegatedFrom.bridgeId : null,
188
+ delegatedContent: typeof msg.content === "string" ? msg.content : "",
189
+ obligationId: typeof msg.obligationId === "string" ? msg.obligationId : null,
190
+ source: "pending",
191
+ timestamp: typeof msg.timestamp === "number" ? msg.timestamp : 0,
192
+ });
193
+ }
194
+ }
195
+ queueItems.sort((a, b) => a.timestamp - b.timestamp);
196
+ const returnObligations = (0, agent_machine_1.readObligationSummary)(agentRoot).items;
197
+ (0, runtime_1.emitNervesEvent)({
198
+ component: "heart",
199
+ event: "heart.mailbox_attention_read",
200
+ message: "reading mailbox attention queue",
201
+ meta: { agentName, queueLength: queueItems.length, pendingChannelCount: pendingChannels.length },
202
+ });
203
+ return {
204
+ queueLength: queueItems.length,
205
+ queueItems,
206
+ pendingChannels,
207
+ returnObligations,
208
+ };
209
+ }
210
+ /* v8 ignore start — defensive parsing */
211
+ function readBridgeInventory(agentRoot) {
212
+ const bridgesDir = path.join(agentRoot, "state", "bridges");
213
+ const items = [];
214
+ for (const file of (0, shared_1.safeReaddir)(bridgesDir)) {
215
+ if (!file.endsWith(".json"))
216
+ continue;
217
+ try {
218
+ const raw = fs.readFileSync(path.join(bridgesDir, file), "utf-8");
219
+ const bridge = JSON.parse(raw);
220
+ if (typeof bridge.id !== "string")
221
+ continue;
222
+ const attachedSessions = Array.isArray(bridge.attachedSessions)
223
+ ? bridge.attachedSessions
224
+ .filter((s) => typeof s.friendId === "string")
225
+ .map((s) => ({
226
+ friendId: s.friendId,
227
+ channel: typeof s.channel === "string" ? s.channel : "",
228
+ key: typeof s.key === "string" ? s.key : "",
229
+ sessionPath: typeof s.sessionPath === "string" ? s.sessionPath : "",
230
+ snapshot: typeof s.snapshot === "string" ? s.snapshot : null,
231
+ }))
232
+ : [];
233
+ const taskLink = bridge.task;
234
+ const normalizedTask = taskLink && typeof taskLink === "object" && typeof taskLink.taskName === "string"
235
+ ? {
236
+ taskName: taskLink.taskName,
237
+ path: typeof taskLink.path === "string" ? taskLink.path : "",
238
+ mode: typeof taskLink.mode === "string" ? taskLink.mode : "bound",
239
+ boundAt: typeof taskLink.boundAt === "string" ? taskLink.boundAt : "",
240
+ }
241
+ : null;
242
+ items.push({
243
+ id: bridge.id,
244
+ objective: typeof bridge.objective === "string" ? bridge.objective : "",
245
+ summary: typeof bridge.summary === "string" ? bridge.summary : "",
246
+ lifecycle: typeof bridge.lifecycle === "string" ? bridge.lifecycle : "unknown",
247
+ runtime: typeof bridge.runtime === "string" ? bridge.runtime : "unknown",
248
+ createdAt: typeof bridge.createdAt === "string" ? bridge.createdAt : "",
249
+ updatedAt: typeof bridge.updatedAt === "string" ? bridge.updatedAt : "",
250
+ attachedSessions,
251
+ task: normalizedTask,
252
+ });
253
+ }
254
+ catch {
255
+ // skip unparseable bridge files
256
+ }
257
+ }
258
+ items.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
259
+ const activeCount = items.filter((item) => item.lifecycle === "active").length;
260
+ return {
261
+ totalCount: items.length,
262
+ activeCount,
263
+ items,
264
+ };
265
+ }
266
+ /* v8 ignore stop */
267
+ /* v8 ignore start — defensive parsing */
268
+ function readDaemonHealthDeep(healthPath) {
269
+ const resolvedPath = healthPath ?? path.join(process.env.HOME ?? "", ".ouro-cli", "daemon-health.json");
270
+ try {
271
+ const raw = fs.readFileSync(resolvedPath, "utf-8");
272
+ const health = JSON.parse(raw);
273
+ return {
274
+ // Layer 1: tighten the parse so only post-Layer-1 vocabulary
275
+ // carries through. Stale cached files that still hold legacy
276
+ // string values like "ok" or "running" — written by an older
277
+ // daemon binary — fall back to "unknown" so downstream Mailbox
278
+ // consumers can detect the unparseable case explicitly.
279
+ status: (0, daemon_health_1.isDaemonStatus)(health.status) ? health.status : "unknown",
280
+ mode: typeof health.mode === "string" ? health.mode : "unknown",
281
+ pid: typeof health.pid === "number" ? health.pid : 0,
282
+ startedAt: typeof health.startedAt === "string" ? health.startedAt : "",
283
+ uptimeSeconds: typeof health.uptimeSeconds === "number" ? health.uptimeSeconds : 0,
284
+ safeMode: health.safeMode && typeof health.safeMode === "object"
285
+ ? {
286
+ active: health.safeMode.active === true,
287
+ reason: typeof health.safeMode.reason === "string" ? health.safeMode.reason : "",
288
+ enteredAt: typeof health.safeMode.enteredAt === "string" ? health.safeMode.enteredAt : "",
289
+ }
290
+ : null,
291
+ degradedComponents: Array.isArray(health.degraded)
292
+ ? health.degraded.map((c) => ({
293
+ component: typeof c.component === "string" ? c.component : "",
294
+ reason: typeof c.reason === "string" ? c.reason : "",
295
+ since: typeof c.since === "string" ? c.since : "",
296
+ }))
297
+ : [],
298
+ agentHealth: health.agents && typeof health.agents === "object"
299
+ ? Object.fromEntries(Object.entries(health.agents).map(([name, entry]) => [
300
+ name,
301
+ {
302
+ status: typeof entry.status === "string" ? entry.status : "unknown",
303
+ pid: typeof entry.pid === "number" ? entry.pid : null,
304
+ crashes: typeof entry.crashes === "number" ? entry.crashes : 0,
305
+ },
306
+ ]))
307
+ : {},
308
+ habitHealth: health.habits && typeof health.habits === "object"
309
+ ? Object.fromEntries(Object.entries(health.habits).map(([name, entry]) => [
310
+ name,
311
+ {
312
+ cronStatus: typeof entry.cronStatus === "string" ? entry.cronStatus : "unknown",
313
+ lastFired: typeof entry.lastFired === "string" ? entry.lastFired : null,
314
+ fallback: entry.fallback === true,
315
+ },
316
+ ]))
317
+ : {},
318
+ };
319
+ }
320
+ catch {
321
+ return null;
322
+ }
323
+ }
324
+ /* v8 ignore stop */
325
+ function readNotesView(agentRoot) {
326
+ const diaryRoot = path.join(agentRoot, "diary");
327
+ const effectiveDiaryRoot = fs.existsSync(diaryRoot) ? diaryRoot : null;
328
+ const diaryEntries = [];
329
+ if (effectiveDiaryRoot) {
330
+ const factsPath = path.join(effectiveDiaryRoot, "facts.jsonl");
331
+ try {
332
+ const raw = fs.readFileSync(factsPath, "utf-8");
333
+ for (const line of raw.split("\n")) {
334
+ if (!line.trim())
335
+ continue;
336
+ try {
337
+ const entry = JSON.parse(line);
338
+ if (typeof entry.id === "string" && typeof entry.text === "string") {
339
+ diaryEntries.push({
340
+ id: entry.id,
341
+ text: entry.text,
342
+ source: typeof entry.source === "string" ? entry.source : "",
343
+ createdAt: typeof entry.createdAt === "string" ? entry.createdAt : "",
344
+ });
345
+ }
346
+ }
347
+ catch {
348
+ // skip unparseable lines
349
+ }
350
+ }
351
+ }
352
+ catch {
353
+ // no diary facts file
354
+ }
355
+ }
356
+ diaryEntries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
357
+ const journalDir = path.join(agentRoot, "journal");
358
+ const journalEntries = [];
359
+ const indexPath = path.join(journalDir, ".index.json");
360
+ try {
361
+ const raw = fs.readFileSync(indexPath, "utf-8");
362
+ const index = JSON.parse(raw);
363
+ if (Array.isArray(index)) {
364
+ for (const entry of index) {
365
+ if (typeof entry.filename === "string") {
366
+ journalEntries.push({
367
+ filename: entry.filename,
368
+ preview: typeof entry.preview === "string" ? entry.preview : "",
369
+ mtime: typeof entry.mtime === "number" ? entry.mtime : 0,
370
+ });
371
+ }
372
+ }
373
+ }
374
+ }
375
+ catch {
376
+ // no journal index
377
+ }
378
+ journalEntries.sort((a, b) => b.mtime - a.mtime);
379
+ return {
380
+ diaryEntryCount: diaryEntries.length,
381
+ recentDiaryEntries: diaryEntries.slice(0, 20),
382
+ journalEntryCount: journalEntries.length,
383
+ recentJournalEntries: journalEntries.slice(0, 20),
384
+ };
385
+ }
386
+ function readFriendView(agentName, options = {}) {
387
+ const bundlesRoot = options.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
388
+ const agentRoot = path.join(bundlesRoot, `${agentName}.ouro`);
389
+ const friendsDir = path.join(agentRoot, "friends");
390
+ const sessionsDir = path.join(agentRoot, "state", "sessions");
391
+ const friends = [];
392
+ for (const file of (0, shared_1.safeReaddir)(friendsDir)) {
393
+ if (!file.endsWith(".json"))
394
+ continue;
395
+ const friendId = file.slice(0, -5);
396
+ try {
397
+ const raw = fs.readFileSync(path.join(friendsDir, file), "utf-8");
398
+ const record = JSON.parse(raw);
399
+ const friendSessionsDir = path.join(sessionsDir, friendId);
400
+ const channels = new Set();
401
+ let sessionCount = 0;
402
+ let latestActivity = null;
403
+ for (const channel of (0, shared_1.safeReaddir)(friendSessionsDir)) {
404
+ const channelDir = path.join(friendSessionsDir, channel);
405
+ if (!(0, shared_1.safeIsDirectory)(channelDir))
406
+ continue;
407
+ for (const keyFile of (0, shared_1.safeReaddir)(channelDir)) {
408
+ if (!keyFile.endsWith(".json"))
409
+ continue;
410
+ channels.add(channel);
411
+ sessionCount++;
412
+ const mtime = (0, shared_1.safeFileMtime)(path.join(channelDir, keyFile));
413
+ if (mtime && (!latestActivity || mtime > latestActivity)) {
414
+ latestActivity = mtime;
415
+ }
416
+ }
417
+ }
418
+ friends.push({
419
+ friendId,
420
+ friendName: typeof record.name === "string" ? record.name : friendId,
421
+ totalTokens: typeof record.totalTokens === "number" ? record.totalTokens : 0,
422
+ sessionCount,
423
+ channels: [...channels].sort(),
424
+ lastActivityAt: latestActivity,
425
+ });
426
+ }
427
+ catch {
428
+ // skip unparseable friend records
429
+ }
430
+ }
431
+ friends.sort((a, b) => b.totalTokens - a.totalTokens);
432
+ return {
433
+ totalFriends: friends.length,
434
+ friends,
435
+ };
436
+ }
437
+ function readLogView(logPath, limit = 100) {
438
+ if (!logPath || !fs.existsSync(logPath)) {
439
+ return { logPath, totalLines: 0, entries: [] };
440
+ }
441
+ try {
442
+ const raw = fs.readFileSync(logPath, "utf-8");
443
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
444
+ const totalLines = lines.length;
445
+ const recentLines = lines.slice(-limit);
446
+ const entries = [];
447
+ for (const line of recentLines) {
448
+ try {
449
+ const parsed = JSON.parse(line);
450
+ entries.push({
451
+ ts: typeof parsed.ts === "string" ? parsed.ts : "",
452
+ level: typeof parsed.level === "string" ? parsed.level : "info",
453
+ event: typeof parsed.event === "string" ? parsed.event : "",
454
+ component: typeof parsed.component === "string" ? parsed.component : "",
455
+ message: typeof parsed.message === "string" ? parsed.message : "",
456
+ trace_id: typeof parsed.trace_id === "string" ? parsed.trace_id : "",
457
+ meta: parsed.meta && typeof parsed.meta === "object" ? parsed.meta : {},
458
+ });
459
+ }
460
+ catch {
461
+ // skip unparseable log lines
462
+ }
463
+ }
464
+ return { logPath, totalLines, entries };
465
+ }
466
+ catch { /* v8 ignore next */
467
+ return { logPath, totalLines: 0, entries: [] };
468
+ }
469
+ }
470
+ function readHabitView(agentRoot, options = {}) {
471
+ const habitsDir = path.join(agentRoot, "habits");
472
+ const now = options.now?.() ?? new Date();
473
+ const items = [];
474
+ for (const file of (0, shared_1.safeReaddir)(habitsDir)) {
475
+ if (!file.endsWith(".md"))
476
+ continue;
477
+ try {
478
+ const filePath = path.join(habitsDir, file);
479
+ const raw = fs.readFileSync(filePath, "utf-8");
480
+ if (!/^---\r?\n[\s\S]*?\r?\n---/.test(raw))
481
+ continue;
482
+ const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(raw, filePath));
483
+ const cadenceMs = parseCadenceMs(habit.cadence);
484
+ let isOverdue = false;
485
+ let overdueMs = null;
486
+ if (habit.status === "active" && habit.lastRun && cadenceMs) {
487
+ const elapsed = now.getTime() - Date.parse(habit.lastRun);
488
+ if (elapsed > cadenceMs) {
489
+ isOverdue = true;
490
+ overdueMs = elapsed - cadenceMs;
491
+ }
492
+ }
493
+ items.push({
494
+ name: habit.name,
495
+ title: habit.title,
496
+ cadence: habit.cadence,
497
+ status: habit.status,
498
+ lastRun: habit.lastRun,
499
+ bodyExcerpt: (0, shared_1.truncateExcerpt)(habit.body, 120),
500
+ isDegraded: false,
501
+ degradedReason: null,
502
+ isOverdue,
503
+ overdueMs,
504
+ });
505
+ }
506
+ catch {
507
+ // skip unparseable habit files
508
+ }
509
+ }
510
+ items.sort((a, b) => {
511
+ if (a.isOverdue && !b.isOverdue)
512
+ return -1;
513
+ if (!a.isOverdue && b.isOverdue)
514
+ return 1;
515
+ return a.name.localeCompare(b.name);
516
+ });
517
+ return {
518
+ totalCount: items.length,
519
+ activeCount: items.filter((h) => h.status === "active").length,
520
+ pausedCount: items.filter((h) => h.status === "paused").length,
521
+ degradedCount: items.filter((h) => h.isDegraded).length,
522
+ overdueCount: items.filter((h) => h.isOverdue).length,
523
+ items,
524
+ };
525
+ }
526
+ function readNeedsMeView(agentName, options = {}) {
527
+ const bundlesRoot = options.bundlesRoot ?? (0, identity_1.getAgentBundlesRoot)();
528
+ const now = options.now?.() ?? new Date();
529
+ const agentRoot = path.join(bundlesRoot, `${agentName}.ouro`);
530
+ const items = [];
531
+ const prefs = readDeskPrefs(agentRoot);
532
+ const dismissed = new Set(prefs.dismissedObligations);
533
+ const sessions = (0, sessions_1.readSessionInventory)(agentName, options);
534
+ for (const s of sessions.items) {
535
+ if (s.replyState === "needs-reply") {
536
+ items.push({
537
+ urgency: "owed-reply",
538
+ label: `${s.friendName} is waiting for a reply`,
539
+ detail: `via ${s.channel} · ${s.latestUserExcerpt ? (0, shared_1.truncateExcerpt)(s.latestUserExcerpt, 80) : ""}`,
540
+ ref: { tab: "sessions", focus: `${s.friendId}/${s.channel}/${s.key}` },
541
+ ageMs: now.getTime() - Date.parse(s.lastActivityAt),
542
+ });
543
+ }
544
+ }
545
+ const obligations = (0, agent_machine_1.readObligationSummary)(agentRoot);
546
+ for (const o of obligations.items) {
547
+ if (dismissed.has(o.id))
548
+ continue;
549
+ const ageMs = now.getTime() - Date.parse(o.updatedAt);
550
+ const isStale = ageMs > 24 * 60 * 60 * 1000;
551
+ const hasResult = o.currentSurface !== null;
552
+ const isOpen = o.status === "pending" || o.status === "investigating" || o.status === "waiting_for_merge" || o.status === "updating_runtime";
553
+ if (isOpen) {
554
+ items.push({
555
+ urgency: hasResult ? "return-ready" : isStale ? "stale-delegation" : "blocking-obligation",
556
+ label: (0, shared_1.truncateExcerpt)(o.content, 80) ?? o.id,
557
+ detail: hasResult ? `result ready — ${o.currentSurface.kind}: ${o.currentSurface.label}` : `${o.status}${o.nextAction ? ` · next: ${o.nextAction}` : ""}`,
558
+ ref: { tab: "work", focus: o.id },
559
+ ageMs,
560
+ });
561
+ }
562
+ }
563
+ const pendingChannels = scanPendingChannels(agentRoot);
564
+ for (const p of pendingChannels) {
565
+ const friendName = (0, shared_1.resolveFriendName)(path.join(agentRoot, "friends"), p.friendId);
566
+ items.push({
567
+ urgency: "stale-delegation",
568
+ label: `${p.messageCount} pending from ${friendName}`,
569
+ detail: `${p.channel}/${p.key}`,
570
+ ref: { tab: "connections" },
571
+ ageMs: null,
572
+ });
573
+ }
574
+ const habits = readHabitView(agentRoot, options);
575
+ for (const h of habits.items) {
576
+ if (h.isOverdue) {
577
+ items.push({
578
+ urgency: "overdue-habit",
579
+ label: `${h.title} is overdue`,
580
+ detail: `every ${h.cadence} · last ${h.lastRun}`,
581
+ ref: { tab: "inner" },
582
+ ageMs: h.overdueMs,
583
+ });
584
+ }
585
+ }
586
+ const urgencyOrder = {
587
+ "owed-reply": 0,
588
+ "blocking-obligation": 1,
589
+ "broken-return": 2,
590
+ "stale-delegation": 3,
591
+ "return-ready": 4,
592
+ "overdue-habit": 5,
593
+ };
594
+ items.sort((a, b) => urgencyOrder[a.urgency] - urgencyOrder[b.urgency]);
595
+ return { items };
596
+ }
597
+ /* v8 ignore start — defensive JSON parsing in desk prefs reader */
598
+ function readDeskPrefs(agentRoot) {
599
+ const prefsPath = path.join(agentRoot, "state", "mailbox-prefs.json");
600
+ const legacyPrefsPath = path.join(agentRoot, "state", "outlook-prefs.json");
601
+ const defaults = {
602
+ carrying: null,
603
+ statusLine: null,
604
+ tabOrder: null,
605
+ starredFriends: [],
606
+ pinnedConstellations: [],
607
+ dismissedObligations: [],
608
+ };
609
+ try {
610
+ const raw = fs.readFileSync(fs.existsSync(prefsPath) ? prefsPath : legacyPrefsPath, "utf-8");
611
+ const parsed = JSON.parse(raw);
612
+ return {
613
+ carrying: typeof parsed.carrying === "string" ? parsed.carrying : null,
614
+ statusLine: typeof parsed.statusLine === "string" ? parsed.statusLine : null,
615
+ tabOrder: Array.isArray(parsed.tabOrder) ? parsed.tabOrder.filter((t) => typeof t === "string") : null,
616
+ starredFriends: Array.isArray(parsed.starredFriends) ? parsed.starredFriends.filter((f) => typeof f === "string") : [],
617
+ pinnedConstellations: Array.isArray(parsed.pinnedConstellations)
618
+ ? parsed.pinnedConstellations.map((c) => ({
619
+ label: typeof c.label === "string" ? c.label : "",
620
+ friendIds: Array.isArray(c.friendIds) ? c.friendIds.filter((f) => typeof f === "string") : [],
621
+ taskRefs: Array.isArray(c.taskRefs) ? c.taskRefs.filter((t) => typeof t === "string") : [],
622
+ bridgeIds: Array.isArray(c.bridgeIds) ? c.bridgeIds.filter((b) => typeof b === "string") : [],
623
+ codingIds: Array.isArray(c.codingIds) ? c.codingIds.filter((c2) => typeof c2 === "string") : [],
624
+ }))
625
+ : [],
626
+ dismissedObligations: Array.isArray(parsed.dismissedObligations) ? parsed.dismissedObligations.filter((id) => typeof id === "string") : [],
627
+ };
628
+ }
629
+ catch {
630
+ return defaults;
631
+ }
632
+ }
633
+ /* v8 ignore stop */
634
+ function parseCadenceMs(cadence) {
635
+ if (!cadence)
636
+ return null;
637
+ const match = /^(\d+)\s*(m|min|h|hr|d|day)s?$/i.exec(cadence.trim());
638
+ if (!match)
639
+ return null;
640
+ const value = parseInt(match[1], 10);
641
+ const multipliers = {
642
+ m: 60 * 1000,
643
+ min: 60 * 1000,
644
+ h: 60 * 60 * 1000,
645
+ hr: 60 * 60 * 1000,
646
+ d: 24 * 60 * 60 * 1000,
647
+ day: 24 * 60 * 60 * 1000,
648
+ };
649
+ const unit = match[2].toLowerCase();
650
+ return value * multipliers[unit];
651
+ }