@ouro.bot/cli 0.1.0-alpha.62 → 0.1.0-alpha.637

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 (432) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +4087 -13
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +144 -0
  15. package/dist/arc/episodes.js +118 -0
  16. package/dist/arc/evolution.js +487 -0
  17. package/dist/arc/intentions.js +134 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +270 -0
  20. package/dist/arc/packets.js +288 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +57 -0
  23. package/dist/heart/active-work.js +860 -43
  24. package/dist/heart/agent-entry.js +69 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/awaiting/await-alert.js +146 -0
  36. package/dist/heart/awaiting/await-expiry.js +108 -0
  37. package/dist/heart/awaiting/await-loader.js +91 -0
  38. package/dist/heart/awaiting/await-parser.js +141 -0
  39. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  40. package/dist/heart/awaiting/await-scheduler.js +377 -0
  41. package/dist/heart/background-operations.js +281 -0
  42. package/dist/heart/bridges/manager.js +137 -17
  43. package/dist/heart/bridges/store.js +14 -2
  44. package/dist/heart/bundle-state.js +168 -0
  45. package/dist/heart/commitments.js +135 -0
  46. package/dist/heart/config-registry.js +322 -0
  47. package/dist/heart/config.js +114 -119
  48. package/dist/heart/core.js +1028 -248
  49. package/dist/heart/cross-chat-delivery.js +3 -18
  50. package/dist/heart/daemon/agent-config-check.js +419 -0
  51. package/dist/heart/daemon/agent-discovery.js +102 -3
  52. package/dist/heart/daemon/agent-service.js +522 -0
  53. package/dist/heart/daemon/agentic-repair.js +547 -0
  54. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  55. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  56. package/dist/heart/daemon/cadence.js +70 -0
  57. package/dist/heart/daemon/cli-defaults.js +776 -0
  58. package/dist/heart/daemon/cli-desk.js +322 -0
  59. package/dist/heart/daemon/cli-exec.js +7468 -0
  60. package/dist/heart/daemon/cli-help.js +505 -0
  61. package/dist/heart/daemon/cli-parse.js +1554 -0
  62. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  63. package/dist/heart/daemon/cli-render.js +763 -0
  64. package/dist/heart/daemon/cli-types.js +8 -0
  65. package/dist/heart/daemon/connect-bay.js +323 -0
  66. package/dist/heart/daemon/daemon-cli.js +29 -1700
  67. package/dist/heart/daemon/daemon-entry.js +485 -2
  68. package/dist/heart/daemon/daemon-health.js +176 -0
  69. package/dist/heart/daemon/daemon-rollup.js +57 -0
  70. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  71. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  72. package/dist/heart/daemon/daemon.js +906 -71
  73. package/dist/heart/daemon/dns-workflow.js +394 -0
  74. package/dist/heart/daemon/doctor-types.js +8 -0
  75. package/dist/heart/daemon/doctor.js +873 -0
  76. package/dist/heart/daemon/health-monitor.js +122 -1
  77. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  78. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  79. package/dist/heart/daemon/http-health-probe.js +80 -0
  80. package/dist/heart/daemon/human-command-screens.js +234 -0
  81. package/dist/heart/daemon/human-readiness.js +114 -0
  82. package/dist/heart/daemon/inner-status.js +89 -0
  83. package/dist/heart/daemon/interactive-repair.js +394 -0
  84. package/dist/heart/daemon/launchd.js +37 -8
  85. package/dist/heart/daemon/log-tailer.js +79 -10
  86. package/dist/heart/daemon/logs-prune.js +110 -0
  87. package/dist/heart/daemon/mcp-canary.js +297 -0
  88. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  89. package/dist/heart/daemon/os-cron-deps.js +135 -0
  90. package/dist/heart/daemon/os-cron.js +14 -12
  91. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  92. package/dist/heart/daemon/ouro-entry.js +3 -1
  93. package/dist/heart/daemon/plugin-cli.js +432 -0
  94. package/dist/heart/daemon/process-manager.js +501 -35
  95. package/dist/heart/daemon/provider-discovery.js +137 -0
  96. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  97. package/dist/heart/daemon/pulse.js +475 -0
  98. package/dist/heart/daemon/readiness-repair.js +365 -0
  99. package/dist/heart/daemon/run-hooks.js +2 -0
  100. package/dist/heart/daemon/runtime-logging.js +11 -3
  101. package/dist/heart/daemon/runtime-metadata.js +2 -30
  102. package/dist/heart/daemon/safe-mode.js +161 -0
  103. package/dist/heart/daemon/sense-manager.js +493 -38
  104. package/dist/heart/daemon/session-id-resolver.js +131 -0
  105. package/dist/heart/daemon/skill-management-installer.js +22 -9
  106. package/dist/heart/daemon/socket-client.js +158 -11
  107. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  108. package/dist/heart/daemon/startup-tui.js +330 -0
  109. package/dist/heart/daemon/task-scheduler.js +117 -39
  110. package/dist/heart/daemon/terminal-ui.js +499 -0
  111. package/dist/heart/daemon/thoughts.js +229 -17
  112. package/dist/heart/daemon/up-progress.js +366 -0
  113. package/dist/heart/daemon/vault-items.js +56 -0
  114. package/dist/heart/delegation.js +1 -4
  115. package/dist/heart/habits/habit-migration.js +189 -0
  116. package/dist/heart/habits/habit-parser.js +140 -0
  117. package/dist/heart/habits/habit-runtime-state.js +100 -0
  118. package/dist/heart/habits/habit-scheduler.js +372 -0
  119. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  120. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  121. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  122. package/dist/heart/{daemon → hatch}/specialist-tools.js +37 -14
  123. package/dist/heart/identity.js +168 -57
  124. package/dist/heart/kept-notes.js +357 -0
  125. package/dist/heart/kicks.js +1 -1
  126. package/dist/heart/machine-identity.js +161 -0
  127. package/dist/heart/mail-import-discovery.js +353 -0
  128. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  129. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  130. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  131. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  132. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  133. package/dist/heart/mailbox/mailbox-http.js +99 -0
  134. package/dist/heart/mailbox/mailbox-read.js +31 -0
  135. package/dist/heart/mailbox/mailbox-types.js +27 -0
  136. package/dist/heart/mailbox/mailbox-view.js +197 -0
  137. package/dist/heart/mailbox/readers/agent-machine.js +418 -0
  138. package/dist/heart/mailbox/readers/continuity-readers.js +319 -0
  139. package/dist/heart/mailbox/readers/mail.js +375 -0
  140. package/dist/heart/mailbox/readers/runtime-readers.js +756 -0
  141. package/dist/heart/mailbox/readers/sessions.js +232 -0
  142. package/dist/heart/mailbox/readers/shared.js +111 -0
  143. package/dist/heart/mcp/mcp-server.js +692 -0
  144. package/dist/heart/migrate-config.js +100 -0
  145. package/dist/heart/model-capabilities.js +19 -0
  146. package/dist/heart/orientation-frame.js +217 -0
  147. package/dist/heart/platform.js +81 -0
  148. package/dist/heart/provider-attempt.js +134 -0
  149. package/dist/heart/provider-binding-resolver.js +272 -0
  150. package/dist/heart/provider-credentials.js +425 -0
  151. package/dist/heart/provider-failover.js +301 -0
  152. package/dist/heart/provider-models.js +81 -0
  153. package/dist/heart/provider-ping.js +262 -0
  154. package/dist/heart/provider-readiness-cache.js +40 -0
  155. package/dist/heart/provider-visibility.js +188 -0
  156. package/dist/heart/providers/anthropic-token.js +131 -0
  157. package/dist/heart/providers/anthropic.js +139 -52
  158. package/dist/heart/providers/azure.js +23 -11
  159. package/dist/heart/providers/error-classification.js +127 -0
  160. package/dist/heart/providers/github-copilot.js +145 -0
  161. package/dist/heart/providers/minimax-vlm.js +189 -0
  162. package/dist/heart/providers/minimax.js +26 -8
  163. package/dist/heart/providers/openai-codex.js +55 -40
  164. package/dist/heart/runtime-capability-check.js +170 -0
  165. package/dist/heart/runtime-credentials.js +367 -0
  166. package/dist/heart/runtime-cwd.js +87 -0
  167. package/dist/heart/sense-truth.js +13 -4
  168. package/dist/heart/session-activity.js +48 -24
  169. package/dist/heart/session-events.js +1163 -0
  170. package/dist/heart/session-playback-cli-main.js +5 -0
  171. package/dist/heart/session-playback-cli.js +36 -0
  172. package/dist/heart/session-playback.js +231 -0
  173. package/dist/heart/session-stats-cli-main.js +5 -0
  174. package/dist/heart/session-stats.js +182 -0
  175. package/dist/heart/session-transcript.js +133 -0
  176. package/dist/heart/start-of-turn-packet.js +345 -0
  177. package/dist/heart/streaming.js +44 -27
  178. package/dist/heart/structured-output.js +196 -0
  179. package/dist/heart/sync-classification.js +176 -0
  180. package/dist/heart/sync.js +449 -0
  181. package/dist/heart/target-resolution.js +9 -5
  182. package/dist/heart/tempo.js +93 -0
  183. package/dist/heart/temporal-view.js +41 -0
  184. package/dist/heart/timeouts.js +101 -0
  185. package/dist/heart/tool-activity-callbacks.js +59 -0
  186. package/dist/heart/tool-description.js +143 -0
  187. package/dist/heart/tool-friction.js +55 -0
  188. package/dist/heart/tool-loop.js +200 -0
  189. package/dist/heart/turn-context.js +389 -0
  190. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  191. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  192. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  193. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  194. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  195. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  196. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  197. package/dist/mailbox-ui/assets/index-9-AxCxuB.js +61 -0
  198. package/dist/mailbox-ui/assets/index-CWzt267f.css +1 -0
  199. package/dist/mailbox-ui/index.html +15 -0
  200. package/dist/mailroom/attention.js +167 -0
  201. package/dist/mailroom/autonomy.js +209 -0
  202. package/dist/mailroom/blob-store.js +715 -0
  203. package/dist/mailroom/body-cache.js +61 -0
  204. package/dist/mailroom/core.js +788 -0
  205. package/dist/mailroom/entry.js +160 -0
  206. package/dist/mailroom/file-store.js +568 -0
  207. package/dist/mailroom/mbox-import.js +393 -0
  208. package/dist/mailroom/migration.js +164 -0
  209. package/dist/mailroom/outbound.js +380 -0
  210. package/dist/mailroom/policy.js +263 -0
  211. package/dist/mailroom/reader.js +233 -0
  212. package/dist/mailroom/search-cache.js +334 -0
  213. package/dist/mailroom/search-relevance.js +319 -0
  214. package/dist/mailroom/smtp-ingress.js +176 -0
  215. package/dist/mailroom/source-state.js +176 -0
  216. package/dist/mailroom/thread.js +109 -0
  217. package/dist/mailroom/travel-extract.js +89 -0
  218. package/dist/mind/bundle-manifest.js +14 -1
  219. package/dist/mind/context.js +251 -101
  220. package/dist/mind/desk-section.js +310 -0
  221. package/dist/mind/diary-integrity.js +60 -0
  222. package/dist/mind/{memory.js → diary.js} +68 -76
  223. package/dist/mind/embedding-provider.js +60 -0
  224. package/dist/mind/file-state.js +179 -0
  225. package/dist/mind/friends/channel.js +39 -0
  226. package/dist/mind/friends/resolver.js +54 -2
  227. package/dist/mind/friends/store-file.js +48 -4
  228. package/dist/mind/friends/types.js +2 -2
  229. package/dist/mind/journal-index.js +162 -0
  230. package/dist/mind/note-search.js +268 -0
  231. package/dist/mind/obligation-steering.js +221 -0
  232. package/dist/mind/pending.js +6 -1
  233. package/dist/mind/prompt-refresh.js +3 -2
  234. package/dist/mind/prompt.js +1075 -146
  235. package/dist/mind/provenance-trust.js +26 -0
  236. package/dist/mind/scrutiny.js +173 -0
  237. package/dist/nerves/cli-logging.js +7 -1
  238. package/dist/nerves/coverage/audit-rules.js +15 -6
  239. package/dist/nerves/coverage/audit.js +28 -2
  240. package/dist/nerves/coverage/cli.js +1 -1
  241. package/dist/nerves/coverage/contract.js +5 -5
  242. package/dist/nerves/coverage/file-completeness.js +139 -5
  243. package/dist/nerves/event-buffer.js +111 -0
  244. package/dist/nerves/index.js +224 -4
  245. package/dist/nerves/observation.js +20 -0
  246. package/dist/nerves/redact.js +79 -0
  247. package/dist/nerves/review/cli-main.js +5 -0
  248. package/dist/nerves/review/cli.js +156 -0
  249. package/dist/nerves/review/core.js +152 -0
  250. package/dist/nerves/runtime.js +5 -1
  251. package/dist/repertoire/ado-client.js +15 -56
  252. package/dist/repertoire/ado-semantic.js +16 -10
  253. package/dist/repertoire/api-client.js +97 -0
  254. package/dist/repertoire/bitwarden-store.js +1040 -0
  255. package/dist/repertoire/bundle-templates.js +72 -0
  256. package/dist/repertoire/bw-installer.js +180 -0
  257. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  258. package/dist/repertoire/coding/context-pack.js +331 -0
  259. package/dist/repertoire/coding/feedback.js +197 -30
  260. package/dist/repertoire/coding/manager.js +166 -10
  261. package/dist/repertoire/coding/spawner.js +55 -9
  262. package/dist/repertoire/coding/tools.js +219 -7
  263. package/dist/repertoire/commerce-errors.js +109 -0
  264. package/dist/repertoire/commerce-self-test.js +156 -0
  265. package/dist/repertoire/credential-access.js +178 -0
  266. package/dist/repertoire/desk/classifier.js +362 -0
  267. package/dist/repertoire/duffel-client.js +185 -0
  268. package/dist/repertoire/github-client.js +14 -55
  269. package/dist/repertoire/graph-client.js +11 -52
  270. package/dist/repertoire/guardrails.js +385 -0
  271. package/dist/repertoire/mcp-client.js +295 -0
  272. package/dist/repertoire/mcp-manager.js +403 -0
  273. package/dist/repertoire/mcp-tools.js +83 -0
  274. package/dist/repertoire/plugin-mcp.js +175 -0
  275. package/dist/repertoire/plugins.js +253 -0
  276. package/dist/repertoire/shell-sessions.js +133 -0
  277. package/dist/repertoire/skills.js +48 -4
  278. package/dist/repertoire/stripe-client.js +131 -0
  279. package/dist/repertoire/tool-results.js +29 -0
  280. package/dist/repertoire/tools-attachments.js +317 -0
  281. package/dist/repertoire/tools-awaiting.js +372 -0
  282. package/dist/repertoire/tools-base.js +59 -1082
  283. package/dist/repertoire/tools-bluebubbles.js +2 -0
  284. package/dist/repertoire/tools-bridge.js +144 -0
  285. package/dist/repertoire/tools-bundle.js +993 -0
  286. package/dist/repertoire/tools-config.js +186 -0
  287. package/dist/repertoire/tools-continuity.js +252 -0
  288. package/dist/repertoire/tools-credential.js +383 -0
  289. package/dist/repertoire/tools-evolution.js +527 -0
  290. package/dist/repertoire/tools-files.js +344 -0
  291. package/dist/repertoire/tools-flight.js +227 -0
  292. package/dist/repertoire/tools-flow.js +119 -0
  293. package/dist/repertoire/tools-github.js +3 -8
  294. package/dist/repertoire/tools-mail.js +1975 -0
  295. package/dist/repertoire/tools-notes.js +438 -0
  296. package/dist/repertoire/tools-obligations.js +143 -0
  297. package/dist/repertoire/tools-orientation.js +31 -0
  298. package/dist/repertoire/tools-record.js +464 -0
  299. package/dist/repertoire/tools-runtime.js +150 -0
  300. package/dist/repertoire/tools-session.js +766 -0
  301. package/dist/repertoire/tools-shell.js +120 -0
  302. package/dist/repertoire/tools-stripe.js +182 -0
  303. package/dist/repertoire/tools-surface.js +344 -0
  304. package/dist/repertoire/tools-teams.js +12 -39
  305. package/dist/repertoire/tools-travel.js +125 -0
  306. package/dist/repertoire/tools-trip.js +982 -0
  307. package/dist/repertoire/tools-user-profile.js +146 -0
  308. package/dist/repertoire/tools-vault.js +40 -0
  309. package/dist/repertoire/tools-voice.js +145 -0
  310. package/dist/repertoire/tools.js +215 -103
  311. package/dist/repertoire/travel-api-client.js +360 -0
  312. package/dist/repertoire/user-profile.js +131 -0
  313. package/dist/repertoire/vault-setup.js +246 -0
  314. package/dist/repertoire/vault-unlock.js +594 -0
  315. package/dist/scripts/claude-code-hook.js +41 -0
  316. package/dist/scripts/claude-code-stop-hook.js +47 -0
  317. package/dist/senses/attention-queue.js +186 -0
  318. package/dist/senses/await-turn-message.js +58 -0
  319. package/dist/senses/bluebubbles/active-turns.js +216 -0
  320. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  321. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  322. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  323. package/dist/senses/bluebubbles/entry.js +77 -0
  324. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  325. package/dist/senses/bluebubbles/index.js +2737 -0
  326. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  327. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  328. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  329. package/dist/senses/bluebubbles/processed-log.js +133 -0
  330. package/dist/senses/bluebubbles/replay.js +137 -0
  331. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  332. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  333. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  334. package/dist/senses/cli/bracketed-paste.js +82 -0
  335. package/dist/senses/cli/image-paste.js +287 -0
  336. package/dist/senses/cli/image-ref-navigation.js +75 -0
  337. package/dist/senses/cli/ink-app.js +156 -0
  338. package/dist/senses/cli/inline-diff.js +64 -0
  339. package/dist/senses/cli/input-keys.js +174 -0
  340. package/dist/senses/cli/kill-ring.js +86 -0
  341. package/dist/senses/cli/message-list.js +51 -0
  342. package/dist/senses/cli/ouro-tui.js +607 -0
  343. package/dist/senses/cli/spinner-imperative.js +135 -0
  344. package/dist/senses/cli/spinner.js +101 -0
  345. package/dist/senses/cli/status-line.js +60 -0
  346. package/dist/senses/cli/streaming-markdown.js +526 -0
  347. package/dist/senses/cli/tool-display.js +85 -0
  348. package/dist/senses/cli/tool-render.js +85 -0
  349. package/dist/senses/cli/tui-store.js +240 -0
  350. package/dist/senses/cli/virtual-list.js +35 -0
  351. package/dist/senses/cli-entry.js +60 -8
  352. package/dist/senses/cli-layout.js +100 -0
  353. package/dist/senses/cli.js +517 -204
  354. package/dist/senses/commands.js +66 -3
  355. package/dist/senses/habit-turn-message.js +108 -0
  356. package/dist/senses/inner-dialog-worker.js +254 -22
  357. package/dist/senses/inner-dialog.js +505 -40
  358. package/dist/senses/mail-entry.js +66 -0
  359. package/dist/senses/mail.js +379 -0
  360. package/dist/senses/pipeline.js +666 -181
  361. package/dist/senses/proactive-content-guard.js +51 -0
  362. package/dist/senses/shared-turn.js +393 -0
  363. package/dist/senses/surface-tool.js +108 -0
  364. package/dist/senses/teams-entry.js +60 -8
  365. package/dist/senses/teams.js +388 -98
  366. package/dist/senses/trust-gate.js +100 -5
  367. package/dist/senses/voice/audio-playback.js +237 -0
  368. package/dist/senses/voice/audio-routing.js +119 -0
  369. package/dist/senses/voice/elevenlabs.js +202 -0
  370. package/dist/senses/voice/floor-control.js +431 -0
  371. package/dist/senses/voice/floor-controller.js +115 -0
  372. package/dist/senses/voice/golden-path.js +116 -0
  373. package/dist/senses/voice/index.js +29 -0
  374. package/dist/senses/voice/meeting.js +113 -0
  375. package/dist/senses/voice/outbound.js +190 -0
  376. package/dist/senses/voice/phone.js +33 -0
  377. package/dist/senses/voice/playback.js +139 -0
  378. package/dist/senses/voice/realtime-eval.js +496 -0
  379. package/dist/senses/voice/realtime-trace.js +531 -0
  380. package/dist/senses/voice/transcript.js +70 -0
  381. package/dist/senses/voice/turn.js +191 -0
  382. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  383. package/dist/senses/voice/twilio-phone.js +5079 -0
  384. package/dist/senses/voice/types.js +2 -0
  385. package/dist/senses/voice/whisper.js +161 -0
  386. package/dist/senses/voice-entry.js +81 -0
  387. package/dist/senses/voice-realtime-eval-command.js +99 -0
  388. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  389. package/dist/senses/voice-twilio-entry.js +87 -0
  390. package/dist/trips/core.js +138 -0
  391. package/dist/trips/store.js +265 -0
  392. package/dist/util/frontmatter.js +53 -0
  393. package/package.json +48 -8
  394. package/skills/agent-commerce.md +106 -0
  395. package/skills/browser-navigation.md +117 -0
  396. package/skills/commerce-setup-guide.md +116 -0
  397. package/skills/commerce-setup.md +84 -0
  398. package/skills/configure-dev-tools.md +99 -0
  399. package/skills/travel-planning.md +138 -0
  400. package/dist/heart/daemon/auth-flow.js +0 -351
  401. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  402. package/dist/heart/safe-workspace.js +0 -228
  403. package/dist/heart/session-recall.js +0 -116
  404. package/dist/mind/associative-recall.js +0 -209
  405. package/dist/repertoire/tasks/board.js +0 -134
  406. package/dist/repertoire/tasks/index.js +0 -224
  407. package/dist/repertoire/tasks/lifecycle.js +0 -80
  408. package/dist/repertoire/tasks/middleware.js +0 -65
  409. package/dist/repertoire/tasks/parser.js +0 -173
  410. package/dist/repertoire/tasks/scanner.js +0 -132
  411. package/dist/repertoire/tasks/transitions.js +0 -144
  412. package/dist/senses/bluebubbles-entry.js +0 -13
  413. package/dist/senses/bluebubbles.js +0 -1177
  414. package/dist/senses/debug-activity.js +0 -148
  415. package/subagents/README.md +0 -7
  416. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  417. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  418. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  419. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  420. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  421. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  422. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  423. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  424. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  425. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  426. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  427. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  428. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  429. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  430. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  431. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  432. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ /**
3
+ * Startup TUI — real-time progress display for `ouro up`.
4
+ *
5
+ * Replaces the old `verifyDaemonAlive()` socket poll with a richer system
6
+ * that shows per-agent status, waits for stability, and reports degraded
7
+ * agents with actionable error information.
8
+ *
9
+ * Pure functions (`renderStartupProgress`, `assessStability`) are fully
10
+ * testable. The polling loop (`pollDaemonStartup`) uses dependency injection
11
+ * for all I/O.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.assessStability = assessStability;
15
+ exports.renderStartupProgress = renderStartupProgress;
16
+ exports.renderWaitingForDaemon = renderWaitingForDaemon;
17
+ exports.pollDaemonStartup = pollDaemonStartup;
18
+ const cli_render_1 = require("./cli-render");
19
+ const runtime_1 = require("../../nerves/runtime");
20
+ const terminal_ui_1 = require("./terminal-ui");
21
+ // ── Constants ──
22
+ const SPINNER_FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏";
23
+ const STABILITY_THRESHOLD_MS = 5_000;
24
+ const POLL_INTERVAL_MS = 500;
25
+ const STARTUP_POLL_TIMEOUT_MS = 180_000;
26
+ // ── ANSI helpers ──
27
+ const RESET = "\x1b[0m";
28
+ const BOLD = "\x1b[1m";
29
+ const DIM = "\x1b[2m";
30
+ const GREEN = "\x1b[38;2;46;204;64m";
31
+ const RED = "\x1b[38;2;231;76;60m";
32
+ const YELLOW = "\x1b[38;2;230;190;50m";
33
+ // ── Pure functions ──
34
+ /**
35
+ * Assess whether all workers have reached a terminal state (stable or crashed).
36
+ * A worker is "stable" when status is "running" and it has been running for
37
+ * at least STABILITY_THRESHOLD_MS. A worker is "definitively failed" when
38
+ * status is "crashed". All other states are unresolved.
39
+ */
40
+ function assessStability(payload, now) {
41
+ const stable = [];
42
+ const degraded = [];
43
+ let allResolved = true;
44
+ for (const worker of payload.workers) {
45
+ if (worker.status === "crashed") {
46
+ degraded.push({
47
+ agent: worker.agent,
48
+ errorReason: worker.errorReason ?? "unknown error",
49
+ fixHint: worker.fixHint ?? "check daemon logs",
50
+ });
51
+ }
52
+ else if (worker.status === "running" && worker.startedAt !== null) {
53
+ const startedMs = new Date(worker.startedAt).getTime();
54
+ const runningMs = now - startedMs;
55
+ if (runningMs >= STABILITY_THRESHOLD_MS) {
56
+ stable.push(worker.agent);
57
+ }
58
+ else {
59
+ allResolved = false;
60
+ }
61
+ }
62
+ else {
63
+ // starting, stopped, or running with null startedAt — not yet resolved
64
+ allResolved = false;
65
+ }
66
+ }
67
+ return { resolved: allResolved, stable, degraded };
68
+ }
69
+ /**
70
+ * Build an ANSI string for in-place terminal display during polling.
71
+ * Uses cursor-up and line-clear escapes to overwrite previous output.
72
+ */
73
+ function renderStartupProgress(payload, elapsed, prevLineCount = 0, options = {}) {
74
+ const isTTY = options.isTTY ?? true;
75
+ const frameIndex = Math.floor(elapsed / 100) % SPINNER_FRAMES.length;
76
+ const spinner = SPINNER_FRAMES[frameIndex];
77
+ const lines = [];
78
+ const elapsedSec = (elapsed / 1000).toFixed(1);
79
+ lines.push(isTTY
80
+ ? `${spinner} ${BOLD}waiting for agents${RESET} ${DIM}(${elapsedSec}s)${RESET}`
81
+ : `${spinner} waiting for agents (${elapsedSec}s)`);
82
+ for (const worker of payload.workers) {
83
+ const statusText = isTTY ? colorStatus(worker.status) : worker.status;
84
+ lines.push(` ${worker.agent}/${worker.worker}: ${statusText}`);
85
+ }
86
+ return renderStartupLines(lines, prevLineCount, isTTY);
87
+ }
88
+ /**
89
+ * Render a pre-socket status line showing what the daemon is doing.
90
+ */
91
+ function renderWaitingForDaemon(elapsed, latestEvent, prevLineCount = 0, options = {}) {
92
+ const isTTY = options.isTTY ?? true;
93
+ const elapsedSec = (elapsed / 1000).toFixed(1);
94
+ const frameIndex = Math.floor(elapsed / 100) % SPINNER_FRAMES.length;
95
+ const spinner = SPINNER_FRAMES[frameIndex];
96
+ const lines = [];
97
+ lines.push(isTTY
98
+ ? `${spinner} ${BOLD}starting background service${RESET} ${DIM}(${elapsedSec}s)${RESET}`
99
+ : `${spinner} starting background service (${elapsedSec}s)`);
100
+ if (latestEvent) {
101
+ const detail = `latest daemon event: ${latestEvent}`;
102
+ lines.push(isTTY ? ` ${DIM}${detail}${RESET}` : ` ${detail}`);
103
+ }
104
+ return renderStartupLines(lines, prevLineCount, isTTY);
105
+ }
106
+ /**
107
+ * Render the final summary after all agents have resolved.
108
+ */
109
+ function renderFinalSummary(result, isTTY) {
110
+ const lines = [];
111
+ for (const agent of result.stable) {
112
+ lines.push(isTTY ? ` ${GREEN}\u2713${RESET} ${agent}: ${GREEN}stable${RESET}` : ` \u2713 ${agent}: stable`);
113
+ }
114
+ for (const d of result.degraded) {
115
+ lines.push(isTTY ? ` ${RED}\u2717${RESET} ${d.agent}: ${RED}degraded${RESET}` : ` \u2717 ${d.agent}: degraded`);
116
+ if (d.errorReason !== "unknown error") {
117
+ lines.push(isTTY ? ` ${DIM}error: ${d.errorReason}${RESET}` : ` error: ${d.errorReason}`);
118
+ }
119
+ if (d.fixHint !== "check daemon logs") {
120
+ lines.push(isTTY ? ` ${DIM}fix: ${d.fixHint}${RESET}` : ` fix: ${d.fixHint}`);
121
+ }
122
+ }
123
+ if (!isTTY)
124
+ return lines.join("\n") + "\n";
125
+ return lines.map((line) => `\x1b[2K${line}`).join("\n") + "\n";
126
+ }
127
+ // ── Polling loop ──
128
+ /**
129
+ * Poll the daemon's status socket until all agents are stable or definitively
130
+ * failed, rendering real-time progress to the terminal.
131
+ *
132
+ * Detects daemon process death: if the spawned PID is no longer alive and the
133
+ * socket never came up, reports the failure immediately instead of spinning.
134
+ */
135
+ async function pollDaemonStartup(deps) {
136
+ const startTime = deps.now();
137
+ const maxWaitMs = deps.maxWaitMs ?? STARTUP_POLL_TIMEOUT_MS;
138
+ let prevLineCount = 0;
139
+ const isTTY = deps.isTTY ?? true;
140
+ const isAlive = deps.isProcessAlive ?? defaultIsProcessAlive;
141
+ const shouldRender = deps.render ?? true;
142
+ let lastProgress = null;
143
+ const reportProgress = (message) => {
144
+ if (!deps.onProgress || message === lastProgress)
145
+ return;
146
+ lastProgress = message;
147
+ deps.onProgress(message);
148
+ };
149
+ (0, runtime_1.emitNervesEvent)({
150
+ component: "daemon",
151
+ event: "daemon.startup_poll_start",
152
+ message: "beginning startup stability polling",
153
+ meta: { socketPath: deps.socketPath, daemonPid: deps.daemonPid },
154
+ });
155
+ while (true) {
156
+ const now = deps.now();
157
+ const elapsed = now - startTime;
158
+ let payload = null;
159
+ try {
160
+ const response = await deps.sendCommand(deps.socketPath, { kind: "daemon.status" });
161
+ payload = (0, cli_render_1.parseStatusPayload)(response.data);
162
+ }
163
+ catch {
164
+ // Socket not yet available — check if the daemon process is still alive
165
+ if (deps.daemonPid !== null && !isAlive(deps.daemonPid)) {
166
+ const latestEvent = deps.readLatestDaemonEvent?.() ?? null;
167
+ const errorMsg = latestEvent ?? "daemon process died during startup";
168
+ (0, runtime_1.emitNervesEvent)({
169
+ level: "error",
170
+ component: "daemon",
171
+ event: "daemon.startup_process_died",
172
+ message: "daemon process died before socket came up",
173
+ meta: { pid: deps.daemonPid, lastEvent: latestEvent },
174
+ });
175
+ // Clear the waiting line
176
+ if (isTTY && prevLineCount > 0) {
177
+ let clear = `\x1b[${prevLineCount}A`;
178
+ for (let i = 0; i < prevLineCount; i++)
179
+ clear += `\x1b[2K\n`;
180
+ deps.writeRaw(clear);
181
+ }
182
+ return {
183
+ stable: [],
184
+ degraded: [{ agent: "daemon", errorReason: errorMsg, fixHint: "check daemon logs or run `ouro doctor`" }],
185
+ };
186
+ }
187
+ const latestEvent = deps.readLatestDaemonEvent?.() ?? null;
188
+ if (elapsed >= maxWaitMs) {
189
+ const errorMsg = latestEvent
190
+ ? `daemon did not answer within ${(maxWaitMs / 1000).toFixed(0)}s; latest event: ${latestEvent}`
191
+ : `daemon did not answer within ${(maxWaitMs / 1000).toFixed(0)}s`;
192
+ const result = {
193
+ stable: [],
194
+ degraded: [{ agent: "daemon", errorReason: errorMsg, fixHint: "check daemon logs or run `ouro doctor`" }],
195
+ };
196
+ if (shouldRender) {
197
+ const summary = renderFinalSummary(result, isTTY);
198
+ deps.writeRaw(summary);
199
+ }
200
+ (0, runtime_1.emitNervesEvent)({
201
+ level: "error",
202
+ component: "daemon",
203
+ event: "daemon.startup_poll_timeout",
204
+ message: "daemon startup polling timed out before the daemon answered",
205
+ meta: { socketPath: deps.socketPath, daemonPid: deps.daemonPid, elapsedMs: elapsed, maxWaitMs, lastEvent: latestEvent },
206
+ });
207
+ return result;
208
+ }
209
+ // Show what the daemon is doing from its log
210
+ reportProgress([
211
+ "waiting for Ouro to answer",
212
+ latestEvent ? `- latest daemon event: ${latestEvent}` : "- background service is still starting",
213
+ ].join("\n"));
214
+ if (shouldRender) {
215
+ const output = renderWaitingForDaemon(elapsed, latestEvent, prevLineCount, { isTTY });
216
+ deps.writeRaw(output);
217
+ prevLineCount = latestEvent ? 2 : 1;
218
+ }
219
+ }
220
+ if (payload) {
221
+ reportProgress(formatStartupProgressDetail(payload));
222
+ if (shouldRender) {
223
+ const output = renderStartupProgress(payload, elapsed, prevLineCount, { isTTY });
224
+ deps.writeRaw(output);
225
+ prevLineCount = payload.workers.length + 1;
226
+ }
227
+ const assessment = assessStability(payload, now);
228
+ if (assessment.resolved) {
229
+ const result = {
230
+ stable: assessment.stable,
231
+ degraded: assessment.degraded,
232
+ };
233
+ if (shouldRender) {
234
+ const summary = renderFinalSummary(result, isTTY);
235
+ deps.writeRaw(summary);
236
+ }
237
+ (0, runtime_1.emitNervesEvent)({
238
+ component: "daemon",
239
+ event: "daemon.startup_poll_end",
240
+ message: "startup polling complete",
241
+ meta: {
242
+ stableCount: result.stable.length,
243
+ degradedCount: result.degraded.length,
244
+ elapsedMs: elapsed,
245
+ },
246
+ });
247
+ return result;
248
+ }
249
+ if (elapsed >= maxWaitMs) {
250
+ const result = buildTimedOutStartupResult(payload, assessment, maxWaitMs);
251
+ if (shouldRender) {
252
+ const summary = renderFinalSummary(result, isTTY);
253
+ deps.writeRaw(summary);
254
+ }
255
+ (0, runtime_1.emitNervesEvent)({
256
+ level: "error",
257
+ component: "daemon",
258
+ event: "daemon.startup_poll_timeout",
259
+ message: "daemon startup polling timed out with unresolved workers",
260
+ meta: {
261
+ socketPath: deps.socketPath,
262
+ daemonPid: deps.daemonPid,
263
+ elapsedMs: elapsed,
264
+ maxWaitMs,
265
+ stableCount: result.stable.length,
266
+ degradedCount: result.degraded.length,
267
+ },
268
+ });
269
+ return result;
270
+ }
271
+ }
272
+ await deps.sleep(POLL_INTERVAL_MS);
273
+ }
274
+ }
275
+ function buildTimedOutStartupResult(payload, assessment, maxWaitMs) {
276
+ const stable = [...assessment.stable];
277
+ const degraded = [...assessment.degraded];
278
+ const stableAgents = new Set(stable);
279
+ const degradedAgents = new Set();
280
+ for (const worker of degraded)
281
+ degradedAgents.add(worker.agent);
282
+ const seconds = (maxWaitMs / 1000).toFixed(0);
283
+ for (const worker of payload.workers) {
284
+ if (stableAgents.has(worker.agent) || degradedAgents.has(worker.agent))
285
+ continue;
286
+ degraded.push({
287
+ agent: worker.agent,
288
+ errorReason: `startup timed out after ${seconds}s while worker was ${worker.status}`,
289
+ fixHint: worker.errorReason
290
+ ? worker.fixHint ?? "check daemon logs"
291
+ : "run `ouro status` or `ouro doctor` for current worker details; the daemon is still answering",
292
+ });
293
+ }
294
+ return { stable, degraded };
295
+ }
296
+ function formatStartupWorkerLine(payload) {
297
+ const base = `- ${payload.agent}/${payload.worker}: ${payload.status}`;
298
+ if (payload.status === "crashed" && payload.errorReason) {
299
+ return `${base} (${payload.errorReason})`;
300
+ }
301
+ return base;
302
+ }
303
+ function formatStartupProgressDetail(payload) {
304
+ if (payload.workers.length === 0)
305
+ return "Ouro answered";
306
+ return [
307
+ "Ouro answered",
308
+ ...payload.workers.map((worker) => formatStartupWorkerLine(worker)),
309
+ ].join("\n");
310
+ }
311
+ function colorStatus(status) {
312
+ const statusColor = status === "running" ? GREEN
313
+ : status === "crashed" ? RED
314
+ : YELLOW;
315
+ return `${statusColor}${status}${RESET}`;
316
+ }
317
+ function renderStartupLines(lines, prevLineCount, isTTY) {
318
+ return (0, terminal_ui_1.renderOverwriteFrame)(lines, prevLineCount, isTTY);
319
+ }
320
+ /* v8 ignore start -- process liveness check: uses real process.kill(0), tested via deployment @preserve */
321
+ function defaultIsProcessAlive(pid) {
322
+ try {
323
+ process.kill(pid, 0);
324
+ return true;
325
+ }
326
+ catch {
327
+ return false;
328
+ }
329
+ }
330
+ /* v8 ignore stop */
@@ -38,7 +38,8 @@ const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  const identity_1 = require("../identity");
40
40
  const runtime_1 = require("../../nerves/runtime");
41
- const parser_1 = require("../../repertoire/tasks/parser");
41
+ const frontmatter_1 = require("../../util/frontmatter");
42
+ const cadence_1 = require("./cadence");
42
43
  function walkMarkdownFiles(root, readdirSync, existsSync, files) {
43
44
  if (!existsSync(root))
44
45
  return;
@@ -53,29 +54,6 @@ function walkMarkdownFiles(root, readdirSync, existsSync, files) {
53
54
  }
54
55
  }
55
56
  }
56
- function parseCadence(raw) {
57
- if (typeof raw !== "string")
58
- return null;
59
- const value = raw.trim();
60
- if (!value)
61
- return null;
62
- // Cron format (minute hour day month weekday)
63
- if (/^\S+\s+\S+\s+\S+\s+\S+\s+\S+$/.test(value)) {
64
- return value;
65
- }
66
- const cadenceMatch = /^(\d+)(m|h|d)$/.exec(value);
67
- if (!cadenceMatch)
68
- return null;
69
- const interval = Number.parseInt(cadenceMatch[1], 10);
70
- if (!Number.isFinite(interval) || interval <= 0)
71
- return null;
72
- const unit = cadenceMatch[2];
73
- if (unit === "m")
74
- return `*/${interval} * * * *`;
75
- if (unit === "h")
76
- return `0 */${interval} * * *`;
77
- return `0 0 */${interval} * *`;
78
- }
79
57
  function parseScheduledAt(raw) {
80
58
  if (typeof raw !== "string")
81
59
  return null;
@@ -91,9 +69,70 @@ function parseScheduledAt(raw) {
91
69
  const month = date.getUTCMonth() + 1;
92
70
  return `${minute} ${hour} ${day} ${month} *`;
93
71
  }
94
- function removeRuntimeFrontmatter(frontmatter) {
95
- const { _isCanonicalFilename, ...clean } = frontmatter;
96
- return clean;
72
+ /**
73
+ * Parse a task markdown file into the minimum scheduler-relevant projection.
74
+ * Inlines the previous `parseTaskFile` shape (only what the scheduler reads),
75
+ * so we don't depend on `src/repertoire/tasks/parser`. The shared
76
+ * `parseFrontmatter` util handles the YAML-ish frontmatter format.
77
+ */
78
+ function parseSchedulerTask(content, filePath) {
79
+ (0, runtime_1.emitNervesEvent)({
80
+ event: "daemon.scheduler_task_parse",
81
+ component: "daemon",
82
+ message: "parsing scheduler task file",
83
+ meta: { filePath },
84
+ });
85
+ const lines = content.split(/\r?\n/);
86
+ if (lines[0]?.trim() !== "---") {
87
+ throw new Error("task file missing frontmatter");
88
+ }
89
+ const closing = lines.findIndex((line, index) => index > 0 && line.trim() === "---");
90
+ if (closing === -1) {
91
+ throw new Error("task file has unterminated frontmatter");
92
+ }
93
+ const rawFrontmatter = lines.slice(1, closing).join("\n");
94
+ const body = lines.slice(closing + 1).join("\n").trim();
95
+ const frontmatter = (0, frontmatter_1.parseFrontmatter)(rawFrontmatter);
96
+ const name = path.basename(filePath);
97
+ const stem = name.replace(/\.md$/i, "");
98
+ const rawStatus = typeof frontmatter.status === "string" ? frontmatter.status : "";
99
+ return { stem, status: rawStatus, frontmatter, body };
100
+ }
101
+ function formatFrontmatterValue(value) {
102
+ if (Array.isArray(value)) {
103
+ if (value.length === 0)
104
+ return ["[]"];
105
+ return ["", ...value.map((entry) => `- ${String(entry)}`)];
106
+ }
107
+ if (value === null)
108
+ return ["null"];
109
+ return [String(value)];
110
+ }
111
+ /**
112
+ * Render a frontmatter+body markdown file. Inlined from the previous
113
+ * `renderTaskFile` (in `src/repertoire/tasks/parser`) so the scheduler can
114
+ * update `lastRun` without depending on the task module.
115
+ */
116
+ function renderSchedulerTask(frontmatter, body) {
117
+ const keys = Object.keys(frontmatter);
118
+ const lines = ["---"];
119
+ for (const key of keys) {
120
+ const rendered = formatFrontmatterValue(frontmatter[key]);
121
+ if (rendered.length === 1) {
122
+ lines.push(`${key}: ${rendered[0]}`);
123
+ }
124
+ else {
125
+ lines.push(`${key}:`);
126
+ for (const entry of rendered.slice(1)) {
127
+ lines.push(entry);
128
+ }
129
+ }
130
+ }
131
+ lines.push("---");
132
+ lines.push("");
133
+ lines.push(body.trim());
134
+ lines.push("");
135
+ return lines.join("\n");
97
136
  }
98
137
  class TaskDrivenScheduler {
99
138
  agents;
@@ -135,29 +174,68 @@ class TaskDrivenScheduler {
135
174
  await this.recordTaskRun(job.agent, job.taskId);
136
175
  return { ok: true, message: `triggered ${jobId}` };
137
176
  }
177
+ /**
178
+ * Discover scheduler-eligible task files across both surfaces:
179
+ * - legacy: `<bundle>/tasks/{one-shots,ongoing}/**\/*.md`
180
+ * - desk: `<bundle>/desk/<track>/<task-slug>/task.md`
181
+ *
182
+ * Dual-read is intentional during the W6 transition: old harnesses still
183
+ * write to `tasks/`; new harnesses + agents write to `desk/`. The scheduler
184
+ * accepts both.
185
+ */
186
+ collectTaskFiles(agent) {
187
+ const bundleRoot = path.join(this.bundlesRoot, `${agent}.ouro`);
188
+ const files = [];
189
+ // Legacy `tasks/{one-shots,ongoing}/` collections.
190
+ const legacyRoot = path.join(bundleRoot, "tasks");
191
+ for (const collection of ["one-shots", "ongoing"]) {
192
+ walkMarkdownFiles(path.join(legacyRoot, collection), this.readdirSync, this.existsSync, files);
193
+ }
194
+ // New `desk/<track>/<task-slug>/task.md` shape.
195
+ const deskRoot = path.join(bundleRoot, "desk");
196
+ if (this.existsSync(deskRoot)) {
197
+ for (const trackEntry of this.readdirSync(deskRoot, { withFileTypes: true })) {
198
+ if (!trackEntry.isDirectory())
199
+ continue;
200
+ if (trackEntry.name.startsWith("_") || trackEntry.name.startsWith("."))
201
+ continue;
202
+ const trackDir = path.join(deskRoot, trackEntry.name);
203
+ for (const taskEntry of this.readdirSync(trackDir, { withFileTypes: true })) {
204
+ if (!taskEntry.isDirectory())
205
+ continue;
206
+ if (taskEntry.name.startsWith("_") || taskEntry.name.startsWith("."))
207
+ continue;
208
+ const taskFile = path.join(trackDir, taskEntry.name, "task.md");
209
+ if (this.existsSync(taskFile))
210
+ files.push(taskFile);
211
+ }
212
+ }
213
+ }
214
+ return files;
215
+ }
138
216
  async reconcile() {
139
217
  const nextJobs = new Map();
140
218
  const nextTaskPaths = new Map();
141
219
  for (const agent of this.agents) {
142
- const taskRoot = path.join(this.bundlesRoot, `${agent}.ouro`, "tasks");
143
- const collections = ["one-shots", "ongoing", "habits"];
144
- const files = [];
145
- for (const collection of collections) {
146
- walkMarkdownFiles(path.join(taskRoot, collection), this.readdirSync, this.existsSync, files);
147
- }
220
+ const files = this.collectTaskFiles(agent);
148
221
  for (const filePath of files) {
149
222
  let task;
150
223
  try {
151
- task = (0, parser_1.parseTaskFile)(this.readFileSync(filePath, "utf-8"), filePath);
224
+ task = parseSchedulerTask(this.readFileSync(filePath, "utf-8"), filePath);
152
225
  }
153
226
  catch {
154
227
  continue;
155
228
  }
156
- const taskId = task.stem;
229
+ // Desk task files live at `desk/<track>/<task-slug>/task.md`, so the
230
+ // markdown basename is "task" — use the parent directory name as the
231
+ // stable slug. Legacy `tasks/<collection>/<stem>.md` keeps the
232
+ // filename stem.
233
+ const isDeskTask = path.basename(filePath) === "task.md";
234
+ const taskId = isDeskTask ? path.basename(path.dirname(filePath)) : task.stem;
157
235
  nextTaskPaths.set(`${agent}:${taskId}`, filePath);
158
236
  if (task.status === "done")
159
237
  continue;
160
- const cadence = parseCadence(task.frontmatter.cadence);
238
+ const cadence = (0, cadence_1.parseCadenceToCron)(task.frontmatter.cadence);
161
239
  if (cadence) {
162
240
  const id = `${agent}:${taskId}:cadence`;
163
241
  nextJobs.set(id, {
@@ -212,18 +290,18 @@ class TaskDrivenScheduler {
212
290
  }
213
291
  let parsed;
214
292
  try {
215
- parsed = (0, parser_1.parseTaskFile)(this.readFileSync(taskPath, "utf-8"), taskPath);
293
+ parsed = parseSchedulerTask(this.readFileSync(taskPath, "utf-8"), taskPath);
216
294
  }
217
295
  catch {
218
296
  return;
219
297
  }
220
298
  const now = this.nowIso();
221
- const frontmatter = removeRuntimeFrontmatter(parsed.frontmatter);
299
+ const frontmatter = { ...parsed.frontmatter };
222
300
  frontmatter.lastRun = now;
223
301
  if (typeof frontmatter.updated === "string") {
224
302
  frontmatter.updated = now.slice(0, 10);
225
303
  }
226
- this.writeFileSync(taskPath, (0, parser_1.renderTaskFile)(frontmatter, parsed.body), "utf-8");
304
+ this.writeFileSync(taskPath, renderSchedulerTask(frontmatter, parsed.body), "utf-8");
227
305
  for (const job of this.jobs.values()) {
228
306
  if (job.agent === agent && job.taskId === taskId) {
229
307
  job.lastRun = now;