UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

226 lines (225 loc) 9.06 kB
/** * KnowledgeMetabolism — 知识新陈代谢总线 * * 治理总线:编排三种进化策略 (矛盾检测 + 冗余分析 + 衰退检测) * 产出 EvolutionProposal,通过 ConfidenceRouter + 状态机 驱动转换。 * * 入口: * - runFullCycle() — 完整治理周期(日常定时 / 手动触发) * - checkDecay() — 只做衰退扫描 * - checkContradictions() — 只做矛盾检测 * - checkRedundancy() — 只做冗余分析 */ import Logger from '../../infrastructure/logging/Logger.js'; /* ────────────────────── Constants ────────────────────── */ const PROPOSAL_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days /* ────────────────────── Class ────────────────────── */ export class KnowledgeMetabolism { #contradictionDetector; #redundancyAnalyzer; #decayDetector; #signalBus; #reportStore; #proposalRepo; #logger = Logger.getInstance(); #pendingTriggers = []; #debounceTimer = null; #running = false; constructor(options) { this.#contradictionDetector = options.contradictionDetector; this.#redundancyAnalyzer = options.redundancyAnalyzer; this.#decayDetector = options.decayDetector; this.#signalBus = options.signalBus ?? null; this.#reportStore = options.reportStore ?? null; this.#proposalRepo = options.proposalRepository ?? null; // Phase 2: 订阅告警型信号,触发代谢周期 if (this.#signalBus) { this.#signalBus.subscribe('decay|quality|anomaly', (signal) => { this.#pendingTriggers.push(signal); this.#scheduleMetabolism(); }); } } #scheduleMetabolism() { // 当前正在执行周期时,忽略信号(防止自身产出的信号导致无限循环) if (this.#running) { return; } if (this.#debounceTimer) { return; } this.#debounceTimer = setTimeout(() => { this.#debounceTimer = null; if (this.#pendingTriggers.length > 0 && !this.#running) { void this.runFullCycle(); this.#pendingTriggers = []; } }, 30_000); } /** * 执行完整治理周期 */ async runFullCycle() { if (this.#running) { this.#logger.warn('KnowledgeMetabolism: cycle already in progress, skipping'); return { contradictions: [], redundancies: [], decayResults: [], proposals: [], summary: { totalScanned: 0, contradictionCount: 0, redundancyCount: 0, decayingCount: 0, proposalCount: 0, }, }; } this.#running = true; // 清除执行期间积累的信号,避免周期结束后立刻再次触发 this.#pendingTriggers = []; try { this.#logger.info('KnowledgeMetabolism: starting full governance cycle'); // 1. 衰退检测 const decayResults = await this.#decayDetector.scanAll(); // 2. 矛盾检测 const contradictions = await this.#contradictionDetector.detectAll(); // 3. 冗余分析 const redundancies = await this.#redundancyAnalyzer.analyzeAll(); // 4. 生成进化提案 const proposals = [ ...this.#proposalsFromContradictions(contradictions), ...this.#proposalsFromRedundancies(redundancies), ...this.#proposalsFromDecay(decayResults), ]; // 5. 持久化提案到 evolution_proposals 表 let persistedCount = 0; if (this.#proposalRepo && proposals.length > 0) { for (const p of proposals) { const sourceMap = { contradiction: 'metabolism', redundancy: 'metabolism', decay: 'decay-scan', enhancement: 'metabolism', }; const record = this.#proposalRepo.create({ type: p.type, targetRecipeId: p.targetRecipeId, relatedRecipeIds: p.relatedRecipeIds, confidence: p.confidence, source: sourceMap[p.source] ?? 'metabolism', description: p.description, evidence: p.evidence.map((e) => ({ detail: e })), }); if (record) { persistedCount++; } } } // 6. 写入治理报告(降级:同时写 ReportStore) if (this.#reportStore && proposals.length > 0) { void this.#reportStore.write({ category: 'governance', type: 'metabolism_cycle', producer: 'KnowledgeMetabolism', data: { proposalCount: proposals.length, persistedCount, contradictionCount: contradictions.length, redundancyCount: redundancies.length, decayingCount: decayResults.filter((d) => d.level !== 'healthy' && d.level !== 'watch') .length, }, timestamp: Date.now(), }); } const report = { contradictions, redundancies, decayResults, proposals, summary: { totalScanned: decayResults.length, contradictionCount: contradictions.length, redundancyCount: redundancies.length, decayingCount: decayResults.filter((d) => d.level !== 'healthy' && d.level !== 'watch') .length, proposalCount: proposals.length, }, }; this.#logger.info(`KnowledgeMetabolism: cycle complete — ${report.summary.proposalCount} proposals generated`); return report; } finally { this.#running = false; // 清除周期期间积累的信号,防止自身产出的信号立即触发下一轮 this.#pendingTriggers = []; } } /** * 只执行衰退扫描 */ async checkDecay() { return await this.#decayDetector.scanAll(); } /** * 只执行矛盾检测 */ async checkContradictions() { return await this.#contradictionDetector.detectAll(); } /** * 只执行冗余分析 */ async checkRedundancy() { return await this.#redundancyAnalyzer.analyzeAll(); } /* ── Proposal Generation ── */ #proposalsFromContradictions(results) { const now = Date.now(); return results.map((r) => ({ type: r.type === 'hard' ? 'contradiction' : 'correction', targetRecipeId: r.recipeA, relatedRecipeIds: [r.recipeB], confidence: r.confidence, source: 'contradiction', description: `${r.type === 'hard' ? 'Hard' : 'Soft'} contradiction detected between recipes`, evidence: r.evidence, proposedAt: now, expiresAt: now + PROPOSAL_TTL, })); } #proposalsFromRedundancies(results) { const now = Date.now(); return results.map((r) => ({ type: 'merge', targetRecipeId: r.recipeA, relatedRecipeIds: [r.recipeB], confidence: r.similarity, source: 'redundancy', description: `Redundant content detected (similarity: ${(r.similarity * 100).toFixed(0)}%)`, evidence: Object.entries(r.dimensions) .filter(([, v]) => v > 0) .map(([k, v]) => `${k}: ${(v * 100).toFixed(0)}%`), proposedAt: now, expiresAt: now + PROPOSAL_TTL, })); } #proposalsFromDecay(results) { const now = Date.now(); return results .filter((r) => r.level === 'decaying' || r.level === 'severe' || r.level === 'dead') .map((r) => ({ type: 'deprecate', targetRecipeId: r.recipeId, relatedRecipeIds: [], confidence: Math.max(0.4, 1 - r.decayScore / 100), source: 'decay', description: `Decay detected: score=${r.decayScore}, level=${r.level}`, evidence: r.signals.map((s) => `${s.strategy}: ${s.detail}`), proposedAt: now, expiresAt: now + PROPOSAL_TTL, })); } }