/** * module: release —— 对外类型(编码规范 §10.1)。 * * 放行门:草稿态 → 事实态的**唯一通道**。门归系统,启门归人(OS 10)。 */ import type { ActionIntent, StaffId, TaskId } from '@contracts'; import type { CriterionCheck, DeliverableCheck, LandingOutcome, LandingVerdict, PrecheckFinding, PrecheckItem, PrecheckReport, } from './internal/domain/precheck.ts'; export type { ActionIntent, CriterionCheck, DeliverableCheck, LandingOutcome, LandingVerdict, PrecheckFinding, PrecheckItem, PrecheckReport, }; export class PrecheckFailedError extends Error { constructor(readonly report: PrecheckReport) { super(`落地预检未过,不发放行卡:${report.findings.map((f) => f.message).join('; ')}`); this.name = 'PrecheckFailedError'; } } export class DeliverablesMissingError extends Error { constructor(readonly missing: readonly DeliverableCheck[]) { super(`必交付物缺一不得提交放行:${missing.map((d) => d.label).join('、')}`); this.name = 'DeliverablesMissingError'; } } export type SubmitForReleaseInput = { readonly taskId: TaskId; readonly ownerId: StaffId; readonly humanCallCap: number; readonly deliverableId: string; readonly title: string; readonly basis: ReadonlyArray<{ k: string; v: string }>; readonly deliverables: readonly DeliverableCheck[]; readonly criteria: readonly CriterionCheck[]; /** 报告可修订:AI 拟值已填的表单字段 */ readonly fields?: ReadonlyArray>; }; export type SubmitOutcome = { readonly report: PrecheckReport; /** 预检全过才发卡;这里是发出的验收工单 ID */ readonly workOrderId: string; }; export type LandInput = { readonly taskId: TaskId; readonly ownerId: StaffId; readonly humanCallCap: number; readonly selectedPorts: Readonly>; }; export type LandOutcome = { readonly verdict: LandingVerdict; /** 落地收敛后才发射的输出口 */ readonly emittedPorts: readonly string[]; readonly ledgerRowsMerged: number; /** 已落地的事实 —— 输出口发射的载荷取自这里 */ readonly merged: ReadonlyArray<{ readonly domain: string; readonly object: string; readonly key: Record; readonly values: Record; }>; /** 落地受阻时发出的落地失败卡 */ readonly failureWorkOrderId?: string; }; export type ReleaseService = { /** 登记写类动作意向(入参冻结,存入草稿态) */ registerIntent(taskId: TaskId, intent: Omit): Promise; listIntents(taskId: TaskId): Promise; /** 预检 → 全过才发验收工单;不过即抛 `PrecheckFailedError`,打回环内修正 */ submitForRelease(input: SubmitForReleaseInput): Promise; /** 只跑预检不发卡 —— 环内随时可看「还差什么」 */ precheck(taskId: TaskId): Promise; /** 放行通过即刻落地:草稿合并 + 动作执行(附幂等键)→ 收敛才发射输出口 */ land(input: LandInput): Promise; };