Skip to content

refactor(policy): move messaging policies into channels - #6129

Merged
cv merged 21 commits into
mainfrom
feat/messaging-channel-policies
Jul 3, 2026
Merged

refactor(policy): move messaging policies into channels#6129
cv merged 21 commits into
mainfrom
feat/messaging-channel-policies

Conversation

@sandl99

@sandl99 sandl99 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR moves messaging-channel network policy data for OpenClaw and Hermes into the channel package tree under src/lib/messaging/channels. It keeps policy resolution manifest-driven while removing messaging endpoint data from central blueprint presets and Hermes baseline policy additions.

Related issues

Fixes #6185

Changes

  • Added channel-owned openclaw.yaml and hermes.yaml policy presets for Telegram, Discord, Slack, Teams, WeChat, and WhatsApp.
  • Added a messaging channel policy resolver and wired sandbox-aware preset loading through onboarding, policy-add/policy-remove, and channels add flows.
  • Updated package/schema/config validation, platform matrix docs sync, internal messaging guidance, and focused tests for the new policy source layout.
  • Split channel YAML contract coverage into test/policy-channel-yaml-contract.test.ts and ratcheted the oversized test/policies.test.ts file budget down.

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)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification:
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: self-reviewed policy/onboarding/channel lifecycle changes; focused tests and CI requested.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: no CI waiver requested; local test-cli failure was reproduced on clean main in this environment.

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push, or npx prek run --from-ref main --to-ref HEAD passes — commit/push hooks passed with local test-cli skipped; full test-cli also fails on clean main locally.
  • Targeted tests pass for changed behavior
  • Full npm test passes (broad runtime changes only)
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — npm run docs passed; Fern reported 2 warnings.
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Verification evidence:

  • npm run typecheck:cli
  • npx tsx scripts/validate-configs.ts
  • npm run build:cli
  • npx vitest run --project cli src/lib/messaging/channels/policy.test.ts src/lib/actions/sandbox/policy-channel-agent-gate.test.ts src/lib/shields/timer.test.ts src/lib/onboard/initial-policy.test.ts
  • npx vitest run --project integration test/onboard-messaging.test.ts test/policies.test.ts
  • npx vitest run --project integration test/policy-channel-yaml-contract.test.ts test/policies.test.ts test/channels-add-preset.test.ts test/validate-blueprint.test.ts
  • npm run source-shape:check
  • npm run test-size:check
  • npm run docs
  • npx prek run --files ... passed all non-test-cli hooks; test-cli failed with the same local platform/runtime fixture failures reproduced on clean main.

Signed-off-by: San Dang sdang@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added/expanded built-in messaging channel policy presets for Discord, Slack, Teams, Telegram, WeChat, and WhatsApp with agent-specific Hermes/OpenClaw variants.
    • Channel policy presets are now packaged and discovered from per-channel policy locations.
  • Bug Fixes
    • Sandbox add/remove/refresh now uses sandbox-scoped preset resolution to avoid incorrect preset selection.
    • Removed messaging-channel network policy templates from the Hermes sandbox policy file to prevent unintended template egress.
  • Documentation
    • Updated messaging integration notes and setup instructions, including WebSocket/Noise/h1-ALPN caveats.
  • Tests
    • Expanded coverage for sandbox-aware preset loading and messaging YAML policy contracts.

@sandl99 sandl99 added area: docs Documentation, examples, guides, or docs build area: security Security controls, permissions, secrets, or hardening labels Jul 1, 2026
@sandl99 sandl99 self-assigned this Jul 1, 2026
@github-code-quality

github-code-quality Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the feat/messaging-chann... branch is 96%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main feat/messaging-chann... 3674607 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.ts 97%
nemoclaw/src/blueprint/ssrf.ts 97%
nemoclaw/src/bl...print/runner.ts 95%
nemoclaw/src/co...ration-state.ts 94%
nemoclaw/src/bl...ate-networks.ts 94%
nemoclaw/src/index.ts 94%

TypeScript / code-coverage/cli

The overall coverage in the feat/messaging-chann... branch is 70%. Coverage data for the main branch is not yet available.

Show a code coverage summary of the most covered files.
File main feat/messaging-chann... 3674607 +/-
src/lib/actions...dbox/rebuild.ts 82%
src/lib/actions...all/run-plan.ts 80%
src/lib/state/o...oard-session.ts 80%
src/lib/shields/index.ts 75%
src/lib/state/sandbox.ts 73%
src/lib/policy/index.ts 70%
src/lib/onboard...er-gpu-patch.ts 69%
src/lib/onboard/preflight.ts 69%
src/lib/actions...licy-channel.ts 57%
src/lib/onboard.ts 20%

Updated July 03, 2026 05:09 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Messaging policy presets move from the central Hermes additions file into per-channel YAML files. The loader, sandbox flows, onboarding, discovery, packaging, docs, and tests now resolve those presets with channel and sandbox context.

Changes

Channel-owned policy migration

Layer / File(s) Summary
Per-channel policy files
agents/hermes/policy-additions.yaml, src/lib/messaging/channels/discord/policy/hermes.yaml, .../slack/policy/hermes.yaml, .../teams/policy/hermes.yaml, .../telegram/policy/hermes.yaml, .../wechat/policy/hermes.yaml, .../whatsapp/policy/openclaw.yaml
Removes the messaging template rules from the central Hermes policy additions file and adds per-channel YAML policy files for Discord, Slack, Teams, Telegram, WeChat, and WhatsApp.
Channel policy loader
src/lib/messaging/channels/policy.ts, src/lib/messaging/channels/index.ts, src/lib/messaging/channels/policy.test.ts
Adds helpers to resolve, load, list, and check messaging channel policy presets by agent, and re-exports them from the channels index.
Sandbox-aware preset resolution
src/lib/policy/index.ts, src/lib/policy/context.ts, src/lib/policy/context.test.ts, src/lib/policy/failure-classifier.test.ts, test/policy-channel-agent-resolution.test.ts
Combines channel and central preset listings, adds sandbox and agent-aware preset loading, updates preset merging to accept agent context, and switches policy context partitioning to load sandbox-scoped presets.
Sandbox action flows
src/lib/actions/sandbox/policy-channel.ts, src/lib/actions/sandbox/policy-channel-agent-gate.test.ts, src/lib/actions/sandbox/policy-channel-policy.test.ts, src/lib/actions/sandbox/policy-channel-refresh.test.ts, test/channels-add-deepagents-rejection.test.ts, test/channels-add-preset.test.ts, test/package-contract/cli/policy-dispatch.test.ts
Switches sandbox policy and channel operations to load presets through sandbox-scoped resolution, and updates the matching regression tests and mocks.
Initial policy preset selection
src/lib/onboard/initial-policy.ts, src/lib/onboard/initial-policy.test.ts, test/onboard-messaging.test.ts
Updates initial sandbox policy creation to choose Hermes-specific or required messaging presets and pass agent context into preset merging, with matching test updates.
Config discovery and packaging
scripts/validate-configs.ts, scripts/find-source-shape-tests.ts, schemas/policy-preset.schema.json, package.json, ci/platform-matrix.json, docs/reference/platform-support.mdx, ci/test-file-size-budget.json, test/validate-config-schemas.test.ts
Expands preset discovery, declarative path detection, schema text, packaging globs, CI references, and validation tests to cover channel-owned policy YAML files.
Path migration and YAML contract tests
test/policies.test.ts, test/policy-channel-yaml-contract.test.ts, test/validate-blueprint.test.ts, test/pr-review-advisor.test.ts, tools/pr-review-advisor/analyze.mts
Updates tests to read channel-owned policy YAML files, removes stale central-policy assertions, and adds runtime-validation classification for policy paths.
Docs and CLI test stubs
src/lib/messaging/AGENTS.md, src/lib/messaging/README.md, test/policy-add-remove-session-sync.test.ts
Updates messaging docs and CLI test harness stubs to point at channel-owned policy files and expose sandbox-scoped preset loading.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant policy_channel_ts as src/lib/actions/sandbox/policy-channel.ts
  participant policy_index_ts as src/lib/policy/index.ts
  participant channels_policy_ts as src/lib/messaging/channels/policy.ts

  policy_channel_ts->>policy_index_ts: loadPresetForSandbox(sandboxName, presetName)
  policy_index_ts->>policy_index_ts: resolve sandbox agent
  policy_index_ts->>channels_policy_ts: loadMessagingChannelPolicyPreset(presetName, agent)
  alt channel preset exists
    channels_policy_ts-->>policy_index_ts: preset YAML content
  else no channel preset
    policy_index_ts->>policy_index_ts: loadCentralPreset(presetName)
    policy_index_ts-->>policy_channel_ts: preset YAML content or null
  end
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#3445: Both change Hermes Discord policy allowlisting in overlapping messaging-policy files.
  • NVIDIA/NemoClaw#3984: Both adjust sandbox-aware messaging preset loading and onboarding policy selection.
  • NVIDIA/NemoClaw#4248: Both modify sandbox channel/policy application flow in src/lib/actions/sandbox/policy-channel.ts.

Suggested labels: area: messaging, area: policy, refactor

Suggested reviewers: cv, ericksoa

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.00% 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
Title check ✅ Passed The title clearly summarizes the main refactor: moving messaging policy definitions into channel-owned files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/messaging-channel-policies

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

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-3: Telegram Hermes policy missing /usr/local/bin/hermes binary allowlist; then add or justify PRA-T1.
Open items: 6 required · 11 warnings · 2 suggestions · 8 test follow-ups
Since last review: 0 prior items resolved · 11 still apply · 5 new items found

Action checklist

  • PRA-3 Fix: Telegram Hermes policy missing /usr/local/bin/hermes binary allowlist in src/lib/messaging/channels/telegram/policy/hermes.yaml:20
  • PRA-4 Fix: Discord Hermes policy missing /usr/local/bin/hermes binary allowlist in src/lib/messaging/channels/discord/policy/hermes.yaml:42
  • PRA-5 Fix: WhatsApp Hermes policy declares only Node binaries, no Python/Hermes in src/lib/messaging/channels/whatsapp/policy/hermes.yaml:44
  • PRA-6 Fix: No binary allowlist validation for any Hermes channel policy in new contract test in test/policy-channel-yaml-contract.test.ts:1
  • PRA-7 Fix: Custom preset (--from-file) agent gate not tested for Deep Agents in src/lib/actions/sandbox/policy-channel-policy.test.ts:247
  • PRA-8 Fix: src/lib/policy/index.ts monolith grew 71 lines (1459 total) — extract preset helpers in src/lib/policy/index.ts:1
  • PRA-1 Resolve or justify: Source-of-truth review needed: src/lib/onboard/initial-policy.ts:238
  • PRA-2 Resolve or justify: Source-of-truth review needed: src/lib/messaging/channels/*/policy/*.yaml (12 files)
  • PRA-9 Resolve or justify: Channel policy directory discovery swallows ENOENT/ENOTDIR silently in scripts/validate-configs.ts:137
  • PRA-10 Resolve or justify: isSafeId regex duplicates manifest ID validation — single source of truth needed in src/lib/messaging/channels/policy.ts:45
  • PRA-11 Resolve or justify: Hermes vs OpenClaw create-time preset logic diverges without documentation in src/lib/onboard/initial-policy.ts:238
  • PRA-12 Resolve or justify: Schema allows websocket protocol without requiring websocket_credential_rewrite in schemas/policy-preset.schema.json:1
  • PRA-13 Resolve or justify: Path traversal test only covers '../' pattern in src/lib/messaging/channels/policy.test.ts:1
  • PRA-14 Resolve or justify: E2E test only validates Hermes Slack policy preservation at sandbox create in test/onboard-messaging.test.ts:1
  • PRA-15 Resolve or justify: Initial policy create-time only tests Discord/Slack for Hermes in src/lib/onboard/initial-policy-real-policy.test.ts:1
  • PRA-18 Resolve or justify: Test scaffold duplication — POLICY_PRESETS fixture repeated across test files in src/lib/actions/sandbox/policy-channel-list.test.ts:185
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: No binary allowlist validation for any Hermes channel policy in new contract test
  • PRA-T7 Add or justify test follow-up: Path traversal test only covers '../' pattern
  • PRA-T8 Add or justify test follow-up: E2E test only validates Hermes Slack policy preservation at sandbox create
  • PRA-16 In-scope improvement: Binary allowlists duplicated across 12 policy files with no single source of truth in src/lib/messaging/channels//policy/.yaml:1
  • PRA-17 In-scope improvement: Channel policy YAML files added to npm package files array — verify intentional in package.json:109

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Required security src/lib/messaging/channels/telegram/policy/hermes.yaml:20 Add /usr/local/bin/hermes to binaries list. Audit whether /usr/local/bin/node is actually needed (remove if bridge is Python-only).
PRA-4 Required security src/lib/messaging/channels/discord/policy/hermes.yaml:42 Add /usr/local/bin/hermes to binaries list. Audit Discord Hermes bridge implementation language; remove Node if bridge is Python-only.
PRA-5 Required security src/lib/messaging/channels/whatsapp/policy/hermes.yaml:44 Determine actual runtime of Hermes WhatsApp bridge. If Python/Hermes-based, add /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python. If Node-only (Baileys), add comment documenting why and add test asserting Node-only.
PRA-6 Required tests test/policy-channel-yaml-contract.test.ts:1 Add parameterized test cases for each Hermes channel policy validating: (1) binary allowlist matches expected runtime, (2) WebSocket credential rewrite where applicable, (3) request_body_credential_rewrite for REST endpoints with credentials.
PRA-7 Required acceptance src/lib/actions/sandbox/policy-channel-policy.test.ts:247 Add test in policy-channel-policy.test.ts for custom preset rejection on Deep Agents with messaging policy key, mirroring the built-in preset test pattern.
PRA-8 Required correctness src/lib/policy/index.ts:1 Extract policy preset loading/merging helpers into src/lib/policy/presets.ts or similar to offset growth. At minimum, justify why new functions couldn't be extracted.
PRA-9 Resolve/justify architecture scripts/validate-configs.ts:137 Add explicit logging when channel policy discovery finds zero files for a known channel, or propagate unexpected errors instead of catching all ENOENT/ENOTDIR.
PRA-10 Resolve/justify architecture src/lib/messaging/channels/policy.ts:45 Either align regex with ChannelManifest ID validation in manifest.ts, or document the restriction and ensure manifest IDs conform. Add test for edge cases.
PRA-11 Resolve/justify architecture src/lib/onboard/initial-policy.ts:238 Document why Hermes uses all vs required. Add test verifying create-time policy matches expected presets for both agents given same activeChannels input.
PRA-12 Resolve/justify security schemas/policy-preset.schema.json:1 Add AJV custom keyword or post-validation check: if protocol=websocket and rules exist, websocket_credential_rewrite must be true. Test with fixture missing the field.
PRA-13 Resolve/justify tests src/lib/messaging/channels/policy.test.ts:1 Add additional path traversal test cases: absolute paths (/etc/passwd), null bytes, URL-encoded traversal (%2e%2e%2f), double-encoded traversal.
PRA-14 Resolve/justify tests test/onboard-messaging.test.ts:1 Add parameterized test cases for each Hermes channel reusing existing mock pattern. At minimum add tests for Discord and Teams (which have WebSocket credential rewrite).
PRA-15 Resolve/justify tests src/lib/onboard/initial-policy-real-policy.test.ts:1 Extend initial-policy-real-policy.test.ts to cover all messaging channels for both agents.
PRA-16 Improvement architecture src/lib/messaging/channels//policy/.yaml:1 Define canonical binary allowlists per agent (e.g., HERMES_AGENT_BINARIES, OPENCLAW_AGENT_BINARIES) in a shared module and test that all channel policies include the correct one (or document exceptions).
PRA-17 Improvement correctness package.json:109 Confirm channel policy YAML files are read at runtime (they are — via loadMessagingChannelPolicyPreset). If so, keep in files array. If only used at build time, remove.
PRA-18 Resolve/justify tests src/lib/actions/sandbox/policy-channel-list.test.ts:185 Extract POLICY_PRESETS fixture to shared test helper (e.g., test/fixtures/policy-presets.ts) and import in both test files.
PRA-19 Resolve/justify tests src/lib/actions/sandbox/policy-channel-policy.test.ts:241 Same as above.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-3 Required — Telegram Hermes policy missing /usr/local/bin/hermes binary allowlist

  • Location: src/lib/messaging/channels/telegram/policy/hermes.yaml:20
  • Category: security
  • Problem: Telegram Hermes policy binaries list contains /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python but omits /usr/local/bin/hermes. Hermes agent binary is /usr/local/bin/hermes (per agents/hermes/manifest.yaml). If the Telegram bridge runs under the Hermes Python process, all egress to api.telegram.org will be blocked by OpenShell L7 proxy.
  • Impact: Hermes Telegram bridge cannot reach api.telegram.org — all bot API calls fail closed, breaking Telegram messaging for Hermes sandboxes.
  • Required action: Add /usr/local/bin/hermes to binaries list. Audit whether /usr/local/bin/node is actually needed (remove if bridge is Python-only).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/telegram/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts validating Hermes Telegram policy binaries include /usr/local/bin/hermes and exclude /usr/local/bin/node if bridge is Python-only.
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/telegram/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Evidence: Telegram Hermes policy at line 18-21 shows binaries: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python. No Hermes binary. Contrast with Slack Hermes policy which uses /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python.

PRA-4 Required — Discord Hermes policy missing /usr/local/bin/hermes binary allowlist

  • Location: src/lib/messaging/channels/discord/policy/hermes.yaml:42
  • Category: security
  • Problem: Discord Hermes policy binaries list contains /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python but omits /usr/local/bin/hermes. Discord Hermes bridge uses WebSocket gateway (gateway.discord.gg) with websocket_credential_rewrite which requires the Hermes Python process.
  • Impact: Hermes Discord bridge cannot reach gateway.discord.gg or discord.com REST endpoints — all Discord messaging fails for Hermes sandboxes.
  • Required action: Add /usr/local/bin/hermes to binaries list. Audit Discord Hermes bridge implementation language; remove Node if bridge is Python-only.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/discord/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts validating Hermes Discord policy binaries include /usr/local/bin/hermes.
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/discord/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Evidence: Discord Hermes policy at line 40-42 shows binaries: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python. No Hermes binary. Contrast with Slack Hermes policy which uses /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python.

PRA-5 Required — WhatsApp Hermes policy declares only Node binaries, no Python/Hermes

  • Location: src/lib/messaging/channels/whatsapp/policy/hermes.yaml:44
  • Category: security
  • Problem: WhatsApp Hermes policy declares only /usr/local/bin/node and /usr/bin/node as allowed binaries. Hermes is a Python agent (binary_path: /usr/local/bin/hermes). If the WhatsApp bridge runs under Hermes/Python, all WhatsApp traffic (web.whatsapp.com, *.whatsapp.net, raw.githubusercontent.com for Baileys version fetch) will be blocked.
  • Impact: Hermes WhatsApp bridge cannot reach WhatsApp Web endpoints — pairing and messaging fail completely for Hermes sandboxes.
  • Required action: Determine actual runtime of Hermes WhatsApp bridge. If Python/Hermes-based, add /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python. If Node-only (Baileys), add comment documenting why and add test asserting Node-only.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/whatsapp/policy/hermes.yaml — should include Hermes/Python paths if bridge is Python-based. Search Hermes agent code for 'whatsapp' bridge entrypoint.
  • Missing regression test: Add test validating Hermes WhatsApp policy binary allowlist matches actual bridge runtime (Node-only or Python/Hermes).
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/whatsapp/policy/hermes.yaml — should include Hermes/Python paths if bridge is Python-based. Search Hermes agent code for 'whatsapp' bridge entrypoint.
  • Evidence: WhatsApp Hermes policy at line 44 shows binaries: /usr/local/bin/node, /usr/bin/node. No Hermes or Python binaries. All other Hermes channel policies (Slack, Teams, WeChat) include /usr/local/bin/hermes and Python paths.

PRA-6 Required — No binary allowlist validation for any Hermes channel policy in new contract test

  • Location: test/policy-channel-yaml-contract.test.ts:1
  • Category: tests
  • Problem: New test file test/policy-channel-yaml-contract.test.ts validates Slack/Discord WebSocket credential rewrite and Discord REST mutation scoping, but does not validate binary allowlists for ANY Hermes channel policy. Four of six Hermes channel policies (Telegram, Discord, WhatsApp, Teams) lack binary allowlist tests.
  • Impact: Binary allowlist regressions (like the three missing /usr/local/bin/hermes entries above) will not be caught by CI.
  • Required action: Add parameterized test cases for each Hermes channel policy validating: (1) binary allowlist matches expected runtime, (2) WebSocket credential rewrite where applicable, (3) request_body_credential_rewrite for REST endpoints with credentials.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run test/policy-channel-yaml-contract.test.ts — currently passes but does not assert binary allowlists.
  • Missing regression test: Add binary allowlist assertions for all 6 Hermes channel policies in test/policy-channel-yaml-contract.test.ts.
  • Done when: The required change is committed and verification passes: Run test/policy-channel-yaml-contract.test.ts — currently passes but does not assert binary allowlists.
  • Evidence: test/policy-channel-yaml-contract.test.ts has 4 test blocks: Slack REST credential rewrite, Hermes messaging gateway inspected WebSocket, Hermes Discord REST mutations scoped, ships policy file for every manifest-supported agent. Zero binary allowlist assertions.

PRA-7 Required — Custom preset (--from-file) agent gate not tested for Deep Agents

  • Location: src/lib/actions/sandbox/policy-channel-policy.test.ts:247
  • Category: acceptance
  • Problem: Custom preset (--from-file) agent gate not tested for Deep Agents. The previous test file policy-add-agent-gate.test.ts was deleted; the new policy-channel-policy.test.ts tests built-in preset rejection but has no test for custom preset file rejection on terminal-runtime agents.
  • Impact: A custom preset with a messaging policy key (e.g., telegram_bot) could bypass the agent gate on DeepAgents if --from-file path is not guarded.
  • Required action: Add test in policy-channel-policy.test.ts for custom preset rejection on Deep Agents with messaging policy key, mirroring the built-in preset test pattern.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search src/lib/actions/sandbox/policy-channel-policy.test.ts for 'fromFile' or 'custom preset' — no such test exists.
  • Missing regression test: Add test: 'rejects a custom preset with a messaging policy key on a terminal-runtime agent before any disclosure, prompt, or apply'.
  • Done when: The required change is committed and verification passes: Search src/lib/actions/sandbox/policy-channel-policy.test.ts for 'fromFile' or 'custom preset' — no such test exists.
  • Evidence: Deleted policy-add-agent-gate.test.ts had 'describe("addSandboxPolicy custom preset (--from-file) agent gate")' with 6 test cases. New policy-channel-policy.test.ts has no fromFile/custom preset tests for DeepAgents.

PRA-8 Required — src/lib/policy/index.ts monolith grew 71 lines (1459 total) — extract preset helpers

  • Location: src/lib/policy/index.ts:1
  • Category: correctness
  • Problem: src/lib/policy/index.ts grew by 71 lines (from 1388 to 1459) in this PR. The file is now a 1460-line monolith handling preset loading, merging, validation, gateway interaction, and custom preset persistence.
  • Impact: Monolith growth makes security review harder, increases coupling, and prevents extraction of policy preset loading/merging helpers into a dedicated module.
  • Required action: Extract policy preset loading/merging helpers into src/lib/policy/presets.ts or similar to offset growth. At minimum, justify why new functions couldn't be extracted.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check line count of src/lib/policy/index.ts — currently ~1460 lines.
  • Missing regression test: No automated check; architecture review needed.
  • Done when: The required change is committed and verification passes: Check line count of src/lib/policy/index.ts — currently ~1460 lines.
  • Evidence: driftContext.monolithDeltas shows src/lib/policy/index.ts delta +71 severity blocker. File handles listPresets, loadPreset, loadPresetForSandbox, loadPresetForAgent, mergePresetIntoPolicy, mergePresetNamesIntoPolicy, applyPreset, applyPresetContent, applyPresets, removePreset, getGatewayPresets, etc.
Review findings by urgency: 6 required fixes, 11 items to resolve/justify, 2 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: src/lib/onboard/initial-policy.ts:238

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Parameterized test: both agents with same activeChannels
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Hermes uses allMessagingChannelPolicyPresets, OpenClaw uses requiredMessagingChannelPolicyPresets; no comment explaining why

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/*/policy/*.yaml (12 files)

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test: all Hermes policies include HERMES_AGENT_BINARIES
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Slack/Teams/WeChat Hermes have hermes binary; Telegram/Discord/WhatsApp do not

PRA-9 Resolve/justify — Channel policy directory discovery swallows ENOENT/ENOTDIR silently

  • Location: scripts/validate-configs.ts:137
  • Category: architecture
  • Problem: Channel policy directory discovery uses try/catch that swallows ENOENT/ENOTDIR. If the channel policy directory structure is broken (e.g., permission denied), validation passes silently.
  • Impact: Silent validation gaps when channel policy directories exist but cannot be read. Missing channel policy directories (e.g., a new channel added without policy files) produce no warning.
  • Recommended action: Add explicit logging when channel policy discovery finds zero files for a known channel, or propagate unexpected errors instead of catching all ENOENT/ENOTDIR.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check scripts/validate-configs.ts walkChannelPolicies catch block — only throws on non-ENOENT/ENOTDIR errors.
  • Missing regression test: Add test simulating permission error on channel policy directory — validation should fail or warn loudly.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check scripts/validate-configs.ts walkChannelPolicies catch block — only throws on non-ENOENT/ENOTDIR errors.
  • Evidence: scripts/validate-configs.ts:137 catch block: `if (code !== "ENOENT" && code !== "ENOTDIR") throw err;` — all ENOENT/ENOTDIR silently ignored.

PRA-10 Resolve/justify — isSafeId regex duplicates manifest ID validation — single source of truth needed

  • Location: src/lib/messaging/channels/policy.ts:45
  • Category: architecture
  • Problem: isSafeId regex /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/ may reject valid future channel IDs. ChannelManifest IDs in manifest.ts may allow different characters. The regex is a localized workaround for path traversal that duplicates validation logic.
  • Impact: Future channel IDs with valid characters (e.g., underscores, uppercase) would be rejected at preset resolution time without a clear migration path. Divergence between manifest ID validation and preset resolution could allow or reject IDs inconsistently.
  • Recommended action: Either align regex with ChannelManifest ID validation in manifest.ts, or document the restriction and ensure manifest IDs conform. Add test for edge cases.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare isSafeId regex with ChannelManifest ID validation in src/lib/messaging/channels/manifest.ts.
  • Missing regression test: Add test for isSafeId with edge cases matching manifest ID validation. Add test ensuring all manifest IDs pass isSafeId.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare isSafeId regex with ChannelManifest ID validation in src/lib/messaging/channels/manifest.ts.
  • Evidence: src/lib/messaging/channels/policy.ts:45 defines isSafeId. Channel IDs used in channelPolicyPath() for filesystem access. Manifest IDs defined in channel manifest files.

PRA-11 Resolve/justify — Hermes vs OpenClaw create-time preset logic diverges without documentation

  • Location: src/lib/onboard/initial-policy.ts:238
  • Category: architecture
  • Problem: Hermes uses allMessagingChannelPolicyPresets (all active channels), OpenClaw uses requiredMessagingChannelPolicyPresets (subset). The reason for this divergence is not documented.
  • Impact: Future maintainers may incorrectly unify or diverge further. Test coverage for both paths exists but the design rationale is opaque.
  • Recommended action: Document why Hermes uses all vs required. Add test verifying create-time policy matches expected presets for both agents given same activeChannels input.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/initial-policy.ts around line 238 and messaging-policy-presets.ts for allMessagingChannelPolicyPresets vs requiredMessagingChannelPolicyPresets.
  • Missing regression test: Add parameterized test in initial-policy-real-policy.test.ts verifying create-time presets for both agents with identical activeChannels.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/initial-policy.ts around line 238 and messaging-policy-presets.ts for allMessagingChannelPolicyPresets vs requiredMessagingChannelPolicyPresets.
  • Evidence: initial-policy.ts:238 calls allMessagingChannelPolicyPresets(activeMessagingChannels) for Hermes, requiredMessagingChannelPolicyPresets(activeMessagingChannels) for OpenClaw. No comment explaining why.

PRA-12 Resolve/justify — Schema allows websocket protocol without requiring websocket_credential_rewrite

  • Location: schemas/policy-preset.schema.json:1
  • Category: security
  • Problem: Schema allows websocket protocol without requiring websocket_credential_rewrite. Discord/Slack Hermes policies set websocket_credential_rewrite: true on gateway endpoints, but the schema does not enforce this coupling.
  • Impact: A preset author could declare a websocket endpoint without credential rewrite, allowing unvalidated WebSocket connections that bypass L7 token injection.
  • Recommended action: Add AJV custom keyword or post-validation check: if protocol=websocket and rules exist, websocket_credential_rewrite must be true. Test with fixture missing the field.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check schemas/policy-preset.schema.json — endpoint definition has websocket_credential_rewrite as optional boolean with no conditional requirement.
  • Missing regression test: Add schema validation test with websocket endpoint missing websocket_credential_rewrite — should fail.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check schemas/policy-preset.schema.json — endpoint definition has websocket_credential_rewrite as optional boolean with no conditional requirement.
  • Evidence: schemas/policy-preset.schema.json endpoint definition: websocket_credential_rewrite is type boolean, optional. No 'if/then' requiring it when protocol=websocket.

PRA-13 Resolve/justify — Path traversal test only covers '../' pattern

  • Location: src/lib/messaging/channels/policy.test.ts:1
  • Category: tests
  • Problem: Path traversal test only covers '../' pattern. Does not test absolute paths (/etc/passwd), null bytes, URL-encoded traversal, double-encoded traversal, or Unicode normalization bypasses.
  • Impact: Path traversal via other vectors could bypass the isSafeId check if channelId comes from untrusted metadata.
  • Recommended action: Add additional path traversal test cases: absolute paths (/etc/passwd), null bytes, URL-encoded traversal (%2e%2e%2f), double-encoded traversal.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check src/lib/messaging/channels/policy.test.ts 'rejects path traversal channel ids from preset metadata' test — only tests '../telegram'.
  • Missing regression test: Add test cases for absolute paths, null bytes, URL-encoded, double-encoded traversal patterns.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check src/lib/messaging/channels/policy.test.ts 'rejects path traversal channel ids from preset metadata' test — only tests '../telegram'.
  • Evidence: policy.test.ts line 106-111: only tests channelId: '../telegram'. No other traversal vectors tested.

PRA-14 Resolve/justify — E2E test only validates Hermes Slack policy preservation at sandbox create

  • Location: test/onboard-messaging.test.ts:1
  • Category: tests
  • Problem: E2E test only validates Hermes Slack policy preservation at sandbox create. Other Hermes channels (Discord, Telegram, Teams, WhatsApp, WeChat) are not covered.
  • Impact: Regression in policy preservation for other channels would not be caught.
  • Recommended action: Add parameterized test cases for each Hermes channel reusing existing mock pattern. At minimum add tests for Discord and Teams (which have WebSocket credential rewrite).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read test/onboard-messaging.test.ts — only Slack is tested for Hermes.
  • Missing regression test: Add parameterized test for each Hermes channel in test/onboard-messaging.test.ts.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read test/onboard-messaging.test.ts — only Slack is tested for Hermes.
  • Evidence: test/onboard-messaging.test.ts tests Hermes Slack preservation. No test for Discord, Teams, Telegram, WhatsApp, WeChat.

PRA-15 Resolve/justify — Initial policy create-time only tests Discord/Slack for Hermes

  • Location: src/lib/onboard/initial-policy-real-policy.test.ts:1
  • Category: tests
  • Problem: Initial policy create-time only tests Discord/Slack for Hermes. Other channels (Telegram, Teams, WhatsApp, WeChat) not verified.
  • Impact: Incomplete test coverage for the Hermes vs OpenClaw divergence. Other channels unverified.
  • Recommended action: Extend initial-policy-real-policy.test.ts to cover all messaging channels for both agents.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check src/lib/onboard/initial-policy-real-policy.test.ts — only tests Discord/Slack for Hermes.
  • Missing regression test: Add parameterized test cases for each Hermes channel in initial-policy-real-policy.test.ts.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check src/lib/onboard/initial-policy-real-policy.test.ts — only tests Discord/Slack for Hermes.
  • Evidence: initial-policy-real-policy.test.ts has single test: 'uses Hermes channel YAML when the Hermes base policy path implies the agent' — only checks slack and discord binaries/rules.

PRA-18 Resolve/justify — Test scaffold duplication — POLICY_PRESETS fixture repeated across test files

  • Location: src/lib/actions/sandbox/policy-channel-list.test.ts:185
  • Category: tests
  • Problem: POLICY_PRESETS fixture duplicated in policy-channel-list.test.ts and policy-channel-policy.test.ts. Shared test helper would reduce maintenance burden.
  • Impact: Fixture changes require updates in multiple files. Inconsistency risk if one copy is updated and another is not.
  • Recommended action: Extract POLICY_PRESETS fixture to shared test helper (e.g., test/fixtures/policy-presets.ts) and import in both test files.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare policy-channel-list.test.ts:20-30 and policy-channel-policy.test.ts:50-60 — identical POLICY_PRESETS arrays.
  • Missing regression test: No regression test needed; refactor verification via existing tests.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare policy-channel-list.test.ts:20-30 and policy-channel-policy.test.ts:50-60 — identical POLICY_PRESETS arrays.
  • Evidence: Both files define identical POLICY_PRESETS: npm, pypi, discord, openclaw-pricing, nous-web, nous-code, telegram, wechat.

PRA-19 Resolve/justify — Test scaffold duplication — POLICY_PRESETS fixture repeated

  • Location: src/lib/actions/sandbox/policy-channel-policy.test.ts:241
  • Category: tests
  • Problem: Same as above — POLICY_PRESETS fixture duplicated in policy-channel-policy.test.ts.
  • Impact: Same as above.
  • Recommended action: Same as above.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Same as above.
  • Missing regression test: Same as above.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Same as above.
  • Evidence: Same as above.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-16 Improvement — Binary allowlists duplicated across 12 policy files with no single source of truth

  • Location: src/lib/messaging/channels//policy/.yaml:1
  • Category: architecture
  • Problem: Binary allowlists duplicated across 12 policy files (6 channels × 2 agents) with no single source of truth. Hermes policies should share a canonical HERMES_AGENT_BINARIES = ['/usr/local/bin/hermes', '/usr/bin/python3*', '/opt/hermes/.venv/bin/python'] but each file repeats it.
  • Impact: Inconsistencies like the three missing /usr/local/bin/hermes entries are inevitable without a shared constant. Maintenance burden grows with each new channel.
  • Suggested action: Define canonical binary allowlists per agent (e.g., HERMES_AGENT_BINARIES, OPENCLAW_AGENT_BINARIES) in a shared module and test that all channel policies include the correct one (or document exceptions).
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare binaries lists across src/lib/messaging/channels/*/policy/hermes.yaml — Slack/Teams/WeChat have Hermes binary, Telegram/Discord/WhatsApp do not.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts asserting all Hermes channel policies include canonical HERMES_AGENT_BINARIES.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Slack Hermes: /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python. Teams Hermes: same. WeChat Hermes: same. Telegram Hermes: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python (missing hermes). Discord Hermes: same as Telegram. WhatsApp Hermes: /usr/local/bin/node, /usr/bin/node (only Node).

PRA-17 Improvement — Channel policy YAML files added to npm package files array — verify intentional

  • Location: package.json:109
  • Category: correctness
  • Problem: Channel policy YAML files added to npm package files array: 'src/lib/messaging/channels/**/policy/*.{yaml,yml}'. Need to verify this is intentional — these files are read at runtime via fs.readFileSync, so they must be published.
  • Impact: If files are not published, runtime preset loading will fail. If they are only used at build/validate time, they should be removed from files array.
  • Suggested action: Confirm channel policy YAML files are read at runtime (they are — via loadMessagingChannelPolicyPreset). If so, keep in files array. If only used at build time, remove.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check package.json files array and src/lib/messaging/channels/policy.ts loadMessagingChannelPolicyPreset — uses fs.readFileSync at runtime.
  • Missing regression test: No test needed; verify files array matches runtime requirements.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: package.json files array includes 'src/lib/messaging/channels/**/policy/*.{yaml,yml}'. policy.ts loadMessagingChannelPolicyPreset reads files via fs.readFileSync at runtime.
Simplification opportunities: 5 possible cuts, net -520 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-8 shrink (src/lib/policy/index.ts:1): Preset loading/merging/validation logic (listPresets, loadPreset, loadPresetForSandbox, loadPresetForAgent, mergePresetIntoPolicy, mergePresetNamesIntoPolicy, extractPresetEntries, parsePresetPolicyKeys, selectAgentPolicyKeys, loadAgentPresetContent, getPresetEndpoints, getPresetValidationWarning, setupPolicyPresetSupported, filterSetupPolicyPresets, listSetupPolicyPresets, clampSetupPolicyPresetNames)
    • Replacement: New module src/lib/policy/presets.ts exporting same functions; index.ts imports and re-exports
    • Net: -400 lines
    • Safety boundary: Must not simplify away: credential redaction (networkPoliciesHasAllowedIps), SSRF/sandbox/network-policy defenses (allowed_ips guard), trust-boundary validation (HOST_GATEWAY_BRIDGE_HOST), data-loss prevention (fail-closed policy merge), required regression tests
  • PRA-10 native (src/lib/messaging/channels/policy.ts:45): isSafeId function and its regex
    • Replacement: Import and use ChannelManifest ID validation from manifest.ts (or shared validation module)
    • Net: -10 lines
    • Safety boundary: Must not weaken path traversal defense — any replacement must reject '../', absolute paths, null bytes, URL-encoded traversal
  • PRA-16 shrink (src/lib/messaging/channels/*/policy/*.yaml:1): Repeated binaries arrays in 12 channel policy YAML files
    • Replacement: Shared constants in src/lib/policy/agent-binaries.ts (or similar) referenced via YAML anchors or build-time generation
    • Net: -50 lines
    • Safety boundary: Must not weaken binary allowlist validation — each channel policy must still explicitly declare its allowlist (or inherit via build-time expansion) so schema validation and runtime behavior are preserved
  • PRA-18 shrink (src/lib/actions/sandbox/policy-channel-list.test.ts:185): Duplicated POLICY_PRESETS fixture arrays in policy-channel-list.test.ts and policy-channel-policy.test.ts
    • Replacement: Import from shared test/fixtures/policy-presets.ts
    • Net: -30 lines
    • Safety boundary: Must not change test behavior — fixture content identical, only deduplication
  • PRA-19 shrink (src/lib/actions/sandbox/policy-channel-policy.test.ts:241): Duplicated POLICY_PRESETS fixture array
    • Replacement: Import from shared test/fixtures/policy-presets.ts
    • Net: -30 lines
    • Safety boundary: Must not change test behavior — fixture content identical, only deduplication
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — rejects a custom preset with a messaging policy key on a terminal-runtime agent before any disclosure, prompt, or apply. Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/policy-additions.yaml, ci/platform-matrix.json, ci/test-file-size-budget.json, docs/network-policy/customize-network-policy.mdx, docs/network-policy/integration-policy-examples.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/network-policies.mdx, docs/reference/platform-support.mdx. Static tests cover new unit behavior but binary allowlist regressions and custom preset agent gate require runtime validation in contract/E2E tests.
  • PRA-T2 Runtime validation — validates Hermes Telegram policy binaries include /usr/local/bin/hermes. Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/policy-additions.yaml, ci/platform-matrix.json, ci/test-file-size-budget.json, docs/network-policy/customize-network-policy.mdx, docs/network-policy/integration-policy-examples.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/network-policies.mdx, docs/reference/platform-support.mdx. Static tests cover new unit behavior but binary allowlist regressions and custom preset agent gate require runtime validation in contract/E2E tests.
  • PRA-T3 Runtime validation — validates Hermes Discord policy binaries include /usr/local/bin/hermes. Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/policy-additions.yaml, ci/platform-matrix.json, ci/test-file-size-budget.json, docs/network-policy/customize-network-policy.mdx, docs/network-policy/integration-policy-examples.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/network-policies.mdx, docs/reference/platform-support.mdx. Static tests cover new unit behavior but binary allowlist regressions and custom preset agent gate require runtime validation in contract/E2E tests.
  • PRA-T4 Runtime validation — validates Hermes WhatsApp policy binary allowlist matches actual bridge runtime. Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/policy-additions.yaml, ci/platform-matrix.json, ci/test-file-size-budget.json, docs/network-policy/customize-network-policy.mdx, docs/network-policy/integration-policy-examples.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/network-policies.mdx, docs/reference/platform-support.mdx. Static tests cover new unit behavior but binary allowlist regressions and custom preset agent gate require runtime validation in contract/E2E tests.
  • PRA-T5 Runtime validation — validates all Hermes channel policies include canonical HERMES_AGENT_BINARIES. Runtime/sandbox/infrastructure paths need behavioral runtime validation: agents/hermes/policy-additions.yaml, ci/platform-matrix.json, ci/test-file-size-budget.json, docs/network-policy/customize-network-policy.mdx, docs/network-policy/integration-policy-examples.mdx, docs/reference/commands-nemohermes.mdx, docs/reference/commands.mdx, docs/reference/network-policies.mdx, docs/reference/platform-support.mdx. Static tests cover new unit behavior but binary allowlist regressions and custom preset agent gate require runtime validation in contract/E2E tests.
  • PRA-T6 No binary allowlist validation for any Hermes channel policy in new contract test — Add parameterized test cases for each Hermes channel policy validating: (1) binary allowlist matches expected runtime, (2) WebSocket credential rewrite where applicable, (3) request_body_credential_rewrite for REST endpoints with credentials.
  • PRA-T7 Path traversal test only covers '../' pattern — Add additional path traversal test cases: absolute paths (/etc/passwd), null bytes, URL-encoded traversal (%2e%2e%2f), double-encoded traversal.
  • PRA-T8 E2E test only validates Hermes Slack policy preservation at sandbox create — Add parameterized test cases for each Hermes channel reusing existing mock pattern. At minimum add tests for Discord and Teams (which have WebSocket credential rewrite).
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: src/lib/onboard/initial-policy.ts:238

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Parameterized test: both agents with same activeChannels
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Hermes uses allMessagingChannelPolicyPresets, OpenClaw uses requiredMessagingChannelPolicyPresets; no comment explaining why

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/*/policy/*.yaml (12 files)

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: Test: all Hermes policies include HERMES_AGENT_BINARIES
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Slack/Teams/WeChat Hermes have hermes binary; Telegram/Discord/WhatsApp do not

PRA-3 Required — Telegram Hermes policy missing /usr/local/bin/hermes binary allowlist

  • Location: src/lib/messaging/channels/telegram/policy/hermes.yaml:20
  • Category: security
  • Problem: Telegram Hermes policy binaries list contains /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python but omits /usr/local/bin/hermes. Hermes agent binary is /usr/local/bin/hermes (per agents/hermes/manifest.yaml). If the Telegram bridge runs under the Hermes Python process, all egress to api.telegram.org will be blocked by OpenShell L7 proxy.
  • Impact: Hermes Telegram bridge cannot reach api.telegram.org — all bot API calls fail closed, breaking Telegram messaging for Hermes sandboxes.
  • Required action: Add /usr/local/bin/hermes to binaries list. Audit whether /usr/local/bin/node is actually needed (remove if bridge is Python-only).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/telegram/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts validating Hermes Telegram policy binaries include /usr/local/bin/hermes and exclude /usr/local/bin/node if bridge is Python-only.
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/telegram/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Evidence: Telegram Hermes policy at line 18-21 shows binaries: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python. No Hermes binary. Contrast with Slack Hermes policy which uses /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python.

PRA-4 Required — Discord Hermes policy missing /usr/local/bin/hermes binary allowlist

  • Location: src/lib/messaging/channels/discord/policy/hermes.yaml:42
  • Category: security
  • Problem: Discord Hermes policy binaries list contains /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python but omits /usr/local/bin/hermes. Discord Hermes bridge uses WebSocket gateway (gateway.discord.gg) with websocket_credential_rewrite which requires the Hermes Python process.
  • Impact: Hermes Discord bridge cannot reach gateway.discord.gg or discord.com REST endpoints — all Discord messaging fails for Hermes sandboxes.
  • Required action: Add /usr/local/bin/hermes to binaries list. Audit Discord Hermes bridge implementation language; remove Node if bridge is Python-only.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/discord/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts validating Hermes Discord policy binaries include /usr/local/bin/hermes.
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/discord/policy/hermes.yaml — should include /usr/local/bin/hermes like Slack/Teams/WeChat Hermes policies.
  • Evidence: Discord Hermes policy at line 40-42 shows binaries: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python. No Hermes binary. Contrast with Slack Hermes policy which uses /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python.

PRA-5 Required — WhatsApp Hermes policy declares only Node binaries, no Python/Hermes

  • Location: src/lib/messaging/channels/whatsapp/policy/hermes.yaml:44
  • Category: security
  • Problem: WhatsApp Hermes policy declares only /usr/local/bin/node and /usr/bin/node as allowed binaries. Hermes is a Python agent (binary_path: /usr/local/bin/hermes). If the WhatsApp bridge runs under Hermes/Python, all WhatsApp traffic (web.whatsapp.com, *.whatsapp.net, raw.githubusercontent.com for Baileys version fetch) will be blocked.
  • Impact: Hermes WhatsApp bridge cannot reach WhatsApp Web endpoints — pairing and messaging fail completely for Hermes sandboxes.
  • Required action: Determine actual runtime of Hermes WhatsApp bridge. If Python/Hermes-based, add /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python. If Node-only (Baileys), add comment documenting why and add test asserting Node-only.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check binaries list in src/lib/messaging/channels/whatsapp/policy/hermes.yaml — should include Hermes/Python paths if bridge is Python-based. Search Hermes agent code for 'whatsapp' bridge entrypoint.
  • Missing regression test: Add test validating Hermes WhatsApp policy binary allowlist matches actual bridge runtime (Node-only or Python/Hermes).
  • Done when: The required change is committed and verification passes: Check binaries list in src/lib/messaging/channels/whatsapp/policy/hermes.yaml — should include Hermes/Python paths if bridge is Python-based. Search Hermes agent code for 'whatsapp' bridge entrypoint.
  • Evidence: WhatsApp Hermes policy at line 44 shows binaries: /usr/local/bin/node, /usr/bin/node. No Hermes or Python binaries. All other Hermes channel policies (Slack, Teams, WeChat) include /usr/local/bin/hermes and Python paths.

PRA-6 Required — No binary allowlist validation for any Hermes channel policy in new contract test

  • Location: test/policy-channel-yaml-contract.test.ts:1
  • Category: tests
  • Problem: New test file test/policy-channel-yaml-contract.test.ts validates Slack/Discord WebSocket credential rewrite and Discord REST mutation scoping, but does not validate binary allowlists for ANY Hermes channel policy. Four of six Hermes channel policies (Telegram, Discord, WhatsApp, Teams) lack binary allowlist tests.
  • Impact: Binary allowlist regressions (like the three missing /usr/local/bin/hermes entries above) will not be caught by CI.
  • Required action: Add parameterized test cases for each Hermes channel policy validating: (1) binary allowlist matches expected runtime, (2) WebSocket credential rewrite where applicable, (3) request_body_credential_rewrite for REST endpoints with credentials.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Run test/policy-channel-yaml-contract.test.ts — currently passes but does not assert binary allowlists.
  • Missing regression test: Add binary allowlist assertions for all 6 Hermes channel policies in test/policy-channel-yaml-contract.test.ts.
  • Done when: The required change is committed and verification passes: Run test/policy-channel-yaml-contract.test.ts — currently passes but does not assert binary allowlists.
  • Evidence: test/policy-channel-yaml-contract.test.ts has 4 test blocks: Slack REST credential rewrite, Hermes messaging gateway inspected WebSocket, Hermes Discord REST mutations scoped, ships policy file for every manifest-supported agent. Zero binary allowlist assertions.

PRA-7 Required — Custom preset (--from-file) agent gate not tested for Deep Agents

  • Location: src/lib/actions/sandbox/policy-channel-policy.test.ts:247
  • Category: acceptance
  • Problem: Custom preset (--from-file) agent gate not tested for Deep Agents. The previous test file policy-add-agent-gate.test.ts was deleted; the new policy-channel-policy.test.ts tests built-in preset rejection but has no test for custom preset file rejection on terminal-runtime agents.
  • Impact: A custom preset with a messaging policy key (e.g., telegram_bot) could bypass the agent gate on DeepAgents if --from-file path is not guarded.
  • Required action: Add test in policy-channel-policy.test.ts for custom preset rejection on Deep Agents with messaging policy key, mirroring the built-in preset test pattern.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search src/lib/actions/sandbox/policy-channel-policy.test.ts for 'fromFile' or 'custom preset' — no such test exists.
  • Missing regression test: Add test: 'rejects a custom preset with a messaging policy key on a terminal-runtime agent before any disclosure, prompt, or apply'.
  • Done when: The required change is committed and verification passes: Search src/lib/actions/sandbox/policy-channel-policy.test.ts for 'fromFile' or 'custom preset' — no such test exists.
  • Evidence: Deleted policy-add-agent-gate.test.ts had 'describe("addSandboxPolicy custom preset (--from-file) agent gate")' with 6 test cases. New policy-channel-policy.test.ts has no fromFile/custom preset tests for DeepAgents.

PRA-8 Required — src/lib/policy/index.ts monolith grew 71 lines (1459 total) — extract preset helpers

  • Location: src/lib/policy/index.ts:1
  • Category: correctness
  • Problem: src/lib/policy/index.ts grew by 71 lines (from 1388 to 1459) in this PR. The file is now a 1460-line monolith handling preset loading, merging, validation, gateway interaction, and custom preset persistence.
  • Impact: Monolith growth makes security review harder, increases coupling, and prevents extraction of policy preset loading/merging helpers into a dedicated module.
  • Required action: Extract policy preset loading/merging helpers into src/lib/policy/presets.ts or similar to offset growth. At minimum, justify why new functions couldn't be extracted.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check line count of src/lib/policy/index.ts — currently ~1460 lines.
  • Missing regression test: No automated check; architecture review needed.
  • Done when: The required change is committed and verification passes: Check line count of src/lib/policy/index.ts — currently ~1460 lines.
  • Evidence: driftContext.monolithDeltas shows src/lib/policy/index.ts delta +71 severity blocker. File handles listPresets, loadPreset, loadPresetForSandbox, loadPresetForAgent, mergePresetIntoPolicy, mergePresetNamesIntoPolicy, applyPreset, applyPresetContent, applyPresets, removePreset, getGatewayPresets, etc.

PRA-9 Resolve/justify — Channel policy directory discovery swallows ENOENT/ENOTDIR silently

  • Location: scripts/validate-configs.ts:137
  • Category: architecture
  • Problem: Channel policy directory discovery uses try/catch that swallows ENOENT/ENOTDIR. If the channel policy directory structure is broken (e.g., permission denied), validation passes silently.
  • Impact: Silent validation gaps when channel policy directories exist but cannot be read. Missing channel policy directories (e.g., a new channel added without policy files) produce no warning.
  • Recommended action: Add explicit logging when channel policy discovery finds zero files for a known channel, or propagate unexpected errors instead of catching all ENOENT/ENOTDIR.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check scripts/validate-configs.ts walkChannelPolicies catch block — only throws on non-ENOENT/ENOTDIR errors.
  • Missing regression test: Add test simulating permission error on channel policy directory — validation should fail or warn loudly.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check scripts/validate-configs.ts walkChannelPolicies catch block — only throws on non-ENOENT/ENOTDIR errors.
  • Evidence: scripts/validate-configs.ts:137 catch block: `if (code !== "ENOENT" && code !== "ENOTDIR") throw err;` — all ENOENT/ENOTDIR silently ignored.

PRA-10 Resolve/justify — isSafeId regex duplicates manifest ID validation — single source of truth needed

  • Location: src/lib/messaging/channels/policy.ts:45
  • Category: architecture
  • Problem: isSafeId regex /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/ may reject valid future channel IDs. ChannelManifest IDs in manifest.ts may allow different characters. The regex is a localized workaround for path traversal that duplicates validation logic.
  • Impact: Future channel IDs with valid characters (e.g., underscores, uppercase) would be rejected at preset resolution time without a clear migration path. Divergence between manifest ID validation and preset resolution could allow or reject IDs inconsistently.
  • Recommended action: Either align regex with ChannelManifest ID validation in manifest.ts, or document the restriction and ensure manifest IDs conform. Add test for edge cases.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare isSafeId regex with ChannelManifest ID validation in src/lib/messaging/channels/manifest.ts.
  • Missing regression test: Add test for isSafeId with edge cases matching manifest ID validation. Add test ensuring all manifest IDs pass isSafeId.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare isSafeId regex with ChannelManifest ID validation in src/lib/messaging/channels/manifest.ts.
  • Evidence: src/lib/messaging/channels/policy.ts:45 defines isSafeId. Channel IDs used in channelPolicyPath() for filesystem access. Manifest IDs defined in channel manifest files.

PRA-11 Resolve/justify — Hermes vs OpenClaw create-time preset logic diverges without documentation

  • Location: src/lib/onboard/initial-policy.ts:238
  • Category: architecture
  • Problem: Hermes uses allMessagingChannelPolicyPresets (all active channels), OpenClaw uses requiredMessagingChannelPolicyPresets (subset). The reason for this divergence is not documented.
  • Impact: Future maintainers may incorrectly unify or diverge further. Test coverage for both paths exists but the design rationale is opaque.
  • Recommended action: Document why Hermes uses all vs required. Add test verifying create-time policy matches expected presets for both agents given same activeChannels input.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read src/lib/onboard/initial-policy.ts around line 238 and messaging-policy-presets.ts for allMessagingChannelPolicyPresets vs requiredMessagingChannelPolicyPresets.
  • Missing regression test: Add parameterized test in initial-policy-real-policy.test.ts verifying create-time presets for both agents with identical activeChannels.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read src/lib/onboard/initial-policy.ts around line 238 and messaging-policy-presets.ts for allMessagingChannelPolicyPresets vs requiredMessagingChannelPolicyPresets.
  • Evidence: initial-policy.ts:238 calls allMessagingChannelPolicyPresets(activeMessagingChannels) for Hermes, requiredMessagingChannelPolicyPresets(activeMessagingChannels) for OpenClaw. No comment explaining why.

PRA-12 Resolve/justify — Schema allows websocket protocol without requiring websocket_credential_rewrite

  • Location: schemas/policy-preset.schema.json:1
  • Category: security
  • Problem: Schema allows websocket protocol without requiring websocket_credential_rewrite. Discord/Slack Hermes policies set websocket_credential_rewrite: true on gateway endpoints, but the schema does not enforce this coupling.
  • Impact: A preset author could declare a websocket endpoint without credential rewrite, allowing unvalidated WebSocket connections that bypass L7 token injection.
  • Recommended action: Add AJV custom keyword or post-validation check: if protocol=websocket and rules exist, websocket_credential_rewrite must be true. Test with fixture missing the field.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check schemas/policy-preset.schema.json — endpoint definition has websocket_credential_rewrite as optional boolean with no conditional requirement.
  • Missing regression test: Add schema validation test with websocket endpoint missing websocket_credential_rewrite — should fail.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check schemas/policy-preset.schema.json — endpoint definition has websocket_credential_rewrite as optional boolean with no conditional requirement.
  • Evidence: schemas/policy-preset.schema.json endpoint definition: websocket_credential_rewrite is type boolean, optional. No 'if/then' requiring it when protocol=websocket.

PRA-13 Resolve/justify — Path traversal test only covers '../' pattern

  • Location: src/lib/messaging/channels/policy.test.ts:1
  • Category: tests
  • Problem: Path traversal test only covers '../' pattern. Does not test absolute paths (/etc/passwd), null bytes, URL-encoded traversal, double-encoded traversal, or Unicode normalization bypasses.
  • Impact: Path traversal via other vectors could bypass the isSafeId check if channelId comes from untrusted metadata.
  • Recommended action: Add additional path traversal test cases: absolute paths (/etc/passwd), null bytes, URL-encoded traversal (%2e%2e%2f), double-encoded traversal.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check src/lib/messaging/channels/policy.test.ts 'rejects path traversal channel ids from preset metadata' test — only tests '../telegram'.
  • Missing regression test: Add test cases for absolute paths, null bytes, URL-encoded, double-encoded traversal patterns.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check src/lib/messaging/channels/policy.test.ts 'rejects path traversal channel ids from preset metadata' test — only tests '../telegram'.
  • Evidence: policy.test.ts line 106-111: only tests channelId: '../telegram'. No other traversal vectors tested.

PRA-14 Resolve/justify — E2E test only validates Hermes Slack policy preservation at sandbox create

  • Location: test/onboard-messaging.test.ts:1
  • Category: tests
  • Problem: E2E test only validates Hermes Slack policy preservation at sandbox create. Other Hermes channels (Discord, Telegram, Teams, WhatsApp, WeChat) are not covered.
  • Impact: Regression in policy preservation for other channels would not be caught.
  • Recommended action: Add parameterized test cases for each Hermes channel reusing existing mock pattern. At minimum add tests for Discord and Teams (which have WebSocket credential rewrite).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read test/onboard-messaging.test.ts — only Slack is tested for Hermes.
  • Missing regression test: Add parameterized test for each Hermes channel in test/onboard-messaging.test.ts.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read test/onboard-messaging.test.ts — only Slack is tested for Hermes.
  • Evidence: test/onboard-messaging.test.ts tests Hermes Slack preservation. No test for Discord, Teams, Telegram, WhatsApp, WeChat.

PRA-15 Resolve/justify — Initial policy create-time only tests Discord/Slack for Hermes

  • Location: src/lib/onboard/initial-policy-real-policy.test.ts:1
  • Category: tests
  • Problem: Initial policy create-time only tests Discord/Slack for Hermes. Other channels (Telegram, Teams, WhatsApp, WeChat) not verified.
  • Impact: Incomplete test coverage for the Hermes vs OpenClaw divergence. Other channels unverified.
  • Recommended action: Extend initial-policy-real-policy.test.ts to cover all messaging channels for both agents.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check src/lib/onboard/initial-policy-real-policy.test.ts — only tests Discord/Slack for Hermes.
  • Missing regression test: Add parameterized test cases for each Hermes channel in initial-policy-real-policy.test.ts.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check src/lib/onboard/initial-policy-real-policy.test.ts — only tests Discord/Slack for Hermes.
  • Evidence: initial-policy-real-policy.test.ts has single test: 'uses Hermes channel YAML when the Hermes base policy path implies the agent' — only checks slack and discord binaries/rules.

PRA-16 Improvement — Binary allowlists duplicated across 12 policy files with no single source of truth

  • Location: src/lib/messaging/channels//policy/.yaml:1
  • Category: architecture
  • Problem: Binary allowlists duplicated across 12 policy files (6 channels × 2 agents) with no single source of truth. Hermes policies should share a canonical HERMES_AGENT_BINARIES = ['/usr/local/bin/hermes', '/usr/bin/python3*', '/opt/hermes/.venv/bin/python'] but each file repeats it.
  • Impact: Inconsistencies like the three missing /usr/local/bin/hermes entries are inevitable without a shared constant. Maintenance burden grows with each new channel.
  • Suggested action: Define canonical binary allowlists per agent (e.g., HERMES_AGENT_BINARIES, OPENCLAW_AGENT_BINARIES) in a shared module and test that all channel policies include the correct one (or document exceptions).
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare binaries lists across src/lib/messaging/channels/*/policy/hermes.yaml — Slack/Teams/WeChat have Hermes binary, Telegram/Discord/WhatsApp do not.
  • Missing regression test: Add test in test/policy-channel-yaml-contract.test.ts asserting all Hermes channel policies include canonical HERMES_AGENT_BINARIES.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Slack Hermes: /usr/local/bin/hermes, /usr/bin/python3*, /opt/hermes/.venv/bin/python. Teams Hermes: same. WeChat Hermes: same. Telegram Hermes: /usr/local/bin/node, /usr/bin/python3*, /opt/hermes/.venv/bin/python (missing hermes). Discord Hermes: same as Telegram. WhatsApp Hermes: /usr/local/bin/node, /usr/bin/node (only Node).

PRA-17 Improvement — Channel policy YAML files added to npm package files array — verify intentional

  • Location: package.json:109
  • Category: correctness
  • Problem: Channel policy YAML files added to npm package files array: 'src/lib/messaging/channels/**/policy/*.{yaml,yml}'. Need to verify this is intentional — these files are read at runtime via fs.readFileSync, so they must be published.
  • Impact: If files are not published, runtime preset loading will fail. If they are only used at build/validate time, they should be removed from files array.
  • Suggested action: Confirm channel policy YAML files are read at runtime (they are — via loadMessagingChannelPolicyPreset). If so, keep in files array. If only used at build time, remove.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check package.json files array and src/lib/messaging/channels/policy.ts loadMessagingChannelPolicyPreset — uses fs.readFileSync at runtime.
  • Missing regression test: No test needed; verify files array matches runtime requirements.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: package.json files array includes 'src/lib/messaging/channels/**/policy/*.{yaml,yml}'. policy.ts loadMessagingChannelPolicyPreset reads files via fs.readFileSync at runtime.

PRA-18 Resolve/justify — Test scaffold duplication — POLICY_PRESETS fixture repeated across test files

  • Location: src/lib/actions/sandbox/policy-channel-list.test.ts:185
  • Category: tests
  • Problem: POLICY_PRESETS fixture duplicated in policy-channel-list.test.ts and policy-channel-policy.test.ts. Shared test helper would reduce maintenance burden.
  • Impact: Fixture changes require updates in multiple files. Inconsistency risk if one copy is updated and another is not.
  • Recommended action: Extract POLICY_PRESETS fixture to shared test helper (e.g., test/fixtures/policy-presets.ts) and import in both test files.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare policy-channel-list.test.ts:20-30 and policy-channel-policy.test.ts:50-60 — identical POLICY_PRESETS arrays.
  • Missing regression test: No regression test needed; refactor verification via existing tests.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare policy-channel-list.test.ts:20-30 and policy-channel-policy.test.ts:50-60 — identical POLICY_PRESETS arrays.
  • Evidence: Both files define identical POLICY_PRESETS: npm, pypi, discord, openclaw-pricing, nous-web, nous-code, telegram, wechat.

PRA-19 Resolve/justify — Test scaffold duplication — POLICY_PRESETS fixture repeated

  • Location: src/lib/actions/sandbox/policy-channel-policy.test.ts:241
  • Category: tests
  • Problem: Same as above — POLICY_PRESETS fixture duplicated in policy-channel-policy.test.ts.
  • Impact: Same as above.
  • Recommended action: Same as above.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Same as above.
  • Missing regression test: Same as above.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Same as above.
  • Evidence: Same as above.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: network-policy, cloud-onboard, onboard-resume, onboard-repair, channels-add-remove, messaging-providers, hermes-e2e, hermes-slack, hermes-discord
Optional E2E: openclaw-slack-pairing, openclaw-discord-pairing, rebuild-hermes, rebuild-openclaw, docs-validation

Dispatch hint: network-policy,cloud-onboard,onboard-resume,onboard-repair,channels-add-remove,messaging-providers,hermes-e2e,hermes-slack,hermes-discord

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • network-policy (high): Required because the PR changes policy preset loading, live policy-add/list behavior, and sandbox egress rules. This job onboards a real sandbox, mutates live OpenShell policy through the CLI, verifies policy-list state, and probes deny-by-default and allowed egress.
  • cloud-onboard (high): Required because initial-policy and policy-selection changes can affect full hosted onboarding and which presets are applied at sandbox creation.
  • onboard-resume (high): Required under the onboarding resume rule because the PR changes policy resume selection/state handling. Unit tests are not sufficient for this state-machine resume path.
  • onboard-repair (high): Required under the onboarding resume rule because policy resume/repair choices can affect repaired onboarding state and applied presets.
  • channels-add-remove (high): Required because channel policy resolution now uses per-agent channel policy files. This job exercises adding a messaging channel after onboarding, rebuilding, checking registry/gateway/policy state, and removing it.
  • messaging-providers (high): Required because the PR changes messaging policy assets and agent-scoped preset availability. This job validates provider creation, credential isolation, policy behavior, and L7 proxy token rewriting for messaging channels.
  • hermes-e2e (high): Required because the Hermes baseline policy changed substantially. This job proves a real Hermes hosted sandbox still onboards, routes inference, and exposes a valid OpenShell policy after the baseline messaging-policy removal.
  • hermes-slack (high): Required because Hermes Slack policy moved from the Hermes baseline to src/lib/messaging/channels/slack/policy/hermes.yaml. This job explicitly asserts the Hermes-scoped Slack policy block, binaries, credential rewrite flags, and live Slack egress behavior.
  • hermes-discord (high): Required because Hermes Discord policy moved into a channel-specific policy file and includes websocket/credential-rewrite behavior. This job validates Hermes Discord config, credential isolation, gateway rewrite, policy update, and rebuild reuse.

Optional E2E

  • openclaw-slack-pairing (high): Useful adjacent confidence for OpenClaw Slack real assistant pairing after OpenClaw Slack policy moved into a per-channel policy YAML.
  • openclaw-discord-pairing (high): Useful adjacent confidence for OpenClaw Discord pairing and gateway behavior after OpenClaw Discord policy moved into a per-channel policy YAML.
  • rebuild-hermes (high): Useful to prove Hermes policy/channel metadata survives sandbox rebuilds after moving channel policies out of the Hermes baseline and into packaged per-channel assets.
  • rebuild-openclaw (high): Useful to prove OpenClaw policy preset metadata and applied policy state survive rebuild after the preset discovery and packaging changes.
  • docs-validation (medium): Optional because docs and platform matrix claims changed for network-policy and messaging behavior; this validates the broader docs boundary beyond the focused PR docs checks.

New E2E recommendations

  • agent-scoped-channel-policy-matrix (high): Existing live coverage directly exercises Telegram add/remove and Hermes Slack/Discord, but the PR changes policy YAML for Teams, WeChat, and WhatsApp as well. Add a matrix-style live or semi-live E2E that proves policy-list/policy-add availability and unknown-preset rejection for every built-in messaging channel across OpenClaw, Hermes, and unsupported terminal agents without requiring real external sends for every provider.
    • Suggested test: agent-scoped-channel-policy-matrix-e2e
  • published-package-policy-assets (medium): The PR relies on package.json including src/lib/messaging/channels/**/policy/*.yaml. Existing source-based E2Es may not prove that an npm-packed or installed artifact contains those YAML files and can discover/apply them at runtime.
    • Suggested test: npm-packed-channel-policy-assets-e2e
  • hermes-non-slack-discord-messaging-policy (medium): Hermes Slack and Discord have dedicated live jobs, but Hermes Telegram, Teams, WeChat, and WhatsApp policy files are new or moved without equivalent live egress/policy assertions.
    • Suggested test: hermes-channel-policy-egress-matrix-e2e

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: network-policy,cloud-onboard,onboard-resume,onboard-repair,channels-add-remove,messaging-providers,hermes-e2e,hermes-slack,hermes-discord

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: network-policy, channels-stop-start, onboard-resume, onboard-repair, ubuntu-repo-cloud-langchain-deepagents-code
Optional E2E targets: hermes-slack, hermes-discord

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=network-policy
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-stop-start
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field targets=ubuntu-repo-cloud-langchain-deepagents-code

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • network-policy: Policy preset discovery, validation, policy-add/list behavior, and channel-scoped preset loading changed; the free-standing network-policy job exercises live policy allow/deny and policy mutation contracts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=network-policy
  • channels-stop-start: Messaging channel policy YAMLs were moved/scoped per agent and channel registry policy behavior changed; this job runs OpenClaw and Hermes channel stop/start, rebuild, registry, policy-list, and in-sandbox config contracts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=channels-stop-start
  • onboard-resume: Changes under src/lib/onboard policy resume/initial-policy selection affect persisted onboarding policy state, so the onboarding resume live job is required.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • onboard-repair: Policy resume/selection changes can affect repair/backstop execution from persisted onboarding sessions; repair is required alongside resume for this state path.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • ubuntu-repo-cloud-langchain-deepagents-code: Agent-scoped messaging policy changes and unsupported-channel preset behavior affect terminal agents; this live-supported typed target exercises the Deep Agents Code policy surface.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field targets=ubuntu-repo-cloud-langchain-deepagents-code

Optional E2E targets

  • hermes-slack: Adjacent Hermes-specific coverage for Slack policy, placeholder, secret-boundary, and Python Slack egress contracts after changes to Hermes channel policy YAMLs.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-slack
  • hermes-discord: Adjacent Hermes-specific coverage for Discord schema, provider, placeholder isolation, gateway rewrite, and rebuild contracts after changes to Hermes channel policy YAMLs.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=hermes-discord

Relevant changed files

  • agents/hermes/policy-additions.yaml
  • package.json
  • schemas/policy-preset.schema.json
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/messaging/channels/discord/policy/hermes.yaml
  • src/lib/messaging/channels/discord/policy/openclaw.yaml
  • src/lib/messaging/channels/index.ts
  • src/lib/messaging/channels/policy.ts
  • src/lib/messaging/channels/slack/policy/hermes.yaml
  • src/lib/messaging/channels/slack/policy/openclaw.yaml
  • src/lib/messaging/channels/teams/policy/hermes.yaml
  • src/lib/messaging/channels/teams/policy/openclaw.yaml
  • src/lib/messaging/channels/telegram/policy/hermes.yaml
  • src/lib/messaging/channels/telegram/policy/openclaw.yaml
  • src/lib/messaging/channels/wechat/policy/hermes.yaml
  • src/lib/messaging/channels/wechat/policy/openclaw.yaml
  • src/lib/messaging/channels/whatsapp/policy/hermes.yaml
  • src/lib/messaging/channels/whatsapp/policy/openclaw.yaml
  • src/lib/onboard/initial-policy.ts
  • src/lib/onboard/policy-resume-selection.ts
  • src/lib/onboard/policy-selection.ts
  • src/lib/policy/context.ts
  • src/lib/policy/index.ts

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-3: Deep Agents messaging policy-add now reports unknown instead of the required unsupported-agent error; then add or justify PRA-T1.
Open items: 1 required · 6 warnings · 0 suggestions · 8 test follow-ups
Since last review: 0 prior items resolved · 5 still apply · 1 new item found

Action checklist

  • PRA-3 Fix: Deep Agents messaging policy-add now reports unknown instead of the required unsupported-agent error in docs/reference/commands.mdx:1135
  • PRA-1 Resolve or justify: Source-of-truth review needed: Custom preset messaging policy-key handling on terminal-runtime agents
  • PRA-2 Resolve or justify: Source-of-truth review needed: Policy context preset catalog for sandbox agents
  • PRA-4 Resolve or justify: Custom messaging-shaped presets still bypass the terminal-runtime agent boundary in src/lib/actions/sandbox/policy-channel.ts:220
  • PRA-5 Resolve or justify: Policy context still uses the OpenClaw default catalog for terminal-runtime agents in src/lib/policy/context.ts:138
  • PRA-6 Resolve or justify: OpenClaw Discord policy grants broad PUT/PATCH over discord.com in src/lib/messaging/channels/discord/policy/openclaw.yaml:19
  • PRA-7 Resolve or justify: Policy monolith grew while absorbing sandbox-aware channel preset resolution in src/lib/policy/index.ts
  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Acceptance clause
  • PRA-T7 Add or justify test follow-up: Acceptance clause
  • PRA-T8 Add or justify test follow-up: Acceptance clause

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Required acceptance docs/reference/commands.mdx:1135 Change the `policy-add` built-in preset path so known messaging channel preset names on unsupported agents fail with explicit unsupported-agent wording before loading endpoint details or prompting. Update `docs/reference/commands.mdx`, `docs/reference/commands-nemohermes.mdx`, and `docs/network-policy/integration-policy-examples.mdx` to describe that contract instead of unknown-preset behavior.
PRA-4 Resolve/justify security src/lib/actions/sandbox/policy-channel.ts:220 Decide and encode the source-of-truth boundary in this PR. Either reject custom presets containing known messaging policy keys for unsupported agents before endpoint preview/apply, or explicitly document and test that operator-authored custom presets are exempt while built-in messaging channel presets remain agent-scoped.
PRA-5 Resolve/justify correctness src/lib/policy/context.ts:138 Pass the sandbox's recorded agent into `listPresets({ agent: ... })` when building policy context, and keep custom presets appended separately. Ensure unsupported messaging presets are absent from `knownUnappliedPresets` for `langchain-deepagents-code` while central presets such as npm/pypi remain visible.
PRA-6 Resolve/justify security src/lib/messaging/channels/discord/policy/openclaw.yaml:19 Narrow the OpenClaw Discord `PUT` and `PATCH` rules to the concrete API paths OpenClaw actually uses, or add an inline YAML rationale plus a focused contract test documenting why OpenClaw requires broad `PUT /**` and `PATCH /**` while Hermes does not.
PRA-7 Resolve/justify architecture src/lib/policy/index.ts Move the sandbox-aware built-in preset listing/loading glue into a small helper module, or offset the growth by extracting adjacent preset-list/load helpers from `src/lib/policy/index.ts`. Keep the mutation and validation boundaries intact.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-3 Required — Deep Agents messaging policy-add now reports unknown instead of the required unsupported-agent error

  • Location: docs/reference/commands.mdx:1135
  • Category: acceptance
  • Problem: Issue [Ubuntu 24.04][Policy&Network] Deep Agents sandbox accepts policy-add for all 5 messaging channels instead of rejecting (unsupported on terminal-runtime) #6185 requires `policy-add <messaging-channel>` on a LangChain Deep Agents Code sandbox to reject with an explicit `unsupported on terminal-runtime agent` or `not a supported channel for langchain-deepagents-code` message before endpoint disclosure or prompting. This PR instead documents and tests the standard unknown-preset path for unavailable messaging presets.
  • Impact: Users and future refactors lose the explicit terminal-runtime contract that the issue asked to enforce. The current tests can lock in the rejected behavior as generic catalog absence rather than an agent/capability denial, making support output less actionable and contradicting the linked acceptance criteria.
  • Required action: Change the `policy-add` built-in preset path so known messaging channel preset names on unsupported agents fail with explicit unsupported-agent wording before loading endpoint details or prompting. Update `docs/reference/commands.mdx`, `docs/reference/commands-nemohermes.mdx`, and `docs/network-policy/integration-policy-examples.mdx` to describe that contract instead of unknown-preset behavior.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `test/policy-channel-agent-resolution.test.ts` in the `policy-add treats unsupported Deep Agents messaging policy...` case and the policy-add sections in both command reference pages; confirm they expect `not a supported channel for agent 'langchain-deepagents-code'` or terminal-runtime wording, not `Unknown preset 'telegram'.`
  • Missing regression test: Add a source-level regression named `policy-add rejects all five Deep Agents messaging presets with explicit unsupported-agent text before endpoint preview or prompt` that loops over `telegram`, `discord`, `slack`, `wechat`, and `whatsapp`, asserts exit code 1, asserts explicit unsupported-agent wording, and asserts no `Endpoints that would be opened` or `Apply '<channel>'` prompt.
  • Done when: The required change is committed and verification passes: Read `test/policy-channel-agent-resolution.test.ts` in the `policy-add treats unsupported Deep Agents messaging policy...` case and the policy-add sections in both command reference pages; confirm they expect `not a supported channel for agent 'langchain-deepagents-code'` or terminal-runtime wording, not `Unknown preset 'telegram'.`.
  • Evidence: The linked issue says `policy-add <messaging-channel>` on Deep Agents `MUST be rejected outright with an explicit "unsupported on terminal-runtime agent" or "not a supported channel for langchain-deepagents-code" message`. The changed docs now say unavailable channel presets use the standard unknown-preset error, and `test/policy-channel-agent-resolution.test.ts` asserts `Unknown preset 'telegram'.` plus absence of `not supported for agent`.
Review findings by urgency: 1 required fix, 6 items to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: Custom preset messaging policy-key handling on terminal-runtime agents

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: No current replacement test documents either rejection or intentional allowance; the previous custom rejection coverage was deleted with `src/lib/actions/sandbox/policy-add-agent-gate.test.ts`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: `applyExternalPreset()` previews custom endpoints and calls `applyPresetContent(..., { custom })`; `applyPresetContent()` only blocks custom `allowed_ips` and does not check known messaging policy keys.

PRA-2 Resolve/justify — Source-of-truth review needed: Policy context preset catalog for sandbox agents

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: No test covers `buildPolicyContext()` for `langchain-deepagents-code` with unsupported messaging presets omitted.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: `partitionPresets()` calls `listPresets()` without options, and the messaging policy resolver defaults omitted agent to OpenClaw.

PRA-4 Resolve/justify — Custom messaging-shaped presets still bypass the terminal-runtime agent boundary

  • Location: src/lib/actions/sandbox/policy-channel.ts:220
  • Category: security
  • Problem: The built-in preset catalog is now sandbox-agent scoped, but the custom preset path still loads arbitrary YAML, previews its endpoints, and applies it through `policies.applyPresetContent(..., { custom })` without checking whether the custom `network_policies` keys are known messaging keys on an unsupported terminal-runtime agent.
  • Impact: If the intended boundary is that terminal-runtime agents cannot receive messaging channel egress, `--from-file`, `--from-dir`, snapshot restore, or other `applyPresetContent(..., { custom })` callers can reintroduce the same Telegram/Discord/Slack/WeChat/WhatsApp/Teams egress categories that the built-in gate hides. If custom operator presets are intentionally exempt, the new trust boundary is not documented or locked by tests.
  • Recommended action: Decide and encode the source-of-truth boundary in this PR. Either reject custom presets containing known messaging policy keys for unsupported agents before endpoint preview/apply, or explicitly document and test that operator-authored custom presets are exempt while built-in messaging channel presets remain agent-scoped.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare `applyExternalPreset()` in `src/lib/actions/sandbox/policy-channel.ts` with the custom branch of `applyPresetContent()` in `src/lib/policy/index.ts`; the current custom security validation blocks `allowed_ips` and reserved provider keys, but does not inspect known messaging policy keys against the sandbox agent.
  • Missing regression test: Add either `Deep Agents rejects --from-file custom preset with messaging policy keys before endpoint preview or apply` or `Deep Agents allows custom operator-authored messaging-like egress while built-in channel presets are rejected`, depending on the intended contract. The rejection version should assert no endpoint preview, no prompt, and no call to `applyPresetContent`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare `applyExternalPreset()` in `src/lib/actions/sandbox/policy-channel.ts` with the custom branch of `applyPresetContent()` in `src/lib/policy/index.ts`; the current custom security validation blocks `allowed_ips` and reserved provider keys, but does not inspect known messaging policy keys against the sandbox agent.
  • Evidence: The deleted `src/lib/actions/sandbox/policy-add-agent-gate.test.ts` previously covered custom presets containing keys such as `telegram_bot`, `discord`, `slack`, `wechat_bridge`, `whatsapp`, and `teams`. The current `applyExternalPreset()` calls `policies.loadPresetFromFile()`, prints `Endpoints that would be opened`, then calls `policies.applyPresetContent()` with `custom`.

PRA-5 Resolve/justify — Policy context still uses the OpenClaw default catalog for terminal-runtime agents

  • Location: src/lib/policy/context.ts:138
  • Category: correctness
  • Problem: `partitionPresets()` calls `listPresets()` without passing the sandbox agent, so the messaging resolver defaults to OpenClaw channel policy files. For a Deep Agents sandbox, `loadPresetForSandbox()` returns null for those messaging presets, but they can still appear as known unapplied built-ins in the rendered policy context and failure-classifier remediation.
  • Impact: Agents can be told that unsupported messaging presets are known remediation targets even though `policy-list` and `policy-add` now omit or reject them for terminal-runtime agents. That creates source-of-truth drift between the human CLI surfaces and the in-sandbox POLICY.md / classifier guidance.
  • Recommended action: Pass the sandbox's recorded agent into `listPresets({ agent: ... })` when building policy context, and keep custom presets appended separately. Ensure unsupported messaging presets are absent from `knownUnappliedPresets` for `langchain-deepagents-code` while central presets such as npm/pypi remain visible.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/policy/context.ts` around `partitionPresets()` and confirm whether it calls `listPresets({ agent: sandboxAgent })`. Then inspect `buildPolicyContext()` to ensure it obtains the same sandbox entry used for applied policies/tier before partitioning.
  • Missing regression test: Add `Deep Agents policy context omits unsupported messaging presets from knownUnappliedPresets and failure-classifier remediation`, asserting that `telegram`, `discord`, `slack`, `wechat`, and `whatsapp` are not suggested for a `langchain-deepagents-code` sandbox while non-messaging presets remain available.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/policy/context.ts` around `partitionPresets()` and confirm whether it calls `listPresets({ agent: sandboxAgent })`. Then inspect `buildPolicyContext()` to ensure it obtains the same sandbox entry used for applied policies/tier before partitioning.
  • Evidence: `src/lib/policy/context.ts:138` currently uses `const builtin = listPresets();`. `src/lib/messaging/channels/policy.ts` normalizes a null/omitted agent to `openclaw`, so an agentless catalog read includes OpenClaw messaging policy files.

PRA-6 Resolve/justify — OpenClaw Discord policy grants broad PUT/PATCH over discord.com

  • Location: src/lib/messaging/channels/discord/policy/openclaw.yaml:19
  • Category: security
  • Problem: The OpenClaw Discord channel policy allows `PUT /**` and `PATCH /**` on `discord.com`, while the Hermes Discord policy scopes mutation methods to concrete Discord API paths and the YAML contract test only enforces the narrower Hermes shape.
  • Impact: A compromised or buggy OpenClaw Node process with Discord egress can perform a much wider set of Discord mutations than the Hermes agent needs, increasing the blast radius of this policy preset and weakening least-privilege guarantees for a high-risk messaging integration.
  • Recommended action: Narrow the OpenClaw Discord `PUT` and `PATCH` rules to the concrete API paths OpenClaw actually uses, or add an inline YAML rationale plus a focused contract test documenting why OpenClaw requires broad `PUT /**` and `PATCH /**` while Hermes does not.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/messaging/channels/discord/policy/openclaw.yaml` and compare its `discord.com` rules with `src/lib/messaging/channels/discord/policy/hermes.yaml`; verify whether broad mutation paths remain and whether a test documents the OpenClaw exception.
  • Missing regression test: Add `OpenClaw Discord REST mutations are scoped to documented API paths` if narrowing, or `OpenClaw Discord broad PUT/PATCH policy is intentionally documented` if the broad rules are required, asserting the exact allowed mutation rules.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/messaging/channels/discord/policy/openclaw.yaml` and compare its `discord.com` rules with `src/lib/messaging/channels/discord/policy/hermes.yaml`; verify whether broad mutation paths remain and whether a test documents the OpenClaw exception.
  • Evidence: OpenClaw policy contains `allow: { method: PUT, path: "/**" }` and `allow: { method: PATCH, path: "/**" }`. `test/policy-channel-yaml-contract.test.ts` asserts Hermes Discord mutation rules do not include `/**`, but does not cover OpenClaw.

PRA-7 Resolve/justify — Policy monolith grew while absorbing sandbox-aware channel preset resolution

  • Location: src/lib/policy/index.ts
  • Category: architecture
  • Problem: The PR introduces a dedicated channel policy resolver module, but `src/lib/policy/index.ts` still grew by about 71 lines and remains the place where listing, loading, agent-aware fallback, validation, merging, gateway reads/writes, and registry persistence are coupled.
  • Impact: This file is a security-critical hotspot for SSRF/policy bypass behavior. More local growth makes it harder to review future changes without accidentally weakening existing `allowed_ips`, `_provider_`, path traversal, OpenShell policy-read, and sandbox-agent validation boundaries.
  • Recommended action: Move the sandbox-aware built-in preset listing/loading glue into a small helper module, or offset the growth by extracting adjacent preset-list/load helpers from `src/lib/policy/index.ts`. Keep the mutation and validation boundaries intact.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect `src/lib/policy/index.ts` around `listPresets()`, `loadPresetForAgent()`, `loadAgentPresetContent()`, and `loadPresetForSandbox()`; confirm whether sandbox-aware catalog selection can be isolated without touching gateway mutation logic.
  • Missing regression test: Existing behavior tests in `src/lib/messaging/channels/policy.test.ts`, `test/policy-channel-agent-resolution.test.ts`, and `src/lib/onboard/initial-policy-real-policy.test.ts` should continue to prove resolver behavior after extraction; add no new test unless behavior changes during the shrink.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect `src/lib/policy/index.ts` around `listPresets()`, `loadPresetForAgent()`, `loadAgentPresetContent()`, and `loadPresetForSandbox()`; confirm whether sandbox-aware catalog selection can be isolated without touching gateway mutation logic.
  • Evidence: Synthetic drift context reports `src/lib/policy/index.ts` grew from 1388 to 1459 lines (+71) while this PR changes policy preset resolution in a large security-sensitive module.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

  • None.
Simplification opportunities: 3 possible cuts

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-3 shrink (docs/reference/commands.mdx:1135): The unknown-preset special-case expectation for known messaging presets on unsupported agents.
    • Replacement: Reuse the existing channel manifest support check/error wording already used by `channels add`, before preset preview.
    • Safety boundary: Keep the pre-preview and pre-prompt fail-closed behavior; do not disclose endpoints for unsupported terminal-runtime messaging presets.
  • PRA-4 shrink (src/lib/actions/sandbox/policy-channel.ts:220): A separate, partially overlapping custom-preset trust boundary from the built-in messaging-preset boundary.
    • Replacement: Centralize the custom messaging-key decision in the policy module so `policy-add --from-file`, `--from-dir`, and snapshot restore share the same documented rule.
    • Safety boundary: Preserve existing `allowed_ips`, `_provider_`, symlink, file-size, and YAML-shape validation; do not remove custom preset support.
  • PRA-7 shrink (src/lib/policy/index.ts): Sandbox-agent-aware preset listing/loading glue from the policy monolith.
    • Replacement: A cohesive helper module that owns built-in central-vs-channel preset resolution and is called by `policy/index.ts`.
    • Safety boundary: Do not simplify away trust-boundary checks for `allowed_ips`, `_provider_`, path traversal, live policy read fail-closed behavior, or sandbox-agent channel policy scoping.
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — policy-add rejects all five Deep Agents messaging presets with explicit unsupported-agent text before endpoint preview or prompt. The PR changes runtime network policy resolution, built-in preset packaging, onboarding create-time policy merge, and CLI rejection behavior for sandbox agents. Unit/source subprocess tests cover important branches, but a read-only review cannot validate packaged runtime behavior or live OpenShell policy mutation.
  • PRA-T2 Runtime validation — Deep Agents policy context omits unsupported messaging presets from knownUnappliedPresets and failure-classifier remediation. The PR changes runtime network policy resolution, built-in preset packaging, onboarding create-time policy merge, and CLI rejection behavior for sandbox agents. Unit/source subprocess tests cover important branches, but a read-only review cannot validate packaged runtime behavior or live OpenShell policy mutation.
  • PRA-T3 Runtime validation — Deep Agents --from-file custom preset with messaging policy key is rejected before endpoint preview and apply, or documented as intentionally allowed. The PR changes runtime network policy resolution, built-in preset packaging, onboarding create-time policy merge, and CLI rejection behavior for sandbox agents. Unit/source subprocess tests cover important branches, but a read-only review cannot validate packaged runtime behavior or live OpenShell policy mutation.
  • PRA-T4 Runtime validation — OpenClaw Discord REST mutation policy is narrowed to concrete paths, or broad PUT/PATCH /** is documented and contract-tested. The PR changes runtime network policy resolution, built-in preset packaging, onboarding create-time policy merge, and CLI rejection behavior for sandbox agents. Unit/source subprocess tests cover important branches, but a read-only review cannot validate packaged runtime behavior or live OpenShell policy mutation.
  • PRA-T5 Runtime validation — Packaged CLI build includes src/lib/messaging/channels/**/policy/*.yaml and can load Hermes/OpenClaw channel policy files after installation. The PR changes runtime network policy resolution, built-in preset packaging, onboarding create-time policy merge, and CLI rejection behavior for sandbox agents. Unit/source subprocess tests cover important branches, but a read-only review cannot validate packaged runtime behavior or live OpenShell policy mutation.
  • PRA-T6 Acceptance clause — `nemoclaw <dcode-sb> policy-add <messaging-channel>` MUST be rejected outright with an explicit "unsupported on terminal-runtime agent" or "not a supported channel for langchain-deepagents-code" message, before any endpoint disclosure or user prompt. — add test evidence or identify existing coverage. Built-in policy-add now rejects before preview/prompt, but the expected message is `Unknown preset 'telegram'.` in `test/policy-channel-agent-resolution.test.ts`, and docs say unavailable channel presets use the standard unknown-preset error.
  • PRA-T7 Acceptance clause — No confirmation prompt is shown. — add test evidence or identify existing coverage. Current tests assert no `Apply 'telegram'` prompt for the built-in Telegram case. They do not directly cover all five issue-listed presets or the custom preset path.
  • PRA-T8 Acceptance clause — `policy-list` continues to report the channel preset as NOT active. — add test evidence or identify existing coverage. `src/lib/actions/sandbox/policy-channel-list.test.ts` asserts unsupported channel policy presets are omitted for `langchain-deepagents-code`. There is no source-level sequence test that runs failed `policy-add` then confirms `policy-list` inactive.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: Custom preset messaging policy-key handling on terminal-runtime agents

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: No current replacement test documents either rejection or intentional allowance; the previous custom rejection coverage was deleted with `src/lib/actions/sandbox/policy-add-agent-gate.test.ts`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: `applyExternalPreset()` previews custom endpoints and calls `applyPresetContent(..., { custom })`; `applyPresetContent()` only blocks custom `allowed_ips` and does not check known messaging policy keys.

PRA-2 Resolve/justify — Source-of-truth review needed: Policy context preset catalog for sandbox agents

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: No test covers `buildPolicyContext()` for `langchain-deepagents-code` with unsupported messaging presets omitted.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: `partitionPresets()` calls `listPresets()` without options, and the messaging policy resolver defaults omitted agent to OpenClaw.

PRA-3 Required — Deep Agents messaging policy-add now reports unknown instead of the required unsupported-agent error

  • Location: docs/reference/commands.mdx:1135
  • Category: acceptance
  • Problem: Issue [Ubuntu 24.04][Policy&Network] Deep Agents sandbox accepts policy-add for all 5 messaging channels instead of rejecting (unsupported on terminal-runtime) #6185 requires `policy-add <messaging-channel>` on a LangChain Deep Agents Code sandbox to reject with an explicit `unsupported on terminal-runtime agent` or `not a supported channel for langchain-deepagents-code` message before endpoint disclosure or prompting. This PR instead documents and tests the standard unknown-preset path for unavailable messaging presets.
  • Impact: Users and future refactors lose the explicit terminal-runtime contract that the issue asked to enforce. The current tests can lock in the rejected behavior as generic catalog absence rather than an agent/capability denial, making support output less actionable and contradicting the linked acceptance criteria.
  • Required action: Change the `policy-add` built-in preset path so known messaging channel preset names on unsupported agents fail with explicit unsupported-agent wording before loading endpoint details or prompting. Update `docs/reference/commands.mdx`, `docs/reference/commands-nemohermes.mdx`, and `docs/network-policy/integration-policy-examples.mdx` to describe that contract instead of unknown-preset behavior.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `test/policy-channel-agent-resolution.test.ts` in the `policy-add treats unsupported Deep Agents messaging policy...` case and the policy-add sections in both command reference pages; confirm they expect `not a supported channel for agent 'langchain-deepagents-code'` or terminal-runtime wording, not `Unknown preset 'telegram'.`
  • Missing regression test: Add a source-level regression named `policy-add rejects all five Deep Agents messaging presets with explicit unsupported-agent text before endpoint preview or prompt` that loops over `telegram`, `discord`, `slack`, `wechat`, and `whatsapp`, asserts exit code 1, asserts explicit unsupported-agent wording, and asserts no `Endpoints that would be opened` or `Apply '<channel>'` prompt.
  • Done when: The required change is committed and verification passes: Read `test/policy-channel-agent-resolution.test.ts` in the `policy-add treats unsupported Deep Agents messaging policy...` case and the policy-add sections in both command reference pages; confirm they expect `not a supported channel for agent 'langchain-deepagents-code'` or terminal-runtime wording, not `Unknown preset 'telegram'.`.
  • Evidence: The linked issue says `policy-add <messaging-channel>` on Deep Agents `MUST be rejected outright with an explicit "unsupported on terminal-runtime agent" or "not a supported channel for langchain-deepagents-code" message`. The changed docs now say unavailable channel presets use the standard unknown-preset error, and `test/policy-channel-agent-resolution.test.ts` asserts `Unknown preset 'telegram'.` plus absence of `not supported for agent`.

PRA-4 Resolve/justify — Custom messaging-shaped presets still bypass the terminal-runtime agent boundary

  • Location: src/lib/actions/sandbox/policy-channel.ts:220
  • Category: security
  • Problem: The built-in preset catalog is now sandbox-agent scoped, but the custom preset path still loads arbitrary YAML, previews its endpoints, and applies it through `policies.applyPresetContent(..., { custom })` without checking whether the custom `network_policies` keys are known messaging keys on an unsupported terminal-runtime agent.
  • Impact: If the intended boundary is that terminal-runtime agents cannot receive messaging channel egress, `--from-file`, `--from-dir`, snapshot restore, or other `applyPresetContent(..., { custom })` callers can reintroduce the same Telegram/Discord/Slack/WeChat/WhatsApp/Teams egress categories that the built-in gate hides. If custom operator presets are intentionally exempt, the new trust boundary is not documented or locked by tests.
  • Recommended action: Decide and encode the source-of-truth boundary in this PR. Either reject custom presets containing known messaging policy keys for unsupported agents before endpoint preview/apply, or explicitly document and test that operator-authored custom presets are exempt while built-in messaging channel presets remain agent-scoped.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare `applyExternalPreset()` in `src/lib/actions/sandbox/policy-channel.ts` with the custom branch of `applyPresetContent()` in `src/lib/policy/index.ts`; the current custom security validation blocks `allowed_ips` and reserved provider keys, but does not inspect known messaging policy keys against the sandbox agent.
  • Missing regression test: Add either `Deep Agents rejects --from-file custom preset with messaging policy keys before endpoint preview or apply` or `Deep Agents allows custom operator-authored messaging-like egress while built-in channel presets are rejected`, depending on the intended contract. The rejection version should assert no endpoint preview, no prompt, and no call to `applyPresetContent`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare `applyExternalPreset()` in `src/lib/actions/sandbox/policy-channel.ts` with the custom branch of `applyPresetContent()` in `src/lib/policy/index.ts`; the current custom security validation blocks `allowed_ips` and reserved provider keys, but does not inspect known messaging policy keys against the sandbox agent.
  • Evidence: The deleted `src/lib/actions/sandbox/policy-add-agent-gate.test.ts` previously covered custom presets containing keys such as `telegram_bot`, `discord`, `slack`, `wechat_bridge`, `whatsapp`, and `teams`. The current `applyExternalPreset()` calls `policies.loadPresetFromFile()`, prints `Endpoints that would be opened`, then calls `policies.applyPresetContent()` with `custom`.

PRA-5 Resolve/justify — Policy context still uses the OpenClaw default catalog for terminal-runtime agents

  • Location: src/lib/policy/context.ts:138
  • Category: correctness
  • Problem: `partitionPresets()` calls `listPresets()` without passing the sandbox agent, so the messaging resolver defaults to OpenClaw channel policy files. For a Deep Agents sandbox, `loadPresetForSandbox()` returns null for those messaging presets, but they can still appear as known unapplied built-ins in the rendered policy context and failure-classifier remediation.
  • Impact: Agents can be told that unsupported messaging presets are known remediation targets even though `policy-list` and `policy-add` now omit or reject them for terminal-runtime agents. That creates source-of-truth drift between the human CLI surfaces and the in-sandbox POLICY.md / classifier guidance.
  • Recommended action: Pass the sandbox's recorded agent into `listPresets({ agent: ... })` when building policy context, and keep custom presets appended separately. Ensure unsupported messaging presets are absent from `knownUnappliedPresets` for `langchain-deepagents-code` while central presets such as npm/pypi remain visible.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/policy/context.ts` around `partitionPresets()` and confirm whether it calls `listPresets({ agent: sandboxAgent })`. Then inspect `buildPolicyContext()` to ensure it obtains the same sandbox entry used for applied policies/tier before partitioning.
  • Missing regression test: Add `Deep Agents policy context omits unsupported messaging presets from knownUnappliedPresets and failure-classifier remediation`, asserting that `telegram`, `discord`, `slack`, `wechat`, and `whatsapp` are not suggested for a `langchain-deepagents-code` sandbox while non-messaging presets remain available.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/policy/context.ts` around `partitionPresets()` and confirm whether it calls `listPresets({ agent: sandboxAgent })`. Then inspect `buildPolicyContext()` to ensure it obtains the same sandbox entry used for applied policies/tier before partitioning.
  • Evidence: `src/lib/policy/context.ts:138` currently uses `const builtin = listPresets();`. `src/lib/messaging/channels/policy.ts` normalizes a null/omitted agent to `openclaw`, so an agentless catalog read includes OpenClaw messaging policy files.

PRA-6 Resolve/justify — OpenClaw Discord policy grants broad PUT/PATCH over discord.com

  • Location: src/lib/messaging/channels/discord/policy/openclaw.yaml:19
  • Category: security
  • Problem: The OpenClaw Discord channel policy allows `PUT /**` and `PATCH /**` on `discord.com`, while the Hermes Discord policy scopes mutation methods to concrete Discord API paths and the YAML contract test only enforces the narrower Hermes shape.
  • Impact: A compromised or buggy OpenClaw Node process with Discord egress can perform a much wider set of Discord mutations than the Hermes agent needs, increasing the blast radius of this policy preset and weakening least-privilege guarantees for a high-risk messaging integration.
  • Recommended action: Narrow the OpenClaw Discord `PUT` and `PATCH` rules to the concrete API paths OpenClaw actually uses, or add an inline YAML rationale plus a focused contract test documenting why OpenClaw requires broad `PUT /**` and `PATCH /**` while Hermes does not.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/messaging/channels/discord/policy/openclaw.yaml` and compare its `discord.com` rules with `src/lib/messaging/channels/discord/policy/hermes.yaml`; verify whether broad mutation paths remain and whether a test documents the OpenClaw exception.
  • Missing regression test: Add `OpenClaw Discord REST mutations are scoped to documented API paths` if narrowing, or `OpenClaw Discord broad PUT/PATCH policy is intentionally documented` if the broad rules are required, asserting the exact allowed mutation rules.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/messaging/channels/discord/policy/openclaw.yaml` and compare its `discord.com` rules with `src/lib/messaging/channels/discord/policy/hermes.yaml`; verify whether broad mutation paths remain and whether a test documents the OpenClaw exception.
  • Evidence: OpenClaw policy contains `allow: { method: PUT, path: "/**" }` and `allow: { method: PATCH, path: "/**" }`. `test/policy-channel-yaml-contract.test.ts` asserts Hermes Discord mutation rules do not include `/**`, but does not cover OpenClaw.

PRA-7 Resolve/justify — Policy monolith grew while absorbing sandbox-aware channel preset resolution

  • Location: src/lib/policy/index.ts
  • Category: architecture
  • Problem: The PR introduces a dedicated channel policy resolver module, but `src/lib/policy/index.ts` still grew by about 71 lines and remains the place where listing, loading, agent-aware fallback, validation, merging, gateway reads/writes, and registry persistence are coupled.
  • Impact: This file is a security-critical hotspot for SSRF/policy bypass behavior. More local growth makes it harder to review future changes without accidentally weakening existing `allowed_ips`, `_provider_`, path traversal, OpenShell policy-read, and sandbox-agent validation boundaries.
  • Recommended action: Move the sandbox-aware built-in preset listing/loading glue into a small helper module, or offset the growth by extracting adjacent preset-list/load helpers from `src/lib/policy/index.ts`. Keep the mutation and validation boundaries intact.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect `src/lib/policy/index.ts` around `listPresets()`, `loadPresetForAgent()`, `loadAgentPresetContent()`, and `loadPresetForSandbox()`; confirm whether sandbox-aware catalog selection can be isolated without touching gateway mutation logic.
  • Missing regression test: Existing behavior tests in `src/lib/messaging/channels/policy.test.ts`, `test/policy-channel-agent-resolution.test.ts`, and `src/lib/onboard/initial-policy-real-policy.test.ts` should continue to prove resolver behavior after extraction; add no new test unless behavior changes during the shrink.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect `src/lib/policy/index.ts` around `listPresets()`, `loadPresetForAgent()`, `loadAgentPresetContent()`, and `loadPresetForSandbox()`; confirm whether sandbox-aware catalog selection can be isolated without touching gateway mutation logic.
  • Evidence: Synthetic drift context reports `src/lib/policy/index.ts` grew from 1388 to 1459 lines (+71) while this PR changes policy preset resolution in a large security-sensitive module.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

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

🧹 Nitpick comments (3)
scripts/validate-configs.ts (1)

61-150: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Repeated try/catch ENOENT + directory-walker pattern could be consolidated.

The ENOENT/ENOTDIR try/catch guard is now duplicated four times, and walkModelSetup/walkChannelPolicies are near-identical recursive walkers differing only by file predicate. Consider extracting a shared safeWalk(dir, predicate) helper to reduce duplication as more discovery targets are added.

🤖 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 `@scripts/validate-configs.ts` around lines 61 - 150, The directory discovery
logic in validate-configs is duplicating the same ENOENT/ENOTDIR guard and
recursive walk pattern in multiple places. Extract a shared helper around the
existing walkModelSetup and walkChannelPolicies behavior, such as a reusable
safeWalk(dir, predicate) or safeReaddir wrapper, and use it for agentsDir,
modelSetupDir, presetsDir, and channelPoliciesDir discovery so the file
predicate and target-specific push logic remain separate while the
traversal/error handling is centralized.
package.json (1)

82-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Glob only covers .yaml, not .yml.

scripts/validate-configs.ts discovers channel policy files with /\.ya?ml$/ (both extensions), but this packaging glob only matches *.yaml. Any future .yml channel policy preset would pass validation but be silently excluded from the published package.

Proposed glob widening
-    "src/lib/messaging/channels/**/policy/*.yaml",
+    "src/lib/messaging/channels/**/policy/*.{yaml,yml}",
🤖 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 `@package.json` at line 82, The packaging glob for channel policy presets only
matches .yaml and misses .yml, so widen the pattern in package.json to cover
both extensions consistently with scripts/validate-configs.ts. Update the
existing src/lib/messaging/channels/**/policy/*.yaml entry so the publish
package includes any .yml policy files as well, keeping the packaging glob
aligned with the validator’s /\.ya?ml$/ discovery in the same preset area.
tools/pr-review-advisor/analyze.mts (1)

706-720: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Duplicated declarative-config path inventory risks drift.

This e2eSignals filter and looksLikeDeclarativeConfigPath in scripts/find-source-shape-tests.ts both hardcode overlapping path patterns for policy/config files (nemoclaw-blueprint/policies/, src/lib/messaging/channels/.../policy/...yaml, agents/*/policy-*.yaml). Adding a new channel or config location requires remembering to update both independently maintained lists.

Consider extracting a shared canonical list/predicate (e.g., a small shared module) that both the shape-test scanner and this advisor import, so the two purposes can't silently diverge.

As per path instructions, "Derive inventories and limits from a canonical source where possible; flag duplicated lists that can silently drift."

🤖 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 `@tools/pr-review-advisor/analyze.mts` around lines 706 - 720, The e2eSignals
filter in analyze.mts duplicates declarative-config path rules that also exist
in looksLikeDeclarativeConfigPath, which can drift over time. Refactor the
shared policy/config path matching into a single canonical helper or small
shared module, then have both e2eSignals and scripts/find-source-shape-tests.ts
import and use it so new policy locations only need to be updated once.

Source: Path instructions

🤖 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/messaging/channels/policy.test.ts`:
- Around line 48-59: The policy test now adds a new conditional via the
null-check around resolveMessagingChannelPolicyPresetPath in policy.test.ts,
which trips the test-conditionals guardrail. Refactor the loop in the
manifest/agent/preset coverage test to avoid an explicit if statement while
still collecting unresolved preset paths, keeping the logic inside
listBuiltInMessagingChannelManifests, listMessagingPolicyPresetMetadata, and
resolveMessagingChannelPolicyPresetPath functionally equivalent.

In `@src/lib/messaging/channels/policy.ts`:
- Around line 26-28: The normalizeAgent resolver currently coerces every
non-hermes agent to openclaw, which can incorrectly apply channel policy YAMLs
for unsupported agents. Update normalizeAgent in policy.ts to only return a
valid MessagingAgentId for explicitly supported agents and otherwise signal an
unsupported value so callers can skip or hard-gate before any policy mutation.
Then ensure the preset-loading flow that uses this resolver checks the
manifest/channel support path before calling policy/provider/credential/registry
rebuild logic, including the add-channel paths referenced by the related blocks.

In `@test/channels-add-preset.test.ts`:
- Line 184: Keep the sandbox-aware stub observable by changing the test harness
stub for policies.loadPresetForSandbox() so it does not simply delegate to
loadPreset(). Update the stub in channels-add-preset.test.ts to exercise
sandbox-scoped behavior directly, using the same policies object and the
loadPresetForSandbox symbol, so Hermes-specific fixtures validate the new
resolution path instead of bypassing it.

In `@test/policy-channel-yaml-contract.test.ts`:
- Around line 57-81: The test in policy-channel-yaml-contract is currently
vacuous because it can pass when the expected Slack REST endpoints or policy
keys disappear, so add explicit assertions that the filtered endpoint list is
non-empty before the loop in the Slack request-body rewrite case, and likewise
assert the result from rulesFor("nous_research", "nousresearch.com") is
non-empty before comparing to an empty array. Use the existing helpers
allEndpoints, channelPolicy, and rulesFor to locate and guard these checks so
the test fails loudly if the underlying YAML data changes or is renamed.

---

Nitpick comments:
In `@package.json`:
- Line 82: The packaging glob for channel policy presets only matches .yaml and
misses .yml, so widen the pattern in package.json to cover both extensions
consistently with scripts/validate-configs.ts. Update the existing
src/lib/messaging/channels/**/policy/*.yaml entry so the publish package
includes any .yml policy files as well, keeping the packaging glob aligned with
the validator’s /\.ya?ml$/ discovery in the same preset area.

In `@scripts/validate-configs.ts`:
- Around line 61-150: The directory discovery logic in validate-configs is
duplicating the same ENOENT/ENOTDIR guard and recursive walk pattern in multiple
places. Extract a shared helper around the existing walkModelSetup and
walkChannelPolicies behavior, such as a reusable safeWalk(dir, predicate) or
safeReaddir wrapper, and use it for agentsDir, modelSetupDir, presetsDir, and
channelPoliciesDir discovery so the file predicate and target-specific push
logic remain separate while the traversal/error handling is centralized.

In `@tools/pr-review-advisor/analyze.mts`:
- Around line 706-720: The e2eSignals filter in analyze.mts duplicates
declarative-config path rules that also exist in looksLikeDeclarativeConfigPath,
which can drift over time. Refactor the shared policy/config path matching into
a single canonical helper or small shared module, then have both e2eSignals and
scripts/find-source-shape-tests.ts import and use it so new policy locations
only need to be updated once.
🪄 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: 5db6ad61-6adf-4903-a6af-83e734050178

📥 Commits

Reviewing files that changed from the base of the PR and between 9df364c and afba216.

📒 Files selected for processing (47)
  • agents/hermes/policy-additions.yaml
  • ci/platform-matrix.json
  • ci/test-file-size-budget.json
  • docs/reference/platform-support.mdx
  • package.json
  • schemas/policy-preset.schema.json
  • scripts/find-source-shape-tests.ts
  • scripts/validate-configs.ts
  • src/lib/actions/sandbox/policy-channel-agent-gate.test.ts
  • src/lib/actions/sandbox/policy-channel-policy.test.ts
  • src/lib/actions/sandbox/policy-channel-refresh.test.ts
  • src/lib/actions/sandbox/policy-channel.ts
  • src/lib/messaging/AGENTS.md
  • src/lib/messaging/README.md
  • src/lib/messaging/channels/discord/policy/hermes.yaml
  • src/lib/messaging/channels/discord/policy/openclaw.yaml
  • src/lib/messaging/channels/index.ts
  • src/lib/messaging/channels/policy.test.ts
  • src/lib/messaging/channels/policy.ts
  • src/lib/messaging/channels/slack/policy/hermes.yaml
  • src/lib/messaging/channels/slack/policy/openclaw.yaml
  • src/lib/messaging/channels/teams/policy/hermes.yaml
  • src/lib/messaging/channels/teams/policy/openclaw.yaml
  • src/lib/messaging/channels/telegram/policy/hermes.yaml
  • src/lib/messaging/channels/telegram/policy/openclaw.yaml
  • src/lib/messaging/channels/wechat/policy/hermes.yaml
  • src/lib/messaging/channels/wechat/policy/openclaw.yaml
  • src/lib/messaging/channels/whatsapp/policy/hermes.yaml
  • src/lib/messaging/channels/whatsapp/policy/openclaw.yaml
  • src/lib/messaging/messaging-network-policy-flow.md
  • src/lib/onboard/initial-policy.test.ts
  • src/lib/onboard/initial-policy.ts
  • src/lib/policy/context.test.ts
  • src/lib/policy/context.ts
  • src/lib/policy/failure-classifier.test.ts
  • src/lib/policy/index.ts
  • test/channels-add-deepagents-rejection.test.ts
  • test/channels-add-preset.test.ts
  • test/onboard-messaging.test.ts
  • test/package-contract/cli/policy-dispatch.test.ts
  • test/policies.test.ts
  • test/policy-add-remove-session-sync.test.ts
  • test/policy-channel-yaml-contract.test.ts
  • test/pr-review-advisor.test.ts
  • test/validate-blueprint.test.ts
  • test/validate-config-schemas.test.ts
  • tools/pr-review-advisor/analyze.mts
💤 Files with no reviewable changes (1)
  • agents/hermes/policy-additions.yaml

Comment thread src/lib/messaging/channels/policy.test.ts
Comment thread src/lib/messaging/channels/policy.ts Outdated
Comment thread test/channels-add-preset.test.ts Outdated
Comment thread test/policy-channel-yaml-contract.test.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.

🧹 Nitpick comments (1)
test/package-contract/cli/policy-dispatch.test.ts (1)

30-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider cleaning up the temp directory after the test.

Unlike the sibling test in test/policy-channel-agent-resolution.test.ts (which calls fs.rmSync(tmpDir, { recursive: true, force: true }) after spawnSync), this test never removes tmpDir. Over many CI runs this leaves stray temp directories behind.

♻️ Suggested cleanup
     expect(result.status).toBe(0);
     const payload = JSON.parse(result.stdout.split("__RESULT__")[1].trim());
     expect(payload.openclawKeys).toEqual(["telegram_bot"]);
     expect(payload.hermesKeys).toEqual(["telegram"]);
+    fs.rmSync(tmpDir, { recursive: true, force: true });
   });

The static analysis warning about fs.writeFileSync(scriptPath, script) (path traversal) is a false positive — scriptPath is derived entirely from fs.mkdtempSync and a fixed filename, not external input.

🤖 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/package-contract/cli/policy-dispatch.test.ts` around lines 30 - 56, The
test in policy-dispatch.test.ts leaves behind the temporary directory created
with fs.mkdtempSync after spawnSync completes. Add cleanup after the assertions
by removing tmpDir with fs.rmSync using recursive and force options, matching
the cleanup pattern used in the sibling temp-dir test, and keep the rest of the
packaged-channel policy check logic unchanged.
🤖 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.

Nitpick comments:
In `@test/package-contract/cli/policy-dispatch.test.ts`:
- Around line 30-56: The test in policy-dispatch.test.ts leaves behind the
temporary directory created with fs.mkdtempSync after spawnSync completes. Add
cleanup after the assertions by removing tmpDir with fs.rmSync using recursive
and force options, matching the cleanup pattern used in the sibling temp-dir
test, and keep the rest of the packaged-channel policy check logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8f3be0eb-e3f3-475b-8d81-5e3af2db3ae5

📥 Commits

Reviewing files that changed from the base of the PR and between d97bbae and 92d4284.

📒 Files selected for processing (7)
  • package.json
  • src/lib/messaging/channels/policy.test.ts
  • src/lib/messaging/channels/policy.ts
  • test/channels-add-preset.test.ts
  • test/package-contract/cli/policy-dispatch.test.ts
  • test/policy-channel-agent-resolution.test.ts
  • test/policy-channel-yaml-contract.test.ts
✅ Files skipped from review due to trivial changes (1)
  • package.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • test/channels-add-preset.test.ts
  • src/lib/messaging/channels/policy.ts
  • test/policy-channel-yaml-contract.test.ts

@sandl99

sandl99 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

Replying to #6129 (comment).

Current head: 678f952da781021c297d261b64f72b6ce61466ba.

We are not taking further code action on the remaining required PRA items from that advisor pass.

Rationale:

  • PRA-7 / PRA-8: The current unsupported-agent behavior is intentional fail-closed behavior, not a permissive fallback. src/lib/messaging/channels/policy.ts only resolves channel-owned messaging policy files for openclaw and hermes; unknown agents return null. loadPresetForSandbox therefore does not apply OpenClaw/Hermes channel policies to unsupported agents. This is covered by test/policy-channel-agent-resolution.test.ts, which registers a sandbox with agent: "langchain-deepagents-code" and verifies loadPresetForSandbox(..., "telegram") returns null while central presets such as npm still work. Adding a warning or importing agent/defs into src/lib/messaging/channels would couple the channel manifest/policy data layer back to the core agent registry, which this PR is explicitly avoiding, and would add operator noise without changing the security outcome.

  • PRA-12: The requested negative cases are covered at the channel policy resolver boundary, where those failure modes exist: unsafe channel ID/path traversal, missing policy file, preset header mismatch, and malformed YAML are covered in src/lib/messaging/channels/policy.test.ts; the sandbox-aware unknown-agent boundary is covered in test/policy-channel-agent-resolution.test.ts. We intentionally did not duplicate these in test/policies.test.ts because that legacy integration file is already at its line budget and duplicate tests there would add size/noise without adding behavior coverage.

  • Malformed channel policy YAML intentionally fails closed. The resolver returns null so bad channel policy data is not loaded. Schema/config validation remains the source for surfacing malformed committed YAML.

All PR checks are green on the current head, including cli-test-shards (3), aggregate cli-tests, CodeRabbit, and both PR review advisors.

@sandl99 sandl99 added area: messaging Messaging channels, bridges, manifests, or channel lifecycle refactor PR restructures code without intended behavior change and removed area: security Security controls, permissions, secrets, or hardening labels Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28526235736
Workflow ref: feat/messaging-channel-policies
Requested targets: network-policy,channels-add-remove,channels-stop-start,hermes-e2e,hermes-slack,hermes-discord,openclaw-slack-pairing,openclaw-discord-pairing,messaging-providers
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 9 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-add-remove ✅ success
channels-stop-start ✅ success
hermes-discord ✅ success
hermes-e2e ✅ success
hermes-slack ✅ success
messaging-providers ✅ success
network-policy ✅ success
openclaw-discord-pairing ✅ success
openclaw-slack-pairing ✅ success

@sandl99 sandl99 added the v0.0.73 label Jul 2, 2026
sandl99 added 3 commits July 2, 2026 22:37
Signed-off-by: San Dang <sdang@nvidia.com>
…time agents (#6197)"

This reverts commit 3a51447.

Signed-off-by: San Dang <sdang@nvidia.com>
Signed-off-by: San Dang <sdang@nvidia.com>
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28608432026
Workflow ref: feat/messaging-channel-policies
Requested targets: network-policy,channels-add-remove,messaging-providers,cloud-onboard,hermes-e2e,hermes-slack,hermes-discord,openclaw-slack-pairing,openclaw-discord-pairing
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 9 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-add-remove ✅ success
cloud-onboard ✅ success
hermes-discord ✅ success
hermes-e2e ✅ success
hermes-slack ✅ success
messaging-providers ✅ success
network-policy ✅ success
openclaw-discord-pairing ✅ success
openclaw-slack-pairing ✅ success

sandl99 added 2 commits July 2, 2026 23:21
Signed-off-by: San Dang <sdang@nvidia.com>
Signed-off-by: San Dang <sdang@nvidia.com>
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28611227084
Workflow ref: feat/messaging-channel-policies
Requested targets: network-policy,channels-add-remove,messaging-providers,cloud-onboard,hermes-e2e,hermes-slack,hermes-discord,openclaw-slack-pairing,openclaw-discord-pairing
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 9 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-add-remove ✅ success
cloud-onboard ✅ success
hermes-discord ✅ success
hermes-e2e ✅ success
hermes-slack ✅ success
messaging-providers ✅ success
network-policy ✅ success
openclaw-discord-pairing ✅ success
openclaw-slack-pairing ✅ success

@cv cv added v0.0.74 and removed v0.0.73 labels Jul 2, 2026
@sandl99

sandl99 commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator Author

@cv Ready to merge

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28639654676
Workflow ref: feat/messaging-channel-policies
Requested targets: network-policy,channels-add-remove,messaging-providers,cloud-onboard,hermes-e2e,hermes-slack,hermes-discord,openclaw-slack-pairing,openclaw-discord-pairing
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 9 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-add-remove ✅ success
cloud-onboard ✅ success
hermes-discord ✅ success
hermes-e2e ✅ success
hermes-slack ✅ success
messaging-providers ✅ success
network-policy ✅ success
openclaw-discord-pairing ✅ success
openclaw-slack-pairing ✅ success

@cv
cv merged commit d13ef62 into main Jul 3, 2026
121 checks passed
@cv
cv deleted the feat/messaging-channel-policies branch July 3, 2026 07:41
@ericksoa ericksoa mentioned this pull request Jul 4, 2026
21 tasks
ericksoa added a commit that referenced this pull request Jul 4, 2026
<!-- markdownlint-disable MD041 -->
## Summary
This PR prepares the user-facing documentation for v0.0.74 before the
release plan is frozen.
It expands the release notes across the 56-commit train and closes
durable documentation gaps found during the pre-tag commit scan.

## Changes
- Expand the `v0.0.74` release notes to cover OpenShell 0.0.72, managed
MCP, progressive tool disclosure, LangChain Deep Agents Code,
onboarding, local inference, messaging, recovery, and contributor
workflows.
- Correct the `destroy` contract for retained per-name volumes,
gateway-unreachable `--force` cleanup, managed MCP ownership, and
same-name recovery.
- Document separate remediation for an unreachable container DNS
resolver versus one that answers with `NXDOMAIN` or `REFUSED`.
- Document the Windows on Arm N1X automatic Ollama safeguard and its
remaining large-model limitations.
- State that messaging conflicts abort rebuild before backup or
deletion, leaving the original sandbox intact.
- Link the agent-runnable value benchmark from the contributor task
index.
- Synchronize generated agent command variants.
- Validate with `npm run docs:sync-agent-variants` and `npm run docs`;
Fern completed with 0 errors and 2 existing warnings.
- Source summary:
- [#6020](#6020) and
[#5876](#5876) ->
`docs/about/release-notes.mdx`: Consolidate the OpenShell 0.0.72 policy
boundary and managed MCP lifecycle.
- [#6251](#6251) and
[#5989](#5989) ->
`docs/about/release-notes.mdx`: Summarize progressive tool disclosure
and sandbox-first inference controls.
- [#6232](#6232),
[#6082](#6082),
[#6219](#6219),
[#6214](#6214),
[#6215](#6215),
[#6230](#6230), and
[#6260](#6260) ->
`docs/about/release-notes.mdx`: Summarize the experimental LangChain
Deep Agents Code status, secret, version, rebuild, snapshot, and MCP
boundaries.
- [#6166](#6166),
[#6254](#6254),
[#6265](#6265),
[#6164](#6164), and
[#6017](#6017) ->
`docs/about/release-notes.mdx`: Summarize BuildKit prebuild, validated
image reuse, bounded readiness, and preflight improvements.
- [#6150](#6150) ->
`docs/about/release-notes.mdx` and `docs/reference/troubleshooting.mdx`:
Separate unreachable-resolver remediation from reachable-but-rejected
DNS responses.
- [#6234](#6234) ->
`docs/about/release-notes.mdx`,
`docs/inference/use-local-inference.mdx`, and
`docs/get-started/windows-preparation.mdx`: Document N1X automatic 9B
selection and the remaining explicit-large-model boundary.
- [#6129](#6129),
[#5987](#5987),
[#5955](#5955), and
[#6220](#6220) ->
`docs/about/release-notes.mdx`,
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, and
`docs/reference/commands-nemohermes.mdx`: Document messaging policy
persistence, status, and the pre-destructive conflict check.
- [#5963](#5963),
[#6050](#6050),
[#6094](#6094),
[#6238](#6238),
[#5988](#5988),
[#6235](#6235),
[#6181](#6181), and
[#5986](#5986) ->
`docs/about/release-notes.mdx`, `docs/reference/commands.mdx`, and
`docs/reference/commands-nemohermes.mdx`: Summarize day-two recovery and
clarify retained-volume and local-only destroy semantics.
- [#6200](#6200),
[#6248](#6248),
[#6168](#6168),
[#6270](#6270), and
[#5649](#5649) ->
`docs/about/release-notes.mdx` and `CONTRIBUTING.md`: Summarize
contributor setup and verification improvements and expose the advisory
value benchmark.

## Type of Change

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

## Quality Gates
<!-- Check exactly one tests line and one docs line. Check other lines
when applicable. Add every requested justification or approval
reference. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: documentation-only release
preparation; generated-variant synchronization and the Fern docs build
validate the changed pages and routes.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification
<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: tests
are not applicable to this documentation-only change; `npm run docs`
validates the source and generated routes.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Expanded setup guidance for Windows on Arm devices with safer default
local model selection.
* Clarified local inference and sandbox messaging behavior, including
conflict checks before rebuilds and safer recovery steps.
* Updated destroy/rebuild/reference docs with more detailed warnings,
failure handling, and volume-retention guidance.
* Improved troubleshooting instructions for Docker DNS issues with
clearer paths for unreachable vs. blocked resolvers.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary
This PR moves messaging-channel network policy data for OpenClaw and
Hermes into the channel package tree under `src/lib/messaging/channels`.
It keeps policy resolution manifest-driven while removing messaging
endpoint data from central blueprint presets and Hermes baseline policy
additions.

## Related issues
Fixes NVIDIA#6185

## Changes
- Added channel-owned `openclaw.yaml` and `hermes.yaml` policy presets
for Telegram, Discord, Slack, Teams, WeChat, and WhatsApp.
- Added a messaging channel policy resolver and wired sandbox-aware
preset loading through onboarding, `policy-add`/`policy-remove`, and
`channels add` flows.
- Updated package/schema/config validation, platform matrix docs sync,
internal messaging guidance, and focused tests for the new policy source
layout.
- Split channel YAML contract coverage into
`test/policy-channel-yaml-contract.test.ts` and ratcheted the oversized
`test/policies.test.ts` file budget down.

## Type of Change

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

## Quality Gates
<!-- Check all that apply. For any "covered by existing tests", "not
applicable", or waiver entry, add a brief justification on the same line
or in the Changes section. -->
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: self-reviewed
policy/onboarding/channel lifecycle changes; focused tests and CI
requested.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue: no CI waiver requested;
local `test-cli` failure was reproduced on clean `main` in this
environment.

## Verification
<!-- Check each item you ran and confirmed. Leave unchecked items you
skipped. Doc-only changes do not require npm test unless you ran it. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [ ] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes — commit/push hooks passed with
local `test-cli` skipped; full `test-cli` also fails on clean `main`
locally.
- [x] Targeted tests pass for changed behavior
- [ ] Full `npm test` passes (broad runtime changes only)
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) — `npm
run docs` passed; Fern reported 2 warnings.
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Verification evidence:
- `npm run typecheck:cli`
- `npx tsx scripts/validate-configs.ts`
- `npm run build:cli`
- `npx vitest run --project cli
src/lib/messaging/channels/policy.test.ts
src/lib/actions/sandbox/policy-channel-agent-gate.test.ts
src/lib/shields/timer.test.ts src/lib/onboard/initial-policy.test.ts`
- `npx vitest run --project integration test/onboard-messaging.test.ts
test/policies.test.ts`
- `npx vitest run --project integration
test/policy-channel-yaml-contract.test.ts test/policies.test.ts
test/channels-add-preset.test.ts test/validate-blueprint.test.ts`
- `npm run source-shape:check`
- `npm run test-size:check`
- `npm run docs`
- `npx prek run --files ...` passed all non-`test-cli` hooks; `test-cli`
failed with the same local platform/runtime fixture failures reproduced
on clean `main`.

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: San Dang <sdang@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added/expanded built-in messaging channel policy presets for Discord,
Slack, Teams, Telegram, WeChat, and WhatsApp with agent-specific
Hermes/OpenClaw variants.
* Channel policy presets are now packaged and discovered from
per-channel policy locations.
* **Bug Fixes**
* Sandbox add/remove/refresh now uses sandbox-scoped preset resolution
to avoid incorrect preset selection.
* Removed messaging-channel network policy templates from the Hermes
sandbox policy file to prevent unintended template egress.
* **Documentation**
* Updated messaging integration notes and setup instructions, including
WebSocket/Noise/h1-ALPN caveats.
* **Tests**
* Expanded coverage for sandbox-aware preset loading and messaging YAML
policy contracts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: San Dang <sdang@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary
This PR prepares the user-facing documentation for v0.0.74 before the
release plan is frozen.
It expands the release notes across the 56-commit train and closes
durable documentation gaps found during the pre-tag commit scan.

## Changes
- Expand the `v0.0.74` release notes to cover OpenShell 0.0.72, managed
MCP, progressive tool disclosure, LangChain Deep Agents Code,
onboarding, local inference, messaging, recovery, and contributor
workflows.
- Correct the `destroy` contract for retained per-name volumes,
gateway-unreachable `--force` cleanup, managed MCP ownership, and
same-name recovery.
- Document separate remediation for an unreachable container DNS
resolver versus one that answers with `NXDOMAIN` or `REFUSED`.
- Document the Windows on Arm N1X automatic Ollama safeguard and its
remaining large-model limitations.
- State that messaging conflicts abort rebuild before backup or
deletion, leaving the original sandbox intact.
- Link the agent-runnable value benchmark from the contributor task
index.
- Synchronize generated agent command variants.
- Validate with `npm run docs:sync-agent-variants` and `npm run docs`;
Fern completed with 0 errors and 2 existing warnings.
- Source summary:
- [NVIDIA#6020](NVIDIA#6020) and
[NVIDIA#5876](NVIDIA#5876) ->
`docs/about/release-notes.mdx`: Consolidate the OpenShell 0.0.72 policy
boundary and managed MCP lifecycle.
- [NVIDIA#6251](NVIDIA#6251) and
[NVIDIA#5989](NVIDIA#5989) ->
`docs/about/release-notes.mdx`: Summarize progressive tool disclosure
and sandbox-first inference controls.
- [NVIDIA#6232](NVIDIA#6232),
[NVIDIA#6082](NVIDIA#6082),
[NVIDIA#6219](NVIDIA#6219),
[NVIDIA#6214](NVIDIA#6214),
[NVIDIA#6215](NVIDIA#6215),
[NVIDIA#6230](NVIDIA#6230), and
[NVIDIA#6260](NVIDIA#6260) ->
`docs/about/release-notes.mdx`: Summarize the experimental LangChain
Deep Agents Code status, secret, version, rebuild, snapshot, and MCP
boundaries.
- [NVIDIA#6166](NVIDIA#6166),
[NVIDIA#6254](NVIDIA#6254),
[NVIDIA#6265](NVIDIA#6265),
[NVIDIA#6164](NVIDIA#6164), and
[NVIDIA#6017](NVIDIA#6017) ->
`docs/about/release-notes.mdx`: Summarize BuildKit prebuild, validated
image reuse, bounded readiness, and preflight improvements.
- [NVIDIA#6150](NVIDIA#6150) ->
`docs/about/release-notes.mdx` and `docs/reference/troubleshooting.mdx`:
Separate unreachable-resolver remediation from reachable-but-rejected
DNS responses.
- [NVIDIA#6234](NVIDIA#6234) ->
`docs/about/release-notes.mdx`,
`docs/inference/use-local-inference.mdx`, and
`docs/get-started/windows-preparation.mdx`: Document N1X automatic 9B
selection and the remaining explicit-large-model boundary.
- [NVIDIA#6129](NVIDIA#6129),
[NVIDIA#5987](NVIDIA#5987),
[NVIDIA#5955](NVIDIA#5955), and
[NVIDIA#6220](NVIDIA#6220) ->
`docs/about/release-notes.mdx`,
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, and
`docs/reference/commands-nemohermes.mdx`: Document messaging policy
persistence, status, and the pre-destructive conflict check.
- [NVIDIA#5963](NVIDIA#5963),
[NVIDIA#6050](NVIDIA#6050),
[NVIDIA#6094](NVIDIA#6094),
[NVIDIA#6238](NVIDIA#6238),
[NVIDIA#5988](NVIDIA#5988),
[NVIDIA#6235](NVIDIA#6235),
[NVIDIA#6181](NVIDIA#6181), and
[NVIDIA#5986](NVIDIA#5986) ->
`docs/about/release-notes.mdx`, `docs/reference/commands.mdx`, and
`docs/reference/commands-nemohermes.mdx`: Summarize day-two recovery and
clarify retained-volume and local-only destroy semantics.
- [NVIDIA#6200](NVIDIA#6200),
[NVIDIA#6248](NVIDIA#6248),
[NVIDIA#6168](NVIDIA#6168),
[NVIDIA#6270](NVIDIA#6270), and
[NVIDIA#5649](NVIDIA#5649) ->
`docs/about/release-notes.mdx` and `CONTRIBUTING.md`: Summarize
contributor setup and verification improvements and expose the advisory
value benchmark.

## Type of Change

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

## Quality Gates
<!-- Check exactly one tests line and one docs line. Check other lines
when applicable. Add every requested justification or approval
reference. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: documentation-only release
preparation; generated-variant synchronization and the Fern docs build
validate the changed pages and routes.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification
<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: tests
are not applicable to this documentation-only change; `npm run docs`
validates the source and generated routes.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Expanded setup guidance for Windows on Arm devices with safer default
local model selection.
* Clarified local inference and sandbox messaging behavior, including
conflict checks before rebuilds and safer recovery steps.
* Updated destroy/rebuild/reference docs with more detailed warnings,
failure handling, and volume-retention guidance.
* Improved troubleshooting instructions for Docker DNS issues with
clearer paths for unreachable vs. blocked resolvers.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@nvshaxie nvshaxie mentioned this pull request Jul 13, 2026
2 tasks
jyaunches added a commit that referenced this pull request Aug 19, 2026
## Summary

`AGENTS.md` tells a contributor to follow the structure of `slack.yaml`
and `discord.yaml` when adding a network policy preset. PR #6129 moved
both files to
`src/lib/messaging/channels/<channel>/policy/<agent>.yaml`, so neither
name resolves under `nemoclaw-blueprint/policies/presets/`. This change
names two presets that exist in that directory today.

## Related Issue

Fixes #9542

## Changes

- `AGENTS.md:307` — replace the `slack.yaml` and `discord.yaml` examples
with `github.yaml` and `brave.yaml`.

One line in, one line out. No abstraction, configuration, fallback,
migration, or compatibility path is added.

**The diff touches one file, not two.** `CLAUDE.md` is a tracked symlink
to `AGENTS.md` (mode `120000`, blob content `AGENTS.md`), so `git diff
--stat` reports `1 file changed, 1 insertion(+), 1 deletion(-)` even
though both `AGENTS.md` and `CLAUDE.md` serve the corrected text. The
symlink blob is unchanged.

### Why the examples are stale

`git log --oneline --diff-filter=D --all` on both paths returns one
commit:

```
d13ef62 refactor(policy): move messaging policies into channels (#6129)
```

`git show --name-status d13ef62` records both as renames:

```
R100 nemoclaw-blueprint/policies/presets/discord.yaml -> src/lib/messaging/channels/discord/policy/openclaw.yaml
R100 nemoclaw-blueprint/policies/presets/slack.yaml   -> src/lib/messaging/channels/slack/policy/openclaw.yaml
```

`git ls-files nemoclaw-blueprint/policies/presets/ | grep -i
'slack\|discord'` returns nothing on `main`.

The stale examples do more than fail to resolve. They direct a
contributor adding a messaging-channel policy back into the directory
that #6129 emptied of messaging policies. `CLAUDE.md` resolves to this
file, so every agent session in this repository reads the guidance.

### Why `github.yaml` and `brave.yaml`

Both exist in the directory that the preceding line names. `brave.yaml`
uses the `protocol: rest` endpoint form with a `rules` list, which
matches the structure the removed `slack.yaml` had. `github.yaml` uses
the `access: full` form with a `binaries` list. The pair shows both
endpoint shapes the preset schema accepts.

### Why no line was added for messaging-channel policies

`src/lib/messaging/AGENTS.md:76` already instructs a contributor to add
or update `src/lib/messaging/channels/<channel>/policy/<agent>.yaml`,
and `AGENTS.md:48` already links that file.
`src/lib/policy/index.ts:112-115` and
`schemas/policy-preset.schema.json:5` state the same split in code. A
second bullet here would repeat guidance the repository already owns
elsewhere.

`AGENTS.md:306` (`nemoclaw-blueprint/policies/presets/`) remains
correct. `scripts/validate-configs.mts:127` reads that directory.

### Scope

I checked the rest of `AGENTS.md` for the same class of drift: every
backticked path-like token, every `npm run` script against both
`package.json` files, the Vitest project names, the commitlint type
list, the `engines.node` range, and the language column of the
architecture table. Line 307 was the only stale reference, so this PR
changes only that line.

## Type of Change

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

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: the change edits two
filenames in a contributor-guidance sentence. It changes no executable
code, no build input, and no behavior-affecting configuration. The claim
it makes is checked directly by `git ls-files
nemoclaw-blueprint/policies/presets/`.
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable — `npm run validate:pr` exits 0. Every hook
reports `Passed`, including `Codebase growth guardrails`, `Repository
checks`, `markdownlint-cli2`, `Source-shape test budget`, and
`TypeScript (CLI)`. I also ran `NEMOCLAW_GROWTH_BASE_REF=upstream/main
npx prek run --from-ref upstream/main --to-ref HEAD` for both the
`pre-commit` and `pre-push` stages (exit 0; the TypeScript hooks report
`no files to check`, which matches a one-line Markdown diff), and `npx
commitlint --from upstream/main --to HEAD` (exit 0).
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — marked not applicable above.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: not applicable; this PR
changes no runtime, test-harness, validation, or coverage input.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [x] `npm run docs` builds without warnings (doc changes only) — `npm
run docs` exits 0 and reports `check-docs-published-routes: OK — 68
guarded page(s), native changelog links, and direct legacy redirects`
and `Found 0 errors and 2 warnings`. Both warnings are pre-existing and
unrelated to this change: `Missing redirects check skipped: not
authenticated` (local run without `FERN_TOKEN`) and the light-mode
accent contrast ratio in the Fern theme. `AGENTS.md` is not an input to
the docs build, and `docs/_build/` is gitignored, so this change
produces no generated-file churn.
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only) — not applicable; `AGENTS.md` is repository guidance,
not a page under `docs/`.
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Net line change: `git diff --numstat` reports `1 1 AGENTS.md`. Net zero
lines.

---
Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Updated network policy preset guidance to reference the current GitHub
and Brave presets.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs Documentation, examples, guides, or docs build area: messaging Messaging channels, bridges, manifests, or channel lifecycle bug-fix PR fixes a bug or regression refactor PR restructures code without intended behavior change

Projects

None yet

2 participants