fix(小宝预警): 稳定风险证据与建议更新

关键改动:

- 优化风险证据的日报工时与静默风险计算

- 稳定 AI 触发签名,避免证据细节变化造成重复请求

- 调整预警建议更新状态与相关测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
Script Generator
2026-07-01 11:26:16 +08:00
parent 8947aeaac7
commit e5ef9ee28b
7 changed files with 421 additions and 43 deletions

View File

@@ -148,6 +148,134 @@ test('buildVersionDailyEvidence groups version activity and detects no activity/
assert.ok(evidence.silentRisks?.some((risk) => risk.key === 'no_activity' && risk.itemId === 'plan-1'));
});
test('buildVersionDailyEvidence uses plan record work start time for daily hours', () => {
const workItems = buildXiaobaoWorkItems({
plans: [
plan({
id: 'plan-cross-day',
title: 'Product plan',
actualStartAt: '2026-06-30T01:00:00.000Z',
createdAt: '2026-06-30T01:00:00.000Z',
}),
],
versions: [{ id: 'ver-1', name: 'V1.0', productName: 'FTB', projectName: 'PM' }],
requirementVersionMap: new Map(),
});
const activities: WorkActivity[] = [
{
id: 'act-plan-record',
actorId: 'pm-1',
date: '2026-07-01',
occurredAt: '2026-07-01T04:00:00.000Z',
sourceType: 'version_plan',
sourceId: 'plan-cross-day',
action: 'version_plan_requirement_progress',
category: 'progress',
title: 'Product plan',
summary: 'Updated product plan requirement progress',
metadata: {
requirementId: 'req-1',
workStartedAt: '2026-07-01T02:00:00.000Z',
},
},
];
const evidence = buildVersionDailyEvidence({
versionId: 'ver-1',
workItems,
activities,
worklogs: [],
now: new Date('2026-07-01T08:00:00.000Z'),
});
assert.equal(evidence.todayActualHours, 2);
});
test('buildVersionDailyEvidence uses previous progress next start time for dev task daily hours', () => {
const workItems = buildXiaobaoWorkItems({
devTasks: [
devTask({
id: 'dev-cross-day-progress',
title: 'Cross-day development',
actualStartAt: '2026-07-01T01:30:00.000Z',
updatedAt: '2026-07-02T10:00:00.000Z',
}),
],
versions: [{ id: 'ver-1', name: 'V1.0', productName: 'FTB', projectName: 'PM' }],
requirementVersionMap: new Map([['req-1', 'ver-1']]),
});
const activities: WorkActivity[] = [
{
id: 'act-dev-progress-day-1',
actorId: 'dev-1',
date: '2026-07-01',
occurredAt: '2026-07-01T10:00:00.000Z',
sourceType: 'dev_task',
sourceId: 'dev-cross-day-progress',
action: 'progress_note_added',
category: 'note',
title: 'Cross-day development',
summary: 'Updated today progress',
metadata: {
note: 'Finished the first part',
nextStartAt: '2026-07-02T01:30:00.000Z',
},
},
{
id: 'act-dev-progress-day-2',
actorId: 'dev-1',
date: '2026-07-02',
occurredAt: '2026-07-02T10:00:00.000Z',
sourceType: 'dev_task',
sourceId: 'dev-cross-day-progress',
action: 'progress_note_added',
category: 'note',
title: 'Cross-day development',
summary: 'Updated today progress',
metadata: {
note: 'Finished the second part',
nextStartAt: '2026-07-03T01:30:00.000Z',
},
},
];
const evidence = buildVersionDailyEvidence({
versionId: 'ver-1',
workItems,
activities,
worklogs: [],
now: new Date('2026-07-02T10:00:00.000Z'),
});
assert.equal(evidence.todayActualHours, 7.5);
});
test('buildVersionDailyEvidence does not emit Infinity-day silent risk details', () => {
const workItems = buildXiaobaoWorkItems({
plans: [
plan({
id: 'plan-no-evidence',
title: 'Plan without evidence',
createdAt: '2026-06-20T01:00:00.000Z',
actualStartAt: '2026-06-20T01:00:00.000Z',
}),
],
versions: [{ id: 'ver-1', name: 'V1.0', productName: 'FTB', projectName: 'PM' }],
requirementVersionMap: new Map(),
});
const evidence = buildVersionDailyEvidence({
versionId: 'ver-1',
workItems,
activities: [],
worklogs: [],
now: new Date('2026-06-29T08:00:00.000Z'),
});
assert.ok((evidence.silentRisks ?? []).length > 0);
assert.equal((evidence.silentRisks ?? []).some((risk) => risk.detail.includes('Infinity')), false);
});
test('buildVersionDailyEvidence mirrors daily report timestamp fallback evidence', () => {
const workItems = buildXiaobaoWorkItems({
plans: [