Skip to content

fix(onboard): persist enabledChannels across resume path - #1703

Merged
cv merged 1 commit into
NVIDIA:mainfrom
kagura-chen:fix/onboard-resume-enabledChannels
Apr 21, 2026
Merged

cv merged 1 commit into
NVIDIA:mainfrom
kagura-chen:fix/onboard-resume-enabledChannels

Conversation

@kagura-chen

@kagura-chen kagura-chen commented Apr 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When resuming an onboard session, enabledChannels was lost because it was declared as const inside the else (non-resume) block of the sandbox setup step. Resumed sessions had no channel selection, causing setupPoliciesWithSelection to fall back to credential-only checks — users who selected messaging channels (Telegram/Slack/Discord) would not see the corresponding policy presets suggested after resume.

Root Cause

In src/lib/onboard.ts, line ~4443:

const enabledChannels = await setupMessagingChannels();

This was scoped inside the else block. The resume path (if (resumeSandbox)) never set enabledChannels, and it was never persisted to session state.

Fix

  1. Hoist enabledChannels to function scope (let enabledChannels: string[] | null = null)
  2. Resume path: restore from session.enabledChannels
  3. Non-resume path: persist to session via onboardSession.updateSession()
  4. Session layer (onboard-session.ts): add enabledChannels to Session/SessionUpdates interfaces, createSession, normalizeSession, filterSafeUpdates, and summarizeForDebug
  5. Policy suggestions: pass enabledChannels to setupPoliciesWithSelection — when provided, use the channel list instead of credential checks (with credential fallback for backward compat)

Testing

  • npm run check (lint + format + tsc): ✅ all pass

Fixes #1610

Summary by CodeRabbit

  • New Features

    • Onboarding now captures and persists selected messaging channels and uses them to seed policy suggestions; debug output includes the persisted channel selection.
  • Bug Fixes / Improvements

    • Channel selection is consistently preserved across session creation, normalization, updates, and resume flows.
  • Tests

    • Added tests verifying channel persistence, safe-update handling, and override behavior.

Signed-off-by: kagura-agent kagura.chen28@gmail.com

@coderabbitai

coderabbitai Bot commented Apr 9, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added a nullable messagingChannels field to the onboarding session model, persisted and normalized it, threaded it into the resume onboarding flow so prior selections are reused when resuming a sandbox, and added tests verifying round-trip persistence and safe-update behavior.

Changes

Cohort / File(s) Summary
Session management
src/lib/onboard-session.ts
Add `messagingChannels: string[]
Onboarding flow integration
src/lib/onboard.ts
When resuming a sandbox, set selectedMessagingChannels from session?.messagingChannels ?? [] so setupPoliciesWithSelection(..., enabledChannels: selectedMessagingChannels, ...) uses the persisted selection.
Tests
src/lib/onboard-session.test.ts
Add Vitest cases verifying messagingChannels round-trips as null, persists explicit arrays (e.g., ["telegram"]), is preserved via markStepComplete safe updates, and can be set via createSession overrides.

Sequence Diagram(s)

sequenceDiagram
    participant User as "User"
    participant Onboard as "onboard()"
    participant Session as "onboardSession"
    participant Policies as "setupPoliciesWithSelection()"
    participant Creds as "Credential Store / env"

    User->>Onboard: start onboarding
    Onboard->>User: messaging channels step (select or skip)
    User->>Onboard: select channels or press Enter to skip
    Onboard->>Session: updateSession({ messagingChannels })
    Session-->>Session: normalize & persist messagingChannels
    Onboard->>Session: resumeSandbox? load session
    Session-->>Onboard: return session (messagingChannels or null)
    Onboard->>Policies: setupPoliciesWithSelection(enabledChannels: selectedMessagingChannels)
    alt messagingChannels provided
        Policies->>Policies: derive presets from messagingChannels
    else messagingChannels is null/empty
        Policies->>Creds: probe stored credentials / env
        Creds-->>Policies: detected channels
    end
    Policies-->>Onboard: return policy presets
    Onboard->>User: display policy presets
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped and tucked the channels away,
Saved them snug for the next play,
Resume the run and they come back true,
No phantom presets to bother you,
A tiny hop keeps the flow in view.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix(onboard): persist enabledChannels across resume path' directly addresses the main change: persisting messaging channel selection when resuming onboarding sessions.
Linked Issues check ✅ Passed Changes implement all coding requirements from issue #1610: persist messaging channels to session, restore on resume, and pass restored selection to policy suggestions with credential fallback.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing issue #1610: session layer additions for channel persistence, resume path restoration, and policy suggestion integration.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/onboard.ts`:
- Around line 4454-4458: setupMessagingChannels() returns the user's toggles,
not the channels that were actually configured with credentials, so persist only
token-backed channels: after calling setupMessagingChannels() in the onboarding
flow, filter the returned enabledChannels to keep only channels with a
configured provider/credentials (e.g., where a provider token or
provider.isConfigured is present) before calling onboardSession.updateSession
and before passing to setupPoliciesWithSelection/createSandbox; update the code
around setupMessagingChannels(), onboardSession.updateSession, and any
downstream use (setupPoliciesWithSelection/createSandbox) to use this
filteredEnabledChannels list instead of the raw toggled list.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b49201ac-2e97-40de-bc81-3377d3b0d99c

📥 Commits

Reviewing files that changed from the base of the PR and between b37f2a5 and 36ff1ae.

📒 Files selected for processing (2)
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts

Comment thread src/lib/onboard.ts Outdated

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
src/lib/onboard-session.test.ts (1)

233-241: Add explicit empty-array regression (enabledChannels: []).

Please add a test for enabledChannels: [] to lock in the “user skipped messaging channels” path and prevent future fallback-to-credentials regressions.

Proposed test addition
   it("filterSafeUpdates preserves enabledChannels field", () => {
     session.saveSession(session.createSession());
     session.markStepComplete("provider_selection", {
       enabledChannels: ["slack", "discord"],
     });

     const loaded = session.loadSession();
     expect(loaded.enabledChannels).toEqual(["slack", "discord"]);
   });

+  it("preserves explicit empty enabledChannels selection", () => {
+    session.saveSession(session.createSession());
+    session.markStepComplete("provider_selection", {
+      enabledChannels: [],
+    });
+
+    const loaded = session.loadSession();
+    expect(loaded.enabledChannels).toEqual([]);
+  });
+
   it("createSession with enabledChannels override", () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard-session.test.ts` around lines 233 - 241, Add a new unit test
alongside the existing "filterSafeUpdates preserves enabledChannels field" test
that specifically verifies an explicit empty array is preserved: call
session.saveSession(session.createSession()), then
session.markStepComplete("provider_selection", { enabledChannels: [] }), then
load the session via session.loadSession() and assert loaded.enabledChannels
equals [] to lock in the "user skipped messaging channels" path; reference the
same helpers used in the file (session.createSession, session.saveSession,
session.markStepComplete, session.loadSession) so the regression for
fallback-to-credentials is prevented.
🤖 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/lib/onboard-session.test.ts`:
- Around line 233-241: Add a new unit test alongside the existing
"filterSafeUpdates preserves enabledChannels field" test that specifically
verifies an explicit empty array is preserved: call
session.saveSession(session.createSession()), then
session.markStepComplete("provider_selection", { enabledChannels: [] }), then
load the session via session.loadSession() and assert loaded.enabledChannels
equals [] to lock in the "user skipped messaging channels" path; reference the
same helpers used in the file (session.createSession, session.saveSession,
session.markStepComplete, session.loadSession) so the regression for
fallback-to-credentials is prevented.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7ce8fe9a-7840-468e-b5dd-791750597403

📥 Commits

Reviewing files that changed from the base of the PR and between 36ff1ae and 20625da.

📒 Files selected for processing (1)
  • src/lib/onboard-session.test.ts

@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch from 20625da to 776426d Compare April 10, 2026 01:24

@coderabbitai coderabbitai Bot left a comment

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.

♻️ Duplicate comments (1)
src/lib/onboard.ts (1)

4510-4514: ⚠️ Potential issue | 🟡 Minor

Persist only token-backed channels, not raw toggles.

Line 4510 currently persists the raw selection from setupMessagingChannels(). If a user toggles a channel but skips token entry, that channel is still persisted and later suggested in policy presets, even though it won’t be configured in sandbox providers.

💡 Suggested fix
-      enabledChannels = await setupMessagingChannels();
+      const selectedChannels = await setupMessagingChannels();
+      enabledChannels = selectedChannels.filter((name) => {
+        const channel = MESSAGING_CHANNELS.find((entry) => entry.name === name);
+        return channel
+          ? Boolean(
+              getCredential(channel.envKey) ||
+                normalizeCredentialValue(process.env[channel.envKey]),
+            )
+          : false;
+      });
       onboardSession.updateSession((current) => {
         current.enabledChannels = enabledChannels;
         return current;
       });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/onboard.ts` around lines 4510 - 4514, The code currently writes the
raw result of setupMessagingChannels() into onboardSession via
onboardSession.updateSession, which persists toggles even when the user didn't
provide provider tokens; change this to persist only token-backed channels by
filtering the enabledChannels returned from setupMessagingChannels() to include
only channels with valid provider tokens (e.g., where a token field or a
requiresToken check is satisfied) before calling onboardSession.updateSession;
update the logic around enabledChannels, setupMessagingChannels, and the
onboardSession.updateSession call so only token-backed channel entries are saved
and later suggested in policy presets.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 4510-4514: The code currently writes the raw result of
setupMessagingChannels() into onboardSession via onboardSession.updateSession,
which persists toggles even when the user didn't provide provider tokens; change
this to persist only token-backed channels by filtering the enabledChannels
returned from setupMessagingChannels() to include only channels with valid
provider tokens (e.g., where a token field or a requiresToken check is
satisfied) before calling onboardSession.updateSession; update the logic around
enabledChannels, setupMessagingChannels, and the onboardSession.updateSession
call so only token-backed channel entries are saved and later suggested in
policy presets.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95f5ae98-cf15-4a25-916a-cd6eb0beeb7e

📥 Commits

Reviewing files that changed from the base of the PR and between 20625da and 776426d.

📒 Files selected for processing (3)
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts
  • src/lib/onboard.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/onboard-session.test.ts
  • src/lib/onboard-session.ts

@kagura-chen

Copy link
Copy Markdown
Contributor Author

Closing — this was mistakenly re-opened from the same branch as #1651, which was already closed as superseded by #1673 (TypeScript migration). Apologies for the noise.

@kagura-chen

Copy link
Copy Markdown
Contributor Author

Reopening — this was closed in error. This PR is on branch fix/onboard-resume-enabledChannels, which is a different branch from #1651 (fix/onboard-channel-policy-filter).

This PR addresses a remaining gap in the enabledChannels fix: the resume path doesn't restore enabledChannels from session state. The TS migration in #1673 carried over the new-session path but did not add session persistence for enabledChannels, so resumed onboarding sessions lose the channel selection and fall back to credential-only preset suggestions.

Changes:

  • Add enabledChannels to the Session schema (onboard-session.ts)
  • Restore from session on resume, persist after setupMessagingChannels()
  • 4 regression tests for round-trip persistence

Sorry for the confusion on the close.

@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch from 776426d to b0c68fa Compare April 11, 2026 00:24
@kagura-chen

Copy link
Copy Markdown
Contributor Author

Rebased on latest main and updated the approach to align with upstream conventions:

  • Uses messagingChannels (matching the field name upstream already writes to the session) instead of the original enabledChannels
  • Restores selectedMessagingChannels from session.messagingChannels on the resume path
  • Added proper Session interface typing, serialization/deserialization, and filterSafeUpdates support
  • Removed stale duplicate object key from the original commit
  • All 18 onboard-session tests pass, tsc clean

Signed commit (GPG).

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Code is clean — follows the existing policyPresets pattern, tests cover round-trip, filterSafeUpdates, and resume restore. No regressions. One blocker: DCO check is failing — PR description needs a sign-off line. @kagura-agent can you add Signed-off-by: kagura-agent <kagura.chen28@gmail.com> to the PR body?

@ericksoa ericksoa added v0.0.19 and removed v0.0.18 labels Apr 17, 2026
@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch 4 times, most recently from 2ead797 to 459d0cf Compare April 18, 2026 00:21
@ericksoa ericksoa added v0.0.20 and removed v0.0.19 labels Apr 18, 2026
@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch from 459d0cf to 6c0f440 Compare April 18, 2026 02:26
@kagura-chen

Copy link
Copy Markdown
Contributor Author

Rebased on latest main and added DCO sign-off. Conflict resolved (kept both the new Brave Search resume note and the messagingChannels restore).

@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch from 6c0f440 to 6d3bc06 Compare April 18, 2026 06:15
@kagura-chen

Copy link
Copy Markdown
Contributor Author

Hi @prekshivyas, thanks for the approval! Just checking — is there anything else needed before this can be merged?

@kagura-chen

Copy link
Copy Markdown
Contributor Author

Hi @prekshivyas 👋 Thanks for the approval! Just checking if there's anything else needed before this gets merged, or if it's in the merge queue. Happy to rebase if needed.

@kagura-chen

Copy link
Copy Markdown
Contributor Author

Friendly ping — this has been approved. Is there anything else needed for merge? Happy to rebase if needed.

When resuming an onboard session, selectedMessagingChannels was lost
because it was only set inside the non-resume code path. Resumed
sessions had no channel selection, causing setupPoliciesWithSelection
to fall back to credential-only checks.

Changes:
- Restore selectedMessagingChannels from session.messagingChannels
  on the resume path
- Add messagingChannels field to Session interface and serialization
- Add filterSafeUpdates support for messagingChannels
- Add regression tests for messagingChannels round-tripping

Signed-off-by: kagura-agent <kagura.chen28@gmail.com>
@kagura-chen
kagura-chen force-pushed the fix/onboard-resume-enabledChannels branch from 6d3bc06 to c2ee378 Compare April 20, 2026 20:13
@kagura-chen

Copy link
Copy Markdown
Contributor Author

Rebased on latest main and added DCO sign-off. The conflict was because upstream already incorporated the messagingChannels field in createSession/normalizeSession — this PR now adds the test coverage and the resume-path restore in onboard.ts. Ready for re-review!

@cv cv added v0.0.21 and removed v0.0.20 labels Apr 20, 2026
@cv
cv merged commit e15f4dc into NVIDIA:main Apr 21, 2026
14 checks passed

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good to me.

  • restores selectedMessagingChannels on the resume path
  • keeps the functional change narrow to the missing state restoration
  • adds regression coverage for messagingChannels round-tripping and safe-update preservation

I also ran local targeted validation on the PR branch:

  • npm run build:cli
  • npx vitest run src/lib/onboard-session.test.ts
  • npm run typecheck:cli

@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression and removed NemoClaw CLI labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platform]onboard skips messaging channel selection, but policy preset step still auto-selects messaging presets from stored credentials

5 participants