Skip to content

fix(dreaming): drop heartbeat assistant responses from dream corpus#104085

Closed
ekinnee wants to merge 14 commits into
openclaw:mainfrom
ekinnee:fix/dreaming-heartbeat-filter
Closed

fix(dreaming): drop heartbeat assistant responses from dream corpus#104085
ekinnee wants to merge 14 commits into
openclaw:mainfrom
ekinnee:fix/dreaming-heartbeat-filter

Conversation

@ekinnee

@ekinnee ekinnee commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The dreaming ingestion pipeline filters heartbeat user messages (containing [OpenClaw heartbeat poll]) via sanitizeSessionText, but the paired assistant response was only dropped when it was the exact string HEARTBEAT_OK. Local models frequently respond with natural-language acknowledgments (e.g. "Heartbeat received. Main is active.") which pass through the sanitizer unchanged and enter the dream corpus as low-confidence memory snippets.

See issue #103720.

Why This Change Was Made

The original text-based heartbeat detection was user-spoofable (anyone could type the heartbeat marker and trigger the drop). The fix uses runtime provenance (provenance: { kind: "heartbeat" }) attached at the source in get-reply-run.ts, which cannot be spoofed by user input.

For existing workspaces with heartbeat contamination, the doctor audit/repair system:

  • Scans session-corpus files for heartbeat-derived lines via source refs
  • Removes only heartbeat lines while preserving normal content
  • Handles both file-backed sessions (.jsonl paths) and SQLite-backed sessions (logical paths without extension) via a fallback to loadTranscriptEventsSync
  • Avoids clearing session ingestion checkpoints to prevent corpus duplication on re-ingestion
  • Falls through to self-ingestion narrative content checks even when heartbeat contamination is found

User Impact

  • No visible change for users without heartbeat contamination
  • Lower memory noise for users with heartbeat-enabled sessions -- average 0.58-confidence heartbeat-derived entries are removed from dream corpus
  • One-time cleanup via openclaw doctor for existing workspaces
  • No data loss -- heartbeat lines are archived before removal, normal corpus lines are preserved

Evidence

Forward Prevention (Provenance-based)

  • Heartbeat turns carry provenance: { kind: "heartbeat" } attached at the source in get-reply-run.ts
  • buildSessionEntry checks message.provenance.kind === "heartbeat" instead of text-matching user content
  • When a heartbeat user message is filtered, the immediately following assistant response is also dropped via a pendingHeartbeatUserDrop flag
  • Cross-message coupling is gated by runtime provenance (not user-spoofable text per PR memory/dreaming: decouple managed cron from heartbeat #70737)

Backward Repair (Targeted Doctor Audit)

  • auditDreamingArtifacts + repairDreamingArtifacts functions available via openclaw doctor
  • Detects and archives heartbeat-derived session-corpus entries, contaminated session-ingestion state, and duplicate diary entries
  • Handles both file-backed and SQLite logical session paths in corpus references

Real Behavior Proof (Rebased on upstream/main @ 5a0fcc2)

Test: Contaminated workspace with 4 corpus lines (2 heartbeat-derived, 2 normal), session ingestion state, and file-backed session transcript.

Audit detects contamination:

  • heartbeatContaminatedSessionCorpusLineCount: 2
  • heartbeatContaminatedSessionCorpusFileCount: 1
  • issues: [{ code: "dreaming-session-corpus-heartbeat-derived", fixable: true }]

Repair removes only heartbeat lines, preserves normal content:

  • removedHeartbeatDerivedLines: 2
  • changed: true
  • Corpus after repair: "Outstanding in his field" preserved, "weather access" preserved, "Heartbeat received" removed, "HEARTBEAT_OK" removed

Idempotent (second repair is no-op):

  • changed: false
  • removedHeartbeatDerivedLines: undefined

Validation

  • Format: oxfmt --check passes
  • Lint: oxlint --deny curly passes
  • Extension tests: 12/12 pass (dreaming-repair.test.ts)
  • Session-files tests: 39/39 pass (session-files.test.ts)
  • Type check: tsgo passes
  • LOC ratchet: both files under 500 lines
  • Rebased onto upstream/main (1541 commits)
  • No merge conflict markers
  • Autoreview: P0 merge marker fixed, P1/P2 findings evaluated (pre-existing pattern, no divergence)

Files Changed

File Change
packages/memory-host-sdk/src/host/session-files.ts pendingHeartbeatUserDrop flag + provenance-based heartbeat detection
packages/memory-host-sdk/src/host/session-files.test.ts Tests: heartbeat provenance filtering
src/sessions/input-provenance.ts Export heartbeat provenance kind constant
src/auto-reply/reply/get-reply-run.ts Attach provenance: { kind: "heartbeat" } to heartbeat replies
extensions/memory-core/src/dreaming-repair.ts Audit + repair functions for dreaming artifacts
extensions/memory-core/src/dreaming-repair-utils.ts New: helper utilities extracted for LOC ratchet
extensions/memory-core/src/dreaming-repair.test.ts Tests for dreaming repair
src/commands/doctor-memory-search.ts Integrate dreaming audit/repair into doctor command
src/commands/doctor-memory-search.test.ts Update mocks for new imports
src/plugin-sdk/sqlite-runtime-testing.ts Export appendSqliteTranscriptMessage for repair fallback
src/plugin-sdk/memory-core-engine-runtime.ts Export repairDreamingArtifacts
src/plugin-sdk/memory-core-bundled-runtime.ts Export repairDreamingArtifacts

@openclaw-barnacle openclaw-barnacle Bot added size: XS triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@ekinnee
ekinnee force-pushed the fix/dreaming-heartbeat-filter branch from 62806d4 to 8de7aaf Compare July 11, 2026 02:42
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 13, 2026, 8:45 PM ET / July 14, 2026, 00:45 UTC.

Summary
The PR adds provenance-based heartbeat turn filtering during session-corpus ingestion and a targeted doctor audit and repair for existing heartbeat-derived dreaming artifacts.

PR surface: Source +566, Tests +375, Other +1. Total +942 across 13 files.

Reproducibility: no. executed current-main reproduction was established in this review, but the source path is high-confidence: current main drops only exact HEARTBEAT_OK assistant text and retains natural-language heartbeat acknowledgments.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: migration/backfill/repair: extensions/memory-core/src/dreaming-repair-utils.ts, migration/backfill/repair: extensions/memory-core/src/dreaming-repair.ts, serialized state: extensions/memory-core/src/dreaming-repair.test.ts, serialized state: packages/memory-host-sdk/src/host/session-files.test.ts, serialized state: packages/memory-host-sdk/src/host/session-files.ts, unknown-data-model-change: extensions/memory-core/src/dreaming-repair-utils.ts, and 9 more. Migration or upgrade compatibility proof is recorded; maintainers should verify it before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #103720
Summary: This PR is the candidate fix for the heartbeat-contamination portion of the canonical open bug report; the earlier merged dreaming refactor is related history rather than a replacement fix.

Members:

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

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🧂 unranked krab
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted exact-head affected-workspace terminal or log proof for cleanup, preservation, idempotence, and subsequent ingestion.
  • [P1] Rebase onto current main and refresh the relevant required checks without changing the proven repair semantics.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR has tests and CI-style validation but no contributor-supplied after-fix run on a real contaminated workspace; add redacted terminal output or logs showing selective cleanup, preservation, idempotence, and subsequent ingestion, then update the PR body to trigger review or ask a maintainer for @clawsweeper re-review, redacting keys, phone numbers, IP addresses, private endpoints, and other private data.

Risk before merge

  • [P1] The doctor path mutates derived corpus and ingestion state; unit tests do not prove selective cleanup, preservation, idempotence, and subsequent ingestion behavior on an actual contaminated JSONL or SQLite workspace.
  • [P1] The branch is behind current main, so the state-repair and session-persistence paths need an exact-head review and required-check refresh after rebasing.

Maintainer options:

  1. Prove the upgrade repair (recommended)
    Require a redacted exact-head run on a contaminated workspace showing before/after corpus state, preserved normal entries, a no-op second repair, and clean subsequent ingestion before merge.
  2. Pause until proof is available
    Keep the PR open without merging if an affected workspace is not currently available to validate the state mutation safely.

Next step before merge

  • [P1] Wait for contributor-supplied exact-head affected-workspace proof, then refresh the review and required checks; there is no remaining narrow code defect suitable for automated repair.

Security
Cleared: The diff adds no dependency, workflow, permission, secret-handling, download, or package-resolution change, and no concrete security or supply-chain regression was found.

Review details

Best possible solution:

Land the provenance-backed forward filter and targeted memory-core doctor repair after a redacted exact-head workspace run demonstrates selective removal, preservation of normal corpus and diary content, idempotence, and clean subsequent ingestion for the applicable storage backends.

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

No executed current-main reproduction was established in this review, but the source path is high-confidence: current main drops only exact HEARTBEAT_OK assistant text and retains natural-language heartbeat acknowledgments.

Is this the best way to solve the issue?

Yes for the implementation direction: runtime provenance is the narrowest non-spoofable forward filter and memory-core doctor is the correct repair owner; merge readiness remains blocked on real upgrade proof.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.

Label justifications:

  • P2: The PR addresses a bounded but real Dreaming session-state quality defect without evidence of data loss, security bypass, or core-runtime unavailability.
  • merge-risk: 🚨 session-state: The doctor repair removes derived corpus entries and reconciles ingestion state, so incorrect matching or checkpoint handling could stale, duplicate, or mis-associate memory state after upgrade.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR has tests and CI-style validation but no contributor-supplied after-fix run on a real contaminated workspace; add redacted terminal output or logs showing selective cleanup, preservation, idempotence, and subsequent ingestion, then update the PR body to trigger review or ask a maintainer for @clawsweeper re-review, redacting keys, phone numbers, IP addresses, private endpoints, and other private data.
Evidence reviewed

PR surface:

Source +566, Tests +375, Other +1. Total +942 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 9 715 149 +566
Tests 3 380 5 +375
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 1 1 0 +1
Total 13 1096 154 +942

What I checked:

  • Current-main bug remains: Current main filters assistant heartbeat output only when the normalized response exactly equals HEARTBEAT_OK, so natural-language acknowledgments remain eligible for corpus ingestion. (packages/memory-host-sdk/src/host/session-files.ts:3166, cae29a079203)
  • Current-main pairing gap: The current ingestion loop deliberately avoids dropping the assistant message following a text-matched heartbeat user message and has no provenance-backed heartbeat pairing state. (packages/memory-host-sdk/src/host/session-files.ts:3468, cae29a079203)
  • PR forward fix: The branch tracks a provenance-authenticated heartbeat user drop and excludes the immediately following assistant acknowledgment without trusting user-spoofable text. (packages/memory-host-sdk/src/host/session-files.ts:802, 5d65f1d880f1)
  • Targeted repair coverage: The branch adds source-reference-based detection and repair tests for both JSONL-backed and SQLite-backed transcript identities while preserving unrelated corpus content. (extensions/memory-core/src/dreaming-repair.test.ts:124, 5d65f1d880f1)
  • Linked canonical report: The open report documents natural-language heartbeat replies contaminating the dream corpus and this PR is the candidate fix for that portion of the report.
  • Re-review continuity: The latest completed ClawSweeper review inspected this same head SHA, found no remaining code defect, and required real affected-workspace proof; no newer PR commit is present in the supplied live context. (5d65f1d880f1)

Likely related people:

  • steipete: Official repository ownership and the PR discussion connect this person to the dreaming upgrade contract, while recent history also touches the session-export path. (role: feature owner and reviewer; confidence: high; commits: 7e0e29ef1749; files: packages/memory-host-sdk/src/host/session-files.ts, extensions/memory-core/src/dreaming-repair.ts)
  • jalehman: Merged dreaming history attributes the session-store classification and heartbeat/cron corpus filtering behavior to this contributor's work. (role: introduced related behavior; confidence: high; commits: a1b01f0281d0, f3cf75d30a33; files: packages/memory-host-sdk/src/host/session-files.ts, extensions/memory-core/src/dreaming-phases.ts)
  • vignesh07: Repository ownership and merged history tie this person to the Dreaming session-corpus ingestion feature affected by the PR. (role: dreaming feature owner; confidence: high; commits: 338c7b8d6672; files: extensions/memory-core/src/dreaming-phases.ts, extensions/memory-core/src/dreaming-phases.test.ts)
  • Patrick-Erichsen: This contributor carried the merged isolated-dreaming and transcript-noise filtering refactor that established the surrounding behavior. (role: merger and adjacent refactor contributor; confidence: medium; commits: aca92b29065f; files: packages/memory-host-sdk/src/host/session-files.ts, extensions/memory-core/src/dreaming-phases.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (21 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-12T19:35:56.127Z sha c59f102 :: needs real behavior proof before merge. :: [P1] Resolve corpus refs through the transcript accessor
  • reviewed 2026-07-12T19:43:03.202Z sha c59f102 :: needs real behavior proof before merge. :: [P1] Resolve corpus refs through the transcript accessor
  • reviewed 2026-07-12T19:49:04.654Z sha c59f102 :: needs real behavior proof before merge. :: [P1] Read SQLite corpus refs through the transcript accessor
  • reviewed 2026-07-13T23:09:37.098Z sha 5a70da0 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T23:17:43.442Z sha 5a70da0 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-13T23:42:54.474Z sha c62dd8a :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-14T00:01:03.423Z sha c62dd8a :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-14T00:33:27.318Z sha 5d65f1d :: needs real behavior proof before merge. :: none

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@openclaw-barnacle openclaw-barnacle Bot added size: S and removed triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. size: XS labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. label Jul 11, 2026
@openclaw-barnacle openclaw-barnacle Bot added the commands Command implementations label Jul 11, 2026
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 11, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the commands Command implementations label Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 11, 2026

@steipete steipete left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The forward behavior is sound: authenticated provenance.kind === "heartbeat" avoids the user-spoofable cross-message coupling rejected in #70737, and the pending flag correctly survives tool/thinking records until the paired assistant text. I cannot land this as the complete bug fix yet because upgraded installations do not converge.

The production evidence in this PR found 21 already-derived ghost entries. This patch changes future transcript ingestion only; it does not invalidate the existing session corpus / ingestion checkpoints or remove already-written DREAMS.md fallback entries. Current auditDreamingArtifacts() detects self-ingested dreaming prompts, not heartbeat-derived contamination or the generic fallback diary phrase, so openclaw doctor will not offer the existing archive/rebuild repair for this case. After upgrade, users can therefore keep seeing the polluted derived state even though new heartbeat turns are filtered.

Please add a bounded convergence contract before merge. The safe shape is an explicit doctor/audit repair (or a versioned derived-corpus rebuild) that can prove heartbeat contamination from source/corpus state, archives the affected derived artifacts, clears the matching ingestion checkpoints, and lets them rebuild under the new filter. Do not delete the generic fallback sentence by text alone: it is also emitted for legitimate request-scoped narrative failures and is not sufficient provenance. Add an upgrade test that starts with pre-fix corpus/checkpoint/diary state, runs the repair or migration, and proves the contaminated artifacts no longer remain eligible while unrelated dream entries survive or are safely archived according to the chosen contract.

I did not find a blocker in the new heartbeat provenance value or the forward session parser tests themselves.

@steipete steipete self-assigned this Jul 11, 2026
@steipete

Copy link
Copy Markdown
Contributor

Forward-only convergence is not bounded by the 2/7-day lookback in the current implementation. Those windows limit which transcript material is selected for future dreaming runs; they do not delete already-written DREAMS.md entries or invalidate the existing corpus/checkpoints. The 21 observed ghost entries can therefore remain indefinitely after upgrade.

I am not accepting manual deletion of all dreams as the upgrade contract because it discards unrelated derived state and is not discoverable or automated. The pre-merge requirement remains a targeted audit/doctor repair or versioned rebuild that archives the affected derived artifacts, clears the matching ingestion checkpoints, and rebuilds under the provenance filter. The repair must use source/corpus provenance rather than deleting the generic fallback sentence by text.

@openclaw-barnacle openclaw-barnacle Bot added extensions: memory-core Extension: memory-core commands Command implementations size: L and removed size: S labels Jul 12, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jul 12, 2026
@ekinnee
ekinnee force-pushed the fix/dreaming-heartbeat-filter branch from c59f102 to 5a70da0 Compare July 13, 2026 22:57
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 13, 2026
@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label Jul 14, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 14, 2026
Erick Kinnee and others added 13 commits July 16, 2026 21:00
The dreaming ingestion pipeline filters heartbeat user messages
(containing [OpenClaw heartbeat poll]) via sanitizeSessionText, but the
paired assistant response is only dropped when it is the exact string
HEARTBEAT_OK. Local models frequently respond with natural-language
acknowledgments (e.g. "Heartbeat received. Main is active.") which pass
through the sanitizer unchanged and enter the dream corpus as
low-confidence (0.58) memory snippets.

Fix: track heartbeat user message drops in buildSessionEntry and skip
the immediately following assistant response. This cross-message coupling
is safe because the heartbeat prompt pattern is injected by the runtime
and cannot be spoofed by user input, unlike [cron:...] or
System (untrusted): ... patterns (see PR openclaw#70737).

Refs: openclaw#103720
…xt matching

Replace text-based heartbeat detection (isGeneratedHeartbeatPromptMessage)
with provenance-based authentication. The heartbeat turn now carries
provenance: { kind: "heartbeat" } when persisted to the transcript,
and buildSessionEntry checks for this provenance instead of matching
user-spoofable text content.

Changes:
- src/sessions/input-provenance.ts: Add "heartbeat" to
  INPUT_PROVENANCE_KIND_VALUES
- src/auto-reply/reply/get-reply-run.ts: Attach heartbeat provenance
  to user turn input when isHeartbeat is true
- packages/memory-host-sdk/src/host/session-files.ts: Check
  message.provenance.kind === "heartbeat" instead of text matching
- packages/memory-host-sdk/src/host/session-files.test.ts: Update
  heartbeat test to include provenance; add lookalike regression test

This addresses the ClawSweeper review finding [P1] about user-spoofable
text matching. The cross-message coupling is now authenticated by
runtime provenance, not user-typed content.

Refs: openclaw#103720
The findHeartbeatContaminatedCorpusLines function could not read
SQLite-backed session transcripts. When a corpus ref had no .jsonl
extension (SQLite logical path format), it appended .jsonl, read an
empty file, and silently skipped — leaving pre-fix heartbeat
contamination intact for SQLite users.

Fix:
- Add loadTranscriptLinesFromSqlite helper that reads events via
  the canonical loadTranscriptEventsSync API
- Serialize all events to preserve original event positions for
  corpus #L<n> line-number references
- Fall back to SQLite reader when filesystem read fails on a
  non-.jsonl corpus ref path

Test: add SQLite-backed session regression test that seeds a
session, writes corpus refs without .jsonl extension, and
verifies both audit detection and targeted repair.
…nd early return

P1: Remove clearScopedSessionIngestionState call after heartbeat line
removal. Clearing the cursor causes the next ingestion to re-process the
transcript from the beginning, duplicating normal corpus lines that were
deliberately retained.

P2: Remove early return after heartbeat cleanup so the self-ingestion
narrative content check and archiveDiary request still run.
…t ID

The session path in corpus refs is already in the format
'sessions/main/abc.jsonl' (includes agent subdirectory). The
previous code prepended source.agentId again, creating a path
like 'agents/main/sessions/main/abc.jsonl' — which silently
returned empty in production workspaces.

Fix: use path.basename to extract just the filename from the
session path, then construct the transcript path correctly.
…LOC ratchet

The dreaming-repair.ts file grew from 337 to 831 lines, exceeding the
500-line LOC ratchet limit. Split helper utilities into a new
dreaming-repair-utils.ts file:

- dreaming-repair.ts (365 lines): imports, types, public API functions
  (auditDreamingArtifacts, repairDreamingArtifacts)
- dreaming-repair-utils.ts (498 lines): all helper functions, constants,
  and internal types
@ekinnee
ekinnee force-pushed the fix/dreaming-heartbeat-filter branch from 5d65f1d to 62a51e8 Compare July 16, 2026 21:04
@openclaw-barnacle openclaw-barnacle Bot removed the scripts Repository scripts label Jul 16, 2026
@ekinnee

ekinnee commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR in favor of a fresh one with the updated repair approach. The forward fix (provenance-based heartbeat detection) is unchanged. The upgrade repair now archives the entire session-corpus directory and clears all SQLite checkpoints instead of targeted line-by-line rewrite, per steipete's review requirements.

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

Labels

commands Command implementations 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. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL 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.

2 participants