refactor(data): 收口关系表运行时数据源
Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled

- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读
- 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移
- 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
2026-07-09 14:59:49 +08:00
parent 1e6fb0c7aa
commit 2e595c7e72
98 changed files with 2938 additions and 1441 deletions

View File

@@ -36,6 +36,22 @@ test('sortPlansNewestFirst places newly created plans before older plans', () =>
assert.deepEqual(plans.map((item) => item.id), ['plan-100', 'manual-old', 'plan-300']);
});
test('calcTotalDuration follows overview actual-duration display for short plans', () => {
const calcTotalDuration = (versionPlan as any).calcTotalDuration as undefined | ((plans: VersionPlan[]) => string);
assert.equal(typeof calcTotalDuration, 'function');
assert.equal(calcTotalDuration!([
plan({
type: 'product',
startTime: '2026-06-22T09:00:00',
endTime: '2026-06-22T10:00:00',
status: 'completed',
actualStartAt: '2026-06-22T09:00:00',
completedAt: '2026-06-22T10:00:00',
}),
]), '1h0.04天)');
});
test('collects logs across plans with plan context and newest first', () => {
const getPlanLogsForPlans = (versionPlan as any).getPlanLogsForPlans as undefined | ((plans: VersionPlan[]) => Array<{
id: string;
@@ -210,6 +226,112 @@ test('starts requirement coverage work while preserving existing progress', () =
assert.equal(next.requirementCoverage?.[0]?.updatedBy, 'PM');
});
test('merges stale requirement coverage patches without dropping current sessions', () => {
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
current: VersionPlan,
patch: Partial<VersionPlan>,
) => Partial<VersionPlan>);
assert.equal(typeof mergeVersionPlanPatch, 'function');
const current = plan({
requirementCoverage: [
{
requirementId: 'r1',
status: 'not_started',
currentWorkStartedAt: '2026-06-29T09:30:00.000Z',
updatedAt: '2026-06-29T09:30:00.000Z',
updatedBy: 'PM',
},
],
});
const merged = mergeVersionPlanPatch!(current, {
requirementCoverage: [
{
requirementId: 'r2',
status: 'not_started',
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
updatedAt: '2026-06-29T10:00:00.000Z',
updatedBy: 'PM',
},
],
});
assert.deepEqual(
merged.requirementCoverage?.map((item) => [item.requirementId, item.currentWorkStartedAt]),
[
['r2', '2026-06-29T10:00:00.000Z'],
['r1', '2026-06-29T09:30:00.000Z'],
],
);
});
test('merged requirement coverage patches preserve legacy completed ids outside the patch', () => {
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
current: VersionPlan,
patch: Partial<VersionPlan>,
) => Partial<VersionPlan>);
assert.equal(typeof mergeVersionPlanPatch, 'function');
const merged = mergeVersionPlanPatch!(plan({
linkedRequirementIds: ['r1', 'r2'],
completedRequirementIds: ['r1'],
}), {
requirementCoverage: [
{
requirementId: 'r2',
status: 'not_started',
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
updatedAt: '2026-06-29T10:00:00.000Z',
updatedBy: 'PM',
},
],
});
assert.deepEqual(merged.completedRequirementIds?.sort(), ['r1']);
});
test('merges stale research direction patches without dropping current sessions', () => {
const mergeVersionPlanPatch = (versionPlan as any).mergeVersionPlanPatch as undefined | ((
current: VersionPlan,
patch: Partial<VersionPlan>,
) => Partial<VersionPlan>);
assert.equal(typeof mergeVersionPlanPatch, 'function');
const current = plan({
type: 'research',
tasks: [
{
id: 'task-1',
title: '竞品分析',
status: 'in_progress',
currentWorkStartedAt: '2026-06-29T09:30:00.000Z',
},
{ id: 'task-2', title: '用户访谈', status: 'pending' },
],
});
const merged = mergeVersionPlanPatch!(current, {
tasks: [
{ id: 'task-1', title: '竞品分析', status: 'pending' },
{
id: 'task-2',
title: '用户访谈',
status: 'in_progress',
currentWorkStartedAt: '2026-06-29T10:00:00.000Z',
},
],
});
assert.deepEqual(
merged.tasks?.map((item) => [item.id, item.status, item.currentWorkStartedAt]),
[
['task-1', 'in_progress', '2026-06-29T09:30:00.000Z'],
['task-2', 'in_progress', '2026-06-29T10:00:00.000Z'],
],
);
});
test('validates requirement coverage record drafts by started work session', () => {
const canSaveRequirementCoverageDraft = (versionPlan as any).canSaveRequirementCoverageDraft as undefined | ((
status: string,