Files
Neo-ZQYY/docs/_overview/wave1-findings/F1-6-tasks.md
Neo e60cfc037c docs(audit): 全局收口反思 — 5 问追溯 + 洞口登记 + 文档规范化大工程立项
Neo 在 F1-6 Sprint 2 收尾后反思"项目全局控制度不够,到处没收口"。
经 5 问追溯调研(2 个子代理 + Bash 实证),识别 5 个未收口洞口 + 1 个
未明确登记的大工程,本次完成"登记 + 修订",实际收口动作待逐项推进。

5 个未收口洞口(已登记 backlog §七):
- P0 #3 F1-6 Sprint 3 范围描述误导(本次已修订 F1-6-tasks.md §4 拆分 3a/3b)
- P0 #5 Sprint 3/4 衔接判断错误(本次已纠正)
- P1 #1 3 项迁移后功能验证未做(IDE slash / 8 subagent / MCP 测试库)
- P1 #2 2026-04-15~05-02 累积基线 17 天工作待验证
- P2 #4 etl-coupon-detail 30+ 待调研 4 个月未定

文档规范化大工程立项(已登记 backlog §八):
- Neo 明确目标:规范化 / 归档 / 对账 / 去重 / 重构 / 零信息损失
- 范围 11 个 docs/ 子目录 + 各模块本地 docs
- 工程量 L+(数十小时,需多 sprint)
- 状态:立项,详细 spec 待 Neo 调度时立

落地修订:
- docs/_overview/architecture-evolution-backlog.md 追加 §七 §八
- docs/_overview/wave1-findings/F1-6-tasks.md §4 Sprint 3 拆分 3a/3b
- docs/audit/changes/2026-05-06__global_closure_reflection.md 反思全文

承认:Claude 在跨 sprint 衔接判断上有盲区,本次反思已纠正,未来 sprint 转换
前必须读完整 §4 范围描述,不靠记忆推断。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:58:18 +08:00

173 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# F1-6 沙箱时光机阶段 B 任务清单
> 创建日期:2026-05-05 (F1-5b 收尾后启动)
> 完整模块 spec:[`docs/_overview/sandbox-replay-engine-spec.md`](../sandbox-replay-engine-spec.md)
> 上游:F1-5b 全部完成(commit `5d4da0a`)
>
> **状态**:Sprint 1 已启动并完成,Sprint 2-4 待启动
## 一、阶段 B 总览
按 sandbox-replay-engine-spec 阶段 B 拆 4 个 sprint:
| Sprint | 范围 | 工作量 | 状态 |
|--------|------|------|------|
| **Sprint 1** | 框架(sandbox_replay 模块 + runtime_aware decorator) + 1 个试点指标(距上次到店天数迁移) | M ~ 4-5h | ✅ 完成(2026-05-05) |
| **Sprint 2** | 5 个会员相关 P1 指标(60d 消费 / 累计消费总额 / 累计交易笔数 / 储值卡余额 / 累计 GMV) | M ~ 4h | ✅ 完成(2026-05-06,4 项迁移 + #3 推迟 Sprint 3) |
| Sprint 3 | 5 个助教/门店 P1 + **MP-2 完整**(daily salary 含 ETL 改造)+ Sprint 2 推迟的 #3(ETL 新增 `total_open_table_count`)| L ~ 9-11h | ⏳ 待启动 |
| Sprint 4 | 5 个 P2 指标(RS 重算 / 客户黏性 / 任务完成率 / Excel 修正 / 月度新增流失) | M-L ~ 6-8h | ⏳ 待启动 |
## 二、Sprint 1 收口(2026-05-05)
### 范围
1. ✅ 建立 `apps/backend/app/services/sandbox_replay/` 模块脚手架
2. ✅ 实现 `@runtime_aware(metric=...)` decorator(自动注入 RuntimeContext)
3. ✅ 试点迁移:`get_last_visit_days`(距上次到店天数,P1-4)
- `consumption_replay.py` 新实现
- `fdw_queries.get_last_visit_days` 改 thin wrapper(兼容 75+ 现有调用)
4. ✅ Unit test 10/10 PASS
5. ✅ MCP 端到端 4a/4b 双口径 PASS
### 关键 bug 发现 + 修复
**bug**:`@trace_service` + `@runtime_aware` 嵌套时,trace_service 的 `_build_params_dict``inspect.signature(func).bind(*args, **kwargs)` 做参数 redact。`functools.wraps` 默认设置 `__wrapped__``inspect.signature` 追溯到原函数(含 keyword-only 必传 ctx 参数),导致 sig.bind 抛 `TypeError: missing a required argument: 'ctx'`
只在 FastAPI 请求 + 有活跃 TraceContext 时触发(直接 Python 调用 get_current_trace 返回 None,跳过 _build_params_dict,不复现)。
**修复**:`runtime_aware` 的 wrapper 不用 `functools.wraps`,改用手动复制 `__name__/__qualname__/__module__/__doc__`,**不设 `__wrapped__`**,让 `inspect.signature` 看到 wrapper 自身 `(*args, **kwargs)` 签名,sig.bind 永远成功。
### 双口径验证证据(关键样本)
**目标 member**: 2799207087163141(黄先生)
| 维度 | 4a live (today=2026-05-05) | 4b sandbox=2026-04-20 |
|------|---------------------------|----------------------|
| stat_date 数据 | 2026-05-01 | 2026-04-15(walkthrough 测试快照) |
| last_consume_date | 2026-04-03 | 2026-03-20 |
| daysSinceVisit 计算 | 32 = 05-05 - 04-03 | **31 = 04-20 - 03-20** |
| API 返回 | 32 ✓ | 31 ✓ |
测试快照已清理,sandbox 已切回 live。
### 走查脚本
`_DEL/walkthrough_f1_6/`:
- `step_sprint1_probe_member.py` — 找有 last_consume 的会员
- `step_sprint1_check_view.py` — 视图层 RLS 行为
- `step_sprint1_direct_call.py` — 直接调 sandbox_replay 函数
- `step_sprint1_repro_etl_conn.py` — etl_conn 复用模式
- `step_sprint1_call_service.py` — 直接调 customer_service.get_customer_detail
- `step_sprint1_4b_probe.py` — sandbox=4-20 视图行为
- `step_sprint1_4b_find_member.py` — 找 sandbox 下有数据的 member
- `step_sprint1_4b_stat_dist.py` — stat_date 分布
- `step_sprint1_4b_seed_data.py` — 插测试快照
- `step_sprint1_cleanup.py` — 清理 + 切回 live
### Sprint 1 commit
`feat(backend): F1-6 sprint1 sandbox_replay 模块脚手架 + get_last_visit_days 迁移试点`
---
## 三、Sprint 2 范围(进行中)
启动顺序按方案 A:从已有 `consumption_replay.py` 模块扩展开始,新模块靠后。
### 5 个会员相关 P1 指标
| # | 指标 | 当前实现位置 | 目标迁移到 | 复杂度 | 状态 |
|---|------|-------------|----------|------|------|
| 1 | 60 天消费 | `fdw_queries.get_consumption_60d` | `sandbox_replay/consumption_replay.py`(扩展) | S | ✅ 2026-05-06(thin wrapper)|
| 2 | 累计消费总额 | (无,新增) | `sandbox_replay/consumption_replay.py`(扩展) | S | ✅ 2026-05-06(无 wrapper,0 调用方)|
| 3 | 累计交易笔数 | DWS 现有 `total_visit_count` 实算 `COUNT(settle_type IN (1,3))` 不符开台次数语义,需 ETL 新增 `total_open_table_count` | `sandbox_replay/consumption_replay.py`(扩展) | S | ⏸️ **推迟 Sprint 3**(ETL 配合,详见 [架构演进 backlog](../architecture-evolution-backlog.md))|
| 4 | 会员储值卡余额 | `fdw_queries.get_member_balance` | `sandbox_replay/balance_replay.py`(新建) | S | ✅ 2026-05-06(thin wrapper,SCD2 时光机)|
| 5 | 累计 GMV | `dws_finance_daily_summary.gross_amount`(门店级,与现有"区间 GMV"语义不同) | `sandbox_replay/finance_replay.py`(新建) | S | ✅ 2026-05-06(无 wrapper,门店级 SUM)|
### Sprint 2 实施模式
所有指标走 `@runtime_aware` decorator + `app.v_dws_*` 视图查询。每个指标:
- 1 个新函数 to sandbox_replay/
- 1 个 thin wrapper in fdw_queries.py(兼容)
- 单元测试(本地不入仓)+ MCP 双口径走查(navigate_to + snapshot + screenshot,**含 UI 实地验证**)
- 审计 + 单独 commit
### Sprint 2 commit
- #1 60d 消费 — commit `d418621`(2026-05-06)
- #2 累计消费总额 — commit `32716bc`(2026-05-06)
- #3 累计交易笔数 — **推迟 Sprint 3**(ETL 配合新增 `total_open_table_count`,详见 [架构演进 backlog](../architecture-evolution-backlog.md) 第 3 项)
- #4 储值卡余额 — commit `7b1cfad`(2026-05-06,SCD2 时光机)
- #5 累计 GMV — `feat(backend): F1-6 sprint2 #5 累计 GMV 加入 sandbox_replay (门店级)`(待提交)
### 估算
5 指标 × 30-50min = 3-4h(#1 实际 ~ 40min)
---
## 四、Sprint 3 范围(待启动)
> ⚠️ 2026-05-06 修订(全局收口反思后):原描述"需 ETL 团队配合"误导 Claude
> 推荐"跳过 Sprint 3 直推 Sprint 4"。**实际上 5 个 P1 指标(#6~#10)完全可独立做,
> 沿用 Sprint 1/2 模式;仅 MP-2 单项需 ETL 配合**,可拆分推进。详见架构演进
> backlog §七 第 3 项。
### 5 个助教/门店相关 P1 指标(可立刻做,不依赖 ETL)+ MP-2 完整(独立子任务,需 ETL 配合)
| # | 指标 | 数据源 | 是否需 ETL 配合 |
|---|------|--------|---------------|
| 6 | 累计服务客户数(助教) | `dws_assistant_customer_stats` daily | **不需要**(走 Sprint 1/2 同款模式)|
| 7 | 助教等级 | `dws_assistant_daily_detail.assistant_level_code` | **不需要** |
| 8 | 月度课时(助教) | `dws_assistant_daily_detail.base_hours` 聚合 | **不需要** |
| 9 | 月度计费金额(助教) | `dws_assistant_daily_detail.total_ledger_amount` 聚合 | **不需要** |
| 10 | 月度新增/流失会员 | `dws_member_*_summary` daily | **不需要** |
| 11 | (Sprint 2 推迟项) 累计交易笔数 | 需 ETL 新增 `total_open_table_count` | **需要** |
| **MP-2 完整 daily salary** | 新建 `dws_assistant_daily_salary` 表 + Excel 上传 UI 改造 | **需要** |
### Sprint 3 拆分实施
**子 Sprint 3a(可立刻启动)**:5 个 P1 指标 #6~#10
- 沿用 Sprint 1/2 §3 五步流程
- 估算 ~ 3-4h
- 不依赖 ETL 团队
**子 Sprint 3b(等 ETL 配合)**:#11(累计交易笔数)+ MP-2 完整
- 需要先与 ETL 团队对齐:新建 `dws_assistant_daily_salary` + 新增 `total_open_table_count` + Excel 上传 UI 改造
- 估算 ~ 5-6h(含 ETL 改造)
### Sprint 3 总估算
5 P1 指标 ~ 3-4h + #11/MP-2 完整 5-6h = **L ~ 8-10h**(可拆 3a + 3b 独立推进)
---
## 五、Sprint 4 范围(待启动)
### 5 个 P2 算法重算指标
| # | 指标 | 难点 |
|---|------|------|
| 11 | RS 关系指数 | 算法窗口期 + 衰减函数,daily 重算需重做累计 |
| 12 | 客户黏性指数 | 类似 RS,有时间衰减 |
| 13 | 任务完成率(coach_tasks) | 需补 dws daily 聚合视图 |
| 14 | Excel 修正(扣款/奖励/支出/收入) | 依赖 effective_date(F1-5b prep 已就位),后端 SQL 加截断 |
| 15 | 月度新增/流失会员(算法版) | dws_member_lifecycle 重算 |
### Sprint 4 估算
M-L ~ 6-8h
---
## 六、阶段 C(F1-7+ 远期)
详见 sandbox-replay-engine-spec.md §11.5:
- 3 个 P3 指标(门店等级 / 助教星级 / 累计 KPI)
- `biz.sandbox_audit_log` 用户行为审计表
- AI app8_consolidate prompt audit
---
## 七、关联
- 完整模块 spec:`docs/_overview/sandbox-replay-engine-spec.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 §11.4 + §11.5(F1-6 待办登记):`docs/prd/specs/P20-runtime-context-sandbox.md`
- Sprint 1 审计:`docs/audit/changes/2026-05-05__f1_6_sprint1_sandbox_replay_kickoff.md`