@ouro.bot/cli 0.1.0-alpha.5 → 0.1.0-alpha.500

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 (380) hide show
  1. package/README.md +226 -183
  2. package/SerpentGuide.ouro/agent.json +82 -0
  3. package/SerpentGuide.ouro/psyche/SOUL.md +25 -0
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
  5. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  6. package/assets/ouroboros.png +0 -0
  7. package/changelog.json +3418 -0
  8. package/dist/arc/attention-types.js +8 -0
  9. package/dist/arc/cares.js +140 -0
  10. package/dist/arc/episodes.js +117 -0
  11. package/dist/arc/intentions.js +133 -0
  12. package/dist/arc/json-store.js +117 -0
  13. package/dist/arc/obligations.js +237 -0
  14. package/dist/arc/packets.js +193 -0
  15. package/dist/arc/presence.js +185 -0
  16. package/dist/arc/task-lifecycle.js +65 -0
  17. package/dist/heart/active-work.js +989 -0
  18. package/dist/heart/agent-entry.js +58 -3
  19. package/dist/heart/attachments/image-normalize.js +194 -0
  20. package/dist/heart/attachments/materialize.js +97 -0
  21. package/dist/heart/attachments/originals.js +88 -0
  22. package/dist/heart/attachments/render.js +29 -0
  23. package/dist/heart/attachments/sources/adapter.js +2 -0
  24. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  25. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  26. package/dist/heart/attachments/sources/index.js +16 -0
  27. package/dist/heart/attachments/store.js +103 -0
  28. package/dist/heart/attachments/types.js +93 -0
  29. package/dist/heart/auth/auth-flow.js +426 -0
  30. package/dist/heart/background-operations.js +281 -0
  31. package/dist/heart/bridges/manager.js +358 -0
  32. package/dist/heart/bridges/state-machine.js +135 -0
  33. package/dist/heart/bridges/store.js +123 -0
  34. package/dist/heart/bundle-state.js +168 -0
  35. package/dist/heart/commitments.js +111 -0
  36. package/dist/heart/config-registry.js +304 -0
  37. package/dist/heart/config.js +193 -130
  38. package/dist/heart/core.js +1010 -261
  39. package/dist/heart/cross-chat-delivery.js +131 -0
  40. package/dist/heart/daemon/agent-config-check.js +490 -0
  41. package/dist/heart/daemon/agent-discovery.js +157 -0
  42. package/dist/heart/daemon/agent-service.js +360 -0
  43. package/dist/heart/daemon/agentic-repair.js +216 -0
  44. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  45. package/dist/heart/daemon/cadence.js +70 -0
  46. package/dist/heart/daemon/cli-defaults.js +640 -0
  47. package/dist/heart/daemon/cli-exec.js +7239 -0
  48. package/dist/heart/daemon/cli-help.js +493 -0
  49. package/dist/heart/daemon/cli-parse.js +1533 -0
  50. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  51. package/dist/heart/daemon/cli-render.js +561 -0
  52. package/dist/heart/daemon/cli-types.js +8 -0
  53. package/dist/heart/daemon/connect-bay.js +323 -0
  54. package/dist/heart/daemon/daemon-cli.js +30 -697
  55. package/dist/heart/daemon/daemon-entry.js +359 -8
  56. package/dist/heart/daemon/daemon-health.js +141 -0
  57. package/dist/heart/daemon/daemon-runtime-sync.js +268 -0
  58. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  59. package/dist/heart/daemon/daemon.js +813 -19
  60. package/dist/heart/daemon/dns-workflow.js +394 -0
  61. package/dist/heart/daemon/doctor-types.js +8 -0
  62. package/dist/heart/daemon/doctor.js +615 -0
  63. package/dist/heart/daemon/health-monitor.js +92 -1
  64. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  65. package/dist/heart/daemon/hooks/bundle-meta.js +206 -0
  66. package/dist/heart/daemon/http-health-probe.js +80 -0
  67. package/dist/heart/daemon/human-command-screens.js +234 -0
  68. package/dist/heart/daemon/human-readiness.js +114 -0
  69. package/dist/heart/daemon/inner-status.js +89 -0
  70. package/dist/heart/daemon/interactive-repair.js +394 -0
  71. package/dist/heart/daemon/launchd.js +171 -0
  72. package/dist/heart/daemon/log-tailer.js +82 -12
  73. package/dist/heart/daemon/logs-prune.js +110 -0
  74. package/dist/heart/daemon/message-router.js +17 -8
  75. package/dist/heart/daemon/os-cron-deps.js +134 -0
  76. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  77. package/dist/heart/daemon/ouro-entry.js +3 -1
  78. package/dist/heart/daemon/process-manager.js +215 -1
  79. package/dist/heart/daemon/provider-discovery.js +137 -0
  80. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  81. package/dist/heart/daemon/pulse.js +475 -0
  82. package/dist/heart/daemon/readiness-repair.js +365 -0
  83. package/dist/heart/daemon/run-hooks.js +39 -0
  84. package/dist/heart/daemon/runtime-logging.js +67 -16
  85. package/dist/heart/daemon/runtime-metadata.js +191 -0
  86. package/dist/heart/daemon/runtime-mode.js +67 -0
  87. package/dist/heart/daemon/safe-mode.js +161 -0
  88. package/dist/heart/daemon/sense-manager.js +431 -0
  89. package/dist/heart/daemon/session-id-resolver.js +131 -0
  90. package/dist/heart/daemon/skill-management-installer.js +94 -0
  91. package/dist/heart/daemon/socket-client.js +307 -0
  92. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  93. package/dist/heart/daemon/startup-tui.js +264 -0
  94. package/dist/heart/daemon/task-scheduler.js +3 -25
  95. package/dist/heart/daemon/terminal-ui.js +499 -0
  96. package/dist/heart/daemon/thoughts.js +524 -0
  97. package/dist/heart/daemon/up-progress.js +366 -0
  98. package/dist/heart/daemon/vault-items.js +56 -0
  99. package/dist/heart/delegation.js +62 -0
  100. package/dist/heart/habits/habit-migration.js +189 -0
  101. package/dist/heart/habits/habit-parser.js +140 -0
  102. package/dist/heart/habits/habit-runtime-state.js +100 -0
  103. package/dist/heart/habits/habit-scheduler.js +372 -0
  104. package/dist/heart/{daemon → hatch}/hatch-animation.js +10 -3
  105. package/dist/heart/{daemon → hatch}/hatch-flow.js +54 -136
  106. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  107. package/dist/heart/hatch/specialist-orchestrator.js +129 -0
  108. package/dist/heart/hatch/specialist-prompt.js +102 -0
  109. package/dist/heart/hatch/specialist-tools.js +306 -0
  110. package/dist/heart/identity.js +274 -61
  111. package/dist/heart/kept-notes.js +357 -0
  112. package/dist/heart/kicks.js +2 -20
  113. package/dist/heart/machine-identity.js +161 -0
  114. package/dist/heart/mail-import-discovery.js +353 -0
  115. package/dist/heart/mcp/mcp-server.js +653 -0
  116. package/dist/heart/migrate-config.js +100 -0
  117. package/dist/heart/model-capabilities.js +59 -0
  118. package/dist/heart/outlook/outlook-http-hooks.js +66 -0
  119. package/dist/heart/outlook/outlook-http-response.js +7 -0
  120. package/dist/heart/outlook/outlook-http-routes.js +244 -0
  121. package/dist/heart/outlook/outlook-http-static.js +103 -0
  122. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  123. package/dist/heart/outlook/outlook-http.js +99 -0
  124. package/dist/heart/outlook/outlook-read.js +31 -0
  125. package/dist/heart/outlook/outlook-types.js +27 -0
  126. package/dist/heart/outlook/outlook-view.js +195 -0
  127. package/dist/heart/outlook/readers/agent-machine.js +382 -0
  128. package/dist/heart/outlook/readers/continuity-readers.js +336 -0
  129. package/dist/heart/outlook/readers/mail.js +362 -0
  130. package/dist/heart/outlook/readers/runtime-readers.js +644 -0
  131. package/dist/heart/outlook/readers/sessions.js +232 -0
  132. package/dist/heart/outlook/readers/shared.js +111 -0
  133. package/dist/heart/platform.js +81 -0
  134. package/dist/heart/progress-story.js +42 -0
  135. package/dist/heart/provider-attempt.js +134 -0
  136. package/dist/heart/provider-binding-resolver.js +255 -0
  137. package/dist/heart/provider-credentials.js +424 -0
  138. package/dist/heart/provider-failover.js +301 -0
  139. package/dist/heart/provider-models.js +81 -0
  140. package/dist/heart/provider-ping.js +262 -0
  141. package/dist/heart/provider-state.js +216 -0
  142. package/dist/heart/provider-visibility.js +188 -0
  143. package/dist/heart/providers/anthropic-token.js +131 -0
  144. package/dist/heart/providers/anthropic.js +202 -50
  145. package/dist/heart/providers/azure.js +104 -13
  146. package/dist/heart/providers/error-classification.js +63 -0
  147. package/dist/heart/providers/github-copilot.js +145 -0
  148. package/dist/heart/providers/minimax-vlm.js +189 -0
  149. package/dist/heart/providers/minimax.js +29 -7
  150. package/dist/heart/providers/openai-codex.js +63 -39
  151. package/dist/heart/runtime-capability-check.js +170 -0
  152. package/dist/heart/runtime-credentials.js +260 -0
  153. package/dist/heart/sense-truth.js +68 -0
  154. package/dist/heart/session-activity.js +190 -0
  155. package/dist/heart/session-events.js +1089 -0
  156. package/dist/heart/session-playback-cli-main.js +5 -0
  157. package/dist/heart/session-playback-cli.js +36 -0
  158. package/dist/heart/session-playback.js +231 -0
  159. package/dist/heart/session-transcript.js +167 -0
  160. package/dist/heart/start-of-turn-packet.js +345 -0
  161. package/dist/heart/streaming.js +129 -34
  162. package/dist/heart/sync.js +332 -0
  163. package/dist/heart/target-resolution.js +127 -0
  164. package/dist/heart/tempo.js +93 -0
  165. package/dist/heart/temporal-view.js +41 -0
  166. package/dist/heart/tool-activity-callbacks.js +36 -0
  167. package/dist/heart/tool-description.js +135 -0
  168. package/dist/heart/tool-friction.js +55 -0
  169. package/dist/heart/tool-loop.js +200 -0
  170. package/dist/heart/turn-context.js +372 -0
  171. package/dist/heart/turn-coordinator.js +28 -0
  172. package/dist/heart/versioning/ouro-bot-global-installer.js +128 -0
  173. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  174. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  175. package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
  176. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  177. package/dist/heart/versioning/staged-restart.js +146 -0
  178. package/dist/heart/versioning/update-checker.js +115 -0
  179. package/dist/heart/versioning/update-hooks.js +142 -0
  180. package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
  181. package/dist/mailroom/attention.js +167 -0
  182. package/dist/mailroom/autonomy.js +209 -0
  183. package/dist/mailroom/blob-store.js +606 -0
  184. package/dist/mailroom/core.js +672 -0
  185. package/dist/mailroom/entry.js +160 -0
  186. package/dist/mailroom/file-store.js +426 -0
  187. package/dist/mailroom/mbox-import.js +382 -0
  188. package/dist/mailroom/outbound.js +380 -0
  189. package/dist/mailroom/policy.js +263 -0
  190. package/dist/mailroom/reader.js +219 -0
  191. package/dist/mailroom/search-cache.js +182 -0
  192. package/dist/mailroom/search-relevance.js +319 -0
  193. package/dist/mailroom/smtp-ingress.js +176 -0
  194. package/dist/mailroom/source-state.js +176 -0
  195. package/dist/mailroom/thread.js +109 -0
  196. package/dist/mailroom/travel-extract.js +89 -0
  197. package/dist/mind/bundle-manifest.js +77 -1
  198. package/dist/mind/context.js +173 -94
  199. package/dist/mind/diary-integrity.js +60 -0
  200. package/dist/mind/{memory.js → diary.js} +84 -96
  201. package/dist/mind/embedding-provider.js +60 -0
  202. package/dist/mind/file-state.js +179 -0
  203. package/dist/mind/first-impressions.js +16 -2
  204. package/dist/mind/friends/channel.js +73 -0
  205. package/dist/mind/friends/group-context.js +144 -0
  206. package/dist/mind/friends/resolver.js +54 -2
  207. package/dist/mind/friends/store-file.js +58 -3
  208. package/dist/mind/friends/trust-explanation.js +74 -0
  209. package/dist/mind/friends/types.js +10 -2
  210. package/dist/mind/journal-index.js +161 -0
  211. package/dist/mind/note-search.js +268 -0
  212. package/dist/mind/obligation-steering.js +221 -0
  213. package/dist/mind/pending.js +76 -9
  214. package/dist/mind/phrases.js +1 -0
  215. package/dist/mind/prompt-refresh.js +3 -2
  216. package/dist/mind/prompt.js +1144 -117
  217. package/dist/mind/provenance-trust.js +26 -0
  218. package/dist/mind/scrutiny.js +173 -0
  219. package/dist/mind/token-estimate.js +8 -12
  220. package/dist/nerves/cli-logging.js +22 -3
  221. package/dist/nerves/coverage/audit-rules.js +15 -6
  222. package/dist/nerves/coverage/audit.js +28 -2
  223. package/dist/nerves/coverage/cli.js +1 -1
  224. package/dist/nerves/coverage/contract.js +5 -5
  225. package/dist/nerves/coverage/file-completeness.js +101 -5
  226. package/dist/nerves/coverage/run-artifacts.js +1 -1
  227. package/dist/nerves/event-buffer.js +111 -0
  228. package/dist/nerves/index.js +224 -4
  229. package/dist/nerves/observation.js +20 -0
  230. package/dist/nerves/redact.js +79 -0
  231. package/dist/nerves/runtime.js +5 -1
  232. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  233. package/dist/outlook-ui/assets/index-Cm51CY9W.js +61 -0
  234. package/dist/outlook-ui/index.html +15 -0
  235. package/dist/repertoire/ado-client.js +17 -56
  236. package/dist/repertoire/ado-semantic.js +11 -10
  237. package/dist/repertoire/api-client.js +97 -0
  238. package/dist/repertoire/bitwarden-store.js +774 -0
  239. package/dist/repertoire/bundle-templates.js +72 -0
  240. package/dist/repertoire/bw-installer.js +180 -0
  241. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  242. package/dist/repertoire/coding/context-pack.js +330 -0
  243. package/dist/repertoire/coding/feedback.js +301 -0
  244. package/dist/repertoire/coding/index.js +4 -1
  245. package/dist/repertoire/coding/manager.js +220 -13
  246. package/dist/repertoire/coding/spawner.js +58 -12
  247. package/dist/repertoire/coding/tools.js +209 -7
  248. package/dist/repertoire/commerce-errors.js +109 -0
  249. package/dist/repertoire/commerce-self-test.js +156 -0
  250. package/dist/repertoire/credential-access.js +111 -0
  251. package/dist/repertoire/data/ado-endpoints.json +188 -0
  252. package/dist/repertoire/duffel-client.js +185 -0
  253. package/dist/repertoire/github-client.js +14 -55
  254. package/dist/repertoire/graph-client.js +11 -52
  255. package/dist/repertoire/guardrails.js +396 -0
  256. package/dist/repertoire/mcp-client.js +255 -0
  257. package/dist/repertoire/mcp-manager.js +305 -0
  258. package/dist/repertoire/mcp-tools.js +63 -0
  259. package/dist/repertoire/shell-sessions.js +133 -0
  260. package/dist/repertoire/skills.js +15 -24
  261. package/dist/repertoire/stripe-client.js +131 -0
  262. package/dist/repertoire/tasks/board.js +43 -5
  263. package/dist/repertoire/tasks/fix.js +182 -0
  264. package/dist/repertoire/tasks/index.js +39 -13
  265. package/dist/repertoire/tasks/lifecycle.js +2 -2
  266. package/dist/repertoire/tasks/parser.js +3 -2
  267. package/dist/repertoire/tasks/scanner.js +194 -37
  268. package/dist/repertoire/tasks/transitions.js +16 -79
  269. package/dist/repertoire/tool-results.js +29 -0
  270. package/dist/repertoire/tools-attachments.js +317 -0
  271. package/dist/repertoire/tools-base.js +49 -707
  272. package/dist/repertoire/tools-bluebubbles.js +94 -0
  273. package/dist/repertoire/tools-bridge.js +141 -0
  274. package/dist/repertoire/tools-bundle.js +984 -0
  275. package/dist/repertoire/tools-config.js +185 -0
  276. package/dist/repertoire/tools-continuity.js +248 -0
  277. package/dist/repertoire/tools-credential.js +381 -0
  278. package/dist/repertoire/tools-files.js +342 -0
  279. package/dist/repertoire/tools-flight.js +224 -0
  280. package/dist/repertoire/tools-flow.js +105 -0
  281. package/dist/repertoire/tools-github.js +1 -7
  282. package/dist/repertoire/tools-mail.js +1377 -0
  283. package/dist/repertoire/tools-notes.js +376 -0
  284. package/dist/repertoire/tools-session.js +749 -0
  285. package/dist/repertoire/tools-shell.js +120 -0
  286. package/dist/repertoire/tools-stripe.js +180 -0
  287. package/dist/repertoire/tools-surface.js +243 -0
  288. package/dist/repertoire/tools-teams.js +64 -61
  289. package/dist/repertoire/tools-travel.js +125 -0
  290. package/dist/repertoire/tools-trip.js +356 -0
  291. package/dist/repertoire/tools-user-profile.js +144 -0
  292. package/dist/repertoire/tools-vault.js +40 -0
  293. package/dist/repertoire/tools.js +149 -98
  294. package/dist/repertoire/travel-api-client.js +360 -0
  295. package/dist/repertoire/user-profile.js +131 -0
  296. package/dist/repertoire/vault-setup.js +246 -0
  297. package/dist/repertoire/vault-unlock.js +561 -0
  298. package/dist/scripts/claude-code-hook.js +41 -0
  299. package/dist/scripts/claude-code-stop-hook.js +47 -0
  300. package/dist/senses/attention-queue.js +116 -0
  301. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  302. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  303. package/dist/senses/bluebubbles/client.js +685 -0
  304. package/dist/senses/bluebubbles/entry.js +73 -0
  305. package/dist/senses/bluebubbles/inbound-log.js +126 -0
  306. package/dist/senses/bluebubbles/index.js +1881 -0
  307. package/dist/senses/bluebubbles/media.js +389 -0
  308. package/dist/senses/bluebubbles/model.js +282 -0
  309. package/dist/senses/bluebubbles/mutation-log.js +116 -0
  310. package/dist/senses/bluebubbles/processed-log.js +111 -0
  311. package/dist/senses/bluebubbles/replay.js +129 -0
  312. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  313. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  314. package/dist/senses/cli/bracketed-paste.js +82 -0
  315. package/dist/senses/cli/image-paste.js +287 -0
  316. package/dist/senses/cli/image-ref-navigation.js +75 -0
  317. package/dist/senses/cli/ink-app.js +156 -0
  318. package/dist/senses/cli/inline-diff.js +64 -0
  319. package/dist/senses/cli/input-keys.js +174 -0
  320. package/dist/senses/cli/kill-ring.js +86 -0
  321. package/dist/senses/cli/message-list.js +51 -0
  322. package/dist/senses/cli/ouro-tui.js +605 -0
  323. package/dist/senses/cli/spinner-imperative.js +135 -0
  324. package/dist/senses/cli/spinner.js +101 -0
  325. package/dist/senses/cli/status-line.js +60 -0
  326. package/dist/senses/cli/streaming-markdown.js +526 -0
  327. package/dist/senses/cli/tool-display.js +83 -0
  328. package/dist/senses/cli/tool-render.js +85 -0
  329. package/dist/senses/cli/tui-store.js +240 -0
  330. package/dist/senses/cli/virtual-list.js +35 -0
  331. package/dist/senses/cli-entry.js +60 -8
  332. package/dist/senses/cli-layout.js +187 -0
  333. package/dist/senses/cli.js +768 -264
  334. package/dist/senses/commands.js +66 -3
  335. package/dist/senses/continuity.js +94 -0
  336. package/dist/senses/habit-turn-message.js +108 -0
  337. package/dist/senses/inner-dialog-worker.js +199 -16
  338. package/dist/senses/inner-dialog.js +640 -91
  339. package/dist/senses/mail-entry.js +66 -0
  340. package/dist/senses/mail.js +379 -0
  341. package/dist/senses/pipeline.js +665 -0
  342. package/dist/senses/proactive-content-guard.js +51 -0
  343. package/dist/senses/shared-turn.js +248 -0
  344. package/dist/senses/surface-tool.js +68 -0
  345. package/dist/senses/teams-entry.js +60 -8
  346. package/dist/senses/teams.js +844 -197
  347. package/dist/senses/trust-gate.js +207 -2
  348. package/dist/trips/core.js +138 -0
  349. package/dist/trips/store.js +146 -0
  350. package/package.json +47 -6
  351. package/skills/agent-commerce.md +106 -0
  352. package/skills/browser-navigation.md +117 -0
  353. package/skills/commerce-setup-guide.md +116 -0
  354. package/skills/commerce-setup.md +84 -0
  355. package/skills/configure-dev-tools.md +101 -0
  356. package/skills/travel-planning.md +138 -0
  357. package/AdoptionSpecialist.ouro/agent.json +0 -20
  358. package/AdoptionSpecialist.ouro/psyche/SOUL.md +0 -22
  359. package/dist/heart/daemon/specialist-orchestrator.js +0 -160
  360. package/dist/heart/daemon/specialist-prompt.js +0 -40
  361. package/dist/heart/daemon/specialist-session.js +0 -142
  362. package/dist/heart/daemon/specialist-tools.js +0 -128
  363. package/dist/heart/daemon/subagent-installer.js +0 -125
  364. package/dist/inner-worker-entry.js +0 -4
  365. package/dist/mind/associative-recall.js +0 -197
  366. package/subagents/README.md +0 -73
  367. package/subagents/work-doer.md +0 -233
  368. package/subagents/work-merger.md +0 -624
  369. package/subagents/work-planner.md +0 -373
  370. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  371. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  372. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  373. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  374. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  375. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  376. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  377. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  378. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  379. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  380. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
@@ -0,0 +1,140 @@
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.parseHabitFile = parseHabitFile;
37
+ exports.renderHabitFile = renderHabitFile;
38
+ const path = __importStar(require("path"));
39
+ const parser_1 = require("../../repertoire/tasks/parser");
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ function isHabitStatus(value) {
42
+ return value === "active" || value === "paused";
43
+ }
44
+ function parseToolsField(raw) {
45
+ if (raw === undefined || raw === null)
46
+ return undefined;
47
+ // YAML dash-list: parseFrontmatter returns unknown[]
48
+ if (Array.isArray(raw)) {
49
+ return raw.filter((item) => typeof item === "string");
50
+ }
51
+ // Inline bracket format: parseFrontmatter returns string like "[a, b, c]"
52
+ if (typeof raw === "string" && raw.startsWith("[") && raw.endsWith("]")) {
53
+ const inner = raw.slice(1, -1);
54
+ if (inner.trim().length === 0)
55
+ return [];
56
+ return inner.split(",").map((s) => s.trim()).filter(Boolean);
57
+ }
58
+ return undefined;
59
+ }
60
+ function extractFrontmatterAndBody(content) {
61
+ const lines = content.split(/\r?\n/);
62
+ if (lines[0]?.trim() !== "---") {
63
+ return null;
64
+ }
65
+ const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
66
+ if (closing === -1) {
67
+ return null;
68
+ }
69
+ const rawFrontmatter = lines.slice(1, closing).join("\n");
70
+ const body = lines.slice(closing + 1).join("\n").trim();
71
+ return { frontmatter: (0, parser_1.parseFrontmatter)(rawFrontmatter), body };
72
+ }
73
+ function parseHabitFile(content, filePath) {
74
+ (0, runtime_1.emitNervesEvent)({
75
+ event: "daemon.habit_parse",
76
+ component: "daemon",
77
+ message: "parsing habit file",
78
+ meta: { filePath },
79
+ });
80
+ const stem = path.basename(filePath, ".md");
81
+ const parsed = extractFrontmatterAndBody(content);
82
+ if (!parsed) {
83
+ return {
84
+ name: stem,
85
+ title: stem,
86
+ cadence: null,
87
+ status: "active",
88
+ lastRun: null,
89
+ created: null,
90
+ tools: undefined,
91
+ body: content.trim(),
92
+ };
93
+ }
94
+ const { frontmatter, body } = parsed;
95
+ const rawTitle = frontmatter.title;
96
+ const title = typeof rawTitle === "string" && rawTitle.length > 0 ? rawTitle : stem;
97
+ const rawCadence = frontmatter.cadence;
98
+ const cadence = typeof rawCadence === "string" && rawCadence.length > 0 ? rawCadence : null;
99
+ const rawStatus = frontmatter.status;
100
+ const status = typeof rawStatus === "string" && isHabitStatus(rawStatus) ? rawStatus : "active";
101
+ const rawLastRun = frontmatter.lastRun ?? frontmatter.last_run;
102
+ const lastRun = typeof rawLastRun === "string" && rawLastRun.length > 0 ? rawLastRun : null;
103
+ const rawCreated = frontmatter.created;
104
+ const created = typeof rawCreated === "string" && rawCreated.length > 0 ? rawCreated : null;
105
+ const tools = parseToolsField(frontmatter.tools);
106
+ return {
107
+ name: stem,
108
+ title,
109
+ cadence,
110
+ status,
111
+ lastRun,
112
+ created,
113
+ tools,
114
+ body,
115
+ };
116
+ }
117
+ function formatFrontmatterValue(value) {
118
+ if (value === null || value === undefined)
119
+ return "null";
120
+ if (Array.isArray(value))
121
+ return `[${value.join(", ")}]`;
122
+ return String(value);
123
+ }
124
+ function renderHabitFile(frontmatter, body) {
125
+ (0, runtime_1.emitNervesEvent)({
126
+ event: "daemon.habit_render",
127
+ component: "daemon",
128
+ message: "rendering habit file",
129
+ meta: {},
130
+ });
131
+ const lines = ["---"];
132
+ for (const key of Object.keys(frontmatter)) {
133
+ lines.push(`${key}: ${formatFrontmatterValue(frontmatter[key])}`);
134
+ }
135
+ lines.push("---");
136
+ lines.push("");
137
+ lines.push(body.trim());
138
+ lines.push("");
139
+ return lines.join("\n");
140
+ }
@@ -0,0 +1,100 @@
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.readHabitLastRun = readHabitLastRun;
37
+ exports.applyHabitRuntimeState = applyHabitRuntimeState;
38
+ exports.writeHabitLastRun = writeHabitLastRun;
39
+ exports.recordHabitRun = recordHabitRun;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const json_store_1 = require("../../arc/json-store");
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ function habitRuntimeStateDir(agentRoot) {
45
+ return path.join(agentRoot, "state", "habits");
46
+ }
47
+ function isNonEmptyString(value) {
48
+ return typeof value === "string" && value.trim().length > 0;
49
+ }
50
+ function stripLegacyLastRunFromDefinition(definitionPath) {
51
+ const content = fs.readFileSync(definitionPath, "utf-8");
52
+ const lines = content.split(/\r?\n/);
53
+ if (lines[0]?.trim() !== "---")
54
+ return;
55
+ const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
56
+ if (closing === -1)
57
+ return;
58
+ const frontmatterLines = lines.slice(1, closing);
59
+ const filtered = frontmatterLines.filter((line) => !/^\s*lastRun\s*:/.test(line) && !/^\s*last_run\s*:/.test(line));
60
+ if (filtered.length === frontmatterLines.length)
61
+ return;
62
+ const nextContent = ["---", ...filtered, "---", ...lines.slice(closing + 1)].join("\n");
63
+ fs.writeFileSync(definitionPath, nextContent, "utf-8");
64
+ }
65
+ function readHabitLastRun(agentRoot, habitName) {
66
+ const record = (0, json_store_1.readJsonFile)(habitRuntimeStateDir(agentRoot), habitName);
67
+ return isNonEmptyString(record?.lastRun) ? record.lastRun : null;
68
+ }
69
+ function applyHabitRuntimeState(agentRoot, habit) {
70
+ const runtimeLastRun = readHabitLastRun(agentRoot, habit.name);
71
+ if (runtimeLastRun === null)
72
+ return habit;
73
+ return { ...habit, lastRun: runtimeLastRun };
74
+ }
75
+ function writeHabitLastRun(agentRoot, habitName, lastRun, updatedAt = lastRun) {
76
+ const record = {
77
+ schemaVersion: 1,
78
+ name: habitName,
79
+ lastRun,
80
+ updatedAt,
81
+ };
82
+ (0, json_store_1.writeJsonFile)(habitRuntimeStateDir(agentRoot), habitName, record);
83
+ (0, runtime_1.emitNervesEvent)({
84
+ component: "daemon",
85
+ event: "daemon.habit_runtime_state_write",
86
+ message: "wrote habit runtime state",
87
+ meta: { agentRoot, habitName, lastRun, updatedAt },
88
+ });
89
+ }
90
+ function recordHabitRun(agentRoot, habitName, lastRun, options = {}) {
91
+ writeHabitLastRun(agentRoot, habitName, lastRun);
92
+ if (!options.definitionPath)
93
+ return;
94
+ try {
95
+ stripLegacyLastRunFromDefinition(options.definitionPath);
96
+ }
97
+ catch {
98
+ // Missing/deleted habit files should never block runtime-state recording.
99
+ }
100
+ }
@@ -0,0 +1,372 @@
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.HabitScheduler = void 0;
37
+ const path = __importStar(require("path"));
38
+ const runtime_1 = require("../../nerves/runtime");
39
+ const habit_parser_1 = require("./habit-parser");
40
+ const habit_runtime_state_1 = require("./habit-runtime-state");
41
+ const cadence_1 = require("../daemon/cadence");
42
+ const WATCH_DEBOUNCE_MS = 200;
43
+ class HabitScheduler {
44
+ agent;
45
+ habitsDir;
46
+ osCronManager;
47
+ onHabitFire;
48
+ deps;
49
+ execForVerify;
50
+ platform;
51
+ watcher = null;
52
+ debounceTimer = null;
53
+ parseErrors = [];
54
+ timerFallbacks = new Map();
55
+ degradedHabitNames = new Map();
56
+ periodicTimer = null;
57
+ constructor(options) {
58
+ this.agent = options.agent;
59
+ this.habitsDir = options.habitsDir;
60
+ this.osCronManager = options.osCronManager;
61
+ this.onHabitFire = options.onHabitFire;
62
+ this.deps = options.deps;
63
+ this.execForVerify = options.execForVerify;
64
+ this.platform = options.platform ?? process.platform;
65
+ }
66
+ start() {
67
+ (0, runtime_1.emitNervesEvent)({
68
+ component: "daemon",
69
+ event: "daemon.habit_scheduler_start",
70
+ message: "habit scheduler starting",
71
+ meta: { agent: this.agent, habitsDir: this.habitsDir },
72
+ });
73
+ const habits = this.scanHabits();
74
+ const jobs = this.buildJobs(habits);
75
+ this.osCronManager.sync(jobs);
76
+ this.verifyCronAndCreateFallbacks(jobs);
77
+ this.fireOverdueHabits(habits);
78
+ }
79
+ reconcile() {
80
+ (0, runtime_1.emitNervesEvent)({
81
+ component: "daemon",
82
+ event: "daemon.habit_scheduler_reconcile",
83
+ message: "habit scheduler reconciling",
84
+ meta: { agent: this.agent },
85
+ });
86
+ // Clear ALL existing timers FIRST to prevent overlap window
87
+ this.clearAllTimerFallbacks();
88
+ const habits = this.scanHabits();
89
+ const jobs = this.buildJobs(habits);
90
+ this.osCronManager.sync(jobs);
91
+ this.verifyCronAndCreateFallbacks(jobs);
92
+ this.fireOverdueHabits(habits);
93
+ }
94
+ fireOverdueHabits(habits) {
95
+ for (const habit of habits) {
96
+ if (habit.status !== "active")
97
+ continue;
98
+ if (!habit.cadence)
99
+ continue;
100
+ const cadenceMs = (0, cadence_1.parseCadenceToMs)(habit.cadence);
101
+ if (cadenceMs === null)
102
+ continue;
103
+ const nowMs = this.deps.now();
104
+ if (habit.lastRun === null) {
105
+ (0, runtime_1.emitNervesEvent)({
106
+ component: "daemon",
107
+ event: "daemon.habit_fire",
108
+ message: "firing overdue habit (never run)",
109
+ meta: { habitName: habit.name, agent: this.agent },
110
+ });
111
+ this.onHabitFire(habit.name);
112
+ continue;
113
+ }
114
+ const lastRunMs = new Date(habit.lastRun).getTime();
115
+ const elapsed = nowMs - lastRunMs;
116
+ if (elapsed >= cadenceMs) {
117
+ (0, runtime_1.emitNervesEvent)({
118
+ component: "daemon",
119
+ event: "daemon.habit_fire",
120
+ message: "firing overdue habit",
121
+ meta: { habitName: habit.name, agent: this.agent, elapsedMs: elapsed },
122
+ });
123
+ this.onHabitFire(habit.name);
124
+ }
125
+ }
126
+ }
127
+ stop() {
128
+ // `_end` (not `_stop`) to pair with `daemon.habit_scheduler_start`
129
+ // under the nerves audit start/end pairing rule.
130
+ (0, runtime_1.emitNervesEvent)({
131
+ component: "daemon",
132
+ event: "daemon.habit_scheduler_end",
133
+ message: "habit scheduler stopping",
134
+ meta: { agent: this.agent },
135
+ });
136
+ this.stopPeriodicReconciliation();
137
+ this.clearAllTimerFallbacks();
138
+ this.osCronManager.removeAll();
139
+ }
140
+ listOverdueHabits() {
141
+ const habits = this.scanHabits();
142
+ const nowMs = this.deps.now();
143
+ const overdue = [];
144
+ for (const habit of habits) {
145
+ if (habit.status !== "active")
146
+ continue;
147
+ if (!habit.cadence)
148
+ continue;
149
+ const cadenceMs = (0, cadence_1.parseCadenceToMs)(habit.cadence);
150
+ if (cadenceMs === null)
151
+ continue;
152
+ if (habit.lastRun === null) {
153
+ overdue.push({ name: habit.name, elapsedMs: Infinity });
154
+ continue;
155
+ }
156
+ const lastRunMs = new Date(habit.lastRun).getTime();
157
+ const elapsed = nowMs - lastRunMs;
158
+ if (elapsed >= cadenceMs) {
159
+ overdue.push({ name: habit.name, elapsedMs: elapsed });
160
+ }
161
+ }
162
+ return overdue;
163
+ }
164
+ getParseErrors() {
165
+ return [...this.parseErrors];
166
+ }
167
+ getHabitFile(name) {
168
+ const filePath = path.join(this.habitsDir, `${name}.md`);
169
+ try {
170
+ const content = this.deps.readFile(filePath, "utf-8");
171
+ return (0, habit_runtime_state_1.applyHabitRuntimeState)(path.dirname(this.habitsDir), (0, habit_parser_1.parseHabitFile)(content, filePath));
172
+ }
173
+ catch {
174
+ return null;
175
+ }
176
+ }
177
+ watchForChanges() {
178
+ const watchFn = this.deps.watch;
179
+ if (!watchFn)
180
+ return;
181
+ // Ensure habits directory exists before watching — agents may not have one yet
182
+ try {
183
+ this.watcher = watchFn(this.habitsDir, (_event, _filename) => {
184
+ if (this.debounceTimer !== null) {
185
+ clearTimeout(this.debounceTimer);
186
+ }
187
+ this.debounceTimer = setTimeout(() => {
188
+ this.debounceTimer = null;
189
+ this.reconcile();
190
+ }, WATCH_DEBOUNCE_MS);
191
+ });
192
+ /* v8 ignore start — ENOENT catch requires real missing directory @preserve */
193
+ }
194
+ catch {
195
+ // habits directory may not exist for all agents — skip watching silently
196
+ }
197
+ /* v8 ignore stop */
198
+ }
199
+ stopWatching() {
200
+ if (this.debounceTimer !== null) {
201
+ clearTimeout(this.debounceTimer);
202
+ this.debounceTimer = null;
203
+ }
204
+ if (this.watcher !== null) {
205
+ this.watcher.close();
206
+ this.watcher = null;
207
+ }
208
+ }
209
+ getDegradedHabits() {
210
+ const result = [];
211
+ for (const [name, reason] of this.degradedHabitNames) {
212
+ result.push({ name, reason });
213
+ }
214
+ return result;
215
+ }
216
+ static DEFAULT_PERIODIC_INTERVAL_MS = 300_000; // 5 minutes
217
+ static INITIAL_RECONCILIATION_DELAY_MS = 30_000; // 30 seconds
218
+ startPeriodicReconciliation(intervalMs) {
219
+ const interval = intervalMs ?? HabitScheduler.DEFAULT_PERIODIC_INTERVAL_MS;
220
+ // First reconciliation after a short delay (30s)
221
+ this.periodicTimer = setTimeout(() => {
222
+ this.reconcile();
223
+ this.scheduleNextReconciliation(interval);
224
+ }, HabitScheduler.INITIAL_RECONCILIATION_DELAY_MS);
225
+ }
226
+ stopPeriodicReconciliation() {
227
+ if (this.periodicTimer !== null) {
228
+ clearTimeout(this.periodicTimer);
229
+ this.periodicTimer = null;
230
+ }
231
+ }
232
+ scheduleNextReconciliation(intervalMs) {
233
+ this.periodicTimer = setTimeout(() => {
234
+ this.reconcile();
235
+ this.scheduleNextReconciliation(intervalMs);
236
+ }, intervalMs);
237
+ }
238
+ verifyCronAndCreateFallbacks(jobs) {
239
+ if (!this.execForVerify)
240
+ return;
241
+ const verifiedLabels = this.verifyCronEntries();
242
+ for (const job of jobs) {
243
+ const label = `bot.ouro.${job.agent}.${job.taskId}`;
244
+ const isVerified = this.platform === "darwin"
245
+ ? verifiedLabels.has(label)
246
+ : verifiedLabels.has(job.taskId);
247
+ if (!isVerified) {
248
+ (0, runtime_1.emitNervesEvent)({
249
+ component: "daemon",
250
+ event: "daemon.habit_cron_verification_failed",
251
+ message: `cron verification failed for habit: ${job.taskId}`,
252
+ meta: { habitName: job.taskId, agent: job.agent, label },
253
+ });
254
+ // Parse cadence from the original habit file for timer interval
255
+ const habitFile = this.getHabitFile(job.taskId);
256
+ const ms = habitFile?.cadence ? (0, cadence_1.parseCadenceToMs)(habitFile.cadence) : null;
257
+ if (ms !== null) {
258
+ this.createTimerFallback(job.taskId, ms);
259
+ }
260
+ this.degradedHabitNames.set(job.taskId, "cron registration failed — using timer fallback");
261
+ }
262
+ }
263
+ }
264
+ verifyCronEntries() {
265
+ const verified = new Set();
266
+ try {
267
+ if (this.platform === "darwin") {
268
+ const output = this.execForVerify("launchctl list");
269
+ const lines = output.split("\n");
270
+ for (const line of lines) {
271
+ const match = line.match(/bot\.ouro\.\S+\.\S+/);
272
+ if (match) {
273
+ verified.add(match[0]);
274
+ }
275
+ }
276
+ }
277
+ else {
278
+ const output = this.execForVerify("crontab -l");
279
+ const lines = output.split("\n");
280
+ for (const line of lines) {
281
+ const match = line.match(/ouro poke \S+ --habit (\S+)/);
282
+ if (match) {
283
+ verified.add(match[1]);
284
+ }
285
+ }
286
+ }
287
+ }
288
+ catch {
289
+ // Verification command failed — return empty set (all habits unverified)
290
+ }
291
+ return verified;
292
+ }
293
+ createTimerFallback(habitName, cadenceMs) {
294
+ const schedule = () => {
295
+ const timer = setTimeout(() => {
296
+ this.onHabitFire(habitName);
297
+ schedule();
298
+ }, cadenceMs);
299
+ this.timerFallbacks.set(habitName, timer);
300
+ };
301
+ schedule();
302
+ }
303
+ clearAllTimerFallbacks() {
304
+ for (const timer of this.timerFallbacks.values()) {
305
+ clearTimeout(timer);
306
+ }
307
+ this.timerFallbacks.clear();
308
+ this.degradedHabitNames.clear();
309
+ }
310
+ scanHabits() {
311
+ let files;
312
+ try {
313
+ files = this.deps.readdir(this.habitsDir);
314
+ }
315
+ catch {
316
+ this.parseErrors = [];
317
+ return [];
318
+ }
319
+ const habits = [];
320
+ const errors = [];
321
+ for (const file of files) {
322
+ if (!file.endsWith(".md"))
323
+ continue;
324
+ const filePath = path.join(this.habitsDir, file);
325
+ try {
326
+ const content = this.deps.readFile(filePath, "utf-8");
327
+ const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(path.dirname(this.habitsDir), (0, habit_parser_1.parseHabitFile)(content, filePath));
328
+ habits.push(habit);
329
+ }
330
+ catch (error) {
331
+ const errorMessage = error instanceof Error ? error.message : String(error);
332
+ errors.push({ file, error: errorMessage });
333
+ (0, runtime_1.emitNervesEvent)({
334
+ level: "error",
335
+ component: "daemon",
336
+ event: "daemon.habit_parse_error",
337
+ message: "failed to parse habit file",
338
+ meta: {
339
+ file,
340
+ error: errorMessage,
341
+ agent: this.agent,
342
+ },
343
+ });
344
+ }
345
+ }
346
+ this.parseErrors = errors;
347
+ return habits;
348
+ }
349
+ buildJobs(habits) {
350
+ const jobs = [];
351
+ for (const habit of habits) {
352
+ if (habit.status !== "active")
353
+ continue;
354
+ if (!habit.cadence)
355
+ continue;
356
+ const cronSchedule = (0, cadence_1.parseCadenceToCron)(habit.cadence);
357
+ if (cronSchedule === null)
358
+ continue;
359
+ jobs.push({
360
+ id: `${this.agent}:${habit.name}:cadence`,
361
+ agent: this.agent,
362
+ taskId: habit.name,
363
+ schedule: cronSchedule,
364
+ lastRun: habit.lastRun,
365
+ command: `${this.deps.ouroPath} poke ${this.agent} --habit ${habit.name}`,
366
+ taskPath: path.join(this.habitsDir, `${habit.name}.md`),
367
+ });
368
+ }
369
+ return jobs;
370
+ }
371
+ }
372
+ exports.HabitScheduler = HabitScheduler;
@@ -20,9 +20,16 @@ async function playHatchAnimation(hatchlingName, writer) {
20
20
  meta: { hatchlingName },
21
21
  });
22
22
  const write = writer ?? ((text) => process.stderr.write(text));
23
+ // Total animation time randomized between 3–5 seconds
24
+ const totalMs = 3000 + Math.floor(Math.random() * 2000);
25
+ const eggPhase = Math.floor(totalMs * 0.4);
26
+ const dotsPhase = Math.floor(totalMs * 0.4);
27
+ const revealPause = totalMs - eggPhase - dotsPhase;
23
28
  write(`\n ${EGG}`);
24
- await wait(400);
29
+ await wait(eggPhase);
25
30
  write(DOTS);
26
- await wait(400);
27
- write(`${SNAKE} \x1b[1m${hatchlingName}\x1b[0m\n\n`);
31
+ await wait(dotsPhase);
32
+ write(`${SNAKE} \x1b[1m${hatchlingName}\x1b[0m`);
33
+ await wait(revealPause);
34
+ write("\n\n");
28
35
  }