Files
chenxin 5da1efe921 📝 docs: 统一 PostgreSQL 主库并固化索引命名约定
- 新增 ADR-024:服务端关系主库统一 PostgreSQL,不设 SQLite 档(pgvector 与中文全文无法在 SQLite 承载,双档必然残缺或第二实现);端侧离线缓存不受约束
- AGENTS.md:权威事实源与部署句更新;8.6 固化 pk_/uk_/idx_/fk_ 索引命名约定
- system-architecture、data-architecture、memory-and-knowledge、roadmap WP-01、handoff(决策 29)同步清理 SQLite 引用
2026-09-09 21:14:10 +08:00

264 lines
19 KiB
Markdown
Raw Permalink 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.
# Hunjing 工程规则
> 目标:交付可维护、可验证、可长期负责的完整 1.0。
> 语言:用户可见输出、文档、注释和 Git Commit 使用简体中文;代码标识符和稳定协议值使用英文。
## 1. 事实源与工作方式
### 1.1 开发前阅读
按任务读取对应文档,不凭旧设计或记忆实现:
1. `docs/product/product-charter.md`:产品宪章、不可侵犯边界与永久禁域(上位约束);
2. `docs/product/product-definition.md`:产品定义与 1.0/2.0 边界;
3. `docs/product/complete-1.0-scope.md`:完整 1.0 范围与发布门;
4. `docs/product/cultural-language.md`:文化名、直白解释与工程映射;
5. `docs/architecture/`:系统、Agent、插件、数据、媒体、社区市场和前端渲染架构;
6. `docs/contracts/`:API、ContentBlock、事件、ID、枚举、请求头和错误;
7. `docs/security/security-and-diagnostics.md`:安全和受保护诊断;
8. `docs/delivery/implementation-roadmap.md`:1.0 TODO 与验收证据。
事实层级:产品范围 → ADR → 架构 → 契约/OpenAPI → 实现 → 测试与运行证据。下游不得静默覆盖上游;运行事实与文档不符时先记录偏差,再修正事实源或实现。
### 1.2 需求处理
- 需求明确:完整实现;需求有多种会显著改变产品/API/数据/安全的解释:先列选项并询问。
- 普通命名、格式和等价技术细节由 AI 按既有规则直接决定,不把常规判断推给用户。
- 多步骤任务先列编号流程和验证方式;只有需要用户决策时暂停。
- 不总结或附和错误前提;先指出问题,再给修正方案并继续可执行部分。
- 未请求不做;发现无关问题只报告,不顺手重构。
### 1.3 实施原则
- **最小实现**:在满足完整当前需求和安全边界前提下采用最少代码、依赖和服务。
- **能力必达,技术按需**:1.0 产品能力是硬范围;数据库、语言、服务拆分和库按 ADR、官方资料、实测规模和维护成本选择,不为堆技术栈而部署。
- **优先复用**:标准库 → 平台能力 → 已安装依赖 → 成熟依赖 → 最小自研。新增依赖前查官方文档、版本兼容、许可、维护状态和现有能力。
- **删除废弃路径**:不为未发布实现保留兼容层;正式公共契约按弃用策略演进。
- **模块化单体优先**:服务拆分须有独立扩缩容、故障域、数据/密钥边界、团队节奏或量化瓶颈证据。
- **安全边界不简化**:认证、授权、租户隔离、审批、交易账、幂等、审计、秘密管理、文件/URL 校验和 Sandbox fail-closed 不得省略。
## 2. 完整 1.0 约束
- `docs/delivery/implementation-roadmap.md` 中全部 1.0 TODO 和发布门完成前,不得称为正式 1.0。
- 产品宪章的永久禁域不可被实现、插件、管理员或自托管配置关闭;与宪章冲突的实现决定都是缺陷。
- 内部工作包可以并行开发和验收,但不是独立公开版本。
- 1.0 包含:角色与记忆、分支多模态对话、多 Agent、插件生态、实时语音、多语言、图像、Live2D、3D 运行编辑、Web/Tauri 桌面与移动、设备感知、完整社区、角色社区、协作空间、真实支付退款分成结算、运营和自托管。
- 已确认 2.0:Blender 级完整建模器、LLM 直接修改完整 3D 几何/绑定、IoT/机器人/物理动作控制。不得把其他已列能力静默移出 1.0。
- 文档 TODO 是真实待办;实现中的 `TODO`、`pass`、省略代码、假数据和无调用点定义不算完成。
## 3. 文化语言与工程标识
- 产品使用完整双层文化体系:文化名 + 直白中文解释;首次出现和高风险界面必须显示直白解释。
- API、OpenAPI、数据库、代码目录、事件、错误码、权限 scope、指标和日志只使用 `docs/contracts/` 登记的中性英文稳定值。
- 后端返回 `status: "running"`,前端本地化为“运转 · 运行中”;不得把文化名作为唯一协议值。
- 权限、金额、退款、删除、支付、结算、审核和现实后果不得用文化叙事掩盖。
- 新文化名先更新 `docs/product/cultural-language.md`;新稳定值先更新契约/OpenAPI。
## 4. API 与数据契约
### 4.1 API 分面
- Native:`api.<domain>/v1`;
- OpenAI-compatible:`gateway.<domain>/openai/v1`;
- Anthropic-compatible:`gateway.<domain>/anthropic/v1`;
- Provider Webhook:`api.<domain>/webhooks/v1`;
- Lingtai C ABI:进程内 `hj_*` 稳定符号,契约见 `docs/contracts/lingtai-ffi.md`;Lingtai gRPC Service:独立服务形态,仅限部署内部网络,契约见 `docs/contracts/lingtai-service.md`;两者为同一灵台引擎核心;
- 内部模块优先用类型化 Port/Command/Query/Event,不为每个模块增加 HTTP。
### 4.2 通用格式
- OpenAPI 3.1 是公共 HTTP 契约单一真源;生成 TypeScript/Rust 客户端,不手写重复 DTO。
- JSON/SQL/path 参数使用 `snake_case`;事件使用 `domain.action`;逻辑模型使用 `kebab-case`。
- 时间为 UTC RFC 3339;时长为 `_ms` 非负整数;金额使用最小货币单位或 Decimal,禁止浮点。
- 列表使用 opaque cursor;更新使用 ETag/`If-Match`;客户端忽略未知响应字段和枚举。
- 创建 Run、支付、退款、结算和外部副作用必须使用 `Idempotency-Key`。
- `Hunjing-Request-ID` 用于业务关联,`traceparent` 用于分布式追踪,两者不能互相替代。
- 1.0 认证采用 OAuth 2.1:Web 使用安全 Session Cookie,Tauri 使用 Authorization Code + PKCE,公共客户端使用短期 Bearer,自动化使用限 scope Service Account API key。
- 凭据只经 Header 传递,不进入 URL、query、业务 body、SSE data 或 WebSocket URL。
- Provider Header deny-by-default,仅 Adapter 白名单透传;用户登录凭据、Cookie 和诊断令牌永不转发上游。
### 4.3 消息与 Run
- 聊天通过 `POST /v1/conversations/{id}/messages` 在同一事务创建 Message 和可选 Run;一个幂等键覆盖两者。
- 后台任务通过 `POST /v1/runs` 显式创建。
- Run → Turn → ModelCall/ToolCall 分层;每个上游 attempt 单独记录,不覆盖失败或重试。
- 首个用户可见流事件前可以安全重试/故障转移;之后不得切换 Provider 重新生成另一份内容。
### 4.4 数据
- PostgreSQL 关系数据是权威事实源(ADR-024,不设 SQLite 主库档);对象存储保存媒体;全文、向量、图投影、推荐特征和缓存均可重建。
- 角色、消息、记忆、知识、社区发布、许可、订单、支付和 Ledger 分离建模。
- Ledger 不可变,修正写反向分录;支付 Provider Adapter 不直接写账。
- 删除传播到主存储、索引、缓存和派生数据;墓碑不保存被删原文。
- 权威状态、AuditEvent 和 OutboxEvent 在同一事务提交。
## 5. 统一 ContentBlock 与流式输出
### 5.1 ContentBlock
Native API 和持久化消息统一使用 `docs/contracts/content-blocks-and-streaming.md` 定义的类型化 Block:
- `text`、`markdown`、`code`、`quote`、`table`、`callout`;
- `math`、`mermaid`;
- `image`、`video`、`audio`、`file`、`gallery`、`avatar`;
- `tool_call`、`tool_result`、`agent_status`、`approval_request`、`artifact`、`citation`、`error`。
用户输入可使用 Markdown 内嵌 Mermaid、代码和数学定界符;服务端必须使用确定性 parser 规范化为 canonical ContentBlock,记录 parser version,不把原始 HTML 当可信内容。
### 5.2 流式事件
统一事件:
```text
content.block.started
content.block.delta
content.block.progress
content.block.completed
content.block.failed
content.block.cancelled
message.completed
```
- Event 在 Run 内有单调 `sequence`;Block delta 有单调 `delta_index`。
- 客户端按 event ID 和 `(block_id, delta_index)` 去重;缺口通过重放或最终 Message 对账,不猜顺序。
- Completed Block/Message 是权威快照,临时累积状态必须可丢弃重建。
- SSE 用于 Run/通知;WebSocket 用于实时语音、协同和设备双向会话。
### 5.3 分级实时渲染
- Markdown/text 增量显示并节流解析;未闭合结构保持源码态。
- Code 按行/时间片高亮,不逐 token 执行 Shiki。
- Math 仅在定界符闭合或 Block 完成后渲染;必须有源码/fallback text。
- Mermaid 仅在 Block 完成后以 strict mode 隔离渲染;失败显示源码和错误摘要。
- 图片、视频、音频和文件先显示结构化进度,资源 ready 后加载。
- Tool/Agent/Approval 使用状态替换,不拼接自由文本模拟状态。
### 5.4 前端安全与可访问性
- 禁用 Markdown 原始 HTML;URL/协议/目标域校验;外链 `noopener noreferrer`。
- Mermaid 禁止 click、HTML label、外部脚本和危险初始化;SVG 二次净化。
- KaTeX/MathJax 禁止 trust/宏注入并限制展开;Shiki 只高亮不执行。
- 图片必须有 alt;音视频有字幕/转写;公式有 MathML/fallback;图表有标题、说明和源码替代。
- 流增量不持续抢焦点;错误、审批和费用不能只靠颜色表达。
## 6. 插件、Agent 与安全
- 所有可扩展能力皆插件;认证、授权、数据隔离、审批、交易 Ledger、审计和 Sandbox 内核不可插件化。
- 只有 bundled Core plugin 可进主进程;声明式/远程插件默认受限;可信本地代码插件也进入独立进程或容器。
- Python import、Node `vm` 和 WebView 不是安全隔离。
- 插件 Manifest 声明版本、依赖、数据、网络、设备、费用、外部目的地与现实后果和配置 Schema;升级新增权限必须重新确认。
- Run 固定 PluginSnapshot;活动 Run 不热替换。安全撤架可以阻断新调用,但保留历史审计。
- 子 Agent 的工具、数据、网络、预算和权限是父 Run 的交集子集;不继承审批令牌,默认不能写长期记忆。
- Tool input 是不可信模型输出,必须 Schema 校验、Policy、审批、路径/URL 约束、资源限制和幂等。
- 无符合策略的 Sandbox 时拒绝执行,不静默退化到宿主。
## 7. 社区、协作、设备与交易
- PersonalDomain、Workspace、Community、Marketplace、Finance 和 Diagnostics 使用不同授权策略。
- 社区私信采用服务端治理的一对一/小群聊,不宣传 E2EE;支持举报、屏蔽、审核和多端同步。
- 公开角色 Release 不包含私密记忆、关系、对话、设备授权或密钥。
- Tauri v2 Desktop/iOS/Android 的文件、相机、麦克风、屏幕、位置和通知同时受 OS 权限与 `device_grant` 约束;采集有持续指示并可即时撤回。
- 购买不等于安装插件,安装不等于启用,启用不等于授予新增权限。
- 支付 Webhook 验签、按事件 ID 幂等、允许乱序;客户端金额不可信;退款、分成和结算可对账。
## 8. 语言与框架规范
### 8.1 TypeScript / Next.js
- TypeScript 开启 `strict`;禁止无理由 `any`、非空断言和重复定义 API 类型。
- 使用生成的 OpenAPI 类型;表单边界使用 Zod/React Hook Form;服务端状态使用 TanStack Query。
- React Server Component 默认;只有需要浏览器 API、交互状态或第三方客户端库时使用 `"use client"`。
- 不在 render 中产生副作用;Effect 必须清理订阅、Timer、Worker 和 WebSocket。
- ContentBlock renderer 采用穷尽判别联合;未知类型走兼容占位,不能崩溃。
- 长列表使用虚拟滚动;Markdown/Math/Mermaid/Shiki 高成本处理放 Worker 并按 content hash 缓存。
- 图标统一 Lucide;界面禁止表情符号代替图标、状态或操作。
- 测试:Vitest + Testing Library;核心旅程和跨端行为使用 Playwright。
### 8.2 Python / FastAPI
- Python 3.12+,使用 uv;格式/Lint 用 Ruff,类型检查用 mypy,测试用 pytest/pytest-asyncio。
- FastAPI 边界使用 Pydantic v2;领域对象不依赖 HTTP Request/Response 或 Provider SDK 类型。
- SQLAlchemy 2.0 typed mapping;迁移只用 Alembic;禁止运行时隐式建表修改生产 Schema。
- I/O 使用 async;不得在事件循环执行阻塞模型、文件、媒体或数据库操作。
- Provider、Tool、Storage、Payment 通过明确 Port;异常映射为稳定领域错误,不匹配错误字符串。
- Decimal/整数处理金额;时间统一 aware UTC datetime。
- 模型/工具流必须可取消,资源使用 `async with`/`try-finally` 释放。
### 8.3 Rust / Tauri
- 使用 Tauri v2 和 stable Rust;`cargo fmt`、`cargo clippy -- -D warnings`、`cargo test`。
- Tauri command 输入使用 serde/specta 类型并校验;不暴露通用 Shell 或任意路径命令。
- Capability/permission 最小化,桌面与移动平台分别声明;敏感命令验证用户、设备和 DeviceGrant。
- 路径 canonicalize 后限制在授权根目录;秘密使用系统 Keychain/Keystore,不写普通配置或日志。
- `unsafe` 仅在无安全替代时使用,封装最小并写明不变量和测试。
- Tokio 任务支持取消和超时;不要持锁跨 `await`。
- 共享 TypeScript 类型由 specta/OpenAPI 生成,不手工漂移。
### 8.4 C++(灵台引擎)
- C++23 与 CMake;`clang-format`、`clang-tidy`,编译警告全开并视为错误;测试与 fuzz 框架在建立工程时按 ADR 登记。
- 对外只导出 `extern "C"` 的 `hj_*` 符号与不透明句柄;异常、STL 类型、RTTI 和 C++ 类不得跨越 ABI 边界;入口函数捕获一切异常并转换为 `HjStatus`。
- 同一核心支持进程内嵌入与 gRPC 独立服务(`hunjing-lingtai-server`)双形态;任何能力在两种形态语义必须一致,服务仅限部署内网并经 mTLS 认证。
- 内存全部 RAII,禁止裸 `new`/`delete`;引擎分配的缓冲只经 `hj_buffer_free` 释放;字符串一律 UTF-8。
- `HjEngine` 线程安全,会话句柄单线程亲和;回调在调用线程同步执行且回调内禁止再入引擎;不持锁跨回调。
- 全部引擎输入(Markdown、模型输出、工具参数、查询、Webhook 字节)按不可信输入处理,长度/深度/节点数有硬上限;`hj_transform` 与 `hj_policy` 为 fuzz 必测目标。
- 每次提交跑 ASan/UBSan,线程路径跑 TSan,并维护 ABI 快照与双形态 golden 一致性测试。
- 引擎无权威状态、不做网络/文件/数据库 I/O(显式只读索引除外);引擎缺失或服务不可达时宿主 fail closed,禁止宿主内第二实现降级。
- 第三方库进入前按官方文档、许可与维护状态评估,gRPC/ANN/分词等选型以补充 ADR 登记。
### 8.5 Go(仅在 ADR 决定拆出高并发服务时)
- 版本以 `go.mod` 为准;`gofmt`/`gofumpt`、`go vet`、`golangci-lint`、`go test ./...`。
- 所有外部 I/O 接受 `context.Context`,传播取消和 deadline;不把 Context 存入 struct。
- 错误使用 `%w` 包装并以 `errors.Is/As` 分类;不匹配错误字符串。
- Goroutine 必须有 owner、退出路径和测试;channel 由发送方关闭;禁止无界队列。
- HTTP/Header/流式协议由共享契约生成或验证,不单独发明模型协议。
### 8.6 SQL 与存储
- 表/列/index 使用 `snake_case`;索引命名使用 `pk_`/`uk_`/`idx_`/`fk_` 前缀加表名与字段;外键、唯一约束、检查约束和租户条件在数据库层落实。
- 所有 Query 明确 PersonalDomain/Workspace/Finance scope;禁止先全表读后应用层过滤。
- N+1、无界列表和 `%keyword%` 全表扫描必须在实现前处理或有量化例外。
- 向量、图、搜索和缓存只保存可重建投影,删除和权限变化必须传播。
## 9. 复杂度与变更规范
- 只改目标所需文件;匹配既有命名、注释密度和风格;保护用户已有改动。
- 删除自己引入的无用代码、导入、配置和孤儿注释。
- 函数有效逻辑超过 40 行、圈复杂度 >10、认知复杂度 >15、参数 >5 时应拆;确需保留须说明原因和风险。
- 不为一个实现创建接口/工厂/配置层;但稳定跨模块/插件/Provider 边界需要 Port 时不受此限制。
- 不重写或删除已有注释,除非需求明确要求或注释已失真。
## 10. 验证纪律
- 中大型或安全/状态/边界/并发/外部依赖变更先写失败测试,再实现通过。
- 逻辑变更优先覆盖公共行为;核心逻辑自动化覆盖目标 80%+。
- 每条需求交付前核对:需求 → 实现位置 → 调用点 → 测试 → 运行证据。
- 新函数、类、配置、事件和 ContentBlock 类型必须有真实调用/消费点。
- 新依赖、资源、Header、事件、ID 和配置名称必须验证真实存在且与契约一致。
- 纯文档变更可不跑代码测试,但必须验证内部链接、Mermaid、Markdown 和契约引用。
- 不报告虚假完成;测试失败、步骤跳过和未实现项必须明确说明。
## 11. 文档与图表
- 正式文档统一在 `docs/`;新增入口同步 `docs/README.md`。
- 稳定 API/字段/ID/事件/错误只在 `docs/contracts/` 和生成 Schema 定义;下游引用,不复制可漂移值集。
- 架构、流程、时序、状态和 ER 图统一使用 Mermaid,提交前必须实际渲染验证。
- 产品文化名更新 `docs/product/cultural-language.md`;工程值更新契约;两层保持一对一映射。
- 每次功能/API/状态变化同步相关产品、架构、契约、TODO 和测试文档。
## 12. 目录与配置
- `docs/`:文档;`logs/`:本地日志;`db/`:本地数据库;`config/`:应用配置;`docker/`:Docker 文件。
- `.env.example` 位于根目录,列出环境变量和中文说明;只提交 `.env.example` 和其他不含秘密的 `*.example.*` 配置,不提交真实 `.env`、密钥、数据库、日志和用户数据。
- 代码导入使用语言包/alias 的项目根路径;运行时文件路径通过统一项目根解析器或配置解析,不依赖进程当前目录。
- Docker 容器名以 `hunjing-` 开头;Compose 不使用顶部 `version`;开发、测试与自托管统一 PostgreSQL(ADR-024),正式环境按完整 1.0 能力启用 Redis、对象存储和 Worker。
- 本地启动、测试、迁移、生成和检查统一通过根 `Makefile`;新增命令同步 `make help`。
## 13. Git 与交付
- 不覆盖、重置或删除用户未授权的现有改动。
- 不执行 `git reset --hard`、强制推送、清理未跟踪文件等破坏性操作,除非用户明确要求并确认目标。
- 只有用户要求时提交或推送;Commit 使用简体中文的 Conventional Commits/Gitmoji 规范。
- 提交前运行适用的 format、lint、typecheck、test、OpenAPI drift、Markdown/Mermaid 和安全检查。