新增: 批次工作落地(推进链/评估闭环/事件总线/并发/加固) + 技术债清理 + 文档整理

后端:
- 工作流推进链(D-03):advance_task/状态机/闸门走 df-nodes Node trait,conditions 条件引擎扩展
- 想法评估闭环:启发式评分+对抗评估,df-ideas/scoring + df-storage/idea_eval_repo + idea 前端打通
- 全局事件数据总线:df-ai/context+context_helpers+augmentation 跨模块解耦
- AI planner/plan_hint/intent:aichat B 路线并行多轮基础
- patch_file 加固(TD-03/04):读改写整体锁防 lost update,expected_hash 合约闭环
- 压缩超时兜底(F-15 卡死根治)
- F-09 多会话并发:LlmConcurrency per-conv + streamingGuard 前端守护 + verify 脚本
- 知识注入 DRY/skills/audit 扩展

清理:
- aichat 技术债(误报 allow/死导入/过时注释 30 项)
- URGENT.md 删除(11 项加急全解决/迁 todo)
- 文档整理(todo/待决策/待审查/ARCHITECTURE/INDEX + 总线/技术债审查新文档)
This commit is contained in:
lxy
2026-06-21 20:51:26 +08:00
parent 330bb7f505
commit bd6a41fe6e
111 changed files with 11931 additions and 1033 deletions
+58 -4
View File
@@ -135,6 +135,7 @@ pub async fn knowledge_create(
source_project: input.source_project,
source_ref: input.source_ref,
reasoning: None,
embedding_status: None,
created_at: now.clone(),
updated_at: now,
};
@@ -281,6 +282,21 @@ pub async fn knowledge_archive(
knowledge_update_status(state, id, "archived".to_string()).await
}
/// 重新生成向量嵌入(补偿重试)— P1 修复(嵌入失败无标记)的补偿入口
///
/// 触发条件:embedding_status='failed' 的已发布知识(provider 临时不可用导致永久无向量索引)。
/// 行为:fire-and-forget,后台逐条重跑嵌入生成(成功置 done,失败仍 failed 可再次触发)。
/// 返回值:本次触发重试的条数(0 表示无 failed 条目或 vector_enabled 关闭)。
#[tauri::command]
pub async fn knowledge_retry_embedding(
state: State<'_, AppState>,
) -> Result<usize, String> {
let count = crate::commands::ai::retry_failed_embeddings(&state)
.await
.map_err(err_str)?;
Ok(count)
}
// ============================================================
// 配置 + 手动提炼
// ============================================================
@@ -300,8 +316,18 @@ pub async fn knowledge_save_config(
state: State<'_, AppState>,
config: KnowledgeConfig,
) -> Result<bool, String> {
let mut cfg = state.knowledge_config.lock().await;
*cfg = config;
// P0(设置走查-2026-06-21):落 Settings KV 持久化,reload_knowledge_config 启动恢复
// (原纯内存 Arc<Mutex> 启动 default 覆盖致 8 项配置重启全丢)。
let json = serde_json::to_string(&config).map_err(|e| e.to_string())?;
{
let mut cfg = state.knowledge_config.lock().await;
*cfg = config;
}
state
.settings
.set(crate::state::KNOWLEDGE_CONFIG_KEY, &json)
.await
.map_err(|e| e.to_string())?;
Ok(true)
}
@@ -375,21 +401,41 @@ pub async fn knowledge_update(
.await
.map_err(err_str)?
.ok_or_else(|| format!("知识不存在: {id}"))?;
// P1 修复(KP-5 审计断档):记录本次实际改动的字段,供 updated 生命线事件审计展示。
// 只在值确实变化时计入 changed_fields(避免无改动也产生 updated 噪音事件)。
let mut changed_fields: Vec<&'static str> = Vec::new();
if let Some(v) = input.title {
if record.title != v {
changed_fields.push("title");
}
record.title = v;
}
if let Some(v) = input.content {
if record.content != v {
changed_fields.push("content");
}
record.content = v;
}
if let Some(v) = input.tags {
if record.tags.as_deref() != Some(v.as_str()) {
changed_fields.push("tags");
}
record.tags = Some(v);
}
// 空串 = 清空(前端编辑器清空 confidence/reasoning 输入框时传 "")
if let Some(v) = input.confidence {
record.confidence = if v.is_empty() { None } else { Some(v) };
let new_conf = if v.is_empty() { None } else { Some(v) };
if record.confidence != new_conf {
changed_fields.push("confidence");
}
record.confidence = new_conf;
}
if let Some(v) = input.reasoning {
record.reasoning = if v.is_empty() { None } else { Some(v) };
let new_reason = if v.is_empty() { None } else { Some(v) };
if record.reasoning != new_reason {
changed_fields.push("reasoning");
}
record.reasoning = new_reason;
}
record.updated_at = now_millis();
state
@@ -397,6 +443,14 @@ pub async fn knowledge_update(
.update_full(&record)
.await
.map_err(err_str)?;
// 生命线:编辑产生(fire-and-forget)。
// 仅在确有字段改动时记录,无改动不产噪音事件(对齐 create/update_status 的语义粒度)。
// source_ref="ui" 标识编辑来自前端 UI(未来可细分 detail/inbox,当前统一 ui)。
if !changed_fields.is_empty() {
KnowledgeTimeline::new(&state.db)
.record_updated(&id, &changed_fields, "ui")
.await;
}
Ok(record)
}