@ouro.bot/cli 0.1.0-alpha.9 → 0.1.0-alpha.900

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 (712) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -176
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/SerpentGuide.ouro/agent.json +83 -0
  11. package/SerpentGuide.ouro/psyche/SOUL.md +25 -0
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
  13. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  14. package/assets/bluebubbles-host +264 -0
  15. package/assets/ouroboros.png +0 -0
  16. package/assets/sanctuary-host-launcher.sh +16 -0
  17. package/changelog.json +6224 -0
  18. package/deploy/unraid/Dockerfile +58 -0
  19. package/deploy/unraid/README.txt +2997 -0
  20. package/deploy/unraid/audit-container-spec.sh +4 -0
  21. package/deploy/unraid/container-runtime.json +1 -0
  22. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  23. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  24. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  25. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  26. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  27. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  28. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  29. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  30. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  31. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  32. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  33. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  34. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  35. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1254 -0
  36. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  37. package/deploy/unraid/sanctuary-replay-gate.mjs +1614 -0
  38. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  39. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
  40. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  41. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  42. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  43. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  44. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  45. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  46. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  47. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  48. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +27 -0
  52. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  53. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  54. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  55. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  56. package/deploy/unraid/sanctuary.xml +30 -0
  57. package/dist/a2a/card.js +57 -0
  58. package/dist/a2a/client.js +250 -0
  59. package/dist/a2a/config.js +50 -0
  60. package/dist/a2a/delegated-command-grants.js +93 -0
  61. package/dist/a2a/delegated-command.js +197 -0
  62. package/dist/a2a/delegation-stores.js +56 -0
  63. package/dist/a2a/did-resolution.js +93 -0
  64. package/dist/a2a/escalation-grants.js +84 -0
  65. package/dist/a2a/escalation-wiring.js +60 -0
  66. package/dist/a2a/identity.js +258 -0
  67. package/dist/a2a/inbound-share.js +110 -0
  68. package/dist/a2a/mission-result-wire.js +196 -0
  69. package/dist/a2a/onboarding.js +133 -0
  70. package/dist/a2a/operator-trust.js +382 -0
  71. package/dist/a2a/outbox-client.js +57 -0
  72. package/dist/a2a/outbox-store.js +188 -0
  73. package/dist/a2a/outbox-wire.js +95 -0
  74. package/dist/a2a/pin-store.js +132 -0
  75. package/dist/a2a/replay-grant-holders.js +33 -0
  76. package/dist/a2a/replay-harness.js +188 -0
  77. package/dist/a2a/resolution-proof.js +53 -0
  78. package/dist/a2a/sealed-chat.js +113 -0
  79. package/dist/a2a/seen-ledger.js +120 -0
  80. package/dist/a2a/server.js +771 -0
  81. package/dist/a2a/task-store.js +69 -0
  82. package/dist/a2a/transport.js +45 -0
  83. package/dist/a2a/trust-commands.js +203 -0
  84. package/dist/a2a/trusted-files.js +185 -0
  85. package/dist/a2a/types.js +3 -0
  86. package/dist/arc/attention-types.js +8 -0
  87. package/dist/arc/cares.js +360 -0
  88. package/dist/arc/episodes.js +118 -0
  89. package/dist/arc/evolution.js +490 -0
  90. package/dist/arc/flight-recorder.js +1034 -0
  91. package/dist/arc/intentions.js +134 -0
  92. package/dist/arc/json-store.js +117 -0
  93. package/dist/arc/obligations.js +386 -0
  94. package/dist/arc/packets.js +336 -0
  95. package/dist/arc/presence.js +185 -0
  96. package/dist/arc/task-lifecycle.js +57 -0
  97. package/dist/commerce/store.js +755 -0
  98. package/dist/commerce/types.js +3 -0
  99. package/dist/heart/active-work.js +1009 -0
  100. package/dist/heart/agent-entry.js +252 -3
  101. package/dist/heart/approval-files.js +113 -0
  102. package/dist/heart/approval-store.js +960 -0
  103. package/dist/heart/attachments/image-normalize.js +194 -0
  104. package/dist/heart/attachments/materialize.js +97 -0
  105. package/dist/heart/attachments/originals.js +88 -0
  106. package/dist/heart/attachments/render.js +29 -0
  107. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  108. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  109. package/dist/heart/attachments/sources/index.js +18 -0
  110. package/dist/heart/attachments/sources/telegram.js +71 -0
  111. package/dist/heart/attachments/store.js +132 -0
  112. package/dist/heart/attachments/types.js +93 -0
  113. package/dist/heart/auth/auth-flow.js +495 -0
  114. package/dist/heart/autonomy-budget.js +478 -0
  115. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  116. package/dist/heart/awaiting/await-alert.js +152 -0
  117. package/dist/heart/awaiting/await-expiry.js +143 -0
  118. package/dist/heart/awaiting/await-loader.js +91 -0
  119. package/dist/heart/awaiting/await-parser.js +152 -0
  120. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  121. package/dist/heart/awaiting/await-scheduler.js +391 -0
  122. package/dist/heart/background-operations.js +281 -0
  123. package/dist/heart/bridges/manager.js +478 -0
  124. package/dist/heart/bridges/state-machine.js +135 -0
  125. package/dist/heart/bridges/store.js +135 -0
  126. package/dist/heart/bundle-state.js +168 -0
  127. package/dist/heart/commitments.js +135 -0
  128. package/dist/heart/config-registry.js +331 -0
  129. package/dist/heart/config.js +225 -137
  130. package/dist/heart/context-loss-gauntlet.js +387 -0
  131. package/dist/heart/context-loss-sentinel.js +1157 -0
  132. package/dist/heart/core.js +2442 -343
  133. package/dist/heart/cross-chat-delivery.js +133 -0
  134. package/dist/heart/daemon/agent-config-check.js +451 -0
  135. package/dist/heart/daemon/agent-discovery.js +355 -0
  136. package/dist/heart/daemon/agent-home.js +319 -0
  137. package/dist/heart/daemon/agent-service.js +542 -0
  138. package/dist/heart/daemon/agentic-repair.js +547 -0
  139. package/dist/heart/daemon/await-private-wake.js +59 -0
  140. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  141. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  142. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  143. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  144. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  145. package/dist/heart/daemon/cadence.js +180 -0
  146. package/dist/heart/daemon/cli-defaults.js +859 -0
  147. package/dist/heart/daemon/cli-desk.js +322 -0
  148. package/dist/heart/daemon/cli-exec.js +9003 -0
  149. package/dist/heart/daemon/cli-help.js +729 -0
  150. package/dist/heart/daemon/cli-parse.js +3140 -0
  151. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  152. package/dist/heart/daemon/cli-render.js +804 -0
  153. package/dist/heart/daemon/cli-types.js +8 -0
  154. package/dist/heart/daemon/connect-bay.js +323 -0
  155. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  156. package/dist/heart/daemon/container-healthcheck.js +112 -0
  157. package/dist/heart/daemon/container-runtime.js +97 -0
  158. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  159. package/dist/heart/daemon/container-spec-auditor.js +235 -0
  160. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  161. package/dist/heart/daemon/daemon-cli.js +30 -882
  162. package/dist/heart/daemon/daemon-entry.js +1002 -13
  163. package/dist/heart/daemon/daemon-health.js +186 -0
  164. package/dist/heart/daemon/daemon-rollup.js +57 -0
  165. package/dist/heart/daemon/daemon-runtime-sync.js +287 -0
  166. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  167. package/dist/heart/daemon/daemon.js +2213 -28
  168. package/dist/heart/daemon/dns-workflow.js +394 -0
  169. package/dist/heart/daemon/doctor-types.js +8 -0
  170. package/dist/heart/daemon/doctor.js +1755 -0
  171. package/dist/heart/daemon/freshness.js +345 -0
  172. package/dist/heart/daemon/habit-private-wake.js +61 -0
  173. package/dist/heart/daemon/health-monitor.js +142 -11
  174. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  175. package/dist/heart/daemon/hooks/bundle-meta.js +226 -0
  176. package/dist/heart/daemon/http-health-probe.js +80 -0
  177. package/dist/heart/daemon/human-command-screens.js +234 -0
  178. package/dist/heart/daemon/human-readiness.js +114 -0
  179. package/dist/heart/daemon/inner-status.js +78 -0
  180. package/dist/heart/daemon/interactive-repair.js +394 -0
  181. package/dist/heart/daemon/launchd.js +188 -0
  182. package/dist/heart/daemon/log-tailer.js +82 -12
  183. package/dist/heart/daemon/logs-prune.js +132 -0
  184. package/dist/heart/daemon/mcp-canary.js +524 -0
  185. package/dist/heart/daemon/message-router.js +80 -11
  186. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  187. package/dist/heart/daemon/os-cron-deps.js +135 -0
  188. package/dist/heart/daemon/os-cron.js +22 -14
  189. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  190. package/dist/heart/daemon/ouro-entry.js +3 -1
  191. package/dist/heart/daemon/plugin-cli.js +432 -0
  192. package/dist/heart/daemon/process-manager.js +766 -54
  193. package/dist/heart/daemon/provider-discovery.js +137 -0
  194. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  195. package/dist/heart/daemon/prunable-bundle.js +144 -0
  196. package/dist/heart/daemon/pulse.js +511 -0
  197. package/dist/heart/daemon/readiness-repair.js +365 -0
  198. package/dist/heart/daemon/run-hooks.js +39 -0
  199. package/dist/heart/daemon/runtime-logging.js +92 -16
  200. package/dist/heart/daemon/runtime-metadata.js +191 -0
  201. package/dist/{repertoire/tasks/lifecycle.js → heart/daemon/runtime-mode.js} +37 -39
  202. package/dist/heart/daemon/safe-mode.js +161 -0
  203. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  204. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  205. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  206. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  207. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  208. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  209. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  210. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  211. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1267 -0
  212. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  213. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  214. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  215. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  216. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  217. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  218. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  219. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  220. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  221. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  222. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  223. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  224. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  225. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  226. package/dist/heart/daemon/sense-manager.js +975 -0
  227. package/dist/heart/daemon/session-id-resolver.js +131 -0
  228. package/dist/heart/daemon/skill-management-installer.js +94 -0
  229. package/dist/heart/daemon/socket-client.js +370 -0
  230. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  231. package/dist/heart/daemon/startup-tui.js +339 -0
  232. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  233. package/dist/heart/daemon/task-scheduler.js +117 -39
  234. package/dist/heart/daemon/terminal-ui.js +499 -0
  235. package/dist/heart/daemon/thoughts.js +591 -0
  236. package/dist/heart/daemon/up-progress.js +366 -0
  237. package/dist/heart/daemon/vault-items.js +56 -0
  238. package/dist/heart/delegation.js +59 -0
  239. package/dist/heart/external-events/router.js +1516 -0
  240. package/dist/heart/failure-reports.js +335 -0
  241. package/dist/heart/file-lock.js +109 -0
  242. package/dist/heart/frontend-approval-runtime.js +506 -0
  243. package/dist/heart/frontend-journal.js +215 -0
  244. package/dist/heart/frontend-session-service.js +237 -0
  245. package/dist/heart/frontend-socket-client.js +164 -0
  246. package/dist/heart/frontend-socket.js +400 -0
  247. package/dist/heart/habits/habit-cancel.js +810 -0
  248. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  249. package/dist/heart/habits/habit-migration.js +194 -0
  250. package/dist/heart/habits/habit-parser.js +278 -0
  251. package/dist/heart/habits/habit-runtime-state.js +93 -0
  252. package/dist/heart/habits/habit-scheduler.js +653 -0
  253. package/dist/heart/habits/habit-session-summary.js +318 -0
  254. package/dist/heart/habits/habit-session.js +636 -0
  255. package/dist/heart/{daemon → hatch}/hatch-animation.js +10 -3
  256. package/dist/heart/{daemon → hatch}/hatch-flow.js +57 -139
  257. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  258. package/dist/heart/hatch/specialist-orchestrator.js +129 -0
  259. package/dist/heart/hatch/specialist-prompt.js +102 -0
  260. package/dist/heart/hatch/specialist-tools.js +318 -0
  261. package/dist/heart/identity.js +312 -67
  262. package/dist/heart/kept-notes.js +289 -0
  263. package/dist/heart/kicks.js +2 -20
  264. package/dist/heart/machine-identity.js +175 -0
  265. package/dist/heart/mail-import-discovery.js +356 -0
  266. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  267. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  268. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  269. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  270. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  271. package/dist/heart/mailbox/mailbox-http.js +99 -0
  272. package/dist/heart/mailbox/mailbox-read.js +39 -0
  273. package/dist/heart/mailbox/mailbox-types.js +27 -0
  274. package/dist/heart/mailbox/mailbox-view.js +197 -0
  275. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  276. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  277. package/dist/heart/mailbox/readers/mail.js +375 -0
  278. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  279. package/dist/heart/mailbox/readers/sessions.js +231 -0
  280. package/dist/heart/mailbox/readers/shared.js +111 -0
  281. package/dist/heart/mcp/mcp-server.js +696 -0
  282. package/dist/heart/migrate-config.js +100 -0
  283. package/dist/heart/model-capabilities.js +59 -0
  284. package/dist/heart/orientation-frame.js +345 -0
  285. package/dist/heart/platform.js +81 -0
  286. package/dist/heart/primitives.js +1 -1
  287. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  288. package/dist/heart/private-runtime/index.js +18 -0
  289. package/dist/heart/private-runtime/ledger.js +221 -0
  290. package/dist/heart/private-runtime/policy.js +260 -0
  291. package/dist/heart/private-runtime/types.js +2 -0
  292. package/dist/heart/progress-story.js +42 -0
  293. package/dist/heart/provider-attempt.js +137 -0
  294. package/dist/heart/provider-binding-resolver.js +273 -0
  295. package/dist/heart/provider-credentials.js +449 -0
  296. package/dist/heart/provider-failover.js +311 -0
  297. package/dist/heart/provider-models.js +96 -0
  298. package/dist/heart/provider-ping.js +265 -0
  299. package/dist/heart/provider-readiness-cache.js +119 -0
  300. package/dist/heart/provider-visibility.js +188 -0
  301. package/dist/heart/providers/anthropic-token.js +131 -0
  302. package/dist/heart/providers/anthropic.js +236 -58
  303. package/dist/heart/providers/azure.js +104 -13
  304. package/dist/heart/providers/error-classification.js +127 -0
  305. package/dist/heart/providers/github-copilot.js +145 -0
  306. package/dist/heart/providers/minimax-vlm.js +189 -0
  307. package/dist/heart/providers/minimax.js +29 -7
  308. package/dist/heart/providers/openai-codex-token.js +349 -0
  309. package/dist/heart/providers/openai-codex.js +63 -39
  310. package/dist/heart/providers/openai-compatible.js +177 -0
  311. package/dist/heart/reply-style.js +56 -0
  312. package/dist/heart/run-ledger.js +247 -0
  313. package/dist/heart/runtime-capability-check.js +170 -0
  314. package/dist/heart/runtime-credentials.js +607 -0
  315. package/dist/heart/runtime-cwd.js +87 -0
  316. package/dist/heart/sense-truth.js +81 -0
  317. package/dist/heart/session-activity.js +237 -0
  318. package/dist/heart/session-events.js +1504 -0
  319. package/dist/heart/session-playback-cli-main.js +5 -0
  320. package/dist/heart/session-playback-cli.js +36 -0
  321. package/dist/heart/session-playback.js +231 -0
  322. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  323. package/dist/heart/session-redaction-repair.js +552 -0
  324. package/dist/heart/session-stats-cli-main.js +5 -0
  325. package/dist/heart/session-stats.js +183 -0
  326. package/dist/heart/session-transcript.js +133 -0
  327. package/dist/heart/shepherd-config.js +113 -0
  328. package/dist/heart/source-grounding.js +283 -0
  329. package/dist/heart/start-of-turn-packet.js +372 -0
  330. package/dist/heart/steward-policy.js +656 -0
  331. package/dist/heart/streaming.js +682 -207
  332. package/dist/heart/structured-output.js +196 -0
  333. package/dist/heart/sync-classification.js +176 -0
  334. package/dist/heart/sync.js +505 -0
  335. package/dist/heart/target-resolution.js +127 -0
  336. package/dist/heart/tempo.js +93 -0
  337. package/dist/heart/temporal-view.js +41 -0
  338. package/dist/heart/timeouts.js +101 -0
  339. package/dist/heart/tool-activity-callbacks.js +59 -0
  340. package/dist/heart/tool-approval.js +382 -0
  341. package/dist/heart/tool-description.js +155 -0
  342. package/dist/heart/tool-friction.js +55 -0
  343. package/dist/heart/tool-loop.js +206 -0
  344. package/dist/heart/turn-context.js +494 -0
  345. package/dist/heart/turn-coordinator.js +28 -0
  346. package/dist/heart/turn-execution-lease.js +30 -0
  347. package/dist/heart/versioning/ouro-bot-global-installer.js +129 -0
  348. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  349. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  350. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  351. package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
  352. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  353. package/dist/heart/versioning/staged-restart.js +146 -0
  354. package/dist/heart/versioning/update-checker.js +116 -0
  355. package/dist/heart/versioning/update-hooks.js +154 -0
  356. package/dist/heart/versioning/version-intent.js +114 -0
  357. package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
  358. package/dist/heart/work-card.js +380 -0
  359. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  360. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  361. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  362. package/dist/mailbox-ui/index.html +16 -0
  363. package/dist/mailroom/attention.js +167 -0
  364. package/dist/mailroom/autonomy.js +209 -0
  365. package/dist/mailroom/blob-store.js +889 -0
  366. package/dist/mailroom/body-cache.js +61 -0
  367. package/dist/mailroom/cache-sync-cli.js +58 -0
  368. package/dist/mailroom/core.js +803 -0
  369. package/dist/mailroom/entry.js +160 -0
  370. package/dist/mailroom/file-store.js +568 -0
  371. package/dist/mailroom/hosted-cache-sync.js +384 -0
  372. package/dist/mailroom/mbox-import.js +393 -0
  373. package/dist/mailroom/migration.js +164 -0
  374. package/dist/mailroom/outbound.js +380 -0
  375. package/dist/mailroom/policy.js +263 -0
  376. package/dist/mailroom/reader.js +292 -0
  377. package/dist/mailroom/search-cache.js +513 -0
  378. package/dist/mailroom/search-relevance.js +319 -0
  379. package/dist/mailroom/smtp-ingress.js +176 -0
  380. package/dist/mailroom/source-state.js +176 -0
  381. package/dist/mailroom/thread.js +109 -0
  382. package/dist/mailroom/travel-extract.js +89 -0
  383. package/dist/mind/bundle-manifest.js +93 -1
  384. package/dist/mind/context.js +318 -104
  385. package/dist/mind/desk-section.js +362 -0
  386. package/dist/mind/diary-integrity.js +60 -0
  387. package/dist/mind/{memory.js → diary.js} +90 -98
  388. package/dist/mind/embedding-provider.js +60 -0
  389. package/dist/mind/file-state.js +179 -0
  390. package/dist/mind/first-impressions.js +16 -2
  391. package/dist/mind/{associative-recall.js → note-search.js} +61 -60
  392. package/dist/mind/obligation-steering.js +227 -0
  393. package/dist/mind/pending.js +103 -10
  394. package/dist/mind/phrases.js +1 -0
  395. package/dist/mind/prompt-budget.js +479 -0
  396. package/dist/mind/prompt-refresh.js +3 -2
  397. package/dist/mind/prompt.js +1417 -140
  398. package/dist/mind/provenance-trust.js +26 -0
  399. package/dist/mind/record-paths.js +312 -0
  400. package/dist/mind/scrutiny.js +173 -0
  401. package/dist/mind/session-transaction.js +564 -0
  402. package/dist/mind/token-estimate.js +8 -12
  403. package/dist/nerves/cli-logging.js +22 -3
  404. package/dist/nerves/coverage/audit-rules.js +15 -6
  405. package/dist/nerves/coverage/audit.js +28 -2
  406. package/dist/nerves/coverage/cli.js +1 -1
  407. package/dist/nerves/coverage/contract.js +5 -5
  408. package/dist/nerves/coverage/file-completeness.js +139 -5
  409. package/dist/nerves/coverage/run-artifacts.js +56 -36
  410. package/dist/nerves/coverage/source-scanner.js +4 -4
  411. package/dist/nerves/event-buffer.js +111 -0
  412. package/dist/nerves/index.js +305 -9
  413. package/dist/nerves/observation.js +20 -0
  414. package/dist/nerves/redact.js +79 -0
  415. package/dist/nerves/review/cli-main.js +5 -0
  416. package/dist/nerves/review/cli.js +156 -0
  417. package/dist/nerves/review/core.js +159 -0
  418. package/dist/nerves/runtime.js +17 -1
  419. package/dist/repertoire/ado-client.js +17 -56
  420. package/dist/repertoire/ado-semantic.js +16 -10
  421. package/dist/repertoire/api-client.js +97 -0
  422. package/dist/repertoire/bitwarden-store.js +1191 -0
  423. package/dist/repertoire/bundle-templates.js +71 -0
  424. package/dist/repertoire/bw-installer.js +180 -0
  425. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  426. package/dist/repertoire/coding/context-pack.js +331 -0
  427. package/dist/repertoire/coding/feedback.js +322 -0
  428. package/dist/repertoire/coding/index.js +18 -3
  429. package/dist/repertoire/coding/manager.js +228 -14
  430. package/dist/repertoire/coding/spawner.js +61 -14
  431. package/dist/repertoire/coding/tools.js +279 -12
  432. package/dist/repertoire/coding/workbench-client.js +272 -0
  433. package/dist/repertoire/coding/workbench-manager.js +346 -0
  434. package/dist/repertoire/commerce-errors.js +109 -0
  435. package/dist/repertoire/commerce-self-test.js +156 -0
  436. package/dist/repertoire/credential-access.js +182 -0
  437. package/dist/repertoire/data/ado-endpoints.json +188 -0
  438. package/dist/repertoire/desk/classifier.js +362 -0
  439. package/dist/repertoire/duffel-client.js +185 -0
  440. package/dist/repertoire/github-client.js +14 -55
  441. package/dist/repertoire/graph-client.js +11 -52
  442. package/dist/repertoire/guardrails.js +1232 -0
  443. package/dist/repertoire/house-sweep.js +469 -0
  444. package/dist/repertoire/mcp-client.js +307 -0
  445. package/dist/repertoire/mcp-manager.js +483 -0
  446. package/dist/repertoire/mcp-tools.js +132 -0
  447. package/dist/repertoire/mcp-write-guard.js +46 -0
  448. package/dist/repertoire/plugin-mcp.js +175 -0
  449. package/dist/repertoire/plugins.js +253 -0
  450. package/dist/repertoire/relationship-authorization.js +322 -0
  451. package/dist/repertoire/sanctuary-container-policy.js +46 -0
  452. package/dist/repertoire/shell-sessions.js +134 -0
  453. package/dist/repertoire/skills.js +45 -24
  454. package/dist/repertoire/stripe-client.js +131 -0
  455. package/dist/repertoire/tool-arguments.js +182 -0
  456. package/dist/repertoire/tool-results.js +29 -0
  457. package/dist/repertoire/tools-a2a.js +699 -0
  458. package/dist/repertoire/tools-attachments.js +322 -0
  459. package/dist/repertoire/tools-awaiting.js +870 -0
  460. package/dist/repertoire/tools-base.js +84 -706
  461. package/dist/repertoire/tools-bluebubbles.js +95 -0
  462. package/dist/repertoire/tools-bridge.js +144 -0
  463. package/dist/repertoire/tools-bundle.js +993 -0
  464. package/dist/repertoire/tools-commerce.js +253 -0
  465. package/dist/repertoire/tools-config.js +186 -0
  466. package/dist/repertoire/tools-continuity.js +575 -0
  467. package/dist/repertoire/tools-credential.js +383 -0
  468. package/dist/repertoire/tools-escalation.js +84 -0
  469. package/dist/repertoire/tools-evolution.js +527 -0
  470. package/dist/repertoire/tools-files.js +344 -0
  471. package/dist/repertoire/tools-flight.js +290 -0
  472. package/dist/repertoire/tools-flow.js +119 -0
  473. package/dist/repertoire/tools-github.js +3 -8
  474. package/dist/repertoire/tools-habits.js +103 -0
  475. package/dist/repertoire/tools-house-care.js +174 -0
  476. package/dist/repertoire/tools-mail.js +1828 -0
  477. package/dist/repertoire/tools-notes.js +496 -0
  478. package/dist/repertoire/tools-obligations.js +182 -0
  479. package/dist/repertoire/tools-orientation.js +31 -0
  480. package/dist/repertoire/tools-record.js +482 -0
  481. package/dist/repertoire/tools-rsvp.js +139 -0
  482. package/dist/repertoire/tools-runtime.js +238 -0
  483. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  484. package/dist/repertoire/tools-session.js +1133 -0
  485. package/dist/repertoire/tools-shell.js +149 -0
  486. package/dist/repertoire/tools-shepherd.js +180 -0
  487. package/dist/repertoire/tools-steward-policy.js +147 -0
  488. package/dist/repertoire/tools-stripe.js +224 -0
  489. package/dist/repertoire/tools-surface.js +369 -0
  490. package/dist/repertoire/tools-teams.js +67 -61
  491. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  492. package/dist/repertoire/tools-travel.js +125 -0
  493. package/dist/repertoire/tools-trip.js +982 -0
  494. package/dist/repertoire/tools-unraid.js +556 -0
  495. package/dist/repertoire/tools-user-profile.js +146 -0
  496. package/dist/repertoire/tools-vault.js +40 -0
  497. package/dist/repertoire/tools-voice-local.js +198 -0
  498. package/dist/repertoire/tools-voice.js +145 -0
  499. package/dist/repertoire/tools.js +534 -123
  500. package/dist/repertoire/travel-api-client.js +360 -0
  501. package/dist/repertoire/unraid-client.js +155 -0
  502. package/dist/repertoire/unraid-restart.js +339 -0
  503. package/dist/repertoire/user-profile.js +131 -0
  504. package/dist/repertoire/vault-setup.js +246 -0
  505. package/dist/repertoire/vault-unlock.js +686 -0
  506. package/dist/rsvp/aisleplanner-client.js +354 -0
  507. package/dist/rsvp/cli.js +926 -0
  508. package/dist/rsvp/config.js +327 -0
  509. package/dist/rsvp/cutover.js +433 -0
  510. package/dist/rsvp/diagnostics.js +232 -0
  511. package/dist/rsvp/diff-renderer.js +176 -0
  512. package/dist/rsvp/habit-policy.js +110 -0
  513. package/dist/rsvp/habit-stage.js +123 -0
  514. package/dist/rsvp/incident-bundle.js +97 -0
  515. package/dist/rsvp/migration.js +204 -0
  516. package/dist/rsvp/native-habit-runner.js +630 -0
  517. package/dist/rsvp/outbound-state.js +628 -0
  518. package/dist/rsvp/query.js +118 -0
  519. package/dist/rsvp/replay.js +233 -0
  520. package/dist/rsvp/snapshot.js +232 -0
  521. package/dist/rsvp/spend-ledger.js +175 -0
  522. package/dist/scripts/claude-code-hook.js +41 -0
  523. package/dist/scripts/claude-code-stop-hook.js +47 -0
  524. package/dist/senses/a2a-entry.js +132 -0
  525. package/dist/senses/acp-server.js +386 -0
  526. package/dist/senses/attention-queue.js +186 -0
  527. package/dist/senses/await-turn-message.js +65 -0
  528. package/dist/senses/bluebubbles/active-turns.js +216 -0
  529. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  530. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  531. package/dist/senses/bluebubbles/client.js +799 -0
  532. package/dist/senses/bluebubbles/context-packet.js +207 -0
  533. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  534. package/dist/senses/bluebubbles/entry.js +90 -0
  535. package/dist/senses/bluebubbles/inbound-log.js +127 -0
  536. package/dist/senses/bluebubbles/index.js +3841 -0
  537. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  538. package/dist/senses/bluebubbles/media.js +389 -0
  539. package/dist/senses/bluebubbles/model.js +392 -0
  540. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +57 -6
  541. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  542. package/dist/senses/bluebubbles/processed-log.js +133 -0
  543. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  544. package/dist/senses/bluebubbles/replay.js +284 -0
  545. package/dist/senses/bluebubbles/runtime-state.js +137 -0
  546. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  547. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  548. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  549. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  550. package/dist/senses/cli/bracketed-paste.js +82 -0
  551. package/dist/senses/cli/image-paste.js +287 -0
  552. package/dist/senses/cli/image-ref-navigation.js +75 -0
  553. package/dist/senses/cli/ink-app.js +156 -0
  554. package/dist/senses/cli/inline-diff.js +64 -0
  555. package/dist/senses/cli/input-keys.js +174 -0
  556. package/dist/senses/cli/kill-ring.js +86 -0
  557. package/dist/senses/cli/message-list.js +51 -0
  558. package/dist/senses/cli/ouro-tui.js +607 -0
  559. package/dist/senses/cli/spinner-imperative.js +135 -0
  560. package/dist/senses/cli/spinner.js +101 -0
  561. package/dist/senses/cli/status-line.js +60 -0
  562. package/dist/senses/cli/streaming-markdown.js +526 -0
  563. package/dist/senses/cli/tool-display.js +85 -0
  564. package/dist/senses/cli/tool-render.js +85 -0
  565. package/dist/senses/cli/tui-store.js +241 -0
  566. package/dist/senses/cli/virtual-list.js +35 -0
  567. package/dist/senses/cli-entry.js +60 -8
  568. package/dist/senses/cli-layout.js +187 -0
  569. package/dist/senses/cli.js +814 -281
  570. package/dist/senses/commands.js +66 -3
  571. package/dist/senses/context-packet-ledger.js +371 -0
  572. package/dist/senses/context-packets.js +154 -0
  573. package/dist/senses/continuity.js +94 -0
  574. package/dist/senses/habit-lifecycle-guard.js +24 -0
  575. package/dist/senses/habit-turn-message.js +160 -0
  576. package/dist/senses/ingress-evidence.js +2 -0
  577. package/dist/senses/mail-entry.js +66 -0
  578. package/dist/senses/mail.js +524 -0
  579. package/dist/senses/pipeline.js +1236 -0
  580. package/dist/senses/private-runtime-worker.js +859 -0
  581. package/dist/senses/private-runtime.js +1627 -0
  582. package/dist/senses/proactive-content-guard.js +51 -0
  583. package/dist/senses/root-host-approval-port.js +345 -0
  584. package/dist/senses/root-host-approval-runtime.js +393 -0
  585. package/dist/senses/sanctuary-authority-resident.js +102 -0
  586. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  587. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  588. package/dist/senses/sanctuary-grounding.js +118 -0
  589. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  590. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  591. package/dist/senses/sanctuary-health-runner.js +104 -0
  592. package/dist/senses/sanctuary-health.js +422 -0
  593. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  594. package/dist/senses/sanctuary-interactive-control.js +410 -0
  595. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  596. package/dist/senses/sanctuary-media-optimization.js +514 -0
  597. package/dist/senses/sanctuary-runtime.js +369 -0
  598. package/dist/senses/sanctuary-sab.js +85 -0
  599. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  600. package/dist/senses/shared-turn.js +793 -0
  601. package/dist/senses/shepherd/client.js +196 -0
  602. package/dist/senses/shepherd/cmux.js +332 -0
  603. package/dist/senses/shepherd/herdr.js +311 -0
  604. package/dist/senses/shepherd/host.js +14 -0
  605. package/dist/senses/shepherd/judge.js +98 -0
  606. package/dist/senses/shepherd/redact.js +37 -0
  607. package/dist/senses/shepherd/returns.js +79 -0
  608. package/dist/senses/shepherd/sense.js +288 -0
  609. package/dist/senses/shepherd-entry.js +78 -0
  610. package/dist/senses/surface-tool.js +109 -0
  611. package/dist/senses/teams-entry.js +60 -8
  612. package/dist/senses/teams.js +956 -211
  613. package/dist/senses/telegram-admission.js +718 -0
  614. package/dist/senses/telegram-approval-runtime.js +793 -0
  615. package/dist/senses/telegram-attachments.js +186 -0
  616. package/dist/senses/telegram-audit-ledger.js +220 -0
  617. package/dist/senses/telegram-authority-transport.js +231 -0
  618. package/dist/senses/telegram-client.js +1749 -0
  619. package/dist/senses/telegram-effect-adapter.js +900 -0
  620. package/dist/senses/telegram-entry.js +83 -0
  621. package/dist/senses/telegram.js +2351 -0
  622. package/dist/senses/trust-gate.js +207 -2
  623. package/dist/senses/voice/audio-playback.js +237 -0
  624. package/dist/senses/voice/audio-routing.js +119 -0
  625. package/dist/senses/voice/call-auth.js +250 -0
  626. package/dist/senses/voice/elevenlabs.js +202 -0
  627. package/dist/senses/voice/floor-control.js +431 -0
  628. package/dist/senses/voice/floor-controller.js +115 -0
  629. package/dist/senses/voice/golden-path.js +116 -0
  630. package/dist/senses/voice/index.js +29 -0
  631. package/dist/senses/voice/local-audio-control.js +344 -0
  632. package/dist/senses/voice/local-audio-devices.js +516 -0
  633. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  634. package/dist/senses/voice/local-audio-identity.js +103 -0
  635. package/dist/senses/voice/local-audio-join.js +325 -0
  636. package/dist/senses/voice/local-audio-mute.js +199 -0
  637. package/dist/senses/voice/local-audio-notify.js +121 -0
  638. package/dist/senses/voice/local-audio-prompts.js +116 -0
  639. package/dist/senses/voice/local-audio-transport.js +427 -0
  640. package/dist/senses/voice/local-audio.js +281 -0
  641. package/dist/senses/voice/local-media-stream.js +145 -0
  642. package/dist/senses/voice/meeting.js +113 -0
  643. package/dist/senses/voice/outbound.js +190 -0
  644. package/dist/senses/voice/phone.js +33 -0
  645. package/dist/senses/voice/playback.js +139 -0
  646. package/dist/senses/voice/process-guards.js +51 -0
  647. package/dist/senses/voice/realtime-eval.js +496 -0
  648. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  649. package/dist/senses/voice/realtime-trace.js +531 -0
  650. package/dist/senses/voice/transcript.js +70 -0
  651. package/dist/senses/voice/turn.js +191 -0
  652. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  653. package/dist/senses/voice/twilio-phone.js +5454 -0
  654. package/dist/senses/voice/types.js +2 -0
  655. package/dist/senses/voice/whisper.js +161 -0
  656. package/dist/senses/voice-entry.js +83 -0
  657. package/dist/senses/voice-realtime-eval-command.js +99 -0
  658. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  659. package/dist/senses/voice-twilio-entry.js +87 -0
  660. package/dist/trips/core.js +138 -0
  661. package/dist/trips/store.js +265 -0
  662. package/dist/util/frontmatter.js +69 -0
  663. package/npm-shrinkwrap.json +8100 -0
  664. package/package.json +83 -12
  665. package/skills/agent-commerce.md +113 -0
  666. package/skills/browser-navigation.md +117 -0
  667. package/skills/commerce-setup-guide.md +116 -0
  668. package/skills/commerce-setup.md +84 -0
  669. package/skills/configure-dev-tools.md +99 -0
  670. package/skills/travel-planning.md +138 -0
  671. package/AdoptionSpecialist.ouro/agent.json +0 -20
  672. package/AdoptionSpecialist.ouro/psyche/SOUL.md +0 -22
  673. package/dist/heart/daemon/specialist-orchestrator.js +0 -160
  674. package/dist/heart/daemon/specialist-prompt.js +0 -47
  675. package/dist/heart/daemon/specialist-session.js +0 -142
  676. package/dist/heart/daemon/specialist-tools.js +0 -132
  677. package/dist/heart/daemon/subagent-installer.js +0 -125
  678. package/dist/inner-worker-entry.js +0 -4
  679. package/dist/mind/friends/channel.js +0 -49
  680. package/dist/mind/friends/resolver.js +0 -84
  681. package/dist/mind/friends/store-file.js +0 -171
  682. package/dist/mind/friends/store.js +0 -4
  683. package/dist/mind/friends/tokens.js +0 -26
  684. package/dist/mind/friends/types.js +0 -21
  685. package/dist/repertoire/tasks/board.js +0 -122
  686. package/dist/repertoire/tasks/index.js +0 -210
  687. package/dist/repertoire/tasks/middleware.js +0 -65
  688. package/dist/repertoire/tasks/parser.js +0 -173
  689. package/dist/repertoire/tasks/scanner.js +0 -132
  690. package/dist/repertoire/tasks/transitions.js +0 -145
  691. package/dist/senses/bluebubbles-client.js +0 -279
  692. package/dist/senses/bluebubbles-entry.js +0 -11
  693. package/dist/senses/bluebubbles-model.js +0 -253
  694. package/dist/senses/bluebubbles.js +0 -332
  695. package/dist/senses/inner-dialog-worker.js +0 -61
  696. package/dist/senses/inner-dialog.js +0 -231
  697. package/subagents/README.md +0 -73
  698. package/subagents/work-doer.md +0 -233
  699. package/subagents/work-merger.md +0 -624
  700. package/subagents/work-planner.md +0 -373
  701. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  702. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  703. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  704. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  705. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  706. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  707. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  708. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  709. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  710. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  711. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  712. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
@@ -0,0 +1,1232 @@
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.OURO_CLI_TRUST_MANIFEST = void 0;
37
+ exports.guardInvocation = guardInvocation;
38
+ const fs = __importStar(require("node:fs"));
39
+ const os = __importStar(require("node:os"));
40
+ const path = __importStar(require("node:path"));
41
+ const friends_1 = require("@ouro.bot/friends");
42
+ const shell_quote_1 = require("shell-quote");
43
+ const runtime_1 = require("../nerves/runtime");
44
+ const store_1 = require("../commerce/store");
45
+ const deny = (reason) => ({ allowed: false, reason });
46
+ const allow = { allowed: true };
47
+ // --- reason templates ---
48
+ // Structural reasons (always-on, apply to everyone)
49
+ const REASONS = {
50
+ readBeforeEdit: "i need to read that file first before i can edit it.",
51
+ readBeforeOverwrite: "i need to read that file first before i can overwrite it.",
52
+ protectedPath: "that path is protected — i can read it but not modify it.",
53
+ psychePath: "my psyche files ship from the repository through a pull request and the replay gate; i can read them but not change them. i file the change request with Claude Code instead.",
54
+ destructiveCommand: "that command is too dangerous to run — it could cause irreversible damage.",
55
+ // Trust reasons (vary by relationship)
56
+ needsTrust: "i'd need a closer friend to vouch for you before i can do that.",
57
+ needsTrustForWrite: "i'd need a closer friend to vouch for you before i can write files outside my home.",
58
+ };
59
+ // --- read-only tools that never need guardrails ---
60
+ const READ_ONLY_TOOLS = new Set(["read_file", "glob", "grep"]);
61
+ // --- protected path detection ---
62
+ const PROTECTED_PATH_SEGMENTS = [
63
+ ".git/",
64
+ ".ouro-cli/vault-unlock/",
65
+ ".ouro-cli/vault-unlock-dpapi/",
66
+ "state/policy/",
67
+ // The pre-trust-directory home of the escalation grants; the file is no longer read, and a model must not recreate it.
68
+ "state/a2a/escalation-grants.json",
69
+ "state/outbox/",
70
+ "state/reports/",
71
+ ];
72
+ const PROTECTED_FILENAMES = ["agent.json", "tool-profiles.json"];
73
+ /** The agent's psyche folder ships only from the repository (a pull request and the replay gate), so no tool writes into it. */
74
+ function isPsychePath(filePath, agentRoot) {
75
+ if (!agentRoot || !filePath)
76
+ return false;
77
+ const psyche = path.resolve(agentRoot, "psyche");
78
+ const target = path.resolve(agentRoot, filePath);
79
+ return target === psyche || target.startsWith(`${psyche}${path.sep}`);
80
+ }
81
+ /**
82
+ * The friends store (`friends/` under the agent root) is written by the harness's own code, which the model's file tools and
83
+ * shell redirects must not reach: a model talked into editing a record could rewrite trust, admission or a legacy grant.
84
+ * Scoped to this agent's root, so a project directory that happens to be named `friends` stays editable. Defence in depth
85
+ * only: a shell can still write anywhere its uid can, which is why delegated-command authority lives outside the bundle.
86
+ */
87
+ function isFriendsStorePath(filePath, agentRoot) {
88
+ if (!agentRoot || !filePath)
89
+ return false;
90
+ const store = path.resolve(agentRoot, "friends");
91
+ const target = path.resolve(agentRoot, filePath);
92
+ return target === store || target.startsWith(`${store}${path.sep}`);
93
+ }
94
+ function isProtectedPath(filePath) {
95
+ for (const segment of PROTECTED_PATH_SEGMENTS) {
96
+ if (filePath.includes(`/${segment}`) || filePath.startsWith(segment))
97
+ return true;
98
+ }
99
+ for (const name of PROTECTED_FILENAMES) {
100
+ if (path.basename(filePath) === name)
101
+ return true;
102
+ }
103
+ return false;
104
+ }
105
+ // --- destructive shell patterns ---
106
+ const DESTRUCTIVE_PATTERNS = [
107
+ /\brm\s+(-\w*\s+)*-\w*r\w*\s+(-\w+\s+)*[/~]/, // rm -rf / or rm -rf ~
108
+ /\bchmod\s+(-\w*\s+)*-\w*R\w*\s+\d+\s+\//, // chmod -R 777 /
109
+ /\bmkfs\b/, // mkfs.*
110
+ /\bdd\s+if=/, // dd if=
111
+ ];
112
+ function isDestructiveShellCommand(command) {
113
+ return DESTRUCTIVE_PATTERNS.some((p) => p.test(command));
114
+ }
115
+ // --- compound command splitting ---
116
+ // Shell operators that chain commands: &&, ||, ;, |, $(), backticks
117
+ const COMPOUND_SEPARATORS = /\s*(?:&&|\|\||;|\|)\s*/;
118
+ const SUBSHELL_PATTERN = /\$\(|`/;
119
+ function splitShellCommands(command) {
120
+ if (SUBSHELL_PATTERN.test(command))
121
+ return [command];
122
+ return command.split(COMPOUND_SEPARATORS).filter(Boolean);
123
+ }
124
+ // --- shell commands that write to protected paths ---
125
+ function shellWritesToProtectedPath(command) {
126
+ const redirectMatch = command.match(/>\s*(\S+)/);
127
+ if (redirectMatch && isProtectedPath(redirectMatch[1]))
128
+ return true;
129
+ const teeMatch = command.match(/tee\s+(?:-\w+\s+)*(\S+)/);
130
+ if (teeMatch && isProtectedPath(teeMatch[1]))
131
+ return true;
132
+ return false;
133
+ }
134
+ // --- the psyche folder in shell commands ---
135
+ // The psyche folder is mounted read-only into the resident at the OS level (the upgrade recreates the container that way). This is the
136
+ // defence in depth in front of that: a shell command that mentions the psyche folder at all runs only if every part of it is
137
+ // a read-only command, because enumerating the ways to write a file (>, >>, tee, cp, mv, sed -i, node -e, python, cd then
138
+ // redirect) is a list the model can always step around.
139
+ const PSYCHE_READ_ONLY_COMMANDS = new Set(["cat", "ls", "head", "tail", "grep", "wc", "sha256sum", "stat", "cd", "pwd"]);
140
+ const SEGMENT_OPERATORS = new Set(["&&", "||", ";", "|"]);
141
+ // --- globs and expansions that could land inside a protected folder ---
142
+ // A word such as /bundle/fr*nds/x.json, /bundle/friend?/x.json or ${F}ends/x.json names no protected folder literally, but the
143
+ // shell could resolve it into one. A word like that counts as mentioning the folder when its directory part can match the folder's
144
+ // path, so the read-only rule below applies to the command.
145
+ const EXPANSION = "\u0001";
146
+ const STABLE_VARIABLES = ["HOME", "TMPDIR", "USER"];
147
+ function neutraliseExpansions(command) {
148
+ return command.replace(/\$\([^)]*\)|`[^`]*`|\$\{([A-Za-z_]\w*)\}|\$([A-Za-z_]\w*)|\$\{[^}]*\}/g, (_match, braced, plain) => {
149
+ const name = braced ?? plain;
150
+ if (name !== undefined && STABLE_VARIABLES.includes(name) && !new RegExp(`\\b${name}=`).test(command) && process.env[name])
151
+ return process.env[name];
152
+ return EXPANSION;
153
+ });
154
+ }
155
+ function wordPattern(word) {
156
+ const generalised = word.replace(/\{[^}]*\}/g, EXPANSION).replace(/\[[^\]]*\]/g, "?");
157
+ let source = "";
158
+ for (const char of generalised)
159
+ source += char === EXPANSION ? ".*" : char === "*" ? "[^/]*" : char === "?" ? "[^/]" : char.replace(/[.+^$()|\\\]{}[]/g, "\\$&");
160
+ return new RegExp(`^${source}$`);
161
+ }
162
+ function globOrExpansionCouldReach(command, folder, agentRoot) {
163
+ const tokens = neutraliseExpansions(command).split(/[\s<>|;&()'"]+/).filter((token) => /[*?[{\u0001]/.test(token));
164
+ return tokens.some((token) => {
165
+ const word = token.startsWith("~") ? expandHome(token) : token;
166
+ const absolute = word.startsWith("/") || word.startsWith(EXPANSION) ? word : `${agentRoot}/${word}`;
167
+ const dir = absolute.slice(0, Math.max(absolute.lastIndexOf("/"), 0));
168
+ return wordPattern(absolute).test(folder) || wordPattern(dir).test(folder);
169
+ });
170
+ }
171
+ function commandMentionsPsyche(command, words, agentRoot) {
172
+ const psyche = path.resolve(agentRoot, "psyche");
173
+ if (globOrExpansionCouldReach(command, psyche, agentRoot))
174
+ return true;
175
+ if (command.includes(psyche) || words.some((word) => word.includes(psyche)))
176
+ return true;
177
+ if (words.some((word) => word === "psyche" || isPsychePath(word, agentRoot)))
178
+ return true;
179
+ // A relative "psyche/..." inside code or a quoted argument, when this agent has such a folder.
180
+ return /(?:^|[\s'"=(])psyche\//.test(command) && fs.existsSync(psyche);
181
+ }
182
+ /**
183
+ * The shared rule: when a shell command mentions a protected folder at all, it runs only if every part of it is a read-only
184
+ * command. The mention test is the only thing that differs between folders.
185
+ */
186
+ function protectedFolderShellWriteRefused(command, mentions) {
187
+ const entries = (0, shell_quote_1.parse)(command);
188
+ const words = entries.filter((entry) => typeof entry === "string");
189
+ if (!mentions(words))
190
+ return false;
191
+ // Substitution, heredocs and any $VAR or ${VAR} expansion: the shell could build a protected path or a command word we cannot see.
192
+ if (/\$[({A-Za-z_]|`|<\(|<</.test(command))
193
+ return true;
194
+ let expectCommandWord = true;
195
+ for (const entry of entries) {
196
+ if (typeof entry === "string") {
197
+ if (expectCommandWord && !/^\w+=/.test(entry)) {
198
+ if (!PSYCHE_READ_ONLY_COMMANDS.has(entry))
199
+ return true;
200
+ expectCommandWord = false;
201
+ }
202
+ continue;
203
+ }
204
+ const op = "op" in entry ? entry.op : "comment";
205
+ if (SEGMENT_OPERATORS.has(op))
206
+ expectCommandWord = true;
207
+ else if (op !== "glob")
208
+ return true;
209
+ }
210
+ return false;
211
+ }
212
+ function psycheShellWriteRefused(command, agentRoot) {
213
+ if (!agentRoot)
214
+ return false;
215
+ return protectedFolderShellWriteRefused(command, (words) => commandMentionsPsyche(command, words, agentRoot));
216
+ }
217
+ // --- the friends store in shell commands ---
218
+ // Same stance as the psyche folder: a command that names this agent's friends store runs only if it is read-only, because a list of
219
+ // the ways to write a file (>, >>, tee, cp, mv, sed -i, node -e, python, cd then redirect, ~ paths) is one the model can step around.
220
+ function expandHome(word) {
221
+ return word === "~" || word.startsWith("~/") ? path.join(os.homedir(), word.slice(1)) : word;
222
+ }
223
+ function commandMentionsFriendsStore(command, words, agentRoot) {
224
+ if (globOrExpansionCouldReach(command, path.resolve(agentRoot, "friends"), agentRoot))
225
+ return true;
226
+ // Only path-shaped words resolve against the store: an ordinary word such as "friends" in prose is not a path.
227
+ if (words.some((word) => word.includes("/") && isFriendsStorePath(expandHome(word), agentRoot)))
228
+ return true;
229
+ // A bare `friends` names the store only as the target of a cd; elsewhere it is an ordinary word ("my friends are kind").
230
+ if (words.some((word, index) => word.startsWith("friends/") || (word === "friends" && words[index - 1] === "cd")))
231
+ return true;
232
+ // A variable or substitution in front of the path ($BUNDLE/friends/x.json): the folder name is still in the command.
233
+ if (/\$[({A-Za-z_]|`/.test(command) && /(?:^|[\/\s'"=])friends(?:$|[\/\s'"])/.test(command))
234
+ return true;
235
+ // An absolute or relative path inside code or a quoted argument, such as node -e "...'/bundle/friends/x.json'...".
236
+ const store = path.resolve(agentRoot, "friends");
237
+ return command.includes(store) || /(?:^|[\s'"=(])friends\//.test(command);
238
+ }
239
+ function friendsShellWriteRefused(command, agentRoot) {
240
+ if (!agentRoot)
241
+ return false;
242
+ return protectedFolderShellWriteRefused(command, (words) => commandMentionsFriendsStore(command, words, agentRoot));
243
+ }
244
+ // --- structural guardrail checks (always on, all trust levels) ---
245
+ function checkReadBeforeWrite(toolName, args, context) {
246
+ if (toolName === "edit_file") {
247
+ const filePath = args.path || "";
248
+ if (!context.readPaths.has(filePath))
249
+ return deny(REASONS.readBeforeEdit);
250
+ }
251
+ if (toolName === "write_file") {
252
+ const filePath = args.path || "";
253
+ if (context.readPaths.has(filePath))
254
+ return allow;
255
+ if (!fs.existsSync(filePath))
256
+ return allow;
257
+ return deny(REASONS.readBeforeOverwrite);
258
+ }
259
+ return allow;
260
+ }
261
+ function checkDestructiveShellPatterns(toolName, args) {
262
+ if (toolName !== "shell")
263
+ return allow;
264
+ const command = args.command || "";
265
+ // Check each subcommand in compound commands for destructive patterns
266
+ for (const sub of splitShellCommands(command)) {
267
+ if (isDestructiveShellCommand(sub))
268
+ return deny(REASONS.destructiveCommand);
269
+ }
270
+ return allow;
271
+ }
272
+ function checkProtectedPaths(toolName, args, context) {
273
+ if (toolName === "write_file" || toolName === "edit_file") {
274
+ const filePath = args.path || "";
275
+ if (isPsychePath(filePath, context.agentRoot))
276
+ return deny(REASONS.psychePath);
277
+ if (isProtectedPath(filePath) || isFriendsStorePath(filePath, context.agentRoot))
278
+ return deny(REASONS.protectedPath);
279
+ }
280
+ if (toolName === "shell") {
281
+ const command = args.command || "";
282
+ if (psycheShellWriteRefused(command, context.agentRoot))
283
+ return deny(REASONS.psychePath);
284
+ if (friendsShellWriteRefused(command, context.agentRoot))
285
+ return deny(REASONS.protectedPath);
286
+ if (shellWritesToProtectedPath(command))
287
+ return deny(REASONS.protectedPath);
288
+ }
289
+ return allow;
290
+ }
291
+ function checkStructuralGuardrails(toolName, args, context) {
292
+ const protectedResult = checkProtectedPaths(toolName, args, context);
293
+ if (!protectedResult.allowed)
294
+ return protectedResult;
295
+ const destructiveResult = checkDestructiveShellPatterns(toolName, args);
296
+ if (!destructiveResult.allowed)
297
+ return destructiveResult;
298
+ return checkReadBeforeWrite(toolName, args, context);
299
+ }
300
+ // --- ouro CLI trust manifest ---
301
+ /** Minimum trust level required for each ouro CLI subcommand. */
302
+ exports.OURO_CLI_TRUST_MANIFEST = {
303
+ whoami: "acquaintance",
304
+ changelog: "acquaintance",
305
+ "session list": "acquaintance",
306
+ "friend list": "friend",
307
+ "friend show": "friend",
308
+ "friend create": "friend",
309
+ "friend update": "family",
310
+ "config model": "friend",
311
+ "config models": "friend",
312
+ "mcp list": "acquaintance",
313
+ "mcp call": "friend",
314
+ auth: "family",
315
+ "auth verify": "family",
316
+ "auth switch": "family",
317
+ rollback: "family",
318
+ versions: "acquaintance",
319
+ };
320
+ // --- trust level comparison ---
321
+ const LEVEL_ORDER = {
322
+ stranger: 0,
323
+ acquaintance: 1,
324
+ friend: 2,
325
+ family: 3,
326
+ };
327
+ function trustLevelSatisfied(required, actual) {
328
+ return LEVEL_ORDER[actual] >= LEVEL_ORDER[required];
329
+ }
330
+ // --- general CLI allowlists for acquaintance ---
331
+ const ACQUAINTANCE_SHELL_ALLOWLIST = new Set([
332
+ "cat", "ls", "head", "tail", "wc", "file", "stat", "which", "echo",
333
+ "pwd", "env", "printenv", "whoami", "date", "uname",
334
+ ]);
335
+ const ACQUAINTANCE_GIT_ALLOWLIST = new Set([
336
+ "status", "log", "show", "diff", "branch",
337
+ ]);
338
+ // --- trust-level shell guardrails ---
339
+ function resolveOuroSubcommand(command) {
340
+ const afterOuro = command.replace(/^ouro\s+/, "").trim();
341
+ /* v8 ignore next -- bare "ouro" is caught upstream by checkShellTrustGuardrails @preserve */
342
+ if (!afterOuro)
343
+ return null;
344
+ const tokens = afterOuro.split(/\s+/);
345
+ const twoWord = tokens.length >= 2 ? `${tokens[0]} ${tokens[1]}` : null;
346
+ // Two-word match first (e.g. "task board"), then one-word (e.g. "whoami")
347
+ if (twoWord && exports.OURO_CLI_TRUST_MANIFEST[twoWord])
348
+ return twoWord;
349
+ if (exports.OURO_CLI_TRUST_MANIFEST[tokens[0]])
350
+ return tokens[0];
351
+ return null;
352
+ }
353
+ // --- MCP server-specific trust rules ---
354
+ const MCP_SERVER_TRUST = {
355
+ browser: { minTrust: "friend", blockGroupChat: true },
356
+ };
357
+ function checkMcpServerTrust(command, context) {
358
+ const match = command.match(/^ouro\s+mcp\s+call\s+(\S+)/);
359
+ if (!match)
360
+ return allow;
361
+ const serverName = match[1];
362
+ const rules = MCP_SERVER_TRUST[serverName];
363
+ if (!rules)
364
+ return allow; // no special rules for this server
365
+ if (!trustLevelSatisfied(rules.minTrust, context.trustLevel ?? "friend")) {
366
+ return deny(REASONS.needsTrust);
367
+ }
368
+ if (rules.blockGroupChat && context.isGroupChat) {
369
+ return deny("browser tools are only available in 1:1 conversations, not group chats.");
370
+ }
371
+ return allow;
372
+ }
373
+ function checkSingleShellCommandTrust(command, trustLevel) {
374
+ const trimmed = command.trim();
375
+ const tokens = trimmed.split(/\s+/);
376
+ const firstToken = tokens[0] || "";
377
+ // ouro CLI — check per-subcommand trust manifest
378
+ if (firstToken === "ouro") {
379
+ const subcommand = resolveOuroSubcommand(trimmed);
380
+ const requiredLevel = subcommand ? exports.OURO_CLI_TRUST_MANIFEST[subcommand] : "friend";
381
+ if (trustLevelSatisfied(requiredLevel, trustLevel))
382
+ return allow;
383
+ return deny(REASONS.needsTrust);
384
+ }
385
+ // git — check subcommand allowlist
386
+ if (firstToken === "git") {
387
+ const gitSub = tokens[1] || "";
388
+ if (ACQUAINTANCE_GIT_ALLOWLIST.has(gitSub))
389
+ return allow;
390
+ return deny(REASONS.needsTrust);
391
+ }
392
+ // General CLI — check allowlist
393
+ if (ACQUAINTANCE_SHELL_ALLOWLIST.has(firstToken))
394
+ return allow;
395
+ return deny(REASONS.needsTrust);
396
+ }
397
+ function checkShellTrustGuardrails(command, trustLevel) {
398
+ // Subshell patterns ($(), backticks) can't be reliably split — check as single command
399
+ /* v8 ignore next -- subshell branch: tested via guardrails.test.ts @preserve */
400
+ if (SUBSHELL_PATTERN.test(command)) {
401
+ return checkSingleShellCommandTrust(command, trustLevel);
402
+ }
403
+ // Compound commands: check each subcommand individually
404
+ const subcommands = splitShellCommands(command);
405
+ if (subcommands.length === 0)
406
+ return checkSingleShellCommandTrust(command, trustLevel);
407
+ for (const sub of subcommands) {
408
+ const result = checkSingleShellCommandTrust(sub, trustLevel);
409
+ if (!result.allowed)
410
+ return result;
411
+ }
412
+ return allow;
413
+ }
414
+ function checkWriteTrustGuardrails(toolName, args, context) {
415
+ if (toolName !== "write_file" && toolName !== "edit_file")
416
+ return allow;
417
+ const filePath = args.path || "";
418
+ if (context.agentRoot && filePath.startsWith(context.agentRoot))
419
+ return allow;
420
+ if (!context.agentRoot)
421
+ return allow;
422
+ return deny(REASONS.needsTrustForWrite);
423
+ }
424
+ // --- credential tool trust gating ---
425
+ // Credential write tools: family only
426
+ const CREDENTIAL_FAMILY_TOOLS = new Set([
427
+ "credential_generate_password", "credential_store", "credential_delete", "vault_setup",
428
+ // User profile tools: family only
429
+ "user_profile_store", "user_profile_get", "user_profile_delete",
430
+ // Payment tools: family only
431
+ "stripe_create_card", "stripe_deactivate_card", "stripe_list_cards",
432
+ // Booking tools that involve payment: family only
433
+ "flight_book", "flight_hold", "flight_cancel",
434
+ ]);
435
+ // Credential read tools: friend+
436
+ const CREDENTIAL_TRUSTED_TOOLS = new Set(["credential_get", "credential_list"]);
437
+ // Travel tools: friend+ (weather_lookup accesses vault credentials indirectly;
438
+ // advisory and geocode are public APIs but gated for consistency)
439
+ // Flight search is also friend+ (read-only, no payment)
440
+ const TRAVEL_TRUSTED_TOOLS = new Set(["weather_lookup", "travel_advisory", "geocode_search", "flight_search"]);
441
+ const A2A_TRUSTED_TOOLS = new Set(["a2a_list_peers", "a2a_send_message", "a2a_get_task"]);
442
+ const COMMERCE_FAMILY_TOOLS = new Set(["commerce_checkout_preview", "commerce_checkout_commit", "commerce_receipt_get", "commerce_access_log"]);
443
+ const COMMERCE_AUTHORITY_TOOLS = new Set(["stripe_create_card", "flight_hold", "flight_book"]);
444
+ // The Shepherd tools read the owner's terminals and speak to them through their desktop, so only family may use them.
445
+ // A call with no known trust level fails closed.
446
+ const SHEPHERD_FAMILY_TOOLS = new Set(["shepherd_overview", "shepherd_read", "shepherd_signal"]);
447
+ const MAIL_FAMILY_TOOLS = new Set(["mail_screener", "mail_decide", "mail_access_log", "mail_send", "mail_index_refresh"]);
448
+ const MAIL_DELEGATED_READ_TOOLS = new Set(["mail_recent", "mail_search"]);
449
+ function opaqueAnsiShellAtoms(command) {
450
+ const atoms = [];
451
+ let inAnsiQuote = false;
452
+ for (let index = 0; index < command.length;) {
453
+ if (!inAnsiQuote && command.startsWith("$'", index)) {
454
+ inAnsiQuote = true;
455
+ index += 2;
456
+ continue;
457
+ }
458
+ const character = command[index];
459
+ if (inAnsiQuote && character === "'") {
460
+ inAnsiQuote = false;
461
+ index += 1;
462
+ continue;
463
+ }
464
+ if (inAnsiQuote && character === "\\") {
465
+ const escape = command.slice(index).match(/^\\(?:x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{1,4}|U[0-9a-fA-F]{1,8}|[0-7]{1,3}|c.|.)?/s)[0];
466
+ atoms.push(null);
467
+ index += escape.length;
468
+ continue;
469
+ }
470
+ if (!inAnsiQuote && (character === "'" || character === '"')) {
471
+ index += 1;
472
+ continue;
473
+ }
474
+ if (!inAnsiQuote && character === "\\" && index + 1 < command.length) {
475
+ atoms.push(command[index + 1]);
476
+ index += 2;
477
+ continue;
478
+ }
479
+ atoms.push(character);
480
+ index += 1;
481
+ }
482
+ return atoms;
483
+ }
484
+ function shellContainsAmbiguousAnsiMailCacheSync(command) {
485
+ if (!command.includes("$'"))
486
+ return false;
487
+ const expected = ["ouro", "mail", "sync-cache"];
488
+ let states = new Set(["0:0"]);
489
+ const crossTokenBoundary = (current) => {
490
+ const next = new Set(["0:0"]);
491
+ for (const state of current) {
492
+ const [tokenIndex, characterIndex] = state.split(":").map(Number);
493
+ if (characterIndex !== expected[tokenIndex].length)
494
+ continue;
495
+ if (tokenIndex === expected.length - 1)
496
+ return { matched: true, states: next };
497
+ next.add(`${tokenIndex + 1}:0`);
498
+ }
499
+ return { matched: false, states: next };
500
+ };
501
+ for (const atom of opaqueAnsiShellAtoms(command)) {
502
+ if (atom === null) {
503
+ const next = new Set(states);
504
+ for (const state of states) {
505
+ const [tokenIndex, characterIndex] = state.split(":").map(Number);
506
+ if (characterIndex >= 0 && characterIndex < expected[tokenIndex].length) {
507
+ next.add(`${tokenIndex}:${characterIndex + 1}`);
508
+ }
509
+ }
510
+ const boundary = crossTokenBoundary(states);
511
+ if (boundary.matched)
512
+ return true;
513
+ states = new Set([...next, ...boundary.states]);
514
+ continue;
515
+ }
516
+ if (/\s|[;&|()`]/.test(atom)) {
517
+ const boundary = crossTokenBoundary(states);
518
+ if (boundary.matched)
519
+ return true;
520
+ states = boundary.states;
521
+ continue;
522
+ }
523
+ const next = new Set();
524
+ for (const state of states) {
525
+ const [tokenIndex, characterIndex] = state.split(":").map(Number);
526
+ const wanted = expected[tokenIndex]?.[characterIndex];
527
+ next.add(wanted?.toLowerCase() === atom.toLowerCase() ? `${tokenIndex}:${characterIndex + 1}` : `${tokenIndex}:-1`);
528
+ }
529
+ states = next;
530
+ }
531
+ return crossTokenBoundary(states).matched;
532
+ }
533
+ const SHELL_COMMAND_BOUNDARIES = new Set(["||", "&&", ";;", "|&", "&", ";", "(", ")", "|", "<("]);
534
+ const SHELL_INTERPRETERS = new Set(["sh", "bash", "zsh"]);
535
+ const SHELL_TOKEN_BOUNDARIES = new Set(["{", "}", "then", "elif", "else", "do"]);
536
+ const SHELL_GRAMMAR_PREFIXES = new Set(["!", "if", "until", "while"]);
537
+ const SHELL_PARAMETER_MARKER = "__OURO_SHELL_PARAMETER_";
538
+ const SHELL_ARRAY_EXPANSION = "__OURO_ARRAY_EXPANSION__";
539
+ function hasUnescapedShellSubstitution(value) {
540
+ for (let index = 0; index < value.length; index += 1) {
541
+ if (value[index] === "\\") {
542
+ index += 1;
543
+ continue;
544
+ }
545
+ if (value.startsWith("$(", index) && !value.startsWith("$((", index))
546
+ return true;
547
+ if (value[index] === "`")
548
+ return true;
549
+ }
550
+ return false;
551
+ }
552
+ function stripHereDocBodies(command) {
553
+ const pending = [];
554
+ const lines = command.split("\n");
555
+ return lines.map((sourceLine) => {
556
+ if (pending.length > 0) {
557
+ const active = pending[0];
558
+ const candidate = active.stripTabs ? sourceLine.replace(/^\t+/, "") : sourceLine;
559
+ if (candidate === active.delimiter) {
560
+ pending.shift();
561
+ return "";
562
+ }
563
+ if (active.quoted || !hasUnescapedShellSubstitution(sourceLine))
564
+ return "";
565
+ return exposeShellSubstitutions(sourceLine).split("\n").slice(1).join("\n");
566
+ }
567
+ const pattern = /<<(?!<)(-)?\s*(?:'([^']*)'|"([^"]*)"|\\([^\s;&|]+)|([^\s;&|]+))/g;
568
+ for (const match of stripShellComments(sourceLine).matchAll(pattern)) {
569
+ pending.push({
570
+ stripTabs: match[1] !== undefined,
571
+ delimiter: match[2] ?? match[3] ?? match[4] ?? match[5],
572
+ quoted: match[2] !== undefined || match[3] !== undefined || match[4] !== undefined,
573
+ });
574
+ }
575
+ return sourceLine;
576
+ }).join("\n");
577
+ }
578
+ function stripShellComments(command) {
579
+ let result = "";
580
+ let quote = null;
581
+ for (let index = 0; index < command.length; index += 1) {
582
+ const character = command[index];
583
+ if (character === "\\" && quote !== "single") {
584
+ result += character + (command[index + 1] ?? "");
585
+ index += 1;
586
+ continue;
587
+ }
588
+ if (character === "'" && quote !== "double")
589
+ quote = quote === "single" ? null : "single";
590
+ else if (character === '"' && quote !== "single")
591
+ quote = quote === "double" ? null : "double";
592
+ if (character === "#" && quote === null && (index === 0 || /[\s;&|()]/.test(command[index - 1]))) {
593
+ const newline = command.indexOf("\n", index);
594
+ if (newline < 0)
595
+ break;
596
+ result += " ".repeat(newline - index) + "\n";
597
+ index = newline;
598
+ continue;
599
+ }
600
+ result += character;
601
+ }
602
+ return result;
603
+ }
604
+ const SHELL_ARRAY_ASSIGNMENT = /([A-Za-z_][A-Za-z0-9_]*)(\+?=)\(([^()\n]*)\)/y;
605
+ const SHELL_INDEXED_ASSIGNMENT = /([A-Za-z_][A-Za-z0-9_]*)\[(\d+)\]=("[^"]*"|'[^']*'|[^\s;&|]+)/y;
606
+ const SHELL_SCALAR_ASSIGNMENT = /([A-Za-z_][A-Za-z0-9_]*)=("[^"]*"|'[^']*'|[^\s;&|()]+)/y;
607
+ const SHELL_ARRAY_PARAMETER = /\$\{([A-Za-z_][A-Za-z0-9_]*)\[(@|\*)\]\}/y;
608
+ const SHELL_SCALAR_PARAMETER = /\$(?:\{([A-Za-z_][A-Za-z0-9_]*)\}|([A-Za-z_][A-Za-z0-9_]*))/y;
609
+ function shellMatchAt(pattern, command, index) {
610
+ pattern.lastIndex = index;
611
+ return pattern.exec(command);
612
+ }
613
+ function shellAssignmentPosition(command, index) {
614
+ let previous = index - 1;
615
+ while (previous >= 0 && /[ \t]/.test(command[previous]))
616
+ previous -= 1;
617
+ return previous < 0 || /[;&|()\n]/.test(command[previous]);
618
+ }
619
+ function parseShellWords(value) {
620
+ if (hasUnescapedShellSubstitution(value) || /(^|[^\\])\$(?!['"])/.test(value))
621
+ return undefined;
622
+ try {
623
+ const entries = (0, shell_quote_1.parse)(value);
624
+ if (entries.some((entry) => typeof entry !== "string"))
625
+ return undefined;
626
+ return entries;
627
+ }
628
+ catch {
629
+ return undefined;
630
+ }
631
+ }
632
+ function shellAssignmentPersists(command, endIndex) {
633
+ let next = endIndex;
634
+ while (next < command.length && /[ \t]/.test(command[next]))
635
+ next += 1;
636
+ return next === command.length || /[;&|\n]/.test(command[next]);
637
+ }
638
+ function shellUnquotedFields(values) {
639
+ const fields = values.flatMap((value) => value.split(/\s+/).filter(Boolean));
640
+ return fields.some((field) => /[*?[]/.test(field)) ? SHELL_ARRAY_EXPANSION : (0, shell_quote_1.quote)(fields);
641
+ }
642
+ function doubleQuotedFragment(value) {
643
+ if (hasUnescapedShellSubstitution(value))
644
+ return undefined;
645
+ try {
646
+ const parsed = (0, shell_quote_1.parse)(`"${value}"`);
647
+ return parsed.length === 1 && typeof parsed[0] === "string" ? parsed[0] : undefined;
648
+ }
649
+ catch {
650
+ return undefined;
651
+ }
652
+ }
653
+ function closingDoubleQuote(command, startIndex) {
654
+ for (let index = startIndex; index < command.length; index += 1) {
655
+ if (command[index] === "\\")
656
+ index += 1;
657
+ else if (command[index] === '"')
658
+ return index;
659
+ }
660
+ return -1;
661
+ }
662
+ function transformOrderedShellVariables(command) {
663
+ const variables = new Map();
664
+ const result = [];
665
+ let quote = null;
666
+ let doubleQuoteStart = -1;
667
+ let doubleQuoteResultIndex = -1;
668
+ for (let index = 0; index < command.length; index += 1) {
669
+ const character = command[index];
670
+ if (character === "\\" && quote !== "single") {
671
+ result.push(character + (command[index + 1] ?? ""));
672
+ index += 1;
673
+ continue;
674
+ }
675
+ if (character === "'") {
676
+ if (quote !== "double")
677
+ quote = quote === "single" ? null : "single";
678
+ result.push(character);
679
+ continue;
680
+ }
681
+ if (character === '"') {
682
+ if (quote !== "single") {
683
+ if (quote === "double") {
684
+ quote = null;
685
+ doubleQuoteStart = -1;
686
+ doubleQuoteResultIndex = -1;
687
+ }
688
+ else {
689
+ quote = "double";
690
+ doubleQuoteStart = index;
691
+ doubleQuoteResultIndex = result.length;
692
+ }
693
+ }
694
+ result.push(character);
695
+ continue;
696
+ }
697
+ if (quote === null && /[A-Za-z_]/.test(character) && shellAssignmentPosition(command, index)) {
698
+ const arrayAssignment = shellMatchAt(SHELL_ARRAY_ASSIGNMENT, command, index);
699
+ if (arrayAssignment) {
700
+ const [, name, operator, body] = arrayAssignment;
701
+ const elements = parseShellWords(body);
702
+ if (elements === undefined)
703
+ variables.delete(name);
704
+ else
705
+ variables.set(name, { array: operator === "+=" ? [...(variables.get(name)?.array ?? []), ...elements] : elements });
706
+ result.push(`${name}=__OURO_ARRAY_LITERAL`);
707
+ index += arrayAssignment[0].length - 1;
708
+ continue;
709
+ }
710
+ const indexedAssignment = shellMatchAt(SHELL_INDEXED_ASSIGNMENT, command, index);
711
+ if (indexedAssignment) {
712
+ const [, name, elementIndex, rawValue] = indexedAssignment;
713
+ const element = parseShellWords(rawValue);
714
+ if (element?.length !== 1)
715
+ variables.delete(name);
716
+ else {
717
+ const array = [...(variables.get(name)?.array ?? [])];
718
+ array[Number(elementIndex)] = element[0];
719
+ variables.set(name, { array });
720
+ }
721
+ result.push(`${name}=__OURO_ARRAY_LITERAL`);
722
+ index += indexedAssignment[0].length - 1;
723
+ continue;
724
+ }
725
+ const scalarAssignment = shellMatchAt(SHELL_SCALAR_ASSIGNMENT, command, index);
726
+ if (scalarAssignment) {
727
+ const [, name, rawValue] = scalarAssignment;
728
+ const scalar = parseShellWords(rawValue);
729
+ if (shellAssignmentPersists(command, index + scalarAssignment[0].length)) {
730
+ if (scalar?.length === 1)
731
+ variables.set(name, { scalar: scalar[0] });
732
+ else
733
+ variables.delete(name);
734
+ }
735
+ result.push(scalarAssignment[0]);
736
+ index += scalarAssignment[0].length - 1;
737
+ continue;
738
+ }
739
+ }
740
+ if (quote !== "single" && character === "$") {
741
+ const arrayExpansion = shellMatchAt(SHELL_ARRAY_PARAMETER, command, index);
742
+ if (arrayExpansion) {
743
+ const [, name, mode] = arrayExpansion;
744
+ const elements = variables.get(name)?.array;
745
+ if (elements === undefined)
746
+ result.push(SHELL_ARRAY_EXPANSION);
747
+ else if (quote === "double" && mode === "@") {
748
+ const closing = closingDoubleQuote(command, index + arrayExpansion[0].length);
749
+ const prefix = doubleQuotedFragment(command.slice(doubleQuoteStart + 1, index));
750
+ const suffix = closing < 0 ? undefined : doubleQuotedFragment(command.slice(index + arrayExpansion[0].length, closing));
751
+ if (closing < 0 || prefix === undefined || suffix === undefined)
752
+ result.push(SHELL_ARRAY_EXPANSION);
753
+ else {
754
+ const presentElements = elements.filter((element) => element !== undefined);
755
+ const expanded = presentElements.length === 0
756
+ ? (prefix.length + suffix.length === 0 ? [] : [`${prefix}${suffix}`])
757
+ : presentElements.map((element, elementIndex) => `${elementIndex === 0 ? prefix : ""}${element}${elementIndex === presentElements.length - 1 ? suffix : ""}`);
758
+ result.splice(doubleQuoteResultIndex);
759
+ result.push((0, shell_quote_1.quote)(expanded));
760
+ quote = null;
761
+ doubleQuoteStart = -1;
762
+ doubleQuoteResultIndex = -1;
763
+ index = closing;
764
+ continue;
765
+ }
766
+ }
767
+ else if (quote === "double")
768
+ result.push(elements.join(" "));
769
+ else
770
+ result.push(shellUnquotedFields(elements));
771
+ index += arrayExpansion[0].length - 1;
772
+ continue;
773
+ }
774
+ const scalarExpansion = shellMatchAt(SHELL_SCALAR_PARAMETER, command, index);
775
+ if (scalarExpansion) {
776
+ const name = scalarExpansion[1] ?? scalarExpansion[2];
777
+ const scalar = variables.get(name)?.scalar;
778
+ if (scalar !== undefined) {
779
+ if (quote === "double")
780
+ result.push(scalar.replace(/["\\$`]/g, "\\$&"));
781
+ else
782
+ result.push(shellUnquotedFields([scalar]));
783
+ index += scalarExpansion[0].length - 1;
784
+ continue;
785
+ }
786
+ if (quote === null) {
787
+ result.push(SHELL_ARRAY_EXPANSION);
788
+ index += scalarExpansion[0].length - 1;
789
+ continue;
790
+ }
791
+ }
792
+ }
793
+ result.push(character);
794
+ }
795
+ return result.join("");
796
+ }
797
+ function findCommandSubstitutionEnd(command, start) {
798
+ let depth = 1;
799
+ let quote = null;
800
+ for (let index = start; index < command.length; index += 1) {
801
+ const character = command[index];
802
+ if (character === "\\" && quote !== "single") {
803
+ index += 1;
804
+ continue;
805
+ }
806
+ if (character === "'" && quote !== "double") {
807
+ quote = quote === "single" ? null : "single";
808
+ continue;
809
+ }
810
+ if (character === '"' && quote !== "single") {
811
+ quote = quote === "double" ? null : "double";
812
+ continue;
813
+ }
814
+ if (quote !== null)
815
+ continue;
816
+ if (character === "(")
817
+ depth += 1;
818
+ else if (character === ")") {
819
+ depth -= 1;
820
+ if (depth === 0)
821
+ return index;
822
+ }
823
+ }
824
+ return -1;
825
+ }
826
+ function exposeShellSubstitutions(command, depth = 0) {
827
+ if (depth >= 32)
828
+ return "ouro mail sync-cache";
829
+ let outer = "";
830
+ const nested = [];
831
+ let quote = null;
832
+ for (let index = 0; index < command.length; index += 1) {
833
+ const character = command[index];
834
+ if (character === "\\" && quote !== "single") {
835
+ outer += character + (command[index + 1] ?? "");
836
+ index += 1;
837
+ continue;
838
+ }
839
+ if (character === "'" && quote !== "double") {
840
+ quote = quote === "single" ? null : "single";
841
+ outer += character;
842
+ continue;
843
+ }
844
+ if (character === '"' && quote !== "single") {
845
+ quote = quote === "double" ? null : "double";
846
+ outer += character;
847
+ continue;
848
+ }
849
+ if (quote !== "single" && command.startsWith("$(", index) && !command.startsWith("$((", index)) {
850
+ const end = findCommandSubstitutionEnd(command, index + 2);
851
+ if (end >= 0) {
852
+ nested.push(exposeShellSubstitutions(command.slice(index + 2, end), depth + 1));
853
+ outer += "${__OURO_COMMAND_SUBSTITUTION}";
854
+ index = end;
855
+ continue;
856
+ }
857
+ }
858
+ if (quote !== "single" && character === "`") {
859
+ let end = index + 1;
860
+ while (end < command.length && command[end] !== "`") {
861
+ if (command[end] === "\\")
862
+ end += 1;
863
+ end += 1;
864
+ }
865
+ if (end < command.length) {
866
+ nested.push(exposeShellSubstitutions(command.slice(index + 1, end), depth + 1));
867
+ outer += "${__OURO_COMMAND_SUBSTITUTION}";
868
+ index = end;
869
+ continue;
870
+ }
871
+ }
872
+ outer += character;
873
+ }
874
+ return [outer, ...nested].join("\n");
875
+ }
876
+ function normalizeShellNewlines(command) {
877
+ let result = "";
878
+ let quote = null;
879
+ for (let index = 0; index < command.length; index += 1) {
880
+ const character = command[index];
881
+ if (character === "\\" && quote !== "single") {
882
+ result += character + (command[index + 1] ?? "");
883
+ index += 1;
884
+ continue;
885
+ }
886
+ if (character === "'" && quote !== "double")
887
+ quote = quote === "single" ? null : "single";
888
+ else if (character === '"' && quote !== "single")
889
+ quote = quote === "double" ? null : "double";
890
+ result += character === "\n" && quote === null ? " ; " : character;
891
+ }
892
+ return result;
893
+ }
894
+ function executableShellView(command) {
895
+ const withoutData = stripShellComments(stripHereDocBodies(command));
896
+ return normalizeShellNewlines(transformOrderedShellVariables(exposeShellSubstitutions(withoutData)));
897
+ }
898
+ function parseShellCommands(command) {
899
+ let parameterIndex = 0;
900
+ const parameterNames = new Map();
901
+ const entries = (0, shell_quote_1.parse)(command, (name) => {
902
+ const marker = `${SHELL_PARAMETER_MARKER}${parameterIndex}__`;
903
+ parameterIndex += 1;
904
+ parameterNames.set(marker, name);
905
+ return marker;
906
+ });
907
+ const commands = [];
908
+ let current = [];
909
+ let skipRedirectionTarget = false;
910
+ const flush = () => {
911
+ if (current.length > 0)
912
+ commands.push(current);
913
+ current = [];
914
+ skipRedirectionTarget = false;
915
+ };
916
+ for (const entry of entries) {
917
+ if (typeof entry === "string") {
918
+ if (skipRedirectionTarget)
919
+ skipRedirectionTarget = false;
920
+ else if (SHELL_TOKEN_BOUNDARIES.has(entry.toLowerCase()))
921
+ flush();
922
+ else
923
+ current.push(entry);
924
+ continue;
925
+ }
926
+ const operation = entry;
927
+ if (operation.op === "glob") {
928
+ current.push(operation.pattern);
929
+ continue;
930
+ }
931
+ if (SHELL_COMMAND_BOUNDARIES.has(operation.op)) {
932
+ flush();
933
+ continue;
934
+ }
935
+ // Every remaining control operator is a redirection. Its next string is
936
+ // a path or descriptor, not an argv token.
937
+ skipRedirectionTarget = true;
938
+ }
939
+ flush();
940
+ return { commands, parameterNames };
941
+ }
942
+ function resolveKnownShellParameters(token, knownVariables, parameterNames) {
943
+ let resolved = token;
944
+ for (const [marker, name] of parameterNames) {
945
+ const known = knownVariables.get(name);
946
+ if (known !== undefined)
947
+ resolved = resolved.replaceAll(marker, known);
948
+ }
949
+ return resolved;
950
+ }
951
+ function shellTokenCanEqual(token, expected) {
952
+ const escaped = token
953
+ .split(new RegExp(`(?:${SHELL_PARAMETER_MARKER}\\d+__|${SHELL_ARRAY_EXPANSION})`, "g"))
954
+ .map((literal) => literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
955
+ .join(".*");
956
+ return new RegExp(`^${escaped}$`, "i").test(expected);
957
+ }
958
+ function shellExecutableCanEqual(token, expected) {
959
+ const basenameToken = token.slice(token.lastIndexOf("/") + 1);
960
+ return shellTokenCanEqual(basenameToken, expected);
961
+ }
962
+ function exactShellExecutable(token) {
963
+ if (token === undefined || token.includes(SHELL_PARAMETER_MARKER))
964
+ return undefined;
965
+ return token.slice(token.lastIndexOf("/") + 1).toLowerCase();
966
+ }
967
+ const SUDO_SHORT_OPERANDS = new Set(["-C", "-D", "-g", "-h", "-p", "-R", "-r", "-T", "-t", "-U", "-u"]);
968
+ const SUDO_LONG_OPERANDS = new Set(["--chdir", "--chroot", "--close-from", "--command-timeout", "--group", "--host", "--other-user", "--prompt", "--role", "--type", "--user"]);
969
+ const TIME_SHORT_OPERANDS = new Set(["-f", "-o"]);
970
+ const TIME_LONG_OPERANDS = new Set(["--format", "--output"]);
971
+ function wrapperOptionAdvance(option, shortOperands, longOperands) {
972
+ if (shortOperands.has(option) || longOperands.has(option))
973
+ return 2;
974
+ if ([...shortOperands].some((candidate) => option.startsWith(candidate) && option.length > candidate.length))
975
+ return 1;
976
+ if ([...longOperands].some((candidate) => option.startsWith(`${candidate}=`)))
977
+ return 1;
978
+ return 0;
979
+ }
980
+ function resolveShellCommand(tokens, startIndex) {
981
+ let index = startIndex;
982
+ while (index < tokens.length) {
983
+ const executable = exactShellExecutable(tokens[index]);
984
+ if (SHELL_GRAMMAR_PREFIXES.has(executable ?? "")) {
985
+ index += 1;
986
+ continue;
987
+ }
988
+ if (executable === "coproc") {
989
+ index += 1;
990
+ const candidate = tokens[index] ?? "";
991
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidate) && !shellExecutableCanEqual(candidate, "ouro") && tokens[index + 1] !== undefined)
992
+ index += 1;
993
+ continue;
994
+ }
995
+ if (executable === "command" || executable === "nohup") {
996
+ index += 1;
997
+ if (executable === "command" && (tokens[index] === "-v" || tokens[index] === "-V"))
998
+ return { index: tokens.length };
999
+ while (tokens[index]?.startsWith("-"))
1000
+ index += 1;
1001
+ continue;
1002
+ }
1003
+ if (executable === "env") {
1004
+ index += 1;
1005
+ while (index < tokens.length) {
1006
+ const option = tokens[index];
1007
+ if (option === "-S" || option === "--split-string")
1008
+ return { index, script: `env ${tokens.slice(index + 1).join(" ")}` };
1009
+ if (option.startsWith("--split-string="))
1010
+ return { index, script: `env ${[option.slice("--split-string=".length), ...tokens.slice(index + 1)].join(" ")}` };
1011
+ if (["-u", "-C", "--unset", "--chdir"].includes(option))
1012
+ index += 2;
1013
+ else if (option.startsWith("-") || /^[A-Za-z_][A-Za-z0-9_]*=/.test(option))
1014
+ index += 1;
1015
+ else
1016
+ break;
1017
+ }
1018
+ continue;
1019
+ }
1020
+ if (executable === "sudo") {
1021
+ index += 1;
1022
+ while (tokens[index]?.startsWith("-")) {
1023
+ const advance = wrapperOptionAdvance(tokens[index], SUDO_SHORT_OPERANDS, SUDO_LONG_OPERANDS);
1024
+ index += advance === 0 ? 1 : advance;
1025
+ }
1026
+ continue;
1027
+ }
1028
+ if (executable === "time") {
1029
+ index += 1;
1030
+ while (tokens[index]?.startsWith("-")) {
1031
+ const advance = wrapperOptionAdvance(tokens[index], TIME_SHORT_OPERANDS, TIME_LONG_OPERANDS);
1032
+ index += advance === 0 ? 1 : advance;
1033
+ }
1034
+ continue;
1035
+ }
1036
+ if (executable === "exec") {
1037
+ index += 1;
1038
+ while (tokens[index]?.startsWith("-"))
1039
+ index += tokens[index] === "-a" ? 2 : 1;
1040
+ continue;
1041
+ }
1042
+ break;
1043
+ }
1044
+ return { index };
1045
+ }
1046
+ function shellScriptRequiresFamily(script, variables, depth) {
1047
+ if (script.includes(SHELL_PARAMETER_MARKER) || script.includes(SHELL_ARRAY_EXPANSION))
1048
+ return true;
1049
+ return shellCommandsContainMailCacheSync(script, variables, depth + 1);
1050
+ }
1051
+ function shellTokensContainMailCacheSync(tokens, startIndex, variables, depth) {
1052
+ const resolved = resolveShellCommand(tokens, startIndex);
1053
+ if (resolved.script !== undefined)
1054
+ return shellScriptRequiresFamily(resolved.script, variables, depth);
1055
+ const executableToken = tokens[resolved.index] ?? "";
1056
+ const executable = exactShellExecutable(executableToken);
1057
+ if (executableToken.includes(SHELL_ARRAY_EXPANSION))
1058
+ return true;
1059
+ if (SHELL_INTERPRETERS.has(executable ?? "")) {
1060
+ const commandOption = tokens.findIndex((token, index) => index > resolved.index && /^-[^-]*c/.test(token));
1061
+ return commandOption >= 0
1062
+ && shellScriptRequiresFamily(tokens[commandOption + 1] ?? "", variables, depth);
1063
+ }
1064
+ if (executable === "eval")
1065
+ return shellScriptRequiresFamily(tokens.slice(resolved.index + 1).join(" "), variables, depth);
1066
+ return shellExecutableCanEqual(executableToken, "ouro")
1067
+ && shellTokenCanEqual(tokens[resolved.index + 1] ?? "", "mail")
1068
+ && shellTokenCanEqual(tokens[resolved.index + 2] ?? "", "sync-cache");
1069
+ }
1070
+ function shellCommandsContainMailCacheSync(command, inheritedVariables = new Map(), depth = 0) {
1071
+ if (depth >= 32)
1072
+ return true;
1073
+ let parsed;
1074
+ try {
1075
+ parsed = parseShellCommands(command);
1076
+ }
1077
+ catch {
1078
+ return false;
1079
+ }
1080
+ const knownVariables = new Map(inheritedVariables);
1081
+ for (const rawTokens of parsed.commands) {
1082
+ const tokens = rawTokens.map((token) => resolveKnownShellParameters(token, knownVariables, parsed.parameterNames));
1083
+ const invocationVariables = new Map(knownVariables);
1084
+ let commandIndex = 0;
1085
+ while (commandIndex < tokens.length) {
1086
+ const assignment = tokens[commandIndex].match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/s);
1087
+ if (!assignment)
1088
+ break;
1089
+ if (assignment[2].includes(SHELL_PARAMETER_MARKER))
1090
+ invocationVariables.delete(assignment[1]);
1091
+ else
1092
+ invocationVariables.set(assignment[1], assignment[2]);
1093
+ commandIndex += 1;
1094
+ }
1095
+ if (commandIndex === tokens.length) {
1096
+ knownVariables.clear();
1097
+ for (const [name, value] of invocationVariables)
1098
+ knownVariables.set(name, value);
1099
+ continue;
1100
+ }
1101
+ if (shellTokensContainMailCacheSync(tokens, commandIndex, invocationVariables, depth))
1102
+ return true;
1103
+ }
1104
+ return false;
1105
+ }
1106
+ function shellContainsMailCacheSync(command) {
1107
+ const executableCommand = executableShellView(command);
1108
+ if (shellContainsAmbiguousAnsiMailCacheSync(executableCommand))
1109
+ return true;
1110
+ return shellCommandsContainMailCacheSync(executableCommand);
1111
+ }
1112
+ function mailCacheSyncShellGuardrail(toolName, args, context) {
1113
+ if (toolName !== "shell" || !shellContainsMailCacheSync(args.command ?? ""))
1114
+ return allow;
1115
+ if (context.trustLevel === undefined || context.trustLevel === "family")
1116
+ return allow;
1117
+ return deny("hosted mail cache convergence requires family trust.");
1118
+ }
1119
+ function mailTrustGuardrail(toolName, args, context) {
1120
+ if (MAIL_FAMILY_TOOLS.has(toolName)) {
1121
+ if (context.trustLevel === undefined || context.trustLevel === "family")
1122
+ return allow;
1123
+ if (toolName === "mail_send")
1124
+ return deny("outbound mail sends require family trust.");
1125
+ return deny(toolName === "mail_decide"
1126
+ ? "mail screener decisions require family trust."
1127
+ : "delegated human mail requires family trust.");
1128
+ }
1129
+ if (MAIL_DELEGATED_READ_TOOLS.has(toolName)) {
1130
+ const scope = (args.scope ?? "").trim().toLowerCase();
1131
+ if (scope === "delegated" || scope === "all") {
1132
+ if (context.trustLevel === undefined || context.trustLevel === "family")
1133
+ return allow;
1134
+ return deny("delegated human mail requires family trust.");
1135
+ }
1136
+ }
1137
+ return allow;
1138
+ }
1139
+ function checkCredentialTrustGuardrails(toolName, context) {
1140
+ if (CREDENTIAL_FAMILY_TOOLS.has(toolName) || COMMERCE_FAMILY_TOOLS.has(toolName)) {
1141
+ if (context.trustLevel === "family")
1142
+ return allow;
1143
+ return deny(REASONS.needsTrust);
1144
+ }
1145
+ if (CREDENTIAL_TRUSTED_TOOLS.has(toolName) || TRAVEL_TRUSTED_TOOLS.has(toolName) || A2A_TRUSTED_TOOLS.has(toolName)) {
1146
+ if ((0, friends_1.isTrustedLevel)(context.trustLevel))
1147
+ return allow;
1148
+ return deny(REASONS.needsTrust);
1149
+ }
1150
+ return allow;
1151
+ }
1152
+ function checkCommerceAuthorityGuardrails(toolName, args, context) {
1153
+ if (!COMMERCE_AUTHORITY_TOOLS.has(toolName))
1154
+ return allow;
1155
+ if (!context.agentRoot)
1156
+ return deny("commerce authority unavailable: agent root could not be resolved.");
1157
+ const result = (0, store_1.validateCommerceAuthority)({
1158
+ agentRoot: context.agentRoot,
1159
+ token: args.commerce_authority,
1160
+ toolName,
1161
+ args,
1162
+ friendId: context.friendId,
1163
+ });
1164
+ if (result.ok)
1165
+ return allow;
1166
+ return deny(`commerce authority required: ${result.reason}`);
1167
+ }
1168
+ function checkFirstClassMcpTrust(context) {
1169
+ if (!context.mcpServerName)
1170
+ return allow;
1171
+ const rules = MCP_SERVER_TRUST[context.mcpServerName] ?? { minTrust: "friend", blockGroupChat: false };
1172
+ if (!trustLevelSatisfied(rules.minTrust, context.trustLevel ?? "friend")) {
1173
+ return deny(REASONS.needsTrust);
1174
+ }
1175
+ if (rules.blockGroupChat && context.isGroupChat) {
1176
+ return deny("browser tools are only available in 1:1 conversations, not group chats.");
1177
+ }
1178
+ return allow;
1179
+ }
1180
+ function checkTrustLevelGuardrails(toolName, args, context) {
1181
+ const cacheSyncResult = mailCacheSyncShellGuardrail(toolName, args, context);
1182
+ if (!cacheSyncResult.allowed)
1183
+ return cacheSyncResult;
1184
+ const mailResult = mailTrustGuardrail(toolName, args, context);
1185
+ if (!mailResult.allowed)
1186
+ return mailResult;
1187
+ if (SHEPHERD_FAMILY_TOOLS.has(toolName) && context.trustLevel !== "family") {
1188
+ return deny("the owner's terminals require family trust.");
1189
+ }
1190
+ // Credential tools have their own trust rules that apply at all levels
1191
+ const credentialResult = checkCredentialTrustGuardrails(toolName, context);
1192
+ if (!credentialResult.allowed)
1193
+ return credentialResult;
1194
+ const commerceAuthorityResult = checkCommerceAuthorityGuardrails(toolName, args, context);
1195
+ if (!commerceAuthorityResult.allowed)
1196
+ return commerceAuthorityResult;
1197
+ // First-class MCP tool trust (e.g. browser_navigate) — applies at all trust levels
1198
+ const firstClassMcpResult = checkFirstClassMcpTrust(context);
1199
+ if (!firstClassMcpResult.allowed)
1200
+ return firstClassMcpResult;
1201
+ // MCP server-specific trust via shell (e.g. ouro mcp call browser) — applies at all trust levels
1202
+ if (toolName === "shell") {
1203
+ const mcpResult = checkMcpServerTrust(args.command || "", context);
1204
+ if (!mcpResult.allowed)
1205
+ return mcpResult;
1206
+ }
1207
+ // Trusted levels (family/friend) — no further trust guardrails. Undefined defaults to friend.
1208
+ if ((0, friends_1.isTrustedLevel)(context.trustLevel))
1209
+ return allow;
1210
+ if (toolName === "shell") {
1211
+ return checkShellTrustGuardrails(args.command || "", context.trustLevel);
1212
+ }
1213
+ return checkWriteTrustGuardrails(toolName, args, context);
1214
+ }
1215
+ // --- main entry point ---
1216
+ function guardInvocation(toolName, args, context) {
1217
+ (0, runtime_1.emitNervesEvent)({
1218
+ component: "tools",
1219
+ event: "tools.guard_check",
1220
+ message: "guardrail check",
1221
+ meta: { toolName },
1222
+ });
1223
+ // Read-only tools are always allowed (no structural or trust guardrails)
1224
+ if (READ_ONLY_TOOLS.has(toolName))
1225
+ return allow;
1226
+ // Layer 1: structural guardrails (always on)
1227
+ const structuralResult = checkStructuralGuardrails(toolName, args, context);
1228
+ if (!structuralResult.allowed)
1229
+ return structuralResult;
1230
+ // Layer 2: trust-level guardrails (varies by friend's trust)
1231
+ return checkTrustLevelGuardrails(toolName, args, context);
1232
+ }