@ouro.bot/cli 0.1.0-alpha.99 → 0.1.0-alpha.991

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 (777) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -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 +6257 -16
  16. package/deploy/unraid/Dockerfile +71 -0
  17. package/deploy/unraid/INSTALL.md +64 -0
  18. package/deploy/unraid/README.txt +3032 -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/github_known_hosts +3 -0
  25. package/deploy/unraid/install.sh +274 -0
  26. package/deploy/unraid/migrate-sanctuary-bundle.mjs +63 -0
  27. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  28. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  29. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  30. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  31. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  32. package/deploy/unraid/ouro-sync-ssh +98 -0
  33. package/deploy/unraid/ouro-sync.sudoers +3 -0
  34. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  35. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  36. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  37. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  38. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  39. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1523 -0
  40. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  41. package/deploy/unraid/sanctuary-replay-gate.mjs +2467 -0
  42. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  43. package/deploy/unraid/sanctuary-sync-cutover.sh +1039 -0
  44. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2088 -0
  45. package/deploy/unraid/sanctuary-unit16-run.sh +570 -0
  46. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  47. package/deploy/unraid/sanctuary.ouro/agent.json +67 -0
  48. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  49. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  50. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  51. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  52. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2255 -0
  53. package/deploy/unraid/sanctuary.ouro/product/PRODUCT.md +13 -0
  54. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  55. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  56. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +7 -0
  57. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +7 -0
  58. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +15 -0
  59. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +3 -0
  60. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  61. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +234 -0
  62. package/deploy/unraid/sanctuary.xml +30 -0
  63. package/dist/a2a/card.js +57 -0
  64. package/dist/a2a/client.js +290 -0
  65. package/dist/a2a/config.js +50 -0
  66. package/dist/a2a/delegated-command-grants.js +93 -0
  67. package/dist/a2a/delegated-command.js +197 -0
  68. package/dist/a2a/delegation-stores.js +56 -0
  69. package/dist/a2a/did-resolution.js +205 -0
  70. package/dist/a2a/escalation-grants.js +84 -0
  71. package/dist/a2a/escalation-wiring.js +60 -0
  72. package/dist/a2a/identity.js +258 -0
  73. package/dist/a2a/inbound-share.js +131 -0
  74. package/dist/a2a/mission-result-wire.js +265 -0
  75. package/dist/a2a/onboarding.js +133 -0
  76. package/dist/a2a/operator-trust.js +399 -0
  77. package/dist/a2a/outbox-client.js +59 -0
  78. package/dist/a2a/outbox-store.js +188 -0
  79. package/dist/a2a/outbox-wire.js +106 -0
  80. package/dist/a2a/pin-store.js +167 -0
  81. package/dist/a2a/refusals.js +53 -0
  82. package/dist/a2a/relay-client.js +106 -0
  83. package/dist/a2a/relay-config-vault.js +64 -0
  84. package/dist/a2a/relay-contacts.js +120 -0
  85. package/dist/a2a/relay-inbox.js +360 -0
  86. package/dist/a2a/relay-retirements.js +89 -0
  87. package/dist/a2a/replay-grant-holders.js +33 -0
  88. package/dist/a2a/replay-harness.js +188 -0
  89. package/dist/a2a/resolution-proof.js +53 -0
  90. package/dist/a2a/sealed-chat.js +114 -0
  91. package/dist/a2a/seen-ledger.js +214 -0
  92. package/dist/a2a/server.js +808 -0
  93. package/dist/a2a/task-store.js +69 -0
  94. package/dist/a2a/transport.js +100 -0
  95. package/dist/a2a/trust-commands.js +203 -0
  96. package/dist/a2a/trusted-files.js +185 -0
  97. package/dist/a2a/types.js +3 -0
  98. package/dist/arc/attention-types.js +8 -0
  99. package/dist/arc/cares.js +360 -0
  100. package/dist/arc/episodes.js +118 -0
  101. package/dist/arc/evolution.js +490 -0
  102. package/dist/arc/flight-recorder.js +1034 -0
  103. package/dist/arc/intentions.js +134 -0
  104. package/dist/arc/json-store.js +117 -0
  105. package/dist/arc/obligations.js +386 -0
  106. package/dist/arc/packets.js +336 -0
  107. package/dist/arc/presence.js +185 -0
  108. package/dist/arc/task-lifecycle.js +57 -0
  109. package/dist/commerce/store.js +755 -0
  110. package/dist/commerce/types.js +3 -0
  111. package/dist/gateway/keys.js +117 -0
  112. package/dist/gateway/server.js +429 -0
  113. package/dist/heart/active-work.js +798 -40
  114. package/dist/heart/agent-entry.js +252 -3
  115. package/dist/heart/approval-files.js +113 -0
  116. package/dist/heart/approval-store.js +960 -0
  117. package/dist/heart/attachments/image-normalize.js +201 -0
  118. package/dist/heart/attachments/materialize.js +97 -0
  119. package/dist/heart/attachments/originals.js +88 -0
  120. package/dist/heart/attachments/render.js +29 -0
  121. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  122. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  123. package/dist/heart/attachments/sources/index.js +18 -0
  124. package/dist/heart/attachments/sources/telegram.js +71 -0
  125. package/dist/heart/attachments/store.js +132 -0
  126. package/dist/heart/attachments/types.js +93 -0
  127. package/dist/heart/auth/auth-flow.js +511 -0
  128. package/dist/heart/autonomy-budget.js +478 -0
  129. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  130. package/dist/heart/awaiting/await-alert.js +152 -0
  131. package/dist/heart/awaiting/await-expiry.js +143 -0
  132. package/dist/heart/awaiting/await-loader.js +91 -0
  133. package/dist/heart/awaiting/await-parser.js +152 -0
  134. package/dist/heart/awaiting/await-runtime-state.js +130 -0
  135. package/dist/heart/awaiting/await-scheduler.js +391 -0
  136. package/dist/heart/background-operations.js +281 -0
  137. package/dist/heart/bluebubbles-host-account.js +78 -0
  138. package/dist/heart/bridges/manager.js +137 -17
  139. package/dist/heart/bridges/store.js +14 -2
  140. package/dist/heart/bundle-state.js +168 -0
  141. package/dist/heart/commitments.js +44 -18
  142. package/dist/heart/config-registry.js +331 -0
  143. package/dist/heart/config.js +179 -131
  144. package/dist/heart/context-loss-gauntlet.js +387 -0
  145. package/dist/heart/context-loss-sentinel.js +1204 -0
  146. package/dist/heart/core.js +2378 -586
  147. package/dist/heart/cross-chat-delivery.js +9 -22
  148. package/dist/heart/daemon/agent-config-check.js +474 -0
  149. package/dist/heart/daemon/agent-discovery.js +287 -3
  150. package/dist/heart/daemon/agent-home.js +355 -0
  151. package/dist/heart/daemon/agent-service.js +542 -0
  152. package/dist/heart/daemon/agentic-repair.js +547 -0
  153. package/dist/heart/daemon/await-private-wake.js +59 -0
  154. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  155. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  156. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  157. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  158. package/dist/heart/daemon/boot-sync-probe.js +223 -0
  159. package/dist/heart/daemon/cadence.js +180 -0
  160. package/dist/heart/daemon/cli-arg-redaction.js +26 -0
  161. package/dist/heart/daemon/cli-defaults.js +881 -0
  162. package/dist/heart/daemon/cli-desk.js +331 -0
  163. package/dist/heart/daemon/cli-exec.js +9339 -0
  164. package/dist/heart/daemon/cli-help.js +766 -0
  165. package/dist/heart/daemon/cli-parse.js +3343 -0
  166. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  167. package/dist/heart/daemon/cli-render.js +819 -0
  168. package/dist/heart/daemon/cli-types.js +8 -0
  169. package/dist/heart/daemon/connect-bay.js +323 -0
  170. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  171. package/dist/heart/daemon/container-healthcheck.js +112 -0
  172. package/dist/heart/daemon/container-runtime.js +97 -0
  173. package/dist/heart/daemon/container-spec-auditor-main.js +187 -0
  174. package/dist/heart/daemon/container-spec-auditor.js +257 -0
  175. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  176. package/dist/heart/daemon/daemon-cli.js +29 -2373
  177. package/dist/heart/daemon/daemon-entry.js +975 -11
  178. package/dist/heart/daemon/daemon-health.js +186 -0
  179. package/dist/heart/daemon/daemon-rollup.js +57 -0
  180. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  181. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  182. package/dist/heart/daemon/daemon.js +2110 -104
  183. package/dist/heart/daemon/desk-admin.js +420 -0
  184. package/dist/heart/daemon/dns-workflow.js +394 -0
  185. package/dist/heart/daemon/doctor-types.js +8 -0
  186. package/dist/heart/daemon/doctor.js +1766 -0
  187. package/dist/heart/daemon/freshness.js +345 -0
  188. package/dist/heart/daemon/habit-private-wake.js +61 -0
  189. package/dist/heart/daemon/health-monitor.js +154 -11
  190. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  191. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  192. package/dist/heart/daemon/http-health-probe.js +80 -0
  193. package/dist/heart/daemon/human-command-screens.js +234 -0
  194. package/dist/heart/daemon/human-readiness.js +114 -0
  195. package/dist/heart/daemon/inner-status.js +78 -0
  196. package/dist/heart/daemon/interactive-repair.js +394 -0
  197. package/dist/heart/daemon/launchd.js +37 -8
  198. package/dist/heart/daemon/log-tailer.js +79 -10
  199. package/dist/heart/daemon/logs-prune.js +132 -0
  200. package/dist/heart/daemon/mcp-canary.js +524 -0
  201. package/dist/heart/daemon/message-router.js +65 -5
  202. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  203. package/dist/heart/daemon/os-cron-deps.js +135 -0
  204. package/dist/heart/daemon/os-cron.js +22 -14
  205. package/dist/heart/daemon/ouro-bot-entry.js +6 -3
  206. package/dist/heart/daemon/ouro-entry.js +9 -3
  207. package/dist/heart/daemon/plugin-cli.js +432 -0
  208. package/dist/heart/daemon/process-manager.js +760 -61
  209. package/dist/heart/daemon/provider-discovery.js +137 -0
  210. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  211. package/dist/heart/daemon/prunable-bundle.js +144 -0
  212. package/dist/heart/daemon/pulse.js +511 -0
  213. package/dist/heart/daemon/readiness-repair.js +365 -0
  214. package/dist/heart/daemon/run-hooks.js +2 -0
  215. package/dist/heart/daemon/runtime-logging.js +47 -14
  216. package/dist/heart/daemon/runtime-metadata.js +2 -30
  217. package/dist/heart/daemon/runtime-mode.js +13 -2
  218. package/dist/heart/daemon/safe-mode.js +161 -0
  219. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2662 -0
  220. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1832 -0
  221. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  222. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +956 -0
  223. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  224. package/dist/heart/daemon/sanctuary-authority-epoch.js +291 -0
  225. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  226. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  227. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1332 -0
  228. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  229. package/dist/heart/daemon/sanctuary-bundle-migration.js +974 -0
  230. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  231. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  232. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  233. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  234. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  235. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  236. package/dist/heart/daemon/sanctuary-package-management.js +113 -0
  237. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  238. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  239. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  240. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  241. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  242. package/dist/heart/daemon/sense-manager.js +786 -48
  243. package/dist/heart/daemon/session-id-resolver.js +131 -0
  244. package/dist/heart/daemon/skill-management-installer.js +1 -1
  245. package/dist/heart/daemon/socket-client.js +180 -12
  246. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  247. package/dist/heart/daemon/startup-tui.js +339 -0
  248. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  249. package/dist/heart/daemon/task-scheduler.js +117 -39
  250. package/dist/heart/daemon/terminal-ui.js +503 -0
  251. package/dist/heart/daemon/thoughts.js +138 -54
  252. package/dist/heart/daemon/up-progress.js +366 -0
  253. package/dist/heart/daemon/vault-items.js +56 -0
  254. package/dist/heart/delegation.js +1 -4
  255. package/dist/heart/external-events/router.js +1531 -0
  256. package/dist/heart/failure-reports.js +336 -0
  257. package/dist/heart/file-lock.js +109 -0
  258. package/dist/heart/frontend-approval-runtime.js +506 -0
  259. package/dist/heart/frontend-journal.js +215 -0
  260. package/dist/heart/frontend-session-service.js +271 -0
  261. package/dist/heart/frontend-socket-client.js +173 -0
  262. package/dist/heart/frontend-socket.js +434 -0
  263. package/dist/heart/frontend-turn-errors.js +20 -0
  264. package/dist/heart/habits/habit-cancel.js +810 -0
  265. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  266. package/dist/heart/habits/habit-migration.js +194 -0
  267. package/dist/heart/habits/habit-parser.js +278 -0
  268. package/dist/heart/habits/habit-runtime-state.js +93 -0
  269. package/dist/heart/habits/habit-scheduler.js +653 -0
  270. package/dist/heart/habits/habit-session-summary.js +318 -0
  271. package/dist/heart/habits/habit-session.js +636 -0
  272. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  273. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  274. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  275. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  276. package/dist/heart/identity.js +239 -59
  277. package/dist/heart/kept-notes.js +289 -0
  278. package/dist/heart/kicks.js +1 -1
  279. package/dist/heart/machine-identity.js +175 -0
  280. package/dist/heart/mail-import-discovery.js +356 -0
  281. package/dist/heart/mailbox/mailbox-http-hooks.js +99 -0
  282. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  283. package/dist/heart/mailbox/mailbox-http-routes.js +406 -0
  284. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  285. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  286. package/dist/heart/mailbox/mailbox-http.js +99 -0
  287. package/dist/heart/mailbox/mailbox-read.js +41 -0
  288. package/dist/heart/mailbox/mailbox-supervision.js +131 -0
  289. package/dist/heart/mailbox/mailbox-types.js +27 -0
  290. package/dist/heart/mailbox/mailbox-view.js +197 -0
  291. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  292. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  293. package/dist/heart/mailbox/readers/mail.js +375 -0
  294. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  295. package/dist/heart/mailbox/readers/sessions.js +231 -0
  296. package/dist/heart/mailbox/readers/shared.js +111 -0
  297. package/dist/heart/mcp/mcp-server.js +760 -0
  298. package/dist/heart/migrate-config.js +100 -0
  299. package/dist/heart/model-capabilities.js +83 -16
  300. package/dist/heart/orientation-frame.js +376 -0
  301. package/dist/heart/platform.js +81 -0
  302. package/dist/heart/primitives.js +1 -1
  303. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  304. package/dist/heart/private-runtime/index.js +18 -0
  305. package/dist/heart/private-runtime/ledger.js +221 -0
  306. package/dist/heart/private-runtime/policy.js +260 -0
  307. package/dist/heart/private-runtime/types.js +2 -0
  308. package/dist/heart/progress-story.js +1 -1
  309. package/dist/heart/provider-attempt.js +137 -0
  310. package/dist/heart/provider-binding-resolver.js +273 -0
  311. package/dist/heart/provider-credentials.js +449 -0
  312. package/dist/heart/provider-failover.js +311 -0
  313. package/dist/heart/provider-models.js +96 -0
  314. package/dist/heart/provider-ping.js +266 -0
  315. package/dist/heart/provider-readiness-cache.js +119 -0
  316. package/dist/heart/provider-visibility.js +188 -0
  317. package/dist/heart/providers/anthropic-token.js +131 -0
  318. package/dist/heart/providers/anthropic.js +248 -67
  319. package/dist/heart/providers/azure.js +23 -11
  320. package/dist/heart/providers/error-classification.js +129 -0
  321. package/dist/heart/providers/github-copilot.js +38 -39
  322. package/dist/heart/providers/minimax-vlm.js +189 -0
  323. package/dist/heart/providers/minimax.js +26 -8
  324. package/dist/heart/providers/openai-codex-token.js +349 -0
  325. package/dist/heart/providers/openai-codex.js +55 -40
  326. package/dist/heart/providers/openai-compatible.js +177 -0
  327. package/dist/heart/reach-channel.js +85 -0
  328. package/dist/heart/reply-style.js +52 -0
  329. package/dist/heart/run-ledger.js +247 -0
  330. package/dist/heart/runtime-capability-check.js +170 -0
  331. package/dist/heart/runtime-credentials.js +608 -0
  332. package/dist/heart/runtime-cwd.js +87 -0
  333. package/dist/heart/sense-truth.js +24 -4
  334. package/dist/heart/session-activity.js +94 -24
  335. package/dist/heart/session-events.js +1521 -0
  336. package/dist/heart/session-playback-cli-main.js +5 -0
  337. package/dist/heart/session-playback-cli.js +36 -0
  338. package/dist/heart/session-playback.js +231 -0
  339. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  340. package/dist/heart/session-redaction-repair.js +552 -0
  341. package/dist/heart/session-stats-cli-main.js +5 -0
  342. package/dist/heart/session-stats.js +183 -0
  343. package/dist/heart/session-transcript.js +133 -0
  344. package/dist/heart/shelf-claims.js +78 -0
  345. package/dist/heart/shepherd/custody-types.js +2 -0
  346. package/dist/heart/shepherd/mandates.js +352 -0
  347. package/dist/heart/shepherd/operation-commands.js +19 -0
  348. package/dist/heart/shepherd/operations.js +135 -0
  349. package/dist/heart/shepherd/supervision.js +114 -0
  350. package/dist/heart/shepherd/types.js +2 -0
  351. package/dist/heart/shepherd-config.js +123 -0
  352. package/dist/heart/source-grounding.js +313 -0
  353. package/dist/heart/start-of-turn-packet.js +372 -0
  354. package/dist/heart/steward-policy.js +656 -0
  355. package/dist/heart/streaming.js +631 -207
  356. package/dist/heart/structured-output.js +196 -0
  357. package/dist/heart/sync-classification.js +176 -0
  358. package/dist/heart/sync-health.js +152 -0
  359. package/dist/heart/sync-lock.js +431 -0
  360. package/dist/heart/sync.js +1579 -0
  361. package/dist/heart/target-resolution.js +11 -7
  362. package/dist/heart/tempo.js +93 -0
  363. package/dist/heart/temporal-view.js +41 -0
  364. package/dist/heart/timeouts.js +101 -0
  365. package/dist/heart/tool-activity-callbacks.js +59 -0
  366. package/dist/heart/tool-approval.js +382 -0
  367. package/dist/heart/tool-description.js +155 -0
  368. package/dist/heart/tool-friction.js +55 -0
  369. package/dist/heart/tool-loop.js +206 -0
  370. package/dist/heart/tool-output-budget.js +41 -0
  371. package/dist/heart/turn-context.js +496 -0
  372. package/dist/heart/turn-execution-lease.js +30 -0
  373. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  374. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
  375. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  376. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  377. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  378. package/dist/heart/versioning/release-sources.js +173 -0
  379. package/dist/heart/versioning/self-update-defaults.js +294 -0
  380. package/dist/heart/versioning/self-update.js +196 -0
  381. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  382. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  383. package/dist/heart/versioning/update-hooks.js +154 -0
  384. package/dist/heart/versioning/update-state.js +126 -0
  385. package/dist/heart/versioning/updater-launchd.js +150 -0
  386. package/dist/heart/versioning/version-intent.js +114 -0
  387. package/dist/heart/work-card.js +380 -0
  388. package/dist/mailbox-ui/assets/index-Dbska1tZ.js +1 -0
  389. package/dist/mailbox-ui/assets/index-DsiKaPyH.css +1 -0
  390. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  391. package/dist/mailbox-ui/index.html +16 -0
  392. package/dist/mailroom/attention.js +167 -0
  393. package/dist/mailroom/autonomy.js +209 -0
  394. package/dist/mailroom/blob-store.js +889 -0
  395. package/dist/mailroom/body-cache.js +61 -0
  396. package/dist/mailroom/cache-sync-cli.js +58 -0
  397. package/dist/mailroom/core.js +803 -0
  398. package/dist/mailroom/entry.js +160 -0
  399. package/dist/mailroom/file-store.js +568 -0
  400. package/dist/mailroom/hosted-cache-sync.js +384 -0
  401. package/dist/mailroom/mbox-import.js +393 -0
  402. package/dist/mailroom/migration.js +164 -0
  403. package/dist/mailroom/outbound.js +380 -0
  404. package/dist/mailroom/policy.js +263 -0
  405. package/dist/mailroom/reader.js +292 -0
  406. package/dist/mailroom/search-cache.js +513 -0
  407. package/dist/mailroom/search-relevance.js +319 -0
  408. package/dist/mailroom/smtp-ingress.js +176 -0
  409. package/dist/mailroom/source-state.js +176 -0
  410. package/dist/mailroom/thread.js +109 -0
  411. package/dist/mailroom/travel-extract.js +89 -0
  412. package/dist/mind/bundle-manifest.js +25 -2
  413. package/dist/mind/context.js +328 -139
  414. package/dist/mind/desk-section.js +362 -0
  415. package/dist/mind/diary-integrity.js +60 -0
  416. package/dist/mind/{memory.js → diary.js} +68 -77
  417. package/dist/mind/embedding-provider.js +60 -0
  418. package/dist/mind/file-state.js +179 -0
  419. package/dist/mind/friend-link-codes.js +209 -0
  420. package/dist/mind/friend-merge.js +336 -0
  421. package/dist/mind/house-names.js +43 -0
  422. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  423. package/dist/mind/obligation-steering.js +199 -3
  424. package/dist/mind/outbound-record.js +168 -0
  425. package/dist/mind/pending.js +36 -10
  426. package/dist/mind/prompt-budget.js +479 -0
  427. package/dist/mind/prompt-refresh.js +3 -2
  428. package/dist/mind/prompt.js +1222 -203
  429. package/dist/mind/provenance-trust.js +26 -0
  430. package/dist/mind/record-paths.js +312 -0
  431. package/dist/mind/scrutiny.js +173 -0
  432. package/dist/mind/session-transaction.js +622 -0
  433. package/dist/nerves/cli-logging.js +7 -1
  434. package/dist/nerves/coverage/audit-rules.js +15 -6
  435. package/dist/nerves/coverage/audit.js +28 -2
  436. package/dist/nerves/coverage/cli.js +1 -1
  437. package/dist/nerves/coverage/contract.js +5 -5
  438. package/dist/nerves/coverage/file-completeness.js +143 -5
  439. package/dist/nerves/coverage/run-artifacts.js +55 -35
  440. package/dist/nerves/coverage/source-scanner.js +4 -4
  441. package/dist/nerves/event-buffer.js +111 -0
  442. package/dist/nerves/index.js +293 -9
  443. package/dist/nerves/observation.js +20 -0
  444. package/dist/nerves/redact.js +79 -0
  445. package/dist/nerves/review/cli-main.js +5 -0
  446. package/dist/nerves/review/cli.js +156 -0
  447. package/dist/nerves/review/core.js +159 -0
  448. package/dist/nerves/runtime.js +17 -1
  449. package/dist/repertoire/ado-client.js +15 -56
  450. package/dist/repertoire/ado-semantic.js +16 -10
  451. package/dist/repertoire/api-client.js +97 -0
  452. package/dist/repertoire/bitwarden-store.js +1199 -0
  453. package/dist/repertoire/bundle-templates.js +71 -0
  454. package/dist/repertoire/bw-installer.js +231 -0
  455. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  456. package/dist/repertoire/coding/context-pack.js +331 -0
  457. package/dist/repertoire/coding/feedback.js +146 -34
  458. package/dist/repertoire/coding/index.js +15 -3
  459. package/dist/repertoire/coding/manager.js +159 -10
  460. package/dist/repertoire/coding/spawner.js +40 -11
  461. package/dist/repertoire/coding/tools.js +182 -18
  462. package/dist/repertoire/coding/workbench-client.js +272 -0
  463. package/dist/repertoire/coding/workbench-manager.js +346 -0
  464. package/dist/repertoire/commerce-errors.js +109 -0
  465. package/dist/repertoire/commerce-self-test.js +156 -0
  466. package/dist/repertoire/credential-access.js +183 -0
  467. package/dist/repertoire/desk/classifier.js +362 -0
  468. package/dist/repertoire/duffel-client.js +185 -0
  469. package/dist/repertoire/github-client.js +14 -55
  470. package/dist/repertoire/graph-client.js +11 -52
  471. package/dist/repertoire/guardrails.js +1480 -22
  472. package/dist/repertoire/house-sweep.js +471 -0
  473. package/dist/repertoire/mcp-client.js +58 -5
  474. package/dist/repertoire/mcp-manager.js +427 -139
  475. package/dist/repertoire/mcp-tools.js +132 -0
  476. package/dist/repertoire/mcp-write-guard.js +46 -0
  477. package/dist/repertoire/plugin-mcp.js +175 -0
  478. package/dist/repertoire/plugins.js +253 -0
  479. package/dist/repertoire/relationship-authorization.js +322 -0
  480. package/dist/repertoire/sanctuary-container-policy.js +50 -0
  481. package/dist/repertoire/shell-sessions.js +134 -0
  482. package/dist/repertoire/skills.js +48 -4
  483. package/dist/repertoire/stripe-client.js +131 -0
  484. package/dist/repertoire/tool-arguments.js +182 -0
  485. package/dist/repertoire/tool-results.js +29 -0
  486. package/dist/repertoire/tools-a2a.js +742 -0
  487. package/dist/repertoire/tools-attachments.js +322 -0
  488. package/dist/repertoire/tools-awaiting.js +897 -0
  489. package/dist/repertoire/tools-base.js +83 -1168
  490. package/dist/repertoire/tools-bluebubbles.js +2 -0
  491. package/dist/repertoire/tools-bridge.js +144 -0
  492. package/dist/repertoire/tools-bundle.js +917 -0
  493. package/dist/repertoire/tools-commerce.js +253 -0
  494. package/dist/repertoire/tools-config.js +186 -0
  495. package/dist/repertoire/tools-continuity.js +588 -0
  496. package/dist/repertoire/tools-credential.js +383 -0
  497. package/dist/repertoire/tools-escalation.js +84 -0
  498. package/dist/repertoire/tools-evolution.js +527 -0
  499. package/dist/repertoire/tools-files.js +362 -0
  500. package/dist/repertoire/tools-flight.js +290 -0
  501. package/dist/repertoire/tools-flow.js +119 -0
  502. package/dist/repertoire/tools-friend-link.js +57 -0
  503. package/dist/repertoire/tools-github.js +3 -8
  504. package/dist/repertoire/tools-habits.js +103 -0
  505. package/dist/repertoire/tools-house-care.js +174 -0
  506. package/dist/repertoire/tools-mail.js +1828 -0
  507. package/dist/repertoire/tools-notes.js +501 -0
  508. package/dist/repertoire/tools-obligations.js +182 -0
  509. package/dist/repertoire/tools-orientation.js +31 -0
  510. package/dist/repertoire/tools-record.js +482 -0
  511. package/dist/repertoire/tools-rsvp.js +139 -0
  512. package/dist/repertoire/tools-runtime.js +238 -0
  513. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  514. package/dist/repertoire/tools-session.js +1141 -0
  515. package/dist/repertoire/tools-shell.js +154 -0
  516. package/dist/repertoire/tools-shepherd-guidance.js +171 -0
  517. package/dist/repertoire/tools-shepherd.js +325 -0
  518. package/dist/repertoire/tools-steward-policy.js +147 -0
  519. package/dist/repertoire/tools-stripe.js +224 -0
  520. package/dist/repertoire/tools-surface.js +369 -0
  521. package/dist/repertoire/tools-teams.js +50 -39
  522. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  523. package/dist/repertoire/tools-travel.js +125 -0
  524. package/dist/repertoire/tools-trip.js +982 -0
  525. package/dist/repertoire/tools-unraid.js +556 -0
  526. package/dist/repertoire/tools-user-profile.js +146 -0
  527. package/dist/repertoire/tools-vault.js +40 -0
  528. package/dist/repertoire/tools-voice-local.js +198 -0
  529. package/dist/repertoire/tools-voice.js +145 -0
  530. package/dist/repertoire/tools.js +523 -156
  531. package/dist/repertoire/travel-api-client.js +360 -0
  532. package/dist/repertoire/unraid-client.js +155 -0
  533. package/dist/repertoire/unraid-restart.js +339 -0
  534. package/dist/repertoire/user-profile.js +131 -0
  535. package/dist/repertoire/vault-setup.js +246 -0
  536. package/dist/repertoire/vault-unlock.js +686 -0
  537. package/dist/rsvp/aisleplanner-client.js +354 -0
  538. package/dist/rsvp/cli.js +936 -0
  539. package/dist/rsvp/config.js +327 -0
  540. package/dist/rsvp/cutover.js +453 -0
  541. package/dist/rsvp/diagnostics.js +232 -0
  542. package/dist/rsvp/diff-renderer.js +176 -0
  543. package/dist/rsvp/habit-policy.js +110 -0
  544. package/dist/rsvp/habit-stage.js +123 -0
  545. package/dist/rsvp/incident-bundle.js +97 -0
  546. package/dist/rsvp/migration.js +204 -0
  547. package/dist/rsvp/native-habit-runner.js +630 -0
  548. package/dist/rsvp/outbound-state.js +628 -0
  549. package/dist/rsvp/query.js +118 -0
  550. package/dist/rsvp/replay.js +233 -0
  551. package/dist/rsvp/snapshot.js +232 -0
  552. package/dist/rsvp/spend-ledger.js +175 -0
  553. package/dist/scripts/claude-code-hook.js +41 -0
  554. package/dist/scripts/claude-code-stop-hook.js +47 -0
  555. package/dist/senses/a2a-entry.js +140 -0
  556. package/dist/senses/acp-server.js +386 -0
  557. package/dist/senses/attention-queue.js +186 -0
  558. package/dist/senses/await-turn-message.js +65 -0
  559. package/dist/senses/bluebubbles/active-turns.js +216 -0
  560. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  561. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  562. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +393 -43
  563. package/dist/senses/bluebubbles/context-packet.js +207 -0
  564. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  565. package/dist/senses/bluebubbles/entry.js +90 -0
  566. package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
  567. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  568. package/dist/senses/bluebubbles/index.js +4054 -0
  569. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  570. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  571. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  572. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  573. package/dist/senses/bluebubbles/outbound-state.js +335 -0
  574. package/dist/senses/bluebubbles/processed-log.js +133 -0
  575. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  576. package/dist/senses/bluebubbles/replay.js +284 -0
  577. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  578. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  579. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  580. package/dist/senses/bluebubbles/webhook-registration.js +257 -0
  581. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  582. package/dist/senses/cli/bracketed-paste.js +82 -0
  583. package/dist/senses/cli/image-paste.js +287 -0
  584. package/dist/senses/cli/image-ref-navigation.js +75 -0
  585. package/dist/senses/cli/ink-app.js +156 -0
  586. package/dist/senses/cli/inline-diff.js +64 -0
  587. package/dist/senses/cli/input-keys.js +174 -0
  588. package/dist/senses/cli/kill-ring.js +86 -0
  589. package/dist/senses/cli/message-list.js +51 -0
  590. package/dist/senses/cli/ouro-tui.js +607 -0
  591. package/dist/senses/cli/spinner-imperative.js +135 -0
  592. package/dist/senses/cli/spinner.js +101 -0
  593. package/dist/senses/cli/status-line.js +60 -0
  594. package/dist/senses/cli/streaming-markdown.js +526 -0
  595. package/dist/senses/cli/tool-display.js +85 -0
  596. package/dist/senses/cli/tool-render.js +85 -0
  597. package/dist/senses/cli/tui-store.js +241 -0
  598. package/dist/senses/cli/virtual-list.js +35 -0
  599. package/dist/senses/cli-entry.js +60 -8
  600. package/dist/senses/cli.js +570 -309
  601. package/dist/senses/commands.js +66 -3
  602. package/dist/senses/context-packet-ledger.js +371 -0
  603. package/dist/senses/context-packets.js +154 -0
  604. package/dist/senses/habit-lifecycle-guard.js +24 -0
  605. package/dist/senses/habit-turn-message.js +160 -0
  606. package/dist/senses/ingress-evidence.js +2 -0
  607. package/dist/senses/mail-entry.js +66 -0
  608. package/dist/senses/mail.js +524 -0
  609. package/dist/senses/pipeline.js +1192 -204
  610. package/dist/senses/private-runtime-worker.js +857 -0
  611. package/dist/senses/private-runtime.js +1622 -0
  612. package/dist/senses/proactive-content-guard.js +51 -0
  613. package/dist/senses/root-host-approval-port.js +345 -0
  614. package/dist/senses/root-host-approval-runtime.js +393 -0
  615. package/dist/senses/sanctuary-authority-resident.js +102 -0
  616. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  617. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  618. package/dist/senses/sanctuary-grounding.js +118 -0
  619. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  620. package/dist/senses/sanctuary-health-acceptance-probe.js +786 -0
  621. package/dist/senses/sanctuary-health-runner.js +106 -0
  622. package/dist/senses/sanctuary-health.js +442 -0
  623. package/dist/senses/sanctuary-house.js +97 -0
  624. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  625. package/dist/senses/sanctuary-interactive-control.js +410 -0
  626. package/dist/senses/sanctuary-media-catalog-contract.js +268 -0
  627. package/dist/senses/sanctuary-media-optimization.js +517 -0
  628. package/dist/senses/sanctuary-runtime.js +390 -0
  629. package/dist/senses/sanctuary-sab.js +85 -0
  630. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  631. package/dist/senses/shared-turn.js +832 -0
  632. package/dist/senses/shepherd/agent-presentation.js +88 -0
  633. package/dist/senses/shepherd/attention-page.js +166 -0
  634. package/dist/senses/shepherd/attention-sidebar.js +76 -0
  635. package/dist/senses/shepherd/attention.js +295 -0
  636. package/dist/senses/shepherd/checkin-config.js +76 -0
  637. package/dist/senses/shepherd/checkin-store.js +386 -0
  638. package/dist/senses/shepherd/client.js +196 -0
  639. package/dist/senses/shepherd/cmux.js +483 -0
  640. package/dist/senses/shepherd/composer.js +336 -0
  641. package/dist/senses/shepherd/copilot-app.js +648 -0
  642. package/dist/senses/shepherd/feedback-reply.js +108 -0
  643. package/dist/senses/shepherd/feedback-source.js +20 -0
  644. package/dist/senses/shepherd/feedback-store.js +331 -0
  645. package/dist/senses/shepherd/feedback-submit.js +182 -0
  646. package/dist/senses/shepherd/feedback-worker.js +208 -0
  647. package/dist/senses/shepherd/guidance.js +273 -0
  648. package/dist/senses/shepherd/herdr.js +427 -0
  649. package/dist/senses/shepherd/host.js +17 -0
  650. package/dist/senses/shepherd/human-decision-guard.js +29 -0
  651. package/dist/senses/shepherd/judge-evaluation-command.js +183 -0
  652. package/dist/senses/shepherd/judge-evaluation-entry.js +13 -0
  653. package/dist/senses/shepherd/judge-evaluation.js +155 -0
  654. package/dist/senses/shepherd/judge.js +210 -0
  655. package/dist/senses/shepherd/notice-outbox.js +262 -0
  656. package/dist/senses/shepherd/observation-publisher.js +320 -0
  657. package/dist/senses/shepherd/operations-defaults.js +86 -0
  658. package/dist/senses/shepherd/operations.js +159 -0
  659. package/dist/senses/shepherd/owner-notice.js +489 -0
  660. package/dist/senses/shepherd/prompt-state.js +60 -0
  661. package/dist/senses/shepherd/recovery.js +543 -0
  662. package/dist/senses/shepherd/redact.js +66 -0
  663. package/dist/senses/shepherd/returns.js +79 -0
  664. package/dist/senses/shepherd/sense.js +849 -0
  665. package/dist/senses/shepherd/shepherd-judge-corpus-v1.json +170 -0
  666. package/dist/senses/shepherd/surface.js +123 -0
  667. package/dist/senses/shepherd/target-binding.js +13 -0
  668. package/dist/senses/shepherd/terminal-process.js +147 -0
  669. package/dist/senses/shepherd-entry.js +98 -0
  670. package/dist/senses/surface-tool.js +109 -0
  671. package/dist/senses/teams-entry.js +68 -8
  672. package/dist/senses/teams-image.js +119 -0
  673. package/dist/senses/teams.js +998 -337
  674. package/dist/senses/telegram-admission.js +718 -0
  675. package/dist/senses/telegram-approval-runtime.js +793 -0
  676. package/dist/senses/telegram-attachments.js +186 -0
  677. package/dist/senses/telegram-audit-ledger.js +220 -0
  678. package/dist/senses/telegram-authority-transport.js +231 -0
  679. package/dist/senses/telegram-client.js +1755 -0
  680. package/dist/senses/telegram-effect-adapter.js +904 -0
  681. package/dist/senses/telegram-entry.js +83 -0
  682. package/dist/senses/telegram-handoff.js +154 -0
  683. package/dist/senses/telegram.js +2474 -0
  684. package/dist/senses/trust-gate.js +104 -9
  685. package/dist/senses/voice/audio-playback.js +237 -0
  686. package/dist/senses/voice/audio-routing.js +119 -0
  687. package/dist/senses/voice/call-auth.js +250 -0
  688. package/dist/senses/voice/elevenlabs.js +202 -0
  689. package/dist/senses/voice/floor-control.js +431 -0
  690. package/dist/senses/voice/floor-controller.js +115 -0
  691. package/dist/senses/voice/golden-path.js +116 -0
  692. package/dist/senses/voice/index.js +29 -0
  693. package/dist/senses/voice/local-audio-control.js +344 -0
  694. package/dist/senses/voice/local-audio-devices.js +516 -0
  695. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  696. package/dist/senses/voice/local-audio-identity.js +103 -0
  697. package/dist/senses/voice/local-audio-join.js +325 -0
  698. package/dist/senses/voice/local-audio-mute.js +199 -0
  699. package/dist/senses/voice/local-audio-notify.js +124 -0
  700. package/dist/senses/voice/local-audio-prompts.js +116 -0
  701. package/dist/senses/voice/local-audio-transport.js +427 -0
  702. package/dist/senses/voice/local-audio.js +281 -0
  703. package/dist/senses/voice/local-media-stream.js +145 -0
  704. package/dist/senses/voice/meeting.js +113 -0
  705. package/dist/senses/voice/outbound.js +190 -0
  706. package/dist/senses/voice/phone.js +33 -0
  707. package/dist/senses/voice/playback.js +139 -0
  708. package/dist/senses/voice/process-guards.js +51 -0
  709. package/dist/senses/voice/realtime-eval.js +496 -0
  710. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  711. package/dist/senses/voice/realtime-trace.js +531 -0
  712. package/dist/senses/voice/transcript.js +70 -0
  713. package/dist/senses/voice/turn.js +191 -0
  714. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  715. package/dist/senses/voice/twilio-phone.js +5454 -0
  716. package/dist/senses/voice/types.js +2 -0
  717. package/dist/senses/voice/whisper.js +161 -0
  718. package/dist/senses/voice-entry.js +83 -0
  719. package/dist/senses/voice-realtime-eval-command.js +99 -0
  720. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  721. package/dist/senses/voice-twilio-entry.js +87 -0
  722. package/dist/trips/core.js +138 -0
  723. package/dist/trips/store.js +265 -0
  724. package/dist/util/frontmatter.js +69 -0
  725. package/npm-shrinkwrap.json +8342 -0
  726. package/package.json +76 -13
  727. package/skills/agent-commerce.md +113 -0
  728. package/skills/browser-navigation.md +117 -0
  729. package/skills/commerce-setup-guide.md +116 -0
  730. package/skills/commerce-setup.md +84 -0
  731. package/skills/configure-dev-tools.md +99 -0
  732. package/skills/travel-planning.md +138 -0
  733. package/dist/heart/daemon/auth-flow.js +0 -430
  734. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  735. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  736. package/dist/heart/daemon/update-hooks.js +0 -138
  737. package/dist/heart/obligations.js +0 -191
  738. package/dist/heart/safe-workspace.js +0 -381
  739. package/dist/heart/session-recall.js +0 -116
  740. package/dist/mind/friends/channel.js +0 -84
  741. package/dist/mind/friends/group-context.js +0 -144
  742. package/dist/mind/friends/resolver.js +0 -84
  743. package/dist/mind/friends/store-file.js +0 -190
  744. package/dist/mind/friends/store.js +0 -4
  745. package/dist/mind/friends/tokens.js +0 -26
  746. package/dist/mind/friends/trust-explanation.js +0 -74
  747. package/dist/mind/friends/types.js +0 -29
  748. package/dist/repertoire/tasks/board.js +0 -134
  749. package/dist/repertoire/tasks/index.js +0 -224
  750. package/dist/repertoire/tasks/lifecycle.js +0 -80
  751. package/dist/repertoire/tasks/middleware.js +0 -65
  752. package/dist/repertoire/tasks/parser.js +0 -173
  753. package/dist/repertoire/tasks/scanner.js +0 -132
  754. package/dist/repertoire/tasks/transitions.js +0 -144
  755. package/dist/senses/bluebubbles-entry.js +0 -13
  756. package/dist/senses/bluebubbles.js +0 -1181
  757. package/dist/senses/debug-activity.js +0 -154
  758. package/dist/senses/inner-dialog-worker.js +0 -90
  759. package/dist/senses/inner-dialog.js +0 -525
  760. package/subagents/README.md +0 -7
  761. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  762. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  763. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  764. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  765. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  766. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  767. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  768. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  769. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  770. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  771. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  772. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  773. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  774. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  775. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  776. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  777. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,917 @@
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.bundleToolDefinitions = void 0;
37
+ exports.__getConfirmationTokenStore = __getConfirmationTokenStore;
38
+ exports.probeFirstPush = probeFirstPush;
39
+ /**
40
+ * Agent-callable bundle management tools.
41
+ *
42
+ * These tools let the agent fix its own git state — initializing the
43
+ * bundle as a repo, adding a remote, making the first commit, and syncing
44
+ * with the remote (bundle_push and bundle_pull_rebase both run the shared
45
+ * merge-only `syncNow`; neither ever leaves a rebase, a merge or a stash). The `bundleState` field in the
46
+ * start-of-turn packet (PR 5) points the agent at these tools whenever
47
+ * it detects an unresolved git issue.
48
+ *
49
+ * ## Security boundaries
50
+ *
51
+ * Every tool computes `bundleRoot = getAgentRoot()` once and refuses to
52
+ * touch anything outside that directory. Path arguments are validated
53
+ * via `path.resolve(bundleRoot, input)` + a prefix check — if the
54
+ * resolved path escapes the bundle, the handler emits a `*_refused`
55
+ * nerves event and returns `{ ok: false, error: "refused: ..." }`
56
+ * without executing the git operation.
57
+ *
58
+ * ## Destructive-op refusal pattern (Directive B)
59
+ *
60
+ * Tools that could lose work (bundle_init_git on an existing repo,
61
+ * bundle_add_remote on a configured remote, etc.) refuse by default and require an explicit `force`
62
+ * flag — mirroring Claude Code's `ExitWorktreeTool` safety pattern. The
63
+ * refusal surface is the LLM's responsibility to bridge with the human:
64
+ * when a tool refuses, the agent should ask the user for permission
65
+ * before retrying with `force: true`.
66
+ *
67
+ * ## Enumeration, not recursive delete (Directive A)
68
+ *
69
+ * No tool uses recursive rmSync or shells out to destructive shell delete
70
+ * commands. `bundle_do_first_commit` stages files
71
+ * via `git add -- <file1> <file2> ...` with explicit enumeration even
72
+ * when the caller omits the files list — the default path internally
73
+ * calls `bundle_list_first_commit` and stages each entry individually.
74
+ */
75
+ const child_process_1 = require("child_process");
76
+ const crypto = __importStar(require("crypto"));
77
+ const fs = __importStar(require("fs"));
78
+ const path = __importStar(require("path"));
79
+ const runtime_1 = require("../nerves/runtime");
80
+ const identity_1 = require("../heart/identity");
81
+ const bundle_state_1 = require("../heart/bundle-state");
82
+ const sync_1 = require("../heart/sync");
83
+ const bundle_templates_1 = require("./bundle-templates");
84
+ function gitExec(bundleRoot, args, timeoutMs = 10000) {
85
+ try {
86
+ const stdout = (0, child_process_1.execFileSync)("git", args, {
87
+ cwd: bundleRoot,
88
+ stdio: "pipe",
89
+ timeout: timeoutMs,
90
+ }).toString();
91
+ return { stdout, stderr: "", code: 0 };
92
+ }
93
+ catch (err) {
94
+ /* v8 ignore start -- defensive fallback branches on the err shape are hard to exercise without mocking; real git failures populate all three fields @preserve */
95
+ const anyErr = err;
96
+ return {
97
+ stdout: anyErr.stdout?.toString() ?? "",
98
+ stderr: anyErr.stderr?.toString() ?? anyErr.message ?? String(err),
99
+ code: anyErr.status ?? 1,
100
+ };
101
+ /* v8 ignore stop */
102
+ }
103
+ }
104
+ function isGitRepo(bundleRoot) {
105
+ return fs.existsSync(path.join(bundleRoot, ".git"));
106
+ }
107
+ function hasHead(bundleRoot) {
108
+ const result = gitExec(bundleRoot, ["rev-parse", "HEAD"]);
109
+ return result.code === 0;
110
+ }
111
+ function getRemoteUrl(bundleRoot, name) {
112
+ const result = gitExec(bundleRoot, ["remote", "get-url", name]);
113
+ if (result.code !== 0)
114
+ return undefined;
115
+ /* v8 ignore next -- empty stdout from `git remote get-url` on a configured remote doesn't happen in practice @preserve */
116
+ return result.stdout.trim() || undefined;
117
+ }
118
+ function listRemotes(bundleRoot) {
119
+ const result = gitExec(bundleRoot, ["remote"]);
120
+ /* v8 ignore next -- `git remote` on an initialized repo always exits 0 @preserve */
121
+ if (result.code !== 0)
122
+ return [];
123
+ return result.stdout.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
124
+ }
125
+ function assertInsideBundle(bundleRoot, rel) {
126
+ // path.resolve against an absolute input keeps it absolute — which may
127
+ // escape the bundle. Force-join then normalize to catch those cases.
128
+ const joined = path.resolve(bundleRoot, rel);
129
+ const normalized = path.normalize(joined);
130
+ /* v8 ignore next -- normalized === bundleRoot happens when rel is "" or "." — guarded by the empty-string check at the caller @preserve */
131
+ if (normalized === bundleRoot)
132
+ return { ok: true, resolved: normalized };
133
+ if (!normalized.startsWith(bundleRoot + path.sep)) {
134
+ return { ok: false, error: `refused: path outside bundle root: ${rel}` };
135
+ }
136
+ return { ok: true, resolved: normalized };
137
+ }
138
+ function json(obj) {
139
+ return JSON.stringify(obj);
140
+ }
141
+ // ─── tool: bundle_check_sync_status ────────────────────────────────────
142
+ const checkSyncStatusHandler = () => {
143
+ const bundleRoot = (0, identity_1.getAgentRoot)();
144
+ (0, runtime_1.emitNervesEvent)({
145
+ component: "repertoire",
146
+ event: "repertoire.bundle_check_sync_status_start",
147
+ message: "checking bundle sync status",
148
+ meta: { bundleRoot },
149
+ });
150
+ const gitRepo = isGitRepo(bundleRoot);
151
+ let hasRemote = false;
152
+ let remoteUrl;
153
+ let dirtyFileCount = 0;
154
+ let firstCommitExists = false;
155
+ let ahead = 0;
156
+ let behind = 0;
157
+ if (gitRepo) {
158
+ const remotes = listRemotes(bundleRoot);
159
+ hasRemote = remotes.length > 0;
160
+ if (hasRemote) {
161
+ remoteUrl = getRemoteUrl(bundleRoot, remotes[0]);
162
+ }
163
+ firstCommitExists = hasHead(bundleRoot);
164
+ const status = gitExec(bundleRoot, ["status", "--porcelain"]);
165
+ /* v8 ignore next -- git status --porcelain only fails on a corrupt repo @preserve */
166
+ if (status.code === 0) {
167
+ dirtyFileCount = status.stdout
168
+ .split("\n")
169
+ .map((l) => l.trim())
170
+ .filter((l) => l.length > 0).length;
171
+ }
172
+ if (hasRemote && firstCommitExists) {
173
+ // Against the last fetched sync branch, named explicitly; no upstream config is assumed.
174
+ const config = bundleSyncConfig(bundleRoot);
175
+ const counts = gitExec(bundleRoot, ["rev-list", "--left-right", "--count", `HEAD...refs/remotes/${config.remote}/${config.branch}`]);
176
+ if (counts.code === 0) {
177
+ const [a, b] = counts.stdout.trim().split("\t").map((n) => parseInt(n, 10));
178
+ ahead = a;
179
+ behind = b;
180
+ }
181
+ }
182
+ }
183
+ const pendingSyncExists = fs.existsSync(path.join(bundleRoot, "state", "pending-sync.json"));
184
+ const bundleStateIssues = (0, bundle_state_1.detectBundleState)(bundleRoot);
185
+ const result = {
186
+ ok: true,
187
+ isGitRepo: gitRepo,
188
+ hasRemote,
189
+ remoteUrl: remoteUrl ?? null,
190
+ dirtyFileCount,
191
+ firstCommitExists,
192
+ ahead,
193
+ behind,
194
+ pendingSyncExists,
195
+ bundleStateIssues,
196
+ };
197
+ (0, runtime_1.emitNervesEvent)({
198
+ component: "repertoire",
199
+ event: "repertoire.bundle_check_sync_status_end",
200
+ message: "bundle sync status checked",
201
+ meta: { bundleRoot, ...result },
202
+ });
203
+ return json(result);
204
+ };
205
+ // ─── tool: bundle_init_git ─────────────────────────────────────────────
206
+ const initGitHandler = (args) => {
207
+ const bundleRoot = (0, identity_1.getAgentRoot)();
208
+ const force = args.force === "true" || args.force === true;
209
+ (0, runtime_1.emitNervesEvent)({
210
+ component: "repertoire",
211
+ event: "repertoire.bundle_init_git_start",
212
+ message: "initializing bundle git repo",
213
+ meta: { bundleRoot, force },
214
+ });
215
+ const alreadyInit = isGitRepo(bundleRoot);
216
+ if (alreadyInit && !force) {
217
+ (0, runtime_1.emitNervesEvent)({
218
+ level: "warn",
219
+ component: "repertoire",
220
+ event: "repertoire.bundle_init_git_refused",
221
+ message: "bundle_init_git refused: already initialized",
222
+ meta: { bundleRoot },
223
+ });
224
+ (0, runtime_1.emitNervesEvent)({
225
+ component: "repertoire",
226
+ event: "repertoire.bundle_init_git_end",
227
+ message: "bundle_init_git refused",
228
+ meta: { bundleRoot, refused: true },
229
+ });
230
+ return json({
231
+ ok: false,
232
+ error: "bundle already has a .git directory — pass force: true to re-init",
233
+ alreadyInit: true,
234
+ });
235
+ }
236
+ if (!alreadyInit) {
237
+ const init = gitExec(bundleRoot, ["init", "--initial-branch=main"]);
238
+ /* v8 ignore start -- git init failure requires a broken git binary or a permissions edge case that's not practical to cover in unit tests @preserve */
239
+ if (init.code !== 0) {
240
+ (0, runtime_1.emitNervesEvent)({
241
+ level: "error",
242
+ component: "repertoire",
243
+ event: "repertoire.bundle_init_git_error",
244
+ message: "git init failed",
245
+ meta: { bundleRoot, stderr: init.stderr },
246
+ });
247
+ (0, runtime_1.emitNervesEvent)({
248
+ component: "repertoire",
249
+ event: "repertoire.bundle_init_git_end",
250
+ message: "git init failed",
251
+ meta: { bundleRoot, ok: false },
252
+ });
253
+ return json({ ok: false, error: `git init failed: ${init.stderr}` });
254
+ }
255
+ /* v8 ignore stop */
256
+ }
257
+ // Write the full .gitignore template if one doesn't already exist.
258
+ // See BUNDLE_GITIGNORE_TEMPLATE's design philosophy: functional blocks
259
+ // only (credentials, state, noise, build artifacts); PII is handled
260
+ // separately by bundle_first_push_review at first-push time.
261
+ const gitignorePath = path.join(bundleRoot, ".gitignore");
262
+ let gitignoreWritten = false;
263
+ if (!fs.existsSync(gitignorePath)) {
264
+ fs.writeFileSync(gitignorePath, bundle_templates_1.BUNDLE_GITIGNORE_TEMPLATE, "utf-8");
265
+ gitignoreWritten = true;
266
+ }
267
+ const result = { ok: true, alreadyInit, gitignoreWritten };
268
+ (0, runtime_1.emitNervesEvent)({
269
+ component: "repertoire",
270
+ event: "repertoire.bundle_init_git_end",
271
+ message: "bundle git initialized",
272
+ meta: { bundleRoot, ...result },
273
+ });
274
+ return json(result);
275
+ };
276
+ // ─── tool: bundle_add_remote ───────────────────────────────────────────
277
+ const REMOTE_URL_PATTERN = /^(https?:\/\/|git@[^\s:]+:)[^\s]+$/;
278
+ const addRemoteHandler = (args) => {
279
+ const bundleRoot = (0, identity_1.getAgentRoot)();
280
+ const url = typeof args.url === "string" ? args.url.trim() : "";
281
+ const name = typeof args.name === "string" && args.name.length > 0 ? args.name : "origin";
282
+ const force = args.force === "true" || args.force === true;
283
+ (0, runtime_1.emitNervesEvent)({
284
+ component: "repertoire",
285
+ event: "repertoire.bundle_add_remote_start",
286
+ message: "adding git remote to bundle",
287
+ meta: { bundleRoot, name, url, force },
288
+ });
289
+ const finish = (ok, payload) => {
290
+ (0, runtime_1.emitNervesEvent)({
291
+ component: "repertoire",
292
+ event: "repertoire.bundle_add_remote_end",
293
+ message: "bundle_add_remote finished",
294
+ meta: { bundleRoot, ok, ...payload },
295
+ });
296
+ return json({ ok, ...payload });
297
+ };
298
+ if (!isGitRepo(bundleRoot)) {
299
+ return finish(false, { error: "bundle is not a git repo — run bundle_init_git first" });
300
+ }
301
+ if (!REMOTE_URL_PATTERN.test(url)) {
302
+ (0, runtime_1.emitNervesEvent)({
303
+ level: "warn",
304
+ component: "repertoire",
305
+ event: "repertoire.bundle_add_remote_refused",
306
+ message: "bundle_add_remote refused: invalid url",
307
+ meta: { bundleRoot, url },
308
+ });
309
+ return finish(false, { error: `invalid remote url: ${url || "(empty)"}` });
310
+ }
311
+ const existing = getRemoteUrl(bundleRoot, name);
312
+ if (existing && !force) {
313
+ (0, runtime_1.emitNervesEvent)({
314
+ level: "warn",
315
+ component: "repertoire",
316
+ event: "repertoire.bundle_add_remote_refused",
317
+ message: "bundle_add_remote refused: remote already exists",
318
+ meta: { bundleRoot, name, existing },
319
+ });
320
+ return finish(false, {
321
+ error: `remote "${name}" already points to ${existing} — pass force: true to overwrite`,
322
+ previousUrl: existing,
323
+ });
324
+ }
325
+ if (existing) {
326
+ const setUrl = gitExec(bundleRoot, ["remote", "set-url", name, url]);
327
+ /* v8 ignore next 3 -- git remote set-url failure requires a permissions/git-state edge case @preserve */
328
+ if (setUrl.code !== 0) {
329
+ return finish(false, { error: `git remote set-url failed: ${setUrl.stderr}` });
330
+ }
331
+ }
332
+ else {
333
+ const add = gitExec(bundleRoot, ["remote", "add", name, url]);
334
+ /* v8 ignore next 3 -- git remote add failure requires a permissions/git-state edge case @preserve */
335
+ if (add.code !== 0) {
336
+ return finish(false, { error: `git remote add failed: ${add.stderr}` });
337
+ }
338
+ }
339
+ return finish(true, { name, url, previousUrl: existing ?? null });
340
+ };
341
+ const listFirstCommitHandler = () => {
342
+ const bundleRoot = (0, identity_1.getAgentRoot)();
343
+ (0, runtime_1.emitNervesEvent)({
344
+ component: "repertoire",
345
+ event: "repertoire.bundle_list_first_commit_start",
346
+ message: "listing first-commit candidates",
347
+ meta: { bundleRoot },
348
+ });
349
+ const finish = (ok, payload) => {
350
+ (0, runtime_1.emitNervesEvent)({
351
+ component: "repertoire",
352
+ event: "repertoire.bundle_list_first_commit_end",
353
+ message: "bundle_list_first_commit finished",
354
+ meta: { bundleRoot, ok, ...payload },
355
+ });
356
+ return json({ ok, ...payload });
357
+ };
358
+ if (!isGitRepo(bundleRoot)) {
359
+ return finish(false, { error: "bundle is not a git repo — run bundle_init_git first" });
360
+ }
361
+ if (hasHead(bundleRoot)) {
362
+ return finish(false, { error: "bundle already has commits — bundle_list_first_commit only applies before the first commit" });
363
+ }
364
+ const ls = gitExec(bundleRoot, ["ls-files", "-o", "--exclude-standard"]);
365
+ /* v8 ignore next 3 -- git ls-files failure requires a corrupt repo @preserve */
366
+ if (ls.code !== 0) {
367
+ return finish(false, { error: `git ls-files failed: ${ls.stderr}` });
368
+ }
369
+ const files = ls.stdout
370
+ .split("\n")
371
+ .map((l) => l.trim())
372
+ .filter((l) => l.length > 0);
373
+ const groups = {};
374
+ let totalFiles = 0;
375
+ let totalBytes = 0;
376
+ for (const relFile of files) {
377
+ const absPath = path.join(bundleRoot, relFile);
378
+ let size = 0;
379
+ try {
380
+ size = fs.statSync(absPath).size;
381
+ /* v8 ignore start -- statSync failure on a git-listed file is a race condition we can't reliably reproduce @preserve */
382
+ }
383
+ catch {
384
+ // File listed by git but not readable — skip silently
385
+ continue;
386
+ }
387
+ /* v8 ignore stop */
388
+ const topDir = relFile.includes(path.sep) ? relFile.split(path.sep)[0] : "(root)";
389
+ if (!groups[topDir]) {
390
+ groups[topDir] = { files: [], totalBytes: 0, fileCount: 0 };
391
+ }
392
+ groups[topDir].files.push({ path: relFile, size });
393
+ groups[topDir].totalBytes += size;
394
+ groups[topDir].fileCount += 1;
395
+ totalFiles += 1;
396
+ totalBytes += size;
397
+ }
398
+ return finish(true, { groups, totalFiles, totalBytes });
399
+ };
400
+ // ─── tool: bundle_do_first_commit ──────────────────────────────────────
401
+ const doFirstCommitHandler = (args) => {
402
+ const bundleRoot = (0, identity_1.getAgentRoot)();
403
+ const rawFiles = args.files;
404
+ const hasExplicitFiles = rawFiles !== undefined;
405
+ const message = typeof args.message === "string" && args.message.length > 0
406
+ ? args.message
407
+ : "initial: import pre-sync bundle state";
408
+ (0, runtime_1.emitNervesEvent)({
409
+ component: "repertoire",
410
+ event: "repertoire.bundle_do_first_commit_start",
411
+ message: "performing first commit",
412
+ meta: { bundleRoot, hasExplicitFiles },
413
+ });
414
+ const finish = (ok, payload) => {
415
+ (0, runtime_1.emitNervesEvent)({
416
+ component: "repertoire",
417
+ event: "repertoire.bundle_do_first_commit_end",
418
+ message: "bundle_do_first_commit finished",
419
+ meta: { bundleRoot, ok, ...payload },
420
+ });
421
+ return json({ ok, ...payload });
422
+ };
423
+ if (!isGitRepo(bundleRoot)) {
424
+ return finish(false, { error: "bundle is not a git repo — run bundle_init_git first" });
425
+ }
426
+ if (hasHead(bundleRoot)) {
427
+ return finish(false, { error: "bundle already has commits — first commit already exists" });
428
+ }
429
+ // Resolve the file list — either explicit or the default set from ls-files.
430
+ let filesToStage;
431
+ if (hasExplicitFiles) {
432
+ if (!Array.isArray(rawFiles)) {
433
+ return finish(false, { error: "files must be an array of relative paths" });
434
+ }
435
+ if (rawFiles.length === 0) {
436
+ // Directive A: explicit enumeration required. Empty list is a refusal.
437
+ (0, runtime_1.emitNervesEvent)({
438
+ level: "warn",
439
+ component: "repertoire",
440
+ event: "repertoire.bundle_do_first_commit_refused",
441
+ message: "bundle_do_first_commit refused: empty file list",
442
+ meta: { bundleRoot },
443
+ });
444
+ return finish(false, { error: "refused: files array must be non-empty — pass explicit file paths or omit the argument to stage everything" });
445
+ }
446
+ filesToStage = rawFiles;
447
+ }
448
+ else {
449
+ const ls = gitExec(bundleRoot, ["ls-files", "-o", "--exclude-standard"]);
450
+ /* v8 ignore next 3 -- git ls-files failure requires a corrupt repo @preserve */
451
+ if (ls.code !== 0) {
452
+ return finish(false, { error: `git ls-files failed: ${ls.stderr}` });
453
+ }
454
+ filesToStage = ls.stdout
455
+ .split("\n")
456
+ .map((l) => l.trim())
457
+ .filter((l) => l.length > 0);
458
+ }
459
+ /* v8 ignore next 3 -- empty filesToStage on default path means ls-files returned zero entries, covered by the empty-bundle test path elsewhere @preserve */
460
+ if (filesToStage.length === 0) {
461
+ return finish(false, { error: "no files to commit" });
462
+ }
463
+ // Security boundary: every file must resolve inside bundleRoot.
464
+ for (const file of filesToStage) {
465
+ /* v8 ignore next 3 -- defensive non-string entry check: LLM tool call args are JSON-parsed, a non-string would already fail JSON schema validation upstream @preserve */
466
+ if (typeof file !== "string" || file.length === 0) {
467
+ return finish(false, { error: `invalid file entry: ${JSON.stringify(file)}` });
468
+ }
469
+ const check = assertInsideBundle(bundleRoot, file);
470
+ if (!check.ok) {
471
+ (0, runtime_1.emitNervesEvent)({
472
+ level: "warn",
473
+ component: "repertoire",
474
+ event: "repertoire.bundle_do_first_commit_refused",
475
+ message: "bundle_do_first_commit refused: path outside bundle root",
476
+ meta: { bundleRoot, file },
477
+ });
478
+ return finish(false, { error: check.error });
479
+ }
480
+ }
481
+ // Stage via `git add -- <file1> <file2> ...` — explicit enumeration.
482
+ const add = gitExec(bundleRoot, ["add", "--", ...filesToStage]);
483
+ /* v8 ignore next 3 -- git add failure on a valid file list requires a corrupt repo or race @preserve */
484
+ if (add.code !== 0) {
485
+ return finish(false, { error: `git add failed: ${add.stderr}` });
486
+ }
487
+ const commit = gitExec(bundleRoot, ["commit", "-m", message]);
488
+ /* v8 ignore next 3 -- git commit failure requires a hook-reject or missing user.email, which createTmpBundle pre-configures @preserve */
489
+ if (commit.code !== 0) {
490
+ return finish(false, { error: `git commit failed: ${commit.stderr}` });
491
+ }
492
+ const rev = gitExec(bundleRoot, ["rev-parse", "HEAD"]);
493
+ const commitSha = rev.stdout.trim();
494
+ return finish(true, { commitSha, fileCount: filesToStage.length, message });
495
+ };
496
+ const CONFIRMATION_TOKEN_TTL_MS = 15 * 60 * 1000;
497
+ const _confirmationTokens = new Map();
498
+ function pruneExpiredTokens(now) {
499
+ for (const [token, entry] of _confirmationTokens) {
500
+ if (now - entry.createdAt > CONFIRMATION_TOKEN_TTL_MS) {
501
+ _confirmationTokens.delete(token);
502
+ }
503
+ }
504
+ }
505
+ /** Test hook: lets unit tests inspect + clear the token store. */
506
+ function __getConfirmationTokenStore() {
507
+ return _confirmationTokens;
508
+ }
509
+ function countFilesInDir(bundleRoot, relDir) {
510
+ // Use `git ls-files --others --exclude-standard -- <dir>` to honor .gitignore.
511
+ const result = gitExec(bundleRoot, ["ls-files", "--others", "--exclude-standard", "--", relDir]);
512
+ /* v8 ignore next -- git ls-files failure requires a corrupt repo @preserve */
513
+ if (result.code !== 0)
514
+ return 0;
515
+ return result.stdout.split("\n").filter((l) => l.trim().length > 0).length;
516
+ }
517
+ function parseGitHubUrl(url) {
518
+ // https://github.com/owner/repo(.git)
519
+ const httpsMatch = url.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(\.git)?$/);
520
+ if (httpsMatch)
521
+ return { owner: httpsMatch[1], repo: httpsMatch[2] };
522
+ // git@github.com:owner/repo(.git)
523
+ const sshMatch = url.match(/^git@github\.com:([^/]+)\/([^/]+?)(\.git)?$/);
524
+ if (sshMatch)
525
+ return { owner: sshMatch[1], repo: sshMatch[2] };
526
+ return null;
527
+ }
528
+ async function checkGitHubVisibility(parsed, fetchFn) {
529
+ const controller = new AbortController();
530
+ /* v8 ignore next -- 5-second timeout abort only fires if fetch takes longer than the test runner allows; the abort path is defensive @preserve */
531
+ const timer = setTimeout(() => controller.abort(), 5000);
532
+ try {
533
+ const res = await fetchFn(`https://api.github.com/repos/${parsed.owner}/${parsed.repo}`, {
534
+ signal: controller.signal,
535
+ headers: { Accept: "application/vnd.github+json" },
536
+ });
537
+ if (!res.ok)
538
+ return "unknown";
539
+ const data = (await res.json());
540
+ if (data.private === true)
541
+ return "private";
542
+ if (data.private === false)
543
+ return "public";
544
+ /* v8 ignore next -- malformed GitHub API response (private field neither true nor false) is not practical to provoke @preserve */
545
+ return "unknown";
546
+ }
547
+ catch {
548
+ return "unknown";
549
+ }
550
+ finally {
551
+ clearTimeout(timer);
552
+ }
553
+ }
554
+ function makeFirstPushReviewHandler(deps = {}) {
555
+ return async () => {
556
+ const bundleRoot = (0, identity_1.getAgentRoot)();
557
+ const fetchFn = deps.fetch ?? globalThis.fetch;
558
+ const now = deps.now ?? Date.now;
559
+ (0, runtime_1.emitNervesEvent)({
560
+ component: "repertoire",
561
+ event: "repertoire.bundle_first_push_review_start",
562
+ message: "reviewing bundle for first push",
563
+ meta: { bundleRoot },
564
+ });
565
+ const finish = (ok, payload) => {
566
+ (0, runtime_1.emitNervesEvent)({
567
+ component: "repertoire",
568
+ event: "repertoire.bundle_first_push_review_end",
569
+ message: "bundle_first_push_review finished",
570
+ meta: { bundleRoot, ok, ...payload },
571
+ });
572
+ return json({ ok, ...payload });
573
+ };
574
+ if (!isGitRepo(bundleRoot)) {
575
+ return finish(false, { error: "bundle is not a git repo — run bundle_init_git first" });
576
+ }
577
+ const remotes = listRemotes(bundleRoot);
578
+ if (remotes.length === 0) {
579
+ return finish(false, { error: "no remote configured — run bundle_add_remote first" });
580
+ }
581
+ const remoteName = remotes[0];
582
+ const remoteUrl = getRemoteUrl(bundleRoot, remoteName);
583
+ /* v8 ignore next 3 -- listRemotes returned a name but get-url failed; only possible under a git race @preserve */
584
+ if (!remoteUrl) {
585
+ return finish(false, { error: "could not resolve remote url" });
586
+ }
587
+ // Enumerate PII directory counts
588
+ const piiCounts = {};
589
+ let totalPiiRecords = 0;
590
+ for (const dir of bundle_templates_1.PII_BUNDLE_DIRECTORIES) {
591
+ const dirPath = path.join(bundleRoot, dir);
592
+ if (!fs.existsSync(dirPath))
593
+ continue;
594
+ const count = countFilesInDir(bundleRoot, dir);
595
+ if (count > 0) {
596
+ piiCounts[dir] = count;
597
+ totalPiiRecords += count;
598
+ }
599
+ }
600
+ // GitHub visibility probe
601
+ const parsedGitHub = parseGitHubUrl(remoteUrl);
602
+ let warningLevel = "generic";
603
+ if (parsedGitHub) {
604
+ const visibility = await checkGitHubVisibility(parsedGitHub, fetchFn);
605
+ if (visibility === "public")
606
+ warningLevel = "public_github";
607
+ else if (visibility === "private")
608
+ warningLevel = "private_github";
609
+ }
610
+ // Build first-person warning text
611
+ const piiSummary = Object.entries(piiCounts)
612
+ .map(([dir, count]) => `${count} ${dir} record${count === 1 ? "" : "s"}`)
613
+ .join(", ");
614
+ const piiClause = piiSummary.length > 0
615
+ ? `my bundle contains personal data: ${piiSummary} (${totalPiiRecords} records total)`
616
+ : "my bundle has no PII directories populated yet";
617
+ let visibilityClause;
618
+ if (warningLevel === "public_github") {
619
+ visibilityClause = `⚠️ ${remoteUrl} is a PUBLIC GitHub repo — anything i push will be visible to anyone. are you SURE you want to push PII to a public repo?`;
620
+ }
621
+ else if (warningLevel === "private_github") {
622
+ visibilityClause = `${remoteUrl} is a PRIVATE GitHub repo. still, confirm you want to push this data there.`;
623
+ }
624
+ else {
625
+ visibilityClause = `${remoteUrl} — i can't verify this remote's visibility. confirm the repo is private before i push PII.`;
626
+ }
627
+ const warningText = `${piiClause}. ${visibilityClause}`;
628
+ // Issue and store the confirmation token
629
+ const token = crypto.randomUUID();
630
+ const currentTime = now();
631
+ pruneExpiredTokens(currentTime);
632
+ _confirmationTokens.set(token, { bundleRoot, createdAt: currentTime });
633
+ return finish(true, {
634
+ warningLevel,
635
+ remoteUrl,
636
+ piiCounts,
637
+ totalPiiRecords,
638
+ warningText,
639
+ confirmRequired: true,
640
+ confirmationToken: token,
641
+ });
642
+ };
643
+ }
644
+ const firstPushReviewHandler = makeFirstPushReviewHandler();
645
+ /**
646
+ * Whether a push to `remote` would be the first push of `branch`: "first" when
647
+ * the remote has no such branch, "pushed" when it has. The remote is asked
648
+ * through sync's own ls-remote (the same flags and environment as sync's push,
649
+ * so in the container it goes through the ouro-sync ssh). A failed ls-remote
650
+ * is "unreachable", never taken for a first push or for a pushed one.
651
+ *
652
+ * Exported for direct unit testing in bundle-push-first-push.test.ts.
653
+ */
654
+ async function probeFirstPush(bundleRoot, remote, branch) {
655
+ const listed = await (0, sync_1.listRemoteRefs)(bundleRoot, remote, [`refs/heads/${branch}`]);
656
+ if (!listed.ok)
657
+ return { kind: "unreachable", error: listed.error };
658
+ return listed.refs.length === 0 ? { kind: "first" } : { kind: "pushed" };
659
+ }
660
+ /** How long a bundle tool waits for the bundle sync lock before reporting busy. */
661
+ const BUNDLE_TOOL_SYNC_WAIT_MS = 10_000;
662
+ /** The bundle's sync remote and branch from agent.json: the agent cannot name another remote. */
663
+ function bundleSyncConfig(bundleRoot) {
664
+ let remote = "origin";
665
+ let branch = "main";
666
+ try {
667
+ const parsed = JSON.parse(fs.readFileSync(path.join(bundleRoot, "agent.json"), "utf-8"));
668
+ if (typeof parsed.sync?.remote === "string" && parsed.sync.remote.length > 0)
669
+ remote = parsed.sync.remote;
670
+ if (typeof parsed.sync?.branch === "string" && parsed.sync.branch.length > 0)
671
+ branch = parsed.sync.branch;
672
+ }
673
+ catch {
674
+ // No readable agent.json: the defaults.
675
+ }
676
+ return { enabled: true, remote, branch };
677
+ }
678
+ /**
679
+ * Both tools sync the bundle through `syncNow`: commit, fetch, merge, push,
680
+ * under the bundle lock. A conflict is aborted and recorded by sync itself,
681
+ * so no tool call leaves a merge, a rebase or a stash behind.
682
+ */
683
+ function makeSyncHandler(toolName, deps = {}) {
684
+ return async (args) => {
685
+ const bundleRoot = (0, identity_1.getAgentRoot)();
686
+ const confirmationToken = typeof args.confirmation_token === "string"
687
+ ? args.confirmation_token
688
+ : undefined;
689
+ const now = deps.now ?? Date.now;
690
+ const config = bundleSyncConfig(bundleRoot);
691
+ const remote = config.remote;
692
+ (0, runtime_1.emitNervesEvent)({
693
+ component: "repertoire",
694
+ event: "repertoire.bundle_sync_tool_start",
695
+ message: "syncing bundle from a tool",
696
+ meta: { bundleRoot, tool: toolName, remote },
697
+ });
698
+ const finish = (ok, payload) => {
699
+ (0, runtime_1.emitNervesEvent)({
700
+ component: "repertoire",
701
+ event: "repertoire.bundle_sync_tool_end",
702
+ message: "bundle sync tool finished",
703
+ meta: { bundleRoot, tool: toolName, ok, ...payload },
704
+ });
705
+ return json({ ok, ...payload });
706
+ };
707
+ const refuse = (message, error) => {
708
+ (0, runtime_1.emitNervesEvent)({
709
+ level: "warn",
710
+ component: "repertoire",
711
+ event: "repertoire.bundle_push_refused",
712
+ message,
713
+ meta: { bundleRoot, tool: toolName },
714
+ });
715
+ return finish(false, { error, kind: "confirmation_required" });
716
+ };
717
+ if (!isGitRepo(bundleRoot)) {
718
+ return finish(false, { error: "bundle is not a git repo" });
719
+ }
720
+ const remotes = listRemotes(bundleRoot);
721
+ if (!remotes.includes(remote)) {
722
+ return finish(false, { error: `remote "${remote}" not configured — run bundle_add_remote first` });
723
+ }
724
+ if (!hasHead(bundleRoot)) {
725
+ return finish(false, { error: "bundle has no commits — run bundle_do_first_commit first" });
726
+ }
727
+ // Directive D: first push to a remote requires the agent to have
728
+ // previously called bundle_first_push_review and obtained a
729
+ // confirmation token. This forces a PII-review gate between
730
+ // "bundle built locally" and "bundle contents on the internet".
731
+ const probe = await probeFirstPush(bundleRoot, remote, config.branch);
732
+ if (probe.kind === "unreachable") {
733
+ return finish(false, { error: `I couldn't reach GitHub to check whether this would be my first push, so I didn't sync: ${probe.error}`, kind: "remote_unreachable" });
734
+ }
735
+ const isFirstPush = probe.kind === "first";
736
+ if (isFirstPush) {
737
+ if (!confirmationToken) {
738
+ return refuse(`${toolName} refused: first push requires confirmation token`, `refused: first push requires a confirmation token — call bundle_first_push_review, show the warning to the user, and pass the returned confirmationToken to ${toolName}`);
739
+ }
740
+ pruneExpiredTokens(now());
741
+ const entry = _confirmationTokens.get(confirmationToken);
742
+ if (!entry) {
743
+ return refuse(`${toolName} refused: confirmation token invalid or expired`, "refused: confirmation token invalid or expired — call bundle_first_push_review again");
744
+ }
745
+ if (entry.bundleRoot !== bundleRoot) {
746
+ return refuse(`${toolName} refused: confirmation token bound to a different bundle`, "refused: confirmation token was issued for a different bundle");
747
+ }
748
+ (0, runtime_1.emitNervesEvent)({
749
+ component: "repertoire",
750
+ event: "repertoire.bundle_push_first_push_confirmed",
751
+ message: "first push confirmed by valid token",
752
+ meta: { bundleRoot },
753
+ });
754
+ }
755
+ const agentName = path.basename(bundleRoot).replace(/\.ouro$/, "");
756
+ // The valid token is the owner's recorded yes, which sync needs before a first push to an empty remote.
757
+ const result = await (0, sync_1.syncNow)(bundleRoot, config, agentName, BUNDLE_TOOL_SYNC_WAIT_MS, { firstPushApproved: isFirstPush });
758
+ const where = { remote, branch: config.branch, firstPush: isFirstPush };
759
+ if (result.paused)
760
+ return finish(false, { ...where, paused: true, pausedUntil: result.pausedUntil, error: `sync paused until ${result.pausedUntil}` });
761
+ if (result.busy)
762
+ return finish(false, { ...where, busy: true, holderPid: result.holderPid, error: result.error });
763
+ // One-shot: the token is spent once sync actually ran, not on a busy or paused refusal.
764
+ if (confirmationToken !== undefined && isFirstPush)
765
+ _confirmationTokens.delete(confirmationToken);
766
+ if (!result.ok) {
767
+ const failure = readPendingFailure(bundleRoot);
768
+ return finish(false, {
769
+ ...where,
770
+ error: result.error,
771
+ ...(failure?.classification ? { kind: failure.classification } : {}),
772
+ ...(failure?.conflictFiles && failure.conflictFiles.length > 0 ? { conflictFiles: failure.conflictFiles } : {}),
773
+ });
774
+ }
775
+ return finish(true, where);
776
+ };
777
+ }
778
+ /** The pending-sync record sync wrote for this failure, when readable. */
779
+ function readPendingFailure(bundleRoot) {
780
+ try {
781
+ return JSON.parse(fs.readFileSync(path.join(bundleRoot, "state", "pending-sync.json"), "utf-8"));
782
+ }
783
+ catch {
784
+ return null;
785
+ }
786
+ }
787
+ const pushHandler = makeSyncHandler("bundle_push");
788
+ const pullRebaseHandler = makeSyncHandler("bundle_pull_rebase");
789
+ // ─── registry ──────────────────────────────────────────────────────────
790
+ exports.bundleToolDefinitions = [
791
+ {
792
+ tool: {
793
+ type: "function",
794
+ function: {
795
+ name: "bundle_check_sync_status",
796
+ description: "Check the git sync status of my bundle. Returns whether my bundle is a git repo, whether it has a remote, the remote URL, the dirty file count, ahead/behind counts, and the structured bundleStateIssues array.",
797
+ parameters: { type: "object", properties: {} },
798
+ },
799
+ },
800
+ handler: checkSyncStatusHandler,
801
+ },
802
+ {
803
+ tool: {
804
+ type: "function",
805
+ function: {
806
+ name: "bundle_init_git",
807
+ description: "Initialize my bundle as a git repo. Refuses if a .git directory already exists unless I pass force: true. Also writes a minimal .gitignore that excludes state/. Safe to run — does not touch any existing files.",
808
+ parameters: {
809
+ type: "object",
810
+ properties: {
811
+ force: { type: "boolean", description: "Re-run git init even if .git already exists. Default false." },
812
+ },
813
+ },
814
+ },
815
+ },
816
+ handler: initGitHandler,
817
+ riskProfile: { mutates: "durable_state_write", risk: "high", reason: "initializes bundle git state" },
818
+ },
819
+ {
820
+ tool: {
821
+ type: "function",
822
+ function: {
823
+ name: "bundle_add_remote",
824
+ description: "Add a git remote to my bundle. Accepts https or git@ URLs. Refuses if the named remote already exists unless I pass force: true. On force, updates the URL via git remote set-url.",
825
+ parameters: {
826
+ type: "object",
827
+ properties: {
828
+ url: { type: "string", description: "The remote URL (https://... or git@...:...)." },
829
+ name: { type: "string", description: "Remote name. Defaults to 'origin'." },
830
+ force: { type: "boolean", description: "Overwrite an existing remote. Default false." },
831
+ },
832
+ required: ["url"],
833
+ },
834
+ },
835
+ },
836
+ handler: addRemoteHandler,
837
+ riskProfile: { mutates: "durable_state_write", risk: "high", reason: "updates bundle git remote configuration" },
838
+ },
839
+ {
840
+ tool: {
841
+ type: "function",
842
+ function: {
843
+ name: "bundle_list_first_commit",
844
+ description: "List all untracked files in my bundle (honoring .gitignore), grouped by top-level directory with per-file sizes. Refuses if the bundle is not a git repo or already has commits. Use this before bundle_do_first_commit to review what would be committed.",
845
+ parameters: { type: "object", properties: {} },
846
+ },
847
+ },
848
+ handler: listFirstCommitHandler,
849
+ },
850
+ {
851
+ tool: {
852
+ type: "function",
853
+ function: {
854
+ name: "bundle_do_first_commit",
855
+ description: "Make the first commit in my bundle. If I pass an explicit files array, stages only those files. If I omit files, stages everything bundle_list_first_commit would return. Refuses on empty array, on paths outside the bundle root, or if HEAD already exists.",
856
+ parameters: {
857
+ type: "object",
858
+ properties: {
859
+ files: { type: "array", items: { type: "string" }, description: "Optional explicit list of relative paths to stage. Omit to stage everything." },
860
+ message: { type: "string", description: "Commit message. Defaults to 'initial: import pre-sync bundle state'." },
861
+ },
862
+ },
863
+ },
864
+ },
865
+ handler: doFirstCommitHandler,
866
+ riskProfile: { mutates: "durable_state_write", risk: "high", reason: "creates a bundle git commit" },
867
+ },
868
+ {
869
+ tool: {
870
+ type: "function",
871
+ function: {
872
+ name: "bundle_first_push_review",
873
+ description: "Review my bundle for PII exposure before the first push to a new remote. Enumerates PII-bearing directories (friends, Desk record, Arc, etc.) with per-directory counts, probes the remote URL for GitHub public/private visibility, and returns a first-person warning text I must show the human plus a confirmationToken I must pass to bundle_push or bundle_pull_rebase on first push. Required before the first push to any new remote.",
874
+ parameters: { type: "object", properties: {} },
875
+ },
876
+ },
877
+ handler: firstPushReviewHandler,
878
+ },
879
+ {
880
+ tool: {
881
+ type: "function",
882
+ function: {
883
+ name: "bundle_push",
884
+ description: "Sync my bundle with its remote now.",
885
+ parameters: {
886
+ type: "object",
887
+ properties: {
888
+ confirmation_token: { type: "string", description: "Opaque token from bundle_first_push_review. Required on the first push to a new remote; ignored on subsequent pushes." },
889
+ },
890
+ },
891
+ },
892
+ },
893
+ handler: pushHandler,
894
+ riskProfile: { mutates: "external_side_effect", risk: "high", reason: "pushes bundle state to a remote" },
895
+ },
896
+ {
897
+ tool: {
898
+ type: "function",
899
+ function: {
900
+ name: "bundle_pull_rebase",
901
+ description: "Sync my bundle with its remote now.",
902
+ parameters: {
903
+ type: "object",
904
+ properties: {
905
+ confirmation_token: { type: "string", description: "Opaque token from bundle_first_push_review. Required on the first push to a new remote; ignored on subsequent pushes." },
906
+ },
907
+ },
908
+ },
909
+ },
910
+ handler: pullRebaseHandler,
911
+ riskProfile: {
912
+ mutates: ["durable_state_write", "external_side_effect"],
913
+ risk: "high",
914
+ reason: "syncs bundle state with a remote",
915
+ },
916
+ },
917
+ ];