From 58d2c79c74e217c0f0b84a5bd749ad668dddff5b Mon Sep 17 00:00:00 2001 From: lanrtop Date: Fri, 19 Jun 2026 13:52:09 +0900 Subject: [PATCH] =?UTF-8?q?feat(onboarding):=20=E6=8E=A5=E5=85=A5=E5=8C=85?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8F=AF=E4=BF=A1=E5=BA=A6=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=EF=BC=88commit=20=E8=A7=84=E8=8C=83=E5=8C=96=E6=AF=94=E4=BE=8B?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_commit_stats 暴露项目 commit 规范化统计(total/conventional/rework);治理面板常驻展示规范化比例 + 返工数,比例 <60% 提示种 lefthook。接入包 A/B/C1/C2/D 全部完成。 --- .blueprint/modules/onboarding-pack.md | 4 ++-- src-tauri/src/commands/commit_metrics.rs | 23 ++++++++++++++++++++- src-tauri/src/lib.rs | 1 + src/components/dashboard/BlueprintModal.tsx | 22 ++++++++++++++++++++ src/lib/commands.ts | 9 ++++++++ 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/.blueprint/modules/onboarding-pack.md b/.blueprint/modules/onboarding-pack.md index 332ef54..25abdc2 100644 --- a/.blueprint/modules/onboarding-pack.md +++ b/.blueprint/modules/onboarding-pack.md @@ -93,8 +93,8 @@ git 是「过去时 + 量化」(做了什么),蓝图是「将来时 + 语 - files: src-tauri/src/commands/buff.rs, src-tauri/src/commands/blueprint.rs - acceptance: check_project 用 `last_commit..HEAD` 取 commit message(git log,复用现有 WSL 路径处理)→ 调 C1 解析写 commit_metrics;首次接入(last_commit 空)限解析最近 N 条;append_usage_snapshot 的 rework_count 改查 commit_metrics(is_rework=1 AND is_ci_auto=0)取代 parse_notes_metrics -### 🔵 D 数据可信度提示 -- status: planned +### ✅ D 数据可信度提示 +- status: done - complexity: S - depends: onboarding-pack(卡 C1、卡 B) - files: src-tauri/src/commands/onboarding.rs, src-tauri/src/commands/commit_metrics.rs diff --git a/src-tauri/src/commands/commit_metrics.rs b/src-tauri/src/commands/commit_metrics.rs index eede0d2..b57129b 100644 --- a/src-tauri/src/commands/commit_metrics.rs +++ b/src-tauri/src/commands/commit_metrics.rs @@ -4,6 +4,7 @@ //! 取代枯竭的「复盘笔记解析」路径。纯解析逻辑(`parse_conventional`)与 DB 无关,可独立单测。 use rusqlite::Connection; +use serde::{Deserialize, Serialize}; /// 一条 commit 的解析结果。 #[derive(Debug, Clone, PartialEq, Eq)] @@ -114,7 +115,6 @@ pub fn rework_count(conn: &Connection, project_id: &str) -> Result } /// commit 规范化统计:(总数, conventional 数)。供数据可信度提示(卡 D)使用。 -#[allow(dead_code)] pub fn conventional_stats(conn: &Connection, project_id: &str) -> Result<(u32, u32), String> { let total: i64 = conn .query_row( @@ -133,6 +133,27 @@ pub fn conventional_stats(conn: &Connection, project_id: &str) -> Result<(u32, u Ok((total as u32, conv as u32)) } +/// 项目 commit 执行质量统计(供前端数据可信度展示)。 +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CommitStats { + pub total: u32, + pub conventional: u32, + pub rework: u32, +} + +/// 查询某项目的 commit 执行质量统计(总数 / conventional 数 / 有效返工数)。 +#[tauri::command] +pub fn get_commit_stats(project_id: String) -> Result { + let conn = crate::db::pool().get().map_err(|e| e.to_string())?; + let (total, conventional) = conventional_stats(&conn, &project_id)?; + let rework = rework_count(&conn, &project_id)?; + Ok(CommitStats { + total, + conventional, + rework, + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 09dea12..6ab08c3 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -267,6 +267,7 @@ pub fn run() { list_buffed_projects, // onboarding pack commands::onboarding::apply_onboarding_pack, + commands::commit_metrics::get_commit_stats, // mentor get_mentor_context, get_project_notes, diff --git a/src/components/dashboard/BlueprintModal.tsx b/src/components/dashboard/BlueprintModal.tsx index 1851692..9eee326 100644 --- a/src/components/dashboard/BlueprintModal.tsx +++ b/src/components/dashboard/BlueprintModal.tsx @@ -23,6 +23,7 @@ import { generateMuhePrompt, archiveProjectDocs, applyOnboardingPack, + getCommitStats, removeBlueprintBuff, getBuffStatus, getUserConventionsStatus, @@ -39,6 +40,7 @@ import { type StalledProject, type BuffStatus, type TemplateResult, + type CommitStats, type UserConventionsStatus, } from "../../lib/commands"; @@ -1061,6 +1063,13 @@ function GovernancePanel({ staleTime: 5000, }); + const { data: commitStats } = useQuery({ + queryKey: ["commit-stats-governance", projectId], + queryFn: () => (projectId ? getCommitStats(projectId) : Promise.resolve(null)), + enabled: !!projectId, + staleTime: 5000, + }); + const [syncing, setSyncing] = useState(false); const [syncResult, setSyncResult] = useState(null); const [syncError, setSyncError] = useState(null); @@ -1521,6 +1530,19 @@ function GovernancePanel({ )} + {buffStatus?.status === "active" && commitStats && commitStats.total > 0 && ( +
+

+ commit 规范化 {commitStats.conventional}/{commitStats.total}( + {Math.round((commitStats.conventional / commitStats.total) * 100)}%) · 返工 {commitStats.rework} +

+ {commitStats.conventional / commitStats.total < 0.6 && ( +

+ ⚠ 规范化偏低,飞轮数据可信度低——种 lefthook(接入包已含)后逐步转准 +

+ )} +
+ )} {/* 项目信息 */} diff --git a/src/lib/commands.ts b/src/lib/commands.ts index d4ebb78..8ea25f5 100644 --- a/src/lib/commands.ts +++ b/src/lib/commands.ts @@ -1615,6 +1615,15 @@ export interface OnboardingReport { export const applyOnboardingPack = (projectPath: string, projectId: string) => invoke("apply_onboarding_pack", { projectPath, projectId }); +export interface CommitStats { + total: number; + conventional: number; + rework: number; +} + +export const getCommitStats = (projectId: string) => + invoke("get_commit_stats", { projectId }); + // ── Beast Global Status (read-only) ─────────────────────────────────────────── export interface BeastGlobalStatus {