@ouro.bot/cli 0.1.0-alpha.98 → 0.1.0-alpha.980

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 (762) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +6189 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/INSTALL.md +64 -0
  18. package/deploy/unraid/README.txt +2997 -0
  19. package/deploy/unraid/audit-container-spec.sh +4 -0
  20. package/deploy/unraid/container-runtime.json +1 -0
  21. package/deploy/unraid/credit-gateway.md +95 -0
  22. package/deploy/unraid/docker-man-template-transaction.mjs +727 -0
  23. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  24. package/deploy/unraid/install.sh +274 -0
  25. package/deploy/unraid/migrate-sanctuary-bundle.mjs +63 -0
  26. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  27. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  28. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  29. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  30. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  31. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  32. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  33. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  34. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  35. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  36. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1377 -0
  37. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  38. package/deploy/unraid/sanctuary-replay-gate.mjs +1776 -0
  39. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  40. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2088 -0
  41. package/deploy/unraid/sanctuary-unit16-run.sh +570 -0
  42. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  43. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  44. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  45. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  46. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  47. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  48. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2255 -0
  49. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +7 -0
  52. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +33 -0
  53. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  54. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +21 -0
  55. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  56. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  57. package/deploy/unraid/sanctuary.xml +29 -0
  58. package/dist/a2a/card.js +57 -0
  59. package/dist/a2a/client.js +250 -0
  60. package/dist/a2a/config.js +50 -0
  61. package/dist/a2a/delegated-command-grants.js +93 -0
  62. package/dist/a2a/delegated-command.js +197 -0
  63. package/dist/a2a/delegation-stores.js +56 -0
  64. package/dist/a2a/did-resolution.js +93 -0
  65. package/dist/a2a/escalation-grants.js +84 -0
  66. package/dist/a2a/escalation-wiring.js +60 -0
  67. package/dist/a2a/identity.js +258 -0
  68. package/dist/a2a/inbound-share.js +110 -0
  69. package/dist/a2a/mission-result-wire.js +196 -0
  70. package/dist/a2a/onboarding.js +133 -0
  71. package/dist/a2a/operator-trust.js +399 -0
  72. package/dist/a2a/outbox-client.js +57 -0
  73. package/dist/a2a/outbox-store.js +188 -0
  74. package/dist/a2a/outbox-wire.js +95 -0
  75. package/dist/a2a/pin-store.js +132 -0
  76. package/dist/a2a/replay-grant-holders.js +33 -0
  77. package/dist/a2a/replay-harness.js +188 -0
  78. package/dist/a2a/resolution-proof.js +53 -0
  79. package/dist/a2a/sealed-chat.js +113 -0
  80. package/dist/a2a/seen-ledger.js +120 -0
  81. package/dist/a2a/server.js +771 -0
  82. package/dist/a2a/task-store.js +69 -0
  83. package/dist/a2a/transport.js +45 -0
  84. package/dist/a2a/trust-commands.js +203 -0
  85. package/dist/a2a/trusted-files.js +185 -0
  86. package/dist/a2a/types.js +3 -0
  87. package/dist/arc/attention-types.js +8 -0
  88. package/dist/arc/cares.js +360 -0
  89. package/dist/arc/episodes.js +118 -0
  90. package/dist/arc/evolution.js +490 -0
  91. package/dist/arc/flight-recorder.js +1034 -0
  92. package/dist/arc/intentions.js +134 -0
  93. package/dist/arc/json-store.js +117 -0
  94. package/dist/arc/obligations.js +386 -0
  95. package/dist/arc/packets.js +336 -0
  96. package/dist/arc/presence.js +185 -0
  97. package/dist/arc/task-lifecycle.js +57 -0
  98. package/dist/commerce/store.js +755 -0
  99. package/dist/commerce/types.js +3 -0
  100. package/dist/gateway/keys.js +117 -0
  101. package/dist/gateway/server.js +429 -0
  102. package/dist/heart/active-work.js +798 -40
  103. package/dist/heart/agent-entry.js +252 -3
  104. package/dist/heart/approval-files.js +113 -0
  105. package/dist/heart/approval-store.js +960 -0
  106. package/dist/heart/attachments/image-normalize.js +201 -0
  107. package/dist/heart/attachments/materialize.js +97 -0
  108. package/dist/heart/attachments/originals.js +88 -0
  109. package/dist/heart/attachments/render.js +29 -0
  110. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  111. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  112. package/dist/heart/attachments/sources/index.js +18 -0
  113. package/dist/heart/attachments/sources/telegram.js +71 -0
  114. package/dist/heart/attachments/store.js +132 -0
  115. package/dist/heart/attachments/types.js +93 -0
  116. package/dist/heart/auth/auth-flow.js +511 -0
  117. package/dist/heart/autonomy-budget.js +478 -0
  118. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  119. package/dist/heart/awaiting/await-alert.js +152 -0
  120. package/dist/heart/awaiting/await-expiry.js +143 -0
  121. package/dist/heart/awaiting/await-loader.js +91 -0
  122. package/dist/heart/awaiting/await-parser.js +152 -0
  123. package/dist/heart/awaiting/await-runtime-state.js +130 -0
  124. package/dist/heart/awaiting/await-scheduler.js +391 -0
  125. package/dist/heart/background-operations.js +281 -0
  126. package/dist/heart/bluebubbles-host-account.js +78 -0
  127. package/dist/heart/bridges/manager.js +137 -17
  128. package/dist/heart/bridges/store.js +14 -2
  129. package/dist/heart/bundle-state.js +168 -0
  130. package/dist/heart/commitments.js +44 -18
  131. package/dist/heart/config-registry.js +331 -0
  132. package/dist/heart/config.js +178 -131
  133. package/dist/heart/context-loss-gauntlet.js +387 -0
  134. package/dist/heart/context-loss-sentinel.js +1204 -0
  135. package/dist/heart/core.js +2377 -586
  136. package/dist/heart/cross-chat-delivery.js +9 -22
  137. package/dist/heart/daemon/agent-config-check.js +474 -0
  138. package/dist/heart/daemon/agent-discovery.js +283 -3
  139. package/dist/heart/daemon/agent-home.js +319 -0
  140. package/dist/heart/daemon/agent-service.js +542 -0
  141. package/dist/heart/daemon/agentic-repair.js +547 -0
  142. package/dist/heart/daemon/await-private-wake.js +59 -0
  143. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  144. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  145. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  146. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  147. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  148. package/dist/heart/daemon/cadence.js +180 -0
  149. package/dist/heart/daemon/cli-arg-redaction.js +26 -0
  150. package/dist/heart/daemon/cli-defaults.js +881 -0
  151. package/dist/heart/daemon/cli-desk.js +322 -0
  152. package/dist/heart/daemon/cli-exec.js +9267 -0
  153. package/dist/heart/daemon/cli-help.js +754 -0
  154. package/dist/heart/daemon/cli-parse.js +3329 -0
  155. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  156. package/dist/heart/daemon/cli-render.js +819 -0
  157. package/dist/heart/daemon/cli-types.js +8 -0
  158. package/dist/heart/daemon/connect-bay.js +323 -0
  159. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  160. package/dist/heart/daemon/container-healthcheck.js +112 -0
  161. package/dist/heart/daemon/container-runtime.js +97 -0
  162. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  163. package/dist/heart/daemon/container-spec-auditor.js +241 -0
  164. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  165. package/dist/heart/daemon/daemon-cli.js +29 -2373
  166. package/dist/heart/daemon/daemon-entry.js +953 -11
  167. package/dist/heart/daemon/daemon-health.js +186 -0
  168. package/dist/heart/daemon/daemon-rollup.js +57 -0
  169. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  170. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  171. package/dist/heart/daemon/daemon.js +2110 -104
  172. package/dist/heart/daemon/dns-workflow.js +394 -0
  173. package/dist/heart/daemon/doctor-types.js +8 -0
  174. package/dist/heart/daemon/doctor.js +1766 -0
  175. package/dist/heart/daemon/freshness.js +345 -0
  176. package/dist/heart/daemon/habit-private-wake.js +61 -0
  177. package/dist/heart/daemon/health-monitor.js +154 -11
  178. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  179. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  180. package/dist/heart/daemon/http-health-probe.js +80 -0
  181. package/dist/heart/daemon/human-command-screens.js +234 -0
  182. package/dist/heart/daemon/human-readiness.js +114 -0
  183. package/dist/heart/daemon/inner-status.js +78 -0
  184. package/dist/heart/daemon/interactive-repair.js +394 -0
  185. package/dist/heart/daemon/launchd.js +37 -8
  186. package/dist/heart/daemon/log-tailer.js +79 -10
  187. package/dist/heart/daemon/logs-prune.js +132 -0
  188. package/dist/heart/daemon/mcp-canary.js +524 -0
  189. package/dist/heart/daemon/message-router.js +65 -5
  190. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  191. package/dist/heart/daemon/os-cron-deps.js +135 -0
  192. package/dist/heart/daemon/os-cron.js +22 -14
  193. package/dist/heart/daemon/ouro-bot-entry.js +6 -3
  194. package/dist/heart/daemon/ouro-entry.js +9 -3
  195. package/dist/heart/daemon/plugin-cli.js +432 -0
  196. package/dist/heart/daemon/process-manager.js +760 -61
  197. package/dist/heart/daemon/provider-discovery.js +137 -0
  198. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  199. package/dist/heart/daemon/prunable-bundle.js +144 -0
  200. package/dist/heart/daemon/pulse.js +511 -0
  201. package/dist/heart/daemon/readiness-repair.js +365 -0
  202. package/dist/heart/daemon/run-hooks.js +2 -0
  203. package/dist/heart/daemon/runtime-logging.js +47 -14
  204. package/dist/heart/daemon/runtime-metadata.js +2 -30
  205. package/dist/heart/daemon/runtime-mode.js +13 -2
  206. package/dist/heart/daemon/safe-mode.js +161 -0
  207. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2662 -0
  208. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1832 -0
  209. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  210. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
  211. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  212. package/dist/heart/daemon/sanctuary-authority-epoch.js +291 -0
  213. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  214. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  215. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1326 -0
  216. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  217. package/dist/heart/daemon/sanctuary-bundle-migration.js +851 -0
  218. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  219. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  220. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  221. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  222. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  223. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  224. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  225. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  226. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  227. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  228. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  229. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  230. package/dist/heart/daemon/sense-manager.js +786 -48
  231. package/dist/heart/daemon/session-id-resolver.js +131 -0
  232. package/dist/heart/daemon/skill-management-installer.js +1 -1
  233. package/dist/heart/daemon/socket-client.js +180 -12
  234. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  235. package/dist/heart/daemon/startup-tui.js +339 -0
  236. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  237. package/dist/heart/daemon/task-scheduler.js +117 -39
  238. package/dist/heart/daemon/terminal-ui.js +503 -0
  239. package/dist/heart/daemon/thoughts.js +138 -54
  240. package/dist/heart/daemon/up-progress.js +366 -0
  241. package/dist/heart/daemon/vault-items.js +56 -0
  242. package/dist/heart/delegation.js +1 -4
  243. package/dist/heart/external-events/router.js +1531 -0
  244. package/dist/heart/failure-reports.js +336 -0
  245. package/dist/heart/file-lock.js +109 -0
  246. package/dist/heart/frontend-approval-runtime.js +506 -0
  247. package/dist/heart/frontend-journal.js +215 -0
  248. package/dist/heart/frontend-session-service.js +271 -0
  249. package/dist/heart/frontend-socket-client.js +173 -0
  250. package/dist/heart/frontend-socket.js +434 -0
  251. package/dist/heart/frontend-turn-errors.js +20 -0
  252. package/dist/heart/habits/habit-cancel.js +810 -0
  253. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  254. package/dist/heart/habits/habit-migration.js +194 -0
  255. package/dist/heart/habits/habit-parser.js +278 -0
  256. package/dist/heart/habits/habit-runtime-state.js +93 -0
  257. package/dist/heart/habits/habit-scheduler.js +653 -0
  258. package/dist/heart/habits/habit-session-summary.js +318 -0
  259. package/dist/heart/habits/habit-session.js +636 -0
  260. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  261. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  262. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  263. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  264. package/dist/heart/identity.js +239 -59
  265. package/dist/heart/kept-notes.js +289 -0
  266. package/dist/heart/kicks.js +1 -1
  267. package/dist/heart/machine-identity.js +175 -0
  268. package/dist/heart/mail-import-discovery.js +356 -0
  269. package/dist/heart/mailbox/mailbox-http-hooks.js +99 -0
  270. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  271. package/dist/heart/mailbox/mailbox-http-routes.js +406 -0
  272. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  273. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  274. package/dist/heart/mailbox/mailbox-http.js +99 -0
  275. package/dist/heart/mailbox/mailbox-read.js +41 -0
  276. package/dist/heart/mailbox/mailbox-supervision.js +131 -0
  277. package/dist/heart/mailbox/mailbox-types.js +27 -0
  278. package/dist/heart/mailbox/mailbox-view.js +197 -0
  279. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  280. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  281. package/dist/heart/mailbox/readers/mail.js +375 -0
  282. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  283. package/dist/heart/mailbox/readers/sessions.js +231 -0
  284. package/dist/heart/mailbox/readers/shared.js +111 -0
  285. package/dist/heart/mcp/mcp-server.js +760 -0
  286. package/dist/heart/migrate-config.js +100 -0
  287. package/dist/heart/model-capabilities.js +83 -16
  288. package/dist/heart/orientation-frame.js +376 -0
  289. package/dist/heart/platform.js +81 -0
  290. package/dist/heart/primitives.js +1 -1
  291. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  292. package/dist/heart/private-runtime/index.js +18 -0
  293. package/dist/heart/private-runtime/ledger.js +221 -0
  294. package/dist/heart/private-runtime/policy.js +260 -0
  295. package/dist/heart/private-runtime/types.js +2 -0
  296. package/dist/heart/progress-story.js +1 -1
  297. package/dist/heart/provider-attempt.js +137 -0
  298. package/dist/heart/provider-binding-resolver.js +273 -0
  299. package/dist/heart/provider-credentials.js +449 -0
  300. package/dist/heart/provider-failover.js +311 -0
  301. package/dist/heart/provider-models.js +96 -0
  302. package/dist/heart/provider-ping.js +266 -0
  303. package/dist/heart/provider-readiness-cache.js +119 -0
  304. package/dist/heart/provider-visibility.js +188 -0
  305. package/dist/heart/providers/anthropic-token.js +131 -0
  306. package/dist/heart/providers/anthropic.js +248 -67
  307. package/dist/heart/providers/azure.js +23 -11
  308. package/dist/heart/providers/error-classification.js +129 -0
  309. package/dist/heart/providers/github-copilot.js +38 -39
  310. package/dist/heart/providers/minimax-vlm.js +189 -0
  311. package/dist/heart/providers/minimax.js +26 -8
  312. package/dist/heart/providers/openai-codex-token.js +349 -0
  313. package/dist/heart/providers/openai-codex.js +55 -40
  314. package/dist/heart/providers/openai-compatible.js +177 -0
  315. package/dist/heart/reach-channel.js +85 -0
  316. package/dist/heart/reply-style.js +52 -0
  317. package/dist/heart/run-ledger.js +247 -0
  318. package/dist/heart/runtime-capability-check.js +170 -0
  319. package/dist/heart/runtime-credentials.js +608 -0
  320. package/dist/heart/runtime-cwd.js +87 -0
  321. package/dist/heart/sense-truth.js +24 -4
  322. package/dist/heart/session-activity.js +94 -24
  323. package/dist/heart/session-events.js +1521 -0
  324. package/dist/heart/session-playback-cli-main.js +5 -0
  325. package/dist/heart/session-playback-cli.js +36 -0
  326. package/dist/heart/session-playback.js +231 -0
  327. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  328. package/dist/heart/session-redaction-repair.js +552 -0
  329. package/dist/heart/session-stats-cli-main.js +5 -0
  330. package/dist/heart/session-stats.js +183 -0
  331. package/dist/heart/session-transcript.js +133 -0
  332. package/dist/heart/shelf-claims.js +78 -0
  333. package/dist/heart/shepherd/custody-types.js +2 -0
  334. package/dist/heart/shepherd/mandates.js +352 -0
  335. package/dist/heart/shepherd/operation-commands.js +19 -0
  336. package/dist/heart/shepherd/operations.js +135 -0
  337. package/dist/heart/shepherd/supervision.js +114 -0
  338. package/dist/heart/shepherd/types.js +2 -0
  339. package/dist/heart/shepherd-config.js +123 -0
  340. package/dist/heart/source-grounding.js +313 -0
  341. package/dist/heart/start-of-turn-packet.js +372 -0
  342. package/dist/heart/steward-policy.js +656 -0
  343. package/dist/heart/streaming.js +631 -207
  344. package/dist/heart/structured-output.js +196 -0
  345. package/dist/heart/sync-classification.js +176 -0
  346. package/dist/heart/sync-health.js +152 -0
  347. package/dist/heart/sync.js +726 -0
  348. package/dist/heart/target-resolution.js +11 -7
  349. package/dist/heart/tempo.js +93 -0
  350. package/dist/heart/temporal-view.js +41 -0
  351. package/dist/heart/timeouts.js +101 -0
  352. package/dist/heart/tool-activity-callbacks.js +59 -0
  353. package/dist/heart/tool-approval.js +382 -0
  354. package/dist/heart/tool-description.js +155 -0
  355. package/dist/heart/tool-friction.js +55 -0
  356. package/dist/heart/tool-loop.js +206 -0
  357. package/dist/heart/turn-context.js +496 -0
  358. package/dist/heart/turn-execution-lease.js +30 -0
  359. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  360. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
  361. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  362. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  363. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  364. package/dist/heart/versioning/release-sources.js +173 -0
  365. package/dist/heart/versioning/self-update-defaults.js +294 -0
  366. package/dist/heart/versioning/self-update.js +196 -0
  367. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  368. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  369. package/dist/heart/versioning/update-hooks.js +154 -0
  370. package/dist/heart/versioning/update-state.js +126 -0
  371. package/dist/heart/versioning/updater-launchd.js +150 -0
  372. package/dist/heart/versioning/version-intent.js +114 -0
  373. package/dist/heart/work-card.js +380 -0
  374. package/dist/mailbox-ui/assets/index-Dbska1tZ.js +1 -0
  375. package/dist/mailbox-ui/assets/index-DsiKaPyH.css +1 -0
  376. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  377. package/dist/mailbox-ui/index.html +16 -0
  378. package/dist/mailroom/attention.js +167 -0
  379. package/dist/mailroom/autonomy.js +209 -0
  380. package/dist/mailroom/blob-store.js +889 -0
  381. package/dist/mailroom/body-cache.js +61 -0
  382. package/dist/mailroom/cache-sync-cli.js +58 -0
  383. package/dist/mailroom/core.js +803 -0
  384. package/dist/mailroom/entry.js +160 -0
  385. package/dist/mailroom/file-store.js +568 -0
  386. package/dist/mailroom/hosted-cache-sync.js +384 -0
  387. package/dist/mailroom/mbox-import.js +393 -0
  388. package/dist/mailroom/migration.js +164 -0
  389. package/dist/mailroom/outbound.js +380 -0
  390. package/dist/mailroom/policy.js +263 -0
  391. package/dist/mailroom/reader.js +292 -0
  392. package/dist/mailroom/search-cache.js +513 -0
  393. package/dist/mailroom/search-relevance.js +319 -0
  394. package/dist/mailroom/smtp-ingress.js +176 -0
  395. package/dist/mailroom/source-state.js +176 -0
  396. package/dist/mailroom/thread.js +109 -0
  397. package/dist/mailroom/travel-extract.js +89 -0
  398. package/dist/mind/bundle-manifest.js +24 -2
  399. package/dist/mind/context.js +328 -139
  400. package/dist/mind/desk-section.js +362 -0
  401. package/dist/mind/diary-integrity.js +60 -0
  402. package/dist/mind/{memory.js → diary.js} +68 -77
  403. package/dist/mind/embedding-provider.js +60 -0
  404. package/dist/mind/file-state.js +179 -0
  405. package/dist/mind/friend-link-codes.js +209 -0
  406. package/dist/mind/friend-merge.js +336 -0
  407. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  408. package/dist/mind/obligation-steering.js +199 -3
  409. package/dist/mind/outbound-record.js +168 -0
  410. package/dist/mind/pending.js +36 -10
  411. package/dist/mind/prompt-budget.js +479 -0
  412. package/dist/mind/prompt-refresh.js +3 -2
  413. package/dist/mind/prompt.js +1166 -203
  414. package/dist/mind/provenance-trust.js +26 -0
  415. package/dist/mind/record-paths.js +312 -0
  416. package/dist/mind/scrutiny.js +173 -0
  417. package/dist/mind/session-transaction.js +622 -0
  418. package/dist/nerves/cli-logging.js +7 -1
  419. package/dist/nerves/coverage/audit-rules.js +15 -6
  420. package/dist/nerves/coverage/audit.js +28 -2
  421. package/dist/nerves/coverage/cli.js +1 -1
  422. package/dist/nerves/coverage/contract.js +5 -5
  423. package/dist/nerves/coverage/file-completeness.js +143 -5
  424. package/dist/nerves/coverage/run-artifacts.js +55 -35
  425. package/dist/nerves/coverage/source-scanner.js +4 -4
  426. package/dist/nerves/event-buffer.js +111 -0
  427. package/dist/nerves/index.js +293 -9
  428. package/dist/nerves/observation.js +20 -0
  429. package/dist/nerves/redact.js +79 -0
  430. package/dist/nerves/review/cli-main.js +5 -0
  431. package/dist/nerves/review/cli.js +156 -0
  432. package/dist/nerves/review/core.js +159 -0
  433. package/dist/nerves/runtime.js +17 -1
  434. package/dist/repertoire/ado-client.js +15 -56
  435. package/dist/repertoire/ado-semantic.js +16 -10
  436. package/dist/repertoire/api-client.js +97 -0
  437. package/dist/repertoire/bitwarden-store.js +1199 -0
  438. package/dist/repertoire/bundle-templates.js +71 -0
  439. package/dist/repertoire/bw-installer.js +231 -0
  440. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  441. package/dist/repertoire/coding/context-pack.js +331 -0
  442. package/dist/repertoire/coding/feedback.js +146 -34
  443. package/dist/repertoire/coding/index.js +15 -3
  444. package/dist/repertoire/coding/manager.js +159 -10
  445. package/dist/repertoire/coding/spawner.js +40 -11
  446. package/dist/repertoire/coding/tools.js +182 -18
  447. package/dist/repertoire/coding/workbench-client.js +272 -0
  448. package/dist/repertoire/coding/workbench-manager.js +346 -0
  449. package/dist/repertoire/commerce-errors.js +109 -0
  450. package/dist/repertoire/commerce-self-test.js +156 -0
  451. package/dist/repertoire/credential-access.js +183 -0
  452. package/dist/repertoire/desk/classifier.js +362 -0
  453. package/dist/repertoire/duffel-client.js +185 -0
  454. package/dist/repertoire/github-client.js +14 -55
  455. package/dist/repertoire/graph-client.js +11 -52
  456. package/dist/repertoire/guardrails.js +971 -20
  457. package/dist/repertoire/house-sweep.js +471 -0
  458. package/dist/repertoire/mcp-client.js +58 -5
  459. package/dist/repertoire/mcp-manager.js +427 -139
  460. package/dist/repertoire/mcp-tools.js +132 -0
  461. package/dist/repertoire/mcp-write-guard.js +46 -0
  462. package/dist/repertoire/plugin-mcp.js +175 -0
  463. package/dist/repertoire/plugins.js +253 -0
  464. package/dist/repertoire/relationship-authorization.js +322 -0
  465. package/dist/repertoire/sanctuary-container-policy.js +50 -0
  466. package/dist/repertoire/shell-sessions.js +134 -0
  467. package/dist/repertoire/skills.js +48 -4
  468. package/dist/repertoire/stripe-client.js +131 -0
  469. package/dist/repertoire/tool-arguments.js +182 -0
  470. package/dist/repertoire/tool-results.js +29 -0
  471. package/dist/repertoire/tools-a2a.js +699 -0
  472. package/dist/repertoire/tools-attachments.js +322 -0
  473. package/dist/repertoire/tools-awaiting.js +897 -0
  474. package/dist/repertoire/tools-base.js +83 -1168
  475. package/dist/repertoire/tools-bluebubbles.js +2 -0
  476. package/dist/repertoire/tools-bridge.js +144 -0
  477. package/dist/repertoire/tools-bundle.js +995 -0
  478. package/dist/repertoire/tools-commerce.js +253 -0
  479. package/dist/repertoire/tools-config.js +186 -0
  480. package/dist/repertoire/tools-continuity.js +588 -0
  481. package/dist/repertoire/tools-credential.js +383 -0
  482. package/dist/repertoire/tools-escalation.js +84 -0
  483. package/dist/repertoire/tools-evolution.js +527 -0
  484. package/dist/repertoire/tools-files.js +344 -0
  485. package/dist/repertoire/tools-flight.js +290 -0
  486. package/dist/repertoire/tools-flow.js +119 -0
  487. package/dist/repertoire/tools-friend-link.js +57 -0
  488. package/dist/repertoire/tools-github.js +3 -8
  489. package/dist/repertoire/tools-habits.js +103 -0
  490. package/dist/repertoire/tools-house-care.js +174 -0
  491. package/dist/repertoire/tools-mail.js +1828 -0
  492. package/dist/repertoire/tools-notes.js +501 -0
  493. package/dist/repertoire/tools-obligations.js +182 -0
  494. package/dist/repertoire/tools-orientation.js +31 -0
  495. package/dist/repertoire/tools-record.js +482 -0
  496. package/dist/repertoire/tools-rsvp.js +139 -0
  497. package/dist/repertoire/tools-runtime.js +238 -0
  498. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  499. package/dist/repertoire/tools-session.js +1141 -0
  500. package/dist/repertoire/tools-shell.js +154 -0
  501. package/dist/repertoire/tools-shepherd-guidance.js +171 -0
  502. package/dist/repertoire/tools-shepherd.js +325 -0
  503. package/dist/repertoire/tools-steward-policy.js +147 -0
  504. package/dist/repertoire/tools-stripe.js +224 -0
  505. package/dist/repertoire/tools-surface.js +369 -0
  506. package/dist/repertoire/tools-teams.js +50 -39
  507. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  508. package/dist/repertoire/tools-travel.js +125 -0
  509. package/dist/repertoire/tools-trip.js +982 -0
  510. package/dist/repertoire/tools-unraid.js +556 -0
  511. package/dist/repertoire/tools-user-profile.js +146 -0
  512. package/dist/repertoire/tools-vault.js +40 -0
  513. package/dist/repertoire/tools-voice-local.js +198 -0
  514. package/dist/repertoire/tools-voice.js +145 -0
  515. package/dist/repertoire/tools.js +518 -156
  516. package/dist/repertoire/travel-api-client.js +360 -0
  517. package/dist/repertoire/unraid-client.js +155 -0
  518. package/dist/repertoire/unraid-restart.js +339 -0
  519. package/dist/repertoire/user-profile.js +131 -0
  520. package/dist/repertoire/vault-setup.js +246 -0
  521. package/dist/repertoire/vault-unlock.js +686 -0
  522. package/dist/rsvp/aisleplanner-client.js +354 -0
  523. package/dist/rsvp/cli.js +936 -0
  524. package/dist/rsvp/config.js +327 -0
  525. package/dist/rsvp/cutover.js +453 -0
  526. package/dist/rsvp/diagnostics.js +232 -0
  527. package/dist/rsvp/diff-renderer.js +176 -0
  528. package/dist/rsvp/habit-policy.js +110 -0
  529. package/dist/rsvp/habit-stage.js +123 -0
  530. package/dist/rsvp/incident-bundle.js +97 -0
  531. package/dist/rsvp/migration.js +204 -0
  532. package/dist/rsvp/native-habit-runner.js +630 -0
  533. package/dist/rsvp/outbound-state.js +628 -0
  534. package/dist/rsvp/query.js +118 -0
  535. package/dist/rsvp/replay.js +233 -0
  536. package/dist/rsvp/snapshot.js +232 -0
  537. package/dist/rsvp/spend-ledger.js +175 -0
  538. package/dist/scripts/claude-code-hook.js +41 -0
  539. package/dist/scripts/claude-code-stop-hook.js +47 -0
  540. package/dist/senses/a2a-entry.js +132 -0
  541. package/dist/senses/acp-server.js +386 -0
  542. package/dist/senses/attention-queue.js +186 -0
  543. package/dist/senses/await-turn-message.js +65 -0
  544. package/dist/senses/bluebubbles/active-turns.js +216 -0
  545. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  546. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  547. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +393 -43
  548. package/dist/senses/bluebubbles/context-packet.js +207 -0
  549. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  550. package/dist/senses/bluebubbles/entry.js +90 -0
  551. package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
  552. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  553. package/dist/senses/bluebubbles/index.js +4054 -0
  554. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  555. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  556. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  557. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  558. package/dist/senses/bluebubbles/outbound-state.js +335 -0
  559. package/dist/senses/bluebubbles/processed-log.js +133 -0
  560. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  561. package/dist/senses/bluebubbles/replay.js +284 -0
  562. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  563. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  564. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  565. package/dist/senses/bluebubbles/webhook-registration.js +257 -0
  566. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  567. package/dist/senses/cli/bracketed-paste.js +82 -0
  568. package/dist/senses/cli/image-paste.js +287 -0
  569. package/dist/senses/cli/image-ref-navigation.js +75 -0
  570. package/dist/senses/cli/ink-app.js +156 -0
  571. package/dist/senses/cli/inline-diff.js +64 -0
  572. package/dist/senses/cli/input-keys.js +174 -0
  573. package/dist/senses/cli/kill-ring.js +86 -0
  574. package/dist/senses/cli/message-list.js +51 -0
  575. package/dist/senses/cli/ouro-tui.js +607 -0
  576. package/dist/senses/cli/spinner-imperative.js +135 -0
  577. package/dist/senses/cli/spinner.js +101 -0
  578. package/dist/senses/cli/status-line.js +60 -0
  579. package/dist/senses/cli/streaming-markdown.js +526 -0
  580. package/dist/senses/cli/tool-display.js +85 -0
  581. package/dist/senses/cli/tool-render.js +85 -0
  582. package/dist/senses/cli/tui-store.js +241 -0
  583. package/dist/senses/cli/virtual-list.js +35 -0
  584. package/dist/senses/cli-entry.js +60 -8
  585. package/dist/senses/cli.js +570 -309
  586. package/dist/senses/commands.js +66 -3
  587. package/dist/senses/context-packet-ledger.js +371 -0
  588. package/dist/senses/context-packets.js +154 -0
  589. package/dist/senses/habit-lifecycle-guard.js +24 -0
  590. package/dist/senses/habit-turn-message.js +160 -0
  591. package/dist/senses/ingress-evidence.js +2 -0
  592. package/dist/senses/mail-entry.js +66 -0
  593. package/dist/senses/mail.js +524 -0
  594. package/dist/senses/pipeline.js +1158 -204
  595. package/dist/senses/private-runtime-worker.js +857 -0
  596. package/dist/senses/private-runtime.js +1627 -0
  597. package/dist/senses/proactive-content-guard.js +51 -0
  598. package/dist/senses/root-host-approval-port.js +345 -0
  599. package/dist/senses/root-host-approval-runtime.js +393 -0
  600. package/dist/senses/sanctuary-authority-resident.js +102 -0
  601. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  602. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  603. package/dist/senses/sanctuary-grounding.js +118 -0
  604. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  605. package/dist/senses/sanctuary-health-acceptance-probe.js +786 -0
  606. package/dist/senses/sanctuary-health-runner.js +106 -0
  607. package/dist/senses/sanctuary-health.js +442 -0
  608. package/dist/senses/sanctuary-house.js +97 -0
  609. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  610. package/dist/senses/sanctuary-interactive-control.js +410 -0
  611. package/dist/senses/sanctuary-media-catalog-contract.js +268 -0
  612. package/dist/senses/sanctuary-media-optimization.js +517 -0
  613. package/dist/senses/sanctuary-runtime.js +390 -0
  614. package/dist/senses/sanctuary-sab.js +85 -0
  615. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  616. package/dist/senses/shared-turn.js +832 -0
  617. package/dist/senses/shepherd/agent-presentation.js +88 -0
  618. package/dist/senses/shepherd/attention-page.js +166 -0
  619. package/dist/senses/shepherd/attention-sidebar.js +76 -0
  620. package/dist/senses/shepherd/attention.js +295 -0
  621. package/dist/senses/shepherd/checkin-config.js +76 -0
  622. package/dist/senses/shepherd/checkin-store.js +386 -0
  623. package/dist/senses/shepherd/client.js +196 -0
  624. package/dist/senses/shepherd/cmux.js +483 -0
  625. package/dist/senses/shepherd/composer.js +336 -0
  626. package/dist/senses/shepherd/copilot-app.js +648 -0
  627. package/dist/senses/shepherd/feedback-reply.js +108 -0
  628. package/dist/senses/shepherd/feedback-source.js +20 -0
  629. package/dist/senses/shepherd/feedback-store.js +331 -0
  630. package/dist/senses/shepherd/feedback-submit.js +182 -0
  631. package/dist/senses/shepherd/feedback-worker.js +208 -0
  632. package/dist/senses/shepherd/guidance.js +273 -0
  633. package/dist/senses/shepherd/herdr.js +427 -0
  634. package/dist/senses/shepherd/host.js +17 -0
  635. package/dist/senses/shepherd/human-decision-guard.js +29 -0
  636. package/dist/senses/shepherd/judge-evaluation-command.js +183 -0
  637. package/dist/senses/shepherd/judge-evaluation-entry.js +13 -0
  638. package/dist/senses/shepherd/judge-evaluation.js +155 -0
  639. package/dist/senses/shepherd/judge.js +210 -0
  640. package/dist/senses/shepherd/notice-outbox.js +262 -0
  641. package/dist/senses/shepherd/observation-publisher.js +320 -0
  642. package/dist/senses/shepherd/operations-defaults.js +86 -0
  643. package/dist/senses/shepherd/operations.js +159 -0
  644. package/dist/senses/shepherd/owner-notice.js +489 -0
  645. package/dist/senses/shepherd/prompt-state.js +60 -0
  646. package/dist/senses/shepherd/recovery.js +543 -0
  647. package/dist/senses/shepherd/redact.js +66 -0
  648. package/dist/senses/shepherd/returns.js +79 -0
  649. package/dist/senses/shepherd/sense.js +849 -0
  650. package/dist/senses/shepherd/shepherd-judge-corpus-v1.json +170 -0
  651. package/dist/senses/shepherd/surface.js +123 -0
  652. package/dist/senses/shepherd/target-binding.js +13 -0
  653. package/dist/senses/shepherd/terminal-process.js +147 -0
  654. package/dist/senses/shepherd-entry.js +98 -0
  655. package/dist/senses/surface-tool.js +109 -0
  656. package/dist/senses/teams-entry.js +68 -8
  657. package/dist/senses/teams-image.js +119 -0
  658. package/dist/senses/teams.js +998 -337
  659. package/dist/senses/telegram-admission.js +718 -0
  660. package/dist/senses/telegram-approval-runtime.js +793 -0
  661. package/dist/senses/telegram-attachments.js +186 -0
  662. package/dist/senses/telegram-audit-ledger.js +220 -0
  663. package/dist/senses/telegram-authority-transport.js +231 -0
  664. package/dist/senses/telegram-client.js +1755 -0
  665. package/dist/senses/telegram-effect-adapter.js +904 -0
  666. package/dist/senses/telegram-entry.js +83 -0
  667. package/dist/senses/telegram-handoff.js +154 -0
  668. package/dist/senses/telegram.js +2474 -0
  669. package/dist/senses/trust-gate.js +104 -9
  670. package/dist/senses/voice/audio-playback.js +237 -0
  671. package/dist/senses/voice/audio-routing.js +119 -0
  672. package/dist/senses/voice/call-auth.js +250 -0
  673. package/dist/senses/voice/elevenlabs.js +202 -0
  674. package/dist/senses/voice/floor-control.js +431 -0
  675. package/dist/senses/voice/floor-controller.js +115 -0
  676. package/dist/senses/voice/golden-path.js +116 -0
  677. package/dist/senses/voice/index.js +29 -0
  678. package/dist/senses/voice/local-audio-control.js +344 -0
  679. package/dist/senses/voice/local-audio-devices.js +516 -0
  680. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  681. package/dist/senses/voice/local-audio-identity.js +103 -0
  682. package/dist/senses/voice/local-audio-join.js +325 -0
  683. package/dist/senses/voice/local-audio-mute.js +199 -0
  684. package/dist/senses/voice/local-audio-notify.js +124 -0
  685. package/dist/senses/voice/local-audio-prompts.js +116 -0
  686. package/dist/senses/voice/local-audio-transport.js +427 -0
  687. package/dist/senses/voice/local-audio.js +281 -0
  688. package/dist/senses/voice/local-media-stream.js +145 -0
  689. package/dist/senses/voice/meeting.js +113 -0
  690. package/dist/senses/voice/outbound.js +190 -0
  691. package/dist/senses/voice/phone.js +33 -0
  692. package/dist/senses/voice/playback.js +139 -0
  693. package/dist/senses/voice/process-guards.js +51 -0
  694. package/dist/senses/voice/realtime-eval.js +496 -0
  695. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  696. package/dist/senses/voice/realtime-trace.js +531 -0
  697. package/dist/senses/voice/transcript.js +70 -0
  698. package/dist/senses/voice/turn.js +191 -0
  699. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  700. package/dist/senses/voice/twilio-phone.js +5454 -0
  701. package/dist/senses/voice/types.js +2 -0
  702. package/dist/senses/voice/whisper.js +161 -0
  703. package/dist/senses/voice-entry.js +83 -0
  704. package/dist/senses/voice-realtime-eval-command.js +99 -0
  705. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  706. package/dist/senses/voice-twilio-entry.js +87 -0
  707. package/dist/trips/core.js +138 -0
  708. package/dist/trips/store.js +265 -0
  709. package/dist/util/frontmatter.js +69 -0
  710. package/npm-shrinkwrap.json +8342 -0
  711. package/package.json +76 -13
  712. package/skills/agent-commerce.md +113 -0
  713. package/skills/browser-navigation.md +117 -0
  714. package/skills/commerce-setup-guide.md +116 -0
  715. package/skills/commerce-setup.md +84 -0
  716. package/skills/configure-dev-tools.md +99 -0
  717. package/skills/travel-planning.md +138 -0
  718. package/dist/heart/daemon/auth-flow.js +0 -430
  719. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  720. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  721. package/dist/heart/daemon/update-hooks.js +0 -138
  722. package/dist/heart/obligations.js +0 -191
  723. package/dist/heart/safe-workspace.js +0 -381
  724. package/dist/heart/session-recall.js +0 -116
  725. package/dist/mind/friends/channel.js +0 -84
  726. package/dist/mind/friends/group-context.js +0 -144
  727. package/dist/mind/friends/resolver.js +0 -84
  728. package/dist/mind/friends/store-file.js +0 -190
  729. package/dist/mind/friends/store.js +0 -4
  730. package/dist/mind/friends/tokens.js +0 -26
  731. package/dist/mind/friends/trust-explanation.js +0 -74
  732. package/dist/mind/friends/types.js +0 -29
  733. package/dist/repertoire/tasks/board.js +0 -134
  734. package/dist/repertoire/tasks/index.js +0 -224
  735. package/dist/repertoire/tasks/lifecycle.js +0 -80
  736. package/dist/repertoire/tasks/middleware.js +0 -65
  737. package/dist/repertoire/tasks/parser.js +0 -173
  738. package/dist/repertoire/tasks/scanner.js +0 -132
  739. package/dist/repertoire/tasks/transitions.js +0 -144
  740. package/dist/senses/bluebubbles-entry.js +0 -13
  741. package/dist/senses/bluebubbles.js +0 -1181
  742. package/dist/senses/debug-activity.js +0 -154
  743. package/dist/senses/inner-dialog-worker.js +0 -90
  744. package/dist/senses/inner-dialog.js +0 -525
  745. package/subagents/README.md +0 -7
  746. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  747. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  748. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  749. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  750. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  751. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  752. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  753. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  754. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  755. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  756. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  757. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  758. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  759. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  760. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  761. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  762. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,105 @@
1
+ "use strict"
2
+
3
+ const { TextDecoder } = require("node:util")
4
+
5
+ const DECLARATION = "<?xml version=\"1.0\"?>"
6
+ const ROOT_OPEN = "<Container version=\"2\">"
7
+ const ROOT_CLOSE = "</Container>"
8
+ const NAME_START = /^[A-Za-z_]$/u
9
+ const NAME_CHARACTER = /^[A-Za-z0-9_.:-]$/u
10
+ const XML_WHITESPACE = /^[\t\n\r ]$/u
11
+ const UTF8_DECODER = new TextDecoder("utf-8", { fatal: true })
12
+
13
+ function decodeUtf8(value) {
14
+ if (typeof value === "string") return value
15
+ if (!(value instanceof Uint8Array)) throw new TypeError("DockerMan template bytes are invalid")
16
+ return UTF8_DECODER.decode(value)
17
+ }
18
+
19
+ function skipWhitespace(value, start) {
20
+ let index = start
21
+ while (XML_WHITESPACE.test(value[index] ?? "")) index += 1
22
+ return index
23
+ }
24
+
25
+ function readName(value, start) {
26
+ if (!NAME_START.test(value[start] ?? "")) return null
27
+ let index = start + 1
28
+ while (NAME_CHARACTER.test(value[index] ?? "")) index += 1
29
+ return { name: value.slice(start, index), index }
30
+ }
31
+
32
+ function readOpenTag(xml, start) {
33
+ if (xml[start] !== "<") return null
34
+ const parsedName = readName(xml, start + 1)
35
+ if (!parsedName) return null
36
+ const attributes = new Map()
37
+ let index = parsedName.index
38
+ while (index < xml.length) {
39
+ if (xml[index] === ">") return { name: parsedName.name, attributes: Object.fromEntries(attributes), form: "text", index: index + 1 }
40
+ if (xml.startsWith("/>", index)) return { name: parsedName.name, attributes: Object.fromEntries(attributes), form: "empty", index: index + 2 }
41
+ const whitespaceEnd = skipWhitespace(xml, index)
42
+ if (whitespaceEnd === index) return null
43
+ index = whitespaceEnd
44
+ if (xml[index] === ">" || xml.startsWith("/>", index)) continue
45
+ const attribute = readName(xml, index)
46
+ if (!attribute || attributes.has(attribute.name)) return null
47
+ index = skipWhitespace(xml, attribute.index)
48
+ if (xml[index] !== "=") return null
49
+ index = skipWhitespace(xml, index + 1)
50
+ if (xml[index] !== "\"") return null
51
+ const end = xml.indexOf("\"", index + 1)
52
+ if (end === -1) return null
53
+ const value = xml.slice(index + 1, end)
54
+ if (!/^[\x20-\x7E]*$/u.test(value) || value.includes("<") || value.includes("&")) return null
55
+ attributes.set(attribute.name, value)
56
+ index = end + 1
57
+ }
58
+ return null
59
+ }
60
+
61
+ function hasValidXmlCharacters(value) {
62
+ for (const character of value) {
63
+ const codePoint = character.codePointAt(0)
64
+ if (!(codePoint === 0x9 || codePoint === 0xA || codePoint === 0xD
65
+ || (codePoint >= 0x20 && codePoint <= 0xD7FF)
66
+ || (codePoint >= 0xE000 && codePoint <= 0xFFFD)
67
+ || (codePoint >= 0x10000 && codePoint <= 0x10FFFF))) return false
68
+ }
69
+ return true
70
+ }
71
+
72
+ // Canonical DockerMan dialect: exact declaration and Container root, flat leaf children, double-quoted ASCII attributes, and literal text without entities or auxiliary XML constructs.
73
+ function parseDockerManTemplateXml(input) {
74
+ let xml
75
+ try { xml = decodeUtf8(input) } catch { return null }
76
+ if (!hasValidXmlCharacters(xml) || !xml.startsWith(DECLARATION)) return null
77
+ let index = skipWhitespace(xml, DECLARATION.length)
78
+ if (!xml.startsWith(ROOT_OPEN, index)) return null
79
+ index += ROOT_OPEN.length
80
+ const children = []
81
+ while (index < xml.length) {
82
+ index = skipWhitespace(xml, index)
83
+ if (xml.startsWith(ROOT_CLOSE, index)) {
84
+ index = skipWhitespace(xml, index + ROOT_CLOSE.length)
85
+ return index === xml.length ? { root: { name: "Container", attributes: { version: "2" } }, children } : null
86
+ }
87
+ const child = readOpenTag(xml, index)
88
+ if (!child) return null
89
+ index = child.index
90
+ if (child.form === "empty") {
91
+ children.push({ name: child.name, attributes: child.attributes, form: child.form, text: "" })
92
+ continue
93
+ }
94
+ const close = `</${child.name}>`
95
+ const end = xml.indexOf("<", index)
96
+ if (end === -1 || !xml.startsWith(close, end)) return null
97
+ const text = xml.slice(index, end)
98
+ if (text.includes("&") || text.includes("]]>")) return null
99
+ children.push({ name: child.name, attributes: child.attributes, form: child.form, text })
100
+ index = end + close.length
101
+ }
102
+ return null
103
+ }
104
+
105
+ module.exports = { decodeUtf8, parseDockerManTemplateXml }
@@ -0,0 +1,274 @@
1
+ #!/bin/bash
2
+ # Ouro Butler installer for Unraid 7.2 or newer.
3
+ #
4
+ # Run it as root in the Unraid web terminal. Download it and read it first if you like:
5
+ # curl -fsSLo /tmp/ouro-butler-install.sh https://github.com/ourostack/ouroboros/releases/latest/download/install.sh
6
+ # bash /tmp/ouro-butler-install.sh
7
+ #
8
+ # What it does, in order (each step says what it is doing as it goes):
9
+ # 1. checks this is Unraid 7.2+, as root, with Docker running and no Butler installed yet
10
+ # 2. asks for your name, the Butler's name, a vault email, your Anthropic API key and your Telegram bot token
11
+ # (secrets are read with the terminal's echo off and never appear in a command line)
12
+ # 3. pulls the Butler image and seeds the Butler's files under /mnt/user/appdata/ouro-butler
13
+ # 4. creates the Butler's vault (you choose its unlock phrase) and stores the Anthropic key in it
14
+ # 5. creates two Unraid API keys for the Butler (read-only, and read plus Docker update) and stores them in the vault
15
+ # 6. finds your Telegram user id when you message the bot, then installs the root authority that holds the bot
16
+ # token and starts the Butler
17
+ #
18
+ # Options:
19
+ # --version <0.1.0-alpha.N> install this release instead of the newest one
20
+ # --vault-server <url> use your own Vaultwarden-compatible server instead of https://vault.ouro.bot
21
+ # --help print this header
22
+ set -euo pipefail
23
+ umask 077
24
+
25
+ IMAGE_REPO=ghcr.io/ourostack/ouroboros-butler
26
+ APPDATA=/mnt/user/appdata/ouro-butler
27
+ RUNTIME=$APPDATA/runtime/.ouro-cli
28
+ BUNDLE=$APPDATA/agent/sanctuary.ouro
29
+ STAGE=$APPDATA/installer
30
+ AUTHORITY=/mnt/user/appdata/ouro-authority
31
+ EVENTS=/boot/config/custom/ouro-events
32
+ CONTAINER=ouro-butler
33
+ AGENT=sanctuary
34
+ TTY=/dev/tty
35
+ VERSION=""
36
+ VAULT_SERVER=""
37
+
38
+ say() { printf '\n== %s\n' "$*"; }
39
+ ok() { printf ' ok %s\n' "$*"; }
40
+ die() { printf '\nSTOPPED: %s\n' "$*" >&2; exit 1; }
41
+
42
+ ask() { # ask <variable> <prompt> [default]
43
+ local answer
44
+ printf '%s%s: ' "$2" "${3:+ [$3]}" > "$TTY"
45
+ IFS= read -r answer < "$TTY" || die "no answer read from the terminal"
46
+ printf -v "$1" '%s' "${answer:-${3:-}}"
47
+ }
48
+
49
+ ask_secret() { # ask_secret <variable> <prompt>
50
+ local answer saved
51
+ saved=$(stty -g < "$TTY")
52
+ printf '%s (input is hidden): ' "$2" > "$TTY"
53
+ stty -echo < "$TTY"
54
+ IFS= read -r answer < "$TTY" || { stty "$saved" < "$TTY"; die "no answer read from the terminal"; }
55
+ stty "$saved" < "$TTY"
56
+ printf '\n' > "$TTY"
57
+ printf -v "$1" '%s' "$answer"
58
+ }
59
+
60
+ confirm() { local reply; ask reply "$1 (y/n)" n; case "$reply" in y|Y|yes|YES) return 0 ;; *) return 1 ;; esac; }
61
+
62
+ while (($# > 0)); do
63
+ case "$1" in
64
+ --version) VERSION="${2:?--version needs a value, for example 0.1.0-alpha.970}"; shift 2 ;;
65
+ --vault-server) VAULT_SERVER="${2:?--vault-server needs a URL}"; shift 2 ;;
66
+ --help|-h) sed -n '2,/^set -euo/p' "$0" | sed '$d; s/^# \{0,1\}//'; exit 0 ;;
67
+ *) die "unknown option $1 (see --help)" ;;
68
+ esac
69
+ done
70
+
71
+ # The ouro CLI from the Butler image, run against the Butler's own files as the Butler's user.
72
+ ouro() {
73
+ docker run --rm --pull=never --network host --user 10001:10001 \
74
+ --mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
75
+ --mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
76
+ --entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@"
77
+ }
78
+ ouro_stdin() {
79
+ docker run --rm -i --pull=never --network host --user 10001:10001 \
80
+ --mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
81
+ --mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
82
+ --entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@"
83
+ }
84
+ ouro_interactive() {
85
+ docker run --rm -it --pull=never --network host --user 10001:10001 \
86
+ --mount "type=bind,src=$RUNTIME,dst=/home/ouro/.ouro-cli" \
87
+ --mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
88
+ --entrypoint node "$IMAGE" /opt/ouro/dist/heart/daemon/ouro-entry.js "$@" < "$TTY"
89
+ }
90
+
91
+ # Write a private file owned by the Butler's user from stdin.
92
+ write_butler_file() {
93
+ local path=$1
94
+ cat > "$path.tmp.$$"
95
+ chown 10001:10001 "$path.tmp.$$"
96
+ chmod 0600 "$path.tmp.$$"
97
+ mv -f "$path.tmp.$$" "$path"
98
+ }
99
+
100
+ # ---------------------------------------------------------------------------------------------------------------
101
+ say "1. checking this host"
102
+ test "$(id -u)" = 0 || die "run this as root (the Unraid web terminal is root)"
103
+ test -r "$TTY" || die "this installer needs a terminal for its questions; run it in the Unraid web terminal"
104
+ test -r /etc/unraid-version || die "this is not Unraid (no /etc/unraid-version)"
105
+ UNRAID_VERSION=$(sed -n 's/^version="\([0-9.]*\).*/\1/p' /etc/unraid-version)
106
+ IFS=. read -r UNRAID_MAJOR UNRAID_MINOR _ <<< "$UNRAID_VERSION"
107
+ if ((UNRAID_MAJOR < 7 || (UNRAID_MAJOR == 7 && UNRAID_MINOR < 2))); then die "Unraid $UNRAID_VERSION is too old; the Butler needs Unraid 7.2 or newer"; fi
108
+ ok "Unraid $UNRAID_VERSION"
109
+ command -v node >/dev/null || die "node is missing (Unraid 7.2 ships it at /usr/local/bin/node)"
110
+ command -v unraid-api >/dev/null || die "unraid-api is missing (Unraid 7.2 ships it)"
111
+ docker info >/dev/null 2>&1 || die "Docker is not running; start it in Settings > Docker"
112
+ ok "node, unraid-api and Docker are available"
113
+ ! docker container inspect "$CONTAINER" >/dev/null 2>&1 || die "an $CONTAINER container already exists; this installer is for a first install (upgrades use the Butler's own upgrade path)"
114
+ test ! -e "$AUTHORITY/active.json" || die "a Butler authority is already installed on this host"
115
+ ok "no Butler installed yet"
116
+
117
+ if test -z "$VERSION"; then
118
+ VERSION=$(node -e 'fetch("https://registry.npmjs.org/-/package/@ouro.bot/cli/dist-tags").then(r => r.json()).then(t => process.stdout.write(t.latest)).catch(() => process.exit(1))') \
119
+ || die "could not look up the newest Butler release; pass --version"
120
+ fi
121
+ [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.]+)?$ ]] || die "version $VERSION does not look like a release version"
122
+ IMAGE=$IMAGE_REPO:$VERSION
123
+ ok "installing Ouro Butler $VERSION"
124
+
125
+ # ---------------------------------------------------------------------------------------------------------------
126
+ say "2. a few questions"
127
+ printf 'The Butler lives on this server and talks to you on Telegram. You can change any name later in\n%s/house/house.json.\n\n' "$BUNDLE" > "$TTY"
128
+ ask OWNER_NAME "Your first name" ""
129
+ test -n "$OWNER_NAME" || die "a name is needed so the Butler knows who it works for"
130
+ ask BUTLER_NAME "What should the Butler call itself" "Butler"
131
+ ask HOUSEHOLD_NAME "A name for this household or server" "$(hostname)"
132
+ printf '\nThe Butler keeps its secrets in a Bitwarden-compatible vault. It gets its own vault account, so use an\nemail address no other Butler uses (for example you+butler@example.com). No mail is sent to it.\n' > "$TTY"
133
+ ask VAULT_EMAIL "Vault account email" ""
134
+ [[ "$VAULT_EMAIL" == *@*.* ]] || die "that does not look like an email address"
135
+ printf '\nThe Butler thinks with Anthropic models. Create an API key at https://console.anthropic.com/settings/keys\n' > "$TTY"
136
+ ask_secret ANTHROPIC_KEY "Anthropic API key"
137
+ [[ "$ANTHROPIC_KEY" == sk-ant-* ]] || die "Anthropic API keys start with sk-ant-"
138
+ printf '\nCreate a Telegram bot for the Butler: message @BotFather, send /newbot, and copy the token it gives you.\n' > "$TTY"
139
+ ask_secret BOT_TOKEN "Telegram bot token"
140
+ [[ "$BOT_TOKEN" =~ ^[0-9]+:[A-Za-z0-9_-]+$ ]] || die "that does not look like a Telegram bot token (digits, a colon, then letters)"
141
+ BOT_INFO=$(TOKEN="$BOT_TOKEN" node -e '
142
+ fetch(`https://api.telegram.org/bot${process.env.TOKEN}/getMe`).then(r => r.json()).then(b => {
143
+ if (!b.ok) process.exit(2)
144
+ process.stdout.write(`${b.result.id}\t${b.result.username}`)
145
+ }).catch(() => process.exit(1))') || die "Telegram did not accept that bot token"
146
+ BOT_USERNAME=${BOT_INFO#*$'\t'}
147
+ ok "Telegram knows the bot @$BOT_USERNAME"
148
+
149
+ # ---------------------------------------------------------------------------------------------------------------
150
+ say "3. Butler image and files"
151
+ docker pull "$IMAGE" >/dev/null || die "could not pull $IMAGE"
152
+ ok "pulled $IMAGE"
153
+ install -d -m 0700 -o 10001 -g 10001 "$APPDATA" "$APPDATA/runtime" "$APPDATA/agent" "$RUNTIME" "$BUNDLE"
154
+ install -d -m 0700 -o 0 -g 0 "$AUTHORITY" "$STAGE"
155
+ if test ! -f "$RUNTIME/machine.json"; then
156
+ NOW=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
157
+ printf '{\n "schemaVersion": 1,\n "machineId": "%s",\n "createdAt": "%s",\n "updatedAt": "%s",\n "hostnameAliases": []\n}\n' "$AGENT" "$NOW" "$NOW" | write_butler_file "$RUNTIME/machine.json"
158
+ fi
159
+ if test ! -f "$BUNDLE/agent.json"; then
160
+ test -z "$(find "$BUNDLE" -mindepth 1 -print -quit)" || die "$BUNDLE has files but no agent.json; move it aside and run the installer again"
161
+ docker run --rm --pull=never --network=none --user 10001:10001 \
162
+ --mount "type=bind,src=$BUNDLE,dst=/home/ouro/AgentBundles/$AGENT.ouro" \
163
+ --entrypoint /bin/sh "$IMAGE" -ceu '
164
+ cp -R /opt/ouro/deploy/unraid/sanctuary.ouro/. /home/ouro/AgentBundles/sanctuary.ouro/
165
+ find /home/ouro/AgentBundles/sanctuary.ouro -type d -exec chmod 0700 {} +
166
+ find /home/ouro/AgentBundles/sanctuary.ouro -type f -exec chmod 0600 {} +'
167
+ fi
168
+ ok "Butler files seeded in $BUNDLE"
169
+ install -d -m 0700 -o 10001 -g 10001 "$BUNDLE/house"
170
+ OWNER_NAME=$OWNER_NAME BUTLER_NAME=$BUTLER_NAME HOUSEHOLD_NAME=$HOUSEHOLD_NAME node -e '
171
+ const house = { ownerName: process.env.OWNER_NAME, butlerName: process.env.BUTLER_NAME, householdName: process.env.HOUSEHOLD_NAME, publicEndpoints: [], requiredContainers: [] }
172
+ process.stdout.write(`${JSON.stringify(house, null, 2)}\n`)' | write_butler_file "$BUNDLE/house/house.json"
173
+ if test ! -f "$BUNDLE/house/HOUSE.md"; then
174
+ printf '# %s\n\n%s owns this Unraid server and is the person %s works for.\n\nAdd anything the Butler should know about this household here: who lives here, what each container is for, what matters most. The Butler reads this file at the start of every conversation.\n' \
175
+ "$HOUSEHOLD_NAME" "$OWNER_NAME" "$BUTLER_NAME" | write_butler_file "$BUNDLE/house/HOUSE.md"
176
+ fi
177
+ ok "house description written to $BUNDLE/house"
178
+
179
+ ASSETS=ouro-butler-installer-assets
180
+ docker rm -f "$ASSETS" >/dev/null 2>&1 || true
181
+ docker create --name "$ASSETS" "$IMAGE" >/dev/null
182
+ docker cp "$ASSETS:/opt/ouro/deploy/unraid/sanctuary-butler-upgrade.mjs" "$STAGE/sanctuary-butler-upgrade.mjs" >/dev/null
183
+ docker cp "$ASSETS:/opt/ouro/deploy/unraid/ouro-events/bootstrap-spool.sh" "$STAGE/bootstrap-spool.sh" >/dev/null
184
+ docker rm -f "$ASSETS" >/dev/null
185
+ chown 0:0 "$STAGE"/*; chmod 0700 "$STAGE"/*
186
+ bash "$STAGE/bootstrap-spool.sh" --install-only
187
+ bash "$EVENTS/bootstrap-spool.sh" --mount
188
+ ok "event spool mounted and registered to mount at boot"
189
+
190
+ # ---------------------------------------------------------------------------------------------------------------
191
+ say "4. vault and model provider"
192
+ VAULT_STATUS=$(ouro vault status --agent "$AGENT" --store plaintext-file 2>&1 || true)
193
+ if [[ "$VAULT_STATUS" != *"local unlock: available"* ]]; then
194
+ printf 'Creating the vault. Choose an unlock phrase and keep it somewhere safe: it is the only way to recover\nthe Butler'"'"'s secrets if this server is lost.\n' > "$TTY"
195
+ ouro_interactive vault create --agent "$AGENT" --email "$VAULT_EMAIL" ${VAULT_SERVER:+--server "$VAULT_SERVER"} --store plaintext-file \
196
+ || die "vault creation did not finish; run the installer again to retry"
197
+ fi
198
+ ok "vault ready"
199
+ printf '%s' "$ANTHROPIC_KEY" | ouro_stdin auth --agent "$AGENT" --provider anthropic --api-key-file /dev/stdin >/dev/null \
200
+ || die "storing the Anthropic key failed"
201
+ unset ANTHROPIC_KEY
202
+ for LANE in outward inner; do
203
+ ouro check --agent "$AGENT" --lane "$LANE" >/dev/null 2>&1 || die "the $LANE model lane did not answer; check the Anthropic key and your account's credit"
204
+ done
205
+ ok "Anthropic key stored in the vault; both model lanes answer"
206
+
207
+ # ---------------------------------------------------------------------------------------------------------------
208
+ say "5. Unraid API access"
209
+ PORT=$(sed -n 's/^PORT="\{0,1\}\([0-9]*\)"\{0,1\}$/\1/p' /boot/config/ident.cfg 2>/dev/null | head -1)
210
+ GRAPHQL_URL="http://127.0.0.1${PORT:+$( [ "$PORT" = 80 ] || printf ':%s' "$PORT")}/graphql"
211
+ READ_PERMISSIONS="ARRAY:READ_ANY,DASHBOARD:READ_ANY,DISK:READ_ANY,DOCKER:READ_ANY,INFO:READ_ANY,LOGS:READ_ANY,NOTIFICATIONS:READ_ANY,SHARE:READ_ANY,VARS:READ_ANY"
212
+ STAMP=$(date +%Y%m%d%H%M%S)
213
+ create_unraid_key() { # create_unraid_key <name> <permissions> <vault field>
214
+ # Unraid 7.2's CLI refuses --permissions without a role ("Invalid data structure"); GUEST adds only own-profile access.
215
+ unraid-api apikey --create --name "$1" --roles GUEST --permissions "$2" --description "Ouro Butler $3" --json 2>/dev/null \
216
+ | node -e '
217
+ let text = ""; process.stdin.on("data", (c) => text += c).on("end", () => {
218
+ const start = text.indexOf("{"); if (start < 0) process.exit(1)
219
+ const key = JSON.parse(text.slice(start)).key; if (typeof key !== "string" || !key) process.exit(1)
220
+ process.stdout.write(key) })' \
221
+ | ouro_stdin vault config set --agent "$AGENT" --key "$3" --scope machine --value-file /dev/stdin >/dev/null \
222
+ || die "creating the Unraid API key $1 failed"
223
+ }
224
+ create_unraid_key "Butler RO $STAMP" "$READ_PERMISSIONS" unraidReadApiKey
225
+ create_unraid_key "Butler RW $STAMP" "$READ_PERMISSIONS,DOCKER:UPDATE_ANY" unraidWriteApiKey
226
+ ouro vault config set --agent "$AGENT" --key unraidGraphqlUrl --scope machine --value "$GRAPHQL_URL" >/dev/null
227
+ ok "API keys \"Butler RO $STAMP\" and \"Butler RW $STAMP\" created (see Settings > Management Access > API Keys)"
228
+
229
+ # ---------------------------------------------------------------------------------------------------------------
230
+ say "6. Telegram and the root authority"
231
+ test ! -L "$AUTHORITY/incoming-token" || die "$AUTHORITY/incoming-token is a link; remove it and run again"
232
+ printf '%s' "$BOT_TOKEN" > "$AUTHORITY/incoming-token.tmp.$$"
233
+ chmod 0600 "$AUTHORITY/incoming-token.tmp.$$"
234
+ mv -f "$AUTHORITY/incoming-token.tmp.$$" "$AUTHORITY/incoming-token"
235
+ unset BOT_TOKEN
236
+ printf '\nOpen Telegram, find @%s and send it any message (for example "hello"). Waiting up to 3 minutes...\n' "$BOT_USERNAME" > "$TTY"
237
+ OWNER_INFO=$(node -e '
238
+ const token = require("node:fs").readFileSync(process.argv[1], "utf8").trim()
239
+ const api = (method, query) => fetch(`https://api.telegram.org/bot${token}/${method}?${query}`).then((r) => r.json())
240
+ const deadline = Date.now() + 180000
241
+ ;(async () => {
242
+ while (Date.now() < deadline) {
243
+ const body = await api("getUpdates", "timeout=20&allowed_updates=%5B%22message%22%5D").catch(() => null)
244
+ const updates = body && body.ok ? body.result : []
245
+ const latest = updates.filter((u) => u.message && u.message.chat && u.message.chat.type === "private" && u.message.from).pop()
246
+ if (latest) {
247
+ await api("getUpdates", `offset=${latest.update_id + 1}&timeout=0`).catch(() => null)
248
+ const from = latest.message.from
249
+ process.stdout.write(`${from.id}\t${from.first_name || ""}${from.username ? ` (@${from.username})` : ""}`)
250
+ return
251
+ }
252
+ if (body && body.ok === false) { process.stderr.write(`Telegram: ${body.description}\n`); process.exit(2) }
253
+ }
254
+ process.exit(1)
255
+ })()' "$AUTHORITY/incoming-token") || die "no message reached the bot; run the installer again and message the bot when asked"
256
+ OWNER_ID=${OWNER_INFO%%$'\t'*}
257
+ confirm "The message came from ${OWNER_INFO#*$'\t'}. Is that you" || die "only the owner should message the bot during install; run the installer again"
258
+ ok "owner Telegram id found"
259
+
260
+ UPGRADE=(node "$STAGE/sanctuary-butler-upgrade.mjs")
261
+ "${UPGRADE[@]}" preflight "$VERSION" --fresh || die "preflight found a problem (above); nothing has been installed yet"
262
+ "${UPGRADE[@]}" prepare "$VERSION" --fresh --owner-id "$OWNER_ID" || die "prepare found a problem (above)"
263
+ LOG=/var/log/ouro-butler-install.log
264
+ printf 'Installing the authority and starting the Butler. This runs on even if this terminal closes; its log is %s.\n' "$LOG" > "$TTY"
265
+ setsid nohup "${UPGRADE[@]}" install "$VERSION" > "$LOG" 2>&1 < /dev/null &
266
+ INSTALL_PID=$!
267
+ tail -n +1 --pid="$INSTALL_PID" -f "$LOG"
268
+ wait "$INSTALL_PID" || die "install did not complete and was rolled back; the log is $LOG"
269
+ "${UPGRADE[@]}" verify || die "the Butler is installed but verify found a problem (above)"
270
+
271
+ say "done"
272
+ printf 'Ouro Butler %s is running. Say hello to @%s on Telegram.\n' "$VERSION" "$BOT_USERNAME"
273
+ printf 'Tell it about your household in %s/house/HOUSE.md.\n' "$BUNDLE"
274
+ printf 'Keep the vault unlock phrase you chose somewhere safe.\n'
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import * as path from "node:path"
3
+ import { pathToFileURL } from "node:url"
4
+
5
+ const USAGE = "Usage: migrate-sanctuary-bundle.mjs --package-root <path> --agent-root <path> --operation <migrate|seed|rollback|finalize-rollback|commit|status|inspect> [--rollback-image-id <sha256:id> --target-image-id <sha256:id>]"
6
+ const BASE_KEYS = ["--package-root", "--agent-root", "--operation"]
7
+ const MIGRATE_KEYS = [...BASE_KEYS, "--rollback-image-id", "--target-image-id"]
8
+
9
+ function parseArguments(args) {
10
+ if (args.length % 2 !== 0) throw new Error(USAGE)
11
+ const values = new Map()
12
+ for (let index = 0; index < args.length; index += 2) {
13
+ const key = args[index]
14
+ const value = args[index + 1]
15
+ if (values.has(key) || typeof value !== "string" || value.length === 0) throw new Error(USAGE)
16
+ values.set(key, value)
17
+ }
18
+ const operation = values.get("--operation")
19
+ if (!["migrate", "seed", "rollback", "finalize-rollback", "commit", "status", "inspect"].includes(operation)) throw new Error(USAGE)
20
+ const expectedKeys = operation === "migrate" ? MIGRATE_KEYS : BASE_KEYS
21
+ if (values.size !== expectedKeys.length || expectedKeys.some((key) => !values.has(key)) || [...values.keys()].some((key) => !expectedKeys.includes(key))) throw new Error(USAGE)
22
+ return values
23
+ }
24
+
25
+ export function runSanctuaryBundleOperation(args, dependencies) {
26
+ const values = parseArguments(args)
27
+ const packageRoot = values.get("--package-root")
28
+ const agentRoot = values.get("--agent-root")
29
+ const operation = values.get("--operation")
30
+ const result = operation === "migrate"
31
+ ? dependencies.migrate({ packageRoot, agentRoot, retainRollback: true, rollbackImageId: values.get("--rollback-image-id"), targetImageId: values.get("--target-image-id") })
32
+ // A fresh install has no earlier image to roll back to, so it writes the packaged files without a rollback record.
33
+ : operation === "seed"
34
+ ? dependencies.migrate({ packageRoot, agentRoot, retainRollback: false })
35
+ : operation === "rollback"
36
+ ? { rolledBack: dependencies.rollback(agentRoot, { retainRecord: true }) }
37
+ // `rollback` keeps crash-retry evidence; the host uses `finalize-rollback` only after old production is audited, ready, and restored to autostart.
38
+ : operation === "finalize-rollback"
39
+ ? { rolledBack: dependencies.rollback(agentRoot, { retainRecord: false }) }
40
+ : operation === "commit"
41
+ ? { committed: dependencies.commit(agentRoot) }
42
+ : operation === "status"
43
+ ? dependencies.status(agentRoot)
44
+ : dependencies.inspect({ packageRoot, agentRoot, runtimePackageVersion: dependencies.getPackageVersion() })
45
+ if (result === null || ("rolledBack" in result && !result.rolledBack) || ("committed" in result && !result.committed)) throw new Error(`${operation} found no pending Sanctuary bundle transaction`)
46
+ return result
47
+ }
48
+
49
+ export async function runSanctuaryBundleCli(args = process.argv.slice(2), output = process.stdout) {
50
+ const migration = await import("../../dist/heart/daemon/sanctuary-bundle-migration.js")
51
+ const manifest = await import("../../dist/mind/bundle-manifest.js")
52
+ const result = runSanctuaryBundleOperation(args, {
53
+ commit: migration.commitSanctuaryPackageManagedBundle,
54
+ getPackageVersion: manifest.getPackageVersion,
55
+ inspect: migration.inspectSanctuaryPackageManagedBundle,
56
+ migrate: migration.migrateSanctuaryPackageManagedBundle,
57
+ rollback: migration.rollbackSanctuaryPackageManagedBundle,
58
+ status: migration.inspectSanctuaryPackageManagedBundleRollback,
59
+ })
60
+ output.write(`${JSON.stringify(result)}\n`)
61
+ }
62
+
63
+ if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) await runSanctuaryBundleCli()
@@ -0,0 +1,92 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ SPOOL_ROOT="/boot/config/custom/ouro-events/spool"
5
+ INSTALL_PATH="/boot/config/custom/ouro-events/bootstrap-spool.sh"
6
+ GO_FILE="/boot/config/go"
7
+ TMPFS_OPTIONS="size=4m,mode=0755,uid=0,gid=0,nodev,nosuid,noexec"
8
+ BOOT_HOOK="/bin/bash /boot/config/custom/ouro-events/bootstrap-spool.sh --mount"
9
+ ACTION="mount"
10
+
11
+ while (($# > 0)); do
12
+ case "$1" in
13
+ --mount|--install-only|--self-test) ACTION="${1#--}"; shift ;;
14
+ --go-file) GO_FILE="${2:?missing --go-file value}"; shift 2 ;;
15
+ --install-path) INSTALL_PATH="${2:?missing --install-path value}"; shift 2 ;;
16
+ *) echo "ouro event spool bootstrap: invalid argument: $1" >&2; exit 2 ;;
17
+ esac
18
+ done
19
+
20
+ mount_spool() {
21
+ local target="$1"
22
+ /bin/mkdir -p "$target"
23
+ /bin/chown 0:0 "$target"
24
+ /bin/chmod 0755 "$target"
25
+ if /bin/mountpoint -q "$target"; then
26
+ [[ "$(/bin/findmnt -n -o FSTYPE --target "$target")" == "tmpfs" ]] || { echo "ouro event spool bootstrap: canonical path is already a non-tmpfs mount" >&2; return 1; }
27
+ else
28
+ /bin/mount -t tmpfs -o "$TMPFS_OPTIONS" ouro-events-spool "$target"
29
+ fi
30
+ [[ "$(/bin/stat -c '%u:%g:%a' "$target")" == "0:0:755" ]] || { echo "ouro event spool bootstrap: tmpfs identity or mode is unsafe" >&2; return 1; }
31
+ local options
32
+ options="$(/bin/findmnt -n -o OPTIONS --target "$target")"
33
+ for required in nodev nosuid noexec; do
34
+ [[ ",$options," == *",$required,"* ]] || { echo "ouro event spool bootstrap: tmpfs is missing $required" >&2; return 1; }
35
+ done
36
+ local size_bytes
37
+ size_bytes="$(/bin/findmnt -bn -o SIZE --target "$target")"
38
+ [[ "$size_bytes" =~ ^[0-9]+$ && "$size_bytes" -le 4194304 ]] || { echo "ouro event spool bootstrap: tmpfs exceeds its 4 MiB bound" >&2; return 1; }
39
+ }
40
+
41
+ install_boot_hook() {
42
+ local install_dir resolved_source resolved_install
43
+ install_dir="$(dirname "$INSTALL_PATH")"
44
+ /bin/mkdir -p "$install_dir"
45
+ resolved_source="$(cd "$(dirname "$0")" && pwd -P)/$(basename "$0")"
46
+ resolved_install="$(cd "$install_dir" && pwd -P)/$(basename "$INSTALL_PATH")"
47
+ if [[ "$resolved_source" != "$resolved_install" ]]; then
48
+ install -m 0700 "$0" "$INSTALL_PATH"
49
+ else
50
+ /bin/chmod 0700 "$INSTALL_PATH"
51
+ fi
52
+ [[ -f "$GO_FILE" ]] || printf '#!/bin/bash\n' > "$GO_FILE"
53
+ if ! grep -Fqx "$BOOT_HOOK" "$GO_FILE"; then
54
+ local temporary="${GO_FILE}.ouro-events.$$"
55
+ awk -v hook="$BOOT_HOOK" 'NR == 1 && /^#!/ { print; print hook; next } NR == 1 { print hook } { print }' "$GO_FILE" > "$temporary"
56
+ /bin/chmod 0700 "$temporary"
57
+ /bin/mv "$temporary" "$GO_FILE"
58
+ fi
59
+ }
60
+
61
+ self_test() {
62
+ [[ "$(/usr/bin/id -u)" == "0" ]] || { echo "ouro event spool bootstrap self-test requires root" >&2; return 1; }
63
+ local test_root target readonly_view
64
+ test_root="$(/usr/bin/mktemp -d /tmp/ouro-event-spool.XXXXXX)"
65
+ target="$test_root/spool"
66
+ readonly_view="$test_root/readonly"
67
+ /bin/chmod 0755 "$test_root"
68
+ /bin/mkdir "$target" "$readonly_view"
69
+ cleanup() {
70
+ /bin/umount "$readonly_view" 2>/dev/null || true
71
+ /bin/umount "$target" 2>/dev/null || true
72
+ /bin/rmdir "$readonly_view" "$target" "$test_root" 2>/dev/null || true
73
+ }
74
+ trap cleanup EXIT
75
+ mount_spool "$target"
76
+ /usr/bin/printf 'probe\n' > "$target/probe"
77
+ /bin/chown 0:0 "$target/probe"
78
+ /bin/chmod 0444 "$target/probe"
79
+ /bin/mount --bind "$target" "$readonly_view"
80
+ /bin/mount -o remount,bind,ro,nodev,nosuid,noexec "$readonly_view"
81
+ /usr/bin/setpriv --reuid=10001 --regid=10001 --clear-groups /usr/bin/test -r "$readonly_view/probe"
82
+ [[ ",$(/bin/findmnt -n -o OPTIONS --target "$readonly_view")," == *",ro,"* ]] || { echo "ouro event spool bootstrap: test bind is not read-only" >&2; return 1; }
83
+ echo "uid10001-ro-bind: pass"
84
+ cleanup
85
+ trap - EXIT
86
+ }
87
+
88
+ case "$ACTION" in
89
+ mount) mount_spool "$SPOOL_ROOT" ;;
90
+ install-only) install_boot_hook ;;
91
+ self-test) self_test ;;
92
+ esac