feat(小宝预警): 增加日报证据与风险趋势
This commit is contained in:
@@ -4,6 +4,7 @@ import { STATUS_PROGRESS, getEstimateHours } from './dev-task';
|
||||
import type { TestCase } from './test-case';
|
||||
import { getTestCaseEstimateHours } from './test-case';
|
||||
import type { VersionDailyEvidence } from './xiaobao-risk-evidence';
|
||||
import { summarizeRiskTrendWithCurrent, type XiaobaoRiskSnapshot } from './xiaobao-risk-trend';
|
||||
import { WORK_HOURS, addWorkHours } from './work-hours';
|
||||
|
||||
export type XiaobaoRiskLevel = 'on_track' | 'attention' | 'at_risk' | 'likely_delayed' | 'blocked';
|
||||
@@ -72,7 +73,7 @@ export interface CalcXiaobaoVersionRiskInput {
|
||||
testCases?: TestCase[];
|
||||
bugs?: Bug[];
|
||||
now?: Date;
|
||||
snapshots?: Array<{ riskScore: number; createdAt?: string; date?: string }>;
|
||||
snapshots?: XiaobaoRiskSnapshot[];
|
||||
silentRisks?: SilentRisk[];
|
||||
dailyEvidence?: VersionDailyEvidence;
|
||||
recentActivityCount?: number;
|
||||
@@ -197,7 +198,19 @@ export function calcXiaobaoVersionRisk(input: CalcXiaobaoVersionRiskInput): Xiao
|
||||
const hasBlockingRisk = criticalBugCount > 0 || blockedCount > 0;
|
||||
const riskLevel = getRiskLevel(riskScore, delayDays, hasBlockingRisk);
|
||||
const confidence = calcConfidence(input, devTasks, testCases, bugs);
|
||||
const trend = calcTrend(riskScore, input.snapshots ?? []);
|
||||
const trend = summarizeRiskTrendWithCurrent(input.snapshots ?? [], {
|
||||
versionId: input.version.id,
|
||||
date: now.toISOString().slice(0, 10),
|
||||
riskScore,
|
||||
riskLevel,
|
||||
forecastReleaseDate,
|
||||
openBugCount: signals.criticalBugCount,
|
||||
failedTestCount: signals.failedTestCount,
|
||||
blockedCount: signals.blockedCount,
|
||||
silentRiskCount: signals.silentRiskCount,
|
||||
confidence,
|
||||
createdAt: now.toISOString(),
|
||||
});
|
||||
|
||||
return {
|
||||
versionId: input.version.id,
|
||||
@@ -280,27 +293,6 @@ function hasEstimate(item: DevTask | TestCase | Bug): boolean {
|
||||
|| (typeof item.aiEstimateHours === 'number' && item.aiEstimateHours > 0);
|
||||
}
|
||||
|
||||
function calcTrend(
|
||||
currentScore: number,
|
||||
snapshots: Array<{ riskScore: number; createdAt?: string; date?: string }>,
|
||||
): XiaobaoVersionRisk['trend'] {
|
||||
if (snapshots.length === 0) {
|
||||
return { direction: 'unknown', delta: 0, summary: '暂无历史快照。' };
|
||||
}
|
||||
const latest = [...snapshots].sort((a, b) => {
|
||||
const aTime = parseDate(a.createdAt ?? a.date)?.getTime() ?? 0;
|
||||
const bTime = parseDate(b.createdAt ?? b.date)?.getTime() ?? 0;
|
||||
return bTime - aTime;
|
||||
})[0];
|
||||
const delta = clampScore(currentScore) - clampScore(latest.riskScore);
|
||||
const direction = Math.abs(delta) < 5 ? 'flat' : delta > 0 ? 'up' : 'down';
|
||||
const summary = direction === 'flat'
|
||||
? '风险基本持平。'
|
||||
: direction === 'up'
|
||||
? `风险上升 ${delta} 分。`
|
||||
: `风险下降 ${Math.abs(delta)} 分。`;
|
||||
return { direction, delta, summary };
|
||||
}
|
||||
|
||||
function getConfidenceLevel(confidence: number): XiaobaoConfidenceLevel {
|
||||
if (confidence >= 75) return 'high';
|
||||
|
||||
Reference in New Issue
Block a user