@goondocks/myco 0.17.2 → 0.18.1

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 (196) hide show
  1. package/README.md +14 -22
  2. package/bin/myco-run +15 -2
  3. package/dist/{agent-run-7AYHXIEF.js → agent-run-I4O2K2CK.js} +7 -7
  4. package/dist/{agent-tasks-UUIFKBD4.js → agent-tasks-UOW5BQIB.js} +7 -7
  5. package/dist/{chunk-XD3NEN3Q.js → chunk-2V7HR7HB.js} +2 -2
  6. package/dist/chunk-44PZCAYS.js +107 -0
  7. package/dist/chunk-44PZCAYS.js.map +1 -0
  8. package/dist/{chunk-DT42247G.js → chunk-75AZFBFW.js} +3 -3
  9. package/dist/{chunk-RMJPQZGF.js → chunk-C3EGL5JX.js} +755 -266
  10. package/dist/chunk-C3EGL5JX.js.map +1 -0
  11. package/dist/{chunk-7DAH5GLC.js → chunk-CKJAWZQE.js} +5 -1
  12. package/dist/chunk-CKJAWZQE.js.map +1 -0
  13. package/dist/{chunk-ML6GTPZU.js → chunk-CML4MCYF.js} +2 -2
  14. package/dist/{chunk-UTLWSKDV.js → chunk-CURS2TNP.js} +45 -4
  15. package/dist/chunk-CURS2TNP.js.map +1 -0
  16. package/dist/{chunk-EBIYONNZ.js → chunk-DPSLJ242.js} +34 -2
  17. package/dist/chunk-DPSLJ242.js.map +1 -0
  18. package/dist/{chunk-BZDZORVP.js → chunk-LSP5HYOO.js} +19 -16
  19. package/dist/chunk-LSP5HYOO.js.map +1 -0
  20. package/dist/{chunk-NUSTG3BH.js → chunk-N75GMQGA.js} +3 -3
  21. package/dist/{chunk-F6C4IC6R.js → chunk-NI23QCHB.js} +3 -3
  22. package/dist/{chunk-C3C5QVLK.js → chunk-O3TRN3RC.js} +2 -2
  23. package/dist/{chunk-3NCVCGUZ.js → chunk-RAV5YMRU.js} +3 -3
  24. package/dist/{chunk-25WHTV4N.js → chunk-RIDSOQDR.js} +21 -7
  25. package/dist/chunk-RIDSOQDR.js.map +1 -0
  26. package/dist/{chunk-HPZ7YAMA.js → chunk-TCSVDQF5.js} +1130 -195
  27. package/dist/chunk-TCSVDQF5.js.map +1 -0
  28. package/dist/{chunk-CTF7TQMJ.js → chunk-TLK46KKD.js} +14 -4
  29. package/dist/chunk-TLK46KKD.js.map +1 -0
  30. package/dist/{chunk-IGBHLFV5.js → chunk-TOER6RNC.js} +22 -2
  31. package/dist/chunk-TOER6RNC.js.map +1 -0
  32. package/dist/{chunk-ZSJPI5MS.js → chunk-TZAXQKO6.js} +6 -2
  33. package/dist/chunk-TZAXQKO6.js.map +1 -0
  34. package/dist/{chunk-RKPTMHED.js → chunk-U3J2DDSR.js} +2 -2
  35. package/dist/{chunk-SI5BBQAT.js → chunk-W7WENJ6F.js} +2 -2
  36. package/dist/{chunk-VVGZL2HX.js → chunk-WYOE4IAX.js} +153 -15
  37. package/dist/{chunk-VVGZL2HX.js.map → chunk-WYOE4IAX.js.map} +1 -1
  38. package/dist/{chunk-XZWFMMJR.js → chunk-XWOQL4XN.js} +3 -3
  39. package/dist/{chunk-5ZISXCDC.js → chunk-YZPI2Y3E.js} +39 -5
  40. package/dist/chunk-YZPI2Y3E.js.map +1 -0
  41. package/dist/{cli-WJVYP2QT.js → cli-D3TJYJ2U.js} +40 -40
  42. package/dist/{client-LZ3ZR4HC.js → client-4LLEXLVK.js} +4 -4
  43. package/dist/{config-ZQIMG3FB.js → config-DA4IUVFL.js} +3 -3
  44. package/dist/{detect-NJ2OREDP.js → detect-SZ2KDUF4.js} +2 -2
  45. package/dist/{detect-providers-C64L3QET.js → detect-providers-PSVKXTWE.js} +4 -4
  46. package/dist/{doctor-XEPBNHM3.js → doctor-KCTXPX5D.js} +12 -12
  47. package/dist/{executor-NXKJU5KW.js → executor-UYIZC3L5.js} +93 -285
  48. package/dist/executor-UYIZC3L5.js.map +1 -0
  49. package/dist/{init-BHVQAQ27.js → init-QFNBKKDC.js} +13 -13
  50. package/dist/{installer-45ZLP2RP.js → installer-BWJED3ED.js} +2 -2
  51. package/dist/{llm-KTD6SR55.js → llm-SMA5ZEAW.js} +4 -4
  52. package/dist/{loader-SHRKUKOS.js → loader-Q3P3R4UP.js} +3 -3
  53. package/dist/{loader-NEX3UF6U.js → loader-SKKUMT5C.js} +3 -3
  54. package/dist/{main-YFVBIRRK.js → main-5THODR77.js} +751 -257
  55. package/dist/main-5THODR77.js.map +1 -0
  56. package/dist/{open-2U7ZRGA3.js → open-7737CSPN.js} +7 -7
  57. package/dist/{post-compact-QIBMEWL3.js → post-compact-2TJ5FPZH.js} +7 -7
  58. package/dist/{post-tool-use-ICGFXDVY.js → post-tool-use-FRTSICC3.js} +6 -6
  59. package/dist/{post-tool-use-failure-C7TLH3XQ.js → post-tool-use-failure-KYO2NCNB.js} +7 -7
  60. package/dist/{pre-compact-IF7K4TQK.js → pre-compact-J6GCJEJR.js} +7 -7
  61. package/dist/{provider-check-LTLQ6BUZ.js → provider-check-AE3L5Z6R.js} +4 -4
  62. package/dist/{registry-TFQ22Z7N.js → registry-O2NZLO3V.js} +4 -4
  63. package/dist/{remove-FBGM2QVJ.js → remove-3WZZC7AX.js} +9 -9
  64. package/dist/{resolution-events-HGKIJOTA.js → resolution-events-XWYLLDRK.js} +4 -4
  65. package/dist/{restart-TQEECRNW.js → restart-HUHEFOXU.js} +8 -8
  66. package/dist/{search-NN5FC4Z6.js → search-ZGN3LDXG.js} +8 -8
  67. package/dist/{server-XMWJ4GF7.js → server-PTXLVVEE.js} +4 -4
  68. package/dist/{session-GLPAFYPO.js → session-7VV3IQMO.js} +9 -9
  69. package/dist/{session-end-TI3ILRBC.js → session-end-SMU55UCM.js} +6 -6
  70. package/dist/{session-start-PJLJDVJJ.js → session-start-NIMWEOIZ.js} +29 -13
  71. package/dist/session-start-NIMWEOIZ.js.map +1 -0
  72. package/dist/{setup-llm-AQSWLXCZ.js → setup-llm-7S3VPAPN.js} +8 -8
  73. package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
  74. package/dist/src/agent/definitions/tasks/full-intelligence.yaml +10 -0
  75. package/dist/src/agent/definitions/tasks/skill-evolve.yaml +163 -49
  76. package/dist/src/agent/definitions/tasks/skill-generate.yaml +44 -27
  77. package/dist/src/agent/definitions/tasks/skill-survey.yaml +132 -138
  78. package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
  79. package/dist/src/cli.js +1 -1
  80. package/dist/src/daemon/main.js +1 -1
  81. package/dist/src/hooks/post-tool-use.js +1 -1
  82. package/dist/src/hooks/session-end.js +1 -1
  83. package/dist/src/hooks/session-start.js +1 -1
  84. package/dist/src/hooks/stop.js +1 -1
  85. package/dist/src/hooks/user-prompt-submit.js +1 -1
  86. package/dist/src/mcp/server.js +1 -1
  87. package/dist/src/symbionts/manifests/codex.yaml +85 -0
  88. package/dist/src/symbionts/templates/claude-code/hooks.json +12 -12
  89. package/dist/src/symbionts/templates/claude-code/settings.json +3 -3
  90. package/dist/src/symbionts/templates/codex/hooks.json +4 -4
  91. package/dist/src/symbionts/templates/cursor/hooks.json +9 -9
  92. package/dist/src/symbionts/templates/cursor/settings.json +2 -2
  93. package/dist/src/symbionts/templates/gemini/hooks.json +6 -6
  94. package/dist/src/symbionts/templates/gemini/settings.json +2 -2
  95. package/dist/src/symbionts/templates/myco-run.cjs +44 -0
  96. package/dist/src/symbionts/templates/opencode/settings.json +2 -2
  97. package/dist/src/symbionts/templates/vscode-copilot/hooks.json +7 -7
  98. package/dist/src/symbionts/templates/vscode-copilot/settings.json +2 -2
  99. package/dist/src/symbionts/templates/windsurf/hooks.json +4 -4
  100. package/dist/src/symbionts/templates/windsurf/settings.json +2 -2
  101. package/dist/src/worker/package-lock.json +4338 -0
  102. package/dist/src/worker/package.json +5 -0
  103. package/dist/src/worker/src/index.ts +58 -65
  104. package/dist/src/worker/src/mcp/auth.ts +65 -0
  105. package/dist/src/worker/src/mcp/server.ts +53 -0
  106. package/dist/src/worker/src/mcp/tools/context.ts +13 -0
  107. package/dist/src/worker/src/mcp/tools/get.ts +15 -0
  108. package/dist/src/worker/src/mcp/tools/graph.ts +35 -0
  109. package/dist/src/worker/src/mcp/tools/search.ts +32 -0
  110. package/dist/src/worker/src/mcp/tools/sessions.ts +24 -0
  111. package/dist/src/worker/src/mcp/tools/skills.ts +16 -0
  112. package/dist/src/worker/src/mcp/tools/team.ts +9 -0
  113. package/dist/src/worker/src/schema.ts +5 -1
  114. package/dist/src/worker/src/search-helpers.ts +70 -0
  115. package/dist/src/worker/wrangler.toml +9 -0
  116. package/dist/{stats-BISBIBXZ.js → stats-GEOQ2DFF.js} +9 -9
  117. package/dist/{stop-47BJ42EO.js → stop-7AKYBJJ2.js} +6 -6
  118. package/dist/{stop-failure-VU5BTLWX.js → stop-failure-NLE2EURG.js} +7 -7
  119. package/dist/{subagent-start-SPTKQRHU.js → subagent-start-LBNZF2TG.js} +7 -7
  120. package/dist/{subagent-stop-UU75BYLC.js → subagent-stop-B2Z5GYAB.js} +7 -7
  121. package/dist/{task-completed-MVDO7TZF.js → task-completed-PO5TETJ7.js} +7 -7
  122. package/dist/{team-7X64J4Y6.js → team-DPNP2RN7.js} +97 -14
  123. package/dist/team-DPNP2RN7.js.map +1 -0
  124. package/dist/ui/assets/{index-rpmSpJpm.js → index-CiI1fwas.js} +120 -120
  125. package/dist/ui/index.html +1 -1
  126. package/dist/{update-DA7VEXOS.js → update-WBWB5URU.js} +18 -9
  127. package/dist/update-WBWB5URU.js.map +1 -0
  128. package/dist/{user-prompt-submit-ADZ4NTVO.js → user-prompt-submit-IZJC3NV7.js} +30 -7
  129. package/dist/user-prompt-submit-IZJC3NV7.js.map +1 -0
  130. package/dist/{verify-QYSERHF7.js → verify-FNSP62I3.js} +5 -5
  131. package/dist/{version-A72TAL2J.js → version-QEVU66NT.js} +2 -2
  132. package/package.json +7 -7
  133. package/dist/chunk-25WHTV4N.js.map +0 -1
  134. package/dist/chunk-5ZISXCDC.js.map +0 -1
  135. package/dist/chunk-7DAH5GLC.js.map +0 -1
  136. package/dist/chunk-BZDZORVP.js.map +0 -1
  137. package/dist/chunk-CTF7TQMJ.js.map +0 -1
  138. package/dist/chunk-EBIYONNZ.js.map +0 -1
  139. package/dist/chunk-HPZ7YAMA.js.map +0 -1
  140. package/dist/chunk-IGBHLFV5.js.map +0 -1
  141. package/dist/chunk-RMJPQZGF.js.map +0 -1
  142. package/dist/chunk-UTLWSKDV.js.map +0 -1
  143. package/dist/chunk-ZSJPI5MS.js.map +0 -1
  144. package/dist/executor-NXKJU5KW.js.map +0 -1
  145. package/dist/main-YFVBIRRK.js.map +0 -1
  146. package/dist/session-start-PJLJDVJJ.js.map +0 -1
  147. package/dist/src/symbionts/templates/hook-guard.cjs +0 -19
  148. package/dist/team-7X64J4Y6.js.map +0 -1
  149. package/dist/update-DA7VEXOS.js.map +0 -1
  150. package/dist/user-prompt-submit-ADZ4NTVO.js.map +0 -1
  151. /package/dist/{agent-run-7AYHXIEF.js.map → agent-run-I4O2K2CK.js.map} +0 -0
  152. /package/dist/{agent-tasks-UUIFKBD4.js.map → agent-tasks-UOW5BQIB.js.map} +0 -0
  153. /package/dist/{chunk-XD3NEN3Q.js.map → chunk-2V7HR7HB.js.map} +0 -0
  154. /package/dist/{chunk-DT42247G.js.map → chunk-75AZFBFW.js.map} +0 -0
  155. /package/dist/{chunk-ML6GTPZU.js.map → chunk-CML4MCYF.js.map} +0 -0
  156. /package/dist/{chunk-NUSTG3BH.js.map → chunk-N75GMQGA.js.map} +0 -0
  157. /package/dist/{chunk-F6C4IC6R.js.map → chunk-NI23QCHB.js.map} +0 -0
  158. /package/dist/{chunk-C3C5QVLK.js.map → chunk-O3TRN3RC.js.map} +0 -0
  159. /package/dist/{chunk-3NCVCGUZ.js.map → chunk-RAV5YMRU.js.map} +0 -0
  160. /package/dist/{chunk-RKPTMHED.js.map → chunk-U3J2DDSR.js.map} +0 -0
  161. /package/dist/{chunk-SI5BBQAT.js.map → chunk-W7WENJ6F.js.map} +0 -0
  162. /package/dist/{chunk-XZWFMMJR.js.map → chunk-XWOQL4XN.js.map} +0 -0
  163. /package/dist/{cli-WJVYP2QT.js.map → cli-D3TJYJ2U.js.map} +0 -0
  164. /package/dist/{client-LZ3ZR4HC.js.map → client-4LLEXLVK.js.map} +0 -0
  165. /package/dist/{config-ZQIMG3FB.js.map → config-DA4IUVFL.js.map} +0 -0
  166. /package/dist/{detect-NJ2OREDP.js.map → detect-SZ2KDUF4.js.map} +0 -0
  167. /package/dist/{detect-providers-C64L3QET.js.map → detect-providers-PSVKXTWE.js.map} +0 -0
  168. /package/dist/{doctor-XEPBNHM3.js.map → doctor-KCTXPX5D.js.map} +0 -0
  169. /package/dist/{init-BHVQAQ27.js.map → init-QFNBKKDC.js.map} +0 -0
  170. /package/dist/{installer-45ZLP2RP.js.map → installer-BWJED3ED.js.map} +0 -0
  171. /package/dist/{llm-KTD6SR55.js.map → llm-SMA5ZEAW.js.map} +0 -0
  172. /package/dist/{loader-NEX3UF6U.js.map → loader-Q3P3R4UP.js.map} +0 -0
  173. /package/dist/{loader-SHRKUKOS.js.map → loader-SKKUMT5C.js.map} +0 -0
  174. /package/dist/{open-2U7ZRGA3.js.map → open-7737CSPN.js.map} +0 -0
  175. /package/dist/{post-compact-QIBMEWL3.js.map → post-compact-2TJ5FPZH.js.map} +0 -0
  176. /package/dist/{post-tool-use-ICGFXDVY.js.map → post-tool-use-FRTSICC3.js.map} +0 -0
  177. /package/dist/{post-tool-use-failure-C7TLH3XQ.js.map → post-tool-use-failure-KYO2NCNB.js.map} +0 -0
  178. /package/dist/{pre-compact-IF7K4TQK.js.map → pre-compact-J6GCJEJR.js.map} +0 -0
  179. /package/dist/{provider-check-LTLQ6BUZ.js.map → provider-check-AE3L5Z6R.js.map} +0 -0
  180. /package/dist/{registry-TFQ22Z7N.js.map → registry-O2NZLO3V.js.map} +0 -0
  181. /package/dist/{remove-FBGM2QVJ.js.map → remove-3WZZC7AX.js.map} +0 -0
  182. /package/dist/{resolution-events-HGKIJOTA.js.map → resolution-events-XWYLLDRK.js.map} +0 -0
  183. /package/dist/{restart-TQEECRNW.js.map → restart-HUHEFOXU.js.map} +0 -0
  184. /package/dist/{search-NN5FC4Z6.js.map → search-ZGN3LDXG.js.map} +0 -0
  185. /package/dist/{server-XMWJ4GF7.js.map → server-PTXLVVEE.js.map} +0 -0
  186. /package/dist/{session-GLPAFYPO.js.map → session-7VV3IQMO.js.map} +0 -0
  187. /package/dist/{session-end-TI3ILRBC.js.map → session-end-SMU55UCM.js.map} +0 -0
  188. /package/dist/{setup-llm-AQSWLXCZ.js.map → setup-llm-7S3VPAPN.js.map} +0 -0
  189. /package/dist/{stats-BISBIBXZ.js.map → stats-GEOQ2DFF.js.map} +0 -0
  190. /package/dist/{stop-47BJ42EO.js.map → stop-7AKYBJJ2.js.map} +0 -0
  191. /package/dist/{stop-failure-VU5BTLWX.js.map → stop-failure-NLE2EURG.js.map} +0 -0
  192. /package/dist/{subagent-start-SPTKQRHU.js.map → subagent-start-LBNZF2TG.js.map} +0 -0
  193. /package/dist/{subagent-stop-UU75BYLC.js.map → subagent-stop-B2Z5GYAB.js.map} +0 -0
  194. /package/dist/{task-completed-MVDO7TZF.js.map → task-completed-PO5TETJ7.js.map} +0 -0
  195. /package/dist/{verify-QYSERHF7.js.map → verify-FNSP62I3.js.map} +0 -0
  196. /package/dist/{version-A72TAL2J.js.map → version-QEVU66NT.js.map} +0 -0
@@ -15,7 +15,7 @@ import {
15
15
  getEmbeddingQueueDepth,
16
16
  getUnembedded,
17
17
  markEmbedded
18
- } from "./chunk-BZDZORVP.js";
18
+ } from "./chunk-LSP5HYOO.js";
19
19
  import {
20
20
  loadSecrets,
21
21
  readSecrets,
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  Anthropic,
26
26
  createEmbeddingProvider
27
- } from "./chunk-HPZ7YAMA.js";
27
+ } from "./chunk-TCSVDQF5.js";
28
28
  import {
29
29
  buildTaskInstruction,
30
30
  closeOpenBatches,
@@ -72,24 +72,24 @@ import {
72
72
  setResponseSummary,
73
73
  updateCandidate,
74
74
  updateNotificationStatus
75
- } from "./chunk-RMJPQZGF.js";
75
+ } from "./chunk-C3EGL5JX.js";
76
76
  import {
77
77
  fullTextSearch,
78
78
  hydrateSearchResults
79
- } from "./chunk-IGBHLFV5.js";
79
+ } from "./chunk-TOER6RNC.js";
80
80
  import {
81
81
  copyTaskToUser,
82
82
  deleteUserTask,
83
83
  loadAllTasks,
84
84
  validateTaskName,
85
85
  writeUserTask
86
- } from "./chunk-3NCVCGUZ.js";
86
+ } from "./chunk-RAV5YMRU.js";
87
87
  import {
88
88
  AgentTaskSchema,
89
89
  registerAgent,
90
90
  resolveDefinitionsDir,
91
91
  taskFromParsed
92
- } from "./chunk-F6C4IC6R.js";
92
+ } from "./chunk-NI23QCHB.js";
93
93
  import {
94
94
  listTurnsByRun
95
95
  } from "./chunk-QLCD77AN.js";
@@ -106,23 +106,23 @@ import {
106
106
  listBufferSessionIds
107
107
  } from "./chunk-V7XG6V6C.js";
108
108
  import "./chunk-IB76KGBY.js";
109
- import "./chunk-CTF7TQMJ.js";
109
+ import "./chunk-TLK46KKD.js";
110
110
  import "./chunk-SAKJMNSR.js";
111
- import "./chunk-VVGZL2HX.js";
111
+ import "./chunk-WYOE4IAX.js";
112
112
  import {
113
113
  checkLocalProvider
114
- } from "./chunk-DT42247G.js";
114
+ } from "./chunk-75AZFBFW.js";
115
115
  import {
116
116
  LmStudioBackend,
117
117
  OllamaBackend
118
- } from "./chunk-ML6GTPZU.js";
118
+ } from "./chunk-CML4MCYF.js";
119
119
  import {
120
120
  countSpores,
121
121
  getSpore,
122
122
  insertSpore,
123
123
  listSpores,
124
124
  updateSporeStatus
125
- } from "./chunk-ZSJPI5MS.js";
125
+ } from "./chunk-TZAXQKO6.js";
126
126
  import {
127
127
  closeSession,
128
128
  countSessions,
@@ -133,7 +133,7 @@ import {
133
133
  listSessions,
134
134
  updateSession,
135
135
  upsertSession
136
- } from "./chunk-25WHTV4N.js";
136
+ } from "./chunk-RIDSOQDR.js";
137
137
  import {
138
138
  backfillUnsynced,
139
139
  countDeadLettered,
@@ -149,13 +149,13 @@ import {
149
149
  pruneOld,
150
150
  retryDeadLettered,
151
151
  syncRow
152
- } from "./chunk-C3C5QVLK.js";
152
+ } from "./chunk-O3TRN3RC.js";
153
153
  import {
154
154
  EMBEDDING_DIMENSIONS,
155
155
  REST_SETTABLE_STATUSES,
156
156
  SCHEMA_VERSION,
157
157
  createSchema
158
- } from "./chunk-UTLWSKDV.js";
158
+ } from "./chunk-CURS2TNP.js";
159
159
  import {
160
160
  CONFIG_FILENAME,
161
161
  MycoConfigSchema,
@@ -164,7 +164,7 @@ import {
164
164
  updateBackupConfig,
165
165
  updateConfig,
166
166
  updateTeamConfig
167
- } from "./chunk-XD3NEN3Q.js";
167
+ } from "./chunk-2V7HR7HB.js";
168
168
  import {
169
169
  closeDatabase,
170
170
  getDatabase,
@@ -173,13 +173,13 @@ import {
173
173
  } from "./chunk-MYX5NCRH.js";
174
174
  import {
175
175
  resolveCliEntryPath
176
- } from "./chunk-XZWFMMJR.js";
176
+ } from "./chunk-XWOQL4XN.js";
177
177
  import {
178
178
  getPluginVersion
179
- } from "./chunk-SI5BBQAT.js";
179
+ } from "./chunk-W7WENJ6F.js";
180
180
  import {
181
181
  loadManifests
182
- } from "./chunk-EBIYONNZ.js";
182
+ } from "./chunk-DPSLJ242.js";
183
183
  import {
184
184
  findPackageRoot
185
185
  } from "./chunk-LPUQPDC2.js";
@@ -213,6 +213,7 @@ import {
213
213
  PROMPT_PREVIEW_CHARS,
214
214
  PROMPT_VECTOR_OVER_FETCH,
215
215
  RELEASE_CHANNELS,
216
+ RESTART_REASON_FILENAME,
216
217
  RESTART_RESPONSE_FLUSH_MS,
217
218
  SEARCH_RESULTS_DEFAULT_LIMIT,
218
219
  SEARCH_SIMILARITY_THRESHOLD,
@@ -228,12 +229,13 @@ import {
228
229
  UPDATE_CONFIG_PATH,
229
230
  UPDATE_ERROR_PATH,
230
231
  UPDATE_SCRIPT_DELAY_SECONDS,
232
+ UPDATE_STAMP_FILENAME,
231
233
  USER_AGENT_ID,
232
234
  USER_AGENT_NAME,
233
235
  USER_TASK_SOURCE,
234
236
  epochSeconds,
235
237
  estimateTokens
236
- } from "./chunk-7DAH5GLC.js";
238
+ } from "./chunk-CKJAWZQE.js";
237
239
  import {
238
240
  LOG_KINDS,
239
241
  kindToComponent
@@ -370,7 +372,7 @@ var DaemonServer = class {
370
372
  this.router.add(method, routePath, handler);
371
373
  }
372
374
  async start(port = 0) {
373
- return new Promise((resolve, reject) => {
375
+ return new Promise((resolve3, reject) => {
374
376
  this.server = http.createServer((req, res) => this.handleRequest(req, res));
375
377
  this.server.on("error", reject);
376
378
  this.server.listen(port, "127.0.0.1", () => {
@@ -378,20 +380,20 @@ var DaemonServer = class {
378
380
  this.port = addr.port;
379
381
  this.writeDaemonJson();
380
382
  this.logger.info(LOG_KINDS.DAEMON_PORT, "Server started", { port: this.port, dashboard: `http://localhost:${this.port}/` });
381
- resolve();
383
+ resolve3();
382
384
  });
383
385
  });
384
386
  }
385
387
  async stop() {
386
- return new Promise((resolve) => {
388
+ return new Promise((resolve3) => {
387
389
  this.removeDaemonJson();
388
390
  if (this.server) {
389
391
  this.server.close(() => {
390
392
  this.logger.info(LOG_KINDS.DAEMON_START, "Server stopped");
391
- resolve();
393
+ resolve3();
392
394
  });
393
395
  } else {
394
- resolve();
396
+ resolve3();
395
397
  }
396
398
  });
397
399
  }
@@ -539,14 +541,14 @@ var DaemonServer = class {
539
541
  }
540
542
  };
541
543
  function readBody(req) {
542
- return new Promise((resolve, reject) => {
544
+ return new Promise((resolve3, reject) => {
543
545
  let data = "";
544
546
  req.on("data", (chunk) => {
545
547
  data += chunk;
546
548
  });
547
549
  req.on("end", () => {
548
550
  try {
549
- resolve(data ? JSON.parse(data) : {});
551
+ resolve3(data ? JSON.parse(data) : {});
550
552
  } catch (e) {
551
553
  reject(e);
552
554
  }
@@ -626,11 +628,11 @@ async function resolvePort(configPort, vaultPath) {
626
628
  return 0;
627
629
  }
628
630
  function isPortAvailable(port) {
629
- return new Promise((resolve) => {
631
+ return new Promise((resolve3) => {
630
632
  const server = net.createServer();
631
- server.once("error", () => resolve(false));
633
+ server.once("error", () => resolve3(false));
632
634
  server.once("listening", () => {
633
- server.close(() => resolve(true));
635
+ server.close(() => resolve3(true));
634
636
  });
635
637
  server.listen(port, "127.0.0.1");
636
638
  });
@@ -639,6 +641,53 @@ function isPortAvailable(port) {
639
641
  // src/symbionts/adapter.ts
640
642
  import fs3 from "fs";
641
643
  import path3 from "path";
644
+
645
+ // src/symbionts/parsers/standard-jsonl.ts
646
+ var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
647
+ var StandardJsonlParser = class {
648
+ constructor(opts) {
649
+ this.opts = opts;
650
+ }
651
+ parseTurns(content) {
652
+ const lines = content.split("\n").filter(Boolean);
653
+ const turns = [];
654
+ let current = null;
655
+ for (const line of lines) {
656
+ let entry;
657
+ try {
658
+ entry = JSON.parse(line);
659
+ } catch {
660
+ continue;
661
+ }
662
+ const role = entry[this.opts.roleField];
663
+ const timestamp = this.opts.extractTimestamp ? entry.timestamp ?? "" : "";
664
+ if (role === "user") {
665
+ if (entry.isMeta === true) continue;
666
+ const msg = entry.message;
667
+ const blocks = Array.isArray(msg?.content) ? msg.content : [];
668
+ const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
669
+ if (!hasText) continue;
670
+ if (current) turns.push(current);
671
+ const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
672
+ const promptText = (this.opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
673
+ const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
674
+ current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
675
+ } else if (role === "assistant" && current) {
676
+ const msg = entry.message;
677
+ if (Array.isArray(msg?.content)) {
678
+ const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
679
+ const text = textParts.join("\n").trim();
680
+ if (text) current.aiResponse = text;
681
+ current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
682
+ }
683
+ }
684
+ }
685
+ if (current) turns.push(current);
686
+ return turns;
687
+ }
688
+ };
689
+
690
+ // src/symbionts/adapter.ts
642
691
  function findJsonlInSubdirs(baseDir, sessionId) {
643
692
  try {
644
693
  for (const entry of fs3.readdirSync(baseDir, { withFileTypes: true })) {
@@ -683,44 +732,8 @@ var EXT_TO_MIME = {
683
732
  function mimeTypeForExtension(ext) {
684
733
  return EXT_TO_MIME[ext.toLowerCase()] ?? "image/png";
685
734
  }
686
- var IMAGE_TEXT_REF_PATTERN = /\[Image: source: [^\]]+\]\n*/g;
687
735
  function parseJsonlTurns(content, opts) {
688
- const lines = content.split("\n").filter(Boolean);
689
- const turns = [];
690
- let current = null;
691
- for (const line of lines) {
692
- let entry;
693
- try {
694
- entry = JSON.parse(line);
695
- } catch {
696
- continue;
697
- }
698
- const role = entry[opts.roleField];
699
- const timestamp = opts.extractTimestamp ? entry.timestamp ?? "" : "";
700
- if (role === "user") {
701
- if (entry.isMeta === true) continue;
702
- const msg = entry.message;
703
- const blocks = Array.isArray(msg?.content) ? msg.content : [];
704
- const hasText = blocks.some((b) => b.type === "text" && b.text?.trim());
705
- if (!hasText && opts.skipToolResultUsers) continue;
706
- if (!hasText) continue;
707
- if (current) turns.push(current);
708
- const rawPrompt = blocks.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("\n");
709
- const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, "") : rawPrompt).trim().slice(0, PROMPT_PREVIEW_CHARS);
710
- const images = blocks.filter((b) => b.type === "image" && b.source?.type === "base64" && b.source.data).map((b) => ({ data: b.source.data, mediaType: b.source.media_type ?? "image/png" }));
711
- current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
712
- } else if (role === "assistant" && current) {
713
- const msg = entry.message;
714
- if (Array.isArray(msg?.content)) {
715
- const textParts = msg.content.filter((b) => b.type === "text" && b.text).map((b) => b.text);
716
- const text = textParts.join("\n").trim();
717
- if (text) current.aiResponse = text;
718
- current.toolCount += msg.content.filter((b) => b.type === "tool_use").length;
719
- }
720
- }
721
- }
722
- if (current) turns.push(current);
723
- return turns;
736
+ return new StandardJsonlParser(opts).parseTurns(content);
724
737
  }
725
738
 
726
739
  // src/symbionts/claude-code.ts
@@ -874,10 +887,100 @@ function parseCursorText(content) {
874
887
  return turns;
875
888
  }
876
889
 
890
+ // src/symbionts/parsers/codex-jsonl.ts
891
+ function parseDataUrl(url) {
892
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
893
+ if (!match) return null;
894
+ return { mediaType: match[1], data: match[2] };
895
+ }
896
+ var IMAGE_WRAPPER_TAG = /^<\/?image\b[^>]*>$/;
897
+ var CODEX_PROMPT_MARKER = "## My request for Codex:\n";
898
+ function cleanCodexPromptText(text) {
899
+ if (IMAGE_WRAPPER_TAG.test(text.trim())) return "";
900
+ const idx = text.indexOf(CODEX_PROMPT_MARKER);
901
+ if (idx !== -1) return text.slice(idx + CODEX_PROMPT_MARKER.length);
902
+ return text;
903
+ }
904
+ var CodexJsonlParser = class {
905
+ parseTurns(content) {
906
+ const lines = content.split("\n").filter(Boolean);
907
+ const turns = [];
908
+ let current = null;
909
+ for (const line of lines) {
910
+ let entry;
911
+ try {
912
+ entry = JSON.parse(line);
913
+ } catch {
914
+ continue;
915
+ }
916
+ if (entry.type !== "response_item") continue;
917
+ const payload = entry.payload;
918
+ if (!payload) continue;
919
+ const payloadType = payload.type;
920
+ const timestamp = entry.timestamp ?? "";
921
+ if (payloadType === "function_call") {
922
+ if (current) current.toolCount++;
923
+ continue;
924
+ }
925
+ if (payloadType !== "message") continue;
926
+ const role = payload.role;
927
+ const blocks = Array.isArray(payload.content) ? payload.content : [];
928
+ if (role === "user") {
929
+ const textParts = blocks.filter((b) => b.type === "input_text" && b.text?.trim()).map((b) => cleanCodexPromptText(b.text)).filter((t) => t.trim());
930
+ if (textParts.length === 0) continue;
931
+ if (current) turns.push(current);
932
+ const promptText = textParts.join("\n").trim().slice(0, PROMPT_PREVIEW_CHARS);
933
+ const images = [];
934
+ for (const b of blocks) {
935
+ if (b.type === "input_image" && b.image_url) {
936
+ const parsed = parseDataUrl(b.image_url);
937
+ if (parsed) images.push(parsed);
938
+ }
939
+ }
940
+ current = { prompt: promptText, toolCount: 0, timestamp, ...images.length > 0 ? { images } : {} };
941
+ } else if (role === "assistant" && current) {
942
+ const textParts = blocks.filter((b) => b.type === "output_text" && b.text).map((b) => b.text);
943
+ const text = textParts.join("\n").trim();
944
+ if (text) current.aiResponse = text;
945
+ }
946
+ }
947
+ if (current) turns.push(current);
948
+ return turns;
949
+ }
950
+ };
951
+
877
952
  // src/symbionts/codex.ts
953
+ import fs5 from "fs";
878
954
  import path6 from "path";
879
955
  import os3 from "os";
880
956
  var TRANSCRIPT_BASE2 = path6.join(os3.homedir(), ".codex");
957
+ var codexParser = new CodexJsonlParser();
958
+ function findCodexTranscript(baseDir, sessionId) {
959
+ const sessionsDir = path6.join(baseDir, "sessions");
960
+ try {
961
+ return scanForSessionFile(sessionsDir, sessionId);
962
+ } catch {
963
+ return null;
964
+ }
965
+ }
966
+ function scanForSessionFile(dir, sessionId) {
967
+ let entries;
968
+ try {
969
+ entries = fs5.readdirSync(dir, { withFileTypes: true });
970
+ } catch {
971
+ return null;
972
+ }
973
+ for (const entry of entries) {
974
+ const fullPath = path6.join(dir, entry.name);
975
+ if (entry.isDirectory()) {
976
+ const found = scanForSessionFile(fullPath, sessionId);
977
+ if (found) return found;
978
+ } else if (entry.isFile() && entry.name.includes(sessionId) && entry.name.endsWith(".jsonl")) {
979
+ return fullPath;
980
+ }
981
+ }
982
+ return null;
983
+ }
881
984
  var codexAdapter = {
882
985
  name: "codex",
883
986
  displayName: "Codex",
@@ -891,18 +994,12 @@ var codexAdapter = {
891
994
  toolInput: "tool_input",
892
995
  toolOutput: "tool_output"
893
996
  },
894
- findTranscript: (sessionId) => findJsonlInSubdirs(TRANSCRIPT_BASE2, sessionId),
895
- // Codex uses 'role' field (like Cursor), not 'type' (like Claude Code)
896
- parseTurns: (content) => parseJsonlTurns(content, {
897
- roleField: "role",
898
- extractTimestamp: false,
899
- skipToolResultUsers: false,
900
- stripImageTextRefs: false
901
- })
997
+ findTranscript: (sessionId) => findCodexTranscript(TRANSCRIPT_BASE2, sessionId),
998
+ parseTurns: (content) => codexParser.parseTurns(content)
902
999
  };
903
1000
 
904
1001
  // src/symbionts/gemini.ts
905
- import fs5 from "fs";
1002
+ import fs6 from "fs";
906
1003
  import path7 from "path";
907
1004
  import os4 from "os";
908
1005
  var GEMINI_TMP = path7.join(os4.homedir(), ".gemini", "tmp");
@@ -922,15 +1019,15 @@ var geminiAdapter = {
922
1019
  },
923
1020
  findTranscript(sessionId) {
924
1021
  try {
925
- for (const project of fs5.readdirSync(GEMINI_TMP, { withFileTypes: true })) {
1022
+ for (const project of fs6.readdirSync(GEMINI_TMP, { withFileTypes: true })) {
926
1023
  if (!project.isDirectory()) continue;
927
1024
  const chatsDir = path7.join(GEMINI_TMP, project.name, "chats");
928
1025
  try {
929
- for (const file of fs5.readdirSync(chatsDir)) {
1026
+ for (const file of fs6.readdirSync(chatsDir)) {
930
1027
  if (!file.endsWith(".json")) continue;
931
1028
  if (file.includes(sessionId.slice(0, 8))) {
932
1029
  try {
933
- const data = JSON.parse(fs5.readFileSync(path7.join(chatsDir, file), "utf-8"));
1030
+ const data = JSON.parse(fs6.readFileSync(path7.join(chatsDir, file), "utf-8"));
934
1031
  if (data.sessionId === sessionId) {
935
1032
  return path7.join(chatsDir, file);
936
1033
  }
@@ -984,7 +1081,7 @@ function parseGeminiJson(content) {
984
1081
  }
985
1082
 
986
1083
  // src/symbionts/windsurf.ts
987
- import fs6 from "fs";
1084
+ import fs7 from "fs";
988
1085
  import path8 from "path";
989
1086
  import os5 from "os";
990
1087
  var TRANSCRIPT_DIR = path8.join(os5.homedir(), ".windsurf", "transcripts");
@@ -1007,7 +1104,7 @@ var windsurfAdapter = {
1007
1104
  findTranscript(sessionId) {
1008
1105
  const candidate = path8.join(TRANSCRIPT_DIR, `${sessionId}.jsonl`);
1009
1106
  try {
1010
- fs6.accessSync(candidate);
1107
+ fs7.accessSync(candidate);
1011
1108
  return candidate;
1012
1109
  } catch {
1013
1110
  return null;
@@ -1142,7 +1239,7 @@ function normalizeResponseParts(response) {
1142
1239
  }
1143
1240
 
1144
1241
  // src/symbionts/registry.ts
1145
- import fs7 from "fs";
1242
+ import fs8 from "fs";
1146
1243
  var ALL_ADAPTERS = [
1147
1244
  claudeCodeAdapter,
1148
1245
  cursorAdapter,
@@ -1165,7 +1262,7 @@ var SymbiontRegistry = class {
1165
1262
  const filePath = adapter.findTranscript(sessionId);
1166
1263
  if (!filePath) continue;
1167
1264
  try {
1168
- const content = fs7.readFileSync(filePath, "utf-8");
1265
+ const content = fs8.readFileSync(filePath, "utf-8");
1169
1266
  const turns = adapter.parseTurns(content);
1170
1267
  if (turns.length > 0) {
1171
1268
  return { turns, source: adapter.name };
@@ -1199,7 +1296,7 @@ var SymbiontRegistry = class {
1199
1296
  */
1200
1297
  parseTurnsFromPath(filePath) {
1201
1298
  try {
1202
- const content = fs7.readFileSync(filePath, "utf-8");
1299
+ const content = fs8.readFileSync(filePath, "utf-8");
1203
1300
  const active = this.detectActiveAgent();
1204
1301
  const orderedAdapters = active ? [active, ...this.adapters.filter((a) => a !== active)] : this.adapters;
1205
1302
  for (const adapter of orderedAdapters) {
@@ -1599,12 +1696,34 @@ async function handleRestart(deps, body) {
1599
1696
 
1600
1697
  // src/daemon/update-checker.ts
1601
1698
  var import_yaml = __toESM(require_dist(), 1);
1602
- import fs8 from "fs";
1699
+ import fs9 from "fs";
1603
1700
  import path9 from "path";
1701
+ import { execFileSync } from "child_process";
1604
1702
  import semver from "semver";
1605
1703
  var REGISTRY_FETCH_TIMEOUT_MS = 1e4;
1704
+ var devBuildCliEntry = null;
1705
+ function setDevBuildCliEntry(cliEntry) {
1706
+ devBuildCliEntry = cliEntry;
1707
+ }
1708
+ function resolveMycoBinary() {
1709
+ return devBuildCliEntry ?? "myco";
1710
+ }
1606
1711
  function isUpdateExempt() {
1607
- return Boolean(process.env.MYCO_CMD);
1712
+ return devBuildCliEntry !== null;
1713
+ }
1714
+ function detectDevBuild(globalPrefix, cliEntry, realpath) {
1715
+ if (!globalPrefix) return null;
1716
+ if (!cliEntry) return null;
1717
+ try {
1718
+ const resolvedEntry = realpath(cliEntry);
1719
+ const resolvedPrefix = realpath(globalPrefix);
1720
+ if (resolvedEntry.startsWith(resolvedPrefix + path9.sep) || resolvedEntry === resolvedPrefix) {
1721
+ return null;
1722
+ }
1723
+ return cliEntry;
1724
+ } catch {
1725
+ return null;
1726
+ }
1608
1727
  }
1609
1728
  function defaultUpdateConfig() {
1610
1729
  return {
@@ -1614,7 +1733,7 @@ function defaultUpdateConfig() {
1614
1733
  }
1615
1734
  function readUpdateConfig() {
1616
1735
  try {
1617
- const raw = fs8.readFileSync(UPDATE_CONFIG_PATH, "utf-8");
1736
+ const raw = fs9.readFileSync(UPDATE_CONFIG_PATH, "utf-8");
1618
1737
  const parsed = import_yaml.default.parse(raw);
1619
1738
  const channel = RELEASE_CHANNELS.includes(parsed?.channel) ? parsed.channel : DEFAULT_RELEASE_CHANNEL;
1620
1739
  const check_interval_hours = typeof parsed?.check_interval_hours === "number" && parsed.check_interval_hours > 0 ? parsed.check_interval_hours : UPDATE_CHECK_INTERVAL_HOURS;
@@ -1624,12 +1743,12 @@ function readUpdateConfig() {
1624
1743
  }
1625
1744
  }
1626
1745
  function writeUpdateConfig(config) {
1627
- fs8.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1628
- fs8.writeFileSync(UPDATE_CONFIG_PATH, import_yaml.default.stringify(config), "utf-8");
1746
+ fs9.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1747
+ fs9.writeFileSync(UPDATE_CONFIG_PATH, import_yaml.default.stringify(config), "utf-8");
1629
1748
  }
1630
1749
  function readCachedCheck() {
1631
1750
  try {
1632
- const raw = fs8.readFileSync(UPDATE_CHECK_CACHE_PATH, "utf-8");
1751
+ const raw = fs9.readFileSync(UPDATE_CHECK_CACHE_PATH, "utf-8");
1633
1752
  return JSON.parse(raw);
1634
1753
  } catch {
1635
1754
  return null;
@@ -1637,7 +1756,7 @@ function readCachedCheck() {
1637
1756
  }
1638
1757
  function clearCachedCheck() {
1639
1758
  try {
1640
- fs8.unlinkSync(UPDATE_CHECK_CACHE_PATH);
1759
+ fs9.unlinkSync(UPDATE_CHECK_CACHE_PATH);
1641
1760
  } catch {
1642
1761
  }
1643
1762
  }
@@ -1675,6 +1794,25 @@ function buildCheckResult(currentVersion, cache, config, error) {
1675
1794
  error
1676
1795
  };
1677
1796
  }
1797
+ function resolveGlobalPrefix() {
1798
+ return execFileSync("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 5e3 }).trim();
1799
+ }
1800
+ function getInstalledVersion(globalPrefix) {
1801
+ try {
1802
+ const pkgPath = path9.join(
1803
+ globalPrefix,
1804
+ "lib",
1805
+ "node_modules",
1806
+ NPM_PACKAGE_NAME,
1807
+ "package.json"
1808
+ );
1809
+ const raw = fs9.readFileSync(pkgPath, "utf-8");
1810
+ const pkg = JSON.parse(raw);
1811
+ return pkg.version ?? null;
1812
+ } catch {
1813
+ return null;
1814
+ }
1815
+ }
1678
1816
  async function checkForUpdate(currentVersion) {
1679
1817
  const config = readUpdateConfig();
1680
1818
  const existingCache = readCachedCheck();
@@ -1717,8 +1855,8 @@ async function checkForUpdate(currentVersion) {
1717
1855
  channel: config.channel
1718
1856
  };
1719
1857
  try {
1720
- fs8.mkdirSync(path9.dirname(UPDATE_CHECK_CACHE_PATH), { recursive: true });
1721
- fs8.writeFileSync(UPDATE_CHECK_CACHE_PATH, JSON.stringify(freshCache, null, 2), "utf-8");
1858
+ fs9.mkdirSync(path9.dirname(UPDATE_CHECK_CACHE_PATH), { recursive: true });
1859
+ fs9.writeFileSync(UPDATE_CHECK_CACHE_PATH, JSON.stringify(freshCache, null, 2), "utf-8");
1722
1860
  } catch {
1723
1861
  }
1724
1862
  return buildCheckResult(currentVersion, freshCache, config, null);
@@ -1731,22 +1869,23 @@ function statusFromCache(currentVersion, cache, config) {
1731
1869
  }
1732
1870
 
1733
1871
  // src/daemon/update-installer.ts
1734
- import fs9 from "fs";
1872
+ import fs10 from "fs";
1735
1873
  import os6 from "os";
1736
1874
  import path10 from "path";
1737
1875
  import { spawn as spawn2 } from "child_process";
1738
1876
  function generateUpdateScript(params) {
1739
- const { targetVersion, projectRoot, vaultDir } = params;
1877
+ const { targetVersion, projectRoot, vaultDir, mycoBinary } = params;
1740
1878
  const packageSpec = `${NPM_PACKAGE_NAME}@${targetVersion}`;
1741
1879
  const quotedProjectRoot = JSON.stringify(projectRoot);
1742
1880
  const quotedVaultDir = JSON.stringify(vaultDir);
1881
+ const quotedMycoBinary = JSON.stringify(mycoBinary);
1743
1882
  const quotedErrorPath = JSON.stringify(UPDATE_ERROR_PATH);
1744
1883
  const errorJson = JSON.stringify(
1745
1884
  JSON.stringify({ error: `npm install failed for ${packageSpec}` })
1746
1885
  );
1747
1886
  return `#!/bin/sh
1748
1887
  set -e
1749
- MYCO="\${MYCO_CMD:-myco}"
1888
+ MYCO=${quotedMycoBinary}
1750
1889
 
1751
1890
  # Wait for daemon to exit cleanly
1752
1891
  sleep ${UPDATE_SCRIPT_DELAY_SECONDS}
@@ -1769,12 +1908,9 @@ fi
1769
1908
  rm -f "$0"
1770
1909
  `;
1771
1910
  }
1772
- function spawnUpdateScript(params) {
1773
- fs9.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1774
- const scriptName = `myco-update-${Date.now()}.sh`;
1775
- const scriptPath = path10.join(os6.tmpdir(), scriptName);
1776
- const script = generateUpdateScript(params);
1777
- fs9.writeFileSync(scriptPath, script, { encoding: "utf-8", mode: 493 });
1911
+ function spawnDetachedScript(namePrefix, content) {
1912
+ const scriptPath = path10.join(os6.tmpdir(), `${namePrefix}-${Date.now()}.sh`);
1913
+ fs10.writeFileSync(scriptPath, content, { encoding: "utf-8", mode: 493 });
1778
1914
  const child = spawn2("/bin/sh", [scriptPath], {
1779
1915
  detached: true,
1780
1916
  stdio: "ignore"
@@ -1782,17 +1918,94 @@ function spawnUpdateScript(params) {
1782
1918
  child.unref();
1783
1919
  return scriptPath;
1784
1920
  }
1921
+ function spawnUpdateScript(params) {
1922
+ fs10.mkdirSync(MYCO_GLOBAL_DIR, { recursive: true });
1923
+ return spawnDetachedScript("myco-update", generateUpdateScript(params));
1924
+ }
1925
+ function generateRestartScript(params) {
1926
+ const { projectRoot, vaultDir, runLocalUpdate, fromVersion, toVersion, mycoBinary } = params;
1927
+ const quotedProjectRoot = JSON.stringify(projectRoot);
1928
+ const quotedVaultDir = JSON.stringify(vaultDir);
1929
+ const quotedMycoBinary = JSON.stringify(mycoBinary);
1930
+ const reasonFile = JSON.stringify(path10.join(vaultDir, RESTART_REASON_FILENAME));
1931
+ const reasonJson = JSON.stringify(JSON.stringify({
1932
+ reason: "version_sync",
1933
+ from_version: fromVersion,
1934
+ to_version: toVersion,
1935
+ local_update_ran: runLocalUpdate
1936
+ }));
1937
+ const updateBlock = runLocalUpdate ? `
1938
+ # Run local project update (hooks, symbionts, gitignore)
1939
+ "$MYCO" update --project ${quotedProjectRoot} || true` : "";
1940
+ return `#!/bin/sh
1941
+ set -e
1942
+ MYCO=${quotedMycoBinary}
1943
+
1944
+ # Wait for daemon to exit cleanly
1945
+ sleep ${UPDATE_SCRIPT_DELAY_SECONDS}
1946
+ ${updateBlock}
1947
+
1948
+ # Write restart reason for the new daemon to pick up
1949
+ echo ${reasonJson} > ${reasonFile}
1950
+
1951
+ # Restart daemon
1952
+ "$MYCO" daemon --vault ${quotedVaultDir} &
1953
+
1954
+ # Clean up this script
1955
+ rm -f "$0"
1956
+ `;
1957
+ }
1958
+ function spawnRestartScript(params) {
1959
+ return spawnDetachedScript("myco-restart", generateRestartScript(params));
1960
+ }
1785
1961
 
1786
1962
  // src/daemon/api/update.ts
1963
+ import semver2 from "semver";
1964
+ import fs11 from "fs";
1965
+ import path11 from "path";
1787
1966
  var ChannelBodySchema = external_exports.object({
1788
1967
  channel: external_exports.enum(RELEASE_CHANNELS)
1789
1968
  });
1790
1969
  function createUpdateHandlers(deps) {
1791
- const { vaultDir, projectRoot, currentVersion, scheduleShutdown } = deps;
1970
+ const { vaultDir, projectRoot, currentVersion, scheduleShutdown, globalPrefix } = deps;
1971
+ let restartInitiated = false;
1972
+ function isStampCurrent() {
1973
+ try {
1974
+ const stampPath = path11.join(vaultDir, UPDATE_STAMP_FILENAME);
1975
+ const stamp = fs11.readFileSync(stampPath, "utf-8").trim();
1976
+ return stamp === currentVersion;
1977
+ } catch {
1978
+ return false;
1979
+ }
1980
+ }
1792
1981
  async function handleUpdateStatus(_req) {
1793
1982
  if (isUpdateExempt()) {
1794
1983
  return { body: { exempt: true, running_version: currentVersion } };
1795
1984
  }
1985
+ if (globalPrefix && !restartInitiated) {
1986
+ const installedVersion = getInstalledVersion(globalPrefix);
1987
+ if (installedVersion && semver2.valid(installedVersion) && semver2.valid(currentVersion) && semver2.gt(installedVersion, currentVersion)) {
1988
+ restartInitiated = true;
1989
+ const runLocalUpdate = !isStampCurrent();
1990
+ spawnRestartScript({
1991
+ projectRoot,
1992
+ vaultDir,
1993
+ runLocalUpdate,
1994
+ fromVersion: currentVersion,
1995
+ toVersion: installedVersion,
1996
+ mycoBinary: resolveMycoBinary()
1997
+ });
1998
+ scheduleShutdown();
1999
+ return {
2000
+ body: {
2001
+ restarting: true,
2002
+ reason: "version_sync",
2003
+ running_version: currentVersion,
2004
+ installed_version: installedVersion
2005
+ }
2006
+ };
2007
+ }
2008
+ }
1796
2009
  const config = readUpdateConfig();
1797
2010
  const cache = readCachedCheck();
1798
2011
  if (isCacheStale(cache, config.check_interval_hours)) {
@@ -1836,7 +2049,12 @@ function createUpdateHandlers(deps) {
1836
2049
  if (!status || !status.update_available) {
1837
2050
  return { status: 400, body: { error: "no_update_available" } };
1838
2051
  }
1839
- spawnUpdateScript({ targetVersion: status.latest_version, projectRoot, vaultDir });
2052
+ spawnUpdateScript({
2053
+ targetVersion: status.latest_version,
2054
+ projectRoot,
2055
+ vaultDir,
2056
+ mycoBinary: resolveMycoBinary()
2057
+ });
1840
2058
  scheduleShutdown();
1841
2059
  return { body: { status: "applying", version: status.latest_version } };
1842
2060
  }
@@ -1877,8 +2095,8 @@ function createUpdateHandlers(deps) {
1877
2095
  }
1878
2096
 
1879
2097
  // src/daemon/backup.ts
1880
- import fs10 from "fs";
1881
- import path11 from "path";
2098
+ import fs12 from "fs";
2099
+ import path12 from "path";
1882
2100
  var BACKUP_TABLES = [
1883
2101
  "sessions",
1884
2102
  "prompt_batches",
@@ -1893,6 +2111,7 @@ var BACKUP_TABLES = [
1893
2111
  "team_members"
1894
2112
  ];
1895
2113
  var BACKUP_EXTENSION = ".sql";
2114
+ var BACKUP_FILENAME_PATTERN = /^[A-Za-z0-9_-]+\.sql$/;
1896
2115
  var BACKUP_HEADER_TEMPLATE = "-- Myco backup";
1897
2116
  function escapeSql(value) {
1898
2117
  return value.replace(/'/g, "''");
@@ -1904,7 +2123,7 @@ function toSqlLiteral(value) {
1904
2123
  return `'${escapeSql(String(value))}'`;
1905
2124
  }
1906
2125
  function createBackup(db, backupDir, machineId) {
1907
- fs10.mkdirSync(backupDir, { recursive: true });
2126
+ fs12.mkdirSync(backupDir, { recursive: true });
1908
2127
  const lines = [];
1909
2128
  const timestamp = epochSeconds();
1910
2129
  lines.push(`${BACKUP_HEADER_TEMPLATE}: machine_id=${machineId}, created_at=${timestamp}`);
@@ -1922,22 +2141,22 @@ function createBackup(db, backupDir, machineId) {
1922
2141
  }
1923
2142
  lines.push("");
1924
2143
  }
1925
- const filePath = path11.join(backupDir, `${machineId}${BACKUP_EXTENSION}`);
1926
- fs10.writeFileSync(filePath, lines.join("\n"), "utf-8");
2144
+ const filePath = path12.join(backupDir, `${machineId}${BACKUP_EXTENSION}`);
2145
+ fs12.writeFileSync(filePath, lines.join("\n"), "utf-8");
1927
2146
  return filePath;
1928
2147
  }
1929
2148
  function listBackups(backupDir) {
1930
2149
  let entries;
1931
2150
  try {
1932
- entries = fs10.readdirSync(backupDir);
2151
+ entries = fs12.readdirSync(backupDir);
1933
2152
  } catch {
1934
2153
  return [];
1935
2154
  }
1936
2155
  const backups = [];
1937
2156
  for (const entry of entries) {
1938
- if (!entry.endsWith(BACKUP_EXTENSION)) continue;
1939
- const filePath = path11.join(backupDir, entry);
1940
- const stat = fs10.statSync(filePath);
2157
+ if (!BACKUP_FILENAME_PATTERN.test(entry)) continue;
2158
+ const filePath = path12.join(backupDir, entry);
2159
+ const stat = fs12.statSync(filePath);
1941
2160
  backups.push({
1942
2161
  machine_id: entry.slice(0, -BACKUP_EXTENSION.length),
1943
2162
  file_name: entry,
@@ -1949,7 +2168,7 @@ function listBackups(backupDir) {
1949
2168
  }
1950
2169
  var INSERT_REGEX = /^INSERT OR IGNORE INTO (\w+)\s+\(([^)]+)\)\s+VALUES\s+\((.+)\);$/;
1951
2170
  function parseBackupFile(backupPath) {
1952
- const content = fs10.readFileSync(backupPath, "utf-8");
2171
+ const content = fs12.readFileSync(backupPath, "utf-8");
1953
2172
  const inserts = [];
1954
2173
  for (const line of content.split("\n")) {
1955
2174
  const match = INSERT_REGEX.exec(line);
@@ -2033,7 +2252,7 @@ function restoreBackup(db, backupPath) {
2033
2252
  }
2034
2253
 
2035
2254
  // src/daemon/api/backup.ts
2036
- import path12 from "path";
2255
+ import path13 from "path";
2037
2256
  function createBackupHandlers(deps) {
2038
2257
  async function handleCreateBackup(_req) {
2039
2258
  const filePath = createBackup(deps.db, deps.backupDir, deps.machineId);
@@ -2092,7 +2311,7 @@ function createBackupConfigHandlers(deps) {
2092
2311
  const { vaultDir } = deps;
2093
2312
  async function handleGetBackupConfig() {
2094
2313
  const cfg = loadConfig(vaultDir);
2095
- return { body: { dir: cfg.backup.dir ?? null, default_dir: path12.resolve(vaultDir, "backups") } };
2314
+ return { body: { dir: cfg.backup.dir ?? null, default_dir: path13.resolve(vaultDir, "backups") } };
2096
2315
  }
2097
2316
  async function handlePutBackupConfig(req) {
2098
2317
  const { dir } = req.body;
@@ -2103,12 +2322,14 @@ function createBackupConfigHandlers(deps) {
2103
2322
  }
2104
2323
 
2105
2324
  // src/daemon/team-sync.ts
2106
- var TeamSyncClient = class {
2325
+ var TeamSyncClient = class _TeamSyncClient {
2107
2326
  workerUrl;
2108
2327
  apiKey;
2109
2328
  machineId;
2110
2329
  syncProtocolVersion;
2111
2330
  fetchFn;
2331
+ mcpToken = null;
2332
+ mcpTokenHash = null;
2112
2333
  constructor(options) {
2113
2334
  this.workerUrl = options.workerUrl.replace(/\/+$/, "");
2114
2335
  this.apiKey = options.apiKey;
@@ -2116,6 +2337,14 @@ var TeamSyncClient = class {
2116
2337
  this.syncProtocolVersion = options.syncProtocolVersion;
2117
2338
  this.fetchFn = options.fetch ?? globalThis.fetch;
2118
2339
  }
2340
+ // Must match getMcpTokenHash() in src/worker/src/mcp/auth.ts
2341
+ static hashToken(token) {
2342
+ let hash = 0;
2343
+ for (let i = 0; i < token.length; i++) {
2344
+ hash = (hash << 5) - hash + token.charCodeAt(i) | 0;
2345
+ }
2346
+ return Math.abs(hash).toString(16).padStart(8, "0").slice(0, 8);
2347
+ }
2119
2348
  /**
2120
2349
  * Register this machine with the team worker.
2121
2350
  */
@@ -2125,7 +2354,12 @@ var TeamSyncClient = class {
2125
2354
  machine_id: this.machineId,
2126
2355
  sync_protocol_version: this.syncProtocolVersion
2127
2356
  });
2128
- return res;
2357
+ const response = res;
2358
+ if (response.mcp_token) {
2359
+ this.mcpToken = response.mcp_token;
2360
+ this.mcpTokenHash = _TeamSyncClient.hashToken(response.mcp_token);
2361
+ }
2362
+ return response;
2129
2363
  }
2130
2364
  /**
2131
2365
  * Push a batch of outbox records to the team worker.
@@ -2191,7 +2425,14 @@ var TeamSyncClient = class {
2191
2425
  if (!res.ok) {
2192
2426
  throw new Error(`Health check failed: ${res.status} ${res.statusText}`);
2193
2427
  }
2194
- return await res.json();
2428
+ const data = await res.json();
2429
+ if (data.mcp_token_hash && data.mcp_token_hash !== this.mcpTokenHash) {
2430
+ try {
2431
+ await this.connect({ machine_id: this.machineId });
2432
+ } catch {
2433
+ }
2434
+ }
2435
+ return data;
2195
2436
  } finally {
2196
2437
  clearTimeout(timer);
2197
2438
  }
@@ -2204,6 +2445,22 @@ var TeamSyncClient = class {
2204
2445
  return res;
2205
2446
  }
2206
2447
  // ---------------------------------------------------------------------------
2448
+ // MCP token accessors
2449
+ // ---------------------------------------------------------------------------
2450
+ getMcpToken() {
2451
+ return this.mcpToken;
2452
+ }
2453
+ getMcpEndpoint() {
2454
+ if (!this.mcpToken) return null;
2455
+ return `${this.workerUrl}/mcp`;
2456
+ }
2457
+ async rotateMcpToken() {
2458
+ const result = await this.request("POST", "/mcp/rotate");
2459
+ this.mcpToken = result.token;
2460
+ this.mcpTokenHash = _TeamSyncClient.hashToken(result.token);
2461
+ return result.token;
2462
+ }
2463
+ // ---------------------------------------------------------------------------
2207
2464
  // Internal
2208
2465
  // ---------------------------------------------------------------------------
2209
2466
  headers() {
@@ -2212,15 +2469,15 @@ var TeamSyncClient = class {
2212
2469
  "Content-Type": "application/json"
2213
2470
  };
2214
2471
  }
2215
- async request(method, path21, body) {
2216
- const res = await this.fetchFn(`${this.workerUrl}${path21}`, {
2472
+ async request(method, path22, body) {
2473
+ const res = await this.fetchFn(`${this.workerUrl}${path22}`, {
2217
2474
  method,
2218
2475
  headers: this.headers(),
2219
2476
  body: body !== void 0 ? JSON.stringify(body) : void 0
2220
2477
  });
2221
2478
  if (!res.ok) {
2222
2479
  const text = await res.text().catch(() => "");
2223
- throw new Error(`Team sync request ${method} ${path21} failed: ${res.status} ${text}`);
2480
+ throw new Error(`Team sync request ${method} ${path22} failed: ${res.status} ${text}`);
2224
2481
  }
2225
2482
  return res.json();
2226
2483
  }
@@ -2228,7 +2485,7 @@ var TeamSyncClient = class {
2228
2485
 
2229
2486
  // src/daemon/api/team-connect.ts
2230
2487
  function createTeamHandlers(deps) {
2231
- const { vaultDir, machineId } = deps;
2488
+ const { vaultDir, machineId, logger } = deps;
2232
2489
  async function handleConnect(req) {
2233
2490
  const { url, api_key } = req.body;
2234
2491
  if (!url || !api_key) {
@@ -2313,7 +2570,9 @@ function createTeamHandlers(deps) {
2313
2570
  deployed_worker_version: config.team.deployed_worker_version ?? null,
2314
2571
  worker_update_available: config.team.enabled ? config.team.deployed_worker_version !== getPluginVersion() : false,
2315
2572
  schema_version: SCHEMA_VERSION,
2316
- sync_protocol_version: SYNC_PROTOCOL_VERSION
2573
+ sync_protocol_version: SYNC_PROTOCOL_VERSION,
2574
+ mcp_token: client?.getMcpToken() ?? null,
2575
+ mcp_endpoint: client?.getMcpEndpoint() ?? null
2317
2576
  }
2318
2577
  };
2319
2578
  }
@@ -2326,11 +2585,17 @@ function createTeamHandlers(deps) {
2326
2585
  return { body: { retried: count } };
2327
2586
  }
2328
2587
  async function handleUpgradeWorker(_req) {
2329
- const { upgradeWorker } = await import("./team-7X64J4Y6.js");
2588
+ const { upgradeWorker } = await import("./team-DPNP2RN7.js");
2589
+ logger.info("team-sync.upgrade.start", "Starting worker upgrade");
2330
2590
  const result = upgradeWorker(vaultDir);
2331
2591
  if (!result.success) {
2592
+ logger.error("team-sync.upgrade.failed", "Worker upgrade failed", { error: result.error });
2332
2593
  return { status: 500, body: { error: result.error } };
2333
2594
  }
2595
+ logger.info("team-sync.upgrade.complete", "Worker upgrade complete", {
2596
+ worker_url: result.worker_url,
2597
+ version: result.version
2598
+ });
2334
2599
  if (result.worker_url && deps.getTeamClient()) {
2335
2600
  const secrets = readSecrets(vaultDir);
2336
2601
  const apiKey = secrets[TEAM_API_KEY_SECRET];
@@ -2345,7 +2610,28 @@ function createTeamHandlers(deps) {
2345
2610
  }
2346
2611
  return { body: result };
2347
2612
  }
2348
- return { handleConnect, handleDisconnect, handleStatus, handleBackfill, handleRetryFailed, handleUpgradeWorker };
2613
+ async function handleRotateMcpToken(_req) {
2614
+ const client = deps.getTeamClient();
2615
+ if (!client) {
2616
+ return {
2617
+ status: 400,
2618
+ body: { error: "Team sync not connected" }
2619
+ };
2620
+ }
2621
+ try {
2622
+ const token = await client.rotateMcpToken();
2623
+ logger.info("team-sync.mcp-token.rotated", "MCP access token rotated");
2624
+ return { body: { token } };
2625
+ } catch (err) {
2626
+ const message = err instanceof Error ? err.message : String(err);
2627
+ logger.error("team-sync.mcp-token.rotate-failed", "MCP token rotation failed", { error: message });
2628
+ return {
2629
+ status: 500,
2630
+ body: { error: message }
2631
+ };
2632
+ }
2633
+ }
2634
+ return { handleConnect, handleDisconnect, handleStatus, handleBackfill, handleRetryFailed, handleUpgradeWorker, handleRotateMcpToken };
2349
2635
  }
2350
2636
 
2351
2637
  // src/daemon/api/session-lifecycle.ts
@@ -2425,8 +2711,8 @@ function createSessionLifecycleHandlers(deps) {
2425
2711
  }
2426
2712
 
2427
2713
  // src/daemon/api/skills.ts
2428
- import fs11 from "fs";
2429
- import path13 from "path";
2714
+ import fs13 from "fs";
2715
+ import path14 from "path";
2430
2716
 
2431
2717
  // src/db/queries/skill-usage.ts
2432
2718
  var USAGE_COLUMNS = [
@@ -2593,15 +2879,15 @@ function createSkillRecordDeleteHandler(deps) {
2593
2879
  if (result.body?.deleted) {
2594
2880
  const record = result.body;
2595
2881
  if (record.name) {
2596
- const projectRoot = path13.resolve(vaultDir, "..");
2597
- const skillDir = path13.resolve(projectRoot, ".agents", "skills", record.name);
2882
+ const projectRoot = path14.resolve(vaultDir, "..");
2883
+ const skillDir = path14.resolve(projectRoot, ".agents", "skills", record.name);
2598
2884
  try {
2599
- fs11.rmSync(skillDir, { recursive: true, force: true });
2885
+ fs13.rmSync(skillDir, { recursive: true, force: true });
2600
2886
  } catch (err) {
2601
2887
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill directory", { name: record.name, error: String(err) });
2602
2888
  }
2603
2889
  try {
2604
- const { syncSkillSymlinks } = await import("./installer-45ZLP2RP.js");
2890
+ const { syncSkillSymlinks } = await import("./installer-BWJED3ED.js");
2605
2891
  syncSkillSymlinks(projectRoot, record.name, { remove: true });
2606
2892
  } catch (err) {
2607
2893
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill symlinks", { name: record.name, error: String(err) });
@@ -2854,12 +3140,12 @@ async function handleGetModels(req) {
2854
3140
 
2855
3141
  // src/daemon/api/stats.ts
2856
3142
  import { createHash as createHash2 } from "crypto";
2857
- import fs12 from "fs";
2858
- import path14 from "path";
3143
+ import fs14 from "fs";
3144
+ import path15 from "path";
2859
3145
  function computeConfigHash(vaultDir) {
2860
3146
  try {
2861
- const configPath = path14.join(vaultDir, CONFIG_FILENAME);
2862
- const raw = fs12.readFileSync(configPath, "utf-8");
3147
+ const configPath = path15.join(vaultDir, CONFIG_FILENAME);
3148
+ const raw = fs14.readFileSync(configPath, "utf-8");
2863
3149
  return createHash2("md5").update(raw).digest("hex");
2864
3150
  } catch {
2865
3151
  return "";
@@ -4212,6 +4498,13 @@ var EmbeddingManager = class {
4212
4498
  searchVectors(query, options) {
4213
4499
  return this.vectorStore.search(query, options);
4214
4500
  }
4501
+ /**
4502
+ * Compute pairwise cosine similarity between all vectors in a namespace.
4503
+ * Used by the evolve instruction builder to find semantically overlapping skills.
4504
+ */
4505
+ pairwiseSimilarity(namespace, threshold) {
4506
+ return this.vectorStore.pairwiseSimilarity(namespace, threshold);
4507
+ }
4215
4508
  // -------------------------------------------------------------------------
4216
4509
  // Private helpers
4217
4510
  // -------------------------------------------------------------------------
@@ -4482,6 +4775,48 @@ var SqliteVecVectorStore = class {
4482
4775
  const rows = this.embeddedIdsStmt.all(namespace);
4483
4776
  return rows.map((r) => r.record_id);
4484
4777
  }
4778
+ /**
4779
+ * Compute pairwise cosine similarity between all vectors in a namespace.
4780
+ * Returns pairs above the threshold, sorted by similarity DESC.
4781
+ *
4782
+ * Uses sqlite-vec's KNN search: for each vector, find the top-K nearest
4783
+ * neighbors within the same namespace. O(n * K) where K is small.
4784
+ */
4785
+ pairwiseSimilarity(namespace, threshold = 0.5) {
4786
+ this.validateNamespace(namespace);
4787
+ const ns = namespace;
4788
+ const allRows = this.db.prepare(
4789
+ `SELECT record_id, embedding FROM vec_${ns}`
4790
+ ).all();
4791
+ if (allRows.length < 2) return [];
4792
+ const pairs = [];
4793
+ const seen = /* @__PURE__ */ new Set();
4794
+ const searchStmt = this.searchStmts.get(ns);
4795
+ for (const row of allRows) {
4796
+ const results = searchStmt.all(
4797
+ row.embedding,
4798
+ // Use the raw embedding as the query vector
4799
+ allRows.length
4800
+ // K = all rows to get exhaustive comparison
4801
+ );
4802
+ for (const match of results) {
4803
+ if (match.record_id === row.record_id) continue;
4804
+ const pairKey = [row.record_id, match.record_id].sort().join("|");
4805
+ if (seen.has(pairKey)) continue;
4806
+ seen.add(pairKey);
4807
+ const similarity = cosineDistanceToSimilarity(match.distance);
4808
+ if (similarity >= threshold) {
4809
+ pairs.push({
4810
+ idA: row.record_id,
4811
+ idB: match.record_id,
4812
+ similarity: Math.round(similarity * 1e3) / 1e3
4813
+ });
4814
+ }
4815
+ }
4816
+ }
4817
+ pairs.sort((a, b) => b.similarity - a.similarity);
4818
+ return pairs;
4819
+ }
4485
4820
  // -------------------------------------------------------------------------
4486
4821
  // Lifecycle
4487
4822
  // -------------------------------------------------------------------------
@@ -4619,6 +4954,12 @@ function planMetadata(row) {
4619
4954
  ...row.source_path != null ? { source_path: row.source_path } : {}
4620
4955
  };
4621
4956
  }
4957
+ function skillRecordMetadata(row) {
4958
+ return {
4959
+ ...row.status != null ? { status: row.status } : {},
4960
+ ...row.name != null ? { name: row.name } : {}
4961
+ };
4962
+ }
4622
4963
  function metadataFor(namespace, row) {
4623
4964
  switch (namespace) {
4624
4965
  case "sessions":
@@ -4629,6 +4970,8 @@ function metadataFor(namespace, row) {
4629
4970
  return planMetadata(row);
4630
4971
  case "artifacts":
4631
4972
  return emptyMetadata();
4973
+ case "skill_records":
4974
+ return skillRecordMetadata(row);
4632
4975
  }
4633
4976
  }
4634
4977
  var SqliteRecordSource = class {
@@ -4643,6 +4986,9 @@ var SqliteRecordSource = class {
4643
4986
  if (namespace === "spores") {
4644
4987
  return this.getUnembeddedActiveSpores(limit);
4645
4988
  }
4989
+ if (namespace === "skill_records") {
4990
+ return this.getUnembeddedActiveSkillRecords(limit);
4991
+ }
4646
4992
  const rows = getUnembedded(namespace, limit);
4647
4993
  const db = getDatabase();
4648
4994
  return rows.map((row) => {
@@ -4689,6 +5035,12 @@ var SqliteRecordSource = class {
4689
5035
  ).all();
4690
5036
  return rows.map((r) => r.id);
4691
5037
  }
5038
+ case "skill_records": {
5039
+ const rows = db.prepare(
5040
+ `SELECT id FROM skill_records WHERE status = ?`
5041
+ ).all(ACTIVE_STATUS2);
5042
+ return rows.map((r) => r.id);
5043
+ }
4692
5044
  }
4693
5045
  }
4694
5046
  /**
@@ -4743,7 +5095,7 @@ var SqliteRecordSource = class {
4743
5095
  assertValidTable(namespace);
4744
5096
  const db = getDatabase();
4745
5097
  const contentFilter = namespace === "sessions" ? " AND summary IS NOT NULL" : "";
4746
- const statusFilter = namespace === "spores" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
5098
+ const statusFilter = namespace === "spores" || namespace === "skill_records" ? ` AND status = '${ACTIVE_STATUS2}'` : "";
4747
5099
  const row = db.prepare(
4748
5100
  `SELECT COUNT(*) AS cnt FROM ${namespace} WHERE embedded = 0${contentFilter}${statusFilter}`
4749
5101
  ).get();
@@ -4768,20 +5120,36 @@ var SqliteRecordSource = class {
4768
5120
  metadata: sporeMetadata(row)
4769
5121
  }));
4770
5122
  }
5123
+ /** Custom query for skill_records: embedded=0 AND status='active'. */
5124
+ getUnembeddedActiveSkillRecords(limit) {
5125
+ const db = getDatabase();
5126
+ const rows = db.prepare(
5127
+ `SELECT id, description AS text, status, name
5128
+ FROM skill_records
5129
+ WHERE embedded = 0 AND status = ?
5130
+ ORDER BY created_at ASC
5131
+ LIMIT ?`
5132
+ ).all(ACTIVE_STATUS2, limit);
5133
+ return rows.map((row) => ({
5134
+ id: String(row.id),
5135
+ text: row.text,
5136
+ metadata: skillRecordMetadata(row)
5137
+ }));
5138
+ }
4771
5139
  };
4772
5140
 
4773
5141
  // src/daemon/database/manager.ts
4774
- import fs14 from "fs";
5142
+ import fs16 from "fs";
4775
5143
 
4776
5144
  // src/db/queries/database.ts
4777
- import fs13 from "fs";
5145
+ import fs15 from "fs";
4778
5146
  function pragmaScalar(name) {
4779
5147
  const db = getDatabase();
4780
5148
  return db.pragma(name, { simple: true });
4781
5149
  }
4782
5150
  function safeFileSize(filePath) {
4783
5151
  try {
4784
- return fs13.statSync(filePath).size;
5152
+ return fs15.statSync(filePath).size;
4785
5153
  } catch (err) {
4786
5154
  if (err.code === "ENOENT") return 0;
4787
5155
  throw err;
@@ -5053,7 +5421,7 @@ var DatabaseMaintenanceManager = class {
5053
5421
  }
5054
5422
  async vacuum() {
5055
5423
  const size_before = this.fileSize();
5056
- const stats = await fs14.promises.statfs(this.vaultDir);
5424
+ const stats = await fs16.promises.statfs(this.vaultDir);
5057
5425
  const free_bytes = Number(stats.bavail) * Number(stats.bsize);
5058
5426
  const required_bytes = size_before * VACUUM_FREE_SPACE_MULTIPLIER;
5059
5427
  if (free_bytes < required_bytes) {
@@ -5101,7 +5469,7 @@ var DatabaseMaintenanceManager = class {
5101
5469
  }
5102
5470
  fileSize() {
5103
5471
  try {
5104
- return fs14.statSync(this.dbPath).size;
5472
+ return fs16.statSync(this.dbPath).size;
5105
5473
  } catch {
5106
5474
  return 0;
5107
5475
  }
@@ -5143,6 +5511,13 @@ function registerBuiltinDomains() {
5143
5511
  { id: "mycelium.spore.created", label: "New spore extracted", defaultMode: "summary", defaultLevel: "info" }
5144
5512
  ]
5145
5513
  });
5514
+ register({
5515
+ domain: "daemon",
5516
+ label: "Daemon",
5517
+ types: [
5518
+ { id: "daemon.version_sync", label: "Version sync restart", defaultMode: "banner", defaultLevel: "info" }
5519
+ ]
5520
+ });
5146
5521
  }
5147
5522
 
5148
5523
  // src/daemon/api/notifications.ts
@@ -5487,6 +5862,9 @@ function testAnthropic() {
5487
5862
  return { ok: true };
5488
5863
  }
5489
5864
 
5865
+ // src/daemon/task-scheduling.ts
5866
+ import { resolve } from "path";
5867
+
5490
5868
  // src/daemon/task-scheduler.ts
5491
5869
  function resolveSchedule(yamlSchedule, configOverride) {
5492
5870
  if (!configOverride?.schedule) return yamlSchedule;
@@ -5544,8 +5922,12 @@ async function registerScheduledTasks(powerManager, deps) {
5544
5922
  logger.info(LOG_KINDS.AGENT_RUN, "Scheduled agent tasks disabled globally (agent.scheduled_tasks_enabled: false)");
5545
5923
  return;
5546
5924
  }
5547
- const { loadAllTasks: loadAllTasks2 } = await import("./registry-TFQ22Z7N.js");
5925
+ const { loadAllTasks: loadAllTasks2 } = await import("./registry-O2NZLO3V.js");
5548
5926
  const allTasks = Array.from(loadAllTasks2(definitionsDir, vaultDir).values());
5927
+ const taskAgentMap = /* @__PURE__ */ new Map();
5928
+ for (const task of allTasks) {
5929
+ taskAgentMap.set(task.name, task.agent);
5930
+ }
5549
5931
  const initialLastRuns = {};
5550
5932
  try {
5551
5933
  const recentRuns = getDatabase().prepare(
@@ -5566,9 +5948,10 @@ async function registerScheduledTasks(powerManager, deps) {
5566
5948
  else runningTasks.delete(name);
5567
5949
  },
5568
5950
  runTask: async (taskName) => {
5569
- const { runAgent } = await import("./executor-NXKJU5KW.js");
5951
+ const { runAgent } = await import("./executor-UYIZC3L5.js");
5570
5952
  const taskConfig = config.agent.tasks?.[taskName];
5571
- const built = buildTaskInstruction(taskName, taskConfig?.params);
5953
+ const projectRoot = resolve(vaultDir, "..");
5954
+ const built = buildTaskInstruction(taskName, taskConfig?.params, taskAgentMap.get(taskName), projectRoot, embeddingManager);
5572
5955
  if (isInstructionRequiredTask(taskName) && !built) {
5573
5956
  logger.info(
5574
5957
  LOG_KINDS.AGENT_RUN,
@@ -5735,7 +6118,7 @@ function createMcpProxyHandlers(deps) {
5735
6118
  name: USER_AGENT_NAME,
5736
6119
  created_at: now
5737
6120
  });
5738
- const { insertResolutionEvent } = await import("./resolution-events-HGKIJOTA.js");
6121
+ const { insertResolutionEvent } = await import("./resolution-events-XWYLLDRK.js");
5739
6122
  const resolutionId = `res-${randomBytes(RESOLUTION_ID_RANDOM_BYTES).toString("hex")}`;
5740
6123
  insertResolutionEvent({
5741
6124
  id: resolutionId,
@@ -5817,6 +6200,7 @@ function createMcpProxyHandlers(deps) {
5817
6200
  }
5818
6201
 
5819
6202
  // src/daemon/api/agent-runs.ts
6203
+ import { resolve as resolve2 } from "path";
5820
6204
  var AGENT_RUNS_DEFAULT_LIMIT = 50;
5821
6205
  var AgentRunBody = external_exports.object({
5822
6206
  task: external_exports.string().optional(),
@@ -5843,9 +6227,11 @@ function createAgentRunHandlers(deps) {
5843
6227
  let built;
5844
6228
  try {
5845
6229
  const taskParams = mycoConfig.agent.tasks?.[task]?.params;
5846
- built = buildTaskInstruction(task, taskParams);
6230
+ const projectRoot = resolve2(vaultDir, "..");
6231
+ built = buildTaskInstruction(task, taskParams, agentId, projectRoot, embeddingManager);
5847
6232
  } catch {
5848
- built = buildTaskInstruction(task);
6233
+ const projectRoot = resolve2(vaultDir, "..");
6234
+ built = buildTaskInstruction(task, void 0, agentId, projectRoot, embeddingManager);
5849
6235
  }
5850
6236
  instruction = built?.instruction;
5851
6237
  runContext = built?.context;
@@ -5860,7 +6246,7 @@ function createAgentRunHandlers(deps) {
5860
6246
  };
5861
6247
  }
5862
6248
  }
5863
- const { runAgent } = await import("./executor-NXKJU5KW.js");
6249
+ const { runAgent } = await import("./executor-UYIZC3L5.js");
5864
6250
  const resultPromise = runAgent(vaultDir, {
5865
6251
  task,
5866
6252
  instruction,
@@ -5929,8 +6315,8 @@ function createAgentRunHandlers(deps) {
5929
6315
  }
5930
6316
 
5931
6317
  // src/daemon/api/attachments.ts
5932
- import fs15 from "fs";
5933
- import path15 from "path";
6318
+ import fs17 from "fs";
6319
+ import path16 from "path";
5934
6320
  var ATTACHMENT_MEDIA_TYPES = {
5935
6321
  png: "image/png",
5936
6322
  jpg: "image/jpeg",
@@ -5950,14 +6336,14 @@ function createAttachmentHandler(deps) {
5950
6336
  const contentType2 = att.media_type ?? "application/octet-stream";
5951
6337
  return { status: 200, headers: { "Content-Type": contentType2 }, body: att.data };
5952
6338
  }
5953
- const filePath = path15.join(vaultDir, "attachments", filename);
6339
+ const filePath = path16.join(vaultDir, "attachments", filename);
5954
6340
  let diskData;
5955
6341
  try {
5956
- diskData = fs15.readFileSync(filePath);
6342
+ diskData = fs17.readFileSync(filePath);
5957
6343
  } catch {
5958
6344
  return { status: 404, body: { error: "not_found" } };
5959
6345
  }
5960
- const ext = path15.extname(filename).slice(1).toLowerCase();
6346
+ const ext = path16.extname(filename).slice(1).toLowerCase();
5961
6347
  const contentType = ATTACHMENT_MEDIA_TYPES[ext] ?? "application/octet-stream";
5962
6348
  return { status: 200, headers: { "Content-Type": contentType }, body: diskData };
5963
6349
  }
@@ -5965,19 +6351,19 @@ function createAttachmentHandler(deps) {
5965
6351
  }
5966
6352
 
5967
6353
  // src/daemon/log-reconcile.ts
5968
- import fs16 from "fs";
5969
- import path16 from "path";
6354
+ import fs18 from "fs";
6355
+ import path17 from "path";
5970
6356
  function reconcileLogBuffer(logDir, sinceTimestamp) {
5971
6357
  let replayed = 0;
5972
6358
  const files = [];
5973
6359
  for (let i = 3; i >= 1; i--) {
5974
- const rotated = path16.join(logDir, `daemon.${i}.log`);
5975
- if (fs16.existsSync(rotated)) files.push(rotated);
6360
+ const rotated = path17.join(logDir, `daemon.${i}.log`);
6361
+ if (fs18.existsSync(rotated)) files.push(rotated);
5976
6362
  }
5977
- const current = path16.join(logDir, "daemon.log");
5978
- if (fs16.existsSync(current)) files.push(current);
6363
+ const current = path17.join(logDir, "daemon.log");
6364
+ if (fs18.existsSync(current)) files.push(current);
5979
6365
  for (const file of files) {
5980
- const content = fs16.readFileSync(file, "utf-8");
6366
+ const content = fs18.readFileSync(file, "utf-8");
5981
6367
  for (const line of content.split("\n")) {
5982
6368
  if (!line.trim()) continue;
5983
6369
  try {
@@ -6256,8 +6642,8 @@ function registerPowerJobs(powerManager, deps) {
6256
6642
  }
6257
6643
 
6258
6644
  // src/daemon/reconciliation.ts
6259
- import fs17 from "fs";
6260
- import path17 from "path";
6645
+ import fs19 from "fs";
6646
+ import path18 from "path";
6261
6647
 
6262
6648
  // src/daemon/event-handlers.ts
6263
6649
  var TOOL_INPUT_STORE_LIMIT = 4e3;
@@ -6426,10 +6812,10 @@ function createReconciler({ bufferDir, logger }) {
6426
6812
  function reconcileSession(sessionId) {
6427
6813
  if (reconciledSessions.has(sessionId)) return;
6428
6814
  reconciledSessions.add(sessionId);
6429
- const bufferPath = path17.join(bufferDir, `${sessionId}.jsonl`);
6815
+ const bufferPath = path18.join(bufferDir, `${sessionId}.jsonl`);
6430
6816
  let content;
6431
6817
  try {
6432
- content = fs17.readFileSync(bufferPath, "utf-8").trim();
6818
+ content = fs19.readFileSync(bufferPath, "utf-8").trim();
6433
6819
  } catch {
6434
6820
  return;
6435
6821
  }
@@ -6498,7 +6884,7 @@ function createReconciler({ bufferDir, logger }) {
6498
6884
  }
6499
6885
 
6500
6886
  // src/daemon/stop-processing.ts
6501
- import fs18 from "fs";
6887
+ import fs20 from "fs";
6502
6888
 
6503
6889
  // src/daemon/capture-images.ts
6504
6890
  var SESSION_SHORT_LEN = 6;
@@ -6535,6 +6921,78 @@ function captureBatchImages(input) {
6535
6921
  }
6536
6922
  }
6537
6923
 
6924
+ // src/daemon/plan-capture.ts
6925
+ import { createHash as createHash4 } from "crypto";
6926
+ import os7 from "os";
6927
+ import path19 from "path";
6928
+ function extractTaggedPlans(text, tags) {
6929
+ const results = [];
6930
+ for (const tag of tags) {
6931
+ const regex = new RegExp(`<${tag}>\\n?([\\s\\S]*?)\\n?</${tag}>`, "g");
6932
+ let match;
6933
+ while ((match = regex.exec(text)) !== null) {
6934
+ const content = match[1].trim();
6935
+ if (content) results.push({ tag, content });
6936
+ }
6937
+ }
6938
+ return results;
6939
+ }
6940
+ var TRANSCRIPT_SOURCE_PREFIX = "transcript:";
6941
+ var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
6942
+ "Write",
6943
+ "Edit",
6944
+ "Create",
6945
+ "write",
6946
+ "edit",
6947
+ "patch",
6948
+ "create"
6949
+ ]);
6950
+ var HEADING_REGEX = /^#\s+(.+)$/m;
6951
+ var PLAN_ID_HASH_LENGTH = 16;
6952
+ function isInPlanDirectory(filePath, watchDirs, projectRoot) {
6953
+ const abs = path19.isAbsolute(filePath) ? filePath : path19.resolve(projectRoot, filePath);
6954
+ return watchDirs.some((dir) => {
6955
+ const expanded = dir.startsWith("~/") ? path19.join(os7.homedir(), dir.slice(2)) : dir;
6956
+ const absDir = path19.isAbsolute(expanded) ? expanded : path19.resolve(projectRoot, expanded);
6957
+ const prefix = absDir.endsWith(path19.sep) ? absDir : absDir + path19.sep;
6958
+ return abs === absDir || abs.startsWith(prefix);
6959
+ });
6960
+ }
6961
+ function isPlanWriteEvent(toolName, toolInput, config) {
6962
+ if (!FILE_WRITE_TOOLS.has(toolName)) return null;
6963
+ const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
6964
+ if (typeof filePath !== "string") return null;
6965
+ if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
6966
+ if (config.extensions?.length) {
6967
+ const ext = path19.extname(filePath).toLowerCase();
6968
+ if (!config.extensions.includes(ext)) return null;
6969
+ }
6970
+ return filePath;
6971
+ }
6972
+ function parsePlanTitle(content, filename) {
6973
+ const match = HEADING_REGEX.exec(content);
6974
+ if (match) return match[1].trim();
6975
+ return filename ?? null;
6976
+ }
6977
+ function capturePlan(input) {
6978
+ const now = Math.floor(Date.now() / 1e3);
6979
+ const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
6980
+ const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
6981
+ const title = parsePlanTitle(input.content, path19.basename(input.sourcePath));
6982
+ return upsertPlan({
6983
+ id,
6984
+ title,
6985
+ content: input.content,
6986
+ source_path: input.sourcePath,
6987
+ session_id: input.sessionId,
6988
+ prompt_batch_id: input.promptBatchId ?? null,
6989
+ content_hash: contentHash,
6990
+ status: "active",
6991
+ created_at: now,
6992
+ updated_at: now
6993
+ });
6994
+ }
6995
+
6538
6996
  // src/daemon/skill-usage.ts
6539
6997
  import crypto from "crypto";
6540
6998
  var SKILL_USAGE_DETECTION_ENABLED = false;
@@ -6604,14 +7062,14 @@ function createStopProcessor(deps) {
6604
7062
  const StopBody = external_exports.object({
6605
7063
  session_id: external_exports.string(),
6606
7064
  user: external_exports.string().optional(),
6607
- transcript_path: external_exports.string().optional(),
6608
- last_assistant_message: external_exports.string().optional()
7065
+ transcript_path: external_exports.string().nullish(),
7066
+ last_assistant_message: external_exports.string().nullish()
6609
7067
  });
6610
7068
  async function triggerTitleSummary(sessionId) {
6611
7069
  if (config.agent.summary_batch_interval <= 0) return;
6612
7070
  if (config.agent.event_tasks_enabled === false) return;
6613
7071
  try {
6614
- const { runAgent } = await import("./executor-NXKJU5KW.js");
7072
+ const { runAgent } = await import("./executor-UYIZC3L5.js");
6615
7073
  runAgent(vaultDir, {
6616
7074
  task: "title-summary",
6617
7075
  instruction: `Process session ${sessionId} only`,
@@ -6701,7 +7159,7 @@ function createStopProcessor(deps) {
6701
7159
  let transcriptText = null;
6702
7160
  if (hookTranscriptPath) {
6703
7161
  try {
6704
- transcriptText = fs18.readFileSync(hookTranscriptPath, "utf-8");
7162
+ transcriptText = fs20.readFileSync(hookTranscriptPath, "utf-8");
6705
7163
  } catch {
6706
7164
  }
6707
7165
  }
@@ -6727,6 +7185,33 @@ function createStopProcessor(deps) {
6727
7185
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to populate batch responses", { error: String(err) });
6728
7186
  }
6729
7187
  }
7188
+ if (deps.planTags.length > 0) {
7189
+ for (const turn of allTurns) {
7190
+ if (!turn.aiResponse) continue;
7191
+ const taggedPlans = extractTaggedPlans(turn.aiResponse, deps.planTags);
7192
+ for (const { tag, content } of taggedPlans) {
7193
+ try {
7194
+ capturePlan({
7195
+ sourcePath: `${TRANSCRIPT_SOURCE_PREFIX}${tag}`,
7196
+ content,
7197
+ sessionId,
7198
+ promptBatchId: latestBatch?.id ?? null
7199
+ });
7200
+ logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan captured from transcript tag", {
7201
+ session_id: sessionId,
7202
+ tag,
7203
+ content_length: content.length
7204
+ });
7205
+ } catch (err) {
7206
+ logger.warn(LOG_KINDS.CAPTURE_PLAN, "Failed to capture plan from transcript tag", {
7207
+ session_id: sessionId,
7208
+ tag,
7209
+ error: err.message
7210
+ });
7211
+ }
7212
+ }
7213
+ }
7214
+ }
6730
7215
  if (!hasTitle) {
6731
7216
  triggerTitleSummary(sessionId);
6732
7217
  }
@@ -6766,11 +7251,18 @@ function createStopProcessor(deps) {
6766
7251
  }
6767
7252
  const handleStopRoute = async (req) => {
6768
7253
  const { session_id: sessionId, user, transcript_path: hookTranscriptPath, last_assistant_message: lastAssistantMessage } = StopBody.parse(req.body);
6769
- if (!registry.getSession(sessionId)) {
7254
+ const existingSessionMeta = registry.getSession(sessionId);
7255
+ if (!hookTranscriptPath && !existingSessionMeta) {
7256
+ logger.info(LOG_KINDS.HOOKS_STOP, "Stop ignored \u2014 ephemeral sub-invocation", {
7257
+ session_id: sessionId
7258
+ });
7259
+ return { body: { ok: true, ignored: "ephemeral-sub-invocation" } };
7260
+ }
7261
+ if (!existingSessionMeta) {
6770
7262
  registry.register(sessionId, { started_at: (/* @__PURE__ */ new Date()).toISOString() });
6771
7263
  logger.debug(LOG_KINDS.LIFECYCLE_AUTO_REGISTER, "Auto-registered session from stop event", { session_id: sessionId });
6772
7264
  }
6773
- const sessionMeta = registry.getSession(sessionId);
7265
+ const sessionMeta = existingSessionMeta ?? registry.getSession(sessionId);
6774
7266
  logger.info(LOG_KINDS.HOOKS_STOP, "Stop received", {
6775
7267
  session_id: sessionId,
6776
7268
  has_transcript_path: !!hookTranscriptPath,
@@ -6781,7 +7273,9 @@ function createStopProcessor(deps) {
6781
7273
  transcript_path: hookTranscriptPath ?? null,
6782
7274
  last_message_preview: lastAssistantMessage?.slice(0, LOG_MESSAGE_PREVIEW_CHARS) ?? null
6783
7275
  });
6784
- const run = () => processStopEvent(sessionId, user, sessionMeta, hookTranscriptPath, lastAssistantMessage).catch((err) => {
7276
+ const normalizedTranscriptPath = hookTranscriptPath ?? void 0;
7277
+ const normalizedAssistantMessage = lastAssistantMessage ?? void 0;
7278
+ const run = () => processStopEvent(sessionId, user, sessionMeta, normalizedTranscriptPath, normalizedAssistantMessage).catch((err) => {
6785
7279
  logger.error(LOG_KINDS.PROCESSOR_SESSION, "Stop processing failed", { session_id: sessionId, error: err.message });
6786
7280
  });
6787
7281
  const prev = activeStopProcessing ?? Promise.resolve();
@@ -6801,69 +7295,8 @@ function createStopProcessor(deps) {
6801
7295
  }
6802
7296
 
6803
7297
  // src/daemon/event-dispatch.ts
6804
- import fs19 from "fs";
6805
- import path19 from "path";
6806
-
6807
- // src/daemon/plan-capture.ts
6808
- import { createHash as createHash4 } from "crypto";
6809
- import os7 from "os";
6810
- import path18 from "path";
6811
- var FILE_WRITE_TOOLS = /* @__PURE__ */ new Set([
6812
- "Write",
6813
- "Edit",
6814
- "Create",
6815
- "write",
6816
- "edit",
6817
- "patch",
6818
- "create"
6819
- ]);
6820
- var HEADING_REGEX = /^#\s+(.+)$/m;
6821
- var PLAN_ID_HASH_LENGTH = 16;
6822
- function isInPlanDirectory(filePath, watchDirs, projectRoot) {
6823
- const abs = path18.isAbsolute(filePath) ? filePath : path18.resolve(projectRoot, filePath);
6824
- return watchDirs.some((dir) => {
6825
- const expanded = dir.startsWith("~/") ? path18.join(os7.homedir(), dir.slice(2)) : dir;
6826
- const absDir = path18.isAbsolute(expanded) ? expanded : path18.resolve(projectRoot, expanded);
6827
- const prefix = absDir.endsWith(path18.sep) ? absDir : absDir + path18.sep;
6828
- return abs === absDir || abs.startsWith(prefix);
6829
- });
6830
- }
6831
- function isPlanWriteEvent(toolName, toolInput, config) {
6832
- if (!FILE_WRITE_TOOLS.has(toolName)) return null;
6833
- const filePath = toolInput?.file_path ?? toolInput?.path ?? toolInput?.filePath;
6834
- if (typeof filePath !== "string") return null;
6835
- if (!isInPlanDirectory(filePath, config.watchDirs, config.projectRoot)) return null;
6836
- if (config.extensions?.length) {
6837
- const ext = path18.extname(filePath).toLowerCase();
6838
- if (!config.extensions.includes(ext)) return null;
6839
- }
6840
- return filePath;
6841
- }
6842
- function parsePlanTitle(content, filename) {
6843
- const match = HEADING_REGEX.exec(content);
6844
- if (match) return match[1].trim();
6845
- return filename ?? null;
6846
- }
6847
- function capturePlan(input) {
6848
- const now = Math.floor(Date.now() / 1e3);
6849
- const contentHash = createHash4(CONTENT_HASH_ALGORITHM).update(input.content).digest("hex");
6850
- const id = createHash4("md5").update(input.sourcePath).digest("hex").slice(0, PLAN_ID_HASH_LENGTH);
6851
- const title = parsePlanTitle(input.content, path18.basename(input.sourcePath));
6852
- return upsertPlan({
6853
- id,
6854
- title,
6855
- content: input.content,
6856
- source_path: input.sourcePath,
6857
- session_id: input.sessionId,
6858
- prompt_batch_id: input.promptBatchId ?? null,
6859
- content_hash: contentHash,
6860
- status: "active",
6861
- created_at: now,
6862
- updated_at: now
6863
- });
6864
- }
6865
-
6866
- // src/daemon/event-dispatch.ts
7298
+ import fs21 from "fs";
7299
+ import path20 from "path";
6867
7300
  var EventBody = external_exports.object({ type: external_exports.string(), session_id: external_exports.string() }).passthrough();
6868
7301
  function createEventDispatcher(deps) {
6869
7302
  const {
@@ -6902,7 +7335,7 @@ function createEventDispatcher(deps) {
6902
7335
  reconcileSession(event.session_id);
6903
7336
  }
6904
7337
  if (!sessionBuffers.has(event.session_id)) {
6905
- const bufferDir = path19.join(vaultDir, "buffer");
7338
+ const bufferDir = path20.join(vaultDir, "buffer");
6906
7339
  sessionBuffers.set(event.session_id, new EventBuffer(bufferDir, event.session_id));
6907
7340
  }
6908
7341
  sessionBuffers.get(event.session_id).append(event);
@@ -6956,10 +7389,10 @@ function createEventDispatcher(deps) {
6956
7389
  );
6957
7390
  if (planFilePath) {
6958
7391
  const captureSessionId = event.session_id;
6959
- fs19.promises.readFile(planFilePath, "utf-8").then((planContent) => {
7392
+ fs21.promises.readFile(planFilePath, "utf-8").then((planContent) => {
6960
7393
  const latestBatch = getLatestBatch(captureSessionId);
6961
7394
  capturePlan({
6962
- sourcePath: path19.relative(projectRoot, planFilePath),
7395
+ sourcePath: path20.relative(projectRoot, planFilePath),
6963
7396
  content: planContent,
6964
7397
  sessionId: captureSessionId,
6965
7398
  promptBatchId: latestBatch?.id ?? null
@@ -7101,14 +7534,14 @@ function createEventDispatcher(deps) {
7101
7534
  }
7102
7535
 
7103
7536
  // src/daemon/main.ts
7104
- import fs20 from "fs";
7537
+ import fs22 from "fs";
7105
7538
  import os8 from "os";
7106
- import path20 from "path";
7539
+ import path21 from "path";
7107
7540
  function killStaleDaemon(vaultDir, logger) {
7108
- const daemonJsonPath = path20.join(vaultDir, "daemon.json");
7541
+ const daemonJsonPath = path21.join(vaultDir, "daemon.json");
7109
7542
  try {
7110
- if (!fs20.existsSync(daemonJsonPath)) return;
7111
- const info = JSON.parse(fs20.readFileSync(daemonJsonPath, "utf-8"));
7543
+ if (!fs22.existsSync(daemonJsonPath)) return;
7544
+ const info = JSON.parse(fs22.readFileSync(daemonJsonPath, "utf-8"));
7112
7545
  if (!info.pid) return;
7113
7546
  if (info.pid === process.pid) return;
7114
7547
  try {
@@ -7117,7 +7550,7 @@ function killStaleDaemon(vaultDir, logger) {
7117
7550
  logger.info(LOG_KINDS.DAEMON_START, "Killed stale daemon", { pid: info.pid });
7118
7551
  } catch {
7119
7552
  }
7120
- fs20.unlinkSync(daemonJsonPath);
7553
+ fs22.unlinkSync(daemonJsonPath);
7121
7554
  } catch {
7122
7555
  }
7123
7556
  }
@@ -7127,18 +7560,19 @@ async function main() {
7127
7560
  process.stderr.write("Usage: mycod --vault <path>\n");
7128
7561
  process.exit(1);
7129
7562
  }
7130
- const vaultDir = path20.resolve(vaultArg);
7563
+ const vaultDir = path21.resolve(vaultArg);
7131
7564
  loadSecrets(vaultDir);
7132
7565
  const config = loadConfig(vaultDir);
7133
7566
  const manifests = loadManifests();
7134
7567
  const symbiontPlanDirs = manifests.flatMap((m) => m.capture?.planDirs ?? []);
7568
+ const symbiontPlanTags = [...new Set(manifests.flatMap((m) => m.capture?.planTags ?? []))];
7135
7569
  const projectRoot = process.cwd();
7136
7570
  let planWatchConfig = {
7137
7571
  watchDirs: [.../* @__PURE__ */ new Set([...symbiontPlanDirs, ...config.capture.plan_dirs ?? []])],
7138
7572
  projectRoot,
7139
7573
  extensions: config.capture.artifact_extensions
7140
7574
  };
7141
- const logger = new DaemonLogger(path20.join(vaultDir, "logs"), {
7575
+ const logger = new DaemonLogger(path21.join(vaultDir, "logs"), {
7142
7576
  level: config.daemon.log_level
7143
7577
  });
7144
7578
  if (config.daemon.log_level === "debug") {
@@ -7150,12 +7584,68 @@ async function main() {
7150
7584
  embedding_provider: config.embedding.provider
7151
7585
  });
7152
7586
  logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan watch directories", { dirs: planWatchConfig.watchDirs });
7587
+ if (symbiontPlanTags.length > 0) {
7588
+ logger.info(LOG_KINDS.CAPTURE_PLAN, "Plan transcript tags", { tags: symbiontPlanTags });
7589
+ }
7153
7590
  const machineId = getMachineId(vaultDir);
7154
7591
  logger.info(LOG_KINDS.DAEMON_START, "Machine ID resolved", { machine_id: machineId });
7592
+ let globalPrefix = null;
7593
+ try {
7594
+ globalPrefix = resolveGlobalPrefix();
7595
+ logger.debug(LOG_KINDS.DAEMON_START, "npm global prefix resolved", { prefix: globalPrefix });
7596
+ } catch (err) {
7597
+ logger.warn(LOG_KINDS.DAEMON_START, "Failed to resolve npm global prefix", {
7598
+ error: err.message
7599
+ });
7600
+ }
7601
+ const devCliEntry = detectDevBuild(
7602
+ globalPrefix,
7603
+ process.argv[1],
7604
+ fs22.realpathSync
7605
+ );
7606
+ if (devCliEntry) {
7607
+ setDevBuildCliEntry(devCliEntry);
7608
+ globalPrefix = null;
7609
+ logger.info(LOG_KINDS.DAEMON_START, "Dev build detected; update checks exempted", {
7610
+ cli_entry: devCliEntry
7611
+ });
7612
+ }
7155
7613
  const db = initDatabase(vaultDbPath(vaultDir));
7156
7614
  createSchema(db, machineId);
7157
7615
  registerBuiltinDomains();
7158
7616
  logger.info(LOG_KINDS.DAEMON_START, "SQLite initialized", { vault: vaultDir });
7617
+ {
7618
+ const reasonPath = path21.join(vaultDir, RESTART_REASON_FILENAME);
7619
+ try {
7620
+ if (fs22.existsSync(reasonPath)) {
7621
+ const raw = JSON.parse(fs22.readFileSync(reasonPath, "utf-8"));
7622
+ fs22.unlinkSync(reasonPath);
7623
+ if (raw.reason === "version_sync" && raw.to_version) {
7624
+ const message = raw.local_update_ran ? "Restarted and updated local project hooks." : "Restarted to pick up the latest version.";
7625
+ notify(vaultDir, {
7626
+ domain: "daemon",
7627
+ type: "daemon.version_sync",
7628
+ title: `Updated to v${raw.to_version}`,
7629
+ message,
7630
+ metadata: {
7631
+ from_version: raw.from_version ?? "unknown",
7632
+ to_version: raw.to_version,
7633
+ local_update_ran: raw.local_update_ran ?? false
7634
+ }
7635
+ });
7636
+ logger.info(LOG_KINDS.DAEMON_START, "Version sync restart detected", {
7637
+ from: raw.from_version,
7638
+ to: raw.to_version,
7639
+ local_update: raw.local_update_ran
7640
+ });
7641
+ }
7642
+ }
7643
+ } catch (err) {
7644
+ logger.warn(LOG_KINDS.DAEMON_START, "Failed to read restart-reason file", {
7645
+ error: err.message
7646
+ });
7647
+ }
7648
+ }
7159
7649
  initTeamContext(config.team.enabled, machineId);
7160
7650
  logger.setPersistFn((entry) => {
7161
7651
  const { timestamp, level, kind, component, message, ...rest } = entry;
@@ -7171,13 +7661,13 @@ async function main() {
7171
7661
  });
7172
7662
  const lastLogTimestamp = getMaxTimestamp();
7173
7663
  if (lastLogTimestamp) {
7174
- const logDir = path20.join(vaultDir, "logs");
7664
+ const logDir = path21.join(vaultDir, "logs");
7175
7665
  const replayedCount = reconcileLogBuffer(logDir, lastLogTimestamp);
7176
7666
  if (replayedCount > 0) {
7177
7667
  logger.info(LOG_KINDS.DAEMON_RECONCILE, `Replayed ${replayedCount} log entries from buffer`, { replayed: replayedCount });
7178
7668
  }
7179
7669
  }
7180
- const vectorsDbPath = path20.join(vaultDir, "vectors.db");
7670
+ const vectorsDbPath = path21.join(vaultDir, "vectors.db");
7181
7671
  const vectorStore = new SqliteVecVectorStore(vectorsDbPath);
7182
7672
  const llmProvider = createEmbeddingProvider(config.embedding);
7183
7673
  const embeddingProvider = new EmbeddingProviderAdapter(llmProvider, config.embedding);
@@ -7187,7 +7677,7 @@ async function main() {
7187
7677
  const databaseManager = new DatabaseMaintenanceManager(vaultDbPath(vaultDir), vaultDir, logger);
7188
7678
  let definitionsDir;
7189
7679
  try {
7190
- const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-NEX3UF6U.js");
7680
+ const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-SKKUMT5C.js");
7191
7681
  definitionsDir = resolveDefinitionsDir2();
7192
7682
  await registerBuiltInAgentsAndTasks(definitionsDir, vaultDir);
7193
7683
  logger.info(LOG_KINDS.AGENT_TASK, "Built-in agents and tasks registered");
@@ -7213,10 +7703,10 @@ async function main() {
7213
7703
  }
7214
7704
  let uiDir = null;
7215
7705
  {
7216
- const root = findPackageRoot(path20.dirname(new URL(import.meta.url).pathname));
7706
+ const root = findPackageRoot(path21.dirname(new URL(import.meta.url).pathname));
7217
7707
  if (root) {
7218
- const candidate = path20.join(root, "dist", "ui");
7219
- if (fs20.existsSync(candidate)) uiDir = candidate;
7708
+ const candidate = path21.join(root, "dist", "ui");
7709
+ if (fs22.existsSync(candidate)) uiDir = candidate;
7220
7710
  }
7221
7711
  }
7222
7712
  if (uiDir) {
@@ -7249,7 +7739,7 @@ async function main() {
7249
7739
  (p) => createPerProjectAdapter(p, claudeCodeAdapter.parseTurns)
7250
7740
  )
7251
7741
  });
7252
- const bufferDir = path20.join(vaultDir, "buffer");
7742
+ const bufferDir = path21.join(vaultDir, "buffer");
7253
7743
  const sessionBuffers = /* @__PURE__ */ new Map();
7254
7744
  const reconciler = createReconciler({ bufferDir, logger });
7255
7745
  reconciler.runStartupReconciliation();
@@ -7260,7 +7750,8 @@ async function main() {
7260
7750
  embeddingManager,
7261
7751
  logger,
7262
7752
  config,
7263
- vaultDir
7753
+ vaultDir,
7754
+ planTags: symbiontPlanTags
7264
7755
  });
7265
7756
  const sessionLifecycle = createSessionLifecycleHandlers({
7266
7757
  registry,
@@ -7335,11 +7826,12 @@ async function main() {
7335
7826
  server.registerRoute("POST", "/api/log", createLogIngestionHandler(logger));
7336
7827
  server.registerRoute("GET", "/api/models", async (req) => handleGetModels(req));
7337
7828
  server.registerRoute("POST", "/api/restart", async (req) => handleRestart({ vaultDir, progressTracker }, req.body));
7338
- const updateProjectRoot = path20.dirname(vaultDir);
7829
+ const updateProjectRoot = path21.dirname(vaultDir);
7339
7830
  const updateHandlers = createUpdateHandlers({
7340
7831
  vaultDir,
7341
7832
  projectRoot: updateProjectRoot,
7342
7833
  currentVersion: server.version,
7834
+ globalPrefix,
7343
7835
  scheduleShutdown: () => {
7344
7836
  setTimeout(() => {
7345
7837
  process.kill(process.pid, "SIGTERM");
@@ -7399,7 +7891,7 @@ async function main() {
7399
7891
  server.registerRoute("GET", "/api/mcp/sessions", mcpProxy.handleSessions);
7400
7892
  server.registerRoute("GET", "/api/mcp/team", mcpProxy.handleTeam);
7401
7893
  const rawBackupDir = config.backup.dir;
7402
- const backupDir = rawBackupDir ? path20.resolve(rawBackupDir.startsWith("~/") ? path20.join(os8.homedir(), rawBackupDir.slice(2)) : rawBackupDir) : path20.resolve(vaultDir, "backups");
7894
+ const backupDir = rawBackupDir ? path21.resolve(rawBackupDir.startsWith("~/") ? path21.join(os8.homedir(), rawBackupDir.slice(2)) : rawBackupDir) : path21.resolve(vaultDir, "backups");
7403
7895
  const backupHandlers = createBackupHandlers({ db, backupDir, machineId });
7404
7896
  server.registerRoute("POST", "/api/backup", backupHandlers.handleCreateBackup);
7405
7897
  server.registerRoute("GET", "/api/backups", backupHandlers.handleListBackups);
@@ -7412,6 +7904,7 @@ async function main() {
7412
7904
  const teamHandlers = createTeamHandlers({
7413
7905
  vaultDir,
7414
7906
  machineId,
7907
+ logger,
7415
7908
  getTeamClient: teamSync.getTeamClient,
7416
7909
  setTeamClient: teamSync.setTeamClient
7417
7910
  });
@@ -7421,6 +7914,7 @@ async function main() {
7421
7914
  server.registerRoute("POST", "/api/team/backfill", teamHandlers.handleBackfill);
7422
7915
  server.registerRoute("POST", "/api/team/retry-failed", teamHandlers.handleRetryFailed);
7423
7916
  server.registerRoute("POST", "/api/team/upgrade-worker", teamHandlers.handleUpgradeWorker);
7917
+ server.registerRoute("POST", "/api/team/rotate-mcp-token", teamHandlers.handleRotateMcpToken);
7424
7918
  server.registerRoute("GET", "/api/search", createSearchHandler({ embeddingManager, getTeamClient: teamSync.getTeamClient, machineId }));
7425
7919
  server.registerRoute("GET", "/api/activity", handleGetFeed);
7426
7920
  server.registerRoute("GET", "/api/embedding/status", async () => handleGetEmbeddingStatus(vaultDir));
@@ -7493,4 +7987,4 @@ export {
7493
7987
  handleUserPrompt,
7494
7988
  main
7495
7989
  };
7496
- //# sourceMappingURL=main-YFVBIRRK.js.map
7990
+ //# sourceMappingURL=main-5THODR77.js.map