Skip to content

fix(memory): record structured dreaming outcomes#97723

Merged
clawsweeper[bot] merged 2 commits into
mainfrom
feature/dreaming-outcome-events
Jun 29, 2026
Merged

fix(memory): record structured dreaming outcomes#97723
clawsweeper[bot] merged 2 commits into
mainfrom
feature/dreaming-outcome-events

Conversation

@momothemage

@momothemage momothemage commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Closes #97690

AI-assisted: yes, authored with Codex.

What Problem This Solves

Fixes an issue where users and operators reading memory dreaming event logs could see artifact-write records but could not tell whether a dreaming phase completed successfully or failed. Failed dreaming phases were visible in unstructured logs, but not in memory/.dreams/events.jsonl, so dashboards, doctor checks, and other structured consumers had no reliable event-log outcome to inspect.

Why This Change Was Made

This adds a conservative public MemoryDreamOutcome contract with the two outcomes the current runtime can accurately emit: completed and failed. New successful dreaming completion events now include outcome: "completed"; existing logs without outcome remain compatible and should be read as legacy completed events. Runtime failure paths now append best-effort failed dreaming events for the specific phase that failed (light, rem, or deep) without publishing unresolved partial, timed_out, or interrupted semantics that belong with the broader crash-recovery design in #97692.

Compatibility And Data Model

This is an additive JSONL event-shape change, not a migration. Existing memory.dream.completed records without outcome still parse through the public SDK and should be interpreted as legacy successful completion records. The new error field is optional and is only written on failed outcomes. Failed-outcome event writes are best-effort and guarded so diagnostic logging cannot mask the original dreaming failure or stop later workspace processing.

Because MemoryHostDreamCompletedEvent is exported through public plugin SDK entrypoints, this PR also updates the pinned plugin SDK surface budgets for the newly exported MemoryDreamOutcome type and its deprecated compatibility re-export surface.

User Impact

Memory event-log consumers can distinguish successful dreaming events from failed dreaming runs without parsing plain-text logs. Existing event logs and existing readers remain compatible because outcome is optional, and diagnostic outcome writes are guarded so an event-log write failure does not mask the original dreaming failure or stop later workspace processing.

Evidence

Real failed dreaming run, using the actual recordShortTermRecalls and runShortTermDreamingPromotionIfTriggered path with DREAMS.md symlinked so report writing refuses to overwrite it. Workspace path is redacted.

$ node --import tsx --input-type=module < one-off failed-dreaming repro
workspace: $WORKSPACE
result: {"handled":true,"reason":"memory-core: short-term dreaming processed"}
logger.error:
memory-core: dreaming promotion failed for workspace $WORKSPACE: Refusing to write symlinked DREAMS.md
memory/.dreams/events.jsonl:
{"type":"memory.recall.recorded","timestamp":"2026-06-29T09:13:53.501Z","query":"backup policy","resultCount":1,"results":[{"path":"memory/2026-04-02.md","startLine":1,"endLine":1,"score":0.9}]}
{"type":"memory.promotion.applied","timestamp":"2026-06-29T09:13:54.860Z","memoryPath":"$WORKSPACE/MEMORY.md","applied":1,"candidates":[{"key":"memory:memory/2026-04-02.md:1:1","path":"memory/2026-04-02.md","startLine":1,"endLine":1,"score":0.5793754415024722,"recallCount":1}]}
{"type":"memory.dream.completed","timestamp":"2026-06-29T09:13:54.860Z","phase":"deep","outcome":"failed","error":"Refusing to write symlinked DREAMS.md","lineCount":0,"storageMode":"separate"}
failed event: {"type":"memory.dream.completed","timestamp":"2026-06-29T09:13:54.860Z","phase":"deep","outcome":"failed","error":"Refusing to write symlinked DREAMS.md","lineCount":0,"storageMode":"separate"}

Targeted validation run locally on this branch:

node scripts/run-vitest.mjs extensions/memory-core/src/memory-events.test.ts extensions/memory-core/src/dreaming.test.ts src/plugin-sdk/memory-host-events.test.ts
# Test Files 3 passed; Tests 68 passed

node scripts/run-vitest.mjs test/scripts/plugin-sdk-surface-report.test.ts
# Test Files 1 passed; Tests 8 passed

node scripts/plugin-sdk-surface-report.mjs --check
# passed with public exports=10400, public deprecated exports=3256, public wildcard reexports=214

OPENCLAW_PLUGIN_SDK_MAX_PUBLIC_FUNCTION_EXPORTS=5218 node scripts/plugin-sdk-surface-report.mjs --check
# fails as expected with: public callable exports 5219 > 5218

pnpm format:check src/plugin-sdk/memory-host-events.test.ts extensions/memory-core/src/dreaming-events.ts extensions/memory-core/src/dreaming-markdown.ts extensions/memory-core/src/dreaming-phases.ts extensions/memory-core/src/dreaming.ts extensions/memory-core/src/memory-events.test.ts extensions/memory-core/src/dreaming.test.ts src/memory-host-sdk/events.ts
# All matched files use the correct format.

pnpm format:check scripts/plugin-sdk-surface-report.mjs
# All matched files use the correct format.

pnpm tsgo:test:extensions
pnpm tsgo:extensions
pnpm tsgo:test:src
pnpm tsgo:core
pnpm plugin-sdk:api:check
pnpm plugin-sdk:check-exports
# all passed

git diff --check
# passed

Behavior proof added in tests:

  • memory-events.test.ts verifies new successful dreaming events include outcome: "completed" and legacy completion events without outcome still read correctly.
  • dreaming.test.ts exercises a real deep-dreaming failure path by making DREAMS.md a symlink that report writing refuses to overwrite, then verifies events.jsonl contains a memory.dream.completed event with phase: "deep", outcome: "failed", and the structured error text.
  • memory-host-events.test.ts covers the public SDK helper path with the new outcome field.
  • plugin-sdk-surface-report.test.ts covers the pinned public SDK surface budgets after exporting the new outcome type.

Note: pnpm check:changed -- <changed files> could not run locally because the installed Crabbox binary is 0.16.0 and the current Testbox delegation requires >= 0.22.0; the targeted lanes above were run directly instead.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation extensions: memory-core Extension: memory-core size: M maintainer Maintainer-authored PR labels Jun 29, 2026
@clawsweeper

clawsweeper Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 29, 2026, 7:19 AM ET / 11:19 UTC.

Summary
The PR adds optional outcome and error fields to memory dream completion events, emits completed and best-effort failed events from memory-core dreaming paths, and updates SDK surface budgets and tests.

PR surface: Source +93, Tests +95, Generated 0, Other 0. Total +188 across 10 files.

Reproducibility: yes. Source inspection shows current main lacks outcome and error on memory.dream.completed, and the PR body includes redacted live output from a real failed dreaming run writing the new JSONL event.

Review metrics: 3 noteworthy metrics.

  • Public Event Contract Expansion: 1 exported union added, 2 optional fields added. The changed type is exported through openclaw/plugin-sdk/memory-host-events, so the outcome names become compatibility surface after release.
  • Runtime Outcome Coverage: 2 outcome names, failed writes for 3 phase names. The branch records the completed and failed states it claims for light, REM, and deep while leaving broader lifecycle states out of scope.
  • SDK Surface Budget Updates: 3 budget values increased. The PR updates public export and deprecated export budgets, confirming this is an intentional SDK surface expansion rather than a private-only change.

Stored data model
Persistent data-model change detected: serialized state: extensions/memory-core/src/dreaming.test.ts, serialized state: extensions/memory-core/src/memory-events.test.ts, unknown-data-model-change: extensions/memory-core/src/dreaming-phases.ts, unknown-data-model-change: extensions/memory-core/src/dreaming.test.ts, vector/embedding metadata: extensions/memory-core/src/dreaming-events.ts, vector/embedding metadata: extensions/memory-core/src/dreaming-phases.ts, and 4 more. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #97690
Summary: This PR is a candidate fix for the open dreaming outcome-normalization issue; the crash-recovery issue is broader, and the other open PR overlaps the same central event-contract gap.

Members:

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

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • [P2] Have a maintainer explicitly accept the narrow completed/failed public event taxonomy before merge.

Risk before merge

Maintainer options:

  1. Accept The Narrow Outcome Contract (recommended)
    Maintainers can approve completed and failed as the shipped additive event taxonomy now and keep broader lifecycle states in [Feature]: Dreaming phase crash recovery — detect and record interrupted runs #97692.
  2. Expand Taxonomy Before Merge
    If maintainers want partial, timed_out, or interrupted in the first public contract, revise the runtime classification and tests before merge.
  3. Pause For Crash-Recovery Design
    Maintainers can pause this branch if started/interrupted recovery should be designed together with the completed-event outcome contract.

Next step before merge

  • [P2] Manual review is needed because the branch publishes a public memory-host event taxonomy and maintainers need to accept the narrow completed/failed contract before automerge.

Security
Cleared: No workflow, dependency, permission, credential, package-resolution, or executable supply-chain surface is changed; the diff uses existing memory event write paths.

Review details

Best possible solution:

Land one maintainer-approved additive completed/failed dreaming outcome contract that keeps old event logs compatible and leaves interrupted or partial crash recovery to the separate lifecycle design issue.

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

Yes. Source inspection shows current main lacks outcome and error on memory.dream.completed, and the PR body includes redacted live output from a real failed dreaming run writing the new JSONL event.

Is this the best way to solve the issue?

Yes as a bounded implementation shape, pending maintainer acceptance. The two-state contract is more conservative than the overlapping broader taxonomy in #97705, with crash recovery left to #97692.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Sufficient (live_output): The PR body includes redacted live output from a real failed dreaming run and shows the resulting memory/.dreams/events.jsonl failed outcome record.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: 🚀 automerge armed.

Label justifications:

  • P2: This is a normal-priority memory-core observability fix with limited runtime blast radius but public event-contract implications.
  • merge-risk: 🚨 compatibility: The diff adds public plugin SDK event fields and outcome names that downstream readers may rely on after release.
  • merge-risk: 🚨 session-state: The diff persists new dreaming phase outcome state in memory event logs that diagnostics and dashboards may use to interpret memory dreaming state.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 🚀 automerge armed: This PR is in ClawSweeper's automerge lane. Sufficient (live_output): The PR body includes redacted live output from a real failed dreaming run and shows the resulting memory/.dreams/events.jsonl failed outcome record.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted live output from a real failed dreaming run and shows the resulting memory/.dreams/events.jsonl failed outcome record.
Evidence reviewed

PR surface:

Source +93, Tests +95, Generated 0, Other 0. Total +188 across 10 files.

View PR surface stats
Area Files Added Removed Net
Source 5 113 20 +93
Tests 3 95 0 +95
Docs 0 0 0 0
Config 0 0 0 0
Generated 1 2 2 0
Other 1 3 3 0
Total 10 213 25 +188

What I checked:

  • Repository policy applied: Root, extensions, plugin SDK, scripts, and docs scoped AGENTS.md files were read; public plugin SDK compatibility guidance applies because memory-host-events is a published SDK subpath. (AGENTS.md:29, cfd8ba8fc81d)
  • Current main lacks outcome fields: Current MemoryHostDreamCompletedEvent contains phase, optional paths, line count, and storage mode only, with no structured outcome or error field. (src/memory-host-sdk/events.ts:57, cfd8ba8fc81d)
  • Current main failure path is log-only: The deep dreaming promotion catch on current main increments failed workspaces and logs the error without appending a structured memory host event. (extensions/memory-core/src/dreaming.ts:692, cfd8ba8fc81d)
  • PR head adds the public outcome contract: The PR head adds MemoryDreamOutcome = "completed" | "failed" plus optional outcome and error fields while preserving legacy records with missing outcome. (src/memory-host-sdk/events.ts:57, 9fa7d20a969c)
  • PR head guards failed-event writes: The new helper appends failed dream events through the existing memory host event writer and catches diagnostic write failures so they do not mask the original dreaming failure. (extensions/memory-core/src/dreaming-events.ts:11, 9fa7d20a969c)
  • Public SDK subpath proof: ./plugin-sdk/memory-host-events is exported from package metadata and listed as a public plugin-owned SDK entrypoint, so event shape additions become compatibility surface after release. (package.json:1200, cfd8ba8fc81d)

Likely related people:

  • vincentkoc: GitHub path history shows Vincent Koc introduced the memory event journal bridge and later tightened memory event diagnostic compatibility, which are central to this public event contract. (role: feature-history contributor; confidence: high; commits: d1c7d9af800d, efca4b7e64c2, 329fa44d23f4; files: src/memory-host-sdk/events.ts, src/plugin-sdk/memory-host-events.ts, extensions/memory-core/src/dreaming-markdown.ts)
  • vignesh07: History shows Vignesh Natarajan authored the commit that simplified the dreaming sweep flow and added the diary surface now being instrumented with structured outcomes. (role: introduced dreaming sweep behavior; confidence: high; commits: 61e61ccc182f; files: extensions/memory-core/src/dreaming-markdown.ts, extensions/memory-core/src/dreaming.ts)
  • steipete: Recent history shows repeated work around memory-core dreaming state, SDK surface documentation, and storage boundaries adjacent to this public compatibility decision. (role: adjacent area contributor; confidence: medium; commits: 3f5e00184431, 77d9ac30bb8d, 0b8aabe8648e; files: extensions/memory-core/src/dreaming.ts, extensions/memory-core/src/dreaming-phases.ts, src/memory-host-sdk/events.ts)
  • qingminglong: Recent path history shows work on light dreaming freshness in the same dreaming-phases.ts flow where this PR records failed light and REM outcomes. (role: recent area contributor; confidence: medium; commits: 5e1f4c10734b; files: extensions/memory-core/src/dreaming-phases.ts)
  • jalehman: Recent commits route the dreaming corpus through session corpus metadata and split memory transcript corpus access in the same memory-core phase area. (role: recent adjacent contributor; confidence: medium; commits: da50a450d271, c24d266b2d09; files: 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.

@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. labels Jun 29, 2026
@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label Jun 29, 2026
@momothemage

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

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

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed 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. labels Jun 29, 2026
@momothemage

Copy link
Copy Markdown
Contributor Author

@clawsweeper automerge

@clawsweeper

clawsweeper Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

🦞✅
Maintainer-approved ClawSweeper automerge is complete.

Approver: momothemage
Head: 9fa7d20a969c
Merge status: merged by ClawSweeper automerge
Merged at: 2026-06-29T11:23:39Z
Merge commit: db2488b6e3d6

What merged:

  • Merged fix(memory): record structured dreaming outcomes after ClawSweeper review.

Automerge notes:

  • PR branch already contained follow-up commit before automerge: chore(plugin-sdk): update surface budgets

The automerge loop is complete.

Automerge progress:

  • 2026-06-29 11:15:13 UTC review queued 9fa7d20a969c (queued)
  • 2026-06-29 11:23:41 UTC merged 9fa7d20a969c (merged by ClawSweeper automerge)

@clawsweeper clawsweeper Bot added the clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge label Jun 29, 2026
@momothemage

Copy link
Copy Markdown
Contributor Author

@clawsweeper approve

@clawsweeper

clawsweeper Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

@clawsweeper clawsweeper Bot added status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane. clawsweeper:human-review Needs maintainer review before ClawSweeper can continue and removed status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 29, 2026
@clawsweeper

clawsweeper Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

🦞✅
ClawSweeper is pausing this repair loop for human review.

Source: clawsweeper[bot]
Reason: - [P2] Manual review is needed because the branch publishes a public memory-host event taxonomy and maintainers need to accept the narrow completed/failed contract before automerge.; Cleared: No workflow, dependency, permission, credential, package-resolution, or executable supply-chain surface is changed; the diff uses existing memory event write paths. (sha=9fa7d20a969ce579ad0a39582734300a4d5292bb)

Why human review is needed:
This item has security-sensitive risk. ClawSweeper is pausing instead of making an autonomous change that could affect trust, credentials, permissions, or exposure.

What the maintainer can do as a next step:
If the maintainer accepts the current risk and wants ClawSweeper to continue merge gates, comment @clawsweeper approve. If the security-sensitive detail still needs changes, describe the safe path or push the fix, then comment @clawsweeper automerge. If the risk should not be automated, keep the PR paused for manual review or comment @clawsweeper stop.

I added clawsweeper:human-review and left the final call with a maintainer.

@momothemage

Copy link
Copy Markdown
Contributor Author

@clawsweeper approve

@clawsweeper clawsweeper Bot removed the clawsweeper:human-review Needs maintainer review before ClawSweeper can continue label Jun 29, 2026
@clawsweeper
clawsweeper Bot merged commit db2488b into main Jun 29, 2026
163 of 175 checks passed
@clawsweeper
clawsweeper Bot deleted the feature/dreaming-outcome-events branch June 29, 2026 11:23
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jun 30, 2026
Summary:
- Merged fix(memory): record structured dreaming outcomes after ClawSweeper review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: chore(plugin-sdk): update surface budgets

Validation:
- ClawSweeper review passed for head 9fa7d20.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9fa7d20
Review: openclaw#97723 (comment)

Co-authored-by: momothemage <[email protected]>
Approved-by: momothemage
QiuYuang pushed a commit to QiuYuang/openclaw that referenced this pull request Jul 1, 2026
Summary:
- Merged fix(memory): record structured dreaming outcomes after ClawSweeper review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: chore(plugin-sdk): update surface budgets

Validation:
- ClawSweeper review passed for head 9fa7d20.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9fa7d20
Review: openclaw#97723 (comment)

Co-authored-by: momothemage <[email protected]>
Approved-by: momothemage
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
Summary:
- Merged fix(memory): record structured dreaming outcomes after ClawSweeper review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: chore(plugin-sdk): update surface budgets

Validation:
- ClawSweeper review passed for head 9fa7d20.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9fa7d20
Review: openclaw#97723 (comment)

Co-authored-by: momothemage <[email protected]>
Approved-by: momothemage
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 3, 2026
Summary:
- Merged fix(memory): record structured dreaming outcomes after ClawSweeper review.

Automerge notes:
- PR branch already contained follow-up commit before automerge: chore(plugin-sdk): update surface budgets

Validation:
- ClawSweeper review passed for head 9fa7d20.
- Required merge gates passed before the squash merge.

Prepared head SHA: 9fa7d20
Review: openclaw#97723 (comment)

Co-authored-by: momothemage <[email protected]>
Approved-by: momothemage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper:automerge Maintainer opted this PR into bounded ClawSweeper-reviewed automerge docs Improvements or additions to documentation extensions: memory-core Extension: memory-core maintainer Maintainer-authored PR 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. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: M status: 🚀 automerge armed This PR is in ClawSweeper's automerge lane.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Dreaming phase completion events lack outcome normalization (no success/failure/partial status)

1 participant