fix: 修复飞轮聚合三处数据质量问题
- 最新快照改为按 at 字段取最大值,不再依赖写入顺序 - blocked_reasons 改为只取最新快照,消除历史快照反复计数导致的虚高 - 版本队列排序改为语义版本比较,修复字符串排序下 1.4.9 > 1.4.10 的问题 - 聚合时跳过 conventions_version=unknown 的历史脏数据项目
This commit is contained in:
parent
0065866f6b
commit
69c05380cc
@ -4,10 +4,10 @@ use std::path::Path;
|
|||||||
// ── 主节点:master CONVENTIONS.md 内容和版本(编译时嵌入)────────────────────
|
// ── 主节点:master CONVENTIONS.md 内容和版本(编译时嵌入)────────────────────
|
||||||
|
|
||||||
const MASTER_CONVENTIONS: &str = include_str!("../../../.blueprint/CONVENTIONS.md");
|
const MASTER_CONVENTIONS: &str = include_str!("../../../.blueprint/CONVENTIONS.md");
|
||||||
const MASTER_CONVENTIONS_VERSION: &str = "1.4.0";
|
const MASTER_CONVENTIONS_VERSION: &str = "1.4.2";
|
||||||
|
|
||||||
// CLAUDE.md 蓝图管理区模板(版本与 CONVENTIONS 保持一致)
|
// CLAUDE.md 蓝图管理区模板(版本与 CONVENTIONS 保持一致)
|
||||||
const CLAUDE_MANAGED_TEMPLATE: &str = r#"<!-- BLUEPRINT_MANAGED_START version="1.4.0" -->
|
const CLAUDE_MANAGED_TEMPLATE: &str = r#"<!-- BLUEPRINT_MANAGED_START version="1.4.2" -->
|
||||||
## 项目蓝图
|
## 项目蓝图
|
||||||
|
|
||||||
本项目使用 `.blueprint/` 目录维护项目全景架构图,驱动需求讨论和任务管理。
|
本项目使用 `.blueprint/` 目录维护项目全景架构图,驱动需求讨论和任务管理。
|
||||||
@ -1192,23 +1192,26 @@ pub fn get_flywheel_stats(project_paths: Vec<String>) -> Result<FlywheelStats, S
|
|||||||
};
|
};
|
||||||
projects_with_data += 1;
|
projects_with_data += 1;
|
||||||
|
|
||||||
// 所有快照中收集 blocked_reasons
|
// 最新快照:按 at 字段取最大值,不依赖写入顺序
|
||||||
for snap in snapshots.iter() {
|
let latest = snapshots.iter()
|
||||||
if let Some(reasons) = snap["blocked_reasons"].as_array() {
|
.max_by_key(|s| s["at"].as_str().unwrap_or(""))
|
||||||
for r in reasons {
|
.unwrap();
|
||||||
if let Some(s) = r.as_str() {
|
|
||||||
*reason_counts.entry(s.to_string()).or_insert(0) += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 最新快照
|
|
||||||
let latest = snapshots.last().unwrap();
|
|
||||||
|
|
||||||
let conventions_version = latest["conventions_version"]
|
let conventions_version = latest["conventions_version"]
|
||||||
.as_str().unwrap_or("unknown").to_string();
|
.as_str().unwrap_or("unknown").to_string();
|
||||||
|
|
||||||
|
// conventions_version 无效时跳过(历史脏数据或未同步规则的项目)
|
||||||
|
if conventions_version == "unknown" { continue; }
|
||||||
|
|
||||||
|
// blocked_reasons 只取最新快照,避免历史快照反复计数导致虚高
|
||||||
|
if let Some(reasons) = latest["blocked_reasons"].as_array() {
|
||||||
|
for r in reasons {
|
||||||
|
if let Some(s) = r.as_str() {
|
||||||
|
*reason_counts.entry(s.to_string()).or_insert(0) += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let latest_dt = latest["at"].as_str()
|
let latest_dt = latest["at"].as_str()
|
||||||
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
.and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok())
|
||||||
.map(|dt| dt.with_timezone(&chrono::Utc));
|
.map(|dt| dt.with_timezone(&chrono::Utc));
|
||||||
@ -1312,8 +1315,17 @@ pub fn get_flywheel_stats(project_paths: Vec<String>) -> Result<FlywheelStats, S
|
|||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
// 按版本降序
|
// 按语义版本降序(解析 "1.4.10" 为 (1,4,10) 再比较,避免字符串排序的 "1.4.9" > "1.4.10" 问题)
|
||||||
cohorts.sort_by(|a, b| b.conventions_version.cmp(&a.conventions_version));
|
let parse_semver = |s: &str| -> (u32, u32, u32) {
|
||||||
|
let mut parts = s.splitn(3, '.');
|
||||||
|
let major = parts.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||||
|
let minor = parts.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||||
|
let patch = parts.next().and_then(|x| x.parse().ok()).unwrap_or(0);
|
||||||
|
(major, minor, patch)
|
||||||
|
};
|
||||||
|
cohorts.sort_by(|a, b| {
|
||||||
|
parse_semver(&b.conventions_version).cmp(&parse_semver(&a.conventions_version))
|
||||||
|
});
|
||||||
|
|
||||||
// TOP10 blocked reasons
|
// TOP10 blocked reasons
|
||||||
let mut sorted_reasons: Vec<_> = reason_counts.into_iter().collect();
|
let mut sorted_reasons: Vec<_> = reason_counts.into_iter().collect();
|
||||||
@ -1507,9 +1519,11 @@ fn append_usage_snapshot(bp_dir: &Path, manifest: &BlueprintManifest, stats: &Bl
|
|||||||
.unwrap_or("unknown")
|
.unwrap_or("unknown")
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
// 读取 CONVENTIONS 版本
|
// 读取 CONVENTIONS 版本;缺失时跳过快照写入,避免产生 vunknown 脏数据
|
||||||
let conventions_version = read_frontmatter_version(&bp_dir.join("CONVENTIONS.md"))
|
let conventions_version = match read_frontmatter_version(&bp_dir.join("CONVENTIONS.md")) {
|
||||||
.unwrap_or_else(|| "unknown".to_string());
|
Some(v) => v,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
// UTC 时间
|
// UTC 时间
|
||||||
let now = chrono::Utc::now();
|
let now = chrono::Utc::now();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user