Skip to content

fix(onboard): preserve slack messaging policy#3862

Merged
ericksoa merged 3 commits into
NVIDIA:mainfrom
yimoj:fix/3753-slack-policy-preserve
May 23, 2026
Merged

fix(onboard): preserve slack messaging policy#3862
ericksoa merged 3 commits into
NVIDIA:mainfrom
yimoj:fix/3753-slack-policy-preserve

Conversation

@yimoj

@yimoj yimoj commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Preserves messaging-required policy presets when onboarding resumes or reapplies a recorded policy selection. This prevents Slack messaging rebuilds from keeping the channel configuration while dropping the slack network policy.

Related Issue

Fixes #3753

Changes

  • Added a shared messaging-channel-to-policy helper for required policy presets.
  • Reused the helper for create-time sandbox policy composition and policy selection/replay paths.
  • Added focused regressions for resumed and custom non-interactive Slack policy preservation.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • make docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Focused verification run locally:

  • npx vitest run src/lib/onboard/messaging-policy-presets.test.ts src/lib/onboard/initial-policy.test.ts test/onboard-preset-diff.test.ts test/policy-tiers-onboard.test.ts
  • npm run typecheck:cli
  • npm run build:cli
  • cd nemoclaw && npm install && npm run build
  • npx vitest run test/ssrf-parity.test.ts nemoclaw/src/commands/migration-state.test.ts
  • codex review -c sandbox_mode=\"danger-full-access\" --uncommitted

Full npm test was attempted under isolated HOME=/tmp/nemoclaw-fix-3753-home / NEMOCLAW_HOME=/tmp/nemoclaw-fix-3753-home/.nemoclaw; it failed in unrelated broad-suite/environment paths (timeouts in CLI/e2e scenario tests and existing gateway-state-sensitive tests). Missing plugin dependency/dist blockers were addressed with cd nemoclaw && npm install && npm run build, and the affected ssrf-parity / migration-state tests then passed.


Signed-off-by: Yimo Jiang yimoj@nvidia.com

Summary by CodeRabbit

  • New Features

    • Onboarding now derives, normalizes, dedupes and merges messaging-channel–required policy presets and persists applied presets when resuming setup.
  • Bug Fixes

    • Presets tied to disabled messaging channels are pruned and excluded during resume, selection, and restore to avoid reapplication; resume now respects enabled/disabled channel state.
  • Tests

    • Added unit and regression tests covering messaging-preset utilities, resume/selection flows, and rebuild restoration.

Review Change Stack

@yimoj yimoj self-assigned this May 20, 2026
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Derives required policy presets from messaging channels, merges/prunes them across create, resume, interactive/non-interactive selection, and rebuild restore flows, and adds utilities plus tests validating normalization, merging, resume reconciliation, and restore-time pruning.

Changes

Messaging Policy Preset Requirements

Layer / File(s) Summary
Messaging policy preset utilities and tests
src/lib/onboard/messaging-policy-presets.ts, src/lib/onboard/messaging-policy-presets.test.ts
New helpers: mergePolicyMessagingChannels() merges channel sources with normalization and dedupe; requiredMessagingChannelPolicyPresets() computes normalized required presets from channels; mergeRequiredMessagingChannelPolicyPresets() appends missing required presets (optionally restricted by known names); pruneDisabledMessagingPolicyPresets() removes presets tied to disabled channels; hasDisabledMessagingPolicyPreset() and mergeAppliedPolicyPresetsForDisabledMessagingCleanup() support applied-preset cleanup. Unit tests validate normalization, merging, and pruning.
Policy selection setup merging
src/lib/onboard/policy-selection.ts
Adds mergeRequiredSetupPolicyPresets which composes Hermes-tool-gateway and messaging-channel required merges; computeSetupPresetSuggestions, preparePolicyPresetResumeSelection, and setupPoliciesWithSelection now use it in suggestions, resume, non-interactive, and interactive branches, and support disabledChannels to prune messaging-derived presets.
Initial policy creation integration
src/lib/onboard/initial-policy.ts
Create-time requested presets for messaging channels now come from requiredMessagingChannelPolicyPresets(activeMessagingChannels) (replacing the removed mapping constant).
Onboard resume flow and channel wiring
src/lib/onboard.ts
Onboard normalizes recorded presets/channels, computes policyMessagingChannels by merging selected + recorded + active channels (respecting disabled channels), uses preparePolicyPresetResumeSelection to reconcile recorded presets, passes policyMessagingChannels into setupPoliciesWithSelection, and persists returned applied presets to the session.
Rebuild restore preset pruning
src/lib/actions/sandbox/rebuild.ts
During sandbox rebuild restore, backupManifest.policyPresets are filtered via pruneDisabledMessagingPolicyPresets(..., rebuildDisabledChannels) before being reapplied.
Rebuild/resume regression tests
test/onboard-preset-diff.test.ts, test/rebuild-policy-presets.test.ts
Adds regression tests to assert the slack preset is preserved when Slack is enabled across resume and non-interactive custom flows, and tests that restore pruning omits presets tied to disabled channels while preserving required presets.
sequenceDiagram
  participant Onboard as src/lib/onboard.ts
  participant PolicySelection as src/lib/onboard/policy-selection.ts
  participant MessagingUtil as src/lib/onboard/messaging-policy-presets.ts
  participant SetupEngine as setupPoliciesWithSelection
  participant Rebuild as src/lib/actions/sandbox/rebuild.ts

  Onboard->>MessagingUtil: mergePolicyMessagingChannels(selected, recorded, active, disabled)
  MessagingUtil-->>Onboard: policyMessagingChannels
  Onboard->>PolicySelection: preparePolicyPresetResumeSelection(..., {recordedPolicyPresets, enabledChannels, disabledChannels})
  PolicySelection-->>Onboard: recordedPolicyPresetsForSupport + flags
  Onboard->>SetupEngine: setupPoliciesWithSelection(..., { enabledChannels: policyMessagingChannels, disabledChannels })
  SetupEngine->>PolicySelection: mergeRequiredSetupPolicyPresets(chosen/applied, {enabledChannels, hermesToolGateways})
  PolicySelection->>MessagingUtil: mergeRequiredMessagingChannelPolicyPresets(..., enabledChannels)
  MessagingUtil-->>PolicySelection: appended required presets
  Rebuild->>MessagingUtil: pruneDisabledMessagingPolicyPresets(backupManifest.policyPresets, rebuildDisabledChannels)
  MessagingUtil-->>Rebuild: savedPresets
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#3984: Overlaps in messaging-channel → preset preparation and create/resume preset logic.

Suggested labels

NemoClaw CLI, Sandbox

Suggested reviewers

  • jyaunches
  • ericksoa

Poem

🐰 I hop through channels, neat and quick,
I stitch lost presets back with a flick.
From resume to rebuild, I prune and mend,
Slack finds its policy and hops back again.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(onboard): preserve slack messaging policy' accurately summarizes the main objective of fixing policy/config drift where Slack channel config survives rebuild while the required Slack network policy is absent.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #3753: adds messaging-channel-to-policy helpers, ensures policy presets are preserved during rebuild/resume, updates policy selection flows, and adds regression test coverage for Slack policy preservation.
Out of Scope Changes check ✅ Passed All changes directly address the invariant that Slack channel enabled implies Slack egress policy present. The new utilities, updated onboard logic, and regression tests are all scoped to policy/channel state consistency without unrelated modifications.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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: 2

🤖 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 `@src/lib/onboard.ts`:
- Around line 10028-10034: The new policy-channel merge (building
policyMessagingChannels from selectedMessagingChannels,
recordedMessagingChannels, and activeMessagingChannels) must be extracted from
onboard.ts into a small helper in src/lib/onboard (e.g.,
createPolicyMessagingChannels or mergePolicyMessagingChannels) and the top-level
onboard.ts should only call that helper with the three inputs and receive the
merged array; move the same extraction for the related block covering lines
~10054-10074 as well, ensure the helper validates
Array.isArray(activeMessagingChannels) and preserves Set de-duplication, and
update onboard.ts to import and call the helper so the entrypoint remains thin.
- Around line 10027-10034: The current merge that builds policyMessagingChannels
uses registry.getSandbox(sandboxName)?.messagingChannels
(activeMessagingChannels) without excluding channels listed in disabledChannels,
which can re-enable stopped channels like "slack"; update the logic that
constructs policyMessagingChannels to first read disabledChannels (e.g.,
registry.getSandbox(sandboxName)?.disabledChannels), ensure it's an array, and
filter out any channel names present in disabledChannels from
activeMessagingChannels (and from the combined set of
selectedMessagingChannels/recordedMessagingChannels) before creating the Set so
disabled channels are never included when deriving required policy presets.
🪄 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: Enterprise

Run ID: c08f1f3e-cf98-48aa-8de7-23129f0805d4

📥 Commits

Reviewing files that changed from the base of the PR and between 11b1937 and 687c34a.

📒 Files selected for processing (6)
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts

Comment thread src/lib/onboard.ts Outdated
Comment thread src/lib/onboard.ts Outdated
@yimoj yimoj force-pushed the fix/3753-slack-policy-preserve branch from 687c34a to 4bd022a Compare May 20, 2026 05:40
@yimoj yimoj added the v0.0.48 Release target label May 20, 2026
@yimoj yimoj force-pushed the fix/3753-slack-policy-preserve branch 2 times, most recently from 80aebaa to 2371fba Compare May 20, 2026 06:22

@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

🧹 Nitpick comments (1)
src/lib/actions/sandbox/rebuild.ts (1)

760-763: Run the targeted channels stop/start e2e before merge.

Given this branch now prunes restored presets based on disabled channels, please run the recommended channels-stop-start-e2e workflow to validate stop/start persistence across destroy/recreate with cached credentials.

As per coding guidelines: "src/lib/actions/sandbox/rebuild.ts: This file controls disabled channel resolution used during onboard and rebuild... E2E test recommendation: channels-stop-start-e2e."

🤖 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 `@src/lib/actions/sandbox/rebuild.ts` around lines 760 - 763, The change prunes
restored presets using pruneDisabledMessagingPolicyPresets (called into
savedPresets with rebuildDisabledChannels), so run the channels-stop-start-e2e
workflow before merging to validate stop/start persistence across
destroy/recreate with cached credentials; specifically, execute the
channels-stop-start-e2e pipeline against this branch, confirm that disabled
channel resolution (pruneDisabledMessagingPolicyPresets -> savedPresets)
preserves stop/start state after sandbox rebuild, and report any failing
scenarios to adjust how rebuildDisabledChannels is computed or applied during
restore.
🤖 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 `@src/lib/onboard.ts`:
- Around line 10060-10078: The fast resume path only verifies that the remaining
(pruned) presets are present in the sandbox via arePolicyPresetsApplied, but it
does not detect extra applied presets that were removed because their channels
are now disabled (e.g., Slack still applied). Update the resumePolicies
condition to also ensure there are no additional applied policy presets beyond
recordedPolicyPresetsForSupport: either replace
arePolicyPresetsApplied(sandboxName, recordedPolicyPresetsForSupport) with a
strict equality check (sandboxAppliedPresets ===
recordedPolicyPresetsForSupport) or add a complementary function (e.g.,
arePolicyPresetsExactMatch or hasNoExtraAppliedPolicyPresets) and use that
together with recordedPolicyPresetsNeedReconcile, referencing
recordedPolicyPresetsForSupport, recordedPolicyPresetsNeedReconcile,
arePolicyPresetsApplied and resumePolicies.

---

Nitpick comments:
In `@src/lib/actions/sandbox/rebuild.ts`:
- Around line 760-763: The change prunes restored presets using
pruneDisabledMessagingPolicyPresets (called into savedPresets with
rebuildDisabledChannels), so run the channels-stop-start-e2e workflow before
merging to validate stop/start persistence across destroy/recreate with cached
credentials; specifically, execute the channels-stop-start-e2e pipeline against
this branch, confirm that disabled channel resolution
(pruneDisabledMessagingPolicyPresets -> savedPresets) preserves stop/start state
after sandbox rebuild, and report any failing scenarios to adjust how
rebuildDisabledChannels is computed or applied during restore.
🪄 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: Enterprise

Run ID: 2333fa41-c915-4b53-934e-fd74904099dd

📥 Commits

Reviewing files that changed from the base of the PR and between 4bd022a and 80aebaa.

📒 Files selected for processing (8)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts
  • test/rebuild-policy-presets.test.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.

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

10052-10063: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't skip policy reconciliation while a disabled messaging preset is still applied.

Line 10063 only checks that the pruned set is present, not that disabled-channel presets are absent. Because Lines 10076-10080 persist recordedPolicyPresetsForSupport before setupPoliciesWithSelection() runs, an interrupted run can leave the session without slack while the sandbox still has it applied. The next --resume will satisfy this fast path and keep the stale egress policy.

💡 Minimal fix
+    const appliedPresetNames = policies.getAppliedPresets(sandboxName);
+    const hasDisabledMessagingPresetsApplied =
+      pruneDisabledMessagingPolicyPresets(
+        appliedPresetNames,
+        activeSandbox?.disabledChannels,
+      ).length !== appliedPresetNames.length;
     const resumePolicies =
       resume &&
       sandboxName &&
       !recordedPolicyPresetsNeedReconcile &&
+      !hasDisabledMessagingPresetsApplied &&
       arePolicyPresetsApplied(sandboxName, recordedPolicyPresetsForSupport);

Also applies to: 10076-10080

🤖 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 `@src/lib/onboard.ts` around lines 10052 - 10063, The fast-path resume
incorrectly treats a pruned recordedPolicyPresetsForSupport as valid even when
it still contains presets that target disabled messaging channels; update the
recordedPolicyPresetsNeedReconcile logic (used to compute resumePolicies) to
consider not only length mismatch but also whether any preset in
recordedPolicyPresetsForSupport touches activeSandbox?.disabledChannels (i.e.,
detect preset.channel intersections) so the resume path is blocked when
disabled-channel presets remain; also ensure the code that persists
recordedPolicyPresetsForSupport (the block around where you save them before
calling setupPoliciesWithSelection) is moved or gated so persistence happens
only after setupPoliciesWithSelection completes successfully. Reference symbols:
recordedPolicyPresetsForSupport, recordedPolicyPresetsNeedReconcile,
pruneDisabledMessagingPolicyPresets, mergeRequiredSetupPolicyPresets,
arePolicyPresetsApplied, setupPoliciesWithSelection,
activeSandbox?.disabledChannels.
🧹 Nitpick comments (1)
src/lib/actions/sandbox/rebuild.ts (1)

760-763: Run the channels stop/start E2E for this path-sensitive change.

Given this logic now gates preset restore based on disabled channels, run the targeted lifecycle E2E to confirm channels stop/channels start behavior remains stable across rebuild.

As per coding guidelines src/lib/actions/sandbox/rebuild.ts: “This file controls disabled channel resolution used during onboard and rebuild… E2E test recommendation: channels-stop-start-e2e”.

🤖 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 `@src/lib/actions/sandbox/rebuild.ts` around lines 760 - 763, This change
affects how disabled channels gate preset restoration in
src/lib/actions/sandbox/rebuild.ts (see pruneDisabledMessagingPolicyPresets,
savedPresets, rebuildDisabledChannels), so run the targeted lifecycle E2E suite
named channels-stop-start-e2e against the rebuild/onboard path to validate
channels stop/start behavior; if the E2E fails, trace failures back to
pruneDisabledMessagingPolicyPresets or the rebuildDisabledChannels resolution
logic and update the code or tests to ensure disabled-channel
preservation/restore semantics match expected behavior before merging.
🤖 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.

Duplicate comments:
In `@src/lib/onboard.ts`:
- Around line 10052-10063: The fast-path resume incorrectly treats a pruned
recordedPolicyPresetsForSupport as valid even when it still contains presets
that target disabled messaging channels; update the
recordedPolicyPresetsNeedReconcile logic (used to compute resumePolicies) to
consider not only length mismatch but also whether any preset in
recordedPolicyPresetsForSupport touches activeSandbox?.disabledChannels (i.e.,
detect preset.channel intersections) so the resume path is blocked when
disabled-channel presets remain; also ensure the code that persists
recordedPolicyPresetsForSupport (the block around where you save them before
calling setupPoliciesWithSelection) is moved or gated so persistence happens
only after setupPoliciesWithSelection completes successfully. Reference symbols:
recordedPolicyPresetsForSupport, recordedPolicyPresetsNeedReconcile,
pruneDisabledMessagingPolicyPresets, mergeRequiredSetupPolicyPresets,
arePolicyPresetsApplied, setupPoliciesWithSelection,
activeSandbox?.disabledChannels.

---

Nitpick comments:
In `@src/lib/actions/sandbox/rebuild.ts`:
- Around line 760-763: This change affects how disabled channels gate preset
restoration in src/lib/actions/sandbox/rebuild.ts (see
pruneDisabledMessagingPolicyPresets, savedPresets, rebuildDisabledChannels), so
run the targeted lifecycle E2E suite named channels-stop-start-e2e against the
rebuild/onboard path to validate channels stop/start behavior; if the E2E fails,
trace failures back to pruneDisabledMessagingPolicyPresets or the
rebuildDisabledChannels resolution logic and update the code or tests to ensure
disabled-channel preservation/restore semantics match expected behavior before
merging.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 65d36433-4682-45c9-a848-1c36a52da176

📥 Commits

Reviewing files that changed from the base of the PR and between 80aebaa and 2371fba.

📒 Files selected for processing (8)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts
  • test/rebuild-policy-presets.test.ts

@yimoj yimoj removed the v0.0.48 Release target label May 20, 2026
@yimoj yimoj force-pushed the fix/3753-slack-policy-preserve branch 2 times, most recently from 63b2174 to f12a919 Compare May 20, 2026 07:16

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lib/onboard.ts (2)

10072-10110: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't drop disabled-channel cleanup presets when session policy history is absent.

mergeAppliedPolicyPresetsForDisabledMessagingCleanup(...) can synthesize presets that must be shown to setupPoliciesWithSelection() so the stale disabled-channel policy gets removed. Lines 10105-10108 discard that state whenever latestSession.policyPresets is null, so resumed/legacy sessions can still leave a disabled preset like slack applied.

💡 Suggested change
+      const selectedPolicyPresetsForSetup =
+        Array.isArray(recordedPolicyPresets) || recordedPolicyPresetsForSupport.length > 0
+          ? recordedPolicyPresetsForSupport
+          : null;
       const setupAppliedPolicyPresets = await setupPoliciesWithSelection(sandboxName, {
-        selectedPresets:
-          Array.isArray(recordedPolicyPresets)
-            ? recordedPolicyPresetsForSupport
-            : null,
+        selectedPresets: selectedPolicyPresetsForSetup,
         enabledChannels: policyMessagingChannels,
         disabledChannels: activeSandbox?.disabledChannels,
         webSearchConfig,
🤖 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 `@src/lib/onboard.ts` around lines 10072 - 10110, The code discards synthesized
cleanup presets from mergeAppliedPolicyPresetsForDisabledMessagingCleanup
whenever recordedPolicyPresets is null, so setupPoliciesWithSelection may not
receive necessary selectedPresets to remove stale disabled-channel policies;
change the selectedPresets argument passed into setupPoliciesWithSelection to
use recordedPolicyPresetsForSupport (or at least check its length) instead of
gating on Array.isArray(recordedPolicyPresets), ensuring that when
recordedPolicyPresetsForSupport contains synthesized presets they are forwarded
to setupPoliciesWithSelection; update the ternary at the selectedPresets key (or
its surrounding logic) to pass recordedPolicyPresetsForSupport when non-empty so
disabled-channel cleanup presets are not dropped.

10027-10124: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Extract this reconciliation block to clear the entrypoint-budget CI failure.

This chunk is the main new orchestration added to src/lib/onboard.ts, and CI is currently red because the file grew past the enforced budget. Moving this policy-state assembly behind a small helper in src/lib/onboard/* should unblock the check while keeping the entrypoint thin.

🤖 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 `@src/lib/onboard.ts` around lines 10027 - 10124, Extract the policy-state
reconciliation block (starting at the
recordedPolicyPresets/recordedMessagingChannels lines through the computation of
resumePolicies and prior to the resume handling) into a new helper function
(e.g., assemblePolicyState) in a new module under src/lib/onboard/; the helper
should accept the minimal inputs (sandboxName, latestSession or
recordedPolicyPresets/recordedMessagingChannels, selectedMessagingChannels,
registry.getSandbox result or sandboxName+registry, policies,
hermesToolGateways, webSearchSupported, activeSandbox?.disabledChannels,
webSearchConfig, provider, model, agent, etc.) and return the computed values
used afterward (at least recordedPolicyPresetsForSupport,
policyMessagingChannels, appliedPolicyPresetsForSupport,
disabledMessagingPolicyPresetApplied, resumePolicies); use the existing helper
functions referenced in the block (mergePolicyMessagingChannels,
pruneDisabledMessagingPolicyPresets, policies.clampSetupPolicyPresetNames,
hasDisabledMessagingPolicyPreset,
mergeAppliedPolicyPresetsForDisabledMessagingCleanup,
mergeRequiredSetupPolicyPresets, arePolicyPresetsApplied) inside the new
assemblePolicyState function and export it, then replace the large inline block
in src/lib/onboard.ts with a single call to assemblePolicyState and use its
returned values unchanged.
🧹 Nitpick comments (2)
src/lib/onboard.ts (1)

10027-10124: Please run the lifecycle E2Es for this path before merge.

This touches resume, disabled-channel cleanup, and Slack policy preservation, so I’d specifically want channels-stop-start-e2e, rebuild-openclaw-e2e, and hermes-slack-e2e on this revision.

As per coding guidelines, channels-stop-start-e2e, rebuild-openclaw-e2e, and hermes-slack-e2e are recommended for onboarding changes in src/lib/onboard.ts.

🤖 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 `@src/lib/onboard.ts` around lines 10027 - 10124, Summary: This change touches
resume logic and disabled-channel/policy preset handling; run the relevant E2E
suites before merging. Action: execute the lifecycle E2E tests for this
onboarding path — channels-stop-start-e2e, rebuild-openclaw-e2e, and
hermes-slack-e2e — and verify no regressions around resume, disabled-channel
cleanup, and Slack policy preservation; focus validation on flows that exercise
resume, mergeRequiredSetupPolicyPresets, pruneDisabledMessagingPolicyPresets,
mergeAppliedPolicyPresetsForDisabledMessagingCleanup,
hasDisabledMessagingPolicyPreset, arePolicyPresetsApplied, and
setupPoliciesWithSelection; if failures occur, capture failures, reproduce
locally, and update the code or tests until all three suites pass.
test/onboard-preset-diff.test.ts (1)

324-458: ⚡ Quick win

Harden these Slack regression tests against inherited messaging env leakage.

These new assertions can flake if parent DISCORD_*/TELEGRAM_* env vars leak into the spawned helper process and activate extra channels implicitly.

Proposed patch (in buildPreamble script body)
 return String.raw`
 // All stubs MUST be installed before requiring onboard so its module-level
 // destructuring picks up the patched functions.
 Object.defineProperty(process, "platform", { value: "darwin" });
+
+for (const key of Object.keys(process.env)) {
+  if (key.startsWith("DISCORD_") || key.startsWith("TELEGRAM_")) {
+    delete process.env[key];
+  }
+}

 const resolver = require(${resolveOpenshellPath});
 resolver.resolveOpenshell = () => "/fake/openshell";

Based on learnings: For hermetic messaging-channel tests in this repo, spawned helper scripts should remove inherited DISCORD_* and TELEGRAM_* env vars to avoid unintended channel activation.

🤖 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 `@test/onboard-preset-diff.test.ts` around lines 324 - 458, The tests flake
because inherited DISCORD_* and TELEGRAM_* env vars can activate messaging
channels in the spawned helper; modify the buildPreamble output to explicitly
remove any process.env keys that start with "DISCORD_" or "TELEGRAM_" before the
helper logic runs. Concretely, inside the buildPreamble-generated script (the
preamble string emitted by buildPreamble), add a short sanitization block that
iterates Object.keys(process.env) and deletes keys matching /^DISCORD_/ or
/^TELEGRAM_/ (e.g., for (const k of Object.keys(process.env)) if
(k.startsWith("DISCORD_") || k.startsWith("TELEGRAM_")) delete process.env[k]);
place this at the very top of the preamble so setupPoliciesWithSelection and any
channel-detection logic sees a hermetic env.
🤖 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.

Outside diff comments:
In `@src/lib/onboard.ts`:
- Around line 10072-10110: The code discards synthesized cleanup presets from
mergeAppliedPolicyPresetsForDisabledMessagingCleanup whenever
recordedPolicyPresets is null, so setupPoliciesWithSelection may not receive
necessary selectedPresets to remove stale disabled-channel policies; change the
selectedPresets argument passed into setupPoliciesWithSelection to use
recordedPolicyPresetsForSupport (or at least check its length) instead of gating
on Array.isArray(recordedPolicyPresets), ensuring that when
recordedPolicyPresetsForSupport contains synthesized presets they are forwarded
to setupPoliciesWithSelection; update the ternary at the selectedPresets key (or
its surrounding logic) to pass recordedPolicyPresetsForSupport when non-empty so
disabled-channel cleanup presets are not dropped.
- Around line 10027-10124: Extract the policy-state reconciliation block
(starting at the recordedPolicyPresets/recordedMessagingChannels lines through
the computation of resumePolicies and prior to the resume handling) into a new
helper function (e.g., assemblePolicyState) in a new module under
src/lib/onboard/; the helper should accept the minimal inputs (sandboxName,
latestSession or recordedPolicyPresets/recordedMessagingChannels,
selectedMessagingChannels, registry.getSandbox result or sandboxName+registry,
policies, hermesToolGateways, webSearchSupported,
activeSandbox?.disabledChannels, webSearchConfig, provider, model, agent, etc.)
and return the computed values used afterward (at least
recordedPolicyPresetsForSupport, policyMessagingChannels,
appliedPolicyPresetsForSupport, disabledMessagingPolicyPresetApplied,
resumePolicies); use the existing helper functions referenced in the block
(mergePolicyMessagingChannels, pruneDisabledMessagingPolicyPresets,
policies.clampSetupPolicyPresetNames, hasDisabledMessagingPolicyPreset,
mergeAppliedPolicyPresetsForDisabledMessagingCleanup,
mergeRequiredSetupPolicyPresets, arePolicyPresetsApplied) inside the new
assemblePolicyState function and export it, then replace the large inline block
in src/lib/onboard.ts with a single call to assemblePolicyState and use its
returned values unchanged.

---

Nitpick comments:
In `@src/lib/onboard.ts`:
- Around line 10027-10124: Summary: This change touches resume logic and
disabled-channel/policy preset handling; run the relevant E2E suites before
merging. Action: execute the lifecycle E2E tests for this onboarding path —
channels-stop-start-e2e, rebuild-openclaw-e2e, and hermes-slack-e2e — and verify
no regressions around resume, disabled-channel cleanup, and Slack policy
preservation; focus validation on flows that exercise resume,
mergeRequiredSetupPolicyPresets, pruneDisabledMessagingPolicyPresets,
mergeAppliedPolicyPresetsForDisabledMessagingCleanup,
hasDisabledMessagingPolicyPreset, arePolicyPresetsApplied, and
setupPoliciesWithSelection; if failures occur, capture failures, reproduce
locally, and update the code or tests until all three suites pass.

In `@test/onboard-preset-diff.test.ts`:
- Around line 324-458: The tests flake because inherited DISCORD_* and
TELEGRAM_* env vars can activate messaging channels in the spawned helper;
modify the buildPreamble output to explicitly remove any process.env keys that
start with "DISCORD_" or "TELEGRAM_" before the helper logic runs. Concretely,
inside the buildPreamble-generated script (the preamble string emitted by
buildPreamble), add a short sanitization block that iterates
Object.keys(process.env) and deletes keys matching /^DISCORD_/ or /^TELEGRAM_/
(e.g., for (const k of Object.keys(process.env)) if (k.startsWith("DISCORD_") ||
k.startsWith("TELEGRAM_")) delete process.env[k]); place this at the very top of
the preamble so setupPoliciesWithSelection and any channel-detection logic sees
a hermetic env.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 401b41ae-3c4f-45d5-b9e8-4fe21ac50f17

📥 Commits

Reviewing files that changed from the base of the PR and between 2371fba and 63b2174.

📒 Files selected for processing (8)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts
  • test/rebuild-policy-presets.test.ts

@yimoj

yimoj commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/onboard.ts (1)

10024-10035: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the effective enabled channel set for the smoke verifier.

activeSandbox.messagingChannels is the configured set, not the enabled set; this file intentionally preserves disabled channels there so channels start can restore them later. Passing that value here means verifyCompatibleEndpointSandboxSmoke(...) can still treat a stopped channel as active even though the policy flow now uses policyMessagingChannels.

Suggested fix
-    const activeMessagingChannels = activeSandbox?.messagingChannels;
+    const activeMessagingChannels = activeSandbox?.messagingChannels;
     const policyMessagingChannels = mergePolicyMessagingChannels(selectedMessagingChannels, recordedMessagingChannels, activeMessagingChannels, activeSandbox?.disabledChannels);
@@
-      messagingChannels: Array.isArray(activeMessagingChannels) ? activeMessagingChannels : [],
+      messagingChannels: policyMessagingChannels,
🤖 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 `@src/lib/onboard.ts` around lines 10024 - 10035, The smoke verifier is being
called with the raw configured set (activeMessagingChannels) which can include
channels marked disabled; instead pass the effective enabled set
(policyMessagingChannels) into verifyCompatibleEndpointSandboxSmoke so the
verifier uses the same channel view as the policy flow—update the call site that
currently passes Array.isArray(activeMessagingChannels) ?
activeMessagingChannels : [] to instead pass
Array.isArray(policyMessagingChannels) ? policyMessagingChannels : []
(referencing activeSandbox, activeMessagingChannels, policyMessagingChannels and
verifyCompatibleEndpointSandboxSmoke to locate the change).
🧹 Nitpick comments (1)
test/rebuild-policy-presets.test.ts (1)

181-188: ⚡ Quick win

Consider adding a clarifying comment to explain the test expectation.

The test expects telegram to be preserved when disabled, while test 1 expects slack to be removed when disabled. Without context, this appears contradictory. The test would benefit from a brief comment explaining the distinction (e.g., "telegram channel does not require a 'telegram' policy preset, so a preset named 'telegram' is preserved" or "only channels with known policy mappings are pruned").

The phrase "for later start and rebuild" in the test name is also unclear—consider clarifying what "later start" refers to in the test documentation.

📝 Suggested clarifying comment
+    // Unlike Slack (which requires the 'slack' preset), Telegram does not have
+    // a required policy preset mapping, so a preset named 'telegram' is preserved
+    // even when the Telegram channel is disabled.
     it("preserves non-required channel presets for later start and rebuild", () => {
🤖 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 `@test/rebuild-policy-presets.test.ts` around lines 181 - 188, Add a short
clarifying comment inside the test "preserves non-required channel presets for
later start and rebuild" explaining why "telegram" is expected to be preserved
(e.g., that pruneDisabledMessagingPolicyPresets only prunes presets that map to
known/required channels, and "telegram" in this case is considered non-required
so it should remain), and rename or expand the test name to clarify what "later
start" means (for example "preserves non-required channel presets for later
start/rebuild when channel mapping is absent"); update references in the test to
pruneDisabledMessagingPolicyPresets, manifest.policyPresets and savedPresets to
make the intent explicit.
🤖 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.

Outside diff comments:
In `@src/lib/onboard.ts`:
- Around line 10024-10035: The smoke verifier is being called with the raw
configured set (activeMessagingChannels) which can include channels marked
disabled; instead pass the effective enabled set (policyMessagingChannels) into
verifyCompatibleEndpointSandboxSmoke so the verifier uses the same channel view
as the policy flow—update the call site that currently passes
Array.isArray(activeMessagingChannels) ? activeMessagingChannels : [] to instead
pass Array.isArray(policyMessagingChannels) ? policyMessagingChannels : []
(referencing activeSandbox, activeMessagingChannels, policyMessagingChannels and
verifyCompatibleEndpointSandboxSmoke to locate the change).

---

Nitpick comments:
In `@test/rebuild-policy-presets.test.ts`:
- Around line 181-188: Add a short clarifying comment inside the test "preserves
non-required channel presets for later start and rebuild" explaining why
"telegram" is expected to be preserved (e.g., that
pruneDisabledMessagingPolicyPresets only prunes presets that map to
known/required channels, and "telegram" in this case is considered non-required
so it should remain), and rename or expand the test name to clarify what "later
start" means (for example "preserves non-required channel presets for later
start/rebuild when channel mapping is absent"); update references in the test to
pruneDisabledMessagingPolicyPresets, manifest.policyPresets and savedPresets to
make the intent explicit.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 1bbda8e1-3f2f-46a5-bb47-3a3b45e30719

📥 Commits

Reviewing files that changed from the base of the PR and between 2371fba and f12a919.

📒 Files selected for processing (8)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts
  • test/rebuild-policy-presets.test.ts

@yimoj yimoj force-pushed the fix/3753-slack-policy-preserve branch from f12a919 to 174e2d8 Compare May 20, 2026 07:26
@yimoj

yimoj commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 2

🤖 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 `@src/lib/onboard/policy-selection.ts`:
- Around line 192-198: The current truthy checks (e.g., if
(options.recordedPolicyPresets)) skip empty-array selections and thus drop
required presets on resume; change these guards to explicitly check for
undefined/null (for example: if (options.recordedPolicyPresets !== undefined &&
options.recordedPolicyPresets !== null) or use
Array.isArray(options.recordedPolicyPresets)) so an empty [] is treated as valid
input and still calls mergeRequiredSetupPolicyPresets with the same payload
(include selectablePolicyPresets.map(...) etc.); apply the same explicit-check
fix to the other occurrence around lines 264-272 to ensure resume/replay always
merges required messaging presets when channels are enabled.

In `@test/onboard-preset-diff.test.ts`:
- Around line 324-458: The tests are flaky because the spawned test script
inherits host env vars that can enable messaging channels; update the runScript
helper to sanitize the environment before spawning the child: copy process.env,
remove any keys starting with "DISCORD_" or "TELEGRAM_" (and any other
messaging-related prefixes you see causing leakage), and pass that cleaned env
into the child process spawn/exec call (the runScript function is the unique
symbol to change). Ensure the rest of runScript behavior (stdout/stderr capture,
exit status) remains unchanged.
🪄 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: Enterprise

Run ID: 3a295cff-be85-4026-9701-4a709a176570

📥 Commits

Reviewing files that changed from the base of the PR and between f12a919 and 174e2d8.

📒 Files selected for processing (8)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/messaging-policy-presets.test.ts
  • src/lib/onboard/messaging-policy-presets.ts
  • src/lib/onboard/policy-selection.ts
  • test/onboard-preset-diff.test.ts
  • test/rebuild-policy-presets.test.ts

Comment thread src/lib/onboard/policy-selection.ts Outdated
Comment thread test/onboard-preset-diff.test.ts
Signed-off-by: Yimo Jiang <yimoj@nvidia.com>
@yimoj yimoj force-pushed the fix/3753-slack-policy-preserve branch from 174e2d8 to fb110d9 Compare May 20, 2026 07:36
@yimoj

yimoj commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yimoj

yimoj commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Reviews resumed.

@yimoj yimoj added the v0.0.48 Release target label May 20, 2026
@wscurran wscurran added enhancement: policy integration: slack Slack integration or channel behavior labels May 20, 2026
@wscurran

Copy link
Copy Markdown
Contributor

ericksoa added 2 commits May 22, 2026 19:04
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>

# Conflicts:
#	src/lib/actions/sandbox/rebuild.ts
#	src/lib/onboard.ts
#	src/lib/onboard/initial-policy.ts
#	src/lib/onboard/policy-selection.ts

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/onboard.ts (1)

9608-9651: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Persist the final preset list back into the sandbox registry.

Both branches only update session state. The registry entry still keeps the earlier boot-time initialSandboxPolicy.appliedPresets, so the next recreate/rebuild can read stale previousEntry?.policies and drop presets that were actually selected in step 8.

💡 Minimal fix
     if (resumePolicies) {
       skippedStepMessage("policies", recordedPolicyPresetsForSupport.join(", "));
+      registry.updateSandbox(sandboxName, {
+        policies: recordedPolicyPresetsForSupport,
+      });
       await recordStepComplete(
         "policies",
         toSessionUpdates({
           sandboxName,
           provider,
@@
       const setupAppliedPolicyPresets = await setupPoliciesWithSelection(sandboxName, {
         selectedPresets:
           Array.isArray(recordedPolicyPresets)
             ? recordedPolicyPresetsForSupport
             : null,
@@
         },
       });
+      registry.updateSandbox(sandboxName, {
+        policies: setupAppliedPolicyPresets,
+      });
       await recordStepComplete(
         "policies",
         toSessionUpdates({
           sandboxName,
           provider,
🤖 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 `@src/lib/onboard.ts` around lines 9608 - 9651, When finishing the "policies"
step (both the resumePolicies branch that uses recordedPolicyPresetsForSupport
and the interactive branch that yields setupAppliedPolicyPresets), persist the
final preset list back into the sandbox registry so
initialSandboxPolicy.appliedPresets / previousEntry?.policies reflect the
user-chosen presets and aren’t stale on recreate/rebuild; place this persistence
immediately after the recordStepComplete("policies", ...) calls and update the
sandbox registry entry (the same registry that stores
initialSandboxPolicy.appliedPresets / previousEntry?.policies) with the applied
presets (use recordedPolicyPresetsForSupport in the resume branch and
setupAppliedPolicyPresets in the interactive branch).
🧹 Nitpick comments (2)
src/lib/onboard.ts (1)

9572-9651: Please run the onboarding/rebuild E2Es for this path.

This block changes resume-time policy reconciliation in src/lib/onboard.ts, so I'd want at least channels-stop-start-e2e plus one end-to-end onboard flow before merge.

As per coding guidelines: "src/lib/onboard.ts: This file contains core onboarding logic... E2E test recommendation: cloud-e2e ... channels-stop-start-e2e ..."

🤖 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 `@src/lib/onboard.ts` around lines 9572 - 9651, Changes to resume-time policy
reconciliation in src/lib/onboard.ts (around functions
mergePolicyMessagingChannels, verifyCompatibleEndpointSandboxSmoke,
preparePolicyPresetResumeSelection, and setupPoliciesWithSelection) require
running the relevant end-to-end tests before merging; run the
channels-stop-start-e2e suite and at least one full onboarding E2E (cloud-e2e or
a full onboard flow) to validate resume/reconcile behavior, confirm policy
presets are applied/skipped as expected, and fix any failures discovered by
updating the reconciliation logic or test fixtures accordingly.
src/lib/actions/sandbox/rebuild.ts (1)

395-410: Run the targeted rebuild/channel lifecycle E2E for this change set.

Given rebuild flow changes in this file, run channels-stop-start-e2e on this branch before merge to validate disabled/enabled channel behavior across rebuild.

As per coding guidelines: src/lib/actions/sandbox/rebuild.ts changes affect disabled channel resolution and should run channels-stop-start-e2e.

🤖 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 `@src/lib/actions/sandbox/rebuild.ts` around lines 395 - 410, This change
touches disabled channel resolution in the sandbox rebuild flow (see
src/lib/actions/sandbox/rebuild.ts around the rebuild logic that calls
captureSandboxListWithGatewayRecovery and handles
isLive/detectOpenShellStateRpcResultIssue), so before merging run the
channels-stop-start-e2e test suite on this branch to validate disabled/enabled
channel behavior across rebuilds; checkout this branch, run the
channels-stop-start-e2e E2E job (or the repo’s CI job that executes that suite),
verify the lifecycle passes (stop, rebuild, start) and that disabled channels
remain correctly resolved, and fix any failures uncovered in the rebuild logic
(particularly around captureSandboxListWithGatewayRecovery,
detectOpenShellStateRpcResultIssue, printOpenShellStateRpcIssue, and
printSandboxListFailureWithRecoveryContext) before merging.
🤖 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.

Outside diff comments:
In `@src/lib/onboard.ts`:
- Around line 9608-9651: When finishing the "policies" step (both the
resumePolicies branch that uses recordedPolicyPresetsForSupport and the
interactive branch that yields setupAppliedPolicyPresets), persist the final
preset list back into the sandbox registry so
initialSandboxPolicy.appliedPresets / previousEntry?.policies reflect the
user-chosen presets and aren’t stale on recreate/rebuild; place this persistence
immediately after the recordStepComplete("policies", ...) calls and update the
sandbox registry entry (the same registry that stores
initialSandboxPolicy.appliedPresets / previousEntry?.policies) with the applied
presets (use recordedPolicyPresetsForSupport in the resume branch and
setupAppliedPolicyPresets in the interactive branch).

---

Nitpick comments:
In `@src/lib/actions/sandbox/rebuild.ts`:
- Around line 395-410: This change touches disabled channel resolution in the
sandbox rebuild flow (see src/lib/actions/sandbox/rebuild.ts around the rebuild
logic that calls captureSandboxListWithGatewayRecovery and handles
isLive/detectOpenShellStateRpcResultIssue), so before merging run the
channels-stop-start-e2e test suite on this branch to validate disabled/enabled
channel behavior across rebuilds; checkout this branch, run the
channels-stop-start-e2e E2E job (or the repo’s CI job that executes that suite),
verify the lifecycle passes (stop, rebuild, start) and that disabled channels
remain correctly resolved, and fix any failures uncovered in the rebuild logic
(particularly around captureSandboxListWithGatewayRecovery,
detectOpenShellStateRpcResultIssue, printOpenShellStateRpcIssue, and
printSandboxListFailureWithRecoveryContext) before merging.

In `@src/lib/onboard.ts`:
- Around line 9572-9651: Changes to resume-time policy reconciliation in
src/lib/onboard.ts (around functions mergePolicyMessagingChannels,
verifyCompatibleEndpointSandboxSmoke, preparePolicyPresetResumeSelection, and
setupPoliciesWithSelection) require running the relevant end-to-end tests before
merging; run the channels-stop-start-e2e suite and at least one full onboarding
E2E (cloud-e2e or a full onboard flow) to validate resume/reconcile behavior,
confirm policy presets are applied/skipped as expected, and fix any failures
discovered by updating the reconciliation logic or test fixtures accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 3f088077-e17f-4b60-b6bd-10398f58c83a

📥 Commits

Reviewing files that changed from the base of the PR and between fb110d9 and e72c173.

📒 Files selected for processing (4)
  • src/lib/actions/sandbox/rebuild.ts
  • src/lib/onboard.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/policy-selection.ts
💤 Files with no reviewable changes (1)
  • src/lib/onboard/policy-selection.ts

@ericksoa ericksoa merged commit 994c0fc into NVIDIA:main May 23, 2026
21 checks passed
@wscurran wscurran added area: policy Network policy, egress rules, presets, or sandbox policy bug-fix PR fixes a bug or regression feature PR adds or expands user-visible functionality and removed fix feature PR adds or expands user-visible functionality labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: policy Network policy, egress rules, presets, or sandbox policy bug-fix PR fixes a bug or regression integration: slack Slack integration or channel behavior v0.0.50 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack messaging rebuild can preserve channel config but drop slack network policy

4 participants