Archived
三面拆分⑬:触发确认链路 + 运营中心「工作流」区 —— 设计只管设计,运营管细节
**触发确认链路**(用户口述五步的第 4/5 步):
接收邮件 → 分类识别 → 命中 RFQ 事件 → ④(可选,运营勾)系统消息到指定人
工作台(带邮件内容)→ ⑤ 工作台点「确认起单」,流程才起。
· 命中不等于必起:勾了「需人工确认」,装配好的入参存成待确认单
(sys.trigger_pending,migration 0019),ConfirmDesk 端口把带来件内容的
系统消息送指定人(eventRef 挂票号,消息列表就地贴确认状态与那枚钮)。
· 先认领后起单:consumed_at 空才认得到 —— 两人同时点、一人点两次,都只起一条流;
起单失败退回认领,不留死票。确认人记进 source.by,留痕可查。
· 登记触发不走确认(登记那一下本身就是人在确认);勾了没指定人 = 配置错误入死信。
· 4 条单测 + 全链实测:投信 → triggersHit=1 且零直起 → AI 工作台收到确认消息
→ 确认起单 → 二次确认幂等回同一流号 → source.by = AI。
**运营中心重排**(区名即运行时:工作流是流程包的运行时,任务是活动的运行时):
· 新「工作流」区:在途看板(从任务区迁入)+ 运行配置 —— 每包的触发器
起单开关 / 确认打勾 / 确认人,和节点负责人(sys.node_owner)。
· 负责人三层:显式指派 > 运营配置 > 轮值 —— 合并点在 process.start,
复用既有派发链一行不改。
· 任务区瘦身成活动运行时(任务/审批/需处置);知识库区改名「数据」
(与设计中心的知识库解开同名);系统区只剩通道实例。
· 设计中心触发器详情页摘掉启停按钮 —— 设计只管设计,启停/确认全在运营。
· 旧深链有改嫁:tasks/board → runs/board,tasks/trg → runs/conf。
reset-runs 补 sys.trigger_pending(待确认单是运行痕 —— 和上回漏 trace_span 同类洞)。
邮件分类 Agent(第 ② 步)现由抽键正则 + S-FEEL 代位,升级路径记进 debt.md。
产品设计.md 运营章、trigger/process 两份 CONTRACT.md 同步。
五闸绿;契约快照随本提交入库。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
@@ -524,6 +524,35 @@ export const listApprovalsRoute = {
|
||||
* 起一条流(测试台专用):**带节点指派**把整条流定向到指定账号 ——
|
||||
* 真实任务照旧落到那个人的工作台,测试台只管起单与观测。
|
||||
*/
|
||||
/**
|
||||
* 触发器的**运营配置**:要不要人工确认、谁来确认 —— 与设计面的 upsert 分口,
|
||||
* 设计动规则不碰这两项,运营动这两项不碰规则。
|
||||
*/
|
||||
export const setTriggerConfirmRoute = {
|
||||
method: 'POST',
|
||||
path: '/api/gov/triggers/:id/confirm',
|
||||
params: z.object({ id: z.string() }),
|
||||
body: z.object({ required: z.boolean(), staffId: z.string().optional() }),
|
||||
output: z.object({ ok: z.boolean() }),
|
||||
} as const satisfies RouteContract;
|
||||
|
||||
/** 节点负责人(运营配置):流程包的哪个节点归谁 —— 显式指派 > 这里 > 轮值 */
|
||||
export const listNodeOwnersRoute = {
|
||||
method: 'GET',
|
||||
path: '/api/gov/packages/:id/owners',
|
||||
params: z.object({ id: z.string() }),
|
||||
output: z.object({ owners: z.array(z.object({ nodeId: z.string(), staffId: z.string() })) }),
|
||||
} as const satisfies RouteContract;
|
||||
|
||||
export const setNodeOwnerRoute = {
|
||||
method: 'PUT',
|
||||
path: '/api/gov/packages/:id/owners/:nodeId',
|
||||
params: z.object({ id: z.string(), nodeId: z.string() }),
|
||||
/** null = 撤掉运营指定,回到轮值 */
|
||||
body: z.object({ staffId: z.string().nullable() }),
|
||||
output: z.object({ ok: z.boolean() }),
|
||||
} as const satisfies RouteContract;
|
||||
|
||||
export const testRunRoute = {
|
||||
method: 'POST',
|
||||
path: '/api/gov/testbed/run',
|
||||
|
||||
@@ -186,6 +186,13 @@ export const systemMessageSchema = z.object({
|
||||
supersededBy: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
/**
|
||||
* 待确认起单(触发确认链路):触发器命中但勾了「需人工确认」——
|
||||
* 这条消息带着那一票,`confirm.consumed` 前工作台上有一枚「确认起单」钮。
|
||||
*/
|
||||
confirm: z
|
||||
.object({ pendingId: z.string(), consumed: z.boolean(), workflowId: z.string().optional() })
|
||||
.optional(),
|
||||
});
|
||||
export type SystemMessageView = z.infer<typeof systemMessageSchema>;
|
||||
|
||||
@@ -211,6 +218,14 @@ export const answerMessageRoute = {
|
||||
output: z.object({ ok: z.boolean() }),
|
||||
} as const satisfies RouteContract;
|
||||
|
||||
/** 确认起单 —— 幂等:已被确认过就如实说,并回那条流的号,绝不起第二条 */
|
||||
export const confirmTriggerPendingRoute = {
|
||||
method: 'POST',
|
||||
path: '/api/desk/trigger-pending/:id/confirm',
|
||||
params: z.object({ id: z.string() }),
|
||||
output: z.object({ workflowId: z.string(), alreadyStarted: z.boolean() }),
|
||||
} as const satisfies RouteContract;
|
||||
|
||||
export type ListMessagesOutput = z.infer<typeof listMessagesRoute.output>;
|
||||
|
||||
/* ── 纪要:工作台五要素里唯一的主动动作 ─────────────────────────────── */
|
||||
|
||||
@@ -278,6 +278,15 @@ export const triggerConfigSchema = z.object({
|
||||
processPackageId: processPackageIdSchema,
|
||||
/** 起单载荷装配:事件信封与载荷字段 → 调用接口的 data 字段;缺必填即起单失败入死信 */
|
||||
mapping: z.array(fieldMappingSchema).default([]),
|
||||
/**
|
||||
* 人工确认 —— **运营配置**(运营中心 · 工作流里勾),不随设计动:
|
||||
* 勾了,命中后不直接起单,先发带来件内容的系统消息到指定人工作台,
|
||||
* 他点「确认起单」流程才起。登记触发不适用 —— 登记那一下本身就是人在确认。
|
||||
* 设计面的 upsert **不写**这两项(那会把运营的勾抹掉),只有运营口(setConfirm)动它。
|
||||
*/
|
||||
confirm: z
|
||||
.object({ required: z.boolean().default(false), staffId: staffIdSchema.optional() })
|
||||
.default({ required: false }),
|
||||
/**
|
||||
* 判别式取**四个互斥值**:周期触发的两型(日历 / 数据日历)在此展开 ——
|
||||
* `TRIGGER_KINDS` 仍是三类分类学(周期 / 事件 / 登记),两者以 `triggerKindOf()` 对应。
|
||||
|
||||
Reference in New Issue
Block a user