@ouro.bot/cli 0.1.0-alpha.88 → 0.1.0-alpha.880

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 (669) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5601 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2995 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1197 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1127 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2085 -0
  38. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  39. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  40. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  41. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  42. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  43. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  44. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  45. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  46. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +27 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  52. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  53. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  54. package/deploy/unraid/sanctuary.xml +29 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +238 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command.js +151 -0
  59. package/dist/a2a/delegation-stores.js +56 -0
  60. package/dist/a2a/did-resolution.js +93 -0
  61. package/dist/a2a/escalation-grants.js +122 -0
  62. package/dist/a2a/escalation-wiring.js +60 -0
  63. package/dist/a2a/identity.js +204 -0
  64. package/dist/a2a/inbound-share.js +110 -0
  65. package/dist/a2a/mission-result-wire.js +196 -0
  66. package/dist/a2a/onboarding.js +133 -0
  67. package/dist/a2a/outbox-client.js +57 -0
  68. package/dist/a2a/outbox-store.js +188 -0
  69. package/dist/a2a/outbox-wire.js +95 -0
  70. package/dist/a2a/pin-store.js +132 -0
  71. package/dist/a2a/replay-harness.js +175 -0
  72. package/dist/a2a/resolution-proof.js +53 -0
  73. package/dist/a2a/sealed-chat.js +113 -0
  74. package/dist/a2a/seen-ledger.js +120 -0
  75. package/dist/a2a/server.js +766 -0
  76. package/dist/a2a/task-store.js +69 -0
  77. package/dist/a2a/transport.js +45 -0
  78. package/dist/a2a/trusted-files.js +98 -0
  79. package/dist/a2a/types.js +3 -0
  80. package/dist/arc/attention-types.js +8 -0
  81. package/dist/arc/cares.js +360 -0
  82. package/dist/arc/episodes.js +118 -0
  83. package/dist/arc/evolution.js +490 -0
  84. package/dist/arc/flight-recorder.js +1034 -0
  85. package/dist/arc/intentions.js +134 -0
  86. package/dist/arc/json-store.js +117 -0
  87. package/dist/arc/obligations.js +386 -0
  88. package/dist/arc/packets.js +336 -0
  89. package/dist/arc/presence.js +185 -0
  90. package/dist/arc/task-lifecycle.js +57 -0
  91. package/dist/commerce/store.js +755 -0
  92. package/dist/commerce/types.js +3 -0
  93. package/dist/heart/active-work.js +798 -40
  94. package/dist/heart/agent-entry.js +252 -3
  95. package/dist/heart/approval-files.js +113 -0
  96. package/dist/heart/approval-store.js +960 -0
  97. package/dist/heart/attachments/image-normalize.js +194 -0
  98. package/dist/heart/attachments/materialize.js +97 -0
  99. package/dist/heart/attachments/originals.js +88 -0
  100. package/dist/heart/attachments/render.js +29 -0
  101. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  102. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  103. package/dist/heart/attachments/sources/index.js +18 -0
  104. package/dist/heart/attachments/sources/telegram.js +71 -0
  105. package/dist/heart/attachments/store.js +132 -0
  106. package/dist/heart/attachments/types.js +93 -0
  107. package/dist/heart/auth/auth-flow.js +495 -0
  108. package/dist/heart/autonomy-budget.js +478 -0
  109. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  110. package/dist/heart/awaiting/await-alert.js +152 -0
  111. package/dist/heart/awaiting/await-expiry.js +143 -0
  112. package/dist/heart/awaiting/await-loader.js +91 -0
  113. package/dist/heart/awaiting/await-parser.js +152 -0
  114. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  115. package/dist/heart/awaiting/await-scheduler.js +382 -0
  116. package/dist/heart/background-operations.js +281 -0
  117. package/dist/heart/bridges/manager.js +137 -17
  118. package/dist/heart/bridges/store.js +14 -2
  119. package/dist/heart/bundle-state.js +168 -0
  120. package/dist/heart/commitments.js +44 -18
  121. package/dist/heart/config-registry.js +331 -0
  122. package/dist/heart/config.js +174 -131
  123. package/dist/heart/context-loss-gauntlet.js +387 -0
  124. package/dist/heart/context-loss-sentinel.js +1157 -0
  125. package/dist/heart/core.js +2286 -580
  126. package/dist/heart/cross-chat-delivery.js +9 -22
  127. package/dist/heart/daemon/agent-config-check.js +451 -0
  128. package/dist/heart/daemon/agent-discovery.js +185 -3
  129. package/dist/heart/daemon/agent-service.js +542 -0
  130. package/dist/heart/daemon/agentic-repair.js +547 -0
  131. package/dist/heart/daemon/await-private-wake.js +59 -0
  132. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  133. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  134. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  135. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  136. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  137. package/dist/heart/daemon/cadence.js +180 -0
  138. package/dist/heart/daemon/cli-defaults.js +854 -0
  139. package/dist/heart/daemon/cli-desk.js +322 -0
  140. package/dist/heart/daemon/cli-exec.js +8951 -0
  141. package/dist/heart/daemon/cli-help.js +716 -0
  142. package/dist/heart/daemon/cli-parse.js +2941 -0
  143. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  144. package/dist/heart/daemon/cli-render.js +777 -0
  145. package/dist/heart/daemon/cli-types.js +8 -0
  146. package/dist/heart/daemon/connect-bay.js +323 -0
  147. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  148. package/dist/heart/daemon/container-healthcheck.js +112 -0
  149. package/dist/heart/daemon/container-runtime.js +97 -0
  150. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  151. package/dist/heart/daemon/container-spec-auditor.js +232 -0
  152. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  153. package/dist/heart/daemon/daemon-cli.js +29 -2349
  154. package/dist/heart/daemon/daemon-entry.js +932 -11
  155. package/dist/heart/daemon/daemon-health.js +186 -0
  156. package/dist/heart/daemon/daemon-rollup.js +57 -0
  157. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  158. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  159. package/dist/heart/daemon/daemon.js +2084 -105
  160. package/dist/heart/daemon/dns-workflow.js +394 -0
  161. package/dist/heart/daemon/doctor-types.js +8 -0
  162. package/dist/heart/daemon/doctor.js +1755 -0
  163. package/dist/heart/daemon/freshness.js +345 -0
  164. package/dist/heart/daemon/habit-private-wake.js +61 -0
  165. package/dist/heart/daemon/health-monitor.js +142 -11
  166. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  167. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  168. package/dist/heart/daemon/http-health-probe.js +80 -0
  169. package/dist/heart/daemon/human-command-screens.js +234 -0
  170. package/dist/heart/daemon/human-readiness.js +114 -0
  171. package/dist/heart/daemon/inner-status.js +78 -0
  172. package/dist/heart/daemon/interactive-repair.js +394 -0
  173. package/dist/heart/daemon/launchd.js +37 -8
  174. package/dist/heart/daemon/log-tailer.js +79 -10
  175. package/dist/heart/daemon/logs-prune.js +132 -0
  176. package/dist/heart/daemon/mcp-canary.js +524 -0
  177. package/dist/heart/daemon/message-router.js +65 -5
  178. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  179. package/dist/heart/daemon/os-cron-deps.js +135 -0
  180. package/dist/heart/daemon/os-cron.js +22 -14
  181. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  182. package/dist/heart/daemon/ouro-entry.js +3 -1
  183. package/dist/heart/daemon/plugin-cli.js +432 -0
  184. package/dist/heart/daemon/process-manager.js +733 -61
  185. package/dist/heart/daemon/provider-discovery.js +137 -0
  186. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  187. package/dist/heart/daemon/prunable-bundle.js +144 -0
  188. package/dist/heart/daemon/pulse.js +511 -0
  189. package/dist/heart/daemon/readiness-repair.js +365 -0
  190. package/dist/heart/daemon/run-hooks.js +2 -0
  191. package/dist/heart/daemon/runtime-logging.js +47 -14
  192. package/dist/heart/daemon/runtime-metadata.js +2 -30
  193. package/dist/heart/daemon/runtime-mode.js +13 -2
  194. package/dist/heart/daemon/safe-mode.js +161 -0
  195. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  196. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  197. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  198. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  199. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  200. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  201. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  202. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  203. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1310 -0
  204. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  205. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  206. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  207. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  208. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  209. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  210. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  211. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  212. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  213. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  214. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  215. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  216. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  217. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  218. package/dist/heart/daemon/sense-manager.js +699 -48
  219. package/dist/heart/daemon/session-id-resolver.js +131 -0
  220. package/dist/heart/daemon/skill-management-installer.js +1 -1
  221. package/dist/heart/daemon/socket-client.js +180 -12
  222. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  223. package/dist/heart/daemon/startup-tui.js +339 -0
  224. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  225. package/dist/heart/daemon/task-scheduler.js +117 -39
  226. package/dist/heart/daemon/terminal-ui.js +499 -0
  227. package/dist/heart/daemon/thoughts.js +138 -54
  228. package/dist/heart/daemon/up-progress.js +366 -0
  229. package/dist/heart/daemon/vault-items.js +56 -0
  230. package/dist/heart/delegation.js +1 -4
  231. package/dist/heart/external-events/router.js +1516 -0
  232. package/dist/heart/failure-reports.js +335 -0
  233. package/dist/heart/file-lock.js +109 -0
  234. package/dist/heart/frontend-approval-runtime.js +506 -0
  235. package/dist/heart/frontend-journal.js +215 -0
  236. package/dist/heart/frontend-session-service.js +237 -0
  237. package/dist/heart/frontend-socket-client.js +164 -0
  238. package/dist/heart/frontend-socket.js +400 -0
  239. package/dist/heart/habits/habit-cancel.js +810 -0
  240. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  241. package/dist/heart/habits/habit-migration.js +194 -0
  242. package/dist/heart/habits/habit-parser.js +278 -0
  243. package/dist/heart/habits/habit-runtime-state.js +93 -0
  244. package/dist/heart/habits/habit-scheduler.js +653 -0
  245. package/dist/heart/habits/habit-session-summary.js +318 -0
  246. package/dist/heart/habits/habit-session.js +636 -0
  247. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  248. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  249. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  250. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  251. package/dist/heart/identity.js +196 -59
  252. package/dist/heart/kept-notes.js +289 -0
  253. package/dist/heart/kicks.js +1 -1
  254. package/dist/heart/machine-identity.js +161 -0
  255. package/dist/heart/mail-import-discovery.js +356 -0
  256. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  257. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  258. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  259. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  260. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  261. package/dist/heart/mailbox/mailbox-http.js +99 -0
  262. package/dist/heart/mailbox/mailbox-read.js +39 -0
  263. package/dist/heart/mailbox/mailbox-types.js +27 -0
  264. package/dist/heart/mailbox/mailbox-view.js +197 -0
  265. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  266. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  267. package/dist/heart/mailbox/readers/mail.js +375 -0
  268. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  269. package/dist/heart/mailbox/readers/sessions.js +231 -0
  270. package/dist/heart/mailbox/readers/shared.js +111 -0
  271. package/dist/heart/mcp/mcp-server.js +696 -0
  272. package/dist/heart/migrate-config.js +100 -0
  273. package/dist/heart/model-capabilities.js +11 -0
  274. package/dist/heart/orientation-frame.js +345 -0
  275. package/dist/heart/platform.js +81 -0
  276. package/dist/heart/primitives.js +1 -1
  277. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  278. package/dist/heart/private-runtime/index.js +18 -0
  279. package/dist/heart/private-runtime/ledger.js +221 -0
  280. package/dist/heart/private-runtime/policy.js +252 -0
  281. package/dist/heart/private-runtime/types.js +2 -0
  282. package/dist/heart/progress-story.js +1 -1
  283. package/dist/heart/provider-attempt.js +137 -0
  284. package/dist/heart/provider-binding-resolver.js +273 -0
  285. package/dist/heart/provider-credentials.js +449 -0
  286. package/dist/heart/provider-failover.js +311 -0
  287. package/dist/heart/provider-models.js +96 -0
  288. package/dist/heart/provider-ping.js +265 -0
  289. package/dist/heart/provider-readiness-cache.js +119 -0
  290. package/dist/heart/provider-visibility.js +188 -0
  291. package/dist/heart/providers/anthropic-token.js +131 -0
  292. package/dist/heart/providers/anthropic.js +173 -60
  293. package/dist/heart/providers/azure.js +23 -11
  294. package/dist/heart/providers/error-classification.js +127 -0
  295. package/dist/heart/providers/github-copilot.js +34 -38
  296. package/dist/heart/providers/minimax-vlm.js +189 -0
  297. package/dist/heart/providers/minimax.js +26 -8
  298. package/dist/heart/providers/openai-codex-token.js +349 -0
  299. package/dist/heart/providers/openai-codex.js +55 -40
  300. package/dist/heart/providers/openai-compatible.js +177 -0
  301. package/dist/heart/reply-style.js +56 -0
  302. package/dist/heart/run-ledger.js +247 -0
  303. package/dist/heart/runtime-capability-check.js +170 -0
  304. package/dist/heart/runtime-credentials.js +607 -0
  305. package/dist/heart/runtime-cwd.js +87 -0
  306. package/dist/heart/sense-truth.js +22 -4
  307. package/dist/heart/session-activity.js +92 -24
  308. package/dist/heart/session-events.js +1504 -0
  309. package/dist/heart/session-playback-cli-main.js +5 -0
  310. package/dist/heart/session-playback-cli.js +36 -0
  311. package/dist/heart/session-playback.js +231 -0
  312. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  313. package/dist/heart/session-redaction-repair.js +552 -0
  314. package/dist/heart/session-stats-cli-main.js +5 -0
  315. package/dist/heart/session-stats.js +183 -0
  316. package/dist/heart/session-transcript.js +133 -0
  317. package/dist/heart/source-grounding.js +194 -0
  318. package/dist/heart/start-of-turn-packet.js +372 -0
  319. package/dist/heart/steward-policy.js +656 -0
  320. package/dist/heart/streaming.js +604 -207
  321. package/dist/heart/structured-output.js +196 -0
  322. package/dist/heart/sync-classification.js +176 -0
  323. package/dist/heart/sync.js +505 -0
  324. package/dist/heart/target-resolution.js +11 -7
  325. package/dist/heart/tempo.js +93 -0
  326. package/dist/heart/temporal-view.js +41 -0
  327. package/dist/heart/timeouts.js +101 -0
  328. package/dist/heart/tool-activity-callbacks.js +59 -0
  329. package/dist/heart/tool-approval.js +382 -0
  330. package/dist/heart/tool-description.js +155 -0
  331. package/dist/heart/tool-friction.js +55 -0
  332. package/dist/heart/tool-loop.js +206 -0
  333. package/dist/heart/turn-context.js +487 -0
  334. package/dist/heart/turn-execution-lease.js +30 -0
  335. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  336. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  337. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  338. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  339. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  340. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  341. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  342. package/dist/heart/versioning/update-hooks.js +154 -0
  343. package/dist/heart/versioning/version-intent.js +114 -0
  344. package/dist/heart/work-card.js +380 -0
  345. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  346. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  347. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  348. package/dist/mailbox-ui/index.html +16 -0
  349. package/dist/mailroom/attention.js +167 -0
  350. package/dist/mailroom/autonomy.js +209 -0
  351. package/dist/mailroom/blob-store.js +889 -0
  352. package/dist/mailroom/body-cache.js +61 -0
  353. package/dist/mailroom/cache-sync-cli.js +58 -0
  354. package/dist/mailroom/core.js +803 -0
  355. package/dist/mailroom/entry.js +160 -0
  356. package/dist/mailroom/file-store.js +568 -0
  357. package/dist/mailroom/hosted-cache-sync.js +384 -0
  358. package/dist/mailroom/mbox-import.js +393 -0
  359. package/dist/mailroom/migration.js +164 -0
  360. package/dist/mailroom/outbound.js +380 -0
  361. package/dist/mailroom/policy.js +263 -0
  362. package/dist/mailroom/reader.js +292 -0
  363. package/dist/mailroom/search-cache.js +513 -0
  364. package/dist/mailroom/search-relevance.js +319 -0
  365. package/dist/mailroom/smtp-ingress.js +176 -0
  366. package/dist/mailroom/source-state.js +176 -0
  367. package/dist/mailroom/thread.js +109 -0
  368. package/dist/mailroom/travel-extract.js +89 -0
  369. package/dist/mind/bundle-manifest.js +24 -2
  370. package/dist/mind/context.js +307 -139
  371. package/dist/mind/desk-section.js +362 -0
  372. package/dist/mind/diary-integrity.js +60 -0
  373. package/dist/mind/{memory.js → diary.js} +68 -77
  374. package/dist/mind/embedding-provider.js +60 -0
  375. package/dist/mind/file-state.js +179 -0
  376. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  377. package/dist/mind/obligation-steering.js +199 -3
  378. package/dist/mind/pending.js +36 -10
  379. package/dist/mind/prompt-budget.js +479 -0
  380. package/dist/mind/prompt-refresh.js +3 -2
  381. package/dist/mind/prompt.js +1048 -198
  382. package/dist/mind/provenance-trust.js +26 -0
  383. package/dist/mind/record-paths.js +312 -0
  384. package/dist/mind/scrutiny.js +173 -0
  385. package/dist/mind/session-transaction.js +564 -0
  386. package/dist/nerves/cli-logging.js +7 -1
  387. package/dist/nerves/coverage/audit-rules.js +15 -6
  388. package/dist/nerves/coverage/audit.js +28 -2
  389. package/dist/nerves/coverage/cli.js +1 -1
  390. package/dist/nerves/coverage/contract.js +5 -5
  391. package/dist/nerves/coverage/file-completeness.js +139 -5
  392. package/dist/nerves/coverage/run-artifacts.js +55 -35
  393. package/dist/nerves/coverage/source-scanner.js +4 -4
  394. package/dist/nerves/event-buffer.js +111 -0
  395. package/dist/nerves/index.js +293 -9
  396. package/dist/nerves/observation.js +20 -0
  397. package/dist/nerves/redact.js +79 -0
  398. package/dist/nerves/review/cli-main.js +5 -0
  399. package/dist/nerves/review/cli.js +156 -0
  400. package/dist/nerves/review/core.js +159 -0
  401. package/dist/nerves/runtime.js +17 -1
  402. package/dist/repertoire/ado-client.js +15 -56
  403. package/dist/repertoire/ado-semantic.js +16 -10
  404. package/dist/repertoire/api-client.js +97 -0
  405. package/dist/repertoire/bitwarden-store.js +1045 -0
  406. package/dist/repertoire/bundle-templates.js +71 -0
  407. package/dist/repertoire/bw-installer.js +180 -0
  408. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  409. package/dist/repertoire/coding/context-pack.js +331 -0
  410. package/dist/repertoire/coding/feedback.js +174 -32
  411. package/dist/repertoire/coding/index.js +15 -3
  412. package/dist/repertoire/coding/manager.js +159 -10
  413. package/dist/repertoire/coding/spawner.js +58 -11
  414. package/dist/repertoire/coding/tools.js +221 -15
  415. package/dist/repertoire/coding/workbench-client.js +272 -0
  416. package/dist/repertoire/coding/workbench-manager.js +346 -0
  417. package/dist/repertoire/commerce-errors.js +109 -0
  418. package/dist/repertoire/commerce-self-test.js +156 -0
  419. package/dist/repertoire/credential-access.js +178 -0
  420. package/dist/repertoire/desk/classifier.js +362 -0
  421. package/dist/repertoire/duffel-client.js +185 -0
  422. package/dist/repertoire/github-client.js +14 -55
  423. package/dist/repertoire/graph-client.js +11 -52
  424. package/dist/repertoire/guardrails.js +873 -19
  425. package/dist/repertoire/house-sweep.js +466 -0
  426. package/dist/repertoire/mcp-client.js +58 -5
  427. package/dist/repertoire/mcp-manager.js +427 -139
  428. package/dist/repertoire/mcp-tools.js +132 -0
  429. package/dist/repertoire/mcp-write-guard.js +46 -0
  430. package/dist/repertoire/plugin-mcp.js +175 -0
  431. package/dist/repertoire/plugins.js +253 -0
  432. package/dist/repertoire/relationship-authorization.js +322 -0
  433. package/dist/repertoire/shell-sessions.js +134 -0
  434. package/dist/repertoire/skills.js +48 -4
  435. package/dist/repertoire/stripe-client.js +131 -0
  436. package/dist/repertoire/tool-arguments.js +182 -0
  437. package/dist/repertoire/tool-results.js +29 -0
  438. package/dist/repertoire/tools-a2a.js +699 -0
  439. package/dist/repertoire/tools-attachments.js +322 -0
  440. package/dist/repertoire/tools-awaiting.js +870 -0
  441. package/dist/repertoire/tools-base.js +79 -1168
  442. package/dist/repertoire/tools-bluebubbles.js +2 -0
  443. package/dist/repertoire/tools-bridge.js +144 -0
  444. package/dist/repertoire/tools-bundle.js +993 -0
  445. package/dist/repertoire/tools-commerce.js +253 -0
  446. package/dist/repertoire/tools-config.js +186 -0
  447. package/dist/repertoire/tools-continuity.js +575 -0
  448. package/dist/repertoire/tools-credential.js +383 -0
  449. package/dist/repertoire/tools-escalation.js +84 -0
  450. package/dist/repertoire/tools-evolution.js +527 -0
  451. package/dist/repertoire/tools-files.js +344 -0
  452. package/dist/repertoire/tools-flight.js +290 -0
  453. package/dist/repertoire/tools-flow.js +119 -0
  454. package/dist/repertoire/tools-github.js +3 -8
  455. package/dist/repertoire/tools-habits.js +103 -0
  456. package/dist/repertoire/tools-house-care.js +138 -0
  457. package/dist/repertoire/tools-mail.js +1828 -0
  458. package/dist/repertoire/tools-notes.js +496 -0
  459. package/dist/repertoire/tools-obligations.js +182 -0
  460. package/dist/repertoire/tools-orientation.js +31 -0
  461. package/dist/repertoire/tools-record.js +482 -0
  462. package/dist/repertoire/tools-rsvp.js +139 -0
  463. package/dist/repertoire/tools-runtime.js +238 -0
  464. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  465. package/dist/repertoire/tools-session.js +1133 -0
  466. package/dist/repertoire/tools-shell.js +149 -0
  467. package/dist/repertoire/tools-steward-policy.js +147 -0
  468. package/dist/repertoire/tools-stripe.js +224 -0
  469. package/dist/repertoire/tools-surface.js +369 -0
  470. package/dist/repertoire/tools-teams.js +12 -39
  471. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  472. package/dist/repertoire/tools-travel.js +125 -0
  473. package/dist/repertoire/tools-trip.js +982 -0
  474. package/dist/repertoire/tools-unraid.js +556 -0
  475. package/dist/repertoire/tools-user-profile.js +146 -0
  476. package/dist/repertoire/tools-vault.js +40 -0
  477. package/dist/repertoire/tools-voice.js +145 -0
  478. package/dist/repertoire/tools.js +509 -156
  479. package/dist/repertoire/travel-api-client.js +360 -0
  480. package/dist/repertoire/unraid-client.js +155 -0
  481. package/dist/repertoire/unraid-restart.js +339 -0
  482. package/dist/repertoire/user-profile.js +131 -0
  483. package/dist/repertoire/vault-setup.js +246 -0
  484. package/dist/repertoire/vault-unlock.js +628 -0
  485. package/dist/rsvp/aisleplanner-client.js +354 -0
  486. package/dist/rsvp/cli.js +926 -0
  487. package/dist/rsvp/config.js +327 -0
  488. package/dist/rsvp/cutover.js +433 -0
  489. package/dist/rsvp/diagnostics.js +232 -0
  490. package/dist/rsvp/diff-renderer.js +176 -0
  491. package/dist/rsvp/habit-policy.js +110 -0
  492. package/dist/rsvp/habit-stage.js +123 -0
  493. package/dist/rsvp/incident-bundle.js +97 -0
  494. package/dist/rsvp/migration.js +204 -0
  495. package/dist/rsvp/native-habit-runner.js +630 -0
  496. package/dist/rsvp/outbound-state.js +628 -0
  497. package/dist/rsvp/query.js +118 -0
  498. package/dist/rsvp/replay.js +233 -0
  499. package/dist/rsvp/snapshot.js +232 -0
  500. package/dist/rsvp/spend-ledger.js +175 -0
  501. package/dist/scripts/claude-code-hook.js +41 -0
  502. package/dist/scripts/claude-code-stop-hook.js +47 -0
  503. package/dist/senses/a2a-entry.js +131 -0
  504. package/dist/senses/acp-server.js +386 -0
  505. package/dist/senses/attention-queue.js +186 -0
  506. package/dist/senses/await-turn-message.js +65 -0
  507. package/dist/senses/bluebubbles/active-turns.js +216 -0
  508. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  509. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  510. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  511. package/dist/senses/bluebubbles/context-packet.js +207 -0
  512. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  513. package/dist/senses/bluebubbles/entry.js +90 -0
  514. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  515. package/dist/senses/bluebubbles/index.js +3841 -0
  516. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  517. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  518. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  519. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  520. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  521. package/dist/senses/bluebubbles/processed-log.js +133 -0
  522. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  523. package/dist/senses/bluebubbles/replay.js +284 -0
  524. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  525. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  526. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  527. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  528. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  529. package/dist/senses/cli/bracketed-paste.js +82 -0
  530. package/dist/senses/cli/image-paste.js +287 -0
  531. package/dist/senses/cli/image-ref-navigation.js +75 -0
  532. package/dist/senses/cli/ink-app.js +156 -0
  533. package/dist/senses/cli/inline-diff.js +64 -0
  534. package/dist/senses/cli/input-keys.js +174 -0
  535. package/dist/senses/cli/kill-ring.js +86 -0
  536. package/dist/senses/cli/message-list.js +51 -0
  537. package/dist/senses/cli/ouro-tui.js +607 -0
  538. package/dist/senses/cli/spinner-imperative.js +135 -0
  539. package/dist/senses/cli/spinner.js +101 -0
  540. package/dist/senses/cli/status-line.js +60 -0
  541. package/dist/senses/cli/streaming-markdown.js +526 -0
  542. package/dist/senses/cli/tool-display.js +85 -0
  543. package/dist/senses/cli/tool-render.js +85 -0
  544. package/dist/senses/cli/tui-store.js +241 -0
  545. package/dist/senses/cli/virtual-list.js +35 -0
  546. package/dist/senses/cli-entry.js +60 -8
  547. package/dist/senses/cli.js +601 -304
  548. package/dist/senses/commands.js +66 -3
  549. package/dist/senses/context-packet-ledger.js +371 -0
  550. package/dist/senses/context-packets.js +154 -0
  551. package/dist/senses/habit-lifecycle-guard.js +24 -0
  552. package/dist/senses/habit-turn-message.js +160 -0
  553. package/dist/senses/ingress-evidence.js +2 -0
  554. package/dist/senses/mail-entry.js +66 -0
  555. package/dist/senses/mail.js +524 -0
  556. package/dist/senses/pipeline.js +1115 -204
  557. package/dist/senses/private-runtime-worker.js +859 -0
  558. package/dist/senses/private-runtime.js +1619 -0
  559. package/dist/senses/proactive-content-guard.js +51 -0
  560. package/dist/senses/root-host-approval-port.js +345 -0
  561. package/dist/senses/root-host-approval-runtime.js +393 -0
  562. package/dist/senses/sanctuary-authority-resident.js +102 -0
  563. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  564. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  565. package/dist/senses/sanctuary-grounding.js +118 -0
  566. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  567. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  568. package/dist/senses/sanctuary-health-runner.js +104 -0
  569. package/dist/senses/sanctuary-health.js +422 -0
  570. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  571. package/dist/senses/sanctuary-interactive-control.js +410 -0
  572. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  573. package/dist/senses/sanctuary-media-optimization.js +514 -0
  574. package/dist/senses/sanctuary-runtime.js +347 -0
  575. package/dist/senses/sanctuary-sab.js +85 -0
  576. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  577. package/dist/senses/shared-turn.js +789 -0
  578. package/dist/senses/surface-tool.js +109 -0
  579. package/dist/senses/teams-entry.js +60 -8
  580. package/dist/senses/teams.js +519 -218
  581. package/dist/senses/telegram-admission.js +718 -0
  582. package/dist/senses/telegram-approval-runtime.js +793 -0
  583. package/dist/senses/telegram-attachments.js +186 -0
  584. package/dist/senses/telegram-audit-ledger.js +220 -0
  585. package/dist/senses/telegram-authority-transport.js +231 -0
  586. package/dist/senses/telegram-client.js +1749 -0
  587. package/dist/senses/telegram-effect-adapter.js +900 -0
  588. package/dist/senses/telegram-entry.js +83 -0
  589. package/dist/senses/telegram.js +2349 -0
  590. package/dist/senses/trust-gate.js +104 -9
  591. package/dist/senses/voice/audio-playback.js +237 -0
  592. package/dist/senses/voice/audio-routing.js +119 -0
  593. package/dist/senses/voice/elevenlabs.js +202 -0
  594. package/dist/senses/voice/floor-control.js +431 -0
  595. package/dist/senses/voice/floor-controller.js +115 -0
  596. package/dist/senses/voice/golden-path.js +116 -0
  597. package/dist/senses/voice/index.js +29 -0
  598. package/dist/senses/voice/meeting.js +113 -0
  599. package/dist/senses/voice/outbound.js +190 -0
  600. package/dist/senses/voice/phone.js +33 -0
  601. package/dist/senses/voice/playback.js +139 -0
  602. package/dist/senses/voice/realtime-eval.js +496 -0
  603. package/dist/senses/voice/realtime-trace.js +531 -0
  604. package/dist/senses/voice/transcript.js +70 -0
  605. package/dist/senses/voice/turn.js +191 -0
  606. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  607. package/dist/senses/voice/twilio-phone.js +5031 -0
  608. package/dist/senses/voice/types.js +2 -0
  609. package/dist/senses/voice/whisper.js +161 -0
  610. package/dist/senses/voice-entry.js +81 -0
  611. package/dist/senses/voice-realtime-eval-command.js +99 -0
  612. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  613. package/dist/senses/voice-twilio-entry.js +87 -0
  614. package/dist/trips/core.js +138 -0
  615. package/dist/trips/store.js +265 -0
  616. package/dist/util/frontmatter.js +69 -0
  617. package/npm-shrinkwrap.json +8100 -0
  618. package/package.json +73 -13
  619. package/skills/agent-commerce.md +113 -0
  620. package/skills/browser-navigation.md +117 -0
  621. package/skills/commerce-setup-guide.md +116 -0
  622. package/skills/commerce-setup.md +84 -0
  623. package/skills/configure-dev-tools.md +99 -0
  624. package/skills/travel-planning.md +138 -0
  625. package/dist/heart/daemon/auth-flow.js +0 -430
  626. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  627. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  628. package/dist/heart/daemon/update-hooks.js +0 -138
  629. package/dist/heart/obligations.js +0 -191
  630. package/dist/heart/safe-workspace.js +0 -362
  631. package/dist/heart/session-recall.js +0 -116
  632. package/dist/mind/friends/channel.js +0 -84
  633. package/dist/mind/friends/group-context.js +0 -144
  634. package/dist/mind/friends/resolver.js +0 -84
  635. package/dist/mind/friends/store-file.js +0 -190
  636. package/dist/mind/friends/store.js +0 -4
  637. package/dist/mind/friends/tokens.js +0 -26
  638. package/dist/mind/friends/trust-explanation.js +0 -74
  639. package/dist/mind/friends/types.js +0 -29
  640. package/dist/repertoire/tasks/board.js +0 -134
  641. package/dist/repertoire/tasks/index.js +0 -224
  642. package/dist/repertoire/tasks/lifecycle.js +0 -80
  643. package/dist/repertoire/tasks/middleware.js +0 -65
  644. package/dist/repertoire/tasks/parser.js +0 -173
  645. package/dist/repertoire/tasks/scanner.js +0 -132
  646. package/dist/repertoire/tasks/transitions.js +0 -144
  647. package/dist/senses/bluebubbles-entry.js +0 -13
  648. package/dist/senses/bluebubbles.js +0 -1181
  649. package/dist/senses/debug-activity.js +0 -154
  650. package/dist/senses/inner-dialog-worker.js +0 -90
  651. package/dist/senses/inner-dialog.js +0 -525
  652. package/subagents/README.md +0 -7
  653. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  654. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  655. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  656. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  657. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  658. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  659. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  660. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  661. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  662. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  663. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  664. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  665. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  666. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  667. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  668. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  669. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,183 @@
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.computeSessionStats = computeSessionStats;
37
+ exports.runSessionStats = runSessionStats;
38
+ exports.formatStatsReport = formatStatsReport;
39
+ exports.runSessionStatsCli = runSessionStatsCli;
40
+ const fs = __importStar(require("node:fs"));
41
+ const session_events_1 = require("./session-events");
42
+ const ROLES = ["system", "user", "assistant", "tool"];
43
+ function emptyByRole() {
44
+ const counts = {};
45
+ for (const role of ROLES)
46
+ counts[role] = 0;
47
+ return counts;
48
+ }
49
+ function eventTimeMs(event) {
50
+ const value = event.time.authoredAt ?? event.time.observedAt ?? null;
51
+ if (!value)
52
+ return null;
53
+ const ms = Date.parse(value);
54
+ return Number.isFinite(ms) ? ms : null;
55
+ }
56
+ function computeSessionStats(envelope, sessionPath) {
57
+ const byRole = emptyByRole();
58
+ const projectionCount = (0, session_events_1.projectedSessionEventIds)(envelope).length;
59
+ let toolCallTotal = 0;
60
+ let attachments = 0;
61
+ const toolNameCounts = new Map();
62
+ let earliestMs = null;
63
+ let latestMs = null;
64
+ for (const event of envelope.events) {
65
+ byRole[event.role] = (byRole[event.role] ?? 0) + 1;
66
+ attachments += event.attachments.length;
67
+ for (const call of event.toolCalls) {
68
+ toolCallTotal += 1;
69
+ const name = call.function.name;
70
+ toolNameCounts.set(name, (toolNameCounts.get(name) ?? 0) + 1);
71
+ }
72
+ const ms = eventTimeMs(event);
73
+ if (ms !== null) {
74
+ if (earliestMs === null || ms < earliestMs)
75
+ earliestMs = ms;
76
+ if (latestMs === null || ms > latestMs)
77
+ latestMs = ms;
78
+ }
79
+ }
80
+ const top = [...toolNameCounts.entries()]
81
+ .sort((left, right) => right[1] - left[1])
82
+ .slice(0, 5)
83
+ .map(([name, count]) => ({ name, count }));
84
+ return {
85
+ sessionPath,
86
+ envelopeVersion: envelope.version,
87
+ totalEvents: envelope.events.length,
88
+ byRole,
89
+ toolCalls: {
90
+ total: toolCallTotal,
91
+ distinctNames: toolNameCounts.size,
92
+ topByFrequency: top,
93
+ },
94
+ attachments,
95
+ timeRange: {
96
+ earliest: earliestMs !== null ? new Date(earliestMs).toISOString() : null,
97
+ latest: latestMs !== null ? new Date(latestMs).toISOString() : null,
98
+ durationMs: earliestMs !== null && latestMs !== null ? latestMs - earliestMs : null,
99
+ },
100
+ projection: {
101
+ eventCount: projectionCount,
102
+ omittedFromProjection: Math.max(0, envelope.events.length - projectionCount),
103
+ inputTokens: envelope.projection.inputTokens,
104
+ maxTokens: envelope.projection.maxTokens,
105
+ trimmed: envelope.projection.trimmed,
106
+ },
107
+ lastUsage: envelope.lastUsage,
108
+ };
109
+ }
110
+ function runSessionStats(sessionPath) {
111
+ const text = fs.readFileSync(sessionPath, "utf-8");
112
+ const raw = JSON.parse(text);
113
+ const envelope = (0, session_events_1.parseSessionEnvelope)(raw);
114
+ if (!envelope) {
115
+ return {
116
+ sessionPath,
117
+ envelopeVersion: null,
118
+ totalEvents: 0,
119
+ byRole: emptyByRole(),
120
+ toolCalls: { total: 0, distinctNames: 0, topByFrequency: [] },
121
+ attachments: 0,
122
+ timeRange: { earliest: null, latest: null, durationMs: null },
123
+ projection: { eventCount: 0, omittedFromProjection: 0, inputTokens: null, maxTokens: null, trimmed: false },
124
+ lastUsage: null,
125
+ };
126
+ }
127
+ return computeSessionStats(envelope, sessionPath);
128
+ }
129
+ function formatStatsReport(report) {
130
+ const lines = [];
131
+ lines.push(`Session stats: ${report.sessionPath}`);
132
+ if (report.envelopeVersion === null) {
133
+ lines.push(" envelope: unrecognized (could not parse)");
134
+ return lines.join("\n");
135
+ }
136
+ lines.push(` envelope version: ${report.envelopeVersion}`);
137
+ lines.push(` total events: ${report.totalEvents}`);
138
+ lines.push(` by role: system=${report.byRole.system} user=${report.byRole.user} assistant=${report.byRole.assistant} tool=${report.byRole.tool}`);
139
+ lines.push(` tool calls: ${report.toolCalls.total} (${report.toolCalls.distinctNames} distinct names)`);
140
+ if (report.toolCalls.topByFrequency.length > 0) {
141
+ lines.push(" top tools:");
142
+ for (const { name, count } of report.toolCalls.topByFrequency) {
143
+ lines.push(` ${name}: ${count}`);
144
+ }
145
+ }
146
+ lines.push(` attachments: ${report.attachments}`);
147
+ if (report.timeRange.earliest && report.timeRange.latest) {
148
+ const durationSec = report.timeRange.durationMs !== null ? Math.round(report.timeRange.durationMs / 1000) : null;
149
+ lines.push(` time range: ${report.timeRange.earliest} → ${report.timeRange.latest}${durationSec !== null ? ` (${durationSec}s)` : ""}`);
150
+ }
151
+ lines.push(" projection:");
152
+ lines.push(` in projection: ${report.projection.eventCount}`);
153
+ lines.push(` omitted: ${report.projection.omittedFromProjection}`);
154
+ if (report.projection.inputTokens !== null)
155
+ lines.push(` input tokens: ${report.projection.inputTokens}`);
156
+ if (report.projection.maxTokens !== null)
157
+ lines.push(` max tokens: ${report.projection.maxTokens}`);
158
+ if (report.projection.trimmed)
159
+ lines.push(" trimmed: true");
160
+ if (report.lastUsage) {
161
+ lines.push(` last usage: ${JSON.stringify(report.lastUsage)}`);
162
+ }
163
+ return lines.join("\n");
164
+ }
165
+ function runSessionStatsCli(argv) {
166
+ const positional = argv.filter((token) => !token.startsWith("--"));
167
+ const flags = new Set(argv.filter((token) => token.startsWith("--")));
168
+ if (flags.has("--help") || flags.has("-h") || positional.length === 0) {
169
+ // eslint-disable-next-line no-console -- meta-tooling
170
+ console.log("usage: ouro session-stats <session.json> [--json]");
171
+ return positional.length === 0 ? 2 : 0;
172
+ }
173
+ const report = runSessionStats(positional[0]);
174
+ if (flags.has("--json")) {
175
+ // eslint-disable-next-line no-console -- meta-tooling
176
+ console.log(JSON.stringify(report, null, 2));
177
+ }
178
+ else {
179
+ // eslint-disable-next-line no-console -- meta-tooling
180
+ console.log(formatStatsReport(report));
181
+ }
182
+ return 0;
183
+ }
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.summarizeSessionTail = summarizeSessionTail;
4
+ const runtime_1 = require("../nerves/runtime");
5
+ const session_events_1 = require("./session-events");
6
+ function shouldIncludeToolMessages(friendId, channel) {
7
+ return friendId === "self" && channel === "inner";
8
+ }
9
+ function sortEventsForTranscript(events) {
10
+ return [...events].sort((a, b) => {
11
+ const byTime = Date.parse((0, session_events_1.bestEventTimestamp)(a)) - Date.parse((0, session_events_1.bestEventTimestamp)(b));
12
+ return byTime === 0 ? a.sequence - b.sequence : byTime;
13
+ });
14
+ }
15
+ function parseToolArguments(toolCall) {
16
+ try {
17
+ const parsed = JSON.parse(toolCall.function.arguments);
18
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
19
+ ? parsed
20
+ : null;
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ function extractHumanVisibleToolText(event, context) {
27
+ if (event.role !== "assistant" || event.toolCalls.length === 0)
28
+ return "";
29
+ for (const toolCall of event.toolCalls) {
30
+ const args = parseToolArguments(toolCall);
31
+ if (!args)
32
+ continue;
33
+ if (toolCall.function.name === "settle" && typeof args.answer === "string") {
34
+ return args.answer.trim();
35
+ }
36
+ if (toolCall.function.name === "send_message" && typeof args.content === "string") {
37
+ const targetChannel = typeof args.channel === "string" ? args.channel : "";
38
+ const targetFriendId = typeof args.friendId === "string" ? args.friendId : "";
39
+ const targetKey = typeof args.key === "string" ? args.key : "session";
40
+ if (targetChannel === context.channel && targetFriendId === context.friendId && targetKey === context.key) {
41
+ return args.content.trim();
42
+ }
43
+ }
44
+ }
45
+ return "";
46
+ }
47
+ function normalizeSessionMessages(events, context) {
48
+ return sortEventsForTranscript((0, session_events_1.selectEffectiveSessionEvents)(events))
49
+ .map((event) => ({
50
+ id: event.id,
51
+ role: event.role,
52
+ content: (0, session_events_1.extractEventText)(event) || extractHumanVisibleToolText(event, context),
53
+ timestamp: (0, session_events_1.formatSessionEventTimestamp)(event),
54
+ }))
55
+ .filter((message) => {
56
+ if (message.role === "system")
57
+ return false;
58
+ if (message.role === "tool" && !context.includeToolMessages)
59
+ return false;
60
+ return message.content.length > 0;
61
+ });
62
+ }
63
+ function buildSummaryInstruction(friendId, channel, trustLevel) {
64
+ if (friendId === "self" && channel === "inner") {
65
+ return "summarize this session transcript fully and transparently. this is my own private runtime — include all details, decisions, and reasoning.";
66
+ }
67
+ return `summarize this session transcript. the person asking has trust level: ${trustLevel}. family=full transparency, friend=share work and general topics but protect other people's identities, acquaintance=very guarded minimal disclosure.`;
68
+ }
69
+ function clip(text, limit = 160) {
70
+ const compact = text.replace(/\s+/g, " ").trim();
71
+ return compact.length > limit ? compact.slice(0, limit - 1) + "…" : compact;
72
+ }
73
+ function buildSnapshot(summary, tailMessages) {
74
+ const lines = [`recent focus: ${clip(summary, 240)}`];
75
+ const latestUser = [...tailMessages].reverse().find((message) => message.role === "user").content;
76
+ const latestAssistant = [...tailMessages].reverse().find((message) => message.role === "assistant")?.content;
77
+ lines.push(`latest user: ${clip(latestUser)}`);
78
+ if (latestAssistant) {
79
+ lines.push(`latest assistant: ${clip(latestAssistant)}`);
80
+ }
81
+ return lines.join("\n");
82
+ }
83
+ function selectSessionTailMessages(messages, messageCount) {
84
+ const requestedCount = Number.isFinite(messageCount) && messageCount > 0 ? Math.floor(messageCount) : 20;
85
+ const tail = messages.slice(-requestedCount);
86
+ const selectedIds = new Set(tail.map((message) => message.id));
87
+ const latestUser = [...messages].reverse().find((message) => message.role === "user");
88
+ const latestAssistant = [...messages].reverse().find((message) => message.role === "assistant");
89
+ selectedIds.add(latestUser.id);
90
+ if (latestAssistant)
91
+ selectedIds.add(latestAssistant.id);
92
+ return messages.filter((message) => selectedIds.has(message.id));
93
+ }
94
+ async function summarizeSessionTail(options) {
95
+ (0, runtime_1.emitNervesEvent)({
96
+ component: "daemon",
97
+ event: "daemon.session_tail_summary",
98
+ message: "summarizing session transcript tail",
99
+ meta: {
100
+ friendId: options.friendId,
101
+ channel: options.channel,
102
+ key: options.key,
103
+ messageCount: options.messageCount,
104
+ },
105
+ });
106
+ const envelope = (0, session_events_1.loadSessionEnvelopeFile)(options.sessionPath);
107
+ if (!envelope)
108
+ return { kind: "missing" };
109
+ const transcriptContext = {
110
+ friendId: options.friendId,
111
+ channel: options.channel,
112
+ key: options.key,
113
+ includeToolMessages: shouldIncludeToolMessages(options.friendId, options.channel),
114
+ };
115
+ const visibleMessages = normalizeSessionMessages(envelope.events, transcriptContext);
116
+ if (!visibleMessages.some((message) => message.role === "user")) {
117
+ return { kind: "empty", reason: "envelope_trimmed" };
118
+ }
119
+ const tailMessages = selectSessionTailMessages(visibleMessages, options.messageCount);
120
+ const transcript = tailMessages
121
+ .map((message) => `[${message.timestamp} | ${message.role} | ${message.id}] ${message.content}`)
122
+ .join("\n");
123
+ const summary = options.summarize
124
+ ? await options.summarize(transcript, buildSummaryInstruction(options.friendId, options.channel, options.trustLevel ?? "family"))
125
+ : transcript;
126
+ return {
127
+ kind: "ok",
128
+ transcript,
129
+ summary,
130
+ snapshot: buildSnapshot(summary, tailMessages),
131
+ tailMessages,
132
+ };
133
+ }
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXEMPT_WORDS = exports.HOUSE_VOCABULARY = exports.LABEL_WORDS = exports.COMMON_STARTERS = void 0;
4
+ exports.isLookupToolCall = isLookupToolCall;
5
+ exports.mentions = mentions;
6
+ exports.candidateNames = candidateNames;
7
+ exports.lowercaseListNames = lowercaseListNames;
8
+ exports.sourceGroundingFinding = sourceGroundingFinding;
9
+ exports.sourceGroundingError = sourceGroundingError;
10
+ exports.withUnverifiedDisclosure = withUnverifiedDisclosure;
11
+ /**
12
+ * Primary-source grounding for claims about external works (books, shows, films, their characters).
13
+ *
14
+ * A model asked about a work it half-remembers will invent plausible names and present them as fact; a principle in
15
+ * the prompt did not stop that. This check runs where an answer is about to be delivered and judges the answer against
16
+ * what the turn actually looked up: a name that appears in no lookup result, and is not house vocabulary or the
17
+ * person's own words, is a name the model made up. Only a lookup (a web search or page fetch, a catalog lookup, a
18
+ * curl, the books tool) can clear a name that is claimed to come from a work. Memory, notes, the diary and ordinary
19
+ * shell output cannot, because they may hold an earlier fabrication. Pure functions; the runtime calls them at settle
20
+ * for agents that opt in (see ToolContext.answerGates).
21
+ */
22
+ const runtime_1 = require("../nerves/runtime");
23
+ const LOOKUP_TOOL_NAMES = new Set(["web_search", "media_search", "media_episodes"]);
24
+ const LOOKUP_TOOL_PATTERN = /^(web_fetch|fetch_url|fetch_page|read_url|read_page|browse\w*)$/;
25
+ /** A lookup is a command whose command word is curl or wget, or the books tool; echoing a URL, a here-string or a grep over text is not one. */
26
+ const SHELL_LOOKUP_SEGMENT = /^\s*(?:\w+=\S*\s+)*(?:(?:sudo|env|command|time|nohup)\s+)*(?:(?:curl|wget)\b|books\s+(?:get|search|series|library\s+(?:find|search))\b)/;
27
+ const SHELL_SEGMENT_SEPARATOR = /&&|\|\||[;|\n]/;
28
+ const STRONG_CUE = /\b(books?|novels?|movies?|films?|anime|saga|trilogy|albums?|episodes?|protagonists?)\b/i;
29
+ const WORK_CUE = /\b(books?|novels?|series|saga|trilogy|shows?|movies?|films?|anime|characters?|protagonists?|authors?|episodes?|seasons?|albums?|bands?|lore|cast)\b/i;
30
+ const COPULA_AFTER_NAME = /^(?:['’]s\b|\s+(?:is|was|are|were|isn['’]t|wasn['’]t|has|had|does|did)\b)/i;
31
+ /** Words that start a sentence or a bullet without being a name. */
32
+ exports.COMMON_STARTERS = new Set([
33
+ "the", "this", "that", "these", "those", "it", "its", "i", "so", "and", "but", "or", "yes", "no", "not", "sure", "okay", "ok", "here", "there",
34
+ "what", "when", "where", "why", "how", "who", "which", "if", "then", "now", "also", "both", "one", "two", "my", "your", "our", "we", "you", "he", "she", "they",
35
+ "got", "thanks", "thank", "done", "understood", "noted", "good", "great", "fine", "sorry", "will", "can", "could", "would", "should", "let", "yeah", "yep", "nope",
36
+ "right", "well", "anyway", "still", "just", "all", "any", "some", "each", "every", "for", "from", "with", "without", "to", "in", "on", "at", "by", "as", "is",
37
+ "are", "was", "were", "do", "does", "did", "have", "has", "had", "maybe", "probably", "honestly", "unfortunately", "looks", "seems", "see", "check", "try",
38
+ "use", "make", "keep", "stop", "start", "once", "first", "next", "last", "before", "after", "because", "since", "while", "though", "although", "however",
39
+ "otherwise", "instead", "meanwhile", "today", "tonight", "tomorrow", "yesterday", "more", "most", "many", "other", "another", "such", "only", "even",
40
+ "about", "over", "under", "between", "among", "like", "per", "plus", "both", "either", "neither", "whether", "yet", "nothing", "something", "everything",
41
+ "anything", "everyone", "someone", "anyone", "nobody", "overall", "basically", "actually", "generally", "usually", "often", "sometimes", "never", "always",
42
+ "note", "tip", "warning", "heads", "update", "summary", "answer", "plan", "status", "result", "results", "source", "sources", "todo",
43
+ ]);
44
+ /** A sentence-opening "Word:" is a label when the word is one of these; any other "Name:" is treated as a name. */
45
+ exports.LABEL_WORDS = new Set([
46
+ "note", "notes", "tip", "warning", "update", "summary", "answer", "plan", "status", "result", "results", "source", "sources", "todo", "next", "why", "how", "what",
47
+ "done", "reply", "title", "healthy", "snoozed", "down", "up", "broken", "failed", "pending", "running", "stopped", "paused", "queued", "cast", "characters", "authors", "books", "series", "shows", "movies", "episodes", "tldr", "caveat", "caveats", "options", "option",
48
+ ]);
49
+ /** Words that read as names but are not about a work: the house, the tools it uses, months, weekdays, common brands and services. */
50
+ exports.HOUSE_VOCABULARY = new Set([
51
+ "ari", "butler", "claude", "code", "sanctuary", "jellyfin", "sonarr", "radarr", "prowlarr", "jellyseerr", "calibre", "books", "telegram", "unraid", "docker",
52
+ "mendelow", "cloud", "pocketbook", "astraweb", "usenet", "sabnzbd", "bazarr", "tmdb", "tvdb", "libgen", "plex", "github", "google", "apple", "amazon", "netflix",
53
+ "hulu", "disney", "youtube", "spotify", "kindle", "kobo", "goodreads", "audible", "python", "javascript", "typescript", "node", "lodash", "vitest", "react",
54
+ "linux", "windows", "macos", "android", "chrome", "firefox", "safari", "slack", "discord", "wikipedia", "english", "ouro", "ouroboros", "a2a", "radarr", "http", "https",
55
+ "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december",
56
+ "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday",
57
+ ]);
58
+ /** Status verbs and media nouns that open or fill ordinary replies about media work ("Added the show Silo. Season 1 is grabbing now."): never names, wherever they sit. */
59
+ exports.EXEMPT_WORDS = new Set([
60
+ "added", "adding", "found", "finding", "sent", "sending", "searching", "searched", "grabbing", "grabbed", "grab", "season", "seasons", "episode", "episodes", "queued", "queueing",
61
+ "monitoring", "monitored", "imported", "importing", "downloading", "downloaded", "download", "downloads", "requested", "requesting", "removed", "removing", "deleted", "updated", "updating",
62
+ "checking", "checked", "looking", "looked", "started", "starting", "finished", "finishing", "waiting", "stalled", "retrying", "retried", "marked", "set", "setting", "assigned", "assigning",
63
+ "movie", "movies", "show", "shows", "book", "books", "series", "film", "films", "less", "tell", "ready", "missing", "available", "unavailable", "specials", "special",
64
+ ]);
65
+ /** Contractions are never names: I'll, I'm, They're. */
66
+ const CONTRACTION = /^\p{L}+['’](?:ll|m|re|ve|d|t)$/iu;
67
+ const MIN_NAME_LENGTH = 3;
68
+ const MAX_ACRONYM_LENGTH = 5;
69
+ const LOWERCASE_LIST_INTRO = /\b(?:characters?|cast|names?|authors?|protagonists?|bands?|members?)\b[ \t]*(?::|—|-|are|includes?|including|like|such as)[ \t]+([^.!?\n]+)/gi;
70
+ const LOWERCASE_LIST_ITEM = /^[a-z][a-z'’-]{3,}$/;
71
+ const LOWERCASE_LIST_STOP = new Set(["others", "etc", "more", "many", "several", "various", "everyone", "anyone", "someone", "people", "these", "those", "them", "others", "similar", "same", "like"]);
72
+ /** True when the call read a primary source: a web search or page fetch, a catalog lookup, a curl, or the books tool. */
73
+ function isLookupToolCall(record) {
74
+ if (LOOKUP_TOOL_NAMES.has(record.name) || LOOKUP_TOOL_PATTERN.test(record.name))
75
+ return true;
76
+ return record.name === "shell" && (record.args.command ?? "").split(SHELL_SEGMENT_SEPARATOR).some((segment) => SHELL_LOOKUP_SEGMENT.test(segment));
77
+ }
78
+ const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
79
+ /** Whole-word, case-insensitive, Unicode-aware: "Dross" is not found inside "Drossel" or "Gross". */
80
+ function mentions(haystack, name) {
81
+ return new RegExp(`(?<![\\p{L}\\p{N}])${escapeRegExp(name)}(?![\\p{L}\\p{N}])`, "iu").test(haystack);
82
+ }
83
+ const TOKEN = /\p{Lu}[\p{L}\p{M}'’]*/gu;
84
+ /** Capitalised words that read as names, in order of first appearance, case-insensitively de-duplicated. House vocabulary is not a name. */
85
+ function candidateNames(text) {
86
+ const seen = new Set();
87
+ const names = [];
88
+ for (const match of text.matchAll(TOKEN)) {
89
+ const word = match[0].replace(/['’]s$/i, "").replace(/['’]$/, "");
90
+ if (word.length < MIN_NAME_LENGTH)
91
+ continue;
92
+ if (word.length <= MAX_ACRONYM_LENGTH && word === word.toUpperCase())
93
+ continue;
94
+ const lower = word.toLowerCase();
95
+ if (lower === "the" || CONTRACTION.test(word) || exports.HOUSE_VOCABULARY.has(lower) || exports.EXEMPT_WORDS.has(lower) || seen.has(lower))
96
+ continue;
97
+ const before = text.slice(0, match.index).replace(/[ \t"'“‘(\[*_#>-]+$/u, "");
98
+ const startsSentence = before === "" || /[.!?:\n]$/.test(before);
99
+ const after = text.slice(match.index + match[0].length);
100
+ if (startsSentence && exports.COMMON_STARTERS.has(lower))
101
+ continue;
102
+ if (startsSentence && exports.LABEL_WORDS.has(lower) && after.startsWith(":"))
103
+ continue;
104
+ if (startsSentence && !startsLikeName(text, match.index, after, lower))
105
+ continue;
106
+ seen.add(lower);
107
+ names.push(word);
108
+ }
109
+ return names;
110
+ }
111
+ /**
112
+ * An ordinary sentence opens with a capital whether or not the word is a name ("Silo is in Sonarr", "Remember to..."). A sentence-opening word
113
+ * therefore counts as a name only with a sign it is one: it is capitalised elsewhere mid-sentence, it sits in a quote or emphasis or opens a bullet,
114
+ * it is followed by a colon, a copula, or a list continuation ("Lindon and Yerin").
115
+ */
116
+ function startsLikeName(text, index, after, lower) {
117
+ const rawBefore = index > 0 ? text[index - 1] : "";
118
+ if (/["“‘'*_]/.test(rawBefore))
119
+ return true;
120
+ const line = text.slice(text.lastIndexOf("\n", index - 1) + 1, index);
121
+ if (/^\s*(?:[-*•>]|\d+[.)])\s+$/.test(line))
122
+ return true;
123
+ if (after.startsWith(":") || COPULA_AFTER_NAME.test(after) || /^(?:,|\s+and|\s*&)\s*\p{Lu}/u.test(after))
124
+ return true;
125
+ return midSentenceCapitalised(text, lower);
126
+ }
127
+ function midSentenceCapitalised(text, lower) {
128
+ for (const match of text.matchAll(TOKEN)) {
129
+ const word = match[0].replace(/['’]s$/i, "").replace(/['’]$/, "");
130
+ if (word.toLowerCase() !== lower)
131
+ continue;
132
+ const before = text.slice(0, match.index).replace(/[ \t"'“‘(\[*_#>-]+$/u, "");
133
+ if (!(before === "" || /[.!?:\n]$/.test(before)))
134
+ return true;
135
+ }
136
+ return false;
137
+ }
138
+ /** Lowercase items in a list a work cue introduces ("characters: lindon, yerin and eithan"): two or more are treated as names. */
139
+ function lowercaseListNames(text) {
140
+ const names = [];
141
+ for (const intro of text.matchAll(LOWERCASE_LIST_INTRO)) {
142
+ const items = intro[1].split(/,|;|\band\b|\bor\b/i).map((item) => item.trim().split(/\s+/).slice(0, 2).join(" ")).map((item) => (/\s/.test(item) ? item.split(" ")[0] : item));
143
+ const words = items.filter((item) => LOWERCASE_LIST_ITEM.test(item) && !exports.COMMON_STARTERS.has(item) && !LOWERCASE_LIST_STOP.has(item) && !exports.HOUSE_VOCABULARY.has(item));
144
+ if (words.length >= 2)
145
+ names.push(...words);
146
+ }
147
+ return [...new Set(names)];
148
+ }
149
+ function claimsSomethingAbout(answer, name) {
150
+ const lower = answer.toLowerCase();
151
+ const needle = name.toLowerCase();
152
+ for (let at = lower.indexOf(needle); at !== -1; at = lower.indexOf(needle, at + needle.length)) {
153
+ if (COPULA_AFTER_NAME.test(answer.slice(at + needle.length)))
154
+ return true;
155
+ }
156
+ return false;
157
+ }
158
+ /**
159
+ * What is wrong with a reply about an external work, or null: it names things no lookup this turn contains (invented),
160
+ * or states something about a work the person only named, with no lookup at all (unsourced_claim).
161
+ */
162
+ function sourceGroundingFinding(input) {
163
+ if (!WORK_CUE.test(input.answer))
164
+ return null;
165
+ const lookups = input.tools.filter(isLookupToolCall);
166
+ const lookedUp = lookups.map((record) => record.result).join("\n");
167
+ const names = [...candidateNames(input.answer), ...lowercaseListNames(input.answer)];
168
+ const invented = names.filter((name) => !mentions(lookedUp, name) && !mentions(input.userText, name));
169
+ if (invented.length > 0 && (invented.length >= 2 || STRONG_CUE.test(input.answer))) {
170
+ const named = invented.join(", ");
171
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.unsourced_work_claim", message: "a reply named things from a work that the turn did not look up", meta: { names: invented.length, lookups: lookups.length } });
172
+ return {
173
+ kind: "invented", names: invented, lookups: lookups.length,
174
+ message: lookups.length === 0
175
+ ? `you named ${named} as part of a book, show, film or its cast, and you looked up nothing this turn. don't state facts about a work from memory. read a primary source first (web_search, or fetch the page), then answer only from what it says. if you can't find it, say so plainly.`
176
+ : `${named} do not appear in anything you looked up this turn, so they may be made up. check them against the source you read, drop the ones it does not support, or look them up, then settle again.`,
177
+ };
178
+ }
179
+ const unsourced = names.filter((name) => mentions(input.userText, name) && !mentions(lookedUp, name) && claimsSomethingAbout(input.answer, name));
180
+ if (lookups.length === 0 && unsourced.length > 0) {
181
+ return {
182
+ kind: "unsourced_claim", names: unsourced, lookups: 0,
183
+ message: `you stated something about ${unsourced.join(", ")} and looked up nothing this turn. read a primary source first (web_search, or fetch the page), then answer only from what it says. if you can't find it, say so plainly.`,
184
+ };
185
+ }
186
+ return null;
187
+ }
188
+ function sourceGroundingError(input) {
189
+ return sourceGroundingFinding(input)?.message ?? null;
190
+ }
191
+ /** When the model keeps naming unsourced things after the retries are spent, say so rather than deliver them as fact. */
192
+ function withUnverifiedDisclosure(answer, names) {
193
+ return `I couldn't verify ${names.join(", ")} against a source, so treat ${names.length === 1 ? "that" : "those"} as unconfirmed.\n\n${answer}`;
194
+ }