Files
Neo-ZQYY/docs/_overview/04a-feedback/P0-5-engineering-consistency-overview.md
Neo 509cf43284 chore(docs): Wave 0 调研产出 + P0/P1/P2 反馈调研
建立项目级标杆文档 docs/_overview/ 作为产品全景索引,
解决"PRD 零碎、文档膨胀、跨子系统调研无入口"的问题。

主要内容:
- 00-index 总索引 + 维护协议 + 与 CLAUDE.md 关系
- 01-product-overview 产品全景脑图(6 角色 / 6 子系统 / 数据流 /
  7 业务概念 / 8+1 AI 矩阵 / 22 术语)
- 02a-miniprogram-page-matrix 小程序 21 页业务指纹
- 02b-adminweb-page-matrix admin-web 19 路由业务指纹
- 03-test-spec 测试规范 (L1-L5 分层 + 走查模板 + 75-95 case 估算)
- 04-doc-conflicts 39 条冲突索引(P0×8 / P1×13 / P2×13 + 5 子项)
- 04a/b/c-conflicts-*-detail 业务故事卡(7 字段:关联/逻辑/影响/选项/判定)
- 05-orphan-pages-cleanup admin-web 6 孤儿页面处置(1 归档 + 4 保留)
- WAVES-MASTER-PLAN.md 全 Wave 主计划(0-5,共 22-32 工作日)
- WAVE-1-KICKOFF.md Wave 1 实施 kickoff
- GLOBAL-DECISION-DASHBOARD.md 全局决策仪表板

反馈调研产物:
- 04a-feedback/ P0 两轮反馈(8+8 项决策 + D-1/2/3 + F-1/2 子代理产出)
- 04b-feedback/ P1 两轮反馈(13+1+5 项 + E-1/2/3/4 + G-1/2 子代理产出)
- 04c-feedback/ P2 反馈(13 项 + 5 子项 + H-1/2/3 子代理产出)
- NEO-DECISIONS-LOG 累积决策记录

关键追加发现 8 处 D Bug(原蓝本 0):
- P0-3 看板沙箱接入(Wave 1 W1-T1)
- P0-5 致命 1 (4 处 fdw_etl 残留, 已修 commit 17f045a)
- P0-5 致命 2 (JWT aud 缺失, 已修 commit 17f045a)
- P0-6 clearAllTasks 守卫 (Wave 3)
- P0-8 DBViewer 黑名单漏 (已修 commit 17f045a)
- P1-3 task-detail 跳转传 task_id 而非 customer_id
- P2-7 board-finance 隐式 null
- 2 个独立 Bug (page_context.created_at + ClueCategory 字典)

参考: docs/_overview/00-index.md
2026-05-04 07:38:28 +08:00

24 KiB

P0-5 工程规范一致性全览

调研时间:2026-05-04 触发:Neo 在 P0-5 反馈"matching.py 直连 ETL 偏离规范"基础上提出 — 找到全项目类似情况,给个全览,并制定工程规范化和一致性的实施方案 关联:04a-feedback/P0-5-matching-evolution.md(本调研为其下游) 性质:只调研不实施,产物为治理路线图


一、规范基线清单(共 14 条)

来源:CLAUDE.md(根 / 子模块) + 已知 spec / BD 手册 + 历史审计。

# 规范 来源 关键判定
R1 业务库通过 FDW 只读访问 ETL,不直连 ETL 库 apps/backend/CLAUDE.md "ETL 数据通过 FDW 映射的 app.v_* RLS 视图访问" 后端不应直接 psycopg2.connectetl_feiqiu
R2 DWS / 取数禁用 consume_money,统一用 items_sum(ledger_amount) feiqiu CLAUDE.md / DWD-DOC 规则 1 SELECT / 计算 / 返回字段不应包含 consume_money
R3 DWD/DWS 视图必须双 schema(原 schema + app schema 同步建) db/CLAUDE.md RLS 双 schema 模板 后端可走 app.v_*,但 dws.v_* 必须存在等价镜像
R4 后端响应统一通过 ResponseWrapperMiddleware 包装 apps/backend/CLAUDE.md 不应有路由用 JSONResponse/response_class 显式绕过
R5 JWT 三类 aud(admin/miniapp/tenant-admin)严格隔离 apps/backend/CLAUDE.md JWT 双认证表 签发与校验都必须设置/校验 aud 字段
R6 AI 应用调用走 dispatcher 调度,不直接调 DashScope SDK apps/backend/CLAUDE.md AI 集成 业务路由不应自行构造 DashScopeClientApplication.call
R7 配置分层 .env < .env.local < 环境变量 < CLI 参数,禁止生产代码硬编码主机/凭据 根 CLAUDE.md 业务源码不应出现硬编码 IP/URL/密钥
R8 测试不连生产库,用 TEST_*_DSN/load_dotenv 加载根 .env 根 CLAUDE.md "测试与验证环境规范" 测试不应引用 PG_DSN/APP_DB_DSN
R9 小程序参数命名 camelCase 对外、snake_case 内部 通用约定 后端 SnakeCase → CamelModel 自动转,前端取 camelCase
R10 审计记录全部归 docs/audit/changes/,不写入子模块 根 CLAUDE.md "文件归属规则" 子模块下不应出现 docs/audit/
R11 _archived/ 目录禁止读取或参考 根 CLAUDE.md 不应被 grep/read,不应被新代码引用
R12 apps/demo-miniprogram/(MOCK 标杆)禁改 根 CLAUDE.md 30 天内不应有 commit 触及
R13 shared 包跨子项目共享 enums/money/datetime_utils 根 CLAUDE.md / 推断 子项目不应重复定义同名工具
R14 DWD/DWS 字段命名约定:ETL 用 tenant_member_id / site_assistant_id,业务可用 member_id / assistant_id(已映射) feiqiu CLAUDE.md fdw_queries.py:48-58 跨层混用应有显式映射注释

二、偏离点全集(按规范分组)

2.1 R1 · FDW / 跨库访问

关键背景:H2(2026-03-20)规范变更后,业务后端"直连 ETL 库 + RLS 视图"已成为事实标准(fdw_queries._fdw_context() 模式)。R1 当前的写法"业务库通过 FDW 访问 ETL"在 apps/backend/CLAUDE.md 中实际已过期,应在治理时同步修订。但即便按事实标准衡量,仍存在多处偏离。

偏离点 1 — apps/backend/app/services/matching.py:62(P0-5 主体)

  • 现状:用 _fdw_context(None, site_id) 直连 ETL,未传入业务库 conn,bd_str 降级为系统今天而非 RuntimeContext.business_date
  • 偏离类型:绕过 RuntimeContext 透传(P0-5 选项 B 主张"补 FDW 外部表"消除直连)
  • 影响:沙箱模式下日期上界裁剪失效(若 site 启用沙箱,匹配读到未来助教/员工)

偏离点 2 — apps/backend/app/database.py:175 get_etl_write_connection() + services/task_generator.py:1107

  • 现状:后端写入 ETL 关系指数表(get_etl_write_connection() 是可写连接,无 RLS,task_generator 直接执行 INSERT)
  • 偏离类型:严重违反 R1(规范明确"FDW 只读访问 ETL")
  • 影响:业务后端越权写 ETL 库,绕过 ETL Loader 流程,数据所有权混乱

偏离点 3 — apps/backend/app/database.py:109 get_etl_global_readonly_connection() + routers/etl_status.py:44

  • 现状:全局只读连接,不设置 app.current_site_id,直连 ETL 库读全局状态
  • 偏离类型:绕过 RLS 隔离(规范前提"直连必带 RLS")
  • 影响:潜在跨门店数据泄露(若被业务路由误调)

偏离点 4-7 — H2 改造遗漏的"伪 FDW"代码(实际必坏)

文件 行号 现状 严重度
routers/tenant_users.py 425, 450 etl_conn = get_etl_readonly_connection(site_id) 后 SQL 写 FROM fdw_etl.v_dim_assistant/v_dim_staff P0 — 必失败
routers/tenant_excel.py 390, 407 同上,SQL 写 fdw_etl.v_dim_assistant/v_dim_staff P0 — 必失败
routers/tenant_clues.py 113, 119 同上,SQL 写 fdw_etl.v_dim_member P0 — 必失败

致命点:这些查询连接的是 etl_feiqiu 库,而 fdw_etl schema 只存在于 zqyy_app 业务库 → 必报 schema "fdw_etl" does not exist → 当前被 try/except 静默吞,接口表面正常但永远返回空列表。这是 P0-5 同类(H2 改造遗漏)的高危偏离。


2.2 R2 · consume_money 字段

偏离点 8 — apps/backend/app/services/fdw_queries.py:1173/1208/1226

  • 现状:get_member_consumption_orders() SELECT 仍包含 sh.consume_money,GROUP BY 也带,字典返回 "consume_money": float(...) 给前端
  • 偏离类型:R2"DWS 取数禁用 consume_money"违反
  • 用途反查:customer_service.py:385 用于"原价/折扣价"对比展示(原价 = consume_money,实付 = total_amount)
  • 评估:业务有真实需求(展示"划线价"),但取自 DWD 原始 consume_money 仍属于规范偏离 → 应在 BD 手册更新口径或加 view 层封装

偏离点 9 — apps/etl/connectors/feiqiu/tasks/utility/dws_build_order_summary_task.py:23

  • 现状:用 (COALESCE(sh.consume_money, 0) = 0 AND COALESCE(sh.pay_amount, 0) > 0) AS recharge_order_flag 识别充值订单
  • 偏离类型:R2 在判定逻辑中使用 consume_money(非金额计算,但仍是该字段)
  • 评估:判定语义合理(充值单消费金额必为 0),但应文档化为"R2 例外:仅作零值判定,不参与金额计算"

2.3 R3 · DWS 双 schema 视图

偏离点 10 — DWS schema 仅暴露 4 个视图,app schema 暴露 50+(规模性偏离)

db/etl_feiqiu/schemas/dws.sqldws.v_* 仅 4 条:

  • dws.v_dws_coach_area_hours(L1206)
  • dws.v_dws_finance_area_daily(L1227)
  • dws.v_dws_finance_board_cache(L1267)
  • dws.v_member_recall_priority(L1292)

db/etl_feiqiu/schemas/app.sqlapp.v_dws_*/app.v_dwd_*/app.v_dim_*/app.v_cfg_* 共约 50 条

DWS 基表共有 38 张(L46-L1027),意味着 ~34 张表只在 app schema 暴露 RLS 视图,违反 R3"双 schema"。

  • 偏离类型:R3 规模性违反
  • 影响:运维直查 dws schema 时只能看到原始基表(无门店过滤),易出错;新建 RLS 视图必须双 schema 的规则反复被忽视
  • 历史标记:memory/MEMORY.md 提到"踩坑 2026-03-29 DWS RLS 双 schema 强制规则"已存在,但执行不严

2.4 R4 · ResponseWrapperMiddleware

评估:无显式偏离,中间件设计良好

app/middleware/response_wrapper.py:33-37 中间件已自动跳过:

  • text/event-stream(SSE)
  • application/json
  • 非 2xx

xcx_chat.py:344 / tenant_excel.py:954StreamingResponse(SSE / 文件下载),由中间件自动跳过包装,不算偏离


2.5 R5 · JWT aud 严格隔离

偏离点 11 — apps/backend/app/auth/jwt.py:42-50 admin/miniapp 签发完全不带 aud 字段

payload = {
    "sub": str(user_id),
    "site_id": site_id,
    "type": "access",
    "exp": expire,
}  # 无 aud!

只有 tenant_auth.py:69/93 显式设置 "aud": "tenant-admin"。意味着:

  • admin-web 与小程序 token 在 payload 层无法区分

  • auth/dependencies.py:124 decode_access_token()没校验 aud

  • 结果:小程序 token 理论上可被用于 admin 端点(若仅依赖 decode_access_token + roles 检查,roles 分类不严就破防)

  • 偏离类型:P0 — 安全性偏离 R5

  • 影响:跨端横向越权风险

  • 修复成本:中(需小程序/admin-web 同步重新签发 token + 后端 verify 接受多 aud)


2.6 R6 · AI 应用走 dispatcher

偏离点 12 — 多处直接构造 DashScopeClient 调用

文件 行号 用途
app/main.py 145 lifespan 内全局单例(合理,作为 dispatcher 注入源)
app/services/chat_service.py 734 _get_dashscope_client() 工厂 + :644 直接 SSE 流式调用百炼
app/services/note_service.py 71 单点客户端实例化(走 App6 直接调用)
app/routers/xcx_chat.py 408 同上,xcx_chat.py:203 SSE 直接调
  • 偏离类型:R6 部分违反
  • 评估:SSE 流式回复天然不能走 dispatcher 的 run_step(dispatcher 设计是同步整段 reply),目前实现合理。但 note_service 直调 App6 应改走 dispatcher
  • 影响:绕过熔断/限流/预算追踪,但 client 内部已有部分保护
  • 修复成本:小(note_service 改走 dispatcher;chat_service SSE 路径标记为合理偏离)

2.7 R7 · 配置硬编码

偏离点 13 — apps/etl/connectors/feiqiu/config/defaults.py:30

  • 现状:"base_url": "https://pc.ficoo.vip/apiprod/admin/v1" 硬编码飞球 API
  • 评估:作为 default 合理,允许 .env 覆盖;不算严格偏离

偏离点 14 — apps/etl/connectors/feiqiu/scripts/refresh_json_and_audit.py:22 / full_api_refresh_v2.py:27

  • 现状:API_BASE = "https://pc.ficoo.vip/apiprod/admin/v1/" 模块顶层硬编码,无 env 读取分支
  • 偏离类型:R7 违反
  • 影响:迁移到飞球新域名/沙箱时改不动;一次性脚本性质风险低
  • 修复成本:小

偏离点 15 — apps/etl/connectors/feiqiu/orchestration/flow_runner.py:255

  • 现状:backend_url = os.getenv("BACKEND_API_URL", "http://127.0.0.1:8000") — fallback 到本机
  • 评估:合理(开发期默认),且有 env 覆盖

偏离点 16 — apps/admin-web/vite.config.ts:11playwright.config.ts:21

  • 现状:proxy target / playwright baseURL 硬编码 localhost:8000 / localhost:5173
  • 评估:合理(开发工具配置,非生产代码)

2.8 R8 · 测试不连生产库

偏离点 17 — apps/backend/tests/tests/unit/test_backfill_script.py:29

  • 现状:with patch.dict("os.environ", {"APP_DB_DSN": "postgresql://test:test@localhost/test"}) — 用 APP_DB_DSN 而非 TEST_APP_DB_DSN
  • 偏离类型:R8 违反(变量名错误,虽然值是假 DSN)
  • 影响:命名混淆,易让人以为生产 DSN 也能用;真跑会因 patch 顺序问题潜在风险
  • 修复成本:极小

偏离点 18 — 测试 load_dotenv 检查

apps/backend/tests/tests/integration/ 下两个 e2e 测试 import load_dotenv,实际加载根 .env(包含 PG_DSN/APP_DB_DSN),依赖 cwd 决定加载哪个 .env。如果集成测试在 backend cwd 跑,会加载 apps/backend/.env.local(其内 CORS_ORIGINS=http://localhost:5173未必有 TEST_*_DSN 覆盖) → 风险:误连生产库

  • 偏离类型:R8 潜在违反
  • 修复成本:中(需 conftest 强制注入 TEST_*_DSN 校验)

2.9 R9 · 命名风格

偏离点 19 — 小程序 task-list.ts:586,628,647 内部混用 camelCase / snake_case

const memberId = (target as any).memberId ?? (target as any).member_id  // L586
const userId = (authUser as any).userId  // L628

后端 CamelModel 应自动转成 camelCase 输出,小程序兜底读 snake_case 表明历史上后端字段未走 CamelModel。需逐字段确认:

  • 是否后端 xcx_* 路由全部走 CamelModel.model_dump(by_alias=True)?

  • 现状部分 service 直接 dict 返回(如 tenant_users.py:441 .model_dump(by_alias=True) 写了,但 routers/xcx_* 是否一致?)

  • 偏离类型:R9 部分违反(已知 P1-9 反馈)

  • 修复成本:中

偏离点 20 — member_id vs tenant_member_id 混用

ETL 库 DWD 字段名 tenant_member_id(fdw_queries.py:48 注释明确),业务 API 对外是 member_id。 fdw_queries.py 内 SELECT/JOIN 都正确映射(tenant_member_id = %s → 返回 member_id),小程序 API 用 memberId

  • 评估:已有显式映射,符合 R14(DWD 字段命名约定),不算偏离;但映射散落在 200+ 行,易遗漏

2.10 R10 · 审计文件归属

偏离点 21 — apps/backend/tests/tests/_archived/

  • 现状:子模块测试目录下有 _archived/(test_ai_app2.py / test_ai_apps_prompt.py / test_ai_clue_writer.py)
  • 偏离类型:R11 + R10 违反(子模块下不应有 _archived/,此为旧 Cursor 时代的产物)
  • 修复成本:小(整体移到根 _DEL/ 或者评审后删除)

偏离点 22 — apps/backend/tests/tests/ 嵌套异常

  • 现状:apps/backend/tests/apps/backend/tests/tests/ 同时存在并各有重复测试文件(test_auth_jwt.py 出现在两层)
  • 偏离类型:目录结构混乱 / 历史迁移残留
  • 影响:pytest 重复执行 / 修改时不知改哪个版本
  • 修复成本:小(取舍后删一份)

偏离点 23 — apps/etl/connectors/feiqiu/tests/unit/unit/

  • 现状:tests/unit/unit/ 三层嵌套,任务测试文件有 task_test_utils.py 同名重复
  • 偏离类型:同 22
  • 修复成本:小

评估:apps/etl/connectors/feiqiu/scripts/audit/

  • 现状:模块内 scripts/audit/ 是审计工具(scanner.py / inventory_analyzer.py 等),不是审计记录
  • 评估:不算偏离(R10 限定的是审计记录,工具放模块内合理)

2.11 R11/R12 · _archived/demo-miniprogram/

偏离点 24 — demo-miniprogram 30 天内被修改

git log 显示:

  • f2e0de8(2026-05-02 反向迁移) — 改 apps/demo-miniprogram/AGENTS.md
  • 81e4173(2026-04-29) — 改同文件
  • 2a7a5d6(2026-04-15~20) — 改 project.miniapp.json / project.private.config.json
  • 偏离类型:R12 违反(MOCK 标杆原则上禁改)
  • 评估:AGENTS.md 是 AI 环境文件,反向迁移期间清理可理解;project.miniapp.json 改动需要审视

_archived/ 目录读取

pre_read_archived_block.py hook 已强阻断,无新违反


2.12 R13 · shared 包共用

未发现明显偏离。packages/shared/ 提供 enums/money/datetime_utils,各子项目正常 import,无重复定义。


三、偏离点严重度矩阵

# 偏离点 规范 原因 影响范围 修复成本 优先级 风险
1 matching.py 不传 conn R1 历史 H2 改造速度优先 单点 Wave 1
2 get_etl_write_connection + task_generator 写 ETL R1 紧急修复(关系指数回写) 模块 Wave 2
3 get_etl_global_readonly_connection 无 RLS R1 设计偏好(系统监控) 单点 长期
4-7 tenant_users/excel/clues 残留 fdw_etl.* SQL(必坏) R1 H2 改造遗漏 模块 立即(P0)
8 fdw_queries 返回 consume_money 给前端 R2 业务划线价需求 单点 Wave 3
9 dws_build_order_summary 用 consume_money 判定 R2 充值单零值判定 单点 极小 文档化
10 DWS schema 30+ 视图缺双 schema 镜像 R3 不知规范 / 历史遗留 全局 Wave 5
11 jwt.py 不带 aud,decode 不验 aud R5 设计偏好(单 secret) 全局 立即(P0)
12 note_service 直调 DashScopeClient R6 紧急功能 单点 Wave 2
13-14 飞球 API 地址硬编码 R7 一次性脚本 单点 极小 长期
17 test_backfill_script 用 APP_DB_DSN R8 命名错误 单点 极小 立即
18 集成测试 .env 加载顺序 R8 配置不严 模块 Wave 1
19 小程序 camelCase/snake_case 混用兜底 R9 历史 P1-9 已知 模块 Wave 3
21 tests/tests/_archived/ R10/R11 历史迁移残留 单点 极小 立即
22 tests/tests/ 嵌套重复 R10 历史迁移残留 模块 立即
23 feiqiu tests/unit/unit/ 嵌套 R10 历史迁移残留 模块 立即
24 demo-miniprogram 30 天内改动 R12 AGENTS.md 迁移 单点 0 文档化(可接受)

统计:24 个偏离点,其中 P0 立即 4 类(偏离 4-7、11、17、21、22、23),Wave 协同 5 类(1、2、8、12、18、19),长期 2 类(3、10、13-14),可接受文档化 3 类(9、20、24)。


四、统一治理方案

4.1 立即治理项(D-Bug 类,数据/安全风险)

治理 A · 修复 4 处必坏的 fdw_etl.* 残留(对齐 P0-5 主体)

文件 改法
routers/tenant_users.py:431 fdw_etl.v_dim_assistant app.v_dim_assistant
routers/tenant_users.py:456-457 fdw_etl.v_dim_staff / v_dim_staff_ex app.v_dim_staff / app.v_dim_staff_ex
routers/tenant_excel.py:394 fdw_etl.v_dim_assistant app.v_dim_assistant
routers/tenant_excel.py:411 fdw_etl.v_dim_staff app.v_dim_staff
routers/tenant_clues.py:119 fdw_etl.v_dim_member app.v_dim_member

后续应改用 _fdw_context() 而非裸 get_etl_readonly_connection(统一拥有 business_date GUC)。

治理 B · JWT aud 标准化(R5)

  1. auth/jwt.py:42 payload 增 "aud": "miniapp"(小程序签发)
  2. 新建 auth/admin_jwt.py 给 admin-web 签发,设 "aud": "admin"
  3. dependencies.py:124 decode_access_token 接受 audience 参数,FastAPI 依赖按路由前缀分流
  4. 测试覆盖:miniapp token 调 admin 端点必须 401,反之亦然

治理 C · 测试目录单轨化

操作
apps/backend/tests/tests/_archived/ → 评审后删除或移到根 _DEL/
apps/backend/tests/tests/apps/backend/tests/ 合并(保留较新版本)
apps/etl/connectors/feiqiu/tests/unit/unit/ 同上
test_backfill_script.py:29APP_DB_DSN 改为 TEST_APP_DB_DSN

4.2 Wave 协同项

Wave 关联偏离 治理措施
Wave 1(matching FDW 重建) 偏离 1、18 P0-5 选项 B 实施时,顺带把 _fdw_context 改为 must 接 conn,集成测试 conftest 强制注入 TEST_*_DSN
Wave 2(关系指数 / AI 流水线) 偏离 2、12 task_generator 关系指数回写 ETL → 改走 ETL 内置 task(由 ETL 主动消费 biz 的关系信号);note_service 改走 dispatcher
Wave 3(对外 API 一致性) 偏离 8、19 引入 view_dwd_order_with_orig_price 封装 consume_money 划线逻辑,前端字段统一 camelCase 强校验
Wave 5(数据库治理) 偏离 10 编写 tools/db/check_dws_dual_schema.py 扫描 dws 基表 vs dws.v_* 视图差集,补齐 30+ 镜像;CI 加守护测试

4.3 长期治理项

L1 · 修订 R1 文字(apps/backend/CLAUDE.md)

事实上 H2 后已统一直连 ETL,规范文字应改为:

ETL 数据通过 _fdw_context(conn, site_id) 直连 ETL 库 + RLS 视图访问;fdw_etl.* 外部表已废弃,新代码禁用。

L2 · 编写 scripts/audit/check_engineering_consistency.py

零 token 静态扫描脚本,检查项:

  1. grep fdw_etl\.apps/backend/app/ 下应零结果(白名单注释除外)
  2. grep audience= 在 jwt 签发函数应非空
  3. grep consume_money 在 backend service / ETL 任务中应有 BD 手册引用
  4. 双 schema 视图差集(对比 dws.v_*app.v_dws_*)
  5. 测试目录嵌套 / _archived/ 子模块违规
  6. localhost/127.0.0.1 在生产源码白名单外

接入 scripts/audit/prescan.py,合并到 /audit 流程

L3 · DWS 双 schema 历史补齐

约 30+ 个 app.v_dws_* 视图需补 dws.v_dws_* 镜像,生成迁移文件 db/etl_feiqiu/migrations/2026-XX-XX__dws_dual_schema_backfill.sql,逆序 DROP 写入回滚。

4.4 可接受偏离项(文档化归档)

偏离 理由 文档化位置
9 (dws_build_order_summary 用 consume_money 零值判定) 仅作零值标记,不参与金额计算,业务语义清晰 apps/etl/connectors/feiqiu/CLAUDE.md 增"R2 例外清单"
chat_service SSE 直调 DashScopeClient 流式 reply 无法走 dispatcher run_step 抽象 apps/backend/CLAUDE.md 增"R6 例外:SSE 流式直连"
20 (member_id ↔ tenant_member_id 映射) 已在 fdw_queries.py 集中映射,无散点违反 已在 fdw_queries.py:48-58 注释
24 (demo-miniprogram AGENTS.md) 反向迁移产物,与代码逻辑无关 CLAUDE.md R12 加"例外:AGENTS.md / project config 文件可随迁移调整"

五、CI / 自动化校验建议

5.1 静态规则(零 token)

检查 工具 失败动作
fdw_etl\.apps/backend/app/ grep + CI 拒绝合并
签发 JWT 必带 aud 字段 tools/audit/check_jwt_aud.py 拒绝合并
dws 基表 vs dws.v_* 视图差集 tools/db/check_dws_dual_schema.py warning(>0 个差集)
测试 from app.config import APP_DB_DSN 等违规导入 grep 拒绝合并
_archived/ 子模块嵌套 find / glob 警告

5.2 提交期 hook

新增 .claude/hooks/pre_commit_engineering_consistency.py:

  • pre-commit 阶段调上述静态扫描脚本
  • 命中即阻断并打印偏离点 + R 编号

5.3 周期性体检

scripts/audit/weekly_consistency_report.py:

  • 每周生成本表(同此文档结构)
  • 输出到 docs/audit/engineering_consistency_<YYYY-MM-DD>.md
  • diff 比上周新增/消除的偏离

六、给 Neo 的决策清单

按优先级倒序请 Neo 决策:

决策 D1(立即 / 高风险)

  • 是否同意 P0 治理 A:修复 4 处 fdw_etl.* 残留(tenant_users/excel/clues),改为 app.v_*?这是真 bug,生产环境必坏,目前被 try/except 静默吞
  • 是否同意 P0 治理 B:JWT aud 标准化(jwt.py 加 aud,decode 加 audience 校验)?需后端+小程序+admin-web 三端协同发版。
  • 是否同意 P0 治理 C:删除 apps/backend/tests/tests/_archived/、合并 tests/tests/ 嵌套?

决策 D2(随 Wave 协同)

  • Wave 1 P0-5 选项 B 实施时,是否一并把 _fdw_context(None, ...) 改为强制传 conn?(避免 business_date 降级)
  • Wave 2:task_generator 写 ETL 关系指数表 → 改为"ETL 主动消费 biz 信号"还是保留 get_etl_write_connection?后者需在 R1 中明确"例外清单"。

决策 D3(长期治理)

  • DWS 双 schema 30+ 视图历史补齐 → 何时启动?(估计需要 1-2 个工作日)
  • 是否增加 .claude/hooks/pre_commit_engineering_consistency.py 提交期阻断?
  • 周期性体检报告 → 接入 /audit 还是独立 weekly?

决策 D4(规范文字修订)

  • R1 在 apps/backend/CLAUDE.md 是否改写为"H2 后规范"(直连 ETL + RLS,弃用 fdw_etl.*)?
  • R2 是否在 feiqiu CLAUDE.md 增"零值判定例外清单"?
  • R6 是否增"SSE 流式直连例外"?

附录 A · 调研覆盖范围与方法

维度 覆盖工具 命中数
FDW / 跨库 grep get_etl_*_connectionfdw_etl\._fdw_context 19 文件
响应包装 grep JSONResponse / response_class / StreamingResponse 2 文件(SSE 合理)
JWT aud grep audience= / aud['"] / verify_token 4 文件
AI 调用 grep DashScopeClient( / dashscope. 4 直调点
RLS 双 schema grep `^CREATE.*VIEW (dws app).`
consume_money grep 9 处
配置硬编码 grep localhost / 127.0.0.1 / https?:// 18 行
测试连库 grep PG_DSN / APP_DB_DSN / TEST_*_DSN 1 单测违规
命名混用 grep 小程序 member_id / memberId / userId 20 文件
审计/归档 ls 子模块 docs/audit、_archived/ 3 处嵌套违规
demo-miniprogram git log 30 天 4 commits

未覆盖维度(后续补):

  • shared 包重复定义检查(R13)
  • xcx_* 路由是否全部走 CamelModel(R9 深度抽样)
  • ETL DWD 12 条强制规则(feiqiu CLAUDE.md)逐项审计

附录 B · 与既有反馈交叉引用

本文偏离 关联反馈 关联文件
偏离 1 P0-5 反馈主体 04a-feedback/P0-5-matching-evolution.md
偏离 11 (新发现 / 未在 P0/P1 列表)
偏离 19/20 P1-9 散落 memberId 04b-feedback/P1-12-scattered-memberid.md
偏离 4-7 (新发现 / 高危)
偏离 10 已知"DWS RLS 双 schema 踩坑"(memory 2026-03-29) MEMORY.md

(全文 ~570 行)