Archived
用户:「评审放行与落账确认这一步的验收卡不应该有重做的选项,因为这里都没有接入 ai」。 W05 的 T_release 整个由配方跑完(guide 是空串,不问模型),件又是只读的 —— 打回之后没有任何东西能接住那句意见:配方只会原样再提交一次,撞在「打回之后台账没动过 就不许再提交」那道闸上,连撞两拍落成一张「连续撞在同一条判据上」的兜底卡。 一颗按下去只会把单子推进死胡同的钮,不如不摆(墙要配路;没有路就别立那扇门)。 · 契约:AcceptanceWorkOrder.redoable(不写 = 打得回,老卡老行为); · 装配层按放行那一步的声明现算 —— releaseRedoable 纯函数(有 auto 且 guide 空 → 打不回; 半 auto 与模型驱动照旧打得回,那儿真有模型会读意见),与 decisionCardFace / executionCardVariant 同一种做法、同一个测试位; · 卡面收起理由框与那颗钮,换一句真路:「这一步只落账,退不回上一步 —— 有异议就别确认, 去终止这一单重开」; · **服务端才是门**:redoable:false 的卡收到非 pass 的回传当场拒(redo-unavailable), 直调 API 绕不过;拒回把真路指出来。 S3 结论审核那张审核卡不受影响 —— 它的重做真会带着意见重判(昨夜那一轮)。 测:card-rules 3 条 + releaseRedoable 4 条,两处变异验证;e2e w05 5/5 released、被拒 0。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
78 lines
3.5 KiB
TypeScript
78 lines
3.5 KiB
TypeScript
/**
|
|
* 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 declare class PrecheckFailedError extends Error {
|
|
readonly report: PrecheckReport;
|
|
constructor(report: PrecheckReport);
|
|
}
|
|
export declare class DeliverablesMissingError extends Error {
|
|
readonly missing: readonly DeliverableCheck[];
|
|
constructor(missing: readonly DeliverableCheck[]);
|
|
}
|
|
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[];
|
|
/** 人工验收清单(剧本声明,固定):卡上一条一枚开关,全部达标才能通过 */
|
|
readonly checklist?: ReadonlyArray<string>;
|
|
/** 这张卡打回得了吗 —— `false` = 打回之后没人接得住(见契约 `AcceptanceWorkOrder.redoable`) */
|
|
readonly redoable?: boolean;
|
|
/** 报告可修订:AI 拟值已填的表单字段 */
|
|
readonly fields?: ReadonlyArray<Record<string, unknown>>;
|
|
/**
|
|
* 验收页的正文块 —— 与执行工单同一套件,可含**绑台账的可编辑表**。
|
|
* 验收是最重的一道门:人得能在成果本身上改,不只是改几个整单级字段。
|
|
*/
|
|
readonly blocks?: ReadonlyArray<Record<string, unknown>>;
|
|
};
|
|
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<Record<string, string>>;
|
|
};
|
|
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<string, unknown>;
|
|
readonly values: Record<string, unknown>;
|
|
}>;
|
|
/** 落地受阻时发出的落地失败卡 */
|
|
readonly failureWorkOrderId?: string;
|
|
};
|
|
export type ReleaseService = {
|
|
/** 登记写类动作意向(入参冻结,存入草稿态) */
|
|
registerIntent(taskId: TaskId, intent: Omit<ActionIntent, 'taskId' | 'state'>): Promise<ActionIntent>;
|
|
listIntents(taskId: TaskId): Promise<ActionIntent[]>;
|
|
/** 预检 → 全过才发验收工单;不过即抛 `PrecheckFailedError`,打回环内修正 */
|
|
submitForRelease(input: SubmitForReleaseInput): Promise<SubmitOutcome>;
|
|
/** 只跑预检不发卡 —— 环内随时可看「还差什么」 */
|
|
precheck(taskId: TaskId): Promise<PrecheckReport>;
|
|
/** 放行通过即刻落地:草稿合并 + 动作执行(附幂等键)→ 收敛才发射输出口 */
|
|
land(input: LandInput): Promise<LandOutcome>;
|
|
};
|