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
@@ -0,0 +1,124 @@
1
+ /**
2
+ * SearchRepoAdapter — SearchEngine 用的轻量级仓储适配器
3
+ *
4
+ * 当完整的 KnowledgeRepositoryImpl / RecipeSourceRefRepositoryImpl 不可用时
5
+ * (例如单元测试中只传入 raw db),SearchEngine 自动使用这些适配器。
6
+ * 放在 lib/repository/ 下,允许使用 raw SQL(lint 白名单目录)。
7
+ */
8
+ /** 解包 DatabaseConnection → raw SearchDb(若已是 raw db 则直接返回) */
9
+ export function unwrapSearchDb(db) {
10
+ return typeof db.getDb === 'function' ? db.getDb() : db;
11
+ }
12
+ /**
13
+ * 通用 db 解包:接受 raw db 或 { getDb() } wrapper,返回 raw db。
14
+ * 可用于 SearchDb、DatabaseLike 等不同 db 类型的构造函数。
15
+ */
16
+ export function unwrapRawDb(db) {
17
+ if (db !== null &&
18
+ db !== undefined &&
19
+ typeof db === 'object' &&
20
+ 'getDb' in db &&
21
+ typeof db.getDb === 'function') {
22
+ return db.getDb();
23
+ }
24
+ return db;
25
+ }
26
+ /**
27
+ * Raw-db 适配器:实现 SearchKnowledgeRepo 接口
28
+ * 仅在 KnowledgeRepositoryImpl 不可用时降级使用。
29
+ */
30
+ export class RawDbKnowledgeAdapter {
31
+ #db;
32
+ constructor(db) {
33
+ this.#db = db;
34
+ }
35
+ findNonDeprecatedSync() {
36
+ return this.#db
37
+ .prepare(`SELECT id, title, description, language, category, knowledgeType, kind,
38
+ content, lifecycle, tags, trigger, difficulty, quality, stats,
39
+ updatedAt, createdAt
40
+ FROM knowledge_entries WHERE lifecycle != 'deprecated'`)
41
+ .all();
42
+ }
43
+ keywordSearchSync(pattern, limit) {
44
+ return this.#db
45
+ .prepare(`SELECT id, title, description, language, category, knowledgeType, kind, lifecycle as status, content, trigger, headers, moduleName, 'knowledge' as type
46
+ FROM knowledge_entries
47
+ WHERE lifecycle != 'deprecated' AND (title LIKE ? ESCAPE '\\' OR description LIKE ? ESCAPE '\\' OR trigger LIKE ? ESCAPE '\\' OR content LIKE ? ESCAPE '\\')
48
+ LIMIT ?`)
49
+ .all(pattern, pattern, pattern, pattern, limit);
50
+ }
51
+ findByIdsDetailSync(ids) {
52
+ if (ids.length === 0) {
53
+ return [];
54
+ }
55
+ const placeholders = ids.map(() => '?').join(',');
56
+ return this.#db
57
+ .prepare(`SELECT id, content, description, trigger, headers, moduleName,
58
+ tags, language, category, updatedAt, createdAt, quality, stats, difficulty,
59
+ whenClause, doClause
60
+ FROM knowledge_entries WHERE id IN (${placeholders})`)
61
+ .all(...ids);
62
+ }
63
+ findUpdatedSinceSync(sinceIso) {
64
+ return this.#db
65
+ .prepare(`SELECT id, title, description, language, category, knowledgeType, kind,
66
+ content, lifecycle, tags, trigger, difficulty, quality, stats,
67
+ updatedAt, createdAt
68
+ FROM knowledge_entries WHERE updatedAt > ?`)
69
+ .all(sinceIso);
70
+ }
71
+ }
72
+ /**
73
+ * Raw-db 适配器:实现 SearchSourceRefRepo 接口
74
+ * 仅在 RecipeSourceRefRepositoryImpl 不可用时降级使用。
75
+ */
76
+ export class RawDbSourceRefAdapter {
77
+ #db;
78
+ constructor(db) {
79
+ this.#db = db;
80
+ }
81
+ findActiveByRecipeIds(ids) {
82
+ if (ids.length === 0) {
83
+ return [];
84
+ }
85
+ const placeholders = ids.map(() => '?').join(',');
86
+ return this.#db
87
+ .prepare(`SELECT recipe_id, source_path, status, new_path
88
+ FROM recipe_source_refs
89
+ WHERE recipe_id IN (${placeholders}) AND status != 'stale'`)
90
+ .all(...ids);
91
+ }
92
+ }
93
+ /**
94
+ * Raw-db 适配器:实现 GuardKnowledgeRepo 接口
95
+ * 仅在 KnowledgeRepositoryImpl 不可用时降级使用。
96
+ */
97
+ export class RawDbGuardAdapter {
98
+ #db;
99
+ constructor(db) {
100
+ this.#db = db;
101
+ }
102
+ findGuardRulesSync(lifecycles) {
103
+ const placeholders = lifecycles.map(() => '?').join(',');
104
+ return this.#db
105
+ .prepare(`SELECT id, title, description, language, scope, constraints, lifecycle
106
+ FROM knowledge_entries WHERE kind = 'rule' AND lifecycle IN (${placeholders})`)
107
+ .all(...lifecycles);
108
+ }
109
+ incrementGuardHitsSync(id, hits) {
110
+ this.#db
111
+ .prepare(`UPDATE knowledge_entries
112
+ SET stats = json_set(COALESCE(stats, '{}'), '$.guardHits', COALESCE(json_extract(stats, '$.guardHits'), 0) + ?),
113
+ updatedAt = strftime('%s', 'now')
114
+ WHERE id = ?`)
115
+ .run(hits, id);
116
+ }
117
+ }
118
+ /* ═══ Vector Sync 适配器 ═══════════════════════════════════ */
119
+ /** 从 raw db 查询非 deprecated 的基本条目信息(SyncCoordinator 对账用) */
120
+ export function queryNonDeprecatedEntries(db) {
121
+ return db
122
+ .prepare(`SELECT id, title, content, kind FROM knowledge_entries WHERE lifecycle != 'deprecated'`)
123
+ .all();
124
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * SessionRepository — 会话管理的仓储实现
3
+ *
4
+ * 操作 sessions 表,负责会话的 CRUD 和过期清理。
5
+ * 使用 Drizzle 类型安全 API。
6
+ */
7
+ import { sessions } from '../../infrastructure/database/drizzle/schema.js';
8
+ import { RepositoryBase } from '../base/RepositoryBase.js';
9
+ export interface SessionEntity {
10
+ id: string;
11
+ scope: string;
12
+ scopeId: string | null;
13
+ context: Record<string, unknown>;
14
+ metadata: Record<string, unknown>;
15
+ actor: string | null;
16
+ createdAt: number;
17
+ lastActiveAt: number | null;
18
+ expiredAt: number | null;
19
+ }
20
+ export interface SessionInsert {
21
+ id: string;
22
+ scope: string;
23
+ scopeId?: string | null;
24
+ context?: Record<string, unknown>;
25
+ metadata?: Record<string, unknown>;
26
+ actor?: string | null;
27
+ createdAt: number;
28
+ lastActiveAt?: number | null;
29
+ }
30
+ export declare class SessionRepositoryImpl extends RepositoryBase<typeof sessions, SessionEntity> {
31
+ #private;
32
+ constructor(drizzle: ConstructorParameters<typeof RepositoryBase<typeof sessions, SessionEntity>>[0]);
33
+ findById(id: string): Promise<SessionEntity | null>;
34
+ create(data: SessionInsert): Promise<SessionEntity>;
35
+ delete(id: string): Promise<boolean>;
36
+ /** 按 scope 查询所有会话 */
37
+ findByScope(scope: string): Promise<SessionEntity[]>;
38
+ /** 按 actor 查询 */
39
+ findByActor(actor: string): Promise<SessionEntity[]>;
40
+ /** 更新最后活跃时间 */
41
+ updateLastActivity(id: string, timestamp?: number): Promise<void>;
42
+ /** 过期清理 — 删除 expiredAt < now 的会话 */
43
+ cleanup(now?: number): Promise<number>;
44
+ /** 会话总数 */
45
+ count(scope?: string): Promise<number>;
46
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * SessionRepository — 会话管理的仓储实现
3
+ *
4
+ * 操作 sessions 表,负责会话的 CRUD 和过期清理。
5
+ * 使用 Drizzle 类型安全 API。
6
+ */
7
+ import { and, count, desc, eq, lt, sql } from 'drizzle-orm';
8
+ import { sessions } from '../../infrastructure/database/drizzle/schema.js';
9
+ import { RepositoryBase } from '../base/RepositoryBase.js';
10
+ /* ═══ 仓储实现 ═══ */
11
+ export class SessionRepositoryImpl extends RepositoryBase {
12
+ constructor(drizzle) {
13
+ super(drizzle, sessions);
14
+ }
15
+ /* ═══ CRUD ═══ */
16
+ async findById(id) {
17
+ const row = this.drizzle.select().from(sessions).where(eq(sessions.id, id)).get();
18
+ return row ? SessionRepositoryImpl.#toEntity(row) : null;
19
+ }
20
+ async create(data) {
21
+ this.drizzle
22
+ .insert(sessions)
23
+ .values({
24
+ id: data.id,
25
+ scope: data.scope,
26
+ scopeId: data.scopeId ?? null,
27
+ context: JSON.stringify(data.context ?? {}),
28
+ metadata: JSON.stringify(data.metadata ?? {}),
29
+ actor: data.actor ?? null,
30
+ createdAt: data.createdAt,
31
+ lastActiveAt: data.lastActiveAt ?? data.createdAt,
32
+ })
33
+ .run();
34
+ const entity = await this.findById(data.id);
35
+ if (!entity) {
36
+ throw new Error(`Failed to create session: ${data.id}`);
37
+ }
38
+ return entity;
39
+ }
40
+ async delete(id) {
41
+ const result = this.drizzle.delete(sessions).where(eq(sessions.id, id)).run();
42
+ return (result.changes ?? 0) > 0;
43
+ }
44
+ /* ═══ 查询 ═══ */
45
+ /** 按 scope 查询所有会话 */
46
+ async findByScope(scope) {
47
+ const rows = this.drizzle
48
+ .select()
49
+ .from(sessions)
50
+ .where(eq(sessions.scope, scope))
51
+ .orderBy(desc(sessions.createdAt))
52
+ .all();
53
+ return rows.map(SessionRepositoryImpl.#toEntity);
54
+ }
55
+ /** 按 actor 查询 */
56
+ async findByActor(actor) {
57
+ const rows = this.drizzle
58
+ .select()
59
+ .from(sessions)
60
+ .where(eq(sessions.actor, actor))
61
+ .orderBy(desc(sessions.lastActiveAt))
62
+ .all();
63
+ return rows.map(SessionRepositoryImpl.#toEntity);
64
+ }
65
+ /** 更新最后活跃时间 */
66
+ async updateLastActivity(id, timestamp) {
67
+ this.drizzle
68
+ .update(sessions)
69
+ .set({ lastActiveAt: timestamp ?? Math.floor(Date.now() / 1000) })
70
+ .where(eq(sessions.id, id))
71
+ .run();
72
+ }
73
+ /** 过期清理 — 删除 expiredAt < now 的会话 */
74
+ async cleanup(now) {
75
+ const threshold = now ?? Math.floor(Date.now() / 1000);
76
+ const result = this.drizzle
77
+ .delete(sessions)
78
+ .where(and(sql `${sessions.expiredAt} IS NOT NULL`, lt(sessions.expiredAt, threshold)))
79
+ .run();
80
+ return result.changes ?? 0;
81
+ }
82
+ /** 会话总数 */
83
+ async count(scope) {
84
+ const condition = scope ? eq(sessions.scope, scope) : undefined;
85
+ const [row] = this.drizzle.select({ cnt: count() }).from(sessions).where(condition).all();
86
+ return row?.cnt ?? 0;
87
+ }
88
+ /* ═══ Private ═══ */
89
+ static #toEntity(row) {
90
+ return {
91
+ id: row.id,
92
+ scope: row.scope,
93
+ scopeId: row.scopeId ?? null,
94
+ context: SessionRepositoryImpl.#safeJson(row.context),
95
+ metadata: SessionRepositoryImpl.#safeJson(row.metadata),
96
+ actor: row.actor ?? null,
97
+ createdAt: row.createdAt,
98
+ lastActiveAt: row.lastActiveAt ?? null,
99
+ expiredAt: row.expiredAt ?? null,
100
+ };
101
+ }
102
+ static #safeJson(str) {
103
+ try {
104
+ return str ? JSON.parse(str) : {};
105
+ }
106
+ catch {
107
+ return {};
108
+ }
109
+ }
110
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * RecipeSourceRefRepository — recipe_source_refs 表 CRUD (Drizzle ORM)
3
+ *
4
+ * Recipe 来源引用桥接表:建立 Recipe ↔ 源码文件的映射关系。
5
+ * 表使用复合主键 (recipe_id, source_path),没有独立 id 列。
6
+ *
7
+ * 主要消费者:SourceRefReconciler
8
+ */
9
+ import type { DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
10
+ export interface RecipeSourceRefEntity {
11
+ recipeId: string;
12
+ sourcePath: string;
13
+ status: string;
14
+ newPath: string | null;
15
+ verifiedAt: number;
16
+ }
17
+ export interface RecipeSourceRefInsert {
18
+ recipeId: string;
19
+ sourcePath: string;
20
+ status?: string;
21
+ newPath?: string | null;
22
+ verifiedAt: number;
23
+ }
24
+ export declare class RecipeSourceRefRepositoryImpl {
25
+ #private;
26
+ constructor(drizzle: DrizzleDB);
27
+ /** 按 Recipe ID 查询所有关联的源引用 */
28
+ findByRecipeId(recipeId: string): RecipeSourceRefEntity[];
29
+ /** 按源文件路径查询所有关联的引用 */
30
+ findBySourcePath(sourcePath: string): RecipeSourceRefEntity[];
31
+ /** 按状态查询 */
32
+ findByStatus(status: string): RecipeSourceRefEntity[];
33
+ /** 查找指定复合键 */
34
+ findOne(recipeId: string, sourcePath: string): RecipeSourceRefEntity | null;
35
+ /** 查询所有 stale 引用 */
36
+ findStale(): RecipeSourceRefEntity[];
37
+ /** 统计条数 */
38
+ count(): number;
39
+ /** UPSERT — 插入或更新(按复合主键) */
40
+ upsert(data: RecipeSourceRefInsert): void;
41
+ /** 更新状态 */
42
+ updateStatus(recipeId: string, sourcePath: string, status: string, newPath?: string): boolean;
43
+ /** 按 Recipe ID 删除所有关联引用 */
44
+ deleteByRecipeId(recipeId: string): number;
45
+ /** 删除指定复合键 */
46
+ deleteOne(recipeId: string, sourcePath: string): boolean;
47
+ /** 检查表是否可访问(SourceRefReconciler 使用) */
48
+ isAccessible(): boolean;
49
+ /** Stale counts grouped by recipe (for SourceRefReconciler signal emission) */
50
+ getStaleCountsByRecipe(): Array<{
51
+ recipeId: string;
52
+ staleCount: number;
53
+ totalCount: number;
54
+ }>;
55
+ /** Find all entries with status='renamed' and non-null new_path */
56
+ findRenamed(): RecipeSourceRefEntity[];
57
+ /** Replace source path (updates composite key column) — used by SourceRefReconciler.applyRepairs */
58
+ replaceSourcePath(recipeId: string, oldSourcePath: string, newSourcePath: string, verifiedAt: number): void;
59
+ /** 查询多个 Recipe 的非 stale 来源引用(SearchEngine _supplementDetails 用) */
60
+ findActiveByRecipeIds(ids: string[]): {
61
+ recipeId: string;
62
+ sourcePath: string;
63
+ status: string;
64
+ newPath: string | null;
65
+ }[];
66
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * RecipeSourceRefRepository — recipe_source_refs 表 CRUD (Drizzle ORM)
3
+ *
4
+ * Recipe 来源引用桥接表:建立 Recipe ↔ 源码文件的映射关系。
5
+ * 表使用复合主键 (recipe_id, source_path),没有独立 id 列。
6
+ *
7
+ * 主要消费者:SourceRefReconciler
8
+ */
9
+ import { and, eq, inArray, isNotNull, ne, sql } from 'drizzle-orm';
10
+ import { recipeSourceRefs } from '../../infrastructure/database/drizzle/schema.js';
11
+ /* ═══ Repository 实现 ═══ */
12
+ export class RecipeSourceRefRepositoryImpl {
13
+ #drizzle;
14
+ constructor(drizzle) {
15
+ this.#drizzle = drizzle;
16
+ }
17
+ /* ─── 查询 ─── */
18
+ /** 按 Recipe ID 查询所有关联的源引用 */
19
+ findByRecipeId(recipeId) {
20
+ return this.#drizzle
21
+ .select()
22
+ .from(recipeSourceRefs)
23
+ .where(eq(recipeSourceRefs.recipeId, recipeId))
24
+ .all();
25
+ }
26
+ /** 按源文件路径查询所有关联的引用 */
27
+ findBySourcePath(sourcePath) {
28
+ return this.#drizzle
29
+ .select()
30
+ .from(recipeSourceRefs)
31
+ .where(eq(recipeSourceRefs.sourcePath, sourcePath))
32
+ .all();
33
+ }
34
+ /** 按状态查询 */
35
+ findByStatus(status) {
36
+ return this.#drizzle
37
+ .select()
38
+ .from(recipeSourceRefs)
39
+ .where(eq(recipeSourceRefs.status, status))
40
+ .all();
41
+ }
42
+ /** 查找指定复合键 */
43
+ findOne(recipeId, sourcePath) {
44
+ const row = this.#drizzle
45
+ .select()
46
+ .from(recipeSourceRefs)
47
+ .where(and(eq(recipeSourceRefs.recipeId, recipeId), eq(recipeSourceRefs.sourcePath, sourcePath)))
48
+ .limit(1)
49
+ .get();
50
+ return row ?? null;
51
+ }
52
+ /** 查询所有 stale 引用 */
53
+ findStale() {
54
+ return this.findByStatus('stale');
55
+ }
56
+ /** 统计条数 */
57
+ count() {
58
+ const row = this.#drizzle.select({ cnt: sql `count(*)` }).from(recipeSourceRefs).get();
59
+ return row?.cnt ?? 0;
60
+ }
61
+ /* ─── 写入 ─── */
62
+ /** UPSERT — 插入或更新(按复合主键) */
63
+ upsert(data) {
64
+ this.#drizzle
65
+ .insert(recipeSourceRefs)
66
+ .values({
67
+ recipeId: data.recipeId,
68
+ sourcePath: data.sourcePath,
69
+ status: data.status ?? 'active',
70
+ newPath: data.newPath ?? null,
71
+ verifiedAt: data.verifiedAt,
72
+ })
73
+ .onConflictDoUpdate({
74
+ target: [recipeSourceRefs.recipeId, recipeSourceRefs.sourcePath],
75
+ set: {
76
+ status: data.status ?? 'active',
77
+ newPath: data.newPath ?? null,
78
+ verifiedAt: data.verifiedAt,
79
+ },
80
+ })
81
+ .run();
82
+ }
83
+ /** 更新状态 */
84
+ updateStatus(recipeId, sourcePath, status, newPath) {
85
+ const set = { status };
86
+ if (newPath !== undefined) {
87
+ set.newPath = newPath;
88
+ }
89
+ const result = this.#drizzle
90
+ .update(recipeSourceRefs)
91
+ .set(set)
92
+ .where(and(eq(recipeSourceRefs.recipeId, recipeId), eq(recipeSourceRefs.sourcePath, sourcePath)))
93
+ .run();
94
+ return result.changes > 0;
95
+ }
96
+ /* ─── 删除 ─── */
97
+ /** 按 Recipe ID 删除所有关联引用 */
98
+ deleteByRecipeId(recipeId) {
99
+ const result = this.#drizzle
100
+ .delete(recipeSourceRefs)
101
+ .where(eq(recipeSourceRefs.recipeId, recipeId))
102
+ .run();
103
+ return result.changes;
104
+ }
105
+ /** 删除指定复合键 */
106
+ deleteOne(recipeId, sourcePath) {
107
+ const result = this.#drizzle
108
+ .delete(recipeSourceRefs)
109
+ .where(and(eq(recipeSourceRefs.recipeId, recipeId), eq(recipeSourceRefs.sourcePath, sourcePath)))
110
+ .run();
111
+ return result.changes > 0;
112
+ }
113
+ /** 检查表是否可访问(SourceRefReconciler 使用) */
114
+ isAccessible() {
115
+ try {
116
+ this.#drizzle
117
+ .select({ recipeId: recipeSourceRefs.recipeId })
118
+ .from(recipeSourceRefs)
119
+ .limit(1)
120
+ .get();
121
+ return true;
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ }
127
+ /** Stale counts grouped by recipe (for SourceRefReconciler signal emission) */
128
+ getStaleCountsByRecipe() {
129
+ const rows = this.#drizzle
130
+ .select({
131
+ recipeId: recipeSourceRefs.recipeId,
132
+ staleCount: sql `count(*)`,
133
+ totalCount: sql `(SELECT count(*) FROM recipe_source_refs r2 WHERE r2.recipe_id = ${recipeSourceRefs.recipeId})`,
134
+ })
135
+ .from(recipeSourceRefs)
136
+ .where(eq(recipeSourceRefs.status, 'stale'))
137
+ .groupBy(recipeSourceRefs.recipeId)
138
+ .all();
139
+ return rows.map((r) => ({
140
+ recipeId: r.recipeId,
141
+ staleCount: Number(r.staleCount),
142
+ totalCount: Number(r.totalCount),
143
+ }));
144
+ }
145
+ /** Find all entries with status='renamed' and non-null new_path */
146
+ findRenamed() {
147
+ return this.#drizzle
148
+ .select()
149
+ .from(recipeSourceRefs)
150
+ .where(and(eq(recipeSourceRefs.status, 'renamed'), isNotNull(recipeSourceRefs.newPath)))
151
+ .all();
152
+ }
153
+ /** Replace source path (updates composite key column) — used by SourceRefReconciler.applyRepairs */
154
+ replaceSourcePath(recipeId, oldSourcePath, newSourcePath, verifiedAt) {
155
+ this.#drizzle
156
+ .update(recipeSourceRefs)
157
+ .set({
158
+ sourcePath: newSourcePath,
159
+ status: 'active',
160
+ newPath: null,
161
+ verifiedAt,
162
+ })
163
+ .where(and(eq(recipeSourceRefs.recipeId, recipeId), eq(recipeSourceRefs.sourcePath, oldSourcePath)))
164
+ .run();
165
+ }
166
+ /** 查询多个 Recipe 的非 stale 来源引用(SearchEngine _supplementDetails 用) */
167
+ findActiveByRecipeIds(ids) {
168
+ if (ids.length === 0) {
169
+ return [];
170
+ }
171
+ return this.#drizzle
172
+ .select({
173
+ recipeId: recipeSourceRefs.recipeId,
174
+ sourcePath: recipeSourceRefs.sourcePath,
175
+ status: recipeSourceRefs.status,
176
+ newPath: recipeSourceRefs.newPath,
177
+ })
178
+ .from(recipeSourceRefs)
179
+ .where(and(inArray(recipeSourceRefs.recipeId, ids), ne(recipeSourceRefs.status, 'stale')))
180
+ .all();
181
+ }
182
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SyncRepoAdapter — KnowledgeSyncService 用的仓储适配器
3
+ *
4
+ * 将 KnowledgeSyncService 中的 raw SQL 操作封装在 lib/repository/ 层(lint 白名单目录),
5
+ * 使 KnowledgeSyncService 本身不再需要 escape-hatch 标记。
6
+ */
7
+ type RawDb = {
8
+ prepare(sql: string): {
9
+ run(...args: unknown[]): void;
10
+ get(...args: unknown[]): unknown;
11
+ all(): Array<Record<string, unknown>>;
12
+ };
13
+ };
14
+ /** KnowledgeSyncService 所需的 DB 操作最小接口 */
15
+ export interface SyncRepo {
16
+ /** 创建可复用的 UPSERT 语句 */
17
+ createUpsertStmt(cols: string[]): {
18
+ run: (...args: unknown[]) => void;
19
+ };
20
+ /** 检查 entry 是否已存在 */
21
+ entryExists(id: string): boolean;
22
+ /** 创建审计日志插入语句(可能失败返回 null) */
23
+ createAuditInsertStmt(): {
24
+ run: (...args: unknown[]) => void;
25
+ } | null;
26
+ /** 查询所有非 deprecated 且有 sourceFile 的条目 */
27
+ findActiveEntriesWithSourceFile(): Array<{
28
+ id: string;
29
+ sourceFile: string;
30
+ }>;
31
+ /** 标记条目为 deprecated */
32
+ deprecateEntry(id: string, reason: string, timestamp: number): void;
33
+ }
34
+ /**
35
+ * Raw-db 适配器:实现 SyncRepo 接口
36
+ * 使用 raw SQL 访问 knowledge_entries 和 audit_logs 表。
37
+ */
38
+ export declare class RawDbSyncAdapter implements SyncRepo {
39
+ #private;
40
+ constructor(db: RawDb);
41
+ createUpsertStmt(cols: string[]): {
42
+ run(...args: unknown[]): void;
43
+ get(...args: unknown[]): unknown;
44
+ all(): Array<Record<string, unknown>>;
45
+ };
46
+ entryExists(id: string): boolean;
47
+ createAuditInsertStmt(): {
48
+ run(...args: unknown[]): void;
49
+ get(...args: unknown[]): unknown;
50
+ all(): Array<Record<string, unknown>>;
51
+ } | null;
52
+ findActiveEntriesWithSourceFile(): Array<{
53
+ id: string;
54
+ sourceFile: string;
55
+ }>;
56
+ deprecateEntry(id: string, reason: string, timestamp: number): void;
57
+ }
58
+ export {};
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SyncRepoAdapter — KnowledgeSyncService 用的仓储适配器
3
+ *
4
+ * 将 KnowledgeSyncService 中的 raw SQL 操作封装在 lib/repository/ 层(lint 白名单目录),
5
+ * 使 KnowledgeSyncService 本身不再需要 escape-hatch 标记。
6
+ */
7
+ /**
8
+ * Raw-db 适配器:实现 SyncRepo 接口
9
+ * 使用 raw SQL 访问 knowledge_entries 和 audit_logs 表。
10
+ */
11
+ export class RawDbSyncAdapter {
12
+ #db;
13
+ constructor(db) {
14
+ this.#db = db;
15
+ }
16
+ createUpsertStmt(cols) {
17
+ const updateCols = cols.filter((c) => !['id', 'createdBy', 'createdAt'].includes(c));
18
+ const setClauses = updateCols.map((c) => `${c} = excluded.${c}`).join(',\n ');
19
+ const sql = `
20
+ INSERT INTO knowledge_entries (${cols.join(', ')})
21
+ VALUES (${cols.map(() => '?').join(', ')})
22
+ ON CONFLICT(id) DO UPDATE SET
23
+ ${setClauses}
24
+ `;
25
+ return this.#db.prepare(sql);
26
+ }
27
+ entryExists(id) {
28
+ const row = this.#db.prepare('SELECT 1 FROM knowledge_entries WHERE id = ?').get(id);
29
+ return !!row;
30
+ }
31
+ createAuditInsertStmt() {
32
+ try {
33
+ return this.#db.prepare(`
34
+ INSERT INTO audit_logs (id, timestamp, actor, actor_context, action, resource, operation_data, result, error_message, duration)
35
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
36
+ `);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ findActiveEntriesWithSourceFile() {
43
+ return this.#db
44
+ .prepare(`SELECT id, sourceFile FROM knowledge_entries
45
+ WHERE lifecycle NOT IN ('deprecated')
46
+ AND sourceFile IS NOT NULL`)
47
+ .all();
48
+ }
49
+ deprecateEntry(id, reason, timestamp) {
50
+ this.#db
51
+ .prepare(`UPDATE knowledge_entries
52
+ SET lifecycle = 'deprecated',
53
+ rejectionReason = ?,
54
+ updatedAt = ?
55
+ WHERE id = ?`)
56
+ .run(reason, timestamp, id);
57
+ }
58
+ }
@@ -29,8 +29,7 @@ export async function runUiStartupTasks(ctx) {
29
29
  sourceRefReconciler: sourceRefReconciler || undefined,
30
30
  });
31
31
  const db = ctx.container.get('database');
32
- const rawDb = db.getDb();
33
- const syncReport = await syncService.syncAll(rawDb, { skipViolations: true });
32
+ const syncReport = await syncService.syncAll(db, { skipViolations: true });
34
33
  report.syncAll = {
35
34
  synced: syncReport.synced,
36
35
  created: syncReport.created,
@@ -54,7 +53,7 @@ export async function runUiStartupTasks(ctx) {
54
53
  try {
55
54
  if (ctx.container.services.stagingManager) {
56
55
  const sm = ctx.container.get('stagingManager');
57
- const result = sm.checkAndPromote();
56
+ const result = await sm.checkAndPromote();
58
57
  report.staging = { promoted: result.promoted.length };
59
58
  if (result.promoted.length > 0) {
60
59
  logger.info(`[UiStartupTasks] Stage 2: auto-promoted ${result.promoted.length} staging entries`);
@@ -104,7 +103,7 @@ export async function runUiStartupTasks(ctx) {
104
103
  try {
105
104
  if (ctx.container.services.proposalExecutor) {
106
105
  const executor = ctx.container.get('proposalExecutor');
107
- const result = executor.checkAndExecute();
106
+ const result = await executor.checkAndExecute();
108
107
  report.proposalCheck = {
109
108
  executed: result.executed.length,
110
109
  rejected: result.rejected.length,
@@ -125,7 +124,7 @@ export async function runUiStartupTasks(ctx) {
125
124
  try {
126
125
  if (ctx.container.services.knowledgeMetabolism) {
127
126
  const metabolism = ctx.container.get('knowledgeMetabolism');
128
- const result = metabolism.runFullCycle();
127
+ const result = await metabolism.runFullCycle();
129
128
  report.metabolismCycle = {
130
129
  proposalCount: result.summary.proposalCount,
131
130
  contradictions: result.summary.contradictionCount,
@@ -146,7 +145,7 @@ export async function runUiStartupTasks(ctx) {
146
145
  try {
147
146
  if (ctx.container.services.lifecycleSupervisor) {
148
147
  const supervisor = ctx.container.get('lifecycleSupervisor');
149
- const result = supervisor.checkTimeouts();
148
+ const result = await supervisor.checkTimeouts();
150
149
  report.timeoutCheck = {
151
150
  timedOut: result.timedOut.length,
152
151
  checked: result.checked,