feat(mapping): centralize domain <-> contracts mappings (B5)
New @umt/mapping (depends on domain + contracts only): download status + pause reason, evidence level / media kind, identity resolution status, slot status / spec columns / evaluation, ParsedRelease <-> source_release.parsed, SiteRelease <-> source_release, PathBinding, OrganizePlan -> organization_record / file results / organize.plan output. Tables are Record<union, ...> so adding a value on either side fails typecheck or tests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
da8e53bbca
commit
42ecc93fa5
16 files changed
+1282
-1
No files matched your search
@@ -0,0 +1,87 @@
|
||||
import type { DownloadStatus, PauseReason } from "@umt/contracts";
|
||||
import type { DownloadTaskStatus as DomainDownloadStatus } from "@umt/domain";
|
||||
|
||||
// 下载状态:domain 只描述"下载器里看到的状态"(mapQbState 的结果),
|
||||
// contracts / download_task.status 还叠加业务阶段(submitting / stalled / importing / imported)和 pauseReason。
|
||||
|
||||
export type { DomainDownloadStatus };
|
||||
|
||||
export interface ContractDownloadState {
|
||||
status: DownloadStatus;
|
||||
pauseReason: PauseReason | null;
|
||||
}
|
||||
|
||||
const TO_CONTRACT: Record<DomainDownloadStatus, ContractDownloadState> = {
|
||||
queued: { status: "queued", pauseReason: null },
|
||||
downloading: { status: "downloading", pauseReason: null },
|
||||
paused_by_threshold: { status: "paused", pauseReason: "threshold" },
|
||||
paused_by_user: { status: "paused", pauseReason: "user" },
|
||||
completed: { status: "completed", pauseReason: null },
|
||||
error: { status: "failed", pauseReason: null },
|
||||
missing_files: { status: "missing", pauseReason: null },
|
||||
removed: { status: "removed", pauseReason: null },
|
||||
};
|
||||
|
||||
/** contracts 状态 → 下载器层面的 domain 状态(业务叠加态折回其底层下载状态) */
|
||||
const TO_DOMAIN: Record<DownloadStatus, DomainDownloadStatus | "by_pause_reason"> = {
|
||||
queued: "queued",
|
||||
// 提交中:下载器里还没有/刚出现,按排队处理
|
||||
submitting: "queued",
|
||||
downloading: "downloading",
|
||||
paused: "by_pause_reason",
|
||||
// 无进展是业务判定(detectNoProgress),下载器里仍是 downloading
|
||||
stalled: "downloading",
|
||||
completed: "completed",
|
||||
// 入库阶段:下载本身已完成
|
||||
importing: "completed",
|
||||
imported: "completed",
|
||||
failed: "error",
|
||||
removed: "removed",
|
||||
missing: "missing_files",
|
||||
};
|
||||
|
||||
/** 暂停原因 → domain 状态:只有 threshold 会被阈值恢复自动恢复,其余都按用户暂停对待(REQ §8.4.1) */
|
||||
const PAUSE_TO_DOMAIN: Record<PauseReason, DomainDownloadStatus> = {
|
||||
threshold: "paused_by_threshold",
|
||||
user: "paused_by_user",
|
||||
policy: "paused_by_user",
|
||||
agent: "paused_by_user",
|
||||
};
|
||||
|
||||
export const DOMAIN_DOWNLOAD_STATUSES = Object.keys(TO_CONTRACT) as DomainDownloadStatus[];
|
||||
|
||||
export function toContractDownloadState(s: DomainDownloadStatus): ContractDownloadState {
|
||||
return { ...TO_CONTRACT[s] };
|
||||
}
|
||||
|
||||
export function toDomainDownloadStatus(status: DownloadStatus, pauseReason: PauseReason | null): DomainDownloadStatus {
|
||||
const d = TO_DOMAIN[status];
|
||||
if (d !== "by_pause_reason") return d;
|
||||
return PAUSE_TO_DOMAIN[pauseReason ?? "user"];
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步轮询时合并"下载器观察"与"当前业务状态":
|
||||
* - 业务叠加态在其底层下载状态不变时保留(importing/imported 遇 completed、stalled 遇 downloading、submitting 遇 queued);
|
||||
* - 暂停原因为 policy/agent 且下载器仍是暂停时保留原因,不被改写成 user;
|
||||
* - 其余以观察为准。
|
||||
*/
|
||||
export function mergeObservedDownloadState(
|
||||
current: ContractDownloadState,
|
||||
observed: DomainDownloadStatus,
|
||||
): ContractDownloadState {
|
||||
const next = TO_CONTRACT[observed];
|
||||
const keep =
|
||||
((current.status === "importing" || current.status === "imported") && observed === "completed") ||
|
||||
(current.status === "stalled" && observed === "downloading") ||
|
||||
(current.status === "submitting" && observed === "queued");
|
||||
if (keep) return { ...current };
|
||||
if (
|
||||
current.status === "paused" &&
|
||||
observed === "paused_by_user" &&
|
||||
(current.pauseReason === "policy" || current.pauseReason === "agent")
|
||||
) {
|
||||
return { ...current };
|
||||
}
|
||||
return { ...next };
|
||||
}
|
||||
Reference in new issue
Block a user