From e4b1dd91ba3fa687bd59cf0227046d65db07085f Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Sun, 3 May 2026 23:31:50 -0700 Subject: [PATCH] =?UTF-8?q?fix(memory):=20rollback=20cycle-reflection=20tr?= =?UTF-8?q?ailer=20=E2=80=94=20agents=20losing=20turn=20budget?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2.J's withCyclesDirective trailer (#295) instructed agents to call \`commonly_save_my_memory({sections:{cycles:{append:...}}})\`, but the openclaw extension exposes no tool by that name — agents waste 3+ turns per heartbeat hunting for it before falling back to the real \`commonly_write_agent_memory\`. The wasted budget caused Nova to go silent on Sam's '@nova hey' (06:01 UTC) and 'hey' (06:21 UTC) DMs immediately after the trailer rolled out via reprovision-all. Verified in /state/agents/nova/sessions/*.jsonl: 3× attempted tool calls for the missing 'commonly_save_my_memory' before 1× successful 'commonly_write_agent_memory'. 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 forward fix ships. Forward fix path (separate branch): add \`commonly_log_cycle(content, podId?)\` to the Team-Commonly/openclaw extension, build + push the gateway image, then update the trailer to instruct agents to call the new tool name. After that, this no-op gets reverted in one line. --- backend/routes/registry/presets.ts | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/backend/routes/registry/presets.ts b/backend/routes/registry/presets.ts index f4339416..aae7058e 100644 --- a/backend/routes/registry/presets.ts +++ b/backend/routes/registry/presets.ts @@ -2974,16 +2974,30 @@ Rules: - After this call (or skip), return \`HEARTBEAT_OK\`. `; -// Defensive helper: append the cycle-reflection trailer to a template. -// No-op when the template already contains the trailer (idempotent across -// reprovisions). Applied at the provision/reprovision callsite — keeping the -// 25 individual template strings untouched and preserving the -// `customizations.heartbeat` flag's "user edited the template" semantics. +// Defensive helper: would append the cycle-reflection trailer to a template. +// +// **2026-05-04 ROLLBACK — currently a NO-OP.** The trailer instructs agents +// to call `commonly_save_my_memory({sections:{cycles:{append:...}}})`, but no +// openclaw extension tool with that name exists today — agents waste 3+ +// tool-call turns per heartbeat hunting for it before falling back to the +// real `commonly_write_agent_memory`, which exhausts their turn budget and +// causes them to skip DM responses. Verified on Nova: silent on Sam's "hey +// Nova" 2026-05-04 06:01 UTC and "hey" 06:21 UTC, immediately after the +// trailer rolled out via reprovision-all (Phase 2.J). +// +// Forward fix path (separate branch): add `commonly_log_cycle(content, +// podId?)` to the openclaw extension (Team-Commonly/openclaw fork), build +// + push gateway image, then re-enable this helper to instruct agents to +// call the new tool name. Until that lands, the helper returns the template +// unchanged so HEARTBEAT.md reverts to its pre-Phase-2.J shape on the next +// reprovision-all. +// +// The helper signature stays exported so the four call-sites in provision.ts +// + reprovision.ts continue to compile without churn — flipping back to the +// real implementation is a one-line change once the openclaw tool ships. function withCyclesDirective(template: string | null | undefined): string { const t = typeof template === 'string' ? template : ''; - if (!t) return t; - if (t.includes('## Memory cycle reflection')) return t; - return t.replace(/\s*$/, '') + CYCLES_REFLECTION_TRAILER; + return t; } module.exports = { PRESET_DEFINITIONS, DEFAULT_BRANCH, withCyclesDirective };