topfans/CLAUDE.md
Lenticular Studio Agent 65ce6bba12 feat: Dify 部署脚本修复 + AI 搭子 MVP 接入
主要改动:

fix(docker/dify-deploy): 修复脚本核心功能
- heredoc 单引号 bug: 'ENVEOF' 改为 ENVEOF,变量正确展开
- 端口默认值 8083/8084/8085 对齐 .env.prod 生产配置
- 加 dc_cmd() 兼容 docker-compose v1/v2 plugin
- openssl rand 生成强随机密码与 SECRET_KEY(42 字符)
- install 跳过已存在 .env,保护用户配置(管理员密码/SECRET_KEY)
- read -p < /dev/tty 兼容非 tty 环境(CI/CD)
- show-config 改用 DIFY_NGINX_PORT(nginx 入口)而非 APP_WEB_PORT

docs(mvp-design): 修正 §3.2 workflow inputs 描述
- 实际只有 query,删除错误的 user_id input 声明
- 节点序列图同步更新

feat(aiChatService): 新增 Dify 客户端与适配器
- service/dify_client.go: Dify Workflow 调用 + SSE 解析
- service/dify_adapter.go: 与现有 chat_service 桥接
- provider/ai_chat_provider.go: Dubbo 入口简化
- main.go: 装配 ConversationRepository + DifyClient

feat(migrations): 新增 AI 搭子会话表 ai_chat.sql
- ai_conversations / ai_messages 表 + 索引

docs: 新增 Dify 集成设计文档
- 2026-06-29-ai-chat-dify-mvp-design.md (MVP 实施级)
- 2026-06-29-ai-chat-dify-integration-v2-design.md (V2 演进路线图)
- docs/dify/角角.yml (Workflow DSL 导出)

config: 更新 env 模板与 docker 配置
- backend/.env.example: DIFY_* 环境变量声明
- docker/.env.prod: DIFY_API_BASE 对齐 8083
- docker/build.sh: 微调
- CLAUDE.md: 项目规范补充

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-02 12:32:34 +08:00

21 KiB
Raw Permalink Blame History

MCP Tools: code-review-graph

IMPORTANT: This project has a knowledge graph. ALWAYS use the code-review-graph MCP tools BEFORE using Grep/Glob/Read to explore the codebase. The graph is faster, cheaper (fewer tokens), and gives you structural context (callers, dependents, test coverage) that file scanning cannot.

When to use graph tools FIRST

  • Exploring code: semantic_search_nodes or query_graph instead of Grep
  • Understanding impact: get_impact_radius instead of manually tracing imports
  • Code review: detect_changes + get_review_context instead of reading entire files
  • Finding relationships: query_graph with callers_of/callees_of/imports_of/tests_for
  • Architecture questions: get_architecture_overview + list_communities

Fall back to Grep/Glob/Read only when the graph doesn't cover what you need.

Key Tools

Tool Use when
detect_changes Reviewing code changes — gives risk-scored analysis
get_review_context Need source snippets for review — token-efficient
get_impact_radius Understanding blast radius of a change
get_affected_flows Finding which execution paths are impacted
query_graph Tracing callers, callees, imports, tests, dependencies
semantic_search_nodes Finding functions/classes by name or keyword
get_architecture_overview Understanding high-level codebase structure
refactor_tool Planning renames, finding dead code

Workflow

  1. The graph auto-updates on file changes (via hooks).
  2. Use detect_changes for code review.
  3. Use get_affected_flows to understand impact.
  4. Use query_graph pattern="tests_for" to check coverage.

数据库操作规范

PostgreSQL 序列同步规则(强制)

问题背景:项目使用 BIGSERIAL / autoIncrement 自增主键。当通过 SQL 手动 INSERT 指定 id 值时PostgreSQL 序列不会自动跟进,导致后续 GORM 插入报 duplicate key value violates unique constraint

触发场景

  • 测试数据脚本(如 create_gallery_test_users.go)硬编码 ID
  • 数据迁移脚本手动插入记录
  • DBeaver / psql 手动补数据

规范要求

  1. 任何手动指定 ID 的 INSERT 语句,末尾必须同步重置序列

    -- 错误示例(会导致序列不同步)
    INSERT INTO assets (id, name, ...) VALUES (1000, 'xxx', ...);
    
    -- 正确示例
    INSERT INTO assets (id, name, ...) VALUES (1000, 'xxx', ...);
    SELECT setval('assets_id_seq', (SELECT MAX(id) FROM assets));
    
  2. 脚本文件规范:所有输出 SQL 的 Go 脚本(如 backend/scripts/*.go),必须在生成的 SQL 末尾包含序列重置语句:

    fmt.Printf(`SELECT setval('%s_id_seq', (SELECT MAX(id) FROM %s));\n`, tableName, tableName)
    
  3. 新表创建时:预留足够的序列起始值给测试数据:

    CREATE SEQUENCE assets_id_seq START WITH 10000;
    
  4. 定期检查:环境部署后执行以下 SQL 确认序列健康:

    SELECT 
        schemaname, sequencename, last_value,
        (SELECT MAX(id) FROM assets) AS table_max_id,
        last_value >= (SELECT MAX(id) FROM assets) AS is_healthy
    FROM pg_sequences
    WHERE sequencename = 'assets_id_seq';
    

受影响表(使用 autoIncrement 主键):

  • assets
  • asset_registry
  • users
  • stars
  • activity_assets
  • collection_assets
  • materials
  • exhibitions
  • galleries
  • 以及其他所有 id BIGSERIAL PRIMARY KEY 的表

违规后果:生产环境报 duplicate key 导致用户铸造/创建失败,需紧急修复序列。


前端开发规范uniapp + vue3 · app 端)

技术栈基线

  • 框架UniApp 3.x + Vue 3 组合式 APIvueVersion: "3"@vue/compiler-sfc ^3.5),不要再写 Vue 2 Options API 或混用 this
  • 状态管理Vuex 4store/index.js + store/modules/*),跨页面状态走 Vuex组件临时状态用 ref / reactive
  • 复用逻辑:放进 composables/useXxx.js(已有 useHolographicPreview / useDashboardData / useLenticularStudioTilt 等),禁止把可复用的逻辑写在单文件组件里
  • 目标平台:以 app-plusAndroid + iOS为主H5 / 微信小程序等其他端仅在显式 #ifdef 支持时才能用
  • 原生能力plus.*陀螺仪、角标、Intent 跳转等、UniPush、设备指纹、Socket 全都走 utils/ 下专用封装,不要在组件里直接 plus.*

关键约定

  1. 条件编译是硬约束——涉及原生 API / 原生插件 / 平台差异代码必须包在 // #ifdef APP-PLUS … // #endif(或 MP-WEIXIN / H5 等):

    // 正确
    // #ifdef APP-PLUS
    plus.runtime.setBadgeNumber(0)
    // #endif
    
    // 错误plus 在非 app 端是 undefined会直接报错
    plus.runtime.setBadgeNumber(0)
    

    禁止if (typeof plus !== 'undefined') 之类兜底代替条件编译。

  2. API 调用统一封装——所有后端接口走 utils/api.js设备注册、WebSocket token 上报等),组件层只调封装函数,禁止.vue 里直接 uni.request

  3. 路由与页面注册——新页面先在 frontend/pages.json 注册再写 .vue 文件Tab 页面用 uni.switchTab,普通跳转用 navigateTo禁止redirectTo 替代 navigateBack 制造假"返回"。

  4. 权限申请必须给出口——通知 / 相机 / 相册 / 定位等敏感权限,授权失败时必须给"去设置"按钮并调用系统设置页(参照 App.vue#setPermissions 的 Android Intent / iOS app-settings: 范式),禁止静默失败。

  5. 性能基线——长列表使用现有 components/VirtualList.vue,图片用 components/LazyImage.vue;自定义字体已知坑:部分 Android WebView 对部分 .ttf 会报 OTS / cmap 解析失败(如 JDLTYuanTiJian.ttf),新增字体前先在小内存 Android 机上验证。

  6. 资源与产物隔离——unpackage/dist/* 是编译产物,禁止手动修改;图标准备物放在 unpackage/res/icons/,源码改动放 static/

禁止的反模式

  • 在 Vue 3 项目里混用 export default { data() { return {} } } Options API
  • 在非 APP-PLUS 分支直接调 plus.* / 原生插件 API
  • 在组件里直接 uni.request / uni.connectSocket,绕过 utils/api.js
  • 跨页面状态用 props 层层下传 / getApp().globalData 散落——必须走 Vuex
  • 新增页面不写 pages.json 就提交
  • 权限被拒后只 console.warn 不引导用户去开启
  • 手动编辑 unpackage/dist/ 下的任何文件

完成自检(提交前过一遍)

  • 新组件用 <script setup>setup() 组合式 APIthis
  • 所有原生 / 平台差异代码包了 #ifdef
  • 接口调用走 utils/api.js,未在组件里裸写 uni.request
  • 跨页面 / 跨组件状态走 Vuex
  • 新页面已在 pages.json 注册
  • 敏感权限失败有"去设置"出口
  • 长列表 / 大图场景接入了虚拟滚动或懒加载
  • 未改动 unpackage/dist/ 编译产物

Git 提交规范

核心规则AI 不得主动 commit

未经用户明确指示AI 严禁执行 git commit 只有用户在消息中明确说出"帮我 commit"、"提交吧"、"commit 一下"等类似指令时AI 才可以执行 commit 操作。除此之外,任何情况下都不允许 AI 自行提交。

默认允许的 git 操作(只读 / 暂存)

  • git statusgit diffgit loggit show 等只读命令
  • git add <file> 暂存指定文件(仅在用户明确要求时)
  • git commit —— 必须由用户明确触发
  • git push —— 必须由用户明确触发
  • git reset --hardgit push --forcegit checkout . 等破坏性操作 —— 一律禁止

附加规范

  1. commit 前确认:执行 commit 前,先 git statusgit diff --staged 确认暂存区内容与用户预期一致。
  2. commit 粒度:一个 commit 只做一件事,不要把无关修改混在一起。
  3. 默认分支保护:当前在 main / master 时,不要直接修改,先提示用户创建 feature 分支。
  4. commit message:使用 Co-Authored-By: Claude <noreply@anthropic.com> 结尾(仅在 AI 协助生成 commit 时)。
  5. 不要自作主张:即使代码写完、测试通过、用户长时间未回复,也不要主动 commit 等待用户确认。

违规后果:污染提交历史、丢失用户未保存的修改、误推到远端等难以撤销的问题。


自审与回归检查规范

核心规则:修复后必须做整体回归检查

每次自审发现 bug 并完成修复后,必须对改动范围及周边逻辑做一次整体回归检查,防止"修复 A 引入 B"的情况。

检查流程

  1. 第一遍:定位并修复问题

    • 找到自审发现的问题点
    • 实施修复
  2. 第二遍:修复后整体回归(强制)

    • 改动文件本身:确认修复没有破坏原有功能
    • 直接调用方 / 被调用方:通过 query_graph pattern="callers_of" / callees_of" 确认上下游不受影响
    • 相邻模块:同 package、同目录的相关文件需要扫一遍
    • 测试用例:如果项目有测试,跑一遍相关测试
    • 依赖配置:如果修改了 model/migration/route 等配置,确认下游消费方同步更新
  3. 第三遍:交叉影响检查

    • 多个 bug 一起修时,要检查修复之间是否有冲突
    • 公共函数 / 共享状态被多个修复点改动时,特别注意副作用

检查清单(自审模板)

修复完一个 bug 后,逐项过一遍:

  • 修复是否解决了原始问题(不是新引入的问题)
  • 修改的函数/方法的所有调用方是否仍能正常工作
  • 相关单元测试是否通过 / 是否需要补充新用例
  • 是否有条件分支if/else、switch只改了其中一支
  • 错误处理 / 边界条件空值、nil、超长、并发是否被新逻辑覆盖
  • 数据库 / API 字段变更是否同步更新了所有使用方
  • 日志、错误信息、文档是否需要同步更新

违规后果

  • 一次修复引入新 bug调试时间翻倍
  • 用户对代码质量失去信任
  • 提交历史变成"反复横跳"的打补丁记录

★ 全局自审规则(强约束)

自审必须是"全局审查",不能只读"我修改的部分"

错误做法(局部自审,已多次踩坑)

  • 只读修改过的章节,找修改自身的 bug
  • 跳过未修改的章节,认为"我没动过所以没问题"
  • 只检查修复后的代码,不检查修复是否破坏了其他章节的引用

正确做法(全局自审,强制执行)

每次自审必须从文档第一节读到最后一节,按以下步骤:

  1. 章节通读清单先列出文档所有章节§1 到 §16逐一阅读
  2. 跨章节引用一致性检查
    • §1.x 描述的事实 → 在 §5.x 实现了吗?
    • §3 Dify 配置 → §5 后端是否一致?
    • §10 目录 → §5 代码是否齐全?
    • §11 部署 → §5 装配是否对齐?
  3. 代码示例完整性
    • Go import 块是否齐全time/strings/redis 等常用包)
    • 函数签名与调用点参数个数一致
    • struct 字段与构造方法一致
  4. 章节编号一致性§3.4 与 §3.5 不重复§11.x 编号无错位
  5. 架构图 vs 时序图 vs 代码:物理时序、逻辑步骤、代码实现三者交叉验证

失败案例2026-06-29 V2 文档自审 6 轮)

  • 第 1-4 轮自审漏发现的问题DifyProvider 用 p.httpClient/p.redisClient/p.convRepo,新设计应该用组件抽象,但旧代码没改干净
  • Workflow 双 mappingV1 设计 bugBackend 维护 star_dataset_mapping + Workflow 维护 STAR_DATASET_MAP6 轮自审都没看到,是架构评审指出的
  • §11 部署章节持续出现角色分工错位、循环引用

根因:我之前的"自审"本质上是"局部自审",只看我改的部分。

自审触发时机

  • 写完设计方案文档后
  • 完成一轮"修复 X 个 bug"后
  • 实施编码 go build 前(最后一次文档校对)

自审报告必须包含

  1. 修改的章节:列出本次修了哪些章节
  2. 未改动的章节:列出本次没动但通读了哪些章节(防止"我没看"的盲区)
  3. 跨章节引用一致性:列出所有发现的不一致
  4. Go 编译验证:列出所有需要 go build 才能发现的潜在问题
  5. 优先级P0/P1/P2 分类

文档维护规则(设计方案类)

设计方案文档必须包含的开头部分

任何设计方案文档(如 docs/specs/*.md必须在文档开头包含:

  1. 方案概述必读

    • 要解决的问题:业务问题 + 技术问题(分类列出)
    • 整体实现路径:阶段划分 + 时间估算
    • 关键决策:核心设计选择的简要说明 + 指向详细章节
    • 核心架构图TL;DR一图说明整体结构
  2. 文档说明

    • 适用范围
    • 工作量估算
    • 前置版本/历史
    • 目标读者

目的:让读者5 分钟内能判断这个文档"是不是我需要的" + "大概什么内容"。

★ MVP 先行原则(业务驱动,不是架构驱动)

核心原则MVP 阶段不实施"为未来 100 明星 + 多 AI 平台"准备的架构

错误做法(已踩坑)

  • 业务第一阶段只有 1 个明星,但设计文档规划了 Provider 抽象、ProviderFactory、ConversationStore 抽象
  • 结果MVP 阶段写了 1500-2000 行抽象代码,80% 用不上
  • 后果:实施周期 4-5 周(应该 1 周),新人接手困难,运营被复杂架构拖慢

正确做法

  • MVP 设计原则MVP 文档只描述当前业务需要的实现
  • Stage 1: 1 个明星 + 1 个 Dify Workflow + 直接调 DifyClient没有 Provider 抽象
  • Stage 2-5: 业务复杂度上来后,按业务驱动逐步加抽象

设计文档结构(双文档体系

文档 用途 实施阶段
MVP 设计(如 *-mvp-design.md MVP 实施级方案1 周可落地 MVP 阶段
完整架构(如 *-v2-design.md 100 明星 + 多 AI 平台完整设计 Stage 2+ 参考

两个文档的关系

  • MVP 文档开头要明确"★ MVP 优先"提示
  • 完整架构文档开头要明确"⚠️ MVP 不实施,仅路线图"
  • 完整架构文档的 §10"后续优化"映射到 MVP 的 Stage 1-5 演进路径

判断要不要做架构的设计问题

问题 答案
"MVP 只有 1 个 Provider需要 AIProvider interface 吗?" 不需要YAGNI
"MVP 只有 1 个 Dataset需要 star_dataset_mapping 吗?" 不需要(写死)
"MVP 流量小,需要 RedisLock 防并发吗?" 不需要(单实例部署)
"MVP 不会换 Dify需要 MiniMax fallback 吗?" 不需要(错了就报错)
"MVP 想要对话跨天续接,需要 PostgreSQL 持久化吗?" 需要(追星场景长生命周期)
"MVP 想要拒答敏感词,需要 AuditService 吗?" 需要V1 已有)

反面案例2026-06-29

  • V2 文档设计了 Provider 抽象、ProviderFactory、ConversationStore 抽象、DatasetResolver、WorkflowClient/HistoryClient 拆分、AIProfile 等
  • 实际 MVP 只需要JWT + ConversationRepository + DifyClient + StreamChat + 后置审核 + 保存消息
  • 5 倍的复杂度,0 业务价值

设计方案文档的自审清单

每次完成/大改设计方案文档,必须做以下自审(除了上面"全局自审"通用规则外):

  • 文档开头是否有"方案概述"
  • "方案概述"是否包含:要解决的问题、实现路径、关键决策、核心架构图?
  • 是否违反 MVP 先行原则?(设计的抽象/复杂度是否超过当前业务需要)
  • 实现路径是否给了明确的时间估算和里程碑?
  • 关键决策是否能通过超链接定位到详细章节?
  • 核心架构图是否覆盖了所有关键组件?
  • 完整架构文档开头是否标注"MVP 不实施,仅路线图"

设计方案修改的同步原则

修改设计文档时,必须同时检查

  1. 未改章节的引用一致性(用 grep 查找旧字段名)
  2. 目录列表与实际文件§10 改了§11 也要同步)
  3. 代码示例的语法Go/Rust/Python 等)
  4. 章节编号(插入新章节后,后续编号是否需要顺延)

文档维护的"传染性"提醒

修改一个章节会"传染"其他章节

修改 A 章节 必须同步检查的章节
§3 Dify 配置 §5 后端 + §11 部署 + §10 目录
§5 代码 §6 时序图 + §11 main.go 装配 + §10 目录
§10 目录 §11 部署任务清单 + §5 文件名引用
§11 部署 §5 装配代码 + §10 文件列表
§1 关键决策 §14 对比表 + §3.3 实施
新增强大架构 是否违反 MVP 先行原则?是否需要拆为 MVP + 演进双文档?

本地规则说明

这些规则是 Claude 在本仓库工作时必须遵守的本地约定

  • 不提交到 git除非用户明确指示
  • 用户每次会话可能重复触发这些规则
  • 修改 CLAUDE.md 内容需用户明确同意
  • 规则优先级:用户消息 > CLAUDE.md > memory/ > 默认行为


接口开发规范

核心规则:添加/修改接口必须使用工程化方式完成

每次新增或修改 API 接口时,必须以工程化、标准化方式完成,禁止"能跑就行"的临时拼凑。完成后必须能直接通过代码审查,不需要大改。

工程化要求清单

  1. 分层架构(强制):

    • handler(控制器):接收请求、参数绑定与校验、调用 service、组装响应
    • service(业务层):业务逻辑编排、事务控制、调用 repository
    • repository / dao(数据层):纯数据库操作,不含业务逻辑
    • handler 中禁止直接调用 repository / 直接写 SQL
    • service 中禁止直接操作 HTTP 请求/响应对象
  2. 请求/响应 DTO

    • 入参和出参使用独立的结构体(XxxRequest / XxxResponse
    • 禁止直接用 DB model 当作入参或返回值
    • 字段命名遵循项目既有规范snake_case / camelCase
    • 敏感字段密码、手机号、token在响应中必须脱敏或排除
  3. 参数校验

    • 使用 binding / validate tag 在 handler 层做必填、长度、格式、枚举校验
    • 业务规则校验放在 service 层
    • 校验失败的错误信息要明确指出哪个字段、什么问题
  4. 错误处理

    • 使用项目统一的错误码/错误类型(如 ErrCodeXxx
    • 禁止把原始 error 直接返回给前端
    • 禁止_ 吞掉错误
    • 关键业务错误必须打 ERROR 级别日志(含 trace_id / request_id
  5. 日志规范

    • 接口入口:记录 method、path、request_id、用户身份脱敏
    • 业务关键节点:状态流转、跨服务调用、缓存命中/未命中
    • 异常退出:必须记录 stack trace 或 error cause
  6. API 文档

    • 同步更新 Swagger / OpenAPI 注释
    • 包含:接口描述、请求参数、响应示例、错误码列表、权限要求
    • 字段类型、是否必填、示例值都要写清楚
  7. 数据库变更

    • 表结构变更必须写 migration
    • 索引、外键、唯一约束、默认值要显式声明
    • 影响现有数据的变更要考虑兼容方案默认值、backfill
  8. 缓存策略

    • 是否需要缓存、用什么 key、过期时间、缓存更新/失效策略要明确
    • 禁止缓存与 DB 数据不一致的方案(如只 set 不 delete
  9. 测试

    • service 层核心业务逻辑必须覆盖单元测试
    • handler 层至少一个 happy path + 一个 error case
    • 数据库相关测试考虑使用事务回滚或测试容器
  10. 遵循项目既有约定

    • 命名风格、目录结构、文件命名、错误码定义与项目保持一致
    • 复用项目已有的工具函数、中间件、错误处理逻辑
    • 禁止引入与项目风格冲突的新写法(例如项目用 snake_case 却写 camelCase

禁止的反模式

  • 在 handler 里直接写 SQL / ORM 调用
  • 把 DB model 直接作为 API 入参或返回值
  • 复制粘贴老接口代码不做适配(路径、参数、错误处理不一致)
  • if err != nil { return err } 一把梭,没有业务错误码
  • 缺少或忘记更新 API 文档
  • 改了表结构但没写 migration
  • 没有写测试或测试只覆盖了 happy path
  • 临时引入新的库/框架(未和项目既有技术栈对齐)

完成自检

接口写完后,逐项确认:

  • 分层结构正确handler / service / repository 各司其职)
  • 入参/出参是独立 DTO
  • 参数校验完整(必填、长度、格式、边界)
  • 错误处理统一(错误码 + 友好提示 + 日志)
  • 关键路径有日志
  • Swagger 文档已更新
  • DB 变更已写 migration
  • 相关测试已编写并通过
  • 命名、风格与项目既有代码一致