/** * module: human-tool —— 对外类型(编码规范 §10.1)。 * * **双层边界**(§9):范式只在引擎层;本模块是前端呈现协议的后端面 —— * 工单两模式(执行 / 验收)+ 对话卡族(决策 / 补全 / 评价)。 * 落地失败卡是**执行工单的系统预置形态**,不构成第五种卡(OS 7.3)。 */ import type { AcceptanceWorkOrder, ChatCard, ChatCardReply, ExecutionWorkOrder, StaffId, TaskId, WorkOrder, WorkOrderReply } from '@contracts'; import type { ArrivalSurface, CardViolation } from './internal/domain/card-rules.ts'; export type { AcceptanceWorkOrder, ArrivalSurface, CardViolation, ChatCard, ChatCardReply, ExecutionWorkOrder, WorkOrder, WorkOrderReply, }; export declare class BareCallError extends Error { readonly violations: readonly CardViolation[]; constructor(violations: readonly CardViolation[]); } export declare class ReplyRejectedError extends Error { readonly violations: readonly CardViolation[]; constructor(violations: readonly CardViolation[]); } export declare class HumanCallBudgetExceededError extends Error { readonly taskId: TaskId; readonly used: number; readonly cap: number; constructor(taskId: TaskId, used: number, cap: number); } /** 工单草稿:id / at 由基座补齐 —— ID 生成不外泄给调用方(domain 零随机) */ export type ExecutionWorkOrderDraft = Omit & { readonly id?: ExecutionWorkOrder['id'] | undefined; readonly at?: string | undefined; }; export type AcceptanceWorkOrderDraft = Omit & { readonly id?: AcceptanceWorkOrder['id'] | undefined; readonly at?: string | undefined; }; /** 发卡的公共入参 */ export type IssueContext = { readonly taskId: TaskId; /** 任务负责人 —— 决定到达面两路 */ readonly ownerId: StaffId; /** 收件人;缺省即负责人 */ readonly recipientId?: StaffId; /** 契约的调人预算(打扰上限) */ readonly humanCallCap: number; }; export type IssuedWorkOrder = { readonly order: WorkOrder; readonly arrival: ArrivalSurface; /** 到达面 = system-message 时的消息 ID(跨人卡) */ readonly messageId?: string; }; export type IssuedChatCard = { readonly card: ChatCard; readonly arrival: ArrivalSurface; readonly messageId?: string; }; export type ReplyOutcome = { readonly order: WorkOrder; /** 这张卡挂在哪一单 —— 装配层要拿它把「人就地改的那几行」写回草稿层 */ readonly taskId: TaskId; /** 完成只出自放行通过 —— 这里为真,任务才可收敛终态 */ readonly producesCompletion: boolean; /** 驳回:环内回转,任务继续 */ readonly rejection?: { readonly kind: 'redo' | 'revise'; readonly comment: string; }; /** 选择组的出口选择 —— 随放行一并确认(AM 1.2) */ readonly selectedPorts: Readonly>; }; export type HumanToolService = { /** 发执行工单;裸调用拒发,预算触顶熔断。id / at 留空即由基座生成 */ issueExecution(context: IssueContext, order: ExecutionWorkOrderDraft): Promise; /** 发验收工单 —— 发卡**前**必须已过落地预检(由 release 保证,见其 CONTRACT) */ issueAcceptance(context: IssueContext, order: AcceptanceWorkOrderDraft): Promise; /** 落地失败卡:执行工单的系统预置形态,不是第五种卡 */ issueLandingFailure(context: IssueContext, input: { readonly failures: ReadonlyArray<{ label: string; reason: string; }>; }): Promise; issueChatCard(context: IssueContext, card: ChatCard): Promise; replyWorkOrder(reply: WorkOrderReply, by: StaffId): Promise; /** * 回传带上 `taskId` —— **数据录入卡的确认要当场写草稿**,而写库要知道写给哪一单。 * 由本模块自己写会让 human-tool 依赖 ledger(越层),所以把事实交出去,由组装层落笔。 */ replyChatCard(reply: ChatCardReply, by: StaffId): Promise<{ card: ChatCard; taskId: TaskId; }>; /** 驳回重答:新卡实例,原卡闭合 —— 只增不改 */ rejectAndReask(cardId: string, reason: string): Promise; /** * 给已发出的验收工单补上选择组(AM 1.2 恰选一口)。 * * 为什么分两步:卡由 `release.submitForRelease` 发 —— 它守的是预检那道门, * 不该也不必知道「这个活动有哪些出口」。出口是契约的事实,由 app 从 manifest 现读后贴上。 */ attachPortChoice(workOrderId: string, choice: { group: string; ports: ReadonlyArray<{ name: string; label?: string | undefined; }>; }): Promise; /** * **算出来的去向**上卡 —— 不给人选,只告诉他走哪一口、凭哪一条。 * 去向是台账那几个数的函数;摆成选择题,等于把可回放的判定换成一次手感。 */ attachRoutedPort(workOrderId: string, routed: { group: string; name: string; label?: string | undefined; because: string; }): Promise; openWorkOrders(taskId: TaskId): Promise; /** 全部工单(含已办结)—— 工作成果要回看定稿的报告,只给 open 就永远是空的 */ allWorkOrders(taskId: TaskId): Promise; chatCards(taskId: TaskId): Promise; /** org 停用前置检查要问的「待答卡」 */ openCardsOf(staffId: StaffId): Promise>; };