fix(小宝预警): 修正趋势快照 Bug 计数

This commit is contained in:
Script Generator
2026-06-29 18:23:04 +08:00
parent b48a7e2049
commit dda453ab5d
2 changed files with 48 additions and 3 deletions

View File

@@ -1,6 +1,8 @@
import test from 'node:test'; import test from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import type { Bug } from './bug';
import { calcXiaobaoVersionRisk } from './xiaobao-risk';
import { buildRiskSignature, summarizeRiskTrend } from './xiaobao-risk-trend'; import { buildRiskSignature, summarizeRiskTrend } from './xiaobao-risk-trend';
import type { XiaobaoRiskSnapshot } from './xiaobao-risk-trend'; import type { XiaobaoRiskSnapshot } from './xiaobao-risk-trend';
@@ -38,3 +40,43 @@ test('buildRiskSignature changes when score and bug counts change', () => {
assert.notEqual(base, changed); assert.notEqual(base, changed);
}); });
test('calcXiaobaoVersionRisk uses all open bugs in the current trend snapshot signature', () => {
const now = new Date('2026-07-02T01:00:00.000Z');
const risk = calcXiaobaoVersionRisk({
version: {
id: 'ver-1',
name: 'V1.0',
expectedReleaseDate: '2026-07-03T10:00:00.000Z',
members: [{ name: 'Alice' }],
},
devTasks: [],
testCases: [],
bugs: [bug({ severity: 'major', priority: 'P2' })],
now,
});
assert.equal(risk.signals.openBugCount, 1);
assert.equal(risk.signals.criticalBugCount, 0);
assert.equal(risk.currentSnapshot.openBugCount, 1);
assert.equal(buildRiskSignature(risk.currentSnapshot).split('|')[5], '1');
});
function bug(patch: Partial<Bug> = {}): Bug {
return {
id: 'bug-1',
bugNo: 'BUG-001',
versionId: 'ver-1',
testCaseId: 'tc-1',
title: 'Non-critical open bug',
description: 'Open but not critical.',
severity: 'major',
priority: 'P2',
reportedBy: 'qa-1',
assigneeId: 'dev-1',
status: 'open',
createdAt: '2026-07-01T09:00:00.000Z',
updatedAt: '2026-07-01T09:00:00.000Z',
...patch,
};
}

View File

@@ -60,6 +60,7 @@ export interface XiaobaoVersionRisk {
silentRisks: SilentRisk[]; silentRisks: SilentRisk[];
dailyEvidence?: VersionDailyEvidence; dailyEvidence?: VersionDailyEvidence;
signals: XiaobaoRiskSignals; signals: XiaobaoRiskSignals;
currentSnapshot: XiaobaoRiskSnapshot;
trend: { trend: {
direction: 'up' | 'down' | 'flat' | 'unknown'; direction: 'up' | 'down' | 'flat' | 'unknown';
delta: number; delta: number;
@@ -198,19 +199,20 @@ export function calcXiaobaoVersionRisk(input: CalcXiaobaoVersionRiskInput): Xiao
const hasBlockingRisk = criticalBugCount > 0 || blockedCount > 0; const hasBlockingRisk = criticalBugCount > 0 || blockedCount > 0;
const riskLevel = getRiskLevel(riskScore, delayDays, hasBlockingRisk); const riskLevel = getRiskLevel(riskScore, delayDays, hasBlockingRisk);
const confidence = calcConfidence(input, devTasks, testCases, bugs); const confidence = calcConfidence(input, devTasks, testCases, bugs);
const trend = summarizeRiskTrendWithCurrent(input.snapshots ?? [], { const currentSnapshot: XiaobaoRiskSnapshot = {
versionId: input.version.id, versionId: input.version.id,
date: now.toISOString().slice(0, 10), date: now.toISOString().slice(0, 10),
riskScore, riskScore,
riskLevel, riskLevel,
forecastReleaseDate, forecastReleaseDate,
openBugCount: signals.criticalBugCount, openBugCount: signals.openBugCount,
failedTestCount: signals.failedTestCount, failedTestCount: signals.failedTestCount,
blockedCount: signals.blockedCount, blockedCount: signals.blockedCount,
silentRiskCount: signals.silentRiskCount, silentRiskCount: signals.silentRiskCount,
confidence, confidence,
createdAt: now.toISOString(), createdAt: now.toISOString(),
}); };
const trend = summarizeRiskTrendWithCurrent(input.snapshots ?? [], currentSnapshot);
return { return {
versionId: input.version.id, versionId: input.version.id,
@@ -226,6 +228,7 @@ export function calcXiaobaoVersionRisk(input: CalcXiaobaoVersionRiskInput): Xiao
silentRisks, silentRisks,
dailyEvidence: input.dailyEvidence, dailyEvidence: input.dailyEvidence,
signals, signals,
currentSnapshot,
trend, trend,
}; };
} }