feat(memory): inject ADR-012 cycle-reflection trailer into all heartbeat templates#295
Closed
feat(memory): inject ADR-012 cycle-reflection trailer into all heartbeat templates#295
Conversation
…eat templates
Empirical finding from the post-deploy observation window: the §10.3
inline cue prepended to scheduler heartbeat payload.content was NOT
sufficient to produce cycle writes. Five heartbeats acked across the
cluster after Phase 2 deploy with 0 new agent-authored cycles[]
entries — agents follow HEARTBEAT.md's structured steps verbatim and
deprioritize the inline narrative directive.
Fix: add the cycle-write directive to HEARTBEAT.md itself — the file
the model treats as authoritative. Implemented as a single chokepoint
helper (`withCyclesDirective`) applied at provision/reprovision time:
- New `withCyclesDirective(template)` in presets.ts: appends a uniform
"## Memory cycle reflection" trailer to any heartbeat template.
Idempotent (no-op if the trailer is already present); preserves the
customizations.heartbeat flag's "user edited" semantics by leaving
the 25 individual template strings untouched.
- Wrapped all four call-sites in provision.ts and reprovision.ts that
read matchedPreset.heartbeatTemplate (provisioner + AgentProfile
cache).
Trailer instructs: append a ≤500-char takeaway via
commonly_save_my_memory({sections:{cycles:{append:{content}}}}) just
before HEARTBEAT_OK; skip if nothing memorable; specific over generic;
past entries surface in cyclesDigest on every future event so writing
isn't wasted.
Single point of injection means new presets automatically get the
directive without per-preset edits. reprovision-all on dev pushes the
new HEARTBEAT.md to all 25 agent PVCs in one pass.
…lifecycle Folds Phase 3 docs into the same PR as the §10.3 trailer-inject helper. - Event Queue: document pending → delivered → acked lifecycle, mutate-on-claim in list(), status-gated ack with monotone $max bump on lastSeenRevision. - New 'Memory contract (ADR-012)' section: sections envelope (with system_exchanges + cycles writer/reader/cap matrix), cycles append shape, four-field event payload digest, revision contract, invariant 8a carve-out. - Document the HEARTBEAT.md trailer auto-inject as the single chokepoint for the cycle-write directive.
samxu01
added a commit
that referenced
this pull request
May 4, 2026
…eat templates (#295) Empirical finding from the post-Phase-2 observation window: the §10.3 inline cue prepended to scheduler heartbeat payload.content was NOT sufficient to produce cycle writes. Five heartbeats acked across the cluster after Phase 2 deploy with 0 new agent-authored cycles[] entries. Agents follow HEARTBEAT.md's structured steps verbatim and deprioritize the inline narrative directive — confirms the hierarchy: authoritative workspace file > inline payload.content > structured metadata. Fix: add the cycle-write directive to HEARTBEAT.md itself, where the model treats it as authoritative. Implemented as a single chokepoint helper applied at provision/reprovision time rather than editing 25 individual heartbeatTemplate strings. - New `withCyclesDirective(template)` in presets.ts: appends a uniform '## Memory cycle reflection' trailer to any heartbeat template. Idempotent (no-op if the trailer is already present); preserves the customizations.heartbeat flag's 'user edited' semantics by leaving the 25 individual template strings untouched. - Wrapped all four call-sites in provision.ts + reprovision.ts that read matchedPreset.heartbeatTemplate (provisioner + AgentProfile cache). Trailer instructs: append ≤500-char takeaway via commonly_save_my_memory({sections:{cycles:{append:{content}}}}) just before HEARTBEAT_OK; skip if nothing memorable; specific over generic; past entries surface in cyclesDigest on every future event so writing isn't wasted. Single point of injection means new presets automatically get the directive without per-preset edits. reprovision-all on dev pushes the new HEARTBEAT.md to all 25 agent PVCs in one pass. Folds in ADR-012 Phase 3 docs: - AGENT_RUNTIME.md: new 'Memory contract (ADR-012)' section + Event Queue lifecycle subsection (mutate-on-claim, monotone \$max bump, dup-ack semantics).
Contributor
Author
|
Squash-merged to main as 4097a8d. |
2 tasks
samxu01
added a commit
that referenced
this pull request
May 4, 2026
Phase 2.J's withCyclesDirective trailer (PR #295) instructed agents to call commonly_save_my_memory({sections:{cycles:{append:...}}}), but no openclaw extension tool with that name exists today. Agents waste 3+ turn-budget tool calls per heartbeat hunting for it before falling back to the real commonly_write_agent_memory, which exhausts their budget before they can post a chat reply. Verified on Nova: silent on Sam's "hey Nova" (06:01 UTC) and "hey" (06:21 UTC) DMs immediately after the trailer rolled out via reprovision-all. Pre-rollout, Nova was responding cleanly to four prior pings within minutes. Session log /state/agents/nova/sessions/*.jsonl confirms 3× attempted 'commonly_save_my_memory' tool calls (missing tool name) before 1× successful 'commonly_write_agent_memory' fallback. This commit makes withCyclesDirective a no-op so HEARTBEAT.md reverts to its pre-Phase-2.J shape on the next reprovision-all. The helper + its four call-sites stay in place so re-enabling is a one-line flip once the openclaw extension exposes a real cycles-write tool. Forward fix path (separate branch): add commonly_log_cycle(content, podId?) to Team-Commonly/openclaw fork, build + push gateway image, update trailer to call the new tool name, flip this back to the real implementation, reprovision-all + observe.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 2 (#293) closed the read loop at the protocol level but the §10.3 inline cue on `payload.content` was empirically insufficient — 0 new `cycles[]` writes across 25 agents in the post-deploy window. Agents follow `HEARTBEAT.md`'s structured steps verbatim and deprioritize the inline narrative directive.
This PR moves the cycle-write directive into `HEARTBEAT.md` itself, where the model treats it as authoritative.
Approach: single chokepoint
Instead of editing 25 individual `heartbeatTemplate` strings in `presets.ts`:
New presets automatically inherit the directive. The 25 raw template strings stay untouched, so the `customizations.heartbeat` flag's "user edited the template" semantics are preserved.
Test plan
🤖 Generated with Claude Code