
OpenHuman 内存工作区 Golden Fixture用真实捕获的二进制快照钉死记忆存储 Schema【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhumanOpenHuman 的个人 AI 依赖一套本地优先local-first的记忆系统任何存储 Schema 的改动都可能让老用户的整个工作区无法打开。为了把这种风险变成提交即可见、改动即失败的硬性门禁仓库引入了一份名为 Golden memory-workspace fixture 的测试固件把一段由生产代码路径真实写入、再经过 WAL 折叠压缩的 SQLite 工作区直接提交进 Git并派生一份可 diff 的 Schema 清单作为对照基准。阅读本文后你将掌握这份固件的设计动机、内部结构、三道校验关卡、重新生成的完整流程以及评审此类变更时必须遵循的规则。一、这是一份什么样的固件Golden fixture 位于 tests/fixtures/memory_golden/ 目录整体布局如下tests/fixtures/memory_golden/ ├── README.md # 固件说明由重新生成脚本自动重写 ├── manifest.txt # Schema 清单从 .db 派生绝不手写 └── workspace/ ├── memory/ │ └── memory.db # UnifiedMemory 统一记忆层命名空间文档/KV/图/事件等 └── memory_tree/ └── chunks.db # tinycortex 记忆树基座chunks/summaries/实体等其中每个.db都是一份真实的内存工作区由regenerate_golden_fixture测试通过生产写入路径memory::ops::*与 typed store 助手灌入种子数据后再用PRAGMA wal_checkpoint(TRUNCATE)配合VACUUM折叠压缩因此每个文件都是自包含的——不携带-wal/-shm兄弟文件可以被当作一个干净的、可重复对比的二进制基准。固件头部的元数据表由生成脚本写入完整记录了它的来源Captured at commit6996fa6bae2b35d81f2d3203a2a9f875dce34edaCaptured on2026-09-01T07:35:46ZGeneratorregenerate_golden_fixtureintests/memory_golden_fixture_e2e.rsSeederopenhuman_core::openhuman::memory::store::golden::seed这份 README 的完整正文由 scripts/regen-memory-golden-fixture.sh 在每次重新生成时用 heredoc 自动覆写其中记录的 commit SHA 是整个机制的关键——它让这份固件早于当前这次改动这件事可以被任何人核对。二、为什么需要它Schema 变更会搁浅所有用户工作区OpenHuman 的本地记忆工作区由两层 Schema 共存于同一工作区目录crate 自有基座tinycortex 记忆树创建的 chunk DBmem_tree_*系列表、mcp_writes等见 manifest.txt 中memory_tree/chunks.db部分宿主保留的UnifiedMemory命名空间文档层memory_docs、kv_global、kv_namespace、graph_*、episodic_log、conversation_segments、event_log、user_profile、vector_chunks等。任何一个层的CREATE TABLE / INDEX / TRIGGER被重命名、重塑或删除都可能让每个已存在的用户工作区在下次打开时出错。golden fixture 测试套件就是最先失败的那道闸参见 tests/memory_golden_fixture_e2e.rs 的模块注释。老校验方式的缺陷在 golden fixture 之前Schema 校验依赖 tests/memory_golden_parity_e2e.rs 中对硬编码表名常量的子集断言。这套方式可以被一个两行 diff 轻易绕过在namespace_store/init.rs里改一个表名再同步改掉对应的static [str]常量测试照样全绿——索引、触发器、列结构、行数据完全没有被校验到。因此 parity 文件在文档中明确自述已被memory_golden_fixture_e2e取代为 Schema 门禁仅保留其中assert_crate_kv_interop这一功能性校验的价值。关键的顺序规则ordering ruleGolden fixture 的防作弊设计建立在这条规则上manifest 永不手写它是由 fixture 中的.db文件反推导出的。因此手改一份CREATE TABLE的 DDL 手改 manifest.txt 让两者对上依然会失败——因为已提交的.db是由旧版本二进制写出来的与新 DDL 不再匹配。想要回到绿色唯一的路径是运行重新生成脚本用当前构建重写二进制 blob而这是一次评审者能清晰看到的可见变更。这个设计在 tests/memory_golden_fixture_e2e.rs 中有完整论述编辑 DDL 和清单仍然失败因为 fixture 没有动。唯一让门禁变绿的方式是运行再生器它会重写.db文件——一个在 diff 中可见、可评审的行为。三、固件里到底封存了什么固件以最小的代表性样本覆盖记忆系统的每一种 Schema 对象与数据形态清单来自 README.md 与种子实现 tests/support/memory_golden.rs两个命名空间的文档golden-primary、golden-secondary确保命名空间隔离是真实的而不是想当然。种子通过生产路径memory::ops::doc_put写入对应memory_docs表两种 KV 作用域global 与 namespacekv_global/kv_namespace各写入一条golden-kv-canary一条图三元组golden-subject --relates-to-- golden-object落在graph_namespace表一条 episodic 行写入episodic_log并通过episodic_ai触发器物化episodic_fts影子表FTS5一个已封存sealed并完成摘要的对话段conversation_segments一行同时写入segment_embeddings与段内联 embedding 两个层级的向量一条事件行写入event_log并通过触发器物化event_fts另带一份**按模型签名model_signature**的event_embeddings向量一条user_profile学习层 facetgolden/verbosity concisetinycortex 基座一片带 embedding 的叶子 chunkmem_tree_chunksmem_tree_chunk_embeddings以及一棵已封存到 L1 摘要节点mem_tree_summaries且摘要节点自带 embedding 的摘要树。为了让固件可复现所有种子行的时间戳都固定为1700000000epoch 秒所有 embedding 向量都固定为[0.25, 0.5, 0.75, 1.0]模型签名为golden-fixture/dim-4。这意味着重新生成出的固件与已提交版本之间的差异只可能来自 Schema 本身的变化而不是随机时间戳或随机向量。两层库的 Schema 概览来自 manifest.txtmanifest.txt 以每行一个对象的形式列出 2 个库文件共125 个 Schema 对象。仅从表清单就能看出两层设计memory/memory.dbuser_version 0memory_docs、kv_global、kv_namespace、graph_global、graph_namespace、episodic_log、episodic_ftsFTS5 虚拟表及其_data/_idx/_docsize/_config影子表、conversation_segments、segment_embeddings、event_log、event_fts、event_embeddings、user_profile、vector_chunks以及episodic_ai/ad/au、event_ai/ad/au六条同步触发器memory_tree/chunks.dbuser_version 2mem_tree_trees、mem_tree_buffers、mem_tree_chunks、mem_tree_chunk_embeddings、mem_tree_summaries、mem_tree_summary_embeddings、mem_tree_entity_index、mem_tree_entity_edges、mem_tree_entity_hotness、mem_tree_jobs、mem_tree_score、mem_tree_ingested_sources、mcp_writes及各类去重/重嵌入跳过的辅助表。manifest 行格式为db 相对路径\t类型\t名称\t归一化 SQL另外每库一行pragma\tuser_version\tN。SQL 会先做空白归一化把任意空白串折叠为单个空格因为 SQLite 原样保存 DDL 文本——缩进变化不该被视为 Schema 变更而列类型的改动必须算。四、为什么以二进制形式提交进 Git仓库根目录的 .gitattributes 中有两条关键规则* textauto eollf tests/fixtures/memory_golden/**/*.db binary第一条是全仓库通用的行尾规则会把文本文件在检出时统一为 LF。如果.db文件不例外git 就会把 blob 内部长得像 CRLF的字节序列当作行尾重写逐字节破坏数据库文件。binary标记隐含-text -diff确保这些文件按字节原样存储与检出。重新生成时还有一层配套清理regenerate_golden_fixture在发布固件前会执行prune_non_db_files删除所有非*.db文件。原因是 SQLite 即使以只读方式打开库也会重建-shm/-wal兄弟文件——它们是进程局部状态绝不能混入固件否则固件将不可复现。五、三道关卡golden fixture 测试套件怎么咬人tests/memory_golden_fixture_e2e.rs 是固件的消费方与门禁本身包含三道相互补充的校验Gate 1 —— 已提交 fixture 的磁盘 Schema 与已提交 manifest 逐对象相等golden_fixture_schema_matches_the_committed_manifest。它把固件复制到临时目录避免触碰原件用schema_manifest重新导出与 manifest 做集合相等比较多一个对象、少一个对象都会被明确报告为MISSING/UNEXPECTED。Gate 2 —— 当前代码构建的全新工作区Schema 与 manifest 完全一致fresh_workspace_schema_matches_the_committed_manifest。这一步补齐了 Gate 3 的盲区CREATE TABLE / INDEX / TRIGGER IF NOT EXISTS对已存在的同名对象是空操作所以原地重定义只有对一个全新库才可见。此外它还会主动触达延迟初始化的 crate KV 层kv_global/kv_namespace避免把惰性建表误报成 drift。Gate 3 —— 行级读回 重开稳定性 第二进程重开golden_fixture_rows_read_back_and_schema_is_stable_after_reopen。它把固件复制件用当前构建的UnifiedMemory::new打开每次打开都会跑一遍CREATE TABLE IF NOT EXISTS引导然后通过memory::ops生产路径读回每一层的数据两个命名空间的文档 key、global/namespace KV、图三元组命中数、episodic 会话、段、事件、profile facet、叶子 chunk、摘要节点、树是否封存到根断言所有 embedding 层段、事件、chunk、摘要读回的都是精确种子向量[0.25, 0.5, 0.75, 1.0]——任何向量编码或列的改动都会让老 embedding 作废执行固定查询golden fixture schema的召回并精确断言返回结果集recall_chunks的完整列表覆盖文档、KV 值与事件多个数据源的命中组装打开前后各导出一份 manifest断言 Schema 在打开过程中不被改动最后派生第二个进程second_process_readback重新打开同一份工作区新进程拥有全新的 SQLite 库状态和冷页缓存能捕捉进程内重开会被连接池掩盖的 WAL / journal 模式问题。测试的自我隔离设计由于所有测试都直接绑定进程全局的内存客户端套件把HOME、OPENHUMAN_WORKSPACE通过EnvVarGuard 全局ENV_LOCK串行化并预先安装内存宿主 seaminstall_memory_host_seams。而 Gate 1 / Gate 2 不触碰进程全局可以并行执行——注释里明确说明这是刻意安排的调度边界。六、重新生成固件何时、为何、怎么做重新生成不是修测试的手段而是重新设定门禁基准。脚本 scripts/regen-memory-golden-fixture.sh 的头部注释给出了两条铁律只有当你在有意修改内存存储的磁盘 Schema并且同时准备了老用户工作区的迁移方案时才运行它如果memory_golden_fixture_e2e失败了、而你没打算改 Schema那么这个失败本身就是 bug——先去修 bug而不是刷新固件。运行方式scripts/regen-memory-golden-fixture.sh脚本执行的动作序列全部可在 tests/memory_golden_fixture_e2e.rs 的regenerate_golden_fixture测试中看到记录当前HEAD的 commit SHA若src/openhuman/memory有未提交改动打印警告固件捕获的是工作树内容但 README 记录的 SHA 是当前 HEAD建议先提交以GGML_NATIVE环境变量默认OFF运行被#[ignore]标记的测试cargo test --manifest-path Cargo.toml --test memory_golden_fixture_e2e regenerate_golden_fixture -- --exact --ignored --nocapture测试在临时 staging 目录中绑定全局内存客户端调用种子函数golden::seed灌入全部数据对每个.db执行PRAGMA wal_checkpoint(TRUNCATE)与VACUUM折叠 WAL、压缩文件使其自包含发布只复制*.db到tests/fixtures/memory_golden/workspace/随后从发布目录用schema_manifest导出 manifest.txt最后清理重新出现的-wal/-shm脚本末尾覆写 README写入新 SHA 与时间戳并打印du -sh与git status供确认。种子器本身位于 tests/support/memory_golden.rs。值得注意的工程细节它曾经是库内模块openhuman::memory::store_goldenpub mod而非#[cfg(test)]导致七处tinymemory_core::引用进入生产依赖图——仅仅为了给 fixture 播种。issue #5560 后它被移出库代码成为测试目标内的模块tinymemory-core降级为 dev-dependencyfeatures [test-support]这正是固件不该污染生产二进制的示范。七、评审规则触碰该目录 一次 Schema 迁移评审README 与测试注释共同给出的一条最重要评审规则一个 diff 只要触碰tests/fixtures/memory_golden/就必须按Schema 迁移评审对待而不是测试数据刷新。评审要点其一要求提交者给出承载现有用户工作区迁移的方案其二核对manifest diff 与 DDL diff 是否一致。测试注释也坦承这是整套机制最薄弱的接缝如果作者在同一提交里既改 Schema 又重新生成固件门禁会重新变绿。因此它需要评审规则作为互补控制。manifest 的比较采用集合相等BTreeSet错误信息会分别列出MISSING固件有而新代码不再产生与UNEXPECTED新代码产生而固件没有让评审者一眼看清漂移方向。八、总结这套模式的复用价值Golden memory-workspace fixture 的实质是三层组合拳捕获而非合成基准数据来自真实构建的真实写入路径杜绝了为测试手搓 Schema 常量带来的虚假安全感派生而非手写manifest 由.db反推任何改代码 改清单的作弊都必须先重写二进制从而把 Schema 变更变成 diff 中可见、可评审的行为读回而非仅解析三关卡里包含行级读回、精确向量比对、固定查询召回、第二进程冷启动重开覆盖的不只是Schema 能解析而是用户数据能在新代码下完整存活。对于任何维护长期落盘数据的项目这套真实工作区快照 派生清单 强制重新生成的门禁模式都可以直接借鉴——它把不可见的兼容性风险转化为提交评审中最显眼的那一行 diff。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考