Skip to content

docs: Dreaming v2 architecture (OpenClaw parity) - #147

Open
TommyBez wants to merge 5 commits into
mainfrom
cursor/dreaming-architecture-docs-6abe
Open

docs: Dreaming v2 architecture (OpenClaw parity)#147
TommyBez wants to merge 5 commits into
mainfrom
cursor/dreaming-architecture-docs-6abe

Conversation

@TommyBez

@TommyBez TommyBez commented May 22, 2026

Copy link
Copy Markdown
Owner

Summary

Adds docs/DREAMING.md, the target architecture for agent memory consolidation (Light → REM → Deep, diary report + best-effort narrative, budget gates, sandbox layout). Links from docs/ARCHITECTURE.md.

Design-only PR — no runtime changes.

Key decisions documented

  • No budget → sweep does not run
  • With budget → REM is always required; Deep is deterministic
  • MEMORY.md promotions only from Deep; DREAMS.md is non-canonical
  • OpenClaw parity: diary narrative LLM is best-effort after structured report

Files

  • docs/DREAMING.md (new)
  • docs/ARCHITECTURE.md (link to dreaming doc)
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Introduces a runtime "Dreaming v2" memory-consolidation pipeline that consolidates recent evidence into durable memory and a cumulative Dream Diary; optional diary narratives are generated safely and skipped on failure.
    • Adds per-agent serialized dreaming runs with budget gating and single-run concurrency.
  • Documentation

    • Comprehensive docs and ADR for Dreaming v2: phases, failure/retry semantics, sandboxed storage, configuration defaults, scheduler behavior, and FAQ.
    • UI text updated to reference "Dream Diary" and runtime memory consolidation.

@vercel

vercel Bot commented May 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
outname Ready Ready Preview, Comment, Open in v0 Jun 8, 2026 5:25pm
outname-api Error Error Jun 8, 2026 5:25pm
outname-app Ready Ready Preview, Comment Jun 8, 2026 5:25pm

Request Review

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TommyBez, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 57 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ccffef24-e60d-42a1-8595-3d92cd74b03c

📥 Commits

Reviewing files that changed from the base of the PR and between ebf71f7 and 6f671a5.

📒 Files selected for processing (1)
  • packages/shared/next/create-outname-next-config.ts

Walkthrough

Adds a new DREAMING.md describing the dreaming v2 memory-governance pipeline (Light, REM, Deep, Diary), with budget gating, deterministic promotion rules, runtime/sandbox constraints, scheduler/workflow mappings, agent/prompt restrictions, and an ARCHITECTURE.md cross-reference.

Changes

Dreaming v2 Memory Pipeline

Layer / File(s) Summary
Architecture overview and concept
docs/DREAMING.md
Introduces dreaming v2 scope, target architecture, product intent, OpenClaw parity targets, phase flowchart, and budget-gating semantics.
Runtime placement and sandbox structure
docs/DREAMING.md
Contrasts v1 vs v2 behavior, defines workflow handler and cron ingress placement, describes persistent sandbox layout and path-guard requirements, and specifies Light phase constraints (no LLM, no MEMORY.md, no diary).
Phase specifications: REM, Deep
docs/DREAMING.md
Defines REM as a required deterministic semantic phase with strict failure semantics and Deep as TypeScript-only deterministic promotion to MEMORY.md with rehydration and Outname-owned marker-based appends (Deep does not call LLM).
Diary behavior and data models
docs/DREAMING.md, packages/ai/agent-runtime/memory-core/diary.ts, packages/ai/agent-runtime/memory-core/types.ts
Specifies Diary report (TypeScript) and optional narrative (bounded best-effort LLM) semantics, non-promotion guarantees, diary append helpers, and sketch data models for recall candidates/signals/manifests.
Store, migrations, and sql.js adapter
packages/ai/agent-runtime/memory-core/store/schema.ts, packages/ai/agent-runtime/memory-core/store/migrations.ts, packages/ai/agent-runtime/memory-core/store/sql-js.ts
Adds Drizzle schema, SQLite migrations, and a sql.js-backed OpenDreaming adapter with export/import helpers.
Sandbox persistence and helpers
packages/ai/agent-runtime/memory-core/store/sandbox.ts, packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/*
Adds sandbox read/write helpers for the Dreaming sqlite file, path guards (memory/.dreams runtime-owned), list/grep/read guards, and agent-visible/writable path assertions.
Core store operations and orchestration steps
packages/ai/agent-runtime/memory-core/store/operations.ts, packages/ai/agent-runtime/workflows/session/steps/dreaming/dreaming-steps.ts, packages/ai/agent-runtime/workflows/session/handlers/handle-dreaming.ts
Implements sweep lifecycle, evidence upsert/derivation, REM scoring, promotion recording, Light/REM/Deep/Diary step implementations, sandbox orchestration, budget gating, diary persistence, and the top-level handleDreaming workflow handler with tests.
Promotion, ranking, sanitization, and markers
packages/ai/agent-runtime/memory-core/promote.ts, packages/ai/agent-runtime/memory-core/rank.ts, packages/ai/agent-runtime/memory-core/sanitize.ts, packages/ai/agent-runtime/memory-core/markers.ts
Adds deterministic text normalization, candidate scoring/eligibility, promotion selection and rendering with Outname HTML markers, and sanitizers to strip managed dreaming content.
Evidence extraction and transcript ingestion
packages/ai/agent-runtime/memory-core/extract.ts, packages/ai/agent-runtime/server/agent-event-transcript-store.ts
Adds line-based evidence snippet extraction and bounded transcript ingestion for recent completed events with per-event/message limits.
Workflow, scheduler, and concurrency changes
packages/ai/agent-runtime/workflows/agent-events/workflow.ts, packages/ai/agent-runtime/server/event-scheduler.ts, packages/ai/agent-runtime/server/agent-event-keys.ts, packages/ai/agent-runtime/server/agent-event-store.ts, packages/ai/agent-runtime/server/session-events.ts
Routes dreaming events to handleDreaming, introduces a per-agent dreaming concurrency key, finds active/queued dreaming events to avoid duplicates, and updates scheduler enqueueing and poke logic.
Tests and type declarations
packages/ai/agent-runtime/memory-core/*.{test,ts}, packages/ai/sql-js.d.ts, tsconfig*.json
Adds unit/integration tests for diary, markers, promote, sql-js adapter, and updates TS include globs and sql.js typings.
UI/Docs copy and ADR
docs/DREAMING.md, docs/ARCHITECTURE.md, CONTEXT.md, docs/adr/0005-dreaming-v2-memory-governance.md, packages/shared/*
Adds DREAMING.md, updates ARCHITECTURE.md and CONTEXT.md glossary, adds ADR, and updates agent-facing copy/templates to reflect runtime-managed Dream Diary and constraints.
Config and dependency
packages/ai/agent-runtime/memory-core/config.ts, packages/ai/package.json
Adds DEFAULT_DREAMING_CONFIG and resolve helper; adds sql.js dependency and typings.

Sequence Diagram(s)

(Skipped — the change set is large and includes many components; a single compact sequence diagram would oversimplify multiple coordinated flows.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • TommyBez/outname#158: Modifies handle-heartbeat related logic; potentially related to the heartbeat/dreaming handler refactor and workflow step changes.

Poem

🐰 In quiet sandboxes the memory hums,
Light sifts the logs and REM counts the sums,
Deep pins a marker where the truth may stay,
Diary notes whisper what the day gave away,
A rabbit hops off—dreams saved for another day.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/dreaming-architecture-docs-6abe

@TommyBez
TommyBez marked this pull request as ready for review May 22, 2026 21:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/DREAMING.md (1)

80-80: ⚡ Quick win

Consider making the cross-reference more specific.

The phrase "see scheduling note below" is vague. Consider linking to the specific section, e.g., "see Budget integration > Scheduling when budget-blocked".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/DREAMING.md` at line 80, The table cell text "see scheduling note below"
is vague—replace it with a specific cross-reference to the exact section (for
example: "see Budget integration > Scheduling when budget-blocked") and make it
a clickable/internal link if your docs system supports anchors; update the table
row string shown (the Budget row in DREAMING.md) to use that explicit section
title or anchor link so readers jump directly to the Scheduling when
budget-blocked note.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/DREAMING.md`:
- Around line 87-97: The fenced code block in DREAMING.md lacks a language
specifier; update the block that shows app/api/cron/liveness/route.ts →
runAgentEventScheduler() → enqueueAgentEvent({ type: 'dreaming' }) and the
agent-runtime entries (handleDreaming, handleHeartbeat, sweep orchestrator) to
start with a language tag such as ```text or ```plaintext so syntax highlighters
and linters properly recognize it; ensure the opening fence before the lines
containing runAgentEventScheduler(), enqueueAgentEvent, handleDreaming(),
handleHeartbeat, and the memory-core sweep note is replaced with ```text (or
```plaintext) and the closing fence remains unchanged.

---

Nitpick comments:
In `@docs/DREAMING.md`:
- Line 80: The table cell text "see scheduling note below" is vague—replace it
with a specific cross-reference to the exact section (for example: "see Budget
integration > Scheduling when budget-blocked") and make it a clickable/internal
link if your docs system supports anchors; update the table row string shown
(the Budget row in DREAMING.md) to use that explicit section title or anchor
link so readers jump directly to the Scheduling when budget-blocked note.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7aca2f8d-a8ae-4bdc-9819-99c6387d086a

📥 Commits

Reviewing files that changed from the base of the PR and between 91a0c01 and b173b7b.

📒 Files selected for processing (2)
  • docs/ARCHITECTURE.md
  • docs/DREAMING.md

Comment thread docs/DREAMING.md
cursoragent and others added 3 commits June 8, 2026 14:55
Document the full memory-core pipeline (Light, REM, Deep, diary report
and best-effort narrative), budget gates, sandbox layout, and OpenClaw
parity targets. Link from ARCHITECTURE.md.

Co-authored-by: Tommaso <tommaso.carnemolla@gmail.com>
Co-authored-by: Tommaso <tommaso.carnemolla@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/ai/agent-runtime/memory-core/extract.ts (1)

25-27: ⚡ Quick win

Prefer for...of iteration for line scanning

This loop is index-based even though iteration is sequential. Converting to for...of with entries() simplifies the control flow while preserving line numbers.

As per coding guidelines, “Prefer for...of loops over .forEach() and indexed for loops.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/extract.ts` around lines 25 - 27,
Replace the indexed for loop with a for...of over lines.entries() to iterate
sequentially while preserving the line index; specifically change the loop that
currently uses "for (let index = 0; index < lines.length; index += 1)" and
references "lines[index]"/"rawText" to use "for (const [index, rawLine] of
lines.entries())" (or equivalent), then feed rawLine.trim() into
normalizeCandidateText and keep using the same index variable where line numbers
are required (e.g., in calls that use normalized or rawText) so behavior and
line-numbering remain unchanged.

Source: Coding guidelines

packages/ai/agent-runtime/memory-core/rank.ts (1)

32-32: ⚡ Quick win

Extract 86_400_000 into a named constant

The repeated day-milliseconds literal is a magic number. Define a single constant (for example MILLISECONDS_PER_DAY) and reuse it in both age calculations.

As per coding guidelines, “Use meaningful variable names instead of magic numbers - extract constants with descriptive names.”

Also applies to: 54-54

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/rank.ts` at line 32, Replace the magic
number 86_400_000 with a well-named constant (e.g., MILLISECONDS_PER_DAY) and
use it for all day-to-millisecond conversions in this module; specifically,
introduce const MILLISECONDS_PER_DAY = 86_400_000 at the top of
packages/ai/agent-runtime/memory-core/rank.ts and update the age calculation(s)
that compute ageDays (and the second occurrence around the other age calculation
at the same file) to use ageDays = ageMs / MILLISECONDS_PER_DAY so both places
reuse the descriptive constant.

Source: Coding guidelines

packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/paths.test.ts (1)

11-23: ⚡ Quick win

Add a prefix-path assertion for runtime-owned coverage.

Current test covers only exact path matching. Add a case for a nested path (e.g., memory/.dreams/subdir/file.txt) to protect the startsWith branch in isRuntimeOwnedPath (Line 76 in paths.ts).

Suggested test addition
   it('blocks runtime-owned dreaming store paths', () => {
     expect(isRuntimeOwnedPath('memory/.dreams/dreaming.sqlite')).toBe(true)
+    expect(isRuntimeOwnedPath('memory/.dreams/subdir/file.txt')).toBe(true)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/paths.test.ts`
around lines 11 - 23, Add a test case that asserts runtime-owned paths are
detected for nested/prefix paths (not just exact matches): call
isRuntimeOwnedPath('memory/.dreams/subdir/file.txt') and expect true, then pass
normalizeSandboxPath('memory/.dreams/subdir/file.txt') into
assertWritableSandboxPath and assertAgentVisibleSandboxPath and expect both to
throw SandboxPathError; this covers the startsWith branch in isRuntimeOwnedPath
and ensures the same protection as the existing exact-path case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ai/agent-runtime/memory-core/extract.ts`:
- Around line 48-49: The loop currently treats input.maxSnippets with a truthy
check so a value of 0 is ignored; change the condition to explicitly check for
undefined/null (e.g., input.maxSnippets != null) before enforcing the cap so
maxSnippets = 0 acts as a limit; update the condition that uses
input.maxSnippets and snippets (the if block shown) to break when
snippets.length >= input.maxSnippets only when input.maxSnippets is not
null/undefined, leaving other behavior unchanged.

In `@packages/ai/agent-runtime/memory-core/sanitize.ts`:
- Around line 3-4: The current DREAMING_MANAGED_BLOCK_RE can remove content
between a start and a non-matching end marker; update the regex in sanitize.ts
(symbol DREAMING_MANAGED_BLOCK_RE) to capture the label after
"outname:dreaming:" and use a backreference for the closing marker so the
start/end names must match (e.g. change to capture group for ([\w-]+) and use \1
in the corresponding :end part), keeping the global flag and
non-greedy/single-line behavior.

In `@packages/ai/agent-runtime/memory-core/store/migrations.ts`:
- Around line 47-78: The CREATE TABLE statements for evidence_snippets,
phase_signals and promotions define relation columns (candidate_key, source_id,
sweep_id, query_key) but lack FOREIGN KEY REFERENCES clauses, so SQLite won't
enforce integrity; update the CREATE TABLE for evidence_snippets to add
REFERENCES to the table that holds candidates (e.g., candidate_key REFERENCES
candidates(key)) and to the table that holds sources (e.g., source_id REFERENCES
sources(id)) and query_key REFERENCES queries(key); update phase_signals to add
sweep_id REFERENCES sweeps(id) and candidate_key REFERENCES candidates(key);
update promotions to add sweep_id REFERENCES sweeps(id) (and key if it should
reference another table) and include appropriate ON DELETE/ON UPDATE behavior
(CASCADE or RESTRICT) as needed; keep the existing PRAGMA foreign_keys = ON and
ensure the new REFERENCES clauses use the exact primary key column names of the
referenced tables.

In `@packages/ai/agent-runtime/memory-core/store/operations.ts`:
- Around line 42-48: The upsert conflict handler in operations.ts currently
updates sweeps via .onConflictDoUpdate(...) setting attempt, error, and status
but leaves completedAt unchanged; update the conflict update set (in the
.onConflictDoUpdate block for sweeps) to explicitly reset completedAt to null
when reopening a sweep (e.g., include completedAt: null alongside attempt,
error, and status) so a retried/replayed sweep cannot retain a stale completion
timestamp.

---

Nitpick comments:
In `@packages/ai/agent-runtime/memory-core/extract.ts`:
- Around line 25-27: Replace the indexed for loop with a for...of over
lines.entries() to iterate sequentially while preserving the line index;
specifically change the loop that currently uses "for (let index = 0; index <
lines.length; index += 1)" and references "lines[index]"/"rawText" to use "for
(const [index, rawLine] of lines.entries())" (or equivalent), then feed
rawLine.trim() into normalizeCandidateText and keep using the same index
variable where line numbers are required (e.g., in calls that use normalized or
rawText) so behavior and line-numbering remain unchanged.

In `@packages/ai/agent-runtime/memory-core/rank.ts`:
- Line 32: Replace the magic number 86_400_000 with a well-named constant (e.g.,
MILLISECONDS_PER_DAY) and use it for all day-to-millisecond conversions in this
module; specifically, introduce const MILLISECONDS_PER_DAY = 86_400_000 at the
top of packages/ai/agent-runtime/memory-core/rank.ts and update the age
calculation(s) that compute ageDays (and the second occurrence around the other
age calculation at the same file) to use ageDays = ageMs / MILLISECONDS_PER_DAY
so both places reuse the descriptive constant.

In
`@packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/paths.test.ts`:
- Around line 11-23: Add a test case that asserts runtime-owned paths are
detected for nested/prefix paths (not just exact matches): call
isRuntimeOwnedPath('memory/.dreams/subdir/file.txt') and expect true, then pass
normalizeSandboxPath('memory/.dreams/subdir/file.txt') into
assertWritableSandboxPath and assertAgentVisibleSandboxPath and expect both to
throw SandboxPathError; this covers the startsWith branch in isRuntimeOwnedPath
and ensures the same protection as the existing exact-path case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d187a519-d11f-4dd0-aa6f-6c852a2e61a6

📥 Commits

Reviewing files that changed from the base of the PR and between c289652 and ebf71f7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (53)
  • apps/app/app/agents/[agentId]/memory/dreams/page.tsx
  • apps/app/app/agents/[agentId]/memory/page.tsx
  • next.config.ts
  • packages/ai/agent-runtime/memory-core/config.ts
  • packages/ai/agent-runtime/memory-core/diary.test.ts
  • packages/ai/agent-runtime/memory-core/diary.ts
  • packages/ai/agent-runtime/memory-core/extract.ts
  • packages/ai/agent-runtime/memory-core/markers.test.ts
  • packages/ai/agent-runtime/memory-core/markers.ts
  • packages/ai/agent-runtime/memory-core/promote.test.ts
  • packages/ai/agent-runtime/memory-core/promote.ts
  • packages/ai/agent-runtime/memory-core/rank.ts
  • packages/ai/agent-runtime/memory-core/sanitize.ts
  • packages/ai/agent-runtime/memory-core/store/migrations.ts
  • packages/ai/agent-runtime/memory-core/store/operations.ts
  • packages/ai/agent-runtime/memory-core/store/sandbox.ts
  • packages/ai/agent-runtime/memory-core/store/schema.ts
  • packages/ai/agent-runtime/memory-core/store/sql-js.test.ts
  • packages/ai/agent-runtime/memory-core/store/sql-js.ts
  • packages/ai/agent-runtime/memory-core/types.ts
  • packages/ai/agent-runtime/server/agent-event-keys.test.ts
  • packages/ai/agent-runtime/server/agent-event-keys.ts
  • packages/ai/agent-runtime/server/agent-event-store.ts
  • packages/ai/agent-runtime/server/agent-event-transcript-store.ts
  • packages/ai/agent-runtime/server/event-scheduler.ts
  • packages/ai/agent-runtime/server/session-events.test.ts
  • packages/ai/agent-runtime/server/session-events.ts
  • packages/ai/agent-runtime/workflows/agent-events/workflow.ts
  • packages/ai/agent-runtime/workflows/events/steps/event-store.ts
  • packages/ai/agent-runtime/workflows/events/workflow.workflow.unit.test.ts
  • packages/ai/agent-runtime/workflows/session/agent-factory.ts
  • packages/ai/agent-runtime/workflows/session/compose-system-prompt.ts
  • packages/ai/agent-runtime/workflows/session/handlers/handle-dreaming.ts
  • packages/ai/agent-runtime/workflows/session/handlers/handle-dreaming.unit.test.ts
  • packages/ai/agent-runtime/workflows/session/handlers/handle-heartbeat.ts
  • packages/ai/agent-runtime/workflows/session/handlers/handle-heartbeat.unit.test.ts
  • packages/ai/agent-runtime/workflows/session/steps/dreaming/dreaming-steps.ts
  • packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/grep.ts
  • packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/list.ts
  • packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/paths.test.ts
  • packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/paths.ts
  • packages/ai/agent-runtime/workflows/session/tools/sandbox-file-helpers/read.ts
  • packages/ai/package.json
  • packages/ai/sql-js.d.ts
  • packages/shared/agents/api/creation-chat/create-requested-agent.ts
  • packages/shared/agents/api/creation-chat/schemas.ts
  • packages/shared/agents/components/agent-form/dreaming-settings.tsx
  • packages/shared/agents/components/agent-memory-pages.tsx
  • packages/shared/agents/server/agents-md-template.ts
  • packages/shared/agents/server/bootstrap-files.ts
  • packages/shared/content/blog/posts.ts
  • tsconfig.json
  • tsconfig.vitest.json
💤 Files with no reviewable changes (2)
  • packages/ai/agent-runtime/workflows/session/agent-factory.ts
  • packages/ai/agent-runtime/workflows/session/handlers/handle-heartbeat.unit.test.ts
✅ Files skipped from review due to trivial changes (12)
  • apps/app/app/agents/[agentId]/memory/dreams/page.tsx
  • next.config.ts
  • tsconfig.json
  • packages/ai/sql-js.d.ts
  • tsconfig.vitest.json
  • packages/shared/agents/components/agent-memory-pages.tsx
  • apps/app/app/agents/[agentId]/memory/page.tsx
  • packages/ai/agent-runtime/server/agent-event-keys.test.ts
  • packages/ai/agent-runtime/memory-core/config.ts
  • packages/shared/agents/api/creation-chat/schemas.ts
  • packages/shared/agents/server/agents-md-template.ts
  • packages/shared/agents/components/agent-form/dreaming-settings.tsx

Comment on lines +48 to +49
if (input.maxSnippets && snippets.length >= input.maxSnippets) {
break

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

maxSnippets = 0 currently behaves as “no limit”

Line 48 uses a truthy check, so 0 is ignored and extraction continues unbounded. Use an explicit undefined/null check for the cap.

Suggested fix
 export function extractEvidenceSnippets(
   input: ExtractEvidenceInput
 ): EvidenceSnippet[] {
+  if ((input.maxSnippets ?? Infinity) <= 0) {
+    return []
+  }
   const cleaned = stripManagedDreamingContent(input.text)
   const snippets: EvidenceSnippet[] = []
   const lines = cleaned.split('\n')
@@
-    if (input.maxSnippets && snippets.length >= input.maxSnippets) {
+    if (
+      input.maxSnippets !== undefined &&
+      snippets.length >= input.maxSnippets
+    ) {
       break
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/extract.ts` around lines 48 - 49, The
loop currently treats input.maxSnippets with a truthy check so a value of 0 is
ignored; change the condition to explicitly check for undefined/null (e.g.,
input.maxSnippets != null) before enforcing the cap so maxSnippets = 0 acts as a
limit; update the condition that uses input.maxSnippets and snippets (the if
block shown) to break when snippets.length >= input.maxSnippets only when
input.maxSnippets is not null/undefined, leaving other behavior unchanged.

Comment on lines +3 to +4
const DREAMING_MANAGED_BLOCK_RE =
/<!--\s*outname:dreaming:[\w-]+:start\b[\s\S]*?<!--\s*outname:dreaming:[\w-]+:end\s*-->/g

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Managed-block regex can over-strip unrelated content

The regex does not require the :end marker label to match the :start label. A mismatched pair can remove arbitrary intervening markdown, which risks data loss during sanitization.

Suggested fix
-const DREAMING_MANAGED_BLOCK_RE =
-  /<!--\s*outname:dreaming:[\w-]+:start\b[\s\S]*?<!--\s*outname:dreaming:[\w-]+:end\s*-->/g
+const DREAMING_MANAGED_BLOCK_RE =
+  /<!--\s*outname:dreaming:([\w-]+):start\b[\s\S]*?<!--\s*outname:dreaming:\1:end\s*-->/g
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const DREAMING_MANAGED_BLOCK_RE =
/<!--\s*outname:dreaming:[\w-]+:start\b[\s\S]*?<!--\s*outname:dreaming:[\w-]+:end\s*-->/g
const DREAMING_MANAGED_BLOCK_RE =
/<!--\s*outname:dreaming:([\w-]+):start\b[\s\S]*?<!--\s*outname:dreaming:\1:end\s*-->/g
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/sanitize.ts` around lines 3 - 4, The
current DREAMING_MANAGED_BLOCK_RE can remove content between a start and a
non-matching end marker; update the regex in sanitize.ts (symbol
DREAMING_MANAGED_BLOCK_RE) to capture the label after "outname:dreaming:" and
use a backreference for the closing marker so the start/end names must match
(e.g. change to capture group for ([\w-]+) and use \1 in the corresponding :end
part), keeping the global flag and non-greedy/single-line behavior.

Comment on lines +47 to +78
CREATE TABLE IF NOT EXISTS evidence_snippets (
id TEXT PRIMARY KEY,
candidate_key TEXT NOT NULL,
source_type TEXT NOT NULL,
source_id TEXT NOT NULL,
path TEXT,
line INTEGER,
text TEXT NOT NULL,
observed_at TEXT NOT NULL,
query_key TEXT NOT NULL
)
`)
sqlite.run(`
CREATE TABLE IF NOT EXISTS phase_signals (
id TEXT PRIMARY KEY,
sweep_id TEXT NOT NULL,
phase TEXT NOT NULL,
candidate_key TEXT,
signal_type TEXT NOT NULL,
score REAL,
metadata_json TEXT NOT NULL,
created_at TEXT NOT NULL
)
`)
sqlite.run(`
CREATE TABLE IF NOT EXISTS promotions (
key TEXT PRIMARY KEY,
sweep_id TEXT NOT NULL,
marker TEXT NOT NULL,
promoted_at TEXT NOT NULL,
memory_path TEXT NOT NULL
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add actual FK constraints for relation columns.

Line 6 enables foreign keys, but Lines 47-78 define relation columns without REFERENCES, so SQLite will not enforce integrity and orphan rows can be written.

Suggested schema adjustment
   sqlite.run(`
     CREATE TABLE IF NOT EXISTS evidence_snippets (
       id TEXT PRIMARY KEY,
-      candidate_key TEXT NOT NULL,
+      candidate_key TEXT NOT NULL REFERENCES recall_candidates(key) ON DELETE CASCADE,
       source_type TEXT NOT NULL,
       source_id TEXT NOT NULL,
       path TEXT,
       line INTEGER,
       text TEXT NOT NULL,
       observed_at TEXT NOT NULL,
       query_key TEXT NOT NULL
     )
   `)
   sqlite.run(`
     CREATE TABLE IF NOT EXISTS phase_signals (
       id TEXT PRIMARY KEY,
-      sweep_id TEXT NOT NULL,
+      sweep_id TEXT NOT NULL REFERENCES sweeps(id) ON DELETE CASCADE,
       phase TEXT NOT NULL,
-      candidate_key TEXT,
+      candidate_key TEXT REFERENCES recall_candidates(key) ON DELETE SET NULL,
       signal_type TEXT NOT NULL,
       score REAL,
       metadata_json TEXT NOT NULL,
       created_at TEXT NOT NULL
     )
   `)
   sqlite.run(`
     CREATE TABLE IF NOT EXISTS promotions (
       key TEXT PRIMARY KEY,
-      sweep_id TEXT NOT NULL,
+      sweep_id TEXT NOT NULL REFERENCES sweeps(id) ON DELETE CASCADE,
       marker TEXT NOT NULL,
       promoted_at TEXT NOT NULL,
       memory_path TEXT NOT NULL
     )
   `)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/store/migrations.ts` around lines 47 -
78, The CREATE TABLE statements for evidence_snippets, phase_signals and
promotions define relation columns (candidate_key, source_id, sweep_id,
query_key) but lack FOREIGN KEY REFERENCES clauses, so SQLite won't enforce
integrity; update the CREATE TABLE for evidence_snippets to add REFERENCES to
the table that holds candidates (e.g., candidate_key REFERENCES candidates(key))
and to the table that holds sources (e.g., source_id REFERENCES sources(id)) and
query_key REFERENCES queries(key); update phase_signals to add sweep_id
REFERENCES sweeps(id) and candidate_key REFERENCES candidates(key); update
promotions to add sweep_id REFERENCES sweeps(id) (and key if it should reference
another table) and include appropriate ON DELETE/ON UPDATE behavior (CASCADE or
RESTRICT) as needed; keep the existing PRAGMA foreign_keys = ON and ensure the
new REFERENCES clauses use the exact primary key column names of the referenced
tables.

Comment on lines +42 to +48
.onConflictDoUpdate({
target: sweeps.id,
set: {
attempt: input.attempt,
error: null,
status: 'running',
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reset completedAt when re-opening an existing sweep row.

At Line 44, conflict updates leave completedAt untouched. If the same sweepId is retried/replayed, you can persist status: 'running' with a stale completion timestamp.

Suggested fix
   .onConflictDoUpdate({
     target: sweeps.id,
     set: {
       attempt: input.attempt,
+      completedAt: null,
       error: null,
+      startedAt: input.nowIso,
       status: 'running',
     },
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.onConflictDoUpdate({
target: sweeps.id,
set: {
attempt: input.attempt,
error: null,
status: 'running',
},
.onConflictDoUpdate({
target: sweeps.id,
set: {
attempt: input.attempt,
completedAt: null,
error: null,
startedAt: input.nowIso,
status: 'running',
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai/agent-runtime/memory-core/store/operations.ts` around lines 42 -
48, The upsert conflict handler in operations.ts currently updates sweeps via
.onConflictDoUpdate(...) setting attempt, error, and status but leaves
completedAt unchanged; update the conflict update set (in the
.onConflictDoUpdate block for sweeps) to explicitly reset completedAt to null
when reopening a sweep (e.g., include completedAt: null alongside attempt,
error, and status) so a retried/replayed sweep cannot retain a stale completion
timestamp.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants