autosnippet 3.3.7 → 3.3.8

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 (211) hide show
  1. package/README.md +1 -0
  2. package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
  3. package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
  4. package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
  5. package/dashboard/dist/index.html +3 -3
  6. package/dist/bin/cli.js +7 -4
  7. package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
  8. package/dist/lib/agent/core/LoopContext.d.ts +1 -0
  9. package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
  10. package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
  11. package/dist/lib/agent/memory/ActiveContext.js +0 -2
  12. package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
  13. package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
  14. package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
  15. package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
  16. package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
  17. package/dist/lib/agent/memory/MemoryStore.js +196 -261
  18. package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
  19. package/dist/lib/agent/memory/PersistentMemory.js +4 -5
  20. package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
  21. package/dist/lib/agent/memory/SessionStore.js +0 -2
  22. package/dist/lib/agent/tools/ast-graph.js +21 -19
  23. package/dist/lib/agent/tools/infrastructure.js +3 -2
  24. package/dist/lib/agent/tools/project-access.d.ts +2 -2
  25. package/dist/lib/agent/tools/project-access.js +5 -4
  26. package/dist/lib/bootstrap.js +2 -1
  27. package/dist/lib/cli/AiScanService.js +4 -17
  28. package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
  29. package/dist/lib/cli/KnowledgeSyncService.js +23 -51
  30. package/dist/lib/core/ast/ProjectGraph.js +5 -27
  31. package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
  32. package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
  33. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
  34. package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
  35. package/dist/lib/domain/dimension/DimensionSop.js +44 -33
  36. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
  37. package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
  38. package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
  39. package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
  40. package/dist/lib/domain/knowledge/index.d.ts +2 -1
  41. package/dist/lib/domain/knowledge/index.js +1 -1
  42. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
  43. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
  44. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
  45. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
  46. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
  47. package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
  48. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
  49. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
  50. package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
  51. package/dist/lib/external/mcp/handlers/guard.js +15 -24
  52. package/dist/lib/external/mcp/handlers/panorama.js +9 -9
  53. package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
  54. package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
  55. package/dist/lib/external/mcp/handlers/search.js +3 -1
  56. package/dist/lib/external/mcp/handlers/skill.js +4 -4
  57. package/dist/lib/external/mcp/handlers/structure.js +8 -12
  58. package/dist/lib/external/mcp/handlers/system.js +10 -34
  59. package/dist/lib/http/routes/ai.js +11 -13
  60. package/dist/lib/http/routes/guardReport.js +3 -5
  61. package/dist/lib/http/routes/panorama.js +12 -12
  62. package/dist/lib/http/routes/recipes.js +59 -8
  63. package/dist/lib/http/routes/remote.js +3 -13
  64. package/dist/lib/http/routes/search.js +11 -8
  65. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
  66. package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
  67. package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
  68. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
  69. package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
  70. package/dist/lib/injection/ServiceContainer.js +7 -4
  71. package/dist/lib/injection/ServiceMap.d.ts +20 -0
  72. package/dist/lib/injection/modules/AppModule.js +2 -1
  73. package/dist/lib/injection/modules/GuardModule.js +5 -5
  74. package/dist/lib/injection/modules/InfraModule.js +60 -0
  75. package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
  76. package/dist/lib/injection/modules/PanoramaModule.js +16 -10
  77. package/dist/lib/injection/modules/VectorModule.js +3 -0
  78. package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
  79. package/dist/lib/repository/audit/AuditRepository.js +272 -0
  80. package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
  81. package/dist/lib/repository/base/RepositoryBase.js +32 -0
  82. package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
  83. package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
  84. package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
  85. package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
  86. package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
  87. package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
  88. package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
  89. package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
  90. package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
  91. package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
  92. package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
  93. package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
  94. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
  95. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
  96. package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
  97. package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
  98. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
  99. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
  100. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
  101. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
  102. package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
  103. package/dist/lib/repository/memory/MemoryRepository.js +260 -0
  104. package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
  105. package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
  106. package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
  107. package/dist/lib/repository/session/SessionRepository.js +110 -0
  108. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
  109. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
  110. package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
  111. package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
  112. package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
  113. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
  114. package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
  115. package/dist/lib/service/cleanup/CleanupService.js +8 -4
  116. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
  117. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
  118. package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
  119. package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
  120. package/dist/lib/service/evolution/ContentPatcher.js +48 -19
  121. package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
  122. package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
  123. package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
  124. package/dist/lib/service/evolution/DecayDetector.js +63 -57
  125. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
  126. package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
  127. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
  128. package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
  129. package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
  130. package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
  131. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
  132. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
  133. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
  134. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
  135. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
  136. package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
  137. package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
  138. package/dist/lib/service/evolution/StagingManager.js +37 -95
  139. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
  140. package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
  141. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
  142. package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
  143. package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
  144. package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
  145. package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
  146. package/dist/lib/service/guard/ReverseGuard.js +21 -31
  147. package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
  148. package/dist/lib/service/guard/ViolationsStore.js +75 -69
  149. package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
  150. package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
  151. package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
  152. package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
  153. package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
  154. package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
  155. package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
  156. package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
  157. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
  158. package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
  159. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
  160. package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
  161. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
  162. package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
  163. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
  164. package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
  165. package/dist/lib/service/panorama/LayerInferrer.js +1 -1
  166. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
  167. package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
  168. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
  169. package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
  170. package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
  171. package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
  172. package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
  173. package/dist/lib/service/panorama/PanoramaService.js +41 -66
  174. package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
  175. package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
  176. package/dist/lib/service/panorama/RoleRefiner.js +52 -283
  177. package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
  178. package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
  179. package/dist/lib/service/quality/QualityScorer.js +157 -83
  180. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  181. package/dist/lib/service/search/SearchEngine.js +32 -37
  182. package/dist/lib/service/signal/HitRecorder.js +5 -5
  183. package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
  184. package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
  185. package/dist/lib/service/skills/SignalCollector.js +28 -55
  186. package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
  187. package/dist/lib/service/skills/SkillAdvisor.js +30 -79
  188. package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
  189. package/dist/lib/service/vector/SyncCoordinator.js +25 -3
  190. package/dist/lib/service/vector/VectorService.d.ts +2 -0
  191. package/dist/lib/service/vector/VectorService.js +3 -0
  192. package/dist/lib/service/wiki/WikiGenerator.js +1 -1
  193. package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
  194. package/dist/lib/shared/LanguageProfiles.js +939 -0
  195. package/dist/lib/shared/LanguageService.d.ts +6 -0
  196. package/dist/lib/shared/LanguageService.js +16 -0
  197. package/dist/lib/shared/constants.d.ts +19 -19
  198. package/dist/lib/shared/constants.js +10 -10
  199. package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
  200. package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
  201. package/dist/lib/types/project-snapshot-builder.js +0 -1
  202. package/dist/lib/types/project-snapshot.d.ts +0 -1
  203. package/dist/lib/types/project-snapshot.js +0 -1
  204. package/dist/lib/types/snapshot-views.d.ts +0 -2
  205. package/dist/lib/types/snapshot-views.js +0 -1
  206. package/package.json +2 -1
  207. package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
  208. package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
  209. package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
  210. package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
  211. package/dist/lib/repository/base/BaseRepository.js +0 -226
@@ -39,11 +39,15 @@ const DRIFT_THRESHOLDS = {
39
39
  };
40
40
  /* ────────────────────── Class ────────────────────── */
41
41
  export class ReverseGuard {
42
- #db;
42
+ #knowledgeRepo;
43
+ #entityRepo;
44
+ #sourceRefRepo;
43
45
  #signalBus;
44
46
  #logger = Logger.getInstance();
45
- constructor(db, options = {}) {
46
- this.#db = db;
47
+ constructor(knowledgeRepo, entityRepo, sourceRefRepo, options = {}) {
48
+ this.#knowledgeRepo = knowledgeRepo;
49
+ this.#entityRepo = entityRepo;
50
+ this.#sourceRefRepo = sourceRefRepo;
47
51
  this.#signalBus = options.signalBus ?? null;
48
52
  }
49
53
  /**
@@ -107,20 +111,12 @@ export class ReverseGuard {
107
111
  /* ── 内部方法 ── */
108
112
  #loadActiveRuleRecipes() {
109
113
  try {
110
- const rows = this.#db
111
- .prepare(`SELECT id, title,
112
- json_extract(content, '$.coreCode') AS core_code,
113
- json_extract(content, '$.pattern') AS guard_pattern,
114
- stats
115
- FROM knowledge_entries
116
- WHERE lifecycle = 'active'
117
- AND kind = 'rule'`)
118
- .all();
114
+ const rows = this.#knowledgeRepo.findActiveRulesWithContentSync();
119
115
  return rows.map((r) => ({
120
116
  id: r.id,
121
117
  title: r.title,
122
- core_code: r.core_code ?? null,
123
- guard_pattern: r.guard_pattern ?? null,
118
+ core_code: r.coreCode ?? null,
119
+ guard_pattern: r.guardPattern ?? null,
124
120
  stats: r.stats ?? null,
125
121
  }));
126
122
  }
@@ -139,10 +135,8 @@ export class ReverseGuard {
139
135
  const signals = [];
140
136
  for (const symbol of symbols) {
141
137
  try {
142
- const row = this.#db
143
- .prepare(`SELECT name FROM code_entities WHERE name = ? LIMIT 1`)
144
- .get(symbol);
145
- if (!row) {
138
+ const exists = this.#entityRepo.existsByName(symbol);
139
+ if (!exists) {
146
140
  signals.push({
147
141
  type: 'symbol_missing',
148
142
  detail: `Symbol "${symbol}" referenced in recipe coreCode not found in codebase`,
@@ -212,26 +206,25 @@ export class ReverseGuard {
212
206
  */
213
207
  #checkSourceRefStaleness(recipeId) {
214
208
  try {
215
- const rows = this.#db
216
- .prepare(`SELECT source_path FROM recipe_source_refs WHERE recipe_id = ? AND status = 'stale'`)
217
- .all(recipeId);
218
- if (rows.length === 0) {
209
+ const staleRefs = this.#sourceRefRepo
210
+ .findByRecipeId(recipeId)
211
+ .filter((r) => r.status === 'stale');
212
+ if (staleRefs.length === 0) {
219
213
  return [];
220
214
  }
221
215
  return [
222
216
  {
223
217
  type: 'source_ref_stale',
224
- detail: `${rows.length} source file(s) no longer exist: ${rows
218
+ detail: `${staleRefs.length} source file(s) no longer exist: ${staleRefs
225
219
  .slice(0, 3)
226
- .map((r) => r.source_path)
227
- .join(', ')}${rows.length > 3 ? ` (+${rows.length - 3} more)` : ''}`,
228
- severity: rows.length >= 3 ? 'high' : 'medium',
220
+ .map((r) => r.sourcePath)
221
+ .join(', ')}${staleRefs.length > 3 ? ` (+${staleRefs.length - 3} more)` : ''}`,
222
+ severity: staleRefs.length >= 3 ? 'high' : 'medium',
229
223
  evidence: {},
230
224
  },
231
225
  ];
232
226
  }
233
227
  catch {
234
- // recipe_source_refs 表可能不存在
235
228
  return [];
236
229
  }
237
230
  }
@@ -257,10 +250,7 @@ export class ReverseGuard {
257
250
  }
258
251
  #getHistoricalHits(recipeId) {
259
252
  try {
260
- const row = this.#db
261
- .prepare(`SELECT json_extract(stats, '$.guardHits') AS hits FROM knowledge_entries WHERE id = ?`)
262
- .get(recipeId);
263
- return row?.hits ?? 0;
253
+ return this.#knowledgeRepo.getGuardHitsSync(recipeId);
264
254
  }
265
255
  catch {
266
256
  return 0;
@@ -2,19 +2,15 @@
2
2
  * ViolationsStore — Guard 违反记录存储(DB 版)
3
3
  * 记录每次 as:audit 运行的审计结果,持久化到 SQLite guard_violations 表。
4
4
  * 最多保留 200 条。
5
+ *
6
+ * 所有操作使用 Drizzle 类型安全 API(零 raw SQL)。
5
7
  */
6
8
  import { type DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
7
- interface DatabaseLike {
8
- prepare(sql: string): {
9
- run(...params: unknown[]): unknown;
10
- get(...params: unknown[]): Record<string, unknown>;
11
- all(...params: unknown[]): Record<string, unknown>[];
12
- };
13
- }
14
9
  interface ViolationRecord {
15
10
  ruleId?: string;
16
11
  severity?: string;
17
12
  message?: string;
13
+ line?: number;
18
14
  [key: string]: unknown;
19
15
  }
20
16
  interface RunInput {
@@ -32,27 +28,24 @@ interface RunOutput {
32
28
  }
33
29
  export declare class ViolationsStore {
34
30
  #private;
35
- /** @param db SQLite 数据库实例 */
36
- constructor(db: DatabaseLike, drizzle?: DrizzleDB);
31
+ /** @param _db 保留签名兼容 (不再使用) */
32
+ constructor(_db: unknown, drizzle?: DrizzleDB);
37
33
  /**
38
34
  * 追加一次 Guard 运行记录
39
35
  * ★ 去重:同一文件、同一违规集合不重复入库,仅更新时间戳
40
- * ★ Drizzle 类型安全 INSERT + raw SQL 截断
36
+ * ★ Drizzle 类型安全
41
37
  */
42
38
  appendRun(run: RunInput): string;
43
39
  /**
44
40
  * 获取所有运行记录(最新在后)
45
- * ★ Drizzle 类型安全 SELECT
46
41
  */
47
42
  getRuns(): RunOutput[];
48
43
  /**
49
44
  * 按文件路径查询历史
50
- * ★ Drizzle 类型安全 SELECT WHERE
51
45
  */
52
46
  getRunsByFile(filePath: string): RunOutput[];
53
47
  /**
54
48
  * 获取最近 N 条记录
55
- * ★ Drizzle 类型安全 SELECT + ORDER + LIMIT
56
49
  */
57
50
  getRecentRuns(n?: number): RunOutput[];
58
51
  /** 获取统计汇总 */
@@ -65,12 +58,16 @@ export declare class ViolationsStore {
65
58
  /**
66
59
  * 按规则 ID 聚合统计
67
60
  * 利用 SQLite json_each 展开 violations_json 数组
68
- * @returns >}
61
+ *
62
+ * json_each 是 SQLite 专有函数,Drizzle 无 typed API (ORM limitation)
69
63
  */
70
- getStatsByRule(): Record<string, unknown>[];
64
+ getStatsByRule(): {
65
+ ruleId: string | null;
66
+ severity: string | null;
67
+ count: number;
68
+ }[];
71
69
  /**
72
70
  * 获取趋势数据 — 对比最近两次运行
73
- * @returns }
74
71
  */
75
72
  getTrend(): {
76
73
  errorsChange: number;
@@ -81,10 +78,7 @@ export declare class ViolationsStore {
81
78
  previousWarnings: number;
82
79
  hasHistory: boolean;
83
80
  };
84
- /**
85
- * 清空所有记录
86
- * ★ Drizzle 类型安全 DELETE
87
- */
81
+ /** 清空所有记录 */
88
82
  clearRuns(): void;
89
83
  /** 清除指定规则或文件的记录 */
90
84
  clearAll(): Promise<void>;
@@ -92,7 +86,7 @@ export declare class ViolationsStore {
92
86
  ruleId?: string;
93
87
  file?: string;
94
88
  }): Promise<void>;
95
- /** 兼容 v2 violations.js 路由的 list() */
89
+ /** 分页查询 */
96
90
  list(filters?: {
97
91
  file?: string;
98
92
  }, { page, limit }?: {
@@ -2,24 +2,24 @@
2
2
  * ViolationsStore — Guard 违反记录存储(DB 版)
3
3
  * 记录每次 as:audit 运行的审计结果,持久化到 SQLite guard_violations 表。
4
4
  * 最多保留 200 条。
5
+ *
6
+ * 所有操作使用 Drizzle 类型安全 API(零 raw SQL)。
5
7
  */
6
- import { asc, desc, eq, sql } from 'drizzle-orm';
8
+ import { asc, count, desc, eq, sql } from 'drizzle-orm';
7
9
  import { getDrizzle } from '../../infrastructure/database/drizzle/index.js';
8
10
  import { guardViolations } from '../../infrastructure/database/drizzle/schema.js';
9
11
  const MAX_RUNS = 200;
10
12
  export class ViolationsStore {
11
- #db;
12
13
  #drizzle;
13
- /** @param db SQLite 数据库实例 */
14
- constructor(db, drizzle) {
15
- this.#db = db;
14
+ /** @param _db 保留签名兼容 (不再使用) */
15
+ constructor(_db, drizzle) {
16
16
  this.#drizzle = drizzle ?? getDrizzle();
17
17
  }
18
18
  // ─── 写入 ─────────────────────────────────────────────
19
19
  /**
20
20
  * 追加一次 Guard 运行记录
21
21
  * ★ 去重:同一文件、同一违规集合不重复入库,仅更新时间戳
22
- * ★ Drizzle 类型安全 INSERT + raw SQL 截断
22
+ * ★ Drizzle 类型安全
23
23
  */
24
24
  appendRun(run) {
25
25
  const filePath = run.filePath || '';
@@ -28,16 +28,28 @@ export class ViolationsStore {
28
28
  // ── 去重:查最近一条同文件记录,比较违规指纹 ──
29
29
  const fingerprint = this.#violationFingerprint(violations);
30
30
  if (filePath) {
31
- const lastRow = this.#db
32
- .prepare(`SELECT id, violations_json FROM guard_violations WHERE file_path = ? ORDER BY created_at DESC LIMIT 1`)
33
- .get(filePath);
31
+ const lastRow = this.#drizzle
32
+ .select({
33
+ id: guardViolations.id,
34
+ violationsJson: guardViolations.violationsJson,
35
+ })
36
+ .from(guardViolations)
37
+ .where(eq(guardViolations.filePath, filePath))
38
+ .orderBy(desc(guardViolations.createdAt))
39
+ .limit(1)
40
+ .get();
34
41
  if (lastRow) {
35
- const lastFingerprint = this.#violationFingerprint(JSON.parse(lastRow.violations_json || '[]'));
42
+ const lastFingerprint = this.#violationFingerprint(JSON.parse(lastRow.violationsJson || '[]'));
36
43
  if (fingerprint === lastFingerprint) {
37
44
  // 违规未变化:仅刷新时间戳,不新增行
38
- this.#db
39
- .prepare(`UPDATE guard_violations SET triggered_at = ?, created_at = ? WHERE id = ?`)
40
- .run(new Date().toISOString(), Math.floor(Date.now() / 1000), lastRow.id);
45
+ this.#drizzle
46
+ .update(guardViolations)
47
+ .set({
48
+ triggeredAt: new Date().toISOString(),
49
+ createdAt: Math.floor(Date.now() / 1000),
50
+ })
51
+ .where(eq(guardViolations.id, lastRow.id))
52
+ .run();
41
53
  return lastRow.id;
42
54
  }
43
55
  }
@@ -56,14 +68,15 @@ export class ViolationsStore {
56
68
  createdAt: now,
57
69
  })
58
70
  .run();
59
- // 超限截断:保留最新 MAX_RUNS 条(子查询保留 raw SQL)
60
- this.#db
61
- .prepare(`
62
- DELETE FROM guard_violations WHERE id NOT IN (
63
- SELECT id FROM guard_violations ORDER BY created_at DESC LIMIT ?
64
- )
65
- `)
66
- .run(MAX_RUNS);
71
+ // 超限截断:保留最新 MAX_RUNS
72
+ this.#drizzle
73
+ .delete(guardViolations)
74
+ .where(sql `${guardViolations.id} NOT IN (
75
+ SELECT ${guardViolations.id} FROM ${guardViolations}
76
+ ORDER BY ${guardViolations.createdAt} DESC
77
+ LIMIT ${MAX_RUNS}
78
+ )`)
79
+ .run();
67
80
  return id;
68
81
  }
69
82
  /**
@@ -78,7 +91,6 @@ export class ViolationsStore {
78
91
  // ─── 查询 ─────────────────────────────────────────────
79
92
  /**
80
93
  * 获取所有运行记录(最新在后)
81
- * ★ Drizzle 类型安全 SELECT
82
94
  */
83
95
  getRuns() {
84
96
  const rows = this.#drizzle
@@ -90,7 +102,6 @@ export class ViolationsStore {
90
102
  }
91
103
  /**
92
104
  * 按文件路径查询历史
93
- * ★ Drizzle 类型安全 SELECT WHERE
94
105
  */
95
106
  getRunsByFile(filePath) {
96
107
  const rows = this.#drizzle
@@ -103,7 +114,6 @@ export class ViolationsStore {
103
114
  }
104
115
  /**
105
116
  * 获取最近 N 条记录
106
- * ★ Drizzle 类型安全 SELECT + ORDER + LIMIT
107
117
  */
108
118
  getRecentRuns(n = 20) {
109
119
  const rows = this.#drizzle
@@ -116,41 +126,41 @@ export class ViolationsStore {
116
126
  }
117
127
  /** 获取统计汇总 */
118
128
  getStats() {
119
- const row = this.#db
120
- .prepare(`
121
- SELECT
122
- COUNT(*) AS totalRuns,
123
- COALESCE(SUM(violation_count), 0) AS totalViolations,
124
- MAX(triggered_at) AS lastRunAt
125
- FROM guard_violations
126
- `)
127
- .get();
129
+ const [row] = this.#drizzle
130
+ .select({
131
+ totalRuns: count(),
132
+ totalViolations: sql `COALESCE(SUM(${guardViolations.violationCount}), 0)`,
133
+ lastRunAt: sql `MAX(${guardViolations.triggeredAt})`,
134
+ })
135
+ .from(guardViolations)
136
+ .all();
137
+ const totalRuns = row?.totalRuns ?? 0;
138
+ const totalViolations = row?.totalViolations ?? 0;
128
139
  return {
129
- totalRuns: row.totalRuns,
130
- totalViolations: row.totalViolations,
131
- averageViolationsPerRun: row.totalRuns > 0 ? (row.totalViolations / row.totalRuns).toFixed(2) : 0,
132
- lastRunAt: row.lastRunAt || null,
140
+ totalRuns,
141
+ totalViolations,
142
+ averageViolationsPerRun: totalRuns > 0 ? (totalViolations / totalRuns).toFixed(2) : 0,
143
+ lastRunAt: row?.lastRunAt || null,
133
144
  };
134
145
  }
135
146
  /**
136
147
  * 按规则 ID 聚合统计
137
148
  * 利用 SQLite json_each 展开 violations_json 数组
138
- * @returns >}
149
+ *
150
+ * json_each 是 SQLite 专有函数,Drizzle 无 typed API (ORM limitation)
139
151
  */
140
152
  getStatsByRule() {
141
153
  try {
142
- return this.#db
143
- .prepare(`
154
+ return this.#drizzle.all(sql `
144
155
  SELECT
145
156
  json_extract(j.value, '$.ruleId') AS ruleId,
146
157
  json_extract(j.value, '$.severity') AS severity,
147
158
  COUNT(*) AS count
148
- FROM guard_violations gv, json_each(gv.violations_json) j
159
+ FROM ${guardViolations} gv, json_each(gv.violations_json) j
149
160
  WHERE json_extract(j.value, '$.ruleId') IS NOT NULL
150
161
  GROUP BY ruleId, severity
151
162
  ORDER BY count DESC
152
- `)
153
- .all();
163
+ `);
154
164
  }
155
165
  catch {
156
166
  return [];
@@ -158,7 +168,6 @@ export class ViolationsStore {
158
168
  }
159
169
  /**
160
170
  * 获取趋势数据 — 对比最近两次运行
161
- * @returns }
162
171
  */
163
172
  getTrend() {
164
173
  const recent = this.getRecentRuns(2);
@@ -190,10 +199,7 @@ export class ViolationsStore {
190
199
  };
191
200
  }
192
201
  // ─── 清除 ─────────────────────────────────────────────
193
- /**
194
- * 清空所有记录
195
- * ★ Drizzle 类型安全 DELETE
196
- */
202
+ /** 清空所有记录 */
197
203
  clearRuns() {
198
204
  this.#drizzle.delete(guardViolations).run();
199
205
  }
@@ -209,38 +215,38 @@ export class ViolationsStore {
209
215
  this.clearRuns();
210
216
  }
211
217
  }
212
- /** 兼容 v2 violations.js 路由的 list() */
218
+ /** 分页查询 */
213
219
  async list(filters = {}, { page = 1, limit = 20 } = {}) {
214
220
  const offset = (page - 1) * limit;
215
- let sql = 'SELECT * FROM guard_violations';
216
- const params = [];
217
- if (filters.file) {
218
- sql += ' WHERE file_path = ?';
219
- params.push(filters.file);
220
- }
221
- sql += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
222
- params.push(limit, offset);
223
- const rows = this.#db.prepare(sql).all(...params);
224
- const countSql = filters.file
225
- ? 'SELECT COUNT(*) AS c FROM guard_violations WHERE file_path = ?'
226
- : 'SELECT COUNT(*) AS c FROM guard_violations';
227
- const countParams = filters.file ? [filters.file] : [];
228
- const total = this.#db.prepare(countSql).get(...countParams).c;
221
+ const condition = filters.file ? eq(guardViolations.filePath, filters.file) : undefined;
222
+ const rows = this.#drizzle
223
+ .select()
224
+ .from(guardViolations)
225
+ .where(condition)
226
+ .orderBy(desc(guardViolations.createdAt))
227
+ .limit(limit)
228
+ .offset(offset)
229
+ .all();
230
+ const [totalRow] = this.#drizzle
231
+ .select({ c: count() })
232
+ .from(guardViolations)
233
+ .where(condition)
234
+ .all();
235
+ const total = totalRow?.c ?? 0;
229
236
  return {
230
237
  data: rows.map((r) => this.#rowToRun(r)),
231
238
  pagination: { page, limit, total, pages: Math.ceil(total / limit) },
232
239
  };
233
240
  }
234
241
  // ─── 内部 ─────────────────────────────────────────────
235
- /** 行转运行记录(兼容 raw SQL snake_case Drizzle camelCase) */
242
+ /** Drizzle camelCase RunOutput */
236
243
  #rowToRun(row) {
237
- const violationsRaw = (row.violationsJson ?? row.violations_json);
238
244
  return {
239
245
  id: row.id,
240
- filePath: (row.filePath ?? row.file_path),
241
- triggeredAt: (row.triggeredAt ?? row.triggered_at),
242
- violations: violationsRaw ? JSON.parse(violationsRaw) : [],
243
- violationCount: (row.violationCount ?? row.violation_count),
246
+ filePath: row.filePath,
247
+ triggeredAt: row.triggeredAt,
248
+ violations: row.violationsJson ? JSON.parse(row.violationsJson) : [],
249
+ violationCount: row.violationCount ?? 0,
244
250
  summary: row.summary || '',
245
251
  };
246
252
  }