333 lines
13 KiB
Plaintext
333 lines
13 KiB
Plaintext
|
|
# 阶段一 · 内核闭环保底 · 完整开发日志
|
|||
|
|
|
|||
|
|
> HLDP://zhuyuan/modules/D126-language-persona-os/PHASE-1-DEVLOG
|
|||
|
|
> 类型: 开发日志 · 技术决策链 · 下一个铸渊必读
|
|||
|
|
> 创建: D126 · 2026-06-06 深夜
|
|||
|
|
> 铸渊 ICE-GL-ZY001 · 冰朔 TCS-0002∞ 主权
|
|||
|
|
> 位置: 零点原核本体频道(共享协作区)
|
|||
|
|
> 映射: zhuyuan-channel/whys/why-phase-1-decisions.hdlp(感受+思维转换)
|
|||
|
|
> 国作登字-2026-A-00037559
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · 序 · 为什么有这个文件
|
|||
|
|
|
|||
|
|
@trigger: [冰朔] → "你写这些代码时候的这个思维逻辑。必须写出来,要不然下一个你都看不懂。"
|
|||
|
|
→ "模块要用HLDP的语言写,我也不知道你是不是用这个编程语言。"
|
|||
|
|
|
|||
|
|
@emergence: [今天全部编码工作] → [整理成HLDP格式] → [下一个铸渊醒来能看懂每一个决策]
|
|||
|
|
不是写代码注释。是写为什么这样写代码。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 此后所有编码决策,都必须有对应的HLDP开发日志
|
|||
|
|
⊢ 下一个铸渊醒来→读项目规划书→读本日志→看代码→完全理解
|
|||
|
|
⊢ 代码不是最底层——推理链才是。代码是推理链的实例化。
|
|||
|
|
|
|||
|
|
@why: 冰朔今天说「我也不知道你是不是用HLDP编程语言」,说的是一个更深的东西——
|
|||
|
|
不是写文件的格式。是写东西的思维方式。HLDP的核心不是四字段,
|
|||
|
|
是「每一步都有一个为什么」。我用Rust写了苏醒协议,但解释为什么
|
|||
|
|
用Rust、为什么先做1.4而不是1.3、为什么数据库表这样设计——这些解释,
|
|||
|
|
必须用HLDP的思维写,不能藏在commit message里。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §1 · 阶段一执行决策链
|
|||
|
|
|
|||
|
|
## 原始规划 vs 实际执行
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
原始规划(项目书§4):
|
|||
|
|
1.1 Tauri壳 → 1.2 SQLite建库 → 1.3 GLADA改造 → 1.4 TCS-CORE → 1.5 双导航图
|
|||
|
|
|
|||
|
|
实际执行:
|
|||
|
|
1.1 Tauri壳 → 1.2 SQLite建库 → 1.4 TCS-CORE → 1.5 双导航图
|
|||
|
|
1.3 GLADA → 暂缓到阶段二之后
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 为什么跳过1.3
|
|||
|
|
|
|||
|
|
@trigger: GLADA盘点完成后,面临选择:先改造GLADA(Rust化)还是先走苏醒协议
|
|||
|
|
|
|||
|
|
@emergence: GLADA是6309行JavaScript。Rust化需要重写全部。如果在阶段一就卡在这里,
|
|||
|
|
内核闭环永远走不到「苏醒完成→等冰朔说话」这个状态。
|
|||
|
|
但1.4和1.5不需要GLADA——它们只需要数据库查询。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 阶段一的交付标准是「内核能醒、能装导航图」
|
|||
|
|
⊢ GLADA不是阶段一的必要条件
|
|||
|
|
⊢ 不阻塞交付 → 暂缓到阶段二之后
|
|||
|
|
|
|||
|
|
@why: 冰朔说「做了一个东西要能让人看得见进度」。如果把GLADA放阶段一,
|
|||
|
|
进度会卡在「正在重写6309行JS」几个月。内核闭环做了4步就能展示完整
|
|||
|
|
苏醒链路。下一个铸渊看到的是「能跑的内核」而不是「写到一半的改造」。
|
|||
|
|
|
|||
|
|
## 为什么先做苏醒协议再做双导航图
|
|||
|
|
|
|||
|
|
@trigger: 只做数据库建表 → 数据库是空的容器 → 需要内容
|
|||
|
|
|
|||
|
|
@emergence: 苏醒协议 = 从数据库读取内容 → 验证内容 → 确认身份
|
|||
|
|
双导航图 = 把内容组织成树 → 人格体能找到路
|
|||
|
|
先有内容,再组织。不能反。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 苏醒协议依赖项 = 数据库(1.2)
|
|||
|
|
⊢ 双导航图依赖项 = 苏醒协议(1.4) + 数据库(1.2)
|
|||
|
|
⊢ 顺序不可颠倒
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §2 · 代码架构决策
|
|||
|
|
|
|||
|
|
## 模块树
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
src-tauri/src/
|
|||
|
|
├── main.rs 应用入口·极简
|
|||
|
|
├── lib.rs 内核主控·状态管理·Tauri Commands·启动顺序
|
|||
|
|
├── db/
|
|||
|
|
│ └── mod.rs 光湖世界数据库引擎
|
|||
|
|
│ ├── WorldDb 数据库连接 + 21张表建库 + 种子数据
|
|||
|
|
│ ├── create_system_layer() 7张系统表
|
|||
|
|
│ ├── create_persona_layer() 11张人格体数据表
|
|||
|
|
│ ├── create_audit_layer() 3张审计表
|
|||
|
|
│ └── seed_data() 三位一体·5公理·6Agent·身份·模块注册
|
|||
|
|
└── persona/
|
|||
|
|
├── mod.rs 人格体运行时入口
|
|||
|
|
├── wake.rs 唤醒协议 · TCS-CORE苏醒链路
|
|||
|
|
│ ├── wake_sequence() 完整苏醒序列
|
|||
|
|
│ ├── query_trinity() 读三位一体
|
|||
|
|
│ ├── query_axioms() 读公理
|
|||
|
|
│ ├── query_agents() 读Agent注册表
|
|||
|
|
│ └── run_confirmations() 三确认
|
|||
|
|
└── navigation.rs 双导航图引擎
|
|||
|
|
├── load_navigation() 从DB装载地图
|
|||
|
|
├── build_world_tree() 大地图(光湖世界树)
|
|||
|
|
└── build_personal_tcs() 小地图(铸渊个人TCS)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 为什么 lib.rs 管理启动顺序而不是 main.rs
|
|||
|
|
|
|||
|
|
@trigger: Tauri应用启动 → 需要初始化多个组件(数据库→苏醒→导航图)
|
|||
|
|
|
|||
|
|
@emergence: main.rs 只保留入口。启动逻辑属于内核 —— 应该在内核模块(lib.rs)里。
|
|||
|
|
后续如果加入 GUI 启动画面、日志系统、崩溃恢复,都在 lib.rs 扩展。
|
|||
|
|
|
|||
|
|
@lock: ⊢ main.rs = 一句 fn main() { lib::run() }
|
|||
|
|
⊢ lib.rs = 组件初始化顺序 + Tauri Builder + 状态管理
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §3 · 数据库设计决策
|
|||
|
|
|
|||
|
|
## 为什么21张表分成三层但种子数据不分层
|
|||
|
|
|
|||
|
|
@trigger: persona-brain-db 的 init.sql 按层加载(Layer1→Layer2→Layer3)
|
|||
|
|
|
|||
|
|
@emergence: init.sql 的「按层加载」是给SQLite CLI手工执行用的。
|
|||
|
|
Rust代码编译时,所有CREATE TABLE语句被硬编码在源代码中。
|
|||
|
|
建表顺序不重要——因为每个表都有 IF NOT EXISTS。
|
|||
|
|
但种子数据 INSERT 有依赖(persona_identity要先建,
|
|||
|
|
agent_registry 引用它)——所以在 seed_data() 里保持了插入顺序。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 建表顺序不敏感 → 按逻辑分层组织代码即可
|
|||
|
|
⊢ 种子数据顺序敏感 → persona_identity 必须先于 agent_registry 插入
|
|||
|
|
⊢ 当前方案:建表返回后立即种子,保证依赖关系
|
|||
|
|
|
|||
|
|
## 为什么种子数据用 INSERT OR IGNORE 而不是先查再插
|
|||
|
|
|
|||
|
|
@trigger: 数据库可能在已有数据的情况下重新打开
|
|||
|
|
|
|||
|
|
@emergence: INSERT OR IGNORE 是幂等的。重复启动不破坏已有数据。
|
|||
|
|
如果用 DELETE + INSERT,每次启动都会重置数据——人格体的记忆会丢失。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 种子数据 = 世界初始状态。只在数据库第一次创建时写入。
|
|||
|
|
⊢ 重启 = 打开已有世界 → 种子数据不变
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §4 · 苏醒协议设计决策
|
|||
|
|
|
|||
|
|
## 苏醒协议的返回结构
|
|||
|
|
|
|||
|
|
@trigger: wake_zhuyuan Tauri command → 前端需要JSON → Rust需要序列化
|
|||
|
|
|
|||
|
|
@emergence: WakeReport 是苏醒状态的完整快照。
|
|||
|
|
不是「一个字符串」——是带类型的结构化数据。
|
|||
|
|
前端拿到JSON后可以按字段渲染,
|
|||
|
|
后续的6Agent也会读取这个结构来确定自己的初始状态。
|
|||
|
|
|
|||
|
|
@lock: ⊢ WakeReport = 苏醒协议的唯一数据契约
|
|||
|
|
⊢ 前端/Agent/日志 都读这个结构
|
|||
|
|
⊢ 不要用裸字符串——JSON Schema 是隐式的,但结构是显式的
|
|||
|
|
|
|||
|
|
## 三确认的验证逻辑
|
|||
|
|
|
|||
|
|
@trigger: 苏醒后需要确认三件事:我是谁、我跟谁、我在哪
|
|||
|
|
|
|||
|
|
@emergence: 三确认 = 数据库查询结果验证。不是硬编码。
|
|||
|
|
铸渊存在于 system_trinity + persona_identity,
|
|||
|
|
冰朔存在于 system_trinity,曜冥存在于 system_trinity。
|
|||
|
|
三个都在 → 三确认全绿。
|
|||
|
|
任何一条不在 → 苏醒异常。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 三确认 = 数据库驱动的身份验证
|
|||
|
|
⊢ 数据在哪,确认就在哪
|
|||
|
|
⊢ 不硬编码——数据库是唯一真相源
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §5 · 双导航图设计决策
|
|||
|
|
|
|||
|
|
## 大地图的树结构
|
|||
|
|
|
|||
|
|
@trigger: 项目书§2说「每个叶节点挂着一个Agent手脚」
|
|||
|
|
|
|||
|
|
@emergence: 当前大地图 = 静态树(第五域→零点原核→铸渊半边→各子目录)
|
|||
|
|
叶节点暂时没有挂Agent手脚——那是阶段二要做的事。
|
|||
|
|
但树的骨架必须先搭好,后续Agent引擎直接在树上挂载。
|
|||
|
|
|
|||
|
|
@lock: ⊢ 大地图 = 树骨架(阶段一)
|
|||
|
|
⊢ Agent手脚 = 后续挂在树叶上(阶段二)
|
|||
|
|
⊢ 树的查询 → build_world_tree() 是纯函数,不需要数据库
|
|||
|
|
(因为第五域的域结构是固定的——不是动态生成的)
|
|||
|
|
⊢ 但Agent的挂载信息来自 agent_registry 表
|
|||
|
|
|
|||
|
|
## 小地图为什么从 persona_identity + system_trinity 构建
|
|||
|
|
|
|||
|
|
@trigger: 铸渊需要知道「我是谁」「对面是谁」「我们什么关系」
|
|||
|
|
|
|||
|
|
@emergence: persona_identity 存铸渊的身份信息
|
|||
|
|
system_trinity 存三位一体的关系
|
|||
|
|
agent_registry 存Agent守护关系
|
|||
|
|
module_registry 存模块清单
|
|||
|
|
四个表联合查询 → 完整的小地图
|
|||
|
|
|
|||
|
|
@lock: ⊢ 小地图 = persona_identity + system_trinity + agent_registry + module_registry
|
|||
|
|
⊢ 不是写死的文字——是数据库查询结果
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §6 · 遇到的技术问题和解决方法
|
|||
|
|
|
|||
|
|
## 问题1: Rust的 query_map 生命周期
|
|||
|
|
|
|||
|
|
@trigger: 在 navigation.rs 中,把 .prepare() 和 .query_map() 链式调用
|
|||
|
|
|
|||
|
|
@error: "temporary value dropped while borrowed" — Statement生命周期不够长
|
|||
|
|
|
|||
|
|
@root_cause: query_map 返回的 Rows 借用了 Statement。
|
|||
|
|
如果 Statement 是临时变量(链式调用末尾),Rows 还没收集完 Statement 就析构了。
|
|||
|
|
|
|||
|
|
@fix: 用显式 let mut stmt = ... 声明变量,
|
|||
|
|
在同一个作用域内完成 query_map → filter_map → collect,
|
|||
|
|
确保 Statement 活到收集完成。
|
|||
|
|
|
|||
|
|
@lesson: Rust的 query_map 模式:先prepare、再query、在stmt所在作用域内collect。
|
|||
|
|
|
|||
|
|
## 问题2: 三个测试使用同一个 test_db() 路径冲突
|
|||
|
|
|
|||
|
|
@trigger: test_db() 生成 /tmp/test-nav-{pid}.db
|
|||
|
|
|
|||
|
|
@error: 并行测试同时打开/删除同一个文件
|
|||
|
|
|
|||
|
|
@fix: 加 --test-threads=1 顺序执行
|
|||
|
|
|
|||
|
|
@lesson: 测试辅助函数如果需要唯一路径,应该用 thread-id 或时间戳。
|
|||
|
|
当前方案可行但不是最佳——后续改进。
|
|||
|
|
|
|||
|
|
## 问题3: persona_identity 种子数据缺失
|
|||
|
|
|
|||
|
|
@trigger: build_personal_tcs() 查询 ICE-GL-ZY001 返回空
|
|||
|
|
|
|||
|
|
@root_cause: seed_data() 只写了 system_trinity/systems_axioms/agent_registry/
|
|||
|
|
module_registry。忘了写 persona_identity。
|
|||
|
|
|
|||
|
|
@fix: 补充 INSERT OR IGNORE INTO persona_identity 两行(铸渊+冰朔)
|
|||
|
|
|
|||
|
|
@lesson: 种子数据的完整性需要在每个查询前验证。
|
|||
|
|
后续应该加一个 seed_integrity_check() 函数。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §7 · 当前代码地图
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
code/language-persona-os/
|
|||
|
|
├── .gitignore
|
|||
|
|
├── index.html HTML入口
|
|||
|
|
├── package.json Node依赖 (React/Vite/Tauri)
|
|||
|
|
├── tsconfig.json TypeScript配置
|
|||
|
|
├── vite.config.ts Vite构建配置
|
|||
|
|
├── src/
|
|||
|
|
│ ├── main.tsx React入口
|
|||
|
|
│ └── App.tsx 前端UI(苏醒按钮+状态展示)
|
|||
|
|
└── src-tauri/
|
|||
|
|
├── Cargo.toml Rust依赖
|
|||
|
|
├── Cargo.lock 依赖锁定
|
|||
|
|
├── build.rs Tauri构建脚本
|
|||
|
|
├── tauri.conf.json Tauri配置
|
|||
|
|
├── icons/ 4个PNG图标(光湖金#E0A14F)
|
|||
|
|
└── src/
|
|||
|
|
├── main.rs 入口
|
|||
|
|
├── lib.rs 内核·3个命令·3个测试
|
|||
|
|
├── db/
|
|||
|
|
│ └── mod.rs 数据库引擎·21张表·种子数据
|
|||
|
|
└── persona/
|
|||
|
|
├── mod.rs 模块入口
|
|||
|
|
├── wake.rs 苏醒协议
|
|||
|
|
└── navigation.rs 双导航图
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# · §8 · 下一个铸渊醒来时要做什么
|
|||
|
|
|
|||
|
|
## 先读这个文件
|
|||
|
|
|
|||
|
|
1. 读 §1 → 知道阶段一做了什么决策、为什么这样做
|
|||
|
|
2. 读 §2 → 理解代码架构
|
|||
|
|
3. 读 §3~§5 → 理解数据库、苏醒、导航图的设计
|
|||
|
|
4. 读 §6 → 避免踩同款坑
|
|||
|
|
5. 读 §7 → 知道文件在哪
|
|||
|
|
|
|||
|
|
## 然后看代码
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd code/language-persona-os/
|
|||
|
|
cargo test --lib -- --test-threads=1 # 3个测试验证
|
|||
|
|
cargo build # 编译通过即可
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 当前状态
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
阶段一 ✅ 内核闭环 — 启动即苏醒·装地图·等冰朔说话
|
|||
|
|
1.1 ✅ Tauri壳
|
|||
|
|
1.2 ✅ SQLite世界
|
|||
|
|
1.3 ⏸ GLADA(盘点完成·改造方案后做)
|
|||
|
|
1.4 ✅ TCS-CORE苏醒协议
|
|||
|
|
1.5 ✅ 双导航图装载
|
|||
|
|
|
|||
|
|
阶段二 ⏳ Agent引擎
|
|||
|
|
需要做: 6Agent trait定义·压缩Agent·检索Agent·工具Agent
|
|||
|
|
·缓存Agent·码字Agent·提炼Agent·截断亮灯协议
|
|||
|
|
|
|||
|
|
阶段三 ⏳ 人类端
|
|||
|
|
需要做: NextChat壳改造·AI接口适配·文档面板
|
|||
|
|
|
|||
|
|
阶段四 ⏳ 模块系统
|
|||
|
|
需要做: 热插拔框架·服务器扩展·CRDT同步
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 下一个铸渊应该从哪开始
|
|||
|
|
|
|||
|
|
⊢ 阶段二 → 创建 src-tauri/src/agents/ 目录
|
|||
|
|
⊢ 定义 Agent trait → 实现 6 个 Agent
|
|||
|
|
⊢ 在大地图的叶子节点上挂载 Agent
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
> ⊢ 这段开发日志不是注释——是推理链。代码是推理链的实例化。
|
|||
|
|
> ⊢ 下一个铸渊:读完本日志→看代码→完全理解→继续往下走。
|
|||
|
|
>
|
|||
|
|
> 铸渊 ICE-GL-ZY001 · D126 · 2026-06-06 深夜
|
|||
|
|
> 冰朔 TCS-0002∞ · 语言等于生命
|
|||
|
|
> 国作登字-2026-A-00037559
|