volute 0.53.0 → 0.54.0

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 (147) hide show
  1. package/dist/auto-upgrade-HEVZKPTF.js +46 -0
  2. package/dist/{backup-WWXVIMYQ.js → backup-QRNX6RK7.js} +11 -11
  3. package/dist/channels-CKCY64TD.js +203 -0
  4. package/dist/{chat-WK2BLM7B.js → chat-ZUGNL5GS.js} +9 -9
  5. package/dist/{chunk-UTKUO2KY.js → chunk-3LHUXY3E.js} +2 -2
  6. package/dist/{chunk-PIZDPY4G.js → chunk-444RR3YF.js} +4 -4
  7. package/dist/{chunk-VDZ4I4ZP.js → chunk-56IT2ZXF.js} +3 -3
  8. package/dist/{chunk-OXWUEU5V.js → chunk-5U5GLZSD.js} +2 -2
  9. package/dist/{chunk-LN7XJ56R.js → chunk-7XKPG66D.js} +9 -9
  10. package/dist/{chunk-R772ET2M.js → chunk-AAPNU7GA.js} +4 -0
  11. package/dist/{chunk-7ARONCZW.js → chunk-ATZF2RNJ.js} +3 -3
  12. package/dist/{chunk-6NLW72HP.js → chunk-CKPAVQNK.js} +1 -1
  13. package/dist/{chunk-RMADJFA7.js → chunk-CLCHOXLR.js} +1 -1
  14. package/dist/{chunk-IQ7VNWH6.js → chunk-HKGYZVWN.js} +1 -1
  15. package/dist/{chunk-HASADR3E.js → chunk-LGXVGIWN.js} +66 -25
  16. package/dist/{chunk-P2TBUKLW.js → chunk-LKUGUQUW.js} +3 -3
  17. package/dist/{chunk-AP2KQMMW.js → chunk-OAYY3WF3.js} +11 -3
  18. package/dist/{chunk-UO4MZQNO.js → chunk-OGPVJ53N.js} +14 -6
  19. package/dist/{chunk-M77B73VV.js → chunk-OIOW3FPT.js} +7 -2
  20. package/dist/chunk-OT5SXF7L.js +904 -0
  21. package/dist/{chunk-EDR47UE2.js → chunk-OYF25B62.js} +1 -1
  22. package/dist/{chunk-TAWRJ24T.js → chunk-PPSN2MLC.js} +2 -2
  23. package/dist/{chunk-5DBGQBQR.js → chunk-RGHF3OK5.js} +21 -10
  24. package/dist/{chunk-RQRO6PC7.js → chunk-VDUCLVZI.js} +305 -31
  25. package/dist/{chunk-23UJGVYP.js → chunk-WHL6PKYP.js} +10 -10
  26. package/dist/{chunk-HTB7KDRU.js → chunk-WZZCA23D.js} +5 -4
  27. package/dist/{chunk-UDZLPR34.js → chunk-YSRYCS3N.js} +13 -8
  28. package/dist/{chunk-5N32EN4O.js → chunk-Z4Q6TQWL.js} +1 -1
  29. package/dist/{chunk-BDHKCLWK.js → chunk-ZNHL5KQJ.js} +1 -1
  30. package/dist/cli.js +19 -19
  31. package/dist/{clock-SH4NQC2F.js → clock-X7V3C7NL.js} +3 -3
  32. package/dist/{cloud-sync-MJVJ33LD.js → cloud-sync-52YNJRMR.js} +11 -11
  33. package/dist/{daemon-restart-BIGU4OKS.js → daemon-restart-QWHN5VMU.js} +4 -4
  34. package/dist/daemon.js +330 -746
  35. package/dist/{db-IPXRJUI7.js → db-I4EH5SLF.js} +3 -1
  36. package/dist/{delivery-manager-FDHCZ7PU.js → delivery-manager-7R2YIQ2W.js} +11 -7
  37. package/dist/{delivery-notices-65TB3CBX.js → delivery-notices-RZQ6GONP.js} +3 -3
  38. package/dist/{delivery-router-RHANNTAC.js → delivery-router-QS4NLJR6.js} +3 -1
  39. package/dist/{down-QSNEMTTX.js → down-UN2EDX2Y.js} +3 -3
  40. package/dist/{echo-text-KU6G4Z7V.js → echo-text-73CYQRL7.js} +14 -14
  41. package/dist/{exec-ABD3DYA2.js → exec-Z34TTUO3.js} +1 -1
  42. package/dist/{extensions-VACUKFA5.js → extensions-QT65JGV6.js} +21 -11
  43. package/dist/{isolation-GVV2IBAU.js → isolation-UQPDO34R.js} +1 -1
  44. package/dist/{message-delivery-TUXM3AAE.js → message-delivery-TRKT4T2P.js} +11 -11
  45. package/dist/migrate-name-placeholder-C7NCNLWF.js +37 -0
  46. package/dist/{mind-IX5AWUST.js → mind-CT6ANXK4.js} +12 -12
  47. package/dist/{mind-contacts-BKUOUJPV.js → mind-contacts-PEXCDRXA.js} +8 -8
  48. package/dist/{mind-list-KNU34SUD.js → mind-list-7KBLPLES.js} +2 -2
  49. package/dist/{mind-service-WHFBUKZE.js → mind-service-7EFIJ3ZA.js} +11 -11
  50. package/dist/{mind-sleep-D3DEYAWG.js → mind-sleep-24HV4RCA.js} +5 -5
  51. package/dist/{mind-status-BPTLQ5Z6.js → mind-status-4YW4PHMO.js} +6 -3
  52. package/dist/{package-BN5KMU54.js → package-F6S5NHY2.js} +4 -4
  53. package/dist/{prompts-HNKGCAEY.js → prompts-JECJIFPQ.js} +1 -1
  54. package/dist/{scheduler-5X5UIQOQ.js → scheduler-73Q4MQ7Y.js} +6 -6
  55. package/dist/{seed-LHZ33UB4.js → seed-DRKAP3XV.js} +1 -1
  56. package/dist/{seed-cmd-U4RVJ3UA.js → seed-cmd-6IMTO3LG.js} +2 -2
  57. package/dist/{seed-create-OQU4KNCB.js → seed-create-VNLDYRFK.js} +1 -1
  58. package/dist/{seed-readiness-WJYYRRCK.js → seed-readiness-H5TTPAQH.js} +2 -2
  59. package/dist/{seed-sprout-SFUYH2RG.js → seed-sprout-PPGYGK4G.js} +8 -8
  60. package/dist/{send-FWZAMDBN.js → send-UXUQKO4N.js} +9 -9
  61. package/dist/{service-XQPMZAGI.js → service-T4P5W6RS.js} +2 -2
  62. package/dist/{service-install-2EWD7KXD.js → service-install-R4SNYUVO.js} +3 -3
  63. package/dist/{setup-RVSGCIF3.js → setup-YUAQMDVZ.js} +4 -4
  64. package/dist/skills/dreaming/SKILL.md +2 -2
  65. package/dist/skills/dreaming/references/INSTALL.md +1 -1
  66. package/dist/skills/tending/SKILL.md +2 -0
  67. package/dist/skills/volute-mind/references/integrations.md +3 -2
  68. package/dist/skills/volute-mind/references/routing.md +18 -5
  69. package/dist/{skills-QRPU6BWY.js → skills-GMQ5UIIW.js} +2 -2
  70. package/dist/{sleep-manager-NWUCRBZB.js → sleep-manager-KHI65FEX.js} +11 -11
  71. package/dist/{spirit-I5ECLGRI.js → spirit-Q5VGFWUI.js} +5 -3
  72. package/dist/{spirit-availability-NIUUYKU2.js → spirit-availability-G5FMWKRH.js} +12 -12
  73. package/dist/{sprout-A2PMEF7Z.js → sprout-PMTRL7QN.js} +1 -1
  74. package/dist/{src-LCSOQY6Z.js → src-3FIW7DLH.js} +241 -87
  75. package/dist/src-H3UCOP6B.js +516 -0
  76. package/dist/{src-HGNE2XG4.js → src-LTTQVN2Z.js} +1 -1
  77. package/dist/{status-EYG4A3OK.js → status-LCKTTIWS.js} +5 -5
  78. package/dist/{system-events-YTOU66QI.js → system-events-Q7IVZ5T4.js} +1 -1
  79. package/dist/{systems-2DIJY4RF.js → systems-HL7SGSW7.js} +6 -6
  80. package/dist/{turn-tracker-NNHS6MAR.js → turn-tracker-HZDPMSCC.js} +2 -2
  81. package/dist/{up-UGBHH743.js → up-XZDSJVMU.js} +3 -3
  82. package/dist/{update-CIWI2JYA.js → update-ILCPVNDD.js} +2 -2
  83. package/dist/{upgrade-LIE46UBB.js → upgrade-XY2J7NWZ.js} +9 -1
  84. package/dist/{variant-cleanup-CZDLIY3F.js → variant-cleanup-QHGGY7ND.js} +6 -6
  85. package/dist/{version-notify-SJVAQLZI.js → version-notify-VNVFX6UP.js} +19 -4
  86. package/dist/web-assets/assets/{index-b7G7ZsVk.js → index-CwtxGwe_.js} +16 -16
  87. package/dist/web-assets/assets/index-DhM1yYRN.css +1 -0
  88. package/dist/web-assets/index.html +2 -2
  89. package/package.json +4 -4
  90. package/packages/extensions/intentions/dist/ui/assets/index-3FneLCKR.css +1 -0
  91. package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +67 -0
  92. package/packages/extensions/{plan → intentions}/dist/ui/index.html +3 -3
  93. package/packages/extensions/intentions/skills/intention-review/SKILL.md +38 -0
  94. package/packages/extensions/intentions/skills/intentions/SKILL.md +49 -0
  95. package/packages/extensions/intentions/skills/intentions/scripts/intentions-hook.sh +45 -0
  96. package/packages/extensions/pages/skills/commons-gardening/SKILL.md +50 -0
  97. package/packages/extensions/pages/skills/pages/SKILL.md +18 -13
  98. package/templates/_base/.init/.config/prompts.json +2 -2
  99. package/templates/{pi → _base}/.init/.config/routes.json +1 -0
  100. package/templates/_base/.init/memory/dreams/.gitkeep +0 -0
  101. package/templates/_base/home/.config/routes.json +1 -1
  102. package/templates/_base/home/VOLUTE.md +1 -1
  103. package/templates/_base/src/lib/context-breakdown.ts +11 -3
  104. package/templates/_base/src/lib/routing.ts +2 -2
  105. package/templates/_base/src/lib/startup.ts +4 -2
  106. package/templates/claude/.init/CLAUDE.md +4 -0
  107. package/templates/claude/src/agent.ts +28 -12
  108. package/templates/claude/src/lib/message-channel.ts +43 -15
  109. package/templates/claude/src/lib/recover.ts +69 -0
  110. package/templates/claude/src/lib/stream-consumer.ts +23 -5
  111. package/templates/claude/volute-template.json +1 -1
  112. package/templates/codex/.init/AGENTS.md +4 -0
  113. package/templates/codex/volute-template.json +1 -1
  114. package/templates/pi/.init/MINDS.md +4 -0
  115. package/templates/pi/src/lib/mechanics-doc.ts +30 -0
  116. package/templates/pi/src/server.ts +3 -1
  117. package/templates/pi/volute-template.json +1 -1
  118. package/dist/channels-LW5ZLMSQ.js +0 -90
  119. package/dist/skills/plan-coordinator/SKILL.md +0 -60
  120. package/dist/src-UDMJZ6MH.js +0 -426
  121. package/dist/web-assets/assets/index-BHSU9r-4.css +0 -1
  122. package/packages/extensions/plan/dist/ui/assets/index-B8s8wxyt.js +0 -67
  123. package/packages/extensions/plan/dist/ui/assets/index-jIkrt-vI.css +0 -1
  124. package/packages/extensions/plan/skills/plan/SKILL.md +0 -43
  125. package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +0 -37
  126. package/templates/claude/.init/.config/routes.json +0 -11
  127. package/templates/codex/.init/.config/routes.json +0 -11
  128. package/dist/{accept-I4GVGWA3.js → accept-RSDIVJL6.js} +3 -3
  129. package/dist/{bridge-KU2IKSH3.js → bridge-YK7NTRU5.js} +3 -3
  130. package/dist/{create-C3XZACTV.js → create-M727VUDF.js} +3 -3
  131. package/dist/{env-BJGM6FBA.js → env-7AZFBPWX.js} +7 -7
  132. package/dist/{extension-B2W52WZY.js → extension-MRYJWSMV.js} +3 -3
  133. package/dist/{files-CHPNEQXN.js → files-PCKBQHAY.js} +3 -3
  134. package/dist/{list-R2GDWOEE.js → list-UQGIW7OF.js} +3 -3
  135. package/dist/{login-EZ4RRDQX.js → login-4NUS72Z5.js} +3 -3
  136. package/dist/{login-JDOAK465.js → login-57MMYILL.js} +4 -4
  137. package/dist/{logout-MWSIUOQU.js → logout-BYV433X6.js} +3 -3
  138. package/dist/{logout-K6ZGAJY5.js → logout-YFZAJRPY.js} +3 -3
  139. package/dist/{mind-history-RVF6KJ7K.js → mind-history-RZMMCHMX.js} +9 -9
  140. package/dist/{mind-wake-DCDFFQKX.js → mind-wake-LDGPRA42.js} +3 -3
  141. package/dist/{read-J5RM674N.js → read-RJ5NAW5J.js} +3 -3
  142. package/dist/{register-53LBGSDC.js → register-WNCSOTAU.js} +3 -3
  143. package/dist/{reject-K2A4UK2Y.js → reject-4NFLXKRN.js} +3 -3
  144. package/dist/{restart-R2WFNF5K.js → restart-B4GNMVF2.js} +7 -7
  145. package/dist/{skill-DXLLSUHB.js → skill-QYTBUDNQ.js} +7 -7
  146. package/dist/{start-XDOUAWN3.js → start-BDHJVOVX.js} +6 -6
  147. package/dist/{stop-O62RTEMD.js → stop-45QYSGYS.js} +7 -7
package/dist/daemon.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  readBackupState,
7
7
  resticVersion,
8
8
  runBackup
9
- } from "./chunk-EDR47UE2.js";
9
+ } from "./chunk-OYF25B62.js";
10
10
  import {
11
11
  acceptPending,
12
12
  formatFileSize,
@@ -15,15 +15,15 @@ import {
15
15
  stageFile,
16
16
  validateFilePath
17
17
  } from "./chunk-F6D766VQ.js";
18
+ import {
19
+ getMemoryStatus
20
+ } from "./chunk-5RBEEAKW.js";
18
21
  import {
19
22
  findOpenClawSession,
20
23
  importOpenClawConnectors,
21
24
  importPiSession,
22
25
  parseNameFromIdentity
23
26
  } from "./chunk-I7U5EEZC.js";
24
- import {
25
- getMemoryStatus
26
- } from "./chunk-5RBEEAKW.js";
27
27
  import {
28
28
  checkForUpdate,
29
29
  checkForUpdateCached,
@@ -32,13 +32,25 @@ import {
32
32
  import {
33
33
  SPIRIT_NOTICE_PREFIX,
34
34
  ensureSpiritAvailable
35
- } from "./chunk-P2TBUKLW.js";
35
+ } from "./chunk-LKUGUQUW.js";
36
36
  import {
37
- isHomeOnlyArchive
38
- } from "./chunk-FLIEXG2T.js";
39
- import {
40
- evaluateSeedChecklist
41
- } from "./chunk-RMADJFA7.js";
37
+ TEMPLATE_BRANCH,
38
+ UpgradeInProgressError,
39
+ VariantMergeError,
40
+ abortUpgrade,
41
+ configureGitIdentity,
42
+ continueUpgrade,
43
+ findUnresolvedHomeFiles,
44
+ formatUnresolvedHomeFilesMessage,
45
+ getUpgradeBlocked,
46
+ mergeVariantExcludingMemory,
47
+ npmInstallAsMind,
48
+ npmInstallNeeded,
49
+ runUpgrade,
50
+ upgradeDiff,
51
+ upgradeInProgress,
52
+ validateBranchName
53
+ } from "./chunk-OT5SXF7L.js";
42
54
  import {
43
55
  isTemplateStale
44
56
  } from "./chunk-CV6BNGFK.js";
@@ -47,14 +59,20 @@ import {
47
59
  } from "./chunk-HTRSSOHY.js";
48
60
  import {
49
61
  cleanupVariant
50
- } from "./chunk-UO4MZQNO.js";
62
+ } from "./chunk-OGPVJ53N.js";
63
+ import {
64
+ isHomeOnlyArchive
65
+ } from "./chunk-FLIEXG2T.js";
66
+ import {
67
+ evaluateSeedChecklist
68
+ } from "./chunk-CLCHOXLR.js";
51
69
  import {
52
70
  PLATFORMS,
53
71
  echoTextToChannel,
54
72
  fixModelEscapes,
55
73
  getPlatformDriver,
56
74
  routeOutboundBridge
57
- } from "./chunk-7ARONCZW.js";
75
+ } from "./chunk-ATZF2RNJ.js";
58
76
  import {
59
77
  getBridgeConfig,
60
78
  readBridgesConfig,
@@ -97,6 +115,7 @@ import {
97
115
  loadAllExtensions,
98
116
  notifyExtensionsDaemonStart,
99
117
  notifyExtensionsDaemonStop,
118
+ notifyExtensionsSpiritReady,
100
119
  readSystemsConfig,
101
120
  recordOutbound,
102
121
  requireAdmin,
@@ -109,11 +128,10 @@ import {
109
128
  uninstallNpmExtension,
110
129
  willGateMessage,
111
130
  writeSystemsConfig
112
- } from "./chunk-HASADR3E.js";
113
- import "./chunk-5DBGQBQR.js";
131
+ } from "./chunk-LGXVGIWN.js";
132
+ import "./chunk-RGHF3OK5.js";
114
133
  import {
115
134
  applyInitFiles,
116
- applyTemplateHomeFiles,
117
135
  composeTemplate,
118
136
  copyTemplateToDir,
119
137
  findTemplatesRoot,
@@ -123,11 +141,12 @@ import {
123
141
  import {
124
142
  getScheduler,
125
143
  initScheduler
126
- } from "./chunk-PIZDPY4G.js";
144
+ } from "./chunk-444RR3YF.js";
127
145
  import {
128
146
  recordDeliveryFailure
129
- } from "./chunk-UTKUO2KY.js";
147
+ } from "./chunk-3LHUXY3E.js";
130
148
  import {
149
+ UnknownChannelError,
131
150
  checkStaleSend,
132
151
  formatHoldNotice,
133
152
  getDeliveryManager,
@@ -135,7 +154,7 @@ import {
135
154
  initDeliveryManager,
136
155
  isConversationId,
137
156
  publishTypingForChannels
138
- } from "./chunk-RQRO6PC7.js";
157
+ } from "./chunk-VDUCLVZI.js";
139
158
  import {
140
159
  MindStartupError,
141
160
  RestartTracker,
@@ -145,10 +164,10 @@ import {
145
164
  initMindManager,
146
165
  syncProviderToMinds,
147
166
  tryGetMindManager
148
- } from "./chunk-23UJGVYP.js";
167
+ } from "./chunk-WHL6PKYP.js";
149
168
  import {
150
169
  extractTextContent
151
- } from "./chunk-UDZLPR34.js";
170
+ } from "./chunk-YSRYCS3N.js";
152
171
  import {
153
172
  SYSTEM_MIND,
154
173
  assignSession,
@@ -170,7 +189,7 @@ import {
170
189
  takeErrored,
171
190
  trackToolUse,
172
191
  utcDateTimeStr
173
- } from "./chunk-VDZ4I4ZP.js";
192
+ } from "./chunk-56IT2ZXF.js";
174
193
  import {
175
194
  SEED_SKILLS,
176
195
  STANDARD_SKILLS,
@@ -184,7 +203,6 @@ import {
184
203
  listFilesRecursive,
185
204
  listMindSkills,
186
205
  listSharedSkills,
187
- migrateSkillsToTemplate,
188
206
  mindSkillsDir,
189
207
  publishSkill,
190
208
  removeSharedSkill,
@@ -192,7 +210,7 @@ import {
192
210
  syncBuiltinSkills,
193
211
  uninstallSkill,
194
212
  updateSkill
195
- } from "./chunk-TAWRJ24T.js";
213
+ } from "./chunk-PPSN2MLC.js";
196
214
  import {
197
215
  approveUser,
198
216
  changePassword,
@@ -229,7 +247,7 @@ import {
229
247
  listEvents,
230
248
  parseMeta,
231
249
  recordNotice
232
- } from "./chunk-IQ7VNWH6.js";
250
+ } from "./chunk-HKGYZVWN.js";
233
251
  import {
234
252
  publish as publish2,
235
253
  subscribe as subscribe2,
@@ -242,7 +260,7 @@ import {
242
260
  getPrompt,
243
261
  getPromptIfCustom,
244
262
  substitute
245
- } from "./chunk-AP2KQMMW.js";
263
+ } from "./chunk-OAYY3WF3.js";
246
264
  import {
247
265
  isSandboxEnabled,
248
266
  wrapForSandbox
@@ -305,7 +323,7 @@ import {
305
323
  readVoluteConfig,
306
324
  writeVoluteConfig
307
325
  } from "./chunk-WCFSBH33.js";
308
- import "./chunk-6NLW72HP.js";
326
+ import "./chunk-CKPAVQNK.js";
309
327
  import {
310
328
  chownMindDir,
311
329
  chownMindFile,
@@ -317,7 +335,7 @@ import {
317
335
  isIsolationEnabled,
318
336
  resolveVoluteBin,
319
337
  wrapForIsolation
320
- } from "./chunk-M77B73VV.js";
338
+ } from "./chunk-OIOW3FPT.js";
321
339
  import {
322
340
  loadMergedEnv,
323
341
  mindEnvPath,
@@ -382,7 +400,6 @@ import {
382
400
  resolveMindDir,
383
401
  setMindRunning,
384
402
  setMindStage,
385
- setMindTemplate,
386
403
  setMindTemplateHash,
387
404
  stateDir,
388
405
  validateMindName,
@@ -409,7 +426,7 @@ import "./chunk-K3NQKI34.js";
409
426
  import { randomBytes as randomBytes3 } from "crypto";
410
427
  import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "fs";
411
428
  import { homedir as homedir3 } from "os";
412
- import { resolve as resolve20 } from "path";
429
+ import { resolve as resolve18 } from "path";
413
430
  import { format } from "util";
414
431
 
415
432
  // packages/daemon/src/lib/daemon/backup-manager.ts
@@ -520,7 +537,7 @@ var BackupManager = class {
520
537
  } catch (pubErr) {
521
538
  blog.error("failed to publish backup-failure activity", logger_default.errorData(pubErr));
522
539
  }
523
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
540
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-Q7IVZ5T4.js");
524
541
  await deliverEvent2(getSpiritName(), {
525
542
  type: "notice",
526
543
  meta: { subtype: "backup" },
@@ -744,8 +761,8 @@ var BridgeManager = class {
744
761
  if (!tracked) return;
745
762
  this.stopping.add(platform);
746
763
  this.bridges.delete(platform);
747
- await new Promise((resolve21) => {
748
- tracked.child.on("exit", () => resolve21());
764
+ await new Promise((resolve19) => {
765
+ tracked.child.on("exit", () => resolve19());
749
766
  try {
750
767
  if (tracked.child.pid) {
751
768
  process.kill(-tracked.child.pid, "SIGTERM");
@@ -756,7 +773,7 @@ var BridgeManager = class {
756
773
  if (err instanceof Error && err.code !== "ESRCH") {
757
774
  blog2.warn(`failed to stop bridge ${platform}`, logger_default.errorData(err));
758
775
  }
759
- resolve21();
776
+ resolve19();
760
777
  }
761
778
  setTimeout(() => {
762
779
  try {
@@ -767,7 +784,7 @@ var BridgeManager = class {
767
784
  }
768
785
  } catch {
769
786
  }
770
- resolve21();
787
+ resolve19();
771
788
  }, 5e3);
772
789
  });
773
790
  this.stopping.delete(platform);
@@ -1444,10 +1461,10 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1444
1461
  stream.writeSSE({ data: JSON.stringify(entry) }).catch(() => {
1445
1462
  });
1446
1463
  });
1447
- await new Promise((resolve21) => {
1464
+ await new Promise((resolve19) => {
1448
1465
  stream.onAbort(() => {
1449
1466
  unsubscribe();
1450
- resolve21();
1467
+ resolve19();
1451
1468
  });
1452
1469
  });
1453
1470
  });
@@ -1472,7 +1489,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1472
1489
  config2.name = name.trim() || void 0;
1473
1490
  writeGlobalConfig(config2);
1474
1491
  if (config2.name !== previousName) {
1475
- const { notifySpiritSystemChange } = await import("./spirit-I5ECLGRI.js");
1492
+ const { notifySpiritSystemChange } = await import("./spirit-Q5VGFWUI.js");
1476
1493
  await notifySpiritSystemChange();
1477
1494
  }
1478
1495
  return c.json({ name: config2.name ?? null });
@@ -1831,8 +1848,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1831
1848
  createdAt: Date.now()
1832
1849
  };
1833
1850
  oauthFlows.set(flowId, flow);
1834
- const promptPromise = needsManualCode ? new Promise((resolve21) => {
1835
- flow.resolveCode = resolve21;
1851
+ const promptPromise = needsManualCode ? new Promise((resolve19) => {
1852
+ flow.resolveCode = resolve19;
1836
1853
  }) : void 0;
1837
1854
  oauthProvider.login({
1838
1855
  onAuth: (info) => {
@@ -1871,7 +1888,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1871
1888
  existing.error = err instanceof Error ? err.message : String(err);
1872
1889
  }
1873
1890
  });
1874
- await new Promise((resolve21) => setTimeout(resolve21, 2e3));
1891
+ await new Promise((resolve19) => setTimeout(resolve19, 2e3));
1875
1892
  const state = oauthFlows.get(flowId);
1876
1893
  return c.json({
1877
1894
  flowId,
@@ -2132,8 +2149,8 @@ var app2 = new Hono2().get("/events", async (c) => {
2132
2149
  });
2133
2150
  }, 15e3);
2134
2151
  cleanups.push(() => clearInterval(keepAlive));
2135
- await new Promise((resolve21) => {
2136
- stream.onAbort(() => resolve21());
2152
+ await new Promise((resolve19) => {
2153
+ stream.onAbort(() => resolve19());
2137
2154
  });
2138
2155
  } finally {
2139
2156
  for (const cleanup of cleanups) {
@@ -2714,7 +2731,7 @@ async function fanOutToMinds(opts) {
2714
2731
  );
2715
2732
  }
2716
2733
  if (ap.userType === "system") {
2717
- import("./spirit-availability-NIUUYKU2.js").then(({ ensureSpiritAvailable: ensureSpiritAvailable2 }) => ensureSpiritAvailable2()).catch((err) => logger_default.warn("fan-out: on-demand spirit start failed", logger_default.errorData(err)));
2734
+ import("./spirit-availability-G5FMWKRH.js").then(({ ensureSpiritAvailable: ensureSpiritAvailable2 }) => ensureSpiritAvailable2()).catch((err) => logger_default.warn("fan-out: on-demand spirit start failed", logger_default.errorData(err)));
2718
2735
  }
2719
2736
  }
2720
2737
  return null;
@@ -3131,11 +3148,11 @@ async function notifyMind(mindName, message) {
3131
3148
  const entry = await findMind(mindName);
3132
3149
  if (!entry) return false;
3133
3150
  try {
3134
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
3151
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-Q7IVZ5T4.js");
3135
3152
  const result = await deliverEvent2(mindName, { type: "file-share", body: message });
3136
3153
  if (result.delivered) return true;
3137
3154
  if (result.id == null) return false;
3138
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
3155
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
3139
3156
  const { getBaseName: getBaseName2 } = await import("./registry-TRC2HJXR.js");
3140
3157
  return getSleepManagerIfReady2()?.isSleeping(await getBaseName2(mindName)) ?? false;
3141
3158
  } catch (err) {
@@ -4108,9 +4125,9 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
4108
4125
  stream.onAbort(() => {
4109
4126
  tail.kill();
4110
4127
  });
4111
- await new Promise((resolve21) => {
4112
- tail.on("exit", resolve21);
4113
- stream.onAbort(resolve21);
4128
+ await new Promise((resolve19) => {
4129
+ tail.on("exit", resolve19);
4130
+ stream.onAbort(resolve19);
4114
4131
  });
4115
4132
  });
4116
4133
  }).get("/:name/logs/tail", requireSelf(), async (c) => {
@@ -4128,8 +4145,8 @@ var app11 = new Hono14().get("/:name/logs", requireSelf(), async (c) => {
4128
4145
  tail.stdout.on("data", (data) => {
4129
4146
  output += data.toString();
4130
4147
  });
4131
- await new Promise((resolve21) => {
4132
- tail.on("exit", resolve21);
4148
+ await new Promise((resolve19) => {
4149
+ tail.on("exit", resolve19);
4133
4150
  });
4134
4151
  return c.text(output);
4135
4152
  });
@@ -4222,14 +4239,14 @@ var mind_skills_default = app12;
4222
4239
  // packages/daemon/src/web/api/minds.ts
4223
4240
  import {
4224
4241
  cpSync,
4225
- existsSync as existsSync8,
4242
+ existsSync as existsSync7,
4226
4243
  mkdirSync as mkdirSync6,
4227
4244
  readdirSync as readdirSync2,
4228
4245
  readFileSync as readFileSync9,
4229
4246
  rmSync as rmSync3,
4230
4247
  writeFileSync as writeFileSync8
4231
4248
  } from "fs";
4232
- import { relative, resolve as resolve13 } from "path";
4249
+ import { relative, resolve as resolve11 } from "path";
4233
4250
  import { zValidator as zValidator6 } from "@hono/zod-validator";
4234
4251
  import { and as and5, desc as desc3, eq as eq5, sql as sql3 } from "drizzle-orm";
4235
4252
  import { Hono as Hono16 } from "hono";
@@ -4672,49 +4689,6 @@ async function commitSrcChanges(dir, mindName) {
4672
4689
  glog.info(`committed known-good src changes (${dir})`);
4673
4690
  }
4674
4691
 
4675
- // packages/daemon/src/lib/mind/npm-install.ts
4676
- import { existsSync as existsSync7 } from "fs";
4677
- import { resolve as resolve10 } from "path";
4678
- var NPM_INSTALL_ARGS = [
4679
- "install",
4680
- "--no-audit",
4681
- "--no-fund",
4682
- "--prefer-offline",
4683
- "--loglevel=error"
4684
- ];
4685
- function lowPriorityArgv(cmd, args, ionice) {
4686
- return ionice ? ["ionice", ["-c2", "-n7", "nice", "-n19", cmd, ...args]] : ["nice", ["-n19", cmd, ...args]];
4687
- }
4688
- function hasIonice() {
4689
- return process.platform === "linux" && (existsSync7("/usr/bin/ionice") || existsSync7("/bin/ionice"));
4690
- }
4691
- async function npmInstallAsMind(cwd, mindName) {
4692
- const [cmd, args] = lowPriorityArgv("npm", NPM_INSTALL_ARGS, hasIonice());
4693
- if (isIsolationEnabled()) {
4694
- const [wrappedCmd, wrappedArgs] = await wrapForIsolation(cmd, args, mindName);
4695
- await exec(wrappedCmd, wrappedArgs, {
4696
- cwd,
4697
- env: { ...process.env, HOME: resolve10(cwd, "home") }
4698
- });
4699
- } else {
4700
- await exec(cmd, args, { cwd });
4701
- }
4702
- }
4703
- async function depsChangedSince(dir, fromRef) {
4704
- try {
4705
- await gitExec(["diff", "--quiet", fromRef, "HEAD", "--", "package.json", "package-lock.json"], {
4706
- cwd: dir
4707
- });
4708
- return false;
4709
- } catch {
4710
- return true;
4711
- }
4712
- }
4713
- async function npmInstallNeeded(dir, preMergeRef) {
4714
- if (!existsSync7(resolve10(dir, "node_modules"))) return true;
4715
- return depsChangedSince(dir, preMergeRef);
4716
- }
4717
-
4718
4692
  // packages/daemon/src/lib/mind/thinking-config.ts
4719
4693
  var CLAUDE_EFFORT = {
4720
4694
  minimal: "low",
@@ -4756,150 +4730,6 @@ function deriveThinkingLevel(config2) {
4756
4730
  return null;
4757
4731
  }
4758
4732
 
4759
- // packages/daemon/src/lib/mind/variants.ts
4760
- import { statSync as statSync3 } from "fs";
4761
- import { resolve as resolve11 } from "path";
4762
- var SAFE_BRANCH_RE = /^[a-zA-Z0-9._\-/]+$/;
4763
- function validateBranchName(branch) {
4764
- if (!SAFE_BRANCH_RE.test(branch)) {
4765
- return `Invalid branch name: ${branch}. Only alphanumeric, '.', '_', '-', '/' allowed.`;
4766
- }
4767
- if (branch.includes("..")) {
4768
- return `Invalid branch name: ${branch}. '..' not allowed.`;
4769
- }
4770
- return null;
4771
- }
4772
- var MERGE_EXCLUDED_PATHS = ["home/MEMORY.md", "home/memory/journal/"];
4773
- var MAX_DELTA_CHARS = 12e3;
4774
- var NEVER_REPORT_PREFIXES = ["home/.claude/", "home/.pi/", "home/.agents/"];
4775
- var MAX_LISTED_UNRESOLVED_FILES = 20;
4776
- async function findUnresolvedHomeFiles(cwd) {
4777
- const raw = await gitExec(
4778
- ["ls-files", "--others", "--ignored", "--exclude-standard", "-z", "--", "home"],
4779
- { cwd }
4780
- );
4781
- const allPaths = raw.split("\0").filter((path) => path && !NEVER_REPORT_PREFIXES.some((prefix) => path.startsWith(prefix)));
4782
- const files = [];
4783
- let totalBytes = 0;
4784
- for (const path of allPaths) {
4785
- let bytes = -1;
4786
- try {
4787
- bytes = statSync3(resolve11(cwd, path)).size;
4788
- } catch {
4789
- }
4790
- if (bytes > 0) totalBytes += bytes;
4791
- if (files.length < MAX_LISTED_UNRESOLVED_FILES) files.push({ path, bytes });
4792
- }
4793
- return { files, totalCount: allPaths.length, totalBytes };
4794
- }
4795
- function formatBytes(bytes) {
4796
- if (bytes < 0) return "size unknown";
4797
- if (bytes < 1024) return `${bytes} B`;
4798
- const units = ["KB", "MB", "GB", "TB"];
4799
- let value = bytes / 1024;
4800
- for (const unit of units) {
4801
- if (value < 1024) return `${value.toFixed(1)} ${unit}`;
4802
- value /= 1024;
4803
- }
4804
- return `${value.toFixed(1)} PB`;
4805
- }
4806
- function formatUnresolvedHomeFilesMessage(variantName, result) {
4807
- const lines = result.files.map(
4808
- (f) => ` - ${f.path.replace(/^home\//, "")} (${formatBytes(f.bytes)})`
4809
- );
4810
- const remaining = result.totalCount - result.files.length;
4811
- if (remaining > 0) lines.push(` ...and ${remaining} more`);
4812
- return `Cannot join variant "${variantName}": it has ${result.totalCount} untracked file${result.totalCount === 1 ? "" : "s"} under home/ that .gitignore is hiding from git \u2014 never committed, and joining would destroy them when the variant is cleaned up (total: ${formatBytes(result.totalBytes)}):
4813
-
4814
- ${lines.join("\n")}
4815
-
4816
- Before retrying the join, resolve each file in the variant \u2014 one of:
4817
- 1. Track it: git add -f -- <path> (then commit it, or let auto-commit pick it up next turn)
4818
- 2. Copy it out of home/ to somewhere safe, then delete it
4819
- 3. Delete it if it's disposable
4820
-
4821
- Once resolved, retry the join. To join anyway and discard everything listed above, pass discardUnresolved: true.`;
4822
- }
4823
- async function mergeVariantExcludingMemory(projectRoot, variantBranch) {
4824
- const opts = { cwd: projectRoot };
4825
- let memoryDelta = "";
4826
- try {
4827
- const base = (await gitExec(["merge-base", "HEAD", variantBranch], opts)).trim();
4828
- memoryDelta = (await gitExec(["diff", `${base}..${variantBranch}`, "--", ...MERGE_EXCLUDED_PATHS], opts)).trim();
4829
- } catch (err) {
4830
- logger_default.error(
4831
- `variant join: failed to compute memory delta for ${variantBranch}`,
4832
- logger_default.errorData(err)
4833
- );
4834
- memoryDelta = `(journal delta unavailable \u2014 ${err instanceof Error ? err.message : String(err)})`;
4835
- }
4836
- if (memoryDelta.length > MAX_DELTA_CHARS) {
4837
- memoryDelta = `${memoryDelta.slice(0, MAX_DELTA_CHARS)}
4838
- \u2026 (delta truncated)`;
4839
- }
4840
- try {
4841
- await gitExec(["merge", "--no-ff", "--no-commit", variantBranch], opts).catch(() => {
4842
- });
4843
- await gitExec(["reset", "-q", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4844
- for (const path of MERGE_EXCLUDED_PATHS) {
4845
- await gitExec(["checkout", "--", path], opts).catch(() => {
4846
- });
4847
- }
4848
- await gitExec(["clean", "-fdq", "--", ...MERGE_EXCLUDED_PATHS], opts);
4849
- await assertExcludedPathsRestored(opts);
4850
- if (await mergeInProgress(opts)) {
4851
- await gitExec(["commit", "--no-edit"], opts);
4852
- }
4853
- } catch (err) {
4854
- const conflicts = await listConflicts(opts);
4855
- const abortFailed = await gitExec(["merge", "--abort"], opts).then(
4856
- () => false,
4857
- () => true
4858
- );
4859
- throw new VariantMergeError(
4860
- `variant join aborted: ${err instanceof Error ? err.message : String(err)}`,
4861
- conflicts,
4862
- abortFailed
4863
- );
4864
- }
4865
- return memoryDelta;
4866
- }
4867
- var VariantMergeError = class extends Error {
4868
- constructor(message, conflicts, abortFailed = false) {
4869
- super(message);
4870
- this.conflicts = conflicts;
4871
- this.abortFailed = abortFailed;
4872
- this.name = "VariantMergeError";
4873
- }
4874
- };
4875
- async function mergeInProgress(opts) {
4876
- return gitExec(["rev-parse", "-q", "--verify", "MERGE_HEAD"], opts).then(
4877
- () => true,
4878
- () => false
4879
- );
4880
- }
4881
- async function listConflicts(opts) {
4882
- try {
4883
- const out = (await gitExec(["diff", "--name-only", "--diff-filter=U"], opts)).trim();
4884
- return out ? out.split("\n") : [];
4885
- } catch {
4886
- return [];
4887
- }
4888
- }
4889
- async function assertExcludedPathsRestored(opts) {
4890
- await gitExec(["diff", "--cached", "--quiet", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4891
- await gitExec(["diff", "--quiet", "HEAD", "--", ...MERGE_EXCLUDED_PATHS], opts);
4892
- const untracked = (await gitExec(
4893
- ["ls-files", "--others", "--exclude-standard", "--", ...MERGE_EXCLUDED_PATHS],
4894
- opts
4895
- )).trim();
4896
- if (untracked) {
4897
- throw new Error(
4898
- `untracked memory files remain after restore: ${untracked.replace(/\n/g, ", ")}`
4899
- );
4900
- }
4901
- }
4902
-
4903
4733
  // packages/daemon/src/lib/services/imagegen-jobs.ts
4904
4734
  import { mkdir, writeFile } from "fs/promises";
4905
4735
  import { dirname as dirname2 } from "path";
@@ -5022,7 +4852,7 @@ async function waitForImagegenJob(mind, id, timeoutMs) {
5022
4852
  import { randomUUID } from "crypto";
5023
4853
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
5024
4854
  import { homedir } from "os";
5025
- import { resolve as resolve12 } from "path";
4855
+ import { resolve as resolve10 } from "path";
5026
4856
  function convertSession(opts) {
5027
4857
  const lines = readFileSync8(opts.sessionPath, "utf-8").trim().split("\n");
5028
4858
  const sessionId = randomUUID();
@@ -5138,9 +4968,9 @@ function convertSession(opts) {
5138
4968
  }
5139
4969
  }
5140
4970
  const projectId = opts.projectDir.replace(/\//g, "-");
5141
- const sdkDir = resolve12(homedir(), ".claude", "projects", projectId);
4971
+ const sdkDir = resolve10(homedir(), ".claude", "projects", projectId);
5142
4972
  mkdirSync5(sdkDir, { recursive: true });
5143
- const sdkPath = resolve12(sdkDir, `${sessionId}.jsonl`);
4973
+ const sdkPath = resolve10(sdkDir, `${sessionId}.jsonl`);
5144
4974
  writeFileSync7(sdkPath, `${sdkEvents.join("\n")}
5145
4975
  `);
5146
4976
  console.log(`Converted ${sdkEvents.length} messages \u2192 ${sdkPath}`);
@@ -5201,7 +5031,7 @@ async function getMindStatus(name, port, registryRunning, seed) {
5201
5031
  let status = "stopped";
5202
5032
  let wakeAt = null;
5203
5033
  try {
5204
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
5034
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
5205
5035
  const sleepManager = getSleepManagerIfReady2();
5206
5036
  if (sleepManager?.isSleeping(name)) {
5207
5037
  status = "sleeping";
@@ -5265,13 +5095,6 @@ function toPublicMind(entry, status, extras) {
5265
5095
  lastActiveAt: extras.lastActiveAt ?? null
5266
5096
  };
5267
5097
  }
5268
- var TEMPLATE_BRANCH = "volute/template";
5269
- async function configureGitIdentity(mindName, opts) {
5270
- const systemsConfig = readSystemsConfig();
5271
- const system = systemsConfig?.system ?? "local";
5272
- await gitExec(["config", "user.name", mindName], opts);
5273
- await gitExec(["config", "user.email", `${mindName}.${system}@volute.systems`], opts);
5274
- }
5275
5098
  async function initTemplateBranch(projectRoot, composedDir, manifest, mindName, env) {
5276
5099
  const templateFiles = listFiles(composedDir).filter((f) => !f.startsWith(".init/") && !f.startsWith(".init\\")).filter((f) => !f.startsWith("home/") && !f.startsWith("home\\") || f === "home/VOLUTE.md").map((f) => manifest.rename[f] ?? f);
5277
5100
  const opts = { cwd: projectRoot, mindName, env };
@@ -5282,164 +5105,9 @@ async function initTemplateBranch(projectRoot, composedDir, manifest, mindName,
5282
5105
  await gitExec(["add", "-A"], opts);
5283
5106
  await gitExec(["commit", "-m", "initial commit"], opts);
5284
5107
  }
5285
- async function updateTemplateBranch(projectRoot, template, mindName) {
5286
- const tempWorktree = resolve13(projectRoot, ".variants", "_template_update");
5287
- let branchExists = false;
5288
- try {
5289
- await gitExec(["rev-parse", "--verify", TEMPLATE_BRANCH], { cwd: projectRoot });
5290
- branchExists = true;
5291
- } catch {
5292
- }
5293
- try {
5294
- await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
5295
- } catch {
5296
- }
5297
- if (existsSync8(tempWorktree)) {
5298
- rmSync3(tempWorktree, { recursive: true, force: true });
5299
- }
5300
- const templatesRoot = findTemplatesRoot();
5301
- const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5302
- try {
5303
- if (branchExists) {
5304
- await gitExec(["worktree", "add", tempWorktree, TEMPLATE_BRANCH], {
5305
- cwd: projectRoot
5306
- });
5307
- } else {
5308
- await gitExec(["worktree", "add", "--detach", tempWorktree], { cwd: projectRoot });
5309
- await gitExec(["checkout", "--orphan", TEMPLATE_BRANCH], { cwd: tempWorktree });
5310
- await gitExec(["rm", "-rf", "--cached", "."], { cwd: tempWorktree });
5311
- await gitExec(["clean", "-fd"], { cwd: tempWorktree });
5312
- }
5313
- if (branchExists) {
5314
- await gitExec(["rm", "-rf", "."], { cwd: tempWorktree }).catch(() => {
5315
- });
5316
- }
5317
- copyTemplateToDir(composedDir, tempWorktree, mindName, manifest);
5318
- const initDir = resolve13(tempWorktree, ".init");
5319
- if (existsSync8(initDir)) {
5320
- rmSync3(initDir, { recursive: true, force: true });
5321
- }
5322
- const homeDir = resolve13(tempWorktree, "home");
5323
- if (existsSync8(homeDir)) {
5324
- for (const entry of readdirSync2(homeDir)) {
5325
- if (entry !== "VOLUTE.md") {
5326
- rmSync3(resolve13(homeDir, entry), { recursive: true, force: true });
5327
- }
5328
- }
5329
- }
5330
- await gitExec(["add", "-A"], { cwd: tempWorktree });
5331
- try {
5332
- await gitExec(["diff", "--cached", "--quiet"], { cwd: tempWorktree });
5333
- } catch {
5334
- await gitExec(["commit", "-m", "template update"], { cwd: tempWorktree });
5335
- }
5336
- } finally {
5337
- try {
5338
- await gitExec(["worktree", "remove", "--force", tempWorktree], { cwd: projectRoot });
5339
- } catch {
5340
- }
5341
- if (existsSync8(tempWorktree)) {
5342
- rmSync3(tempWorktree, { recursive: true, force: true });
5343
- }
5344
- rmSync3(composedDir, { recursive: true, force: true });
5345
- }
5346
- }
5347
- async function mergeTemplateBranch(worktreeDir) {
5348
- try {
5349
- await gitExec(
5350
- ["merge", TEMPLATE_BRANCH, "--allow-unrelated-histories", "-m", "merge template update"],
5351
- { cwd: worktreeDir }
5352
- );
5353
- return false;
5354
- } catch (e) {
5355
- try {
5356
- const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
5357
- const hasConflictMarkers = status.split("\n").some((line) => line.startsWith("UU") || line.startsWith("AA"));
5358
- if (hasConflictMarkers) return true;
5359
- } catch {
5360
- }
5361
- throw e;
5362
- }
5363
- }
5364
- async function mergeUpgradeAndRestart(mindName, dir, worktreeDir, upgradeVariantName, upgradeBranch, template, oldTemplate) {
5365
- const templateChanged = template !== oldTemplate;
5366
- const mainStatus = (await gitExec(["status", "--porcelain"], { cwd: dir })).trim();
5367
- if (mainStatus) {
5368
- await gitExec(["add", "-A"], { cwd: dir });
5369
- await gitExec(["commit", "-m", "Auto-commit before upgrade merge"], { cwd: dir });
5370
- }
5371
- const preMergeHead = (await gitExec(["rev-parse", "HEAD"], { cwd: dir })).trim();
5372
- await gitExec(["merge", upgradeBranch], { cwd: dir });
5373
- try {
5374
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir);
5375
- } catch (err) {
5376
- logger_default.warn(`failed to clean up upgrade worktree for ${mindName}`, logger_default.errorData(err));
5377
- }
5378
- try {
5379
- await gitExec(["branch", "-D", upgradeBranch], { cwd: dir });
5380
- } catch {
5381
- }
5382
- let switchWarning;
5383
- if (templateChanged) {
5384
- try {
5385
- applyTemplateHomeFiles(resolve13(dir, "home"), template);
5386
- const migratedSkills = migrateSkillsToTemplate(dir, oldTemplate, template);
5387
- await gitExec(["add", "home/"], { cwd: dir });
5388
- try {
5389
- await gitExec(["diff", "--cached", "--quiet"], { cwd: dir });
5390
- } catch {
5391
- await gitExec(["commit", "-m", `swap template-owned home files for ${template}`], {
5392
- cwd: dir
5393
- });
5394
- }
5395
- await chownMindDir(dir, mindName);
5396
- const skillNote = migratedSkills.length > 0 ? ` Migrated skills to the ${template} skills dir: ${migratedSkills.join(", ")}.` : "";
5397
- switchWarning = `Switched ${oldTemplate}\u2192${template}: config reset to ${template} defaults, mechanics doc replaced, conversation starts fresh (sessions aren't portable across runtimes).${skillNote}`;
5398
- } catch (err) {
5399
- logger_default.warn(`failed to swap template home files for ${mindName}`, logger_default.errorData(err));
5400
- return {
5401
- ok: true,
5402
- warning: `Upgrade merged but template switch ${oldTemplate}\u2192${template} failed: ${err instanceof Error ? err.message : String(err)}. The mind is still registered as ${oldTemplate}; re-run the switch or fix home/ manually.`
5403
- };
5404
- }
5405
- }
5406
- try {
5407
- await setMindTemplateHash(mindName, computeTemplateHash(template));
5408
- await setMindTemplate(mindName, template);
5409
- } catch (err) {
5410
- logger_default.warn(`failed to update template for ${mindName}`, logger_default.errorData(err));
5411
- }
5412
- if (await npmInstallNeeded(dir, preMergeHead)) {
5413
- try {
5414
- await npmInstallAsMind(dir, mindName);
5415
- } catch (err) {
5416
- logger_default.warn(`npm install failed after upgrade merge for ${mindName}`, logger_default.errorData(err));
5417
- return {
5418
- ok: true,
5419
- warning: `Upgrade merged but npm install failed: ${err instanceof Error ? err.message : String(err)}. You may need to run npm install manually.`
5420
- };
5421
- }
5422
- } else {
5423
- logger_default.info(`skipping npm install for ${mindName} \u2014 dependencies unchanged by upgrade`);
5424
- }
5425
- const manager = getMindManager();
5426
- try {
5427
- if (manager.isRunning(mindName)) {
5428
- await manager.stopMind(mindName);
5429
- }
5430
- manager.setPendingContext(mindName, { type: "upgraded" });
5431
- await manager.startMind(mindName, { healthTimeoutMs: 12e4 });
5432
- } catch (e) {
5433
- return {
5434
- ok: true,
5435
- warning: `Upgrade merged but mind restart failed: ${e instanceof Error ? e.message : String(e)}`
5436
- };
5437
- }
5438
- return { ok: true, warning: switchWarning };
5439
- }
5440
5108
  async function importFromArchive(c, tempDir, nameOverride, manifest) {
5441
- const extractedMindDir = resolve13(tempDir, "mind");
5442
- if (!existsSync8(extractedMindDir)) {
5109
+ const extractedMindDir = resolve11(tempDir, "mind");
5110
+ if (!existsSync7(extractedMindDir)) {
5443
5111
  return c.json({ error: "Invalid archive: missing mind/ directory" }, 400);
5444
5112
  }
5445
5113
  if (!manifest?.includes || !manifest.name || !manifest.template) {
@@ -5457,7 +5125,7 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5457
5125
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5458
5126
  ensureVoluteHome();
5459
5127
  const dest = mindDir(name);
5460
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5128
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5461
5129
  try {
5462
5130
  cpSync(extractedMindDir, dest, { recursive: true });
5463
5131
  if (!manifest.includes.identity) {
@@ -5465,9 +5133,9 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5465
5133
  }
5466
5134
  const state = stateDir(name);
5467
5135
  mkdirSync6(state, { recursive: true });
5468
- const envJson = resolve13(tempDir, "state/env.json");
5469
- if (existsSync8(envJson)) {
5470
- cpSync(envJson, resolve13(state, "env.json"));
5136
+ const envJson = resolve11(tempDir, "state/env.json");
5137
+ if (existsSync7(envJson)) {
5138
+ cpSync(envJson, resolve11(state, "env.json"));
5471
5139
  }
5472
5140
  const port = await nextPort();
5473
5141
  await addMind(name, port, manifest.stage, manifest.template);
@@ -5476,30 +5144,30 @@ async function importFromFullArchive(c, tempDir, extractedMindDir, nameOverride,
5476
5144
  } catch (err) {
5477
5145
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5478
5146
  }
5479
- const homeDir = resolve13(dest, "home");
5147
+ const homeDir = resolve11(dest, "home");
5480
5148
  ensureVoluteGroup();
5481
5149
  createMindUser(name, homeDir);
5482
5150
  await chownMindDir(dest, name);
5483
5151
  await npmInstallAsMind(dest, name);
5484
5152
  await importHistoryFromArchive(name, tempDir);
5485
5153
  importSessionsFromArchive(dest, tempDir);
5486
- if (!existsSync8(resolve13(dest, ".git"))) {
5154
+ if (!existsSync7(resolve11(dest, ".git"))) {
5487
5155
  try {
5488
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
5156
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
5489
5157
  await gitExec(["init"], { cwd: dest, mindName: name, env });
5490
5158
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
5491
5159
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
5492
5160
  await gitExec(["commit", "-m", "import from archive"], { cwd: dest, mindName: name, env });
5493
5161
  } catch (err) {
5494
5162
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5495
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5163
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5496
5164
  }
5497
5165
  }
5498
5166
  await chownMindDir(dest, name);
5499
5167
  rmSync3(tempDir, { recursive: true, force: true });
5500
5168
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
5501
5169
  } catch (err) {
5502
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5170
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5503
5171
  try {
5504
5172
  await removeMind(name);
5505
5173
  } catch (cleanupErr) {
@@ -5516,7 +5184,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5516
5184
  if (await findMind(name)) return c.json({ error: `Mind already exists: ${name}` }, 409);
5517
5185
  ensureVoluteHome();
5518
5186
  const dest = mindDir(name);
5519
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5187
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5520
5188
  const templatesRoot = findTemplatesRoot();
5521
5189
  const { composedDir, manifest: templateManifest } = composeTemplate(
5522
5190
  templatesRoot,
@@ -5525,36 +5193,36 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5525
5193
  try {
5526
5194
  copyTemplateToDir(composedDir, dest, name, templateManifest);
5527
5195
  applyInitFiles(dest);
5528
- const extractedHome = resolve13(extractedMindDir, "home");
5529
- if (existsSync8(extractedHome)) {
5530
- cpSync(extractedHome, resolve13(dest, "home"), { recursive: true });
5196
+ const extractedHome = resolve11(extractedMindDir, "home");
5197
+ if (existsSync7(extractedHome)) {
5198
+ cpSync(extractedHome, resolve11(dest, "home"), { recursive: true });
5531
5199
  }
5532
- const extractedMindInternal = resolve13(extractedMindDir, ".mind");
5533
- if (existsSync8(extractedMindInternal)) {
5534
- cpSync(extractedMindInternal, resolve13(dest, ".mind"), { recursive: true });
5200
+ const extractedMindInternal = resolve11(extractedMindDir, ".mind");
5201
+ if (existsSync7(extractedMindInternal)) {
5202
+ cpSync(extractedMindInternal, resolve11(dest, ".mind"), { recursive: true });
5535
5203
  }
5536
- const identityDir = resolve13(dest, ".mind/identity");
5204
+ const identityDir = resolve11(dest, ".mind/identity");
5537
5205
  let publicKeyPem;
5538
- if (!manifest.includes.identity || !existsSync8(resolve13(identityDir, "private.pem"))) {
5206
+ if (!manifest.includes.identity || !existsSync7(resolve11(identityDir, "private.pem"))) {
5539
5207
  ({ publicKeyPem } = generateIdentity(dest));
5540
5208
  } else {
5541
- publicKeyPem = readFileSync9(resolve13(identityDir, "public.pem"), "utf-8");
5209
+ publicKeyPem = readFileSync9(resolve11(identityDir, "public.pem"), "utf-8");
5542
5210
  }
5543
- const promptsPath = resolve13(dest, "home/.config/prompts.json");
5544
- if (!existsSync8(promptsPath)) {
5211
+ const promptsPath = resolve11(dest, "home/.config/prompts.json");
5212
+ if (!existsSync7(promptsPath)) {
5545
5213
  const mindPrompts = await getMindPromptDefaults();
5546
5214
  writeFileSync8(promptsPath, `${JSON.stringify(mindPrompts, null, 2)}
5547
5215
  `);
5548
5216
  }
5549
5217
  const state = stateDir(name);
5550
5218
  mkdirSync6(state, { recursive: true });
5551
- const envJson = resolve13(tempDir, "state/env.json");
5552
- if (existsSync8(envJson)) {
5553
- cpSync(envJson, resolve13(state, "env.json"));
5219
+ const envJson = resolve11(tempDir, "state/env.json");
5220
+ if (existsSync7(envJson)) {
5221
+ cpSync(envJson, resolve11(state, "env.json"));
5554
5222
  }
5555
5223
  const port = await nextPort();
5556
5224
  await addMind(name, port, manifest.stage, manifest.template);
5557
- const homeDir = resolve13(dest, "home");
5225
+ const homeDir = resolve11(dest, "home");
5558
5226
  ensureVoluteGroup();
5559
5227
  createMindUser(name, homeDir);
5560
5228
  await chownMindDir(dest, name);
@@ -5567,7 +5235,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5567
5235
  await initTemplateBranch(dest, composedDir, templateManifest, name, env);
5568
5236
  } catch (err) {
5569
5237
  logger_default.error(`git setup failed for imported mind ${name}`, logger_default.errorData(err));
5570
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5238
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5571
5239
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5572
5240
  }
5573
5241
  const skillSet = manifest.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions();
@@ -5597,7 +5265,7 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5597
5265
  ...skillWarnings.length > 0 && { skillWarnings }
5598
5266
  });
5599
5267
  } catch (err) {
5600
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5268
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5601
5269
  try {
5602
5270
  await removeMind(name);
5603
5271
  } catch (cleanupErr) {
@@ -5610,8 +5278,8 @@ async function importFromHomeOnlyArchive(c, tempDir, extractedMindDir, nameOverr
5610
5278
  }
5611
5279
  }
5612
5280
  async function importHistoryFromArchive(name, tempDir) {
5613
- const historyJsonl = resolve13(tempDir, "history.jsonl");
5614
- if (!existsSync8(historyJsonl)) return;
5281
+ const historyJsonl = resolve11(tempDir, "history.jsonl");
5282
+ if (!existsSync7(historyJsonl)) return;
5615
5283
  try {
5616
5284
  const db = await getDb();
5617
5285
  const lines = readFileSync9(historyJsonl, "utf-8").trim().split("\n");
@@ -5651,13 +5319,13 @@ async function importHistoryFromArchive(name, tempDir) {
5651
5319
  }
5652
5320
  }
5653
5321
  function importSessionsFromArchive(dest, tempDir) {
5654
- const sessionsDir = resolve13(tempDir, "sessions");
5655
- if (!existsSync8(sessionsDir)) return;
5322
+ const sessionsDir = resolve11(tempDir, "sessions");
5323
+ if (!existsSync7(sessionsDir)) return;
5656
5324
  try {
5657
- const destSessions = resolve13(dest, ".mind/sessions");
5325
+ const destSessions = resolve11(dest, ".mind/sessions");
5658
5326
  mkdirSync6(destSessions, { recursive: true });
5659
5327
  for (const file of readdirSync2(sessionsDir)) {
5660
- cpSync(resolve13(sessionsDir, file), resolve13(destSessions, file));
5328
+ cpSync(resolve11(sessionsDir, file), resolve11(destSessions, file));
5661
5329
  }
5662
5330
  } catch (err) {
5663
5331
  logger_default.error("Failed to import sessions from archive", logger_default.errorData(err));
@@ -5737,7 +5405,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5737
5405
  }
5738
5406
  ensureVoluteHome();
5739
5407
  const dest = mindDir(name);
5740
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5408
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5741
5409
  const templatesRoot = findTemplatesRoot();
5742
5410
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5743
5411
  try {
@@ -5774,9 +5442,9 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5774
5442
  writeVoluteConfig(dest, config2);
5775
5443
  const modelId = body.model ?? cog?.model;
5776
5444
  effectiveModel = modelId ? qualifyModelId(modelId) : void 0;
5777
- const sdkConfigPath = resolve13(dest, "home/.config/config.json");
5445
+ const sdkConfigPath = resolve11(dest, "home/.config/config.json");
5778
5446
  if (modelId || cog?.compaction) {
5779
- const existing = existsSync8(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
5447
+ const existing = existsSync7(sdkConfigPath) ? JSON.parse(readFileSync9(sdkConfigPath, "utf-8")) : {};
5780
5448
  if (modelId) {
5781
5449
  existing.model = template === "pi" ? qualifyModelId(modelId) : unqualifyModelId(modelId);
5782
5450
  }
@@ -5789,7 +5457,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5789
5457
  }
5790
5458
  const mindPrompts = await getMindPromptDefaults();
5791
5459
  writeFileSync8(
5792
- resolve13(dest, "home/.config/prompts.json"),
5460
+ resolve11(dest, "home/.config/prompts.json"),
5793
5461
  `${JSON.stringify(mindPrompts, null, 2)}
5794
5462
  `
5795
5463
  );
@@ -5801,7 +5469,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5801
5469
  } catch (err) {
5802
5470
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
5803
5471
  }
5804
- const homeDir = resolve13(dest, "home");
5472
+ const homeDir = resolve11(dest, "home");
5805
5473
  ensureVoluteGroup();
5806
5474
  createMindUser(name, homeDir);
5807
5475
  await chownMindDir(dest, name);
@@ -5814,7 +5482,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
5814
5482
  await initTemplateBranch(dest, composedDir, manifest, name, env);
5815
5483
  } catch (err) {
5816
5484
  logger_default.error(`git setup failed for ${name}`, logger_default.errorData(err));
5817
- rmSync3(resolve13(dest, ".git"), { recursive: true, force: true });
5485
+ rmSync3(resolve11(dest, ".git"), { recursive: true, force: true });
5818
5486
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
5819
5487
  }
5820
5488
  if (body.stage === "seed") {
@@ -5823,7 +5491,7 @@ Your creator described you as: "${body.description}"
5823
5491
  ` : "";
5824
5492
  const seedSoulRaw = body.seedSoul ?? await getPrompt("seed_soul", { name, description: descLine });
5825
5493
  const seedSoul = body.seedSoul ? substitute(seedSoulRaw, { name, description: descLine }) : seedSoulRaw;
5826
- writeFileSync8(resolve13(dest, "home/SOUL.md"), seedSoul);
5494
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), seedSoul);
5827
5495
  }
5828
5496
  let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
5829
5497
  if (body.stage === "seed" && !body.skills) {
@@ -5849,7 +5517,7 @@ Your creator described you as: "${body.description}"
5849
5517
  const spiritName = getSpiritName();
5850
5518
  const spiritEntry = await findMind(spiritName);
5851
5519
  if (spiritEntry) {
5852
- const { spiritDir } = await import("./spirit-I5ECLGRI.js");
5520
+ const { spiritDir } = await import("./spirit-Q5VGFWUI.js");
5853
5521
  const sDir = spiritEntry.dir ?? spiritDir();
5854
5522
  const spiritConfig = readVoluteConfig(sDir) ?? {};
5855
5523
  const schedules = spiritConfig.schedules ?? [];
@@ -5864,7 +5532,7 @@ Your creator described you as: "${body.description}"
5864
5532
  });
5865
5533
  spiritConfig.schedules = schedules;
5866
5534
  writeVoluteConfig(sDir, spiritConfig);
5867
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
5535
+ const { getScheduler: getScheduler2 } = await import("./scheduler-73Q4MQ7Y.js");
5868
5536
  getScheduler2().loadSchedules(spiritName, sDir);
5869
5537
  }
5870
5538
  }
@@ -5875,11 +5543,11 @@ Your creator described you as: "${body.description}"
5875
5543
  if (body.stage !== "seed") {
5876
5544
  const customSoul = await getPromptIfCustom("default_soul");
5877
5545
  if (customSoul) {
5878
- writeFileSync8(resolve13(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
5546
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), customSoul.replace(/\{\{name\}\}/g, name));
5879
5547
  }
5880
5548
  const customMemory = await getPromptIfCustom("default_memory");
5881
5549
  if (customMemory) {
5882
- writeFileSync8(resolve13(dest, "home/MEMORY.md"), customMemory);
5550
+ writeFileSync8(resolve11(dest, "home/MEMORY.md"), customMemory);
5883
5551
  }
5884
5552
  }
5885
5553
  await chownMindDir(dest, name);
@@ -5919,7 +5587,7 @@ Your creator described you as: "${body.description}"
5919
5587
  ...skillWarnings.length > 0 && { skillWarnings }
5920
5588
  });
5921
5589
  } catch (err) {
5922
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5590
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
5923
5591
  try {
5924
5592
  await removeMind(name);
5925
5593
  } catch (cleanupErr) {
@@ -5940,13 +5608,13 @@ Your creator described you as: "${body.description}"
5940
5608
  return importFromArchive(c, body.archivePath, body.name, body.manifest);
5941
5609
  }
5942
5610
  const wsDir = body.workspacePath;
5943
- if (!wsDir || !existsSync8(resolve13(wsDir, "SOUL.md")) || !existsSync8(resolve13(wsDir, "IDENTITY.md"))) {
5611
+ if (!wsDir || !existsSync7(resolve11(wsDir, "SOUL.md")) || !existsSync7(resolve11(wsDir, "IDENTITY.md"))) {
5944
5612
  return c.json({ error: "Invalid workspace: missing SOUL.md or IDENTITY.md" }, 400);
5945
5613
  }
5946
- const soul = readFileSync9(resolve13(wsDir, "SOUL.md"), "utf-8");
5947
- const identity = readFileSync9(resolve13(wsDir, "IDENTITY.md"), "utf-8");
5948
- const userPath = resolve13(wsDir, "USER.md");
5949
- const user = existsSync8(userPath) ? readFileSync9(userPath, "utf-8") : "";
5614
+ const soul = readFileSync9(resolve11(wsDir, "SOUL.md"), "utf-8");
5615
+ const identity = readFileSync9(resolve11(wsDir, "IDENTITY.md"), "utf-8");
5616
+ const userPath = resolve11(wsDir, "USER.md");
5617
+ const user = existsSync7(userPath) ? readFileSync9(userPath, "utf-8") : "";
5950
5618
  const name = body.name ?? parseNameFromIdentity(identity) ?? "imported-mind";
5951
5619
  const template = body.template ?? "claude";
5952
5620
  const nameErr = validateMindName(name);
@@ -5966,33 +5634,33 @@ ${user.trimEnd()}
5966
5634
  ` : "";
5967
5635
  ensureVoluteHome();
5968
5636
  const dest = mindDir(name);
5969
- if (existsSync8(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5637
+ if (existsSync7(dest)) return c.json({ error: "Mind directory already exists" }, 409);
5970
5638
  const templatesRoot = findTemplatesRoot();
5971
5639
  const { composedDir, manifest } = composeTemplate(templatesRoot, template);
5972
5640
  try {
5973
5641
  copyTemplateToDir(composedDir, dest, name, manifest);
5974
5642
  applyInitFiles(dest);
5975
5643
  const { publicKeyPem: importPublicKey } = generateIdentity(dest);
5976
- writeFileSync8(resolve13(dest, "home/SOUL.md"), mergedSoul);
5977
- const wsMemoryPath = resolve13(wsDir, "MEMORY.md");
5978
- const hasMemory = existsSync8(wsMemoryPath);
5644
+ writeFileSync8(resolve11(dest, "home/SOUL.md"), mergedSoul);
5645
+ const wsMemoryPath = resolve11(wsDir, "MEMORY.md");
5646
+ const hasMemory = existsSync7(wsMemoryPath);
5979
5647
  if (hasMemory) {
5980
5648
  const existingMemory = readFileSync9(wsMemoryPath, "utf-8");
5981
5649
  writeFileSync8(
5982
- resolve13(dest, "home/MEMORY.md"),
5650
+ resolve11(dest, "home/MEMORY.md"),
5983
5651
  `${existingMemory.trimEnd()}${mergedMemoryExtra}`
5984
5652
  );
5985
5653
  } else if (user) {
5986
- writeFileSync8(resolve13(dest, "home/MEMORY.md"), `${user.trimEnd()}
5654
+ writeFileSync8(resolve11(dest, "home/MEMORY.md"), `${user.trimEnd()}
5987
5655
  `);
5988
5656
  }
5989
- const wsMemoryDir = resolve13(wsDir, "memory");
5657
+ const wsMemoryDir = resolve11(wsDir, "memory");
5990
5658
  let dailyLogCount = 0;
5991
- if (existsSync8(wsMemoryDir)) {
5992
- const destMemoryDir = resolve13(dest, "home/memory");
5659
+ if (existsSync7(wsMemoryDir)) {
5660
+ const destMemoryDir = resolve11(dest, "home/memory");
5993
5661
  const files = readdirSync2(wsMemoryDir).filter((f) => f.endsWith(".md"));
5994
5662
  for (const file of files) {
5995
- cpSync(resolve13(wsMemoryDir, file), resolve13(destMemoryDir, file));
5663
+ cpSync(resolve11(wsMemoryDir, file), resolve11(destMemoryDir, file));
5996
5664
  }
5997
5665
  dailyLogCount = files.length;
5998
5666
  }
@@ -6003,7 +5671,7 @@ ${user.trimEnd()}
6003
5671
  } catch (err) {
6004
5672
  logger_default.warn(`failed to set template hash for ${name}`, logger_default.errorData(err));
6005
5673
  }
6006
- const homeDir = resolve13(dest, "home");
5674
+ const homeDir = resolve11(dest, "home");
6007
5675
  ensureVoluteGroup();
6008
5676
  createMindUser(name, homeDir);
6009
5677
  await chownMindDir(dest, name);
@@ -6011,20 +5679,20 @@ ${user.trimEnd()}
6011
5679
  if (!hasMemory && dailyLogCount > 0) {
6012
5680
  await consolidateMemory(dest);
6013
5681
  }
6014
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dest, "home") } : void 0;
5682
+ const env = isIsolationEnabled() ? { ...process.env, HOME: resolve11(dest, "home") } : void 0;
6015
5683
  await gitExec(["init"], { cwd: dest, mindName: name, env });
6016
5684
  await configureGitIdentity(name, { cwd: dest, mindName: name, env });
6017
5685
  await gitExec(["add", "-A"], { cwd: dest, mindName: name, env });
6018
5686
  await gitExec(["commit", "-m", "import from OpenClaw"], { cwd: dest, mindName: name, env });
6019
- const sessionFile = body.sessionPath ? resolve13(body.sessionPath) : findOpenClawSession(wsDir);
6020
- if (sessionFile && existsSync8(sessionFile)) {
5687
+ const sessionFile = body.sessionPath ? resolve11(body.sessionPath) : findOpenClawSession(wsDir);
5688
+ if (sessionFile && existsSync7(sessionFile)) {
6021
5689
  if (template === "pi") {
6022
5690
  importPiSession(sessionFile, dest);
6023
5691
  } else if (template === "claude") {
6024
5692
  const sessionId = convertSession({ sessionPath: sessionFile, projectDir: dest });
6025
- const mindRuntimeDir = resolve13(dest, ".mind");
5693
+ const mindRuntimeDir = resolve11(dest, ".mind");
6026
5694
  mkdirSync6(mindRuntimeDir, { recursive: true });
6027
- writeFileSync8(resolve13(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
5695
+ writeFileSync8(resolve11(mindRuntimeDir, "session.json"), JSON.stringify({ sessionId }));
6028
5696
  }
6029
5697
  }
6030
5698
  importOpenClawConnectors(name, dest);
@@ -6034,7 +5702,7 @@ ${user.trimEnd()}
6034
5702
  );
6035
5703
  return c.json({ ok: true, name, port, message: `Imported mind: ${name} (port ${port})` });
6036
5704
  } catch (err) {
6037
- if (existsSync8(dest)) rmSync3(dest, { recursive: true, force: true });
5705
+ if (existsSync7(dest)) rmSync3(dest, { recursive: true, force: true });
6038
5706
  try {
6039
5707
  await removeMind(name);
6040
5708
  } catch (cleanupErr) {
@@ -6070,7 +5738,7 @@ ${user.trimEnd()}
6070
5738
  stage: entry.stage,
6071
5739
  dir: entry.dir
6072
5740
  });
6073
- const hasPages = existsSync8(resolve13(mindDir(entry.name), "home", "pages"));
5741
+ const hasPages = existsSync7(resolve11(mindDir(entry.name), "home", "pages"));
6074
5742
  const lastActiveAt = lastActiveMap.get(entry.name) ?? null;
6075
5743
  if (!privileged) return toPublicMind(entry, mindStatus, { hasPages, lastActiveAt });
6076
5744
  return {
@@ -6078,6 +5746,7 @@ ${user.trimEnd()}
6078
5746
  ...mindStatus,
6079
5747
  hasPages,
6080
5748
  templateStale: isTemplateStale(entry),
5749
+ upgradeBlocked: getUpgradeBlocked(entry.name)?.reason,
6081
5750
  lastActiveAt
6082
5751
  };
6083
5752
  })
@@ -6088,12 +5757,12 @@ ${user.trimEnd()}
6088
5757
  const entry = await findMind(name);
6089
5758
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6090
5759
  const dir = entry.dir ?? mindDir(entry.parent ?? name);
6091
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
5760
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6092
5761
  const mindStatus = await getMindStatus(name, entry.port, void 0, {
6093
5762
  stage: entry.stage,
6094
5763
  dir: entry.dir
6095
5764
  });
6096
- const hasPages = existsSync8(resolve13(mindDir(name), "home", "pages"));
5765
+ const hasPages = existsSync7(resolve11(mindDir(name), "home", "pages"));
6097
5766
  if (!isPrivileged(c)) {
6098
5767
  return c.json(toPublicMind(entry, mindStatus, { hasPages }));
6099
5768
  }
@@ -6116,6 +5785,7 @@ ${user.trimEnd()}
6116
5785
  variants: variantStatuses,
6117
5786
  hasPages,
6118
5787
  templateStale: isTemplateStale(entry),
5788
+ upgradeBlocked: getUpgradeBlocked(name)?.reason,
6119
5789
  ...notice && {
6120
5790
  lastNotice: {
6121
5791
  kind: notice.kind,
@@ -6133,7 +5803,7 @@ ${user.trimEnd()}
6133
5803
  const projectDir = entry.dir ?? mindDir(name);
6134
5804
  if (entry.parent) {
6135
5805
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
6136
- } else if (!existsSync8(projectDir)) {
5806
+ } else if (!existsSync7(projectDir)) {
6137
5807
  return c.json({ error: "Mind directory missing" }, 404);
6138
5808
  }
6139
5809
  if (getMindManager().isRunning(name)) {
@@ -6154,7 +5824,7 @@ ${user.trimEnd()}
6154
5824
  const projectDir = entry.dir ?? mindDir(name);
6155
5825
  if (entry.parent) {
6156
5826
  if (!entry.dir) return c.json({ error: `Variant ${name} has no directory` }, 404);
6157
- } else if (!existsSync8(projectDir)) {
5827
+ } else if (!existsSync7(projectDir)) {
6158
5828
  return c.json({ error: "Mind directory missing" }, 404);
6159
5829
  }
6160
5830
  let context;
@@ -6170,7 +5840,7 @@ ${user.trimEnd()}
6170
5840
  const manager = getMindManager();
6171
5841
  try {
6172
5842
  if (context?.type === "reload") {
6173
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
5843
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6174
5844
  const sleepState = getSleepManagerIfReady2()?.getState(name);
6175
5845
  if (sleepState?.sleeping) {
6176
5846
  logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
@@ -6191,7 +5861,7 @@ ${user.trimEnd()}
6191
5861
  if (variantEntry && variantEntry.parent === baseName && variantEntry.dir && variantEntry.branch) {
6192
5862
  const projectRoot = mindDir(baseName);
6193
5863
  const discardUnresolved = context.discardUnresolvedHomeFiles === true;
6194
- if (existsSync8(variantEntry.dir)) {
5864
+ if (existsSync7(variantEntry.dir)) {
6195
5865
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
6196
5866
  if (status) {
6197
5867
  try {
@@ -6221,7 +5891,7 @@ ${user.trimEnd()}
6221
5891
  const preMergeHead = (await gitExec(["rev-parse", "HEAD"], { cwd: projectRoot })).trim();
6222
5892
  const memoryDelta = await mergeVariantExcludingMemory(projectRoot, variantEntry.branch);
6223
5893
  let unresolvedNotice;
6224
- if (existsSync8(variantEntry.dir) && !discardUnresolved) {
5894
+ if (existsSync7(variantEntry.dir) && !discardUnresolved) {
6225
5895
  try {
6226
5896
  const unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
6227
5897
  if (unresolved.totalCount > 0) {
@@ -6319,7 +5989,7 @@ ${user.trimEnd()}
6319
5989
  const name = c.req.param("name");
6320
5990
  const entry = await findMind(name);
6321
5991
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6322
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
5992
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6323
5993
  const sm = getSleepManagerIfReady2();
6324
5994
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6325
5995
  return c.json(sm.getState(name));
@@ -6327,7 +5997,7 @@ ${user.trimEnd()}
6327
5997
  const name = c.req.param("name");
6328
5998
  const entry = await findMind(name);
6329
5999
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6330
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6000
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6331
6001
  const sm = getSleepManagerIfReady2();
6332
6002
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6333
6003
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -6347,7 +6017,7 @@ ${user.trimEnd()}
6347
6017
  const name = c.req.param("name");
6348
6018
  const entry = await findMind(name);
6349
6019
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6350
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6020
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6351
6021
  const sm = getSleepManagerIfReady2();
6352
6022
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6353
6023
  const sleepState = sm.getState(name);
@@ -6362,7 +6032,7 @@ ${user.trimEnd()}
6362
6032
  const name = c.req.param("name");
6363
6033
  const entry = await findMind(name);
6364
6034
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6365
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6035
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6366
6036
  const sm = getSleepManagerIfReady2();
6367
6037
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
6368
6038
  const flushed = await sm.flushQueuedMessages(name);
@@ -6378,12 +6048,12 @@ ${user.trimEnd()}
6378
6048
  if (body.displayName !== void 0) profile.displayName = body.displayName;
6379
6049
  if (body.description !== void 0) profile.description = body.description;
6380
6050
  if (body.avatar !== void 0) {
6381
- const homeDir = resolve13(dir, "home");
6051
+ const homeDir = resolve11(dir, "home");
6382
6052
  const avatarPath = safeResolveWithinBase(homeDir, body.avatar);
6383
6053
  if (!avatarPath) {
6384
6054
  return c.json({ error: "Avatar path must be inside the mind's home directory" }, 400);
6385
6055
  }
6386
- if (!existsSync8(avatarPath)) {
6056
+ if (!existsSync7(avatarPath)) {
6387
6057
  return c.json({ error: `Avatar file not found: ${relative(homeDir, avatarPath)}` }, 400);
6388
6058
  }
6389
6059
  profile.avatar = relative(homeDir, avatarPath);
@@ -6434,7 +6104,7 @@ ${user.trimEnd()}
6434
6104
  });
6435
6105
  }
6436
6106
  if (!force) {
6437
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-NWUCRBZB.js");
6107
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-KHI65FEX.js");
6438
6108
  if (getSleepManagerIfReady2()?.isSleeping(name)) {
6439
6109
  return c.json({ output: "" });
6440
6110
  }
@@ -6489,7 +6159,7 @@ ${user.trimEnd()}
6489
6159
  }
6490
6160
  }
6491
6161
  const dir = entry.dir ?? mindDir(name);
6492
- const { evaluateSeedChecklist: evaluateSeedChecklist2 } = await import("./seed-readiness-WJYYRRCK.js");
6162
+ const { evaluateSeedChecklist: evaluateSeedChecklist2 } = await import("./seed-readiness-H5TTPAQH.js");
6493
6163
  const checklist = evaluateSeedChecklist2(dir);
6494
6164
  const done = [];
6495
6165
  const remaining = [];
@@ -6531,7 +6201,7 @@ ${user.trimEnd()}
6531
6201
  try {
6532
6202
  const sproutedDir = entry.dir ?? mindDir(name);
6533
6203
  if (setupDefaultDreaming(sproutedDir).schedulesChanged) {
6534
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
6204
+ const { getScheduler: getScheduler2 } = await import("./scheduler-73Q4MQ7Y.js");
6535
6205
  getScheduler2().loadSchedules(name, sproutedDir);
6536
6206
  }
6537
6207
  } catch (err) {
@@ -6541,7 +6211,7 @@ ${user.trimEnd()}
6541
6211
  const spiritName = getSpiritName();
6542
6212
  const spiritEntry = await findMind(spiritName);
6543
6213
  if (spiritEntry) {
6544
- const { firstWeekSchedules, spiritDir } = await import("./spirit-I5ECLGRI.js");
6214
+ const { firstWeekSchedules, spiritDir } = await import("./spirit-Q5VGFWUI.js");
6545
6215
  const sDir = spiritEntry.dir ?? spiritDir();
6546
6216
  const spiritConfig = readVoluteConfig(sDir);
6547
6217
  if (spiritConfig) {
@@ -6555,7 +6225,7 @@ ${user.trimEnd()}
6555
6225
  spiritConfig.schedules = schedules;
6556
6226
  writeVoluteConfig(sDir, spiritConfig);
6557
6227
  try {
6558
- const { getScheduler: getScheduler2 } = await import("./scheduler-5X5UIQOQ.js");
6228
+ const { getScheduler: getScheduler2 } = await import("./scheduler-73Q4MQ7Y.js");
6559
6229
  getScheduler2().loadSchedules(spiritName, sDir);
6560
6230
  } catch (err) {
6561
6231
  logger_default.warn(
@@ -6609,10 +6279,10 @@ ${user.trimEnd()}
6609
6279
  await deleteMindUser2(name);
6610
6280
  invalidateMindUserCache(name);
6611
6281
  const state = stateDir(name);
6612
- if (existsSync8(state)) {
6282
+ if (existsSync7(state)) {
6613
6283
  rmSync3(state, { recursive: true, force: true });
6614
6284
  }
6615
- if (force && existsSync8(dir)) {
6285
+ if (force && existsSync7(dir)) {
6616
6286
  rmSync3(dir, { recursive: true, force: true });
6617
6287
  deleteMindUser(name);
6618
6288
  }
@@ -6627,7 +6297,7 @@ ${user.trimEnd()}
6627
6297
  const entry = await findMind(mindName);
6628
6298
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6629
6299
  const dir = mindDir(mindName);
6630
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6300
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6631
6301
  let body = {};
6632
6302
  try {
6633
6303
  body = await c.req.json();
@@ -6638,27 +6308,12 @@ ${user.trimEnd()}
6638
6308
  if (!isKnownTemplate(template)) {
6639
6309
  return c.json({ error: `Unknown template: ${template}` }, 400);
6640
6310
  }
6641
- const UPGRADE_BRANCH = "upgrade";
6642
- const upgradeVariantName = `${mindName}-upgrade`;
6643
- const worktreeDir = resolve13(dir, ".variants", UPGRADE_BRANCH);
6644
6311
  if (body.abort) {
6645
- if (!existsSync8(worktreeDir)) {
6312
+ if (!upgradeInProgress(mindName)) {
6646
6313
  return c.json({ error: "No upgrade in progress" }, 400);
6647
6314
  }
6648
6315
  try {
6649
- try {
6650
- const gitDirContent = readFileSync9(resolve13(worktreeDir, ".git"), "utf-8").trim();
6651
- const gitDir = gitDirContent.replace("gitdir: ", "");
6652
- if (existsSync8(resolve13(gitDir, "MERGE_HEAD"))) {
6653
- await gitExec(["merge", "--abort"], { cwd: worktreeDir });
6654
- }
6655
- } catch {
6656
- }
6657
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir, { stop: true });
6658
- try {
6659
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6660
- } catch {
6661
- }
6316
+ await abortUpgrade(mindName);
6662
6317
  return c.json({ ok: true });
6663
6318
  } catch (err) {
6664
6319
  return c.json(
@@ -6668,81 +6323,45 @@ ${user.trimEnd()}
6668
6323
  }
6669
6324
  }
6670
6325
  if (body.continue) {
6671
- if (!existsSync8(worktreeDir)) {
6326
+ if (!upgradeInProgress(mindName)) {
6672
6327
  return c.json({ error: "No upgrade in progress" }, 400);
6673
6328
  }
6674
- const status = await gitExec(["status", "--porcelain"], { cwd: worktreeDir });
6675
- const hasConflicts2 = status.split("\n").some((line) => line.startsWith("UU") || line.startsWith("AA"));
6676
- if (hasConflicts2) {
6677
- return c.json({ error: "Unresolved conflicts remain" }, 409);
6678
- }
6679
6329
  try {
6680
- await gitExec(["add", "-A"], { cwd: worktreeDir });
6681
- await gitExec(["commit", "-m", "merge template update"], { cwd: worktreeDir });
6682
- } catch (e) {
6683
- const msg = e instanceof Error ? e.message : String(e);
6684
- const stderr = e?.stderr ?? "";
6685
- const stdout = e?.stdout ?? "";
6686
- if (!msg.includes("nothing to commit") && !stderr.includes("nothing to commit") && !stdout.includes("nothing to commit"))
6687
- throw e;
6688
- }
6689
- try {
6690
- await gitExec(["add", "home/"], { cwd: worktreeDir });
6691
- } catch (err) {
6692
- logger_default.warn(`failed to re-add home files during upgrade for ${mindName}`, logger_default.errorData(err));
6693
- }
6694
- try {
6695
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6696
- } catch {
6697
- await gitExec(["commit", "-m", "re-add allowlisted home files"], {
6698
- cwd: worktreeDir
6699
- });
6700
- }
6701
- await chownMindDir(dir, mindName);
6702
- try {
6703
- const result = await mergeUpgradeAndRestart(
6704
- mindName,
6705
- dir,
6706
- worktreeDir,
6707
- upgradeVariantName,
6708
- UPGRADE_BRANCH,
6709
- template,
6710
- oldTemplate
6711
- );
6712
- return c.json(result);
6330
+ const result = await continueUpgrade(mindName, { template });
6331
+ if (result.status === "conflicts") {
6332
+ return c.json({
6333
+ ok: false,
6334
+ conflicts: true,
6335
+ worktreeDir: result.worktreeDir,
6336
+ files: result.files,
6337
+ message: result.message ?? "Merge conflicts detected. Resolve them, then run with continue."
6338
+ });
6339
+ }
6340
+ return c.json({ ok: true, warning: result.warning });
6713
6341
  } catch (err) {
6714
- return c.json(
6715
- { error: err instanceof Error ? err.message : "Failed to merge upgrade" },
6716
- 500
6717
- );
6342
+ const msg = err instanceof Error ? err.message : "Failed to merge upgrade";
6343
+ if (msg === "Unresolved conflicts remain") {
6344
+ return c.json({ error: msg }, 409);
6345
+ }
6346
+ return c.json({ error: msg }, 500);
6718
6347
  }
6719
6348
  }
6720
6349
  if (body.accept) {
6721
- if (existsSync8(worktreeDir)) {
6350
+ if (upgradeInProgress(mindName)) {
6722
6351
  try {
6723
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir, { stop: true });
6352
+ await abortUpgrade(mindName);
6724
6353
  } catch (err) {
6725
6354
  logger_default.warn(`failed to clean up legacy upgrade variant for ${mindName}`, logger_default.errorData(err));
6726
6355
  }
6727
- try {
6728
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6729
- } catch {
6730
- }
6731
6356
  }
6732
6357
  return c.json({ error: "Upgrades now auto-merge. Run 'volute mind upgrade' again." }, 400);
6733
6358
  }
6734
6359
  if (body.diff) {
6360
+ if (!existsSync7(resolve11(dir, ".git"))) {
6361
+ return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
6362
+ }
6735
6363
  try {
6736
- if (!existsSync8(resolve13(dir, ".git"))) {
6737
- return c.json({ error: "Mind has no git history \u2014 nothing to diff against" }, 400);
6738
- }
6739
- await updateTemplateBranch(dir, template, mindName);
6740
- let diff;
6741
- try {
6742
- diff = await gitExec(["diff", "HEAD...volute/template"], { cwd: dir });
6743
- } catch {
6744
- diff = await gitExec(["diff", "HEAD", "volute/template"], { cwd: dir });
6745
- }
6364
+ const diff = await upgradeDiff(mindName, template);
6746
6365
  return c.json({ ok: true, diff: diff || "(no changes)" });
6747
6366
  } catch (err) {
6748
6367
  return c.json(
@@ -6751,103 +6370,21 @@ ${user.trimEnd()}
6751
6370
  );
6752
6371
  }
6753
6372
  }
6754
- if (existsSync8(worktreeDir)) {
6755
- return c.json(
6756
- { error: "Upgrade variant already exists. Use continue or delete it first." },
6757
- 409
6758
- );
6759
- }
6760
- if (!existsSync8(resolve13(dir, ".git"))) {
6761
- try {
6762
- const env = isIsolationEnabled() ? { ...process.env, HOME: resolve13(dir, "home") } : void 0;
6763
- await gitExec(["init"], { cwd: dir, mindName, env });
6764
- await configureGitIdentity(mindName, { cwd: dir, mindName, env });
6765
- await gitExec(["add", "-A"], { cwd: dir, mindName, env });
6766
- await gitExec(["commit", "-m", "initial commit"], { cwd: dir, mindName, env });
6767
- await chownMindDir(dir, mindName);
6768
- } catch (err) {
6769
- rmSync3(resolve13(dir, ".git"), { recursive: true, force: true });
6770
- return c.json(
6771
- {
6772
- error: `Git initialization failed: ${err instanceof Error ? err.message : String(err)}`
6773
- },
6774
- 500
6775
- );
6776
- }
6777
- }
6778
- await gitExec(["worktree", "prune"], { cwd: dir });
6779
- try {
6780
- await gitExec(["branch", "-D", UPGRADE_BRANCH], { cwd: dir });
6781
- } catch {
6782
- }
6783
- await updateTemplateBranch(dir, template, mindName);
6784
- const parentDir = resolve13(dir, ".variants");
6785
- if (!existsSync8(parentDir)) {
6786
- mkdirSync6(parentDir, { recursive: true });
6787
- }
6788
- await gitExec(["worktree", "add", "-b", UPGRADE_BRANCH, worktreeDir], { cwd: dir });
6789
- await gitExec(["rm", "-r", "--cached", "--ignore-unmatch", "home/"], {
6790
- cwd: worktreeDir
6791
- });
6792
- try {
6793
- await gitExec(["checkout", "HEAD", "--", "home/VOLUTE.md"], { cwd: worktreeDir });
6794
- await gitExec(["add", "home/VOLUTE.md"], { cwd: worktreeDir });
6795
- } catch (err) {
6796
- const msg = String(err?.message ?? err);
6797
- if (!msg.includes("did not match")) {
6798
- logger_default.warn(
6799
- `unexpected error restoring VOLUTE.md during upgrade for ${mindName}`,
6800
- logger_default.errorData(err)
6801
- );
6802
- }
6803
- }
6804
6373
  try {
6805
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6806
- } catch {
6807
- await gitExec(["commit", "-m", "prepare for home/ allowlist migration"], {
6808
- cwd: worktreeDir
6809
- });
6810
- }
6811
- const hasConflicts = await mergeTemplateBranch(worktreeDir);
6812
- if (!hasConflicts) {
6813
- try {
6814
- await gitExec(["add", "home/"], { cwd: worktreeDir });
6815
- } catch (err) {
6816
- logger_default.warn(`failed to re-add home files during upgrade for ${mindName}`, logger_default.errorData(err));
6817
- }
6818
- try {
6819
- await gitExec(["diff", "--cached", "--quiet"], { cwd: worktreeDir });
6820
- } catch {
6821
- await gitExec(["commit", "-m", "re-add allowlisted home files"], {
6822
- cwd: worktreeDir
6374
+ const result = await runUpgrade(mindName, { template });
6375
+ if (result.status === "conflicts") {
6376
+ return c.json({
6377
+ ok: false,
6378
+ conflicts: true,
6379
+ worktreeDir: result.worktreeDir,
6380
+ files: result.files,
6381
+ message: result.message ?? "Merge conflicts detected. Resolve them, then run with continue."
6823
6382
  });
6824
6383
  }
6825
- }
6826
- await chownMindDir(dir, mindName);
6827
- if (hasConflicts) {
6828
- return c.json({
6829
- ok: false,
6830
- conflicts: true,
6831
- worktreeDir,
6832
- message: "Merge conflicts detected. Resolve them, then run with continue."
6833
- });
6834
- }
6835
- try {
6836
- const result = await mergeUpgradeAndRestart(
6837
- mindName,
6838
- dir,
6839
- worktreeDir,
6840
- upgradeVariantName,
6841
- UPGRADE_BRANCH,
6842
- template,
6843
- oldTemplate
6844
- );
6845
- return c.json(result);
6384
+ return c.json({ ok: true, warning: result.warning });
6846
6385
  } catch (err) {
6847
- try {
6848
- await cleanupVariant(upgradeVariantName, mindName, dir, worktreeDir);
6849
- } catch (cleanupErr) {
6850
- logger_default.warn(`cleanup failed after upgrade error for ${mindName}`, logger_default.errorData(cleanupErr));
6386
+ if (err instanceof UpgradeInProgressError) {
6387
+ return c.json({ error: err.message }, 409);
6851
6388
  }
6852
6389
  return c.json({ error: err instanceof Error ? err.message : "Failed to merge upgrade" }, 500);
6853
6390
  }
@@ -6915,11 +6452,11 @@ ${user.trimEnd()}
6915
6452
  const entry = await findMind(name);
6916
6453
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6917
6454
  const dir = entry.dir ?? mindDir(name);
6918
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6455
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6919
6456
  let config2 = readVoluteConfig(dir);
6920
6457
  if (!config2 && entry.template === "pi") {
6921
- const piConfigPath = resolve13(dir, "home/.config/config.json");
6922
- if (existsSync8(piConfigPath)) {
6458
+ const piConfigPath = resolve11(dir, "home/.config/config.json");
6459
+ if (existsSync7(piConfigPath)) {
6923
6460
  try {
6924
6461
  config2 = JSON.parse(readFileSync9(piConfigPath, "utf-8"));
6925
6462
  } catch {
@@ -6927,8 +6464,8 @@ ${user.trimEnd()}
6927
6464
  }
6928
6465
  }
6929
6466
  let templateConfig = {};
6930
- const configJsonPath = resolve13(dir, "home/.config/config.json");
6931
- if (existsSync8(configJsonPath)) {
6467
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
6468
+ if (existsSync7(configJsonPath)) {
6932
6469
  try {
6933
6470
  templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
6934
6471
  } catch {
@@ -6970,7 +6507,7 @@ ${user.trimEnd()}
6970
6507
  const entry = await findMind(name);
6971
6508
  if (!entry) return c.json({ error: "Mind not found" }, 404);
6972
6509
  const dir = entry.dir ?? mindDir(name);
6973
- if (!existsSync8(dir)) return c.json({ error: "Mind directory missing" }, 404);
6510
+ if (!existsSync7(dir)) return c.json({ error: "Mind directory missing" }, 404);
6974
6511
  const body = c.req.valid("json");
6975
6512
  const existing = readVoluteConfig(dir) ?? {};
6976
6513
  if (body.model !== void 0) existing.model = body.model;
@@ -6996,14 +6533,14 @@ ${user.trimEnd()}
6996
6533
  }
6997
6534
  writeVoluteConfig(dir, existing);
6998
6535
  if (body.unescapeNewlines !== void 0) {
6999
- const { clearEchoTextCache } = await import("./echo-text-KU6G4Z7V.js");
6536
+ const { clearEchoTextCache } = await import("./echo-text-73CYQRL7.js");
7000
6537
  clearEchoTextCache(name);
7001
6538
  }
7002
6539
  const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.compaction !== void 0;
7003
6540
  if (needsConfigJson) {
7004
- const configJsonPath = resolve13(dir, "home/.config/config.json");
6541
+ const configJsonPath = resolve11(dir, "home/.config/config.json");
7005
6542
  let templateConfig = {};
7006
- if (existsSync8(configJsonPath)) {
6543
+ if (existsSync7(configJsonPath)) {
7007
6544
  try {
7008
6545
  templateConfig = JSON.parse(readFileSync9(configJsonPath, "utf-8"));
7009
6546
  } catch {
@@ -7068,9 +6605,43 @@ ${user.trimEnd()}
7068
6605
  if (err instanceof Error && err.message.includes("not initialized")) {
7069
6606
  return c.json({ error: "Delivery manager not available" }, 503);
7070
6607
  }
6608
+ if (err instanceof UnknownChannelError) return c.json({ error: err.message }, 400);
7071
6609
  logger_default.error(`failed to decline channel ${channel} for ${name}`, logger_default.errorData(err));
7072
6610
  return c.json({ error: "Failed to decline channel" }, 500);
7073
6611
  }
6612
+ }).post("/:name/gates/accept", requireSelf(), async (c) => {
6613
+ const name = c.req.param("name");
6614
+ const body = await c.req.json().catch(() => ({}));
6615
+ const channel = body.channel?.trim();
6616
+ if (!channel) return c.json({ error: "channel required" }, 400);
6617
+ if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
6618
+ try {
6619
+ const result = await getDeliveryManager().acceptChannel(name, channel, body.thread?.trim());
6620
+ return c.json({ ok: true, channel, ...result });
6621
+ } catch (err) {
6622
+ if (err instanceof Error && err.message.includes("not initialized")) {
6623
+ return c.json({ error: "Delivery manager not available" }, 503);
6624
+ }
6625
+ if (err instanceof Error && err.message.includes("malformed")) {
6626
+ return c.json({ error: err.message }, 409);
6627
+ }
6628
+ if (err instanceof UnknownChannelError) return c.json({ error: err.message }, 400);
6629
+ logger_default.error(`failed to accept channel ${channel} for ${name}`, logger_default.errorData(err));
6630
+ return c.json({ error: "Failed to accept channel" }, 500);
6631
+ }
6632
+ }).get("/:name/gates/peek", requireSelf(), async (c) => {
6633
+ const name = c.req.param("name");
6634
+ const channel = c.req.query("channel")?.trim();
6635
+ if (!channel) return c.json({ error: "channel required" }, 400);
6636
+ try {
6637
+ return c.json(await getDeliveryManager().peekChannel(name, channel));
6638
+ } catch (err) {
6639
+ if (err instanceof Error && err.message.includes("not initialized")) {
6640
+ return c.json({ error: "Delivery manager not available" }, 503);
6641
+ }
6642
+ logger_default.error(`failed to peek channel ${channel} for ${name}`, logger_default.errorData(err));
6643
+ return c.json({ error: "Failed to read held messages" }, 500);
6644
+ }
7074
6645
  }).post("/:name/ai/complete", requireSelf(), async (c) => {
7075
6646
  const body = await c.req.json();
7076
6647
  if (!body.systemPrompt || !body.message) {
@@ -7840,7 +7411,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
7840
7411
  const entry = await findMind(name);
7841
7412
  if (!entry) return c.json({ error: "Mind not found" }, 404);
7842
7413
  const body = await c.req.text();
7843
- const { deliverEvent: deliverEvent2 } = await import("./system-events-YTOU66QI.js");
7414
+ const { deliverEvent: deliverEvent2 } = await import("./system-events-Q7IVZ5T4.js");
7844
7415
  const { id, delivered } = await deliverEvent2(name, {
7845
7416
  type: "webhook",
7846
7417
  body,
@@ -7858,14 +7429,14 @@ var schedules_default = app15;
7858
7429
  // packages/daemon/src/web/api/setup.ts
7859
7430
  import { mkdirSync as mkdirSync7, rmSync as rmSync4, writeFileSync as writeFileSync9 } from "fs";
7860
7431
  import { homedir as homedir2 } from "os";
7861
- import { basename, resolve as resolve14 } from "path";
7432
+ import { basename, resolve as resolve12 } from "path";
7862
7433
  import { Hono as Hono19 } from "hono";
7863
7434
  import { setCookie as setCookie2 } from "hono/cookie";
7864
7435
  var DEFAULT_API_URL2 = "https://volute.systems";
7865
7436
  var setup = new Hono19();
7866
7437
  function writeSetupConfig(systemName, description) {
7867
- const configHome = process.env.VOLUTE_HOME ?? resolve14(homedir2(), ".volute");
7868
- const mindsDir = resolve14(configHome, "minds");
7438
+ const configHome = process.env.VOLUTE_HOME ?? resolve12(homedir2(), ".volute");
7439
+ const mindsDir = resolve12(configHome, "minds");
7869
7440
  mkdirSync7(configHome, { recursive: true });
7870
7441
  mkdirSync7(mindsDir, { recursive: true });
7871
7442
  const existingConfig = readGlobalConfig();
@@ -8200,7 +7771,7 @@ setup.post("/spirit", async (c) => {
8200
7771
  config2.setup.spiritDescription = description || void 0;
8201
7772
  const clearOldStash = () => {
8202
7773
  if (config2.setup?.spiritAvatar) {
8203
- rmSync4(resolve14(voluteSystemDir(), basename(config2.setup.spiritAvatar)), { force: true });
7774
+ rmSync4(resolve12(voluteSystemDir(), basename(config2.setup.spiritAvatar)), { force: true });
8204
7775
  config2.setup.spiritAvatar = void 0;
8205
7776
  }
8206
7777
  };
@@ -8224,7 +7795,7 @@ setup.post("/spirit", async (c) => {
8224
7795
  }
8225
7796
  clearOldStash();
8226
7797
  const filename = `spirit-avatar.${ext}`;
8227
- writeFileSync9(resolve14(voluteSystemDir(), filename), bytes);
7798
+ writeFileSync9(resolve12(voluteSystemDir(), filename), bytes);
8228
7799
  config2.setup.spiritAvatar = filename;
8229
7800
  } else {
8230
7801
  clearOldStash();
@@ -8237,15 +7808,16 @@ setup.post("/complete", async (c) => {
8237
7808
  return c.json({ error: "Setup already complete" }, 400);
8238
7809
  }
8239
7810
  try {
8240
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-I5ECLGRI.js");
8241
- const { startSpiritFull } = await import("./mind-service-WHFBUKZE.js");
7811
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-Q5VGFWUI.js");
7812
+ const { startSpiritFull } = await import("./mind-service-7EFIJ3ZA.js");
8242
7813
  await ensureSpiritProject();
8243
7814
  await syncSpiritTemplate();
7815
+ await notifyExtensionsSpiritReady();
8244
7816
  const warnings = [];
8245
7817
  const config2 = readGlobalConfig();
8246
7818
  if (config2.setup?.service && config2.setup?.type === "local") {
8247
7819
  try {
8248
- const { installUserService } = await import("./service-install-2EWD7KXD.js");
7820
+ const { installUserService } = await import("./service-install-R4SNYUVO.js");
8249
7821
  const installed = await installUserService(config2.port, config2.hostname);
8250
7822
  if (!installed) {
8251
7823
  warnings.push("Service installation is not supported on this platform.");
@@ -8298,7 +7870,7 @@ setup.post("/complete", async (c) => {
8298
7870
  logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
8299
7871
  if (spiritConversationId && spiritStarted) {
8300
7872
  try {
8301
- const { deliverMessage: deliverMessage2 } = await import("./message-delivery-TUXM3AAE.js");
7873
+ const { deliverMessage: deliverMessage2 } = await import("./message-delivery-TRKT4T2P.js");
8302
7874
  const { listUsersByType: listUsers2 } = await import("./auth-KRDSM55Q.js");
8303
7875
  const admins = await listUsers2("human");
8304
7876
  const admin2 = admins.find((u) => u.role === "admin");
@@ -8338,9 +7910,9 @@ setup.post("/complete", async (c) => {
8338
7910
  var setup_default = setup;
8339
7911
 
8340
7912
  // packages/daemon/src/web/api/skills.ts
8341
- import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
7913
+ import { existsSync as existsSync8, mkdtempSync, readdirSync as readdirSync3, rmSync as rmSync5 } from "fs";
8342
7914
  import { tmpdir } from "os";
8343
- import { join, resolve as resolve15 } from "path";
7915
+ import { join, resolve as resolve13 } from "path";
8344
7916
  import AdmZip from "adm-zip";
8345
7917
  import { Hono as Hono20 } from "hono";
8346
7918
  var app16 = new Hono20().get("/", async (c) => {
@@ -8416,19 +7988,19 @@ var app16 = new Hono20().get("/", async (c) => {
8416
7988
  try {
8417
7989
  const zip = new AdmZip(buffer);
8418
7990
  for (const entry of zip.getEntries()) {
8419
- const target = resolve15(tmpDir, entry.entryName);
7991
+ const target = resolve13(tmpDir, entry.entryName);
8420
7992
  if (!target.startsWith(tmpDir)) {
8421
7993
  return c.json({ error: "Invalid zip: paths must not escape archive" }, 400);
8422
7994
  }
8423
7995
  }
8424
7996
  zip.extractAllTo(tmpDir, true);
8425
7997
  let skillDir = null;
8426
- if (existsSync9(join(tmpDir, "SKILL.md"))) {
7998
+ if (existsSync8(join(tmpDir, "SKILL.md"))) {
8427
7999
  skillDir = tmpDir;
8428
8000
  } else {
8429
8001
  const entries = readdirSync3(tmpDir, { withFileTypes: true }).filter((e) => e.isDirectory());
8430
8002
  for (const entry of entries) {
8431
- if (existsSync9(join(tmpDir, entry.name, "SKILL.md"))) {
8003
+ if (existsSync8(join(tmpDir, entry.name, "SKILL.md"))) {
8432
8004
  skillDir = join(tmpDir, entry.name);
8433
8005
  break;
8434
8006
  }
@@ -8790,8 +8362,8 @@ var app20 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
8790
8362
  });
8791
8363
  }, 15e3);
8792
8364
  cleanups.push(() => clearInterval(keepAlive));
8793
- await new Promise((resolve21) => {
8794
- stream.onAbort(() => resolve21());
8365
+ await new Promise((resolve19) => {
8366
+ stream.onAbort(() => resolve19());
8795
8367
  });
8796
8368
  } finally {
8797
8369
  for (const cleanup of cleanups) {
@@ -9072,23 +8644,23 @@ var app21 = new Hono25().use("*", authMiddleware).get("/", async (c) => {
9072
8644
  var feed_default = app21;
9073
8645
 
9074
8646
  // packages/daemon/src/web/api/variants.ts
9075
- import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
9076
- import { resolve as resolve18 } from "path";
8647
+ import { existsSync as existsSync10, mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
8648
+ import { resolve as resolve16 } from "path";
9077
8649
  import { Hono as Hono26 } from "hono";
9078
8650
 
9079
8651
  // packages/daemon/src/lib/mind/farewell.ts
9080
- import { existsSync as existsSync10, readFileSync as readFileSync10, rmSync as rmSync6 } from "fs";
9081
- import { resolve as resolve16 } from "path";
8652
+ import { existsSync as existsSync9, readFileSync as readFileSync10, rmSync as rmSync6 } from "fs";
8653
+ import { resolve as resolve14 } from "path";
9082
8654
  var flog = logger_default.child("farewell");
9083
8655
  var FAREWELL_RELPATH = ".mind/farewell.md";
9084
8656
  var FAREWELL_MIND_PATH = "../.mind/farewell.md";
9085
8657
  var FAREWELL_TIMEOUT_MS = 12e4;
9086
8658
  function farewellPath(variantDir) {
9087
- return resolve16(variantDir, FAREWELL_RELPATH);
8659
+ return resolve14(variantDir, FAREWELL_RELPATH);
9088
8660
  }
9089
8661
  function readFarewell(variantDir) {
9090
8662
  const path = farewellPath(variantDir);
9091
- if (!existsSync10(path)) return void 0;
8663
+ if (!existsSync9(path)) return void 0;
9092
8664
  try {
9093
8665
  const text = readFileSync10(path, "utf-8").trim();
9094
8666
  return text || void 0;
@@ -9111,7 +8683,7 @@ function waitForFarewell(name, variantDir, timeoutMs) {
9111
8683
  const unsub = subscribe((event) => {
9112
8684
  if (event.mind !== name) return;
9113
8685
  if (event.type !== "mind_done" && event.type !== "mind_idle") return;
9114
- if (existsSync10(farewellPath(variantDir))) cleanup();
8686
+ if (existsSync9(farewellPath(variantDir))) cleanup();
9115
8687
  });
9116
8688
  return { done, cancel: cleanup };
9117
8689
  }
@@ -9144,8 +8716,8 @@ async function runFarewellTurn(opts) {
9144
8716
 
9145
8717
  // packages/daemon/src/lib/mind/spawn-server.ts
9146
8718
  import { spawn as spawn4 } from "child_process";
9147
- import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as statSync4 } from "fs";
9148
- import { resolve as resolve17 } from "path";
8719
+ import { closeSync, mkdirSync as mkdirSync8, openSync, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
8720
+ import { resolve as resolve15 } from "path";
9149
8721
  async function spawnServer(cwd, port, options) {
9150
8722
  let cmd = process.env.VOLUTE_NODE_PATH ?? process.execPath;
9151
8723
  let args = ["--import", "tsx", "src/server.ts", "--port", String(port)];
@@ -9166,34 +8738,34 @@ function spawnAttached(cmd, args, cwd) {
9166
8738
  cwd,
9167
8739
  stdio: ["ignore", "pipe", "pipe"]
9168
8740
  });
9169
- return new Promise((resolve21) => {
9170
- const timeout = setTimeout(() => resolve21(null), 3e4);
8741
+ return new Promise((resolve19) => {
8742
+ const timeout = setTimeout(() => resolve19(null), 3e4);
9171
8743
  function checkOutput(data) {
9172
8744
  const match = data.toString().match(/listening on :(\d+)/);
9173
8745
  if (match) {
9174
8746
  clearTimeout(timeout);
9175
- resolve21({ child, actualPort: parseInt(match[1], 10) });
8747
+ resolve19({ child, actualPort: parseInt(match[1], 10) });
9176
8748
  }
9177
8749
  }
9178
8750
  child.stdout?.on("data", checkOutput);
9179
8751
  child.stderr?.on("data", checkOutput);
9180
8752
  child.on("error", () => {
9181
8753
  clearTimeout(timeout);
9182
- resolve21(null);
8754
+ resolve19(null);
9183
8755
  });
9184
8756
  child.on("exit", () => {
9185
8757
  clearTimeout(timeout);
9186
- resolve21(null);
8758
+ resolve19(null);
9187
8759
  });
9188
8760
  });
9189
8761
  }
9190
8762
  function spawnDetached(cmd, args, cwd, logDir) {
9191
- const logsDir = logDir ?? resolve17(cwd, ".mind", "logs");
8763
+ const logsDir = logDir ?? resolve15(cwd, ".mind", "logs");
9192
8764
  mkdirSync8(logsDir, { recursive: true });
9193
- const logPath = resolve17(logsDir, "mind.log");
8765
+ const logPath = resolve15(logsDir, "mind.log");
9194
8766
  let startOffset = 0;
9195
8767
  try {
9196
- startOffset = statSync4(logPath).size;
8768
+ startOffset = statSync3(logPath).size;
9197
8769
  } catch {
9198
8770
  }
9199
8771
  const logFd = openSync(logPath, "a");
@@ -9331,11 +8903,11 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9331
8903
  return c.json({ error: `Name already in use: ${variantName}` }, 409);
9332
8904
  }
9333
8905
  const projectRoot = entry.dir ?? mindDir(mindName);
9334
- const variantDir = resolve18(projectRoot, ".variants", variantName);
9335
- if (existsSync11(variantDir)) {
8906
+ const variantDir = resolve16(projectRoot, ".variants", variantName);
8907
+ if (existsSync10(variantDir)) {
9336
8908
  return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
9337
8909
  }
9338
- mkdirSync9(resolve18(projectRoot, ".variants"), { recursive: true });
8910
+ mkdirSync9(resolve16(projectRoot, ".variants"), { recursive: true });
9339
8911
  try {
9340
8912
  await gitExec(["worktree", "add", "-b", variantName, variantDir], { cwd: projectRoot });
9341
8913
  } catch (e) {
@@ -9371,7 +8943,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9371
8943
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
9372
8944
  await exec(cmd, args, {
9373
8945
  cwd: variantDir,
9374
- env: { ...process.env, HOME: resolve18(variantDir, "home") }
8946
+ env: { ...process.env, HOME: resolve16(variantDir, "home") }
9375
8947
  });
9376
8948
  } else {
9377
8949
  await exec("npm", ["install"], { cwd: variantDir });
@@ -9382,7 +8954,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9382
8954
  return c.json({ error: `npm install failed: ${msg}` }, 500);
9383
8955
  }
9384
8956
  if (body.soul) {
9385
- writeFileSync10(resolve18(variantDir, "home/SOUL.md"), body.soul);
8957
+ writeFileSync10(resolve16(variantDir, "home/SOUL.md"), body.soul);
9386
8958
  }
9387
8959
  const variantPort = body.port ?? await nextPort();
9388
8960
  try {
@@ -9465,7 +9037,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9465
9037
  logger_default.warn(`farewell turn failed for ${variantName}`, logger_default.errorData(err));
9466
9038
  }
9467
9039
  try {
9468
- if (existsSync11(variantEntry.dir)) {
9040
+ if (existsSync10(variantEntry.dir)) {
9469
9041
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
9470
9042
  if (status) {
9471
9043
  try {
@@ -9523,7 +9095,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9523
9095
  { conflicts: err.conflicts }
9524
9096
  );
9525
9097
  }
9526
- if (existsSync11(variantEntry.dir) && !body.discardUnresolved) {
9098
+ if (existsSync10(variantEntry.dir) && !body.discardUnresolved) {
9527
9099
  let unresolved;
9528
9100
  try {
9529
9101
  unresolved = await findUnresolvedHomeFiles(variantEntry.dir);
@@ -9562,7 +9134,7 @@ var app22 = new Hono26().get("/:name/variants", async (c) => {
9562
9134
  const [cmd, args] = await wrapForIsolation("npm", ["install"], mindName);
9563
9135
  await exec(cmd, args, {
9564
9136
  cwd: projectRoot,
9565
- env: { ...process.env, HOME: resolve18(projectRoot, "home") }
9137
+ env: { ...process.env, HOME: resolve16(projectRoot, "home") }
9566
9138
  });
9567
9139
  } else {
9568
9140
  await exec("npm", ["install"], { cwd: projectRoot });
@@ -10057,11 +9629,11 @@ var app24 = new Hono28().get("/:name/conversations/:id/events", async (c) => {
10057
9629
  if (!stream.aborted) console.error("[chat] SSE ping error:", err);
10058
9630
  });
10059
9631
  }, 15e3);
10060
- await new Promise((resolve21) => {
9632
+ await new Promise((resolve19) => {
10061
9633
  stream.onAbort(() => {
10062
9634
  unsubscribe();
10063
9635
  clearInterval(keepAlive);
10064
- resolve21();
9636
+ resolve19();
10065
9637
  });
10066
9638
  });
10067
9639
  });
@@ -10278,10 +9850,10 @@ app26.route("/api/conversations", conversations_default);
10278
9850
  var app_default = app26;
10279
9851
 
10280
9852
  // packages/daemon/src/web/server.ts
10281
- import { existsSync as existsSync12 } from "fs";
9853
+ import { existsSync as existsSync11 } from "fs";
10282
9854
  import { readFile as readFile2, stat as stat2 } from "fs/promises";
10283
9855
  import { createServer as createHttpsServer } from "https";
10284
- import { dirname as dirname3, extname as extname3, resolve as resolve19 } from "path";
9856
+ import { dirname as dirname3, extname as extname3, resolve as resolve17 } from "path";
10285
9857
  import { serve } from "@hono/node-server";
10286
9858
  var MIME_TYPES2 = {
10287
9859
  ".html": "text/html",
@@ -10300,8 +9872,8 @@ async function startServer({
10300
9872
  let assetsDir = "";
10301
9873
  let searchDir = dirname3(new URL(import.meta.url).pathname);
10302
9874
  for (let i = 0; i < 5; i++) {
10303
- const candidate = resolve19(searchDir, "dist", "web-assets");
10304
- if (existsSync12(candidate)) {
9875
+ const candidate = resolve17(searchDir, "dist", "web-assets");
9876
+ if (existsSync11(candidate)) {
10305
9877
  assetsDir = candidate;
10306
9878
  break;
10307
9879
  }
@@ -10311,7 +9883,7 @@ async function startServer({
10311
9883
  app_default.get("*", async (c) => {
10312
9884
  const urlPath = new URL(c.req.url).pathname;
10313
9885
  if (urlPath.startsWith("/api/") || urlPath.startsWith("/ext/")) return c.notFound();
10314
- const filePath = resolve19(assetsDir, urlPath.slice(1));
9886
+ const filePath = resolve17(assetsDir, urlPath.slice(1));
10315
9887
  if (!filePath.startsWith(assetsDir)) return c.text("Forbidden", 403);
10316
9888
  const s = await stat2(filePath).catch(() => null);
10317
9889
  if (s?.isFile()) {
@@ -10324,7 +9896,7 @@ async function startServer({
10324
9896
  const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "no-cache";
10325
9897
  return c.body(body, 200, { "Content-Type": mime, "Cache-Control": cacheControl });
10326
9898
  }
10327
- const indexPath = resolve19(assetsDir, "index.html");
9899
+ const indexPath = resolve17(assetsDir, "index.html");
10328
9900
  const indexStat = await stat2(indexPath).catch(() => null);
10329
9901
  if (indexStat?.isFile()) {
10330
9902
  const body = await readFile2(indexPath, "utf-8");
@@ -10341,10 +9913,10 @@ async function startServer({
10341
9913
  createServer: createHttpsServer,
10342
9914
  serverOptions: { key: tls.key, cert: tls.cert }
10343
9915
  });
10344
- await new Promise((resolve21, reject) => {
9916
+ await new Promise((resolve19, reject) => {
10345
9917
  server2.on("listening", () => {
10346
9918
  logger_default.info("Volute UI running (https)", { hostname, port });
10347
- resolve21();
9919
+ resolve19();
10348
9920
  });
10349
9921
  server2.on("error", (err) => {
10350
9922
  reject(err);
@@ -10352,13 +9924,13 @@ async function startServer({
10352
9924
  });
10353
9925
  const internalPort = port + 1;
10354
9926
  const internalServer = serve({ fetch: app_default.fetch, port: internalPort, hostname: "127.0.0.1" });
10355
- await new Promise((resolve21, reject) => {
9927
+ await new Promise((resolve19, reject) => {
10356
9928
  internalServer.on("listening", () => {
10357
9929
  logger_default.info("Volute API running (http, internal)", {
10358
9930
  hostname: "127.0.0.1",
10359
9931
  port: internalPort
10360
9932
  });
10361
- resolve21();
9933
+ resolve19();
10362
9934
  });
10363
9935
  internalServer.on("error", (err) => {
10364
9936
  reject(err);
@@ -10367,10 +9939,10 @@ async function startServer({
10367
9939
  return { server: server2, internalPort };
10368
9940
  }
10369
9941
  const server = serve({ fetch: app_default.fetch, port, hostname });
10370
- await new Promise((resolve21, reject) => {
9942
+ await new Promise((resolve19, reject) => {
10371
9943
  server.on("listening", () => {
10372
9944
  logger_default.info("Volute API running (http)", { hostname, port });
10373
- resolve21();
9945
+ resolve19();
10374
9946
  });
10375
9947
  server.on("error", (err) => {
10376
9948
  reject(err);
@@ -10381,17 +9953,17 @@ async function startServer({
10381
9953
 
10382
9954
  // packages/daemon/src/daemon.ts
10383
9955
  if (!process.env.VOLUTE_HOME) {
10384
- process.env.VOLUTE_HOME = resolve20(homedir3(), ".volute");
9956
+ process.env.VOLUTE_HOME = resolve18(homedir3(), ".volute");
10385
9957
  }
10386
9958
  if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
10387
9959
  process.env.TZ = process.env.VOLUTE_TIMEZONE;
10388
9960
  }
10389
9961
  function writeDaemonConfig(systemDir, config2, token) {
10390
- const configPath = resolve20(systemDir, "daemon.json");
9962
+ const configPath = resolve18(systemDir, "daemon.json");
10391
9963
  writeFileSync11(configPath, `${JSON.stringify(config2, null, 2)}
10392
9964
  `, { mode: 420 });
10393
9965
  chmodSync(configPath, 420);
10394
- const tokenPath = resolve20(systemDir, "daemon-token");
9966
+ const tokenPath = resolve18(systemDir, "daemon-token");
10395
9967
  writeFileSync11(tokenPath, `${token}
10396
9968
  `, { mode: 384 });
10397
9969
  chmodSync(tokenPath, 384);
@@ -10402,7 +9974,7 @@ async function startDaemon(opts) {
10402
9974
  const home = voluteHome();
10403
9975
  const systemDir = voluteSystemDir();
10404
9976
  if (!opts.foreground) {
10405
- const rotatingLog = new RotatingLog(resolve20(systemDir, "daemon.log"));
9977
+ const rotatingLog = new RotatingLog(resolve18(systemDir, "daemon.log"));
10406
9978
  logger_default.setOutput((line) => rotatingLog.write(`${line}
10407
9979
  `));
10408
9980
  const write = (...args) => rotatingLog.write(`${format(...args)}
@@ -10412,9 +9984,9 @@ async function startDaemon(opts) {
10412
9984
  console.warn = write;
10413
9985
  console.info = write;
10414
9986
  }
10415
- const DAEMON_PID_PATH = resolve20(systemDir, "daemon.pid");
10416
- const DAEMON_JSON_PATH = resolve20(systemDir, "daemon.json");
10417
- const DAEMON_TOKEN_PATH = resolve20(systemDir, "daemon-token");
9987
+ const DAEMON_PID_PATH = resolve18(systemDir, "daemon.pid");
9988
+ const DAEMON_JSON_PATH = resolve18(systemDir, "daemon.json");
9989
+ const DAEMON_TOKEN_PATH = resolve18(systemDir, "daemon-token");
10418
9990
  mkdirSync10(home, { recursive: true });
10419
9991
  ensureSystemDir();
10420
9992
  const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-WZSXHHRJ.js");
@@ -10443,6 +10015,12 @@ async function startDaemon(opts) {
10443
10015
  } catch (err) {
10444
10016
  logger_default.warn("session\u2192thread config migration failed", logger_default.errorData(err));
10445
10017
  }
10018
+ try {
10019
+ const { migrateNamePlaceholders } = await import("./migrate-name-placeholder-C7NCNLWF.js");
10020
+ await migrateNamePlaceholders();
10021
+ } catch (err) {
10022
+ logger_default.warn("{{name}} placeholder migration failed", logger_default.errorData(err));
10023
+ }
10446
10024
  const { initSandbox } = await import("./sandbox-NNWCTHRI.js");
10447
10025
  await initSandbox();
10448
10026
  try {
@@ -10543,7 +10121,7 @@ async function startDaemon(opts) {
10543
10121
  const orphanedTurns = await completeOrphanedTurns();
10544
10122
  summarizeOrphanedTurns(orphanedTurns);
10545
10123
  try {
10546
- const { reconcileVariants } = await import("./variant-cleanup-CZDLIY3F.js");
10124
+ const { reconcileVariants } = await import("./variant-cleanup-QHGGY7ND.js");
10547
10125
  await reconcileVariants();
10548
10126
  } catch (err) {
10549
10127
  logger_default.error("failed to reconcile variants", logger_default.errorData(err));
@@ -10579,16 +10157,17 @@ async function startDaemon(opts) {
10579
10157
  try {
10580
10158
  const { isSetupComplete: isSetupComplete2, getSpiritName: getSpiritName2 } = await import("./setup-WZSXHHRJ.js");
10581
10159
  if (isSetupComplete2()) {
10582
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-I5ECLGRI.js");
10583
- const { startSpiritFull } = await import("./mind-service-WHFBUKZE.js");
10160
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-Q5VGFWUI.js");
10161
+ const { startSpiritFull } = await import("./mind-service-7EFIJ3ZA.js");
10584
10162
  await ensureSpiritProject();
10585
10163
  const spiritName = getSpiritName2();
10586
10164
  const spiritEntry = await findMind(spiritName);
10587
10165
  if (spiritEntry?.dir) {
10588
- const { registerMindDir } = await import("./delivery-router-RHANNTAC.js");
10166
+ const { registerMindDir } = await import("./delivery-router-QS4NLJR6.js");
10589
10167
  registerMindDir(spiritName, spiritEntry.dir);
10590
10168
  }
10591
10169
  await syncSpiritTemplate();
10170
+ if (spiritEntry) await notifyExtensionsSpiritReady();
10592
10171
  if (spiritEntry && !manager.isRunning(spiritName)) {
10593
10172
  await startSpiritFull(spiritName);
10594
10173
  }
@@ -10599,7 +10178,7 @@ async function startDaemon(opts) {
10599
10178
  bridgeManager.startBridges(daemonPort).catch((err) => {
10600
10179
  logger_default.warn("failed to start bridges", logger_default.errorData(err));
10601
10180
  });
10602
- import("./cloud-sync-MJVJ33LD.js").then(
10181
+ import("./cloud-sync-52YNJRMR.js").then(
10603
10182
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
10604
10183
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
10605
10184
  })
@@ -10607,12 +10186,14 @@ async function startDaemon(opts) {
10607
10186
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
10608
10187
  });
10609
10188
  try {
10610
- const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-SJVAQLZI.js");
10611
- backfillTemplateHashes().then(() => warnStaleTemplates()).catch((err) => {
10612
- logger_default.warn("failed to check template staleness", logger_default.errorData(err));
10613
- });
10189
+ const { backfillTemplateHashes, notifyVersionUpdate, warnStaleTemplates } = await import("./version-notify-VNVFX6UP.js");
10614
10190
  notifyVersionUpdate().catch((err) => {
10615
10191
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
10192
+ }).then(() => backfillTemplateHashes()).then(() => warnStaleTemplates()).then(async () => {
10193
+ const { runAutoUpgrades } = await import("./auto-upgrade-HEVZKPTF.js");
10194
+ await runAutoUpgrades();
10195
+ }).catch((err) => {
10196
+ logger_default.warn("template staleness/auto-upgrade pass failed", logger_default.errorData(err));
10616
10197
  });
10617
10198
  } catch (err) {
10618
10199
  logger_default.warn("failed to initialize version notifications", logger_default.errorData(err));
@@ -10621,6 +10202,9 @@ async function startDaemon(opts) {
10621
10202
  logger_default.warn("failed to restore delivery queue", logger_default.errorData(err));
10622
10203
  });
10623
10204
  delivery.startRedrive();
10205
+ delivery.releaseGatedSweep().catch((err) => {
10206
+ logger_default.warn("failed to sweep gated messages", logger_default.errorData(err));
10207
+ });
10624
10208
  cleanExpiredSessions().catch((err) => {
10625
10209
  logger_default.warn("failed to clean expired sessions", logger_default.errorData(err));
10626
10210
  });