@ouro.bot/cli 0.1.0-alpha.45 → 0.1.0-alpha.450

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