autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
226 lines (225 loc) • 9.06 kB
JavaScript
/**
* 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,
}));
}
}