Skip to content

fix(lifeops): keep proactive digests to personal inboxes#7889

Merged
lalalune merged 1 commit into
developfrom
nubs/lifeops-proactive-personal-inbox-20260521
May 22, 2026
Merged

fix(lifeops): keep proactive digests to personal inboxes#7889
lalalune merged 1 commit into
developfrom
nubs/lifeops-proactive-personal-inbox-20260521

Conversation

@NubsCarson
Copy link
Copy Markdown
Member

@NubsCarson NubsCarson commented May 22, 2026

Summary

Prevents proactive LifeOps GM/GN inbox digests from summarizing chat connector memories as unread personal inbox items.

Why

During live local-source testing, the proactive worker sent a night summary DM that included stale Discord test-channel messages as "unread" inbox highlights. The root cause is that chat connector memories do not yet carry reliable per-owner read state; the inbox layer conservatively marks those cached chat items unread so explicit inbox views can still triage them. Proactive digests should not use that same broad channel set for unsolicited owner DMs.

Change

  • Adds a small proactiveInboxDigestRequest() policy helper for the proactive worker.
  • Keeps proactive inbox digests scoped to channels with personal inbox semantics: Gmail, X DMs, iMessage, WhatsApp, and SMS.
  • Preserves explicit inbox behavior for chat connectors; this only changes the proactive digest query.

Validation

  • bunx @biomejs/biome check --write src/activity-profile/proactive-worker.ts src/activity-profile/proactive-inbox-digest.ts test/proactive-worker.test.ts --no-errors-on-unmatched
  • bun test --timeout 30000 test/proactive-worker.test.ts
  • bun run build
  • Live mitigation verified locally: after setting ELIZA_DISABLE_PROACTIVE_AGENT=1 and restarting, logs show [proactive] Proactive agent task skipped — ELIZA_DISABLE_PROACTIVE_AGENT=1 and no new GN digest fired after restart.

Greptile Summary

Scopes proactive GM/GN inbox digests to personal messaging channels only (Gmail, X DMs, iMessage, WhatsApp, SMS) to prevent stale chat-connector memories (Discord, Telegram, Signal) from surfacing as "unread" highlights in unsolicited owner DMs.

  • Extracts the channel-filter policy into a new proactiveInboxDigestRequest() helper in proactive-inbox-digest.ts, replacing the bare { limit: 24 } call in loadInboxDigest.
  • Adds missedOnly: true, groupByThread: true, and sortByPriority: true alongside the explicit channel allow-list; the resolveInboxRequest path in service-mixin-inbox.ts correctly falls back to all channels when channels is omitted, so explicit inbox views are unaffected.
  • Ships a unit test that pins the exact channel list and verifies that chat connectors are excluded.

Confidence Score: 4/5

Safe to merge; the change is narrowly scoped to the proactive digest path and does not touch explicit inbox views or shared data structures.

The fix is correct and well-contained. The only open question is whether signal belongs in the personal-channel allow-list alongside iMessage and WhatsApp — its omission could silently suppress Signal DMs from proactive digests if the connector is in use.

The new proactive-inbox-digest.ts file deserves a quick check on the signal channel exclusion decision.

Important Files Changed

Filename Overview
plugins/plugin-lifeops/src/activity-profile/proactive-inbox-digest.ts New policy helper that restricts proactive inbox digests to personal channels (gmail, x_dm, imessage, whatsapp, sms). Dead ?? [] fallback on a non-optional field and the intentional omission of signal are worth a second look.
plugins/plugin-lifeops/src/activity-profile/proactive-worker.ts Single call-site change: loadInboxDigest now uses proactiveInboxDigestRequest() instead of the bare { limit: 24 } object, correctly delegating channel scoping to the new policy helper.
plugins/plugin-lifeops/test/proactive-worker.test.ts New unit test that validates the channel list and base parameters. The three not.toContain assertions are redundant given the prior toEqual check.

Sequence Diagram

sequenceDiagram
    participant PW as proactive-worker
    participant PID as proactiveInboxDigestRequest()
    participant SVC as LifeOpsService.getInbox()
    participant RIR as resolveInboxRequest()

    PW->>PID: call proactiveInboxDigestRequest()
    PID-->>PW: "{ limit:24, channels:[gmail,x_dm,imessage,whatsapp,sms], missedOnly:true }"
    PW->>SVC: getInbox(request)
    SVC->>RIR: resolveInboxRequest(request)
    RIR-->>SVC: "allowed = Set{gmail, x_dm, imessage, whatsapp, sms}"
    Note over RIR: chat channels (discord, telegram, signal) NOT in allowed set
    SVC-->>PW: LifeOpsInbox (personal channels only)
    PW->>PW: build InboxDigestSlim for GM/GN DM
Loading

Reviews (1): Last reviewed commit: "fix(lifeops): keep proactive digests to ..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Auto reviews are disabled on this repository. 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: f0e84928-e041-4f10-82e4-5cfb42cb44d1

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 nubs/lifeops-proactive-personal-inbox-20260521

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.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 22, 2026

Claude encountered an error —— View job


I'll analyze this and get back to you.

@github-actions
Copy link
Copy Markdown
Contributor

LifeOps Benchmark — eliza

Run ID: lifeops-eliza-26260312668

LifeOps Benchmark

Model: gpt-oss-120b
Judge: claude-opus-4-7
Scenarios: 25
pass@1: 0.000
pass@k: 0.000
Total cost: $0.0000

Full artifacts: see the lifeops-run-eliza-26260312668 upload on this run.

export function proactiveInboxDigestRequest(): GetLifeOpsInboxRequest {
return {
...PROACTIVE_INBOX_DIGEST_REQUEST,
channels: [...(PROACTIVE_INBOX_DIGEST_REQUEST.channels ?? [])],
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.

P2 Dead ?? [] fallback on a non-optional field

PROACTIVE_INBOX_DIGEST_REQUEST.channels is always defined — it is a typed literal in the same file — so the ?? [] branch is unreachable dead code. If the intention is purely defensive copying (in case a caller mutates the returned array), the plain spread [...PROACTIVE_INBOX_DIGEST_REQUEST.channels] communicates that intent more clearly without implying the value could be absent.

Comment on lines +20 to +23
]);
expect(request.channels).not.toContain("discord");
expect(request.channels).not.toContain("telegram");
expect(request.channels).not.toContain("signal");
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.

P2 Redundant negative assertions after toEqual

The three not.toContain assertions (discord, telegram, signal) are logically implied by the preceding expect(request.channels).toEqual([...]) which already pins the exact contents of the array. If toEqual passes, the array cannot contain any element outside the expected list. Removing the three assertions avoids coupling the test to an implementation-level concern that is already fully covered.

// the inbox layer conservatively marks them unread so explicit inbox views
// can still triage them. Proactive digests should only summarize channels
// with personal inbox semantics until chat read/mention state is grounded.
channels: ["gmail", "x_dm", "imessage", "whatsapp", "sms"],
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.

P2 signal excluded from proactive personal inbox channels

The LIFEOPS_INBOX_CHANNELS set contains "signal", and Signal is a personal end-to-end encrypted messenger whose read state is owned by the user (similar to iMessage/WhatsApp). The PR description groups it with chat connectors (Discord, Telegram) as a reason for exclusion, but Signal is not a server/community platform. Was this omission intentional, or should "signal" be included alongside the other personal messaging channels? Was signal intentionally excluded from the proactive digest channels, or should it be included alongside iMessage/WhatsApp?

@github-actions
Copy link
Copy Markdown
Contributor

LifeOps Benchmark — hermes

Run ID: lifeops-hermes-26260312668

LifeOps Benchmark

Model: gpt-oss-120b
Judge: claude-opus-4-7
Scenarios: 25
pass@1: 0.320
pass@k: 0.320
Total cost: $0.8902

Full artifacts: see the lifeops-run-hermes-26260312668 upload on this run.

@NubsCarson
Copy link
Copy Markdown
Member Author

CI note after the first run:

Validated locally on the branch:

  • bunx @biomejs/biome check --write src/activity-profile/proactive-worker.ts src/activity-profile/proactive-inbox-digest.ts test/proactive-worker.test.ts --no-errors-on-unmatched
  • bun test --timeout 30000 test/proactive-worker.test.ts
  • bun run build from plugins/plugin-lifeops

The current red jobs do not appear to be caused by this LifeOps digest change:

  • Server Tests failed in unrelated areas: packages/app-core route catalog (home missing from generated route catalog) and scripts/build-llama-cpp-dflash-targets.test.mjs expecting ios-arm64-metal-fused targets.
  • Plugin Tests failed in @elizaos/plugin-computeruse#test / unrelated plugin test execution. No failure was reported for plugins/plugin-lifeops or the new proactive digest test.

Keeping this PR scoped to the proactive digest fix rather than chasing those unrelated lanes here.

@lalalune lalalune merged commit a90806b into develop May 22, 2026
34 of 39 checks passed
@lalalune lalalune deleted the nubs/lifeops-proactive-personal-inbox-20260521 branch May 22, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants