修复: 前端 TS 阻断 + G1/G2 单测 + 归档已完成项

- 修复 vue-tsc 3 阻断: i18n 重复 err key 删除 + store 补 relateIdeas
- G1: extract_pinned_goal 单测 10 条(mention剥离/截断/空输入/全角冒号)
- G2: is_empty_tool_result 单测 11 条(JSON标记/中文/英文/非空判定)
- 归档: todo.md/docs/todo.md/待决策.md/待审查.md 已完成项迁入归档
This commit is contained in:
2026-06-27 22:35:37 +08:00
parent 6e1485e4f9
commit 5c539fe764
12 changed files with 615 additions and 2761 deletions

View File

@@ -2097,3 +2097,67 @@ struct ContinueSnapshot {
agent_language: Option<String>,
model_override: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
// ============================================================
// G2 is_empty_tool_result 单测
// ============================================================
#[test]
fn test_empty_tool_result_empty_string() {
assert!(is_empty_tool_result(""));
}
#[test]
fn test_empty_tool_result_whitespace() {
assert!(is_empty_tool_result(" "));
}
#[test]
fn test_empty_tool_result_total_zero() {
assert!(is_empty_tool_result(r#"{"total":0}"#));
}
#[test]
fn test_empty_tool_result_entries_empty() {
assert!(is_empty_tool_result(r#"{"entries":[]}"#));
}
#[test]
fn test_empty_tool_result_matches_empty() {
assert!(is_empty_tool_result(r#"{"matches":[]}"#));
}
#[test]
fn test_empty_tool_result_results_empty() {
assert!(is_empty_tool_result(r#"{"results":[]}"#));
}
#[test]
fn test_empty_tool_result_files_empty() {
assert!(is_empty_tool_result(r#"{"files":[]}"#));
}
#[test]
fn test_empty_tool_result_chinese_no_match() {
assert!(is_empty_tool_result("未找到相关文件"));
}
#[test]
fn test_empty_tool_result_english_no_match() {
assert!(is_empty_tool_result("No matches found"));
}
#[test]
fn test_non_empty_tool_result() {
assert!(!is_empty_tool_result(r#"{"total":5}"#));
}
#[test]
fn test_non_empty_tool_result_with_content() {
assert!(!is_empty_tool_result(r#"{"entries":["a.txt","b.txt"]}"#));
}
}

View File

@@ -1816,3 +1816,67 @@ pub async fn ai_stop_loop(
let _ = app.state::<AppState>().ai_event_bus.publish_event(ev);
Ok("ok".to_string())
}
#[cfg(test)]
mod tests {
use super::*;
// ============================================================
// G1 extract_pinned_goal 单测
// ============================================================
#[test]
fn test_extract_plain_goal() {
let goal = extract_pinned_goal("实现代码审查功能");
assert_eq!(goal, "实现代码审查功能");
}
#[test]
fn test_extract_strip_mention_suffix() {
let goal = extract_pinned_goal("分析灵感模块不足 [项目: DevFlow]");
assert_eq!(goal, "分析灵感模块不足");
}
#[test]
fn test_extract_strip_mention_prefix() {
let goal = extract_pinned_goal("[任务: T-123] 修复登录页白屏");
assert_eq!(goal, "修复登录页白屏");
}
#[test]
fn test_extract_empty_input() {
let goal = extract_pinned_goal("");
assert!(goal.is_empty());
}
#[test]
fn test_extract_only_mention() {
let goal = extract_pinned_goal("[项目: DevFlow]");
assert!(goal.is_empty());
}
#[test]
fn test_extract_english_kind() {
let goal = extract_pinned_goal("Fix login bug [task: T-789]");
assert_eq!(goal, "Fix login bug");
}
#[test]
fn test_extract_fullwidth_colon() {
let goal = extract_pinned_goal("重构模块 [项目DevFlow]");
assert_eq!(goal, "重构模块");
}
#[test]
fn test_extract_truncate_long() {
let long = "a".repeat(GOAL_MAX_CHARS + 100);
let goal = extract_pinned_goal(&long);
assert_eq!(goal.chars().count(), GOAL_MAX_CHARS);
}
#[test]
fn test_extract_mention_unclosed() {
let goal = extract_pinned_goal("测试 [项目: DevFlow");
assert_eq!(goal, "测试 [项目: DevFlow");
}
}