@ouro.bot/cli 0.1.0-alpha.8 → 0.1.0-alpha.800

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 (624) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -176
  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/SerpentGuide.ouro/agent.json +83 -0
  11. package/SerpentGuide.ouro/psyche/SOUL.md +25 -0
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
  13. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  14. package/assets/bluebubbles-host +264 -0
  15. package/assets/ouroboros.png +0 -0
  16. package/changelog.json +5563 -0
  17. package/deploy/unraid/Dockerfile +48 -0
  18. package/deploy/unraid/README.txt +3012 -0
  19. package/deploy/unraid/audit-container-spec.sh +4 -0
  20. package/deploy/unraid/container-runtime.json +1 -0
  21. package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
  22. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  23. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  24. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  25. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  26. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  27. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  28. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  29. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  30. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  31. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  32. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  33. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  34. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2030 -0
  35. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  36. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  37. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  38. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  39. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  40. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  41. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  43. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +11 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +11 -0
  47. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  48. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  49. package/deploy/unraid/sanctuary.xml +27 -0
  50. package/dist/a2a/card.js +57 -0
  51. package/dist/a2a/client.js +180 -0
  52. package/dist/a2a/config.js +50 -0
  53. package/dist/a2a/delegation-stores.js +56 -0
  54. package/dist/a2a/did-resolution.js +93 -0
  55. package/dist/a2a/identity.js +170 -0
  56. package/dist/a2a/inbound-share.js +107 -0
  57. package/dist/a2a/mission-result-wire.js +196 -0
  58. package/dist/a2a/onboarding.js +115 -0
  59. package/dist/a2a/pin-store.js +132 -0
  60. package/dist/a2a/seen-ledger.js +120 -0
  61. package/dist/a2a/server.js +604 -0
  62. package/dist/a2a/task-store.js +69 -0
  63. package/dist/a2a/transport.js +45 -0
  64. package/dist/a2a/types.js +3 -0
  65. package/dist/arc/attention-types.js +8 -0
  66. package/dist/arc/cares.js +360 -0
  67. package/dist/arc/episodes.js +118 -0
  68. package/dist/arc/evolution.js +490 -0
  69. package/dist/arc/flight-recorder.js +1034 -0
  70. package/dist/arc/intentions.js +134 -0
  71. package/dist/arc/json-store.js +117 -0
  72. package/dist/arc/obligations.js +386 -0
  73. package/dist/arc/packets.js +336 -0
  74. package/dist/arc/presence.js +185 -0
  75. package/dist/arc/task-lifecycle.js +57 -0
  76. package/dist/commerce/store.js +755 -0
  77. package/dist/commerce/types.js +3 -0
  78. package/dist/heart/active-work.js +1009 -0
  79. package/dist/heart/agent-entry.js +252 -3
  80. package/dist/heart/approval-files.js +113 -0
  81. package/dist/heart/approval-store.js +950 -0
  82. package/dist/heart/attachments/image-normalize.js +194 -0
  83. package/dist/heart/attachments/materialize.js +97 -0
  84. package/dist/heart/attachments/originals.js +88 -0
  85. package/dist/heart/attachments/render.js +29 -0
  86. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  87. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  88. package/dist/heart/attachments/sources/index.js +18 -0
  89. package/dist/heart/attachments/sources/telegram.js +71 -0
  90. package/dist/heart/attachments/store.js +132 -0
  91. package/dist/heart/attachments/types.js +93 -0
  92. package/dist/heart/auth/auth-flow.js +495 -0
  93. package/dist/heart/autonomy-budget.js +478 -0
  94. package/dist/heart/awaiting/await-alert.js +148 -0
  95. package/dist/heart/awaiting/await-expiry.js +143 -0
  96. package/dist/heart/awaiting/await-loader.js +91 -0
  97. package/dist/heart/awaiting/await-parser.js +149 -0
  98. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  99. package/dist/heart/awaiting/await-scheduler.js +382 -0
  100. package/dist/heart/background-operations.js +281 -0
  101. package/dist/heart/bridges/manager.js +478 -0
  102. package/dist/heart/bridges/state-machine.js +135 -0
  103. package/dist/heart/bridges/store.js +135 -0
  104. package/dist/heart/bundle-state.js +168 -0
  105. package/dist/heart/commitments.js +135 -0
  106. package/dist/heart/config-registry.js +331 -0
  107. package/dist/heart/config.js +195 -137
  108. package/dist/heart/context-loss-gauntlet.js +387 -0
  109. package/dist/heart/context-loss-sentinel.js +1157 -0
  110. package/dist/heart/core.js +2257 -338
  111. package/dist/heart/cross-chat-delivery.js +133 -0
  112. package/dist/heart/daemon/agent-config-check.js +451 -0
  113. package/dist/heart/daemon/agent-discovery.js +263 -0
  114. package/dist/heart/daemon/agent-service.js +542 -0
  115. package/dist/heart/daemon/agentic-repair.js +547 -0
  116. package/dist/heart/daemon/await-private-wake.js +59 -0
  117. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  118. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  119. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  120. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  121. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  122. package/dist/heart/daemon/cadence.js +180 -0
  123. package/dist/heart/daemon/cli-defaults.js +836 -0
  124. package/dist/heart/daemon/cli-desk.js +322 -0
  125. package/dist/heart/daemon/cli-exec.js +8730 -0
  126. package/dist/heart/daemon/cli-help.js +710 -0
  127. package/dist/heart/daemon/cli-parse.js +2719 -0
  128. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  129. package/dist/heart/daemon/cli-render.js +777 -0
  130. package/dist/heart/daemon/cli-types.js +8 -0
  131. package/dist/heart/daemon/connect-bay.js +323 -0
  132. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  133. package/dist/heart/daemon/container-healthcheck.js +112 -0
  134. package/dist/heart/daemon/container-runtime.js +97 -0
  135. package/dist/heart/daemon/container-spec-auditor-main.js +170 -0
  136. package/dist/heart/daemon/container-spec-auditor.js +236 -0
  137. package/dist/heart/daemon/daemon-bootstrap-startup.js +107 -0
  138. package/dist/heart/daemon/daemon-cli.js +30 -786
  139. package/dist/heart/daemon/daemon-entry.js +971 -13
  140. package/dist/heart/daemon/daemon-health.js +186 -0
  141. package/dist/heart/daemon/daemon-rollup.js +57 -0
  142. package/dist/heart/daemon/daemon-runtime-sync.js +287 -0
  143. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  144. package/dist/heart/daemon/daemon.js +2156 -28
  145. package/dist/heart/daemon/dns-workflow.js +394 -0
  146. package/dist/heart/daemon/doctor-types.js +8 -0
  147. package/dist/heart/daemon/doctor.js +1755 -0
  148. package/dist/heart/daemon/freshness.js +345 -0
  149. package/dist/heart/daemon/habit-private-wake.js +61 -0
  150. package/dist/heart/daemon/health-monitor.js +142 -11
  151. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  152. package/dist/heart/daemon/hooks/bundle-meta.js +226 -0
  153. package/dist/heart/daemon/http-health-probe.js +80 -0
  154. package/dist/heart/daemon/human-command-screens.js +234 -0
  155. package/dist/heart/daemon/human-readiness.js +114 -0
  156. package/dist/heart/daemon/inner-status.js +78 -0
  157. package/dist/heart/daemon/interactive-repair.js +394 -0
  158. package/dist/heart/daemon/launchd.js +188 -0
  159. package/dist/heart/daemon/log-tailer.js +82 -12
  160. package/dist/heart/daemon/logs-prune.js +132 -0
  161. package/dist/heart/daemon/mcp-canary.js +524 -0
  162. package/dist/heart/daemon/message-router.js +80 -11
  163. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  164. package/dist/heart/daemon/os-cron-deps.js +135 -0
  165. package/dist/heart/daemon/os-cron.js +22 -14
  166. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  167. package/dist/heart/daemon/ouro-entry.js +3 -1
  168. package/dist/heart/daemon/plugin-cli.js +432 -0
  169. package/dist/heart/daemon/process-manager.js +739 -54
  170. package/dist/heart/daemon/provider-discovery.js +137 -0
  171. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  172. package/dist/heart/daemon/prunable-bundle.js +144 -0
  173. package/dist/heart/daemon/pulse.js +511 -0
  174. package/dist/heart/daemon/readiness-repair.js +365 -0
  175. package/dist/heart/daemon/run-hooks.js +39 -0
  176. package/dist/heart/daemon/runtime-logging.js +92 -16
  177. package/dist/heart/daemon/runtime-metadata.js +191 -0
  178. package/dist/{repertoire/tasks/lifecycle.js → heart/daemon/runtime-mode.js} +37 -39
  179. package/dist/heart/daemon/safe-mode.js +161 -0
  180. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2609 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1866 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +976 -0
  184. package/dist/heart/daemon/sanctuary-bundle-migration.js +728 -0
  185. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  186. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  187. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  188. package/dist/heart/daemon/sense-manager.js +948 -0
  189. package/dist/heart/daemon/session-id-resolver.js +131 -0
  190. package/dist/heart/daemon/skill-management-installer.js +94 -0
  191. package/dist/heart/daemon/socket-client.js +370 -0
  192. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  193. package/dist/heart/daemon/startup-tui.js +339 -0
  194. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  195. package/dist/heart/daemon/task-scheduler.js +117 -39
  196. package/dist/heart/daemon/terminal-ui.js +499 -0
  197. package/dist/heart/daemon/thoughts.js +591 -0
  198. package/dist/heart/daemon/up-progress.js +366 -0
  199. package/dist/heart/daemon/vault-items.js +56 -0
  200. package/dist/heart/delegation.js +59 -0
  201. package/dist/heart/external-events/router.js +1414 -0
  202. package/dist/heart/habits/habit-cancel.js +810 -0
  203. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  204. package/dist/heart/habits/habit-migration.js +194 -0
  205. package/dist/heart/habits/habit-parser.js +278 -0
  206. package/dist/heart/habits/habit-runtime-state.js +93 -0
  207. package/dist/heart/habits/habit-scheduler.js +653 -0
  208. package/dist/heart/habits/habit-session-summary.js +318 -0
  209. package/dist/heart/habits/habit-session.js +636 -0
  210. package/dist/heart/{daemon → hatch}/hatch-animation.js +10 -3
  211. package/dist/heart/{daemon → hatch}/hatch-flow.js +57 -139
  212. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  213. package/dist/heart/hatch/specialist-orchestrator.js +129 -0
  214. package/dist/heart/hatch/specialist-prompt.js +102 -0
  215. package/dist/heart/hatch/specialist-tools.js +318 -0
  216. package/dist/heart/identity.js +297 -67
  217. package/dist/heart/kept-notes.js +289 -0
  218. package/dist/heart/kicks.js +2 -20
  219. package/dist/heart/machine-identity.js +161 -0
  220. package/dist/heart/mail-import-discovery.js +353 -0
  221. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  222. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  223. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  224. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  225. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  226. package/dist/heart/mailbox/mailbox-http.js +99 -0
  227. package/dist/heart/mailbox/mailbox-read.js +39 -0
  228. package/dist/heart/mailbox/mailbox-types.js +27 -0
  229. package/dist/heart/mailbox/mailbox-view.js +197 -0
  230. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  231. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  232. package/dist/heart/mailbox/readers/mail.js +375 -0
  233. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  234. package/dist/heart/mailbox/readers/sessions.js +232 -0
  235. package/dist/heart/mailbox/readers/shared.js +111 -0
  236. package/dist/heart/mcp/mcp-server.js +696 -0
  237. package/dist/heart/migrate-config.js +100 -0
  238. package/dist/heart/model-capabilities.js +59 -0
  239. package/dist/heart/orientation-frame.js +345 -0
  240. package/dist/heart/platform.js +81 -0
  241. package/dist/heart/primitives.js +1 -1
  242. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  243. package/dist/heart/private-runtime/index.js +18 -0
  244. package/dist/heart/private-runtime/ledger.js +221 -0
  245. package/dist/heart/private-runtime/policy.js +252 -0
  246. package/dist/heart/private-runtime/types.js +2 -0
  247. package/dist/heart/progress-story.js +42 -0
  248. package/dist/heart/provider-attempt.js +137 -0
  249. package/dist/heart/provider-binding-resolver.js +273 -0
  250. package/dist/heart/provider-credentials.js +449 -0
  251. package/dist/heart/provider-failover.js +311 -0
  252. package/dist/heart/provider-models.js +96 -0
  253. package/dist/heart/provider-ping.js +265 -0
  254. package/dist/heart/provider-readiness-cache.js +119 -0
  255. package/dist/heart/provider-visibility.js +188 -0
  256. package/dist/heart/providers/anthropic-token.js +131 -0
  257. package/dist/heart/providers/anthropic.js +236 -58
  258. package/dist/heart/providers/azure.js +104 -13
  259. package/dist/heart/providers/error-classification.js +127 -0
  260. package/dist/heart/providers/github-copilot.js +145 -0
  261. package/dist/heart/providers/minimax-vlm.js +189 -0
  262. package/dist/heart/providers/minimax.js +29 -7
  263. package/dist/heart/providers/openai-codex-token.js +349 -0
  264. package/dist/heart/providers/openai-codex.js +63 -39
  265. package/dist/heart/providers/openai-compatible.js +177 -0
  266. package/dist/heart/run-ledger.js +247 -0
  267. package/dist/heart/runtime-capability-check.js +170 -0
  268. package/dist/heart/runtime-credentials.js +607 -0
  269. package/dist/heart/runtime-cwd.js +87 -0
  270. package/dist/heart/sense-truth.js +79 -0
  271. package/dist/heart/session-activity.js +235 -0
  272. package/dist/heart/session-events.js +1318 -0
  273. package/dist/heart/session-playback-cli-main.js +5 -0
  274. package/dist/heart/session-playback-cli.js +36 -0
  275. package/dist/heart/session-playback.js +231 -0
  276. package/dist/heart/session-stats-cli-main.js +5 -0
  277. package/dist/heart/session-stats.js +182 -0
  278. package/dist/heart/session-transcript.js +133 -0
  279. package/dist/heart/start-of-turn-packet.js +372 -0
  280. package/dist/heart/steward-policy.js +302 -0
  281. package/dist/heart/streaming.js +682 -207
  282. package/dist/heart/structured-output.js +196 -0
  283. package/dist/heart/sync-classification.js +176 -0
  284. package/dist/heart/sync.js +449 -0
  285. package/dist/heart/target-resolution.js +127 -0
  286. package/dist/heart/tempo.js +93 -0
  287. package/dist/heart/temporal-view.js +41 -0
  288. package/dist/heart/timeouts.js +101 -0
  289. package/dist/heart/tool-activity-callbacks.js +59 -0
  290. package/dist/heart/tool-approval.js +342 -0
  291. package/dist/heart/tool-description.js +155 -0
  292. package/dist/heart/tool-friction.js +55 -0
  293. package/dist/heart/tool-loop.js +200 -0
  294. package/dist/heart/turn-context.js +481 -0
  295. package/dist/heart/turn-coordinator.js +28 -0
  296. package/dist/heart/versioning/ouro-bot-global-installer.js +129 -0
  297. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  298. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  299. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  300. package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
  301. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  302. package/dist/heart/versioning/staged-restart.js +146 -0
  303. package/dist/heart/versioning/update-checker.js +116 -0
  304. package/dist/heart/versioning/update-hooks.js +154 -0
  305. package/dist/heart/versioning/version-intent.js +114 -0
  306. package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
  307. package/dist/heart/work-card.js +380 -0
  308. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  309. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  310. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  311. package/dist/mailbox-ui/index.html +16 -0
  312. package/dist/mailroom/attention.js +167 -0
  313. package/dist/mailroom/autonomy.js +209 -0
  314. package/dist/mailroom/blob-store.js +889 -0
  315. package/dist/mailroom/body-cache.js +61 -0
  316. package/dist/mailroom/cache-sync-cli.js +58 -0
  317. package/dist/mailroom/core.js +803 -0
  318. package/dist/mailroom/entry.js +160 -0
  319. package/dist/mailroom/file-store.js +568 -0
  320. package/dist/mailroom/hosted-cache-sync.js +384 -0
  321. package/dist/mailroom/mbox-import.js +393 -0
  322. package/dist/mailroom/migration.js +164 -0
  323. package/dist/mailroom/outbound.js +380 -0
  324. package/dist/mailroom/policy.js +263 -0
  325. package/dist/mailroom/reader.js +292 -0
  326. package/dist/mailroom/search-cache.js +513 -0
  327. package/dist/mailroom/search-relevance.js +319 -0
  328. package/dist/mailroom/smtp-ingress.js +176 -0
  329. package/dist/mailroom/source-state.js +176 -0
  330. package/dist/mailroom/thread.js +109 -0
  331. package/dist/mailroom/travel-extract.js +89 -0
  332. package/dist/mind/bundle-manifest.js +93 -1
  333. package/dist/mind/context.js +287 -104
  334. package/dist/mind/desk-section.js +362 -0
  335. package/dist/mind/diary-integrity.js +60 -0
  336. package/dist/mind/{memory.js → diary.js} +90 -98
  337. package/dist/mind/embedding-provider.js +60 -0
  338. package/dist/mind/file-state.js +179 -0
  339. package/dist/mind/first-impressions.js +16 -2
  340. package/dist/mind/{associative-recall.js → note-search.js} +61 -60
  341. package/dist/mind/obligation-steering.js +227 -0
  342. package/dist/mind/pending.js +102 -9
  343. package/dist/mind/phrases.js +1 -0
  344. package/dist/mind/prompt-budget.js +479 -0
  345. package/dist/mind/prompt-refresh.js +3 -2
  346. package/dist/mind/prompt.js +1377 -140
  347. package/dist/mind/provenance-trust.js +26 -0
  348. package/dist/mind/record-paths.js +312 -0
  349. package/dist/mind/scrutiny.js +173 -0
  350. package/dist/mind/session-transaction.js +415 -0
  351. package/dist/mind/token-estimate.js +8 -12
  352. package/dist/nerves/cli-logging.js +22 -3
  353. package/dist/nerves/coverage/audit-rules.js +15 -6
  354. package/dist/nerves/coverage/audit.js +28 -2
  355. package/dist/nerves/coverage/cli.js +1 -1
  356. package/dist/nerves/coverage/contract.js +5 -5
  357. package/dist/nerves/coverage/file-completeness.js +139 -5
  358. package/dist/nerves/coverage/run-artifacts.js +56 -36
  359. package/dist/nerves/coverage/source-scanner.js +4 -4
  360. package/dist/nerves/event-buffer.js +111 -0
  361. package/dist/nerves/index.js +305 -9
  362. package/dist/nerves/observation.js +20 -0
  363. package/dist/nerves/redact.js +79 -0
  364. package/dist/nerves/review/cli-main.js +5 -0
  365. package/dist/nerves/review/cli.js +156 -0
  366. package/dist/nerves/review/core.js +159 -0
  367. package/dist/nerves/runtime.js +17 -1
  368. package/dist/repertoire/ado-client.js +17 -56
  369. package/dist/repertoire/ado-semantic.js +16 -10
  370. package/dist/repertoire/api-client.js +97 -0
  371. package/dist/repertoire/bitwarden-store.js +1045 -0
  372. package/dist/repertoire/bundle-templates.js +71 -0
  373. package/dist/repertoire/bw-installer.js +180 -0
  374. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  375. package/dist/repertoire/coding/context-pack.js +331 -0
  376. package/dist/repertoire/coding/feedback.js +322 -0
  377. package/dist/repertoire/coding/index.js +18 -3
  378. package/dist/repertoire/coding/manager.js +228 -14
  379. package/dist/repertoire/coding/spawner.js +61 -14
  380. package/dist/repertoire/coding/tools.js +279 -12
  381. package/dist/repertoire/coding/workbench-client.js +272 -0
  382. package/dist/repertoire/coding/workbench-manager.js +346 -0
  383. package/dist/repertoire/commerce-errors.js +109 -0
  384. package/dist/repertoire/commerce-self-test.js +156 -0
  385. package/dist/repertoire/credential-access.js +178 -0
  386. package/dist/repertoire/data/ado-endpoints.json +188 -0
  387. package/dist/repertoire/desk/classifier.js +362 -0
  388. package/dist/repertoire/duffel-client.js +185 -0
  389. package/dist/repertoire/github-client.js +14 -55
  390. package/dist/repertoire/graph-client.js +11 -52
  391. package/dist/repertoire/guardrails.js +1083 -0
  392. package/dist/repertoire/mcp-client.js +295 -0
  393. package/dist/repertoire/mcp-manager.js +434 -0
  394. package/dist/repertoire/mcp-tools.js +83 -0
  395. package/dist/repertoire/plugin-mcp.js +175 -0
  396. package/dist/repertoire/plugins.js +253 -0
  397. package/dist/repertoire/relationship-authorization.js +194 -0
  398. package/dist/repertoire/shell-sessions.js +133 -0
  399. package/dist/repertoire/skills.js +45 -24
  400. package/dist/repertoire/stripe-client.js +131 -0
  401. package/dist/repertoire/tool-arguments.js +148 -0
  402. package/dist/repertoire/tool-results.js +29 -0
  403. package/dist/repertoire/tools-a2a.js +699 -0
  404. package/dist/repertoire/tools-attachments.js +322 -0
  405. package/dist/repertoire/tools-awaiting.js +575 -0
  406. package/dist/repertoire/tools-base.js +85 -707
  407. package/dist/repertoire/tools-bluebubbles.js +95 -0
  408. package/dist/repertoire/tools-bridge.js +144 -0
  409. package/dist/repertoire/tools-bundle.js +993 -0
  410. package/dist/repertoire/tools-commerce.js +253 -0
  411. package/dist/repertoire/tools-config.js +186 -0
  412. package/dist/repertoire/tools-continuity.js +575 -0
  413. package/dist/repertoire/tools-credential.js +383 -0
  414. package/dist/repertoire/tools-evolution.js +527 -0
  415. package/dist/repertoire/tools-files.js +344 -0
  416. package/dist/repertoire/tools-flight.js +290 -0
  417. package/dist/repertoire/tools-flow.js +119 -0
  418. package/dist/repertoire/tools-github.js +3 -8
  419. package/dist/repertoire/tools-habits.js +103 -0
  420. package/dist/repertoire/tools-mail.js +1828 -0
  421. package/dist/repertoire/tools-notes.js +485 -0
  422. package/dist/repertoire/tools-obligations.js +182 -0
  423. package/dist/repertoire/tools-orientation.js +31 -0
  424. package/dist/repertoire/tools-record.js +482 -0
  425. package/dist/repertoire/tools-rsvp.js +139 -0
  426. package/dist/repertoire/tools-runtime.js +150 -0
  427. package/dist/repertoire/tools-session.js +1108 -0
  428. package/dist/repertoire/tools-shell.js +133 -0
  429. package/dist/repertoire/tools-steward-policy.js +95 -0
  430. package/dist/repertoire/tools-stripe.js +224 -0
  431. package/dist/repertoire/tools-surface.js +369 -0
  432. package/dist/repertoire/tools-teams.js +67 -61
  433. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  434. package/dist/repertoire/tools-travel.js +125 -0
  435. package/dist/repertoire/tools-trip.js +982 -0
  436. package/dist/repertoire/tools-unraid.js +484 -0
  437. package/dist/repertoire/tools-user-profile.js +146 -0
  438. package/dist/repertoire/tools-vault.js +40 -0
  439. package/dist/repertoire/tools-voice.js +145 -0
  440. package/dist/repertoire/tools.js +441 -102
  441. package/dist/repertoire/travel-api-client.js +360 -0
  442. package/dist/repertoire/unraid-client.js +155 -0
  443. package/dist/repertoire/unraid-restart.js +212 -0
  444. package/dist/repertoire/user-profile.js +131 -0
  445. package/dist/repertoire/vault-setup.js +246 -0
  446. package/dist/repertoire/vault-unlock.js +628 -0
  447. package/dist/rsvp/aisleplanner-client.js +354 -0
  448. package/dist/rsvp/cli.js +926 -0
  449. package/dist/rsvp/config.js +327 -0
  450. package/dist/rsvp/cutover.js +433 -0
  451. package/dist/rsvp/diagnostics.js +232 -0
  452. package/dist/rsvp/diff-renderer.js +176 -0
  453. package/dist/rsvp/habit-policy.js +110 -0
  454. package/dist/rsvp/habit-stage.js +123 -0
  455. package/dist/rsvp/incident-bundle.js +97 -0
  456. package/dist/rsvp/migration.js +204 -0
  457. package/dist/rsvp/native-habit-runner.js +630 -0
  458. package/dist/rsvp/outbound-state.js +628 -0
  459. package/dist/rsvp/query.js +118 -0
  460. package/dist/rsvp/replay.js +233 -0
  461. package/dist/rsvp/snapshot.js +232 -0
  462. package/dist/rsvp/spend-ledger.js +175 -0
  463. package/dist/scripts/claude-code-hook.js +41 -0
  464. package/dist/scripts/claude-code-stop-hook.js +47 -0
  465. package/dist/senses/a2a-entry.js +115 -0
  466. package/dist/senses/attention-queue.js +186 -0
  467. package/dist/senses/await-turn-message.js +58 -0
  468. package/dist/senses/bluebubbles/active-turns.js +216 -0
  469. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  470. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  471. package/dist/senses/bluebubbles/client.js +799 -0
  472. package/dist/senses/bluebubbles/context-packet.js +207 -0
  473. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  474. package/dist/senses/bluebubbles/entry.js +90 -0
  475. package/dist/senses/bluebubbles/inbound-log.js +127 -0
  476. package/dist/senses/bluebubbles/index.js +3839 -0
  477. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  478. package/dist/senses/bluebubbles/media.js +389 -0
  479. package/dist/senses/bluebubbles/model.js +392 -0
  480. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +57 -6
  481. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  482. package/dist/senses/bluebubbles/processed-log.js +133 -0
  483. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  484. package/dist/senses/bluebubbles/replay.js +284 -0
  485. package/dist/senses/bluebubbles/runtime-state.js +137 -0
  486. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  487. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  488. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  489. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  490. package/dist/senses/cli/bracketed-paste.js +82 -0
  491. package/dist/senses/cli/image-paste.js +287 -0
  492. package/dist/senses/cli/image-ref-navigation.js +75 -0
  493. package/dist/senses/cli/ink-app.js +156 -0
  494. package/dist/senses/cli/inline-diff.js +64 -0
  495. package/dist/senses/cli/input-keys.js +174 -0
  496. package/dist/senses/cli/kill-ring.js +86 -0
  497. package/dist/senses/cli/message-list.js +51 -0
  498. package/dist/senses/cli/ouro-tui.js +607 -0
  499. package/dist/senses/cli/spinner-imperative.js +135 -0
  500. package/dist/senses/cli/spinner.js +101 -0
  501. package/dist/senses/cli/status-line.js +60 -0
  502. package/dist/senses/cli/streaming-markdown.js +526 -0
  503. package/dist/senses/cli/tool-display.js +85 -0
  504. package/dist/senses/cli/tool-render.js +85 -0
  505. package/dist/senses/cli/tui-store.js +241 -0
  506. package/dist/senses/cli/virtual-list.js +35 -0
  507. package/dist/senses/cli-entry.js +60 -8
  508. package/dist/senses/cli-layout.js +187 -0
  509. package/dist/senses/cli.js +813 -281
  510. package/dist/senses/commands.js +66 -3
  511. package/dist/senses/context-packet-ledger.js +371 -0
  512. package/dist/senses/context-packets.js +154 -0
  513. package/dist/senses/continuity.js +94 -0
  514. package/dist/senses/habit-lifecycle-guard.js +24 -0
  515. package/dist/senses/habit-turn-message.js +160 -0
  516. package/dist/senses/ingress-evidence.js +2 -0
  517. package/dist/senses/mail-entry.js +66 -0
  518. package/dist/senses/mail.js +524 -0
  519. package/dist/senses/pipeline.js +1213 -0
  520. package/dist/senses/private-runtime-worker.js +859 -0
  521. package/dist/senses/private-runtime.js +1496 -0
  522. package/dist/senses/proactive-content-guard.js +51 -0
  523. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  524. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  525. package/dist/senses/sanctuary-grounding.js +118 -0
  526. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  527. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  528. package/dist/senses/sanctuary-health-runner.js +101 -0
  529. package/dist/senses/sanctuary-health.js +408 -0
  530. package/dist/senses/sanctuary-interactive-control.js +306 -0
  531. package/dist/senses/sanctuary-media-catalog-contract.js +235 -0
  532. package/dist/senses/sanctuary-media-optimization.js +514 -0
  533. package/dist/senses/sanctuary-runtime.js +338 -0
  534. package/dist/senses/sanctuary-sab.js +85 -0
  535. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  536. package/dist/senses/shared-turn.js +571 -0
  537. package/dist/senses/surface-tool.js +109 -0
  538. package/dist/senses/teams-entry.js +60 -8
  539. package/dist/senses/teams.js +953 -211
  540. package/dist/senses/telegram-admission.js +711 -0
  541. package/dist/senses/telegram-approval-runtime.js +566 -0
  542. package/dist/senses/telegram-attachments.js +182 -0
  543. package/dist/senses/telegram-audit-ledger.js +220 -0
  544. package/dist/senses/telegram-client.js +1677 -0
  545. package/dist/senses/telegram-effect-adapter.js +859 -0
  546. package/dist/senses/telegram-entry.js +83 -0
  547. package/dist/senses/telegram.js +2026 -0
  548. package/dist/senses/trust-gate.js +207 -2
  549. package/dist/senses/voice/audio-playback.js +237 -0
  550. package/dist/senses/voice/audio-routing.js +119 -0
  551. package/dist/senses/voice/elevenlabs.js +202 -0
  552. package/dist/senses/voice/floor-control.js +431 -0
  553. package/dist/senses/voice/floor-controller.js +115 -0
  554. package/dist/senses/voice/golden-path.js +116 -0
  555. package/dist/senses/voice/index.js +29 -0
  556. package/dist/senses/voice/meeting.js +113 -0
  557. package/dist/senses/voice/outbound.js +190 -0
  558. package/dist/senses/voice/phone.js +33 -0
  559. package/dist/senses/voice/playback.js +139 -0
  560. package/dist/senses/voice/realtime-eval.js +496 -0
  561. package/dist/senses/voice/realtime-trace.js +531 -0
  562. package/dist/senses/voice/transcript.js +70 -0
  563. package/dist/senses/voice/turn.js +191 -0
  564. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  565. package/dist/senses/voice/twilio-phone.js +5081 -0
  566. package/dist/senses/voice/types.js +2 -0
  567. package/dist/senses/voice/whisper.js +161 -0
  568. package/dist/senses/voice-entry.js +81 -0
  569. package/dist/senses/voice-realtime-eval-command.js +99 -0
  570. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  571. package/dist/senses/voice-twilio-entry.js +87 -0
  572. package/dist/trips/core.js +138 -0
  573. package/dist/trips/store.js +265 -0
  574. package/dist/util/frontmatter.js +69 -0
  575. package/npm-shrinkwrap.json +8144 -0
  576. package/package.json +82 -12
  577. package/skills/agent-commerce.md +113 -0
  578. package/skills/browser-navigation.md +117 -0
  579. package/skills/commerce-setup-guide.md +116 -0
  580. package/skills/commerce-setup.md +84 -0
  581. package/skills/configure-dev-tools.md +99 -0
  582. package/skills/travel-planning.md +138 -0
  583. package/AdoptionSpecialist.ouro/agent.json +0 -20
  584. package/AdoptionSpecialist.ouro/psyche/SOUL.md +0 -22
  585. package/dist/heart/daemon/specialist-orchestrator.js +0 -160
  586. package/dist/heart/daemon/specialist-prompt.js +0 -47
  587. package/dist/heart/daemon/specialist-session.js +0 -142
  588. package/dist/heart/daemon/specialist-tools.js +0 -132
  589. package/dist/heart/daemon/subagent-installer.js +0 -125
  590. package/dist/inner-worker-entry.js +0 -4
  591. package/dist/mind/friends/channel.js +0 -49
  592. package/dist/mind/friends/resolver.js +0 -84
  593. package/dist/mind/friends/store-file.js +0 -171
  594. package/dist/mind/friends/store.js +0 -4
  595. package/dist/mind/friends/tokens.js +0 -26
  596. package/dist/mind/friends/types.js +0 -21
  597. package/dist/repertoire/tasks/board.js +0 -122
  598. package/dist/repertoire/tasks/index.js +0 -210
  599. package/dist/repertoire/tasks/middleware.js +0 -65
  600. package/dist/repertoire/tasks/parser.js +0 -173
  601. package/dist/repertoire/tasks/scanner.js +0 -132
  602. package/dist/repertoire/tasks/transitions.js +0 -145
  603. package/dist/senses/bluebubbles-client.js +0 -279
  604. package/dist/senses/bluebubbles-entry.js +0 -11
  605. package/dist/senses/bluebubbles-model.js +0 -253
  606. package/dist/senses/bluebubbles.js +0 -332
  607. package/dist/senses/inner-dialog-worker.js +0 -61
  608. package/dist/senses/inner-dialog.js +0 -231
  609. package/subagents/README.md +0 -73
  610. package/subagents/work-doer.md +0 -233
  611. package/subagents/work-merger.md +0 -624
  612. package/subagents/work-planner.md +0 -373
  613. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  614. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  615. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  616. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  617. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  618. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  619. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  620. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  621. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  622. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  623. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  624. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
@@ -0,0 +1,810 @@
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.HabitCancellationError = exports.HISTORICAL_HABIT_EVIDENCE_BRIDGE_SHA256 = void 0;
37
+ exports.resolveHistoricalHabitEvidenceBridgeTrust = resolveHistoricalHabitEvidenceBridgeTrust;
38
+ exports.renderHabitCancellationAcknowledgement = renderHabitCancellationAcknowledgement;
39
+ exports.validateHabitEvidenceBridge = validateHabitEvidenceBridge;
40
+ exports.cancelHabit = cancelHabit;
41
+ const node_crypto_1 = require("node:crypto");
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const runtime_1 = require("../../nerves/runtime");
45
+ const semantic_receipts_1 = require("../../senses/bluebubbles/semantic-receipts");
46
+ const habit_parser_1 = require("./habit-parser");
47
+ const habit_lifecycle_1 = require("./habit-lifecycle");
48
+ const CAPTURE_LOCATOR_PATTERN = /^capture:([a-f0-9]{64})$/;
49
+ const HASH_PATTERN = /^[a-f0-9]{64}$/;
50
+ const BRIDGE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
51
+ const ISO_MILLISECONDS_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
52
+ const retainedCancellationLeases = new Map();
53
+ exports.HISTORICAL_HABIT_EVIDENCE_BRIDGE_SHA256 = "34a90f6ce3f7b092edb8114cf7ab640486fd7e6d7667acfd0249408fff394201";
54
+ function resolveHistoricalHabitEvidenceBridgeTrust(bridgeSha256, actorDisplayName) {
55
+ if (bridgeSha256 !== exports.HISTORICAL_HABIT_EVIDENCE_BRIDGE_SHA256)
56
+ return null;
57
+ return {
58
+ cancellationReason: `Confirmed requester ${actorDisplayName} asked to end the RSVP report after the wedding.`,
59
+ };
60
+ }
61
+ class HabitCancellationError extends Error {
62
+ code;
63
+ constructor(code, options = {}) {
64
+ super(code, options.cause === undefined ? undefined : { cause: options.cause });
65
+ this.name = "HabitCancellationError";
66
+ this.code = code;
67
+ }
68
+ }
69
+ exports.HabitCancellationError = HabitCancellationError;
70
+ function renderHabitCancellationAcknowledgement(habitId, actorDisplayName, boundaryState) {
71
+ return (0, habit_lifecycle_1.renderHabitCancellationAcknowledgement)(habitId, actorDisplayName, boundaryState);
72
+ }
73
+ function validateHabitEvidenceBridge(input, deps = {}) {
74
+ const storeFs = deps.fs ?? fs;
75
+ const agentRoot = requiredString(input.agentRoot, "bridge_agent_root_required");
76
+ const bridgeId = validatedBridgeId(input.bridgeId);
77
+ const bridgeRoot = path.join(agentRoot, "state", "senses", "bluebubbles", "evidence-bridges");
78
+ const bridgePath = path.join(bridgeRoot, `${bridgeId}.json`);
79
+ const bridgeBytes = readUtf8(storeFs, bridgePath, "bridge_evidence_missing");
80
+ const bridgeSha256 = sha256(bridgeBytes);
81
+ const value = parseJsonRecord(bridgeBytes, "bridge_evidence_invalid");
82
+ if ((0, habit_lifecycle_1.serializeHabitLifecycleJson)(value) !== bridgeBytes) {
83
+ throw new HabitCancellationError("bridge_evidence_not_canonical");
84
+ }
85
+ requireExactKeys(value, [
86
+ "schemaVersion",
87
+ "bridgeId",
88
+ "sourceKind",
89
+ "createdAt",
90
+ "confirmedAt",
91
+ "actor",
92
+ "participants",
93
+ "request",
94
+ "evidence",
95
+ ], "bridge_evidence_invalid");
96
+ if (value.schemaVersion !== 1
97
+ || value.bridgeId !== bridgeId
98
+ || value.sourceKind !== "operator_confirmation"
99
+ || !isCanonicalTimestamp(value.createdAt)
100
+ || value.confirmedAt !== value.createdAt)
101
+ throw new HabitCancellationError("bridge_evidence_invalid");
102
+ const actor = requiredRecord(value.actor, "bridge_actor_invalid");
103
+ requireExactKeys(actor, ["displayName", "provider", "externalId"], "bridge_actor_invalid");
104
+ const actorDisplayName = requiredSingleLine(actor.displayName, "bridge_actor_invalid");
105
+ if (actor.provider !== null || actor.externalId !== null) {
106
+ throw new HabitCancellationError("bridge_actor_invalid");
107
+ }
108
+ const trusted = deps.trustedBridge
109
+ ? deps.trustedBridge(bridgeId, bridgeSha256)
110
+ : resolveHistoricalHabitEvidenceBridgeTrust(bridgeSha256, actorDisplayName);
111
+ if (!trusted)
112
+ throw new HabitCancellationError("bridge_trust_rejected");
113
+ const cancellationReason = requiredSingleLine(trusted.cancellationReason, "bridge_cancellation_reason_invalid");
114
+ if (!Array.isArray(value.participants) || value.participants.length === 0) {
115
+ throw new HabitCancellationError("bridge_participants_invalid");
116
+ }
117
+ for (const participantValue of value.participants) {
118
+ const participant = requiredRecord(participantValue, "bridge_participants_invalid");
119
+ requireExactKeys(participant, ["displayName", "provider", "externalId", "role"], "bridge_participants_invalid");
120
+ requiredSingleLine(participant.displayName, "bridge_participants_invalid");
121
+ if (participant.provider !== null
122
+ || participant.externalId !== null
123
+ || participant.role !== "group_participant_only")
124
+ throw new HabitCancellationError("bridge_participants_invalid");
125
+ }
126
+ const request = requiredRecord(value.request, "bridge_request_invalid");
127
+ requireExactKeys(request, ["eventGuid", "text", "sha256"], "bridge_request_invalid");
128
+ const eventGuid = requiredString(request.eventGuid, "bridge_request_invalid");
129
+ const requestText = requiredString(request.text, "bridge_request_invalid");
130
+ const requestSha256 = validatedHash(request.sha256, "bridge_request_invalid");
131
+ if (sha256(requestText) !== requestSha256) {
132
+ throw new HabitCancellationError("bridge_request_invalid");
133
+ }
134
+ const evidence = requiredRecord(value.evidence, "bridge_evidence_invalid");
135
+ requireExactKeys(evidence, ["operatorConfirmation", "screenshots", "sources"], "bridge_evidence_invalid");
136
+ validateOperatorConfirmation(bridgeRoot, evidence.operatorConfirmation, storeFs);
137
+ validateBridgeScreenshots(bridgeRoot, evidence.screenshots, storeFs);
138
+ validateBridgeSources({
139
+ value: evidence.sources,
140
+ eventGuid,
141
+ requestText,
142
+ requestSha256,
143
+ storeFs,
144
+ });
145
+ return {
146
+ locator: { kind: "bridge", id: bridgeId },
147
+ actor: { displayName: actorDisplayName, provider: null, externalId: null },
148
+ request: {
149
+ text: requestText,
150
+ sha256: requestSha256,
151
+ observedAt: value.confirmedAt,
152
+ },
153
+ cancellationReason,
154
+ };
155
+ }
156
+ async function cancelHabit(input, deps = {}) {
157
+ let operationId = null;
158
+ let evidenceKeyHash = null;
159
+ let started = false;
160
+ try {
161
+ const locator = validatedCancellationLocator(input);
162
+ const identity = (0, habit_lifecycle_1.buildHabitEvidenceIdentity)({
163
+ habitId: input.habitId,
164
+ kind: locator.kind,
165
+ id: locator.id,
166
+ });
167
+ evidenceKeyHash = identity.evidenceKeyHash;
168
+ operationId = (0, habit_lifecycle_1.buildHabitCancellationOperation)(evidenceKeyHash).operationId;
169
+ emitHabitCancellationStart(input.habitId, operationId, evidenceKeyHash);
170
+ started = true;
171
+ readDefinitionSnapshot(input.agentRoot, input.habitId, deps);
172
+ const preflightJournal = (0, habit_lifecycle_1.readHabitLifecycleJournal)({
173
+ agentRoot: input.agentRoot,
174
+ habitId: input.habitId,
175
+ operationId,
176
+ }, deps);
177
+ const initialEvidence = preflightJournal?.state === "cancellation_receipt_committed"
178
+ ? null
179
+ : resolveCancellationEvidence(input, deps);
180
+ const leaseKey = cancellationLeaseKey(input.agentRoot, input.habitId, operationId);
181
+ let lease = retainedCancellationLeases.get(leaseKey);
182
+ if (lease && !(0, habit_lifecycle_1.habitLifecycleLeaseIsCurrent)(lease, deps)) {
183
+ retainedCancellationLeases.delete(leaseKey);
184
+ lease = undefined;
185
+ }
186
+ if (!lease) {
187
+ const lock = await (0, habit_lifecycle_1.acquireHabitLifecycleLock)({
188
+ agentRoot: input.agentRoot,
189
+ habitId: input.habitId,
190
+ operationId,
191
+ }, deps);
192
+ if (lock.status !== "acquired") {
193
+ throw new HabitCancellationError(lock.error);
194
+ }
195
+ lease = lock.lease;
196
+ }
197
+ let receipt = null;
198
+ let primaryError;
199
+ try {
200
+ let evidence = null;
201
+ if (initialEvidence !== null) {
202
+ evidence = resolveCancellationEvidence(input, deps);
203
+ if ((0, habit_lifecycle_1.serializeHabitLifecycleJson)(evidence) !== (0, habit_lifecycle_1.serializeHabitLifecycleJson)(initialEvidence)) {
204
+ throw new HabitCancellationError("cancellation_evidence_changed");
205
+ }
206
+ }
207
+ const definition = readDefinitionSnapshot(input.agentRoot, input.habitId, deps);
208
+ receipt = executeCancellationUnderLock({
209
+ lease,
210
+ definition,
211
+ evidence,
212
+ evidenceKeyHash,
213
+ operationId,
214
+ }, deps);
215
+ }
216
+ catch (error) {
217
+ primaryError = error;
218
+ }
219
+ let releaseError;
220
+ try {
221
+ await releaseCancellationLease(leaseKey, lease, deps);
222
+ }
223
+ catch (error) {
224
+ releaseError = error;
225
+ }
226
+ if (primaryError !== undefined)
227
+ throw primaryError;
228
+ if (releaseError !== undefined)
229
+ throw releaseError;
230
+ // executeCancellationUnderLock either returns a receipt or supplies primaryError.
231
+ const completedReceipt = receipt;
232
+ (0, runtime_1.emitNervesEvent)({
233
+ component: "daemon",
234
+ event: "habit_cancel_end",
235
+ message: "grounded habit cancellation completed",
236
+ meta: {
237
+ habitId: input.habitId,
238
+ operationId,
239
+ evidenceKeyHash,
240
+ boundaryState: completedReceipt.transition.boundaryState,
241
+ },
242
+ });
243
+ return completedReceipt;
244
+ }
245
+ catch (error) {
246
+ const wrapped = asCancellationError(error);
247
+ if (!started)
248
+ emitHabitCancellationStart(input.habitId, operationId, evidenceKeyHash);
249
+ (0, runtime_1.emitNervesEvent)({
250
+ level: "error",
251
+ component: "daemon",
252
+ event: "habit_cancel_error",
253
+ message: "grounded habit cancellation failed",
254
+ meta: {
255
+ habitId: input.habitId,
256
+ operationId,
257
+ evidenceKeyHash,
258
+ errorCode: wrapped.code,
259
+ },
260
+ });
261
+ throw wrapped;
262
+ }
263
+ }
264
+ function emitHabitCancellationStart(habitId, operationId, evidenceKeyHash) {
265
+ (0, runtime_1.emitNervesEvent)({
266
+ component: "daemon",
267
+ event: "habit_cancel_start",
268
+ message: "grounded habit cancellation started",
269
+ meta: { habitId, operationId, evidenceKeyHash },
270
+ });
271
+ }
272
+ function executeCancellationUnderLock(input, deps) {
273
+ const { lease, evidence, evidenceKeyHash, operationId } = input;
274
+ let definition = input.definition;
275
+ let journal = (0, habit_lifecycle_1.readHabitLifecycleJournal)({
276
+ agentRoot: lease.agentRoot,
277
+ habitId: lease.habitId,
278
+ operationId,
279
+ }, deps);
280
+ const existingReceipt = (0, habit_lifecycle_1.readHabitLifecycleReceipt)({
281
+ agentRoot: lease.agentRoot,
282
+ habitId: lease.habitId,
283
+ evidenceKeyHash,
284
+ }, deps);
285
+ if (journal?.state === "cancellation_receipt_committed") {
286
+ if (!existingReceipt) {
287
+ throw new HabitCancellationError("cancellation_committed_state_invalid");
288
+ }
289
+ const committedPreparation = journal.cancellationPreparation;
290
+ assertPreparedReceipt(existingReceipt, committedPreparation.receipt, null);
291
+ if (definition.status !== "cancelled") {
292
+ throw new HabitCancellationError("cancellation_definition_state_invalid");
293
+ }
294
+ assertDefinitionMatches(definition.bytes, committedPreparation.definitionCancelledSha256);
295
+ confirmCancellationDurability(lease, definition.path, evidenceKeyHash, operationId, deps);
296
+ return existingReceipt;
297
+ }
298
+ if (evidence === null)
299
+ throw new HabitCancellationError("cancellation_evidence_required");
300
+ if (journal === null || journal.state === "lock_acquired") {
301
+ if (existingReceipt)
302
+ throw new HabitCancellationError("cancellation_receipt_without_intent");
303
+ if (definition.status !== "active" && definition.status !== "paused") {
304
+ throw new HabitCancellationError("habit_definition_already_cancelled");
305
+ }
306
+ const cancelledAt = cancellationNow(deps);
307
+ const boundaryState = classifyConcurrentSendBoundary(lease.agentRoot, lease.habitId, evidence.request.observedAt, cancelledAt, deps);
308
+ const cancelledBytes = renderCancelledDefinition(definition, evidence.locator, evidence.cancellationReason, cancelledAt);
309
+ const receipt = buildCancellationReceipt({
310
+ habitId: lease.habitId,
311
+ operationId,
312
+ evidenceKeyHash,
313
+ evidence,
314
+ fromStatus: definition.status,
315
+ cancelledAt,
316
+ boundaryState,
317
+ });
318
+ const preparation = {
319
+ receipt,
320
+ definitionBeforeSha256: sha256(definition.bytes),
321
+ definitionCancelledSha256: sha256(cancelledBytes),
322
+ };
323
+ if (journal === null) {
324
+ journal = (0, habit_lifecycle_1.createHabitLifecycleJournal)({
325
+ habitId: lease.habitId,
326
+ operationId,
327
+ operationKind: "cancel",
328
+ updatedAt: cancelledAt,
329
+ });
330
+ (0, habit_lifecycle_1.writeHabitLifecycleJournal)(lease, journal, deps);
331
+ }
332
+ journal = (0, habit_lifecycle_1.transitionHabitLifecycleJournal)(journal, {
333
+ state: "cancellation_intent",
334
+ at: cancelledAt,
335
+ evidenceKeyHash,
336
+ cancellationPreparation: preparation,
337
+ });
338
+ (0, habit_lifecycle_1.writeHabitLifecycleJournal)(lease, journal, deps);
339
+ }
340
+ const preparation = journal.cancellationPreparation;
341
+ assertPreparedReceipt(preparation.receipt, preparation.receipt, evidence);
342
+ const journalPath = (0, habit_lifecycle_1.getHabitLifecyclePaths)({
343
+ agentRoot: lease.agentRoot,
344
+ habitId: lease.habitId,
345
+ operationId,
346
+ }).journal;
347
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, journalPath, deps);
348
+ const definitionHash = sha256(definition.bytes);
349
+ if (definitionHash === preparation.definitionBeforeSha256) {
350
+ if ((definition.status !== "active" && definition.status !== "paused")
351
+ || definition.status !== preparation.receipt.transition.fromStatus) {
352
+ throw new HabitCancellationError("cancellation_definition_state_invalid");
353
+ }
354
+ if (journal.state !== "cancellation_intent") {
355
+ throw new HabitCancellationError("cancellation_definition_state_invalid");
356
+ }
357
+ const cancelledBytes = renderCancelledDefinition(definition, evidence.locator, evidence.cancellationReason, preparation.receipt.transition.cancelledAt);
358
+ if (sha256(cancelledBytes) !== preparation.definitionCancelledSha256) {
359
+ throw new HabitCancellationError("cancellation_definition_digest_mismatch");
360
+ }
361
+ (0, habit_lifecycle_1.writeHabitLifecycleDefinition)(lease, definition.path, cancelledBytes, deps);
362
+ definition = { path: definition.path, bytes: cancelledBytes, status: "cancelled" };
363
+ }
364
+ else {
365
+ if (definitionHash !== preparation.definitionCancelledSha256) {
366
+ throw new HabitCancellationError("cancellation_definition_digest_mismatch");
367
+ }
368
+ if (definition.status !== "cancelled") {
369
+ throw new HabitCancellationError("cancellation_definition_state_invalid");
370
+ }
371
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, definition.path, deps);
372
+ }
373
+ if (journal.state === "cancellation_intent") {
374
+ journal = (0, habit_lifecycle_1.transitionHabitLifecycleJournal)(journal, {
375
+ state: "definition_cancelled",
376
+ at: preparation.receipt.transition.cancelledAt,
377
+ boundaryState: preparation.receipt.transition.boundaryState,
378
+ });
379
+ (0, habit_lifecycle_1.writeHabitLifecycleJournal)(lease, journal, deps);
380
+ }
381
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, journalPath, deps);
382
+ if (existingReceipt) {
383
+ assertPreparedReceipt(existingReceipt, preparation.receipt, evidence);
384
+ const receiptPath = (0, habit_lifecycle_1.getHabitLifecyclePaths)({
385
+ agentRoot: lease.agentRoot,
386
+ habitId: lease.habitId,
387
+ evidenceKeyHash,
388
+ }).receipt;
389
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, receiptPath, deps);
390
+ }
391
+ else {
392
+ (0, habit_lifecycle_1.publishHabitLifecycleReceipt)(lease, evidenceKeyHash, preparation.receipt, deps);
393
+ }
394
+ journal = (0, habit_lifecycle_1.transitionHabitLifecycleJournal)(journal, {
395
+ state: "cancellation_receipt_committed",
396
+ at: preparation.receipt.createdAt,
397
+ });
398
+ (0, habit_lifecycle_1.writeHabitLifecycleJournal)(lease, journal, deps);
399
+ return preparation.receipt;
400
+ }
401
+ function cancellationLeaseKey(agentRoot, habitId, operationId) {
402
+ return JSON.stringify([path.resolve(agentRoot), habitId, operationId]);
403
+ }
404
+ async function releaseCancellationLease(leaseKey, lease, deps) {
405
+ const attempts = Math.floor(habit_lifecycle_1.HABIT_LIFECYCLE_TIMEOUT_MS / habit_lifecycle_1.HABIT_LIFECYCLE_POLL_MS) + 1;
406
+ const wait = deps.sleep ?? ((milliseconds) => new Promise((resolve) => {
407
+ setTimeout(resolve, milliseconds);
408
+ }));
409
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
410
+ let released;
411
+ try {
412
+ released = (0, habit_lifecycle_1.releaseHabitLifecycleLock)(lease, deps);
413
+ }
414
+ catch (error) {
415
+ retainedCancellationLeases.set(leaseKey, lease);
416
+ throw new HabitCancellationError("lifecycle_lock_release_failed", { cause: error });
417
+ }
418
+ if (released) {
419
+ retainedCancellationLeases.delete(leaseKey);
420
+ return;
421
+ }
422
+ if (attempt + 1 < attempts)
423
+ await wait(habit_lifecycle_1.HABIT_LIFECYCLE_POLL_MS);
424
+ }
425
+ retainedCancellationLeases.set(leaseKey, lease);
426
+ throw new HabitCancellationError("lifecycle_lock_release_failed");
427
+ }
428
+ function confirmCancellationDurability(lease, definitionPath, evidenceKeyHash, operationId, deps) {
429
+ const paths = (0, habit_lifecycle_1.getHabitLifecyclePaths)({
430
+ agentRoot: lease.agentRoot,
431
+ habitId: lease.habitId,
432
+ evidenceKeyHash,
433
+ operationId,
434
+ });
435
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, paths.journal, deps);
436
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, definitionPath, deps);
437
+ (0, habit_lifecycle_1.confirmHabitLifecyclePathDurability)(lease, paths.receipt, deps);
438
+ }
439
+ function resolveCancellationEvidence(input, deps) {
440
+ const locator = validatedCancellationLocator(input);
441
+ if (locator.kind === "capture")
442
+ return validateCaptureEvidence(input.agentRoot, locator.id, deps);
443
+ return validateHabitEvidenceBridge({
444
+ agentRoot: input.agentRoot,
445
+ bridgeId: locator.id,
446
+ }, deps);
447
+ }
448
+ function validatedCancellationLocator(input) {
449
+ if (!isRecord(input.authority))
450
+ throw new HabitCancellationError("cancellation_authority_invalid");
451
+ if (input.authority.kind === "current_ingress") {
452
+ const match = CAPTURE_LOCATOR_PATTERN.exec(input.evidenceLocator);
453
+ if (!match)
454
+ throw new HabitCancellationError("capture_evidence_locator_invalid");
455
+ const current = input.authority.currentIngressEvidence;
456
+ if (!isRecord(current)
457
+ || Object.keys(current).length !== 3
458
+ || current.schemaVersion !== 1
459
+ || current.provider !== "bluebubbles"
460
+ || typeof current.captureKeyHash !== "string"
461
+ || !HASH_PATTERN.test(current.captureKeyHash))
462
+ throw new HabitCancellationError("current_ingress_evidence_invalid");
463
+ if (match[1] !== current.captureKeyHash) {
464
+ throw new HabitCancellationError("evidence_capture_mismatch");
465
+ }
466
+ return { kind: "capture", id: match[1] };
467
+ }
468
+ if (input.authority.kind !== "offline_bridge") {
469
+ throw new HabitCancellationError("cancellation_authority_invalid");
470
+ }
471
+ if (CAPTURE_LOCATOR_PATTERN.test(input.evidenceLocator)) {
472
+ throw new HabitCancellationError("offline_capture_evidence_forbidden");
473
+ }
474
+ return { kind: "bridge", id: validatedBridgeId(input.evidenceLocator) };
475
+ }
476
+ function validateCaptureEvidence(agentRoot, captureKeyHash, deps) {
477
+ const cutover = (0, semantic_receipts_1.readBlueBubblesSemanticCutoverAtRoot)(agentRoot, deps);
478
+ if (!cutover)
479
+ throw new HabitCancellationError("capture_cutover_invalid");
480
+ const capture = (0, semantic_receipts_1.readBlueBubblesSemanticCaptureAtRoot)(agentRoot, captureKeyHash, deps);
481
+ if (!capture)
482
+ throw new HabitCancellationError("capture_evidence_missing_or_invalid");
483
+ const disposition = (0, semantic_receipts_1.classifyBlueBubblesRecoveryRecord)(capture, cutover);
484
+ if (disposition.disposition !== "handleable" || disposition.keyHash !== captureKeyHash) {
485
+ throw new HabitCancellationError("capture_evidence_not_handleable");
486
+ }
487
+ const event = capture.event;
488
+ if (capture.keyHash !== captureKeyHash
489
+ || capture.providerNamespace !== cutover.providerNamespace
490
+ || capture.capturedAt < cutover.effectiveAt
491
+ || event.provider !== "bluebubbles"
492
+ || event.kind !== "message"
493
+ || event.fromMe
494
+ || typeof event.text !== "string"
495
+ || event.text.length === 0
496
+ || typeof event.textSha256 !== "string"
497
+ || event.textSha256 !== sha256(event.text)
498
+ || event.actor.provider !== "imessage-handle"
499
+ || typeof event.actor.externalId !== "string"
500
+ || event.actor.externalId.trim().length === 0
501
+ || typeof event.actor.displayName !== "string")
502
+ throw new HabitCancellationError("capture_message_evidence_invalid");
503
+ const displayName = requiredSingleLine(event.actor.displayName, "capture_actor_invalid");
504
+ return {
505
+ locator: { kind: "capture", id: captureKeyHash },
506
+ actor: {
507
+ displayName,
508
+ provider: event.actor.provider,
509
+ externalId: event.actor.externalId,
510
+ },
511
+ request: {
512
+ text: event.text,
513
+ sha256: event.textSha256,
514
+ observedAt: capture.capturedAt,
515
+ },
516
+ cancellationReason: `Confirmed requester ${displayName} asked to end this habit.`,
517
+ };
518
+ }
519
+ function readDefinitionSnapshot(agentRoot, habitId, deps) {
520
+ const definitionPath = path.join(agentRoot, "habits", `${habitId}.md`);
521
+ let bytes;
522
+ try {
523
+ bytes = (deps.fs ?? fs).readFileSync(definitionPath, "utf8");
524
+ }
525
+ catch (error) {
526
+ throw new HabitCancellationError("habit_definition_missing_or_unreadable", { cause: error });
527
+ }
528
+ const parsed = (0, habit_parser_1.parseHabitFile)(bytes, definitionPath);
529
+ if (parsed.status === "degraded") {
530
+ throw new HabitCancellationError(`habit_definition_degraded:${parsed.degradedReason}`);
531
+ }
532
+ return { path: definitionPath, bytes, status: parsed.status };
533
+ }
534
+ function renderCancelledDefinition(definition, locator, cancellationReason, cancelledAt) {
535
+ const evidenceValue = locator.kind === "capture" ? `capture:${locator.id}` : locator.id;
536
+ const lineEnding = definition.bytes.includes("\r\n") ? "\r\n" : "\n";
537
+ const lifecycleLines = [
538
+ "status: cancelled",
539
+ `cancelledAt: ${cancelledAt}`,
540
+ `cancelledEvidence: ${evidenceValue}`,
541
+ `cancelledReason: ${requiredSingleLine(cancellationReason, "cancellation_reason_invalid")}`,
542
+ ].join(lineEnding);
543
+ const bomLength = definition.bytes.startsWith("\uFEFF") ? 1 : 0;
544
+ const lines = physicalLines(definition.bytes);
545
+ const closingIndex = lines.findIndex((line, index) => index > 0 && line.content.trim() === "---");
546
+ const hasFrontmatter = lines[0]?.content.trim() === "---" && closingIndex > 0;
547
+ const frontmatterLines = hasFrontmatter ? lines.slice(1, closingIndex) : [];
548
+ if (frontmatterLines.some((line) => /^(?:cancelledAt|cancelledEvidence|cancelledReason):/.test(line.content))) {
549
+ throw new HabitCancellationError("habit_definition_lifecycle_lines_invalid");
550
+ }
551
+ const statusLines = frontmatterLines.filter((line) => /^status:/.test(line.content));
552
+ if (statusLines.length > 1)
553
+ throw new HabitCancellationError("habit_definition_status_line_invalid");
554
+ if (statusLines.length === 1) {
555
+ const statusLine = statusLines[0];
556
+ return `${definition.bytes.slice(0, statusLine.start)}${lifecycleLines}${definition.bytes.slice(statusLine.contentEnd)}`;
557
+ }
558
+ if (hasFrontmatter) {
559
+ const closing = lines[closingIndex];
560
+ return `${definition.bytes.slice(0, closing.start)}${lifecycleLines}${lineEnding}${definition.bytes.slice(closing.start)}`;
561
+ }
562
+ return `${definition.bytes.slice(0, bomLength)}---${lineEnding}${lifecycleLines}${lineEnding}---${lineEnding}${definition.bytes.slice(bomLength)}`;
563
+ }
564
+ function physicalLines(value) {
565
+ const lines = [];
566
+ let start = 0;
567
+ while (start < value.length) {
568
+ const newline = value.indexOf("\n", start);
569
+ const end = newline === -1 ? value.length : newline + 1;
570
+ const raw = value.slice(start, end);
571
+ const content = raw.endsWith("\r\n")
572
+ ? raw.slice(0, -2)
573
+ : raw.endsWith("\n")
574
+ ? raw.slice(0, -1)
575
+ : raw;
576
+ lines.push({ content, start, contentEnd: start + content.length });
577
+ start = end;
578
+ }
579
+ return lines;
580
+ }
581
+ function buildCancellationReceipt(input) {
582
+ const acknowledgement = renderHabitCancellationAcknowledgement(input.habitId, input.evidence.actor.displayName, input.boundaryState);
583
+ return {
584
+ schemaVersion: 1,
585
+ habitId: input.habitId,
586
+ operationId: input.operationId,
587
+ evidenceKeyHash: input.evidenceKeyHash,
588
+ evidenceLocator: input.evidence.locator,
589
+ actor: input.evidence.actor,
590
+ request: input.evidence.request,
591
+ transition: {
592
+ fromStatus: input.fromStatus,
593
+ toStatus: "cancelled",
594
+ cancelledAt: input.cancelledAt,
595
+ boundaryState: input.boundaryState,
596
+ },
597
+ acknowledgement,
598
+ createdAt: input.cancelledAt,
599
+ };
600
+ }
601
+ function classifyConcurrentSendBoundary(agentRoot, habitId, requestObservedAt, cancelledAt, deps) {
602
+ const candidates = (0, habit_lifecycle_1.listHabitLifecycleJournals)({ agentRoot, habitId }, deps)
603
+ .filter((journal) => journal.operationKind === "send"
604
+ && journal.intentAt !== null
605
+ && journal.intentAt <= cancelledAt
606
+ && (journal.classifiedAt === null || journal.classifiedAt >= requestObservedAt));
607
+ if (candidates.some((journal) => journal.state === "crossed"))
608
+ return "crossed";
609
+ if (candidates.some((journal) => (journal.state === "crossing_unknown" || journal.state === "send_intent")))
610
+ return "crossing_unknown";
611
+ return "not_crossed";
612
+ }
613
+ function assertPreparedReceipt(actual, prepared, evidence) {
614
+ if ((0, habit_lifecycle_1.serializeHabitLifecycleJson)(actual) !== (0, habit_lifecycle_1.serializeHabitLifecycleJson)(prepared)
615
+ || (evidence !== null && ((0, habit_lifecycle_1.serializeHabitLifecycleJson)(prepared.evidenceLocator) !== (0, habit_lifecycle_1.serializeHabitLifecycleJson)(evidence.locator)
616
+ || (0, habit_lifecycle_1.serializeHabitLifecycleJson)(prepared.actor) !== (0, habit_lifecycle_1.serializeHabitLifecycleJson)(evidence.actor)
617
+ || (0, habit_lifecycle_1.serializeHabitLifecycleJson)(prepared.request) !== (0, habit_lifecycle_1.serializeHabitLifecycleJson)(evidence.request))))
618
+ throw new HabitCancellationError("cancellation_prepared_receipt_mismatch");
619
+ }
620
+ function assertDefinitionMatches(bytes, expectedSha256) {
621
+ if (sha256(bytes) !== expectedSha256) {
622
+ throw new HabitCancellationError("cancellation_definition_digest_mismatch");
623
+ }
624
+ }
625
+ function validateOperatorConfirmation(bridgeRoot, raw, storeFs) {
626
+ const value = requiredRecord(raw, "bridge_confirmation_invalid");
627
+ requireExactKeys(value, ["path", "sha256"], "bridge_confirmation_invalid");
628
+ const relativePath = validatedArtifactPath(value.path, "bridge_confirmation_invalid");
629
+ const expectedSha256 = validatedHash(value.sha256, "bridge_confirmation_invalid");
630
+ const bytes = readUtf8(storeFs, path.join(bridgeRoot, relativePath), "bridge_confirmation_invalid");
631
+ if (sha256(bytes) !== expectedSha256 || !bytes.endsWith("\n") || bytes.endsWith("\n\n") || bytes.includes("\r")) {
632
+ throw new HabitCancellationError("bridge_confirmation_invalid");
633
+ }
634
+ }
635
+ function validateBridgeScreenshots(bridgeRoot, raw, storeFs) {
636
+ if (!Array.isArray(raw) || raw.length !== 2) {
637
+ throw new HabitCancellationError("bridge_screenshots_invalid");
638
+ }
639
+ raw.forEach((entry, index) => {
640
+ const value = requiredRecord(entry, "bridge_screenshots_invalid");
641
+ requireExactKeys(value, ["index", "sourcePath", "artifactPath", "sha256"], "bridge_screenshots_invalid");
642
+ if (value.index !== index + 1)
643
+ throw new HabitCancellationError("bridge_screenshots_invalid");
644
+ const sourcePath = requiredString(value.sourcePath, "bridge_screenshots_invalid");
645
+ if (!path.isAbsolute(sourcePath))
646
+ throw new HabitCancellationError("bridge_screenshots_invalid");
647
+ const artifactPath = validatedArtifactPath(value.artifactPath, "bridge_screenshots_invalid");
648
+ const expectedSha256 = validatedHash(value.sha256, "bridge_screenshots_invalid");
649
+ const artifactBytes = readBuffer(storeFs, path.join(bridgeRoot, artifactPath), "bridge_screenshots_invalid");
650
+ if (sha256(artifactBytes) !== expectedSha256) {
651
+ throw new HabitCancellationError("bridge_screenshots_invalid");
652
+ }
653
+ });
654
+ }
655
+ function validateBridgeSources(input) {
656
+ if (!Array.isArray(input.value) || input.value.length !== 3) {
657
+ throw new HabitCancellationError("bridge_sources_invalid");
658
+ }
659
+ const [inboundRaw, sessionRaw, contextRaw] = input.value;
660
+ const inbound = requiredRecord(inboundRaw, "bridge_inbound_evidence_invalid");
661
+ requireExactKeys(inbound, ["role", "path", "fileSha256", "eventGuid", "requestSha256"], "bridge_inbound_evidence_invalid");
662
+ if (inbound.role !== "inbound_request"
663
+ || inbound.eventGuid !== input.eventGuid
664
+ || inbound.requestSha256 !== input.requestSha256)
665
+ throw new HabitCancellationError("bridge_inbound_evidence_invalid");
666
+ const inboundBytes = validatedSourceBytes(inbound, input.storeFs, "bridge_inbound_evidence_invalid");
667
+ const inboundRows = inboundBytes.split("\n").filter((line) => line.length > 0).map((line) => {
668
+ const row = parseJsonRecord(line, "bridge_inbound_evidence_invalid");
669
+ return row;
670
+ }).filter((row) => row.messageGuid === input.eventGuid);
671
+ if (inboundRows.length !== 1
672
+ || inboundRows[0].textForAgent !== input.requestText
673
+ || sha256(String(inboundRows[0].textForAgent)) !== input.requestSha256)
674
+ throw new HabitCancellationError("bridge_inbound_request_invalid");
675
+ const session = requiredRecord(sessionRaw, "bridge_session_evidence_invalid");
676
+ requireExactKeys(session, ["role", "path", "fileSha256", "eventId", "normalizedRequestSha256"], "bridge_session_evidence_invalid");
677
+ if (session.role !== "session_rendering"
678
+ || session.normalizedRequestSha256 !== input.requestSha256)
679
+ throw new HabitCancellationError("bridge_session_evidence_invalid");
680
+ const sessionBytes = validatedSourceBytes(session, input.storeFs, "bridge_session_evidence_invalid");
681
+ const sessionValue = parseJsonRecord(sessionBytes, "bridge_session_evidence_invalid");
682
+ if (!Array.isArray(sessionValue.events))
683
+ throw new HabitCancellationError("bridge_session_evidence_invalid");
684
+ const sessionEvents = sessionValue.events.filter((entry) => (isRecord(entry) && entry.id === session.eventId));
685
+ if (sessionEvents.length !== 1 || typeof sessionEvents[0].content !== "string") {
686
+ throw new HabitCancellationError("bridge_session_evidence_invalid");
687
+ }
688
+ const prefixEnd = sessionEvents[0].content.indexOf(": ");
689
+ if (prefixEnd < 0)
690
+ throw new HabitCancellationError("bridge_session_normalization_invalid");
691
+ const normalized = sessionEvents[0].content.slice(prefixEnd + 2);
692
+ if (normalized !== input.requestText || sha256(normalized) !== input.requestSha256) {
693
+ throw new HabitCancellationError("bridge_session_normalization_invalid");
694
+ }
695
+ const context = requiredRecord(contextRaw, "bridge_context_evidence_invalid");
696
+ requireExactKeys(context, ["role", "path", "fileSha256", "eventGuid"], "bridge_context_evidence_invalid");
697
+ if (context.role !== "context_chronology" || context.eventGuid !== input.eventGuid) {
698
+ throw new HabitCancellationError("bridge_context_evidence_invalid");
699
+ }
700
+ const contextBytes = validatedSourceBytes(context, input.storeFs, "bridge_context_evidence_invalid");
701
+ const contextValue = parseJsonRecord(contextBytes, "bridge_context_evidence_invalid");
702
+ if (contextValue.anchorMessageGuid !== input.eventGuid
703
+ || !Array.isArray(contextValue.messages)
704
+ || contextValue.messages.length !== 2
705
+ || contextValue.messages.some((entry) => (!isRecord(entry)
706
+ || typeof entry.authorLabel !== "string"
707
+ || typeof entry.bodyPreview !== "string"
708
+ || typeof entry.timestamp !== "string")))
709
+ throw new HabitCancellationError("bridge_context_evidence_invalid");
710
+ }
711
+ function validatedSourceBytes(value, storeFs, code) {
712
+ const sourcePath = requiredString(value.path, code);
713
+ const expectedSha256 = validatedHash(value.fileSha256, code);
714
+ const bytes = readUtf8(storeFs, sourcePath, code);
715
+ if (sha256(bytes) !== expectedSha256)
716
+ throw new HabitCancellationError(code);
717
+ return bytes;
718
+ }
719
+ function validatedArtifactPath(value, code) {
720
+ const relativePath = requiredString(value, code);
721
+ if (path.basename(relativePath) !== relativePath || relativePath === "." || relativePath === "..") {
722
+ throw new HabitCancellationError(code);
723
+ }
724
+ return relativePath;
725
+ }
726
+ function cancellationNow(deps) {
727
+ return (deps.now ?? (() => new Date()))().toISOString();
728
+ }
729
+ function requiredRecord(value, code) {
730
+ if (!isRecord(value))
731
+ throw new HabitCancellationError(code);
732
+ return value;
733
+ }
734
+ function requireExactKeys(value, keys, code) {
735
+ const actual = Object.keys(value);
736
+ if (actual.length !== keys.length || actual.some((key, index) => key !== keys[index])) {
737
+ throw new HabitCancellationError(code);
738
+ }
739
+ }
740
+ function requiredString(value, code) {
741
+ if (typeof value !== "string" || value.trim().length === 0) {
742
+ throw new HabitCancellationError(code);
743
+ }
744
+ return value;
745
+ }
746
+ function requiredSingleLine(value, code) {
747
+ const text = requiredString(value, code);
748
+ if (/[\r\n]/.test(text))
749
+ throw new HabitCancellationError(code);
750
+ return text;
751
+ }
752
+ function validatedHash(value, code) {
753
+ if (typeof value !== "string" || !HASH_PATTERN.test(value)) {
754
+ throw new HabitCancellationError(code);
755
+ }
756
+ return value;
757
+ }
758
+ function validatedBridgeId(value) {
759
+ const bridgeId = requiredString(value, "bridge_id_invalid");
760
+ if (!BRIDGE_ID_PATTERN.test(bridgeId) || bridgeId === "." || bridgeId === "..") {
761
+ throw new HabitCancellationError("bridge_id_invalid");
762
+ }
763
+ return bridgeId;
764
+ }
765
+ function isCanonicalTimestamp(value) {
766
+ if (typeof value !== "string" || !ISO_MILLISECONDS_PATTERN.test(value))
767
+ return false;
768
+ const parsed = new Date(value);
769
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;
770
+ }
771
+ function readUtf8(storeFs, filePath, code) {
772
+ try {
773
+ return storeFs.readFileSync(filePath, "utf8");
774
+ }
775
+ catch (error) {
776
+ throw new HabitCancellationError(code, { cause: error });
777
+ }
778
+ }
779
+ function readBuffer(storeFs, filePath, code) {
780
+ try {
781
+ return storeFs.readFileSync(filePath);
782
+ }
783
+ catch (error) {
784
+ throw new HabitCancellationError(code, { cause: error });
785
+ }
786
+ }
787
+ function parseJsonRecord(bytes, code) {
788
+ let value;
789
+ try {
790
+ value = JSON.parse(bytes);
791
+ }
792
+ catch (error) {
793
+ throw new HabitCancellationError(code, { cause: error });
794
+ }
795
+ return requiredRecord(value, code);
796
+ }
797
+ function isRecord(value) {
798
+ return typeof value === "object" && value !== null && !Array.isArray(value);
799
+ }
800
+ function sha256(value) {
801
+ return (0, node_crypto_1.createHash)("sha256").update(value).digest("hex");
802
+ }
803
+ function asCancellationError(error) {
804
+ if (error instanceof HabitCancellationError)
805
+ return error;
806
+ if (error instanceof habit_lifecycle_1.HabitLifecycleError) {
807
+ return new HabitCancellationError(error.code, { cause: error });
808
+ }
809
+ return new HabitCancellationError("habit_cancellation_failed", { cause: error });
810
+ }