oh-my-openagent memory-core 包级指令面审查:13 个源码域、核心不变量与公共 API 的一致性验证
【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
导读
oh-my-openagent(OmO)在packages/memory-core/中维护着一个"harness 中立"(harness-neutral)的智能体记忆引擎:以 Git 仓库为底层的 Markdown 记忆文件系统(MemFS)、原子化的记忆工具、提示词编译、反射调度、会话检索、同步与种子内容。本文以仓库中的审查记录 .omo/evidence/20260812-init-deep/manual-review.md 为主线,完整还原一次"包级指令面审查"(manual instruction-surface review)的范围、精确校验方法与 PASS 判定标准,并结合 packages/memory-core/AGENTS.md 与源码实现,逐层拆解 memory-core 的 13 个源码域、8 条核心不变量、7 组公共 API 表面以及包级 QA 流程。读完本文,你将掌握如何用"路径存在性 + 符号存在性"的机械检查验证文档与源码同步,并理解该引擎每个子系统的职责边界与不变量约束。
一、审查背景:为什么需要"指令面审查"
在像 oh-my-openagent 这样包含大量 core 包与多个 harness 适配器(Senpi、Pi、OpenCode 等)的仓库中,每个包都有一份AGENTS.md,作为面向维护者与 Agent 的"指令面"(instruction surface):它告诉后续修改者这个包能做什么、不允许做什么、如何测试。如果指令面与源码脱节,后续改动就可能破坏不变量。
这次审查(记录于 manual-review.md)针对的是memory-core包的指令面,其核心目标可以概括为三条:
- 指南必须是"包级范围"的:只描述 memory-core 自己拥有的领域,不得重复根级 OpenCode/Codex QA 指令,也不得越界描述适配器的完整架构;
- 指南中每一个被点名的路径与符号都必须真实存在于当前源码;
- 适配器特有行为必须归属 Senpi 组件,不得被反向导入 core 包。
审查结论为PASS(NAMED_PATHS_OK/NAMED_SYMBOLS_OK/STYLE_OK),并且"包表链接是唯一一次祖先级编辑"——即指南只向上引用过一次packages/AGENTS.md的包表格,其余全部是包内自洽内容。
二、审查范围:四份文档的职责划分
审查精确划定了四份关键文档,每份承担不同职责,理解这份分工是复现审查的前提:
| 文档 | 职责 |
|---|---|
| packages/AGENTS.md | 仓库级指南,尤其关注其中的Core 包表格,用于确认 memory-core 在包矩阵中的位置与包表链接的合法性 |
| packages/memory-core/AGENTS.md | 本次审查的主体:memory-core 的包级指令面,从上到下逐段核对 |
| packages/memory-core/src/index.ts | 验证文档所声称的公共 barrel(唯一公共导出面)是否与代码一致 |
| packages/omo-senpi/src/components/memory/AGENTS.md | 核对adapter/core 边界,避免出现重复的适配器指令 |
这四份文档对应了指令面的四个层次:仓库层(包归属)→ 包层(领域职责)→ 导出层(公共 API)→ 适配器层(消费边界)。审查确认:Senpi 组件仍然是适配器注册与生命周期行为的唯一所有者,而 memory-core 保持零 Senpi 导入。
三、memory-core 的 13 个源码域(ANATOMY)
memory-core的指令面将其实现组织为 13 个源码目录加一个测试文件,公共入口是 src/index.ts 的 barrel 导出(export * from "./git"…"./seeds",共 17 个导出组,含personas与recall两个辅助域)。下表按 AGENTS.md 的 ANATOMY 表整理,并补充各目录的核心职责细节:
| 目录 | 责任 |
|---|---|
src/git/ | Git 命令边界、clean-tree 检查、提交、合并、remote 与类型化 git 错误 |
src/identity/ | 记忆身份解析与OMO_MEMORY_HOME目录布局 |
src/locks/ | 记忆写入、反射调度、会话记录状态的跨进程锁;机器级recall-wake计数租约(每槽位recall-wake.slot-<n>.lock、FIFOrecall-wake.tickets/、默认 2 槽、基于证明的陈旧恢复、有界等待最终以RecallWakeBusyError结束) |
src/memfs/ | 记忆路径校验、Markdown frontmatter 解析、hook 脚本安装 |
src/tools/ | memory与memory_apply_patch操作、patch 解析、类型化工具错误、自动提交行为 |
src/journal/ | 每会话会话记录游标、反射快照与持久化日志状态 |
src/facts/ | 持久化事实管道:队列 + 游标水位、失败退避/存储、负载上限、人物路由、恢复、变更规划 |
src/people/ | 人物卡文法:解析/序列化、slug 规则、保留 slug、观察项 |
src/soul/ | Soul 文件路径与身份作用域的 soul-notice 水位消费 |
src/reflection/ | 触发求值、运行预留、worktree 执行、完成校验、合并结果、孤儿清扫(回收无人拥有的 worktree/分支)、以及重复失败后的 park 策略(每间隔一次半开探测) |
src/compile/ | 将已提交的记忆修订编译为标记化的系统提示块,并按模板哈希缓存 |
src/search/ | 查询解析、会话记录 provider、排序的记忆/会话检索 |
src/sync/ | 远端镜像同步与秘密脱敏 |
src/reminders/ | 反射与记忆维护提醒生成 |
src/seeds/ | 默认记忆块与首次运行仓库播种 |
src/concurrency/ | 锁与多写入者测试用的子进程夹具,不是公共运行时模块(也正因如此,它未出现在 index.ts 的 barrel 中) |
从源码结构可以推断,src/concurrency/是唯一一个"仅供测试"的目录:barrel 明确不导出它,AGENTS.md 也将其标注为非公共运行时模块,这体现了"公共表面必须显式、最小"的设计原则。
四、核心不变量:memory-core 的行为底线
AGENTS.md 定义了 8 条核心不变量,它们是本次审查"STYLE_OK"与后续代码评审的事实基准:
保持 harness 中立:生产代码与包依赖不得导入 Senpi、Pi、OpenCode 适配器或其他 harness 特定包。该边界由 src/harness-neutrality.test.ts 强制:它先检查
package.json中 dependencies/devDependencies/peerDependencies 的包名,再递归扫描src/下每个.ts文件,断言不包含@code-yeongyu/senpi、@earendil-works/、@mariozechner/pi-、@oh-my-opencode/omo-senpi、@oh-my-opencode/senpi-task等禁用前缀的导入。把记忆仓库当作事务状态:写工具必须先获取
memory-write锁、要求仓库干净、校验路径、执行单次操作,且只提交受影响路径。不得绕过GitMemoryRepo、锁域或工具入口。从已提交状态编译:提示编译只能针对
HEAD或显式修订,未提交的工作树内容不构成权威记忆。这一点在 src/compile/compile.ts 中落实:compileMemoryBlockAtRevision通过repo.lsTree(revision)枚举树、repo.show(revision, path)读取文件,从未触碰工作树。保持 Markdown 契约:记忆文件必须有含非空
description的 YAML frontmatter;read_only: "true"阻止修改;保持 UTF-8、规范化仓库相对路径与 LF 输出。对应实现位于 src/tools/memory.ts 的loadEditable(read_only检查)与readUtf8(UTF-8/UTF-16 BOM 检测与TextDecoder("utf-8", { fatal: true })严格解码)。Frontmatter 是严格 YAML,一处文法全局生效:
renderMemoryFile是唯一写入者,它对yaml包无法原样读回的标量加引号并重新解析自己的头部;读取端解码带引号标量、保留非契约键(extra)以让 SKILL.md 的name/version在编辑后存活,仅对既有文件回退到旧版"首个冒号"文法。describeFrontmatterViolation是 pre-commit hook 规则、validateCompletion与normalizeMemoryFrontmatter(以公共 git 目录中的标记为键的一次性旧版修复)的共享闸门。禁止手写不带引号的description:。保持反射转移确定性:手动触发 > 压缩触发 > 步数触发;同时只允许一个活动运行与一个已合并的待处理预留。这由 src/reflection/machine.ts 中的优先级表支撑:
step-count: 1、compaction: 2、manual: 3,dream 各 origin 独立排序。锁保持领域特定:使用
memory-write、reflection-scheduler或会话专属锁,不得用单一全局锁替代,也不得添加基于计时的测试。外部同步前必须脱敏:远端镜像输出必须经过 sync 脱敏层,严禁把含秘密的原始日志或配置提交进记忆。
此外,AGENTS.md 还强调两条事实管道纪律:事实状态持久且 fail-closed(队列/游标/已消费写入在身份作用域锁下原子发布,.tmp+ rename、模式0o600;畸形 JSON 解析为空而不阻塞;入队/消费水位永不回退,排序遵循规范化的日志位置/快照边界,绝不做词法 message-ID 比较);行为模式绝不存入人物卡(卡片行只允许IDENTITY/ATTRIBUTE/RELATIONSHIP/INSTRUCTION前缀与有界元数据)。
五、公共 API 表面:从文档到源码的 7 组符号
AGENTS.md 列出了 7 组公共 API,本次审查的NAMED_SYMBOLS_OK正是逐一对它们做git grep验证。下表将文档声明与源码落点一一对应(均已在本仓库确认存在):
| 文档声明 | 源码位置 |
|---|---|
runMemoryTool():实现create、str_replace、insert、delete、rename、update_description | src/tools/memory.ts |
runMemoryApplyPatch():在记忆仓库内应用多文件 Codex 风格 patch | src/tools/memory-apply-patch.ts |
GitMemoryRepo:仓库初始化、clean 检查、提交、修订、合并 worktree、remote 检测 | src/git/repo.ts |
evaluateTransitions()/reserveTransition()/completeTransition():纯反射状态机 | src/reflection/machine.ts |
compileMemoryBlock()/compileMemoryBlockAtRevision():渲染注入到 harness 提示中的已提交记忆投影 | src/compile/compile.ts |
FactsQueue、applyFactsBatch()、planFactsMutation() | src/facts/ |
consumeSoulNoticeDelta() | src/soul/ |
以工具层为例,runMemoryTool的每个命令都遵循同一事务骨架:先commitMemoryWrite(持锁、clean 检查、校验、执行、只提交受影响路径),失败时把 patch 解析错误(MemoryPatchParseError/MemoryPatchHunkError)与其他错误统一包装为类型化MemoryToolError。str_replace的实现刻意只替换第一处匹配(与 letta-code 实测行为对齐,见 Senpi 组件 AGENTS.md 的 divergence #11),找不到old_string时返回明确错误;insert要求insert_line为数字并把行号下限钳制为 1。这些细节说明公共 API 不只是签名,还包含错误语义与边界行为。
六、精确检查:路径与符号的机械验证
审查最硬核的部分是"精确检查"(Exact checks),它用两条 bash 循环把文档中的每个声明变成可执行断言:
# 1) 路径存在性:文档点名的 14 个源码入口必须全部存在 for p in src/git src/identity src/locks src/memfs src/tools src/journal \ src/reflection src/compile src/search src/sync src/reminders src/seeds \ src/concurrency src/index.ts src/harness-neutrality.test.ts; do test -e "packages/memory-core/$p" done # 2) 符号存在性:文档声明的 6 组公共符号必须在 src 内可被 grep 到 for sym in runMemoryTool runMemoryApplyPatch GitMemoryRepo \ evaluateTransitions reserveTransition completeTransition \ compileMemoryBlock compileMemoryBlockAtRevision; do git grep -q "$sym" -- packages/memory-core/src done本仓库复现这两条命令的结果为:14 个路径全部OK,8 个符号(completeTransition与compileMemoryBlockAtRevision也在文档列出的同一组符号循环内)均能在src/中找到。审查记录将观察结果总结为三行状态:
NAMED_PATHS_OK NAMED_SYMBOLS_OK STYLE_OKSTYLE_OK对应文风检查:指南通篇避免了被禁止的破折号字符与仓库禁用的填充语,且唯一的祖先级编辑就是包表链接。这套"先机械断言、后人工风格判断"的流程本身即可复用到其他 core 包的指令面维护中。
七、审查结论与边界确认
审查 verdict 明确了五条判定依据:
- 指南是包级范围的:完整映射了 13 个源码域、核心不变量、公共表面、消费者、包级 QA 与本地反模式;
- 没有复述根级 OpenCode/Codex QA 指令,也没有展开完整的适配器架构;
- Senpi 组件始终是适配器注册与生命周期行为的唯一所有者(见 packages/omo-senpi/src/components/memory/AGENTS.md 的 Anatomy 表:
index.ts工厂、wiring.ts注册面、identity-runtime.ts、worker/等全部留在适配器侧); - 每个被点名的路径与符号都在当前源码中存在;
- 指南避免了被禁字符与仓库禁用填充语,包表链接是唯一祖先级编辑。
最终结论:PASS。
八、复现审查与包级 QA
如果你要在本地对 memory-core 做同样或后续的验证,可直接使用 AGENTS.md 给出的包级 QA 命令:
# 运行包内全部单元测试(含 harness-neutrality 边界测试) bun test packages/memory-core/src/ # 包级类型检查 bun run --cwd packages/memory-core typecheckAGENTS.md 还给出了聚焦改动的测试策略:先跑最近的同目录*.test.ts,再跑整个包套件;并发测试必须用有界超时精确等待状态或进程事件,严禁加入固定 sleep 或重试循环——这与"禁止基于计时的测试"的不变量一脉相承。
九、反模式清单:评审与自检的检查表
AGENTS.md 以六条反模式收尾,它们同时是评审者和 Agent 的"红线":
- 在
memory-core中导入 harness 包(违反中立性,harness-neutrality.test.ts会直接红灯); - 不经过路径校验、frontmatter 解析、加锁与原子 git 提交,直接写记忆 Markdown;
- 把脏工作树当作编译记忆来读(违反"从已提交状态编译");
- 修改
read_only块或接受非 UTF-8 记忆文件; - 吞掉 git、锁、合并或反射失败;
- 用"计时运气"测试跨进程行为。
这套清单的价值在于它把抽象不变量翻译成了可直接在 code review 中勾选的条目:任何一条命中,都意味着新的改动违反了 memory-core 的行为契约。
结语
一次 PASS 的指令面审查,本质上是在回答三个问题:指南是否只属于自己包的领域、指南点名的每个路径和符号是否真实、适配器边界是否清晰。围绕 manual-review.md 展开的这次审查,完整覆盖了 memory-core 的 13 个源码域、8 条核心不变量、7 组公共 API 与包级 QA 流程,并以可复现的 bash 断言作为证据。对于需要向 memory-core 贡献代码的开发者而言,packages/memory-core/AGENTS.md 既是地图也是契约——先读它,再动代码。
【免费下载链接】oh-my-openagentOmO: Just type "mass ulw" keyword with your prompt. Now you are the master of graph engineering.项目地址: https://gitcode.com/gh_mirrors/oh/oh-my-openagent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考