autosnippet 3.3.4 → 3.3.6

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 (221) hide show
  1. package/README.md +174 -83
  2. package/config/constitution.yaml +2 -0
  3. package/dashboard/dist/assets/icons-D1aVZYFW.js +1 -0
  4. package/dashboard/dist/assets/index-CxHOu8Hd.css +1 -0
  5. package/dashboard/dist/assets/index-DDdAOpYT.js +128 -0
  6. package/dashboard/dist/index.html +3 -3
  7. package/dist/bin/api-server.js +1 -0
  8. package/dist/bin/cli.d.ts +1 -0
  9. package/dist/bin/cli.js +136 -9
  10. package/dist/lib/agent/AgentFactory.d.ts +0 -17
  11. package/dist/lib/agent/AgentFactory.js +1 -25
  12. package/dist/lib/agent/capabilities.d.ts +11 -0
  13. package/dist/lib/agent/capabilities.js +29 -5
  14. package/dist/lib/agent/context/ExplorationTracker.js +10 -1
  15. package/dist/lib/agent/context/exploration/ExplorationStrategies.d.ts +2 -0
  16. package/dist/lib/agent/context/exploration/ExplorationStrategies.js +2 -2
  17. package/dist/lib/agent/domain/insight-analyst.d.ts +47 -3
  18. package/dist/lib/agent/domain/insight-analyst.js +111 -11
  19. package/dist/lib/agent/domain/insight-evolver.d.ts +69 -0
  20. package/dist/lib/agent/domain/insight-evolver.js +230 -0
  21. package/dist/lib/agent/domain/insight-gate.d.ts +42 -0
  22. package/dist/lib/agent/domain/insight-gate.js +41 -0
  23. package/dist/lib/agent/domain/insight-producer.d.ts +27 -2
  24. package/dist/lib/agent/domain/insight-producer.js +60 -5
  25. package/dist/lib/agent/domain/scan-prompts.js +10 -7
  26. package/dist/lib/agent/memory/ActiveContext.d.ts +2 -28
  27. package/dist/lib/agent/memory/MemoryCoordinator.d.ts +2 -2
  28. package/dist/lib/agent/memory/SessionStore.d.ts +6 -12
  29. package/dist/lib/agent/memory/SessionStore.js +9 -15
  30. package/dist/lib/agent/memory/memory-flush-contract.d.ts +49 -0
  31. package/dist/lib/agent/memory/memory-flush-contract.js +16 -0
  32. package/dist/lib/agent/memory/session-store-schema.d.ts +20 -0
  33. package/dist/lib/agent/memory/session-store-schema.js +41 -0
  34. package/dist/lib/agent/presets.d.ts +89 -1
  35. package/dist/lib/agent/presets.js +53 -5
  36. package/dist/lib/agent/tools/_shared.d.ts +7 -15
  37. package/dist/lib/agent/tools/_shared.js +20 -21
  38. package/dist/lib/agent/tools/composite.d.ts +25 -22
  39. package/dist/lib/agent/tools/composite.js +108 -109
  40. package/dist/lib/agent/tools/evolution-tools.d.ts +145 -0
  41. package/dist/lib/agent/tools/evolution-tools.js +161 -0
  42. package/dist/lib/agent/tools/index.d.ts +163 -92
  43. package/dist/lib/agent/tools/index.js +9 -1
  44. package/dist/lib/agent/tools/lifecycle.d.ts +7 -1
  45. package/dist/lib/agent/tools/lifecycle.js +59 -75
  46. package/dist/lib/cli/AiScanService.js +1 -1
  47. package/dist/lib/cli/KnowledgeSyncService.d.ts +5 -1
  48. package/dist/lib/cli/KnowledgeSyncService.js +6 -3
  49. package/dist/lib/core/AstAnalyzer.d.ts +1 -0
  50. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.d.ts → domain/dimension/DimensionCopy.d.ts} +2 -2
  51. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.js → domain/dimension/DimensionCopy.js} +22 -72
  52. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +54 -0
  53. package/dist/lib/domain/dimension/DimensionRegistry.js +620 -0
  54. package/dist/lib/domain/dimension/DimensionSop.d.ts +55 -0
  55. package/dist/lib/domain/dimension/DimensionSop.js +1604 -0
  56. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +61 -0
  57. package/dist/lib/domain/dimension/UnifiedDimension.js +53 -0
  58. package/dist/lib/domain/dimension/index.d.ts +10 -0
  59. package/dist/lib/domain/dimension/index.js +9 -0
  60. package/dist/lib/domain/knowledge/FieldSpec.d.ts +1 -1
  61. package/dist/lib/domain/knowledge/FieldSpec.js +29 -16
  62. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +33 -111
  63. package/dist/lib/domain/knowledge/KnowledgeEntry.js +27 -6
  64. package/dist/lib/domain/knowledge/KnowledgeRepository.d.ts +1 -0
  65. package/dist/lib/domain/knowledge/KnowledgeRepository.js +3 -0
  66. package/dist/lib/domain/knowledge/Lifecycle.js +1 -1
  67. package/dist/lib/domain/knowledge/StyleGuide.d.ts +1 -1
  68. package/dist/lib/domain/knowledge/StyleGuide.js +1 -1
  69. package/dist/lib/domain/knowledge/UnifiedValidator.js +15 -0
  70. package/dist/lib/domain/knowledge/values/Stats.d.ts +1 -1
  71. package/dist/lib/domain/knowledge/values/Stats.js +2 -2
  72. package/dist/lib/external/mcp/McpServer.js +4 -0
  73. package/dist/lib/external/mcp/handlers/TargetClassifier.d.ts +1 -1
  74. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.d.ts +8 -16
  75. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +10 -10
  76. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.d.ts +7 -0
  77. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +20 -0
  78. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +52 -132
  79. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +204 -17
  80. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.d.ts +11 -75
  81. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.js +40 -191
  82. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.d.ts +13 -78
  83. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +30 -52
  84. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.d.ts +0 -1
  85. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.d.ts +99 -12
  86. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +172 -161
  87. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +7 -17
  88. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.d.ts +46 -0
  89. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.js +58 -0
  90. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.d.ts +25 -0
  91. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.js +47 -0
  92. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +50 -12
  93. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +30 -10
  94. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-text.js +1 -1
  95. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.d.ts +24 -0
  96. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.js +14 -0
  97. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.d.ts +14 -0
  98. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.js +48 -0
  99. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.d.ts +21 -0
  100. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.js +45 -0
  101. package/dist/lib/external/mcp/handlers/bootstrap/shared/skill-generator.d.ts +1 -1
  102. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.d.ts +27 -0
  103. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.js +44 -0
  104. package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +14 -10
  105. package/dist/lib/external/mcp/handlers/bootstrap-external.js +39 -51
  106. package/dist/lib/external/mcp/handlers/bootstrap-internal.d.ts +2 -0
  107. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +115 -82
  108. package/dist/lib/external/mcp/handlers/consolidated.d.ts +4 -4
  109. package/dist/lib/external/mcp/handlers/consolidated.js +115 -162
  110. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +69 -1
  111. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +54 -0
  112. package/dist/lib/external/mcp/handlers/evolve-external.js +226 -0
  113. package/dist/lib/external/mcp/handlers/knowledge.js +26 -2
  114. package/dist/lib/external/mcp/handlers/rescan-external.d.ts +76 -0
  115. package/dist/lib/external/mcp/handlers/rescan-external.js +335 -0
  116. package/dist/lib/external/mcp/handlers/rescan-internal.d.ts +120 -0
  117. package/dist/lib/external/mcp/handlers/rescan-internal.js +359 -0
  118. package/dist/lib/external/mcp/handlers/search.d.ts +6 -5
  119. package/dist/lib/external/mcp/handlers/search.js +6 -5
  120. package/dist/lib/external/mcp/handlers/types.d.ts +2 -1
  121. package/dist/lib/external/mcp/handlers/wiki-external.js +2 -2
  122. package/dist/lib/external/mcp/tools.d.ts +8 -18
  123. package/dist/lib/external/mcp/tools.js +60 -3
  124. package/dist/lib/http/routes/knowledge.js +122 -1
  125. package/dist/lib/http/routes/modules.js +25 -3
  126. package/dist/lib/http/routes/panorama.js +16 -4
  127. package/dist/lib/infrastructure/cache/CacheCoordinator.d.ts +41 -0
  128. package/dist/lib/infrastructure/cache/CacheCoordinator.js +105 -0
  129. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.d.ts +7 -0
  130. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.js +28 -0
  131. package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +1 -1
  132. package/dist/lib/injection/ServiceContainer.js +55 -0
  133. package/dist/lib/injection/ServiceMap.d.ts +8 -1
  134. package/dist/lib/injection/modules/InfraModule.js +4 -1
  135. package/dist/lib/injection/modules/KnowledgeModule.js +38 -1
  136. package/dist/lib/repository/evolution/ProposalRepository.d.ts +99 -0
  137. package/dist/lib/repository/evolution/ProposalRepository.js +255 -0
  138. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +4 -0
  139. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +16 -1
  140. package/dist/lib/service/bootstrap/BootstrapEventEmitter.d.ts +3 -2
  141. package/dist/lib/service/bootstrap/BootstrapEventEmitter.js +1 -1
  142. package/dist/lib/service/bootstrap/DeliveryVerifier.d.ts +51 -0
  143. package/dist/lib/service/bootstrap/DeliveryVerifier.js +163 -0
  144. package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +22 -4
  145. package/dist/lib/service/bootstrap/UiStartupTasks.js +73 -5
  146. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +54 -0
  147. package/dist/lib/service/bootstrap/bootstrap-event-types.js +10 -0
  148. package/dist/lib/service/cleanup/CleanupService.d.ts +85 -0
  149. package/dist/lib/service/cleanup/CleanupService.js +324 -0
  150. package/dist/lib/service/delivery/AgentInstructionsGenerator.js +39 -43
  151. package/dist/lib/service/delivery/FileProtection.d.ts +20 -0
  152. package/dist/lib/service/delivery/FileProtection.js +54 -0
  153. package/dist/lib/service/delivery/SkillsSyncer.js +16 -21
  154. package/dist/lib/service/evolution/ContentPatcher.d.ts +44 -0
  155. package/dist/lib/service/evolution/ContentPatcher.js +310 -0
  156. package/dist/lib/service/evolution/DecayDetector.d.ts +4 -3
  157. package/dist/lib/service/evolution/DecayDetector.js +97 -22
  158. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -2
  159. package/dist/lib/service/evolution/KnowledgeMetabolism.js +29 -2
  160. package/dist/lib/service/evolution/ProposalExecutor.d.ts +66 -0
  161. package/dist/lib/service/evolution/ProposalExecutor.js +424 -0
  162. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +64 -0
  163. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +458 -0
  164. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +89 -0
  165. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +492 -0
  166. package/dist/lib/service/evolution/StagingManager.js +5 -3
  167. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +44 -0
  168. package/dist/lib/service/evolution/createSupersedeProposal.js +81 -0
  169. package/dist/lib/service/guard/ComplianceReporter.d.ts +4 -0
  170. package/dist/lib/service/guard/ComplianceReporter.js +51 -0
  171. package/dist/lib/service/guard/GuardCheckEngine.js +5 -4
  172. package/dist/lib/service/guard/GuardCrossFileChecks.js +2 -0
  173. package/dist/lib/service/guard/ReverseGuard.d.ts +1 -1
  174. package/dist/lib/service/guard/ReverseGuard.js +32 -2
  175. package/dist/lib/service/knowledge/ConfidenceRouter.js +1 -1
  176. package/dist/lib/service/knowledge/KnowledgeService.d.ts +11 -1
  177. package/dist/lib/service/knowledge/KnowledgeService.js +44 -4
  178. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +225 -0
  179. package/dist/lib/service/knowledge/RecipeProductionGateway.js +384 -0
  180. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +2 -0
  181. package/dist/lib/service/knowledge/SourceRefReconciler.js +48 -0
  182. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +3 -2
  183. package/dist/lib/service/panorama/DimensionAnalyzer.js +15 -140
  184. package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
  185. package/dist/lib/service/search/SearchEngine.d.ts +11 -10
  186. package/dist/lib/service/search/SearchEngine.js +38 -36
  187. package/dist/lib/service/search/SearchTypes.d.ts +14 -8
  188. package/dist/lib/service/search/SearchTypes.js +1 -1
  189. package/dist/lib/service/search/tokenizer.d.ts +1 -1
  190. package/dist/lib/service/search/tokenizer.js +2 -2
  191. package/dist/lib/shared/schemas/common.d.ts +4 -4
  192. package/dist/lib/shared/schemas/http-requests.d.ts +12 -1
  193. package/dist/lib/shared/schemas/http-requests.js +8 -0
  194. package/dist/lib/shared/schemas/mcp-tools.d.ts +33 -2
  195. package/dist/lib/shared/schemas/mcp-tools.js +42 -0
  196. package/dist/lib/types/evolution.d.ts +135 -0
  197. package/dist/lib/types/evolution.js +6 -0
  198. package/dist/lib/types/graph-shared.d.ts +25 -0
  199. package/dist/lib/types/graph-shared.js +7 -0
  200. package/dist/lib/types/knowledge-wire.d.ts +131 -0
  201. package/dist/lib/types/knowledge-wire.js +7 -0
  202. package/dist/lib/types/project-snapshot-builder.d.ts +19 -0
  203. package/dist/lib/types/project-snapshot-builder.js +189 -0
  204. package/dist/lib/types/project-snapshot.d.ts +399 -0
  205. package/dist/lib/types/project-snapshot.js +17 -0
  206. package/dist/lib/types/search-wire.d.ts +46 -0
  207. package/dist/lib/types/search-wire.js +7 -0
  208. package/dist/lib/types/snapshot-views.d.ts +58 -0
  209. package/dist/lib/types/snapshot-views.js +103 -0
  210. package/package.json +1 -1
  211. package/skills/autosnippet-recipes/SKILL.md +1 -1
  212. package/templates/instructions/agent-static.md +2 -0
  213. package/templates/instructions/conventions.md +3 -1
  214. package/templates/recipes-setup/README.md +2 -2
  215. package/dashboard/dist/assets/icons-BJ2mUBi8.js +0 -1
  216. package/dashboard/dist/assets/index-B659K9t5.js +0 -128
  217. package/dashboard/dist/assets/index-NCm40PMD.css +0 -1
  218. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.d.ts +0 -169
  219. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +0 -727
  220. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.d.ts +0 -370
  221. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +0 -821
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import express from 'express';
7
7
  import { ioLimit } from '#shared/concurrency.js';
8
- import { BatchPublishBody, CreateKnowledgeBody, DeprecateKnowledgeBody, KnowledgeUsageBody, UpdateKnowledgeBody, } from '#shared/schemas/http-requests.js';
8
+ import { BatchDeleteBody, BatchDeprecateBody, BatchPublishBody, CreateKnowledgeBody, DeprecateKnowledgeBody, KnowledgeUsageBody, UpdateKnowledgeBody, } from '#shared/schemas/http-requests.js';
9
9
  import Logger from '../../infrastructure/logging/Logger.js';
10
10
  import { getServiceContainer } from '../../injection/ServiceContainer.js';
11
11
  import { validate } from '../middleware/validate.js';
@@ -140,6 +140,28 @@ router.get('/lifecycle', async (req, res) => {
140
140
  }
141
141
  res.json({ success: true, data: lifecycle });
142
142
  });
143
+ /**
144
+ * POST /api/v1/knowledge/quality/refresh-all
145
+ * 批量重新计算所有条目的质量评分
146
+ */
147
+ router.post('/quality/refresh-all', async (_req, res) => {
148
+ const container = getServiceContainer();
149
+ const knowledgeService = container.get('knowledgeService');
150
+ const result = await knowledgeService.list({}, { page: 1, pageSize: 10000 });
151
+ const all = result.data;
152
+ let updated = 0;
153
+ let failed = 0;
154
+ for (const entry of all) {
155
+ try {
156
+ await knowledgeService.updateQuality(entry.id);
157
+ updated++;
158
+ }
159
+ catch {
160
+ failed++;
161
+ }
162
+ }
163
+ res.json({ success: true, data: { updated, failed, total: all.length } });
164
+ });
143
165
  /**
144
166
  * GET /api/v1/knowledge/:id
145
167
  * 获取知识条目详情
@@ -229,6 +251,54 @@ router.patch('/:id/reactivate', requirePermission('knowledge', 'update'), async
229
251
  const entry = await knowledgeService.reactivate(id, context);
230
252
  res.json({ success: true, data: sanitizeForAPI(entry) });
231
253
  });
254
+ /**
255
+ * PATCH /api/v1/knowledge/:id/stage
256
+ * 暂存 (pending → staging)
257
+ */
258
+ router.patch('/:id/stage', requirePermission('knowledge', 'update'), async (req, res) => {
259
+ const id = String(req.params.id);
260
+ const container = getServiceContainer();
261
+ const knowledgeService = container.get('knowledgeService');
262
+ const context = getContext(req);
263
+ const entry = await knowledgeService.stage(id, context);
264
+ res.json({ success: true, data: sanitizeForAPI(entry) });
265
+ });
266
+ /**
267
+ * PATCH /api/v1/knowledge/:id/evolve
268
+ * 进化 (active → evolving)
269
+ */
270
+ router.patch('/:id/evolve', requirePermission('knowledge', 'update'), async (req, res) => {
271
+ const id = String(req.params.id);
272
+ const container = getServiceContainer();
273
+ const knowledgeService = container.get('knowledgeService');
274
+ const context = getContext(req);
275
+ const entry = await knowledgeService.evolve(id, context);
276
+ res.json({ success: true, data: sanitizeForAPI(entry) });
277
+ });
278
+ /**
279
+ * PATCH /api/v1/knowledge/:id/decay
280
+ * 衰退 (active|evolving → decaying)
281
+ */
282
+ router.patch('/:id/decay', requirePermission('knowledge', 'update'), async (req, res) => {
283
+ const id = String(req.params.id);
284
+ const container = getServiceContainer();
285
+ const knowledgeService = container.get('knowledgeService');
286
+ const context = getContext(req);
287
+ const entry = await knowledgeService.decay(id, context);
288
+ res.json({ success: true, data: sanitizeForAPI(entry) });
289
+ });
290
+ /**
291
+ * PATCH /api/v1/knowledge/:id/restore
292
+ * 恢复为已发布 (decaying|evolving → active)
293
+ */
294
+ router.patch('/:id/restore', requirePermission('knowledge', 'update'), async (req, res) => {
295
+ const id = String(req.params.id);
296
+ const container = getServiceContainer();
297
+ const knowledgeService = container.get('knowledgeService');
298
+ const context = getContext(req);
299
+ const entry = await knowledgeService.restore(id, context);
300
+ res.json({ success: true, data: sanitizeForAPI(entry) });
301
+ });
232
302
  /* ═══ 批量操作 ═══════════════════════════════════════════ */
233
303
  /**
234
304
  * POST /api/v1/knowledge/batch-publish
@@ -258,6 +328,57 @@ router.post('/batch-publish', requirePermission('knowledge', 'publish'), validat
258
328
  },
259
329
  });
260
330
  });
331
+ /**
332
+ * POST /api/v1/knowledge/batch-delete
333
+ * 批量删除知识条目
334
+ */
335
+ router.post('/batch-delete', requirePermission('knowledge', 'delete'), validate(BatchDeleteBody), async (req, res) => {
336
+ const { ids } = req.body;
337
+ const container = getServiceContainer();
338
+ const knowledgeService = container.get('knowledgeService');
339
+ const context = getContext(req);
340
+ const results = await Promise.allSettled(ids.map((id) => ioLimit(() => knowledgeService.delete(id, context))));
341
+ const deleted = results.filter((r) => r.status === 'fulfilled').length;
342
+ const failed = results
343
+ .map((r, i) => (r.status === 'rejected' ? { id: ids[i], error: r.reason?.message } : null))
344
+ .filter(Boolean);
345
+ res.json({
346
+ success: true,
347
+ data: {
348
+ total: ids.length,
349
+ deletedCount: deleted,
350
+ failureCount: failed.length,
351
+ failed,
352
+ },
353
+ });
354
+ });
355
+ /**
356
+ * POST /api/v1/knowledge/batch-deprecate
357
+ * 批量废弃知识条目 (active → deprecated)
358
+ */
359
+ router.post('/batch-deprecate', requirePermission('knowledge', 'publish'), validate(BatchDeprecateBody), async (req, res) => {
360
+ const { ids, reason } = req.body;
361
+ const container = getServiceContainer();
362
+ const knowledgeService = container.get('knowledgeService');
363
+ const context = getContext(req);
364
+ const results = await Promise.allSettled(ids.map((id) => ioLimit(() => knowledgeService.deprecate(id, reason || 'batch deprecate', context))));
365
+ const deprecated = results
366
+ .filter((r) => r.status === 'fulfilled')
367
+ .map((r) => sanitizeForAPI(r.value));
368
+ const failed = results
369
+ .map((r, i) => (r.status === 'rejected' ? { id: ids[i], error: r.reason?.message } : null))
370
+ .filter(Boolean);
371
+ res.json({
372
+ success: true,
373
+ data: {
374
+ deprecated,
375
+ failed,
376
+ total: ids.length,
377
+ successCount: deprecated.length,
378
+ failureCount: failed.length,
379
+ },
380
+ });
381
+ });
261
382
  /* ═══ 使用 / 质量 ═══════════════════════════════════════ */
262
383
  /**
263
384
  * POST /api/v1/knowledge/:id/usage
@@ -5,7 +5,7 @@
5
5
  * 所有端点通过 container.get('moduleService') 获取 ModuleService 实例
6
6
  */
7
7
  import express from 'express';
8
- import { ModuleBootstrapBody, ScanFolderBody, ScanProjectBody, ScanTargetBody, } from '#shared/schemas/http-requests.js';
8
+ import { ModuleBootstrapBody, ModuleRescanBody, ScanFolderBody, ScanProjectBody, ScanTargetBody, } from '#shared/schemas/http-requests.js';
9
9
  import Logger from '../../infrastructure/logging/Logger.js';
10
10
  import { getServiceContainer } from '../../injection/ServiceContainer.js';
11
11
  import { validate } from '../middleware/validate.js';
@@ -416,14 +416,17 @@ router.get('/project-info', async (req, res) => {
416
416
  router.post('/bootstrap', validate(ModuleBootstrapBody), async (req, res) => {
417
417
  const { maxFiles, skipGuard, contentMaxLines } = req.body || {};
418
418
  const container = getServiceContainer();
419
- const agentFactory = container.get('agentFactory');
420
419
  logger.info('Bootstrap cold start initiated (ModuleService path)');
421
- const bootstrapResult = await agentFactory.bootstrapKnowledge({
420
+ // 直接调用 bootstrap-internal handler(统一编排管线)
421
+ const { bootstrapKnowledge } = await import('#external/mcp/handlers/bootstrap-internal.js');
422
+ const raw = await bootstrapKnowledge({ container, logger }, {
422
423
  maxFiles: maxFiles || 500,
423
424
  skipGuard: skipGuard || false,
424
425
  contentMaxLines: contentMaxLines || 120,
425
426
  loadSkills: true,
426
427
  });
428
+ const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
429
+ const bootstrapResult = parsed?.data || parsed;
427
430
  res.json({
428
431
  success: true,
429
432
  data: {
@@ -456,4 +459,23 @@ router.get('/bootstrap/status', async (req, res) => {
456
459
  data: taskManager.getSessionStatus(),
457
460
  });
458
461
  });
462
+ /**
463
+ * POST /api/v1/modules/rescan
464
+ * 增量扫描:保留已有 Recipe,重新分析项目,补齐缺失知识
465
+ * 使用内部 Agent pipeline 自动完成知识补齐
466
+ */
467
+ router.post('/rescan', validate(ModuleRescanBody), async (req, res) => {
468
+ const { reason, dimensions } = req.body || {};
469
+ const container = getServiceContainer();
470
+ logger.info('Rescan (internal) initiated from Dashboard', { reason, dimensions });
471
+ // 直接调用 rescan-internal handler(统一编排管线)
472
+ const { rescanInternal } = await import('#external/mcp/handlers/rescan-internal.js');
473
+ const raw = await rescanInternal({ container, logger }, { reason: reason || 'dashboard-rescan', dimensions });
474
+ const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
475
+ const result = parsed?.data || parsed;
476
+ res.json({
477
+ success: true,
478
+ data: result,
479
+ });
480
+ });
459
481
  export default router;
@@ -14,7 +14,7 @@ const router = express.Router();
14
14
  * GET /api/v1/panorama
15
15
  * 返回项目全景概览(层级、模块、覆盖率)
16
16
  */
17
- router.get('/', async (_req, res) => {
17
+ router.get('/', async (req, res) => {
18
18
  try {
19
19
  const container = getServiceContainer();
20
20
  const panoramaService = container.get('panoramaService');
@@ -25,6 +25,9 @@ router.get('/', async (_req, res) => {
25
25
  });
26
26
  return;
27
27
  }
28
+ if (req.query.refresh === 'true' && typeof panoramaService.invalidate === 'function') {
29
+ panoramaService.invalidate();
30
+ }
28
31
  if (typeof panoramaService.ensureData === 'function') {
29
32
  await panoramaService.ensureData();
30
33
  }
@@ -42,7 +45,7 @@ router.get('/', async (_req, res) => {
42
45
  * GET /api/v1/panorama/health
43
46
  * 返回全景健康度评分
44
47
  */
45
- router.get('/health', async (_req, res) => {
48
+ router.get('/health', async (req, res) => {
46
49
  try {
47
50
  const container = getServiceContainer();
48
51
  const panoramaService = container.get('panoramaService');
@@ -53,6 +56,9 @@ router.get('/health', async (_req, res) => {
53
56
  });
54
57
  return;
55
58
  }
59
+ if (req.query.refresh === 'true' && typeof panoramaService.invalidate === 'function') {
60
+ panoramaService.invalidate();
61
+ }
56
62
  if (typeof panoramaService.ensureData === 'function') {
57
63
  await panoramaService.ensureData();
58
64
  }
@@ -70,7 +76,7 @@ router.get('/health', async (_req, res) => {
70
76
  * GET /api/v1/panorama/gaps
71
77
  * 返回知识空白区列表
72
78
  */
73
- router.get('/gaps', async (_req, res) => {
79
+ router.get('/gaps', async (req, res) => {
74
80
  try {
75
81
  const container = getServiceContainer();
76
82
  const panoramaService = container.get('panoramaService');
@@ -81,6 +87,9 @@ router.get('/gaps', async (_req, res) => {
81
87
  });
82
88
  return;
83
89
  }
90
+ if (req.query.refresh === 'true' && typeof panoramaService.invalidate === 'function') {
91
+ panoramaService.invalidate();
92
+ }
84
93
  if (typeof panoramaService.ensureData === 'function') {
85
94
  await panoramaService.ensureData();
86
95
  }
@@ -98,7 +107,7 @@ router.get('/gaps', async (_req, res) => {
98
107
  * GET /api/v1/panorama/coverage
99
108
  * 返回各模块知识覆盖率热力图数据
100
109
  */
101
- router.get('/coverage', async (_req, res) => {
110
+ router.get('/coverage', async (req, res) => {
102
111
  try {
103
112
  const container = getServiceContainer();
104
113
  const panoramaService = container.get('panoramaService');
@@ -109,6 +118,9 @@ router.get('/coverage', async (_req, res) => {
109
118
  });
110
119
  return;
111
120
  }
121
+ if (req.query.refresh === 'true' && typeof panoramaService.invalidate === 'function') {
122
+ panoramaService.invalidate();
123
+ }
112
124
  if (typeof panoramaService.ensureData === 'function') {
113
125
  await panoramaService.ensureData();
114
126
  }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * CacheCoordinator — 跨进程缓存失效协调器
3
+ *
4
+ * 利用 SQLite 内置的 `PRAGMA data_version` 检测其他进程的 DB 写入。
5
+ * 当检测到 data_version 变化时,通知所有注册的订阅者清除内存缓存。
6
+ *
7
+ * 原理:
8
+ * - SQLite 的 data_version 是一个连接级别的计数器
9
+ * - 当 *其他* 连接(包括其他进程)提交写事务后,当前连接的下次读操作
10
+ * 会看到递增的 data_version
11
+ * - 通过定期轮询(默认 2s),实现近实时的跨进程缓存失效
12
+ * - 开销极低:一次 pragma 读取 < 0.01ms
13
+ *
14
+ * 典型场景:
15
+ * - MCP Server 冷启动写入 33 条 Recipe → HTTP Server 的 data_version 变化
16
+ * - 用户 CLI 执行 `asd embed` → Dashboard API 的缓存自动失效
17
+ *
18
+ * @module infrastructure/cache/CacheCoordinator
19
+ */
20
+ import type { SqliteDatabase } from '../database/DatabaseConnection.js';
21
+ export type InvalidateHandler = () => void;
22
+ export declare class CacheCoordinator {
23
+ #private;
24
+ constructor(db: SqliteDatabase, pollIntervalMs?: number);
25
+ /** 启动轮询(仅长驻进程需要:HTTP server / MCP server) */
26
+ start(): void;
27
+ /** 停止轮询 */
28
+ stop(): void;
29
+ /**
30
+ * 注册缓存失效回调
31
+ *
32
+ * @param name 标识名(用于日志,如 'panoramaService')
33
+ * @param handler 失效时调用的清除函数
34
+ * @returns 取消注册函数
35
+ */
36
+ subscribe(name: string, handler: InvalidateHandler): () => void;
37
+ /** 当前订阅者数量(诊断用) */
38
+ get subscriberCount(): number;
39
+ /** 手动触发一次检查(测试用) */
40
+ check(): boolean;
41
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * CacheCoordinator — 跨进程缓存失效协调器
3
+ *
4
+ * 利用 SQLite 内置的 `PRAGMA data_version` 检测其他进程的 DB 写入。
5
+ * 当检测到 data_version 变化时,通知所有注册的订阅者清除内存缓存。
6
+ *
7
+ * 原理:
8
+ * - SQLite 的 data_version 是一个连接级别的计数器
9
+ * - 当 *其他* 连接(包括其他进程)提交写事务后,当前连接的下次读操作
10
+ * 会看到递增的 data_version
11
+ * - 通过定期轮询(默认 2s),实现近实时的跨进程缓存失效
12
+ * - 开销极低:一次 pragma 读取 < 0.01ms
13
+ *
14
+ * 典型场景:
15
+ * - MCP Server 冷启动写入 33 条 Recipe → HTTP Server 的 data_version 变化
16
+ * - 用户 CLI 执行 `asd embed` → Dashboard API 的缓存自动失效
17
+ *
18
+ * @module infrastructure/cache/CacheCoordinator
19
+ */
20
+ import Logger from '../logging/Logger.js';
21
+ export class CacheCoordinator {
22
+ #db;
23
+ #lastVersion;
24
+ #interval = null;
25
+ #subscribers = new Map();
26
+ #pollMs;
27
+ constructor(db, pollIntervalMs = 2000) {
28
+ this.#db = db;
29
+ this.#pollMs = pollIntervalMs;
30
+ this.#lastVersion = this.#readVersion();
31
+ }
32
+ /** 启动轮询(仅长驻进程需要:HTTP server / MCP server) */
33
+ start() {
34
+ if (this.#interval) {
35
+ return;
36
+ }
37
+ this.#interval = setInterval(() => this.#check(), this.#pollMs);
38
+ // unref 避免阻止进程正常退出
39
+ if (this.#interval.unref) {
40
+ this.#interval.unref();
41
+ }
42
+ Logger.info('[CacheCoordinator] Started', {
43
+ pollMs: this.#pollMs,
44
+ subscribers: this.#subscribers.size,
45
+ });
46
+ }
47
+ /** 停止轮询 */
48
+ stop() {
49
+ if (this.#interval) {
50
+ clearInterval(this.#interval);
51
+ this.#interval = null;
52
+ }
53
+ }
54
+ /**
55
+ * 注册缓存失效回调
56
+ *
57
+ * @param name 标识名(用于日志,如 'panoramaService')
58
+ * @param handler 失效时调用的清除函数
59
+ * @returns 取消注册函数
60
+ */
61
+ subscribe(name, handler) {
62
+ this.#subscribers.set(name, handler);
63
+ return () => {
64
+ this.#subscribers.delete(name);
65
+ };
66
+ }
67
+ /** 当前订阅者数量(诊断用) */
68
+ get subscriberCount() {
69
+ return this.#subscribers.size;
70
+ }
71
+ /** 手动触发一次检查(测试用) */
72
+ check() {
73
+ return this.#check();
74
+ }
75
+ // ── 内部方法 ──────────────────────────────────────
76
+ #readVersion() {
77
+ return this.#db.pragma('data_version', { simple: true });
78
+ }
79
+ /** @returns true 如果版本变化并触发了失效 */
80
+ #check() {
81
+ const current = this.#readVersion();
82
+ if (current === this.#lastVersion) {
83
+ return false;
84
+ }
85
+ const prev = this.#lastVersion;
86
+ this.#lastVersion = current;
87
+ const names = [...this.#subscribers.keys()];
88
+ Logger.info('[CacheCoordinator] DB changed by another process, invalidating caches', {
89
+ prevVersion: prev,
90
+ newVersion: current,
91
+ targets: names,
92
+ });
93
+ for (const [name, handler] of this.#subscribers) {
94
+ try {
95
+ handler();
96
+ }
97
+ catch (err) {
98
+ Logger.warn(`[CacheCoordinator] Invalidation handler "${name}" threw`, {
99
+ error: err.message,
100
+ });
101
+ }
102
+ }
103
+ return true;
104
+ }
105
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Migration 006 — Lifecycle Transition Events
3
+ *
4
+ * Recipe 生命周期状态转移事件日志表(Event Sourcing 模式)。
5
+ * 记录每次状态转移的完整审计信息,支持回溯与监控。
6
+ */
7
+ export default function migrate(db: import('better-sqlite3').Database): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Migration 006 — Lifecycle Transition Events
3
+ *
4
+ * Recipe 生命周期状态转移事件日志表(Event Sourcing 模式)。
5
+ * 记录每次状态转移的完整审计信息,支持回溯与监控。
6
+ */
7
+ export default function migrate(db) {
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS lifecycle_transition_events (
10
+ id TEXT PRIMARY KEY,
11
+ recipe_id TEXT NOT NULL,
12
+ from_state TEXT NOT NULL,
13
+ to_state TEXT NOT NULL,
14
+ trigger TEXT NOT NULL,
15
+ operator_id TEXT NOT NULL DEFAULT 'system',
16
+ evidence_json TEXT,
17
+ proposal_id TEXT,
18
+ created_at INTEGER NOT NULL,
19
+
20
+ FOREIGN KEY (recipe_id) REFERENCES knowledge_entries(id),
21
+ FOREIGN KEY (proposal_id) REFERENCES evolution_proposals(id)
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_lte_recipe_id ON lifecycle_transition_events(recipe_id);
25
+ CREATE INDEX IF NOT EXISTS idx_lte_created_at ON lifecycle_transition_events(created_at);
26
+ CREATE INDEX IF NOT EXISTS idx_lte_trigger ON lifecycle_transition_events(trigger);
27
+ `);
28
+ }
@@ -468,7 +468,7 @@ export class HnswVectorAdapter extends VectorStore {
468
468
  }));
469
469
  }
470
470
  /**
471
- * 关键词搜索 (BM25 简化版: token 匹配 + IDF 近似)
471
+ * 关键词搜索 (token 匹配 + IDF 近似)
472
472
  * @returns >}
473
473
  */
474
474
  #keywordSearch(queryText, limit, filter) {
@@ -5,6 +5,7 @@ import { resolveProjectRoot } from '#shared/resolveProjectRoot.js';
5
5
  import ProjectGraph from '../core/ast/ProjectGraph.js';
6
6
  // ─── v3.1: Multi-Language Discovery + Enhancement ────────
7
7
  import { initEnhancementRegistry } from '../core/enhancement/index.js';
8
+ import { CacheCoordinator } from '../infrastructure/cache/CacheCoordinator.js';
8
9
  import { GraphCache } from '../infrastructure/cache/GraphCache.js';
9
10
  // ─── P3: Infrastructure ──────────────────────────────
10
11
  import Logger from '../infrastructure/logging/Logger.js';
@@ -132,6 +133,8 @@ export class ServiceContainer {
132
133
  await VectorModule.initializeVectorService(this);
133
134
  // v3.4: 初始化 Knowledge 服务(绑定 EventBus → SearchEngine.refreshIndex + sourceRefs)
134
135
  KnowledgeModule.initializeKnowledgeServices(this);
136
+ // v3.5: 跨进程缓存协调器(利用 SQLite PRAGMA data_version 检测其他进程写入)
137
+ this.#initCacheCoordinator();
135
138
  this.logger.info('Service container initialized successfully');
136
139
  }
137
140
  catch (error) {
@@ -175,6 +178,58 @@ export class ServiceContainer {
175
178
  clearedSingletons: cleared,
176
179
  });
177
180
  }
181
+ // ─── 跨进程缓存协调 ─────
182
+ /**
183
+ * 初始化 CacheCoordinator:当其他进程写入 DB 后,自动清除本进程的内存缓存。
184
+ *
185
+ * 订阅的服务:
186
+ * - panoramaService: invalidate() — 模块图 + 全景分析
187
+ * - guardCheckEngine: clearCache() — 规则缓存
188
+ * - searchEngine: buildIndex() — 搜索索引
189
+ *
190
+ * 仅在长驻进程(HTTP server / MCP server)中自动启动轮询。
191
+ * CLI 场景无需启动(进程生命周期短,缓存不会过时)。
192
+ */
193
+ #initCacheCoordinator() {
194
+ try {
195
+ const db = this.singletons.database;
196
+ const rawDb = db?.getDb ? db.getDb() : null;
197
+ if (!rawDb) {
198
+ return;
199
+ }
200
+ const coordinator = new CacheCoordinator(rawDb);
201
+ this.singletons.cacheCoordinator = coordinator;
202
+ this.register('cacheCoordinator', () => coordinator);
203
+ // 懒订阅:仅在对应服务已初始化时绑定
204
+ coordinator.subscribe('panoramaService', () => {
205
+ const svc = this.singletons.panoramaService;
206
+ svc?.invalidate?.();
207
+ });
208
+ coordinator.subscribe('guardCheckEngine', () => {
209
+ const svc = this.singletons.guardCheckEngine;
210
+ svc?.clearCache?.();
211
+ });
212
+ coordinator.subscribe('searchEngine', () => {
213
+ const svc = this.singletons.searchEngine;
214
+ svc?.buildIndex?.();
215
+ });
216
+ // 长驻进程自动启动轮询(CLI 不启动)
217
+ const isMcp = process.env.ASD_MCP_MODE === '1';
218
+ const isApiServer = process.env.ASD_API_SERVER === '1';
219
+ if (isMcp || isApiServer) {
220
+ coordinator.start();
221
+ }
222
+ this.logger.info('CacheCoordinator initialized', {
223
+ subscribers: coordinator.subscriberCount,
224
+ polling: isMcp || isApiServer,
225
+ });
226
+ }
227
+ catch (err) {
228
+ this.logger.warn('CacheCoordinator init failed (non-blocking)', {
229
+ error: err.message,
230
+ });
231
+ }
232
+ }
178
233
  // ─── 容器级语言偏好 ─────
179
234
  /** 获取当前默认 UI 语言偏好 */
180
235
  getLang() {
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @module ServiceMap
8
8
  */
9
+ import type DimensionCopy from '#domain/dimension/DimensionCopy.js';
9
10
  import type { AgentFactory } from '../agent/AgentFactory.js';
10
11
  import type { ToolRegistry } from '../agent/tools/ToolRegistry.js';
11
12
  import type { KnowledgeSyncService } from '../cli/KnowledgeSyncService.js';
@@ -15,6 +16,7 @@ import type Gateway from '../core/gateway/Gateway.js';
15
16
  import type { AiProvider } from '../external/ai/AiProvider.js';
16
17
  import type AuditLogger from '../infrastructure/audit/AuditLogger.js';
17
18
  import type AuditStore from '../infrastructure/audit/AuditStore.js';
19
+ import type { CacheCoordinator } from '../infrastructure/cache/CacheCoordinator.js';
18
20
  import type DatabaseConnection from '../infrastructure/database/DatabaseConnection.js';
19
21
  import type { EventBus } from '../infrastructure/event/EventBus.js';
20
22
  import type Logger from '../infrastructure/logging/Logger.js';
@@ -24,7 +26,6 @@ import type { VectorStore } from '../infrastructure/vector/VectorStore.js';
24
26
  import type { KnowledgeRepositoryImpl } from '../repository/knowledge/KnowledgeRepository.impl.js';
25
27
  import type { TokenUsageStore } from '../repository/token/TokenUsageStore.js';
26
28
  import type { BootstrapTaskManager } from '../service/bootstrap/BootstrapTaskManager.js';
27
- import type DimensionCopy from '../service/bootstrap/DimensionCopyRegistry.js';
28
29
  import type { CursorDeliveryPipeline } from '../service/delivery/CursorDeliveryPipeline.js';
29
30
  import type { ComplianceReporter } from '../service/guard/ComplianceReporter.js';
30
31
  import type { ExclusionManager } from '../service/guard/ExclusionManager.js';
@@ -117,4 +118,10 @@ export interface ServiceMap {
117
118
  layerInferrer: LayerInferrer;
118
119
  panoramaAggregator: PanoramaAggregator;
119
120
  panoramaService: PanoramaService;
121
+ cacheCoordinator: CacheCoordinator;
122
+ _projectRoot: string;
123
+ _config: Record<string, unknown>;
124
+ _lang: string | null;
125
+ _fileCache: unknown[] | null;
126
+ _embedProvider: unknown;
120
127
  }
@@ -65,7 +65,10 @@ export function register(c) {
65
65
  });
66
66
  c.singleton('knowledgeSyncService', (ct) => {
67
67
  const projectRoot = resolveProjectRoot(ct);
68
- return new KnowledgeSyncService(projectRoot);
68
+ const sourceRefReconciler = ct.singletons.sourceRefReconciler;
69
+ return new KnowledgeSyncService(projectRoot, {
70
+ sourceRefReconciler: sourceRefReconciler || undefined,
71
+ });
69
72
  });
70
73
  // ═══ ReportStore ═══
71
74
  c.singleton('reportStore', (ct) => {