Skip to content

feat(memory-core): record terminal task outcomes for dreaming feedback#75140

Closed
keane-751892 wants to merge 1 commit into
openclaw:mainfrom
keane-751892:feat/task-outcome-recorder
Closed

feat(memory-core): record terminal task outcomes for dreaming feedback#75140
keane-751892 wants to merge 1 commit into
openclaw:mainfrom
keane-751892:feat/task-outcome-recorder

Conversation

@keane-751892

Copy link
Copy Markdown

Summary

Adds a plugin-sdk seam (openclaw/plugin-sdk/task-events) that lets plugins subscribe to the task registry's lifecycle events without owning the singleton observer that tests rely on. Multiple listeners can register in parallel via addTaskRegistryEventListener(listener), which returns an unsubscribe function. Listener exceptions are swallowed so one consumer cannot break the registry's notification path.

Wires memory-core to the seam: when a task transitions into a terminal state (succeeded, failed, timed_out, cancelled, lost), append a JSONL outcome record to <workspace>/memory/.dreams/task-outcomes.jsonl with status, runtime, agent, label, durationMs, and a short summary. Dreaming can pick these up later as candidate "what worked / what failed" entries, closing the missing task → memory feedback loop.

The task-outcomes.jsonl path keeps the new data isolated from the existing MemoryHostEvent log so the shared schema stays untouched.

Files changed

  • src/tasks/task-registry.store.ts — multi-listener registry helpers (`addTaskRegistryEventListener`, `hasAdditionalTaskRegistryEventListeners`, `notifyAdditionalTaskRegistryEventListeners`)
  • src/tasks/task-registry.ts — emit path now also fans out to the additional listener set
  • src/plugin-sdk/task-events.ts — new SDK facade (re-exports types and addTaskRegistryEventListener)
  • scripts/lib/plugin-sdk-entrypoints.json + package.json + regenerated docs/.generated/plugin-sdk-api-baseline.sha256 — register the new subpath
  • extensions/memory-core/src/task-outcome-recorder.ts + tests — terminal-transition recorder writing JSONL events
  • extensions/memory-core/index.ts — wire registerTaskOutcomeRecorder into the plugin's register(api) pass

Test plan

  • pnpm test extensions/memory-core/src/task-outcome-recorder.test.ts — 9 tests covering shouldRecord, summarizeOutcome, buildOutcomeRecord, and JSON-serializable output
  • pnpm check:changed — typecheck (core + extensions) and tests green; lint shows only the unrelated pre-existing doctor-state-integrity.ts:875 warning

Notes for review

  • I kept the singleton-observer pattern intact for tests. The new listener set is additive.
  • resolveAgentWorkspaceDir is already exposed via openclaw/plugin-sdk/memory-core-host-engine-foundation, so memory-core can resolve a workspace from task.agentId without needing a new SDK seam.
  • The recorder skips when no agentId resolves and falls back to resolveDefaultAgentId(api.config). If neither is available, it silently does nothing (best-effort) rather than blocking the registry.

🤖 Generated with Claude Code

Add a plugin-sdk seam (task-events) that lets plugins subscribe to the
task registry's lifecycle events without owning the singleton observer
that tests rely on. Multiple listeners can register in parallel and
exceptions inside one listener are swallowed so they cannot break the
emit path.

Wire memory-core to the seam: when a task transitions into a terminal
state (succeeded, failed, timed_out, cancelled, lost), append a
JSONL outcome record to <workspace>/memory/.dreams/task-outcomes.jsonl
with status, runtime, agent, label, durationMs, and a short summary.
Dreaming can pick these up later as candidate "what worked / what
failed" entries, closing the missing task -> memory feedback loop.

The task-outcomes.jsonl path keeps the new data isolated from the
existing MemoryHostEvent log, so the shared schema stays untouched.

Thanks @keane-751892
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation extensions: memory-core Extension: memory-core scripts Repository scripts size: M triage: dirty-candidate Candidate: broad unrelated surfaces; may need splitting or cleanup. labels Apr 30, 2026
@clawsweeper

clawsweeper Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Thanks for the contribution. I reviewed the branch, and this PR is not a good landing base for OpenClaw.

Close as low-signal unmergeable: the task-to-memory feedback idea is useful, but the branch promotes raw task records into a public SDK, adds noncanonical JSONL runtime storage, leaks listener lifecycle ownership, is conflicting, and lacks real behavior proof, so most of the diff would need replacement rather than polish.

So I’m closing this PR rather than keeping an unmergeable branch open. A new narrow PR that carries only the useful part is welcome.

Review details

Best possible solution:

Close this branch and ask for a new narrow PR only after maintainers approve a scoped task-lifecycle event contract and a canonical persistence path using plugin state or the safe memory event journal.

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

No current-main bug reproduction applies because this is a feature PR. The PR-introduced blockers are high-confidence from source inspection of the raw SDK export, direct JSONL append path, and discarded unsubscribe function.

Is this the best way to solve the issue?

No. A task-to-memory feedback loop is plausible, but this implementation is not the best shape until the public event scope, privacy boundary, persistence owner, listener lifecycle, and proof path are redesigned.

Security review:

Security review needs attention: Security review needs attention because the diff exposes raw task lifecycle data through a public SDK path and writes workspace outcome records without the existing safe append helper.

  • [medium] Global task events may expose cross-agent task data — src/plugin-sdk/task-events.ts:14
    The proposed public SDK event stream carries full task registry records to plugin listeners, including task text, errors, agent IDs, requester/session keys, and owner metadata without a scoped capability or privacy boundary.
    Confidence: 0.9
  • [medium] Workspace append bypasses the safe memory event writer — extensions/memory-core/src/task-outcome-recorder.ts:103
    The recorder appends task outcome data under the workspace with plain fs.appendFile instead of the existing memory event helper that uses appendRegularFile with symlink-parent rejection.
    Confidence: 0.84

AGENTS.md: found and applied where relevant.

What I checked:

  • Repository policy applied: Read the full root policy and scoped guides for plugin SDK, extensions, scripts, and docs; the plugin API, SQLite-first storage, lifecycle cleanup, and proof requirements directly affected the verdict. (AGENTS.md:29, 6de357ad4772)
  • Current main has no task-outcome sidecar or public task-events SDK: Targeted search on current main finds only the internal TaskRegistryObserverEvent surface, with no task-outcomes file, task.outcome record, task-events SDK subpath, or addTaskRegistryEventListener export. (src/tasks/task-registry.store.ts:35, 6de357ad4772)
  • PR head exposes raw task events publicly: The PR adds openclaw/plugin-sdk/task-events and re-exports addTaskRegistryEventListener plus TaskRegistryObserverEvent from the internal task registry store. (src/plugin-sdk/task-events.ts:14, f3207715b222)
  • PR head writes a new plain JSONL sidecar: The recorder creates memory/.dreams/task-outcomes.jsonl and appends with fs.appendFile directly rather than using the existing memory event writer or SQLite/plugin state. (extensions/memory-core/src/task-outcome-recorder.ts:103, f3207715b222)
  • Current memory event writer uses a safer append path: The existing memory host event helper writes events.jsonl through appendRegularFile with rejectSymlinkParents, showing the established safer path this PR bypasses. (src/memory-host-sdk/events.ts:90, 6de357ad4772)
  • Memory-core runtime state already has a SQLite plugin-state owner: Current memory-core dreaming state is backed by api.runtime.state.openKeyedStore through the plugin-state runtime, not by new ad hoc runtime sidecars. (extensions/memory-core/src/dreaming-state.ts:69, 6de357ad4772)

Likely related people:

  • vincentkoc: Recent history includes task registry helper export trimming, task recovery work, and memory event compatibility changes around the surfaces this PR exposes. (role: recent task registry and plugin SDK contributor; confidence: high; commits: 71645bb8a321, 273eed4c51cb, efca4b7e64c2; files: src/tasks/task-registry.store.ts, src/tasks/task-registry.ts, src/memory-host-sdk/events.ts)
  • steipete: Recent history shows shared SQLite task-state migration, memory-core dreams state work, and task execution helper documentation relevant to the storage and lifecycle concerns. (role: recent persistence and lifecycle-adjacent contributor; confidence: high; commits: d115fb4cf9f9, 3f5e00184431, 606e3d78669a; files: src/tasks/task-registry.store.ts, extensions/memory-core/src/dreaming-state.ts, extensions/memory-core/index.ts)
  • mbelinky: Earlier task lifecycle and task registry storage commits are relevant to the registry event model and task persistence behavior this PR would expose. (role: task lifecycle feature-history contributor; confidence: medium; commits: 92d0b3a557bc, 17c36b5093da; files: src/tasks/task-registry.store.ts, src/tasks/task-registry.ts)
  • momothemage: Merged the adjacent structured dreaming outcome path that uses the existing memory event journal instead of this PR's separate task-outcome sidecar. (role: recent adjacent memory outcome contributor; confidence: medium; commits: db2488b6e3d6; files: src/memory-host-sdk/events.ts, extensions/memory-core/src/dreaming-events.ts, extensions/memory-core/src/dreaming.ts)

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

@openclaw-barnacle

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 30, 2026
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 30, 2026
@barnacle-openclaw barnacle-openclaw Bot removed the stale Marked as stale due to inactivity label May 30, 2026
@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: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label Jun 14, 2026
@clawsweeper

clawsweeper Bot commented Jun 29, 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

docs Improvements or additions to documentation extensions: memory-core Extension: memory-core merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. 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: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: M status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: dirty-candidate Candidate: broad unrelated surfaces; may need splitting or cleanup. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant