@ouro.bot/cli 0.1.0-alpha.81 → 0.1.0-alpha.811

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 (623) 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/changelog.json +5189 -16
  15. package/deploy/unraid/Dockerfile +48 -0
  16. package/deploy/unraid/README.txt +3032 -0
  17. package/deploy/unraid/audit-container-spec.sh +4 -0
  18. package/deploy/unraid/container-runtime.json +1 -0
  19. package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
  20. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  21. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  22. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  23. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  24. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  25. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  26. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  27. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  28. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  29. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  30. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  31. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  32. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2031 -0
  33. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  34. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  35. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  36. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  37. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  38. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  39. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  40. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  41. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +11 -0
  43. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +11 -0
  45. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  46. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  47. package/deploy/unraid/sanctuary.xml +27 -0
  48. package/dist/a2a/card.js +57 -0
  49. package/dist/a2a/client.js +180 -0
  50. package/dist/a2a/config.js +50 -0
  51. package/dist/a2a/delegation-stores.js +56 -0
  52. package/dist/a2a/did-resolution.js +93 -0
  53. package/dist/a2a/identity.js +170 -0
  54. package/dist/a2a/inbound-share.js +107 -0
  55. package/dist/a2a/mission-result-wire.js +196 -0
  56. package/dist/a2a/onboarding.js +115 -0
  57. package/dist/a2a/pin-store.js +132 -0
  58. package/dist/a2a/seen-ledger.js +120 -0
  59. package/dist/a2a/server.js +604 -0
  60. package/dist/a2a/task-store.js +69 -0
  61. package/dist/a2a/transport.js +45 -0
  62. package/dist/a2a/types.js +3 -0
  63. package/dist/arc/attention-types.js +8 -0
  64. package/dist/arc/cares.js +360 -0
  65. package/dist/arc/episodes.js +118 -0
  66. package/dist/arc/evolution.js +490 -0
  67. package/dist/arc/flight-recorder.js +1034 -0
  68. package/dist/arc/intentions.js +134 -0
  69. package/dist/arc/json-store.js +117 -0
  70. package/dist/arc/obligations.js +386 -0
  71. package/dist/arc/packets.js +336 -0
  72. package/dist/arc/presence.js +185 -0
  73. package/dist/arc/task-lifecycle.js +57 -0
  74. package/dist/commerce/store.js +755 -0
  75. package/dist/commerce/types.js +3 -0
  76. package/dist/heart/active-work.js +820 -29
  77. package/dist/heart/agent-entry.js +252 -3
  78. package/dist/heart/approval-files.js +113 -0
  79. package/dist/heart/approval-store.js +950 -0
  80. package/dist/heart/attachments/image-normalize.js +194 -0
  81. package/dist/heart/attachments/materialize.js +97 -0
  82. package/dist/heart/attachments/originals.js +88 -0
  83. package/dist/heart/attachments/render.js +29 -0
  84. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  85. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  86. package/dist/heart/attachments/sources/index.js +18 -0
  87. package/dist/heart/attachments/sources/telegram.js +71 -0
  88. package/dist/heart/attachments/store.js +132 -0
  89. package/dist/heart/attachments/types.js +93 -0
  90. package/dist/heart/auth/auth-flow.js +495 -0
  91. package/dist/heart/autonomy-budget.js +478 -0
  92. package/dist/heart/awaiting/await-alert.js +148 -0
  93. package/dist/heart/awaiting/await-expiry.js +143 -0
  94. package/dist/heart/awaiting/await-loader.js +91 -0
  95. package/dist/heart/awaiting/await-parser.js +149 -0
  96. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  97. package/dist/heart/awaiting/await-scheduler.js +382 -0
  98. package/dist/heart/background-operations.js +281 -0
  99. package/dist/heart/bridges/manager.js +137 -17
  100. package/dist/heart/bridges/store.js +14 -2
  101. package/dist/heart/bundle-state.js +168 -0
  102. package/dist/heart/commitments.js +64 -18
  103. package/dist/heart/config-registry.js +331 -0
  104. package/dist/heart/config.js +174 -131
  105. package/dist/heart/context-loss-gauntlet.js +387 -0
  106. package/dist/heart/context-loss-sentinel.js +1157 -0
  107. package/dist/heart/core.js +2164 -581
  108. package/dist/heart/cross-chat-delivery.js +9 -22
  109. package/dist/heart/daemon/agent-config-check.js +451 -0
  110. package/dist/heart/daemon/agent-discovery.js +185 -3
  111. package/dist/heart/daemon/agent-service.js +542 -0
  112. package/dist/heart/daemon/agentic-repair.js +547 -0
  113. package/dist/heart/daemon/await-private-wake.js +59 -0
  114. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  115. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  116. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  117. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  118. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  119. package/dist/heart/daemon/cadence.js +180 -0
  120. package/dist/heart/daemon/cli-defaults.js +854 -0
  121. package/dist/heart/daemon/cli-desk.js +322 -0
  122. package/dist/heart/daemon/cli-exec.js +8822 -0
  123. package/dist/heart/daemon/cli-help.js +716 -0
  124. package/dist/heart/daemon/cli-parse.js +2771 -0
  125. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  126. package/dist/heart/daemon/cli-render.js +777 -0
  127. package/dist/heart/daemon/cli-types.js +8 -0
  128. package/dist/heart/daemon/connect-bay.js +323 -0
  129. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  130. package/dist/heart/daemon/container-healthcheck.js +112 -0
  131. package/dist/heart/daemon/container-runtime.js +97 -0
  132. package/dist/heart/daemon/container-spec-auditor-main.js +170 -0
  133. package/dist/heart/daemon/container-spec-auditor.js +236 -0
  134. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  135. package/dist/heart/daemon/daemon-cli.js +29 -2317
  136. package/dist/heart/daemon/daemon-entry.js +921 -11
  137. package/dist/heart/daemon/daemon-health.js +186 -0
  138. package/dist/heart/daemon/daemon-rollup.js +57 -0
  139. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  140. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  141. package/dist/heart/daemon/daemon.js +2084 -105
  142. package/dist/heart/daemon/dns-workflow.js +394 -0
  143. package/dist/heart/daemon/doctor-types.js +8 -0
  144. package/dist/heart/daemon/doctor.js +1755 -0
  145. package/dist/heart/daemon/freshness.js +345 -0
  146. package/dist/heart/daemon/habit-private-wake.js +61 -0
  147. package/dist/heart/daemon/health-monitor.js +142 -11
  148. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  149. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  150. package/dist/heart/daemon/http-health-probe.js +80 -0
  151. package/dist/heart/daemon/human-command-screens.js +234 -0
  152. package/dist/heart/daemon/human-readiness.js +114 -0
  153. package/dist/heart/daemon/inner-status.js +78 -0
  154. package/dist/heart/daemon/interactive-repair.js +394 -0
  155. package/dist/heart/daemon/launchd.js +37 -8
  156. package/dist/heart/daemon/log-tailer.js +79 -10
  157. package/dist/heart/daemon/logs-prune.js +132 -0
  158. package/dist/heart/daemon/mcp-canary.js +524 -0
  159. package/dist/heart/daemon/message-router.js +65 -5
  160. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  161. package/dist/heart/daemon/os-cron-deps.js +135 -0
  162. package/dist/heart/daemon/os-cron.js +22 -14
  163. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  164. package/dist/heart/daemon/ouro-entry.js +3 -1
  165. package/dist/heart/daemon/plugin-cli.js +432 -0
  166. package/dist/heart/daemon/process-manager.js +733 -61
  167. package/dist/heart/daemon/provider-discovery.js +137 -0
  168. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  169. package/dist/heart/daemon/prunable-bundle.js +144 -0
  170. package/dist/heart/daemon/pulse.js +511 -0
  171. package/dist/heart/daemon/readiness-repair.js +365 -0
  172. package/dist/heart/daemon/run-hooks.js +2 -0
  173. package/dist/heart/daemon/runtime-logging.js +47 -14
  174. package/dist/heart/daemon/runtime-metadata.js +2 -30
  175. package/dist/heart/daemon/runtime-mode.js +13 -2
  176. package/dist/heart/daemon/safe-mode.js +161 -0
  177. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2647 -0
  178. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1904 -0
  179. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  180. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
  181. package/dist/heart/daemon/sanctuary-bundle-migration.js +728 -0
  182. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  183. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  184. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  185. package/dist/heart/daemon/sense-manager.js +689 -48
  186. package/dist/heart/daemon/session-id-resolver.js +131 -0
  187. package/dist/heart/daemon/skill-management-installer.js +1 -1
  188. package/dist/heart/daemon/socket-client.js +180 -12
  189. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  190. package/dist/heart/daemon/startup-tui.js +339 -0
  191. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  192. package/dist/heart/daemon/task-scheduler.js +117 -39
  193. package/dist/heart/daemon/terminal-ui.js +499 -0
  194. package/dist/heart/daemon/thoughts.js +138 -54
  195. package/dist/heart/daemon/up-progress.js +366 -0
  196. package/dist/heart/daemon/vault-items.js +56 -0
  197. package/dist/heart/delegation.js +1 -4
  198. package/dist/heart/external-events/router.js +1414 -0
  199. package/dist/heart/frontend-approval-runtime.js +506 -0
  200. package/dist/heart/frontend-journal.js +215 -0
  201. package/dist/heart/frontend-session-service.js +237 -0
  202. package/dist/heart/frontend-socket-client.js +154 -0
  203. package/dist/heart/frontend-socket.js +400 -0
  204. package/dist/heart/habits/habit-cancel.js +810 -0
  205. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  206. package/dist/heart/habits/habit-migration.js +194 -0
  207. package/dist/heart/habits/habit-parser.js +278 -0
  208. package/dist/heart/habits/habit-runtime-state.js +93 -0
  209. package/dist/heart/habits/habit-scheduler.js +653 -0
  210. package/dist/heart/habits/habit-session-summary.js +318 -0
  211. package/dist/heart/habits/habit-session.js +636 -0
  212. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  213. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  214. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  215. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  216. package/dist/heart/identity.js +196 -59
  217. package/dist/heart/kept-notes.js +289 -0
  218. package/dist/heart/kicks.js +1 -1
  219. package/dist/heart/machine-identity.js +161 -0
  220. package/dist/heart/mail-import-discovery.js +356 -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 +231 -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 +11 -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 +1 -1
  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 +173 -60
  258. package/dist/heart/providers/azure.js +23 -11
  259. package/dist/heart/providers/error-classification.js +127 -0
  260. package/dist/heart/providers/github-copilot.js +34 -38
  261. package/dist/heart/providers/minimax-vlm.js +189 -0
  262. package/dist/heart/providers/minimax.js +26 -8
  263. package/dist/heart/providers/openai-codex-token.js +349 -0
  264. package/dist/heart/providers/openai-codex.js +55 -40
  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 +22 -4
  271. package/dist/heart/session-activity.js +92 -24
  272. package/dist/heart/session-events.js +1440 -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-redaction-repair-cli-main.js +31 -0
  277. package/dist/heart/session-redaction-repair.js +543 -0
  278. package/dist/heart/session-stats-cli-main.js +5 -0
  279. package/dist/heart/session-stats.js +182 -0
  280. package/dist/heart/session-transcript.js +133 -0
  281. package/dist/heart/start-of-turn-packet.js +372 -0
  282. package/dist/heart/steward-policy.js +302 -0
  283. package/dist/heart/streaming.js +604 -207
  284. package/dist/heart/structured-output.js +196 -0
  285. package/dist/heart/sync-classification.js +176 -0
  286. package/dist/heart/sync.js +449 -0
  287. package/dist/heart/target-resolution.js +11 -7
  288. package/dist/heart/tempo.js +93 -0
  289. package/dist/heart/temporal-view.js +41 -0
  290. package/dist/heart/timeouts.js +101 -0
  291. package/dist/heart/tool-activity-callbacks.js +59 -0
  292. package/dist/heart/tool-approval.js +375 -0
  293. package/dist/heart/tool-description.js +155 -0
  294. package/dist/heart/tool-friction.js +55 -0
  295. package/dist/heart/tool-loop.js +200 -0
  296. package/dist/heart/turn-context.js +482 -0
  297. package/dist/heart/turn-execution-lease.js +30 -0
  298. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  299. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  300. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  301. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  302. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  303. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  304. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  305. package/dist/heart/versioning/update-hooks.js +154 -0
  306. package/dist/heart/versioning/version-intent.js +114 -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 +24 -2
  333. package/dist/mind/context.js +279 -111
  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} +68 -77
  337. package/dist/mind/embedding-provider.js +60 -0
  338. package/dist/mind/file-state.js +179 -0
  339. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  340. package/dist/mind/obligation-steering.js +227 -0
  341. package/dist/mind/pending.js +36 -10
  342. package/dist/mind/prompt-budget.js +479 -0
  343. package/dist/mind/prompt-refresh.js +3 -2
  344. package/dist/mind/prompt.js +1059 -187
  345. package/dist/mind/provenance-trust.js +26 -0
  346. package/dist/mind/record-paths.js +312 -0
  347. package/dist/mind/scrutiny.js +173 -0
  348. package/dist/mind/session-transaction.js +564 -0
  349. package/dist/nerves/cli-logging.js +7 -1
  350. package/dist/nerves/coverage/audit-rules.js +15 -6
  351. package/dist/nerves/coverage/audit.js +28 -2
  352. package/dist/nerves/coverage/cli.js +1 -1
  353. package/dist/nerves/coverage/contract.js +5 -5
  354. package/dist/nerves/coverage/file-completeness.js +139 -5
  355. package/dist/nerves/coverage/run-artifacts.js +55 -35
  356. package/dist/nerves/coverage/source-scanner.js +4 -4
  357. package/dist/nerves/event-buffer.js +111 -0
  358. package/dist/nerves/index.js +293 -9
  359. package/dist/nerves/observation.js +20 -0
  360. package/dist/nerves/redact.js +79 -0
  361. package/dist/nerves/review/cli-main.js +5 -0
  362. package/dist/nerves/review/cli.js +156 -0
  363. package/dist/nerves/review/core.js +159 -0
  364. package/dist/nerves/runtime.js +17 -1
  365. package/dist/repertoire/ado-client.js +15 -56
  366. package/dist/repertoire/ado-semantic.js +16 -10
  367. package/dist/repertoire/api-client.js +97 -0
  368. package/dist/repertoire/bitwarden-store.js +1045 -0
  369. package/dist/repertoire/bundle-templates.js +71 -0
  370. package/dist/repertoire/bw-installer.js +180 -0
  371. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  372. package/dist/repertoire/coding/context-pack.js +331 -0
  373. package/dist/repertoire/coding/feedback.js +218 -30
  374. package/dist/repertoire/coding/index.js +15 -3
  375. package/dist/repertoire/coding/manager.js +166 -10
  376. package/dist/repertoire/coding/spawner.js +58 -11
  377. package/dist/repertoire/coding/tools.js +242 -14
  378. package/dist/repertoire/coding/workbench-client.js +272 -0
  379. package/dist/repertoire/coding/workbench-manager.js +346 -0
  380. package/dist/repertoire/commerce-errors.js +109 -0
  381. package/dist/repertoire/commerce-self-test.js +156 -0
  382. package/dist/repertoire/credential-access.js +178 -0
  383. package/dist/repertoire/desk/classifier.js +362 -0
  384. package/dist/repertoire/duffel-client.js +185 -0
  385. package/dist/repertoire/github-client.js +14 -55
  386. package/dist/repertoire/graph-client.js +11 -52
  387. package/dist/repertoire/guardrails.js +811 -18
  388. package/dist/repertoire/mcp-client.js +44 -3
  389. package/dist/repertoire/mcp-manager.js +427 -139
  390. package/dist/repertoire/mcp-tools.js +124 -0
  391. package/dist/repertoire/plugin-mcp.js +175 -0
  392. package/dist/repertoire/plugins.js +253 -0
  393. package/dist/repertoire/relationship-authorization.js +194 -0
  394. package/dist/repertoire/shell-sessions.js +134 -0
  395. package/dist/repertoire/skills.js +48 -4
  396. package/dist/repertoire/stripe-client.js +131 -0
  397. package/dist/repertoire/tool-arguments.js +170 -0
  398. package/dist/repertoire/tool-results.js +29 -0
  399. package/dist/repertoire/tools-a2a.js +699 -0
  400. package/dist/repertoire/tools-attachments.js +322 -0
  401. package/dist/repertoire/tools-awaiting.js +575 -0
  402. package/dist/repertoire/tools-base.js +82 -1139
  403. package/dist/repertoire/tools-bluebubbles.js +2 -0
  404. package/dist/repertoire/tools-bridge.js +144 -0
  405. package/dist/repertoire/tools-bundle.js +993 -0
  406. package/dist/repertoire/tools-commerce.js +253 -0
  407. package/dist/repertoire/tools-config.js +186 -0
  408. package/dist/repertoire/tools-continuity.js +575 -0
  409. package/dist/repertoire/tools-credential.js +383 -0
  410. package/dist/repertoire/tools-evolution.js +527 -0
  411. package/dist/repertoire/tools-files.js +344 -0
  412. package/dist/repertoire/tools-flight.js +290 -0
  413. package/dist/repertoire/tools-flow.js +119 -0
  414. package/dist/repertoire/tools-github.js +3 -8
  415. package/dist/repertoire/tools-habits.js +103 -0
  416. package/dist/repertoire/tools-mail.js +1828 -0
  417. package/dist/repertoire/tools-notes.js +485 -0
  418. package/dist/repertoire/tools-obligations.js +182 -0
  419. package/dist/repertoire/tools-orientation.js +31 -0
  420. package/dist/repertoire/tools-record.js +482 -0
  421. package/dist/repertoire/tools-rsvp.js +139 -0
  422. package/dist/repertoire/tools-runtime.js +150 -0
  423. package/dist/repertoire/tools-session.js +1133 -0
  424. package/dist/repertoire/tools-shell.js +149 -0
  425. package/dist/repertoire/tools-steward-policy.js +95 -0
  426. package/dist/repertoire/tools-stripe.js +224 -0
  427. package/dist/repertoire/tools-surface.js +369 -0
  428. package/dist/repertoire/tools-teams.js +12 -39
  429. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  430. package/dist/repertoire/tools-travel.js +125 -0
  431. package/dist/repertoire/tools-trip.js +982 -0
  432. package/dist/repertoire/tools-unraid.js +484 -0
  433. package/dist/repertoire/tools-user-profile.js +146 -0
  434. package/dist/repertoire/tools-vault.js +40 -0
  435. package/dist/repertoire/tools-voice.js +145 -0
  436. package/dist/repertoire/tools.js +470 -147
  437. package/dist/repertoire/travel-api-client.js +360 -0
  438. package/dist/repertoire/unraid-client.js +155 -0
  439. package/dist/repertoire/unraid-restart.js +212 -0
  440. package/dist/repertoire/user-profile.js +131 -0
  441. package/dist/repertoire/vault-setup.js +246 -0
  442. package/dist/repertoire/vault-unlock.js +628 -0
  443. package/dist/rsvp/aisleplanner-client.js +354 -0
  444. package/dist/rsvp/cli.js +926 -0
  445. package/dist/rsvp/config.js +327 -0
  446. package/dist/rsvp/cutover.js +433 -0
  447. package/dist/rsvp/diagnostics.js +232 -0
  448. package/dist/rsvp/diff-renderer.js +176 -0
  449. package/dist/rsvp/habit-policy.js +110 -0
  450. package/dist/rsvp/habit-stage.js +123 -0
  451. package/dist/rsvp/incident-bundle.js +97 -0
  452. package/dist/rsvp/migration.js +204 -0
  453. package/dist/rsvp/native-habit-runner.js +630 -0
  454. package/dist/rsvp/outbound-state.js +628 -0
  455. package/dist/rsvp/query.js +118 -0
  456. package/dist/rsvp/replay.js +233 -0
  457. package/dist/rsvp/snapshot.js +232 -0
  458. package/dist/rsvp/spend-ledger.js +175 -0
  459. package/dist/scripts/claude-code-hook.js +41 -0
  460. package/dist/scripts/claude-code-stop-hook.js +47 -0
  461. package/dist/senses/a2a-entry.js +115 -0
  462. package/dist/senses/acp-server.js +386 -0
  463. package/dist/senses/attention-queue.js +186 -0
  464. package/dist/senses/await-turn-message.js +58 -0
  465. package/dist/senses/bluebubbles/active-turns.js +216 -0
  466. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  467. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  468. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  469. package/dist/senses/bluebubbles/context-packet.js +207 -0
  470. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  471. package/dist/senses/bluebubbles/entry.js +90 -0
  472. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  473. package/dist/senses/bluebubbles/index.js +3841 -0
  474. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  475. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  476. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  477. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  478. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  479. package/dist/senses/bluebubbles/processed-log.js +133 -0
  480. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  481. package/dist/senses/bluebubbles/replay.js +284 -0
  482. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  483. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  484. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  485. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  486. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  487. package/dist/senses/cli/bracketed-paste.js +82 -0
  488. package/dist/senses/cli/image-paste.js +287 -0
  489. package/dist/senses/cli/image-ref-navigation.js +75 -0
  490. package/dist/senses/cli/ink-app.js +156 -0
  491. package/dist/senses/cli/inline-diff.js +64 -0
  492. package/dist/senses/cli/input-keys.js +174 -0
  493. package/dist/senses/cli/kill-ring.js +86 -0
  494. package/dist/senses/cli/message-list.js +51 -0
  495. package/dist/senses/cli/ouro-tui.js +607 -0
  496. package/dist/senses/cli/spinner-imperative.js +135 -0
  497. package/dist/senses/cli/spinner.js +101 -0
  498. package/dist/senses/cli/status-line.js +60 -0
  499. package/dist/senses/cli/streaming-markdown.js +526 -0
  500. package/dist/senses/cli/tool-display.js +85 -0
  501. package/dist/senses/cli/tool-render.js +85 -0
  502. package/dist/senses/cli/tui-store.js +241 -0
  503. package/dist/senses/cli/virtual-list.js +35 -0
  504. package/dist/senses/cli-entry.js +60 -8
  505. package/dist/senses/cli.js +604 -320
  506. package/dist/senses/commands.js +66 -3
  507. package/dist/senses/context-packet-ledger.js +371 -0
  508. package/dist/senses/context-packets.js +154 -0
  509. package/dist/senses/habit-lifecycle-guard.js +24 -0
  510. package/dist/senses/habit-turn-message.js +160 -0
  511. package/dist/senses/ingress-evidence.js +2 -0
  512. package/dist/senses/mail-entry.js +66 -0
  513. package/dist/senses/mail.js +524 -0
  514. package/dist/senses/pipeline.js +1115 -204
  515. package/dist/senses/private-runtime-worker.js +859 -0
  516. package/dist/senses/private-runtime.js +1502 -0
  517. package/dist/senses/proactive-content-guard.js +51 -0
  518. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  519. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  520. package/dist/senses/sanctuary-grounding.js +118 -0
  521. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  522. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  523. package/dist/senses/sanctuary-health-runner.js +101 -0
  524. package/dist/senses/sanctuary-health.js +408 -0
  525. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  526. package/dist/senses/sanctuary-interactive-control.js +306 -0
  527. package/dist/senses/sanctuary-media-catalog-contract.js +235 -0
  528. package/dist/senses/sanctuary-media-optimization.js +514 -0
  529. package/dist/senses/sanctuary-runtime.js +338 -0
  530. package/dist/senses/sanctuary-sab.js +85 -0
  531. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  532. package/dist/senses/shared-turn.js +759 -0
  533. package/dist/senses/surface-tool.js +109 -0
  534. package/dist/senses/teams-entry.js +60 -8
  535. package/dist/senses/teams.js +519 -218
  536. package/dist/senses/telegram-admission.js +711 -0
  537. package/dist/senses/telegram-approval-runtime.js +675 -0
  538. package/dist/senses/telegram-attachments.js +182 -0
  539. package/dist/senses/telegram-audit-ledger.js +220 -0
  540. package/dist/senses/telegram-client.js +1694 -0
  541. package/dist/senses/telegram-effect-adapter.js +859 -0
  542. package/dist/senses/telegram-entry.js +83 -0
  543. package/dist/senses/telegram.js +2084 -0
  544. package/dist/senses/trust-gate.js +104 -9
  545. package/dist/senses/voice/audio-playback.js +237 -0
  546. package/dist/senses/voice/audio-routing.js +119 -0
  547. package/dist/senses/voice/elevenlabs.js +202 -0
  548. package/dist/senses/voice/floor-control.js +431 -0
  549. package/dist/senses/voice/floor-controller.js +115 -0
  550. package/dist/senses/voice/golden-path.js +116 -0
  551. package/dist/senses/voice/index.js +29 -0
  552. package/dist/senses/voice/meeting.js +113 -0
  553. package/dist/senses/voice/outbound.js +190 -0
  554. package/dist/senses/voice/phone.js +33 -0
  555. package/dist/senses/voice/playback.js +139 -0
  556. package/dist/senses/voice/realtime-eval.js +496 -0
  557. package/dist/senses/voice/realtime-trace.js +531 -0
  558. package/dist/senses/voice/transcript.js +70 -0
  559. package/dist/senses/voice/turn.js +191 -0
  560. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  561. package/dist/senses/voice/twilio-phone.js +5031 -0
  562. package/dist/senses/voice/types.js +2 -0
  563. package/dist/senses/voice/whisper.js +161 -0
  564. package/dist/senses/voice-entry.js +81 -0
  565. package/dist/senses/voice-realtime-eval-command.js +99 -0
  566. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  567. package/dist/senses/voice-twilio-entry.js +87 -0
  568. package/dist/trips/core.js +138 -0
  569. package/dist/trips/store.js +265 -0
  570. package/dist/util/frontmatter.js +69 -0
  571. package/npm-shrinkwrap.json +8138 -0
  572. package/package.json +72 -13
  573. package/skills/agent-commerce.md +113 -0
  574. package/skills/browser-navigation.md +117 -0
  575. package/skills/commerce-setup-guide.md +116 -0
  576. package/skills/commerce-setup.md +84 -0
  577. package/skills/configure-dev-tools.md +99 -0
  578. package/skills/travel-planning.md +138 -0
  579. package/dist/heart/daemon/auth-flow.js +0 -430
  580. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  581. package/dist/heart/daemon/ouro-version-manager.js +0 -164
  582. package/dist/heart/daemon/update-hooks.js +0 -138
  583. package/dist/heart/obligations.js +0 -141
  584. package/dist/heart/safe-workspace.js +0 -228
  585. package/dist/heart/session-recall.js +0 -116
  586. package/dist/mind/friends/channel.js +0 -84
  587. package/dist/mind/friends/group-context.js +0 -144
  588. package/dist/mind/friends/resolver.js +0 -84
  589. package/dist/mind/friends/store-file.js +0 -190
  590. package/dist/mind/friends/store.js +0 -4
  591. package/dist/mind/friends/tokens.js +0 -26
  592. package/dist/mind/friends/trust-explanation.js +0 -74
  593. package/dist/mind/friends/types.js +0 -29
  594. package/dist/repertoire/tasks/board.js +0 -134
  595. package/dist/repertoire/tasks/index.js +0 -224
  596. package/dist/repertoire/tasks/lifecycle.js +0 -80
  597. package/dist/repertoire/tasks/middleware.js +0 -65
  598. package/dist/repertoire/tasks/parser.js +0 -173
  599. package/dist/repertoire/tasks/scanner.js +0 -132
  600. package/dist/repertoire/tasks/transitions.js +0 -144
  601. package/dist/senses/bluebubbles-entry.js +0 -13
  602. package/dist/senses/bluebubbles.js +0 -1181
  603. package/dist/senses/debug-activity.js +0 -154
  604. package/dist/senses/inner-dialog-worker.js +0 -90
  605. package/dist/senses/inner-dialog.js +0 -525
  606. package/subagents/README.md +0 -7
  607. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  608. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  609. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  610. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  611. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  612. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  613. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  614. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  615. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  616. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  617. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  618. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  619. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  620. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  621. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  622. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  623. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.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
+ }