# module: trigger 职责: 触发器三类(周期两型 / 事件 / 登记)的配置、判定与经调用接口起单; 起单幂等;数据日历型的逐行扫描 不负责: 流程包的结构与流转(见 process)、事件的投递(见 event —— 触发器是它的一个消费方) 公开出口: index.ts - 类型:`TriggerService` `TriggerConfig` `EventScope` `FireOutcome` `AssemblyResult` - 错误:`TriggerInputMissingError` - 端口类型:`TriggerStore` `ProcessGateway` `Sfeel` `DeadLetterSink` `LedgerScanner` - 用例工厂:`createTriggerService(deps): TriggerService` - 纯函数:`matchesEvent` `assembleInput` `triggerIdempotencyKey` `nextCalendarFire` `dataCalendarKey` `applyOffset` `scopeOf` - adapter:`createTriggerStore`;Drizzle 表:`triggerTable` `triggerClaimTable` 层级: L7(编码规范 §4) 依赖: @contracts;@shared/db;process(L7 同层 → 经 `ProcessGateway` 端口由 app 注入); port:`Sfeel` / `DeadLetterSink`(message)/ `LedgerScanner`(ledger) 被依赖: event(经 `TriggerMatcher` 端口,由 app 注入 —— event 是 L1,不反向依赖本模块)、app 不变量(OS 3.1 / 6.3): - **命中不等于必起**(2026-07-30 触发确认链路):触发器可勾「需人工确认」(运营配置, 设计面的 upsert 不写 confirm 两列,只有 setConfirm 动)。勾了,命中后装配好的入参 存成待确认单(`sys.trigger_pending`),带来件内容的系统消息(`ConfirmDesk` 端口)送 指定人工作台;`confirmPending` 才起单。**先认领后起单**(consumed_at 空才认得到), 并发确认只有一个赢;起单失败退回认领,不留死票。登记触发不走确认 —— 登记那一下本身就是人在确认;勾了确认没指定人 = 配置错误入死信,不静默直起。 - **触发器与流程包平级**:配置独立存放,增删启停**不改流程包的任何版本** - **只负责起单**:经调用接口调起流程包;流程包与活动内部不含任何触发逻辑 - **同一事件流,不另设通路**:`match` 供 event 的三级消费判定使用 - **同一事件对同一触发器至多起一单**:以事件 ID 为幂等键 - **宽进**(2026-07-30,用户定,替代旧「缺必填即入死信」):缺必填**照样起单** —— 装到多少带多少(`AssemblyResult.partial`);收敛点在活动:受理归一、信息不全派补全单。 死信只留给真错误(勾了确认没指定人、包无生效版这类配置错误) - **数据日历型同一行同一日期只触发一次**(键含日期值);字段值变更后可再触发 - 命中规则求值失败按**不命中**处置 —— 规则写坏了不让事件流停摆