autosnippet 3.3.6 → 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.
- package/README.md +1 -0
- package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
- package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
- package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.js +8 -4
- package/dist/lib/agent/AgentRuntime.d.ts +2 -2
- package/dist/lib/agent/AgentRuntime.js +26 -18
- package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
- package/dist/lib/agent/core/LoopContext.d.ts +1 -0
- package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
- package/dist/lib/agent/domain/ChatAgentTasks.js +4 -0
- package/dist/lib/agent/forced-summary.js +7 -2
- package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
- package/dist/lib/agent/memory/ActiveContext.js +0 -2
- package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
- package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
- package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
- package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
- package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
- package/dist/lib/agent/memory/MemoryStore.js +196 -261
- package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
- package/dist/lib/agent/memory/PersistentMemory.js +4 -5
- package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
- package/dist/lib/agent/memory/SessionStore.js +0 -2
- package/dist/lib/agent/tools/ast-graph.js +21 -19
- package/dist/lib/agent/tools/infrastructure.js +3 -2
- package/dist/lib/agent/tools/project-access.d.ts +2 -2
- package/dist/lib/agent/tools/project-access.js +5 -4
- package/dist/lib/bootstrap.js +2 -1
- package/dist/lib/cli/AiScanService.js +8 -21
- package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
- package/dist/lib/cli/KnowledgeSyncService.js +23 -51
- package/dist/lib/core/ast/ProjectGraph.js +5 -27
- package/dist/lib/core/discovery/ConfigWatcher.d.ts +64 -0
- package/dist/lib/core/discovery/ConfigWatcher.js +336 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +28 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +1303 -0
- package/dist/lib/core/discovery/DiscovererPreference.d.ts +44 -0
- package/dist/lib/core/discovery/DiscovererPreference.js +141 -0
- package/dist/lib/core/discovery/DiscovererRegistry.d.ts +10 -1
- package/dist/lib/core/discovery/DiscovererRegistry.js +42 -2
- package/dist/lib/core/discovery/ProjectDiscoverer.d.ts +19 -0
- package/dist/lib/core/discovery/index.d.ts +2 -0
- package/dist/lib/core/discovery/index.js +4 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.d.ts +32 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.js +148 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.d.ts +43 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.js +171 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.d.ts +45 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.js +122 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.d.ts +49 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.js +282 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.d.ts +33 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.js +229 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.d.ts +37 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.js +212 -0
- package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
- package/dist/lib/domain/dimension/DimensionSop.js +44 -33
- package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
- package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +7 -1
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +17 -3
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
- package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
- package/dist/lib/domain/knowledge/index.d.ts +2 -1
- package/dist/lib/domain/knowledge/index.js +1 -1
- package/dist/lib/external/ai/AiProvider.d.ts +12 -0
- package/dist/lib/external/ai/AiProvider.js +24 -0
- package/dist/lib/external/ai/AiProviderManager.d.ts +101 -0
- package/dist/lib/external/ai/AiProviderManager.js +193 -0
- package/dist/lib/external/ai/providers/ClaudeProvider.js +11 -0
- package/dist/lib/external/ai/providers/GoogleGeminiProvider.js +18 -0
- package/dist/lib/external/ai/providers/MockProvider.d.ts +21 -3
- package/dist/lib/external/ai/providers/MockProvider.js +290 -14
- package/dist/lib/external/ai/providers/OpenAiProvider.js +16 -0
- package/dist/lib/external/lark/LarkTransport.d.ts +5 -1
- package/dist/lib/external/lark/LarkTransport.js +10 -2
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.d.ts +20 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +432 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -24
- package/dist/lib/external/mcp/handlers/bootstrap/refine.js +8 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
- package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +9 -0
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +3 -1
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/consolidated.js +2 -1
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +9 -4
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +18 -18
- package/dist/lib/external/mcp/handlers/guard.js +15 -24
- package/dist/lib/external/mcp/handlers/knowledge.js +5 -4
- package/dist/lib/external/mcp/handlers/panorama.js +9 -9
- package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
- package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
- package/dist/lib/external/mcp/handlers/search.js +3 -1
- package/dist/lib/external/mcp/handlers/skill.js +4 -4
- package/dist/lib/external/mcp/handlers/structure.js +8 -12
- package/dist/lib/external/mcp/handlers/system.js +10 -34
- package/dist/lib/http/routes/ai.js +109 -30
- package/dist/lib/http/routes/candidates.js +11 -4
- package/dist/lib/http/routes/commands.js +10 -1
- package/dist/lib/http/routes/guardReport.js +3 -5
- package/dist/lib/http/routes/health.js +11 -0
- package/dist/lib/http/routes/modules.js +27 -0
- package/dist/lib/http/routes/panorama.js +12 -12
- package/dist/lib/http/routes/recipes.js +66 -8
- package/dist/lib/http/routes/remote.js +3 -13
- package/dist/lib/http/routes/search.js +11 -8
- package/dist/lib/http/utils/routeHelpers.js +2 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
- package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
- package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
- package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
- package/dist/lib/injection/ServiceContainer.d.ts +6 -5
- package/dist/lib/injection/ServiceContainer.js +18 -31
- package/dist/lib/injection/ServiceMap.d.ts +22 -0
- package/dist/lib/injection/modules/AiModule.d.ts +6 -9
- package/dist/lib/injection/modules/AiModule.js +82 -39
- package/dist/lib/injection/modules/AppModule.js +2 -1
- package/dist/lib/injection/modules/GuardModule.js +5 -5
- package/dist/lib/injection/modules/InfraModule.js +60 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
- package/dist/lib/injection/modules/PanoramaModule.js +16 -10
- package/dist/lib/injection/modules/VectorModule.js +3 -0
- package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
- package/dist/lib/repository/audit/AuditRepository.js +272 -0
- package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
- package/dist/lib/repository/base/RepositoryBase.js +32 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
- package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
- package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
- package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
- package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
- package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
- package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
- package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
- package/dist/lib/repository/memory/MemoryRepository.js +260 -0
- package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
- package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
- package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
- package/dist/lib/repository/session/SessionRepository.js +110 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
- package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
- package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
- package/dist/lib/service/cleanup/CleanupService.d.ts +54 -7
- package/dist/lib/service/cleanup/CleanupService.js +291 -40
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
- package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
- package/dist/lib/service/evolution/ContentPatcher.js +48 -19
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
- package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
- package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
- package/dist/lib/service/evolution/DecayDetector.js +63 -57
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
- package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
- package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
- package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
- package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
- package/dist/lib/service/evolution/StagingManager.js +37 -95
- package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
- package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
- package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
- package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
- package/dist/lib/service/guard/ReverseGuard.js +21 -31
- package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
- package/dist/lib/service/guard/ViolationsStore.js +75 -69
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +45 -63
- package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -496
- package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
- package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
- package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
- package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +97 -46
- package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
- package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
- package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
- package/dist/lib/service/module/ModuleService.js +10 -19
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +14 -3
- package/dist/lib/service/panorama/CouplingAnalyzer.js +137 -32
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
- package/dist/lib/service/panorama/DimensionAnalyzer.js +94 -33
- package/dist/lib/service/panorama/LayerInferrer.d.ts +16 -1
- package/dist/lib/service/panorama/LayerInferrer.js +118 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +14 -4
- package/dist/lib/service/panorama/ModuleDiscoverer.js +209 -61
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +15 -4
- package/dist/lib/service/panorama/PanoramaAggregator.js +128 -62
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
- package/dist/lib/service/panorama/PanoramaScanner.js +60 -31
- package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
- package/dist/lib/service/panorama/PanoramaService.js +49 -69
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +41 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +10 -5
- package/dist/lib/service/panorama/RoleRefiner.js +92 -282
- package/dist/lib/service/panorama/TechStackProfiler.d.ts +13 -0
- package/dist/lib/service/panorama/TechStackProfiler.js +79 -0
- package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
- package/dist/lib/service/quality/QualityScorer.js +157 -83
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +32 -37
- package/dist/lib/service/signal/HitRecorder.js +5 -5
- package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
- package/dist/lib/service/skills/SignalCollector.d.ts +6 -8
- package/dist/lib/service/skills/SignalCollector.js +34 -60
- package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
- package/dist/lib/service/skills/SkillAdvisor.js +30 -79
- package/dist/lib/service/vector/ContextualEnricher.d.ts +1 -0
- package/dist/lib/service/vector/ContextualEnricher.js +4 -0
- package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
- package/dist/lib/service/vector/SyncCoordinator.js +25 -3
- package/dist/lib/service/vector/VectorService.d.ts +2 -0
- package/dist/lib/service/vector/VectorService.js +3 -0
- package/dist/lib/service/wiki/WikiGenerator.js +1 -1
- package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
- package/dist/lib/shared/LanguageProfiles.js +939 -0
- package/dist/lib/shared/LanguageService.d.ts +6 -0
- package/dist/lib/shared/LanguageService.js +19 -0
- package/dist/lib/shared/constants.d.ts +19 -19
- package/dist/lib/shared/constants.js +10 -10
- package/dist/lib/shared/developer-identity.d.ts +18 -0
- package/dist/lib/shared/developer-identity.js +62 -0
- package/dist/lib/shared/schemas/http-requests.d.ts +8 -17
- package/dist/lib/shared/schemas/http-requests.js +9 -6
- package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
- package/dist/lib/types/knowledge-wire.d.ts +1 -0
- package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
- package/dist/lib/types/project-snapshot-builder.js +0 -1
- package/dist/lib/types/project-snapshot.d.ts +0 -1
- package/dist/lib/types/project-snapshot.js +0 -1
- package/dist/lib/types/snapshot-views.d.ts +0 -2
- package/dist/lib/types/snapshot-views.js +0 -1
- package/package.json +2 -1
- package/dashboard/dist/assets/icons-D1aVZYFW.js +0 -1
- package/dashboard/dist/assets/index-CxHOu8Hd.css +0 -1
- package/dashboard/dist/assets/index-DDdAOpYT.js +0 -128
- package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
- package/dist/lib/repository/base/BaseRepository.js +0 -226
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* 3. 独立价值 — 内容长度、具体性、是否有独立 coreCode
|
|
16
16
|
*/
|
|
17
17
|
var _a;
|
|
18
|
+
import { COUNTABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
|
|
18
19
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
19
20
|
import { ContradictionDetector } from './ContradictionDetector.js';
|
|
20
21
|
/* ────────────────────── Constants ────────────────────── */
|
|
@@ -29,10 +30,10 @@ const MAX_CANDIDATES_PER_ANALYSIS = 30;
|
|
|
29
30
|
const WEIGHTS = { title: 0.2, clause: 0.3, code: 0.3, guard: 0.2 };
|
|
30
31
|
/* ────────────────────── Class ────────────────────── */
|
|
31
32
|
export class ConsolidationAdvisor {
|
|
32
|
-
#
|
|
33
|
+
#knowledgeRepo;
|
|
33
34
|
#logger = Logger.getInstance();
|
|
34
|
-
constructor(
|
|
35
|
-
this.#
|
|
35
|
+
constructor(knowledgeRepo) {
|
|
36
|
+
this.#knowledgeRepo = knowledgeRepo;
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* 分析候选知识与现有知识库的关系,返回融合建议。
|
|
@@ -40,11 +41,11 @@ export class ConsolidationAdvisor {
|
|
|
40
41
|
* @param candidate - 待提交的候选数据
|
|
41
42
|
* @returns ConsolidationAdvice — 建议 + 理由 + 上下文
|
|
42
43
|
*/
|
|
43
|
-
analyze(candidate) {
|
|
44
|
+
async analyze(candidate) {
|
|
44
45
|
// ── Step 1: 独立价值评估 ──
|
|
45
46
|
const substanceScore = this.#assessSubstance(candidate);
|
|
46
47
|
// ── Step 2: 加载同域 / 相关 Recipe ──
|
|
47
|
-
const related = this.#loadRelatedRecipes(candidate);
|
|
48
|
+
const related = await this.#loadRelatedRecipes(candidate);
|
|
48
49
|
// ── Step 3: insufficient — 独立价值不足,交给 Agent 与开发者决定 ──
|
|
49
50
|
if (substanceScore < MIN_SUBSTANCE_SCORE) {
|
|
50
51
|
if (related.length > 0) {
|
|
@@ -188,12 +189,12 @@ export class ConsolidationAdvisor {
|
|
|
188
189
|
* @param candidates - 待提交的候选数组
|
|
189
190
|
* @returns BatchConsolidationResult — 每条分析 + 批次内重叠
|
|
190
191
|
*/
|
|
191
|
-
analyzeBatch(candidates) {
|
|
192
|
+
async analyzeBatch(candidates) {
|
|
192
193
|
// 对每个候选独立分析(vs DB)
|
|
193
|
-
const items =
|
|
194
|
-
|
|
195
|
-
advice: this.analyze(
|
|
196
|
-
}
|
|
194
|
+
const items = [];
|
|
195
|
+
for (let index = 0; index < candidates.length; index++) {
|
|
196
|
+
items.push({ index, advice: await this.analyze(candidates[index]) });
|
|
197
|
+
}
|
|
197
198
|
// 检测批次内候选之间的相互重叠
|
|
198
199
|
const internalOverlaps = [];
|
|
199
200
|
for (let i = 0; i < candidates.length; i++) {
|
|
@@ -288,78 +289,41 @@ export class ConsolidationAdvisor {
|
|
|
288
289
|
return msg;
|
|
289
290
|
}
|
|
290
291
|
/* ════════════════════ 相关 Recipe 加载 ════════════════════ */
|
|
291
|
-
#loadRelatedRecipes(candidate) {
|
|
292
|
+
async #loadRelatedRecipes(candidate) {
|
|
292
293
|
try {
|
|
293
|
-
// 先按 category 精确匹配 + trigger 前缀匹配
|
|
294
294
|
const category = candidate.category || '';
|
|
295
295
|
const trigger = candidate.trigger || '';
|
|
296
296
|
const triggerPrefix = trigger.startsWith('@')
|
|
297
297
|
? trigger.slice(0, Math.max(3, trigger.indexOf('-', 1) > 0 ? trigger.indexOf('-', 1) : trigger.length))
|
|
298
298
|
: '';
|
|
299
|
-
|
|
299
|
+
const toSummary = (e) => ({
|
|
300
|
+
id: e.id,
|
|
301
|
+
title: e.title,
|
|
302
|
+
doClause: e.doClause || null,
|
|
303
|
+
dontClause: e.dontClause || null,
|
|
304
|
+
coreCode: e.coreCode || null,
|
|
305
|
+
category: e.category || null,
|
|
306
|
+
trigger: e.trigger || null,
|
|
307
|
+
whenClause: e.whenClause || null,
|
|
308
|
+
guardPattern: e.content?.pattern || null,
|
|
309
|
+
});
|
|
300
310
|
if (category) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
json_extract(content, '$.coreCode') AS coreCode,
|
|
307
|
-
category, trigger, whenClause,
|
|
308
|
-
json_extract(content, '$.pattern') AS guardPattern
|
|
309
|
-
FROM knowledge_entries
|
|
310
|
-
WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
|
|
311
|
-
AND category = ?
|
|
312
|
-
ORDER BY lifecycle DESC
|
|
313
|
-
LIMIT ?`)
|
|
314
|
-
.all(category, MAX_CANDIDATES_PER_ANALYSIS);
|
|
315
|
-
// 如果同 category 不够,再加载 trigger 相关的
|
|
316
|
-
if (rows.length < 5 && triggerPrefix.length >= 3) {
|
|
317
|
-
const extra = this.#db
|
|
318
|
-
.prepare(`SELECT id, title,
|
|
319
|
-
doClause,
|
|
320
|
-
dontClause,
|
|
321
|
-
json_extract(content, '$.coreCode') AS coreCode,
|
|
322
|
-
category, trigger, whenClause,
|
|
323
|
-
json_extract(content, '$.pattern') AS guardPattern
|
|
324
|
-
FROM knowledge_entries
|
|
325
|
-
WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
|
|
326
|
-
AND category != ?
|
|
327
|
-
AND trigger LIKE ?
|
|
328
|
-
LIMIT ?`)
|
|
329
|
-
.all(category, `${triggerPrefix}%`, MAX_CANDIDATES_PER_ANALYSIS - rows.length);
|
|
330
|
-
const existingIds = new Set(rows.map((r) => r.id));
|
|
311
|
+
const entries = await this.#knowledgeRepo.findAllByLifecyclesAndCategory(COUNTABLE_LIFECYCLES, category, MAX_CANDIDATES_PER_ANALYSIS);
|
|
312
|
+
const results = entries.map(toSummary);
|
|
313
|
+
if (results.length < 5 && triggerPrefix.length >= 3) {
|
|
314
|
+
const extra = await this.#knowledgeRepo.findByLifecyclesAndTriggerPrefix(COUNTABLE_LIFECYCLES, category, triggerPrefix, MAX_CANDIDATES_PER_ANALYSIS - results.length);
|
|
315
|
+
const existingIds = new Set(results.map((r) => r.id));
|
|
331
316
|
for (const e of extra) {
|
|
332
|
-
|
|
333
|
-
|
|
317
|
+
const s = toSummary(e);
|
|
318
|
+
if (!existingIds.has(s.id)) {
|
|
319
|
+
results.push(s);
|
|
334
320
|
}
|
|
335
321
|
}
|
|
336
322
|
}
|
|
323
|
+
return results;
|
|
337
324
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
rows = this.#db
|
|
341
|
-
.prepare(`SELECT id, title,
|
|
342
|
-
doClause,
|
|
343
|
-
dontClause,
|
|
344
|
-
json_extract(content, '$.coreCode') AS coreCode,
|
|
345
|
-
category, trigger, whenClause,
|
|
346
|
-
json_extract(content, '$.pattern') AS guardPattern
|
|
347
|
-
FROM knowledge_entries
|
|
348
|
-
WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
|
|
349
|
-
LIMIT ?`)
|
|
350
|
-
.all(MAX_CANDIDATES_PER_ANALYSIS);
|
|
351
|
-
}
|
|
352
|
-
return rows.map((r) => ({
|
|
353
|
-
id: r.id,
|
|
354
|
-
title: r.title,
|
|
355
|
-
doClause: r.doClause ?? null,
|
|
356
|
-
dontClause: r.dontClause ?? null,
|
|
357
|
-
coreCode: r.coreCode ?? null,
|
|
358
|
-
category: r.category ?? null,
|
|
359
|
-
trigger: r.trigger ?? null,
|
|
360
|
-
whenClause: r.whenClause ?? null,
|
|
361
|
-
guardPattern: r.guardPattern ?? null,
|
|
362
|
-
}));
|
|
325
|
+
const entries = await this.#knowledgeRepo.findAllByLifecycles(COUNTABLE_LIFECYCLES);
|
|
326
|
+
return entries.slice(0, MAX_CANDIDATES_PER_ANALYSIS).map(toSummary);
|
|
363
327
|
}
|
|
364
328
|
catch (err) {
|
|
365
329
|
this.#logger.warn(`ConsolidationAdvisor: failed to load recipes: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -16,19 +16,12 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module service/evolution/ContentPatcher
|
|
18
18
|
*/
|
|
19
|
+
import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
|
|
20
|
+
import type { RecipeSourceRefRepositoryImpl } from '../../repository/sourceref/RecipeSourceRefRepository.js';
|
|
19
21
|
import type { ContentPatchResult } from '../../types/evolution.js';
|
|
20
|
-
interface DatabaseLike {
|
|
21
|
-
prepare(sql: string): {
|
|
22
|
-
all(...params: unknown[]): Record<string, unknown>[];
|
|
23
|
-
get(...params: unknown[]): Record<string, unknown> | undefined;
|
|
24
|
-
run(...params: unknown[]): {
|
|
25
|
-
changes: number;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
22
|
export declare class ContentPatcher {
|
|
30
23
|
#private;
|
|
31
|
-
constructor(
|
|
24
|
+
constructor(knowledgeRepo: KnowledgeRepositoryImpl, sourceRefRepo: RecipeSourceRefRepositoryImpl);
|
|
32
25
|
/**
|
|
33
26
|
* 从 Proposal evidence 提取 suggestedChanges 并应用到 Recipe
|
|
34
27
|
*
|
|
@@ -39,6 +32,5 @@ export declare class ContentPatcher {
|
|
|
39
32
|
type: string;
|
|
40
33
|
targetRecipeId: string;
|
|
41
34
|
evidence: Record<string, unknown>[];
|
|
42
|
-
}, patchSource?: 'agent-suggestion' | 'correction' | 'merge'): ContentPatchResult
|
|
35
|
+
}, patchSource?: 'agent-suggestion' | 'correction' | 'merge'): Promise<ContentPatchResult>;
|
|
43
36
|
}
|
|
44
|
-
export {};
|
|
@@ -31,20 +31,22 @@ const PATCHABLE_FIELDS = new Set([
|
|
|
31
31
|
]);
|
|
32
32
|
/* ────────────────────── Class ────────────────────── */
|
|
33
33
|
export class ContentPatcher {
|
|
34
|
-
#
|
|
34
|
+
#knowledgeRepo;
|
|
35
|
+
#sourceRefRepo;
|
|
35
36
|
#logger = Logger.getInstance();
|
|
36
|
-
constructor(
|
|
37
|
-
this.#
|
|
37
|
+
constructor(knowledgeRepo, sourceRefRepo) {
|
|
38
|
+
this.#knowledgeRepo = knowledgeRepo;
|
|
39
|
+
this.#sourceRefRepo = sourceRefRepo;
|
|
38
40
|
}
|
|
39
41
|
/**
|
|
40
42
|
* 从 Proposal evidence 提取 suggestedChanges 并应用到 Recipe
|
|
41
43
|
*
|
|
42
44
|
* @returns ContentPatchResult — success: 是否成功应用了至少一个 patch
|
|
43
45
|
*/
|
|
44
|
-
applyProposal(proposal, patchSource = 'agent-suggestion') {
|
|
46
|
+
async applyProposal(proposal, patchSource = 'agent-suggestion') {
|
|
45
47
|
const recipeId = proposal.targetRecipeId;
|
|
46
48
|
// 1. 获取 Recipe 当前内容
|
|
47
|
-
const recipe = this.#getRecipe(recipeId);
|
|
49
|
+
const recipe = await this.#getRecipe(recipeId);
|
|
48
50
|
if (!recipe) {
|
|
49
51
|
return this.#skipResult(recipeId, patchSource, 'Recipe not found');
|
|
50
52
|
}
|
|
@@ -66,7 +68,7 @@ export class ContentPatcher {
|
|
|
66
68
|
return this.#skipResult(recipeId, patchSource, 'No valid fields to patch');
|
|
67
69
|
}
|
|
68
70
|
// 6. 持久化
|
|
69
|
-
this.#persistRecipe(recipe);
|
|
71
|
+
await this.#persistRecipe(recipe);
|
|
70
72
|
// 7. 创建 after 快照
|
|
71
73
|
const afterSnapshot = this.#createSnapshot(recipe);
|
|
72
74
|
this.#logger.info(`[ContentPatcher] Applied ${fieldsPatched.length} patches to recipe ${recipeId}: ${fieldsPatched.join(', ')}`);
|
|
@@ -257,20 +259,47 @@ export class ContentPatcher {
|
|
|
257
259
|
};
|
|
258
260
|
}
|
|
259
261
|
/* ═══════════════════ DB ═══════════════════ */
|
|
260
|
-
#getRecipe(recipeId) {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
async #getRecipe(recipeId) {
|
|
263
|
+
const entry = await this.#knowledgeRepo.findById(recipeId);
|
|
264
|
+
if (!entry) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
// 从 recipe_source_refs 表读取关联的源引用路径
|
|
268
|
+
const refs = this.#sourceRefRepo.findByRecipeId(entry.id);
|
|
269
|
+
const sourcePaths = refs.map((r) => r.sourcePath);
|
|
270
|
+
return {
|
|
271
|
+
id: entry.id,
|
|
272
|
+
title: entry.title,
|
|
273
|
+
coreCode: entry.coreCode || '',
|
|
274
|
+
doClause: entry.doClause || '',
|
|
275
|
+
dontClause: entry.dontClause || '',
|
|
276
|
+
whenClause: entry.whenClause || '',
|
|
277
|
+
content: JSON.stringify(entry.content || {}),
|
|
278
|
+
sourceRefs: JSON.stringify(sourcePaths),
|
|
279
|
+
headers: JSON.stringify(entry.headers || []),
|
|
280
|
+
};
|
|
266
281
|
}
|
|
267
|
-
#persistRecipe(recipe) {
|
|
268
|
-
this.#
|
|
269
|
-
.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
async #persistRecipe(recipe) {
|
|
283
|
+
await this.#knowledgeRepo.update(recipe.id, {
|
|
284
|
+
coreCode: recipe.coreCode,
|
|
285
|
+
doClause: recipe.doClause,
|
|
286
|
+
dontClause: recipe.dontClause,
|
|
287
|
+
whenClause: recipe.whenClause,
|
|
288
|
+
content: safeJsonParse(recipe.content, {}),
|
|
289
|
+
headers: safeJsonParse(recipe.headers, []),
|
|
290
|
+
});
|
|
291
|
+
// 同步 sourceRefs 到 recipe_source_refs 表
|
|
292
|
+
const newPaths = safeJsonParse(recipe.sourceRefs, []);
|
|
293
|
+
const now = Math.floor(Date.now() / 1000);
|
|
294
|
+
this.#sourceRefRepo.deleteByRecipeId(recipe.id);
|
|
295
|
+
for (const sourcePath of newPaths) {
|
|
296
|
+
this.#sourceRefRepo.upsert({
|
|
297
|
+
recipeId: recipe.id,
|
|
298
|
+
sourcePath,
|
|
299
|
+
status: 'active',
|
|
300
|
+
verifiedAt: now,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
274
303
|
}
|
|
275
304
|
/* ═══════════════════ Helpers ═══════════════════ */
|
|
276
305
|
#skipResult(recipeId, patchSource, reason) {
|
|
@@ -13,11 +13,7 @@
|
|
|
13
13
|
* 结果:硬矛盾 (confidence ≥ 0.8) / 软矛盾 (0.4-0.8)
|
|
14
14
|
*/
|
|
15
15
|
import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
|
|
16
|
-
|
|
17
|
-
prepare(sql: string): {
|
|
18
|
-
all(...params: unknown[]): Record<string, unknown>[];
|
|
19
|
-
};
|
|
20
|
-
}
|
|
16
|
+
import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
|
|
21
17
|
export interface ContradictionResult {
|
|
22
18
|
recipeA: string;
|
|
23
19
|
recipeB: string;
|
|
@@ -37,13 +33,13 @@ interface RecipeEntry {
|
|
|
37
33
|
}
|
|
38
34
|
export declare class ContradictionDetector {
|
|
39
35
|
#private;
|
|
40
|
-
constructor(
|
|
36
|
+
constructor(knowledgeRepo: KnowledgeRepositoryImpl, options?: {
|
|
41
37
|
signalBus?: SignalBus;
|
|
42
38
|
});
|
|
43
39
|
/**
|
|
44
40
|
* 检测所有 active/staging/evolving Recipe 之间的矛盾
|
|
45
41
|
*/
|
|
46
|
-
detectAll(): ContradictionResult[]
|
|
42
|
+
detectAll(): Promise<ContradictionResult[]>;
|
|
47
43
|
/**
|
|
48
44
|
* 检测两条 Recipe 是否矛盾
|
|
49
45
|
*/
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* 结果:硬矛盾 (confidence ≥ 0.8) / 软矛盾 (0.4-0.8)
|
|
14
14
|
*/
|
|
15
15
|
var _a;
|
|
16
|
+
import { CONSUMABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
|
|
16
17
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
17
18
|
/* ────────────────────── Constants ────────────────────── */
|
|
18
19
|
const NEGATION_PATTERNS_ZH = /不(再)?使用|禁止|废弃|移除|取消|停止|不要|不采用|弃用|淘汰/;
|
|
@@ -71,18 +72,18 @@ const STOP_WORDS = new Set([
|
|
|
71
72
|
]);
|
|
72
73
|
/* ────────────────────── Class ────────────────────── */
|
|
73
74
|
export class ContradictionDetector {
|
|
74
|
-
#
|
|
75
|
+
#knowledgeRepo;
|
|
75
76
|
#signalBus;
|
|
76
77
|
#logger = Logger.getInstance();
|
|
77
|
-
constructor(
|
|
78
|
-
this.#
|
|
78
|
+
constructor(knowledgeRepo, options = {}) {
|
|
79
|
+
this.#knowledgeRepo = knowledgeRepo;
|
|
79
80
|
this.#signalBus = options.signalBus ?? null;
|
|
80
81
|
}
|
|
81
82
|
/**
|
|
82
83
|
* 检测所有 active/staging/evolving Recipe 之间的矛盾
|
|
83
84
|
*/
|
|
84
|
-
detectAll() {
|
|
85
|
-
const recipes = this.#loadRecipes();
|
|
85
|
+
async detectAll() {
|
|
86
|
+
const recipes = await this.#loadRecipes();
|
|
86
87
|
const results = [];
|
|
87
88
|
for (let i = 0; i < recipes.length; i++) {
|
|
88
89
|
for (let j = i + 1; j < recipes.length; j++) {
|
|
@@ -155,26 +156,18 @@ export class ContradictionDetector {
|
|
|
155
156
|
};
|
|
156
157
|
}
|
|
157
158
|
/* ── Internal ── */
|
|
158
|
-
#loadRecipes() {
|
|
159
|
+
async #loadRecipes() {
|
|
159
160
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
id: r.id,
|
|
171
|
-
title: r.title,
|
|
172
|
-
lifecycle: r.lifecycle,
|
|
173
|
-
doClause: r.doClause ?? null,
|
|
174
|
-
dontClause: r.dontClause ?? null,
|
|
175
|
-
guardPattern: r.guardPattern ?? null,
|
|
176
|
-
description: r.description ?? null,
|
|
177
|
-
content_markdown: r.content_markdown ?? null,
|
|
161
|
+
const entries = await this.#knowledgeRepo.findAllByLifecycles(CONSUMABLE_LIFECYCLES);
|
|
162
|
+
return entries.map((e) => ({
|
|
163
|
+
id: e.id,
|
|
164
|
+
title: e.title,
|
|
165
|
+
lifecycle: e.lifecycle,
|
|
166
|
+
doClause: e.doClause || null,
|
|
167
|
+
dontClause: e.dontClause || null,
|
|
168
|
+
guardPattern: e.content?.pattern || null,
|
|
169
|
+
description: e.description || null,
|
|
170
|
+
content_markdown: e.content?.markdown || null,
|
|
178
171
|
}));
|
|
179
172
|
}
|
|
180
173
|
catch {
|
|
@@ -18,13 +18,11 @@
|
|
|
18
18
|
* 20-39: 严重 → Grace Period 缩短到 15d
|
|
19
19
|
* 0-19: 死亡 → 跳过确认直接 deprecated
|
|
20
20
|
*/
|
|
21
|
+
import type { DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
|
|
21
22
|
import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
get(...params: unknown[]): Record<string, unknown> | undefined;
|
|
26
|
-
};
|
|
27
|
-
}
|
|
23
|
+
import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
|
|
24
|
+
import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
|
|
25
|
+
import type { RecipeSourceRefRepositoryImpl } from '../../repository/sourceref/RecipeSourceRefRepository.js';
|
|
28
26
|
export interface DecaySignal {
|
|
29
27
|
recipeId: string;
|
|
30
28
|
strategy: DecayStrategy;
|
|
@@ -57,16 +55,19 @@ interface RecipeForDecay {
|
|
|
57
55
|
}
|
|
58
56
|
export declare class DecayDetector {
|
|
59
57
|
#private;
|
|
60
|
-
constructor(
|
|
58
|
+
constructor(knowledgeRepo: KnowledgeRepositoryImpl, options?: {
|
|
61
59
|
signalBus?: SignalBus;
|
|
60
|
+
knowledgeEdgeRepo?: KnowledgeEdgeRepositoryImpl;
|
|
61
|
+
sourceRefRepo?: RecipeSourceRefRepositoryImpl;
|
|
62
|
+
drizzle?: DrizzleDB;
|
|
62
63
|
});
|
|
63
64
|
/**
|
|
64
65
|
* 扫描所有 active 条目的衰退状态
|
|
65
66
|
*/
|
|
66
|
-
scanAll(): DecayScoreResult[]
|
|
67
|
+
scanAll(): Promise<DecayScoreResult[]>;
|
|
67
68
|
/**
|
|
68
69
|
* 评估单条 Recipe 的衰退状态
|
|
69
70
|
*/
|
|
70
|
-
evaluate(recipe: RecipeForDecay): DecayScoreResult
|
|
71
|
+
evaluate(recipe: RecipeForDecay): Promise<DecayScoreResult>;
|
|
71
72
|
}
|
|
72
73
|
export {};
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* 0-19: 死亡 → 跳过确认直接 deprecated
|
|
20
20
|
*/
|
|
21
21
|
var _a;
|
|
22
|
+
import { and, like, sql } from 'drizzle-orm';
|
|
23
|
+
import { auditLogs } from '../../infrastructure/database/drizzle/schema.js';
|
|
22
24
|
import Logger from '../../infrastructure/logging/Logger.js';
|
|
23
25
|
/* ────────────────────── Helpers ────────────────────── */
|
|
24
26
|
/**
|
|
@@ -49,21 +51,27 @@ const SCORE_WEIGHTS = {
|
|
|
49
51
|
};
|
|
50
52
|
/* ────────────────────── Class ────────────────────── */
|
|
51
53
|
export class DecayDetector {
|
|
52
|
-
#
|
|
54
|
+
#knowledgeRepo;
|
|
55
|
+
#edgeRepo;
|
|
56
|
+
#sourceRefRepo;
|
|
57
|
+
#drizzle;
|
|
53
58
|
#signalBus;
|
|
54
59
|
#logger = Logger.getInstance();
|
|
55
|
-
constructor(
|
|
56
|
-
this.#
|
|
60
|
+
constructor(knowledgeRepo, options = {}) {
|
|
61
|
+
this.#knowledgeRepo = knowledgeRepo;
|
|
62
|
+
this.#edgeRepo = options.knowledgeEdgeRepo ?? null;
|
|
63
|
+
this.#sourceRefRepo = options.sourceRefRepo ?? null;
|
|
64
|
+
this.#drizzle = options.drizzle ?? null;
|
|
57
65
|
this.#signalBus = options.signalBus ?? null;
|
|
58
66
|
}
|
|
59
67
|
/**
|
|
60
68
|
* 扫描所有 active 条目的衰退状态
|
|
61
69
|
*/
|
|
62
|
-
scanAll() {
|
|
63
|
-
const recipes = this.#loadActiveRecipes();
|
|
70
|
+
async scanAll() {
|
|
71
|
+
const recipes = await this.#loadActiveRecipes();
|
|
64
72
|
const results = [];
|
|
65
73
|
for (const recipe of recipes) {
|
|
66
|
-
const result = this.evaluate(recipe);
|
|
74
|
+
const result = await this.evaluate(recipe);
|
|
67
75
|
results.push(result);
|
|
68
76
|
}
|
|
69
77
|
// 发射衰退信号
|
|
@@ -87,7 +95,7 @@ export class DecayDetector {
|
|
|
87
95
|
/**
|
|
88
96
|
* 评估单条 Recipe 的衰退状态
|
|
89
97
|
*/
|
|
90
|
-
evaluate(recipe) {
|
|
98
|
+
async evaluate(recipe) {
|
|
91
99
|
const stats = _a.#parseStats(recipe.stats);
|
|
92
100
|
const signals = [];
|
|
93
101
|
const now = Date.now();
|
|
@@ -127,7 +135,7 @@ export class DecayDetector {
|
|
|
127
135
|
});
|
|
128
136
|
}
|
|
129
137
|
// 策略 3: 符号漂移(由 ReverseGuard 提供,此处从 DB 查 drift 标记)
|
|
130
|
-
if (this.#hasSymbolDrift(recipe.id)) {
|
|
138
|
+
if (await this.#hasSymbolDrift(recipe.id)) {
|
|
131
139
|
signals.push({
|
|
132
140
|
recipeId: recipe.id,
|
|
133
141
|
strategy: 'symbol_drift',
|
|
@@ -135,7 +143,7 @@ export class DecayDetector {
|
|
|
135
143
|
});
|
|
136
144
|
}
|
|
137
145
|
// 策略 3b: 来源引用失效(由 SourceRefReconciler 填充 recipe_source_refs)
|
|
138
|
-
const staleRefCount = this.#getStaleSourceRefCount(recipe.id);
|
|
146
|
+
const staleRefCount = await this.#getStaleSourceRefCount(recipe.id);
|
|
139
147
|
if (staleRefCount > 0) {
|
|
140
148
|
signals.push({
|
|
141
149
|
recipeId: recipe.id,
|
|
@@ -144,7 +152,7 @@ export class DecayDetector {
|
|
|
144
152
|
});
|
|
145
153
|
}
|
|
146
154
|
// 策略 4: 被取代(有 deprecated_by 关系指向更新版本)
|
|
147
|
-
if (this.#isSuperseded(recipe.id)) {
|
|
155
|
+
if (await this.#isSuperseded(recipe.id)) {
|
|
148
156
|
signals.push({
|
|
149
157
|
recipeId: recipe.id,
|
|
150
158
|
strategy: 'superseded',
|
|
@@ -152,7 +160,7 @@ export class DecayDetector {
|
|
|
152
160
|
});
|
|
153
161
|
}
|
|
154
162
|
// 计算 decayScore(staleRatio 影响 quality 维度)
|
|
155
|
-
const staleRatio = this.#getSourceRefStaleRatio(recipe.id);
|
|
163
|
+
const staleRatio = await this.#getSourceRefStaleRatio(recipe.id);
|
|
156
164
|
const dimensions = this.#computeScoreDimensions(stats, recipe, { staleRatio });
|
|
157
165
|
const decayScore = Math.round(dimensions.freshness * SCORE_WEIGHTS.freshness * 100 +
|
|
158
166
|
dimensions.usage * SCORE_WEIGHTS.usage * 100 +
|
|
@@ -171,23 +179,24 @@ export class DecayDetector {
|
|
|
171
179
|
};
|
|
172
180
|
}
|
|
173
181
|
/* ── Internal ── */
|
|
174
|
-
#loadActiveRecipes() {
|
|
182
|
+
async #loadActiveRecipes() {
|
|
175
183
|
try {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
const entries = await this.#knowledgeRepo.findAllByLifecycles(['active']);
|
|
185
|
+
return entries.map((e) => {
|
|
186
|
+
const qualityObj = typeof e.quality === 'object'
|
|
187
|
+
? {
|
|
188
|
+
grade: e.quality.grade ?? null,
|
|
189
|
+
score: e.quality.overall ?? null,
|
|
190
|
+
}
|
|
191
|
+
: _a.#parseQuality(null);
|
|
183
192
|
return {
|
|
184
|
-
id:
|
|
185
|
-
title:
|
|
186
|
-
lifecycle:
|
|
187
|
-
stats:
|
|
193
|
+
id: e.id,
|
|
194
|
+
title: e.title,
|
|
195
|
+
lifecycle: e.lifecycle,
|
|
196
|
+
stats: typeof e.stats === 'object' ? JSON.stringify(e.stats) : null,
|
|
188
197
|
quality_grade: qualityObj.grade,
|
|
189
198
|
quality_score: qualityObj.score,
|
|
190
|
-
created_at:
|
|
199
|
+
created_at: e.createdAt ?? null,
|
|
191
200
|
};
|
|
192
201
|
});
|
|
193
202
|
}
|
|
@@ -240,61 +249,58 @@ export class DecayDetector {
|
|
|
240
249
|
const authority = Math.min(1, authorityRaw / 100);
|
|
241
250
|
return { freshness, usage, quality, authority };
|
|
242
251
|
}
|
|
243
|
-
#hasSymbolDrift(recipeId) {
|
|
252
|
+
async #hasSymbolDrift(recipeId) {
|
|
244
253
|
try {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
.
|
|
254
|
+
if (!this.#drizzle) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
const row = this.#drizzle
|
|
258
|
+
.select({ id: auditLogs.id })
|
|
259
|
+
.from(auditLogs)
|
|
260
|
+
.where(and(like(auditLogs.action, '%ReverseGuard%'), sql `json_extract(${auditLogs.operationData}, '$.target') = ${recipeId}`))
|
|
261
|
+
.limit(1)
|
|
262
|
+
.get();
|
|
252
263
|
return !!row;
|
|
253
264
|
}
|
|
254
265
|
catch {
|
|
255
266
|
return false;
|
|
256
267
|
}
|
|
257
268
|
}
|
|
258
|
-
#getStaleSourceRefCount(recipeId) {
|
|
269
|
+
async #getStaleSourceRefCount(recipeId) {
|
|
259
270
|
try {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
271
|
+
if (!this.#sourceRefRepo) {
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
const refs = this.#sourceRefRepo.findByRecipeId(recipeId);
|
|
275
|
+
return refs.filter((r) => r.status === 'stale').length;
|
|
265
276
|
}
|
|
266
277
|
catch {
|
|
267
|
-
// recipe_source_refs 表可能不存在
|
|
268
278
|
return 0;
|
|
269
279
|
}
|
|
270
280
|
}
|
|
271
|
-
|
|
272
|
-
#getSourceRefStaleRatio(recipeId) {
|
|
281
|
+
async #getSourceRefStaleRatio(recipeId) {
|
|
273
282
|
try {
|
|
274
|
-
|
|
275
|
-
.prepare(`SELECT
|
|
276
|
-
SUM(CASE WHEN status = 'stale' THEN 1 ELSE 0 END) AS stale,
|
|
277
|
-
COUNT(*) AS total
|
|
278
|
-
FROM recipe_source_refs
|
|
279
|
-
WHERE recipe_id = ?`)
|
|
280
|
-
.get(recipeId);
|
|
281
|
-
if (!row || row.total === 0) {
|
|
283
|
+
if (!this.#sourceRefRepo) {
|
|
282
284
|
return 0;
|
|
283
285
|
}
|
|
284
|
-
|
|
286
|
+
const refs = this.#sourceRefRepo.findByRecipeId(recipeId);
|
|
287
|
+
if (refs.length === 0) {
|
|
288
|
+
return 0;
|
|
289
|
+
}
|
|
290
|
+
const stale = refs.filter((r) => r.status === 'stale').length;
|
|
291
|
+
return stale / refs.length;
|
|
285
292
|
}
|
|
286
293
|
catch {
|
|
287
294
|
return 0;
|
|
288
295
|
}
|
|
289
296
|
}
|
|
290
|
-
#isSuperseded(recipeId) {
|
|
297
|
+
async #isSuperseded(recipeId) {
|
|
291
298
|
try {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return !!row;
|
|
299
|
+
if (!this.#edgeRepo) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
const edges = await this.#edgeRepo.findByRelation(recipeId, 'recipe', 'deprecated_by');
|
|
303
|
+
return edges.length > 0;
|
|
298
304
|
}
|
|
299
305
|
catch {
|
|
300
306
|
return false;
|