reload 卡死三层预防(走查中遭遇 uvicorn graceful shutdown 死等触发): - Layer 1 (apps/backend/start_uvicorn.py 新): 把 reload-excludes 封装在 Python 字符串内,ps1 命令行只有字面路径,根治 PowerShell PSNativeCommandArgumentPassing 在不同 profile 下 wildcard 展开 行为差异(数组 splatting 和 --% 都不稳)。同时显式设 timeout-graceful-shutdown=5,5 秒强杀防死等 - Layer 2 (scripts/ops/backend-watchdog.ps1 新): 自主 socket 探针 (TcpClient + 手写 HTTP/1.1 GET,Connection: close)规避 .NET HttpClient pool 复用 + 系统代理误报;3s × 3 = 9s 触发重启; 进程链 kill 至 pwsh 后端窗口(关闭原窗口);3 次/小时上限自停 - Layer 3 (scripts/ops/start-admin.ps1): 启动时拉起 watchdog, 菜单 [4] 仅重启后端选项,主菜单退出时一并 kill 看门狗 CLAUDE.md: 新增"后端 reload 卡死预防(强制)"章节, 分级文件风险表 + SOP + 启动菜单速查 走查报告(应查尽查严肃版): - 后端 6 个改造点 PASS(P1-P4 + GUC + ai_run_logs runtime 字段) - admin-web 7 页 Playwright 实地走查 → 5 项 UI 不完整登记 F1-5b - 小程序看板 tab 7 页 weixin-devtools-mcp 实地 + DB 数据核对 → board-finance 5/6 项上界裁剪吻合;board-customer 业务日生效; board-coach 月度聚合表设计盲区;5 项 sandbox 覆盖盲区登记 F1-5b - 8 张走查截图归档 docs/audit/changes/screenshots/2026-05-05_f1_5a_walkthrough/ audit_dashboard 刷新到 153 条审计 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
239 lines
14 KiB
Markdown
239 lines
14 KiB
Markdown
# CLAUDE.md
|
||
|
||
本文件为 Claude Code (claude.ai/code) 在本仓库工作时的指导规范。
|
||
|
||
## 语言(强制)
|
||
|
||
始终使用中文,覆盖所有场景:
|
||
|
||
- 对话回复、解释、提问、状态更新 → 中文
|
||
- 代码注释 → 中文
|
||
- Git commit message → 中文描述 + 英文 Co-Authored-By 签名行
|
||
- PR 标题与正文 → 中文
|
||
- 审计记录、文档、变更说明 → 中文
|
||
- 错误提示、日志说明 → 中文
|
||
- 变量名/函数名/类名 → 保持英文(编程惯例)
|
||
- 第三方 API 字段名、CLI 命令 → 保持原文
|
||
|
||
禁止在回复中使用英文段落或英文标题(技术术语、代码片段、专有名词内嵌除外)。
|
||
|
||
## CLI / Shell 中文与编码(强制)
|
||
|
||
- Python:`encoding="utf-8"`;必要时设 `PYTHONUTF8=1`。
|
||
- CSV 给 Excel 打开时用 `utf-8-sig`(带 BOM)。
|
||
- PowerShell / Node / Shell:不依赖系统默认 ANSI 编码;输出中文时优先 UTF-8。
|
||
- 终端中文乱码时**不要把乱码当作事实**:先调编码重跑,或明确说明"终端编码异常,结果需复核",转述可确认的信息。
|
||
- Shell 路径含中文/空格/特殊字符必须正确加引号。
|
||
- 复杂中文输出走脚本或结构化 API(JSON),避免手写脆弱 shell 转义。
|
||
- PowerShell 不支持 Bash 风格 heredoc:复杂中文片段用 here-string 管道传给 Python。
|
||
- Python 文档模板里的 Windows 路径(`C:\Users\...`)注意反斜杠转义,避免 Unicode 转义错误。
|
||
|
||
## 项目概览
|
||
|
||
NeoZQYY Monorepo — 面向台球门店业务的全栈数据平台。多门店隔离(`site_id` + RLS),领域语言中文,货币 CNY,金额 `numeric(2)`。
|
||
|
||
### 子系统
|
||
|
||
| 目录 | 说明 |
|
||
|------|------|
|
||
| `apps/etl/connectors/feiqiu/` | 飞球 Connector:API → ODS → DWD → DWS |
|
||
| `apps/backend/` | FastAPI 后端(JWT 双认证、WebSocket、AI 集成) |
|
||
| `apps/miniprogram/` | 微信小程序(C 端,Donut + TDesign) |
|
||
| `apps/admin-web/` | 系统管理后台(开发/运维视角,操作 ETL 库;ETL 配置 / 数据质量 / 系统监控) |
|
||
| `apps/tenant-admin/` | 租户管理后台(门店管理员 `site_admin`/`tenant_admin`;用户审核 / Excel 上传 / 维客线索,门店隔离视角) |
|
||
| `apps/mcp-server/` | MCP Server(PostgreSQL 只读,AI 工具集成) |
|
||
| `packages/shared/` | 跨项目共享包(enums, money, datetime_utils) |
|
||
| `apps/demo-miniprogram/` | MOCK 小程序(假数据驱动,页面样式/展示格式标杆校对) |
|
||
| `db/` | 权威 DDL(`schemas/`)/ 迁移归档 / FDW 配置 |
|
||
| `tools/` | 通用工具(db/reporting/health/h5-to-mp-checker) |
|
||
| `scripts/ops/` | 日常运维脚本(ETL 监控、数据回填、导出等) |
|
||
|
||
## 技术栈
|
||
|
||
- Python 3.10+,uv workspace(4 成员:etl/connectors/feiqiu、backend、mcp-server、shared)
|
||
- 前端:React + Vite + Ant Design,各应用独立 pnpm
|
||
- PostgreSQL 四库:`etl_feiqiu` / `test_etl_feiqiu`(ETL,六层 Schema)、`zqyy_app` / `test_zqyy_app`(业务)
|
||
- DSN:`PG_DSN`(ETL)、`APP_DB_DSN`(业务),根 `.env` 定义
|
||
- 配置分层:`.env` < `.env.local` < 环境变量 < CLI 参数
|
||
|
||
## 架构模式(顶层)
|
||
|
||
- **数据库六层 Schema**:`meta` → `ods` → `dwd` → `core` → `dws` → `app`(RLS 视图);`zqyy_app` 通过 FDW 只读映射 `etl_feiqiu.app`;多门店通过 `site_id` + `app.current_site_id` 会话变量过滤
|
||
- **RLS 双 Schema 强制规则(踩坑 2026-03-29)**:新建 DWS/DWD 表的 RLS 视图必须**同时**在原 schema(如 `dws`)和 `app` schema 创建。后端走 `app.v_*`。只在 `dws` 创建会让后端查询失败;回滚需逆序 DROP
|
||
- 详细子模块架构(响应包装、JWT、AI 集成、ETL Loader/SCD2/Flow、DDL)见对应 `CLAUDE.md`(自动加载):
|
||
- `apps/backend/CLAUDE.md` — FastAPI 后端
|
||
- `apps/etl/connectors/feiqiu/CLAUDE.md` — 飞球 ETL(含 12 条 DWD 强制规则)
|
||
- `db/CLAUDE.md` — DDL / 迁移 / RLS 双 schema 模板
|
||
|
||
## 文件归属规则
|
||
|
||
| 判断标准 | 放置位置 |
|
||
|----------|----------|
|
||
| 只有本模块开发者需要看的文档 | 模块内 `docs/` |
|
||
| 跨模块对照或全局视角的文档 | 根 `docs/` |
|
||
| 只验证本模块逻辑的测试 | 模块内 `tests/` |
|
||
| 守护 monorepo 结构/约定的测试 | 根 `tests/` |
|
||
| 只操作本模块数据的脚本 | 模块内 `scripts/` |
|
||
| 日常运维脚本(回填/导出/种子/初始化) | `scripts/ops/` |
|
||
| 可复用通用工具(健康检查/数据库/报表/分析) | `tools/`(按类型分子目录) |
|
||
| 审计记录(任何模块的变更) | 根 `docs/audit/` — 禁止写入子模块 |
|
||
| 数据库文档(全局 schema 视角) | 根 `docs/database/` |
|
||
| 归档/待删除内容 | `_DEL/`(保持原路径结构,用户定期手动清理) |
|
||
|
||
审计产物路径:
|
||
- 变更记录:`docs/audit/changes/<YYYY-MM-DD>__<slug>.md`
|
||
- 审计一览表:`docs/audit/audit_dashboard.md`(`scripts/audit/gen_audit_dashboard.py` 自动生成,勿手动编辑)
|
||
|
||
## 飞球数据规范
|
||
|
||
> 完整规则见 `apps/etl/connectors/feiqiu/CLAUDE.md`(进入 ETL 目录时自动加载)。
|
||
|
||
**核心速查**:
|
||
- `consume_money` 禁止直接计算 → 用 `items_sum` 拆分字段
|
||
- 取数优先级:DWS > DWD > 禁止 ODS
|
||
- 参考优先级:DWD-DOC > DWS 权威规范 > BD 手册 > ETL 任务文档 > DDL 注释
|
||
- 所有 `_archived/` 目录禁止读取或参考
|
||
|
||
## 编码前需求审问(强制)
|
||
|
||
新建功能/模块/页面/接口、重构、多模块联动、需求存在模糊或隐含假设时:
|
||
1. 不立即动手,先提问循环(每轮 3-5 个问题)
|
||
2. 必问维度:用户角色、核心操作、完成后果、数据写入/展示/来源、错误/成功反馈、认证权限、存储(哪个库/新表?)、终端适配、边界条件(并发/幂等/超时)
|
||
3. 输出「需求确认摘要」,用户确认后才进入实施
|
||
|
||
例外:用户说"直接改/跳过审问/不用问了"、Bug 修复(有明确复现步骤)、纯格式/文档调整、已有完整 spec
|
||
|
||
## 逻辑改动前置调研(强制)
|
||
|
||
任何逻辑改动(ETL/业务规则/API/数据模型/前端交互),写代码前必须完成调研:
|
||
1. 用 Explore 子代理调研:目标模块文件、`docs/audit/changes/` 历史审计、相关 README/PRD/BD 手册、要修改的文件及其调用方/被调用方、数据流向(上游→当前→下游)、影响范围
|
||
2. 输出「改动前上下文摘要」(模块职责、历史变更、影响范围、风险点),用户确认后开始实施
|
||
|
||
流程:需求审问 → 用户确认 → 前置调研 → 用户确认 → 编码实施
|
||
|
||
例外:纯格式调整、注释/文档纯文字修改、用户说"直接改/跳过调研"、新建文件且不涉及已有逻辑
|
||
|
||
## 改动后验证(强制)
|
||
|
||
逻辑改动完成后,必须执行以下验证步骤:
|
||
1. 运行相关测试(单元/集成/lint),如无法运行需说明原因
|
||
2. 输出 diff 摘要(改了哪些文件、每个文件改动要点)
|
||
3. 列出未覆盖的风险点(未测试的路径、可能的副作用、需要人工验证的场景)
|
||
|
||
例外:纯格式/文档/注释调整、用户说"跳过验证"
|
||
|
||
## 后端 reload 卡死预防(强制)
|
||
|
||
**机制**:`uvicorn --reload` 检测到 .py 修改 → 等 lifespan shutdown → 等 WebSocket / asyncio task / DB 连接释放 → 等不到就死等。已在 `start-admin.ps1` + `backend-watchdog.ps1` 做了三层保护,但写代码时仍需配合。
|
||
|
||
**改 Python 文件按风险分级**:
|
||
|
||
| 风险 | 文件位置示例 | 操作 |
|
||
|---|---|---|
|
||
| 极低 | `app/ai/prompts/*.py` `app/schemas/*.py` 工具/helper | 直接改,reload 自动应用 |
|
||
| 中 | `app/services/*` `app/ai/*`(非 dispatcher) `app/routers/*` | 改前关浏览器(切 WS),改后看终端 "Application startup complete" |
|
||
| 高 | `app/main.py`(lifespan) `app/services/scheduler.py` `task_queue.py` `app/ai/dispatcher.py` 全局单例(`_admin_svc` 等) | 用启动菜单 [4] 仅重启后端,或 taskkill + 双击 bat |
|
||
|
||
**测试 SOP**:
|
||
1. 改 Python 前先 `curl http://127.0.0.1:8000/health` 确认健康
|
||
2. 改完文件等 30 秒,再 `curl /health` 二次确认;若仍 timeout → 选启动菜单 [4]
|
||
3. 看门狗(`backend-watchdog.ps1`)会在连续 30 秒不响应时自动 kill+重启,不需要手动操作
|
||
|
||
**启动菜单(双击 `start-admin.bat`)**:
|
||
- [1] 终止所有服务(含看门狗)
|
||
- [2] 重启所有服务(含看门狗)
|
||
- [3] 退出
|
||
- [4] 仅重启后端(保留前端,推荐:测试时 reload 卡死 / Python 改动)
|
||
|
||
**禁止**:
|
||
- 改 lifespan / dispatcher / 全局单例时不要靠 reload,**手动停后端再启动**
|
||
- 不要在 reload 没完成时连续改 .py 文件(前一次没收完后一次又触发,必卡)
|
||
|
||
## 数据库 Schema 变更规则
|
||
|
||
修改 PostgreSQL schema(迁移/DDL/表/ORM)时**必须**同步 `docs/database/`:变更说明 + 兼容性影响(ETL/后端/小程序)+ 回滚策略 + ≥3 条校验 SQL。详细模板见 `db/CLAUDE.md`。
|
||
|
||
## 测试与验证环境规范
|
||
|
||
1. 必须 `load_dotenv` 加载根 `.env`;必需变量缺失时立即报错,禁止静默回退空字符串
|
||
2. cwd 与正式一致:ETL → `apps/etl/connectors/feiqiu/`;后端 → `apps/backend/`
|
||
3. 配置走 `AppConfig.load()` 正常流程,不得为测试单独构造简化配置
|
||
4. 数据库使用测试库(`TEST_DB_DSN`),禁止连正式库
|
||
5. 属性测试分组执行:每次单个测试函数或 `-k` 筛选,禁止一次性跑全部;hypothesis 默认 `max_examples=100`
|
||
|
||
例外:用户指定简化环境、纯单元测试用 FakeDB/FakeAPI、`--dry-run` CLI 验证
|
||
|
||
## 脚本规范
|
||
|
||
- 复杂操作优先写 Python 脚本,避免复杂 shell 逻辑
|
||
- 一次性运维脚本 → `scripts/ops/`;模块专属 → 模块内 `scripts/`
|
||
- `scripts/ops/` 中的脚本不在 uv workspace 内,导入 ETL 纯函数需用 `importlib.util` + stub 方式(参考 `scripts/ops/backfill_finance_area_daily.py`、`tests/conftest.py`)
|
||
|
||
## 子代理使用原则
|
||
|
||
- 委托子代理:批量文件读取(≥3 个)、大范围搜索、不熟悉的模块探索、多步骤 shell 操作
|
||
- 主流程直接处理:单个已知文件、简单单条命令、小范围精确搜索
|
||
|
||
## 审计
|
||
|
||
任何逻辑改动必须可追溯、可验证、可回滚。
|
||
|
||
完成一轮改动后,使用 `/audit` 命令执行审计。流程:
|
||
1. 运行 `python scripts/audit/prescan.py` 预扫描(自动识别变更文件、分类风险、合规检查,零 token)
|
||
2. 补充语义上下文(从对话记忆中提取每个变更的原因和思路)
|
||
3. 委托子代理写审计记录到 `docs/audit/changes/`
|
||
4. 补齐缺失的文档同步
|
||
5. 运行 `python scripts/audit/gen_audit_dashboard.py` 刷新审计一览表
|
||
|
||
预扫描脚本支持 `--files` 参数:当 git status 包含大量历史未提交变更时,可只传入本次会话涉及的文件列表。
|
||
|
||
## Claude Code 资产入口
|
||
|
||
| 资产 | 位置 |
|
||
|------|------|
|
||
| 项目 slash 命令 | `.claude/commands/*.md`(5 个:`/audit` `/db-docs` `/doc-sync` `/pre-change` `/spec-close`) |
|
||
| 项目 hooks | `.claude/hooks/*.py` + `.claude/settings.json` |
|
||
| 项目设置 | `.claude/settings.json` / `.claude/settings.local.json`(PATH/虚拟环境) |
|
||
| 项目 MCP | `.mcp.json`(**单一权威源**) |
|
||
| 用户级 subagents(8 个) | `~/.claude/agents/`(planner / architect / code-reviewer / security-reviewer / database-reviewer / python-reviewer / tdd-guide / refactor-cleaner) |
|
||
| 用户级 skills | `~/.claude/skills/<name>/SKILL.md` |
|
||
| 用户级 rules(自动加载) | `~/.claude/rules/{python,typescript,web,zh}/` |
|
||
| 自动记忆 | `~/.claude/projects/c--Project-NeoZQYY/memory/` |
|
||
|
||
### 子模块 CLAUDE.md(按需自动加载,避免在根级重复)
|
||
|
||
| 子模块 | CLAUDE.md 内容 |
|
||
|------|------|
|
||
| `apps/backend/` | FastAPI 全局响应包装、CamelModel、JWT 三类 aud、AI 集成、TaskQueue/Scheduler、FDW 访问 |
|
||
| `apps/etl/connectors/feiqiu/` | DWD-DOC 标杆、12 条 DWD 强制规则、DWS 权威规范(幂等/课程定价/绩效/会员分层/调度窗口/指数参数/台桌分类) |
|
||
| `apps/demo-miniprogram/` | MOCK 标杆禁改、UI 校对基准、与 `apps/miniprogram/` 关系 |
|
||
| `db/` | Schema 变更模板、RLS 双 schema 模板、目录结构、DDL 刷新、测试规范 |
|
||
|
||
## Hook 与权限
|
||
|
||
项目已注册的 hooks(见 `.claude/settings.json`):
|
||
|
||
| 时机 | Hook | 行为 |
|
||
|------|------|------|
|
||
| SessionStart | `session_start_context.py` | 注入项目状态摘要 |
|
||
| PreToolUse (Read/Edit/Write/Glob) | `pre_read_archived_block.py` | 强阻断 `_archived/` 目录读取 |
|
||
| PreToolUse (Bash/Edit/Write) | `pre_demo_protect.py` | 提醒 `demo-miniprogram` 保护 |
|
||
| PostToolUse (Edit/Write) | `post_edit_audit_reminder.py` | 提醒审计 |
|
||
| PostToolUse (Edit/Write) | `post_edit_db_doc_sync.py` | 提醒 DB 文档同步 |
|
||
| PostToolUse (Edit/Write) | `post_edit_rls_dual_schema.py` | RLS 双 schema 检查 |
|
||
| Stop | `stop_audit_check.py` / `stop_verify_check.py` | 收尾审计/验证检查 |
|
||
|
||
## 不破坏原则
|
||
|
||
- 不回滚用户已有改动,不使用破坏性 git 命令(`reset --hard` / `push --force` / `checkout .`),除非用户明确要求
|
||
- 不修改 `apps/demo-miniprogram/`(MOCK 标杆,禁改)
|
||
- 不写入 `_archived/` 目录
|
||
- 不在测试库以外执行 DDL / TRUNCATE / DELETE
|
||
|
||
## 历史追溯
|
||
|
||
- 日常追溯先查精简索引:`docs/ai-env-history/README.md`、`docs/audit/changes/`、`docs/audit/audit_dashboard.md`
|
||
- 历史摘要只解释来龙去脉,编码前以**当前文件、当前 diff、当前测试**为准
|
||
- 原始 JSONL 可追查细节,但**不要把密钥、DSN、token 原文写入仓库文档**
|
||
- 迁移路径:旧服务器 → 本机 → Claude Code → Codex → Cursor → **Claude Code(当前)**;详见 `docs/claude_code_migration.md`
|