Skip to content

fix(memory-core): skip markdown placeholder snippets in short-term promotion (#80582) [AI-assisted]#94985

Closed
ml12580 wants to merge 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-80582
Closed

fix(memory-core): skip markdown placeholder snippets in short-term promotion (#80582) [AI-assisted]#94985
ml12580 wants to merge 1 commit into
openclaw:mainfrom
ml12580:fix/vuln-80582

Conversation

@ml12580

@ml12580 ml12580 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

[AI-assisted] This PR was generated using Claude Code.

Summary

  • Problem: The short-term memory promotion pipeline in extensions/memory-core recorded markdown skeleton placeholders — bare list markers (-, *, +), heading-only lines, and heading + empty-bullet ranges — as promotable recall candidates. During relocation, broad substring matching could also anchor a meaningful candidate onto a bare-marker window (e.g. a target containing - matching a - line at quality 1), so empty/structurally meaningless blocks could be appended into MEMORY.md.
  • Why it matters now: These placeholders carry no durable content but still consume recall-store slots, accrue ranking signals, and can be promoted as empty blocks into long-term memory, contaminating it with markdown skeleton noise (issue Memory: skip markdown placeholder snippets during short-term promotion #80582).
  • Intended outcome: Placeholder snippets are dropped at every entry point (recall recording, grounded-candidate recording, store load/normalization, and ranking), and relocation substring matching refuses to anchor onto placeholder ranges. Real notes (including CJK and heading-with-body lines) are unaffected.
  • Out of scope: No change to dreaming-contamination filtering (already present), no change to scoring weights, no change to the on-disk store format.
  • Success looks like: Placeholder snippets never reach the recall store or ranking, and a meaningful candidate no longer relocates onto a bare marker line.
  • Reviewer focus: The placeholder detection helpers (isMarkdownPlaceholderLine, isPlaceholderShortTermSnippet, isUnpromotableShortTermSnippet) and the narrow guard added to compareCandidateWindow.

Linked context

Closes #80582

Related: the issue includes a patch sketch; this PR implements it with one justified deviation (see "Risk checklist").

Real behavior proof

  • Behavior or issue addressed: Short-term memory promotion recorded markdown skeleton placeholders (bare -/*/+, heading-only lines, heading + empty-bullet ranges) as promotable candidates and anchored relocation substring matches onto them (Memory: skip markdown placeholder snippets during short-term promotion #80582).
  • Real environment tested: Windows 10 Enterprise LTSC 2019, Node v22.22.3, OpenClaw extensions/memory-core short-term-promotion shard.
  • Exact steps or command run after this patch: Ran the memory-core short-term-promotion vitest shard via node scripts/run-vitest.mjs run --config test/vitest/vitest.extension-memory.config.ts with the shard include filter pointed at extensions/memory-core/src/short-term-promotion.test.ts, once with the production fix reverted and once with the fix applied.
  • Evidence after fix (terminal capture): Shard run via node scripts/run-vitest.mjs after the fix. Terminal capture (console output):
 Test Files  1 passed (1)
      Tests  83 passed (83)
   Start at  22:04:49
   Duration  57.06s
  • Observed result after fix: After the fix all 83 tests pass, including the 5 new regression tests (bare markers, skeleton ranges, grounded placeholders, store-load drop, and relocation-onto-placeholder). Before the fix the same shard reported 5 failed | 78 passed (83) — the 5 new tests failed because placeholders were recorded/ranked and a candidate relocated onto a bare - line (applied was 1, expected 0).
  • What was not tested: macOS/Linux not tested; the full pnpm test suite was not run locally (scoped to the memory-core shard plus format/tsgo/lint/build); pnpm check:host-env-policy:swift is skipped on Windows (no Swift); a live long-term dreaming promotion run against a real workspace was not executed end-to-end.
  • Proof limitations or environment constraints: Local verification is Windows-only. The placeholder filtering is pure logic exercised directly through the real recordShortTermRecalls / recordGroundedShortTermCandidates / rankShortTermPromotionCandidates / store-normalization / relocation code paths in the extension shard; CI runs the same shard on Linux Node 24.
  • Before evidence: Shard run with the production fix reverted (placeholders not filtered). Terminal capture (console output):
 Test Files  1 failed (1)
      Tests  5 failed | 78 passed (83)

The relocation regression failed with expected 1 to be 0 (applied.applied was 1), confirming the candidate relocated onto the bare - line before the fix.

Tests and validation

  • Commands run: pnpm exec oxfmt --check (both files clean), pnpm tsgo (clean), pnpm exec oxlint --type-aware on the changed files (clean), pnpm build, and pnpm test:extension memory-core (short-term-promotion shard: 83/83 pass).
  • Regression coverage added: 5 new tests in extensions/memory-core/src/short-term-promotion.test.ts — bare marker recording, multi-line skeleton range recording, grounded placeholder recording, store-load placeholder drop, and relocation-onto-placeholder refusal.
  • What failed before this fix: the 5 new tests failed against the unpatched production code (5 failed | 78 passed); they pass after the fix (83 passed).
  • Pre-existing unrelated Windows failures observed in the broader memory-core shard (manager.watcher-config.test.ts chokidar watcher tests and one qmd-manager.test.ts case failing on ENOENT mkdir '...Notes #1: blue' because Windows disallows : in directory names) were confirmed to also fail on clean main without this PR's changes.

Risk checklist

Did user-visible behavior change? No

Did config, environment, or migration behavior change? No

Did security, auth, secrets, network, or tool execution behavior change? No

What is the highest-risk area? Correctness of the placeholder detector — it must not drop legitimate notes. A heading line that also carries a list item with body text (e.g. ## Notes - real content) is intentionally kept, and ordinary prose/list lines are never placeholders.

How is that risk mitigated? The detector only treats a line as a placeholder when it is empty, a bare -/*/+, or a heading line without an inline list item carrying body text. The existing 78 tests (including CJK heading-prefixed relocations and bullet-prefixed dreaming snippets) still pass, and the new tests assert real notes are kept while placeholders are dropped.

Deviation from the issue's patch sketch: the issue suggests an isMeaningfulRelocationSubstring token-count guard for relocation. That check splits on [^A-Za-z0-9_]+, which treats CJK characters as separators and would reject legitimate non-English relocations (the suite has CJK rehydration tests). This PR instead uses a narrower placeholder-only guard in compareCandidateWindow that blocks substring matches only when either side is a placeholder — achieving the issue's stated goal ("avoid matching onto placeholders") without regressing CJK relocations. The exact-match branch is unchanged.

Current review state

Next action: await CI and maintainer/ClawSweeper review.

Waiting on: CI (format/lint/tsgo/build + memory-core shard on Linux Node 24).

Bot/reviewer comments addressed: none yet (PR just opened).

…omotion (openclaw#80582)

Bare list markers (-, *, +), heading-only lines, and heading + empty-bullet
ranges carry no durable content but were recorded as short-term recall
candidates and could be promoted into MEMORY.md as empty blocks. Broad
substring matching in compareCandidateWindow also anchored meaningful
candidates onto bare-marker windows.

Add isMarkdownPlaceholderLine / isPlaceholderShortTermSnippet /
isUnpromotableShortTermSnippet and filter placeholders at recall recording,
grounded-candidate recording, store load/normalization, and ranking. Guard
compareCandidateWindow substring branches so neither side may be a
placeholder (exact match unchanged). The relocation guard is intentionally
narrower than a token count: an ASCII-only token check would split CJK
text into separators and reject legitimate non-English relocations.
@openclaw-barnacle openclaw-barnacle Bot added extensions: memory-core Extension: memory-core size: M proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

This PR should close because the same remaining memory-core bug is still owned by the open canonical issue, and maintainer review on the prior same-issue repair rejected this heuristic filter family in favor of a typed/source-shape-aware normalization repair.

Root-cause cluster
Relationship: superseded
Canonical: #80582
Summary: This PR targets the same short-term promotion placeholder bug as the canonical issue, but it is superseded by maintainer direction to replace heuristic markdown filtering with typed/source-shape-aware normalization.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Canonical path: Keep #80582 as the canonical tracker and implement the maintainer-requested typed/source-shape-aware short-term promotion normalization repair in a replacement branch.

So I’m closing this here and keeping the remaining discussion on #80582.

Review details

Best possible solution:

Keep #80582 as the canonical tracker and implement the maintainer-requested typed/source-shape-aware short-term promotion normalization repair in a replacement branch.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main and v2026.6.8 are source-reproducible because non-empty markdown placeholders still pass contamination-only recording, ranking, and apply gates.

Is this the best way to solve the issue?

No. The branch is a plausible narrow filter, but prior maintainer review rejected this heuristic direction and the current head still has concrete over-broad and incomplete apply-side behavior.

Security review:

Security review cleared: The diff changes memory-core filtering logic and colocated tests only, with no dependency, workflow, package metadata, secret-handling, or code-execution surface changes.

AGENTS.md: found and applied where relevant.

What I checked:

Likely related people:

  • vignesh07: Authored and merged the weighted short-term promotion flow that introduced the central record/rank/apply surface affected here. (role: feature introducer; confidence: high; commits: 4c1022c73b39; files: extensions/memory-core/src/short-term-promotion.ts, extensions/memory-core/src/short-term-promotion.test.ts)
  • mbelinky: Authored the grounded backfill work that feeds durable candidates into the same short-term promotion store path. (role: recent area contributor; confidence: high; commits: e8209e4cf9b8; files: extensions/memory-core/src/short-term-promotion.ts, extensions/memory-core/src/dreaming-phases.ts)
  • gumadeiras: Authored the existing dreaming self-ingestion guard, the closest current precedent for filtering invalid snippets in this promotion pipeline. (role: adjacent filtering contributor; confidence: medium; commits: 0c4e0d703023; files: extensions/memory-core/src/short-term-promotion.ts, extensions/memory-core/src/short-term-promotion.test.ts)
  • vincentkoc: Recently worked on multilingual memory promotion and provided the maintainer direction closing the prior unsafe heuristic fix for the same canonical issue. (role: recent reviewer and adjacent contributor; confidence: medium; commits: 0609bf858175; files: extensions/memory-core/src/short-term-promotion.ts, extensions/memory-core/src/short-term-promotion.test.ts)

Codex review notes: model internal, reasoning high; reviewed against b16fd6bee7fa.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. labels Jun 19, 2026
@ml12580

ml12580 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR. ClawSweeper flagged it as superseded, and I see now that maintainer @vincentkoc already reviewed and closed the same-approach PR #92698 with the note that the core markdown-placeholder heuristic is both over- and under-broad and "not safe to land," directing the canonical issue #80582 toward a typed/source-shape-aware normalization repair rather than another heuristic filter.

This PR is the same heuristic family (and narrower than #92698), so it would hit the same rejection. I'll step aside rather than spend more review cycles on an approach the maintainer has already declined. The canonical issue #80582 stays open for the representation-level repair.

@clawsweeper clawsweeper Bot removed the status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. label Jun 19, 2026
@ml12580 ml12580 closed this Jun 19, 2026
@clawsweeper clawsweeper Bot added the status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. label Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper applied the proposed close for this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extensions: memory-core Extension: memory-core merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory: skip markdown placeholder snippets during short-term promotion

1 participant