@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831

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 (647) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5308 -16
  16. package/deploy/unraid/Dockerfile +54 -0
  17. package/deploy/unraid/README.txt +2983 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  34. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  35. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
  36. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  37. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  38. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  39. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  40. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  41. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  42. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
  43. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
  49. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  50. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
  51. package/deploy/unraid/sanctuary.xml +28 -0
  52. package/dist/a2a/card.js +57 -0
  53. package/dist/a2a/client.js +180 -0
  54. package/dist/a2a/config.js +50 -0
  55. package/dist/a2a/delegation-stores.js +56 -0
  56. package/dist/a2a/did-resolution.js +93 -0
  57. package/dist/a2a/identity.js +170 -0
  58. package/dist/a2a/inbound-share.js +107 -0
  59. package/dist/a2a/mission-result-wire.js +196 -0
  60. package/dist/a2a/onboarding.js +115 -0
  61. package/dist/a2a/pin-store.js +132 -0
  62. package/dist/a2a/seen-ledger.js +120 -0
  63. package/dist/a2a/server.js +604 -0
  64. package/dist/a2a/task-store.js +69 -0
  65. package/dist/a2a/transport.js +45 -0
  66. package/dist/a2a/types.js +3 -0
  67. package/dist/arc/attention-types.js +8 -0
  68. package/dist/arc/cares.js +360 -0
  69. package/dist/arc/episodes.js +118 -0
  70. package/dist/arc/evolution.js +490 -0
  71. package/dist/arc/flight-recorder.js +1034 -0
  72. package/dist/arc/intentions.js +134 -0
  73. package/dist/arc/json-store.js +117 -0
  74. package/dist/arc/obligations.js +386 -0
  75. package/dist/arc/packets.js +336 -0
  76. package/dist/arc/presence.js +185 -0
  77. package/dist/arc/task-lifecycle.js +57 -0
  78. package/dist/commerce/store.js +755 -0
  79. package/dist/commerce/types.js +3 -0
  80. package/dist/heart/active-work.js +798 -40
  81. package/dist/heart/agent-entry.js +252 -3
  82. package/dist/heart/approval-files.js +113 -0
  83. package/dist/heart/approval-store.js +960 -0
  84. package/dist/heart/attachments/image-normalize.js +194 -0
  85. package/dist/heart/attachments/materialize.js +97 -0
  86. package/dist/heart/attachments/originals.js +88 -0
  87. package/dist/heart/attachments/render.js +29 -0
  88. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  89. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  90. package/dist/heart/attachments/sources/index.js +18 -0
  91. package/dist/heart/attachments/sources/telegram.js +71 -0
  92. package/dist/heart/attachments/store.js +132 -0
  93. package/dist/heart/attachments/types.js +93 -0
  94. package/dist/heart/auth/auth-flow.js +495 -0
  95. package/dist/heart/autonomy-budget.js +478 -0
  96. package/dist/heart/awaiting/await-alert.js +148 -0
  97. package/dist/heart/awaiting/await-expiry.js +143 -0
  98. package/dist/heart/awaiting/await-loader.js +91 -0
  99. package/dist/heart/awaiting/await-parser.js +149 -0
  100. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  101. package/dist/heart/awaiting/await-scheduler.js +382 -0
  102. package/dist/heart/background-operations.js +281 -0
  103. package/dist/heart/bridges/manager.js +137 -17
  104. package/dist/heart/bridges/store.js +14 -2
  105. package/dist/heart/bundle-state.js +168 -0
  106. package/dist/heart/commitments.js +44 -18
  107. package/dist/heart/config-registry.js +331 -0
  108. package/dist/heart/config.js +174 -131
  109. package/dist/heart/context-loss-gauntlet.js +387 -0
  110. package/dist/heart/context-loss-sentinel.js +1157 -0
  111. package/dist/heart/core.js +2169 -581
  112. package/dist/heart/cross-chat-delivery.js +9 -22
  113. package/dist/heart/daemon/agent-config-check.js +451 -0
  114. package/dist/heart/daemon/agent-discovery.js +185 -3
  115. package/dist/heart/daemon/agent-service.js +542 -0
  116. package/dist/heart/daemon/agentic-repair.js +547 -0
  117. package/dist/heart/daemon/await-private-wake.js +59 -0
  118. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  119. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  120. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  121. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  122. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  123. package/dist/heart/daemon/cadence.js +180 -0
  124. package/dist/heart/daemon/cli-defaults.js +854 -0
  125. package/dist/heart/daemon/cli-desk.js +322 -0
  126. package/dist/heart/daemon/cli-exec.js +8822 -0
  127. package/dist/heart/daemon/cli-help.js +716 -0
  128. package/dist/heart/daemon/cli-parse.js +2771 -0
  129. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  130. package/dist/heart/daemon/cli-render.js +777 -0
  131. package/dist/heart/daemon/cli-types.js +8 -0
  132. package/dist/heart/daemon/connect-bay.js +323 -0
  133. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  134. package/dist/heart/daemon/container-healthcheck.js +112 -0
  135. package/dist/heart/daemon/container-runtime.js +97 -0
  136. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  137. package/dist/heart/daemon/container-spec-auditor.js +229 -0
  138. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  139. package/dist/heart/daemon/daemon-cli.js +29 -2349
  140. package/dist/heart/daemon/daemon-entry.js +930 -11
  141. package/dist/heart/daemon/daemon-health.js +186 -0
  142. package/dist/heart/daemon/daemon-rollup.js +57 -0
  143. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  144. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  145. package/dist/heart/daemon/daemon.js +2084 -105
  146. package/dist/heart/daemon/dns-workflow.js +394 -0
  147. package/dist/heart/daemon/doctor-types.js +8 -0
  148. package/dist/heart/daemon/doctor.js +1755 -0
  149. package/dist/heart/daemon/freshness.js +345 -0
  150. package/dist/heart/daemon/habit-private-wake.js +61 -0
  151. package/dist/heart/daemon/health-monitor.js +142 -11
  152. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  153. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  154. package/dist/heart/daemon/http-health-probe.js +80 -0
  155. package/dist/heart/daemon/human-command-screens.js +234 -0
  156. package/dist/heart/daemon/human-readiness.js +114 -0
  157. package/dist/heart/daemon/inner-status.js +78 -0
  158. package/dist/heart/daemon/interactive-repair.js +394 -0
  159. package/dist/heart/daemon/launchd.js +37 -8
  160. package/dist/heart/daemon/log-tailer.js +79 -10
  161. package/dist/heart/daemon/logs-prune.js +132 -0
  162. package/dist/heart/daemon/mcp-canary.js +524 -0
  163. package/dist/heart/daemon/message-router.js +65 -5
  164. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  165. package/dist/heart/daemon/os-cron-deps.js +135 -0
  166. package/dist/heart/daemon/os-cron.js +22 -14
  167. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  168. package/dist/heart/daemon/ouro-entry.js +3 -1
  169. package/dist/heart/daemon/plugin-cli.js +432 -0
  170. package/dist/heart/daemon/process-manager.js +733 -61
  171. package/dist/heart/daemon/provider-discovery.js +137 -0
  172. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  173. package/dist/heart/daemon/prunable-bundle.js +144 -0
  174. package/dist/heart/daemon/pulse.js +511 -0
  175. package/dist/heart/daemon/readiness-repair.js +365 -0
  176. package/dist/heart/daemon/run-hooks.js +2 -0
  177. package/dist/heart/daemon/runtime-logging.js +47 -14
  178. package/dist/heart/daemon/runtime-metadata.js +2 -30
  179. package/dist/heart/daemon/runtime-mode.js +13 -2
  180. package/dist/heart/daemon/safe-mode.js +161 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  184. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  185. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  186. package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
  187. package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
  188. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  189. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
  190. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  191. package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
  192. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  193. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
  194. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  195. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  196. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  197. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  198. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  199. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  200. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  201. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
  202. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  203. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
  204. package/dist/heart/daemon/sense-manager.js +699 -48
  205. package/dist/heart/daemon/session-id-resolver.js +131 -0
  206. package/dist/heart/daemon/skill-management-installer.js +1 -1
  207. package/dist/heart/daemon/socket-client.js +180 -12
  208. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  209. package/dist/heart/daemon/startup-tui.js +339 -0
  210. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  211. package/dist/heart/daemon/task-scheduler.js +117 -39
  212. package/dist/heart/daemon/terminal-ui.js +499 -0
  213. package/dist/heart/daemon/thoughts.js +138 -54
  214. package/dist/heart/daemon/up-progress.js +366 -0
  215. package/dist/heart/daemon/vault-items.js +56 -0
  216. package/dist/heart/delegation.js +1 -4
  217. package/dist/heart/external-events/router.js +1430 -0
  218. package/dist/heart/frontend-approval-runtime.js +506 -0
  219. package/dist/heart/frontend-journal.js +215 -0
  220. package/dist/heart/frontend-session-service.js +237 -0
  221. package/dist/heart/frontend-socket-client.js +164 -0
  222. package/dist/heart/frontend-socket.js +400 -0
  223. package/dist/heart/habits/habit-cancel.js +810 -0
  224. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  225. package/dist/heart/habits/habit-migration.js +194 -0
  226. package/dist/heart/habits/habit-parser.js +278 -0
  227. package/dist/heart/habits/habit-runtime-state.js +93 -0
  228. package/dist/heart/habits/habit-scheduler.js +653 -0
  229. package/dist/heart/habits/habit-session-summary.js +318 -0
  230. package/dist/heart/habits/habit-session.js +636 -0
  231. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  232. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  233. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  234. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  235. package/dist/heart/identity.js +196 -59
  236. package/dist/heart/kept-notes.js +289 -0
  237. package/dist/heart/kicks.js +1 -1
  238. package/dist/heart/machine-identity.js +161 -0
  239. package/dist/heart/mail-import-discovery.js +356 -0
  240. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  241. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  242. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  243. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  244. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  245. package/dist/heart/mailbox/mailbox-http.js +99 -0
  246. package/dist/heart/mailbox/mailbox-read.js +39 -0
  247. package/dist/heart/mailbox/mailbox-types.js +27 -0
  248. package/dist/heart/mailbox/mailbox-view.js +197 -0
  249. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  250. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  251. package/dist/heart/mailbox/readers/mail.js +375 -0
  252. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  253. package/dist/heart/mailbox/readers/sessions.js +231 -0
  254. package/dist/heart/mailbox/readers/shared.js +111 -0
  255. package/dist/heart/mcp/mcp-server.js +696 -0
  256. package/dist/heart/migrate-config.js +100 -0
  257. package/dist/heart/model-capabilities.js +11 -0
  258. package/dist/heart/orientation-frame.js +345 -0
  259. package/dist/heart/platform.js +81 -0
  260. package/dist/heart/primitives.js +1 -1
  261. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  262. package/dist/heart/private-runtime/index.js +18 -0
  263. package/dist/heart/private-runtime/ledger.js +221 -0
  264. package/dist/heart/private-runtime/policy.js +252 -0
  265. package/dist/heart/private-runtime/types.js +2 -0
  266. package/dist/heart/progress-story.js +1 -1
  267. package/dist/heart/provider-attempt.js +137 -0
  268. package/dist/heart/provider-binding-resolver.js +273 -0
  269. package/dist/heart/provider-credentials.js +449 -0
  270. package/dist/heart/provider-failover.js +311 -0
  271. package/dist/heart/provider-models.js +96 -0
  272. package/dist/heart/provider-ping.js +265 -0
  273. package/dist/heart/provider-readiness-cache.js +119 -0
  274. package/dist/heart/provider-visibility.js +188 -0
  275. package/dist/heart/providers/anthropic-token.js +131 -0
  276. package/dist/heart/providers/anthropic.js +173 -60
  277. package/dist/heart/providers/azure.js +23 -11
  278. package/dist/heart/providers/error-classification.js +127 -0
  279. package/dist/heart/providers/github-copilot.js +34 -38
  280. package/dist/heart/providers/minimax-vlm.js +189 -0
  281. package/dist/heart/providers/minimax.js +26 -8
  282. package/dist/heart/providers/openai-codex-token.js +349 -0
  283. package/dist/heart/providers/openai-codex.js +55 -40
  284. package/dist/heart/providers/openai-compatible.js +177 -0
  285. package/dist/heart/run-ledger.js +247 -0
  286. package/dist/heart/runtime-capability-check.js +170 -0
  287. package/dist/heart/runtime-credentials.js +607 -0
  288. package/dist/heart/runtime-cwd.js +87 -0
  289. package/dist/heart/sense-truth.js +22 -4
  290. package/dist/heart/session-activity.js +92 -24
  291. package/dist/heart/session-events.js +1504 -0
  292. package/dist/heart/session-playback-cli-main.js +5 -0
  293. package/dist/heart/session-playback-cli.js +36 -0
  294. package/dist/heart/session-playback.js +231 -0
  295. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  296. package/dist/heart/session-redaction-repair.js +552 -0
  297. package/dist/heart/session-stats-cli-main.js +5 -0
  298. package/dist/heart/session-stats.js +183 -0
  299. package/dist/heart/session-transcript.js +133 -0
  300. package/dist/heart/start-of-turn-packet.js +372 -0
  301. package/dist/heart/steward-policy.js +618 -0
  302. package/dist/heart/streaming.js +604 -207
  303. package/dist/heart/structured-output.js +196 -0
  304. package/dist/heart/sync-classification.js +176 -0
  305. package/dist/heart/sync.js +449 -0
  306. package/dist/heart/target-resolution.js +11 -7
  307. package/dist/heart/tempo.js +93 -0
  308. package/dist/heart/temporal-view.js +41 -0
  309. package/dist/heart/timeouts.js +101 -0
  310. package/dist/heart/tool-activity-callbacks.js +59 -0
  311. package/dist/heart/tool-approval.js +382 -0
  312. package/dist/heart/tool-description.js +155 -0
  313. package/dist/heart/tool-friction.js +55 -0
  314. package/dist/heart/tool-loop.js +200 -0
  315. package/dist/heart/turn-context.js +482 -0
  316. package/dist/heart/turn-execution-lease.js +30 -0
  317. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  318. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  319. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  320. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  321. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  322. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  323. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  324. package/dist/heart/versioning/update-hooks.js +154 -0
  325. package/dist/heart/versioning/version-intent.js +114 -0
  326. package/dist/heart/work-card.js +380 -0
  327. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  328. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  329. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  330. package/dist/mailbox-ui/index.html +16 -0
  331. package/dist/mailroom/attention.js +167 -0
  332. package/dist/mailroom/autonomy.js +209 -0
  333. package/dist/mailroom/blob-store.js +889 -0
  334. package/dist/mailroom/body-cache.js +61 -0
  335. package/dist/mailroom/cache-sync-cli.js +58 -0
  336. package/dist/mailroom/core.js +803 -0
  337. package/dist/mailroom/entry.js +160 -0
  338. package/dist/mailroom/file-store.js +568 -0
  339. package/dist/mailroom/hosted-cache-sync.js +384 -0
  340. package/dist/mailroom/mbox-import.js +393 -0
  341. package/dist/mailroom/migration.js +164 -0
  342. package/dist/mailroom/outbound.js +380 -0
  343. package/dist/mailroom/policy.js +263 -0
  344. package/dist/mailroom/reader.js +292 -0
  345. package/dist/mailroom/search-cache.js +513 -0
  346. package/dist/mailroom/search-relevance.js +319 -0
  347. package/dist/mailroom/smtp-ingress.js +176 -0
  348. package/dist/mailroom/source-state.js +176 -0
  349. package/dist/mailroom/thread.js +109 -0
  350. package/dist/mailroom/travel-extract.js +89 -0
  351. package/dist/mind/bundle-manifest.js +24 -2
  352. package/dist/mind/context.js +309 -111
  353. package/dist/mind/desk-section.js +362 -0
  354. package/dist/mind/diary-integrity.js +60 -0
  355. package/dist/mind/{memory.js → diary.js} +68 -77
  356. package/dist/mind/embedding-provider.js +60 -0
  357. package/dist/mind/file-state.js +179 -0
  358. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  359. package/dist/mind/obligation-steering.js +199 -3
  360. package/dist/mind/pending.js +36 -10
  361. package/dist/mind/prompt-budget.js +479 -0
  362. package/dist/mind/prompt-refresh.js +3 -2
  363. package/dist/mind/prompt.js +1050 -189
  364. package/dist/mind/provenance-trust.js +26 -0
  365. package/dist/mind/record-paths.js +312 -0
  366. package/dist/mind/scrutiny.js +173 -0
  367. package/dist/mind/session-transaction.js +564 -0
  368. package/dist/nerves/cli-logging.js +7 -1
  369. package/dist/nerves/coverage/audit-rules.js +15 -6
  370. package/dist/nerves/coverage/audit.js +28 -2
  371. package/dist/nerves/coverage/cli.js +1 -1
  372. package/dist/nerves/coverage/contract.js +5 -5
  373. package/dist/nerves/coverage/file-completeness.js +139 -5
  374. package/dist/nerves/coverage/run-artifacts.js +55 -35
  375. package/dist/nerves/coverage/source-scanner.js +4 -4
  376. package/dist/nerves/event-buffer.js +111 -0
  377. package/dist/nerves/index.js +293 -9
  378. package/dist/nerves/observation.js +20 -0
  379. package/dist/nerves/redact.js +79 -0
  380. package/dist/nerves/review/cli-main.js +5 -0
  381. package/dist/nerves/review/cli.js +156 -0
  382. package/dist/nerves/review/core.js +159 -0
  383. package/dist/nerves/runtime.js +17 -1
  384. package/dist/repertoire/ado-client.js +15 -56
  385. package/dist/repertoire/ado-semantic.js +16 -10
  386. package/dist/repertoire/api-client.js +97 -0
  387. package/dist/repertoire/bitwarden-store.js +1045 -0
  388. package/dist/repertoire/bundle-templates.js +71 -0
  389. package/dist/repertoire/bw-installer.js +180 -0
  390. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  391. package/dist/repertoire/coding/context-pack.js +331 -0
  392. package/dist/repertoire/coding/feedback.js +174 -32
  393. package/dist/repertoire/coding/index.js +15 -3
  394. package/dist/repertoire/coding/manager.js +159 -10
  395. package/dist/repertoire/coding/spawner.js +58 -11
  396. package/dist/repertoire/coding/tools.js +221 -15
  397. package/dist/repertoire/coding/workbench-client.js +272 -0
  398. package/dist/repertoire/coding/workbench-manager.js +346 -0
  399. package/dist/repertoire/commerce-errors.js +109 -0
  400. package/dist/repertoire/commerce-self-test.js +156 -0
  401. package/dist/repertoire/credential-access.js +178 -0
  402. package/dist/repertoire/desk/classifier.js +362 -0
  403. package/dist/repertoire/duffel-client.js +185 -0
  404. package/dist/repertoire/github-client.js +14 -55
  405. package/dist/repertoire/graph-client.js +11 -52
  406. package/dist/repertoire/guardrails.js +811 -18
  407. package/dist/repertoire/mcp-client.js +44 -3
  408. package/dist/repertoire/mcp-manager.js +427 -139
  409. package/dist/repertoire/mcp-tools.js +124 -0
  410. package/dist/repertoire/plugin-mcp.js +175 -0
  411. package/dist/repertoire/plugins.js +253 -0
  412. package/dist/repertoire/relationship-authorization.js +322 -0
  413. package/dist/repertoire/shell-sessions.js +134 -0
  414. package/dist/repertoire/skills.js +48 -4
  415. package/dist/repertoire/stripe-client.js +131 -0
  416. package/dist/repertoire/tool-arguments.js +170 -0
  417. package/dist/repertoire/tool-results.js +29 -0
  418. package/dist/repertoire/tools-a2a.js +699 -0
  419. package/dist/repertoire/tools-attachments.js +322 -0
  420. package/dist/repertoire/tools-awaiting.js +575 -0
  421. package/dist/repertoire/tools-base.js +77 -1138
  422. package/dist/repertoire/tools-bluebubbles.js +2 -0
  423. package/dist/repertoire/tools-bridge.js +144 -0
  424. package/dist/repertoire/tools-bundle.js +993 -0
  425. package/dist/repertoire/tools-commerce.js +253 -0
  426. package/dist/repertoire/tools-config.js +186 -0
  427. package/dist/repertoire/tools-continuity.js +575 -0
  428. package/dist/repertoire/tools-credential.js +383 -0
  429. package/dist/repertoire/tools-evolution.js +527 -0
  430. package/dist/repertoire/tools-files.js +344 -0
  431. package/dist/repertoire/tools-flight.js +290 -0
  432. package/dist/repertoire/tools-flow.js +119 -0
  433. package/dist/repertoire/tools-github.js +3 -8
  434. package/dist/repertoire/tools-habits.js +103 -0
  435. package/dist/repertoire/tools-mail.js +1828 -0
  436. package/dist/repertoire/tools-notes.js +485 -0
  437. package/dist/repertoire/tools-obligations.js +182 -0
  438. package/dist/repertoire/tools-orientation.js +31 -0
  439. package/dist/repertoire/tools-record.js +482 -0
  440. package/dist/repertoire/tools-rsvp.js +139 -0
  441. package/dist/repertoire/tools-runtime.js +150 -0
  442. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  443. package/dist/repertoire/tools-session.js +1133 -0
  444. package/dist/repertoire/tools-shell.js +149 -0
  445. package/dist/repertoire/tools-steward-policy.js +119 -0
  446. package/dist/repertoire/tools-stripe.js +224 -0
  447. package/dist/repertoire/tools-surface.js +369 -0
  448. package/dist/repertoire/tools-teams.js +12 -39
  449. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  450. package/dist/repertoire/tools-travel.js +125 -0
  451. package/dist/repertoire/tools-trip.js +982 -0
  452. package/dist/repertoire/tools-unraid.js +531 -0
  453. package/dist/repertoire/tools-user-profile.js +146 -0
  454. package/dist/repertoire/tools-vault.js +40 -0
  455. package/dist/repertoire/tools-voice.js +145 -0
  456. package/dist/repertoire/tools.js +494 -148
  457. package/dist/repertoire/travel-api-client.js +360 -0
  458. package/dist/repertoire/unraid-client.js +155 -0
  459. package/dist/repertoire/unraid-restart.js +339 -0
  460. package/dist/repertoire/user-profile.js +131 -0
  461. package/dist/repertoire/vault-setup.js +246 -0
  462. package/dist/repertoire/vault-unlock.js +628 -0
  463. package/dist/rsvp/aisleplanner-client.js +354 -0
  464. package/dist/rsvp/cli.js +926 -0
  465. package/dist/rsvp/config.js +327 -0
  466. package/dist/rsvp/cutover.js +433 -0
  467. package/dist/rsvp/diagnostics.js +232 -0
  468. package/dist/rsvp/diff-renderer.js +176 -0
  469. package/dist/rsvp/habit-policy.js +110 -0
  470. package/dist/rsvp/habit-stage.js +123 -0
  471. package/dist/rsvp/incident-bundle.js +97 -0
  472. package/dist/rsvp/migration.js +204 -0
  473. package/dist/rsvp/native-habit-runner.js +630 -0
  474. package/dist/rsvp/outbound-state.js +628 -0
  475. package/dist/rsvp/query.js +118 -0
  476. package/dist/rsvp/replay.js +233 -0
  477. package/dist/rsvp/snapshot.js +232 -0
  478. package/dist/rsvp/spend-ledger.js +175 -0
  479. package/dist/scripts/claude-code-hook.js +41 -0
  480. package/dist/scripts/claude-code-stop-hook.js +47 -0
  481. package/dist/senses/a2a-entry.js +115 -0
  482. package/dist/senses/acp-server.js +386 -0
  483. package/dist/senses/attention-queue.js +186 -0
  484. package/dist/senses/await-turn-message.js +58 -0
  485. package/dist/senses/bluebubbles/active-turns.js +216 -0
  486. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  487. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  488. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  489. package/dist/senses/bluebubbles/context-packet.js +207 -0
  490. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  491. package/dist/senses/bluebubbles/entry.js +90 -0
  492. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  493. package/dist/senses/bluebubbles/index.js +3841 -0
  494. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  495. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  496. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  497. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  498. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  499. package/dist/senses/bluebubbles/processed-log.js +133 -0
  500. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  501. package/dist/senses/bluebubbles/replay.js +284 -0
  502. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  503. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  504. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  505. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  506. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  507. package/dist/senses/cli/bracketed-paste.js +82 -0
  508. package/dist/senses/cli/image-paste.js +287 -0
  509. package/dist/senses/cli/image-ref-navigation.js +75 -0
  510. package/dist/senses/cli/ink-app.js +156 -0
  511. package/dist/senses/cli/inline-diff.js +64 -0
  512. package/dist/senses/cli/input-keys.js +174 -0
  513. package/dist/senses/cli/kill-ring.js +86 -0
  514. package/dist/senses/cli/message-list.js +51 -0
  515. package/dist/senses/cli/ouro-tui.js +607 -0
  516. package/dist/senses/cli/spinner-imperative.js +135 -0
  517. package/dist/senses/cli/spinner.js +101 -0
  518. package/dist/senses/cli/status-line.js +60 -0
  519. package/dist/senses/cli/streaming-markdown.js +526 -0
  520. package/dist/senses/cli/tool-display.js +85 -0
  521. package/dist/senses/cli/tool-render.js +85 -0
  522. package/dist/senses/cli/tui-store.js +241 -0
  523. package/dist/senses/cli/virtual-list.js +35 -0
  524. package/dist/senses/cli-entry.js +60 -8
  525. package/dist/senses/cli.js +604 -320
  526. package/dist/senses/commands.js +66 -3
  527. package/dist/senses/context-packet-ledger.js +371 -0
  528. package/dist/senses/context-packets.js +154 -0
  529. package/dist/senses/habit-lifecycle-guard.js +24 -0
  530. package/dist/senses/habit-turn-message.js +160 -0
  531. package/dist/senses/ingress-evidence.js +2 -0
  532. package/dist/senses/mail-entry.js +66 -0
  533. package/dist/senses/mail.js +524 -0
  534. package/dist/senses/pipeline.js +1115 -204
  535. package/dist/senses/private-runtime-worker.js +859 -0
  536. package/dist/senses/private-runtime.js +1517 -0
  537. package/dist/senses/proactive-content-guard.js +51 -0
  538. package/dist/senses/root-host-approval-port.js +345 -0
  539. package/dist/senses/root-host-approval-runtime.js +393 -0
  540. package/dist/senses/sanctuary-authority-resident.js +102 -0
  541. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  542. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  543. package/dist/senses/sanctuary-grounding.js +118 -0
  544. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  545. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  546. package/dist/senses/sanctuary-health-runner.js +100 -0
  547. package/dist/senses/sanctuary-health.js +408 -0
  548. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  549. package/dist/senses/sanctuary-interactive-control.js +410 -0
  550. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  551. package/dist/senses/sanctuary-media-optimization.js +514 -0
  552. package/dist/senses/sanctuary-runtime.js +340 -0
  553. package/dist/senses/sanctuary-sab.js +85 -0
  554. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  555. package/dist/senses/shared-turn.js +772 -0
  556. package/dist/senses/surface-tool.js +109 -0
  557. package/dist/senses/teams-entry.js +60 -8
  558. package/dist/senses/teams.js +519 -218
  559. package/dist/senses/telegram-admission.js +718 -0
  560. package/dist/senses/telegram-approval-runtime.js +793 -0
  561. package/dist/senses/telegram-attachments.js +186 -0
  562. package/dist/senses/telegram-audit-ledger.js +220 -0
  563. package/dist/senses/telegram-authority-transport.js +231 -0
  564. package/dist/senses/telegram-client.js +1749 -0
  565. package/dist/senses/telegram-effect-adapter.js +896 -0
  566. package/dist/senses/telegram-entry.js +83 -0
  567. package/dist/senses/telegram.js +2324 -0
  568. package/dist/senses/trust-gate.js +104 -9
  569. package/dist/senses/voice/audio-playback.js +237 -0
  570. package/dist/senses/voice/audio-routing.js +119 -0
  571. package/dist/senses/voice/elevenlabs.js +202 -0
  572. package/dist/senses/voice/floor-control.js +431 -0
  573. package/dist/senses/voice/floor-controller.js +115 -0
  574. package/dist/senses/voice/golden-path.js +116 -0
  575. package/dist/senses/voice/index.js +29 -0
  576. package/dist/senses/voice/meeting.js +113 -0
  577. package/dist/senses/voice/outbound.js +190 -0
  578. package/dist/senses/voice/phone.js +33 -0
  579. package/dist/senses/voice/playback.js +139 -0
  580. package/dist/senses/voice/realtime-eval.js +496 -0
  581. package/dist/senses/voice/realtime-trace.js +531 -0
  582. package/dist/senses/voice/transcript.js +70 -0
  583. package/dist/senses/voice/turn.js +191 -0
  584. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  585. package/dist/senses/voice/twilio-phone.js +5031 -0
  586. package/dist/senses/voice/types.js +2 -0
  587. package/dist/senses/voice/whisper.js +161 -0
  588. package/dist/senses/voice-entry.js +81 -0
  589. package/dist/senses/voice-realtime-eval-command.js +99 -0
  590. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  591. package/dist/senses/voice-twilio-entry.js +87 -0
  592. package/dist/trips/core.js +138 -0
  593. package/dist/trips/store.js +265 -0
  594. package/dist/util/frontmatter.js +69 -0
  595. package/npm-shrinkwrap.json +8138 -0
  596. package/package.json +72 -13
  597. package/skills/agent-commerce.md +113 -0
  598. package/skills/browser-navigation.md +117 -0
  599. package/skills/commerce-setup-guide.md +116 -0
  600. package/skills/commerce-setup.md +84 -0
  601. package/skills/configure-dev-tools.md +99 -0
  602. package/skills/travel-planning.md +138 -0
  603. package/dist/heart/daemon/auth-flow.js +0 -430
  604. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  605. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  606. package/dist/heart/daemon/update-hooks.js +0 -138
  607. package/dist/heart/obligations.js +0 -191
  608. package/dist/heart/safe-workspace.js +0 -228
  609. package/dist/heart/session-recall.js +0 -116
  610. package/dist/mind/friends/channel.js +0 -84
  611. package/dist/mind/friends/group-context.js +0 -144
  612. package/dist/mind/friends/resolver.js +0 -84
  613. package/dist/mind/friends/store-file.js +0 -190
  614. package/dist/mind/friends/store.js +0 -4
  615. package/dist/mind/friends/tokens.js +0 -26
  616. package/dist/mind/friends/trust-explanation.js +0 -74
  617. package/dist/mind/friends/types.js +0 -29
  618. package/dist/repertoire/tasks/board.js +0 -134
  619. package/dist/repertoire/tasks/index.js +0 -224
  620. package/dist/repertoire/tasks/lifecycle.js +0 -80
  621. package/dist/repertoire/tasks/middleware.js +0 -65
  622. package/dist/repertoire/tasks/parser.js +0 -173
  623. package/dist/repertoire/tasks/scanner.js +0 -132
  624. package/dist/repertoire/tasks/transitions.js +0 -144
  625. package/dist/senses/bluebubbles-entry.js +0 -13
  626. package/dist/senses/bluebubbles.js +0 -1181
  627. package/dist/senses/debug-activity.js +0 -154
  628. package/dist/senses/inner-dialog-worker.js +0 -90
  629. package/dist/senses/inner-dialog.js +0 -525
  630. package/subagents/README.md +0 -7
  631. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  632. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  633. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  634. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  635. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  636. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  637. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  638. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  639. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  640. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  641. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  642. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  643. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  644. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  645. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  646. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  647. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,859 @@
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.HEARTBEAT_OK_REST_SUPPRESSION_MS = exports.HABIT_RECURSION_BURST_THRESHOLD = exports.HABIT_RECURSION_BURST_WINDOW_MS = exports.HABIT_RECURSION_MIN_INTERVAL_MS = exports.MAX_CONSECUTIVE_INSTINCT_TURNS = void 0;
37
+ exports.createPrivateRuntimeWorker = createPrivateRuntimeWorker;
38
+ exports.startPrivateRuntimeWorker = startPrivateRuntimeWorker;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const private_runtime_1 = require("./private-runtime");
42
+ const router_1 = require("../heart/external-events/router");
43
+ const runtime_1 = require("../nerves/runtime");
44
+ const identity_1 = require("../heart/identity");
45
+ const pending_1 = require("../mind/pending");
46
+ const habit_parser_1 = require("../heart/habits/habit-parser");
47
+ const habit_runtime_state_1 = require("../heart/habits/habit-runtime-state");
48
+ const habit_session_1 = require("../heart/habits/habit-session");
49
+ const flight_recorder_1 = require("../arc/flight-recorder");
50
+ const habit_session_summary_1 = require("../heart/habits/habit-session-summary");
51
+ const friends_1 = require("@ouro.bot/friends");
52
+ const tools_base_1 = require("../repertoire/tools-base");
53
+ const tools_surface_1 = require("../repertoire/tools-surface");
54
+ const tools_1 = require("../repertoire/tools");
55
+ const habit_policy_1 = require("../rsvp/habit-policy");
56
+ const spend_ledger_1 = require("../rsvp/spend-ledger");
57
+ const run_ledger_1 = require("../heart/run-ledger");
58
+ const autonomy_budget_1 = require("../heart/autonomy-budget");
59
+ const habit_lifecycle_guard_1 = require("./habit-lifecycle-guard");
60
+ function createQueueCompletion(rejectOnError) {
61
+ let resolve;
62
+ let reject;
63
+ const promise = new Promise((resolvePromise, rejectPromise) => {
64
+ resolve = resolvePromise;
65
+ reject = rejectPromise;
66
+ });
67
+ return { promise, resolve, reject, errors: [], rejectOnError };
68
+ }
69
+ function isUsageData(value) {
70
+ const usage = value;
71
+ return !!usage
72
+ && typeof usage.input_tokens === "number"
73
+ && typeof usage.output_tokens === "number"
74
+ && typeof usage.total_tokens === "number";
75
+ }
76
+ function extractUsageFromHabitResults(results) {
77
+ const aggregate = {
78
+ input_tokens: 0,
79
+ output_tokens: 0,
80
+ reasoning_tokens: 0,
81
+ total_tokens: 0,
82
+ };
83
+ let found = false;
84
+ for (const result of results) {
85
+ if (!result || typeof result !== "object")
86
+ continue;
87
+ const usage = result.usage;
88
+ if (!isUsageData(usage))
89
+ continue;
90
+ found = true;
91
+ aggregate.input_tokens += usage.input_tokens;
92
+ aggregate.output_tokens += usage.output_tokens;
93
+ aggregate.reasoning_tokens += typeof usage.reasoning_tokens === "number" ? usage.reasoning_tokens : 0;
94
+ aggregate.total_tokens += usage.total_tokens;
95
+ }
96
+ return found ? aggregate : undefined;
97
+ }
98
+ function habitRunLedgerBase(habitRun) {
99
+ const target = {
100
+ habitName: habitRun.habit.name,
101
+ runId: habitRun.runId,
102
+ trigger: habitRun.trigger,
103
+ operationId: habitRun.operationId,
104
+ };
105
+ return {
106
+ agent: (0, identity_1.getAgentName)(),
107
+ triggerType: "habit",
108
+ sourceKind: "private-runtime",
109
+ senseOrHabit: habitRun.habit.name,
110
+ startedAt: habitRun.startedAt,
111
+ target,
112
+ idempotencyScope: target,
113
+ provider: "unknown",
114
+ model: "unknown",
115
+ sessionRef: {
116
+ channel: "inner",
117
+ keyHash: (0, run_ledger_1.runLedgerHash)({ habitName: habitRun.habit.name, runId: habitRun.runId }),
118
+ },
119
+ };
120
+ }
121
+ function recordHabitRunLedger(habitRun, lifecycle, endedAt) {
122
+ const usage = extractUsageFromHabitResults(habitRun.results);
123
+ const record = (0, run_ledger_1.createRunLedgerRecord)({
124
+ ...habitRunLedgerBase(habitRun),
125
+ lifecycle,
126
+ ...(endedAt ? { endedAt } : {}),
127
+ ...(lifecycle === "completed" || lifecycle === "error"
128
+ ? { usage: (0, run_ledger_1.usageMetadataFromUsageData)(usage, usage ? "provider" : "none") }
129
+ : {}),
130
+ });
131
+ (0, run_ledger_1.appendRunLedgerRecordNonFatal)(habitRun.agentRoot, record);
132
+ if (habitRun.rsvpPolicy) {
133
+ try {
134
+ (0, spend_ledger_1.recordRsvpSpendLedgerRun)(habitRun.agentRoot, record);
135
+ }
136
+ catch (error) {
137
+ (0, runtime_1.emitNervesEvent)({
138
+ level: "error",
139
+ component: "rsvp",
140
+ event: "rsvp.spend_ledger_record_error",
141
+ message: "failed to record RSVP spend ledger row",
142
+ meta: { runId: record.runId, lifecycle, error: String(error) },
143
+ });
144
+ }
145
+ }
146
+ }
147
+ function reserveHabitAutonomyBudget(habitRun, nowIso) {
148
+ const target = {
149
+ habitName: habitRun.habit.name,
150
+ runId: habitRun.runId,
151
+ trigger: habitRun.trigger,
152
+ operationId: habitRun.operationId,
153
+ };
154
+ if (habitRun.rsvpPolicy) {
155
+ target.rsvpSnapshotRef = habitRun.rsvpPolicy.snapshotRef;
156
+ target.rsvpBudgetRef = habitRun.rsvpPolicy.budgetRef;
157
+ target.rsvpIdempotencyRef = habitRun.rsvpPolicy.idempotencyRef;
158
+ }
159
+ const agentName = (0, identity_1.getAgentName)();
160
+ return (0, autonomy_budget_1.reserveAutonomyBudget)(habitRun.agentRoot, {
161
+ agent: agentName,
162
+ triggerType: "habit",
163
+ sourceKind: "private-runtime",
164
+ senseOrHabit: habitRun.habit.name,
165
+ target,
166
+ idempotencyKey: `habit:${habitRun.habit.name}:${habitRun.runId}`,
167
+ now: nowIso,
168
+ }, (0, autonomy_budget_1.resolveAutonomyBudgetPolicy)(habitRun.agentRoot, agentName));
169
+ }
170
+ /**
171
+ * Cap on consecutive `instinct` follow-on turns triggered by `hasPendingWork()`
172
+ * with no externally-queued work in between. Without this cap, a turn that
173
+ * writes anything back into the private-runtime pending dir as a side effect of
174
+ * processing (e.g. a surface tool routing a response) puts the worker into
175
+ * a self-sustaining loop where the next turn's drain produces another write,
176
+ * and so on. Real workflows rarely chain more than 2–3 instinct turns; an
177
+ * external trigger (habit, poke, chat) resets the counter so legitimate
178
+ * follow-on work is unaffected.
179
+ *
180
+ * Three feels right: legitimate cascading follow-ups (e.g. processing a
181
+ * batch of delegated returns) get through; a true self-loop caps fast.
182
+ */
183
+ exports.MAX_CONSECUTIVE_INSTINCT_TURNS = 3;
184
+ /**
185
+ * Habit recursion detector thresholds. The instinct cap above protects
186
+ * against pending-dir self-loops; this protects against the *external*
187
+ * IPC self-loop where heartbeat-shaped messages get re-issued faster
188
+ * than their cadence — e.g. a hook misconfigured to repost on every
189
+ * heartbeat, a daemon retry storm, or a stuck timer firing back-to-back.
190
+ *
191
+ * MIN_INTERVAL_MS — two of the same habit within this window is suspect
192
+ * regardless of cadence (no realistic habit fires every few seconds).
193
+ * BURST_THRESHOLD over BURST_WINDOW_MS catches slower runaways that stay
194
+ * just under MIN_INTERVAL_MS.
195
+ *
196
+ * Detection is observation-only: it emits warn-level nerves events, it
197
+ * does not drop the message. An operator (or follow-up auto-recovery)
198
+ * decides what to do with the signal.
199
+ */
200
+ exports.HABIT_RECURSION_MIN_INTERVAL_MS = 5_000;
201
+ exports.HABIT_RECURSION_BURST_WINDOW_MS = 60_000;
202
+ exports.HABIT_RECURSION_BURST_THRESHOLD = 5;
203
+ exports.HEARTBEAT_OK_REST_SUPPRESSION_MS = 20 * 60_000;
204
+ function defaultHasPendingWork(pendingDir) {
205
+ if (pendingDir)
206
+ return (0, pending_1.hasPendingMessages)(pendingDir);
207
+ const agentArgIndex = process.argv.indexOf("--agent");
208
+ const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
209
+ return agentName ? (0, pending_1.hasPendingMessages)((0, pending_1.getPrivateRuntimePendingDir)(agentName)) : false;
210
+ }
211
+ function isHeartbeatOkRestResult(result) {
212
+ if (!result || typeof result !== "object")
213
+ return false;
214
+ const maybeResult = result;
215
+ return maybeResult.turnOutcome === "rested" && maybeResult.restStatus === "HEARTBEAT_OK";
216
+ }
217
+ function isRecord(value) {
218
+ return !!value && typeof value === "object" && !Array.isArray(value);
219
+ }
220
+ function contentToText(content) {
221
+ if (typeof content === "string")
222
+ return content.trim();
223
+ if (!Array.isArray(content))
224
+ return "";
225
+ return content
226
+ .map((part) => isRecord(part) && typeof part.text === "string" ? part.text : "")
227
+ .filter((text) => text.trim().length > 0)
228
+ .join("\n")
229
+ .trim();
230
+ }
231
+ function resultMessages(result) {
232
+ if (Array.isArray(result))
233
+ return result.flatMap((entry) => resultMessages(entry));
234
+ return isRecord(result) && Array.isArray(result.messages) ? result.messages : [];
235
+ }
236
+ function latestAssistantText(results) {
237
+ for (let resultIndex = results.length - 1; resultIndex >= 0; resultIndex--) {
238
+ const messages = resultMessages(results[resultIndex]);
239
+ for (let messageIndex = messages.length - 1; messageIndex >= 0; messageIndex--) {
240
+ const message = messages[messageIndex];
241
+ if (!isRecord(message) || message.role !== "assistant")
242
+ continue;
243
+ const text = contentToText(message.content);
244
+ if (text.length > 0)
245
+ return text.replace(/^checkpoint\s*:\s*/i, "").trim() || text;
246
+ }
247
+ }
248
+ return null;
249
+ }
250
+ function deriveHabitSummarySnapshot(habitRun) {
251
+ const assistant = latestAssistantText(habitRun.results);
252
+ if (assistant)
253
+ return { summary: assistant, decisions: [], nextLikelyStep: null };
254
+ if (habitRun.errors.length > 0) {
255
+ return {
256
+ summary: `Habit ${habitRun.habit.name} finished with errors: ${habitRun.errors.join("; ")}`,
257
+ decisions: [],
258
+ nextLikelyStep: null,
259
+ };
260
+ }
261
+ const surfaced = habitRun.surfaceAttempts.find((attempt) => attempt.result !== "blocked" && attempt.result !== "failed" && attempt.result !== "unavailable");
262
+ if (surfaced) {
263
+ return {
264
+ summary: `Habit ${habitRun.habit.name} surfaced via ${surfaced.recipient}/${surfaced.channel}.`,
265
+ decisions: [],
266
+ nextLikelyStep: null,
267
+ };
268
+ }
269
+ const produced = habitRun.producedRefs.find((ref) => ref.kind !== "none");
270
+ if (produced) {
271
+ return {
272
+ summary: `Habit ${habitRun.habit.name} produced ${produced.kind}: ${produced.locator}.`,
273
+ decisions: [],
274
+ nextLikelyStep: null,
275
+ };
276
+ }
277
+ if (habitRun.results.some(isHeartbeatOkRestResult)) {
278
+ return {
279
+ summary: `Habit ${habitRun.habit.name} rested with HEARTBEAT_OK.`,
280
+ decisions: [],
281
+ nextLikelyStep: null,
282
+ };
283
+ }
284
+ return {
285
+ summary: `Habit ${habitRun.habit.name} completed without additional surfaced output.`,
286
+ decisions: [],
287
+ nextLikelyStep: null,
288
+ };
289
+ }
290
+ function readHabitForRun(agentRoot, habitName, errors) {
291
+ const habitPath = path.join(agentRoot, "habits", `${habitName}.md`);
292
+ try {
293
+ return (0, habit_parser_1.parseHabitFile)(fs.readFileSync(habitPath, "utf-8"), habitPath);
294
+ }
295
+ catch (error) {
296
+ const reason = error instanceof Error ? error.message : String(error);
297
+ errors.push(`habit file could not be read: ${reason}`);
298
+ (0, runtime_1.emitNervesEvent)({
299
+ level: "warn",
300
+ component: "senses",
301
+ event: "senses.habit_file_read_error",
302
+ message: "habit file could not be read for habit session",
303
+ meta: { habitName, habitPath, reason },
304
+ });
305
+ return (0, habit_parser_1.createDegradedHabitFile)(habitPath, "read_error");
306
+ }
307
+ }
308
+ async function prepareHabitRun(habitName, trigger, startedAt) {
309
+ const agentRoot = (0, identity_1.getAgentRoot)();
310
+ const errors = [];
311
+ const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, readHabitForRun(agentRoot, habitName, errors));
312
+ if (habit.status === "degraded" && habit.degradedDetail !== null) {
313
+ errors.push(habit.degradedDetail);
314
+ }
315
+ const lifecycleBlockedReason = (0, habit_lifecycle_guard_1.privateRuntimeHabitRejectionReason)(habit, "private-runtime-worker");
316
+ const blockedReason = (0, habit_policy_1.isRsvpHabitName)(habitName) && !habit.rsvp
317
+ ? "RSVP habit metadata is required before private runtime execution"
318
+ : lifecycleBlockedReason;
319
+ if (blockedReason && !errors.includes(blockedReason))
320
+ errors.push(blockedReason);
321
+ const runId = (0, flight_recorder_1.createHabitRunId)(habitName, new Date(startedAt));
322
+ const operationId = habit.continuity.mode === "stateful" ? `habit:${habit.name}` : null;
323
+ const priorSessionSummary = readPriorSessionSummary(agentRoot, operationId);
324
+ const paths = (0, habit_session_1.createHabitSessionPaths)(agentRoot, runId, habit.name);
325
+ const friendStore = new friends_1.FileFriendStore(path.join(agentRoot, "friends"));
326
+ const permissionEnvelope = await (0, habit_session_1.normalizeHabitPermissionEnvelope)(habit, { agentRoot, friendStore });
327
+ const rsvpPolicy = habit.rsvp ? (0, habit_policy_1.rsvpHabitRuntimePolicy)(habit.rsvp) : undefined;
328
+ const requestedTools = blockedReason ? [] : habit.rsvp ? [...habit_policy_1.RSVP_HABIT_ALLOWED_TOOLS] : habit.tools ?? null;
329
+ const toolPolicy = (0, habit_session_1.filterHabitToolsForEnvelope)([...tools_base_1.baseToolDefinitions, tools_surface_1.surfaceToolDefinition], requestedTools, permissionEnvelope, riskProfileForHabitPolicy);
330
+ return {
331
+ agentRoot,
332
+ habit,
333
+ runId,
334
+ operationId,
335
+ trigger,
336
+ startedAt,
337
+ priorSessionSummary,
338
+ paths,
339
+ permissionEnvelope,
340
+ toolPolicy,
341
+ ...(rsvpPolicy ? { rsvpPolicy } : {}),
342
+ ...(blockedReason ? { blockedReason } : {}),
343
+ friendStore,
344
+ results: [],
345
+ errors,
346
+ producedRefs: [],
347
+ surfaceAttempts: [],
348
+ };
349
+ }
350
+ function riskProfileForHabitPolicy(definition, name) {
351
+ const probeArgs = name === "shell" ? { command: "touch /tmp/habit-policy-probe" } : {};
352
+ return (0, tools_1.riskProfileForTool)(definition, name, probeArgs);
353
+ }
354
+ function readPriorSessionSummary(agentRoot, operationId) {
355
+ if (operationId === null)
356
+ return undefined;
357
+ try {
358
+ const summary = (0, habit_session_summary_1.readHabitSessionSummary)(agentRoot, { operationId, which: "latest" });
359
+ if (!summary)
360
+ return { mode: "stateful", summary: null, sources: {}, warnings: [] };
361
+ return {
362
+ mode: "stateful",
363
+ summary: summary.summary,
364
+ sources: summary.sources,
365
+ warnings: summary.warnings,
366
+ };
367
+ }
368
+ catch (error) {
369
+ return {
370
+ mode: "stateful",
371
+ summary: null,
372
+ sources: {},
373
+ warnings: [`prior summary read failed: ${String(error)}`],
374
+ };
375
+ }
376
+ }
377
+ function createPrivateRuntimeWorker(runTurn = (options) => (0, private_runtime_1.runPrivateRuntimeTurn)(options), hasPendingWork = defaultHasPendingWork, nowSource = () => Date.now()) {
378
+ let running = false;
379
+ const queue = [];
380
+ const lastFireByHabit = new Map();
381
+ const recentHabitFires = [];
382
+ const startedHabitLedgerRunIds = new Set();
383
+ let heartbeatOkRestedAt = null;
384
+ function recordHabitStartIfNeeded(habitRun) {
385
+ if (startedHabitLedgerRunIds.has(habitRun.runId))
386
+ return;
387
+ recordHabitRunLedger(habitRun, "started");
388
+ startedHabitLedgerRunIds.add(habitRun.runId);
389
+ }
390
+ function recordHabitCompletion(habitRun, endedAt = habitRun.startedAt) {
391
+ recordHabitStartIfNeeded(habitRun);
392
+ recordHabitRunLedger(habitRun, habitRun.errors.length > 0 ? "error" : "completed", endedAt);
393
+ (0, habit_session_1.completeHabitRun)({
394
+ agentRoot: habitRun.agentRoot,
395
+ habit: habitRun.habit,
396
+ runId: habitRun.runId,
397
+ trigger: habitRun.trigger,
398
+ startedAt: habitRun.startedAt,
399
+ endedAt,
400
+ operationId: habitRun.operationId,
401
+ permissionEnvelope: habitRun.permissionEnvelope,
402
+ toolPolicy: habitRun.toolPolicy,
403
+ producedRefs: habitRun.producedRefs,
404
+ surfaceAttempts: habitRun.surfaceAttempts,
405
+ errors: habitRun.errors,
406
+ summarySnapshot: deriveHabitSummarySnapshot(habitRun),
407
+ });
408
+ }
409
+ function clearHeartbeatRestShield() {
410
+ heartbeatOkRestedAt = null;
411
+ }
412
+ function shouldReuseHeartbeatOkRest(habitName) {
413
+ if (habitName !== "heartbeat" || heartbeatOkRestedAt === null)
414
+ return false;
415
+ if (nowSource() - heartbeatOkRestedAt > exports.HEARTBEAT_OK_REST_SUPPRESSION_MS)
416
+ return false;
417
+ if (hasPendingWork()) {
418
+ clearHeartbeatRestShield();
419
+ return false;
420
+ }
421
+ return true;
422
+ }
423
+ async function reuseHeartbeatOkRest(habitName) {
424
+ const nowIso = new Date(nowSource()).toISOString();
425
+ const habitRun = await prepareHabitRun(habitName, "overdue", nowIso);
426
+ if (habitRun.blockedReason) {
427
+ clearHeartbeatRestShield();
428
+ recordHabitCompletion(habitRun, nowIso);
429
+ return;
430
+ }
431
+ habitRun.results.push({ turnOutcome: "rested", restStatus: "HEARTBEAT_OK" });
432
+ recordHabitCompletion(habitRun, nowIso);
433
+ (0, runtime_1.emitNervesEvent)({
434
+ level: "info",
435
+ component: "senses",
436
+ event: "senses.heartbeat_ok_rest_reused",
437
+ message: "heartbeat skipped because previous HEARTBEAT_OK rest is still valid and no pending work exists",
438
+ meta: {
439
+ habitName,
440
+ quietWindowMs: exports.HEARTBEAT_OK_REST_SUPPRESSION_MS,
441
+ restedAgoMs: nowSource() - heartbeatOkRestedAt,
442
+ },
443
+ });
444
+ }
445
+ function recordHabitFireForRecursion(habitName) {
446
+ const now = nowSource();
447
+ const previous = lastFireByHabit.get(habitName);
448
+ if (previous !== undefined) {
449
+ const intervalMs = now - previous;
450
+ if (intervalMs < exports.HABIT_RECURSION_MIN_INTERVAL_MS) {
451
+ (0, runtime_1.emitNervesEvent)({
452
+ level: "warn",
453
+ component: "senses",
454
+ event: "senses.habit_recursion_suspected",
455
+ message: "habit fired suspiciously fast after the previous fire — possible self-recursion or duplicate dispatch",
456
+ meta: {
457
+ habitName,
458
+ intervalMs,
459
+ thresholdMs: exports.HABIT_RECURSION_MIN_INTERVAL_MS,
460
+ },
461
+ });
462
+ }
463
+ }
464
+ lastFireByHabit.set(habitName, now);
465
+ recentHabitFires.push(now);
466
+ while (recentHabitFires.length > 0 && now - recentHabitFires[0] > exports.HABIT_RECURSION_BURST_WINDOW_MS) {
467
+ recentHabitFires.shift();
468
+ }
469
+ if (recentHabitFires.length >= exports.HABIT_RECURSION_BURST_THRESHOLD) {
470
+ (0, runtime_1.emitNervesEvent)({
471
+ level: "warn",
472
+ component: "senses",
473
+ event: "senses.habit_recursion_burst",
474
+ message: "habit messages arriving in a burst — possible runaway loop",
475
+ meta: {
476
+ count: recentHabitFires.length,
477
+ windowMs: exports.HABIT_RECURSION_BURST_WINDOW_MS,
478
+ thresholdCount: exports.HABIT_RECURSION_BURST_THRESHOLD,
479
+ lastHabitName: habitName,
480
+ },
481
+ });
482
+ }
483
+ }
484
+ const startExternalEventHeartbeat = (event) => {
485
+ const renew = () => {
486
+ for (const member of [event, ...(event.relatedEvents ?? [])]) {
487
+ try {
488
+ (0, router_1.renewExternalEventClaim)(member.recordPath, { owner: member.claimOwner, expectedGeneration: member.generation, leaseMs: 30_000 });
489
+ }
490
+ catch (error) {
491
+ (0, runtime_1.emitNervesEvent)({
492
+ level: "warn", component: "senses", event: "senses.external_event_lease_renew_error",
493
+ message: "external-event turn lease renewal failed",
494
+ meta: { recordPath: member.recordPath, generation: member.generation, error: error instanceof Error ? error.message : String(error) },
495
+ });
496
+ }
497
+ }
498
+ };
499
+ renew();
500
+ const timer = setInterval(renew, 10_000);
501
+ timer.unref?.();
502
+ return () => clearInterval(timer);
503
+ };
504
+ async function run(reason, taskId, habitName, awaitName, trigger, privateTurnDecision, noSend, externalEvent, dispatchId) {
505
+ const completion = createQueueCompletion(dispatchId !== undefined);
506
+ let activeCompletion = completion;
507
+ if (running) {
508
+ queue.push({ reason, taskId, habitName, awaitName, trigger, privateTurnDecision, noSend, externalEvent, dispatchId, completion, ...(externalEvent ? { stopExternalEventHeartbeat: startExternalEventHeartbeat(externalEvent) } : {}) });
509
+ return completion.promise;
510
+ }
511
+ running = true;
512
+ void (async () => {
513
+ try {
514
+ let nextReason = reason;
515
+ let nextTaskId = taskId;
516
+ let nextHabitName = habitName;
517
+ let nextAwaitName = awaitName;
518
+ let nextTrigger = trigger;
519
+ let nextPrivateTurnDecision = privateTurnDecision;
520
+ let nextExternalEvent = externalEvent;
521
+ let nextExternalEventHeartbeat = externalEvent ? startExternalEventHeartbeat(externalEvent) : undefined;
522
+ let nextCompletion = completion;
523
+ let nextNoSend = reason === "habit" ? noSend : undefined;
524
+ let nextHabitRun = null;
525
+ let consecutiveInstinctTurns = reason === "instinct" ? 1 : 0;
526
+ runLoop: do {
527
+ const currentReason = nextReason;
528
+ const currentHabitName = nextHabitName;
529
+ const currentTrigger = nextTrigger ?? "overdue";
530
+ const currentNoSend = nextNoSend;
531
+ const currentExternalEvent = nextExternalEvent;
532
+ const currentExternalEventHeartbeat = nextExternalEventHeartbeat;
533
+ const currentCompletion = nextCompletion;
534
+ activeCompletion = currentCompletion;
535
+ nextExternalEventHeartbeat = undefined;
536
+ nextCompletion = undefined;
537
+ const currentHabitRun = currentReason === "habit" && currentHabitName
538
+ ? nextHabitRun && nextHabitRun.habit.name === currentHabitName
539
+ ? nextHabitRun
540
+ : await prepareHabitRun(currentHabitName, currentTrigger, new Date(nowSource()).toISOString())
541
+ : null;
542
+ nextHabitRun = null;
543
+ let currentHabitRunFinalized = false;
544
+ const finalizeCurrentHabitRun = () => {
545
+ if (!currentHabitRun || currentHabitRunFinalized)
546
+ return;
547
+ recordHabitCompletion(currentHabitRun, new Date(nowSource()).toISOString());
548
+ currentHabitRunFinalized = true;
549
+ };
550
+ const turnErrors = [];
551
+ if (!(currentReason === "habit" && currentHabitName === "heartbeat")) {
552
+ clearHeartbeatRestShield();
553
+ }
554
+ let turnResult;
555
+ let blockedAutonomyTurn = false;
556
+ try {
557
+ const turnStartedAt = new Date(nowSource()).toISOString();
558
+ const autonomyDecision = currentHabitRun && !currentHabitRun.blockedReason
559
+ ? reserveHabitAutonomyBudget(currentHabitRun, turnStartedAt)
560
+ : null;
561
+ if (currentHabitRun)
562
+ recordHabitStartIfNeeded(currentHabitRun);
563
+ if (currentHabitRun?.blockedReason) {
564
+ blockedAutonomyTurn = true;
565
+ turnResult = {
566
+ turnOutcome: "blocked",
567
+ reason: currentHabitRun.blockedReason,
568
+ };
569
+ clearHeartbeatRestShield();
570
+ }
571
+ else if (autonomyDecision && !autonomyDecision.allowed) {
572
+ blockedAutonomyTurn = true;
573
+ const reason = `autonomy budget blocked: ${autonomyDecision.reason}`;
574
+ turnErrors.push(reason);
575
+ turnResult = {
576
+ turnOutcome: "blocked",
577
+ reason,
578
+ autonomyReceiptId: autonomyDecision.receiptId,
579
+ };
580
+ clearHeartbeatRestShield();
581
+ }
582
+ else {
583
+ const turnOptions = {
584
+ reason: nextReason,
585
+ taskId: nextTaskId,
586
+ habitName: nextHabitName,
587
+ awaitName: nextAwaitName,
588
+ ...(currentNoSend ? { noSend: true } : {}),
589
+ ...(nextPrivateTurnDecision ? { privateTurnDecision: nextPrivateTurnDecision } : {}),
590
+ ...(nextExternalEvent ? { externalEvent: nextExternalEvent } : {}),
591
+ ...(currentHabitRun
592
+ ? {
593
+ trigger: currentHabitRun.trigger,
594
+ preparedHabit: {
595
+ runId: currentHabitRun.runId,
596
+ trigger: currentHabitRun.trigger,
597
+ operationId: currentHabitRun.operationId,
598
+ habit: currentHabitRun.habit,
599
+ priorSessionSummary: currentHabitRun.priorSessionSummary,
600
+ },
601
+ habitSession: {
602
+ runId: currentHabitRun.runId,
603
+ sessionPath: currentHabitRun.paths.sessionPath,
604
+ pendingDir: currentHabitRun.paths.pendingDir,
605
+ permissionEnvelope: currentHabitRun.permissionEnvelope,
606
+ toolPolicy: currentHabitRun.toolPolicy,
607
+ ...(currentHabitRun.rsvpPolicy ? { rsvpPolicy: currentHabitRun.rsvpPolicy } : {}),
608
+ friendStore: currentHabitRun.friendStore,
609
+ recordProducedRef: (ref) => { currentHabitRun.producedRefs.push(ref); },
610
+ recordSurfaceAttempt: (attempt) => { currentHabitRun.surfaceAttempts.push(attempt); },
611
+ recordError: (error) => { currentHabitRun.errors.push(error); },
612
+ },
613
+ }
614
+ : {}),
615
+ };
616
+ turnResult = await runTurn(turnOptions);
617
+ }
618
+ }
619
+ catch (error) {
620
+ clearHeartbeatRestShield();
621
+ turnErrors.push(error instanceof Error ? error.message : String(error));
622
+ (0, runtime_1.emitNervesEvent)({
623
+ level: "error",
624
+ component: "senses",
625
+ event: "senses.private_runtime_worker_error",
626
+ message: "private-runtime worker turn failed",
627
+ meta: {
628
+ reason: nextReason,
629
+ error: error instanceof Error ? error.message : String(error),
630
+ },
631
+ });
632
+ }
633
+ currentExternalEventHeartbeat?.();
634
+ if (currentExternalEvent) {
635
+ const turnOutcome = turnResult && typeof turnResult === "object" && "turnOutcome" in turnResult
636
+ ? turnResult.turnOutcome
637
+ : undefined;
638
+ const failureReason = turnErrors.length > 0 || turnOutcome === "errored"
639
+ ? "private-runtime external-event turn failed"
640
+ : blockedAutonomyTurn || turnOutcome === "blocked" || turnOutcome === "suspended"
641
+ ? "external-event turn was blocked"
642
+ : "external-event turn completed without a terminal disposition";
643
+ let settledIncomplete = false;
644
+ for (const member of [currentExternalEvent, ...(currentExternalEvent.relatedEvents ?? [])]) {
645
+ const result = (0, router_1.settleExternalEventFailureIfOwned)(member.recordPath, {
646
+ owner: member.claimOwner,
647
+ expectedGeneration: member.generation,
648
+ error: failureReason,
649
+ });
650
+ settledIncomplete = result.settled || settledIncomplete;
651
+ }
652
+ if (settledIncomplete && turnErrors.length === 0)
653
+ turnErrors.push(failureReason);
654
+ }
655
+ if (currentReason === "habit" && currentHabitName === "heartbeat") {
656
+ heartbeatOkRestedAt = isHeartbeatOkRestResult(turnResult) ? nowSource() : null;
657
+ }
658
+ if (currentHabitRun) {
659
+ currentHabitRun.results.push(turnResult);
660
+ currentHabitRun.errors.push(...turnErrors);
661
+ }
662
+ currentCompletion?.errors.push(...turnErrors);
663
+ const settleCurrentCompletion = () => {
664
+ /* v8 ignore next -- every run and queued entry is constructed with a completion @preserve */
665
+ if (!currentCompletion)
666
+ return;
667
+ if (currentCompletion.rejectOnError && currentCompletion.errors.length > 0)
668
+ currentCompletion.reject(new Error(currentCompletion.errors.join("; ")));
669
+ else
670
+ currentCompletion.resolve();
671
+ if (activeCompletion === currentCompletion)
672
+ activeCompletion = undefined;
673
+ };
674
+ // Drain queue first. Externally-queued work resets the instinct cap
675
+ // because a real outside trigger arrived between turns.
676
+ if (queue.length > 0)
677
+ settleCurrentCompletion();
678
+ while (queue.length > 0) {
679
+ const next = queue.shift();
680
+ activeCompletion = next.completion;
681
+ if (next.reason === "habit" && next.habitName === "heartbeat" && shouldReuseHeartbeatOkRest(next.habitName)) {
682
+ finalizeCurrentHabitRun();
683
+ await reuseHeartbeatOkRest(next.habitName);
684
+ next.completion.resolve();
685
+ /* v8 ignore next -- activeCompletion was assigned from this exact queue entry immediately above @preserve */
686
+ if (activeCompletion === next.completion)
687
+ activeCompletion = undefined;
688
+ continue;
689
+ }
690
+ if (!(next.reason === "habit" && next.habitName === "heartbeat")) {
691
+ clearHeartbeatRestShield();
692
+ }
693
+ finalizeCurrentHabitRun();
694
+ nextReason = next.reason;
695
+ nextTaskId = next.taskId;
696
+ nextHabitName = next.habitName;
697
+ nextAwaitName = next.awaitName;
698
+ nextTrigger = next.trigger;
699
+ nextPrivateTurnDecision = next.privateTurnDecision;
700
+ nextExternalEvent = next.externalEvent;
701
+ nextExternalEventHeartbeat = next.stopExternalEventHeartbeat;
702
+ nextCompletion = next.completion;
703
+ nextNoSend = next.reason === "habit" ? next.noSend : undefined;
704
+ consecutiveInstinctTurns = nextReason === "instinct" ? consecutiveInstinctTurns + 1 : 0;
705
+ continue runLoop;
706
+ }
707
+ if (blockedAutonomyTurn) {
708
+ finalizeCurrentHabitRun();
709
+ settleCurrentCompletion();
710
+ break;
711
+ }
712
+ // Then check hasPendingWork fallback. This is the loop site: any
713
+ // tool that writes to the private-runtime pending dir during a turn
714
+ // would cause hasPendingWork() to be true here, producing a
715
+ // self-sustaining "instinct" loop with no external input. Cap it.
716
+ if (hasPendingWork(currentHabitRun?.paths.pendingDir)) {
717
+ if (currentExternalEvent && (turnErrors.length > 0
718
+ || (turnResult && typeof turnResult === "object" && "turnOutcome" in turnResult && turnResult.turnOutcome === "errored"))) {
719
+ finalizeCurrentHabitRun();
720
+ settleCurrentCompletion();
721
+ break;
722
+ }
723
+ clearHeartbeatRestShield();
724
+ if (consecutiveInstinctTurns >= exports.MAX_CONSECUTIVE_INSTINCT_TURNS) {
725
+ (0, runtime_1.emitNervesEvent)({
726
+ level: "warn",
727
+ component: "senses",
728
+ event: "senses.private_runtime_worker_instinct_loop_capped",
729
+ message: "private-runtime worker stopped chaining instinct turns; pending work remains for next external trigger",
730
+ meta: {
731
+ consecutiveInstinctTurns,
732
+ cap: exports.MAX_CONSECUTIVE_INSTINCT_TURNS,
733
+ lastReason: nextReason,
734
+ },
735
+ });
736
+ finalizeCurrentHabitRun();
737
+ settleCurrentCompletion();
738
+ break;
739
+ }
740
+ if (currentReason === "habit" && currentHabitName && currentHabitRun) {
741
+ consecutiveInstinctTurns += 1;
742
+ nextReason = "habit";
743
+ nextTaskId = undefined;
744
+ nextHabitName = currentHabitName;
745
+ nextAwaitName = undefined;
746
+ nextTrigger = currentTrigger;
747
+ nextPrivateTurnDecision = undefined;
748
+ nextExternalEvent = undefined;
749
+ nextExternalEventHeartbeat = undefined;
750
+ nextNoSend = currentNoSend;
751
+ nextHabitRun = currentHabitRun;
752
+ }
753
+ else {
754
+ finalizeCurrentHabitRun();
755
+ consecutiveInstinctTurns += 1;
756
+ nextReason = "instinct";
757
+ nextTaskId = undefined;
758
+ nextHabitName = undefined;
759
+ nextAwaitName = undefined;
760
+ nextTrigger = undefined;
761
+ nextPrivateTurnDecision = undefined;
762
+ nextExternalEvent = undefined;
763
+ nextExternalEventHeartbeat = undefined;
764
+ nextNoSend = undefined;
765
+ }
766
+ nextCompletion = currentCompletion;
767
+ continue;
768
+ }
769
+ finalizeCurrentHabitRun();
770
+ settleCurrentCompletion();
771
+ break;
772
+ } while (true);
773
+ }
774
+ finally {
775
+ running = false;
776
+ }
777
+ })().catch((error) => {
778
+ activeCompletion?.reject(error);
779
+ for (const queued of queue.splice(0)) {
780
+ queued.stopExternalEventHeartbeat?.();
781
+ queued.completion.reject(error);
782
+ }
783
+ });
784
+ return completion.promise;
785
+ }
786
+ async function handleMessage(message) {
787
+ if (!message || typeof message !== "object")
788
+ return;
789
+ const maybeMessage = message;
790
+ if (maybeMessage.type === "habit") {
791
+ /* v8 ignore next -- defensive fallback: live habit dispatch always sets habitName @preserve */
792
+ const habitName = maybeMessage.habitName ?? "(unnamed)";
793
+ if (shouldReuseHeartbeatOkRest(habitName)) {
794
+ await reuseHeartbeatOkRest(habitName);
795
+ return;
796
+ }
797
+ recordHabitFireForRecursion(habitName);
798
+ await run("habit", undefined, maybeMessage.habitName, undefined, maybeMessage.trigger ?? "overdue", maybeMessage.privateTurnDecision, maybeMessage.noSend, undefined, maybeMessage.dispatchId);
799
+ return;
800
+ }
801
+ if (maybeMessage.type === "await") {
802
+ clearHeartbeatRestShield();
803
+ /* v8 ignore next -- defensive fallback: live await dispatch always sets awaitName @preserve */
804
+ const awaitName = maybeMessage.awaitName ?? "(unnamed)";
805
+ recordHabitFireForRecursion(`await:${awaitName}`);
806
+ await run("await", undefined, undefined, maybeMessage.awaitName, undefined, maybeMessage.privateTurnDecision, undefined, undefined, maybeMessage.dispatchId);
807
+ return;
808
+ }
809
+ if (maybeMessage.type === "heartbeat") {
810
+ // Backward compatibility: heartbeat -> habit/heartbeat
811
+ if (shouldReuseHeartbeatOkRest("heartbeat")) {
812
+ await reuseHeartbeatOkRest("heartbeat");
813
+ return;
814
+ }
815
+ recordHabitFireForRecursion("heartbeat");
816
+ await run("habit", undefined, "heartbeat", undefined, "overdue", maybeMessage.privateTurnDecision, undefined, undefined, maybeMessage.dispatchId);
817
+ return;
818
+ }
819
+ if (maybeMessage.type === "poke") {
820
+ clearHeartbeatRestShield();
821
+ await run("instinct", maybeMessage.taskId, undefined, undefined, undefined, maybeMessage.privateTurnDecision, undefined, undefined, maybeMessage.dispatchId);
822
+ return;
823
+ }
824
+ if (maybeMessage.type === "chat" ||
825
+ maybeMessage.type === "message") {
826
+ clearHeartbeatRestShield();
827
+ await run("instinct", undefined, undefined, undefined, undefined, maybeMessage.privateTurnDecision, undefined, maybeMessage.externalEvent, maybeMessage.dispatchId);
828
+ return;
829
+ }
830
+ if (maybeMessage.type === "shutdown") {
831
+ process.exit(0);
832
+ }
833
+ }
834
+ function cancelMessage(dispatchId) {
835
+ const index = queue.findIndex((entry) => entry.dispatchId === dispatchId);
836
+ if (index < 0)
837
+ return false;
838
+ const [cancelled] = queue.splice(index, 1);
839
+ cancelled?.stopExternalEventHeartbeat?.();
840
+ cancelled?.completion.reject(new Error(`Private-runtime dispatch ${dispatchId} was cancelled.`));
841
+ return true;
842
+ }
843
+ return { run, handleMessage, cancelMessage };
844
+ }
845
+ async function startPrivateRuntimeWorker(options = {}) {
846
+ const worker = createPrivateRuntimeWorker();
847
+ if (options.attachProcessListeners ?? true) {
848
+ process.on("message", (message) => {
849
+ void worker.handleMessage(message);
850
+ });
851
+ process.on("disconnect", () => {
852
+ process.exit(0);
853
+ });
854
+ }
855
+ for (const message of options.bufferedMessages ?? []) {
856
+ void worker.handleMessage(message);
857
+ }
858
+ return worker;
859
+ }