Skip to content

Dreaming pipeline promotes empty-result placeholder "No strong candidate truths surfaced" into MEMORY.md #80858

Description

@chopra2007

Summary

On days where the REM dreaming phase finds zero candidate truths, the pipeline still writes a placeholder bullet into the REM dream file. That placeholder is subsequently ingested by light sleep, emitted as a - Candidate: line into the daily memory file, and then promoted by applyShortTermPromotions into the long-term workspace/MEMORY.md. Each empty-REM day permanently bloats MEMORY.md with a meaningless entry.

Version

[email protected] (npm global install).

Reproduction

Run the dreaming pipeline on a day where REM produces no candidate truths above the 0.45 confidence threshold (e.g. a low-activity day).

  1. workspace/memory/dreaming/rem/YYYY-MM-DD.md ends up containing:

    ### Possible Lasting Truths
    - No strong candidate truths surfaced.
    
  2. The next light sleep pass ingests that placeholder bullet as a memory entry. buildLightDreamingBody emits it as a Candidate line into the daily memory file workspace/memory/YYYY-MM-DD.md:

    - Candidate: Possible Lasting Truths: No strong candidate truths surfaced.
      - confidence: 0.00
      - evidence: memory/YYYY-MM-DD.md:443-443
      - recalls: 0
      - status: staged
    
  3. applyShortTermPromotions (in dist/short-term-promotion-*.js) treats it as a valid candidate. It passes isContaminatedDreamingSnippet (no confidence/evidence/status/recalls keys in the snippet itself) and accumulates enough score to be promoted. workspace/MEMORY.md gains:

    <!-- openclaw-memory-promotion:memory:memory/YYYY-MM-DD.md:443:443 -->
    - - Candidate: Possible Lasting Truths: No strong candidate truths surfaced. [score=0.832 recalls=0 avg=0.620 source=memory/YYYY-MM-DD.md:13-13]
    

In my workspace this produced three identical noise entries (2026-04-19, 2026-04-20, 2026-04-21) under three separate ## Promoted From Short-Term Memory (YYYY-MM-DD) headers.

Expected behavior

Days with zero candidate truths should add nothing to long-term MEMORY.md. Empty results are not findings.

Actual behavior

Every empty-REM day produces three pieces of bloat — a placeholder bullet in the REM dream file, a Candidate line in the daily memory file, and a promoted entry in MEMORY.md.

Root cause

In dist/dreaming-phases-*.js, previewRemDreaming:

const bodyLines = [
    "### Reflections",
    ...reflections,
    "",
    "### Possible Lasting Truths",
    ...candidateTruths.length > 0
        ? candidateTruths.map((entry) => `- ${entry.snippet} [confidence=${entry.confidence.toFixed(2)} evidence=${entry.evidence}]`)
        : ["- No strong candidate truths surfaced."]
];

The else branch unconditionally emits a human-readable placeholder line into the REM file even when there is nothing to promote. Downstream the placeholder becomes indistinguishable from a real candidate.

Proposed fix

1. dist/dreaming-phases-*.js — skip the entire ### Possible Lasting Truths section when candidateTruths.length === 0:

const bodyLines = [
    "### Reflections",
    ...reflections,
    ...(candidateTruths.length > 0 ? [
        "",
        "### Possible Lasting Truths",
        ...candidateTruths.map((entry) => `- ${entry.snippet} [confidence=${entry.confidence.toFixed(2)} evidence=${entry.evidence}]`)
    ] : [])
];

2. dist/short-term-promotion-*.js — defensive filter in applyShortTermPromotions so historical placeholders in already-written daily memory files don't get promoted on future runs:

const selected = options.candidates.filter((candidate) => {
    if (isContaminatedDreamingSnippet(candidate.snippet)) return false;
    if (/no strong candidate truths surfaced/i.test(candidate.snippet || "")) return false;
    if (candidate.promotedAt) return false;
    // …
});

Both edits applied locally; node -e "require('…dreaming-phases….js'); require('…short-term-promotion….js')" loads both modules cleanly.

Workaround

Patching the two dist/ files in /usr/lib/node_modules/openclaw/ as above and stripping the existing placeholder entries from workspace/MEMORY.md. The patch is lost on npm install -g openclaw upgrade.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions