@goondocks/myco 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/README.md +6 -4
  2. package/dist/{agent-run-T433ENJS.js → agent-run-S4MFWUSV.js} +8 -8
  3. package/dist/{agent-tasks-TAIU3V5I.js → agent-tasks-JZ77AZSK.js} +8 -8
  4. package/dist/{chunk-TRA3R4EC.js → chunk-34NHDRWI.js} +1 -3
  5. package/dist/chunk-34NHDRWI.js.map +1 -0
  6. package/dist/{chunk-LF5Z62X6.js → chunk-4JVHWBZF.js} +2 -2
  7. package/dist/{chunk-GDCSPMH4.js → chunk-6JZEAOLG.js} +3 -3
  8. package/dist/{chunk-2QMDRZPJ.js → chunk-C3GNF7RJ.js} +5 -5
  9. package/dist/{chunk-DJQOYEK3.js → chunk-CJ2KTRWI.js} +52 -4
  10. package/dist/chunk-CJ2KTRWI.js.map +1 -0
  11. package/dist/{chunk-3MEOYXOW.js → chunk-D2NTFSVO.js} +3 -3
  12. package/dist/{chunk-5YQ6VOFZ.js → chunk-DZWSHCAC.js} +2 -2
  13. package/dist/{chunk-CUADDHHU.js → chunk-E7NUADTQ.js} +9 -1
  14. package/dist/chunk-E7NUADTQ.js.map +1 -0
  15. package/dist/{chunk-4O3QNM5I.js → chunk-G6LM45FD.js} +3 -3
  16. package/dist/{chunk-SV6UCB2Z.js → chunk-GSKXOCFG.js} +3 -1
  17. package/dist/chunk-GSKXOCFG.js.map +1 -0
  18. package/dist/{chunk-RBFECYNA.js → chunk-I3S6L7QC.js} +2 -2
  19. package/dist/{chunk-SPJGJEFV.js → chunk-IRSNOBGD.js} +2 -2
  20. package/dist/{chunk-75J2BR4P.js → chunk-KYSLNB3C.js} +580 -415
  21. package/dist/chunk-KYSLNB3C.js.map +1 -0
  22. package/dist/{chunk-GYIA6XLB.js → chunk-MVBCON4D.js} +2 -2
  23. package/dist/chunk-MVBCON4D.js.map +1 -0
  24. package/dist/{chunk-6GG2IVNV.js → chunk-OH334Y3J.js} +4 -4
  25. package/dist/{chunk-Z7TZJ2SP.js → chunk-P6C6ADBU.js} +2 -2
  26. package/dist/{chunk-OKCSSDFC.js → chunk-RPILIIYT.js} +2 -2
  27. package/dist/{chunk-X5IXK5KO.js → chunk-TIAYBVSI.js} +153 -18
  28. package/dist/chunk-TIAYBVSI.js.map +1 -0
  29. package/dist/{chunk-BFM6AM6R.js → chunk-U255A3RE.js} +2 -2
  30. package/dist/chunk-U5EW2VIQ.js +86 -0
  31. package/dist/chunk-U5EW2VIQ.js.map +1 -0
  32. package/dist/{chunk-DTE3SHYK.js → chunk-UILSK6DK.js} +2 -2
  33. package/dist/{chunk-EYMKBNRP.js → chunk-V2ZBYKDU.js} +3 -3
  34. package/dist/{chunk-GCCBXCHF.js → chunk-VEQLNB7E.js} +3 -3
  35. package/dist/{chunk-TQO4PF5K.js → chunk-VQZPWCBH.js} +4 -4
  36. package/dist/{chunk-HHZ3RTEI.js → chunk-VWXDSDJU.js} +2 -2
  37. package/dist/{chunk-X4XFJG6I.js → chunk-W7ZOOZMK.js} +3 -3
  38. package/dist/{chunk-23FJUKCN.js → chunk-WKAYMCPR.js} +2 -2
  39. package/dist/{chunk-4BQ5QE76.js → chunk-XAXQ72L3.js} +9 -2
  40. package/dist/chunk-XAXQ72L3.js.map +1 -0
  41. package/dist/{cli-W37MRZHD.js → cli-U2FZT4GP.js} +42 -42
  42. package/dist/{client-YNTTC75R.js → client-MZL5SFQI.js} +5 -5
  43. package/dist/{config-MOWCOJJ4.js → config-VHHCGE4F.js} +4 -4
  44. package/dist/{detect-GFYKKHLJ.js → detect-6FNYONJF.js} +2 -2
  45. package/dist/{detect-providers-EU35RUL3.js → detect-providers-R7QOB3H6.js} +5 -5
  46. package/dist/{doctor-PAAQU5AS.js → doctor-OJW7SCDQ.js} +13 -13
  47. package/dist/{executor-4OXDK4ZA.js → executor-HP3Y64PD.js} +495 -157
  48. package/dist/executor-HP3Y64PD.js.map +1 -0
  49. package/dist/{init-PHQAQANR.js → init-XVAONLZ7.js} +18 -18
  50. package/dist/{init-wizard-RFD46XAJ.js → init-wizard-3OPLXLNA.js} +8 -8
  51. package/dist/{installer-BTUNKWOU.js → installer-AARSFXI6.js} +2 -2
  52. package/dist/llm-LS7U7BHC.js +17 -0
  53. package/dist/{loader-WGDVRGLM.js → loader-QDWQTBX4.js} +4 -4
  54. package/dist/{loader-WC4U5NM5.js → loader-YQDG5GI5.js} +4 -4
  55. package/dist/{logs-WFBX2I7C.js → logs-TMKNLSJY.js} +3 -3
  56. package/dist/{main-ADLCOYKM.js → main-VAU5UPY7.js} +608 -214
  57. package/dist/main-VAU5UPY7.js.map +1 -0
  58. package/dist/{open-3VPUP3HD.js → open-ES2AOXL5.js} +8 -8
  59. package/dist/{openai-embeddings-SEIV7AM3.js → openai-embeddings-FUW6CSN2.js} +5 -5
  60. package/dist/{openrouter-ELODIZRP.js → openrouter-YSIUSUQL.js} +5 -5
  61. package/dist/{post-compact-5NYLOC46.js → post-compact-CCSP4ZRC.js} +8 -8
  62. package/dist/{post-tool-use-SNNXSZ5Y.js → post-tool-use-5UIVOE7I.js} +7 -7
  63. package/dist/{post-tool-use-failure-POKVXQHY.js → post-tool-use-failure-SR2523FX.js} +8 -8
  64. package/dist/{pre-compact-ZUICBJEX.js → pre-compact-2G2UWGDZ.js} +8 -8
  65. package/dist/{provider-check-B66E5PWS.js → provider-check-VEYONGNU.js} +5 -5
  66. package/dist/{registry-DHWVHXWY.js → registry-5R3DLJQH.js} +5 -5
  67. package/dist/{remove-SVU2V4Q7.js → remove-L4HNBCSZ.js} +10 -10
  68. package/dist/{resolution-events-DBCRVZGU.js → resolution-events-CHOKR35X.js} +5 -5
  69. package/dist/{restart-NBB5CXJ4.js → restart-ZQ3QNRF4.js} +9 -9
  70. package/dist/{search-YUQZFRZX.js → search-ECJ76TU3.js} +9 -9
  71. package/dist/{server-NBRX56VL.js → server-4MUFDPDP.js} +5 -5
  72. package/dist/{session-2QP4HMZ5.js → session-ZHYO3BBY.js} +10 -10
  73. package/dist/{session-end-NNFBW7CQ.js → session-end-UJM3UODF.js} +7 -7
  74. package/dist/{session-start-NPNP4IXX.js → session-start-UXLG36AZ.js} +12 -12
  75. package/dist/{setup-llm-C3IGFLRN.js → setup-llm-NEN5XPNY.js} +9 -9
  76. package/dist/skill-staging-SWM7UC5D.js +25 -0
  77. package/dist/src/agent/definitions/tasks/full-intelligence.yaml +1 -1
  78. package/dist/src/agent/definitions/tasks/skill-generate.yaml +55 -21
  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 +1 -0
  88. package/dist/src/symbionts/templates/codex/settings.json +5 -0
  89. package/dist/src/worker/src/schema.ts +16 -0
  90. package/dist/{stats-FEEXIRMS.js → stats-AYRSUFHR.js} +10 -10
  91. package/dist/{stop-FGDGWXTK.js → stop-5WD22XAH.js} +7 -7
  92. package/dist/{stop-failure-5YAGH2TQ.js → stop-failure-FLFIOPJY.js} +8 -8
  93. package/dist/{subagent-start-UCKVJDR4.js → subagent-start-AMCPECUD.js} +8 -8
  94. package/dist/{subagent-stop-H25B3QEC.js → subagent-stop-4M4BUENR.js} +8 -8
  95. package/dist/{task-completed-2JGZN2CF.js → task-completed-QJOEVDXZ.js} +8 -8
  96. package/dist/{team-TG5WZXWO.js → team-FWEVWYIY.js} +6 -6
  97. package/dist/ui/assets/index-Bjv_ck3c.css +1 -0
  98. package/dist/ui/assets/index-RYHXSJv1.js +842 -0
  99. package/dist/ui/index.html +2 -2
  100. package/dist/{update-EG3N2EXI.js → update-F2LPJMUE.js} +10 -10
  101. package/dist/{user-prompt-submit-7FFQ3ORA.js → user-prompt-submit-UOAIU3JW.js} +7 -7
  102. package/dist/{verify-2M3DYHEY.js → verify-ITBMLK67.js} +9 -9
  103. package/dist/{version-JUQU5W22.js → version-2NJN3WW6.js} +2 -2
  104. package/dist/version-2NJN3WW6.js.map +1 -0
  105. package/package.json +1 -1
  106. package/dist/chunk-4BQ5QE76.js.map +0 -1
  107. package/dist/chunk-75J2BR4P.js.map +0 -1
  108. package/dist/chunk-CUADDHHU.js.map +0 -1
  109. package/dist/chunk-DJQOYEK3.js.map +0 -1
  110. package/dist/chunk-GYIA6XLB.js.map +0 -1
  111. package/dist/chunk-SV6UCB2Z.js.map +0 -1
  112. package/dist/chunk-TRA3R4EC.js.map +0 -1
  113. package/dist/chunk-X5IXK5KO.js.map +0 -1
  114. package/dist/executor-4OXDK4ZA.js.map +0 -1
  115. package/dist/llm-D4VWYUK7.js +0 -17
  116. package/dist/main-ADLCOYKM.js.map +0 -1
  117. package/dist/ui/assets/index-7Vimyg7g.js +0 -837
  118. package/dist/ui/assets/index-DlEQ8A8Y.css +0 -1
  119. /package/dist/{agent-run-T433ENJS.js.map → agent-run-S4MFWUSV.js.map} +0 -0
  120. /package/dist/{agent-tasks-TAIU3V5I.js.map → agent-tasks-JZ77AZSK.js.map} +0 -0
  121. /package/dist/{chunk-LF5Z62X6.js.map → chunk-4JVHWBZF.js.map} +0 -0
  122. /package/dist/{chunk-GDCSPMH4.js.map → chunk-6JZEAOLG.js.map} +0 -0
  123. /package/dist/{chunk-2QMDRZPJ.js.map → chunk-C3GNF7RJ.js.map} +0 -0
  124. /package/dist/{chunk-3MEOYXOW.js.map → chunk-D2NTFSVO.js.map} +0 -0
  125. /package/dist/{chunk-5YQ6VOFZ.js.map → chunk-DZWSHCAC.js.map} +0 -0
  126. /package/dist/{chunk-4O3QNM5I.js.map → chunk-G6LM45FD.js.map} +0 -0
  127. /package/dist/{chunk-RBFECYNA.js.map → chunk-I3S6L7QC.js.map} +0 -0
  128. /package/dist/{chunk-SPJGJEFV.js.map → chunk-IRSNOBGD.js.map} +0 -0
  129. /package/dist/{chunk-6GG2IVNV.js.map → chunk-OH334Y3J.js.map} +0 -0
  130. /package/dist/{chunk-Z7TZJ2SP.js.map → chunk-P6C6ADBU.js.map} +0 -0
  131. /package/dist/{chunk-OKCSSDFC.js.map → chunk-RPILIIYT.js.map} +0 -0
  132. /package/dist/{chunk-BFM6AM6R.js.map → chunk-U255A3RE.js.map} +0 -0
  133. /package/dist/{chunk-DTE3SHYK.js.map → chunk-UILSK6DK.js.map} +0 -0
  134. /package/dist/{chunk-EYMKBNRP.js.map → chunk-V2ZBYKDU.js.map} +0 -0
  135. /package/dist/{chunk-GCCBXCHF.js.map → chunk-VEQLNB7E.js.map} +0 -0
  136. /package/dist/{chunk-TQO4PF5K.js.map → chunk-VQZPWCBH.js.map} +0 -0
  137. /package/dist/{chunk-HHZ3RTEI.js.map → chunk-VWXDSDJU.js.map} +0 -0
  138. /package/dist/{chunk-X4XFJG6I.js.map → chunk-W7ZOOZMK.js.map} +0 -0
  139. /package/dist/{chunk-23FJUKCN.js.map → chunk-WKAYMCPR.js.map} +0 -0
  140. /package/dist/{cli-W37MRZHD.js.map → cli-U2FZT4GP.js.map} +0 -0
  141. /package/dist/{client-YNTTC75R.js.map → client-MZL5SFQI.js.map} +0 -0
  142. /package/dist/{config-MOWCOJJ4.js.map → config-VHHCGE4F.js.map} +0 -0
  143. /package/dist/{detect-GFYKKHLJ.js.map → detect-6FNYONJF.js.map} +0 -0
  144. /package/dist/{detect-providers-EU35RUL3.js.map → detect-providers-R7QOB3H6.js.map} +0 -0
  145. /package/dist/{doctor-PAAQU5AS.js.map → doctor-OJW7SCDQ.js.map} +0 -0
  146. /package/dist/{init-PHQAQANR.js.map → init-XVAONLZ7.js.map} +0 -0
  147. /package/dist/{init-wizard-RFD46XAJ.js.map → init-wizard-3OPLXLNA.js.map} +0 -0
  148. /package/dist/{installer-BTUNKWOU.js.map → installer-AARSFXI6.js.map} +0 -0
  149. /package/dist/{llm-D4VWYUK7.js.map → llm-LS7U7BHC.js.map} +0 -0
  150. /package/dist/{loader-WC4U5NM5.js.map → loader-QDWQTBX4.js.map} +0 -0
  151. /package/dist/{loader-WGDVRGLM.js.map → loader-YQDG5GI5.js.map} +0 -0
  152. /package/dist/{logs-WFBX2I7C.js.map → logs-TMKNLSJY.js.map} +0 -0
  153. /package/dist/{open-3VPUP3HD.js.map → open-ES2AOXL5.js.map} +0 -0
  154. /package/dist/{openai-embeddings-SEIV7AM3.js.map → openai-embeddings-FUW6CSN2.js.map} +0 -0
  155. /package/dist/{openrouter-ELODIZRP.js.map → openrouter-YSIUSUQL.js.map} +0 -0
  156. /package/dist/{post-compact-5NYLOC46.js.map → post-compact-CCSP4ZRC.js.map} +0 -0
  157. /package/dist/{post-tool-use-SNNXSZ5Y.js.map → post-tool-use-5UIVOE7I.js.map} +0 -0
  158. /package/dist/{post-tool-use-failure-POKVXQHY.js.map → post-tool-use-failure-SR2523FX.js.map} +0 -0
  159. /package/dist/{pre-compact-ZUICBJEX.js.map → pre-compact-2G2UWGDZ.js.map} +0 -0
  160. /package/dist/{provider-check-B66E5PWS.js.map → provider-check-VEYONGNU.js.map} +0 -0
  161. /package/dist/{registry-DHWVHXWY.js.map → registry-5R3DLJQH.js.map} +0 -0
  162. /package/dist/{remove-SVU2V4Q7.js.map → remove-L4HNBCSZ.js.map} +0 -0
  163. /package/dist/{resolution-events-DBCRVZGU.js.map → resolution-events-CHOKR35X.js.map} +0 -0
  164. /package/dist/{restart-NBB5CXJ4.js.map → restart-ZQ3QNRF4.js.map} +0 -0
  165. /package/dist/{search-YUQZFRZX.js.map → search-ECJ76TU3.js.map} +0 -0
  166. /package/dist/{server-NBRX56VL.js.map → server-4MUFDPDP.js.map} +0 -0
  167. /package/dist/{session-2QP4HMZ5.js.map → session-ZHYO3BBY.js.map} +0 -0
  168. /package/dist/{session-end-NNFBW7CQ.js.map → session-end-UJM3UODF.js.map} +0 -0
  169. /package/dist/{session-start-NPNP4IXX.js.map → session-start-UXLG36AZ.js.map} +0 -0
  170. /package/dist/{setup-llm-C3IGFLRN.js.map → setup-llm-NEN5XPNY.js.map} +0 -0
  171. /package/dist/{version-JUQU5W22.js.map → skill-staging-SWM7UC5D.js.map} +0 -0
  172. /package/dist/{stats-FEEXIRMS.js.map → stats-AYRSUFHR.js.map} +0 -0
  173. /package/dist/{stop-FGDGWXTK.js.map → stop-5WD22XAH.js.map} +0 -0
  174. /package/dist/{stop-failure-5YAGH2TQ.js.map → stop-failure-FLFIOPJY.js.map} +0 -0
  175. /package/dist/{subagent-start-UCKVJDR4.js.map → subagent-start-AMCPECUD.js.map} +0 -0
  176. /package/dist/{subagent-stop-H25B3QEC.js.map → subagent-stop-4M4BUENR.js.map} +0 -0
  177. /package/dist/{task-completed-2JGZN2CF.js.map → task-completed-QJOEVDXZ.js.map} +0 -0
  178. /package/dist/{team-TG5WZXWO.js.map → team-FWEVWYIY.js.map} +0 -0
  179. /package/dist/{update-EG3N2EXI.js.map → update-F2LPJMUE.js.map} +0 -0
  180. /package/dist/{user-prompt-submit-7FFQ3ORA.js.map → user-prompt-submit-UOAIU3JW.js.map} +0 -0
  181. /package/dist/{verify-2M3DYHEY.js.map → verify-ITBMLK67.js.map} +0 -0
@@ -2,8 +2,19 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  DaemonLogger,
4
4
  LEVEL_ORDER
5
- } from "./chunk-GYIA6XLB.js";
5
+ } from "./chunk-MVBCON4D.js";
6
6
  import {
7
+ EMBEDDABLE_TABLES,
8
+ EMBEDDABLE_TEXT_COLUMNS,
9
+ assertValidTable,
10
+ clearEmbedded,
11
+ gatherStats,
12
+ getEmbeddingQueueDepth,
13
+ getUnembedded,
14
+ markEmbedded
15
+ } from "./chunk-VQZPWCBH.js";
16
+ import {
17
+ buildTaskInstruction,
7
18
  closeOpenBatches,
8
19
  countBatchesBySession,
9
20
  countCandidates,
@@ -30,8 +41,8 @@ import {
30
41
  incrementActivityCount,
31
42
  incrementSkillUsageCount,
32
43
  insertBatchStateless,
44
+ isInstructionRequiredTask,
33
45
  listBatchesBySession,
34
- listCandidates,
35
46
  listCandidatesWithCount,
36
47
  listDigestExtracts,
37
48
  listEntities,
@@ -48,78 +59,71 @@ import {
48
59
  setResponseSummary,
49
60
  updateCandidate,
50
61
  updateNotificationStatus
51
- } from "./chunk-75J2BR4P.js";
62
+ } from "./chunk-KYSLNB3C.js";
52
63
  import {
53
64
  fullTextSearch,
54
65
  hydrateSearchResults
55
- } from "./chunk-DTE3SHYK.js";
66
+ } from "./chunk-UILSK6DK.js";
67
+ import {
68
+ cleanupStagedSkill,
69
+ listStaleStagingDirs
70
+ } from "./chunk-U5EW2VIQ.js";
56
71
  import {
57
72
  withTaskConfig
58
73
  } from "./chunk-SODRR3HE.js";
59
- import {
60
- EMBEDDABLE_TABLES,
61
- EMBEDDABLE_TEXT_COLUMNS,
62
- assertValidTable,
63
- clearEmbedded,
64
- gatherStats,
65
- getEmbeddingQueueDepth,
66
- getUnembedded,
67
- markEmbedded
68
- } from "./chunk-TQO4PF5K.js";
69
74
  import {
70
75
  getMachineId
71
76
  } from "./chunk-ENWBFX7F.js";
72
77
  import {
73
78
  createEmbeddingProvider
74
- } from "./chunk-2QMDRZPJ.js";
79
+ } from "./chunk-C3GNF7RJ.js";
75
80
  import {
76
81
  copyTaskToUser,
77
82
  deleteUserTask,
78
83
  loadAllTasks,
79
84
  validateTaskName,
80
85
  writeUserTask
81
- } from "./chunk-3MEOYXOW.js";
86
+ } from "./chunk-D2NTFSVO.js";
82
87
  import {
83
88
  AgentTaskSchema,
84
89
  registerAgent,
85
90
  resolveDefinitionsDir,
86
91
  taskFromParsed
87
- } from "./chunk-X4XFJG6I.js";
92
+ } from "./chunk-W7ZOOZMK.js";
88
93
  import {
89
94
  listTurnsByRun
90
95
  } from "./chunk-QLCD77AN.js";
91
96
  import {
92
97
  checkLocalProvider
93
- } from "./chunk-GDCSPMH4.js";
98
+ } from "./chunk-6JZEAOLG.js";
94
99
  import {
95
100
  EventBuffer,
96
101
  cleanStaleBuffers,
97
102
  listBufferSessionIds
98
103
  } from "./chunk-V7XG6V6C.js";
99
104
  import "./chunk-IB76KGBY.js";
100
- import "./chunk-RBFECYNA.js";
101
- import "./chunk-OKCSSDFC.js";
102
- import "./chunk-5YQ6VOFZ.js";
103
- import "./chunk-6GG2IVNV.js";
105
+ import "./chunk-I3S6L7QC.js";
106
+ import "./chunk-RPILIIYT.js";
107
+ import "./chunk-DZWSHCAC.js";
108
+ import "./chunk-OH334Y3J.js";
104
109
  import "./chunk-SAKJMNSR.js";
105
110
  import {
106
111
  loadSecrets,
107
112
  readSecrets,
108
113
  writeSecret
109
114
  } from "./chunk-RJMXDUMA.js";
110
- import "./chunk-X5IXK5KO.js";
115
+ import "./chunk-TIAYBVSI.js";
111
116
  import {
112
117
  LmStudioBackend,
113
118
  OllamaBackend
114
- } from "./chunk-HHZ3RTEI.js";
119
+ } from "./chunk-VWXDSDJU.js";
115
120
  import {
116
121
  countSpores,
117
122
  getSpore,
118
123
  insertSpore,
119
- listSporeIdsSince,
120
124
  listSpores,
121
125
  updateSporeStatus
122
- } from "./chunk-SPJGJEFV.js";
126
+ } from "./chunk-IRSNOBGD.js";
123
127
  import {
124
128
  closeSession,
125
129
  countSessions,
@@ -130,7 +134,7 @@ import {
130
134
  listSessions,
131
135
  updateSession,
132
136
  upsertSession
133
- } from "./chunk-23FJUKCN.js";
137
+ } from "./chunk-WKAYMCPR.js";
134
138
  import {
135
139
  backfillUnsynced,
136
140
  countDeadLettered,
@@ -146,12 +150,13 @@ import {
146
150
  pruneOld,
147
151
  retryDeadLettered,
148
152
  syncRow
149
- } from "./chunk-LF5Z62X6.js";
153
+ } from "./chunk-4JVHWBZF.js";
150
154
  import {
151
155
  EMBEDDING_DIMENSIONS,
156
+ REST_SETTABLE_STATUSES,
152
157
  SCHEMA_VERSION,
153
158
  createSchema
154
- } from "./chunk-DJQOYEK3.js";
159
+ } from "./chunk-CJ2KTRWI.js";
155
160
  import {
156
161
  CONFIG_FILENAME,
157
162
  MycoConfigSchema,
@@ -160,7 +165,7 @@ import {
160
165
  updateBackupConfig,
161
166
  updateConfig,
162
167
  updateTeamConfig
163
- } from "./chunk-4BQ5QE76.js";
168
+ } from "./chunk-XAXQ72L3.js";
164
169
  import {
165
170
  closeDatabase,
166
171
  getDatabase,
@@ -169,13 +174,13 @@ import {
169
174
  } from "./chunk-MYX5NCRH.js";
170
175
  import {
171
176
  resolveCliEntryPath
172
- } from "./chunk-4O3QNM5I.js";
177
+ } from "./chunk-G6LM45FD.js";
173
178
  import {
174
179
  getPluginVersion
175
- } from "./chunk-BFM6AM6R.js";
180
+ } from "./chunk-U255A3RE.js";
176
181
  import {
177
182
  loadManifests
178
- } from "./chunk-SV6UCB2Z.js";
183
+ } from "./chunk-GSKXOCFG.js";
179
184
  import {
180
185
  findPackageRoot
181
186
  } from "./chunk-LPUQPDC2.js";
@@ -190,7 +195,6 @@ import {
190
195
  EMBEDDING_BATCH_SIZE,
191
196
  EXCLUDED_SPORE_STATUSES,
192
197
  FEED_DEFAULT_LIMIT,
193
- LOG_CONTEXT_PREVIEW_CHARS,
194
198
  LOG_MESSAGE_PREVIEW_CHARS,
195
199
  LOG_PROMPT_PREVIEW_CHARS,
196
200
  MS_PER_DAY,
@@ -230,11 +234,11 @@ import {
230
234
  USER_TASK_SOURCE,
231
235
  epochSeconds,
232
236
  estimateTokens
233
- } from "./chunk-TRA3R4EC.js";
237
+ } from "./chunk-34NHDRWI.js";
234
238
  import {
235
239
  LOG_KINDS,
236
240
  kindToComponent
237
- } from "./chunk-CUADDHHU.js";
241
+ } from "./chunk-E7NUADTQ.js";
238
242
  import {
239
243
  require_dist
240
244
  } from "./chunk-D7TYRPRM.js";
@@ -1326,6 +1330,12 @@ function createPlanDirHandlers(deps) {
1326
1330
  return { handleGetPlanDirs, handleUpdatePlanDirs };
1327
1331
  }
1328
1332
 
1333
+ // src/utils/parse-csv-list.ts
1334
+ function parseCsvList(raw) {
1335
+ if (!raw) return [];
1336
+ return raw.split(",").map((token) => token.trim()).filter((token) => token.length > 0);
1337
+ }
1338
+
1329
1339
  // src/db/queries/logs.ts
1330
1340
  var DEFAULT_PAGE_SIZE = 100;
1331
1341
  var DEFAULT_STREAM_LIMIT = 200;
@@ -1382,7 +1392,7 @@ function searchLogs(params) {
1382
1392
  }
1383
1393
  }
1384
1394
  if (params.component !== void 0 && params.component.length > 0) {
1385
- const components = params.component.split(",").map((c) => c.trim()).filter(Boolean);
1395
+ const components = parseCsvList(params.component);
1386
1396
  if (components.length > 0) {
1387
1397
  conditions.push(`le.component IN (SELECT value FROM json_each(?))`);
1388
1398
  queryParams.push(JSON.stringify(components));
@@ -1437,6 +1447,19 @@ function getLogsSince(sinceId, limit) {
1437
1447
  const cursor = entries.length > 0 ? entries[entries.length - 1].id : sinceId;
1438
1448
  return { entries, cursor };
1439
1449
  }
1450
+ function getLogTail(limit) {
1451
+ const db = getDatabase();
1452
+ const effectiveLimit = limit ?? DEFAULT_STREAM_LIMIT;
1453
+ const rows = db.prepare(
1454
+ `SELECT id, timestamp, level, kind, component, message, data, session_id
1455
+ FROM log_entries
1456
+ ORDER BY id DESC
1457
+ LIMIT ?`
1458
+ ).all(effectiveLimit);
1459
+ const entries = rows.map(toLogEntryRow).reverse();
1460
+ const cursor = entries.length > 0 ? entries[entries.length - 1].id : 0;
1461
+ return { entries, cursor };
1462
+ }
1440
1463
  function getLogEntry(id) {
1441
1464
  const db = getDatabase();
1442
1465
  const row = db.prepare(
@@ -1488,12 +1511,14 @@ async function handleLogSearch(req) {
1488
1511
  async function handleLogStream(req) {
1489
1512
  const sinceStr = req.query.since;
1490
1513
  const limitStr = req.query.limit;
1491
- const sinceId = sinceStr ? parseInt(sinceStr, 10) : 0;
1514
+ const categoryFilter = req.query.category || void 0;
1492
1515
  const limit = limitStr ? parseInt(limitStr, 10) : void 0;
1493
- const result = getLogsSince(sinceId, limit);
1516
+ const result = sinceStr === void 0 ? getLogTail(limit) : getLogsSince(parseInt(sinceStr, 10), limit);
1517
+ const entries = result.entries.map(formatEntry);
1518
+ const filtered = categoryFilter ? entries.filter((e) => e.category === categoryFilter) : entries;
1494
1519
  return {
1495
1520
  body: {
1496
- entries: result.entries.map(formatEntry),
1521
+ entries: filtered,
1497
1522
  cursor: result.cursor
1498
1523
  }
1499
1524
  };
@@ -1536,8 +1561,11 @@ function createLogIngestionHandler(logger) {
1536
1561
  };
1537
1562
  }
1538
1563
  function formatEntry(entry) {
1564
+ const dot = entry.kind.indexOf(".");
1565
+ const category = dot > 0 ? entry.kind.slice(0, dot) : entry.kind;
1539
1566
  return {
1540
1567
  ...entry,
1568
+ category,
1541
1569
  data: entry.data ? JSON.parse(entry.data) : null
1542
1570
  };
1543
1571
  }
@@ -2299,7 +2327,7 @@ function createTeamHandlers(deps) {
2299
2327
  return { body: { retried: count } };
2300
2328
  }
2301
2329
  async function handleUpgradeWorker(_req) {
2302
- const { upgradeWorker } = await import("./team-TG5WZXWO.js");
2330
+ const { upgradeWorker } = await import("./team-FWEVWYIY.js");
2303
2331
  const result = upgradeWorker(vaultDir);
2304
2332
  if (!result.success) {
2305
2333
  return { status: 500, body: { error: result.error } };
@@ -2457,10 +2485,13 @@ function countUsageForSkill(skillId) {
2457
2485
  // src/daemon/api/skills.ts
2458
2486
  var DEFAULT_LIST_OFFSET = 0;
2459
2487
  async function handleListCandidates(req) {
2460
- const status = req.query.status || void 0;
2461
2488
  const limit = req.query.limit ? Number(req.query.limit) : DEFAULT_LIST_LIMIT;
2462
2489
  const offset = req.query.offset ? Number(req.query.offset) : DEFAULT_LIST_OFFSET;
2463
- const { items: candidates, total } = listCandidatesWithCount({ status, limit, offset });
2490
+ const { items: candidates, total } = listCandidatesWithCount({
2491
+ statuses: parseCsvList(req.query.status),
2492
+ limit,
2493
+ offset
2494
+ });
2464
2495
  return { status: 200, body: { candidates, total } };
2465
2496
  }
2466
2497
  async function handleGetCandidate(req) {
@@ -2470,11 +2501,22 @@ async function handleGetCandidate(req) {
2470
2501
  }
2471
2502
  return { status: 200, body: { candidate } };
2472
2503
  }
2504
+ var ALLOWED_REST_STATUSES = new Set(REST_SETTABLE_STATUSES);
2473
2505
  async function handleUpdateCandidate(req) {
2474
2506
  const id = req.params.id;
2475
2507
  const body = req.body;
2476
2508
  if (!body) return { status: 400, body: { error: "Request body required" } };
2477
2509
  const { status, topic, rationale, confidence, source_ids, skill_id } = body;
2510
+ if (status !== void 0) {
2511
+ if (typeof status !== "string" || !ALLOWED_REST_STATUSES.has(status)) {
2512
+ return {
2513
+ status: 400,
2514
+ body: {
2515
+ error: `Invalid status '${String(status)}'. REST callers may only set: ${[...ALLOWED_REST_STATUSES].join(", ")}. The 'generated' status is set internally by vault_finalize_skill after validation.`
2516
+ }
2517
+ };
2518
+ }
2519
+ }
2478
2520
  const updated = updateCandidate(id, {
2479
2521
  ...status !== void 0 ? { status } : {},
2480
2522
  ...topic !== void 0 ? { topic } : {},
@@ -2560,7 +2602,7 @@ function createSkillRecordDeleteHandler(deps) {
2560
2602
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill directory", { name: record.name, error: String(err) });
2561
2603
  }
2562
2604
  try {
2563
- const { syncSkillSymlinks } = await import("./installer-BTUNKWOU.js");
2605
+ const { syncSkillSymlinks } = await import("./installer-AARSFXI6.js");
2564
2606
  syncSkillSymlinks(projectRoot, record.name, { remove: true });
2565
2607
  } catch (err) {
2566
2608
  logger.warn(LOG_KINDS.PROCESSOR_BATCH, "Failed to remove skill symlinks", { name: record.name, error: String(err) });
@@ -3582,19 +3624,19 @@ function createSessionContextHandler(deps) {
3582
3624
  const source = extract ? "digest" : "basic";
3583
3625
  const contextText = parts.join("\n\n");
3584
3626
  const estimatedTokens = estimateTokens(contextText);
3585
- const preview = contextText.slice(0, LOG_CONTEXT_PREVIEW_CHARS);
3586
- logger.info(LOG_KINDS.CONTEXT_SESSION, "Session context injected", {
3587
- session_id,
3588
- source,
3589
- tier: extract ? tier : void 0,
3590
- text_length: contextText.length,
3591
- estimated_tokens: estimatedTokens,
3592
- generated_at: extract?.generated_at,
3593
- preview
3594
- });
3595
- logger.debug(LOG_KINDS.CONTEXT_SESSION, `Session context: "${preview}\u2026" (${estimatedTokens} est. tokens, source=${source}${extract ? `, tier=${tier}, generated=${extract.generated_at}` : ""})`, {
3596
- session_id
3597
- });
3627
+ logger.info(
3628
+ LOG_KINDS.CONTEXT_SESSION,
3629
+ `Session context: ${estimatedTokens} est. tokens, source=${source}${extract ? `, tier=${tier}` : ""}`,
3630
+ {
3631
+ session_id,
3632
+ source,
3633
+ tier: extract ? tier : void 0,
3634
+ text_length: contextText.length,
3635
+ estimated_tokens: estimatedTokens,
3636
+ generated_at: extract?.generated_at,
3637
+ injected_text: contextText
3638
+ }
3639
+ );
3598
3640
  return {
3599
3641
  body: {
3600
3642
  text: contextText,
@@ -3663,17 +3705,13 @@ function createPromptContextHandler(deps) {
3663
3705
  const text = formatSporeContext(spores);
3664
3706
  const promptTokens = estimateTokens(text);
3665
3707
  const titles = spores.map((s) => s.title);
3666
- logger.info(LOG_KINDS.CONTEXT_PROMPT, "Prompt context injected", {
3708
+ logger.info(LOG_KINDS.CONTEXT_PROMPT, `Prompt context: ${spores.length} spores [${titles.join(", ")}] (~${promptTokens} tokens)`, {
3667
3709
  session_id,
3668
3710
  spore_count: spores.length,
3669
- scores: spores.map((s) => s.score.toFixed(3)),
3670
3711
  spore_titles: titles,
3712
+ scores: spores.map((s) => s.score.toFixed(3)),
3671
3713
  estimated_tokens: promptTokens,
3672
- preview: text.slice(0, LOG_CONTEXT_PREVIEW_CHARS)
3673
- });
3674
- logger.debug(LOG_KINDS.CONTEXT_PROMPT, `Prompt context: ${spores.length} spores [${titles.join(", ")}] (~${promptTokens} tokens)`, {
3675
- session_id,
3676
- scores: spores.map((s) => s.score.toFixed(3))
3714
+ injected_text: text
3677
3715
  });
3678
3716
  return { body: { text } };
3679
3717
  };
@@ -3787,6 +3825,53 @@ async function handleEmbeddingReembedStale(manager) {
3787
3825
  return { body: result };
3788
3826
  }
3789
3827
 
3828
+ // src/daemon/database/types.ts
3829
+ var VACUUM_ERROR_CODE = "insufficient_disk_space";
3830
+ var VacuumPrecheckError = class extends Error {
3831
+ constructor(required_bytes, free_bytes) {
3832
+ super("VACUUM requires at least " + required_bytes + " bytes free; only " + free_bytes + " available");
3833
+ this.required_bytes = required_bytes;
3834
+ this.free_bytes = free_bytes;
3835
+ this.name = "VacuumPrecheckError";
3836
+ }
3837
+ };
3838
+
3839
+ // src/daemon/api/database.ts
3840
+ async function handleDatabaseDetails(manager) {
3841
+ const details = await manager.getDetails();
3842
+ return { body: details };
3843
+ }
3844
+ async function handleDatabaseOptimize(manager) {
3845
+ const result = await manager.optimize();
3846
+ return { body: result };
3847
+ }
3848
+ async function handleDatabaseVacuum(manager) {
3849
+ try {
3850
+ const result = await manager.vacuum();
3851
+ return { body: result };
3852
+ } catch (err) {
3853
+ if (err instanceof VacuumPrecheckError) {
3854
+ return {
3855
+ status: 409,
3856
+ body: {
3857
+ error: VACUUM_ERROR_CODE,
3858
+ required_bytes: err.required_bytes,
3859
+ free_bytes: err.free_bytes
3860
+ }
3861
+ };
3862
+ }
3863
+ throw err;
3864
+ }
3865
+ }
3866
+ async function handleDatabaseReindex(manager) {
3867
+ const result = await manager.reindex();
3868
+ return { body: result };
3869
+ }
3870
+ async function handleDatabaseIntegrityCheck(manager) {
3871
+ const result = await manager.integrityCheck();
3872
+ return { body: result };
3873
+ }
3874
+
3790
3875
  // src/daemon/embedding/manager.ts
3791
3876
  import { createHash as createHash3 } from "crypto";
3792
3877
  var ACTIVE_STATUS = "active";
@@ -4622,6 +4707,344 @@ var SqliteRecordSource = class {
4622
4707
  }
4623
4708
  };
4624
4709
 
4710
+ // src/daemon/database/manager.ts
4711
+ import fs14 from "fs";
4712
+
4713
+ // src/db/queries/database.ts
4714
+ import fs13 from "fs";
4715
+ function pragmaScalar(name) {
4716
+ const db = getDatabase();
4717
+ return db.pragma(name, { simple: true });
4718
+ }
4719
+ function safeFileSize(filePath) {
4720
+ try {
4721
+ return fs13.statSync(filePath).size;
4722
+ } catch (err) {
4723
+ if (err.code === "ENOENT") return 0;
4724
+ throw err;
4725
+ }
4726
+ }
4727
+ function getDatabaseFileStats(dbPath) {
4728
+ const size_bytes = safeFileSize(dbPath);
4729
+ const wal_size_bytes = safeFileSize(dbPath + "-wal");
4730
+ const page_size = Number(pragmaScalar("page_size"));
4731
+ const page_count = Number(pragmaScalar("page_count"));
4732
+ const freelist_count = Number(pragmaScalar("freelist_count"));
4733
+ const fragmentation_pct = page_count > 0 ? freelist_count / page_count * 100 : 0;
4734
+ return {
4735
+ path: dbPath,
4736
+ size_bytes,
4737
+ wal_size_bytes,
4738
+ page_size,
4739
+ page_count,
4740
+ freelist_count,
4741
+ fragmentation_pct
4742
+ };
4743
+ }
4744
+ function quoteIdent(name) {
4745
+ return '"' + name.replace(/"/g, '""') + '"';
4746
+ }
4747
+ function getTablesBreakdown() {
4748
+ const db = getDatabase();
4749
+ const tableRows = db.prepare(
4750
+ "SELECT name, sql FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
4751
+ ).all();
4752
+ const userTableRows = tableRows.filter((row) => !(row.sql ?? "").startsWith("CREATE TABLE '"));
4753
+ const indexCountRows = db.prepare(
4754
+ "SELECT tbl_name, COUNT(*) AS cnt FROM sqlite_master WHERE type='index' GROUP BY tbl_name"
4755
+ ).all();
4756
+ const indexCountByTable = new Map(indexCountRows.map((r) => [r.tbl_name, Number(r.cnt)]));
4757
+ const countsByTable = /* @__PURE__ */ new Map();
4758
+ if (userTableRows.length > 0) {
4759
+ const unionSql = userTableRows.map((_, i) => `SELECT ? AS t, COUNT(*) AS c FROM ${quoteIdent(userTableRows[i].name)}`).join(" UNION ALL ");
4760
+ const params = userTableRows.map((row) => row.name);
4761
+ try {
4762
+ const rows = db.prepare(unionSql).all(...params);
4763
+ for (const r of rows) {
4764
+ countsByTable.set(r.t, Number(r.c ?? 0));
4765
+ }
4766
+ } catch {
4767
+ for (const row of userTableRows) {
4768
+ try {
4769
+ const r = db.prepare(`SELECT COUNT(*) AS c FROM ${quoteIdent(row.name)}`).get();
4770
+ countsByTable.set(row.name, Number(r.c ?? 0));
4771
+ } catch {
4772
+ countsByTable.set(row.name, 0);
4773
+ }
4774
+ }
4775
+ }
4776
+ }
4777
+ return userTableRows.map((row) => ({
4778
+ name: row.name,
4779
+ rows: countsByTable.get(row.name) ?? 0,
4780
+ index_count: indexCountByTable.get(row.name) ?? 0,
4781
+ is_fts: (row.sql ?? "").toLowerCase().includes("fts5")
4782
+ }));
4783
+ }
4784
+ function getIndexesList() {
4785
+ const db = getDatabase();
4786
+ const rows = db.prepare(
4787
+ "SELECT name, tbl_name, sql FROM sqlite_master WHERE type='index' ORDER BY tbl_name, name"
4788
+ ).all();
4789
+ return rows.map((r) => {
4790
+ const type = r.name.startsWith("sqlite_autoindex_") ? "auto" : "btree";
4791
+ return {
4792
+ name: r.name,
4793
+ table: r.tbl_name,
4794
+ type,
4795
+ sql: r.sql
4796
+ };
4797
+ });
4798
+ }
4799
+ function getSchemaInfo() {
4800
+ const journal_mode = String(pragmaScalar("journal_mode"));
4801
+ const foreign_keys_raw = pragmaScalar("foreign_keys");
4802
+ const foreign_keys = Number(foreign_keys_raw) === 1;
4803
+ return {
4804
+ version: SCHEMA_VERSION,
4805
+ journal_mode,
4806
+ foreign_keys
4807
+ };
4808
+ }
4809
+ function getLastDatabaseLogTimestamp(kind) {
4810
+ const db = getDatabase();
4811
+ const row = db.prepare(
4812
+ "SELECT timestamp FROM log_entries WHERE kind = ? ORDER BY id DESC LIMIT 1"
4813
+ ).get(kind);
4814
+ if (!row) return null;
4815
+ const t = new Date(row.timestamp).getTime();
4816
+ return Number.isFinite(t) ? t : null;
4817
+ }
4818
+ function getLastDatabaseLogTimestamps(kinds) {
4819
+ const result = /* @__PURE__ */ new Map();
4820
+ for (const k of kinds) result.set(k, null);
4821
+ if (kinds.length === 0) return result;
4822
+ const db = getDatabase();
4823
+ const placeholders = kinds.map(() => "?").join(",");
4824
+ const rows = db.prepare(
4825
+ `SELECT kind, MAX(timestamp) AS latest FROM log_entries WHERE kind IN (${placeholders}) GROUP BY kind`
4826
+ ).all(...kinds);
4827
+ for (const row of rows) {
4828
+ if (!row.latest) continue;
4829
+ const t = new Date(row.latest).getTime();
4830
+ result.set(row.kind, Number.isFinite(t) ? t : null);
4831
+ }
4832
+ return result;
4833
+ }
4834
+ function runVacuum() {
4835
+ const db = getDatabase();
4836
+ db.exec("VACUUM");
4837
+ }
4838
+ function runAnalyze() {
4839
+ const db = getDatabase();
4840
+ db.exec("ANALYZE");
4841
+ }
4842
+ function runReindex() {
4843
+ const db = getDatabase();
4844
+ db.exec("REINDEX");
4845
+ }
4846
+ function runIntegrityCheck() {
4847
+ const db = getDatabase();
4848
+ const rows = db.prepare("PRAGMA integrity_check").all();
4849
+ const messages = rows.map((r) => r.integrity_check);
4850
+ const ok = messages.length === 1 && messages[0] === "ok";
4851
+ return {
4852
+ status: ok ? "ok" : "issues",
4853
+ issues: ok ? [] : messages
4854
+ };
4855
+ }
4856
+ function runForeignKeyCheck() {
4857
+ const db = getDatabase();
4858
+ const rows = db.prepare("PRAGMA foreign_key_check").all();
4859
+ return rows;
4860
+ }
4861
+ function runWalCheckpointTruncate() {
4862
+ const db = getDatabase();
4863
+ const rows = db.pragma("wal_checkpoint(TRUNCATE)");
4864
+ const row = rows[0] ?? { busy: 0, log: 0, checkpointed: 0 };
4865
+ return {
4866
+ busy: Number(row.busy),
4867
+ log: Number(row.log),
4868
+ checkpointed: Number(row.checkpointed)
4869
+ };
4870
+ }
4871
+ function runPragmaOptimize() {
4872
+ const db = getDatabase();
4873
+ db.pragma("optimize");
4874
+ }
4875
+ var FTS_TABLE_PATTERN = /^[a-z_][a-z0-9_]*_fts$/;
4876
+ function runFtsOptimize(ftsTableName) {
4877
+ if (!FTS_TABLE_PATTERN.test(ftsTableName)) {
4878
+ throw new Error("Invalid FTS5 table name: " + ftsTableName);
4879
+ }
4880
+ const db = getDatabase();
4881
+ const row = db.prepare(
4882
+ "SELECT sql FROM sqlite_master WHERE type='table' AND name=?"
4883
+ ).get(ftsTableName);
4884
+ if (!row || !(row.sql ?? "").toLowerCase().includes("fts5")) {
4885
+ throw new Error("Not an FTS5 table: " + ftsTableName);
4886
+ }
4887
+ const quoted = '"' + ftsTableName + '"';
4888
+ const optimizeSql = "INSERT INTO " + quoted + "(" + quoted + ") VALUES ('optimize')";
4889
+ db.prepare(optimizeSql).run();
4890
+ }
4891
+ function listFtsTableNames() {
4892
+ const db = getDatabase();
4893
+ const rows = db.prepare(
4894
+ "SELECT name FROM sqlite_master WHERE type='table' AND sql LIKE '%fts5%' ORDER BY name"
4895
+ ).all();
4896
+ return rows.map((r) => r.name).filter((name) => FTS_TABLE_PATTERN.test(name));
4897
+ }
4898
+
4899
+ // src/daemon/database/manager.ts
4900
+ var VACUUM_FREE_SPACE_MULTIPLIER = 2;
4901
+ var DatabaseMaintenanceManager = class {
4902
+ constructor(dbPath, vaultDir, logger) {
4903
+ this.dbPath = dbPath;
4904
+ this.vaultDir = vaultDir;
4905
+ this.logger = logger;
4906
+ }
4907
+ async getDetails() {
4908
+ const file = getDatabaseFileStats(this.dbPath);
4909
+ const schema = getSchemaInfo();
4910
+ const tables = getTablesBreakdown();
4911
+ const indexes = getIndexesList();
4912
+ const lastRuns = getLastDatabaseLogTimestamps([
4913
+ LOG_KINDS.DATABASE_OPTIMIZE,
4914
+ LOG_KINDS.DATABASE_VACUUM,
4915
+ LOG_KINDS.DATABASE_INTEGRITY_CHECK,
4916
+ LOG_KINDS.DATABASE_INTEGRITY_ISSUES
4917
+ ]);
4918
+ const optimizeMs = lastRuns.get(LOG_KINDS.DATABASE_OPTIMIZE) ?? null;
4919
+ const vacuumMs = lastRuns.get(LOG_KINDS.DATABASE_VACUUM) ?? null;
4920
+ const integrityOkMs = lastRuns.get(LOG_KINDS.DATABASE_INTEGRITY_CHECK) ?? null;
4921
+ const integrityIssuesMs = lastRuns.get(LOG_KINDS.DATABASE_INTEGRITY_ISSUES) ?? null;
4922
+ let last_integrity_check = null;
4923
+ if (integrityOkMs !== null || integrityIssuesMs !== null) {
4924
+ const okMs = integrityOkMs ?? 0;
4925
+ const issuesMs = integrityIssuesMs ?? 0;
4926
+ if (okMs >= issuesMs) {
4927
+ last_integrity_check = { at: new Date(okMs).toISOString(), status: "ok" };
4928
+ } else {
4929
+ last_integrity_check = { at: new Date(issuesMs).toISOString(), status: "issues" };
4930
+ }
4931
+ }
4932
+ return {
4933
+ file,
4934
+ schema,
4935
+ tables,
4936
+ indexes,
4937
+ last_optimize_at: optimizeMs ? new Date(optimizeMs).toISOString() : null,
4938
+ last_vacuum_at: vacuumMs ? new Date(vacuumMs).toISOString() : null,
4939
+ last_integrity_check
4940
+ };
4941
+ }
4942
+ async getLastOptimizeAt() {
4943
+ return getLastDatabaseLogTimestamp(LOG_KINDS.DATABASE_OPTIMIZE);
4944
+ }
4945
+ async optimize() {
4946
+ const startedAt = Date.now();
4947
+ const completed = [];
4948
+ const failed = [];
4949
+ const steps = [
4950
+ { name: "analyze", fn: runAnalyze },
4951
+ { name: "pragma_optimize", fn: runPragmaOptimize },
4952
+ ...listFtsTableNames().map((tbl) => ({
4953
+ name: "fts_optimize:" + tbl,
4954
+ fn: () => runFtsOptimize(tbl)
4955
+ })),
4956
+ // wal_checkpoint_truncate returns WalCheckpointResult; if busy !== 0 another
4957
+ // reader blocked the checkpoint — log a warning but don't fail the step.
4958
+ {
4959
+ name: "wal_checkpoint_truncate",
4960
+ fn: () => {
4961
+ const result = runWalCheckpointTruncate();
4962
+ if (result.busy !== 0) {
4963
+ this.logger.warn(LOG_KINDS.DATABASE_ERROR, "wal_checkpoint blocked by reader", {
4964
+ busy: result.busy,
4965
+ log: result.log,
4966
+ checkpointed: result.checkpointed
4967
+ });
4968
+ }
4969
+ }
4970
+ }
4971
+ ];
4972
+ for (const step of steps) {
4973
+ const stepStart = Date.now();
4974
+ try {
4975
+ step.fn();
4976
+ completed.push({ name: step.name, duration_ms: Date.now() - stepStart, ok: true });
4977
+ } catch (err) {
4978
+ const error = err.message;
4979
+ failed.push({ name: step.name, duration_ms: Date.now() - stepStart, ok: false, error });
4980
+ this.logger.warn(LOG_KINDS.DATABASE_ERROR, "optimize step failed: " + step.name, { error });
4981
+ }
4982
+ }
4983
+ const duration_ms = Date.now() - startedAt;
4984
+ this.logger.info(LOG_KINDS.DATABASE_OPTIMIZE, "Database optimize complete", {
4985
+ completed: completed.length,
4986
+ failed: failed.length,
4987
+ duration_ms
4988
+ });
4989
+ return { actions_completed: completed, actions_failed: failed, duration_ms };
4990
+ }
4991
+ async vacuum() {
4992
+ const size_before = this.fileSize();
4993
+ const stats = await fs14.promises.statfs(this.vaultDir);
4994
+ const free_bytes = Number(stats.bavail) * Number(stats.bsize);
4995
+ const required_bytes = size_before * VACUUM_FREE_SPACE_MULTIPLIER;
4996
+ if (free_bytes < required_bytes) {
4997
+ throw new VacuumPrecheckError(required_bytes, free_bytes);
4998
+ }
4999
+ const startedAt = Date.now();
5000
+ runVacuum();
5001
+ const duration_ms = Date.now() - startedAt;
5002
+ const size_after = this.fileSize();
5003
+ const freed_bytes = size_before - size_after;
5004
+ this.logger.info(LOG_KINDS.DATABASE_VACUUM, "Database vacuum complete", {
5005
+ size_before,
5006
+ size_after,
5007
+ freed_bytes,
5008
+ duration_ms
5009
+ });
5010
+ return { size_before, size_after, freed_bytes, duration_ms };
5011
+ }
5012
+ async reindex() {
5013
+ const startedAt = Date.now();
5014
+ runReindex();
5015
+ const duration_ms = Date.now() - startedAt;
5016
+ this.logger.info(LOG_KINDS.DATABASE_REINDEX, "Database reindex complete", { duration_ms });
5017
+ return { duration_ms };
5018
+ }
5019
+ async integrityCheck() {
5020
+ const startedAt = Date.now();
5021
+ const integrity = runIntegrityCheck();
5022
+ const fkViolations = runForeignKeyCheck();
5023
+ const duration_ms = Date.now() - startedAt;
5024
+ const status = integrity.status === "ok" && fkViolations.length === 0 ? "ok" : "issues";
5025
+ const logKind = status === "ok" ? LOG_KINDS.DATABASE_INTEGRITY_CHECK : LOG_KINDS.DATABASE_INTEGRITY_ISSUES;
5026
+ this.logger.info(logKind, "Database integrity check complete", {
5027
+ status,
5028
+ issue_count: integrity.issues.length,
5029
+ fk_violations: fkViolations.length,
5030
+ duration_ms
5031
+ });
5032
+ return {
5033
+ status,
5034
+ issues: integrity.issues,
5035
+ fk_violations: fkViolations.length,
5036
+ duration_ms
5037
+ };
5038
+ }
5039
+ fileSize() {
5040
+ try {
5041
+ return fs14.statSync(this.dbPath).size;
5042
+ } catch {
5043
+ return 0;
5044
+ }
5045
+ }
5046
+ };
5047
+
4625
5048
  // src/notifications/domains.ts
4626
5049
  function registerBuiltinDomains() {
4627
5050
  register({
@@ -5010,129 +5433,20 @@ function buildScheduledJobs(tasks, configOverrides, context, initialLastRuns) {
5010
5433
  if (!check) return;
5011
5434
  if (!check()) return;
5012
5435
  }
5013
- try {
5014
- context.setTaskRunning(task.name, true);
5015
- await context.runTask(task.name);
5016
- } finally {
5017
- lastRun = Date.now();
5018
- context.setTaskRunning(task.name, false);
5019
- }
5436
+ const ctx = context;
5437
+ ctx.setTaskRunning(task.name, true);
5438
+ lastRun = Date.now();
5439
+ void ctx.runTask(task.name).catch((err) => {
5440
+ ctx.onTaskError?.(task.name, err);
5441
+ }).finally(() => {
5442
+ ctx.setTaskRunning(task.name, false);
5443
+ });
5020
5444
  }
5021
5445
  });
5022
5446
  }
5023
5447
  return jobs;
5024
5448
  }
5025
5449
 
5026
- // src/agent/instruction-builders.ts
5027
- var SKILL_GENERATE_TASK = "skill-generate";
5028
- var SKILL_EVOLVE_TASK = "skill-evolve";
5029
- function buildSkillGenerateInstruction() {
5030
- const candidates = listCandidates({ status: "approved", limit: 1 });
5031
- if (candidates.length === 0) return void 0;
5032
- const c = candidates[0];
5033
- const parts = [
5034
- `candidate_id: ${c.id}`,
5035
- `topic: ${c.topic}`,
5036
- `confidence: ${c.confidence}`,
5037
- `rationale: ${c.rationale}`,
5038
- "",
5039
- "## Source Material"
5040
- ];
5041
- let sourceIds = [];
5042
- try {
5043
- sourceIds = JSON.parse(c.source_ids || "[]");
5044
- } catch {
5045
- }
5046
- for (const src of sourceIds) {
5047
- if (src.type === "spore") {
5048
- const spore = getSpore(src.id);
5049
- if (spore) {
5050
- parts.push(`
5051
- ### Spore: ${src.id} (${spore.observation_type}, importance ${spore.importance})`);
5052
- parts.push(spore.content);
5053
- if (spore.context) parts.push(`Context: ${spore.context}`);
5054
- if (spore.tags) parts.push(`Tags: ${spore.tags}`);
5055
- }
5056
- } else if (src.type === "session") {
5057
- const session = getSession(src.id);
5058
- if (session) {
5059
- parts.push(`
5060
- ### Session: ${src.id}`);
5061
- if (session.title) parts.push(`Title: ${session.title}`);
5062
- if (session.summary) parts.push(session.summary);
5063
- }
5064
- }
5065
- }
5066
- return parts.join("\n");
5067
- }
5068
- var SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS = 24;
5069
- var SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN = 5;
5070
- function buildSkillEvolveInstruction(params) {
5071
- const assessIntervalHours = Number(params?.assess_interval_hours ?? SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS);
5072
- const maxSkillsPerRun = Number(params?.max_skills_per_run ?? SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN);
5073
- const now = epochSeconds();
5074
- const intervalSeconds = assessIntervalHours * 3600;
5075
- const allSkills = listSkillRecords({ status: "active", limit: 100 });
5076
- const needsAssessment = [];
5077
- for (const skill of allSkills) {
5078
- let props = {};
5079
- try {
5080
- props = JSON.parse(skill.properties || "{}");
5081
- } catch {
5082
- props = {};
5083
- }
5084
- const lastAssessedAt = typeof props.last_assessed_at === "number" ? props.last_assessed_at : 0;
5085
- const knowledgeWatermark = typeof props.knowledge_watermark === "number" ? props.knowledge_watermark : 0;
5086
- if (lastAssessedAt > 0 && now - lastAssessedAt < intervalSeconds) continue;
5087
- const newSporeIds = listSporeIdsSince(knowledgeWatermark, 10);
5088
- if (newSporeIds.length === 0) continue;
5089
- const lineage = listLineageForSkill(skill.id, 1);
5090
- if (lineage.length === 0) continue;
5091
- needsAssessment.push({
5092
- id: skill.id,
5093
- name: skill.name,
5094
- generation: skill.generation,
5095
- description: skill.description,
5096
- contentSnapshot: lineage[0].content_snapshot,
5097
- newSporeIds
5098
- });
5099
- if (needsAssessment.length >= maxSkillsPerRun) {
5100
- break;
5101
- }
5102
- }
5103
- if (needsAssessment.length === 0) {
5104
- return "No skills need assessment. All active skills are current or were recently assessed. Report skip via vault_report and finish.";
5105
- }
5106
- const parts = [
5107
- `${needsAssessment.length} skill(s) need assessment.`,
5108
- `assess_interval_hours: ${assessIntervalHours}`,
5109
- `max_skills_per_run: ${maxSkillsPerRun}`
5110
- ];
5111
- for (const skill of needsAssessment) {
5112
- parts.push("");
5113
- parts.push("---");
5114
- parts.push(`## Skill: ${skill.name} (gen ${skill.generation})`);
5115
- parts.push(`id: ${skill.id}`);
5116
- parts.push(`description: ${skill.description}`);
5117
- parts.push(`new_spore_ids: ${JSON.stringify(skill.newSporeIds)}`);
5118
- parts.push("");
5119
- parts.push("### Current Content");
5120
- parts.push("");
5121
- parts.push(skill.contentSnapshot);
5122
- }
5123
- return parts.join("\n");
5124
- }
5125
- function buildTaskInstruction(taskName, taskParams) {
5126
- switch (taskName) {
5127
- case SKILL_GENERATE_TASK:
5128
- return buildSkillGenerateInstruction();
5129
- case SKILL_EVOLVE_TASK:
5130
- return buildSkillEvolveInstruction(taskParams);
5131
- default:
5132
- return void 0;
5133
- }
5134
- }
5135
-
5136
5450
  // src/daemon/task-scheduling.ts
5137
5451
  async function registerScheduledTasks(powerManager, deps) {
5138
5452
  const { definitionsDir, vaultDir, embeddingManager, logger, config } = deps;
@@ -5145,7 +5459,7 @@ async function registerScheduledTasks(powerManager, deps) {
5145
5459
  logger.info(LOG_KINDS.AGENT_RUN, "Scheduled agent tasks disabled globally (agent.scheduled_tasks_enabled: false)");
5146
5460
  return;
5147
5461
  }
5148
- const { loadAllTasks: loadAllTasks2 } = await import("./registry-DHWVHXWY.js");
5462
+ const { loadAllTasks: loadAllTasks2 } = await import("./registry-5R3DLJQH.js");
5149
5463
  const allTasks = Array.from(loadAllTasks2(definitionsDir, vaultDir).values());
5150
5464
  const initialLastRuns = {};
5151
5465
  try {
@@ -5167,10 +5481,23 @@ async function registerScheduledTasks(powerManager, deps) {
5167
5481
  else runningTasks.delete(name);
5168
5482
  },
5169
5483
  runTask: async (taskName) => {
5170
- const { runAgent } = await import("./executor-4OXDK4ZA.js");
5484
+ const { runAgent } = await import("./executor-HP3Y64PD.js");
5171
5485
  const taskConfig = config.agent.tasks?.[taskName];
5172
- const instruction = buildTaskInstruction(taskName, taskConfig?.params);
5173
- const result = await runAgent(vaultDir, { task: taskName, instruction, embeddingManager });
5486
+ const built = buildTaskInstruction(taskName, taskConfig?.params);
5487
+ if (isInstructionRequiredTask(taskName) && !built) {
5488
+ logger.info(
5489
+ LOG_KINDS.AGENT_RUN,
5490
+ `Scheduled task ${taskName} skipped \u2014 no work to do`,
5491
+ { task: taskName, reason: "no-work" }
5492
+ );
5493
+ return;
5494
+ }
5495
+ const result = await runAgent(vaultDir, {
5496
+ task: taskName,
5497
+ instruction: built?.instruction,
5498
+ runContext: built?.context,
5499
+ embeddingManager
5500
+ });
5174
5501
  logger.info(LOG_KINDS.AGENT_RUN, `Scheduled task ${taskName} completed`, {
5175
5502
  status: result.status,
5176
5503
  runId: result.runId
@@ -5230,6 +5557,11 @@ async function registerScheduledTasks(powerManager, deps) {
5230
5557
  "has-approved-candidates": () => {
5231
5558
  return countCandidates({ status: "approved" }) > 0;
5232
5559
  }
5560
+ },
5561
+ onTaskError: (taskName, err) => {
5562
+ logger.error(LOG_KINDS.AGENT_ERROR, `Detached task "${taskName}" threw`, {
5563
+ error: err instanceof Error ? err.message : String(err)
5564
+ });
5233
5565
  }
5234
5566
  };
5235
5567
  const scheduledJobs = buildScheduledJobs(
@@ -5318,7 +5650,7 @@ function createMcpProxyHandlers(deps) {
5318
5650
  name: USER_AGENT_NAME,
5319
5651
  created_at: now
5320
5652
  });
5321
- const { insertResolutionEvent } = await import("./resolution-events-DBCRVZGU.js");
5653
+ const { insertResolutionEvent } = await import("./resolution-events-CHOKR35X.js");
5322
5654
  const resolutionId = `res-${randomBytes(RESOLUTION_ID_RANDOM_BYTES).toString("hex")}`;
5323
5655
  insertResolutionEvent({
5324
5656
  id: resolutionId,
@@ -5411,17 +5743,37 @@ function createAgentRunHandlers(deps) {
5411
5743
  async function handleRun(req) {
5412
5744
  const { task, instruction: rawInstruction, agentId } = AgentRunBody.parse(req.body);
5413
5745
  let instruction = rawInstruction;
5746
+ let runContext;
5414
5747
  if (task && !instruction) {
5748
+ let built;
5415
5749
  try {
5416
5750
  const mycoConfig = loadConfig(vaultDir);
5417
5751
  const taskParams = mycoConfig.agent.tasks?.[task]?.params;
5418
- instruction = buildTaskInstruction(task, taskParams);
5752
+ built = buildTaskInstruction(task, taskParams);
5419
5753
  } catch {
5420
- instruction = buildTaskInstruction(task);
5754
+ built = buildTaskInstruction(task);
5755
+ }
5756
+ instruction = built?.instruction;
5757
+ runContext = built?.context;
5758
+ if (task && isInstructionRequiredTask(task) && !built) {
5759
+ return {
5760
+ body: {
5761
+ ok: true,
5762
+ message: `Task ${task} skipped \u2014 no work to do`,
5763
+ status: "skipped",
5764
+ reason: "no-work"
5765
+ }
5766
+ };
5421
5767
  }
5422
5768
  }
5423
- const { runAgent } = await import("./executor-4OXDK4ZA.js");
5424
- const resultPromise = runAgent(vaultDir, { task, instruction, agentId, embeddingManager });
5769
+ const { runAgent } = await import("./executor-HP3Y64PD.js");
5770
+ const resultPromise = runAgent(vaultDir, {
5771
+ task,
5772
+ instruction,
5773
+ agentId,
5774
+ embeddingManager,
5775
+ runContext
5776
+ });
5425
5777
  const effectiveAgentId = agentId ?? "myco-agent";
5426
5778
  const runId = getLatestRunId(effectiveAgentId, task);
5427
5779
  resultPromise.then((result) => {
@@ -5483,7 +5835,7 @@ function createAgentRunHandlers(deps) {
5483
5835
  }
5484
5836
 
5485
5837
  // src/daemon/api/attachments.ts
5486
- import fs13 from "fs";
5838
+ import fs15 from "fs";
5487
5839
  import path15 from "path";
5488
5840
  var ATTACHMENT_MEDIA_TYPES = {
5489
5841
  png: "image/png",
@@ -5507,7 +5859,7 @@ function createAttachmentHandler(deps) {
5507
5859
  const filePath = path15.join(vaultDir, "attachments", filename);
5508
5860
  let diskData;
5509
5861
  try {
5510
- diskData = fs13.readFileSync(filePath);
5862
+ diskData = fs15.readFileSync(filePath);
5511
5863
  } catch {
5512
5864
  return { status: 404, body: { error: "not_found" } };
5513
5865
  }
@@ -5519,19 +5871,19 @@ function createAttachmentHandler(deps) {
5519
5871
  }
5520
5872
 
5521
5873
  // src/daemon/log-reconcile.ts
5522
- import fs14 from "fs";
5874
+ import fs16 from "fs";
5523
5875
  import path16 from "path";
5524
5876
  function reconcileLogBuffer(logDir, sinceTimestamp) {
5525
5877
  let replayed = 0;
5526
5878
  const files = [];
5527
5879
  for (let i = 3; i >= 1; i--) {
5528
5880
  const rotated = path16.join(logDir, `daemon.${i}.log`);
5529
- if (fs14.existsSync(rotated)) files.push(rotated);
5881
+ if (fs16.existsSync(rotated)) files.push(rotated);
5530
5882
  }
5531
5883
  const current = path16.join(logDir, "daemon.log");
5532
- if (fs14.existsSync(current)) files.push(current);
5884
+ if (fs16.existsSync(current)) files.push(current);
5533
5885
  for (const file of files) {
5534
- const content = fs14.readFileSync(file, "utf-8");
5886
+ const content = fs16.readFileSync(file, "utf-8");
5535
5887
  for (const line of content.split("\n")) {
5536
5888
  if (!line.trim()) continue;
5537
5889
  try {
@@ -5722,8 +6074,9 @@ async function runSessionMaintenance(deps) {
5722
6074
  }
5723
6075
 
5724
6076
  // src/daemon/power-jobs.ts
6077
+ var STAGING_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
5725
6078
  function registerPowerJobs(powerManager, deps) {
5726
- const { embeddingManager, registry, logger, config, db, backupDir, machineId, vaultDir } = deps;
6079
+ const { embeddingManager, registry, logger, config, db, backupDir, machineId, vaultDir, databaseManager } = deps;
5727
6080
  let reconcileRunning = false;
5728
6081
  powerManager.register({
5729
6082
  name: "embedding-reconcile",
@@ -5773,10 +6126,42 @@ function registerPowerJobs(powerManager, deps) {
5773
6126
  }
5774
6127
  }
5775
6128
  });
6129
+ powerManager.register({
6130
+ name: "database-optimize",
6131
+ runIn: ["idle", "sleep"],
6132
+ fn: async () => {
6133
+ if (!config.maintenance?.auto_optimize) return;
6134
+ const intervalMs = (config.maintenance.auto_optimize_interval_hours ?? 24) * MS_PER_HOUR;
6135
+ const lastRun = await databaseManager.getLastOptimizeAt();
6136
+ if (lastRun !== null && Date.now() - lastRun < intervalMs) return;
6137
+ try {
6138
+ await databaseManager.optimize();
6139
+ } catch (err) {
6140
+ logger.error(LOG_KINDS.DATABASE_ERROR, "Auto-optimize failed", {
6141
+ error: err.message
6142
+ });
6143
+ }
6144
+ }
6145
+ });
6146
+ powerManager.register({
6147
+ name: "staging-gc",
6148
+ runIn: ["idle", "sleep"],
6149
+ fn: async () => {
6150
+ const stale = listStaleStagingDirs(vaultDir, STAGING_MAX_AGE_MS);
6151
+ if (stale.length === 0) return;
6152
+ for (const candidateId of stale) {
6153
+ cleanupStagedSkill(vaultDir, candidateId);
6154
+ }
6155
+ logger.info(LOG_KINDS.MAINTENANCE_STAGING_GC, "Staging GC swept stale skill drafts", {
6156
+ count: stale.length,
6157
+ candidate_ids: stale
6158
+ });
6159
+ }
6160
+ });
5776
6161
  }
5777
6162
 
5778
6163
  // src/daemon/reconciliation.ts
5779
- import fs15 from "fs";
6164
+ import fs17 from "fs";
5780
6165
  import path17 from "path";
5781
6166
 
5782
6167
  // src/daemon/event-handlers.ts
@@ -5942,7 +6327,7 @@ function createReconciler({ bufferDir, logger }) {
5942
6327
  const bufferPath = path17.join(bufferDir, `${sessionId}.jsonl`);
5943
6328
  let content;
5944
6329
  try {
5945
- content = fs15.readFileSync(bufferPath, "utf-8").trim();
6330
+ content = fs17.readFileSync(bufferPath, "utf-8").trim();
5946
6331
  } catch {
5947
6332
  return;
5948
6333
  }
@@ -6011,7 +6396,7 @@ function createReconciler({ bufferDir, logger }) {
6011
6396
  }
6012
6397
 
6013
6398
  // src/daemon/stop-processing.ts
6014
- import fs16 from "fs";
6399
+ import fs18 from "fs";
6015
6400
 
6016
6401
  // src/daemon/skill-usage.ts
6017
6402
  import crypto from "crypto";
@@ -6089,7 +6474,7 @@ function createStopProcessor(deps) {
6089
6474
  if (config.agent.summary_batch_interval <= 0) return;
6090
6475
  if (config.agent.event_tasks_enabled === false) return;
6091
6476
  try {
6092
- const { runAgent } = await import("./executor-4OXDK4ZA.js");
6477
+ const { runAgent } = await import("./executor-HP3Y64PD.js");
6093
6478
  runAgent(vaultDir, {
6094
6479
  task: "title-summary",
6095
6480
  instruction: `Process session ${sessionId} only`,
@@ -6179,7 +6564,7 @@ function createStopProcessor(deps) {
6179
6564
  let transcriptText = null;
6180
6565
  if (hookTranscriptPath) {
6181
6566
  try {
6182
- transcriptText = fs16.readFileSync(hookTranscriptPath, "utf-8");
6567
+ transcriptText = fs18.readFileSync(hookTranscriptPath, "utf-8");
6183
6568
  } catch {
6184
6569
  }
6185
6570
  }
@@ -6234,7 +6619,7 @@ function createStopProcessor(deps) {
6234
6619
  const filename = `${sessionShort}-t${resolvedPromptNumber}-${j + 1}.${ext}`;
6235
6620
  const imageBuffer = Buffer.from(img.data, "base64");
6236
6621
  try {
6237
- insertAttachment({
6622
+ const inserted = insertAttachment({
6238
6623
  id: `${sessionShort}-b${resolvedPromptNumber}-${j + 1}`,
6239
6624
  session_id: sessionId,
6240
6625
  prompt_batch_id: resolvedBatchId ?? void 0,
@@ -6243,7 +6628,9 @@ function createStopProcessor(deps) {
6243
6628
  data: imageBuffer,
6244
6629
  created_at: epochSeconds()
6245
6630
  });
6246
- logger.debug(LOG_KINDS.CAPTURE_ATTACHMENT, "Image stored in DB", { filename, batch: resolvedPromptNumber });
6631
+ if (inserted) {
6632
+ logger.debug(LOG_KINDS.CAPTURE_ATTACHMENT, "Image stored in DB", { filename, batch: resolvedPromptNumber });
6633
+ }
6247
6634
  } catch (err) {
6248
6635
  logger.warn(LOG_KINDS.CAPTURE_ATTACHMENT, "Failed to record attachment", { error: String(err) });
6249
6636
  }
@@ -6293,7 +6680,7 @@ function createStopProcessor(deps) {
6293
6680
  }
6294
6681
 
6295
6682
  // src/daemon/event-dispatch.ts
6296
- import fs17 from "fs";
6683
+ import fs19 from "fs";
6297
6684
  import path19 from "path";
6298
6685
 
6299
6686
  // src/daemon/plan-capture.ts
@@ -6430,7 +6817,7 @@ function createEventDispatcher(deps) {
6430
6817
  );
6431
6818
  if (planFilePath) {
6432
6819
  const captureSessionId = event.session_id;
6433
- fs17.promises.readFile(planFilePath, "utf-8").then((planContent) => {
6820
+ fs19.promises.readFile(planFilePath, "utf-8").then((planContent) => {
6434
6821
  const latestBatch = getLatestBatch(captureSessionId);
6435
6822
  capturePlan({
6436
6823
  sourcePath: path19.relative(projectRoot, planFilePath),
@@ -6575,14 +6962,14 @@ function createEventDispatcher(deps) {
6575
6962
  }
6576
6963
 
6577
6964
  // src/daemon/main.ts
6578
- import fs18 from "fs";
6965
+ import fs20 from "fs";
6579
6966
  import os8 from "os";
6580
6967
  import path20 from "path";
6581
6968
  function killStaleDaemon(vaultDir, logger) {
6582
6969
  const daemonJsonPath = path20.join(vaultDir, "daemon.json");
6583
6970
  try {
6584
- if (!fs18.existsSync(daemonJsonPath)) return;
6585
- const info = JSON.parse(fs18.readFileSync(daemonJsonPath, "utf-8"));
6971
+ if (!fs20.existsSync(daemonJsonPath)) return;
6972
+ const info = JSON.parse(fs20.readFileSync(daemonJsonPath, "utf-8"));
6586
6973
  if (!info.pid) return;
6587
6974
  if (info.pid === process.pid) return;
6588
6975
  try {
@@ -6591,7 +6978,7 @@ function killStaleDaemon(vaultDir, logger) {
6591
6978
  logger.info(LOG_KINDS.DAEMON_START, "Killed stale daemon", { pid: info.pid });
6592
6979
  } catch {
6593
6980
  }
6594
- fs18.unlinkSync(daemonJsonPath);
6981
+ fs20.unlinkSync(daemonJsonPath);
6595
6982
  } catch {
6596
6983
  }
6597
6984
  }
@@ -6658,9 +7045,10 @@ async function main() {
6658
7045
  const recordSource = new SqliteRecordSource();
6659
7046
  const embeddingManager = new EmbeddingManager(vectorStore, embeddingProvider, recordSource, logger);
6660
7047
  logger.info(LOG_KINDS.EMBEDDING_EMBED, "EmbeddingManager initialized", { vectors_db: vectorsDbPath });
7048
+ const databaseManager = new DatabaseMaintenanceManager(vaultDbPath(vaultDir), vaultDir, logger);
6661
7049
  let definitionsDir;
6662
7050
  try {
6663
- const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-WC4U5NM5.js");
7051
+ const { registerBuiltInAgentsAndTasks, resolveDefinitionsDir: resolveDefinitionsDir2 } = await import("./loader-YQDG5GI5.js");
6664
7052
  definitionsDir = resolveDefinitionsDir2();
6665
7053
  await registerBuiltInAgentsAndTasks(definitionsDir, vaultDir);
6666
7054
  logger.info(LOG_KINDS.AGENT_TASK, "Built-in agents and tasks registered");
@@ -6689,7 +7077,7 @@ async function main() {
6689
7077
  const root = findPackageRoot(path20.dirname(new URL(import.meta.url).pathname));
6690
7078
  if (root) {
6691
7079
  const candidate = path20.join(root, "dist", "ui");
6692
- if (fs18.existsSync(candidate)) uiDir = candidate;
7080
+ if (fs20.existsSync(candidate)) uiDir = candidate;
6693
7081
  }
6694
7082
  }
6695
7083
  if (uiDir) {
@@ -6800,6 +7188,7 @@ async function main() {
6800
7188
  server,
6801
7189
  configHash: configHashRef
6802
7190
  }));
7191
+ server.registerRoute("GET", "/api/logs", handleLogStream);
6803
7192
  server.registerRoute("GET", "/api/logs/search", handleLogSearch);
6804
7193
  server.registerRoute("GET", "/api/logs/stream", handleLogStream);
6805
7194
  server.registerRoute("GET", "/api/logs/:id", handleLogDetail);
@@ -6900,6 +7289,11 @@ async function main() {
6900
7289
  server.registerRoute("POST", "/api/embedding/reconcile", async () => handleEmbeddingReconcile(embeddingManager));
6901
7290
  server.registerRoute("POST", "/api/embedding/clean-orphans", async () => handleEmbeddingCleanOrphans(embeddingManager));
6902
7291
  server.registerRoute("POST", "/api/embedding/reembed-stale", async () => handleEmbeddingReembedStale(embeddingManager));
7292
+ server.registerRoute("GET", "/api/database/details", async () => handleDatabaseDetails(databaseManager));
7293
+ server.registerRoute("POST", "/api/database/optimize", async () => handleDatabaseOptimize(databaseManager));
7294
+ server.registerRoute("POST", "/api/database/vacuum", async () => handleDatabaseVacuum(databaseManager));
7295
+ server.registerRoute("POST", "/api/database/reindex", async () => handleDatabaseReindex(databaseManager));
7296
+ server.registerRoute("POST", "/api/database/integrity-check", async () => handleDatabaseIntegrityCheck(databaseManager));
6903
7297
  server.registerRoute("GET", "/api/notifications", async (req) => handleListNotifications(vaultDir, req.query));
6904
7298
  server.registerRoute("POST", "/api/notifications", async (req) => handleCreateNotification(vaultDir, req.body));
6905
7299
  server.registerRoute("PATCH", "/api/notifications/:id", async (req) => handleUpdateNotification(vaultDir, req.params.id, req.body));
@@ -6925,7 +7319,7 @@ async function main() {
6925
7319
  logger.warn(LOG_KINDS.DAEMON_CONFIG, "Failed to persist auto-derived port", { error: err.message });
6926
7320
  }
6927
7321
  }
6928
- registerPowerJobs(powerManager, { embeddingManager, registry, logger, config, db, backupDir, machineId, vaultDir });
7322
+ registerPowerJobs(powerManager, { embeddingManager, registry, logger, config, db, backupDir, machineId, vaultDir, databaseManager });
6929
7323
  teamSync.registerFlushJob(powerManager);
6930
7324
  await registerScheduledTasks(powerManager, { definitionsDir, vaultDir, embeddingManager, logger, config });
6931
7325
  powerManager.start();
@@ -6959,4 +7353,4 @@ export {
6959
7353
  handleUserPrompt,
6960
7354
  main
6961
7355
  };
6962
- //# sourceMappingURL=main-ADLCOYKM.js.map
7356
+ //# sourceMappingURL=main-VAU5UPY7.js.map