Part of the v0.58.7 → HEAD TinyAgents-migration audit (see parent issue). Repairs the memory read→dedupe→write→update-index protocol (#4444 / PR #4444, commit 19bf3aa).
Problem
The protocol's write cycle can only be closed by a successful update_memory_md call (src/openhuman/agent/harness/memory_protocol.rs:73-76,138-147), and every durable write appends an instruction to call it. But UpdateMemoryMdTool is never registered in the production registry: all_tools_with_runtime (src/openhuman/tools/ops.rs:268-270) registers MemoryStoreTool/MemoryRecallTool/MemoryForgetTool only; the tool is merely re-exported (src/openhuman/tools/impl/filesystem/mod.rs:30) and constructed once in a test. The archivist's named = ["update_memory_md", ...] (src/openhuman/agent_registry/agents/archivist/agent.toml:23) silently resolves away because subagents only filter the parent set.
Result: memory_store succeeds → middleware instructs the model to call update_memory_md → unknown-tool error → tracker never sees IndexUpdate → escalated "MEMORY.md index is drifting… Reconcile it now" on every subsequent write (memory_protocol.rs:138-144) + after_agent stale-index warning every run (src/openhuman/tinyagents/middleware.rs:1589-1603). Permanent, unsatisfiable nag loop; wasted model round-trips; MEMORY.md never index-updated.
Secondary problems (fix together)
update_memory_md writes are an unlocked, non-atomic read-modify-write (src/openhuman/tools/impl/filesystem/update_memory_md.rs:159-190): concurrent runs (parallel forks, cron) lose an append; crash mid-write truncates MEMORY.md. Becomes live the moment registration is fixed.
remember_preference/save_preference durable writes are classified MemoryOp::Other (memory_protocol.rs:79-98) — undocumented gap in write classification.
Fix plan
- Register
UpdateMemoryMdTool in all_tools_with_runtime (src/openhuman/tools/ops.rs), respecting the same visibility rules as the other memory tools.
- Make the write atomic and serialized: temp-file + rename, guarded by a per-workspace async lock (or reuse an existing file-lock helper). The per-run
MemoryProtocolTracker has zero cross-run awareness, so file-level safety is the only guard.
- Classify
remember_preference/save_preference as durable writes in the protocol (or document why not).
- Add a startup/registry inventory assertion so a protocol-mandated tool missing from the registry fails a test, not production (mirror the "adapter inventory test" pattern).
Acceptance criteria
- A live turn that stores a memory can complete the full read→dedupe→write→index cycle with zero unknown-tool errors and no drift warnings.
- Two concurrent index updates both survive; a killed process never leaves a truncated MEMORY.md.
- Inventory test fails if
memory_protocol.rs mandates a tool that isn't registered.
Part of the v0.58.7 → HEAD TinyAgents-migration audit (see parent issue). Repairs the memory read→dedupe→write→update-index protocol (#4444 / PR #4444, commit 19bf3aa).
Problem
The protocol's write cycle can only be closed by a successful
update_memory_mdcall (src/openhuman/agent/harness/memory_protocol.rs:73-76,138-147), and every durable write appends an instruction to call it. ButUpdateMemoryMdToolis never registered in the production registry:all_tools_with_runtime(src/openhuman/tools/ops.rs:268-270) registersMemoryStoreTool/MemoryRecallTool/MemoryForgetToolonly; the tool is merely re-exported (src/openhuman/tools/impl/filesystem/mod.rs:30) and constructed once in a test. The archivist'snamed = ["update_memory_md", ...](src/openhuman/agent_registry/agents/archivist/agent.toml:23) silently resolves away because subagents only filter the parent set.Result:
memory_storesucceeds → middleware instructs the model to callupdate_memory_md→ unknown-tool error → tracker never seesIndexUpdate→ escalated "MEMORY.md index is drifting… Reconcile it now" on every subsequent write (memory_protocol.rs:138-144) +after_agentstale-index warning every run (src/openhuman/tinyagents/middleware.rs:1589-1603). Permanent, unsatisfiable nag loop; wasted model round-trips; MEMORY.md never index-updated.Secondary problems (fix together)
update_memory_mdwrites are an unlocked, non-atomic read-modify-write (src/openhuman/tools/impl/filesystem/update_memory_md.rs:159-190): concurrent runs (parallel forks, cron) lose an append; crash mid-write truncates MEMORY.md. Becomes live the moment registration is fixed.remember_preference/save_preferencedurable writes are classifiedMemoryOp::Other(memory_protocol.rs:79-98) — undocumented gap in write classification.Fix plan
UpdateMemoryMdToolinall_tools_with_runtime(src/openhuman/tools/ops.rs), respecting the same visibility rules as the other memory tools.MemoryProtocolTrackerhas zero cross-run awareness, so file-level safety is the only guard.remember_preference/save_preferenceas durable writes in the protocol (or document why not).Acceptance criteria
memory_protocol.rsmandates a tool that isn't registered.