# 沙箱时光机引擎 (Sandbox Replay Engine) — 模块 Spec > 版本:v1.0 · 创建日期:2026-05-05 > 决策来源:F1-5b Wave B MP-2 调研收尾(Neo 同意分阶段实现,加入主干任务排期) > 主要落地依赖:F1-5a runtime_context 框架 + F1-5b 业务日上界裁剪基础设施 > > **状态**:Spec 阶段(未启动实施) ## 一、设计意图 P20 沙箱(`runtime_mode='sandbox' + sandbox_business_date`)的核心承诺是 **"设定某个历史日期 X 后,系统所有数据/统计/AI 生成内容呈现的状态都是 X 那天的样子"**,即"时光机"语义。 当前 F1-5a/F1-5b 已建立基础设施,但**业务读取层只覆盖了"daily 累计型"指标**(财务流水 / 服务记录),**未覆盖"月度结算型 / 状态算法型 / Excel 修正型"指标**。沙箱设到 4-20 时,部分页面仍能"看见未来"或显示已知最终结果,违反时光机语义。 本模块旨在**统一所有业务读取按 sandbox_business_date 重算**,达成完整时光机体验。 ## 二、当前已就位的基础设施(继承) | 层 | 已做 | Wave / Commit | |----|------|--------------| | **RuntimeContext 框架** | site_runtime_context 表 + apply_runtime_session_vars() | F1-5a 421e193 | | **数据写入隔离** | ai_run_logs / coach_tasks / 各业务写入表带 runtime_mode + sandbox_instance_id | F1-5a + F1-5b A1 af02446 | | **app 视图业务日上界裁剪** | 39 个 app.v_* 视图加 `WHERE stat_date <= business_date_now()`(2026-05-02 迁移) | 2026-05-02 ETL 迁移 | | **后端读取**(daily 累计型指标) | board-finance / customer-detail / customer-records / coach-service-records 等 | F1-5b MP-1/3/5 | | **后端读取**(权限路由) | manager 角色权限隔离 | F1-5b BE-1 | | **admin-web sandbox 透出** | UI-1/2/3/4/5 全套 runtime 字段 + 提示条 + 全局徽章 | F1-5b Wave A/B | | **Excel 修正表 schema 准备** | salary_adjustments / stg_finance_expense / stg_platform_income 加 effective_date NOT NULL | F1-5b MP-2 prep(本次) | ## 三、缺失能力清单(本模块覆盖范围) 22 个指标按复杂度 + 优先级分: ### P1 — Daily 视图已有,后端 service 切换即可(14 项,S 复杂度) | # | 指标 | 当前数据源 | 目标 daily 视图 | 重算逻辑 | |---|------|-----------|----------------|---------| | 1 | 会员储值卡余额 | dws_member_balance_snapshot(状态) | dws_member_balance_change daily 累计 | SUM(收入-支出) WHERE date<=B | | 2 | 60 天消费 | dws_member_consumption_summary | dws_member_consumption_daily | SUM 60 day window 终点为 B | | 3 | 累计消费总额 | 同上 | 同上 | SUM all WHERE date<=B | | 4 | 距上次到店天数 | 状态字段 | dwd 消费记录 | B - MAX(visit_date WHERE<=B) | | 5 | 累计服务客户数(助教) | dws_assistant_customer_stats | daily 累计 | COUNT DISTINCT member WHERE date<=B | | 6 | 助教等级 | dws_assistant_daily_detail.assistant_level_code | 同表 | SELECT WHERE stat_date=B | | 7 | 月度课时(助教) | dws_assistant_daily_detail.base_hours 等 | 同表月度聚合 | SUM WHERE month_of(B) AND stat_date<=B | | 8 | 月度计费金额(助教) | dws_assistant_daily_detail.total_ledger_amount | 同上 | SUM WHERE month_of(B) AND stat_date<=B | | 9 | 门店月度财务 | dws_finance_daily_summary | 同表(已实现 MP-1) | ✓ 已完成 | | 10 | 月度新增会员 | dws_member_*_summary | dws_member_daily | COUNT WHERE join_date<=B AND month_of(B) | | 11 | 月度流失会员 | 同上 | 同上 | COUNT WHERE last_visit Decimal: """根据 RuntimeContext 自动选 live / sandbox 路径。""" # 实现内会判断: # - if runtime_ctx.is_sandbox: 调 balance_replay.partial(business_date) # - else: 调 dws_query.live_balance() pass ``` ### 5.3 测试模式 每个 replay 模块配套 unit test(BE-3 / T3 模式): - mock get_runtime_context 返回 live / sandbox 两路 - 断言 SQL 包含 daily 累计 + business_date 截断 - 部分 integration test 用真实测试库验证数据一致性 ### 5.4 性能考虑 - daily 累计 SQL 比 monthly snapshot 慢(SUM 多行 vs 单行查) - 建议:sandbox 模式下接受性能折衷;live 模式仍走原 dws 月度路径 - 必要时可做 in-memory cache(business_date 不变时缓存命中) ## 六、阶段 B 前置依赖清单 | 依赖 | 来源 | 状态 | |------|------|------| | RuntimeContext + business_date | F1-5a | ✓ 已完成 | | app 视图 daily 上界裁剪 | 2026-05-02 迁移 | ✓ 已完成 | | Excel 修正表 effective_date 字段 | F1-5b MP-2 prep(本次) | ✓ 本次完成 | | ETL Excel 上传 UI 支持 effective_date 列 | F1-6 阶段 B 内 | ⏳ 待做 | | dws_assistant_daily_salary 表/视图 | F1-6 阶段 B 内(MP-2 真正实施) | ⏳ 待做 | | dws_member_daily 系列视图(部分缺失) | F1-6 阶段 B 内 | ⏳ 待做 | ## 七、阶段 C 远期目标 ### sandbox_audit_log(用户行为审计) **业务目标**:沙箱模式下用户的所有操作都记录,切回 live 后可追溯,支持"沙箱演练复盘"场景。 **表设计草案**: ```sql CREATE TABLE biz.sandbox_audit_log ( id BIGSERIAL PRIMARY KEY, site_id BIGINT NOT NULL, sandbox_instance_id VARCHAR(100) NOT NULL, user_id BIGINT NOT NULL, action_type VARCHAR(50) NOT NULL, -- 'view' / 'trigger_ai' / 'modify' / ... page_path VARCHAR(200), payload JSONB, created_at TIMESTAMPTZ DEFAULT now() ); ``` **写入入口**:统一 middleware 或 decorator 拦截 sandbox 模式请求。 ## 八、关联 - F1-5a 主体审计:`docs/audit/changes/2026-05-05__wave1_f1_5a_sandbox_batch_run.md` - F1-5a 走查报告:`docs/audit/changes/2026-05-05__wave1_f1_5a_backend_walkthrough.md` - F1-5b 任务清单:`docs/_overview/wave1-findings/F1-5b-tasks.md` - F1-5b MP-2 prep 审计:`docs/audit/changes/2026-05-05__wave1_f1_5b_mp2_prep.md` - P20 SPEC:`docs/prd/specs/P20-runtime-context-sandbox.md` - 业务日上界 ETL 迁移:`db/etl_feiqiu/migrations/20260502__rls_views_business_date_upper_bound.sql` ## 九、决策路径(Owner Approval) - **2026-05-05 Neo 决策**: > "沙箱'全数据时光机'模块可行性 — 同意,分阶段实现,往主干任务排期中增加。" - **本 spec 状态**:已 commit,等待 F1-6 启动。F1-6 启动时本 spec 作为阶段 B 实施依据。