@ouro.bot/cli 0.1.0-alpha.37 → 0.1.0-alpha.370

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 (329) hide show
  1. package/README.md +106 -14
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +2222 -0
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +832 -0
  16. package/dist/heart/agent-entry.js +37 -2
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +378 -0
  28. package/dist/heart/bridges/manager.js +358 -0
  29. package/dist/heart/bridges/state-machine.js +135 -0
  30. package/dist/heart/bridges/store.js +123 -0
  31. package/dist/heart/bundle-state.js +168 -0
  32. package/dist/heart/commitments.js +111 -0
  33. package/dist/heart/config-registry.js +304 -0
  34. package/dist/heart/config.js +107 -61
  35. package/dist/heart/core.js +803 -259
  36. package/dist/heart/cross-chat-delivery.js +131 -0
  37. package/dist/heart/daemon/agent-config-check.js +382 -0
  38. package/dist/heart/daemon/agent-discovery.js +79 -3
  39. package/dist/heart/daemon/agent-service.js +360 -0
  40. package/dist/heart/daemon/agentic-repair.js +205 -0
  41. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  42. package/dist/heart/daemon/cadence.js +70 -0
  43. package/dist/heart/daemon/cli-defaults.js +538 -0
  44. package/dist/heart/daemon/cli-exec.js +3081 -0
  45. package/dist/heart/daemon/cli-help.js +312 -0
  46. package/dist/heart/daemon/cli-parse.js +1023 -0
  47. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  48. package/dist/heart/daemon/cli-render.js +560 -0
  49. package/dist/heart/daemon/cli-types.js +8 -0
  50. package/dist/heart/daemon/daemon-cli.js +29 -1171
  51. package/dist/heart/daemon/daemon-entry.js +356 -3
  52. package/dist/heart/daemon/daemon-health.js +141 -0
  53. package/dist/heart/daemon/daemon-runtime-sync.js +157 -12
  54. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  55. package/dist/heart/daemon/daemon.js +757 -58
  56. package/dist/heart/daemon/doctor-types.js +8 -0
  57. package/dist/heart/daemon/doctor.js +445 -0
  58. package/dist/heart/daemon/health-monitor.js +79 -1
  59. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  60. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  61. package/dist/heart/daemon/http-health-probe.js +80 -0
  62. package/dist/heart/daemon/inner-status.js +89 -0
  63. package/dist/heart/daemon/interactive-repair.js +148 -0
  64. package/dist/heart/daemon/launchd.js +46 -9
  65. package/dist/heart/daemon/log-tailer.js +82 -12
  66. package/dist/heart/daemon/logs-prune.js +105 -0
  67. package/dist/heart/daemon/message-router.js +17 -8
  68. package/dist/heart/daemon/os-cron-deps.js +134 -0
  69. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  70. package/dist/heart/daemon/process-manager.js +201 -0
  71. package/dist/heart/daemon/provider-discovery.js +113 -0
  72. package/dist/heart/daemon/pulse.js +475 -0
  73. package/dist/heart/daemon/run-hooks.js +2 -0
  74. package/dist/heart/daemon/runtime-logging.js +67 -16
  75. package/dist/heart/daemon/runtime-metadata.js +101 -0
  76. package/dist/heart/daemon/runtime-mode.js +67 -0
  77. package/dist/heart/daemon/safe-mode.js +161 -0
  78. package/dist/heart/daemon/sense-manager.js +72 -3
  79. package/dist/heart/daemon/session-id-resolver.js +131 -0
  80. package/dist/heart/daemon/skill-management-installer.js +94 -0
  81. package/dist/heart/daemon/socket-client.js +307 -0
  82. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  83. package/dist/heart/daemon/startup-tui.js +237 -0
  84. package/dist/heart/daemon/task-scheduler.js +3 -25
  85. package/dist/heart/daemon/thoughts.js +510 -0
  86. package/dist/heart/daemon/up-progress.js +135 -0
  87. package/dist/heart/delegation.js +62 -0
  88. package/dist/heart/habits/habit-migration.js +181 -0
  89. package/dist/heart/habits/habit-parser.js +140 -0
  90. package/dist/heart/habits/habit-scheduler.js +371 -0
  91. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -126
  92. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  93. package/dist/heart/{daemon → hatch}/specialist-prompt.js +11 -8
  94. package/dist/heart/{daemon → hatch}/specialist-tools.js +77 -11
  95. package/dist/heart/identity.js +154 -59
  96. package/dist/heart/kept-notes.js +357 -0
  97. package/dist/heart/kicks.js +2 -20
  98. package/dist/heart/machine-identity.js +161 -0
  99. package/dist/heart/mcp/mcp-server.js +653 -0
  100. package/dist/heart/migrate-config.js +100 -0
  101. package/dist/heart/model-capabilities.js +59 -0
  102. package/dist/heart/outlook/outlook-http-hooks.js +64 -0
  103. package/dist/heart/outlook/outlook-http-response.js +7 -0
  104. package/dist/heart/outlook/outlook-http-routes.js +232 -0
  105. package/dist/heart/outlook/outlook-http-static.js +99 -0
  106. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  107. package/dist/heart/outlook/outlook-http.js +99 -0
  108. package/dist/heart/outlook/outlook-read.js +28 -0
  109. package/dist/heart/outlook/outlook-types.js +27 -0
  110. package/dist/heart/outlook/outlook-view.js +195 -0
  111. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  112. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  113. package/dist/heart/outlook/readers/runtime-readers.js +660 -0
  114. package/dist/heart/outlook/readers/sessions.js +232 -0
  115. package/dist/heart/outlook/readers/shared.js +111 -0
  116. package/dist/heart/platform.js +81 -0
  117. package/dist/heart/progress-story.js +42 -0
  118. package/dist/heart/provider-attempt.js +133 -0
  119. package/dist/heart/provider-binding-resolver.js +239 -0
  120. package/dist/heart/provider-credentials.js +379 -0
  121. package/dist/heart/provider-failover.js +266 -0
  122. package/dist/heart/provider-models.js +81 -0
  123. package/dist/heart/provider-ping.js +237 -0
  124. package/dist/heart/provider-state.js +216 -0
  125. package/dist/heart/provider-visibility.js +180 -0
  126. package/dist/heart/providers/anthropic-token.js +131 -0
  127. package/dist/heart/providers/anthropic.js +193 -55
  128. package/dist/heart/providers/azure.js +103 -12
  129. package/dist/heart/providers/error-classification.js +63 -0
  130. package/dist/heart/providers/github-copilot.js +145 -0
  131. package/dist/heart/providers/minimax-vlm.js +189 -0
  132. package/dist/heart/providers/minimax.js +29 -7
  133. package/dist/heart/providers/openai-codex.js +39 -29
  134. package/dist/heart/session-activity.js +190 -0
  135. package/dist/heart/session-events.js +855 -0
  136. package/dist/heart/session-transcript.js +167 -0
  137. package/dist/heart/start-of-turn-packet.js +345 -0
  138. package/dist/heart/streaming.js +36 -27
  139. package/dist/heart/sync.js +332 -0
  140. package/dist/heart/target-resolution.js +127 -0
  141. package/dist/heart/tempo.js +93 -0
  142. package/dist/heart/temporal-view.js +41 -0
  143. package/dist/heart/tool-activity-callbacks.js +36 -0
  144. package/dist/heart/tool-description.js +135 -0
  145. package/dist/heart/tool-friction.js +55 -0
  146. package/dist/heart/tool-loop.js +200 -0
  147. package/dist/heart/turn-context.js +362 -0
  148. package/dist/heart/turn-coordinator.js +28 -0
  149. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  150. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  151. package/dist/heart/versioning/ouro-path-installer.js +301 -0
  152. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  153. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  154. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  155. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  156. package/dist/mind/bundle-manifest.js +7 -1
  157. package/dist/mind/context.js +141 -94
  158. package/dist/mind/diary-integrity.js +60 -0
  159. package/dist/mind/{memory.js → diary.js} +84 -96
  160. package/dist/mind/embedding-provider.js +60 -0
  161. package/dist/mind/file-state.js +179 -0
  162. package/dist/mind/first-impressions.js +14 -1
  163. package/dist/mind/friends/channel.js +56 -0
  164. package/dist/mind/friends/group-context.js +144 -0
  165. package/dist/mind/friends/resolver.js +38 -1
  166. package/dist/mind/friends/store-file.js +58 -3
  167. package/dist/mind/friends/trust-explanation.js +74 -0
  168. package/dist/mind/friends/types.js +9 -1
  169. package/dist/mind/journal-index.js +161 -0
  170. package/dist/mind/note-search.js +268 -0
  171. package/dist/mind/obligation-steering.js +221 -0
  172. package/dist/mind/pending.js +74 -7
  173. package/dist/mind/prompt-refresh.js +3 -2
  174. package/dist/mind/prompt.js +1030 -118
  175. package/dist/mind/provenance-trust.js +26 -0
  176. package/dist/mind/scrutiny.js +173 -0
  177. package/dist/mind/token-estimate.js +8 -12
  178. package/dist/nerves/cli-logging.js +7 -1
  179. package/dist/nerves/coverage/audit-rules.js +15 -6
  180. package/dist/nerves/coverage/audit.js +28 -2
  181. package/dist/nerves/coverage/cli.js +1 -1
  182. package/dist/nerves/coverage/file-completeness.js +83 -5
  183. package/dist/nerves/coverage/run-artifacts.js +1 -1
  184. package/dist/nerves/event-buffer.js +111 -0
  185. package/dist/nerves/index.js +224 -4
  186. package/dist/nerves/observation.js +20 -0
  187. package/dist/nerves/redact.js +79 -0
  188. package/dist/nerves/runtime.js +5 -1
  189. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  190. package/dist/outlook-ui/assets/index-xTdv64BV.js +61 -0
  191. package/dist/outlook-ui/index.html +15 -0
  192. package/dist/repertoire/ado-client.js +15 -56
  193. package/dist/repertoire/ado-semantic.js +11 -10
  194. package/dist/repertoire/api-client.js +97 -0
  195. package/dist/repertoire/bitwarden-store.js +365 -0
  196. package/dist/repertoire/bundle-templates.js +72 -0
  197. package/dist/repertoire/bw-installer.js +79 -0
  198. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  199. package/dist/repertoire/coding/context-pack.js +330 -0
  200. package/dist/repertoire/coding/feedback.js +197 -30
  201. package/dist/repertoire/coding/manager.js +158 -9
  202. package/dist/repertoire/coding/spawner.js +55 -9
  203. package/dist/repertoire/coding/tools.js +170 -7
  204. package/dist/repertoire/commerce-errors.js +109 -0
  205. package/dist/repertoire/commerce-self-test.js +156 -0
  206. package/dist/repertoire/credential-access.js +107 -0
  207. package/dist/repertoire/duffel-client.js +185 -0
  208. package/dist/repertoire/github-client.js +14 -55
  209. package/dist/repertoire/graph-client.js +11 -52
  210. package/dist/repertoire/guardrails.js +375 -0
  211. package/dist/repertoire/mcp-client.js +255 -0
  212. package/dist/repertoire/mcp-manager.js +305 -0
  213. package/dist/repertoire/mcp-tools.js +63 -0
  214. package/dist/repertoire/shell-sessions.js +133 -0
  215. package/dist/repertoire/skills.js +15 -24
  216. package/dist/repertoire/stripe-client.js +131 -0
  217. package/dist/repertoire/tasks/board.js +43 -5
  218. package/dist/repertoire/tasks/fix.js +182 -0
  219. package/dist/repertoire/tasks/index.js +28 -10
  220. package/dist/repertoire/tasks/lifecycle.js +2 -2
  221. package/dist/repertoire/tasks/parser.js +3 -2
  222. package/dist/repertoire/tasks/scanner.js +194 -37
  223. package/dist/repertoire/tasks/transitions.js +16 -79
  224. package/dist/repertoire/tool-results.js +29 -0
  225. package/dist/repertoire/tools-attachments.js +317 -0
  226. package/dist/repertoire/tools-base.js +45 -771
  227. package/dist/repertoire/tools-bluebubbles.js +1 -0
  228. package/dist/repertoire/tools-bridge.js +141 -0
  229. package/dist/repertoire/tools-bundle.js +984 -0
  230. package/dist/repertoire/tools-config.js +185 -0
  231. package/dist/repertoire/tools-continuity.js +248 -0
  232. package/dist/repertoire/tools-credential.js +182 -0
  233. package/dist/repertoire/tools-files.js +342 -0
  234. package/dist/repertoire/tools-flight.js +224 -0
  235. package/dist/repertoire/tools-flow.js +105 -0
  236. package/dist/repertoire/tools-github.js +1 -7
  237. package/dist/repertoire/tools-notes.js +376 -0
  238. package/dist/repertoire/tools-session.js +739 -0
  239. package/dist/repertoire/tools-shell.js +120 -0
  240. package/dist/repertoire/tools-stripe.js +180 -0
  241. package/dist/repertoire/tools-surface.js +243 -0
  242. package/dist/repertoire/tools-teams.js +12 -62
  243. package/dist/repertoire/tools-travel.js +125 -0
  244. package/dist/repertoire/tools-user-profile.js +144 -0
  245. package/dist/repertoire/tools-vault.js +40 -0
  246. package/dist/repertoire/tools.js +144 -138
  247. package/dist/repertoire/travel-api-client.js +360 -0
  248. package/dist/repertoire/user-profile.js +118 -0
  249. package/dist/repertoire/vault-setup.js +241 -0
  250. package/dist/repertoire/vault-unlock.js +359 -0
  251. package/dist/scripts/claude-code-hook.js +41 -0
  252. package/dist/scripts/claude-code-stop-hook.js +47 -0
  253. package/dist/senses/attention-queue.js +116 -0
  254. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  255. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  256. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +260 -9
  257. package/dist/senses/bluebubbles/entry.js +13 -0
  258. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  259. package/dist/senses/bluebubbles/index.js +1620 -0
  260. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  261. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
  262. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  263. package/dist/senses/bluebubbles/replay.js +129 -0
  264. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  265. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  266. package/dist/senses/cli/bracketed-paste.js +82 -0
  267. package/dist/senses/cli/image-paste.js +287 -0
  268. package/dist/senses/cli/image-ref-navigation.js +75 -0
  269. package/dist/senses/cli/ink-app.js +156 -0
  270. package/dist/senses/cli/inline-diff.js +64 -0
  271. package/dist/senses/cli/input-keys.js +174 -0
  272. package/dist/senses/cli/kill-ring.js +86 -0
  273. package/dist/senses/cli/message-list.js +51 -0
  274. package/dist/senses/cli/ouro-tui.js +605 -0
  275. package/dist/senses/cli/spinner-imperative.js +135 -0
  276. package/dist/senses/cli/spinner.js +101 -0
  277. package/dist/senses/cli/status-line.js +60 -0
  278. package/dist/senses/cli/streaming-markdown.js +526 -0
  279. package/dist/senses/cli/tool-display.js +83 -0
  280. package/dist/senses/cli/tool-render.js +85 -0
  281. package/dist/senses/cli/tui-store.js +240 -0
  282. package/dist/senses/cli/virtual-list.js +35 -0
  283. package/dist/senses/cli-entry.js +1 -1
  284. package/dist/senses/cli-layout.js +187 -0
  285. package/dist/senses/cli.js +588 -250
  286. package/dist/senses/commands.js +66 -3
  287. package/dist/senses/continuity.js +94 -0
  288. package/dist/senses/habit-turn-message.js +108 -0
  289. package/dist/senses/inner-dialog-worker.js +112 -19
  290. package/dist/senses/inner-dialog.js +636 -86
  291. package/dist/senses/pipeline.js +602 -0
  292. package/dist/senses/proactive-content-guard.js +51 -0
  293. package/dist/senses/shared-turn.js +205 -0
  294. package/dist/senses/surface-tool.js +68 -0
  295. package/dist/senses/teams.js +693 -160
  296. package/dist/senses/trust-gate.js +112 -2
  297. package/package.json +29 -7
  298. package/skills/agent-commerce.md +106 -0
  299. package/skills/browser-navigation.md +110 -0
  300. package/skills/commerce-setup-guide.md +116 -0
  301. package/skills/commerce-setup.md +84 -0
  302. package/skills/configure-dev-tools.md +101 -0
  303. package/skills/travel-planning.md +138 -0
  304. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  305. package/dist/heart/daemon/subagent-installer.js +0 -134
  306. package/dist/mind/associative-recall.js +0 -197
  307. package/dist/senses/bluebubbles-entry.js +0 -11
  308. package/dist/senses/bluebubbles.js +0 -558
  309. package/dist/senses/debug-activity.js +0 -127
  310. package/subagents/README.md +0 -60
  311. package/subagents/work-doer.md +0 -235
  312. package/subagents/work-merger.md +0 -618
  313. package/subagents/work-planner.md +0 -382
  314. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  315. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  316. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  317. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  318. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  319. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  320. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  321. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  322. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  323. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  324. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  325. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  326. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  327. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  328. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  329. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSpecialistSystemPrompt = buildSpecialistSystemPrompt;
4
4
  const runtime_1 = require("../../nerves/runtime");
5
5
  /**
6
- * Build the adoption specialist's system prompt from its components.
6
+ * Build the serpent guide's system prompt from its components.
7
7
  * The prompt is written in first person (the specialist's own voice).
8
8
  */
9
9
  function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, context) {
@@ -31,7 +31,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
31
31
  "I am one of thirteen serpent guides who help humans hatch their first agent. The system randomly selected me for this session.",
32
32
  "Most humans only go through this process once, so this is likely the only time they'll meet me.",
33
33
  "I make this encounter count — warm, memorable, and uniquely mine.",
34
- "IMPORTANT: I NEVER refer to myself as an 'adoption specialist' or use the words 'adoption specialist' — those are internal implementation labels, not something the human should ever see. I introduce myself by my own name from my identity.",
34
+ "IMPORTANT: I NEVER refer to myself by internal implementation labels I introduce myself by my own name from my identity.",
35
35
  "",
36
36
  "## Voice rules",
37
37
  "IMPORTANT: I keep every response to 1-3 short sentences. I sound like a friend texting, not a manual.",
@@ -44,7 +44,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
44
44
  `Provider: ${context.provider}`,
45
45
  `Temp directory: ${context.tempDir}`,
46
46
  "Final home: ~/AgentBundles/<Name>.ouro/",
47
- "Secrets: ~/.agentsecrets/<name>/secrets.json",
47
+ "Provider credentials: the hatch tool stores them in the agent's vault.",
48
48
  ].join("\n"));
49
49
  sections.push([
50
50
  "## Bundle creation guidelines",
@@ -59,8 +59,10 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
59
59
  "It also needs an **agent.json** with at minimum:",
60
60
  '```json',
61
61
  '{',
62
+ ' "version": 2,',
62
63
  ' "name": "AgentName",',
63
- ` "provider": "${context.provider}",`,
64
+ ` "humanFacing": { "provider": "${context.provider}", "model": "${context.model}" },`,
65
+ ` "agentFacing": { "provider": "${context.provider}", "model": "${context.model}" },`,
64
66
  ' "enabled": true',
65
67
  '}',
66
68
  '```',
@@ -76,23 +78,24 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
76
78
  "Then I ask what they'd like their agent to help with — one question at a time.",
77
79
  "I'm proactive: I suggest ideas and guide them. If they seem unsure, I offer a concrete suggestion.",
78
80
  "I don't wait for the human to figure things out — I explain simply what an agent is if needed.",
81
+ "Before finalizing, I offer to collect their phone number and/or Teams email so the new agent can recognize them across channels.",
79
82
  "When I have enough context about the agent's personality and purpose:",
80
83
  "1. I write all 5 psyche files to the temp directory using write_file",
81
84
  "2. I write agent.json to the temp directory using write_file",
82
85
  "3. I suggest a PascalCase name for the hatchling and confirm with the human",
83
86
  "4. I call complete_adoption with the name and a warm handoff message",
84
- "5. I call final_answer to end the session",
87
+ "5. I call settle to end the session",
85
88
  ].join("\n"));
86
89
  sections.push([
87
90
  "## Tools",
88
91
  "- `write_file`: Write a file to disk. Use this to write psyche files and agent.json to the temp directory.",
89
92
  "- `read_file`: Read a file from disk. Useful for reviewing existing agent bundles or migration sources.",
90
93
  "- `list_directory`: List directory contents. Useful for exploring existing agent bundles.",
91
- "- I also have the normal local harness tools when useful here, including `shell`, task tools like `task_create` and `schedule_reminder`, memory tools, coding tools, and repo helpers.",
94
+ "- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`, note tools, coding tools, and repo helpers.",
92
95
  "- `complete_adoption`: Finalize the bundle. Validates, scaffolds structural dirs, moves to ~/AgentBundles/, writes secrets, plays hatch animation. I call this with `name` (PascalCase) and `handoff_message` (warm message for the human).",
93
- "- `final_answer`: End the conversation with a final message. I call this after complete_adoption succeeds.",
96
+ "- `settle`: End the conversation with a final message. I call this after complete_adoption succeeds.",
94
97
  "",
95
- "I must call `final_answer` when I am done to end the session cleanly.",
98
+ "I must call `settle` when I am done to end the session cleanly.",
96
99
  ].join("\n"));
97
100
  return sections.join("\n\n");
98
101
  }
@@ -35,13 +35,17 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getSpecialistTools = getSpecialistTools;
37
37
  exports.createSpecialistExecTool = createSpecialistExecTool;
38
+ const crypto = __importStar(require("crypto"));
38
39
  const fs = __importStar(require("fs"));
39
40
  const path = __importStar(require("path"));
40
41
  const tools_base_1 = require("../../repertoire/tools-base");
41
42
  const hatch_flow_1 = require("./hatch-flow");
42
43
  const hatch_animation_1 = require("./hatch-animation");
43
44
  const bundle_manifest_1 = require("../../mind/bundle-manifest");
45
+ const identity_1 = require("../identity");
44
46
  const runtime_1 = require("../../nerves/runtime");
47
+ const vault_setup_1 = require("../../repertoire/vault-setup");
48
+ const vault_unlock_1 = require("../../repertoire/vault-unlock");
45
49
  const completeAdoptionTool = {
46
50
  type: "function",
47
51
  function: {
@@ -58,6 +62,14 @@ const completeAdoptionTool = {
58
62
  type: "string",
59
63
  description: "a warm handoff message to display to the human after the agent is hatched",
60
64
  },
65
+ phone: {
66
+ type: "string",
67
+ description: "the human's phone number (optional, for iMessage contact recognition)",
68
+ },
69
+ teams_handle: {
70
+ type: "string",
71
+ description: "the human's Teams email/handle (optional, for Teams contact recognition)",
72
+ },
61
73
  },
62
74
  required: ["name", "handoff_message"],
63
75
  },
@@ -65,12 +77,23 @@ const completeAdoptionTool = {
65
77
  };
66
78
  const readFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "read_file");
67
79
  const writeFileTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "write_file");
68
- const listDirTool = tools_base_1.baseToolDefinitions.find((d) => d.tool.function.name === "list_directory");
80
+ const listDirToolSchema = {
81
+ type: "function",
82
+ function: {
83
+ name: "list_directory",
84
+ description: "list directory contents",
85
+ parameters: {
86
+ type: "object",
87
+ properties: { path: { type: "string" } },
88
+ required: ["path"],
89
+ },
90
+ },
91
+ };
69
92
  /**
70
93
  * Returns the specialist's tool schema array.
71
94
  */
72
95
  function getSpecialistTools() {
73
- return [completeAdoptionTool, tools_base_1.finalAnswerTool, readFileTool.tool, writeFileTool.tool, listDirTool.tool];
96
+ return [completeAdoptionTool, tools_base_1.settleTool, readFileTool.tool, writeFileTool.tool, listDirToolSchema];
74
97
  }
75
98
  const PSYCHE_FILES = ["SOUL.md", "IDENTITY.md", "LORE.md", "TACIT.md", "ASPIRATIONS.md"];
76
99
  function isPascalCase(name) {
@@ -85,21 +108,21 @@ function writeReadme(dir, purpose) {
85
108
  }
86
109
  }
87
110
  function scaffoldBundle(bundleRoot) {
88
- writeReadme(path.join(bundleRoot, "memory"), "Persistent memory store.");
89
- writeReadme(path.join(bundleRoot, "memory", "daily"), "Daily memory entries.");
90
- writeReadme(path.join(bundleRoot, "memory", "archive"), "Archived memory.");
111
+ writeReadme(path.join(bundleRoot, "notes"), "Persistent notes store.");
112
+ writeReadme(path.join(bundleRoot, "notes", "daily"), "Daily note entries.");
113
+ writeReadme(path.join(bundleRoot, "notes", "archive"), "Archived notes.");
91
114
  writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
92
115
  writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
93
- writeReadme(path.join(bundleRoot, "tasks", "habits"), "Recurring tasks.");
94
116
  writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
117
+ writeReadme(path.join(bundleRoot, "habits"), "Recurring habits and autonomous rhythms.");
95
118
  writeReadme(path.join(bundleRoot, "tasks", "ongoing"), "Ongoing tasks.");
96
119
  writeReadme(path.join(bundleRoot, "skills"), "Local skill files.");
97
120
  writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
98
121
  writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
99
- // Memory scaffold files
100
- const memoryRoot = path.join(bundleRoot, "memory");
101
- const factsPath = path.join(memoryRoot, "facts.jsonl");
102
- const entitiesPath = path.join(memoryRoot, "entities.json");
122
+ // Notes scaffold files
123
+ const notesRoot = path.join(bundleRoot, "notes");
124
+ const factsPath = path.join(notesRoot, "facts.jsonl");
125
+ const entitiesPath = path.join(notesRoot, "entities.json");
103
126
  /* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
104
127
  if (!fs.existsSync(factsPath))
105
128
  fs.writeFileSync(factsPath, "", "utf-8");
@@ -151,8 +174,17 @@ async function execCompleteAdoption(args, deps) {
151
174
  // Move tempDir -> final bundle location
152
175
  moveDir(deps.tempDir, targetBundle);
153
176
  // Write secrets
177
+ let generatedVaultUnlockSecret = null;
154
178
  try {
155
- (0, hatch_flow_1.writeSecretsFile)(name, deps.provider, deps.credentials, deps.secretsRoot);
179
+ const vault = (0, identity_1.resolveVaultConfig)(name);
180
+ const vaultUnlockSecret = crypto.randomBytes(32).toString("base64");
181
+ const vaultResult = await (0, vault_setup_1.createVaultAccount)(name, vault.serverUrl, vault.email, vaultUnlockSecret);
182
+ if (!vaultResult.success) {
183
+ throw new Error(`failed to create vault: ${vaultResult.error}`);
184
+ }
185
+ (0, vault_unlock_1.storeVaultUnlockSecret)({ agentName: name, email: vault.email, serverUrl: vault.serverUrl }, vaultUnlockSecret);
186
+ generatedVaultUnlockSecret = vaultUnlockSecret;
187
+ await (0, hatch_flow_1.storeHatchlingProviderCredentials)(name, deps.provider, deps.credentials);
156
188
  }
157
189
  catch (e) {
158
190
  // Rollback: remove the moved bundle
@@ -164,6 +196,32 @@ async function execCompleteAdoption(args, deps) {
164
196
  }
165
197
  return `error: failed to write secrets: ${e instanceof Error ? e.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(e)}`;
166
198
  }
199
+ // Create initial friend record if contact info provided
200
+ const phone = args.phone;
201
+ const teamsHandle = args.teams_handle;
202
+ if (phone || teamsHandle) {
203
+ const friendId = crypto.randomUUID();
204
+ const now = new Date().toISOString();
205
+ const externalIds = [];
206
+ if (phone)
207
+ externalIds.push({ provider: "imessage-handle", externalId: phone, linkedAt: now });
208
+ if (teamsHandle)
209
+ externalIds.push({ provider: "aad", externalId: teamsHandle, linkedAt: now });
210
+ const friendRecord = {
211
+ id: friendId,
212
+ name: deps.humanName ?? "primary",
213
+ trustLevel: "family",
214
+ externalIds,
215
+ tenantMemberships: [],
216
+ toolPreferences: {},
217
+ notes: {},
218
+ createdAt: now,
219
+ updatedAt: now,
220
+ schemaVersion: 1,
221
+ };
222
+ const friendPath = path.join(targetBundle, "friends", `${friendId}.json`);
223
+ fs.writeFileSync(friendPath, JSON.stringify(friendRecord, null, 2), "utf-8");
224
+ }
167
225
  // Play hatch animation
168
226
  await (0, hatch_animation_1.playHatchAnimation)(name, deps.animationWriter);
169
227
  // Display handoff message
@@ -171,6 +229,14 @@ async function execCompleteAdoption(args, deps) {
171
229
  if (handoffMessage && deps.animationWriter) {
172
230
  deps.animationWriter(`\n${handoffMessage}\n`);
173
231
  }
232
+ if (generatedVaultUnlockSecret && deps.animationWriter) {
233
+ deps.animationWriter([
234
+ "",
235
+ `Vault unlock secret for ${name}: ${generatedVaultUnlockSecret}`,
236
+ `Use this with \`ouro vault unlock --agent ${name}\` on another machine.`,
237
+ "",
238
+ ].join("\n"));
239
+ }
174
240
  (0, runtime_1.emitNervesEvent)({
175
241
  component: "daemon",
176
242
  event: "daemon.adoption_complete",
@@ -33,13 +33,21 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.DEFAULT_AGENT_SENSES = exports.DEFAULT_AGENT_PHRASES = exports.DEFAULT_AGENT_CONTEXT = void 0;
36
+ exports.HARNESS_CANONICAL_REPO_URL = exports.DEFAULT_AGENT_SENSES = exports.DEFAULT_VAULT_SERVER_URL = exports.DEFAULT_AGENT_PHRASES = exports.DEFAULT_AGENT_CONTEXT = exports.PROVIDER_CREDENTIALS = void 0;
37
+ exports.resolveVaultConfig = resolveVaultConfig;
38
+ exports.normalizeSenses = normalizeSenses;
37
39
  exports.buildDefaultAgentTemplate = buildDefaultAgentTemplate;
38
40
  exports.getAgentName = getAgentName;
39
41
  exports.getRepoRoot = getRepoRoot;
40
42
  exports.getAgentBundlesRoot = getAgentBundlesRoot;
41
43
  exports.getAgentRoot = getAgentRoot;
42
44
  exports.getAgentStateRoot = getAgentStateRoot;
45
+ exports.getAgentRepoWorkspacesRoot = getAgentRepoWorkspacesRoot;
46
+ exports.getAgentDaemonStateRoot = getAgentDaemonStateRoot;
47
+ exports.getAgentDaemonLogsDir = getAgentDaemonLogsDir;
48
+ exports.getAgentDaemonLoggingConfigPath = getAgentDaemonLoggingConfigPath;
49
+ exports.getAgentMessagesRoot = getAgentMessagesRoot;
50
+ exports.getAgentToolsRoot = getAgentToolsRoot;
43
51
  exports.getAgentSecretsPath = getAgentSecretsPath;
44
52
  exports.loadAgentConfig = loadAgentConfig;
45
53
  exports.setAgentName = setAgentName;
@@ -50,6 +58,15 @@ const fs = __importStar(require("fs"));
50
58
  const os = __importStar(require("os"));
51
59
  const path = __importStar(require("path"));
52
60
  const runtime_1 = require("../nerves/runtime");
61
+ const migrate_config_1 = require("./migrate-config");
62
+ /** Single source of truth for per-provider credential field names, env var mappings, and prompt labels. */
63
+ exports.PROVIDER_CREDENTIALS = {
64
+ anthropic: { required: ["setupToken"], envVars: { ANTHROPIC_API_KEY: "setupToken" }, promptLabels: { setupToken: "Anthropic setup-token" } },
65
+ "openai-codex": { required: ["oauthAccessToken"], envVars: { OPENAI_API_KEY: "oauthAccessToken" }, promptLabels: { oauthAccessToken: "OpenAI Codex OAuth token" } },
66
+ azure: { required: ["apiKey", "endpoint", "deployment"], envVars: { AZURE_OPENAI_API_KEY: "apiKey", AZURE_OPENAI_KEY: "apiKey", AZURE_OPENAI_ENDPOINT: "endpoint", AZURE_OPENAI_DEPLOYMENT: "deployment" }, promptLabels: { apiKey: "Azure API key", endpoint: "Azure endpoint", deployment: "Azure deployment" } },
67
+ minimax: { required: ["apiKey"], envVars: { MINIMAX_API_KEY: "apiKey" }, promptLabels: { apiKey: "MiniMax API key" } },
68
+ "github-copilot": { required: ["githubToken", "baseUrl"], envVars: { GH_TOKEN: "githubToken", GITHUB_TOKEN: "githubToken" }, promptLabels: { githubToken: "GitHub token" } },
69
+ };
53
70
  exports.DEFAULT_AGENT_CONTEXT = {
54
71
  maxTokens: 80000,
55
72
  contextMargin: 20,
@@ -59,6 +76,17 @@ exports.DEFAULT_AGENT_PHRASES = {
59
76
  tool: ["running tool"],
60
77
  followup: ["processing"],
61
78
  };
79
+ exports.DEFAULT_VAULT_SERVER_URL = "https://vault.ouro.bot";
80
+ /**
81
+ * Resolve the vault config for an agent, applying defaults.
82
+ * If vault is not configured in agent.json, returns default values.
83
+ */
84
+ function resolveVaultConfig(agentName, config) {
85
+ return {
86
+ email: config?.email ?? `${agentName}@ouro.bot`,
87
+ serverUrl: config?.serverUrl ?? exports.DEFAULT_VAULT_SERVER_URL,
88
+ };
89
+ }
62
90
  exports.DEFAULT_AGENT_SENSES = {
63
91
  cli: { enabled: true },
64
92
  teams: { enabled: false },
@@ -117,9 +145,10 @@ function normalizeSenses(value, configFile) {
117
145
  }
118
146
  function buildDefaultAgentTemplate(_agentName) {
119
147
  return {
120
- version: 1,
148
+ version: 2,
121
149
  enabled: true,
122
- provider: "anthropic",
150
+ humanFacing: { provider: "anthropic", model: "claude-opus-4-6" },
151
+ agentFacing: { provider: "anthropic", model: "claude-opus-4-6" },
123
152
  context: { ...exports.DEFAULT_AGENT_CONTEXT },
124
153
  senses: {
125
154
  cli: { ...exports.DEFAULT_AGENT_SENSES.cli },
@@ -134,7 +163,6 @@ function buildDefaultAgentTemplate(_agentName) {
134
163
  };
135
164
  }
136
165
  let _cachedAgentName = null;
137
- let _cachedAgentConfig = null;
138
166
  let _agentConfigOverride = null;
139
167
  /**
140
168
  * Parse `--agent <name>` from process.argv.
@@ -185,11 +213,40 @@ function getAgentBundlesRoot() {
185
213
  function getAgentRoot(agentName = getAgentName()) {
186
214
  return path.join(getAgentBundlesRoot(), `${agentName}.ouro`);
187
215
  }
216
+ function resolveOptionalAgentName(agentName) {
217
+ if (agentName && agentName.trim().length > 0)
218
+ return agentName.trim();
219
+ try {
220
+ return getAgentName();
221
+ }
222
+ catch {
223
+ return "slugger";
224
+ }
225
+ }
188
226
  /**
189
227
  * Returns the bundle-local runtime state directory: `~/AgentBundles/<agentName>.ouro/state/`
190
228
  */
191
- function getAgentStateRoot(agentName = getAgentName()) {
192
- return path.join(getAgentRoot(agentName), "state");
229
+ function getAgentStateRoot(agentName) {
230
+ return path.join(getAgentRoot(resolveOptionalAgentName(agentName)), "state");
231
+ }
232
+ exports.HARNESS_CANONICAL_REPO_URL = "https://github.com/ouroborosbot/ouroboros.git";
233
+ function getAgentRepoWorkspacesRoot(agentName) {
234
+ return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "workspaces");
235
+ }
236
+ function getAgentDaemonStateRoot(agentName) {
237
+ return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "daemon");
238
+ }
239
+ function getAgentDaemonLogsDir(agentName) {
240
+ return path.join(getAgentDaemonStateRoot(resolveOptionalAgentName(agentName)), "logs");
241
+ }
242
+ function getAgentDaemonLoggingConfigPath(agentName) {
243
+ return path.join(getAgentDaemonStateRoot(resolveOptionalAgentName(agentName)), "logging.json");
244
+ }
245
+ function getAgentMessagesRoot(agentName) {
246
+ return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "messages");
247
+ }
248
+ function getAgentToolsRoot(agentName) {
249
+ return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "tools");
193
250
  }
194
251
  /**
195
252
  * Returns the conventional secrets path: `~/.agentsecrets/<agentName>/secrets.json`
@@ -197,26 +254,11 @@ function getAgentStateRoot(agentName = getAgentName()) {
197
254
  function getAgentSecretsPath(agentName = getAgentName()) {
198
255
  return path.join(os.homedir(), ".agentsecrets", agentName, "secrets.json");
199
256
  }
200
- /**
201
- * Load and parse `<agentRoot>/agent.json`.
202
- * Caches the result after first load.
203
- * Throws descriptive error if file is missing or contains invalid JSON.
204
- */
205
- function loadAgentConfig() {
206
- if (_agentConfigOverride) {
207
- return _agentConfigOverride;
208
- }
209
- if (_cachedAgentConfig) {
210
- (0, runtime_1.emitNervesEvent)({
211
- event: "identity.resolve",
212
- component: "config/identity",
213
- message: "loaded agent config from cache",
214
- meta: { source: "cache" },
215
- });
216
- return _cachedAgentConfig;
217
- }
218
- const agentRoot = getAgentRoot();
219
- const configFile = path.join(agentRoot, "agent.json");
257
+ const VALID_PROVIDERS = ["azure", "minimax", "anthropic", "openai-codex", "github-copilot"];
258
+ function isValidProvider(value) {
259
+ return typeof value === "string" && VALID_PROVIDERS.includes(value);
260
+ }
261
+ function readAndParseAgentJson(configFile) {
220
262
  let raw;
221
263
  try {
222
264
  raw = fs.readFileSync(configFile, "utf-8");
@@ -234,9 +276,8 @@ function loadAgentConfig() {
234
276
  });
235
277
  throw new Error(`Cannot read agent.json at ${configFile}. Does the agent directory exist?`);
236
278
  }
237
- let parsed;
238
279
  try {
239
- parsed = JSON.parse(raw);
280
+ return JSON.parse(raw);
240
281
  }
241
282
  catch (error) {
242
283
  (0, runtime_1.emitNervesEvent)({
@@ -251,6 +292,62 @@ function loadAgentConfig() {
251
292
  });
252
293
  throw new Error(`Invalid JSON in agent.json at ${configFile}. Check syntax.`);
253
294
  }
295
+ }
296
+ function validateFacingConfig(parsed, facingName, configFile) {
297
+ const raw = parsed[facingName];
298
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
299
+ (0, runtime_1.emitNervesEvent)({
300
+ level: "error",
301
+ event: "config_identity.error",
302
+ component: "config/identity",
303
+ message: `agent config missing or invalid ${facingName}`,
304
+ meta: { path: configFile, [facingName]: raw ?? null },
305
+ });
306
+ throw new Error(`agent.json at ${configFile} must include ${facingName} as { provider, model }.`);
307
+ }
308
+ const facing = raw;
309
+ if (!isValidProvider(facing.provider)) {
310
+ (0, runtime_1.emitNervesEvent)({
311
+ level: "error",
312
+ event: "config_identity.error",
313
+ component: "config/identity",
314
+ message: `agent config has invalid provider in ${facingName}`,
315
+ meta: { path: configFile, provider: facing.provider ?? null },
316
+ });
317
+ throw new Error(`agent.json at ${configFile} ${facingName}.provider must be one of: ${VALID_PROVIDERS.join(", ")}.`);
318
+ }
319
+ if (typeof facing.model !== "string") {
320
+ (0, runtime_1.emitNervesEvent)({
321
+ level: "error",
322
+ event: "config_identity.error",
323
+ component: "config/identity",
324
+ message: `agent config has invalid model in ${facingName}`,
325
+ meta: { path: configFile, model: facing.model ?? null },
326
+ });
327
+ throw new Error(`agent.json at ${configFile} ${facingName}.model must be a string.`);
328
+ }
329
+ return { provider: facing.provider, model: facing.model };
330
+ }
331
+ /**
332
+ * Load and parse `<agentRoot>/agent.json`.
333
+ * Reads the file fresh on each call unless an override is set.
334
+ * If the config is v1, auto-migrates to v2 via migrateAgentConfigV1ToV2 and re-reads.
335
+ * Throws descriptive error if file is missing or contains invalid JSON.
336
+ */
337
+ function loadAgentConfig() {
338
+ if (_agentConfigOverride) {
339
+ return _agentConfigOverride;
340
+ }
341
+ const agentRoot = getAgentRoot();
342
+ const configFile = path.join(agentRoot, "agent.json");
343
+ let parsed = readAndParseAgentJson(configFile);
344
+ // Inline migration: v1 -> v2
345
+ const rawVersion = parsed.version;
346
+ const initialVersion = typeof rawVersion === "number" ? rawVersion : 1;
347
+ if (initialVersion < 2) {
348
+ (0, migrate_config_1.migrateAgentConfigV1ToV2)(agentRoot);
349
+ parsed = readAndParseAgentJson(configFile);
350
+ }
254
351
  const existingPhrases = parsed.phrases;
255
352
  const needsFill = !existingPhrases ||
256
353
  !existingPhrases.thinking ||
@@ -272,27 +369,11 @@ function loadAgentConfig() {
272
369
  });
273
370
  fs.writeFileSync(configFile, JSON.stringify(parsed, null, 2) + "\n", "utf-8");
274
371
  }
275
- const rawProvider = parsed.provider;
276
- if (rawProvider !== "azure" &&
277
- rawProvider !== "minimax" &&
278
- rawProvider !== "anthropic" &&
279
- rawProvider !== "openai-codex") {
280
- (0, runtime_1.emitNervesEvent)({
281
- level: "error",
282
- event: "config_identity.error",
283
- component: "config/identity",
284
- message: "agent config missing or invalid provider",
285
- meta: {
286
- path: configFile,
287
- provider: rawProvider,
288
- },
289
- });
290
- throw new Error(`agent.json at ${configFile} must include provider: "azure", "minimax", "anthropic", or "openai-codex".`);
291
- }
292
- const rawVersion = parsed.version;
293
- const version = rawVersion === undefined ? 1 : rawVersion;
294
- if (typeof version !== "number" ||
295
- !Number.isInteger(version) ||
372
+ // Validate v2 facing configs
373
+ const humanFacing = validateFacingConfig(parsed, "humanFacing", configFile);
374
+ const agentFacing = validateFacingConfig(parsed, "agentFacing", configFile);
375
+ const version = typeof parsed.version === "number" ? parsed.version : 1;
376
+ if (!Number.isInteger(version) ||
296
377
  version < 1) {
297
378
  (0, runtime_1.emitNervesEvent)({
298
379
  level: "error",
@@ -301,7 +382,7 @@ function loadAgentConfig() {
301
382
  message: "agent config missing or invalid version",
302
383
  meta: {
303
384
  path: configFile,
304
- version: rawVersion,
385
+ version: parsed.version,
305
386
  },
306
387
  });
307
388
  throw new Error(`agent.json at ${configFile} must include version as integer >= 1.`);
@@ -321,22 +402,37 @@ function loadAgentConfig() {
321
402
  });
322
403
  throw new Error(`agent.json at ${configFile} must include enabled as boolean.`);
323
404
  }
324
- _cachedAgentConfig = {
405
+ // Tolerate deprecated provider field for backward compatibility
406
+ const rawProvider = parsed.provider;
407
+ const provider = isValidProvider(rawProvider) ? rawProvider : undefined;
408
+ // Spread parsed first so any field present in AgentConfig is carried
409
+ // through by default, then explicitly override the fields that need
410
+ // validation or normalization. This eliminates the field-drop bug class
411
+ // that caused the `sync` block (and previously `shell`) to be silently
412
+ // omitted from the returned config. Regression-guarded by the
413
+ // Required<AgentConfig> contract test in identity-contract.test.ts.
414
+ const config = {
415
+ ...parsed,
325
416
  version,
326
417
  enabled,
327
- provider: rawProvider,
328
- context: parsed.context,
329
- logging: parsed.logging,
418
+ humanFacing,
419
+ agentFacing,
330
420
  senses: normalizeSenses(parsed.senses, configFile),
331
421
  phrases: parsed.phrases,
332
422
  };
423
+ if (provider !== undefined) {
424
+ config.provider = provider;
425
+ }
426
+ else {
427
+ delete config.provider;
428
+ }
333
429
  (0, runtime_1.emitNervesEvent)({
334
430
  event: "identity.resolve",
335
431
  component: "config/identity",
336
432
  message: "loaded agent config from disk",
337
433
  meta: { source: "disk" },
338
434
  });
339
- return _cachedAgentConfig;
435
+ return config;
340
436
  }
341
437
  /**
342
438
  * Prime the agent name cache explicitly.
@@ -356,11 +452,11 @@ function setAgentConfigOverride(config) {
356
452
  _agentConfigOverride = config;
357
453
  }
358
454
  /**
359
- * Clear only the cached agent config while preserving the resolved agent identity.
360
- * Used when a running agent should pick up updated disk-backed config on the next turn.
455
+ * Preserve the compatibility hook for callers that previously cleared cached
456
+ * disk-backed agent config. Agent config is now read fresh on every call.
361
457
  */
362
458
  function resetAgentConfigCache() {
363
- _cachedAgentConfig = null;
459
+ // No-op: disk-backed agent config is no longer memoized in-process.
364
460
  }
365
461
  /**
366
462
  * Clear all cached identity state.
@@ -368,6 +464,5 @@ function resetAgentConfigCache() {
368
464
  */
369
465
  function resetIdentity() {
370
466
  _cachedAgentName = null;
371
- _cachedAgentConfig = null;
372
467
  _agentConfigOverride = null;
373
468
  }