autosnippet 3.3.7 → 3.3.9

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 (218) hide show
  1. package/README.md +1 -0
  2. package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
  3. package/dashboard/dist/assets/index-DEU4tJtP.js +112 -0
  4. package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -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 +8 -2
  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/cli/SetupService.js +5 -4
  31. package/dist/lib/core/ast/ProjectGraph.js +5 -27
  32. package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
  33. package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
  34. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
  35. package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
  36. package/dist/lib/domain/dimension/DimensionSop.js +44 -33
  37. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
  38. package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
  39. package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
  40. package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
  41. package/dist/lib/domain/knowledge/index.d.ts +2 -1
  42. package/dist/lib/domain/knowledge/index.js +1 -1
  43. package/dist/lib/external/mcp/McpServer.js +19 -2
  44. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
  45. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
  46. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +10 -29
  47. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
  48. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
  49. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
  50. package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
  51. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
  52. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
  53. package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
  54. package/dist/lib/external/mcp/handlers/guard.js +15 -24
  55. package/dist/lib/external/mcp/handlers/panorama.js +9 -9
  56. package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
  57. package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
  58. package/dist/lib/external/mcp/handlers/search.js +3 -1
  59. package/dist/lib/external/mcp/handlers/skill.js +4 -4
  60. package/dist/lib/external/mcp/handlers/structure.js +8 -12
  61. package/dist/lib/external/mcp/handlers/system.js +10 -34
  62. package/dist/lib/http/routes/ai.js +11 -13
  63. package/dist/lib/http/routes/guardReport.js +3 -5
  64. package/dist/lib/http/routes/panorama.js +12 -12
  65. package/dist/lib/http/routes/recipes.js +59 -8
  66. package/dist/lib/http/routes/remote.js +3 -13
  67. package/dist/lib/http/routes/search.js +11 -8
  68. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
  69. package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
  70. package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
  71. package/dist/lib/infrastructure/database/DatabaseConnection.js +7 -6
  72. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
  73. package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
  74. package/dist/lib/injection/ServiceContainer.js +7 -4
  75. package/dist/lib/injection/ServiceMap.d.ts +20 -0
  76. package/dist/lib/injection/modules/AppModule.js +2 -1
  77. package/dist/lib/injection/modules/GuardModule.js +5 -5
  78. package/dist/lib/injection/modules/InfraModule.js +60 -0
  79. package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
  80. package/dist/lib/injection/modules/PanoramaModule.js +16 -10
  81. package/dist/lib/injection/modules/VectorModule.js +3 -0
  82. package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
  83. package/dist/lib/repository/audit/AuditRepository.js +272 -0
  84. package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
  85. package/dist/lib/repository/base/RepositoryBase.js +32 -0
  86. package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
  87. package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
  88. package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
  89. package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
  90. package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
  91. package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
  92. package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
  93. package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
  94. package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
  95. package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
  96. package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
  97. package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
  98. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
  99. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
  100. package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
  101. package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
  102. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
  103. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
  104. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
  105. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
  106. package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
  107. package/dist/lib/repository/memory/MemoryRepository.js +260 -0
  108. package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
  109. package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
  110. package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
  111. package/dist/lib/repository/session/SessionRepository.js +110 -0
  112. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
  113. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
  114. package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
  115. package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
  116. package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
  117. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
  118. package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
  119. package/dist/lib/service/cleanup/CleanupService.js +8 -4
  120. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +21 -9
  121. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
  122. package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
  123. package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
  124. package/dist/lib/service/evolution/ContentPatcher.js +48 -19
  125. package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
  126. package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
  127. package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
  128. package/dist/lib/service/evolution/DecayDetector.js +63 -57
  129. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
  130. package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
  131. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
  132. package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
  133. package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
  134. package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
  135. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
  136. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
  137. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
  138. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
  139. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
  140. package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
  141. package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
  142. package/dist/lib/service/evolution/StagingManager.js +37 -95
  143. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
  144. package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
  145. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
  146. package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
  147. package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
  148. package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
  149. package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
  150. package/dist/lib/service/guard/ReverseGuard.js +21 -31
  151. package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
  152. package/dist/lib/service/guard/ViolationsStore.js +75 -69
  153. package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
  154. package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
  155. package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
  156. package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
  157. package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
  158. package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
  159. package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
  160. package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
  161. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
  162. package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
  163. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
  164. package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
  165. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
  166. package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
  167. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
  168. package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
  169. package/dist/lib/service/panorama/LayerInferrer.js +1 -1
  170. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
  171. package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
  172. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
  173. package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
  174. package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
  175. package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
  176. package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
  177. package/dist/lib/service/panorama/PanoramaService.js +41 -66
  178. package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
  179. package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
  180. package/dist/lib/service/panorama/RoleRefiner.js +52 -283
  181. package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
  182. package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
  183. package/dist/lib/service/quality/QualityScorer.js +157 -83
  184. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  185. package/dist/lib/service/search/SearchEngine.js +32 -37
  186. package/dist/lib/service/signal/HitRecorder.js +5 -5
  187. package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
  188. package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
  189. package/dist/lib/service/skills/SignalCollector.js +28 -55
  190. package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
  191. package/dist/lib/service/skills/SkillAdvisor.js +30 -79
  192. package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
  193. package/dist/lib/service/vector/SyncCoordinator.js +25 -3
  194. package/dist/lib/service/vector/VectorService.d.ts +2 -0
  195. package/dist/lib/service/vector/VectorService.js +3 -0
  196. package/dist/lib/service/wiki/WikiGenerator.js +1 -1
  197. package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
  198. package/dist/lib/shared/LanguageProfiles.js +939 -0
  199. package/dist/lib/shared/LanguageService.d.ts +6 -0
  200. package/dist/lib/shared/LanguageService.js +16 -0
  201. package/dist/lib/shared/PathGuard.js +16 -10
  202. package/dist/lib/shared/constants.d.ts +19 -19
  203. package/dist/lib/shared/constants.js +10 -10
  204. package/dist/lib/shared/isOwnDevRepo.d.ts +29 -4
  205. package/dist/lib/shared/isOwnDevRepo.js +64 -4
  206. package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
  207. package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
  208. package/dist/lib/types/project-snapshot-builder.js +0 -1
  209. package/dist/lib/types/project-snapshot.d.ts +0 -1
  210. package/dist/lib/types/project-snapshot.js +0 -1
  211. package/dist/lib/types/snapshot-views.d.ts +0 -2
  212. package/dist/lib/types/snapshot-views.js +0 -1
  213. package/package.json +2 -1
  214. package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
  215. package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
  216. package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
  217. package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
  218. package/dist/lib/repository/base/BaseRepository.js +0 -226
@@ -0,0 +1,91 @@
1
+ /**
2
+ * CodeEntityRepository — AST 代码实体的仓储实现
3
+ *
4
+ * 从 CodeEntityGraph 和 PanoramaScanner 提取的数据操作,
5
+ * 使用 Drizzle 类型安全 API。
6
+ */
7
+ import { codeEntities } from '../../infrastructure/database/drizzle/schema.js';
8
+ import { RepositoryBase } from '../base/RepositoryBase.js';
9
+ export interface CodeEntity {
10
+ id: number;
11
+ entityId: string;
12
+ entityType: string;
13
+ projectRoot: string;
14
+ name: string;
15
+ filePath: string | null;
16
+ lineNumber: number | null;
17
+ superclass: string | null;
18
+ protocols: string[];
19
+ metadata: Record<string, unknown>;
20
+ createdAt: number;
21
+ updatedAt: number;
22
+ }
23
+ export interface CodeEntityInsert {
24
+ entityId: string;
25
+ entityType: string;
26
+ projectRoot: string;
27
+ name: string;
28
+ filePath?: string | null;
29
+ lineNumber?: number | null;
30
+ superclass?: string | null;
31
+ protocols?: string[];
32
+ metadata?: Record<string, unknown>;
33
+ }
34
+ export declare class CodeEntityRepositoryImpl extends RepositoryBase<typeof codeEntities, CodeEntity> {
35
+ #private;
36
+ constructor(drizzle: ConstructorParameters<typeof RepositoryBase<typeof codeEntities, CodeEntity>>[0]);
37
+ findById(id: number): Promise<CodeEntity | null>;
38
+ create(data: CodeEntityInsert): Promise<CodeEntity>;
39
+ delete(id: number): Promise<boolean>;
40
+ /** UPSERT — 按 (entityId, entityType, projectRoot) 唯一约束 */
41
+ upsert(entity: CodeEntityInsert): Promise<CodeEntity>;
42
+ /** 批量 UPSERT */
43
+ batchUpsert(entities: CodeEntityInsert[]): Promise<number>;
44
+ /** 按文件路径查询 */
45
+ findByFile(filePath: string, projectRoot: string): Promise<CodeEntity[]>;
46
+ /** 按实体类型列表 */
47
+ listByType(entityType: string, projectRoot: string, limit?: number): Promise<CodeEntity[]>;
48
+ /** 按名称搜索 */
49
+ searchByName(query: string, projectRoot: string, options?: {
50
+ entityType?: string;
51
+ limit?: number;
52
+ }): Promise<CodeEntity[]>;
53
+ /** 按 entityId + entityType + projectRoot 精确查找 */
54
+ findByEntityId(entityId: string, entityType: string, projectRoot: string): Promise<CodeEntity | null>;
55
+ /** 删除指定项目的所有实体 */
56
+ clearProject(projectRoot: string): Promise<number>;
57
+ /** 删除指定文件的实体(用于增量更新调用图) */
58
+ deleteByFile(filePath: string, projectRoot: string): Promise<number>;
59
+ /** 获取实体总数 */
60
+ getEntityCount(projectRoot?: string): Promise<number>;
61
+ /** 按类型统计实体数 */
62
+ countByType(projectRoot: string): Promise<Record<string, number>>;
63
+ /** 按文件路径和实体类型删除 */
64
+ deleteByFileAndType(filePath: string, entityType: string, projectRoot: string): Promise<number>;
65
+ /** 按 entityId + projectRoot 查找(不限 entityType) */
66
+ findByEntityIdOnly(entityId: string, projectRoot: string): Promise<CodeEntity | null>;
67
+ /** 查询非 module 实体的 (entityId, filePath) 去重列表 */
68
+ findDistinctEntityIdsWithFilePath(projectRoot: string): Promise<Array<{
69
+ entityId: string;
70
+ filePath: string;
71
+ }>>;
72
+ /** 查询本地模块 (排除 external/host nodeType) */
73
+ findLocalModules(projectRoot: string): Promise<Array<{
74
+ entityId: string;
75
+ name: string;
76
+ }>>;
77
+ /** 查询指定 nodeType 的模块实体 */
78
+ findModulesByNodeTypes(projectRoot: string, nodeTypes: string[]): Promise<CodeEntity[]>;
79
+ /** 统计指定 nodeType 的模块数量 */
80
+ countModulesByNodeType(projectRoot: string, nodeType: string): Promise<number>;
81
+ /** 按 projectRoot + filePaths 批量查询实体 */
82
+ findByProjectAndFilePaths(projectRoot: string, filePaths: string[]): Promise<CodeEntity[]>;
83
+ /** 查询非 module 实体的去重文件路径列表 */
84
+ findDistinctFilePaths(projectRoot: string, limit?: number): Promise<string[]>;
85
+ /** 批量 INSERT OR IGNORE (不更新已存在的行) */
86
+ batchInsertIgnore(entities: CodeEntityInsert[]): Promise<number>;
87
+ /**
88
+ * 符号名是否存在 (ReverseGuard.#symbolExists)
89
+ */
90
+ existsByName(name: string): boolean;
91
+ }
@@ -0,0 +1,361 @@
1
+ /**
2
+ * CodeEntityRepository — AST 代码实体的仓储实现
3
+ *
4
+ * 从 CodeEntityGraph 和 PanoramaScanner 提取的数据操作,
5
+ * 使用 Drizzle 类型安全 API。
6
+ */
7
+ import { and, count, eq, inArray, isNotNull, like, ne, sql } from 'drizzle-orm';
8
+ import { codeEntities } from '../../infrastructure/database/drizzle/schema.js';
9
+ import { unixNow } from '../../shared/utils/common.js';
10
+ import { RepositoryBase } from '../base/RepositoryBase.js';
11
+ /* ═══ Repository 实现 ═══ */
12
+ export class CodeEntityRepositoryImpl extends RepositoryBase {
13
+ constructor(drizzle) {
14
+ super(drizzle, codeEntities);
15
+ }
16
+ /* ─── CRUD ─── */
17
+ async findById(id) {
18
+ const rows = this.drizzle.select().from(this.table).where(eq(this.table.id, id)).limit(1).all();
19
+ return rows.length > 0 ? this.#mapRow(rows[0]) : null;
20
+ }
21
+ async create(data) {
22
+ return this.upsert(data);
23
+ }
24
+ async delete(id) {
25
+ const result = this.drizzle.delete(this.table).where(eq(this.table.id, id)).run();
26
+ return result.changes > 0;
27
+ }
28
+ /* ─── 核心操作 ─── */
29
+ /** UPSERT — 按 (entityId, entityType, projectRoot) 唯一约束 */
30
+ async upsert(entity) {
31
+ const now = unixNow();
32
+ const protocolsJson = JSON.stringify(entity.protocols ?? []);
33
+ const metaJson = JSON.stringify(entity.metadata ?? {});
34
+ this.drizzle
35
+ .insert(this.table)
36
+ .values({
37
+ entityId: entity.entityId,
38
+ entityType: entity.entityType,
39
+ projectRoot: entity.projectRoot,
40
+ name: entity.name,
41
+ filePath: entity.filePath ?? null,
42
+ lineNumber: entity.lineNumber ?? null,
43
+ superclass: entity.superclass ?? null,
44
+ protocols: protocolsJson,
45
+ metadataJson: metaJson,
46
+ createdAt: now,
47
+ updatedAt: now,
48
+ })
49
+ .onConflictDoUpdate({
50
+ target: [this.table.entityId, this.table.entityType, this.table.projectRoot],
51
+ set: {
52
+ name: entity.name,
53
+ filePath: sql `${entity.filePath ?? null}`,
54
+ lineNumber: sql `${entity.lineNumber ?? null}`,
55
+ superclass: sql `${entity.superclass ?? null}`,
56
+ protocols: protocolsJson,
57
+ metadataJson: metaJson,
58
+ updatedAt: now,
59
+ },
60
+ })
61
+ .run();
62
+ // 返回 upserted 行
63
+ const rows = this.drizzle
64
+ .select()
65
+ .from(this.table)
66
+ .where(and(eq(this.table.entityId, entity.entityId), eq(this.table.entityType, entity.entityType), eq(this.table.projectRoot, entity.projectRoot)))
67
+ .limit(1)
68
+ .all();
69
+ return this.#mapRow(rows[0]);
70
+ }
71
+ /** 批量 UPSERT */
72
+ async batchUpsert(entities) {
73
+ if (entities.length === 0) {
74
+ return 0;
75
+ }
76
+ let upserted = 0;
77
+ this.transaction((tx) => {
78
+ const now = unixNow();
79
+ for (const entity of entities) {
80
+ tx.insert(this.table)
81
+ .values({
82
+ entityId: entity.entityId,
83
+ entityType: entity.entityType,
84
+ projectRoot: entity.projectRoot,
85
+ name: entity.name,
86
+ filePath: entity.filePath ?? null,
87
+ lineNumber: entity.lineNumber ?? null,
88
+ superclass: entity.superclass ?? null,
89
+ protocols: JSON.stringify(entity.protocols ?? []),
90
+ metadataJson: JSON.stringify(entity.metadata ?? {}),
91
+ createdAt: now,
92
+ updatedAt: now,
93
+ })
94
+ .onConflictDoUpdate({
95
+ target: [this.table.entityId, this.table.entityType, this.table.projectRoot],
96
+ set: {
97
+ name: entity.name,
98
+ filePath: sql `${entity.filePath ?? null}`,
99
+ lineNumber: sql `${entity.lineNumber ?? null}`,
100
+ superclass: sql `${entity.superclass ?? null}`,
101
+ protocols: JSON.stringify(entity.protocols ?? []),
102
+ metadataJson: JSON.stringify(entity.metadata ?? {}),
103
+ updatedAt: now,
104
+ },
105
+ })
106
+ .run();
107
+ upserted++;
108
+ }
109
+ });
110
+ return upserted;
111
+ }
112
+ /* ─── 查询 ─── */
113
+ /** 按文件路径查询 */
114
+ async findByFile(filePath, projectRoot) {
115
+ const rows = this.drizzle
116
+ .select()
117
+ .from(this.table)
118
+ .where(and(eq(this.table.filePath, filePath), eq(this.table.projectRoot, projectRoot)))
119
+ .all();
120
+ return rows.map((r) => this.#mapRow(r));
121
+ }
122
+ /** 按实体类型列表 */
123
+ async listByType(entityType, projectRoot, limit = 100) {
124
+ const rows = this.drizzle
125
+ .select()
126
+ .from(this.table)
127
+ .where(and(eq(this.table.entityType, entityType), eq(this.table.projectRoot, projectRoot)))
128
+ .orderBy(this.table.name)
129
+ .limit(limit)
130
+ .all();
131
+ return rows.map((r) => this.#mapRow(r));
132
+ }
133
+ /** 按名称搜索 */
134
+ async searchByName(query, projectRoot, options = {}) {
135
+ const { entityType, limit = 50 } = options;
136
+ const conditions = [
137
+ eq(this.table.projectRoot, projectRoot),
138
+ like(this.table.name, `%${query}%`),
139
+ ];
140
+ if (entityType) {
141
+ conditions.push(eq(this.table.entityType, entityType));
142
+ }
143
+ const rows = this.drizzle
144
+ .select()
145
+ .from(this.table)
146
+ .where(and(...conditions))
147
+ .orderBy(this.table.name)
148
+ .limit(limit)
149
+ .all();
150
+ return rows.map((r) => this.#mapRow(r));
151
+ }
152
+ /** 按 entityId + entityType + projectRoot 精确查找 */
153
+ async findByEntityId(entityId, entityType, projectRoot) {
154
+ const rows = this.drizzle
155
+ .select()
156
+ .from(this.table)
157
+ .where(and(eq(this.table.entityId, entityId), eq(this.table.entityType, entityType), eq(this.table.projectRoot, projectRoot)))
158
+ .limit(1)
159
+ .all();
160
+ return rows.length > 0 ? this.#mapRow(rows[0]) : null;
161
+ }
162
+ /** 删除指定项目的所有实体 */
163
+ async clearProject(projectRoot) {
164
+ const result = this.drizzle
165
+ .delete(this.table)
166
+ .where(eq(this.table.projectRoot, projectRoot))
167
+ .run();
168
+ return result.changes;
169
+ }
170
+ /** 删除指定文件的实体(用于增量更新调用图) */
171
+ async deleteByFile(filePath, projectRoot) {
172
+ const result = this.drizzle
173
+ .delete(this.table)
174
+ .where(and(eq(this.table.filePath, filePath), eq(this.table.projectRoot, projectRoot)))
175
+ .run();
176
+ return result.changes;
177
+ }
178
+ /** 获取实体总数 */
179
+ async getEntityCount(projectRoot) {
180
+ const condition = projectRoot ? eq(this.table.projectRoot, projectRoot) : undefined;
181
+ const [row] = this.drizzle.select({ cnt: count() }).from(this.table).where(condition).all();
182
+ return row?.cnt ?? 0;
183
+ }
184
+ /** 按类型统计实体数 */
185
+ async countByType(projectRoot) {
186
+ const rows = this.drizzle
187
+ .select({
188
+ entityType: this.table.entityType,
189
+ cnt: count(),
190
+ })
191
+ .from(this.table)
192
+ .where(eq(this.table.projectRoot, projectRoot))
193
+ .groupBy(this.table.entityType)
194
+ .all();
195
+ const result = {};
196
+ for (const row of rows) {
197
+ result[row.entityType] = row.cnt;
198
+ }
199
+ return result;
200
+ }
201
+ /** 按文件路径和实体类型删除 */
202
+ async deleteByFileAndType(filePath, entityType, projectRoot) {
203
+ const result = this.drizzle
204
+ .delete(this.table)
205
+ .where(and(eq(this.table.filePath, filePath), eq(this.table.entityType, entityType), eq(this.table.projectRoot, projectRoot)))
206
+ .run();
207
+ return result.changes;
208
+ }
209
+ /** 按 entityId + projectRoot 查找(不限 entityType) */
210
+ async findByEntityIdOnly(entityId, projectRoot) {
211
+ const rows = this.drizzle
212
+ .select()
213
+ .from(this.table)
214
+ .where(and(eq(this.table.entityId, entityId), eq(this.table.projectRoot, projectRoot)))
215
+ .limit(1)
216
+ .all();
217
+ return rows.length > 0 ? this.#mapRow(rows[0]) : null;
218
+ }
219
+ /* ─── Panorama 域查询 (Phase 5e) ─── */
220
+ /** 查询非 module 实体的 (entityId, filePath) 去重列表 */
221
+ async findDistinctEntityIdsWithFilePath(projectRoot) {
222
+ const rows = this.drizzle
223
+ .selectDistinct({
224
+ entityId: this.table.entityId,
225
+ filePath: this.table.filePath,
226
+ })
227
+ .from(this.table)
228
+ .where(and(eq(this.table.projectRoot, projectRoot), isNotNull(this.table.filePath), ne(this.table.entityType, 'module')))
229
+ .all();
230
+ return rows.filter((r) => r.filePath !== null);
231
+ }
232
+ /** 查询本地模块 (排除 external/host nodeType) */
233
+ async findLocalModules(projectRoot) {
234
+ const rows = this.drizzle
235
+ .selectDistinct({
236
+ entityId: this.table.entityId,
237
+ name: this.table.name,
238
+ })
239
+ .from(this.table)
240
+ .where(and(eq(this.table.entityType, 'module'), eq(this.table.projectRoot, projectRoot), sql `COALESCE(json_extract(${this.table.metadataJson}, '$.nodeType'), 'local') NOT IN ('external', 'host')`))
241
+ .all();
242
+ return rows;
243
+ }
244
+ /** 查询指定 nodeType 的模块实体 */
245
+ async findModulesByNodeTypes(projectRoot, nodeTypes) {
246
+ if (nodeTypes.length === 0) {
247
+ return [];
248
+ }
249
+ const placeholders = nodeTypes.map((t) => `'${t.replace(/'/g, "''")}'`).join(', ');
250
+ const rows = this.drizzle
251
+ .select()
252
+ .from(this.table)
253
+ .where(and(eq(this.table.entityType, 'module'), eq(this.table.projectRoot, projectRoot), sql `json_extract(${this.table.metadataJson}, '$.nodeType') IN (${sql.raw(placeholders)})`))
254
+ .all();
255
+ return rows.map((r) => this.#mapRow(r));
256
+ }
257
+ /** 统计指定 nodeType 的模块数量 */
258
+ async countModulesByNodeType(projectRoot, nodeType) {
259
+ const [row] = this.drizzle
260
+ .select({ cnt: count() })
261
+ .from(this.table)
262
+ .where(and(eq(this.table.entityType, 'module'), eq(this.table.projectRoot, projectRoot), sql `json_extract(${this.table.metadataJson}, '$.nodeType') = ${nodeType}`))
263
+ .all();
264
+ return row?.cnt ?? 0;
265
+ }
266
+ /** 按 projectRoot + filePaths 批量查询实体 */
267
+ async findByProjectAndFilePaths(projectRoot, filePaths) {
268
+ if (filePaths.length === 0) {
269
+ return [];
270
+ }
271
+ const rows = this.drizzle
272
+ .select()
273
+ .from(this.table)
274
+ .where(and(eq(this.table.projectRoot, projectRoot), inArray(this.table.filePath, filePaths)))
275
+ .all();
276
+ return rows.map((r) => this.#mapRow(r));
277
+ }
278
+ /** 查询非 module 实体的去重文件路径列表 */
279
+ async findDistinctFilePaths(projectRoot, limit = 2000) {
280
+ const rows = this.drizzle
281
+ .selectDistinct({ filePath: this.table.filePath })
282
+ .from(this.table)
283
+ .where(and(eq(this.table.projectRoot, projectRoot), isNotNull(this.table.filePath), ne(this.table.entityType, 'module')))
284
+ .limit(limit)
285
+ .all();
286
+ return rows.filter((r) => r.filePath !== null).map((r) => r.filePath);
287
+ }
288
+ /** 批量 INSERT OR IGNORE (不更新已存在的行) */
289
+ async batchInsertIgnore(entities) {
290
+ if (entities.length === 0) {
291
+ return 0;
292
+ }
293
+ let inserted = 0;
294
+ const now = unixNow();
295
+ this.transaction((tx) => {
296
+ for (const entity of entities) {
297
+ tx.insert(this.table)
298
+ .values({
299
+ entityId: entity.entityId,
300
+ entityType: entity.entityType,
301
+ projectRoot: entity.projectRoot,
302
+ name: entity.name,
303
+ filePath: entity.filePath ?? null,
304
+ lineNumber: entity.lineNumber ?? null,
305
+ superclass: entity.superclass ?? null,
306
+ protocols: JSON.stringify(entity.protocols ?? []),
307
+ metadataJson: JSON.stringify(entity.metadata ?? {}),
308
+ createdAt: now,
309
+ updatedAt: now,
310
+ })
311
+ .onConflictDoNothing()
312
+ .run();
313
+ inserted++;
314
+ }
315
+ });
316
+ return inserted;
317
+ }
318
+ /**
319
+ * 符号名是否存在 (ReverseGuard.#symbolExists)
320
+ */
321
+ existsByName(name) {
322
+ const row = this.drizzle
323
+ .select({ name: this.table.name })
324
+ .from(this.table)
325
+ .where(eq(this.table.name, name))
326
+ .limit(1)
327
+ .get();
328
+ return row != null;
329
+ }
330
+ /* ─── 内部辅助 ─── */
331
+ #mapRow(row) {
332
+ let protocols = [];
333
+ let metadata = {};
334
+ try {
335
+ protocols = JSON.parse(row.protocols ?? '[]');
336
+ }
337
+ catch {
338
+ /* ignore */
339
+ }
340
+ try {
341
+ metadata = JSON.parse(row.metadataJson ?? '{}');
342
+ }
343
+ catch {
344
+ /* ignore */
345
+ }
346
+ return {
347
+ id: row.id,
348
+ entityId: row.entityId,
349
+ entityType: row.entityType,
350
+ projectRoot: row.projectRoot,
351
+ name: row.name,
352
+ filePath: row.filePath,
353
+ lineNumber: row.lineNumber,
354
+ superclass: row.superclass,
355
+ protocols,
356
+ metadata,
357
+ createdAt: row.createdAt,
358
+ updatedAt: row.updatedAt,
359
+ };
360
+ }
361
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * DeliveryRepoAdapter — CursorDeliveryPipeline 用的仓储适配器
3
+ *
4
+ * 将 call graph 分析中的 raw SQL 查询封装在 lib/repository/ 层。
5
+ */
6
+ type RawDb = {
7
+ prepare(sql: string): {
8
+ all(...args: unknown[]): Array<Record<string, unknown>>;
9
+ };
10
+ };
11
+ /** CursorDeliveryPipeline call graph 分析所需的最小接口 */
12
+ export interface CallGraphRepo {
13
+ /** 查询 phase5 调用边 */
14
+ findCallEdges(): Array<{
15
+ from_id: string;
16
+ to_id: string;
17
+ metadata_json: string;
18
+ }>;
19
+ /** 查询方法级代码实体的 entity_id + file_path */
20
+ findMethodEntities(): Array<{
21
+ entity_id: string;
22
+ file_path: string;
23
+ }>;
24
+ }
25
+ /** Raw-db 适配器:实现 CallGraphRepo 接口 */
26
+ export declare class RawDbCallGraphAdapter implements CallGraphRepo {
27
+ #private;
28
+ constructor(db: RawDb);
29
+ findCallEdges(): Array<{
30
+ from_id: string;
31
+ to_id: string;
32
+ metadata_json: string;
33
+ }>;
34
+ findMethodEntities(): Array<{
35
+ entity_id: string;
36
+ file_path: string;
37
+ }>;
38
+ }
39
+ export {};
@@ -0,0 +1,23 @@
1
+ /**
2
+ * DeliveryRepoAdapter — CursorDeliveryPipeline 用的仓储适配器
3
+ *
4
+ * 将 call graph 分析中的 raw SQL 查询封装在 lib/repository/ 层。
5
+ */
6
+ /** Raw-db 适配器:实现 CallGraphRepo 接口 */
7
+ export class RawDbCallGraphAdapter {
8
+ #db;
9
+ constructor(db) {
10
+ this.#db = db;
11
+ }
12
+ findCallEdges() {
13
+ return this.#db
14
+ .prepare(`SELECT from_id, to_id, metadata_json FROM knowledge_edges
15
+ WHERE relation = 'calls' AND metadata_json LIKE '%phase5%'`)
16
+ .all();
17
+ }
18
+ findMethodEntities() {
19
+ return this.#db
20
+ .prepare(`SELECT entity_id, file_path FROM code_entities WHERE entity_type = 'method'`)
21
+ .all();
22
+ }
23
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * LifecycleEventRepository — lifecycle_transition_events 表 CRUD (Drizzle ORM)
3
+ *
4
+ * 操作 lifecycle_transition_events 表,存储 Recipe 生命周期状态转移事件。
5
+ *
6
+ * Drizzle 迁移策略:
7
+ * - 替代 RecipeLifecycleSupervisor 中的所有 rawDb.prepare() 调用
8
+ * - 消除 12 个 escape-hatch 注解
9
+ */
10
+ import type { DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
11
+ import type { TransitionEvent, TransitionEvidence } from '../../types/evolution.js';
12
+ export interface RecordEventInput {
13
+ id: string;
14
+ recipeId: string;
15
+ fromState: string;
16
+ toState: string;
17
+ trigger: string;
18
+ operatorId: string;
19
+ evidence: TransitionEvidence | null;
20
+ proposalId: string | null;
21
+ createdAt: number;
22
+ }
23
+ export interface TransitionEventRow {
24
+ id: string;
25
+ recipeId: string;
26
+ fromState: string;
27
+ toState: string;
28
+ trigger: TransitionEvent['trigger'];
29
+ operatorId: string;
30
+ evidence: TransitionEvidence | null;
31
+ proposalId: string | null;
32
+ createdAt: number;
33
+ }
34
+ export declare class LifecycleEventRepository {
35
+ #private;
36
+ constructor(drizzle: DrizzleDB);
37
+ record(input: RecordEventInput): void;
38
+ /** 获取指定 Recipe 的转移历史(按时间倒序) */
39
+ getHistory(recipeId: string, limit?: number): TransitionEvent[];
40
+ /** 统计指定时间之后的事件数量 */
41
+ countSince(since: number): number;
42
+ /** 按 trigger 分组统计(限定时间窗口,按数量倒序前 N) */
43
+ topTriggersSince(since: number, limit?: number): {
44
+ trigger: string;
45
+ count: number;
46
+ }[];
47
+ /** 按 trigger 值统计数量 */
48
+ countByTrigger(trigger: string): number;
49
+ /** 按多个 trigger 值统计数量 */
50
+ countByTriggers(triggers: string[]): number;
51
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * LifecycleEventRepository — lifecycle_transition_events 表 CRUD (Drizzle ORM)
3
+ *
4
+ * 操作 lifecycle_transition_events 表,存储 Recipe 生命周期状态转移事件。
5
+ *
6
+ * Drizzle 迁移策略:
7
+ * - 替代 RecipeLifecycleSupervisor 中的所有 rawDb.prepare() 调用
8
+ * - 消除 12 个 escape-hatch 注解
9
+ */
10
+ import { count, desc, eq, gt, sql } from 'drizzle-orm';
11
+ import { lifecycleTransitionEvents } from '../../infrastructure/database/drizzle/schema.js';
12
+ /* ────────────────────── Class ────────────────────── */
13
+ export class LifecycleEventRepository {
14
+ #drizzle;
15
+ constructor(drizzle) {
16
+ this.#drizzle = drizzle;
17
+ }
18
+ /* ═══════════════════ Write ═══════════════════ */
19
+ record(input) {
20
+ this.#drizzle
21
+ .insert(lifecycleTransitionEvents)
22
+ .values({
23
+ id: input.id,
24
+ recipeId: input.recipeId,
25
+ fromState: input.fromState,
26
+ toState: input.toState,
27
+ trigger: input.trigger,
28
+ operatorId: input.operatorId,
29
+ evidenceJson: input.evidence ? JSON.stringify(input.evidence) : null,
30
+ proposalId: input.proposalId,
31
+ createdAt: input.createdAt,
32
+ })
33
+ .run();
34
+ }
35
+ /* ═══════════════════ Read ═══════════════════ */
36
+ /** 获取指定 Recipe 的转移历史(按时间倒序) */
37
+ getHistory(recipeId, limit = 50) {
38
+ const rows = this.#drizzle
39
+ .select()
40
+ .from(lifecycleTransitionEvents)
41
+ .where(eq(lifecycleTransitionEvents.recipeId, recipeId))
42
+ .orderBy(desc(lifecycleTransitionEvents.createdAt))
43
+ .limit(limit)
44
+ .all();
45
+ return rows.map((r) => this.#mapRow(r));
46
+ }
47
+ /** 统计指定时间之后的事件数量 */
48
+ countSince(since) {
49
+ const result = this.#drizzle
50
+ .select({ cnt: count() })
51
+ .from(lifecycleTransitionEvents)
52
+ .where(gt(lifecycleTransitionEvents.createdAt, since))
53
+ .get();
54
+ return result?.cnt ?? 0;
55
+ }
56
+ /** 按 trigger 分组统计(限定时间窗口,按数量倒序前 N) */
57
+ topTriggersSince(since, limit = 5) {
58
+ const rows = this.#drizzle
59
+ .select({
60
+ trigger: lifecycleTransitionEvents.trigger,
61
+ cnt: count(),
62
+ })
63
+ .from(lifecycleTransitionEvents)
64
+ .where(gt(lifecycleTransitionEvents.createdAt, since))
65
+ .groupBy(lifecycleTransitionEvents.trigger)
66
+ .orderBy(sql `count(*) desc`)
67
+ .limit(limit)
68
+ .all();
69
+ return rows.map((r) => ({ trigger: r.trigger, count: r.cnt }));
70
+ }
71
+ /** 按 trigger 值统计数量 */
72
+ countByTrigger(trigger) {
73
+ const result = this.#drizzle
74
+ .select({ cnt: count() })
75
+ .from(lifecycleTransitionEvents)
76
+ .where(eq(lifecycleTransitionEvents.trigger, trigger))
77
+ .get();
78
+ return result?.cnt ?? 0;
79
+ }
80
+ /** 按多个 trigger 值统计数量 */
81
+ countByTriggers(triggers) {
82
+ if (triggers.length === 0) {
83
+ return 0;
84
+ }
85
+ // Build OR condition for multiple triggers
86
+ const result = this.#drizzle
87
+ .select({ cnt: count() })
88
+ .from(lifecycleTransitionEvents)
89
+ .where(sql `${lifecycleTransitionEvents.trigger} IN (${sql.join(triggers.map((t) => sql `${t}`), sql `, `)})`)
90
+ .get();
91
+ return result?.cnt ?? 0;
92
+ }
93
+ /* ═══════════════════ Internal ═══════════════════ */
94
+ #mapRow(row) {
95
+ return {
96
+ id: row.id,
97
+ recipeId: row.recipeId,
98
+ fromState: row.fromState,
99
+ toState: row.toState,
100
+ trigger: row.trigger,
101
+ operatorId: row.operatorId,
102
+ evidence: row.evidenceJson ? safeJsonParse(row.evidenceJson, null) : null,
103
+ proposalId: row.proposalId ?? null,
104
+ createdAt: row.createdAt,
105
+ };
106
+ }
107
+ }
108
+ /* ────────────────────── Util ────────────────────── */
109
+ function safeJsonParse(json, fallback) {
110
+ if (!json) {
111
+ return fallback;
112
+ }
113
+ try {
114
+ return JSON.parse(json);
115
+ }
116
+ catch {
117
+ return fallback;
118
+ }
119
+ }