autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
97 lines (96 loc) • 3.88 kB
TypeScript
/**
* ProposalRepository — evolution_proposals 表 CRUD (Drizzle ORM)
*
* 操作 evolution_proposals 表,存储进化提案(merge/supersede/enhance/deprecate/
* reorganize/contradiction/correction)。
*
* 设计要求:
* - 去重:同 target + 同 type 不允许多个 observing 状态的 Proposal
* - Rate Limit:同一 target 不允许同时存在多个相同类型的 observing Proposal
* - JSON 字段(evidence/related_recipe_ids)序列化/反序列化
*
* Drizzle 迁移策略 (Phase 5a):
* - 全部 raw SQL → Drizzle 类型安全 API
* - 构造器接收 DrizzleDB(不再需要 raw Database)
*/
import type { DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
/** Proposal 类型 — 统一标准 */
export type ProposalType = 'merge' | 'supersede' | 'enhance' | 'deprecate' | 'reorganize' | 'contradiction' | 'correction';
/** Proposal 来源 */
export type ProposalSource = 'ide-agent' | 'metabolism' | 'decay-scan';
/** Proposal 状态 */
export type ProposalStatus = 'pending' | 'observing' | 'executed' | 'rejected' | 'expired';
/** evolution_proposals 行对象 */
export interface ProposalRecord {
id: string;
type: ProposalType;
targetRecipeId: string;
relatedRecipeIds: string[];
confidence: number;
source: ProposalSource;
description: string;
evidence: Record<string, unknown>[];
status: ProposalStatus;
proposedAt: number;
expiresAt: number;
resolvedAt: number | null;
resolvedBy: string | null;
resolution: string | null;
}
/** 创建 Proposal 输入 */
export interface CreateProposalInput {
type: ProposalType;
targetRecipeId: string;
relatedRecipeIds?: string[];
confidence: number;
source: ProposalSource;
description: string;
evidence?: Record<string, unknown>[];
status?: ProposalStatus;
expiresAt?: number;
}
/** 查询过滤器 */
export interface ProposalFilter {
status?: ProposalStatus | ProposalStatus[];
type?: ProposalType;
targetRecipeId?: string;
source?: ProposalSource;
expiredBefore?: number;
}
export declare class ProposalRepository {
#private;
constructor(drizzle: DrizzleDB);
/**
* 创建 Proposal 并写入 DB。
*
* - 自动生成 ID(ep-{timestamp}-{random})
* - 自动设定 expiresAt(按 type 默认窗口)
* - 自动判断 status(低风险 + 高置信度 → observing,否则 pending)
* - 去重:同 target + 同 type 已有 pending/observing 时拒绝创建
*/
create(input: CreateProposalInput): ProposalRecord | null;
/** 按 ID 查询 */
findById(id: string): ProposalRecord | null;
/** 按条件查询 */
find(filter?: ProposalFilter): ProposalRecord[];
/** 查询已到期的 observing 状态 Proposal */
findExpiredObserving(): ProposalRecord[];
/** 查询所有未完成的 Proposal(pending + observing) */
findActive(): ProposalRecord[];
/** 按 target Recipe ID 查询活跃 Proposal */
findByTarget(targetRecipeId: string): ProposalRecord[];
/** 将 Proposal 状态转为 observing */
startObserving(id: string): boolean;
/** 标记 Proposal 为已执行 */
markExecuted(id: string, resolution: string, resolvedBy?: string): boolean;
/** 标记 Proposal 为已拒绝 */
markRejected(id: string, resolution: string, resolvedBy?: string): boolean;
/** 标记 Proposal 为过期 */
markExpired(id: string): boolean;
/** 更新 evidence(用于追加观察期指标快照) */
updateEvidence(id: string, evidence: Record<string, unknown>[]): boolean;
/** 按 target Recipe ID 删除所有 Proposal(用于知识删除时清理关联提案) */
deleteByTargetRecipeId(targetRecipeId: string): number;
/** 统计各状态的 Proposal 数量 */
stats(): Record<ProposalStatus, number>;
}