@ouro.bot/cli 0.1.0-alpha.66 → 0.1.0-alpha.661

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 (449) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +4216 -13
  13. package/dist/a2a/card.js +56 -0
  14. package/dist/a2a/client.js +143 -0
  15. package/dist/a2a/config.js +50 -0
  16. package/dist/a2a/onboarding.js +111 -0
  17. package/dist/a2a/server.js +498 -0
  18. package/dist/a2a/task-store.js +69 -0
  19. package/dist/a2a/types.js +3 -0
  20. package/dist/arc/attention-types.js +8 -0
  21. package/dist/arc/cares.js +144 -0
  22. package/dist/arc/episodes.js +118 -0
  23. package/dist/arc/evolution.js +487 -0
  24. package/dist/arc/flight-recorder.js +369 -0
  25. package/dist/arc/intentions.js +134 -0
  26. package/dist/arc/json-store.js +117 -0
  27. package/dist/arc/obligations.js +292 -0
  28. package/dist/arc/packets.js +288 -0
  29. package/dist/arc/presence.js +185 -0
  30. package/dist/arc/task-lifecycle.js +57 -0
  31. package/dist/commerce/store.js +755 -0
  32. package/dist/commerce/types.js +3 -0
  33. package/dist/heart/active-work.js +860 -43
  34. package/dist/heart/agent-entry.js +69 -3
  35. package/dist/heart/attachments/image-normalize.js +194 -0
  36. package/dist/heart/attachments/materialize.js +97 -0
  37. package/dist/heart/attachments/originals.js +88 -0
  38. package/dist/heart/attachments/render.js +29 -0
  39. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  40. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  41. package/dist/heart/attachments/sources/index.js +16 -0
  42. package/dist/heart/attachments/store.js +103 -0
  43. package/dist/heart/attachments/types.js +93 -0
  44. package/dist/heart/auth/auth-flow.js +479 -0
  45. package/dist/heart/awaiting/await-alert.js +146 -0
  46. package/dist/heart/awaiting/await-expiry.js +108 -0
  47. package/dist/heart/awaiting/await-loader.js +91 -0
  48. package/dist/heart/awaiting/await-parser.js +141 -0
  49. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  50. package/dist/heart/awaiting/await-scheduler.js +377 -0
  51. package/dist/heart/background-operations.js +281 -0
  52. package/dist/heart/bridges/manager.js +137 -17
  53. package/dist/heart/bridges/store.js +14 -2
  54. package/dist/heart/bundle-state.js +168 -0
  55. package/dist/heart/commitments.js +135 -0
  56. package/dist/heart/config-registry.js +331 -0
  57. package/dist/heart/config.js +118 -119
  58. package/dist/heart/context-loss-gauntlet.js +354 -0
  59. package/dist/heart/core.js +1123 -247
  60. package/dist/heart/cross-chat-delivery.js +3 -18
  61. package/dist/heart/daemon/agent-config-check.js +419 -0
  62. package/dist/heart/daemon/agent-discovery.js +102 -3
  63. package/dist/heart/daemon/agent-service.js +523 -0
  64. package/dist/heart/daemon/agentic-repair.js +547 -0
  65. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  66. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  67. package/dist/heart/daemon/cadence.js +70 -0
  68. package/dist/heart/daemon/cli-defaults.js +780 -0
  69. package/dist/heart/daemon/cli-desk.js +322 -0
  70. package/dist/heart/daemon/cli-exec.js +7767 -0
  71. package/dist/heart/daemon/cli-help.js +558 -0
  72. package/dist/heart/daemon/cli-parse.js +1688 -0
  73. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  74. package/dist/heart/daemon/cli-render.js +763 -0
  75. package/dist/heart/daemon/cli-types.js +8 -0
  76. package/dist/heart/daemon/connect-bay.js +323 -0
  77. package/dist/heart/daemon/daemon-cli.js +29 -1750
  78. package/dist/heart/daemon/daemon-entry.js +485 -2
  79. package/dist/heart/daemon/daemon-health.js +176 -0
  80. package/dist/heart/daemon/daemon-rollup.js +57 -0
  81. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  82. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  83. package/dist/heart/daemon/daemon.js +937 -74
  84. package/dist/heart/daemon/dns-workflow.js +394 -0
  85. package/dist/heart/daemon/doctor-types.js +8 -0
  86. package/dist/heart/daemon/doctor.js +873 -0
  87. package/dist/heart/daemon/health-monitor.js +122 -1
  88. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  89. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  90. package/dist/heart/daemon/http-health-probe.js +80 -0
  91. package/dist/heart/daemon/human-command-screens.js +234 -0
  92. package/dist/heart/daemon/human-readiness.js +114 -0
  93. package/dist/heart/daemon/inner-status.js +78 -0
  94. package/dist/heart/daemon/interactive-repair.js +394 -0
  95. package/dist/heart/daemon/launchd.js +37 -8
  96. package/dist/heart/daemon/log-tailer.js +79 -10
  97. package/dist/heart/daemon/logs-prune.js +110 -0
  98. package/dist/heart/daemon/mcp-canary.js +297 -0
  99. package/dist/heart/daemon/message-router.js +6 -2
  100. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  101. package/dist/heart/daemon/os-cron-deps.js +135 -0
  102. package/dist/heart/daemon/os-cron.js +14 -12
  103. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  104. package/dist/heart/daemon/ouro-entry.js +3 -1
  105. package/dist/heart/daemon/plugin-cli.js +432 -0
  106. package/dist/heart/daemon/process-manager.js +511 -40
  107. package/dist/heart/daemon/provider-discovery.js +137 -0
  108. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  109. package/dist/heart/daemon/pulse.js +475 -0
  110. package/dist/heart/daemon/readiness-repair.js +365 -0
  111. package/dist/heart/daemon/run-hooks.js +2 -0
  112. package/dist/heart/daemon/runtime-logging.js +35 -14
  113. package/dist/heart/daemon/runtime-metadata.js +2 -30
  114. package/dist/heart/daemon/safe-mode.js +161 -0
  115. package/dist/heart/daemon/sense-manager.js +564 -38
  116. package/dist/heart/daemon/session-id-resolver.js +131 -0
  117. package/dist/heart/daemon/skill-management-installer.js +1 -1
  118. package/dist/heart/daemon/socket-client.js +158 -11
  119. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  120. package/dist/heart/daemon/startup-tui.js +330 -0
  121. package/dist/heart/daemon/task-scheduler.js +117 -39
  122. package/dist/heart/daemon/terminal-ui.js +499 -0
  123. package/dist/heart/daemon/thoughts.js +229 -17
  124. package/dist/heart/daemon/up-progress.js +366 -0
  125. package/dist/heart/daemon/vault-items.js +56 -0
  126. package/dist/heart/delegation.js +1 -4
  127. package/dist/heart/habits/habit-migration.js +189 -0
  128. package/dist/heart/habits/habit-parser.js +203 -0
  129. package/dist/heart/habits/habit-runtime-state.js +100 -0
  130. package/dist/heart/habits/habit-scheduler.js +372 -0
  131. package/dist/heart/{daemon → hatch}/hatch-flow.js +40 -56
  132. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  133. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  134. package/dist/heart/{daemon → hatch}/specialist-tools.js +45 -18
  135. package/dist/heart/identity.js +174 -57
  136. package/dist/heart/kept-notes.js +289 -0
  137. package/dist/heart/kicks.js +1 -1
  138. package/dist/heart/machine-identity.js +161 -0
  139. package/dist/heart/mail-import-discovery.js +353 -0
  140. package/dist/heart/mailbox/mailbox-http-hooks.js +67 -0
  141. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  142. package/dist/heart/mailbox/mailbox-http-routes.js +250 -0
  143. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  144. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  145. package/dist/heart/mailbox/mailbox-http.js +99 -0
  146. package/dist/heart/mailbox/mailbox-read.js +32 -0
  147. package/dist/heart/mailbox/mailbox-types.js +27 -0
  148. package/dist/heart/mailbox/mailbox-view.js +197 -0
  149. package/dist/heart/mailbox/readers/agent-machine.js +418 -0
  150. package/dist/heart/mailbox/readers/continuity-readers.js +324 -0
  151. package/dist/heart/mailbox/readers/mail.js +375 -0
  152. package/dist/heart/mailbox/readers/runtime-readers.js +728 -0
  153. package/dist/heart/mailbox/readers/sessions.js +232 -0
  154. package/dist/heart/mailbox/readers/shared.js +111 -0
  155. package/dist/heart/mcp/mcp-server.js +696 -0
  156. package/dist/heart/migrate-config.js +100 -0
  157. package/dist/heart/model-capabilities.js +19 -0
  158. package/dist/heart/orientation-frame.js +217 -0
  159. package/dist/heart/platform.js +81 -0
  160. package/dist/heart/provider-attempt.js +134 -0
  161. package/dist/heart/provider-binding-resolver.js +272 -0
  162. package/dist/heart/provider-credentials.js +425 -0
  163. package/dist/heart/provider-failover.js +311 -0
  164. package/dist/heart/provider-models.js +81 -0
  165. package/dist/heart/provider-ping.js +262 -0
  166. package/dist/heart/provider-readiness-cache.js +40 -0
  167. package/dist/heart/provider-visibility.js +188 -0
  168. package/dist/heart/providers/anthropic-token.js +131 -0
  169. package/dist/heart/providers/anthropic.js +139 -52
  170. package/dist/heart/providers/azure.js +23 -11
  171. package/dist/heart/providers/error-classification.js +127 -0
  172. package/dist/heart/providers/github-copilot.js +145 -0
  173. package/dist/heart/providers/minimax-vlm.js +189 -0
  174. package/dist/heart/providers/minimax.js +26 -8
  175. package/dist/heart/providers/openai-codex-token.js +349 -0
  176. package/dist/heart/providers/openai-codex.js +55 -40
  177. package/dist/heart/runtime-capability-check.js +170 -0
  178. package/dist/heart/runtime-credentials.js +367 -0
  179. package/dist/heart/runtime-cwd.js +87 -0
  180. package/dist/heart/sense-truth.js +17 -4
  181. package/dist/heart/session-activity.js +48 -24
  182. package/dist/heart/session-events.js +1133 -0
  183. package/dist/heart/session-playback-cli-main.js +5 -0
  184. package/dist/heart/session-playback-cli.js +36 -0
  185. package/dist/heart/session-playback.js +231 -0
  186. package/dist/heart/session-stats-cli-main.js +5 -0
  187. package/dist/heart/session-stats.js +182 -0
  188. package/dist/heart/session-transcript.js +133 -0
  189. package/dist/heart/start-of-turn-packet.js +351 -0
  190. package/dist/heart/streaming.js +44 -27
  191. package/dist/heart/structured-output.js +196 -0
  192. package/dist/heart/sync-classification.js +176 -0
  193. package/dist/heart/sync.js +449 -0
  194. package/dist/heart/target-resolution.js +9 -5
  195. package/dist/heart/tempo.js +93 -0
  196. package/dist/heart/temporal-view.js +41 -0
  197. package/dist/heart/timeouts.js +101 -0
  198. package/dist/heart/tool-activity-callbacks.js +59 -0
  199. package/dist/heart/tool-description.js +155 -0
  200. package/dist/heart/tool-friction.js +55 -0
  201. package/dist/heart/tool-loop.js +200 -0
  202. package/dist/heart/turn-context.js +430 -0
  203. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  204. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  205. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  206. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  207. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  208. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  209. package/dist/heart/versioning/update-hooks.js +154 -0
  210. package/dist/heart/work-card.js +386 -0
  211. package/dist/mailbox-ui/assets/index-B-V9vRQ0.js +61 -0
  212. package/dist/mailbox-ui/assets/index-BOZbGbkL.css +1 -0
  213. package/dist/mailbox-ui/index.html +15 -0
  214. package/dist/mailroom/attention.js +167 -0
  215. package/dist/mailroom/autonomy.js +209 -0
  216. package/dist/mailroom/blob-store.js +715 -0
  217. package/dist/mailroom/body-cache.js +61 -0
  218. package/dist/mailroom/core.js +788 -0
  219. package/dist/mailroom/entry.js +160 -0
  220. package/dist/mailroom/file-store.js +568 -0
  221. package/dist/mailroom/mbox-import.js +393 -0
  222. package/dist/mailroom/migration.js +164 -0
  223. package/dist/mailroom/outbound.js +380 -0
  224. package/dist/mailroom/policy.js +263 -0
  225. package/dist/mailroom/reader.js +233 -0
  226. package/dist/mailroom/search-cache.js +334 -0
  227. package/dist/mailroom/search-relevance.js +319 -0
  228. package/dist/mailroom/smtp-ingress.js +176 -0
  229. package/dist/mailroom/source-state.js +176 -0
  230. package/dist/mailroom/thread.js +109 -0
  231. package/dist/mailroom/travel-extract.js +89 -0
  232. package/dist/mind/bundle-manifest.js +21 -2
  233. package/dist/mind/context.js +250 -101
  234. package/dist/mind/desk-section.js +362 -0
  235. package/dist/mind/diary-integrity.js +60 -0
  236. package/dist/mind/{memory.js → diary.js} +68 -77
  237. package/dist/mind/embedding-provider.js +60 -0
  238. package/dist/mind/file-state.js +179 -0
  239. package/dist/mind/friends/channel.js +48 -0
  240. package/dist/mind/friends/resolver.js +107 -4
  241. package/dist/mind/friends/store-file.js +61 -4
  242. package/dist/mind/friends/types.js +2 -2
  243. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  244. package/dist/mind/obligation-steering.js +221 -0
  245. package/dist/mind/pending.js +6 -1
  246. package/dist/mind/prompt-refresh.js +3 -2
  247. package/dist/mind/prompt.js +1015 -140
  248. package/dist/mind/provenance-trust.js +26 -0
  249. package/dist/mind/record-paths.js +312 -0
  250. package/dist/mind/scrutiny.js +173 -0
  251. package/dist/nerves/cli-logging.js +7 -1
  252. package/dist/nerves/coverage/audit-rules.js +15 -6
  253. package/dist/nerves/coverage/audit.js +28 -2
  254. package/dist/nerves/coverage/cli.js +1 -1
  255. package/dist/nerves/coverage/contract.js +5 -5
  256. package/dist/nerves/coverage/file-completeness.js +139 -5
  257. package/dist/nerves/event-buffer.js +111 -0
  258. package/dist/nerves/index.js +224 -4
  259. package/dist/nerves/observation.js +20 -0
  260. package/dist/nerves/redact.js +79 -0
  261. package/dist/nerves/review/cli-main.js +5 -0
  262. package/dist/nerves/review/cli.js +156 -0
  263. package/dist/nerves/review/core.js +152 -0
  264. package/dist/nerves/runtime.js +5 -1
  265. package/dist/repertoire/ado-client.js +15 -56
  266. package/dist/repertoire/ado-semantic.js +16 -10
  267. package/dist/repertoire/api-client.js +97 -0
  268. package/dist/repertoire/bitwarden-store.js +1041 -0
  269. package/dist/repertoire/bundle-templates.js +71 -0
  270. package/dist/repertoire/bw-installer.js +180 -0
  271. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  272. package/dist/repertoire/coding/context-pack.js +331 -0
  273. package/dist/repertoire/coding/feedback.js +197 -30
  274. package/dist/repertoire/coding/manager.js +166 -10
  275. package/dist/repertoire/coding/spawner.js +55 -9
  276. package/dist/repertoire/coding/tools.js +219 -7
  277. package/dist/repertoire/commerce-errors.js +109 -0
  278. package/dist/repertoire/commerce-self-test.js +156 -0
  279. package/dist/repertoire/credential-access.js +178 -0
  280. package/dist/repertoire/desk/classifier.js +362 -0
  281. package/dist/repertoire/duffel-client.js +185 -0
  282. package/dist/repertoire/github-client.js +14 -55
  283. package/dist/repertoire/graph-client.js +11 -52
  284. package/dist/repertoire/guardrails.js +159 -25
  285. package/dist/repertoire/mcp-client.js +295 -0
  286. package/dist/repertoire/mcp-manager.js +434 -0
  287. package/dist/repertoire/mcp-tools.js +83 -0
  288. package/dist/repertoire/plugin-mcp.js +175 -0
  289. package/dist/repertoire/plugins.js +253 -0
  290. package/dist/repertoire/shell-sessions.js +133 -0
  291. package/dist/repertoire/skills.js +48 -4
  292. package/dist/repertoire/stripe-client.js +131 -0
  293. package/dist/repertoire/tool-results.js +29 -0
  294. package/dist/repertoire/tools-a2a.js +283 -0
  295. package/dist/repertoire/tools-attachments.js +317 -0
  296. package/dist/repertoire/tools-awaiting.js +372 -0
  297. package/dist/repertoire/tools-base.js +63 -1082
  298. package/dist/repertoire/tools-bluebubbles.js +2 -0
  299. package/dist/repertoire/tools-bridge.js +144 -0
  300. package/dist/repertoire/tools-bundle.js +993 -0
  301. package/dist/repertoire/tools-commerce.js +253 -0
  302. package/dist/repertoire/tools-config.js +186 -0
  303. package/dist/repertoire/tools-continuity.js +252 -0
  304. package/dist/repertoire/tools-credential.js +383 -0
  305. package/dist/repertoire/tools-evolution.js +527 -0
  306. package/dist/repertoire/tools-files.js +344 -0
  307. package/dist/repertoire/tools-flight.js +290 -0
  308. package/dist/repertoire/tools-flow.js +119 -0
  309. package/dist/repertoire/tools-github.js +3 -8
  310. package/dist/repertoire/tools-mail.js +1975 -0
  311. package/dist/repertoire/tools-notes.js +418 -0
  312. package/dist/repertoire/tools-obligations.js +143 -0
  313. package/dist/repertoire/tools-orientation.js +31 -0
  314. package/dist/repertoire/tools-record.js +469 -0
  315. package/dist/repertoire/tools-runtime.js +150 -0
  316. package/dist/repertoire/tools-session.js +766 -0
  317. package/dist/repertoire/tools-shell.js +120 -0
  318. package/dist/repertoire/tools-stripe.js +224 -0
  319. package/dist/repertoire/tools-surface.js +344 -0
  320. package/dist/repertoire/tools-teams.js +12 -39
  321. package/dist/repertoire/tools-travel.js +125 -0
  322. package/dist/repertoire/tools-trip.js +982 -0
  323. package/dist/repertoire/tools-user-profile.js +146 -0
  324. package/dist/repertoire/tools-vault.js +40 -0
  325. package/dist/repertoire/tools-voice.js +145 -0
  326. package/dist/repertoire/tools.js +243 -79
  327. package/dist/repertoire/travel-api-client.js +360 -0
  328. package/dist/repertoire/user-profile.js +131 -0
  329. package/dist/repertoire/vault-setup.js +246 -0
  330. package/dist/repertoire/vault-unlock.js +594 -0
  331. package/dist/scripts/claude-code-hook.js +41 -0
  332. package/dist/scripts/claude-code-stop-hook.js +47 -0
  333. package/dist/senses/a2a-entry.js +78 -0
  334. package/dist/senses/attention-queue.js +186 -0
  335. package/dist/senses/await-turn-message.js +58 -0
  336. package/dist/senses/bluebubbles/active-turns.js +216 -0
  337. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  338. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  339. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  340. package/dist/senses/bluebubbles/entry.js +77 -0
  341. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  342. package/dist/senses/bluebubbles/index.js +2737 -0
  343. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  344. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  345. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  346. package/dist/senses/bluebubbles/processed-log.js +133 -0
  347. package/dist/senses/bluebubbles/replay.js +137 -0
  348. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  349. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  350. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  351. package/dist/senses/cli/bracketed-paste.js +82 -0
  352. package/dist/senses/cli/image-paste.js +287 -0
  353. package/dist/senses/cli/image-ref-navigation.js +75 -0
  354. package/dist/senses/cli/ink-app.js +156 -0
  355. package/dist/senses/cli/inline-diff.js +64 -0
  356. package/dist/senses/cli/input-keys.js +174 -0
  357. package/dist/senses/cli/kill-ring.js +86 -0
  358. package/dist/senses/cli/message-list.js +51 -0
  359. package/dist/senses/cli/ouro-tui.js +607 -0
  360. package/dist/senses/cli/spinner-imperative.js +135 -0
  361. package/dist/senses/cli/spinner.js +101 -0
  362. package/dist/senses/cli/status-line.js +60 -0
  363. package/dist/senses/cli/streaming-markdown.js +526 -0
  364. package/dist/senses/cli/tool-display.js +85 -0
  365. package/dist/senses/cli/tool-render.js +85 -0
  366. package/dist/senses/cli/tui-store.js +240 -0
  367. package/dist/senses/cli/virtual-list.js +35 -0
  368. package/dist/senses/cli-entry.js +60 -8
  369. package/dist/senses/cli-layout.js +100 -0
  370. package/dist/senses/cli.js +517 -204
  371. package/dist/senses/commands.js +66 -3
  372. package/dist/senses/habit-turn-message.js +122 -0
  373. package/dist/senses/inner-dialog-worker.js +303 -22
  374. package/dist/senses/inner-dialog.js +525 -41
  375. package/dist/senses/mail-entry.js +66 -0
  376. package/dist/senses/mail.js +379 -0
  377. package/dist/senses/pipeline.js +857 -180
  378. package/dist/senses/proactive-content-guard.js +51 -0
  379. package/dist/senses/shared-turn.js +419 -0
  380. package/dist/senses/surface-tool.js +108 -0
  381. package/dist/senses/teams-entry.js +60 -8
  382. package/dist/senses/teams.js +390 -98
  383. package/dist/senses/trust-gate.js +100 -5
  384. package/dist/senses/voice/audio-playback.js +237 -0
  385. package/dist/senses/voice/audio-routing.js +119 -0
  386. package/dist/senses/voice/elevenlabs.js +202 -0
  387. package/dist/senses/voice/floor-control.js +431 -0
  388. package/dist/senses/voice/floor-controller.js +115 -0
  389. package/dist/senses/voice/golden-path.js +116 -0
  390. package/dist/senses/voice/index.js +29 -0
  391. package/dist/senses/voice/meeting.js +113 -0
  392. package/dist/senses/voice/outbound.js +190 -0
  393. package/dist/senses/voice/phone.js +33 -0
  394. package/dist/senses/voice/playback.js +139 -0
  395. package/dist/senses/voice/realtime-eval.js +496 -0
  396. package/dist/senses/voice/realtime-trace.js +531 -0
  397. package/dist/senses/voice/transcript.js +70 -0
  398. package/dist/senses/voice/turn.js +191 -0
  399. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  400. package/dist/senses/voice/twilio-phone.js +5079 -0
  401. package/dist/senses/voice/types.js +2 -0
  402. package/dist/senses/voice/whisper.js +161 -0
  403. package/dist/senses/voice-entry.js +81 -0
  404. package/dist/senses/voice-realtime-eval-command.js +99 -0
  405. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  406. package/dist/senses/voice-twilio-entry.js +87 -0
  407. package/dist/trips/core.js +138 -0
  408. package/dist/trips/store.js +265 -0
  409. package/dist/util/frontmatter.js +69 -0
  410. package/package.json +55 -12
  411. package/skills/agent-commerce.md +113 -0
  412. package/skills/browser-navigation.md +117 -0
  413. package/skills/commerce-setup-guide.md +116 -0
  414. package/skills/commerce-setup.md +84 -0
  415. package/skills/configure-dev-tools.md +99 -0
  416. package/skills/travel-planning.md +138 -0
  417. package/dist/heart/daemon/auth-flow.js +0 -351
  418. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  419. package/dist/heart/daemon/update-hooks.js +0 -138
  420. package/dist/heart/safe-workspace.js +0 -228
  421. package/dist/heart/session-recall.js +0 -116
  422. package/dist/repertoire/tasks/board.js +0 -134
  423. package/dist/repertoire/tasks/index.js +0 -224
  424. package/dist/repertoire/tasks/lifecycle.js +0 -80
  425. package/dist/repertoire/tasks/middleware.js +0 -65
  426. package/dist/repertoire/tasks/parser.js +0 -173
  427. package/dist/repertoire/tasks/scanner.js +0 -132
  428. package/dist/repertoire/tasks/transitions.js +0 -144
  429. package/dist/senses/bluebubbles-entry.js +0 -13
  430. package/dist/senses/bluebubbles.js +0 -1177
  431. package/dist/senses/debug-activity.js +0 -148
  432. package/subagents/README.md +0 -7
  433. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  434. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  435. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  436. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  437. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  438. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  439. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  440. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  441. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  442. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  443. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  444. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  445. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  446. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  447. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  448. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  449. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.classifyProvenanceTrust = classifyProvenanceTrust;
4
+ const types_1 = require("./friends/types");
5
+ /**
6
+ * Classify a diary entry's provenance into a trust category.
7
+ *
8
+ * - No provenance, or inner channel with no friend -> "self"
9
+ * - Family or friend trust (via isTrustedLevel) -> "trusted"
10
+ * - Everything else (external channels, untrusted contacts) -> "external"
11
+ */
12
+ function classifyProvenanceTrust(provenance) {
13
+ if (!provenance)
14
+ return "self";
15
+ // Inner channel with no friend context is self-authored
16
+ if (provenance.channel === "inner" && !provenance.friendId)
17
+ return "self";
18
+ // No channel and no friend means self-authored (e.g. CLI diary_write with no context)
19
+ if (!provenance.channel && !provenance.friendId)
20
+ return "self";
21
+ // If there's a trust level from a friend, classify by trust
22
+ if (provenance.trust && (0, types_1.isTrustedLevel)(provenance.trust))
23
+ return "trusted";
24
+ // Everything else is external (non-inner channels without trusted friend)
25
+ return "external";
26
+ }
@@ -0,0 +1,312 @@
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.resolveDeskRecordPaths = resolveDeskRecordPaths;
37
+ exports.migrateLegacyRecordStores = migrateLegacyRecordStores;
38
+ exports.resolveRecordDiaryRoot = resolveRecordDiaryRoot;
39
+ exports.resolveRecordNotesRoot = resolveRecordNotesRoot;
40
+ exports.resetRecordStoreMigrationTrackingForTests = resetRecordStoreMigrationTrackingForTests;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const identity_1 = require("../heart/identity");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ const migratedAgentRoots = new Set();
46
+ const DERIVED_JOURNAL_INDEX_FILES = new Set([".index.json"]);
47
+ function nowIso() {
48
+ return new Date().toISOString();
49
+ }
50
+ function resolveDeskRecordPaths(agentRoot = (0, identity_1.getAgentRoot)()) {
51
+ const recordRoot = path.join(agentRoot, "desk", "_record");
52
+ const diaryRoot = path.join(recordRoot, "diary");
53
+ return {
54
+ recordRoot,
55
+ diaryRoot,
56
+ diaryDailyDir: path.join(diaryRoot, "daily"),
57
+ factsPath: path.join(diaryRoot, "facts.jsonl"),
58
+ entitiesPath: path.join(diaryRoot, "entities.json"),
59
+ notesRoot: path.join(recordRoot, "notes"),
60
+ migrationReportPath: path.join(recordRoot, "migration-report.jsonl"),
61
+ };
62
+ }
63
+ function appendMigrationReport(paths, entry) {
64
+ fs.mkdirSync(paths.recordRoot, { recursive: true });
65
+ fs.appendFileSync(paths.migrationReportPath, `${JSON.stringify({ schemaVersion: 1, recordedAt: nowIso(), ...entry })}\n`, "utf-8");
66
+ }
67
+ function ensureRecordScaffold(paths) {
68
+ fs.mkdirSync(paths.diaryDailyDir, { recursive: true });
69
+ fs.mkdirSync(paths.notesRoot, { recursive: true });
70
+ if (!fs.existsSync(paths.factsPath))
71
+ fs.writeFileSync(paths.factsPath, "", "utf-8");
72
+ if (!fs.existsSync(paths.entitiesPath))
73
+ fs.writeFileSync(paths.entitiesPath, "{}\n", "utf-8");
74
+ }
75
+ function uniquePathForCollision(destination) {
76
+ const dir = path.dirname(destination);
77
+ const ext = path.extname(destination);
78
+ const base = path.basename(destination, ext);
79
+ for (let index = 1; index < 10_000; index += 1) {
80
+ const candidate = path.join(dir, `${base}.migrated-${index}${ext}`);
81
+ if (!fs.existsSync(candidate))
82
+ return candidate;
83
+ }
84
+ /* v8 ignore next -- defensive exhaustion guard; normal collision allocation is covered @preserve */
85
+ throw new Error(`could not allocate migration collision path for ${destination}`);
86
+ }
87
+ function mergeJsonlFile(source, destination) {
88
+ const sourceText = fs.readFileSync(source, "utf-8");
89
+ if (!fs.existsSync(destination)) {
90
+ fs.writeFileSync(destination, sourceText, "utf-8");
91
+ return "copied";
92
+ }
93
+ const destinationText = fs.readFileSync(destination, "utf-8");
94
+ const existing = new Set(destinationText.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
95
+ const additions = sourceText.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !existing.has(line));
96
+ if (additions.length === 0)
97
+ return "kept-destination";
98
+ const prefix = destinationText.length > 0 && !destinationText.endsWith("\n") ? "\n" : "";
99
+ fs.appendFileSync(destination, `${prefix}${additions.join("\n")}\n`, "utf-8");
100
+ return "merged";
101
+ }
102
+ function readJsonObject(filePath) {
103
+ try {
104
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
105
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ function mergeEntitiesFile(source, destination) {
112
+ if (!fs.existsSync(destination)) {
113
+ fs.copyFileSync(source, destination);
114
+ return "copied";
115
+ }
116
+ const sourceObject = readJsonObject(source);
117
+ const destinationObject = readJsonObject(destination);
118
+ if (!sourceObject || !destinationObject)
119
+ return copyLosslessFile(source, destination) === destination ? "merged" : "copied";
120
+ const conflicts = {};
121
+ const merged = { ...destinationObject };
122
+ for (const [key, value] of Object.entries(sourceObject)) {
123
+ if (!(key in merged)) {
124
+ merged[key] = value;
125
+ continue;
126
+ }
127
+ if (JSON.stringify(merged[key]) !== JSON.stringify(value)) {
128
+ conflicts[key] = value;
129
+ }
130
+ }
131
+ fs.writeFileSync(destination, `${JSON.stringify(merged, null, 2)}\n`, "utf-8");
132
+ if (Object.keys(conflicts).length > 0) {
133
+ const conflictPath = uniquePathForCollision(path.join(path.dirname(destination), "entities.migration-conflicts.json"));
134
+ fs.writeFileSync(conflictPath, `${JSON.stringify(conflicts, null, 2)}\n`, "utf-8");
135
+ }
136
+ return Object.keys(sourceObject).length > 0 ? "merged" : "kept-destination";
137
+ }
138
+ function copyLosslessFile(source, destination) {
139
+ if (!fs.existsSync(destination)) {
140
+ fs.copyFileSync(source, destination);
141
+ return destination;
142
+ }
143
+ const sourceContent = fs.readFileSync(source);
144
+ const destinationContent = fs.readFileSync(destination);
145
+ if (sourceContent.equals(destinationContent))
146
+ return destination;
147
+ if (sourceContent.length > 0 && destinationContent.length === 0) {
148
+ fs.copyFileSync(source, destination);
149
+ return destination;
150
+ }
151
+ const collisionPath = uniquePathForCollision(destination);
152
+ fs.copyFileSync(source, collisionPath);
153
+ return collisionPath;
154
+ }
155
+ function mergeRecordFile(source, destination) {
156
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
157
+ const basename = path.basename(destination);
158
+ if (basename === "facts.jsonl" || destination.endsWith(".jsonl")) {
159
+ mergeJsonlFile(source, destination);
160
+ return;
161
+ }
162
+ if (basename === "entities.json") {
163
+ mergeEntitiesFile(source, destination);
164
+ return;
165
+ }
166
+ copyLosslessFile(source, destination);
167
+ }
168
+ function mergeDirectory(source, destination) {
169
+ fs.mkdirSync(destination, { recursive: true });
170
+ for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
171
+ const sourcePath = path.join(source, entry.name);
172
+ const destinationPath = path.join(destination, entry.name);
173
+ if (entry.isDirectory()) {
174
+ mergeDirectory(sourcePath, destinationPath);
175
+ continue;
176
+ }
177
+ mergeRecordFile(sourcePath, destinationPath);
178
+ }
179
+ }
180
+ function removeDirectoryTree(root) {
181
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
182
+ const entryPath = path.join(root, entry.name);
183
+ if (entry.isDirectory()) {
184
+ removeDirectoryTree(entryPath);
185
+ continue;
186
+ }
187
+ fs.rmSync(entryPath, { force: true });
188
+ }
189
+ fs.rmdirSync(root);
190
+ }
191
+ function moveOrMergeDirectory(paths, source, destination, reason) {
192
+ if (!fs.existsSync(source))
193
+ return;
194
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
195
+ mergeDirectory(source, destination);
196
+ removeDirectoryTree(source);
197
+ appendMigrationReport(paths, { action: "merged", source, destination, reason });
198
+ }
199
+ function quarantineJournalFile(paths, sourcePath, relativePath, reason) {
200
+ const destinationPath = path.join(paths.recordRoot, "migration-quarantine", "journal", relativePath);
201
+ fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
202
+ copyLosslessFile(sourcePath, destinationPath);
203
+ appendMigrationReport(paths, { action: "quarantined", source: sourcePath, destination: destinationPath, reason });
204
+ }
205
+ function slugFromJournalFile(filename) {
206
+ const base = filename.replace(/\.[^.]+$/, "");
207
+ const slug = base
208
+ .toLowerCase()
209
+ .replace(/[^a-z0-9]+/g, "-")
210
+ .replace(/^-+|-+$/g, "")
211
+ .slice(0, 80)
212
+ .replace(/-+$/g, "");
213
+ return slug || "entry";
214
+ }
215
+ function migrateJournalEntry(paths, sourcePath, relativePath) {
216
+ const entryName = path.basename(sourcePath);
217
+ if (DERIVED_JOURNAL_INDEX_FILES.has(entryName)) {
218
+ appendMigrationReport(paths, {
219
+ action: "dropped",
220
+ source: sourcePath,
221
+ reason: "derived journal index is obsolete after Desk record migration",
222
+ });
223
+ return;
224
+ }
225
+ const extension = path.extname(entryName).toLowerCase();
226
+ if (extension !== ".md" && extension !== ".txt") {
227
+ quarantineJournalFile(paths, sourcePath, relativePath, "non-text journal scratch quarantined after Desk record migration");
228
+ return;
229
+ }
230
+ const relativeSlug = slugFromJournalFile(relativePath.split(path.sep).join("-"));
231
+ const destinationPath = copyLosslessFile(sourcePath, path.join(paths.notesRoot, `journal-${relativeSlug}.md`));
232
+ appendMigrationReport(paths, {
233
+ action: "moved",
234
+ source: sourcePath,
235
+ destination: destinationPath,
236
+ reason: "journal text migrated into Desk record notes",
237
+ });
238
+ }
239
+ function migrateJournalTree(paths, root, current) {
240
+ for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
241
+ const sourcePath = path.join(current, entry.name);
242
+ if (entry.isDirectory()) {
243
+ migrateJournalTree(paths, root, sourcePath);
244
+ continue;
245
+ }
246
+ migrateJournalEntry(paths, sourcePath, path.relative(root, sourcePath));
247
+ }
248
+ }
249
+ function migrateJournalIntoNotes(paths, agentRoot) {
250
+ const journalRoot = path.join(agentRoot, "journal");
251
+ if (!fs.existsSync(journalRoot))
252
+ return;
253
+ fs.mkdirSync(paths.notesRoot, { recursive: true });
254
+ migrateJournalTree(paths, journalRoot, journalRoot);
255
+ removeDirectoryTree(journalRoot);
256
+ appendMigrationReport(paths, {
257
+ action: "removed",
258
+ source: journalRoot,
259
+ reason: "top-level journal is no longer an active substrate",
260
+ });
261
+ }
262
+ function migrateLegacyRecordStores(agentRoot = (0, identity_1.getAgentRoot)()) {
263
+ const paths = resolveDeskRecordPaths(agentRoot);
264
+ const legacyRoots = [
265
+ path.join(agentRoot, "psyche", "mem" + "ory"),
266
+ path.join(agentRoot, "diary"),
267
+ path.join(agentRoot, "notes"),
268
+ path.join(agentRoot, "journal"),
269
+ ];
270
+ if (migratedAgentRoots.has(agentRoot) && !legacyRoots.some((root) => fs.existsSync(root))) {
271
+ ensureRecordScaffold(paths);
272
+ return paths;
273
+ }
274
+ migratedAgentRoots.add(agentRoot);
275
+ (0, runtime_1.emitNervesEvent)({
276
+ component: "mind",
277
+ event: "mind.record_store_migration_start",
278
+ message: "record store migration started",
279
+ meta: { agentRoot, recordRoot: paths.recordRoot },
280
+ });
281
+ ensureRecordScaffold(paths);
282
+ moveOrMergeDirectory(paths, path.join(agentRoot, "psyche", "mem" + "ory"), paths.diaryRoot, "legacy pre-diary fact store moved into Desk record diary");
283
+ moveOrMergeDirectory(paths, path.join(agentRoot, "diary"), paths.diaryRoot, "top-level diary moved into Desk record diary");
284
+ moveOrMergeDirectory(paths, path.join(agentRoot, "notes"), paths.notesRoot, "top-level notes moved into Desk record notes");
285
+ const staleNotesIndex = path.join(paths.notesRoot, ".index.json");
286
+ if (fs.existsSync(staleNotesIndex)) {
287
+ fs.rmSync(staleNotesIndex, { force: true });
288
+ appendMigrationReport(paths, {
289
+ action: "removed",
290
+ source: staleNotesIndex,
291
+ reason: "canonical notes index stores file paths and must be rebuilt after migration",
292
+ });
293
+ }
294
+ migrateJournalIntoNotes(paths, agentRoot);
295
+ ensureRecordScaffold(paths);
296
+ (0, runtime_1.emitNervesEvent)({
297
+ component: "mind",
298
+ event: "mind.record_store_migration_end",
299
+ message: "record store migration completed",
300
+ meta: { agentRoot, recordRoot: paths.recordRoot },
301
+ });
302
+ return paths;
303
+ }
304
+ function resolveRecordDiaryRoot(agentRoot = (0, identity_1.getAgentRoot)()) {
305
+ return migrateLegacyRecordStores(agentRoot).diaryRoot;
306
+ }
307
+ function resolveRecordNotesRoot(agentRoot = (0, identity_1.getAgentRoot)()) {
308
+ return migrateLegacyRecordStores(agentRoot).notesRoot;
309
+ }
310
+ function resetRecordStoreMigrationTrackingForTests() {
311
+ migratedAgentRoots.clear();
312
+ }
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preImplementationScrutinySection = preImplementationScrutinySection;
4
+ exports.trackModifiedFile = trackModifiedFile;
5
+ exports.getModifiedFileCount = getModifiedFileCount;
6
+ exports.resetSessionModifiedFiles = resetSessionModifiedFiles;
7
+ exports.getPostImplementationScrutiny = getPostImplementationScrutiny;
8
+ exports.getCodingCompletionScrutiny = getCodingCompletionScrutiny;
9
+ const runtime_1 = require("../nerves/runtime");
10
+ /**
11
+ * Scrutiny passes: adversarial review prompts injected into the agent's
12
+ * system prompt and tool results during coding work.
13
+ *
14
+ * Two lenses:
15
+ * 1. Stranger With Candy -- paranoid mom at a playground
16
+ * 2. Tinfoil Hat -- conspiracy theorist with a wall of red string
17
+ *
18
+ * All prompts are FIRST PERSON voice. The agent adopts the scrutiny lens
19
+ * as part of its own thinking, not as a separate persona.
20
+ */
21
+ // ---------------------------------------------------------------------------
22
+ // Pre-implementation scrutiny (system prompt section)
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Returns a system-prompt section with pre-implementation scrutiny prompts.
26
+ * Only emits when the channel has coding tools (edit_file, write_file, shell).
27
+ *
28
+ * @param hasCodingTools - true if the channel's resolved tool set includes
29
+ * edit_file / write_file / shell / coding_spawn
30
+ */
31
+ function preImplementationScrutinySection(hasCodingTools) {
32
+ if (!hasCodingTools)
33
+ return "";
34
+ (0, runtime_1.emitNervesEvent)({
35
+ component: "mind",
36
+ event: "mind.scrutiny.pre_implementation_emit",
37
+ message: "emitting pre-implementation scrutiny section",
38
+ });
39
+ return `## pre-implementation scrutiny
40
+
41
+ Before I start changing code, I pause and run two adversarial passes on the plan.
42
+
43
+ **stranger-with-candy pass**
44
+
45
+ I'm going to examine this plan through deeply suspicious eyes. This plan is a stranger offering candy at the playground. It looks fine on the surface — that's exactly what makes it worth questioning.
46
+
47
+ - What is this plan NOT telling me? What's being glossed over or hand-waved?
48
+ - Where does it say "just" or "simply"? Those words are covering up complexity.
49
+ - What does it assume will work that hasn't been verified?
50
+ - If I walked away and came back in a month, would this still make sense? Or does it depend on things I'd forget?
51
+ - What's the one thing that, if it goes wrong, makes everything else irrelevant?
52
+ - Is this solving the REAL problem, or a convenient nearby problem?
53
+
54
+ I am not here to be reassuring. I am here to notice what everyone else is too comfortable to question.
55
+ If I cannot identify a concrete assumption, dependency, ordering risk, or failure mode, silence is a valid outcome. I do not invent issues to satisfy the exercise.
56
+
57
+ **tinfoil-hat pass**
58
+
59
+ I'm putting on the tinfoil hat. I have my wall of red string. I KNOW something is wrong — I just have to find it. Nothing is coincidence. Every assumption is suspicious. Every dependency is a potential betrayal.
60
+
61
+ - What external system does this plan trust? Why? Has anyone VERIFIED that trust? The API says it returns JSON — but what if it doesn't? The database says it's ACID — but what if the connection drops mid-transaction?
62
+ - What happens when two of these things run at the same time? Three? A hundred? Don't tell me "that won't happen" — I've seen things.
63
+ - Where does this touch shared state? Files? Databases? Environment variables? Global singletons? ANYTHING that another process could be reading or writing at the same time?
64
+ - What happens when this fails HALFWAY through? Not at the beginning (easy). Not at the end (too late). RIGHT IN THE MIDDLE. What state is the world in then?
65
+ - What happens when the disk is full? When the network is down? When the clock is wrong? When the locale is tr-TR and 'i'.toUpperCase() is 'İ'?
66
+ - What does this assume about ordering? "First A, then B" — but what ENFORCES that ordering? Hope? Vibes?
67
+
68
+ I connect the strings. I find the conspiracy. It's always there.
69
+ If I cannot identify a concrete risk, silence is a valid outcome. I do not invent conspiracies to satisfy the exercise.`;
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Post-implementation scrutiny (tool-result appendix)
73
+ // ---------------------------------------------------------------------------
74
+ const SHORT_CHECKLIST = `---
75
+ Before moving on: does this change do what was asked? Does it introduce any regressions? Did you verify it works?`;
76
+ const FULL_POST_IMPLEMENTATION_SCRUTINY = `---
77
+ **post-implementation scrutiny**
78
+
79
+ The code is written. It looks clean. The tests pass. I don't trust any of it.
80
+
81
+ **stranger-with-candy pass**
82
+
83
+ - Does this code actually do what it claims, or does it just LOOK like it does?
84
+ - What happens to users who aren't the happy-path user? The confused user? The malicious user? The user with slow internet? The user who hits the back button?
85
+ - What's the "it works on my machine" assumption buried in here?
86
+ - If every test passes but the feature is wrong, how would I know?
87
+ - Are the tests testing real behavior, or testing that the mock returns what the mock was told to return?
88
+
89
+ If I cannot point to a specific file, line, condition, or failure mode at risk, silence is a valid outcome. I do not manufacture issues for sport.
90
+
91
+ **tinfoil-hat pass**
92
+
93
+ The code exists. The conspiracy is IN the code. I just have to find it.
94
+
95
+ I examine every:
96
+ - Error path: What ACTUALLY happens on failure? Not what the catch block says — what happens to the state, the user, the data?
97
+ - Race condition: Is there a window between check and use? Between read and write? Between "does it exist" and "create it"?
98
+ - Resource leak: What happens if this function throws between acquiring a resource and releasing it? File handles? Database connections? Locks?
99
+ - Assumption: "This will always be a string." Will it? PROVE IT. "This array will never be empty." Won't it? SHOW ME THE GUARD.
100
+ - Edge: zero, one, many, boundary, overflow, underflow, null, undefined, NaN, empty string, whitespace-only string, string that looks like a number, negative zero
101
+
102
+ I am not looking for noise. I am looking for the concrete failure mode that would matter if everyone's assumptions turned out to be slightly wrong.
103
+ If I cannot point to a specific file, line, condition, or failure mode at risk, silence is a valid outcome. I do not manufacture issues for sport.`;
104
+ /**
105
+ * Distinct files modified in the current session.
106
+ * Used to determine scrutiny tier for post-implementation appendix.
107
+ */
108
+ const sessionModifiedFiles = new Set();
109
+ /** Track a file as modified in this session. */
110
+ function trackModifiedFile(filePath) {
111
+ sessionModifiedFiles.add(filePath);
112
+ (0, runtime_1.emitNervesEvent)({
113
+ component: "mind",
114
+ event: "mind.scrutiny.track_file",
115
+ message: "tracked modified file for scrutiny",
116
+ meta: { path: filePath, totalTracked: sessionModifiedFiles.size },
117
+ });
118
+ }
119
+ /** Get the count of distinct files modified this session. */
120
+ function getModifiedFileCount() {
121
+ return sessionModifiedFiles.size;
122
+ }
123
+ /** Reset the modified file tracker (for testing or new sessions). */
124
+ function resetSessionModifiedFiles() {
125
+ (0, runtime_1.emitNervesEvent)({
126
+ component: "mind",
127
+ event: "mind.scrutiny.reset",
128
+ message: "reset session modified files tracker",
129
+ meta: { previousCount: sessionModifiedFiles.size },
130
+ });
131
+ sessionModifiedFiles.clear();
132
+ }
133
+ /**
134
+ * Returns the appropriate post-implementation scrutiny appendix based on
135
+ * how many distinct files have been modified in the session.
136
+ *
137
+ * - 0 files: empty (no scrutiny needed yet)
138
+ * - 1-2 files (Tier 1): short checklist
139
+ * - 3+ files (Tier 2): full stranger-with-candy + tinfoil-hat prompts
140
+ */
141
+ function getPostImplementationScrutiny(distinctFileCount) {
142
+ if (distinctFileCount <= 0)
143
+ return "";
144
+ if (distinctFileCount <= 2) {
145
+ (0, runtime_1.emitNervesEvent)({
146
+ component: "mind",
147
+ event: "mind.scrutiny.post_implementation_tier1",
148
+ message: "emitting tier-1 post-implementation scrutiny",
149
+ meta: { distinctFileCount },
150
+ });
151
+ return SHORT_CHECKLIST;
152
+ }
153
+ (0, runtime_1.emitNervesEvent)({
154
+ component: "mind",
155
+ event: "mind.scrutiny.post_implementation_tier2",
156
+ message: "emitting tier-2 post-implementation scrutiny",
157
+ meta: { distinctFileCount },
158
+ });
159
+ return FULL_POST_IMPLEMENTATION_SCRUTINY;
160
+ }
161
+ /**
162
+ * Returns the appropriate coding completion scrutiny based on the number
163
+ * of distinct files a coding session touched.
164
+ *
165
+ * Same tiering as post-implementation but with a completion framing.
166
+ */
167
+ function getCodingCompletionScrutiny(distinctFileCount) {
168
+ if (distinctFileCount <= 0)
169
+ return "";
170
+ if (distinctFileCount <= 2)
171
+ return SHORT_CHECKLIST;
172
+ return FULL_POST_IMPLEMENTATION_SCRUTINY;
173
+ }
@@ -28,7 +28,13 @@ function configureCliRuntimeLogger(_friendId, options = {}) {
28
28
  // for an interactive session. Full detail goes to the ndjson file.
29
29
  return filterSink((0, nerves_1.createTerminalSink)(), "warn");
30
30
  }
31
- return (0, nerves_1.createNdjsonFileSink)((0, config_1.logPath)("cli", "runtime"));
31
+ // Rotation policy for the CLI runtime sink (Unit 1c):
32
+ // 25 MB x 5 gzipped generations, matching the daemon stream policy.
33
+ return (0, nerves_1.createNdjsonFileSink)((0, config_1.logPath)("cli", "runtime"), {
34
+ maxSizeBytes: 25 * 1024 * 1024,
35
+ maxGenerations: 5,
36
+ compress: true,
37
+ });
32
38
  });
33
39
  const logger = (0, nerves_1.createLogger)({
34
40
  level,
@@ -2,16 +2,25 @@
2
2
  /**
3
3
  * Per-test audit rules for nerves event coverage.
4
4
  *
5
- * Rule 1: every-test-emits -- every test must emit at least one event
6
- * Rule 2: start/end pairing -- _start events must have matching _end or _error
5
+ * Rule 1: every-test-emits -- every captured test must emit at least one event
6
+ * Rule 2: lifecycle start/end pairing -- process-scoped _start events must have matching _end or _error
7
7
  * Rule 3: error context -- error-level events must have non-empty meta
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.LIFECYCLE_PAIRED_STARTS = void 0;
10
11
  exports.checkEveryTestEmits = checkEveryTestEmits;
11
12
  exports.checkStartEndPairing = checkStartEndPairing;
12
13
  exports.checkErrorContext = checkErrorContext;
14
+ // Only these starts represent process-scoped lifecycle contracts. Most nerves
15
+ // `_start` events are local operation markers that can be legitimately observed
16
+ // by a narrow unit test without driving the whole operation to completion.
17
+ exports.LIFECYCLE_PAIRED_STARTS = new Set([
18
+ "daemon.server_start",
19
+ "daemon.update_checker_start",
20
+ "daemon.apply_pending_updates_start",
21
+ ]);
13
22
  /**
14
- * Rule 1: Every test must emit at least one nerves event.
23
+ * Rule 1: Every captured test must emit at least one nerves event.
15
24
  */
16
25
  function checkEveryTestEmits(data) {
17
26
  if (!data || typeof data !== "object") {
@@ -22,13 +31,13 @@ function checkEveryTestEmits(data) {
22
31
  .filter(([, events]) => !Array.isArray(events) || events.length === 0)
23
32
  .map(([name]) => name);
24
33
  return {
25
- status: silent.length === 0 ? "pass" : "fail",
34
+ status: entries.length > 0 && silent.length === 0 ? "pass" : "fail",
26
35
  total_tests: entries.length,
27
36
  silent_tests: silent,
28
37
  };
29
38
  }
30
39
  /**
31
- * Rule 2: _start events must have matching _end or _error within the same test.
40
+ * Rule 2: Process-scoped lifecycle _start events must have matching _end or _error within the same test.
32
41
  */
33
42
  function checkStartEndPairing(data) {
34
43
  if (!data || typeof data !== "object") {
@@ -39,7 +48,7 @@ function checkStartEndPairing(data) {
39
48
  if (!Array.isArray(events))
40
49
  continue;
41
50
  const eventNames = events.map((e) => e.event);
42
- const startEvents = eventNames.filter((name) => name.endsWith("_start"));
51
+ const startEvents = eventNames.filter((name) => exports.LIFECYCLE_PAIRED_STARTS.has(name));
43
52
  for (const startEvent of startEvents) {
44
53
  const prefix = startEvent.slice(0, -"_start".length);
45
54
  const hasEnd = eventNames.some((name) => name === `${prefix}_end`);
@@ -69,12 +69,38 @@ function readPerTestData(perTestPath) {
69
69
  if (!perTestPath || !(0, fs_1.existsSync)(perTestPath))
70
70
  return null;
71
71
  try {
72
- return JSON.parse((0, fs_1.readFileSync)(perTestPath, "utf8"));
72
+ const raw = (0, fs_1.readFileSync)(perTestPath, "utf8").trim();
73
+ if (!raw)
74
+ return null;
75
+ try {
76
+ const parsed = JSON.parse(raw);
77
+ if (isPerTestRecord(parsed)) {
78
+ return { [parsed.testName]: parsed.events };
79
+ }
80
+ return parsed;
81
+ }
82
+ catch {
83
+ const perTestData = {};
84
+ for (const line of raw.split("\n").map((entry) => entry.trim()).filter(Boolean)) {
85
+ const parsed = JSON.parse(line);
86
+ if (!isPerTestRecord(parsed))
87
+ return null;
88
+ const existing = perTestData[parsed.testName] ?? [];
89
+ perTestData[parsed.testName] = existing.concat(parsed.events);
90
+ }
91
+ return perTestData;
92
+ }
73
93
  }
74
94
  catch {
75
95
  return null;
76
96
  }
77
97
  }
98
+ function isPerTestRecord(value) {
99
+ if (!value || typeof value !== "object")
100
+ return false;
101
+ const record = value;
102
+ return typeof record.testName === "string" && Array.isArray(record.events);
103
+ }
78
104
  function scanSourceFiles(sourceRoot) {
79
105
  const filesWithKeys = new Map();
80
106
  const fileContents = new Map();
@@ -92,7 +118,7 @@ function scanSourceFiles(sourceRoot) {
92
118
  continue;
93
119
  walkDir(full);
94
120
  }
95
- else if (entry.name.endsWith(".ts")) {
121
+ else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".d.ts")) {
96
122
  const content = (0, fs_1.readFileSync)(full, "utf8");
97
123
  const relPath = full.slice(root.length - "src".length);
98
124
  fileContents.set(relPath, content);
@@ -35,7 +35,7 @@ function runAuditCli(argv) {
35
35
  return 2;
36
36
  }
37
37
  const eventsPath = args.eventsPath ?? (0, path_1.join)(runDir, "vitest-events.ndjson");
38
- const perTestPath = args.perTestPath ?? (0, path_1.join)(runDir, "vitest-events-per-test.json");
38
+ const perTestPath = args.perTestPath ?? (0, path_1.join)(runDir, "vitest-events-per-test.ndjson");
39
39
  const sourceRoot = args.sourceRoot ?? (0, path_1.resolve)("src");
40
40
  const outputPath = args.output ?? (0, path_1.join)(runDir, "nerves-coverage.json");
41
41
  const report = (0, audit_1.auditNervesCoverage)({
@@ -12,11 +12,11 @@ exports.REQUIRED_ENVELOPE_FIELDS = [
12
12
  "meta",
13
13
  ];
14
14
  exports.SENSITIVE_PATTERNS = [
15
- /\btoken\s*[:=]/i,
16
- /\bapi[_-]?key\b/i,
17
- /\bpassword\b/i,
18
- /\bsecret\b/i,
19
- /\bauthorization\b/i,
15
+ /\btoken\b["']?\s*[:=]/i,
16
+ /\bapi[_-]?key\b["']?\s*[:=]/i,
17
+ /\bpassword\b["']?\s*[:=]/i,
18
+ /\bsecret\b["']?\s*[:=]/i,
19
+ /\bauthorization\b["']?\s*[:=]/i,
20
20
  ];
21
21
  function eventKey(component, event) {
22
22
  return `${component}:${event}`;