feat(flywheel): 阶段三执行质量预测层(trailer 死链修复 + 风险画像) #2
@ -305,8 +305,8 @@ modules:
|
||||
name: 飞轮智能成长
|
||||
area: backend
|
||||
status: in_progress
|
||||
progress: 92
|
||||
note: "阶段三已过 architect+splitter(2026-07-04):P3-A~E 五卡待执行;P0 发现 R1 trailer 管道死链(%s 只取 subject),P3-A 修复"
|
||||
progress: 98
|
||||
note: "阶段三 P3-A~E 全部完成(2026-07-04):trailer 死链修复+回填、commit_files 采集、predict_task_risk MCP、梦核高风险 scope 段、返工热区 UI;剩存量回填与 MCP 实调终验(待新 build 重启)"
|
||||
position: [1750, 650]
|
||||
|
||||
- id: cloud-products
|
||||
|
||||
@ -183,12 +183,26 @@
|
||||
- files: src-tauri/src/commands/blueprint.rs
|
||||
- acceptance: "[cargo test] 梦核 prompt 构建函数单测断言输出含「跨项目高风险 scope」数据段(返工率 top scope + 项目分布);规则置信度段在 P3-A 数据流入后自然激活(注入点 blueprint.rs rule_hit_stats 已存在)"
|
||||
|
||||
### 📋 P3-E. FlywheelPanel 风险展示 + commands.ts 同步(可选收尾)
|
||||
- status: todo
|
||||
### ✅ P3-E. FlywheelPanel 风险展示 + commands.ts 同步(可选收尾)
|
||||
- status: done
|
||||
- done_note: 2026-07-04 完成。实现形态微调:Git 执行质量表已有 TOP scope 列(F2 遗产),故新增独立「返工热区」块展示 get_high_risk_scopes(跨项目返工率降序,分级配色与 classify_risk 阈值一致 ≥35% 红 / ≥15% 琥珀);Tauri command get_high_risk_scopes 薄包装 + lib.rs 注册 + commands.ts 封装(R01)。pnpm typecheck exit 0,cargo test 92 全绿
|
||||
- complexity: S
|
||||
- depends: flywheel-intelligence(卡 P3-C)
|
||||
- files: src/lib/commands.ts, src/components/dashboard/BlueprintModal.tsx
|
||||
- acceptance: "[pnpm typecheck] exit 0;FlywheelPanel「Git 执行质量」卡片新增各项目返工率 top scope 列(get_scope_risk_profile 封装同步,R01)"
|
||||
- files: src/lib/commands.ts, src/components/insight/FlywheelPanel.tsx, src-tauri/src/commands/risk.rs, src-tauri/src/lib.rs
|
||||
- acceptance: "[pnpm typecheck] exit 0;FlywheelPanel 新增跨项目返工热区展示(get_high_risk_scopes 封装同步,R01)"
|
||||
|
||||
## 复盘笔记
|
||||
|
||||
【复盘】阶段三执行质量预测层 P3-A~E(2026-07-04)
|
||||
任务类型: 后端数据管道 + MCP工具 + 前端展示
|
||||
复杂度: L(architect+splitter 拆为 2M+1M+1S+1S,单会话连续执行)
|
||||
实际轮数: 1轮(预估 1 轮)
|
||||
是否返工: 否
|
||||
有效策略: architect 阶段先查数据库实况而非只读设计文档——由此发现 R1 trailer 管道死链(%s 只取 subject,单测喂全文全绿而生产喂 subject 永空),这个 P0 若不修,阶段三核心闭环(规则置信度)建在死数据上;「单元绿、集成死」用真 git 仓库 e2e 测试驻军;UPSERT 只回填 NULL 不覆盖,让回填天然幂等;三处重复的 git log 取数统一为单一入口(read_git_log),--name-only 让指标与文件单次进程同取
|
||||
顺手修的旧债: generate_muhe_prompt 用 pool() 导致测试环境必 panic(不可测),改 try_pool() 走占位文案
|
||||
遗留: 存量数据回填与 predict_task_risk MCP 实调,待新 build 发布重启后终验(跑一次「全量导入」即回填 trailer + 文件)
|
||||
auto_applied_rules: R01, R05, R06, R07, R13
|
||||
rule_effectiveness: R06=有效(conn 注入使 risk.rs 7 测试全部 in-memory 可行), R07=有效(e2e git 仓库回归测试抓住的正是集成层缺口), R13=有效(acceptance 可执行格式让五张卡零歧义), R01=有效(commands.ts 同步时确认 HighRiskScope 类型单一来源), R05=有效(commit_files migration 随手写进 migrate())
|
||||
|
||||
## 决策记录
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -31,3 +31,6 @@ src-tauri/dev_manager.db
|
||||
|
||||
# 防止签名密钥被误提交(Windows ~ 路径展开问题)
|
||||
~/
|
||||
|
||||
# 测试运行产物(根目录杂散 DB)
|
||||
/dev-manager-tauri.db
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
||||
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
|
||||
|
||||
<!-- ONBOARDING_MANAGED_START version="1.1.0" -->
|
||||
<!-- ONBOARDING_MANAGED_START version="1.2.0" -->
|
||||
|
||||
## 分支策略
|
||||
|
||||
@ -72,6 +72,22 @@ git commit -m "feat(模块): 一件事"
|
||||
PR 别攒太大(建议每 3~5 个 commit 或几百行内就开一次),否则 CI code review 易超时失效。
|
||||
「所有检测通过」≠ 代码被审查过——大 PR 即使 CI 全绿,review 可能已静默失效。
|
||||
|
||||
## PR 创建(炼境托管项目)
|
||||
|
||||
本项目由炼境管理,MCP 已注入且 `.claude/liangjing.json` 含 `project_id`。
|
||||
|
||||
**推送分支后,通过炼境 MCP 创建 PR,禁止用 curl + git credential fill 提取 token:**
|
||||
|
||||
```
|
||||
1. Read .claude/liangjing.json → 取出 project_id
|
||||
2. 调用 MCP 工具 create_pull_request:
|
||||
{ "project_id": "<id>", "head": "dev", "base": "main",
|
||||
"title": "<Conventional Commits 格式>", "body": "<变更摘要>" }
|
||||
3. 炼境内部用存储的 Gitea 凭证调 API,返回 pr_url
|
||||
```
|
||||
|
||||
若炼境未运行(MCP 不可用),降级方案:去 Gitea 网页手动创建 PR。
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
|
||||
@ -167,6 +167,16 @@ pub fn high_risk_scopes(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Tauri command:跨项目返工热区(FlywheelPanel「返工热区」块)。薄包装,逻辑在 high_risk_scopes。
|
||||
#[tauri::command]
|
||||
pub fn get_high_risk_scopes(
|
||||
min_commits: Option<u32>,
|
||||
limit: Option<u32>,
|
||||
) -> Result<Vec<HighRiskScope>, String> {
|
||||
let conn = crate::db::pool().get().map_err(|e| e.to_string())?;
|
||||
high_risk_scopes(&conn, min_commits.unwrap_or(5), limit.unwrap_or(10) as usize)
|
||||
}
|
||||
|
||||
/// 核心入口:按 scope 和/或文件清单预测任务风险。
|
||||
pub fn predict_task_risk(
|
||||
conn: &Connection,
|
||||
|
||||
@ -278,6 +278,7 @@ pub fn run() {
|
||||
commands::commit_metrics::ingest_full_git_history,
|
||||
commands::commit_metrics::get_project_commit_health,
|
||||
commands::commit_metrics::get_all_commit_health,
|
||||
commands::risk::get_high_risk_scopes,
|
||||
// mentor
|
||||
get_mentor_context,
|
||||
get_project_notes,
|
||||
|
||||
@ -9,10 +9,12 @@ import {
|
||||
archiveProjectDocs,
|
||||
ingestFullGitHistory,
|
||||
getAllCommitHealth,
|
||||
getHighRiskScopes,
|
||||
type Project,
|
||||
type FlywheelStats,
|
||||
type StalledProject,
|
||||
type CommitHealthWithName,
|
||||
type HighRiskScope,
|
||||
} from "../../lib/commands";
|
||||
|
||||
function StalledProjectRow({ p, projectsMap, onArchive }: {
|
||||
@ -84,6 +86,11 @@ export function FlywheelPanel() {
|
||||
queryFn: () => getAllCommitHealth(),
|
||||
});
|
||||
|
||||
const { data: riskScopes } = useQuery<HighRiskScope[]>({
|
||||
queryKey: ["high-risk-scopes"],
|
||||
queryFn: () => getHighRiskScopes(),
|
||||
});
|
||||
|
||||
const [ingesting, setIngesting] = useState(false);
|
||||
const [ingestSummary, setIngestSummary] = useState<string | null>(null);
|
||||
|
||||
@ -375,6 +382,42 @@ export function FlywheelPanel() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 返工热区(飞轮阶段三预测层) */}
|
||||
{riskScopes && riskScopes.length > 0 && (
|
||||
<div className="bg-white rounded-lg border border-gray-100 p-3 space-y-2">
|
||||
<p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wider">
|
||||
返工热区
|
||||
<span className="ml-1.5 normal-case font-normal">历史返工率最高的模块,开工前提高警惕</span>
|
||||
</p>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-[10px]">
|
||||
<thead>
|
||||
<tr className="text-gray-400 border-b border-gray-100">
|
||||
<th className="text-left pb-1 font-medium">项目</th>
|
||||
<th className="text-left pb-1 font-medium">scope</th>
|
||||
<th className="text-right pb-1 font-medium">commits</th>
|
||||
<th className="text-right pb-1 font-medium">返工率</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-50">
|
||||
{riskScopes.map((s) => (
|
||||
<tr key={`${s.project_name}-${s.scope}`} className="hover:bg-gray-50">
|
||||
<td className="py-1 text-gray-700 truncate max-w-[80px]" title={s.project_name}>
|
||||
{s.project_name}
|
||||
</td>
|
||||
<td className="py-1 text-gray-500 font-mono truncate max-w-[100px]">{s.scope}</td>
|
||||
<td className="py-1 text-right font-mono text-gray-500">{s.commits}</td>
|
||||
<td className={`py-1 text-right font-mono font-semibold ${s.rework_rate >= 0.35 ? "text-red-500" : s.rework_rate >= 0.15 ? "text-amber-500" : "text-gray-500"}`}>
|
||||
{Math.round(s.rework_rate * 100)}%
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 梦核分析 */}
|
||||
<div className="bg-white rounded-lg border border-gray-100 p-3 space-y-2">
|
||||
<p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wider">梦核分析</p>
|
||||
|
||||
@ -1611,6 +1611,18 @@ export interface CommitHealthWithName extends ProjectCommitHealth {
|
||||
export const getAllCommitHealth = () =>
|
||||
invoke<CommitHealthWithName[]>("get_all_commit_health");
|
||||
|
||||
// 飞轮阶段三:跨项目返工热区(样本 ≥minCommits 且有非 CI 返工的 scope,按返工率降序)
|
||||
export interface HighRiskScope {
|
||||
project_name: string;
|
||||
scope: string;
|
||||
commits: number;
|
||||
rework: number;
|
||||
rework_rate: number;
|
||||
}
|
||||
|
||||
export const getHighRiskScopes = (minCommits?: number, limit?: number) =>
|
||||
invoke<HighRiskScope[]>("get_high_risk_scopes", { minCommits, limit });
|
||||
|
||||
// ── Gitea Integration ────────────────────────────────────────────────────────
|
||||
|
||||
export interface GiteaInstance {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user