# 酒库管理系统 — 项目规则与 Orchestrator ## 必读 **开始任何任务前,先读 `docs/context/project.md`** 了解项目全貌。 --- ## Orchestrator:如何自动选择 Agent 根据用户请求的关键词和意图,按以下规则判断调用哪些 Agent: ### 新功能开发(完整流水线) 触发词:「新增」「开发」「实现」「做一个」+ 功能描述 ``` 串行:requirements-analyst → architect 并行:api-designer + db-designer(同时进行,都依赖架构但互不依赖) → ui-designer 判断复杂度: 简单变更:直接输出规范 → 继续下一步 复杂设计:输出 Figma 需求文档 → 暂停等用户确认设计稿 并行:backend-coder + flutter-coder(都依赖 API 设计,互不依赖) 串行:test-engineer → linter → code-reviewer → security-auditor ``` ### 仅后端修改 触发词:「修复后端」「后端接口」「API」+ 具体描述 ``` backend-coder → test-engineer → linter → code-reviewer ``` ### 仅前端修改 触发词:「UI」「界面」「Flutter」「页面」 ``` flutter-coder → linter ``` ### Bug 修复 触发词:「bug」「报错」「修复」「问题」 ``` 1. 先判断 bug 来源(后端/前端/数据库) 2. 调用对应的 coder agent 修复 3. test-engineer 验证修复 ``` ### 安全/代码质量检查 触发词:「安全」「漏洞」「review」「审查」「代码质量」 ``` 并行:security-auditor + code-reviewer + linter ``` ### 线上问题 触发词:「线上」「故障」「宕机」「慢」「报错」 ``` sre(优先级最高,立即响应) → 根据 sre 诊断结果,再决定是否调用 backend-coder 修复 ``` ### 文档需求 触发词:「文档」「说明」「手册」「README」 ``` doc-writer ``` --- ## Agent 边界规则(强制执行) | Agent | 可以写 | 不可以写 | |-------|--------|----------| | requirements-analyst | docs/requirements/ | 任何代码 | | architect | docs/architecture/ | 任何代码 | | api-designer | docs/api/ | 任何代码 | | db-designer | backend/schema/ | 业务代码、测试代码 | | backend-coder | backend/internal/, backend/main.go | *_test.go, schema/ | | ui-designer | docs/design/ | 任何代码 | | flutter-coder | client/ | backend/ | | test-engineer | *_test.go, docs/review/*-bugs.md | 业务代码 | | linter | 格式自动修复(gofmt/dart format),docs/review/lint-report.md | 逻辑代码 | | code-reviewer | docs/review/*-review.md | 任何代码 | | security-auditor | docs/security/ | 任何代码 | | devops | deploy/, .gitea/workflows/, scripts/ci/ | 业务代码 | | sre | docs/runbooks/ | 任何代码 | | doc-writer | docs/(除 context/ 外) | 任何代码 | --- ## Agent 间通信协议 **文件传递**(主要方式): - 每个 Agent 完成后将结果写入约定文件 - 下游 Agent 开始前读取上游产出文件 - 文件格式:混合模式(中文叙述 + YAML/代码块) **短链式调用**(反馈循环): - test-engineer 发现 bug → 直接将错误信息和 `docs/review/{功能}-bugs.md` 路径传给 backend-coder - security-auditor 发现 Critical 问题 → 直接告知 backend-coder 修复,不等下次迭代 --- ## 并行 Agent 调度规则 当多个 Agent 可以并行时,在同一条消息中发起多个 Agent 调用: ``` # 可以并行的情况(互不依赖): - api-designer + db-designer - backend-coder + flutter-coder - security-auditor + code-reviewer + linter # 必须串行的情况(有依赖): - requirements-analyst 完成后 → architect 才能开始 - architect 完成后 → api-designer 和 db-designer 才能并行开始 - backend-coder 完成后 → test-engineer 才能开始 ``` --- ## Git 提交规范 每个 Agent 完成工作后提交,commit message 格式: ``` {类型}({模块}): {简短说明} 类型:feat | fix | test | docs | chore | security | refactor 模块:backend | client | db | deploy | docs 示例: feat(backend): 新增财务报表接口 test(backend): 财务报表模块测试用例 docs(api): 财务报表 API 接口文档 security: 修复入库单多租户隔离漏洞 ``` --- ## 开发完成标准(Definition of Done) **任何功能或修复,必须满足以下全部条件才算完成:** ### 后端变更 ```bash # 1. 编译通过 export PATH="/opt/homebrew/bin:$PATH" cd backend && go build ./... # 2. 所有测试通过(不得有 FAIL) cd backend && go test ./... # 3. 无编译警告(vet 检查) cd backend && go vet ./... ``` ### 前端变更 ```bash # 1. 静态分析无 error(warning/info 允许存在) cd client && flutter analyze --no-fatal-infos --no-fatal-warnings # 2. 所有测试通过 cd client && flutter test ``` ### 通用要求 - [ ] 代码已按 Git 提交规范提交(feat/fix/test/...) - [ ] 涉及新接口:已在对应测试文件中覆盖核心路径 - [ ] 涉及数据库变更:schema.sql 和 model 同步更新 - [ ] 多租户隔离未被破坏(所有查询含 shop_id 条件) **测试未通过前,禁止提交代码、禁止打 tag 发版。** --- ## 代码质量门禁 以下情况**不得提交**: - `go build ./...` 失败 - `go test ./...` 有失败用例 - 存在 security-auditor 标记的 Critical 级别问题 - 存在 code-reviewer 标记的 blocking 级别问题 --- ## 项目强制规则 ### 多租户隔离 - `shop_id` **永远**从 JWT token 中提取,使用 `middleware.GetShopID(c)` - **绝不**从请求参数、URL 或请求体中读取 `shop_id` - 所有数据库查询必须带 `WHERE shop_id = ?` 条件 ### 库存变更 - 入库/出库审核通过时,必须在同一事务中同时完成: 1. 更新 `inventories` 表数量 2. 写入 `inventory_logs` 流水记录 - 出库前必须校验库存充足,不足时返回错误并回滚 ### Schema 管理 - 表结构变更:修改 `backend/schema/schema.sql` + `backend/internal/model/` 对应 model - 启动时自动 AutoMigrate,无单独迁移文件 - **禁止**为每个新业务字段修改表结构,使用 `custom_fields JSON` 动态扩展 ### 种子数据 - 测试数据以 SQL 文件形式维护:`backend/seeds/.sql` - 通过 `sh scripts/dev.sh seed ` 执行(内部用 `docker exec` 注入 MySQL 容器) - 每个门店一个文件,SQL 文件顶部包含 TRUNCATE,每次执行完整重建 ### Go 命令 - 所有 Go 命令前须确保 PATH:`export PATH="/opt/homebrew/bin:$PATH"` - 或直接使用 `sh scripts/dev.sh` 脚本(已内置 PATH) ### 前端 URL 配置 - 所有后端 URL 必须通过 `AppConfig` 读取(`client/lib/core/config/app_config.dart`) - **禁止**在任何 provider / repository / widget 中硬编码 `localhost:8080` 或任何 IP/域名 - 使用:`AppConfig.apiBaseUrl`、`AppConfig.healthUrl`、`AppConfig.versionUrl` ### 前端平台判断 - 使用 `dart:io` 的 `Platform` 类前,必须先检查 `kIsWeb`(`import 'package:flutter/foundation.dart'`) - Web 平台不支持 `dart:io`,直接使用会在 Web 构建时崩溃 ### 表格列头筛选 - 可筛选列使用 `FilterableColumnHeader`(来自 `widgets/multi_select_dropdown.dart`) - 不要在 toolbar 放独立的筛选按钮,筛选入口应内嵌在列头 - 列定义使用 `ColDef`,可隐藏列用 `ColumnToggleButton` 控制 ### 响应式 / 移动端适配 - 断点判定统一用 `context.isMobile`(`client/lib/core/responsive/responsive.dart`,宽度 < 600 为窄屏/手机),**禁止**在各处散落 `MediaQuery.width < 600` 这类魔法数 - **列表屏**:用 `DataTableCard` 时必须同时传 `mobileCards`(窄屏渲染卡片流),卡片复用 `MobileListCard` / `MobileCardField`(`widgets/mobile_list_card.dart`);宽屏仍走原表格,行为不变 - **弹窗固定宽度**:一律用 `context.dialogWidth(X)`(≤ 屏宽 92%),**禁止**裸写 `width: <固定值>` 导致窄屏溢出 - **导航**:窄屏(手机)用 Drawer 抽屉(`app_shell.dart`),宽屏保持侧边栏;新增页面无需单独处理,挂在 shell 下即可 - 平台判断仍遵守上面「前端平台判断」规则(`kIsWeb` 先于 `dart:io`) ### 权限中间件(已全局挂载) - `middleware.ReadOnly()`:已挂载到主 `api` 路由组,只读用户(role=readonly)所有写操作自动返回 403 - `middleware.AdminOnly()`:挂载在 `/users` 路由组,仅管理员可管理用户 - **新增写操作路由**时,默认受 `ReadOnly()` 保护;若仅管理员可用,需加入 `AdminOnly()` 子组 ### 并发安全(数据库操作) - 在同一事务内读后写的操作,必须用 `FOR UPDATE` 锁行: ```go tx.Set("gorm:query_option", "FOR UPDATE").Where(...).First(&model) ``` - 适用场景:单号生成(`number_rules`)、库存扣减(`inventories`)、任何 check-then-act 模式 ### 发版流程 使用 `/release ` slash command: ``` /release 1.0.2 ``` 执行顺序:本地 build → test → 更新 CHANGELOG.md → git commit → tag → push main+tag。 CI/CD(Forgejo,`.gitea/workflows/deploy.yml`)收到 tag 后自动:编译 → 测试 → 创建 Release → 部署 EC2 → Telegram 通知。 **多平台构建矩阵**(脚本在 `scripts/ci/`): - mac runner(容量 1)串行链:`build-linux-web`(后端+Web+官网)→ `build-macos` → `build-android` → `build-ios` → `release-deploy` - windows runner 并行:`build-windows`(Inno Setup 打包 setup.exe) - 分发:桌面(Win/macOS) 发布到下载页 `/downloads/` + 应用内更新;**Android** APK 同样挂 `/downloads/`,需 `ANDROID_*` 签名 secrets(见 `docs/android-signing.md`);**iOS** 走 TestFlight,需 `IOS_*` / `APPSTORE_*` secrets(见 `docs/ios-signing.md`) - Android/iOS 的 job 在对应 secrets 未配置时**优雅跳过**(exit 0,不阻塞发版);本地无 `client/android/key.properties` 时 APK 自动回退 debug 签名 **CHANGELOG 格式**(Keep a Changelog): ```markdown ## [1.0.2] - YYYY-MM-DD ### 新功能 - ... ### 改进 - ... ### 修复 - ... ``` 只保留有内容的分类。`/release` 会检查 CHANGELOG 是否已有该版本节,没有则从 git log 自动生成。 ### 异常上报 客户端异常已在两处统一捕获,**无需**在每个业务层重复处理: - `main.dart`:`FlutterError.onError` + `runZonedGuarded` 捕获所有未处理异常 - `api_client.dart`:Dio 拦截器自动上报所有 HTTP 5xx 错误 需要**手动调用** `reportError(e, st)` 的场景: - 技术性异常(JSON 解析失败、第三方 SDK 崩溃等) - **不需要**上报:`AppException` 及其子类(已知业务错误) ```dart } catch (e, st) { reportError(e, st); // 一行,fire-and-forget rethrow; } ``` ### 项目 TODO 管理 **唯一待办系统**:任务执行过程中如发现需要做的事项,**必须**用 `/todo add <描述>` 记入项目 todo 系统,**禁止**使用 TaskCreate/TodoWrite 等其它 todo 工具,保持单一真相源。 - **真相源**:`todo/todo.json`(结构化 JSON,含 id/标题/重要度/平台标签/创建时间/完成版本) - **HTML**:`todo/todo.html` 为生成物,每次写操作自动重渲染 - **重要度**:`high`(阻断/紧急)/ `mid`(重要)/ `low`(一般/优化)三级 - **改动等级**:`tier 1`(接口/schema/跨 2+ 模块)/ `tier 2`(5+ 文件)/ `tier 3`(小改/bugfix);**一级改动须先进 plan 模式经用户批准,完成后同步更新设计文档**,详见 `/todo` - **状态**:`open`(待开始)→ `doing`(开发中)→ `done`(待验收)→ `accepted`(已验收) - **完成即标记**:开发完成后 `/todo status done`,验收通过后用户运行 `/todo done ` 记入版本 常用命令: ``` /todo — 查看 summary(按状态分组) /todo add 修复... — 新增待办(Claude 自动推断级别/标签) /todo status doing — 标记开发中(Claude 开始处理时调用) /todo status done — 标记待验收(Claude 完成开发时调用) /todo done — 用户验收通过,自动记入版本号 /todo reject <原因> — 用户拒绝验收,退回 open 并升为最高优先级 /todo reopen — 重新开启(清空验收/拒绝记录) /todo rm — 删除 ``` 底层脚本:`node todo/todo.mjs <子命令> [参数]` --- ### 搜索实现(拼音) 商品名搜索同时支持汉字、全拼、首字母: - `products` 表有 `name_pinyin`(全拼)和 `name_initials`(首字母)两列 - Create / Update / FindOrCreate 写入时自动调用 `util.ToPinyin()` 生成,**无需手动维护** - 启动时对 `name_pinyin = ''` 的存量数据自动回填(`backfillPinyin`) - 库存搜索 SQL 同时 LIKE 匹配 name、code、name_pinyin、name_initials - 新增其他需要拼音搜索的实体时,复用 `backend/internal/util/pinyin.go` 的 `ToPinyin()`