Files
Alfred/docs/development/README.md

264 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发规范
AI 工具必须严格遵守以下全部约束。
## 专题文档
| 文档 | 内容 |
| ---------------------------------- | ---------------------------------- |
| [architecture.md](architecture.md) | 项目结构、启动流程、前后端边界 |
| [backend.md](backend.md) | 模块 API、数据访问函数、AI 层说明 |
| [frontend.md](frontend.md) | 组件索引、页面组成、hooks/工具清单 |
| [release.md](release.md) | 开发服务、构建、脚本、环境变量 |
---
## 一、全局规则
### 语言与环境
- 使用中文编写注释、文档和交流内容。
- 仅使用 bun 作为包管理器和 bunx 作为工具运行器;禁止 npm、pnpm、yarn、npx、pnpx。
- 无需考虑向前兼容。
### 依赖引入
**后端**优先级(上层已有方案则不得引入新依赖):
1. Bun 内置 APIBun.serve、bun:sqlite 等)
2. es-toolkit
3. 标准 Web APIfetch、Headers 等)
4. 已批准三方库pino、@sinclair/typebox、ajv、drizzle-orm、ai、@ai-sdk/\*
5. 自行实现(仅以上都不满足时)
**前端**:优先复用已有组件/hooks/依赖库;确需新增依赖时先说明原因。
**Zod**AI 工具层(`src/server/ai/tools/`)使用 Zod 定义 `tool()``inputSchema`,以满足 AI SDK 对 `ZodSchema` 的类型推断要求,属于框架级约束而非项目选型冲突。配置校验层使用 TypeBox + Ajv两层级各司其职不混用。
### 目录边界
| 目录 | 约束 |
| ------------------------ | -------------------------------------------- |
| `src/server/` | 后端,禁止 import src/web/ |
| `src/server/db/` | 数据库层schema、connection、migration、DAO |
| `src/server/ai/` | AI Provider Registry + Agent + 工具 |
| `src/server/config/` | 配置子系统types、variables、issues、schema |
| `src/server/helpers/` | 跨路由工具响应格式化、URL 拼接 |
| `src/server/middleware/` | 参数校验 + 错误处理中间件 |
| `src/web/` | 前端,禁止 import src/server/ 运行时实现 |
| `src/web/consoles/` | 控制台外壳Admin / Workbench |
| `src/shared/` | 前后端共享类型api.ts和常量app.ts |
| `scripts/` | 独立脚本,可 import 项目源码 |
| `drizzle/` | SQL migration 文件(开发期产出) |
| `tests/` | 测试目录,镜像 src/ 结构 |
### 类型与配置
- 共享类型唯一源头:`src/shared/api.ts`;应用常量唯一源头:`src/shared/app.ts`;版本号唯一源头:`package.json`
- 配置加载流程unknown → AuthoringConfig → NormalizedConfig → ValidatedConfig → ResolvedConfig。
- 配置系统入口:`src/server/config.ts`(统一配置加载、运行时校验、默认值解析)。
- Ajv 严格拒绝模式:不类型转换、不注入默认值、不删除未知字段。
- 新增/修改配置字段必须同步更新 TypeBox schema、`config.schema.json`、测试和用户文档。
### 后端日志
- 运行时代码通过 Logger 接口输出,禁止 `console.*`(仅 `logger.ts` 实现类内部可用)。
- 敏感字段authorization、cookie、password 等)自动 redact。
### API 路由
- 每个端点一个文件:`src/server/routes/{资源}/{操作}.ts`
- 路由在 `server.ts``Bun.serve({ routes })` 中声明式注册。
- 新增路由:创建 handler → 在 `server.ts` 注册 → 在 `tests/server/` 添加测试。
### 前端数据层
- 统一使用 `fetch`,不引入 axios。
- 错误抛异常TanStack Query error 状态承接。
- 返回类型必须匹配后端 JSON 形状;包装对象(如 `{ project }`)须在 hook 内提取业务对象。
- 服务端状态用 TanStack Query组件内状态用 `useState`,不引入额外状态管理库。
### 禁止事项
- 禁止前端 import `src/server/`
- 禁止后端使用 `console.*`
- 禁止组件内联 `style` 属性
- 禁止 CSS 覆盖 `.ant-*` 内部类名
- 禁止 `!important`
- 禁止硬编码色值(使用 `var(--ant-*)` CSS 变量)
- 禁止路由 handler 直接操作 `bun:sqlite` / Drizzle ORM须通过 DAO 层)
- 禁止跳过或忽略测试
- 禁止在 `Modal onOk` 中直接执行异步提交(用 `Form onFinish`
---
## 二、后端红线
### 路由 handler
- 签名:`(req: Request, db: Database, mode: RuntimeMode, logger?: Logger): Promise<Response>`
- 业务错误:`jsonResponse(createApiError(msg, status), { mode, status })`;未知异常直接 throw`withErrorHandler` 兜底。
- body 解析后立即校验必填字段和类型,失败返回 400。
- ID 参数走 `validateIdParam`,分页参数走 `validatePagination`
- 路由注册:`withErrorHandler` 包裹 + 动态 `await import()` 加载 handler。
### 数据访问层
- handler 通过 `src/server/db/*.ts` 函数操作数据库,禁止直接使用 `bun:sqlite` 或 Drizzle。
- DAO 函数第一个参数接收原始 `Database`,内部 `wrap(db)` 转 Drizzle。
- 返回联合类型:成功 `{ resource: T }`,失败 `{ error: string; status: number }`
- 输入输出类型来自 `src/shared/api.ts`
- 列表查询使用 `paginateQuery()`,不重复实现分页。
- 列名 snake_caseTS 类型 camelCaseDrizzle schema 映射。
### AI 调用层
- Provider 实例:`buildProviderRegistry(db)`,每次从 DB 重建,不缓存。
- Agent 实例:`createAlfredAgent(model)` 工厂。
- SSE 响应:`createAgentUIStreamResponse``onFinish` 持久化完整 parts。
- 工具定义:`src/server/ai/tools/`
### 错误处理
- 业务异常用 `AppError(statusCode)``jsonResponse(createApiError(...))`
- handler 外层 `withErrorHandler` 兜底,不手动 try-catch 整个 handler。
- 生产模式错误响应不暴露内部细节。
---
## 三、前端红线
### 组件规范
- 优先 antd 默认能力 + props不额外改写视觉。
- `ConfigProvider(zhCN)` 配置中文 locale 和主题,不在 CSS 硬编码亮/暗分支。
- 应用级能力message、modal、notification通过 `AntApp` + `App.useApp()` 获取。
- 页面保持编排职责,组合 hooks + 展示组件;复杂页面按功能边界拆分。
### 能力优先级(上层满足则不用下层)
1. antd 组件/props
2. antd 布局组件Layout、Space、Flex
3. antd theme token + CSS 变量
4. TanStack Query + useState
5. 已有 hooks`use-*.ts`)和工具函数(`utils/`
6. CSS Modules就近放置
7. 引入新依赖(需说明原因)
### 样式红线
- 严禁内联 `style`、覆盖 `.ant-*``!important`、硬编码色值。
- 颜色使用 `var(--ant-*)` CSS 变量。
- 不引入 Tailwind/Sass/Less/CSS-in-JS 等额外样式方案。
- 全局 CSS 类名用 `app-*` 前缀,禁止泛名。样式增长后用 CSS Modules 就近维护。
### 表单与交互
- Modal + Form`Form onFinish` 处理提交,`Modal onOk` 只调 `form.submit()`
- 必填文本字段同时配 `required` + `whitespace`
- 操作确认用 `Popconfirm`,反馈用 antd message。
### 错误边界
- 生产入口必须启用 `ErrorBoundary``ReactQueryDevtools``DEV` 模式渲染。
---
## 四、测试规范
### 后端
- 路由测试通过真实 `startServer` 覆盖路由注册、HTTP method、fallback、header 和核心错误路径。
- SQLite 测试复用 `tests/helpers.ts`,不分散实现临时目录清理。
- DAO/路由测试优先用真实 migration 初始化。
- logger/bootstrap fallback 输出须捕获断言,正常测试不污染 stdout/stderr。
### 前端
- 目录 `tests/web/`,结构对应 `src/web/`
- 用 jsdom + `@testing-library/react` 测试用户行为,断言基于可见文本/role/按钮。
- 系统边界复用 `tests/web/test-utils.tsx`
- 数据页面覆盖:请求参数、成功可见结果、关键错误路径。
- ErrorBoundary/hooks/fetch helper 用单元测试覆盖异常,页面测试只保留用户路径。
---
## 常用命令
| 命令 | 说明 |
| -------------------------------- | -------------------------------------- |
| `bun run dev config.yaml` | 启动双进程开发环境 |
| `bun run dev:server config.yaml` | 仅后端 API server |
| `bun run dev:web` | 仅 Vite dev server |
| `bun run check` | schema:check + typecheck + lint + test |
| `bun run verify` | check + build 完整验证 |
| `bun run build` | 构建生产可执行文件 |
| `bun run schema` | 生成 config.schema.json |
| `bun run schema:check` | 检查 schema 同步 |
| `bun run typecheck` | TypeScript 类型检查 |
| `bun run lint` | ESLint + Prettier 检查 |
| `bun run format` | Prettier 格式化 |
| `bun test` | 运行全部测试 |
| `bun run clean` | 清理构建缓存 |
| `bun run version:patch` | 升迁 patch 版本 |
| `bun run version:minor` | 升迁 minor 版本 |
| `bun run version:major` | 升迁 major 版本 |
| `bun run version:set` | 显式设置版本号 |
## 质量门禁
| 变更类型 | 必跑命令 |
| ----------------------- | --------------------------------------------------------- |
| 常规代码变更 | `bun run check` |
| 构建、部署、集成变更 | `bun run verify` |
| 配置 schema 变化 | `bun run schema``bun run schema:check``bun run check` |
| SQLite 测试基础设施变化 | 相关测试 + SQLite 聚焦 `--rerun-each` + `bun run check` |
| 仅文档变更 | 检查链接、索引和文档归属一致性 |
正式提交优先运行 `bun run verify`。无法执行时须在收尾说明中记录。
## 已知设计决策
| 决策 | 原因 |
| -------------------------- | ----------------------------------------------------------------------------------------- |
| Provider.apiKey 返回给前端 | 个人项目apiKey 非严格密码,前端需要展示和编辑。如需保护,应改为返回脱敏值或仅后端存储。 |
## 文档影响分析
| 变更影响 | 更新 |
| -------------------------------------- | ------------------------------------------ |
| 用户可见行为、配置、部署、运行行为 | `docs/user/` 对应文档 |
| 开发流程、架构、测试、构建发布流程 | `docs/development/` 对应文档 |
| 项目定位、快速开始、核心能力、文档导航 | `README.md` |
| 文档同步规则或归属矩阵 | `docs/README.md``openspec/config.yaml` |
| 开发规范变化 | 本文档对应章节 |
无需更新文档时,须在收尾说明中说明原因。
## 更新触发条件
修改常用命令、质量门禁、开发规范(任何章节)、目录边界或开发文档索引时,必须更新本文档。
### 文档编撰规范
本节开发文档面向 AI 工具阅读,编撰时遵循以下原则:
**精简原则**
- 删除引导语、适用场景、过渡句等装饰性文字。AI 无需"应首先阅读"或"本文档说明…"类引导。
- 不重复项目结构树AI 可通过 glob 获取目录结构。
- 不重复已在 README.md 声明的规范细节专题文档只记录实现层面的函数签名、API 端点、模块职责等索引信息。
- 表格标题自明时不再加说明段落。
**信息完整性**
- 所有函数签名、API 端点(方法+路径+说明)、数据访问函数清单必须完整列举,不可用"等"省略。
- 页面行为描述须包含关键交互逻辑(如 Tab 切换、默认值、条件跳转、测试不阻止保存等),不可只写组件名。
- 配置文件列表必须完整,不可遗漏已有文件。
**结构规范**
- 每个专题文档末尾保留 `## 更新触发条件` 章节,明确列出哪些变更必须更新该文档。
- 用表格和编号列表替代散文段落,减少 token 消耗。
- 同一信息只在一处维护,避免多处重复导致不一致。