Skip to content

feat(memory): expand conversational event semantics#524

Open
vsumner wants to merge 3 commits intocodex/memory-observation-p1from
codex/memory-observation-p2
Open

feat(memory): expand conversational event semantics#524
vsumner wants to merge 3 commits intocodex/memory-observation-p1from
codex/memory-observation-p2

Conversation

@vsumner
Copy link
Copy Markdown
Collaborator

@vsumner vsumner commented Apr 1, 2026

Why

PR 1 introduced stricter memory discipline and the first conversational event types, but the working-memory layer still collapsed too many runtime outcomes into generic completion text. That left the system with weaker temporal recall for the exact cases we care about in long agent sessions: blocked work, explicit constraints, terminal outcomes, and concrete deadlines.

This PR finishes that next slice by making those states first-class working-memory events and aligning the persistence prompt/tool schema with the runtime taxonomy. The goal is not to add the observation log yet. The goal is to make the current working-memory surface semantically better before adding another memory layer.

Scope

This PR is intentionally limited to the rest of P2 on the existing working-memory path:

  • expand conversational event taxonomy
  • route more branch/worker/task/delegation outcomes into typed events
  • align persistence prompts/tool schema with the new event types
  • add focused regression coverage for the new emitter paths

This PR does not introduce the observation-log MVP or prompt assembly refactor yet.

What Changed

  • Added new working-memory event types: deadline_set, blocked_on, constraint, and outcome.
  • Branch and worker completion summaries now classify explicit outcome:, blocked_on:, and constraint: prefixes into typed conversational events instead of leaving them as generic completion strings.
  • Task creation and task updates now emit Outcome only when the task actually reaches done; non-terminal changes remain TaskUpdate.
  • Duplicate worker spawn suppression now emits BlockedOn, and cross-agent delegation now emits a real Outcome event rather than dead metadata embedded in an AgentMessage summary.
  • The memory persistence prompt and memory_persistence_complete schema now teach and accept the full conversational event taxonomy so extracted events match the runtime shapes.
  • Added focused tests covering outcome-emitting task/delegation flows, event-type roundtrips, persistence event writing, and conversational summary classification.

Testing

  • cargo fmt --all
  • cargo test -p spacebot emits_outcome -- --test-threads=1 --nocapture
  • cargo test -p spacebot test_event_type_roundtrip -- --test-threads=1 --nocapture
  • cargo test -p spacebot conversational_event_summary_ -- --test-threads=1 --nocapture
  • cargo test -p spacebot persists_conversational_events -- --test-threads=1 --nocapture
  • just preflight
  • just gate-pr

Notes

  • This PR is intentionally stacked on codex/memory-observation-p1. After PR 522 merges, retarget this PR to main.
  • send_agent_message, task_create, and task_update now have direct emitter tests because the earlier coverage only proved taxonomy/classifier plumbing, not the actual tool-level event emissions.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b3b63d44-6349-4fab-96d2-d4a6b0fdfbc7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/memory-observation-p2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vsumner vsumner marked this pull request as ready for review April 1, 2026 12:31
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/agent/channel.rs (1)

3870-3898: Consider adding test coverage for constraint: prefix and edge cases.

The tests cover outcome: and blocked_on: extraction plus fallback behavior, but don't verify:

  • constraint: prefix extraction (the third recognized prefix)
  • Case insensitivity (e.g., "OUTCOME: ..." or "Outcome: ...")
  • Empty content after prefix (e.g., "outcome:" or "outcome: ")
🧪 Suggested additional tests
+    #[test]
+    fn conversational_event_summary_extracts_constraint_prefix() {
+        let (event_type, summary) = classify_conversational_event_summary(
+            "constraint: must not exceed rate limit",
+            WorkingMemoryEventType::BranchCompleted,
+        );
+        assert_eq!(event_type, WorkingMemoryEventType::Constraint);
+        assert_eq!(summary, "must not exceed rate limit");
+    }
+
+    #[test]
+    fn conversational_event_summary_is_case_insensitive() {
+        let (event_type, _) = classify_conversational_event_summary(
+            "OUTCOME: done",
+            WorkingMemoryEventType::WorkerCompleted,
+        );
+        assert_eq!(event_type, WorkingMemoryEventType::Outcome);
+
+        let (event_type, _) = classify_conversational_event_summary(
+            "Blocked_On: waiting",
+            WorkingMemoryEventType::WorkerCompleted,
+        );
+        assert_eq!(event_type, WorkingMemoryEventType::BlockedOn);
+    }
+
+    #[test]
+    fn conversational_event_summary_handles_empty_content_after_prefix() {
+        let (event_type, summary) = classify_conversational_event_summary(
+            "outcome:",
+            WorkingMemoryEventType::WorkerCompleted,
+        );
+        assert_eq!(event_type, WorkingMemoryEventType::Outcome);
+        assert_eq!(summary, "outcome:");
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/agent/channel.rs` around lines 3870 - 3898, Add unit tests for
classify_conversational_event_summary to cover the missing `constraint:` prefix,
case-insensitive prefixes, and empty-content edge cases: add a test that passes
a string starting with `"constraint: ..."` and assert the returned event_type is
WorkingMemoryEventType::Constraint and summary excludes the prefix; add tests
that pass prefixes in different cases (e.g., `"OUTCOME: ...", "Outcome: ..."`)
and assert they are normalized to the same WorkingMemoryEventType (e.g.,
WorkerCompleted -> Outcome) with trimmed summaries; and add tests for inputs
like `"outcome:"` and `"outcome:   "` asserting the event_type is Outcome and
the summary is an empty string (or trimmed-empty) to confirm correct
trimming/empty handling in classify_conversational_event_summary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/agent/channel.rs`:
- Around line 3870-3898: Add unit tests for
classify_conversational_event_summary to cover the missing `constraint:` prefix,
case-insensitive prefixes, and empty-content edge cases: add a test that passes
a string starting with `"constraint: ..."` and assert the returned event_type is
WorkingMemoryEventType::Constraint and summary excludes the prefix; add tests
that pass prefixes in different cases (e.g., `"OUTCOME: ...", "Outcome: ..."`)
and assert they are normalized to the same WorkingMemoryEventType (e.g.,
WorkerCompleted -> Outcome) with trimmed summaries; and add tests for inputs
like `"outcome:"` and `"outcome:   "` asserting the event_type is Outcome and
the summary is an empty string (or trimmed-empty) to confirm correct
trimming/empty handling in classify_conversational_event_summary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 71c3bbb2-b19f-4852-924c-9bf0f433f5b1

📥 Commits

Reviewing files that changed from the base of the PR and between af64604 and 24d18ba.

📒 Files selected for processing (8)
  • prompts/en/memory_persistence.md.j2
  • src/agent/channel.rs
  • src/memory/working.rs
  • src/tools/memory_persistence_complete.rs
  • src/tools/send_agent_message.rs
  • src/tools/spawn_worker.rs
  • src/tools/task_create.rs
  • src/tools/task_update.rs

@vsumner vsumner force-pushed the codex/memory-observation-p2 branch from 24d18ba to 3e8dced Compare April 1, 2026 13:08
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.

1 participant