# r3-engineer.md · 工程师 R3 修订版 **作者视角**: 工程师(实现细节 / 边界异常 / 可测试性 / 性能) **修订基线**: r1-engineer.md(R1 稿)+ r2-pm-reviews-others.md + r2-architect-reviews-others.md(针对工程师的 review) **修订日期**: 2026-05-23 **修订原则**: [需要改] 必修;[冲突] 协商或转 OPEN_QUESTION;[建议] 自由采纳;保留未被 review 命中的章节 > 关键变更摘要(详细见文末"R3 修订记录"): > 1. **求解器**: SCIP → **CP-SAT**(服从架构师 E-A1) > 2. **决策变量口径**: 周聚合 5200 → **日级 72000**(200 SKU × 90 天 × 2 物流 × 2 = x+y 二元,对齐架构师 E-A2/E-A7) > 3. **Robust 方案**: v1 用 **3 场景(P10/P50/P90)独立跑 + stage-1 共享 non-anticipativity**(对齐架构师 E-A5);最终写入助理待办的是"基础决策 = P50 解 + 三场景一致性标签" > 4. **预警 SLA**: 15min → **承诺 30min / 目标 15min**(与 PM/架构师统一) > 5. **infeasible**: 自动放松 → **改为弹窗让 CEO 三选一**(PM 反馈) > 6. **§5.4 非法参数**: 后端兜底 max → **改为 reject 400 + audit**(PM 反馈) > 7. **§5.6 灵敏度**: 27 场景 → **15 场景(3 关键参数 OAT 6 场景 + 2 关键参数 9 组合)** > 8. **§5.7 preview-decision**: 砍掉"实时置信度重算"(架构师 E-A3) > 9. **§5.8 实时刷新**: WebSocket → **v1 仅 30s 轮询**(架构师 E-A8) > 10. **§5.2 Schema 映射器**: v1 锁定硬编码 + ingestion_run_id / content_hash 双 ID 拆分 > 11. **§5.9 推送**: 强制 ≥ 2 独立渠道 + critical 穿透静音 UI 显式告知 + fire-and-forget > 12. **ADR-06**: "周决策 vs 每日 + 事件触发" 改为 OPEN_QUESTION --- ## §5 详细功能说明 ### 5.1 通用约定(时区 / 格式 / 货币 / i18n / 命名) | 项 | 约定 | 说明 | |---|------|------| | 时区 | 所有持久化时间用 UTC(ISO 8601, 含毫秒+Z) | 解决 R1-T8 | | 业务日切 | 按"美西站点本地时间"日切(PST/PDT,含夏令时) | 销量/库存以亚马逊站点为准 | | 展示时区 | UI 默认 Asia/Shanghai,用户可切换 | 顶部时区指示器 | | 货币 | 原值以销售站点币种存储(USD 为主);展示按"原币 + 折算 CNY"双显示 | **汇率拉取时间改为美西时间 23:00 拉取(与日切对齐),缓存 24h**(响应架构师 P-A7) | | 汇率展示口径 | 展示汇率为日批跑时刻汇率,盘中不重新折算 | 兼容性说明同步给 PM §10.4 | | 数量精度 | 件 = 整数;金额 = 2 位小数;天数 = 1 位小数;百分比 = 1 位小数 | 所有 UI/导出一致 | | SKU 编号 | 内部 SKU ID = UUIDv4;展示用 seller-sku(≤ 40 字符) | 解耦 ASIN 与 SKU | | 时间窗口 | 决策计算窗口 T = 90 天滚动;历史训练窗口 = 365 天 | | | 空值规则 | 必填缺失 → 拒绝写入并标 error;可选缺失 → null + 标 warning | | | i18n | v1 仅中文(zh-CN);预留 i18n key | v1.5 可加英文 | | 文件导出 | CSV 用 UTF-8 BOM;时间列附 ISO 字符串列 | | | ID 幂等 | 所有创建型 API 必须接受 client_request_id(TTL 24h) | | | 取整规则 | 数量上取整(ceil),金额四舍五入(half-even) | | ### 5.2 FR-1 数据接入 Adapter **位置**: 系统底座 / "数据源管理"页 + "数据快照"页 **界面元素与展示规则**(**变更**:移除"Schema 字段映射器"行): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 数据源列表(12+4 项 D1~D16) | Table | 显示名称/类型/最后同步/状态徽章 | 点击进详情 | 无 admin 权限只读 | | 模式切换 Toggle | Switch | "Mock" 模式 | 切到 Real 弹二次确认;记 audit | Real 数据源未接入时禁用 | | 同步频率选择 | Dropdown | 日(02:00 UTC) | 可选 实时/15min/1h/日 | 数据源不支持 push 时实时档禁用 | | 立即同步按钮 | Button | 可点 | 触发即时拉取 | 上次同步 < 60s 内禁用 | | 数据质量校验报告 | Panel | 折叠 | 展开显示 缺失率/异常值数/重复键数 | 无最近一次同步时禁用 | | 数据快照列表 | Table | 倒序 30 天 | 选中可"复制为决策输入" | 快照被引用时禁用删除 | | **Schema 字段映射查看器(只读,v1)** | Panel | 显示当前 v1 硬编码 FBA schema | 仅展示,不可编辑 | **v1 完全只读;v1.5 开放编辑(迁入 TD-15)** | **交互逻辑**(**关键变更**:①Schema 映射器降级 ②snapshot ID 拆分): 1. **Adapter 抽象层**:Strategy 模式 `IDataAdapter`(`fetch / normalize / validate`);v1 提供 `MockAdapter` 与 `FBAStubAdapter`。 2. **Schema 映射 v1 锁定**(响应架构师 E-A6):v1 阶段 Schema 映射硬编码在 `FBAStubAdapter` 内,**不开放运行时编辑/版本回滚**;UI 只读展示。这样 `forecast_point / decision_recommendation` 的输入字段名永不变,避免快照引用失效(架构师 §4.4.4 强一致区约束)。v1.5 解锁时新增 `schema_mapping_version` 实体(详见 TD-15)。 3. **数据写入双 ID 拆分**(响应架构师 E-A11): - `ingestion_run_id`(行级,UUID):每行写入哪次拉取,用于审计追溯(写入 architect §4.3.2 schema) - `snapshot_content_hash`(运行级,sha256(payload)):整批数据的内容指纹,用于求解器输入缓存命中判断(§5.5 缓存逻辑用) - 旧的合并 `snapshot_id` 字段废弃 4. **统一标准时间**:每条 raw record 入库时附 `source_tz`、`source_ts`、`utc_ts`、`business_date_pst` 四个字段。 5. **数据质量校验**:6 类规则(必填非空 / 类型 / 值域 / 引用完整性 / 异常值 z-score / 时序连续性)。 6. **Mock→Real 切换审计**:每次切换写 `audit_log`;UI 顶部斑马条样式由模式决定。 **异常场景**(保留 R1 全表,新增 1 行): | 类型 | 场景 | 处理 | |---|---|---| | 网络异常 | 数据源 API 超时(>30s) | 重试 3 次(指数退避 1s/4s/16s);失败用上次快照 + 顶部红条 + alert | | 网络异常 | DNS 解析失败 | 降级到 last-known-good 快照;P1 告警 | | 数据异常 | 字段缺失 > 5% | 拒绝整批写入;UI 弹错误详情 + 下载 sample | | 数据异常 | 销量负值/价格 0 | 该 SKU 标 quarantine,不进优化 | | 数据异常 | 同 SKU 同日两条不同库存 | 取 source_ts 最新;记 conflict log | | 权限不足 | 切 Real 但无 admin | 弹"无权限"toast | | 第三方失败 | FBA API 返 5xx | 重试 + 降级;连续 24h 失败 → P0 | | 第三方失败 | API 限流 429 | 按 Retry-After 头退避 | | 设备差异 | 移动端数据源列表过宽 | 横向滚动 + 关键列固定 | | 用户操作冲突 | 删除快照时该快照正被引用 | 阻止删除 | | **数据异常(新)** | **Schema 不匹配(FBA API 升级新字段)** | **v1 阶段:硬阻断 + 写错误日志 + P0 通知 admin(不允许运行时调整 schema)** | **边界数值**: 同 R1。 --- ### 5.3 FR-2 销量预测(区间预测) **位置**: 后台 / "预测中心" + 主 Dashboard 内嵌区间图 **界面元素与展示规则**: 同 R1。 **交互逻辑**(**关键变更**:3 quantile 改为对齐架构师场景法): 1. **模型方案**:分层路由 —— 稳定 SKU(FR-16 输出"稳定"类)用季节性朴素法 + Holt-Winters;波动 SKU 用 LightGBM 分位数回归(**quantile 0.1 / 0.5 / 0.9 三个模型同训**,对齐架构师 E-A5 共识"v1 用 3 场景,5 场景 P25/P75 留 v1.5");长尾 SKU 直接出"低需求标签 + 安全库存常数"。 2. **特征**:销量历史(滞后 1/7/14/28)/ 7 天均值与标准差 / DOW / 月内位次 / 广告 spend / BSR / 价格 / 是否促销日 / 是否缺货历史日。 3. **训练频率**:每日 01:00 UTC 增量训练;每周日全量重训。 4. **区间→优化引擎对接**(**变更**):FR-2 输出 `{p10, p50, p90}` → FR-4 引擎用这 3 个分位点构造 **3 场景**(S_low=P10 / S_mid=P50 / S_high=P90),权重 0.25 / 0.50 / 0.25,对应架构师 §3.5.4 "3 场景退化方案"。**v1.5 升级到 5 场景时模型扩到 5 quantile**。 5. **置信度→人话翻译**(FR-6 联动):区间宽度 / p50 ≤ 0.3 → 高;0.3–0.6 → 中;>0.6 → 低。 6. **置信度更新触发器**(响应架构师 E-A3):置信度仅在**每日批跑后更新**,不在 preview-decision 实时重算。 **异常场景**: 同 R1。 **边界数值**: - 训练窗口下限:14 天 - 异常值截断:z-score > 6 winsorize - 模型保留版本数:30 个 - 训练单 SKU 时长上限:30 s - 区间显示精度:销量单位件,p50 取整;区间下界 max(0, floor(p10)) --- ### 5.4 FR-3 经济目标函数实现 **位置**: 后端核心服务"计算引擎 / 目标函数模块"(无独立 UI;通过 FR-6 可解释面板间接展示) **界面元素与展示规则**("参数管理"页 UI): 同 R1。 **交互逻辑**(保留 R1 5 条): 1. **目标函数实现**:插件式函数注册 —— 每项成本/收益作为一个 `CostComponent`;总目标 = Σ components。 2. **缺货分段**:缺货损失分两段——day 0..14 线性(=日销售额);day 15..∞ 加 `rank_recovery_multiplier × decay(d)` 项(decay = 指数衰减 30 天衰到 1)。 3. **存储**:所有参数版本化(`parameters` 表 with effective_from / effective_to),决策计算时绑定 snapshot 的参数版本号。 4. **单位一致性**:所有金额内部用 USD 微元(micro-USD = 1e-6 USD,整数)避免浮点误差。 5. **目标函数 self-test**:每次发布前跑 50 条预置 case,失败则阻断发布。 **异常场景**(**关键变更**:非法参数改为 reject 400): | 类型 | 场景 | 处理 | |---|---|---| | 数据异常 | FBA 费率表 SKU 体积缺失 | 该 SKU 用品类平均费率,并标 warning | | **数据异常(变更)** | **缺货倍数被改成负数** | **前端表单校验拦截;后端遇到非法值(含负数、超出 [0.1, 100] 区间)直接 return 400 错误 + audit log,不做静默兜底;可解释面板 `parameter_version` 必须显示真实参数值**(响应 PM 反馈:兜底改值跟可解释承诺冲突) | | 并发冲突 | 决策跑到一半参数被改 | 决策绑定参数 snapshot,本次任务不受影响 | | 权限不足 | 普通用户改参数 | 403 + UI 隐藏编辑按钮 | | 第三方失败 | 汇率 API 失败 | 用最近 24h 缓存;超 24h 用 30 天均值并标 warning | | 用户操作冲突 | 回滚参数到已被清理的版本 | 提示并阻止 | **边界数值**(**关键变更**:变量数口径统一为日级 72000): - 参数版本保留:100 个 + 永久保留"被引用于已执行决策"的版本 - **单次目标函数评估 < 5 ms(200 SKU × 90 天 × 2 物流方式 × 2 (x 连续 + y 二元) = 72000 变量,对齐架构师 §3.1.1 决策变量口径,响应 E-A7)** - 浮点容差:1e-6 USD --- ### 5.5 FR-4 MINLP 优化引擎 **位置**: 后端核心 / 调度任务(无独立 UI;通过 FR-6 决策清单展示结果)+ "求解器监控"管理页 **界面元素与展示规则**(管理页)(**变更**:求解器配置改为 CP-SAT): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 当前任务进度 | ProgressBar | 0% / 实时百分比 | hover 显示当前阶段 | - | | 历史任务表 | Table | 最近 30 天,倒序 | 列:runId/触发方式/SKU 数/求解时长/状态/decision_id | - | | **求解器配置** | Panel | **显示当前 backend = CP-SAT (Google OR-Tools)** + worker 数(默认 8)+ time_limit + gap_tolerance | 改后下次任务生效 | 非 admin 只读 | | 失败任务详情 | Modal | - | 显示日志 + 求解器 stderr + 重跑按钮 | - | | 求解性能图表 | Chart | 30 天求解时长趋势 | hover 显示当日详情 | - | | **infeasible 决策弹窗(新)** | **Modal** | **infeasible 时主动弹出**(FR-6 顶部红条 + 此 Modal)| **CEO 三选一:①批准临时多花 X% 资金(带预填 +20%,可调)②跳过这批不下单 ③改其他 SKU 节省(进入子流程让 CEO 选择牺牲 SKU);选 ① 时必须确认文字"我授权本次临时增资 $XXX"** | **不属 admin/CEO 角色禁用整 Modal** | **交互逻辑**(**关键变更**:①SCIP→CP-SAT ②周聚合→日级 ③三场景输出"主推+次推+底线" ④infeasible 改弹窗): 1. **求解器选型**(响应架构师 E-A1,服从其裁决):v1 默认 **CP-SAT (Google OR-Tools,Python via `ortools.sat.python.cp_model`)**;理由:(a) 对启动成本/最小批量这类逻辑约束表达自然;(b) 8 worker 并行性能成熟;(c) MILP gap 报告完善;(d) 与架构师 §3.5.4 性能预算(5 场景 10-30 min)口径一致。接口抽象为 `IOptimizer`,**SCIP 留作 v1.5 备选**(如 CP-SAT 在大规模 SKU 表现不佳)。 2. **问题形式化**(**关键变更**:日级而非周聚合,响应架构师 E-A2 + E-A7): - 决策变量:`x_s,t,m ∈ Z_+`(SKU s × **天 t(t = 1..90,日级**) × 物流方式 m)+ `y_s,t,m ∈ {0,1}`(是否在该日发货的二元变量,用大 M 跟 x 耦合) - 维度:200 SKU × 90 天 × 2 物流 × 2 (x + y) = **72000 决策变量** - 目标:max Σ (revenue - cost components) - 约束:库存平衡递推(C1);FBA Restock Limit(C2);总资金(C6);批量经济量起订(C3);x ≤ M·y 大 M 耦合(C7) 3. **3 场景 Robust 方案**(响应架构师 E-A5 + PM "三场景按哪个执行" 反馈): - **基础解 = P50 单场景求解**,作为唯一进入 FR-7 助理待办的"主推决策" - **次推 = P10 解(悲观/容量足)**:仅作"对照"展示在 FR-6 详情面板,不进待办 - **底线 = P90 解(乐观/最少补货)**:仅作"对照" - **三场景一致性标签**(喂给 FR-6 置信度):若 P10/P50/P90 三解的"是否发货 + 物流方式"对某 SKU 完全一致 → 高一致性 / 一项差异 → 中 / 两项差异 → 低 - **v1.5 升级到 stage-1 共享 non-anticipativity + CVaR 多场景联合优化**(架构师 §3.5 完整方案) 4. **维度控制**:72000 变量。预处理:对超低需求 SKU(FR-16 长尾)跳过优化直接走规则;对当前库存 >120 天可卖的 SKU 跳过;预期参与求解 SKU 数 ≈ 100-150。 5. **后处理**:日级解直接拆出 per-SKU per-day 发货建议;输出含 per-SKU 的成本/收益拆解(喂给 FR-6 可解释面板)。 6. **接口阻抗已通过 §5.3 N4 解决**:FR-2 输出 P10/P50/P90 三档,FR-4 用 3 场景独立跑后按 N3 输出主推+次推+底线。 7. **缓存**:相同 input_hash(`snapshot_content_hash` + params_version + forecast_version)24h 内命中缓存。 **异常场景**(**关键变更**:infeasible 改弹窗确认): | 类型 | 场景 | 处理 | |---|---|---| | **数据异常(变更)** | **模型 infeasible(约束冲突,如 Restock Limit < 必须补量、资金不够)** | **不再自动放松软约束。改为:①优化引擎返回 `infeasible_diagnosis`(列出哪些约束被违反、违反多少);②FR-6 顶部弹"infeasible 决策弹窗"(见上表)让 CEO 三选一;③选 ① 批准临时多花后,绑定该次决策的"临时参数 snapshot"重跑(不污染全局参数);④所有 infeasible 事件写 `infeasible_log` 表,周复盘可看**(响应 PM "重大决策不静默") | | 数据异常 | 求解器返回 unbounded | 阻断;通知管理员;fallback 用上次决策 | | 第三方失败 | CP-SAT worker 进程崩溃 / OOM | 监控 + 自动重启 1 次;二次失败上报 P0 | | 并发冲突 | 同一 snapshot 被两个调度同时触发 | 分布式锁(Redis SETNX, TTL 30min);后到的等待并复用结果 | | 性能 | 求解超时(>30 min) | 接受 CP-SAT current best 解,并标"未达最优 gap = X%" | | 用户操作冲突 | 用户点"重跑"时上一个任务未结束 | 提示"上一个任务进行中"或选"取消并重跑" | | 设备差异 | 管理页移动端宽度不足 | 关键列固定,详情进二级页 | **边界数值**(**关键变更**:72000 变量、单次时长延长): - **单次求解时长上限:1800 s(30 min,基础解 P50 场景)**;3 场景串行总时长 ≤ 90 min(与架构师 §3.5.4 性能预算口径一致;如 R2 二次 spike 显示串行超时,启用并行 3 worker 跑 3 场景) - gap 容忍:默认 1% - 内存峰值:< 8 GB(CP-SAT 8 worker) - 并发任务上限:1(v1 单租户单实例) - 求解输入缓存 TTL:24 h - **决策变量数(口径统一)**:200 SKU × 90 天 × 2 物流 × 2(x+y) = 72000 --- ### 5.6 FR-5 灵敏度分析模块 **位置**: 后端模块 + Dashboard 二级 Tab "灵敏度" **界面元素与展示规则**(**变更**:扰动场景数 27 → 15): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 参数选择 Chip 组 | Chip Group | 默认勾选 "缺货倍数 / 资金成本率 / 销量 p50" | 多选触发重跑 | 优化引擎任务进行中禁用 | | 扰动范围 | RadioGroup | ±20% | ±10/±20/±30/自定义 | - | | 龙卷风图 | Chart | 横向条形,按参数对总收益的影响排序 | hover 显示扰动前后数值 | 无最近一次基础决策时禁用 | | 决策稳定性指标 | Card | 显示"核心决策稳定率 X%" | hover 解释计算口径 | - | | 单 SKU 决策切换表 | Table | 默认隐藏 | 展开显示"扰动后变更物流方式或数量的 SKU 清单" | - | | 跑灵敏度按钮 | Button | 可点 | 触发后台 batch 任务 | 上次跑 <30min 内禁用 | **交互逻辑**(**关键变更**:场景数对齐架构师): 1. **执行模式**(响应架构师 E-A4):**OAT 6 场景**(3 个关键参数 × {−20%, +20%} = 6)**+ 2 关键参数全组合 9 场景**(缺货倍数 × 资金成本率,3 档 × 3 档)= **共 15 场景**(替代 R1 的 27 场景)。 2. **核心决策稳定率定义**:"核心决策" = top-30 总成本 SKU 的"是否发货 + 物流方式" 二元决策;稳定率 = (扰动后与基础一致的核心决策数) / 30;**口径与 PM §8.2 "≥ 70%" 一致**(仅 top-30 SKU;物流方式翻转算 1 票不一致)。 3. **结果存储**:灵敏度 run 是独立 entity(`sensitivity_runs`),关联到基础 decision_id;保留 90 天。 4. **触发时机**:每日基础决策后自动跑一次(凌晨 03:00 UTC);用户也可手工触发。 5. **可解释面板**联动:FR-6 单条建议里嵌"该建议在 ±20% 扰动下稳定/不稳定"小图标。 6. **与 §5.5 robust 区分**(响应 PM P-A2 反馈):FR-5 灵敏度针对**经济参数**(缺货倍数、资金成本率);§5.5 的 3 场景针对**销量需求**不确定性——两者口径不同、UI 不混合展示。 **异常场景**: | 类型 | 场景 | 处理 | |---|---|---| | 性能 | 15 场景 × 5 min ≈ 75 min 仍偏长 | warm-start MIP(基础解为热启动);目标 ≤ 60 min;超时记 timeout 跳过余下场景 | | 数据异常 | 某个扰动场景 infeasible | 该场景标"infeasible",不计入稳定率分母 | | 并发冲突 | 用户手工触发与定时任务冲突 | 队列化 | | 第三方失败 | CP-SAT 在第 N 个场景失败 | 跳过该场景,记 log;不影响其他 | | 设备差异 | 龙卷风图在小屏失真 | 切换为表格视图 | **边界数值**: - 单场景求解时长(heuristic warm-start):≤ 240 s - 总 batch 时长上限:3600 s(1h,与架构师 §3.2.3 性能预算 1h 硬超时对齐) - 目标 batch 时长:≤ 60 min - 稳定率统计 SKU 数:top 30(按总成本) - 场景数:15(OAT 6 + 全组合 9) --- ### 5.7 FR-6 决策清单 + 可解释面板 **位置**: 主 Dashboard 首页"今日决策" Tab(**注**:决策频率"每日"vs"周节奏"留作 OQ-E1,详见 R3 修订记录) **界面元素与展示规则**(**变更**:可解释面板新增"三场景对照" + 决策版本区分 superseded/expired): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 顶部摘要卡片 | Card | "今日扫描 200 SKU,建议发货 N 项,预估总收益影响 +$X" | 数据更新时间戳 + Mock/Real 模式徽章 | 无最近决策时显示空态 | | 决策清单 | Table | 默认按"建议优先级"倒序 | 列:SKU/当前库存/可卖天数/建议数量/物流/置信度/预估收益/操作 | 决策任务跑挂时显示"昨日 11:23 决策"+ 红条 | | 空清单态 | EmptyState | "今日 200 SKU 都健康,最近临界 SKU 还有 45 天" + 库存全景缩略图 | 点缩略图进 FR-9 仪表盘;**额外展示"过去 7 天回顾 / 平均决策准确率 / 累计节省金额"**(响应 PM AC 矩阵反馈,对齐 US-5) | - | | 单条操作按钮组 | ButtonGroup | "接受/调整/改物流/跳过/查看详情" | 接受/跳过后该行折叠+置灰 | "已执行"行禁用 | | 批量选择框 | Checkbox | 未勾 | 勾选后顶部出现"批量接受 N 条"按钮(联动 FR-14) | 用户非 decision_owner 时禁用 | | 可解释面板(侧抽屉) | Drawer | 关闭 | 点行展开,分 3 层:①一句话理由 ②6 项收益/成本分解条形图 ③数学展开(公式 + 参数版本 + 预测区间 + 灵敏度小图)+ **新增 ④"三场景对照":P10/P50/P90 三套解的差异(如"乐观场景建议数 80 / 主推 100 / 悲观场景建议 150"),让 CEO 理解"如果实际销量偏低/偏高,决策怎么变"** | - | | "今日已决"折叠区 | Section | 默认折叠 | 展开看今日已处理的决策(含跳过原因) | - | | **"已被新建议替代"区(变更)** | **Section** | **默认折叠** | **展开看昨日 superseded(系统自动替代)的决策;与"我跳过的"和"24h 过期我未拍板"分三段视觉区分**(响应 PM 反馈 P-A7 + §5.7-§5.13 冲突)| - | | 信息密度切换 | Toggle | 精简(默认) | 切"详细" → 表格多 4 列;切"专业"显示数学符号 | - | | **infeasible 顶部红条 + 弹窗(新)** | **Banner+Modal** | **infeasible 时主动弹出**(详见 §5.5 弹窗逻辑) | **CEO 三选一处理** | - | **交互逻辑**(**关键变更**:①preview-decision 砍置信度 ②决策版本区分 superseded/expired ③三场景对照 UI ④CEO 收助理退回通知): 1. **三层信息分层**:摘要 30 秒 / 决策清单 5 分钟 / 可解释面板 数学层(专业模式)。 2. **拍板交互闭环**: - "接受" → 写 `decisions` 表 status=accepted,触发 FR-7 助理任务创建 - "调整数量" → 弹 Modal 输入新数量;保存后 status = accepted_modified - "改物流" → 切换 sea↔air;后端重算成本并显示对比 - "跳过" → 必须填原因;status = skipped - "查看详情" → 抽屉(含三场景对照) 3. **置信度文案**:高 = "本建议在多场景下稳定,可放心执行";中 = "本建议受 1-2 个参数较大影响,建议看下详情";低 = "本建议不稳定,建议人工判断"。 4. **preview-decision 实时重算**(响应架构师 E-A3): - 前端送参数 → 后端 `/preview-decision` API(< 200ms) - **只重算 landed cost + 预估收益**(这两项是闭式计算,可在 200ms 内完成) - **不重算置信度**:置信度沿用上次批跑结果;调整数量后 UI 加 tooltip:"置信度按今早批跑结果,调整数量后此值仅供参考;如需精确置信度请等下次批跑或手工触发灵敏度跑" - 单 SKU 重算非全局最优(PM US-3 文案对齐:tooltip"此为单条决策的成本变化,全局最优需等下次批跑") - 前端 debounce 300ms 5. **空清单设计**:除"今日健康"文字外,下方展示"未来 7/14/30 天最早到临界 SKU"倒计时(来自 FR-15)+ "过去 7 天回顾 / 平均决策准确率 / 累计节省金额"三项小卡片(响应 PM AC 覆盖反馈)。 6. **决策版本生命周期**(响应 PM P-A7 + §5.7 vs §5.13 冲突): - **superseded**:每次基础决策跑出来后,原本"未拍板"的"昨日清单"自动标 superseded("已被新建议替代");视觉=灰色背景 + 蓝色"已替代"标签 - **expired**:决策 24h 后用户未拍板自动 expired(区别于 superseded:expired 是无新建议覆盖时的过期,superseded 是有新建议覆盖时的替代);视觉=灰色背景 + 橙色"已过期"标签 - **accepted / accepted_modified / skipped**:用户主动拍板,状态独立 - **周复盘评分口径**(响应 PM §5.7 vs §5.13 冲突):周复盘仅评 `accepted / accepted_modified` 两类(用户负责的部分);superseded / expired / skipped 不进 FR-12 正确率分母,但单列"系统反复自我修正的 SKU 清单"作为模型质量参考 7. **CEO 收助理退回通知**(响应 PM 建议):助理点"退回 CEO"后,触发 FR-8 推送 priority=warning 到 CEO(默认企微)+ FR-6 顶部红色徽章 "您有 N 条决策被助理退回,需复核";点击进退回详情页 **异常场景**: 同 R1,新增 1 行: | 类型 | 场景 | 处理 | |---|---|---| | 数据异常 | 决策清单缺关键字段(如预估收益 null) | 该行显示"数据异常"+ 灰色 + 禁用接受 | | 网络异常 | "调整"重算 landed cost 接口超时 | 输入框旁红字提示,按钮禁用;3 秒后允许重试 | | 并发冲突 | 用户接受某条时该条已被助理标"已执行" | 弹"已被执行,刷新查看最新状态" | | 并发冲突 | 同时打开两个 tab 各自拍板 | decision_id + version 乐观锁;后到的提示冲突 | | 权限不足 | 助理打开本页 | 仅可"查看",所有操作按钮置灰 | | 第三方失败 | 求解器昨晚失败导致今日无清单 | 顶部红条 "决策任务昨夜失败" + "查看原因"链接 + "用前日决策"按钮 | | 设备差异 | 移动端表格无法横滚 | 切换"卡片视图" | | 用户操作冲突 | "调整数量"调到 0 | 拦截:提示"请用'跳过'代替 0 数量" | | 用户操作冲突 | 重复接受同一条 | 幂等键(decision_id+action)防重 | | **infeasible 场景(新)** | **求解器返 infeasible** | **顶部红条 + 弹窗让 CEO 三选一**(详见 §5.5) | **边界数值**: 同 R1。新增:决策版本 expired TTL = 24h(从 base decision 时刻起);superseded 触发条件 = 新基础决策跑出时所有未拍板的旧决策;CEO 收退回通知延迟 < 30s。 --- ### 5.8 FR-7 助理操作视图 + 状态回写 **位置**: 助理专用工作台 **界面元素与展示规则**: 同 R1。 **交互逻辑**(**关键变更**:WebSocket → 30s 轮询,对齐架构师 E-A8): 1. **状态机**:accepted → pending → in_progress → shipped;任何状态可 → blocked(带原因);24h 内可 → returned_to_ceo(FR-7 助理否决权)。**`returned_to_ceo` 后原决策状态改为 `pending_review`**(与架构师 §6.2.1 + PM §10.3.1 三方统一命名,响应架构师 P-A5;决策状态 enum 在 schema 中新增 `pending_review` 取值)。 2. **状态回写**(**变更**):助理操作后通过**前端 30s 轮询** + **状态变更 push 到通知队列**(不走 WebSocket);CEO 视图 30s 后看到更新;如需更快感知,加"手动刷新"按钮。**v1 不引入 WebSocket / SSE 基础设施**(响应架构师 E-A8 简化);v1.5 视实际需求评估 WebSocket。 3. **运单信息**:shipped 状态写入 `shipments` 表:tracking_no、carrier、eta、proof_attachment_url、**`cancel_reason_code` / `cancel_reason_text` / `exception_reason_code`**(响应 PM 反馈 P-A6:异常/取消原因结构化)。 4. **数据隔离**:助理只能看自己被分配 SKU 的决策;CEO 全可见。 5. **退回 CEO**:弹 Modal 必填原因 + 建议;**触发 FR-8 推送给 CEO(priority=warning)+ FR-6 顶部徽章**(与 §5.7 N7 对齐);原决策恢复 `pending_review`。 **异常场景**(**变更**:WebSocket 行替换为轮询失败行): | 类型 | 场景 | 处理 | |---|---|---| | 网络异常 | 状态保存请求超时 | 本地暂存 + 重试 3 次;失败提示"网络问题,请检查后重试" | | 数据异常 | 附件超过 10 MB | 拦截 + 提示压缩 | | 数据异常 | 运单号格式不合法 | 简单正则(≥6 字符);通过即接受 | | 权限不足 | 助理操作非分配给自己的决策 | 403 + 提示 | | 并发冲突 | 两个助理同时改同一条 | 乐观锁 | | **第三方失败(变更)** | **轮询请求失败** | **指数退避(5s/15s/45s);连续失败 5 次后顶部 toast "网络不稳定,请检查后手动刷新"** | | 设备差异 | 助理在手机上操作 | 移动端单卡片 + 大按钮设计 | | 用户操作冲突 | 助理"已发货"后 CEO 还想改 | 阻止 CEO 编辑;提示"已发货,需新建决策或联系助理" | **边界数值**: 同 R1。 --- ### 5.9 FR-8 缺货预警系统 **位置**: 后台监控任务 + 顶部"预警铃铛" + 独立"预警中心"页 **界面元素与展示规则**(**变更**:静音 UI 显式告知 critical 穿透 + 推送渠道强制 ≥2): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 顶部铃铛 | IconButton | 未读数徽章(红) | 点开下拉看最新 5 条 | 无未读时无徽章 | | 预警中心列表 | Table | 倒序时间;列:触发时间/SKU/类型/严重度/可卖天数/操作 | 行点击进 FR-6 详情 | - | | 严重度徽章 | Badge | critical(红)/ warning(橙)/ info(蓝) | - | - | | **静音控制** | Panel | 默认全开 | 按 SKU/全局 设置静音 + 时长(1h/8h/24h/直到下次决策);**UI 文案明示:"静音此 SKU 的普通预警(critical 仍会推送,如需关闭请到全局静音设置)"** | - | | 聚合配置 | Form | 默认 5 分钟聚合窗口 | 1/5/15/60 min 可选 | 非 admin 只读 | | **推送渠道配置(变更)** | **Form** | **默认企微 + Bark(至少 2 条独立通道)**;提供"添加短信渠道"入口(v1 手工配阿里云 SMS 或类似)| 多选;测试发送按钮 | **若启用渠道数 < 2 时保存按钮禁用 + 提示"至少需 2 条独立通道(防单点失败)"** | | **fallback 顺序配置(新)** | **OrderedList** | **企微 → Bark → 短信**(默认) | **拖拽排序;fallback 仅在 transport 层失败(API 返 5xx 或超时)触发,不基于"用户已读"** | - | | **未读告警告示板(变更)** | **Panel** | **顶部铃铛 + 邮件兜底 + 短信兜底链路状态** | **若所有渠道连续失败 5 次 → 顶部红条 + 邮件兜底(额外发送到 CEO 注册邮箱)** | - | **交互逻辑**(**关键变更**:①SLA 改为 30min ②强制 ≥2 渠道 ③fire-and-forget ④critical 穿透静音 UI 显式 ⑤短信兜底): 1. **触发规则**(3 类,同 R1)。 2. **聚合**:5 分钟窗口内同一 SKU 的多个预警合并为一条。 3. **去重 vs 日报**:预警与日报独立 entity,不合并;FR-6 决策清单中"已触发预警的 SKU"行加红色左边框 + 小铃铛图标。 4. **推送渠道**(**关键变更**): - **强制配置 ≥ 2 条独立通道**(响应 PM 反馈:单通道失败=没预警);默认推荐 "企微 + Bark";强烈建议加第三条 SMS(阿里云 SMS 或运营商网关)作为最后一道防线 - **fire-and-forget 语义**(响应架构师 E-A10):推送成功 = API 返成功(HTTP 2xx),不等用户已读;PM US-4 "1h 内收到预警"的度量点 = "推送 API 返成功" - **fallback 触发条件**:transport 层失败(API 5xx / timeout / DNS 失败)才 fallback 到下一渠道;2xx 但未读 不 fallback - **fallback 顺序**:用户可在 UI 拖拽配置(默认企微 → Bark → SMS) - **全链路失败兜底**:连续 5 次推送全失败 → ①顶部红条 ②触发邮件兜底(发到 CEO 注册邮箱)③写本地未送达队列(admin 可手工重发) 5. **静音**(**变更**):写 `mute_rules`(scope=sku|global, until=ts);推送前查 rule。**critical 默认穿透静音**;UI 上每个静音设置项必显示提示"critical 不受此静音影响";每条 critical 推送的消息文末附加文字"⚠️ 此为严重预警,已穿透您的静音设置" 6. **SLA**(**关键变更**): - **承诺 SLA = 触发到推送 ≤ 30 min**(PM 验收基线,与 PM/架构师统一,响应架构师 P-A3) - **目标 SLO = ≤ 15 min**(内部 metric 目标,超过 15min 报黄,超过 30min 报红) - 业务承诺统一为 30min(覆盖架构师 §6.3.3 监控扫描 15min + 推送渠道重试 buffer) **异常场景**(**变更**:critical 穿透静音 UI 提示 + 全失败兜底): | 类型 | 场景 | 处理 | |---|---|---| | 数据异常 | 历史 30 天数据缺失 | 跳过该 SKU 的"销量异常"规则;记 warning | | **网络异常(变更)** | **推送渠道不可达** | **重试 3 次(1s/4s/16s)+ fallback 到下一渠道;连续 5 次全渠道失败 → 顶部红条 + 邮件兜底 + 本地未送达队列**(响应 PM 反馈:单通道兜底不够) | | 第三方失败 | 企微 token 过期 | 自动尝试 refresh;失败标渠道为"异常"并通知 admin | | 并发冲突 | 同时触发与静音设置 | 静音以触发时刻 query 为准 | | 权限不足 | 助理改聚合配置 | 403 | | 设备差异 | 移动端弹窗推送 | iOS 走 Bark,Android 走企微 | | **用户操作冲突(变更)** | **静音规则与紧急 critical** | **critical 默认穿透静音;UI 上**所有静音设置控件**必显示"critical 不受此静音影响"提示文字;每条 critical 推送消息文末附"⚠️ 此为严重预警,已穿透您的静音设置"** | **边界数值**(**变更**): - **触发到推送 SLA:承诺 30 min / 目标 15 min**(响应 PM 协商) - 单 SKU 同类预警节流:1 小时内最多 1 条 - 历史保留:180 天 - 推送渠道并发:3 个并行 - **强制最低渠道数:2** --- ### 5.10 FR-9 周报 Dashboard 同 R1(PM/架构师 review 未直接修订此章节)。 --- ### 5.11 FR-10 Mock/Real 模式切换 同 R1(review 未直接修订)。 --- ### 5.12 FR-11 三策略回测 **位置**: "回测中心"独立页 **界面元素与展示规则**(**变更**:新增"挑战集 vs 正常分布"对比 + 资金池语义说明): | 元素 | 类型 | 默认态 | 操作后 | 禁用条件 | |---|---|---|---|---| | 回测配置 | Form | 数据集(mock/影子)/ 时间窗(默认 90 天)/ 策略选择(系统/保守/激进 三选必勾系统)/ **数据集类型(正常分布 / 挑战集 / 全部)** | - | - | | 跑回测按钮 | Button | 可点 | 触发 job + 进度条 | 上次跑中或 <10min 内禁用 | | 结果对比图 | Chart | 三策略的累计总收益曲线 + 缺货次数柱图 + 库存价值面积图;**含"正常分布 vs 挑战集"两套对比 Tab** | hover 显示日数据 | 无结果时占位 | | 关键指标表 | Table | 列:策略/缺货天数/库存周转/物流成本/总收益;**分"正常分布"和"挑战集"两组** | 排序 | - | | 一句话结论 | Card | "系统策略相比保守策略 +X%(正常)+Y%(挑战)" | hover 看计算口径 | - | | 历史回测对比 | Table | 列出过往回测,可选择"对比两次" | - | - | **交互逻辑**(**关键变更**:①资金池语义明示 ②挑战集进 L5 并必跑): 1. **策略定义**: - 系统策略 = FR-4 引擎输出 - 保守策略 = 维持 ≥ 60 天可卖库存,全海运 - 激进策略 = 维持 ≥ 14 天,缺货前 5 天空运 2. **回测引擎**:模拟时间推进(天)→ 每天用当日 snapshot 跑当日策略 → 累计每日的销售/成本 → 周末汇总。 3. **资金池语义**(响应架构师 E-A9): - **三策略各自有独立资金池**(不互相消耗),每策略以"基础资金 $X" 为预算上限求解;缺货损失分别累计 - **不通过 tenant_id 隔离**(tenant_id 仅 mock / real / shadow 用),改用回测内部的 `strategy_id` 子隔离 - 三策略基础资金 = 同一数值(如 $1M),确保对比公平 4. **挑战集**(响应 PM 反馈 P-A4 / 架构师 §4.5.4 联动): - **L5 极端场景数据集新增"业务级挑战集" fixture**:节假日尖峰 / 断货事件 / 广告突发 / Lead Time 异常 4 类(具体 fixture 见 §10.B) - **三策略回测必须在"正常分布"和"挑战集"上分别出结果**,UI 展示双 Tab - CEO 验收口径:两套数据集都要满足"系统 ≥ 保守 ≥ 激进" 5. **统计显著性**:跑 N 次(默认 30 次 mock,影子模式 1 次);输出均值 ± 95% CI。 6. **数据复现**:回测 job 绑定 snapshot + 参数 + 模型版本,可一键"重跑此回测"。 **异常场景**: 同 R1。 **边界数值**: - 单次回测时长:< 30 min(单数据集单策略);三策略 × 两数据集 = 6 次 × 30 min = 3h,可并行 3 路 = 1h - 历史回测保留:50 次 --- ### 5.13 FR-12 周复盘报告 **位置**: 周报页内 Section + 独立"复盘"邮件 **交互逻辑**(**关键变更**:评分口径明确仅评 accepted/modified): 1. **正确性评分算法**: - 系统建议数量 ≤ 实际需求 × 1.2 且 ≥ 实际需求 × 0.8 → 正确 - 否则按偏差比例打分 → 部分正确 / 错误 - 物流方式:实际未缺货 → 选海运算正确;缺货 → 必须空运 2. **评分口径**(**关键变更**,响应 PM §5.7-§5.13 冲突): - **仅评 `accepted / accepted_modified` 两类**(用户负责并执行的);这是"事后正确率"的分子分母 - **`superseded / expired / skipped` 不进正确率分母**;单列"系统反复自我修正 / 用户未拍板 / 用户主动跳过"三段,作为模型质量参考但不计 PM §8.3 验收指标 3. **数据延迟**:复盘需要 7-14 天后的"实际销量"才能算分;用户在第 N+14 天看到第 N 周完整复盘。**v1 上线后前 14 天没有完整复盘数据,PM §8.3 验收窗口需相应延长**(已转给 PM §10.5)。 4. **影子模式特殊处理**:影子 SKU 的复盘单列。 5. **学习闭环**:用户标注的 "我的判断" 进入训练反馈池(FR-2 v1.5 增量训练用)。 **异常场景 / 边界数值**: 同 R1。 --- ### 5.14 FR-13 影子模式 同 R1(仅同步 §5.12 资金池语义:影子模式 capital_pool 与 mock/real 物理隔离 via tenant_id,与回测内 strategy_id 子隔离不重叠)。 --- ### 5.15 FR-14 批量接受 + 责任回路 **位置**: FR-6 决策清单顶部"批量接受"按钮 + 周复盘"批量决策回顾" Section **界面元素与展示规则**: 同 R1。 **交互逻辑**(**变更**:CEO 收到助理批量退回的通知闭环): 1. **批量条件强约束**:默认仅"高置信度 + 灵敏度稳定 + 数量 ≤ 安全阈值"的决策可被批量接受。 2. **责任回路**: - 批量接受时强制确认文字("我确认批量接受 N 条") - 助理 24h 内可整批/单条退回 CEO(带原因) - **退回触发 FR-8 推送给 CEO(priority=warning)+ FR-6 顶部红色徽章 "您有 N 条决策被助理退回,需复核"**(响应 PM 建议,闭环 US-12 CEO 侧通知) - 周复盘"批量决策" Section 必看;超过 2 条错误时弹提示"建议调整批量条件" 3. **批量审计**:batch_id 关联所有子决策,可追溯。 **异常场景 / 边界数值**: 同 R1。 --- ### 5.16 FR-15 60/90 天上游下单预警 同 R1。**OPEN_QUESTION 同步给 Controller**(OQ-E2):US-6 的"工厂产能/排期"在 v1 是否退化为"只输出 X 天后该下单"(与 §5.16 当前实现一致),还是 v1 必须补 `supplier` / `sku_supplier` 实体?此事关 PM 文案 + 架构师 schema,工程师建议**前者**(v1 退化,与现状一致),需 PM 同步改 US-6 文案。 --- ### 5.17 FR-16 SKU 自动分类 同 R1(review 未直接修订)。 --- ## §7 边界与异常 ### 7.1 数据边界 同 R1。 ### 7.2 并发与冲突 | 场景 | 策略 | |------|------| | 同决策被多人拍板 | 乐观锁 + version 字段;后到 409 + 显示差异 | | 同 SKU 多预警短时触发 | 5min 窗口聚合 | | 同数据源被多个 sync 触发 | 分布式锁(Redis)+ 去重 | | 同求解任务被重复触发 | input_hash(`snapshot_content_hash` + params_version + forecast_version)去重 + 缓存复用 | | 参数改动与决策计算 | 决策绑定参数版本快照 | | 助理与 CEO 同时改一条决策 | 状态机约束:助理 accepted→shipped;CEO 不可改 in_progress 之后 | | 同一 batch 内部分被改 | 单条改优先,其他保持 | | **跨 tab 操作(变更)** | **30s 轮询 + 本地 toast 通知;下次刷新看到最新状态**(不再依赖 WebSocket 广播) | ### 7.3 第三方依赖失败 | 依赖 | 失败模式 | 缓解 | 监控 | |------|---------|------|------| | FBA Reports API | 5xx / 限流 / 超时 | 指数退避 + 上次快照 fallback + P1 告警 | 成功率 / 平均延迟 | | **求解器(CP-SAT,变更)** | OOM / 崩溃 | 自动重启 1 次 + 上报 P0 | 求解时长 / 失败率 | | 推送渠道(企微/Bark/Telegram/SMS) | API 返错 / token 失效 | **多渠道 fallback(按用户配置顺序,仅 transport 层失败触发)+ 邮件兜底 + 失败队列 + token 自动 refresh** | 各渠道成功率 | | 汇率 API | 不可达 | 24h 缓存 → 30 天均值 → 标 warning | 缓存命中率 | | 货代/海运/空运报价 | v1 无真实接入 | 用户手工录入 + 周更提醒 | 报价新鲜度 | | 对象存储(附件) | 上传失败 | 重试 + 本地暂存 | 上传成功率 | | **~~WebSocket~~(移除)** | - | - | - | | 数据库 | 主库故障 | 读从库降级 + P0 告警 | 主从延迟 | ### 7.4 平台与设备差异 同 R1。 ### 7.5 极端情况 同 R1。 --- ## §9.D 技术债 ### 优先级 1(必须解决,阻塞发布或留隐患) | ID | 技术债 | 原因 | 解决方式 | |----|--------|------|---------| | TD-1 | **CP-SAT 求解器规模 spike**(变更) | 200 SKU × 90 天 × 72000 变量 + 3 场景 | **2 周 spike**:CP-SAT 8 worker 在 72000 变量 P50 场景下 ≤ 30 min;3 场景串行 ≤ 90 min;不过则启用 SKU 分组并行降级 | | TD-2 | 区间预测 → 求解器接口阻抗 | R3 N2 | v1 用 3 场景独立跑(P10/P50/P90)+ 主推 P50 输出唯一待办;不做 stage-1 共享 robust(v1.5) | | TD-3 | 数据 Schema 按真实 FBA API 反向设计 | T7 | v1 阶段 1 必产出 schema doc + 反向 mock | | TD-4 | Mock vs Shadow 物理隔离 | R3 | 独立 schema / 独立 capital_pool | | TD-5 | 时区一致性 | T8 | 全链路打 utc_ts + business_date_pst | | TD-6 | 参数版本与决策快照绑定 | 复现性 | 每决策记 params_version_id | | **TD-15(新)** | **Schema 映射运行时编辑** | **v1 锁定硬编码降低 schema 漂移风险**(架构师 E-A6 共识) | **v1.5 开放:新增 schema_mapping_version 实体并加入强一致区** | | **TD-16(新)** | **infeasible 弹窗 + 临时参数 snapshot 重跑** | **PM 反馈:重大决策不静默** | **v1 必须实现 infeasible_log 表 + 弹窗 UI + 临时 snapshot 绑定逻辑** | ### 优先级 2(可延后到 v1.1 / v1.5) | ID | 技术债 | 延后原因 | |----|--------|---------| | TD-7 | 真实数据 API 接入 | 锚点 §1.5 明确 v1.5 | | TD-8 | Robust optimization / Stochastic programming(CVaR + stage-1 共享) | v1 三场景对照已可用 | | TD-9 | 在线增量学习 | v1 每周全量重训也够 | | TD-10 | 多租户 / SaaS 化 | v1.5+ | | TD-11 | PWA 离线模式 | v1 仅桌面主力 | | TD-12 | i18n 英文 | v1 仅中文 | | TD-13 | 模型可解释性(SHAP 等) | v1 用特征贡献条简化 | | TD-14 | 求解器云原生化(k8s 弹性) | v1 单实例可承载 200 SKU | | **TD-17(新)** | **WebSocket / SSE 实时推送** | **v1 用 30s 轮询替代**(架构师 E-A8) | | **TD-18(新)** | **5 quantile 模型 (P10/P25/P50/P75/P90)** | **v1 用 3 quantile 配 3 场景**;v1.5 升 5 场景时同步训 5 quantile | | **TD-19(新)** | **Supplier / sku_supplier 实体** | **v1 US-6 退化为'X 天后该下单',不算工厂产能;v1.5 实现完整供应商模块** | --- ## §9.E 性能瓶颈 ### 已知瓶颈(**变更**:求解器从 SCIP 改 CP-SAT;变量数口径统一日级 72000;灵敏度场景数 27→15;preview 砍置信度) | # | 瓶颈点 | 量化预期 | 触发监控 | 触发优化条件 | |---|--------|---------|---------|------------| | P1 | **CP-SAT 求解器单次时长** | **200 SKU × 90 天 × 2 物流 × 2 = 72000 变量;P50 基础解预期 5-30 min;3 场景串行 15-90 min** | metric `solver.duration_seconds` | > 30 min 持续 3 天 → 启用 SKU 分组并行 / 升 v1.5 加 Gurobi | | P2 | **灵敏度 15 场景 batch** | 串行 15 × 4 min = 60 min;warm-start 后 ≤ 60 min;并行 3 路可降到 20 min | `sensitivity.batch_duration` | > 60 min → 加并行度或减场景 | | P3 | 每日数据同步 | 12 数据源 × 10w 行 ≈ 5-15 min | `sync.duration` | > 30 min → 分片并发 | | P4 | 预测训练 200 SKU | LightGBM quantile × 3 ≈ 30s/SKU × 200 = 100 min;并行 8 路 = 13 min | `train.duration_per_sku` | > 30s/SKU → 减特征 | | P5 | 决策清单 API 响应 | 200 行 + 6 列 < 500 ms | `api.list_decisions.p95` | > 1s → 加索引 / 缓存 | | P6 | **preview-decision 实时重算(变更)** | **单 SKU 仅算 landed cost + 预估收益(闭式)< 200 ms;不重算置信度** | `api.preview.p95` | > 500 ms → 简化重算逻辑 | | P7 | **~~WebSocket 并发连接~~(移除)** | **改 30s 轮询;CEO + 助理 + tab 共 < 20 并发请求/min** | `api.poll_qps` | > 200 → 加缓存 | | P8 | 数据库写入 QPS | 高峰每日 02:00 ≈ 200 QPS | `db.write_qps` | > 1000 → 分库 / 异步队列 | | P9 | 数据快照存储 | 90 天 × 10w 行/天 ≈ 几十 GB | `storage.usage` | > 70% → 触发归档 | | P10 | 周报 PDF 生成 | 含 chart 渲染 < 60s | `report.pdf_duration` | > 120s → 缓存 chart 图 | ### 性能预算总览(**变更**:预警 SLA 改 30min) | SLO | 目标 | 测量 | |-----|------|------| | 每日批处理完成时间 | **凌晨 02:00 UTC 启动 → 08:00 UTC 完成(含数据同步+训练+决策+灵敏度+周报);按"美西 23:00 触发流水线"对齐架构师 §6.1 + PM US-1 "次日 BJ 9:00 看日报"** | `batch.pipeline_duration` | | **预警 SLA**(变更) | **触发到推送:承诺 30 min / 目标 15 min** | `alert.delivery_latency` | | Dashboard 加载 | 首屏 < 2 s | `frontend.lcp` | | 操作响应 | 拍板/调整 < 500 ms | `api.p95` | --- ## §9.F 上线后稳定性风险 | 风险 | 缓解 | 监控 | |------|------|------| | **CP-SAT 求解器内存泄漏 → OOM**(变更) | 进程级隔离 + 自动重启 + max_memory_limit 8GB | `process.memory_rss` 持续 > 6GB 报警 | | 推送渠道大面积失败 | **多渠道 fallback + 失败队列 + 邮件兜底 + 短信兜底 + ≥ 2 通道强制** | 各渠道成功率 < 95% 报警 | | 决策连续多日不准 | 7 天滚动正确率 < 50% 自动降级朴素策略 | `decision.weekly_accuracy` | | 助理状态机卡死(如 in_progress 7 天不变) | 自动告警 + CEO 视图标"长时未更新" | 状态停留时长 monitoring | | 数据源 schema 突变(FBA API 升级) | **Schema 校验 + 失败硬阻断 + 通知 admin(v1 不允许运行时调整 schema)** | schema_version_mismatch_count | | 时区切换日异常(夏令时) | 单独测试套件 + 切换日前 24h 预演 | `business_date_consistency_check` | | 影子模式被错当 Mock 用 | UI 顶部独立紫色标识 + 决策不进 FR-7 | `mode_misuse_attempts` | | 用户连续 N 天不打开 | 周报邮件兜底 + 紧急 critical 必推 | `user.last_active` | | 数据回流延迟导致复盘卡住 | 复盘"待回流"标识 + 14 天硬切 | `playback.pending_count` | | 并发改参数导致目标函数发散 | 参数版本快照 + self-test 50 case 阻断发布 | self-test failure 报警 | | 长尾 SKU 被错分类 → 不出建议 | FR-16 人工覆盖 + 周复盘必看 | `sku.no_recommendation_streak` > 30 天 | | 批量接受失误(高比例错误) | 周复盘批量正确率 < 80% 自动提示调整条件 | `batch.accuracy` | | **CP-SAT 在某 SKU 组合上 infeasible**(变更) | **不再自动放松;改弹窗让 CEO 三选一 + 写 infeasible_log** | `solver.infeasible_count` | | 助理离职数据丢失 | 账号停用前导出待办;自动归还 CEO 池 | account_disable_audit | | 法律/合规:商业数据走个人微信 | 默认渠道企微 / Bark / Telegram,禁用个人微信 | 渠道配置审计 | | **临时参数 snapshot 滥用**(新) | infeasible 临时增资场景的参数 snapshot 必须有 24h 自动失效 + 周复盘必看"本周临时增资记录" | `temp_param_snapshot_count` | --- ## §10.A AC 自动化测试矩阵 ### 总体覆盖原则 - 单元测试覆盖率:核心模块(FR-3/4/5)≥ 85%,UI ≥ 70% - E2E 主流程:FR-6 拍板闭环、FR-7 助理状态机、FR-10 模式切换 必须 P0 自动化 - 性能基线测试:每次 release 跑 - **新增**:US 反向覆盖矩阵(响应 PM AC 反馈),每个 PM US 至少 1 条 E2E 主流程 AC P0 ### AC 矩阵(按 FR 分组) | AC ID | 描述 | 类型 | 自动化优先级 | 测试数据要求 | |-------|------|------|--------------|-------------| | AC-1.1 | Mock 模式默认开启,顶部斑马条可见 | 主流程 | P0 | mock fixture | | AC-1.2 | 切 Real 需二次确认 + 写 audit | 状态切换 | P0 | admin 用户 | | AC-1.3 | 数据源 API 超时 3 次重试后用 last-known-good | 异常 | P0 | API stub 超时 | | AC-1.4 | 字段缺失 > 5% 整批拒绝 | 边界值 | P0 | 缺失 6% 的 fixture | | AC-1.5 | snapshot 不可变(修改报 409) | 异常 | P1 | 已存在 snapshot | | AC-1.6 | 跨夏令时业务日切正确 | 边界值 | P0 | DST 切换日 fixture | | **AC-1.7(新)** | **Schema 不匹配时硬阻断 + P0 通知 admin(v1)** | 异常 | P0 | 新增字段的 stub | | **AC-1.8(新)** | **ingestion_run_id 与 snapshot_content_hash 字段双写** | 主流程 | P0 | 任意 fixture | | AC-2.1 | SKU 历史 <14 天走冷启动分支 | 边界值 | P0 | 短历史 SKU | | AC-2.2 | 输出 p10/p50/p90 三值 | 主流程 | P0 | 完整 SKU | | AC-2.3 | 训练 30s 超时 fallback 上版本 | 异常 | P1 | 慢训练 stub | | AC-2.4 | 全 0 历史不出预测 | 边界值 | P0 | 长尾 fixture | | AC-3.1 | 5 项 component 计算正确(与 oracle 比对) | 主流程 | P0 | 50 预置 case | | AC-3.2 | 缺货倍数分段(≤14 天 vs >14 天) | 边界值 | P0 | 缺货 15 天 case | | AC-3.3 | 参数版本快照绑定决策 | 状态切换 | P0 | 多版本参数 | | AC-3.4 | self-test 50 case 失败阻断发布 | 回归 | P0 | 故意错误 case | | **AC-3.5(新)** | **非法参数(负数/超区间)后端返 400 + audit;不做兜底改值** | 异常 | P0 | 注入负数 | | **AC-4.1(变更)** | **200 SKU × 90 天日级求解 ≤ 30 min(CP-SAT, P50 单场景)** | 主流程 | P0 | 全量 fixture | | **AC-4.2(变更)** | **infeasible 触发弹窗,CEO 选 ①批准临时增资 → 用临时 snapshot 重跑 → 写 infeasible_log** | 异常 | P0 | 冲突约束 fixture | | AC-4.3 | CP-SAT 求解器崩溃自动重启 1 次 | 异常 | P1 | 注入崩溃 | | AC-4.4 | 相同 input_hash 24h 缓存命中 | 主流程 | P1 | 重复输入 | | AC-4.5 | 求解超时返回 current best + 标 gap | 边界值 | P0 | 超长输入 | | **AC-4.6(新)** | **3 场景输出"主推=P50"进入待办;P10/P90 仅作详情对照** | 主流程 | P0 | 已知 P10/P50/P90 | | **AC-5.1(变更)** | **15 场景 batch ≤ 60 min(OAT 6 + 全组合 9)** | 主流程 | P0 | 标准输入 | | AC-5.2 | 核心决策稳定率算式正确(top-30,物流翻转算 1 票不一致) | 主流程 | P0 | 已知 baseline + 扰动 | | AC-5.3 | 单场景 infeasible 不计稳定率分母 | 边界值 | P1 | 含 infeasible 场景 | | AC-6.1 | 决策清单按建议优先级倒序 | 主流程 | P0 | 多优先级 fixture | | AC-6.2 | 空清单显示"今日健康" + 倒计时 + 过去 7 天回顾卡片 | 边界值 | P0 | 健康库存 fixture | | **AC-6.3(变更)** | **"调整数量"实时重算 landed cost + 预估收益 < 200ms;置信度不重算(tooltip 提示)** | 主流程 | P0 | 标准 SKU | | AC-6.4 | "调整"调到 0 拦截 | 异常 | P1 | - | | AC-6.5 | 决策版本乐观锁,后到 409 | 并发 | P0 | 双 tab 模拟 | | AC-6.6 | 助理打开本页操作按钮置灰 | 权限 | P0 | assistant 角色 | | AC-6.7 | 求解器昨晚失败显示红条 + 用前日决策 | 异常 | P0 | 注入失败 | | AC-6.8 | 移动端切换卡片视图 | 兼容 | P1 | iPhone viewport | | AC-6.9 | "跳过"必须有原因(提示) | 主流程 | P1 | - | | **AC-6.10(新)** | **决策版本 superseded 与 expired 分别标识,UI 三段视觉区分** | 主流程 | P0 | 跨日 fixture | | **AC-6.11(新)** | **可解释面板"三场景对照"展示 P10/P50/P90 三套解** | 主流程 | P0 | 已知三场景结果 | | AC-7.1 | 助理状态机:pending→in_progress→shipped 正确 | 状态切换 | P0 | 助理账号 | | AC-7.2 | shipped 必须上传附件 | 边界值 | P0 | 无附件场景 | | AC-7.3 | 24h 内可退回 CEO,超后禁用 | 边界值 | P0 | 24h boundary | | **AC-7.4(变更)** | **轮询失败 5 次后顶部 toast;不依赖 WebSocket** | 异常 | P1 | 注入轮询失败 | | AC-7.5 | 助理只能看分配 SKU | 权限 | P0 | 多助理 fixture | | **AC-7.6(新)** | **状态名统一 `pending_review`(助理退回后)跨 3 文档命名** | 主流程 | P0 | 退回流程 | | **AC-7.7(新)** | **shipment 表记录 cancel_reason_code / exception_reason_code** | 主流程 | P0 | 取消场景 | | AC-8.1 | 库存 ≤ 21 天触发 critical | 主流程 | P0 | 临界库存 | | AC-8.2 | 5min 窗口聚合同 SKU 多预警 | 主流程 | P0 | 短时多次触发 | | AC-8.3 | 静音规则生效 | 状态切换 | P0 | 静音 fixture | | **AC-8.4(变更)** | **critical 穿透静音 + UI 显式提示文字 + 推送消息文末附"⚠️"** | 边界值 | P0 | 静音 + critical 触发 | | **AC-8.5(变更)** | **推送到企微 ≤ 30 min(承诺)/ ≤ 15 min(目标)** | 主流程 | P0 | 企微 stub | | **AC-8.6(变更)** | **渠道全失败连续 5 次 → 邮件兜底触发** | 异常 | P0 | 注入全失败 | | **AC-8.7(新)** | **配置渠道数 < 2 时保存被禁用 + 提示** | 边界值 | P0 | 单渠道配置 | | **AC-8.8(新)** | **fallback 仅在 transport 失败时触发,不基于"用户已读"** | 异常 | P0 | API 5xx vs 2xx 未读 | | AC-9.1 | 周报周一 09:00 自动生成 | 主流程 | P0 | 时间 mock | | AC-9.2 | PDF 导出 < 60s | 主流程 | P1 | 完整周数据 | | AC-9.3 | 除 0 指标显示 "–" | 边界值 | P1 | 零数据 | | AC-10.1 | Mock/Real 切换二次确认 | 状态切换 | P0 | admin | | AC-10.2 | Real 数据源未就绪禁用切换 | 边界值 | P0 | 未配置 stub | | AC-10.3 | Mock 决策不进助理视图 | 主流程 | P0 | 助理账号 + Mock | | AC-10.4 | 切换冷却 30s | 边界值 | P1 | - | | AC-11.1 | 三策略回测结果统计显著 | 主流程 | P0 | 30 次 mock run | | AC-11.2 | 历史数据 <30 天拒绝跑 | 边界值 | P1 | 短历史 | | AC-11.3 | 回测 snapshot 可复现 | 回归 | P0 | 已知 snapshot | | **AC-11.4(新)** | **三策略各自独立资金池(不互相消耗)** | 主流程 | P0 | 双资金池验证 | | **AC-11.5(新)** | **正常分布 vs 挑战集 两套结果分别输出,CEO 验收口径"系统 ≥ 保守 ≥ 激进"两套都满足** | 主流程 | P0 | L3 + L5 fixture | | AC-12.1 | 正确性评分按 ±20% 阈值算 | 主流程 | P0 | 已知销量 | | AC-12.2 | 14 天前数据未回流标"待回流" | 边界值 | P0 | - | | **AC-12.3(新)** | **正确率分母仅含 accepted / accepted_modified;superseded / expired / skipped 不计** | 主流程 | P0 | 混合状态 fixture | | AC-13.1 | 影子 SKU 与 Mock 物理隔离 | 主流程 | P0 | 双轨 fixture | | AC-13.2 | 必须 4 类齐全才能启用 | 边界值 | P0 | 仅 3 类 fixture | | AC-13.3 | 影子资金池独立 | 主流程 | P0 | 双 pool 验证 | | AC-14.1 | 批量接受需输入确认文字 | 主流程 | P0 | - | | AC-14.2 | 低置信度行禁用批量勾选 | 边界值 | P0 | 混合置信度 | | AC-14.3 | 助理 24h 内可整批退回 | 状态切换 | P0 | - | | AC-14.4 | 批量正确率 < 80% 提示调整 | 主流程 | P1 | 历史批量数据 | | **AC-14.5(新)** | **助理退回 CEO 时触发 FR-8 推送 + FR-6 顶部红色徽章给 CEO** | 主流程 | P0 | 退回场景 | | AC-15.1 | 60/90 天扫描准确性 | 主流程 | P0 | 已知库存+预测 | | AC-15.2 | 在途数据缺失按 0 计 + warning | 边界值 | P1 | - | | AC-16.1 | CV < 0.3 分类为稳定 | 主流程 | P0 | 不同 CV 的 SKU | | AC-16.2 | 人工覆盖 90 天后失效 | 边界值 | P1 | 时间 mock | | AC-16.3 | 历史 <30 天默认长尾 | 边界值 | P0 | 短历史 | ### **US 反向覆盖矩阵(新增,响应 PM 反馈)** | PM US | E2E 主流程 AC | 备注 | |-------|--------------|------| | US-1 每日 9:00 BJ 看发货清单 | AC-6.1 + AC-6.10 | 决策清单基础展示;**OQ-E1 待定(周节奏 vs 每日)** | | US-2 5 分钟内拍板 | AC-6.3 + AC-6.5 + AC-6.6 | 操作响应 < 500ms + 乐观锁 | | US-3 调整数量实时重算 | AC-6.3 | tooltip 已说明"全局最优需下次批跑"(响应架构师 P-A4) | | US-4 1h 内收到缺货预警 | AC-8.5 | 承诺 30min / 目标 15min | | US-5 空清单的安心 | AC-6.2 + AC-6.10 | 包含过去 7 天回顾 + 倒计时 | | US-6 60/90 天上游预警 | AC-15.1 + 待补"点预警跳转决策面板"E2E | **OQ-E2:v1 是否补 supplier 实体** | | US-7 模式切换不污染 | AC-10.1 + AC-10.3 + AC-13.1 | | | US-8 影子对照 | AC-13.1 + AC-13.2 + AC-13.3 + 待补"手工录入实际决策"E2E | **R3 补充**:增加 AC-13.4(待写)覆盖录入流程 | | US-9 决策可解释 | AC-6.11 + AC-3.3 + AC-3.1 | 三场景对照 + 参数版本 + 公式 | | US-10 三策略回测可视化 | AC-11.1 + AC-11.4 + AC-11.5 + 待补"评审会渲染"E2E | | | US-11 助理状态回写 | AC-7.1 + AC-7.2 + AC-7.5 + AC-7.6 | | | US-12 助理 24h 否决权 | AC-7.3 + AC-14.3 + AC-14.5 | CEO 侧通知闭环 | | US-13 周复盘报告 | AC-12.1 + AC-12.2 + AC-12.3 | 评分口径明确 | --- ## §10.B 测试数据规范 ### 测试数据集分层(**变更**:L5 新增业务级挑战集) | 层 | 用途 | 规模 | 来源 | |----|------|------|------| | L1 单元测试 fixture | 函数级 | 单 SKU 几条 | 手工构造 | | L2 集成测试 fixture | 模块级 | 5-20 SKU × 30 天 | Mock 生成器 + 手工 | | L3 性能基线数据集 | 性能回归 | 200 SKU × 365 天 | Mock 生成器(固定 seed) | | L4 影子模式数据集 | 真实对照 | 4 SKU × 90 天 | 用户提供 | | **L5 极端场景数据集(扩充)** | 边界测试 + **业务级挑战集** | 各类异常 SKU + **节假日尖峰 / 断货事件 / 广告突发 / Lead Time 异常 4 类挑战集** | 手工构造 + Mock 生成器 | ### 关键 fixture 清单(**新增 4 个业务挑战集**) | Fixture | 用途 | 内容特征 | |---------|------|---------| | `fx_stable_sku` | 稳定 SKU 全链路 | CV<0.3, 365 天历史 | | `fx_volatile_sku` | 波动 SKU | CV>0.5 | | `fx_seasonal_sku` | 季节性 | 含 Q4 高峰 | | `fx_longtail_sku` | 长尾 | 月销 <5 | | `fx_new_sku` | 新品 | <14 天历史 | | `fx_stockout_history` | 含历史缺货 | 校准 FR-12 | | `fx_dst_boundary` | 夏令时切换 | 含 3 月 / 11 月切换日 | | `fx_corrupt_data` | 异常值 | 含负销量/0 价格 | | `fx_full_200_sku` | 性能基线 | 200 SKU × 365 天 | | `fx_infeasible` | 求解 infeasible | 约束冲突 | | `fx_high_confidence_batch` | 批量接受测试 | 全部高置信度 | | `fx_mixed_confidence` | 批量拦截测试 | 含低置信度 | | **`fx_challenge_holiday_peak`** | **业务挑战集** | **节假日 Q4 销量尖峰 3-5x** | | **`fx_challenge_stockout_event`** | **业务挑战集** | **突发断货事件(供应商断供 14 天)** | | **`fx_challenge_ad_surge`** | **业务挑战集** | **广告突发投放 → 销量短期波动** | | **`fx_challenge_lead_time_anomaly`** | **业务挑战集** | **Lead Time 异常翻倍** | ### 数据生成与版本化 - Mock 生成器代码与 fixture 共版本(git tag) - 性能基线数据用固定 seed - 影子数据加密存储 ### 测试环境分层(**变更**:求解器改 CP-SAT) | 环境 | 数据 | 求解器 | 用途 | |------|------|-------|------| | dev | L1+L2 | **CP-SAT** | 日常开发 | | ci | L1+L2+L5 | **CP-SAT** | PR 触发 | | staging | L3 全量 | **CP-SAT**(v1.5 可加 Gurobi 二选一) | release 前 | | perf | L3 性能基线 | 与生产一致(CP-SAT) | 性能回归 | | prod | 真实 | 生产配置(CP-SAT) | - | --- ## §10.C 回归基线 ### 性能基线(**变更**:CP-SAT + 灵敏度 15 场景 + 预警 SLA 30min) | 指标 | 基线(v1.0) | 回归阈值 | 处理 | |------|------------|---------|------| | **CP-SAT 求解(200 SKU × 90 天日级 72000 变量,P50 场景)** | **20 min** | 退化 > 50% | 阻断发布 | | **3 场景串行总求解时长** | **60 min** | 退化 > 50% | 阻断发布 | | **灵敏度 15 场景 batch** | **45 min** | 退化 > 30% | 警告 + 必须解释 | | 数据同步全流程 | 8 min | 退化 > 50% | 警告 | | 模型训练 200 SKU | 12 min | 退化 > 50% | 警告 | | 决策清单 API P95 | 300 ms | 退化 > 100% | 阻断发布 | | **预警 SLA(承诺)** | **30 min(承诺)/ 15 min(目标)** | **承诺退化 > 0%(>30min)阻断;目标退化 > 100%(>30min)警告** | - | | 周报 PDF 生成 | 40 s | 退化 > 100% | 警告 | ### 决策质量基线(mock 数据 30 次回测) | 指标 | 基线(系统策略) | 回归阈值 | |------|----------------|---------| | 三策略总收益排序:系统 > 保守 > 激进(**正常分布 + 挑战集都要满足**) | 必须成立 | 不成立则阻断 | | 系统 vs 保守总收益提升 | +X%(待 spike 后定标) | 下降 > 20% 阻断 | | 缺货事件数 | 基线 N 次 | 增加 > 50% 阻断 | | 灵敏度核心稳定率 | > 70% | < 60% 阻断 | ### 兼容性基线 同 R1。 ### 自动化回归套件 同 R1。 --- ## §12 附录 ### 12.1 术语表 同 R1,**新增**: | 术语 | 中文 | 释义 | |------|------|------| | CP-SAT | Constraint Programming SAT solver | Google OR-Tools 提供的约束规划+SAT 求解器 | | OAT | One-At-a-Time | 灵敏度分析单变量扰动法 | | pending_review | 待复核 | 助理退回 CEO 后的决策状态 | | superseded | 已替代 | 决策被新基础决策自动替代(用户未拍板时) | | expired | 已过期 | 决策 24h 后用户未拍板自动过期(且无新建议覆盖) | ### 12.2 缩写与 FR 编号映射 同 R1。 ### 12.3 关联 API 文档(**变更**:求解器从 SCIP/Gurobi 改 CP-SAT) | 系统 | 接口文档 | v1 状态 | |------|---------|---------| | Amazon Seller Central | https://developer-docs.amazon.com/sp-api/ | v1 仅 schema 参考,不接入 | | Amazon Ads API | https://advertising.amazon.com/API/docs/ | v1.5 接入 | | 货代报价 API | TBD | v1.5 接入;v1 手工录入 | | 企业微信应用 API | https://developer.work.weixin.qq.com/ | v1 接入 | | Bark Push | https://github.com/Finb/Bark | v1 接入 | | Telegram Bot API | https://core.telegram.org/bots/api | v1 接入 | | **阿里云 SMS(或类似短信网关)** | TBD(按用户选择) | **v1 接入(作为推送强制 2 通道之一的候选)** | | **Google OR-Tools / CP-SAT** | https://developers.google.com/optimization/cp/cp_solver | **v1 主求解器** | | ~~SCIP / PySCIPOpt~~ | - | **v1.5 备选** | | ~~Gurobi~~ | - | **v1.5+ 备选** | | LightGBM | https://lightgbm.readthedocs.io/ | v1 用于波动 SKU 预测 | ### 12.4 关键架构决策记录(ADR 索引,简版) | ADR | 决策 | 替代方案 | 选择原因 | |-----|------|---------|---------| | **ADR-01(变更)** | **求解器用 CP-SAT (Google OR-Tools)** | SCIP / Gurobi / CPLEX | **架构师 R2 裁决;逻辑约束表达自然 + 8 worker 并行成熟 + 0 license** | | ADR-02 | 区间预测用分位数回归 LightGBM | Prophet / DeepAR | 工程成熟 + 单 SKU < 30s | | ADR-03 | 预警与日报不合并 | 合并收件箱 | 状态机/SLA 完全不同 | | ADR-04 | Mock 与 Shadow 物理隔离 | 共用 DB + tenant_id | 资金池/隔离更强 | | ADR-05 | UTC 入库 + PST 业务日 | 单一时区 | 多站点扩展性 | | **~~ADR-06~~(撤销,转 OPEN_QUESTION OQ-E1)** | ~~周决策 + 事件触发预警~~ | 每日决策 | **R1 提前敲定不当,PM 反馈 ADR 心智会让工程按周节奏走偏;改为 OQ-E1 待企业家裁决** | | ADR-07 | 求解输入用 input_hash 缓存 | 不缓存 | 24h 复跑可立即命中 | | ADR-08 | 参数版本快照绑定决策 | 当前最新值 | 复盘可复现 | | **ADR-09(新)** | **infeasible 弹窗让 CEO 三选一** | 自动放松软约束 +20% | PM 反馈:重大决策不静默 | | **ADR-10(新)** | **决策变量日级 200×90×2×2 = 72000** | 周聚合 5200 | 与架构师 §3.1.1 + PM US-3/US-4 "精确到日的一键空运" 对齐 | | **ADR-11(新)** | **3 场景 (P10/P50/P90) 独立跑 + 主推 P50** | 5 场景 stage-1 共享 CVaR | v1 简化;v1.5 升级(TD-2, TD-8) | | **ADR-12(新)** | **v1 不用 WebSocket,仅 30s 轮询** | WebSocket / SSE | 架构师 E-A8:省一个完整子系统 | | **ADR-13(新)** | **Schema 映射 v1 锁定硬编码** | 运行时编辑+版本回滚 | 架构师 E-A6:v1 自用 200 SKU 不需要 schema 版本灵活性 | | **ADR-14(新)** | **推送渠道强制 ≥ 2 + fire-and-forget + transport 层 fallback** | 单通道 + ACK | PM 反馈:单通道失败=没预警;架构师 E-A10:v1 不引入读已读语义 | | **ADR-15(新)** | **预警 SLA 承诺 30min / 目标 15min** | 仅 15min 或仅 1h | PM 协商;与架构师 P-A3 统一三方口径 | --- ## ⚠️ 待 R3 跟其他主笔对齐的章节边界 | 议题 | 我的章节涉及 | 需对齐对象 | 期望确认 | |------|------------|----------|---------| | 1. §5.1 时区/货币(汇率改美西 23:00 拉取) | 5.1 | 业务主笔 | 是否同意展示口径"盘中波动不重新折算" | | 2. ADR-01 求解器用 CP-SAT | 5.5 / 12.4 | 架构主笔 | **已对齐**(服从架构师裁决) | | 3. 决策频率:OQ-E1 周节奏 vs 每日 + 事件触发 | 5.7 / ADR-06 撤销 | PM / 企业家 | 待裁决 | | 4. 预警 SLA 承诺 30min / 目标 15min | 5.9 / 9.E | PM / 架构师 | **已三方对齐** | | 5. 影子模式 SKU 数下限 4 | 5.14 / 9.F | 业务/战略主笔 | 4 个是否够(战略 R3 要求 20+) | | 6. AC 编号体系 | 10.A | 测试/QA 主笔 | 是否对齐 | | 7. OQ-E2 US-6 supplier 实体 v1 是否补 | 5.16 | PM / 架构师 | 工程师建议 v1 退化 | | 8. 临时参数 snapshot 滥用风险 | 9.F / TD-16 | 业务主笔 | 24h 自动失效 + 周复盘必看是否够 | --- # R3 修订记录 ## R3 已处理的 PM review | Review 编号(PM) | 处理 | |---|---| | §5.5 "三场景按哪个执行" + 跟架构师对齐 | **已修订**:3 场景独立跑 + 主推=P50(唯一进待办)+ 次推/底线作详情对照;与架构师 E-A5 共识对齐 | | §5.5 infeasible 自动放松软约束 | **已修订**:改为 infeasible 弹窗让 CEO 三选一 + 临时参数 snapshot 绑定重跑 + infeasible_log(ADR-09) | | §5.9 SLA 15min vs PM 1h 冲突 | **已协商**:承诺 30min / 目标 15min(ADR-15) | | §5.9 推送全失败兜底(短信兜底) | **已修订**:强制 ≥ 2 独立渠道 + 邮件兜底 + 短信渠道(ADR-14) | | §5.7 vs §5.13 周复盘评分口径 | **已修订**:仅评 accepted/accepted_modified;superseded/expired/skipped 不进分母(AC-12.3) | | §5.9 critical 穿透静音 UI 显式 | **已修订**:UI 文案明示 + 推送消息文末附"⚠️"(AC-8.4) | | §10.A 缺 US 反向覆盖矩阵 | **已新增**:US 反向覆盖矩阵 13 条 | | ADR-06 周决策 vs 每日 提前敲定 | **已撤销** ADR-06,改为 **OQ-E1** 转 Controller | | §5.15 助理退回 CEO 通知体验 | **已修订**:触发 FR-8 推送 priority=warning + FR-6 顶部红色徽章(AC-14.5) | | §5.4 后端兜底 max(0.1, x) | **已修订**:改为后端直接 return 400 + audit;不做静默兜底(AC-3.5) | ## R3 已处理的架构师 review | Review 编号(架构师) | 处理 | |---|---| | E-A1 SCIP → CP-SAT | **已修订**(服从架构师裁决):求解器改 CP-SAT;§5.5 / §10.B / §10.C / §12.3 / ADR-01 全部对齐 | | E-A2 周聚合 5200 vs 日级 72000 | **已修订**:统一日级 72000(200×90×2×2),ADR-10 | | E-A3 preview-decision < 200ms 不算置信度 | **已修订**:砍掉实时置信度重算 + tooltip 提示 | | E-A4 灵敏度 27 场景 vs 5-7 场景 | **已修订**:改为 15 场景(OAT 6 + 全组合 9) | | E-A5 3 quantile vs 5 quantile | **已修订**:v1 用 3 quantile + 3 场景(P10/P50/P90),5 quantile/5 场景留 v1.5(TD-18) | | E-A6 Schema 映射器 v1 锁定 | **已修订**:v1 硬编码 + UI 只读,v1.5 解锁(TD-15, ADR-13) | | E-A7 §5.4 36000 vs §5.5 5200 口径不一 | **已修订**:统一日级 72000 | | E-A8 WebSocket → 30s 轮询 | **已修订**:v1 删 WebSocket,仅 30s 轮询(ADR-12, TD-17) | | E-A9 三策略资金池语义 | **已修订**:三策略独立资金池(不互相消耗)+ strategy_id 子隔离不复用 tenant_id(AC-11.4) | | E-A10 推送 fallback 语义 + fire-and-forget | **已修订**:fire-and-forget + transport 层失败才 fallback + 用户可拖拽配置顺序(ADR-14) | | E-A11 snapshot_id 拆分 | **已修订**:拆 ingestion_run_id(行级审计)+ snapshot_content_hash(运行级缓存判定) | ## 转给 Controller 的 OPEN_QUESTION | OQ-ID | 议题 | 工程师立场 | 待裁决方 | |-------|------|----------|---------| | **OQ-E1** | **决策频率:周节奏 vs 每日 + 事件触发**(ADR-06 撤销,PM/工程师/企业家三方需对齐) | 工程师中性,等业务裁决;如周节奏,§5.7 摘要文案 + §5.9 周报触发逻辑需联动改 | 企业家 / PM | | **OQ-E2** | **US-6 v1 是否补 supplier / sku_supplier 实体支持"工厂下单"** | 工程师建议 v1 退化为"只输出 X 天后该下单",v1.5 实现完整供应商模块(TD-19) | PM / 企业家 | | **OQ-E3** | **CP-SAT 在 72000 变量 + 3 场景串行下的实际性能**(需 2 周 TD-1 spike 验证) | 如 spike 不过 → 启用 SKU 分组并行(架构师 §3.2.4 第二档降级)或砍范围 | 工程师内部 spike 决定 | | **OQ-E4** | **PM §8.3 "4 周验收"窗口需延长到 8 周**(前 14 天没完整复盘数据,统计样本不足;架构师 P-A2 提出) | 工程师支持延长;建议 PM §10.5 改为 "+8 周验收(首次完整复盘窗口)" | PM | | **OQ-E5** | **影子模式 SKU 下限 4 是否够**(战略 R3 要求 20+;工程师 R1 写 4-20 区间) | 工程师不反对扩到 20;技术上无障碍,但需用户配合提供更多 SKU 真实数据 | 战略 / 业务主笔 | --- **END r3-engineer.md**