feat(flywheel): 返工热区 UI + get_high_risk_scopes 命令,阶段三收官
- risk.rs 新增 Tauri command get_high_risk_scopes(薄包装)+ lib.rs 注册 - commands.ts 封装 HighRiskScope 类型与调用(R01) - FlywheelPanel 新增「返工热区」块:跨项目返工率降序, 分级配色与 classify_risk 阈值一致(≥35% 红 / ≥15% 琥珀) - 蓝图:P3-A~E 五卡全部 done,附 L 级复盘笔记,模块 progress 98 Rules-Applied: R01,R13
This commit is contained in:
parent
66dc6209a8
commit
a5cb30734d
@ -305,8 +305,8 @@ modules:
|
|||||||
name: 飞轮智能成长
|
name: 飞轮智能成长
|
||||||
area: backend
|
area: backend
|
||||||
status: in_progress
|
status: in_progress
|
||||||
progress: 92
|
progress: 98
|
||||||
note: "阶段三已过 architect+splitter(2026-07-04):P3-A~E 五卡待执行;P0 发现 R1 trailer 管道死链(%s 只取 subject),P3-A 修复"
|
note: "阶段三 P3-A~E 全部完成(2026-07-04):trailer 死链修复+回填、commit_files 采集、predict_task_risk MCP、梦核高风险 scope 段、返工热区 UI;剩存量回填与 MCP 实调终验(待新 build 重启)"
|
||||||
position: [1750, 650]
|
position: [1750, 650]
|
||||||
|
|
||||||
- id: cloud-products
|
- id: cloud-products
|
||||||
|
|||||||
@ -183,12 +183,26 @@
|
|||||||
- files: src-tauri/src/commands/blueprint.rs
|
- files: src-tauri/src/commands/blueprint.rs
|
||||||
- acceptance: "[cargo test] 梦核 prompt 构建函数单测断言输出含「跨项目高风险 scope」数据段(返工率 top scope + 项目分布);规则置信度段在 P3-A 数据流入后自然激活(注入点 blueprint.rs rule_hit_stats 已存在)"
|
- acceptance: "[cargo test] 梦核 prompt 构建函数单测断言输出含「跨项目高风险 scope」数据段(返工率 top scope + 项目分布);规则置信度段在 P3-A 数据流入后自然激活(注入点 blueprint.rs rule_hit_stats 已存在)"
|
||||||
|
|
||||||
### 📋 P3-E. FlywheelPanel 风险展示 + commands.ts 同步(可选收尾)
|
### ✅ P3-E. FlywheelPanel 风险展示 + commands.ts 同步(可选收尾)
|
||||||
- status: todo
|
- 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
|
- complexity: S
|
||||||
- depends: flywheel-intelligence(卡 P3-C)
|
- depends: flywheel-intelligence(卡 P3-C)
|
||||||
- files: src/lib/commands.ts, src/components/dashboard/BlueprintModal.tsx
|
- 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「Git 执行质量」卡片新增各项目返工率 top scope 列(get_scope_risk_profile 封装同步,R01)"
|
- 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 ~ 路径展开问题)
|
# 防止签名密钥被误提交(Windows ~ 路径展开问题)
|
||||||
~/
|
~/
|
||||||
|
|
||||||
|
# 测试运行产物(根目录杂散 DB)
|
||||||
|
/dev-manager-tauri.db
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
> 把此文件粘贴给任何 AI Agent,让它了解本项目的 git 工作方式。由炼境接入包分发。
|
||||||
> `ONBOARDING_MANAGED` 标记块由炼境版本化管理(重跑接入包可原位升级),块外可自由补充项目特有约定。
|
> `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 别攒太大(建议每 3~5 个 commit 或几百行内就开一次),否则 CI code review 易超时失效。
|
||||||
「所有检测通过」≠ 代码被审查过——大 PR 即使 CI 全绿,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
|
```bash
|
||||||
|
|||||||
@ -167,6 +167,16 @@ pub fn high_risk_scopes(
|
|||||||
Ok(result)
|
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 和/或文件清单预测任务风险。
|
/// 核心入口:按 scope 和/或文件清单预测任务风险。
|
||||||
pub fn predict_task_risk(
|
pub fn predict_task_risk(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
|
|||||||
@ -278,6 +278,7 @@ pub fn run() {
|
|||||||
commands::commit_metrics::ingest_full_git_history,
|
commands::commit_metrics::ingest_full_git_history,
|
||||||
commands::commit_metrics::get_project_commit_health,
|
commands::commit_metrics::get_project_commit_health,
|
||||||
commands::commit_metrics::get_all_commit_health,
|
commands::commit_metrics::get_all_commit_health,
|
||||||
|
commands::risk::get_high_risk_scopes,
|
||||||
// mentor
|
// mentor
|
||||||
get_mentor_context,
|
get_mentor_context,
|
||||||
get_project_notes,
|
get_project_notes,
|
||||||
|
|||||||
@ -9,10 +9,12 @@ import {
|
|||||||
archiveProjectDocs,
|
archiveProjectDocs,
|
||||||
ingestFullGitHistory,
|
ingestFullGitHistory,
|
||||||
getAllCommitHealth,
|
getAllCommitHealth,
|
||||||
|
getHighRiskScopes,
|
||||||
type Project,
|
type Project,
|
||||||
type FlywheelStats,
|
type FlywheelStats,
|
||||||
type StalledProject,
|
type StalledProject,
|
||||||
type CommitHealthWithName,
|
type CommitHealthWithName,
|
||||||
|
type HighRiskScope,
|
||||||
} from "../../lib/commands";
|
} from "../../lib/commands";
|
||||||
|
|
||||||
function StalledProjectRow({ p, projectsMap, onArchive }: {
|
function StalledProjectRow({ p, projectsMap, onArchive }: {
|
||||||
@ -84,6 +86,11 @@ export function FlywheelPanel() {
|
|||||||
queryFn: () => getAllCommitHealth(),
|
queryFn: () => getAllCommitHealth(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: riskScopes } = useQuery<HighRiskScope[]>({
|
||||||
|
queryKey: ["high-risk-scopes"],
|
||||||
|
queryFn: () => getHighRiskScopes(),
|
||||||
|
});
|
||||||
|
|
||||||
const [ingesting, setIngesting] = useState(false);
|
const [ingesting, setIngesting] = useState(false);
|
||||||
const [ingestSummary, setIngestSummary] = useState<string | null>(null);
|
const [ingestSummary, setIngestSummary] = useState<string | null>(null);
|
||||||
|
|
||||||
@ -375,6 +382,42 @@ export function FlywheelPanel() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</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">
|
<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>
|
<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 = () =>
|
export const getAllCommitHealth = () =>
|
||||||
invoke<CommitHealthWithName[]>("get_all_commit_health");
|
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 ────────────────────────────────────────────────────────
|
// ── Gitea Integration ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
export interface GiteaInstance {
|
export interface GiteaInstance {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user