Commit Graph

6 Commits

Author SHA1 Message Date
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
Neo
c446920c9e feat(backend): F1-6 sprint2 #5 累计 GMV 加入 sandbox_replay (门店级)
Sprint 2 收尾指标:门店级累计 GMV(与 #1-#4 会员级粒度不同),新建
sandbox_replay/finance_replay.py 模块。无原 fdw_queries.get_total_gmv
函数(0 现有调用方),不写 thin wrapper(spec §5.5 决策原则)。

数据源 dws_finance_daily_summary.gross_amount(门店日度财务汇总,daily 累计)。
SQL 模式 SUM(gross_amount) WHERE stat_date <= ctx.business_date,与 #1-#4
取最新单行不同,是多行累计 SUM。SQL 层 COALESCE(SUM(...), 0) 兜底,无数据
返回 Decimal('0')(开店前累计 GMV = 0,业务语义)。

口径 gross_amount = table_fee + goods + assistant_pd + assistant_cx,**不含
electricity_money**(与会员级 items_sum 略有差异,docstring 明确防止交叉验证)。

双口径数值验证 PASS(直接 Python,site=2790685415443269 朗朗桌球):
- 4a live(today=2026-05-05): ¥5,725,837.51
- 4b sandbox=2026-04-20: ¥5,653,063.37(差异 ¥72,774,即 4-21~4-27 七天合计)

新增防御性回归测试 test_get_total_gmv_no_member_ids_param 阻断未来误加
member_id 参数(门店级粒度强约束)。

unit test sprint1+sprint2 累计 28/28 PASS,无回归。

Sprint 2 收尾(4 项迁移 + #3 推迟 Sprint 3 等 ETL 配合)。

详见 docs/audit/changes/2026-05-06__f1_6_sprint2_total_gmv.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:32:14 +08:00
Neo
7b1cfadc2e feat(backend): F1-6 sprint2 #4 储值卡余额迁移 sandbox_replay (SCD2 时光机)
新建 sandbox_replay/balance_replay.py 模块,迁移 fdw_queries.get_member_balance,
fdw_queries 改 thin wrapper 保持 5 处现有调用(chat/coach/customer x2/task_manager)
透明兼容。

数据源 dim_member_card_account 是 SCD2 维度表(原生支持时光机),sandbox 改造
关键是替换 scd2_is_current=1 过滤为 scd2_start_time + scd2_end_time 时间过滤
(ref_date+1day 边界 = 当天结束时仍 active 的版本,timestamptz 比较稳定)。

双口径 UI 走查 PASS(member=2799207363643141 葛先生,SCD2 历史余额变化样本):
- 4a live(today=2026-05-05): 储值余额 ¥6,602
- 4b sandbox=2026-04-20: 储值余额 ¥18,080(差异 1.1w+,时光机效果显著)

unit test sprint1+sprint2 累计 24/24 PASS,无回归。

附带本次 sprint 2 触发的架构级登记:
- 新建 docs/_overview/architecture-evolution-backlog.md(DWD 孤立 + Core 中间件 +
  库重组,长远架构演进 backlog)
- F1-6-tasks.md 登记 #3 累计交易笔数推迟 Sprint 3(ETL 配合新增
  total_open_table_count,因现有 total_visit_count 实算 COUNT(settle_type IN (1,3))
  含商城订单,不符 Neo "开台次数"业务语义)
- sandbox-replay-engine-spec §5.5 thin wrapper 决策原则(已在 #2 commit)

详见 docs/audit/changes/2026-05-06__f1_6_sprint2_member_balance.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 01:26:18 +08:00
Neo
32716bc71a feat(backend): F1-6 sprint2 #2 累计消费总额加入 sandbox_replay
新增指标(无 fdw_queries 原查询 + 0 现有调用方 + 无 thin wrapper),沿用
sprint 1/sprint2 #1 模式 @trace_service + @runtime_aware decorator + 显式
stat_date <= ctx.business_date 上界 + dws_member_consumption_summary
.total_consume_amount 字段 items_sum 口径。

双口径数值验证 PASS(member=2799207087163141 黄先生,直接 Python 调用):
- 4a live(today=2026-05-05): get_total_consume_amount=1252.65
- 4b sandbox=2026-04-20: get_total_consume_amount=999.99(walkthrough 测试快照)

unit test sprint1+sprint2 累计 19/19 PASS,无回归。

记录 thin wrapper 决策原则到 spec §5.5(迁移辅助层,非常态架构;
fdw_queries 长远退化纯 ETL 物理访问层,清理放收尾 sprint)。

注:#3 累计交易笔数因 spec §4 字段未明确(dws_order_summary vs
total_visit_count)暂停,等 Neo 决断后继续。

详见 docs/audit/changes/2026-05-06__f1_6_sprint2_total_consume_amount.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 00:52:08 +08:00
Neo
d418621951 feat(backend): F1-6 sprint2 #1 60d 消费迁移到 sandbox_replay
迁移 fdw_queries.get_consumption_60d 到 sandbox_replay.consumption_replay,
沿用 sprint 1 模式: @trace_service + @runtime_aware decorator + 显式
stat_date <= ctx.business_date 上界(与视图过滤双保险),fdw_queries 改
thin wrapper 保持 customer_service 2 处调用兼容。

双口径走查 PASS(member=2799207087163141 黄先生):
- 4a live(today=2026-05-05): 小程序 stat 卡条 60天消费 ¥115(consume_amount_60d=115.36)
- 4b sandbox=2026-04-20: 小程序 stat 卡条 60天消费 ¥89(walkthrough 测试快照 88.88)

unit test sprint1+sprint2 累计 15/15 PASS,无回归。

详见 docs/audit/changes/2026-05-06__f1_6_sprint2_consumption_60d.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 00:27:13 +08:00
Neo
9f1e35d71a feat(backend): F1-6 sprint1 sandbox_replay 模块脚手架 + get_last_visit_days 迁移试点 (W1)
F1-5b 完成后启动 F1-6 沙箱时光机阶段 B,Sprint 1 范围:
1. 建立 sandbox_replay 模块脚手架
2. 实现 @runtime_aware decorator(自动注入 RuntimeContext)
3. 试点迁移 1 个指标:get_last_visit_days(P1-4 距上次到店天数)
4. MCP 端到端 4a/4b 双口径走查

新增文件:
- apps/backend/app/services/sandbox_replay/__init__.py(模块入口 + re-export)
- apps/backend/app/services/sandbox_replay/_decorator.py(@runtime_aware 实现)
- apps/backend/app/services/sandbox_replay/consumption_replay.py(get_last_visit_days 试点)
- docs/_overview/wave1-findings/F1-6-tasks.md(F1-6 任务清单 4 个 sprint)
- docs/audit/changes/2026-05-05__f1_6_sprint1_sandbox_replay_kickoff.md(Sprint 1 审计)

修改:
- apps/backend/app/services/fdw_queries.py:218-238
  get_last_visit_days 改 thin wrapper,委托 sandbox_replay.consumption_replay
  保持 75+ 现有调用点无感兼容

关键 bug 修复:@trace_service + @runtime_aware 嵌套 sig.bind 失败
- 现象:仅 FastAPI 请求 + 有活跃 TraceContext 时复现
  (直接 Python 脚本 get_current_trace 返回 None,跳过 _build_params_dict)
- 根因:functools.wraps 设置 __wrapped__ 让 inspect.signature 追溯原函数
  → bind 时缺 keyword-only 必传 ctx → TypeError
- 修复:_decorator.py 不用 functools.wraps,手动复制元信息但不设
  __wrapped__,inspect.signature 看到 wrapper 自身 (*args, **kwargs)

测试:
- unit test 10/10 PASS(本地 .gitignore:71 不入仓)
- 直接 customer_service.get_customer_detail PASS(独立诊断脚本)
- etl_conn 复用模式 PASS

MCP 双口径(member=2799207087163141 黄先生):
- 4a live (today=2026-05-05): daysSinceVisit=32(05-05 - 04-03)
- 4b sandbox=2026-04-20: daysSinceVisit=31(04-20 - 03-20)
  通过插 walkthrough 测试快照 stat_date=2026-04-15 演示
  (测试库 dws_member_consumption_summary 仅 stat_date=2026-05-01 一行,
   sandbox=4-20 时被视图层 stat_date <= business_date_now() 过滤)
- 测试快照已清理,sandbox 已切回 live

Sprint 2-4 待启动(见 F1-6-tasks.md):
- Sprint 2:5 个会员 P1 指标(余额/60d 消费/累计交易/GMV/累计服务客户数)
- Sprint 3:5 个助教/门店 P1 + MP-2 完整(含 ETL 改造)
- Sprint 4:5 个 P2 算法重算指标

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:53:19 +08:00