@ouro.bot/cli 0.1.0-alpha.44 → 0.1.0-alpha.441

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 +2789 -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 +439 -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 +214 -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 +626 -0
  44. package/dist/heart/daemon/cli-exec.js +5646 -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 +457 -0
  51. package/dist/heart/daemon/daemon-cli.js +28 -1582
  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 +175 -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 +236 -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 +307 -0
  67. package/dist/heart/daemon/launchd.js +46 -9
  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 +76 -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 +145 -32
  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 +272 -0
  90. package/dist/heart/daemon/task-scheduler.js +3 -25
  91. package/dist/heart/daemon/terminal-ui.js +224 -0
  92. package/dist/heart/daemon/thoughts.js +510 -0
  93. package/dist/heart/daemon/up-progress.js +313 -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 +239 -0
  128. package/dist/heart/provider-credentials.js +400 -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 +239 -0
  132. package/dist/heart/provider-state.js +216 -0
  133. package/dist/heart/provider-visibility.js +186 -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 +733 -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} +260 -9
  267. package/dist/senses/bluebubbles/entry.js +73 -0
  268. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  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} +45 -3
  273. package/dist/senses/bluebubbles/replay.js +129 -0
  274. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  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 -11
  318. package/dist/senses/bluebubbles.js +0 -854
  319. package/dist/senses/debug-activity.js +0 -127
  320. package/subagents/README.md +0 -86
  321. package/subagents/work-doer.md +0 -235
  322. package/subagents/work-merger.md +0 -618
  323. package/subagents/work-planner.md +0 -382
  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
@@ -37,6 +37,115 @@ exports.bundleMetaHook = bundleMetaHook;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  const runtime_1 = require("../../../nerves/runtime");
40
+ /**
41
+ * Migrate bundle from schema 1 to schema 2:
42
+ * - Move state/{episodes,obligations,cares,intentions}/* to arc/{name}/*
43
+ * - Move the old psyche note store to diary/
44
+ * Idempotent: skips missing sources; on collision, newer mtime wins.
45
+ */
46
+ function migrateToSchema2(agentRoot) {
47
+ (0, runtime_1.emitNervesEvent)({
48
+ component: "daemon",
49
+ event: "daemon.bundle_migration_start",
50
+ message: "migrating bundle to schema 2",
51
+ meta: { agentRoot },
52
+ });
53
+ // Migrate arc entities
54
+ for (const name of ["episodes", "obligations", "cares", "intentions"]) {
55
+ const src = path.join(agentRoot, "state", name);
56
+ const dest = path.join(agentRoot, "arc", name);
57
+ migrateDirectory(src, dest);
58
+ }
59
+ // Migrate diary from the old pre-diary bundle layout.
60
+ const legacyDiarySrc = path.join(agentRoot, "psyche", "mem" + "ory");
61
+ const diaryDest = path.join(agentRoot, "diary");
62
+ migrateDirectory(legacyDiarySrc, diaryDest);
63
+ // Update bundle .gitignore
64
+ updateBundleGitignore(agentRoot);
65
+ (0, runtime_1.emitNervesEvent)({
66
+ component: "daemon",
67
+ event: "daemon.bundle_migration_end",
68
+ message: "bundle migration to schema 2 complete",
69
+ meta: { agentRoot },
70
+ });
71
+ }
72
+ /**
73
+ * Ensure bundle .gitignore has state/ ignored and does NOT ignore arc/, diary/, journal/.
74
+ */
75
+ function updateBundleGitignore(agentRoot) {
76
+ const gitignorePath = path.join(agentRoot, ".gitignore");
77
+ let lines = [];
78
+ try {
79
+ if (fs.existsSync(gitignorePath)) {
80
+ lines = fs.readFileSync(gitignorePath, "utf-8").split("\n");
81
+ }
82
+ }
83
+ catch {
84
+ // If we can't read, start fresh
85
+ }
86
+ // Remove arc/, diary/, journal/ from ignore (they should be tracked)
87
+ const toRemove = new Set(["arc/", "diary/", "journal/"]);
88
+ lines = lines.filter((line) => !toRemove.has(line.trim()));
89
+ // Ensure state/ is in the ignore list
90
+ const hasState = lines.some((line) => line.trim() === "state/");
91
+ if (!hasState) {
92
+ lines.push("state/");
93
+ }
94
+ // Write back, trimming trailing empty lines and ensuring trailing newline
95
+ const content = lines.join("\n").replace(/\n+$/, "") + "\n";
96
+ try {
97
+ fs.writeFileSync(gitignorePath, content, "utf-8");
98
+ }
99
+ catch {
100
+ // Non-blocking: if we can't write .gitignore, migration still succeeds
101
+ }
102
+ }
103
+ /**
104
+ * Recursively copy files from src to dest.
105
+ * Creates destination directories as needed. Skips if source doesn't exist.
106
+ * When both source and destination exist, compares mtimes: newer file wins.
107
+ * Logs a warning either way when a collision is detected.
108
+ */
109
+ function migrateDirectory(src, dest) {
110
+ if (!fs.existsSync(src))
111
+ return;
112
+ fs.mkdirSync(dest, { recursive: true });
113
+ const entries = fs.readdirSync(src, { withFileTypes: true });
114
+ for (const entry of entries) {
115
+ const srcPath = path.join(src, entry.name);
116
+ const destPath = path.join(dest, entry.name);
117
+ if (entry.isDirectory()) {
118
+ migrateDirectory(srcPath, destPath);
119
+ }
120
+ else if (!fs.existsSync(destPath)) {
121
+ fs.copyFileSync(srcPath, destPath);
122
+ }
123
+ else {
124
+ // Collision: both source and destination exist — compare mtimes
125
+ const srcMtime = fs.statSync(srcPath).mtimeMs;
126
+ const destMtime = fs.statSync(destPath).mtimeMs;
127
+ if (srcMtime > destMtime) {
128
+ fs.copyFileSync(srcPath, destPath);
129
+ (0, runtime_1.emitNervesEvent)({
130
+ level: "warn",
131
+ component: "daemon",
132
+ event: "daemon.bundle_migration_collision",
133
+ message: `migration collision: source newer, overwriting destination`,
134
+ meta: { srcPath, destPath, srcMtime, destMtime },
135
+ });
136
+ }
137
+ else {
138
+ (0, runtime_1.emitNervesEvent)({
139
+ level: "warn",
140
+ component: "daemon",
141
+ event: "daemon.bundle_migration_collision",
142
+ message: `migration collision: destination newer or equal, keeping destination`,
143
+ meta: { srcPath, destPath, srcMtime, destMtime },
144
+ });
145
+ }
146
+ }
147
+ }
148
+ }
40
149
  async function bundleMetaHook(ctx) {
41
150
  (0, runtime_1.emitNervesEvent)({
42
151
  component: "daemon",
@@ -56,9 +165,14 @@ async function bundleMetaHook(ctx) {
56
165
  // Malformed JSON -- treat as missing, will overwrite with fresh
57
166
  existing = undefined;
58
167
  }
168
+ // Run schema-2 migration if needed
169
+ const currentSchema = existing?.bundleSchemaVersion ?? 1;
170
+ if (currentSchema < 2) {
171
+ migrateToSchema2(ctx.agentRoot);
172
+ }
59
173
  const updated = {
60
174
  runtimeVersion: ctx.currentVersion,
61
- bundleSchemaVersion: existing?.bundleSchemaVersion ?? 1,
175
+ bundleSchemaVersion: currentSchema < 2 ? 2 : currentSchema,
62
176
  lastUpdated: new Date().toISOString(),
63
177
  };
64
178
  // Save old runtimeVersion as previousRuntimeVersion (if there was one)
@@ -0,0 +1,80 @@
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.createHttpHealthProbe = createHttpHealthProbe;
37
+ const http = __importStar(require("node:http"));
38
+ function createHttpHealthProbe(name, port, timeoutMs = 5000) {
39
+ return {
40
+ name,
41
+ check: () => new Promise((resolve) => {
42
+ const req = http.get({
43
+ hostname: "127.0.0.1",
44
+ port,
45
+ path: "/health",
46
+ timeout: timeoutMs,
47
+ }, (res) => {
48
+ let body = "";
49
+ res.on("data", (chunk) => {
50
+ body += chunk.toString();
51
+ });
52
+ res.on("end", () => {
53
+ if (res.statusCode !== 200) {
54
+ resolve({ ok: false, detail: `HTTP ${res.statusCode}` });
55
+ return;
56
+ }
57
+ try {
58
+ const parsed = JSON.parse(body);
59
+ if (parsed.status === "ok") {
60
+ resolve({ ok: true });
61
+ }
62
+ else {
63
+ resolve({ ok: false, detail: `unexpected status: ${String(parsed.status)}` });
64
+ }
65
+ }
66
+ catch {
67
+ resolve({ ok: false, detail: "invalid JSON response" });
68
+ }
69
+ });
70
+ });
71
+ req.on("timeout", () => {
72
+ req.destroy();
73
+ resolve({ ok: false, detail: "timeout" });
74
+ });
75
+ req.on("error", (err) => {
76
+ resolve({ ok: false, detail: err.message });
77
+ });
78
+ }),
79
+ };
80
+ }
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildOuroHomeActions = buildOuroHomeActions;
4
+ exports.resolveOuroHomeAction = resolveOuroHomeAction;
5
+ exports.renderOuroHomeScreen = renderOuroHomeScreen;
6
+ exports.renderAgentPickerScreen = renderAgentPickerScreen;
7
+ exports.resolveNamedAgentSelection = resolveNamedAgentSelection;
8
+ exports.renderHumanReadinessBoard = renderHumanReadinessBoard;
9
+ exports.renderHumanCommandBoard = renderHumanCommandBoard;
10
+ exports.renderHouseStatusScreen = renderHouseStatusScreen;
11
+ const runtime_1 = require("../../nerves/runtime");
12
+ const terminal_ui_1 = require("./terminal-ui");
13
+ function renderScreenEvent(screen) {
14
+ (0, runtime_1.emitNervesEvent)({
15
+ component: "daemon",
16
+ event: "daemon.human_screen_rendered",
17
+ message: "rendered human command screen",
18
+ meta: { screen },
19
+ });
20
+ }
21
+ function buildOuroHomeActions(agents) {
22
+ if (agents.length === 0) {
23
+ return [
24
+ { key: "1", label: "Hatch a new agent", kind: "hatch", command: "ouro hatch" },
25
+ { key: "2", label: "Clone an existing bundle", kind: "clone", command: "ouro clone <remote>" },
26
+ { key: "3", label: "Show help", kind: "help", command: "ouro --help" },
27
+ { key: "4", label: "Exit", kind: "exit", command: "exit" },
28
+ ];
29
+ }
30
+ const actions = agents.map((agent, index) => ({
31
+ key: String(index + 1),
32
+ label: `Talk to ${agent}`,
33
+ kind: "chat",
34
+ command: `ouro chat ${agent}`,
35
+ agent,
36
+ }));
37
+ return [
38
+ ...actions,
39
+ { key: String(actions.length + 1), label: "Prepare the house", kind: "up", command: "ouro up" },
40
+ { key: String(actions.length + 2), label: "Connect an agent", kind: "connect", command: "ouro connect --agent <agent>" },
41
+ { key: String(actions.length + 3), label: "Repair an agent", kind: "repair", command: "ouro repair --agent <agent>" },
42
+ { key: String(actions.length + 4), label: "Show help", kind: "help", command: "ouro --help" },
43
+ { key: String(actions.length + 5), label: "Exit", kind: "exit", command: "exit" },
44
+ ];
45
+ }
46
+ function resolveOuroHomeAction(answer, actions) {
47
+ const normalized = answer.trim().toLowerCase();
48
+ if (!normalized)
49
+ return undefined;
50
+ const byKey = actions.find((action) => action.key === normalized);
51
+ if (byKey)
52
+ return byKey;
53
+ const byAgent = actions.find((action) => action.agent?.toLowerCase() === normalized);
54
+ if (byAgent)
55
+ return byAgent;
56
+ return actions.find((action) => action.kind === normalized || action.label.toLowerCase() === normalized);
57
+ }
58
+ function renderOuroHomeScreen(options) {
59
+ renderScreenEvent("home");
60
+ const actions = buildOuroHomeActions(options.agents);
61
+ const sections = [
62
+ {
63
+ title: options.agents.length === 0 ? "Start here" : "Around the house",
64
+ lines: options.agents.length === 0
65
+ ? ["No agents are home yet. Hatch someone new or bring an existing bundle aboard."]
66
+ : options.agents.map((agent) => `${agent} is home and ready when called.`),
67
+ },
68
+ ];
69
+ const actionRows = actions.map((action, index) => ({
70
+ label: action.label,
71
+ actor: "agent-runnable",
72
+ command: action.command,
73
+ ...(index === 0 ? { recommended: true } : {}),
74
+ }));
75
+ return (0, terminal_ui_1.renderTerminalBoard)({
76
+ isTTY: options.isTTY,
77
+ columns: options.columns,
78
+ masthead: {
79
+ subtitle: options.agents.length === 0
80
+ ? "No agents are home yet."
81
+ : "Welcome home.",
82
+ },
83
+ title: "Ouro home",
84
+ summary: options.agents.length === 0
85
+ ? "Hatch someone new or bring an existing bundle aboard."
86
+ : "Choose who to wake or what to prepare without memorizing commands.",
87
+ sections,
88
+ actions: actionRows,
89
+ prompt: `Choose [1-${actions.length}] or type a name: `,
90
+ });
91
+ }
92
+ function renderAgentPickerScreen(options) {
93
+ renderScreenEvent("agent-picker");
94
+ return (0, terminal_ui_1.renderTerminalBoard)({
95
+ isTTY: options.isTTY,
96
+ columns: options.columns,
97
+ masthead: {
98
+ subtitle: options.subtitle,
99
+ },
100
+ title: options.title,
101
+ summary: "Type the number or name that matches the agent you want.",
102
+ sections: [
103
+ {
104
+ title: "Agents",
105
+ lines: options.agents.map((agent, index) => `${index + 1}. ${agent}`),
106
+ },
107
+ ],
108
+ prompt: `Choose [1-${options.agents.length}] or type a name: `,
109
+ });
110
+ }
111
+ function resolveNamedAgentSelection(answer, agents) {
112
+ const normalized = answer.trim().toLowerCase();
113
+ if (!normalized)
114
+ return undefined;
115
+ const numbered = Number.parseInt(normalized, 10);
116
+ if (Number.isFinite(numbered))
117
+ return agents[numbered - 1];
118
+ return agents.find((agent) => agent.toLowerCase() === normalized);
119
+ }
120
+ function statusLabel(status) {
121
+ return status.replace(/-/g, " ");
122
+ }
123
+ function renderHumanReadinessBoard(options) {
124
+ renderScreenEvent("readiness");
125
+ const sections = options.snapshot.items.map((item) => ({
126
+ title: item.title,
127
+ lines: [
128
+ `${statusLabel(item.status)} — ${item.summary}`,
129
+ ...item.detailLines,
130
+ ],
131
+ }));
132
+ return renderHumanCommandBoard({
133
+ title: options.title,
134
+ subtitle: options.subtitle,
135
+ summary: options.snapshot.summary,
136
+ isTTY: options.isTTY,
137
+ columns: options.columns,
138
+ sections,
139
+ actions: options.snapshot.nextActions,
140
+ prompt: options.prompt,
141
+ });
142
+ }
143
+ function renderHumanCommandBoard(options) {
144
+ renderScreenEvent("command-board");
145
+ return (0, terminal_ui_1.renderTerminalBoard)({
146
+ isTTY: options.isTTY,
147
+ columns: options.columns,
148
+ masthead: {
149
+ subtitle: options.subtitle,
150
+ },
151
+ title: options.title,
152
+ summary: options.summary,
153
+ sections: options.sections,
154
+ actions: options.actions,
155
+ prompt: options.prompt,
156
+ });
157
+ }
158
+ function renderHouseStatusScreen(options) {
159
+ renderScreenEvent("house-status");
160
+ const sections = [
161
+ {
162
+ title: "House pulse",
163
+ lines: [
164
+ `Daemon: ${options.payload.overview.daemon}`,
165
+ `Health: ${options.payload.overview.health}`,
166
+ `Outlook: ${options.payload.overview.outlookUrl}`,
167
+ `Updated: ${options.payload.overview.lastUpdated}`,
168
+ ],
169
+ },
170
+ ];
171
+ if (options.payload.agents.length > 0) {
172
+ sections.push({
173
+ title: "Agents",
174
+ lines: options.payload.agents.map((agent) => `${agent.name} — ${agent.enabled ? "enabled" : "disabled"}`),
175
+ });
176
+ }
177
+ if (options.payload.providers.length > 0) {
178
+ sections.push({
179
+ title: "Providers",
180
+ lines: options.payload.providers.map((provider) => {
181
+ const detail = [provider.readiness, provider.detail, provider.source, provider.credential].filter(Boolean).join("; ");
182
+ return `${provider.agent} ${provider.lane} — ${provider.provider} / ${provider.model}${detail ? ` — ${detail}` : ""}`;
183
+ }),
184
+ });
185
+ }
186
+ if (options.payload.senses.length > 0) {
187
+ sections.push({
188
+ title: "Senses",
189
+ lines: options.payload.senses.map((sense) => {
190
+ const status = sense.enabled ? sense.status : "disabled";
191
+ return `${sense.agent} — ${sense.label ?? sense.sense} — ${status}${sense.detail ? ` — ${sense.detail}` : ""}`;
192
+ }),
193
+ });
194
+ }
195
+ if (options.payload.workers.length > 0) {
196
+ sections.push({
197
+ title: "Workers",
198
+ lines: options.payload.workers.map((worker) => {
199
+ const details = [`restarts: ${worker.restartCount}`];
200
+ if (worker.pid !== null)
201
+ details.unshift(`pid ${worker.pid}`);
202
+ if (worker.lastExitCode !== null)
203
+ details.push(`exit=${worker.lastExitCode}`);
204
+ if (worker.lastSignal !== null)
205
+ details.push(`signal=${worker.lastSignal}`);
206
+ if (worker.errorReason)
207
+ details.push(`error: ${worker.errorReason}`);
208
+ if (worker.fixHint)
209
+ details.push(`fix: ${worker.fixHint}`);
210
+ return `${worker.agent} — ${worker.worker} — ${worker.status} — ${details.join("; ")}`;
211
+ }),
212
+ });
213
+ }
214
+ if (options.payload.sync.length > 0) {
215
+ sections.push({
216
+ title: "Git sync",
217
+ lines: options.payload.sync.map((row) => {
218
+ if (!row.enabled)
219
+ return `${row.agent} — disabled`;
220
+ if (row.gitInitialized === false)
221
+ return `${row.agent} — needs git init`;
222
+ if (row.remoteUrl)
223
+ return `${row.agent} — ${row.remote} -> ${row.remoteUrl}`;
224
+ return `${row.agent} — local only`;
225
+ }),
226
+ });
227
+ }
228
+ return renderHumanCommandBoard({
229
+ title: "House status",
230
+ subtitle: "The house is awake enough to answer clearly.",
231
+ summary: "What is awake, resting, or asking for care.",
232
+ isTTY: options.isTTY,
233
+ columns: options.columns,
234
+ sections,
235
+ });
236
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readinessItemFromIssue = readinessItemFromIssue;
4
+ exports.buildHumanReadinessSnapshot = buildHumanReadinessSnapshot;
5
+ const runtime_1 = require("../../nerves/runtime");
6
+ const STATUS_PRIORITY = {
7
+ locked: 0,
8
+ "needs credentials": 1,
9
+ "needs attention": 2,
10
+ "needs setup": 3,
11
+ missing: 4,
12
+ "not attached": 5,
13
+ ready: 6,
14
+ attached: 6,
15
+ };
16
+ function statusFromIssue(issue) {
17
+ switch (issue.kind) {
18
+ case "vault-locked":
19
+ return "locked";
20
+ case "vault-unconfigured":
21
+ return "needs setup";
22
+ case "provider-credentials-missing":
23
+ return "needs credentials";
24
+ case "provider-live-check-failed":
25
+ return issue.actions[0]?.kind === "provider-auth" ? "needs credentials" : "needs attention";
26
+ case "generic":
27
+ return "needs attention";
28
+ }
29
+ }
30
+ function copyActions(actions) {
31
+ return actions.map((action) => ({
32
+ label: action.label,
33
+ command: action.command,
34
+ actor: action.actor,
35
+ ...(action.executable === undefined ? {} : { executable: action.executable }),
36
+ }));
37
+ }
38
+ function readinessItemFromIssue(issue, options) {
39
+ return {
40
+ key: options.key,
41
+ title: options.title,
42
+ status: statusFromIssue(issue),
43
+ summary: issue.summary,
44
+ detailLines: issue.detail ? [issue.detail] : [],
45
+ actions: copyActions(issue.actions),
46
+ };
47
+ }
48
+ function compareStatus(a, b) {
49
+ return STATUS_PRIORITY[a.status] - STATUS_PRIORITY[b.status];
50
+ }
51
+ function uniqueActions(items) {
52
+ const seen = new Set();
53
+ const actions = [];
54
+ for (const item of [...items].sort(compareStatus)) {
55
+ for (const [index, action] of item.actions.entries()) {
56
+ if (seen.has(action.command))
57
+ continue;
58
+ seen.add(action.command);
59
+ actions.push({
60
+ ...action,
61
+ ...(actions.length === 0 && index === 0 ? { recommended: true } : {}),
62
+ });
63
+ }
64
+ }
65
+ return actions;
66
+ }
67
+ function overallStatus(items) {
68
+ if (items.length === 0)
69
+ return "ready";
70
+ return [...items].sort(compareStatus)[0].status;
71
+ }
72
+ function summaryFor(status) {
73
+ if (status === "ready" || status === "attached") {
74
+ return "Everything needed here is ready.";
75
+ }
76
+ if (status === "locked") {
77
+ return "Start by unlocking the vault on this machine, then continue through the remaining steps.";
78
+ }
79
+ if (status === "needs credentials") {
80
+ return "At least one credential is missing, so the next move is to authenticate it.";
81
+ }
82
+ if (status === "needs attention") {
83
+ return "Something is configured but not healthy yet, so verify or refresh it before moving on.";
84
+ }
85
+ if (status === "needs setup") {
86
+ return "This capability needs setup before it can be used.";
87
+ }
88
+ return "This area still needs a little attention.";
89
+ }
90
+ function buildHumanReadinessSnapshot(options) {
91
+ const status = overallStatus(options.items);
92
+ const nextActions = uniqueActions(options.items);
93
+ const primaryAction = nextActions[0];
94
+ (0, runtime_1.emitNervesEvent)({
95
+ component: "daemon",
96
+ event: "daemon.human_readiness_snapshot",
97
+ message: "built human readiness snapshot",
98
+ meta: {
99
+ agent: options.agent,
100
+ title: options.title,
101
+ items: options.items.length,
102
+ status,
103
+ },
104
+ });
105
+ return {
106
+ agent: options.agent,
107
+ title: options.title,
108
+ status,
109
+ summary: summaryFor(status),
110
+ items: [...options.items].sort(compareStatus),
111
+ ...(primaryAction ? { primaryAction } : {}),
112
+ nextActions,
113
+ };
114
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildInnerStatusOutput = buildInnerStatusOutput;
4
+ const runtime_1 = require("../../nerves/runtime");
5
+ function formatRelativeTime(elapsedMs) {
6
+ const minutes = Math.floor(elapsedMs / (60 * 1000));
7
+ if (minutes < 1)
8
+ return "just now";
9
+ if (minutes === 1)
10
+ return "1 minute ago";
11
+ if (minutes < 60)
12
+ return `${minutes} minutes ago`;
13
+ const hours = Math.floor(minutes / 60);
14
+ if (hours === 1)
15
+ return "1 hour ago";
16
+ return `${hours} hours ago`;
17
+ }
18
+ function formatCadence(cadenceMs) {
19
+ const minutes = Math.round(cadenceMs / (60 * 1000));
20
+ if (minutes >= 60) {
21
+ const hours = Math.round(minutes / 60);
22
+ return `${hours}h`;
23
+ }
24
+ return `${minutes}m`;
25
+ }
26
+ function buildInnerStatusOutput(input) {
27
+ const { agentName, runtimeState, journalFiles, heartbeat, attentionCount, now } = input;
28
+ const lines = [];
29
+ lines.push(`inner dialog status: ${agentName}`);
30
+ // Last turn
31
+ if (runtimeState?.lastCompletedAt) {
32
+ const lastMs = new Date(runtimeState.lastCompletedAt).getTime();
33
+ const elapsed = now - lastMs;
34
+ const relativeTime = formatRelativeTime(elapsed);
35
+ const reasonSuffix = runtimeState.reason ? ` (${runtimeState.reason})` : "";
36
+ lines.push(` last turn: ${relativeTime}${reasonSuffix}`);
37
+ }
38
+ else {
39
+ lines.push(" last turn: unknown");
40
+ }
41
+ // Status
42
+ if (runtimeState) {
43
+ const reasonSuffix = runtimeState.status === "running" && runtimeState.reason ? ` (${runtimeState.reason})` : "";
44
+ lines.push(` status: ${runtimeState.status}${reasonSuffix}`);
45
+ }
46
+ else {
47
+ lines.push(" status: unknown");
48
+ }
49
+ // Heartbeat health
50
+ if (heartbeat && heartbeat.lastCompletedAt !== null) {
51
+ const elapsed = now - heartbeat.lastCompletedAt;
52
+ const threshold = heartbeat.cadenceMs * 1.5;
53
+ const health = elapsed < threshold ? "healthy" : "overdue";
54
+ const cadenceStr = formatCadence(heartbeat.cadenceMs);
55
+ const sinceStr = formatRelativeTime(elapsed);
56
+ lines.push(` heartbeat: ${health} (cadence ${cadenceStr}, ${sinceStr})`);
57
+ }
58
+ else {
59
+ lines.push(" heartbeat: unknown");
60
+ }
61
+ // Journal
62
+ if (journalFiles.length === 0) {
63
+ lines.push(" journal: (empty)");
64
+ }
65
+ else {
66
+ lines.push(" journal:");
67
+ const sorted = [...journalFiles].sort((a, b) => b.mtimeMs - a.mtimeMs);
68
+ for (const file of sorted) {
69
+ const elapsed = now - file.mtimeMs;
70
+ const relativeTime = formatRelativeTime(elapsed);
71
+ lines.push(` - ${file.name} (${relativeTime})`);
72
+ }
73
+ }
74
+ // Attention
75
+ const thoughtWord = attentionCount === 1 ? "thought" : "thoughts";
76
+ lines.push(` attention: ${attentionCount} held ${thoughtWord}`);
77
+ (0, runtime_1.emitNervesEvent)({
78
+ component: "daemon",
79
+ event: "daemon.inner_status_read",
80
+ message: "inner dialog status read",
81
+ meta: {
82
+ agentName,
83
+ status: runtimeState?.status ?? "unknown",
84
+ journalCount: journalFiles.length,
85
+ attentionCount,
86
+ },
87
+ });
88
+ return lines.join("\n");
89
+ }