- [P20260221-232732] 2026-02-21 23:27:32 +0800
  - summary: CONTEXT TRANSFER: We are continuing a conversation that had gotten too long. Here is a summary: --- ## TASK 1: 前后端联调 — a…
  - prompt:
```text
CONTEXT TRANSFER: We are continuing a conversation that had gotten too long. Here is a summary:

---
## TASK 1: 前后端联调 — admin-web 任务配置、提交、执行、验证

**STATUS**: in-progress (DDL 合并进行中)

**USER QUERIES**: All queries in this conversation are continuations of the same task from previous context transfers.

**SHORT DESCRIPTION**: 前后端联调：通过 admin-web 浏览器配置 ETL 任务（api_full, full_window, 2025-11-01~2026-02-20, 30天窗口切分, force-full, 19个任务），提交执行，修复发现的 BUG，做回归测试和数据检验。

**DETAILS**:

### BUG 1~11（前几轮上下文已完成）
- v1~v8 共 8 次执行，11 个 BUG 全部修复并验证通过
- v8 最终成绩: 14/19 成功, 5/19 级联失败, 耗时 1m24s
- 完整 BUG 报告已导出到 `export/SYSTEM/LOGS/2026-02-21__etl_full_bug_report.md`

### BUG 12 — 哨兵日期 BC 转换问题（代码修复+存量修复+验证 全部完成）

**根因**：上游飞球 API 对"未设置"的日期返回 `0001-01-01T00:00:00`（哨兵值），ODS `timestamp` 转 DWD `timestamptz` 时在 `Asia/Shanghai` 时区下变成 `0001-12-31 23:59:43 BC`，psycopg2 无法解析。

**代码修复（3 处，已完成）**：
1. `_cast_expr` — 对 `timestamptz` CAST 加 `CASE WHEN (base)::timestamp >= '0002-01-01'::timestamp THEN ... ELSE NULL END`（注意用 `(base)::timestamp` 显式 CAST，因为 base 可能是 JSONB `->>'key'` 提取的 text 类型）
2. `_build_fact_select_exprs` — 事实表 `timestamp → timestamptz` 同类型列加哨兵过滤
3. `_merge_dim_scd2` — ODS→DWD SELECT 和 DWD 现有数据读取均加哨兵过滤
4. 新增类属性 `_SENTINEL_DATE_THRESHOLD = "0002-01-01"`

**存量数据修复（已完成）**：通过 MCP SQL 工具（`mcp_pg_etl_execute_sql`）直接执行 6 条 UPDATE，绕过 psycopg2 的 BC 日期解析问题。验证确认所有 6 个表/列的 BC 日期已清零。

**执行验证**：
- v9: status=success, exit_code=0, 92.8s — 但 `dwd.dim_site_ex` 报错（`text >= timestamp` 类型不匹配，因为 JSONB `->>'create_time'` 返回 text）
- v10: status=success, exit_code=0, 90.5s — 修复 `_cast_expr` 后全部通过，0 错误，42 个 DWD 表全部装载成功

### DDL 及文档落地（进行中）

**已完成**：
1. 迁移脚本：`db/etl_feiqiu/migrations/2026-02-22__fix_bc_sentinel_dates_to_null.sql` — 6 条 UPDATE，幂等可重复执行
2. 变更日志：`docs/database/etl_feiqiu_schema_migration.md` — 迁移 11 条目已追加（含根因、影响范围、代码变更、回滚策略、4 组验证 SQL）
3. BD 手册：`docs/database/BD_Manual_fix_bc_sentinel_dates.md` — 完整问题描述、受影响对象、修复方案、设计决策

**未完成 — 合并到主 DDL**：
用户要求将修改合并到主 DDL 文件 `db/etl_feiqiu/schemas/dwd.sql`。已通过 grepSearch 找到了所有受影响列的位置和 COMMENT 定义。需要做的是：
- 更新 6 个受影响列的 COMMENT，将示例值从 `0001-01-01 00:00:00` 改为说明哨兵值处理约定（ETL 装载时 < 0002-01-01 的值置为 NULL）
- 具体需要更新的 COMMENT 行（dwd.sql 中有重复的 COMMENT 行，需要去重）：
  - `dwd.dim_assistant_ex.birth_date`（约第 360 行，有 3 条重复 COMMENT）
  - `dwd.dim_member_card_account_ex.disable_start_time`（约第 606 行，有 3 条重复）
  - `dwd.dim_member_card_account_ex.disable_end_time`（约第 607 行，有 3 条重复）
  - `dwd.dwd_assistant_service_log_ex.composite_grade_time`（约第 1579 行，有 3 条重复）
  - `dwd.dwd_settlement_head_ex.revoke_time`（约第 1135 行）
  - `dwd.dwd_recharge_order_ex.revoke_time`（约第 2020 行）

**NEXT STEPS**:
1. 读取 `dwd.sql` 中每个受影响列的 COMMENT 行的精确内容
2. 去除重复的 COMMENT 行（每列只保留 1 条）
3. 更新 COMMENT 内容，添加哨兵值处理说明：`【哨兵值处理】上游 API 返回 0001-01-01T00:00:00 表示"未设置"，ETL 装载时转为 NULL`
4. 在 `dwd.sql` 文件头部或受影响表附近添加注释说明哨兵日期约定
5. 完成后需要运行 `/audit`（改动命中 `db/` 和 `tasks/` 高风险路径）

### 认证信息
- refresh_token（7天有效，到 2026-02-28）: `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwic2l0ZV9pZCI6Mjc5MDY4NTQxNTQ0MzI2OSwidHlwZSI6InJlZnJlc2giLCJleHAiOjE3NzIyNjM0NjN9.XYoda5lfxNtTSAGWoLlYhS9cA-hTK9iqK0SqUyn2KV4`
- 刷新 API: `POST http://localhost:8000/api/auth/refresh` body: `{"refresh_token": "..."}`
- 提交执行 API: `POST http://localhost:8000/api/execution/run`
- 查询执行状态: `GET /api/execution/history?limit=5`（不是 `/api/execution/{id}`，那个返回 404）
- 查询执行日志: `GET /api/execution/{id}/logs`
- token 文件: `scripts/ops/.monitor_token`

### 关键 DDL 发现
- `dwd.dim_table` 主键字段是 `table_id`（不是 `site_table_id`）
- `dwd.dim_member` 没有 `site_id`，只有 `register_site_id`；没有 `birthday` 字段
- `dwd.dwd_recharge_order` 没有 `pay_money`/`gift_money`，实际字段为 `pay_amount`/`point_amount`
- ODS 表中 PostgreSQL 列名全小写（`sitegoodsid`），不是 JSON 原始驼峰（`siteGoodsId`）
- `dwd.sql` 中部分列的 COMMENT 有重复行（同一列 3 条相同 COMMENT），需要去重

**FILEPATHS**:
- `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` — BUG 12 代码修复主文件（`_cast_expr`、`_merge_dim_scd2`、`_build_fact_select_exprs`）
- `db/etl_feiqiu/schemas/dwd.sql` — 主 DDL 文件，需要合并 COMMENT 更新
- `db/etl_feiqiu/migrations/2026-02-22__fix_bc_sentinel_dates_to_null.sql` — 存量修复迁移脚本（已创建）
- `docs/database/etl_feiqiu_schema_migration.md` — 变更日志（迁移 11 已追加）
- `docs/database/BD_Manual_fix_bc_sentinel_dates.md` — BD 手册（已创建）
- `apps/etl/connectors/feiqiu/orchestration/flow_runner.py` — BUG 11 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/finance_base_task.py` — BUG 8 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py` — BUG 8 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/member_visit_task.py` — BUG 5+6 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/finance_income_task.py` — BUG 7 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/assistant_daily_task.py` — BUG 1 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/assistant_monthly_task.py` — BUG 2 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/assistant_customer_task.py` — BUG 3+4 已修复
- `apps/etl/connectors/feiqiu/tasks/dws/member_consumption_task.py` — BUG 4 已修复
- `scripts/ops/fix_bc_dates.py` — 存量修复脚本（已废弃，psycopg2 无法处理 BC 日期）
- `scripts/ops/poll_v9.py` / `scripts/ops/poll_v10.py` — 轮询脚本

**USER CORRECTIONS AND INSTRUCTIONS**:
- 所有说明性文字使用简体中文
- 输出路径必须通过 `_env_paths.get_output_path()` 从 `.env` 读取，禁止硬编码
- `scripts/ops/` 下的脚本必须 `load_dotenv` 加载根 `.env`
- 提交执行 API 路径是 `/api/execution/run`（不是 `/submit`）
- 查询执行状态用 `/api/execution/history?limit=5`（不是 `/api/execution/{id}`）
- 改动命中 `tasks/` 和 `db/` 高风险路径，完成后需要运行 `/audit`
- 后端服务运行在 `localhost:8000`，admin-web 通过 pnpm dev 运行
- 脚本执行规范：优先编写 Python 脚本再执行，避免 PowerShell 复杂逻辑
- cwd 注意：`scripts/ops/` 下的脚本需要 `cwd: scripts/ops` 执行
- 此问题有普遍性，对所有表、任务进行全面修复（用户明确要求）
- 用户要求"合并到主 DDL"，即更新 `db/etl_feiqiu/schemas/dwd.sql` 中受影响列的 COMMENT

Files to read:
- `db/etl_feiqiu/schemas/dwd.sql` — 主 DDL 文件，需要合并 COMMENT 更新（当前进行中的工作）
- `db/etl_feiqiu/migrations/2026-02-22__fix_bc_sentinel_dates_to_null.sql` — 已创建的迁移脚本，参考用
- `docs/database/etl_feiqiu_schema_migration.md` — 变更日志，确认迁移 11 已正确追加（读前 120 行即可）
- `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` — 代码修复主文件，参考 `_cast_expr` 方法确认修复正确性

USER QUERIES(most recent first):
1. 合并到主DLL
2. Output:
Command executed successfully with no output.

Exit Code: 0
3. Output:
Command executed successfully with no output.

Exit Code: 0
4. 合并到主DLL
5. Output:
Command executed successfully with no output.

Exit Code: 0
6. Output:
Command executed successfully with no output.

Exit Code: 0
7. Output:
Command executed successfully with no output.

Exit Code: 0
8. 这个修改，落地 DDL 及相关文档。
9. Output:
Command executed successfully with no output.

Exit Code: 0
10. Output:
Command executed successfully with no output.

Exit Code: 0
11. Output:
Command executed successfully with no output.

Exit Code: 0
---

METADATA:
The previous conversation had 6 messages.

INSTRUCTIONS:
Continue working until the user query has been fully addressed. Do not ask for clarification - proceed with the work based on the context provided.
IMPORTANT: you need to read from the files to Read section
```
