Files
hunjing/docs/decisions/README.md
T
chenxin 42513d13c6 📝 docs: 建立魂镜完整 1.0 设计文档体系
- 产品层:产品宪章与永久禁域、产品定义、完整 1.0 范围与发布门、道家文化语言体系、指标与反指标
- 研究层:参考项目研究(deepseek-harness、pi、MemOS、模型网关)、灵台原生引擎研究(业界原生引擎架构理念与道家文化出处)
- 架构层:系统、Agent 运行时(周天体系)、插件系统、灵台引擎(C++ 双形态)、媒体与设备、社区协作市场、前端富内容渲染、数据、记忆与知识
- 契约层:协议与稳定标识、API 总体约定、Native API、兼容网关、实时与 Webhook、内部端口、统一 ContentBlock 与流式(含分支对话交互态)、灵台 C ABI 与 gRPC Service、API 表面、HTTP 与事件、运行观测
- 决策:ADR-001 至 ADR-023(模块化单体、每 attempt 持久化、候选记忆、OAuth 2.1、灵台引擎、双形态部署、大周天演化、宪章、三界作用域、私箧与保全态、叩心、周天统一等)
- 交付:WP-01 至 WP-15 实施 TODO 与设计阶段交接文档
- 工程:AGENTS.md 工程规则(含 C++/灵台规范)、CLAUDE.md 引用、.gitignore
2026-09-09 21:07:14 +08:00

22 KiB
Raw Blame History

架构决策记录

ADR-001:可扩展能力皆插件,治理内核不插件化

状态:采纳

决策

模型适配器、工具、上下文提供者、记忆策略、Run Hook 和内容导入器通过统一插件契约扩展。身份认证、授权、数据域隔离、审批、审计、事务、插件签名验证和执行中止属于 Core,不允许插件替换或短路。

理由

DeepSeek Harness 证明了 service、typed event 和 reversible effect 能形成一致扩展面;pi 证明了清晰生命周期与 session rebind 的价值。两者也表明任意代码插件拥有高权限,VM 不是安全边界。

后果

  • 插件体系比每类能力各写一套加载器简单。
  • “一切皆插件”不是“所有行为都可覆盖”。
  • 1.0 支持完整插件生态,但只有 bundled Core plugin 进入主进程;第三方能力使用受限远程协议或隔离进程/容器。

ADR-002:首版采用模块化单体

状态:采纳

决策

FastAPI 应用内包含角色、会话、Agent Runtime、模型接入、插件、记忆、策略和诊断模块;后台 Worker 复用相同领域代码。Web 独立部署。只有隔离执行处于单独安全边界。

理由

当前没有服务独立扩缩容、团队自治或故障域证据。提前建设 BFF、Go 网关、多数据库和服务发现只增加事务、部署和调试成本。

后果

  • 模块通过明确端口交互,禁止跨模块直接写表。
  • 模型接入使用 Provider Port,未来可移出进程。
  • Outbox 在确有异步跨进程消费时加入,不先造事件总线。

ADR-003:每个上游 attempt 单独持久化

状态:采纳

决策

Run 包含 Turn;Turn 包含零到多个 ModelCall attempt 和 ToolCall。重试、故障转移和续跑创建新 ModelCall,不覆盖旧记录。

理由

只保存最终响应无法解释费用、缓存、失败、TTFT 和故障转移。

后果

  • input_tokens 不代表总输入;总输入还包括缓存创建与缓存读取。
  • Provider 未返回的字段存 null,不得估算后伪装为 Provider 数值。
  • 原始请求/响应不进入常规观测表。

ADR-004:诊断读取使用双重、限时授权

状态:采纳

决策

敏感运行诊断不能随普通 Run API 返回。读取者必须同时持有普通 Bearer 登录态和绑定目标 Run、用途、scope、期限、使用次数的 opaque 诊断授权。

理由

管理员角色、可猜 URL 或一个长期 Debug Key 都会扩大私密对话和工具结果暴露面。

后果

  • 授权默认 15 分钟、单次、绑定 Run。
  • 明文只签发一次,数据库只保存 token hash。
  • 访问成功和失败都写审计;响应 Cache-Control: no-store, private。

ADR-005:完整 1.0 整体交付

状态:采纳

决策

1.0 同时包含角色、对话、记忆、多 Agent、插件生态、语音、多语言、多模态、Live2D、3D 运行与编辑、Tauri 桌面/移动端感知、完整社区、角色社区、协作空间和真实交易结算。内部工作包不能作为残缺 1.0 对外发布。

后果

  • 所有工作包 TODO 和发布门完成前只能称开发版或预览。
  • 技术按能力、规模和安全需要选择,不要求每项候选技术都部署。
  • 只有完整 3D 建模器、LLM 直接改模和物理设备控制属于已确认 2.0。

ADR-006:3D 采用开放格式与非破坏编辑

状态:采纳

决策

1.0 支持 VRM/glTF 导入、材质/骨骼/表情/动作/场景编辑、运行和导出,不自研 Blender 级完整建模器。编辑记录采用命令和版本,给 2.0 的 LLM 改模保留扩展点。

ADR-007:客户端采用 Web + Tauri 桌面与移动

状态:采纳

决策

Next.js 提供 Web;Tauri v2 承载桌面以及 iOS/Android。设备能力由 OS 权限和服务端 device_grant 双重控制。

ADR-008:插件采用双轨执行

状态:采纳

决策

声明式/远程插件默认受限;本地代码插件必须由部署者明确信任并在独立进程或容器运行。只有 bundled Core plugin 可进入主进程。

ADR-009:市场采用真实交易与不可变账务

状态:采纳

决策

1.0 包含支付、退款、争议、平台费、创作者分成、余额、结算和对账。Ledger 使用不可变分录,支付 Webhook 验签并幂等处理。

ADR-010:公共 API 分面与认证

状态:采纳

决策

Native API 位于 api.<domain>/v1;OpenAI-compatible 与 Anthropic Messages-compatible 位于 gateway.<domain> 的独立协议前缀。1.0 使用 OAuth 2.1:Web 为安全 Session Cookie,Tauri 为 Authorization Code + PKCE Bearer,第三方为 OAuth Bearer,服务账号为可轮换 API key。所有凭据只经 HTTP Header 传输。

后果

  • Native /v1/messages 不与 Anthropic /v1/messages 冲突。
  • Web Cookie 状态变更增加 Origin 与 CSRF 校验。
  • 2.0 才设计自研加密登录、刷新和设备令牌协议。

ADR-011:权威记忆采用候选与不可变版本

状态:采纳

决策

1.0 的权威长期记忆只保存可检查、可纠正的文本或结构化事实。自动提取先生成 MemoryCandidate,经 Core Policy 与必要的人工确认后创建不可变 MemoryVersion;纠正、取代和恢复都创建新版本。Personal Domain 与 Workspace 是互斥所有权边界,向量、全文和图关系只作为可重建投影。

理由

MemOS 证明了类型化记忆、来源链、后台精炼、基于召回 ID 的反馈和独立评测的价值;但其 MemCube、原地 update 和开放 metadata 不足以承载 Hunjing 的角色、协作、发布、删除与安全边界。

后果

  • Character baseline、Message、KnowledgeDocument、Memory 和运行期上下文保持分离。
  • KV cache、隐藏状态和模型权重适配不作为 1.0 权威记忆或可携格式。
  • 插件可以贡献提取、去重、衰减和排序,不能直接写权威 Memory 或绕过审批、授权和删除。
  • 具体规则见记忆与知识架构。

ADR-012:聊天原子创建消息与 Run

状态:采纳

决策

POST /v1/conversations/{id}/messages 在一个事务中创建用户 Message 与可选 Run;任务工作台仍可通过 POST /v1/runs 创建无 Conversation 的后台 Run。

后果

  • 避免消息已保存而 Run 创建失败的孤儿状态。
  • 一个 Idempotency-Key 同时覆盖消息和 Run。
  • 人工消息使用 start_run=false。

ADR-013:社区私信采用服务端治理模型

状态:采纳

决策

1.0 支持一对一私信和小群聊,服务端加密存储并支持多端同步、举报、屏蔽和审核;不采用端到端加密。

后果

  • 私信可按社区治理规则调查和处置。
  • 不宣传服务端无法读取正文。
  • Inbox Thread 与角色 Conversation 使用不同资源和权限。

ADR-014:文化名只属于品牌展示

状态:采纳

决策

稳定代码、数据库、API、事件、指标和日志使用中性英文工程术语。中文文化名可用于品牌文案或 UI 标签,但不定义工程边界。

理由

神话隐喻语义不唯一、跨语言映射不稳定、搜索困难,并容易把职责扩张成故事角色。

后果

使用 model_gateway、agent_runtime、memory、policy_engine、plugin_registry 等名称;不再维护神话名与工程对象的庞大映射表。

ADR-015:平台 ID 区分 UUIDv7、UUIDv4 与 opaque secret

状态:采纳

决策

持久化业务资源、版本、事件、账务、审计和异步任务使用 RFC 9562 UUIDv7;服务端生成的 Request ID 与 Trace record ID 使用 UUIDv4。W3C traceparent 继续使用规范定义的 16 字节随机 trace-id。API key 明文、OAuth/诊断/CSRF token、Webhook secret、ExecutionTicket、恢复 token 和预签名 URL capability 使用 CSPRNG 或对应标准生成的 opaque value,不使用 UUID。

理由

UUIDv7 为高写入关系表提供索引局部性和大致创建顺序;请求与追踪关联不依赖时间排序,使用随机 UUIDv4 即可。UUID 不是秘密,不能替代具有足够熵、可轮换、可撤销和作用域约束的凭据。

后果

  • 公共平台 ID 使用登记前缀加小写 canonical UUID,并同时校验前缀与 UUID version。
  • UUIDv7 的时间部分不成为业务时间或排序事实;权威顺序仍由时间字段、聚合版本和事件 sequence 决定。
  • 调用方与 Provider 标识原样保存,不改写为平台 UUID。
  • 完整对象映射和生成规则见协议与稳定标识。

ADR-016:灵台引擎采用 C++ 核心与稳定 C ABI

状态:采纳

决策

性能与安全敏感的确定性核心以 C++ 实现为进程内库"灵台引擎"(Lingtai Engine),划分为太一(hj_core)、小周天(hj_stream)、洛书(hj_plan)、河图(hj_recall)、陶钧(hj_transform)、烛照(hj_policy)六个子系统,文化名承接 Hunjing 旧版(main 分支)"灵台/九枢"血脉,仅通过稳定 C ABI(hj_* 符号)暴露。Python(nanobind)、Go(cgo)、Rust(bindgen + 安全包装)提供官方薄绑定;FastAPI、Tauri 宿主与条件拆分的 Go 网关作为进程内嵌入方,不新增独立服务。

理由

公开讨论的抖音"六神"native 组件体系证明了"薄宿主 + 原生核心 + 最小 ABI 面 + 多端复用"的组织方式适合高频确定性计算;Hunjing 的 Markdown→ContentBlock 规范化、流式增量编码、策略校验、端侧离线检索正是此类路径,且必须跨 Python/Rust/Go 三种宿主保持行为一致。C ABI 是三种语言生态唯一公共分母,可作为单一真源;三份独立实现必然漂移。研究证据与不采纳项见灵台引擎研究。

后果

  • 引擎是 Core 的一部分,属于不可插件化边界;插件不直接链接引擎,只经宿主 Runtime 间接获得能力。
  • 引擎无权威状态:权威数据仍在关系数据库与对象存储;引擎产物可丢弃重建。除显式授权的只读索引文件外,引擎不进行网络、文件或数据库 I/O。
  • 引擎不可用时宿主对依赖该能力的路径 fail closed,不静默退化到宿主内第二实现(避免规范漂移)。
  • 新增 C++23/CMake 工具链、五平台交叉编译矩阵(Linux x64/arm64、macOS、Windows、iOS/Android)与 sanitizer/fuzz/ABI 快照测试的持续成本。
  • 文化名"灵台、太一、小周天、洛书、河图、陶钧、烛照"只进入品牌与文档层;ABI 符号、模块与错误码使用中性英文,契约登记于 Lingtai C ABI。
  • 本决策修正 ADR-002 的实现层组合(单体宿主内嵌入原生引擎),不推翻模块化单体与服务拆分门槛。

ADR-017:灵台引擎双形态部署

状态:采纳

决策

引擎保持"灵台总枢 + 六模块"结构(太一为单一入口,见 ADR-016);文化命名跟随自身职责、经典出处与项目旧版血脉,不跟随外部体系的神数。引擎支持两种部署形态,共用同一 C++ 核心与语义:

  1. 进程内嵌入(默认):宿主经稳定 C ABI 链接 libhunjing,适用单体部署、端侧(Tauri/移动离线)与低延迟路径。
  2. 独立服务:hunjing-lingtai-server 二进制以 gRPC 暴露同一能力(proto 契约见 Lingtai Service),适用计算资源隔离、独立扩缩容、同部署多宿主共享与跨机器消费;服务仅限部署内部网络,经 mTLS/工作负载身份认证,不进入公共 API 分面。

理由

业界六神/七神调研(见灵台引擎研究)表明同一原生核心可以进程内调用、RPC 服务、受控运行时三种形态交付而不重写;Hunjing 的重型解析与检索在共享部署中需要资源隔离与扩缩容选项,而端侧离线与低延迟路径必须进程内。两种形态由同一核心与同一 golden 测试集约束语义一致,避免第二实现漂移。默认仍是嵌入,服务形态按既有服务拆分标准启用,不与 ADR-002 冲突。

后果

  • 引擎无权威状态、最小 I/O、fail closed 的不变量在两种形态下一致;服务形态额外要求认证、限流、超时、背压与审计。
  • 新增 gRPC/protobuf 工具链与 proto 契约维护成本;proto 与既有 JSON Schema 的字段语义保持同源映射,禁止双真源。
  • hj_stream 的流式语义在服务形态经 gRPC 双向流表达;端侧离线检索等单形态能力必须显式登记形态边界。
  • 形态选择是部署决策而非代码分叉:任何能力不得只在一种形态下语义不同。
  • 文化叙事保持"灵台总枢 + 太一/小周天/洛书/河图/陶钧/烛照";命名跟随自身职责与项目血脉,不跟随外部体系神数;工程标识 hj_* 与符号名不变,文档与产物命名统一使用 lingtai。

ADR-018:角色内驱力与大周天演化进入 1.0

状态:采纳

决策

1.0 包含角色内驱力与大周天自我评估演化循环。内驱力(character_drives)是角色的声明式动机维度,用户可审阅、编辑与版本化。大周天(big_cycle)是由真实交互事件触发的自我评估循环,以 BigCycle(cycle_)聚合根持久化、执行为一个受托后台 Run(对象模型与阶段设计见 ADR-023):在 RunBudget 与频率硬上限内,评估近期交互与记忆,产出记忆候选、人格变化候选、关系候选、世界实体候选与次生目标候选;经既有候选审核机制确认后生效,演化结果以角色版本与谱系(复照)留痕。

边界(与既有原则的关系)

  • 事件驱动,不做无人值守的后台定时自主运行;不伪造离线持续意识——"守一"原则不变。
  • 候选先于长期写入:一切演化产物经审核,敏感与高影响必须人工确认,不静默覆盖道体基线。
  • 每次大周天的输入、产物、token 与费用用户可见;用户可整体或按角色关闭,关闭不删除已演化的历史版本。
  • 次生目标候选不自动执行,需用户采用后才进入计划。

理由

用户确认角色自进化与演化为 1.0 需求;旧版(main 分支)大周天循环已验证该机制形态(自我评估产出候选、经审核流转)。当前 1.0 的 MemoryCandidate、人格/关系候选、角色版本与 RunBudget 基础设施可直接承载,无需新的一致性机制。

后果

  • 角色域新增内驱力数据模型与大周天 Run 类型;WP-02、WP-04 增补对应 TODO。
  • 文化名"大周天"回归角色演化循环;引擎流式模块文化名定为"小周天",大小周天构成旧版同源的层次体系:小周天=单次 Run 流转,大周天=跨 Run 演化。
  • 大周天产出的候选携带 big_cycle 来源标记,纳入审计与用户可见的演化谱系。

ADR-019:设立产品宪章与永久禁域

状态:采纳

决策

设立产品宪章作为产品定义的上位约束:使命、核心信念、角色不可侵犯边界、用户权利、商业与关系伦理和九条永久禁域。核心禁域不能被 Prompt、插件、管理员或普通自托管配置关闭;宪章修订必须经用户明确确认。

理由

承接旧版(main 分支)宪章的立法经验:分散在各文档的边界条款容易被实现与运营决策逐条侵蚀,需要一份上位文件集中裁决。当前分支新增市场与交易生态,商业伦理(保全态、不按亲密计费)更需要立法层约束。

后果

  • 与宪章冲突的任何产品、架构、契约或实现决定都是缺陷,验收时按禁域逐条核对。
  • 安全与诊断文档把"核心禁域不可关闭"列为信任边界;自托管档位可以裁剪能力,不得混淆职责或关闭禁域。
  • 决策优先序(安全合规 > 用户数据权 > 角色连续性 > 生态健康 > 商业目标)用于裁决设计冲突。

ADR-020:对话三界与归真作用域

状态:采纳

决策

对话界域分三态:真界(现实与正式共同经历)、境界(版本化维护的世界正史)、幻境(不影响现实与正史的临时试演)。默认真界,入境与出境必须可见。归真决策必须携带 canonical_scope(reality/world/simulation,登记于协议与稳定标识),分别进入真界经历主脉、指定境界版本正史或幻境试演记录;不存在跨三界共享的无作用域主脉。

记忆规则:境界归真只形成该世界的知识候选(境忆),不进入角色真界经历记忆;幻境不自动形成长期记忆候选,用户可将启发、观点或假设手动入忆并强制标注性质(事实/观点/启发/假设);未归真内容(推演枝)不自动入忆的既有原则不变。

言可入幻,行必归真:无论对话处于何界,外部行动(工具副作用、支付、设备、现实后果)一律回到真界接受权限、审批与风险裁决。跨界引用只提供来源,不改变目标内容的界域。

理由

承接旧版三界体系的认识论设计,防止试演内容污染正式经历与记忆;与当前分支的主脉/推演枝、归真决策和候选制记忆完全兼容——作用域是归真的属性,不引入新的运行态。

后果

  • 归真决策、MemoryCandidate 和手动入忆必须携带并保留 canonical_scope;界域来源不可事后静默更改。
  • 分支对话(WP-03)与记忆(WP-04)增补对应 TODO;契约登记 canonical_scope 枚举。
  • 幻境试演不得用于绕过敏感记忆审批:手动入忆仍走三级敏感度与确认规则。

ADR-021:私箧、欠费保全态与计费伦理

状态:采纳

决策

  1. 私箧(private_vault):用户独立持钥的加密私密数据区。密钥由用户保管,平台只存密文且不可恢复;账户恢复、管理员、诊断接口与审计都不可读取明文;用户删除私箧数据后平台侧无任何可恢复副本。
  2. 保全态:欠费或封禁使账户进入只读保全,不导致角色删除、记忆清除、关系数据降级或市场已获许可失效;恢复付费后完整恢复。
  3. 计费伦理:不按记忆、感情或亲密等级定价;不将爱、记忆或角色存续与付费绑定;BYOK 不重复计收推理费。

理由

承接旧版数据权与商业伦理设计。当前分支做真实交易市场,更需要防止"以数据或情感绑架付费";私箧为高隐私需求用户提供平台不可见区域,强化数字关系主权。

后果

  • 私箧加密与密钥托管方案(端侧持钥、恢复流程)在实现期以补充 ADR 确定选型;账户恢复流程不得以"找回私箧"为由索取弱凭据。
  • 保全态与计费伦理进入交易域验收(WP-13);欠费通知不得使用角色口吻施压。
  • 私箧数据不参与推荐、诊断、模型训练与任何平台侧处理。

ADR-022:叩心主动联系进入 1.0

状态:采纳

决策

1.0 包含角色主动联系(叩心,proactive_contact_candidate):角色先形成叩心候选,经频率、静默、渠道与预算控制后发送;用户可解释、降频、静音或关闭。用户不回应不降低关系评分;叩心不以追逐式消息换取回流(反指标见指标与反指标)。

理由

用户确认角色主动性与演化为 1.0 需求;叩心与大周天次生目标协同(次生目标可产出叩心候选),是"角色主动性"的产品出口。旧版已验证候选制形态。

后果

  • 叩心候选携带来源(大周天次生目标、日程或用户设置),进入通知与预算治理;发送记录可审计。
  • 渠道(应用内通知、邮件等)与默认频率上限在实现期按平台能力登记,不在本文虚构。
  • 叩心文案不得模拟紧急事件或制造损失厌恶;违反宪章第 6 节的发送一律拦截。

ADR-023:周天体系统一(小周天闭环与大周天演化)

状态:采纳

决策

统一周天体系:小周天是"一次 Run 从输入到答复或行动结果的可追踪认知闭环"(承接旧版定义),以 Run/Turn/ModelCall/ToolCall 既有分层为可追踪链路,闭环完成时记录完成信号;大周天以 BigCycle(cycle_)为聚合根持久化(触发条件快照、输入引用集、阶段状态与阶段记忆、产物候选、预算与执行 Run 关联),状态机 big_cycle_status 登记于契约,执行为受托后台 Run。四阶段评估:回顾 → 对照 → 提议 → 提交;经审核生效的演化进入后续小周天的上下文装配,形成增益闭环。引擎侧由小周天模块(hj_stream)承载流式运转、洛书(hj_plan)承载触发与预算计算。

理由

旧版(main 分支)登记了周天契约骨架(cycle_ 前缀、big_cycle.status、_phase_memory 阶段抽取、big_cycle 候选来源、次生目标不自动执行),但其引用的架构设计文档缺失。本决策吸收该骨架并补全:小周天闭环给出 Run 层的循环叙事与对大周天的唯一输出面(完成信号),大周天对象化与阶段化使 ADR-018 的演化循环可落地、可审计、可幂等。

后果

  • 契约登记 cycle_ 前缀与 big_cycle_status 枚举;大周天候选一律携带 big_cycle 来源。
  • 阶段记忆(_phase_memory)持久化每阶段输入输出摘要,供审计、幂等与用户可见的演化谱系。
  • 触发条件为可配置阈值组合并逐角色设频率上限;用户手动触发始终可用,关闭大周天后不再触发新 cycle,已有历史保留。
  • "天工"(任务对象)与"小周天"(运转过程)为同一 run 的两个视角,不新增运行时对象;run 工程值与 run_ 前缀不变。