Skip to content

fix(messaging): inject Teams mention hints at runtime#5956

Merged
cv merged 15 commits into
mainfrom
fix/msteams-openclaw-skill
Jun 30, 2026
Merged

fix(messaging): inject Teams mention hints at runtime#5956
cv merged 15 commits into
mainfrom
fix/msteams-openclaw-skill

Conversation

@sandl99

@sandl99 sandl99 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR installs a Microsoft Teams-specific OpenClaw runtime preload that keeps native Teams mention syntax next to OpenClaw's message tool hints. The preload patches the pinned @openclaw/msteams prompt export at its exact package entry while preserving Teams startup if the upstream export changes or is immutable.

This supersedes #5864 because the issue is not a parser-spacing variant in NemoClaw. OpenClaw's Teams send path already parses the supported syntax into Teams mention entities; NemoClaw's failure mode is that the bot was often not prompted to use that syntax.

Related Issue

Replaces #5864.
Fixes #5852

Changes

  • Add a Teams OpenClaw msteams-message-hints runtime preload installed for boot and connect through the messaging runtime-preload machinery.
  • Restrict the CommonJS hook to the reviewed @openclaw/msteams/dist/channel-plugin-api.js boundary; plugin-shaped child dependencies and unrelated msteams paths remain untouched.
  • Restore the global load hook in finally after the exact entry attempt, whether patching succeeds, fails, or the module throws.
  • Fail open with one bounded static warning when the plugin export cannot be patched; never include upstream error text or make prompt guidance take Teams down.
  • Recognize the pinned openclaw.mjs gateway launcher shape without activating for arbitrary Node children whose third argument is gateway.
  • Cover CommonJS and native require(esm) entry loads, the real dist/index.js to channel-plugin-api.js flow, child-module isolation, idempotency, immutable exports, warning behavior, hook restoration, launcher gating, and unrelated ESM linking.
  • Remove the local regex reimplementation that previously overstated production Teams sender coverage.
  • Add a compiled package-contract regression that models the reviewed 2026.5.27 runtimeExtensions → OpenClaw createRequire → ESM channel-plugin-api.js load seam, binds it to the repository OpenClaw pin, records the manually reviewed package-load shape, and asserts the mention contract/order plus hook restoration without vendoring the upstream parser.

Source Boundary

The pinned OpenClaw 2026.5.27 package loads its Teams plugin through dist/channel-plugin-api.js, where msteamsPlugin.agentPrompt.messageToolHints is exported. NemoClaw changes only that prompt function. It does not fork or modify the Bot Framework sender or mention parser.

The manifest keeps the preload asset optional: false: a missing or mispackaged compiled file is a NemoClaw build/setup failure. After that asset loads, an upstream export-shape mismatch or immutable plugin is intentionally fail-open so Teams preserves upstream behavior, emits one bounded static warning, and starts without the additional prompt hint.

A repository test cannot honestly claim real Teams delivery or Bot Framework mention conversion without a provisioned Teams app, tenant, webhook, and live message. Vendoring third-party package code as a fixture would also create false production proof. The focused tests therefore lock the reviewed package export/lifecycle boundary, while live channels-stop-start and messaging-providers runs validate adjacent runtime installation and lifecycle. Actual mention conversion remains the pinned upstream package's contract; revalidate this preload whenever the OpenClaw pin changes, and remove it once upstream ships equivalent prompt guidance.

Sequencing note: #5595 upgrades the OpenClaw pin and overlaps the Teams manifest/compiler surface. If #5595 lands first or this PR is rebased across it, revalidate this package boundary and keep or remove the shim based on the new pinned package; do not assume the 2026.5.27 contract remains unchanged.

Release Decision

For v0.0.71, this PR is release-deferred. Both required exact-head advisor verdicts remain blocking (merge_after_fixes and needs_rework), and live Teams Bot Framework delivery proof is unavailable. Maintainers are not overriding either gate; do not merge this PR for v0.0.71.

The residual evidence gap is that repository tests cannot prove a Teams UI mention chip or user notification without a provisioned Teams tenant, app, and webhook. This PR changes only always-visible prompt guidance; it does not modify or claim automated proof of the Bot Framework sender/parser.

The pinned 2026.5.27 npm package and OpenClaw loader seam were manually reviewed. Hermetic CI enforces the repository pin, reviewed package-load shape, hint contract, and loader restoration, but that evidence does not satisfy the required delivery-proof gate. If production mentions still render raw IDs, the source fix belongs in the upstream Teams send path.

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: this restores expected Teams-native mention prompting automatically and adds no user action, command, configuration, environment variable, or support boundary.
  • 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: exact entry scoping, fail-open warning, lifecycle restoration, child-module isolation, and launcher gating were manually audited and regression-tested.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub
  • Git hooks passed during commit and push
  • Targeted tests pass for changed behavior — 47/47 across compiled package-contract, preload, channel-manifest, and compiler tests
  • 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)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Exact-head live evidence (head e120c86d):

Pre-follow-up live evidence (head 8149bce):


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

Summary by CodeRabbit

  • New Features

    • Improved Microsoft Teams message tool hints to consistently include native mention guidance.
    • Added automatic preloading of the Teams hint patch for both initial startup and reconnect phases.
  • Bug Fixes

    • Ensures the mention hint is injected only once and positioned before the first targeting-related hint.
    • Applies best-effort patching that won’t break unrelated module loading.
  • Tests

    • Expanded unit/contract coverage to verify CommonJS/ESM compatibility, idempotency, correct hint ordering, and safe loader behavior.

Signed-off-by: San Dang <sdang@nvidia.com>
@sandl99 sandl99 added the area: docs Documentation, examples, guides, or docs build label Jun 29, 2026
@sandl99 sandl99 self-assigned this Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 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

A new preload patches @openclaw/msteams message hints at load time, registers that preload in the Teams manifest, and adds contract and integration tests covering hint insertion, idempotency, and loader behavior.

Changes

Teams OpenClaw Mention Hint Patch

Layer / File(s) Summary
Runtime patch module
src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts
Adds the preload hook, plugin detection, hint wrapping logic, warning handling, and module-load restoration around @openclaw/msteams.
Teams manifest and compiler registration
src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/manifests.test.ts, src/lib/messaging/compiler/manifest-compiler.test.ts
Registers msteams-message-hints in runtime.openclaw.nodePreloads for boot and connect, and updates manifest/compiler assertions for the compiled preload entry.
Preload package contract test
test/package-contract/msteams-message-hints-preload.test.ts
Adds a package-boundary contract test that loads the compiled preload in a subprocess, checks hint order, and confirms Module._load is restored.
Preload behavior tests
test/openclaw-msteams-message-hints-patch.test.ts
Expands subprocess-based tests for CJS/ESM fixtures, idempotency, unrelated-module exclusion, formatter output, and relative ESM linking after preload installation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

integration: openclaw

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 matches the main change: injecting Teams mention hints at runtime for messaging.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/msteams-openclaw-skill

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

@github-code-quality

github-code-quality Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in the branch is 96%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File e120c86 +/-
nemoclaw/src/se...cret-scanner.ts 100%
nemoclaw/src/commands/slash.ts 100%
nemoclaw/src/li...bprocess-env.ts 100%
nemoclaw/src/bl...eprint/state.ts 98%
nemoclaw/src/onboard/config.ts 98%
nemoclaw/src/bl...int/snapshot.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 branch is 68%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File e120c86 +/-
src/lib/actions...all/run-plan.ts 80%
src/lib/state/o...oard-session.ts 79%
src/lib/actions...dbox/rebuild.ts 74%
src/lib/state/sandbox.ts 72%
src/lib/shields/index.ts 70%
src/lib/onboard/preflight.ts 69%
src/lib/actions...licy-channel.ts 60%
src/lib/onboard...er-gpu-patch.ts 59%
src/lib/policy/index.ts 52%
src/lib/onboard.ts 20%

Updated June 30, 2026 07:37 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-5: Fragile string-based module identification bypassable via hoisting/symlinks; then add or justify PRA-T1.
Open items: 9 required · 12 warnings · 2 suggestions · 8 test follow-ups
Since last review: 1 prior item resolved · 25 still apply · 3 new items found

Action checklist

  • PRA-5 Fix: Fragile string-based module identification bypassable via hoisting/symlinks in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:78
  • PRA-6 Fix: patchLoadedModule patches 4 export shapes without module identity verification in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:115
  • PRA-7 Fix: patchPlugin catches all errors silently — fail-open with no diagnostics in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138
  • PRA-8 Fix: Global Module._load hook persists after failed patch — affects all module resolution in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:165
  • PRA-9 Fix: Tests run against TypeScript source, not compiled JavaScript production artifact in test/openclaw-msteams-message-hints-patch.test.ts:19
  • PRA-10 Fix: Manifest optional:false but runtime fails open — guarantee mismatch in src/lib/messaging/channels/teams/manifest.ts:137
  • PRA-11 Fix: Security Category 2 FAIL: Input validation insufficient for Module._load trust boundary in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • PRA-12 Fix: Security Category 8 FAIL: Missing 7 critical negative tests for trust boundary in test/openclaw-msteams-message-hints-patch.test.ts:1
  • PRA-13 Fix: Security Category 9 FAIL: Holistic posture degraded by trust boundary violations in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • PRA-1 Resolve or justify: Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts
  • PRA-2 Resolve or justify: Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138
  • PRA-3 Resolve or justify: Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:154
  • PRA-4 Resolve or justify: Source-of-truth review needed: test/openclaw-msteams-message-hints-patch.test.ts
  • PRA-14 Resolve or justify: Preload is localized workaround without automated removal enforcement in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • PRA-15 Resolve or justify: Massive OpenClaw SDK stub scaffolding duplicated in test — extract to shared helper in test/openclaw-msteams-message-hints-patch.test.ts:1
  • PRA-16 Resolve or justify: Fail-open catch and conditional hook restoration are workaround behaviors without source-fix justification in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:75
  • PRA-17 Resolve or justify: @openclaw/msteams pinned but no npm audit/OSV scan on transitive deps in CI in nemoclaw/package.json:17
  • PRA-18 Resolve or justify: Single-use env var MSTEAMS_FILE leaks process-global state risk in test/openclaw-msteams-message-hints-patch.test.ts:80
  • PRA-19 Resolve or justify: Fragile console.log/JSON.parse stdout capture for result retrieval in test/openclaw-msteams-message-hints-patch.test.ts:103
  • 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: Tests run against TypeScript source, not compiled JavaScript production artifact
  • PRA-T7 Add or justify test follow-up: Single-use env var MSTEAMS_FILE leaks process-global state risk
  • PRA-T8 Add or justify test follow-up: Fragile console.log/JSON.parse stdout capture for result retrieval
  • PRA-22 In-scope improvement: Terminology inconsistency: 'Microsoft Entra ID object IDs' vs 'Teams user id or AAD object id' in docs/manage-sandboxes/messaging-channels.mdx:1
  • PRA-23 In-scope improvement: ES5 IIFE + var despite ES2022 target — inconsistent with codebase in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:40

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 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-4 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-5 Required security src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:78 Replace with canonical verification: require.resolve(request) to get absolute path, read package.json from that path, verify name === '@openclaw/msteams'. Cache resolved path per request. Handle ESM/CJS differences. Follow slack-channel-guard.ts pattern for targeted patching via Module._extensions['.js'] and Module.registerHooks.
PRA-6 Required correctness src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:115 Add package.json name verification inside patchLoadedModule as second gate. Only patch if module's package.json name === '@openclaw/msteams'. Use require('package.json') from resolved module path (requires PRA-4 fix first).
PRA-7 Required security src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138 Replace empty catch with diagnostic emission: console.error('[nemoclaw:msteams-hints] patch failed:', e). Make fail-closed (throw) since manifest declares optional: false. At minimum, log to stderr so it appears in sandbox logs.
PRA-8 Required security src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:165 Use targeted patching like slack-channel-guard.ts: Module._extensions['.js'] for CJS (file-targeted) + Module.registerHooks for ESM. Install patch only for @openclaw/msteams files. Restore immediately after patch attempt regardless of success. Add timeout-based restoration and max-attempts guard.
PRA-9 Required tests test/openclaw-msteams-message-hints-patch.test.ts:19 Add test that runs against compiled JavaScript output. Either: (a) add build step in test setup that compiles preloads via tsconfig.runtime-preloads.json and tests .js, or (b) add separate test file that requires compiled path and runs same assertions. Mirror nemoclaw-start-telegram-runtime.test.ts pattern which copies compiled .js to test location.
PRA-10 Required security src/lib/messaging/channels/teams/manifest.ts:137 Either: (a) change optional: true and add runtime warning diagnostic when patch fails, or (b) keep optional: false but make patchPlugin throw on failure (fail-closed) with clear error message. Option (b) aligns build-time and runtime guarantees.
PRA-11 Required security src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1 Implement canonical module verification: require.resolve(request) -> read package.json -> verify name === '@openclaw/msteams'. Cache result. Use targeted Module._extensions['.js'] + Module.registerHooks. Add diagnostic emission on patch failure. This fixes PRA-4, PRA-5, PRA-21, and this finding combined.
PRA-12 Required security test/openclaw-msteams-message-hints-patch.test.ts:1 Add 7 negative tests each verifying preload does NOT patch or behaves correctly under attack/adversarial conditions. Each test should be a separate it() block with clear attack vector description.
PRA-13 Required security src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1 Fix all Category 2, 5, 8 issues above. Add process gate (done), canonical verification, fail-closed patching, diagnostics, compiled-output test, align optional:false with fail-closed, automated removal check.
PRA-14 Resolve/justify architecture src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1 Document answers inline in preload header. Add automated version-pin test that fails when @openclaw/msteams version in nemoclaw/package.json exceeds known-good version without native hint. Ensure removal criterion actionable (e.g., version check in CI).
PRA-15 Resolve/justify architecture test/openclaw-msteams-message-hints-patch.test.ts:1 Extract fixture generation and probe runner to shared test helper under test/helpers/msteams-fixtures.ts or test/fixtures/. Reduces duplication and ensures consistent test patterns.
PRA-16 Resolve/justify architecture src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:75 Document answers inline at lines 75 and 151. If upstream fix is planned, add version gate test. If not, justify why workaround is permanent and add removal automation.
PRA-17 Resolve/justify security nemoclaw/package.json:17 Add CI step: npm audit --omit=dev (or OSV scanner) on nemoclaw/package.json transitive dependencies. Fail build on high/critical vulnerabilities. Verify all deps from trusted npm registry.
PRA-18 Resolve/justify tests test/openclaw-msteams-message-hints-patch.test.ts:80 Replace process.env.MSTEAMS_FILE with module-scoped const MSTEAMS_FILE = fixtureFile or embed fixture path directly in -e script template.
PRA-19 Resolve/justify tests test/openclaw-msteams-message-hints-patch.test.ts:103 Replace fragile console.log/JSON.parse stdout capture with file-based result passing (write result to temp file, read back).
PRA-20 Resolve/justify acceptance src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:14 Add E2E scenario test that sends a message with @[Display Name](id) through the Teams channel and verifies the Bot Framework payload contains a mention entity with type 'mention' and the correct user ID. Can be a contract test against the reviewed @openclaw/msteams send path.

🚨 Required before merge

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

PRA-5 Required — Fragile string-based module identification bypassable via hoisting/symlinks

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:78
  • Category: security
  • Problem: isOpenClawMSTeamsPackagePath() uses substring match on '/node_modules/@openclaw/msteams/' which is bypassable via: (1) malicious package '@evil/msteams' hoisted to root node_modules, (2) symlink traversal into target directory, (3) monorepo hoisting at different depths. No canonical verification of module identity before patching.
  • Impact: A compromised or misconfigured dependency could pass the string check and have its exports mutated by the preload, affecting all module resolution in the process. This is a Module._load trust boundary violation.
  • Required action: Replace with canonical verification: require.resolve(request) to get absolute path, read package.json from that path, verify name === '@openclaw/msteams'. Cache resolved path per request. Handle ESM/CJS differences. Follow slack-channel-guard.ts pattern for targeted patching via Module._extensions['.js'] and Module.registerHooks.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check isOpenClawMSTeamsPackagePath() at lines 78-82; create a test fixture with a hoisted/symlinked fake @openclaw/msteams package and verify it's rejected
  • Missing regression test: Negative test: create fixture with fake @openclaw/msteams at /node_modules/@evil/msteams hoisted to root, verify preload does not patch it
  • Done when: The required change is committed and verification passes: Check isOpenClawMSTeamsPackagePath() at lines 78-82; create a test fixture with a hoisted/symlinked fake @openclaw/msteams package and verify it's rejected.
  • Evidence: isOpenClawMSTeamsPackagePath() at lines 78-82 uses simple indexOf/endsWith string matching on user-controllable request/parent paths

PRA-6 Required — patchLoadedModule patches 4 export shapes without module identity verification

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:115
  • Category: correctness
  • Problem: patchLoadedModule blindly patches loaded.msteamsPlugin, loaded.default.msteamsPlugin, loaded.default, and loaded without verifying the loaded module is actually @openclaw/msteams. Combined with PRA-4, any module whose path passes the string check gets its exports probed and potentially mutated.
  • Impact: Non-target modules matching the fragile path pattern could have their exports corrupted, causing silent runtime failures in unrelated code.
  • Required action: Add package.json name verification inside patchLoadedModule as second gate. Only patch if module's package.json name === '@openclaw/msteams'. Use require('package.json') from resolved module path (requires PRA-4 fix first).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check patchLoadedModule() at lines 115-124; verify it has no canonical identity check before patching
  • Missing regression test: Negative test: load a module with matching path pattern but different package.json name, verify it is not patched
  • Done when: The required change is committed and verification passes: Check patchLoadedModule() at lines 115-124; verify it has no canonical identity check before patching.
  • Evidence: patchLoadedModule() at lines 115-124 probes 4 export shapes unconditionally after isOpenClawMSTeamsPackagePath check

PRA-7 Required — patchPlugin catches all errors silently — fail-open with no diagnostics

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138
  • Category: security
  • Problem: patchPlugin catches all errors and returns false (fail-open) with no diagnostic emission. If the plugin object is immutable (Object.freeze) or has a setter that throws, the patch silently fails and Teams starts without the mention hint. The manifest declares optional: false but runtime behaves as optional: true.
  • Impact: Upstream export shape changes or immutable plugins silently degrade Teams mention prompting without any observable signal in sandbox logs. Operators cannot diagnose why hints are missing.
  • Required action: Replace empty catch with diagnostic emission: console.error('[nemoclaw:msteams-hints] patch failed:', e). Make fail-closed (throw) since manifest declares optional: false. At minimum, log to stderr so it appears in sandbox logs.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check patchPlugin() catch block at lines 138-140; verify it logs nothing on failure
  • Missing regression test: Test: verify that when patch fails (e.g., upstream shape change), the runtime throws rather than silently continuing — aligns with optional: false
  • Done when: The required change is committed and verification passes: Check patchPlugin() catch block at lines 138-140; verify it logs nothing on failure.
  • Evidence: patchPlugin() catch block at line 138-140: '} catch (_e) { return false; }' with no logging

PRA-8 Required — Global Module._load hook persists after failed patch — affects all module resolution

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:165
  • Category: security
  • Problem: Global Module._load monkey-patch affects ALL module resolution in the process. Hook only restores on first successful patch (in finally block after first matching load). If the first @openclaw/msteams load fails to patch, the hook stays installed and intercepts all subsequent require() calls. Slack-channel-guard.ts uses targeted Module._extensions['.js'] for CJS and Module.registerHooks for ESM, patching only files under /@openclaw/slack/.
  • Impact: A failed patch on first load leaves a global hook that intercepts every subsequent module load, adding overhead and risk of interference with unrelated modules. No timeout or max-attempts guard.
  • Required action: Use targeted patching like slack-channel-guard.ts: Module._extensions['.js'] for CJS (file-targeted) + Module.registerHooks for ESM. Install patch only for @openclaw/msteams files. Restore immediately after patch attempt regardless of success. Add timeout-based restoration and max-attempts guard.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check Module._load assignment at line 165 and restoreLoadHook at lines 154-157; verify hook persists after failed patch
  • Missing regression test: Negative test: cause first @openclaw/msteams load to fail patch, then verify subsequent unrelated requires work normally and hook is restored
  • Done when: The required change is committed and verification passes: Check Module._load assignment at line 165 and restoreLoadHook at lines 154-157; verify hook persists after failed patch.
  • Evidence: Module._load = nemoclawMSTeamsLoad at line 165; restoreLoadHook only restores if Module._load === nemoclawMSTeamsLoad (line 155), called in finally after first matching load

PRA-9 Required — Tests run against TypeScript source, not compiled JavaScript production artifact

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:19
  • Category: tests
  • Problem: MSTEAMS_HINT_PRELOAD constant points to .ts file but production uses compiled JavaScript from /usr/local/lib/nemoclaw/preloads/. The package-contract test expects compiled output at dist/... but the main test suite does not. TypeScript-only behavior (type-only imports, non-standard syntax) could pass tests but fail at runtime.
  • Impact: Tests provide false confidence; the compiled output could have different behavior (e.g., removed type-only imports, transformed syntax) that breaks in production.
  • Required action: Add test that runs against compiled JavaScript output. Either: (a) add build step in test setup that compiles preloads via tsconfig.runtime-preloads.json and tests .js, or (b) add separate test file that requires compiled path and runs same assertions. Mirror nemoclaw-start-telegram-runtime.test.ts pattern which copies compiled .js to test location.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check MSTEAMS_HINT_PRELOAD constant at line 19 points to .ts file; verify no test runs against compiled .js
  • Missing regression test: Add test file that requires the compiled preload from dist/ and runs identical assertions
  • Done when: The required change is committed and verification passes: Check MSTEAMS_HINT_PRELOAD constant at line 19 points to .ts file; verify no test runs against compiled .js.
  • Evidence: Line 19: const MSTEAMS_HINT_PRELOAD = path.join(import.meta.dirname, '..', 'src', 'lib', 'messaging', 'channels', 'teams', 'runtime', 'msteams-message-hints.ts');

PRA-10 Required — Manifest optional:false but runtime fails open — guarantee mismatch

  • Location: src/lib/messaging/channels/teams/manifest.ts:137
  • Category: security
  • Problem: Manifest declares optional: false (build fails if missing) but preload fails open silently at runtime. This creates a false guarantee: setup-time check passes but runtime patch can silently do nothing. The slack-channel-guard.ts approach throws on unrecognized shapes (fail-closed).
  • Impact: Operators see successful setup (preload installed) but runtime silently degrades mention prompting. No alignment between build-time and runtime guarantees.
  • Required action: Either: (a) change optional: true and add runtime warning diagnostic when patch fails, or (b) keep optional: false but make patchPlugin throw on failure (fail-closed) with clear error message. Option (b) aligns build-time and runtime guarantees.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check manifest.ts line 137: optional: false; check preload patchPlugin catch block returns false silently
  • Missing regression test: Test: verify that when patch fails (e.g., upstream shape change), the build fails or runtime throws rather than silently continuing
  • Done when: The required change is committed and verification passes: Check manifest.ts line 137: optional: false; check preload patchPlugin catch block returns false silently.
  • Evidence: manifest.ts line 137: optional: false; preload patchPlugin catch returns false silently

PRA-11 Required — Security Category 2 FAIL: Input validation insufficient for Module._load trust boundary

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: security
  • Problem: The preload intercepts all module loads and decides whether to patch based on user-controllable request/parent paths. No canonical verification of module identity before patching. This is a trust boundary violation where untrusted input (module request path) controls security-critical patching behavior.
  • Impact: Any module loaded in the gateway process can influence whether the preload patches it by controlling its request path or parent filename. Combined with global hook scope, this is a broad trust boundary violation.
  • Required action: Implement canonical module verification: require.resolve(request) -> read package.json -> verify name === '@openclaw/msteams'. Cache result. Use targeted Module._extensions['.js'] + Module.registerHooks. Add diagnostic emission on patch failure. This fixes PRA-4, PRA-5, PRA-21, and this finding combined.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Review entire preload for any canonical identity verification before patching; none exists
  • Missing regression test: 7 negative tests each verifying preload does NOT patch under attack/adversarial conditions (hoisted fake, symlink traversal, monorepo hoisting, prototype pollution, ESM loader confusion, relative path traversal, malicious parent)
  • Done when: The required change is committed and verification passes: Review entire preload for any canonical identity verification before patching; none exists.
  • Evidence: Entire preload uses isOpenClawMSTeamsPackagePath string matching; no require.resolve + package.json verification

PRA-12 Required — Security Category 8 FAIL: Missing 7 critical negative tests for trust boundary

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:1
  • Category: security
  • Problem: Current tests cover: unrelated path, frozen plugin, non-gateway process, false launcher, ESM relative imports. Missing: (1) hoisted malicious @openclaw/msteams at different scope, (2) symlink traversal into target dir, (3) monorepo hoisting at different depth, (4) prototype pollution via patched module, (5) ESM loader hook confusion, (6) relative path traversal (../../@openclaw/msteams), (7) malicious parent filename injection.
  • Impact: No test coverage for the trust boundary attack vectors that PRA-4 identifies. A malicious or misconfigured dependency could bypass the patch targeting without detection.
  • Required action: Add 7 negative tests each verifying preload does NOT patch or behaves correctly under attack/adversarial conditions. Each test should be a separate it() block with clear attack vector description.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Count negative test cases in test file; verify coverage of 7 attack vectors listed
  • Missing regression test: 7 new it() blocks: hoisted fake package, symlink traversal, monorepo hoisting, prototype pollution, ESM loader confusion, relative path traversal, malicious parent filename
  • Done when: The required change is committed and verification passes: Count negative test cases in test file; verify coverage of 7 attack vectors listed.
  • Evidence: Test file has 13 it() blocks; none cover the 7 trust-boundary attack vectors

PRA-13 Required — Security Category 9 FAIL: Holistic posture degraded by trust boundary violations

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: security
  • Problem: The preload introduces a global Module._load hook that can be influenced by any loaded module's request path. No process gate for the hook installation (only gateway flavor check). No audit trail of patched modules. No max-attempts or timeout guard. The combination of PRA-4 through PRA-11 creates a surface where a compromised or misconfigured dependency could affect the patching behavior.
  • Impact: Cumulative risk: global hook + no canonical verification + fail-open + no compiled tests + missing negative tests = defense-in-depth failure for a security-critical patching mechanism.
  • Required action: Fix all Category 2, 5, 8 issues above. Add process gate (done), canonical verification, fail-closed patching, diagnostics, compiled-output test, align optional:false with fail-closed, automated removal check.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Review preload holistically: global hook, no canonical verification, fail-open, no compiled test, optional:false mismatch
  • Missing regression test: Integration test: full sandbox startup with Teams channel, verify mention hint present in actual message tool output
  • Done when: The required change is committed and verification passes: Review preload holistically: global hook, no canonical verification, fail-open, no compiled test, optional:false mismatch.
  • Evidence: All PRA-4 through PRA-11 findings compound
Review findings by urgency: 9 required fixes, 12 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/messaging/channels/teams/runtime/msteams-message-hints.ts

  • 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: Package-contract test locks reviewed artifact shape + hashes; version-pin test fails if pin changes
  • 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: Preload header lines 10-20 describe removal criterion but no CI automation exists

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138

  • 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: Frozen plugin test verifies warning + fail-open
  • 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: patchPlugin catch block at line 138: '} catch (_e) { return false; }' with no logging

PRA-3 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:154

  • 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: Restoration test passes only when first patch succeeds
  • 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: restoreLoadHook only restores if Module._load === nemoclawMSTeamsLoad (line 155), called in finally after first matching load

PRA-4 Resolve/justify — Source-of-truth review needed: test/openclaw-msteams-message-hints-patch.test.ts

  • 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: All 13 existing tests pass; need 7 more negative tests
  • 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: 150+ lines of inline fixture scaffolding; MSTEAMS_FILE env var; console.log/JSON.parse stdout capture

PRA-14 Resolve/justify — Preload is localized workaround without automated removal enforcement

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: architecture
  • Problem: Comment states 'Removal criterion: drop this preload once minimum @openclaw/msteams version includes native mention hint' but no CI check enforces this. The version pin in nemoclaw/package.json (2026.5.27) could drift without detection.
  • Impact: Workaround could persist indefinitely even after upstream adds native support, adding unnecessary complexity and attack surface.
  • Recommended action: Document answers inline in preload header. Add automated version-pin test that fails when @openclaw/msteams version in nemoclaw/package.json exceeds known-good version without native hint. Ensure removal criterion actionable (e.g., version check in CI).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check preload header comment for removal criterion; verify no CI job validates version pin against upstream native hint availability
  • Missing regression test: CI test: read @openclaw/msteams version from nemoclaw/package.json, fetch upstream package metadata, fail if version > known-good without native hint
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check preload header comment for removal criterion; verify no CI job validates version pin against upstream native hint availability.
  • Evidence: Preload header lines 10-20 describe removal criterion but no automation exists

PRA-15 Resolve/justify — Massive OpenClaw SDK stub scaffolding duplicated in test — extract to shared helper

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:1
  • Category: architecture
  • Problem: 150+ lines of fixture generation (pluginFixtureSource, writeMSTeamsPackage, writeMSTeamsEntryFlow, writeMSTeamsPackageWithPluginShapedChild, writeUnrelatedMSTeamsLikeModule, runHintsProbe) duplicated in single test file. Creates maintenance burden when upstream changes.
  • Impact: Duplicated scaffolding makes tests harder to maintain and increases risk of fixture drift from reality. Package-contract test duplicates similar logic.
  • Recommended action: Extract fixture generation and probe runner to shared test helper under test/helpers/msteams-fixtures.ts or test/fixtures/. Reduces duplication and ensures consistent test patterns.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check test file for fixture/helper duplication; 150+ lines of scaffolding in single test file
  • Missing regression test: N/A - refactor improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check test file for fixture/helper duplication; 150+ lines of scaffolding in single test file.
  • Evidence: Lines 30-130: pluginFixtureSource, writeMSTeamsPackage, writeMSTeamsEntryFlow, writeMSTeamsPackageWithPluginShapedChild, writeUnrelatedMSTeamsLikeModule, runHintsProbe

PRA-16 Resolve/justify — Fail-open catch and conditional hook restoration are workaround behaviors without source-fix justification

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:75
  • Category: architecture
  • Problem: The comment at line 75 says 'Runtime patching is deliberately best-effort' but doesn't answer: what invalid state is handled, where that state is created, why the source cannot be fixed in this PR, what regression test proves the source cannot regress, and when the workaround can be removed.
  • Impact: Workaround behaviors (fail-open, conditional restoration) are accepted without the required source-of-truth justification, making future removal or fix difficult to evaluate.
  • Recommended action: Document answers inline at lines 75 and 151. If upstream fix is planned, add version gate test. If not, justify why workaround is permanent and add removal automation.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check preload header comment and patchPlugin catch block for source-of-truth justification
  • Missing regression test: N/A - documentation/justification gap
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check preload header comment and patchPlugin catch block for source-of-truth justification.
  • Evidence: Header comment lines 10-20 and patchPlugin catch at line 138 lack the 5 required source-of-truth answers

PRA-17 Resolve/justify — @openclaw/msteams pinned but no npm audit/OSV scan on transitive deps in CI

  • Location: nemoclaw/package.json:17
  • Category: security
  • Problem: @openclaw/msteams@2026.5.27 pinned but no npm audit/OSV scan on transitive dependencies in CI. The package and its dependencies could have known vulnerabilities that go undetected.
  • Impact: Supply-chain vulnerability in transitive dependencies could go undetected until exploited.
  • Recommended action: Add CI step: npm audit --omit=dev (or OSV scanner) on nemoclaw/package.json transitive dependencies. Fail build on high/critical vulnerabilities. Verify all deps from trusted npm registry.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check .github/workflows/ for npm audit or OSV scanning step; none found
  • Missing regression test: CI job that runs npm audit on nemoclaw/package.json and fails on high/critical
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check .github/workflows/ for npm audit or OSV scanning step; none found.
  • Evidence: nemoclaw/package.json line 17 pins openclawVersion: 2026.5.27; no audit workflow found

PRA-18 Resolve/justify — Single-use env var MSTEAMS_FILE leaks process-global state risk

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:80
  • Category: tests
  • Problem: MSTEAMS_FILE env var used for test communication — process-global leak risk. The env var is set in spawnSync options but if tests run in parallel or leak, it could affect other tests or processes.
  • Impact: Parallel test runs could cross-contaminate fixture paths, causing flaky tests or false positives.
  • Recommended action: Replace process.env.MSTEAMS_FILE with module-scoped const MSTEAMS_FILE = fixtureFile or embed fixture path directly in -e script template.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check runHintsProbe() at lines 80-86; MSTEAMS_FILE passed via env object
  • Missing regression test: N/A - test infrastructure improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check runHintsProbe() at lines 80-86; MSTEAMS_FILE passed via env object.
  • Evidence: runHintsProbe() spawnSync env: { ...process.env, MSTEAMS_FILE: fixtureFile }

PRA-19 Resolve/justify — Fragile console.log/JSON.parse stdout capture for result retrieval

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:103
  • Category: tests
  • Problem: runHintsProbe uses console.log/JSON.parse stdout capture for result retrieval. If the preload or loaded module writes to stdout, JSON parsing fails. Should use file-based result passing or structured IPC.
  • Impact: Test flakiness when any loaded code writes to stdout. False negatives/positives from stdout pollution.
  • Recommended action: Replace fragile console.log/JSON.parse stdout capture with file-based result passing (write result to temp file, read back).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check runHintsProbe() script template at lines 103-110; console.log(JSON.stringify(...)) parsed from stdout
  • Missing regression test: N/A - test infrastructure improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check runHintsProbe() script template at lines 103-110; console.log(JSON.stringify(...)) parsed from stdout.
  • Evidence: Script template: 'console.log(JSON.stringify(plugin.agentPrompt.messageToolHints({ cfg: {} })));' parsed from stdout

PRA-20 Resolve/justify — No E2E test proving Teams mention renders as real mention chip (issue #5852)

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:14
  • Category: acceptance
  • Problem: The preload injects hint text into messageToolHints but there's no test verifying the actual Teams Bot Framework send path converts @[Display Name](id) into a native mention entity that renders as a mention chip in Teams client. Issue [macOS][Agent&Skills] MS Teams bot @mention renders raw AAD object ID instead of a display-name mention #5852 shows raw AAD object ID rendered instead of mention chip.
  • Impact: Prompt guidance added but no verification that the Bot Framework send path actually produces correct Teams mention entities. The underlying rendering bug may persist.
  • Recommended action: Add E2E scenario test that sends a message with @[Display Name](id) through the Teams channel and verifies the Bot Framework payload contains a mention entity with type 'mention' and the correct user ID. Can be a contract test against the reviewed @openclaw/msteams send path.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search test/e2e/ for Teams mention tests; none found
  • Missing regression test: E2E test: send message with @[Display Name](id) through Teams channel, verify Bot Framework activity.entities contains mention with correct user AAD ID
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search test/e2e/ for Teams mention tests; none found.
  • Evidence: Issue [macOS][Agent&Skills] MS Teams bot @mention renders raw AAD object ID instead of a display-name mention #5852 shows raw AAD ID rendered; preload only adds prompt hint, no send-path verification

PRA-21 Resolve/justify — Preload uses global Module._load instead of targeted Module._extensions/registerHooks like slack-channel-guard.ts

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: correctness
  • Problem: Preload uses global Module._load instead of targeted Module._extensions/registerHooks like slack-channel-guard.ts. The slack pattern is proven, scoped, and restores cleanly. The current approach is broader, riskier, and inconsistent with codebase precedent.
  • Impact: Inconsistent security architecture; global hook adds unnecessary risk surface. Slack pattern is proven in same codebase.
  • Recommended action: Refactor to use Module._extensions['.js'] for CJS (file-targeted) + Module.registerHooks for ESM, exactly like slack-channel-guard.ts lines 259-290. Only patch files under /@openclaw/msteams/.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Compare msteams-message-hints.ts Module._load approach (line 165) with slack-channel-guard.ts Module._extensions/registerHooks (lines 259-290)
  • Missing regression test: N/A - architecture alignment
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Compare msteams-message-hints.ts Module._load approach (line 165) with slack-channel-guard.ts Module._extensions/registerHooks (lines 259-290).
  • Evidence: Line 165: Module._load = nemoclawMSTeamsLoad vs slack-channel-guard.ts lines 259-290 using Module._extensions['.js'] + Module.registerHooks

💡 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-22 Improvement — Terminology inconsistency: 'Microsoft Entra ID object IDs' vs 'Teams user id or AAD object id'

  • Location: docs/manage-sandboxes/messaging-channels.mdx:1
  • Category: docs
  • Problem: Documentation mentions Microsoft Entra ID object IDs but preload hint says 'Teams user id or AAD object id'. The preload uses 'Teams user id or AAD object id' while docs say 'Microsoft Entra ID object IDs'. Minor inconsistency but could confuse operators.
  • Impact: Operator confusion about which ID format to use for TEAMS_ALLOWED_USERS.
  • Suggested action: Align terminology: either update preload to 'Microsoft Entra ID object ID' or update docs to mention both formats. Prefer Entra ID as Microsoft's current branding.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Compare preload MSTEAMS_MENTION_HINT constant with docs messaging-channels.mdx Teams section
  • Missing regression test: N/A - documentation consistency
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Preload line 14: 'Teams user id or AAD object id'; docs: 'Microsoft Entra ID object IDs'

PRA-23 Improvement — ES5 IIFE + var despite ES2022 target — inconsistent with codebase

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:40
  • Category: correctness
  • Problem: Preload uses ES5 IIFE + var despite ES2022 target; inconsistent with codebase. The file is compiled to ES2022 but written in ES5 style. Slack-channel-guard.ts uses the same pattern but this should be normalized if the codebase standard is modern syntax.
  • Impact: Code style inconsistency; harder to read and maintain. No functional impact but signals technical debt.
  • Suggested action: Either: (a) convert to modern IIFE with const/let and arrow functions, or (b) document why ES5 style is required (e.g., compatibility with older Node in sandbox). If no reason, use modern syntax for consistency.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check tsconfig for target; verify preload uses var/function instead of const/arrow
  • Missing regression test: N/A - style consistency
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Preload uses (function () { 'use strict'; var ... })(); pattern; tsconfig target is ES2022
Simplification opportunities: 19 possible cuts, net -43 lines possible

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

  • PRA-5 native (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:78): isOpenClawMSTeamsPackagePath() string matching logic (lines 78-82)
    • Replacement: require.resolve(request) + read package.json + verify name === '@openclaw/msteams' with caching
    • Net: -5 lines
    • Safety boundary: Must preserve exact entry targeting: only @openclaw/msteams/dist/channel-plugin-api.js load flow
  • PRA-6 native (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:115): Four unconditional patchPlugin calls on guessed export shapes
    • Replacement: Single patchPlugin call after canonical identity verification
    • Net: -10 lines
    • Safety boundary: Must still handle the reviewed @openclaw/msteams export shapes (default export, msteamsPlugin property)
  • PRA-7 stdlib (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138): Silent catch returning false
    • Replacement: console.error('[nemoclaw:msteams-hints] patch failed:', e); throw e;
    • Net: 0 lines
    • Safety boundary: Must not break Teams gateway startup if fail-open is intentional — but optional:false requires fail-closed
  • PRA-8 native (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:165): Global Module._load monkey-patch (lines 145-165)
    • Replacement: Module._extensions['.js'] for CJS + Module.registerHooks for ESM, file-targeted to /@openclaw/msteams/
    • Net: -20 lines
    • Safety boundary: Must preserve ESM/CJS dual support and hook restoration semantics from slack-channel-guard.ts
  • PRA-9 delete (test/openclaw-msteams-message-hints-patch.test.ts:19): Direct require of .ts file in tests
    • Replacement: Require compiled .js from dist/ or build step in test setup
    • Net: 0 lines
    • Safety boundary: Must test the exact artifact that runs in production sandboxes
  • PRA-10 shrink (src/lib/messaging/channels/teams/manifest.ts:137): optional: false with silent fail-open runtime
    • Replacement: optional: false with fail-closed patching (throw on failure)
    • Net: 0 lines
    • Safety boundary: Must not break Teams gateway if upstream genuinely changes — but then version pin should be updated
  • PRA-11 native (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1): String-based path matching trust boundary
    • Replacement: Canonical require.resolve + package.json name verification
    • Net: -10 lines
    • Safety boundary: Must only patch the reviewed @openclaw/msteams package entry point
  • PRA-12 shrink (test/openclaw-msteams-message-hints-patch.test.ts:1): N/A — adding tests
    • Replacement: Extract shared fixture helpers to test/helpers/msteams-fixtures.ts to reduce duplication while adding 7 new tests
    • Net: 100 lines
    • Safety boundary: Must not weaken existing positive test coverage
  • PRA-13 native (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1): Global Module._load hook architecture
    • Replacement: Targeted Module._extensions/registerHooks like slack-channel-guard.ts
    • Net: -20 lines
    • Safety boundary: Must preserve boot+connect injection via NODE_OPTIONS and gateway process gating
  • PRA-14 delete (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1): Manual removal criterion comment only
    • Replacement: Automated CI version-pin check + inline documentation of 5 source-of-truth questions
    • Net: 10 lines
    • Safety boundary: Must not remove preload until upstream actually provides equivalent hint
  • PRA-15 shrink (test/openclaw-msteams-message-hints-patch.test.ts:1): 150+ lines of inline fixture scaffolding
    • Replacement: Import from test/helpers/msteams-fixtures.ts
    • Net: -120 lines
    • Safety boundary: Must preserve exact fixture shapes and probe behavior for all 13 existing tests
  • PRA-16 yagni (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:75): Unjustified fail-open + conditional restoration
    • Replacement: Fail-closed with diagnostics (aligns with optional:false) + immediate hook restoration
    • Net: -5 lines
    • Safety boundary: Must not break Teams gateway if upstream shape genuinely changes unexpectedly
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 — Add test running against compiled JavaScript output (mirror nemoclaw-start-telegram-runtime.test.ts pattern). Runtime/sandbox/infrastructure paths need behavioral runtime validation: src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts. Tests run against TypeScript source not compiled output; missing 7 negative trust-boundary tests; no integration test for actual Teams mention rendering.
  • PRA-T2 Runtime validation — Add 7 negative trust-boundary tests: hoisted fake package, symlink traversal, monorepo hoisting, prototype pollution, ESM loader confusion, relative path traversal, malicious parent filename. Runtime/sandbox/infrastructure paths need behavioral runtime validation: src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts. Tests run against TypeScript source not compiled output; missing 7 negative trust-boundary tests; no integration test for actual Teams mention rendering.
  • PRA-T3 Runtime validation — Add integration test: full sandbox startup with Teams channel, verify mention hint present in actual message tool output. Runtime/sandbox/infrastructure paths need behavioral runtime validation: src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts. Tests run against TypeScript source not compiled output; missing 7 negative trust-boundary tests; no integration test for actual Teams mention rendering.
  • PRA-T4 Runtime validation — Add contract test against reviewed @openclaw/msteams send path verifying mention entity generation. Runtime/sandbox/infrastructure paths need behavioral runtime validation: src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts. Tests run against TypeScript source not compiled output; missing 7 negative trust-boundary tests; no integration test for actual Teams mention rendering.
  • PRA-T5 Runtime validation — Add CI version-pin test: fail when @openclaw/msteams version exceeds known-good without native hint. Runtime/sandbox/infrastructure paths need behavioral runtime validation: src/lib/messaging/channels/teams/manifest.ts, src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts. Tests run against TypeScript source not compiled output; missing 7 negative trust-boundary tests; no integration test for actual Teams mention rendering.
  • PRA-T6 Tests run against TypeScript source, not compiled JavaScript production artifact — Add test that runs against compiled JavaScript output. Either: (a) add build step in test setup that compiles preloads via tsconfig.runtime-preloads.json and tests .js, or (b) add separate test file that requires compiled path and runs same assertions. Mirror nemoclaw-start-telegram-runtime.test.ts pattern which copies compiled .js to test location.
  • PRA-T7 Single-use env var MSTEAMS_FILE leaks process-global state risk — Replace process.env.MSTEAMS_FILE with module-scoped const MSTEAMS_FILE = fixtureFile or embed fixture path directly in -e script template.
  • PRA-T8 Fragile console.log/JSON.parse stdout capture for result retrieval — Replace fragile console.log/JSON.parse stdout capture with file-based result passing (write result to temp file, read back).
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts

  • 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: Package-contract test locks reviewed artifact shape + hashes; version-pin test fails if pin changes
  • 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: Preload header lines 10-20 describe removal criterion but no CI automation exists

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138

  • 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: Frozen plugin test verifies warning + fail-open
  • 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: patchPlugin catch block at line 138: '} catch (_e) { return false; }' with no logging

PRA-3 Resolve/justify — Source-of-truth review needed: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:154

  • 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: Restoration test passes only when first patch succeeds
  • 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: restoreLoadHook only restores if Module._load === nemoclawMSTeamsLoad (line 155), called in finally after first matching load

PRA-4 Resolve/justify — Source-of-truth review needed: test/openclaw-msteams-message-hints-patch.test.ts

  • 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: All 13 existing tests pass; need 7 more negative tests
  • 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: 150+ lines of inline fixture scaffolding; MSTEAMS_FILE env var; console.log/JSON.parse stdout capture

PRA-5 Required — Fragile string-based module identification bypassable via hoisting/symlinks

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:78
  • Category: security
  • Problem: isOpenClawMSTeamsPackagePath() uses substring match on '/node_modules/@openclaw/msteams/' which is bypassable via: (1) malicious package '@evil/msteams' hoisted to root node_modules, (2) symlink traversal into target directory, (3) monorepo hoisting at different depths. No canonical verification of module identity before patching.
  • Impact: A compromised or misconfigured dependency could pass the string check and have its exports mutated by the preload, affecting all module resolution in the process. This is a Module._load trust boundary violation.
  • Required action: Replace with canonical verification: require.resolve(request) to get absolute path, read package.json from that path, verify name === '@openclaw/msteams'. Cache resolved path per request. Handle ESM/CJS differences. Follow slack-channel-guard.ts pattern for targeted patching via Module._extensions['.js'] and Module.registerHooks.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check isOpenClawMSTeamsPackagePath() at lines 78-82; create a test fixture with a hoisted/symlinked fake @openclaw/msteams package and verify it's rejected
  • Missing regression test: Negative test: create fixture with fake @openclaw/msteams at /node_modules/@evil/msteams hoisted to root, verify preload does not patch it
  • Done when: The required change is committed and verification passes: Check isOpenClawMSTeamsPackagePath() at lines 78-82; create a test fixture with a hoisted/symlinked fake @openclaw/msteams package and verify it's rejected.
  • Evidence: isOpenClawMSTeamsPackagePath() at lines 78-82 uses simple indexOf/endsWith string matching on user-controllable request/parent paths

PRA-6 Required — patchLoadedModule patches 4 export shapes without module identity verification

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:115
  • Category: correctness
  • Problem: patchLoadedModule blindly patches loaded.msteamsPlugin, loaded.default.msteamsPlugin, loaded.default, and loaded without verifying the loaded module is actually @openclaw/msteams. Combined with PRA-4, any module whose path passes the string check gets its exports probed and potentially mutated.
  • Impact: Non-target modules matching the fragile path pattern could have their exports corrupted, causing silent runtime failures in unrelated code.
  • Required action: Add package.json name verification inside patchLoadedModule as second gate. Only patch if module's package.json name === '@openclaw/msteams'. Use require('package.json') from resolved module path (requires PRA-4 fix first).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check patchLoadedModule() at lines 115-124; verify it has no canonical identity check before patching
  • Missing regression test: Negative test: load a module with matching path pattern but different package.json name, verify it is not patched
  • Done when: The required change is committed and verification passes: Check patchLoadedModule() at lines 115-124; verify it has no canonical identity check before patching.
  • Evidence: patchLoadedModule() at lines 115-124 probes 4 export shapes unconditionally after isOpenClawMSTeamsPackagePath check

PRA-7 Required — patchPlugin catches all errors silently — fail-open with no diagnostics

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:138
  • Category: security
  • Problem: patchPlugin catches all errors and returns false (fail-open) with no diagnostic emission. If the plugin object is immutable (Object.freeze) or has a setter that throws, the patch silently fails and Teams starts without the mention hint. The manifest declares optional: false but runtime behaves as optional: true.
  • Impact: Upstream export shape changes or immutable plugins silently degrade Teams mention prompting without any observable signal in sandbox logs. Operators cannot diagnose why hints are missing.
  • Required action: Replace empty catch with diagnostic emission: console.error('[nemoclaw:msteams-hints] patch failed:', e). Make fail-closed (throw) since manifest declares optional: false. At minimum, log to stderr so it appears in sandbox logs.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check patchPlugin() catch block at lines 138-140; verify it logs nothing on failure
  • Missing regression test: Test: verify that when patch fails (e.g., upstream shape change), the runtime throws rather than silently continuing — aligns with optional: false
  • Done when: The required change is committed and verification passes: Check patchPlugin() catch block at lines 138-140; verify it logs nothing on failure.
  • Evidence: patchPlugin() catch block at line 138-140: '} catch (_e) { return false; }' with no logging

PRA-8 Required — Global Module._load hook persists after failed patch — affects all module resolution

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:165
  • Category: security
  • Problem: Global Module._load monkey-patch affects ALL module resolution in the process. Hook only restores on first successful patch (in finally block after first matching load). If the first @openclaw/msteams load fails to patch, the hook stays installed and intercepts all subsequent require() calls. Slack-channel-guard.ts uses targeted Module._extensions['.js'] for CJS and Module.registerHooks for ESM, patching only files under /@openclaw/slack/.
  • Impact: A failed patch on first load leaves a global hook that intercepts every subsequent module load, adding overhead and risk of interference with unrelated modules. No timeout or max-attempts guard.
  • Required action: Use targeted patching like slack-channel-guard.ts: Module._extensions['.js'] for CJS (file-targeted) + Module.registerHooks for ESM. Install patch only for @openclaw/msteams files. Restore immediately after patch attempt regardless of success. Add timeout-based restoration and max-attempts guard.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check Module._load assignment at line 165 and restoreLoadHook at lines 154-157; verify hook persists after failed patch
  • Missing regression test: Negative test: cause first @openclaw/msteams load to fail patch, then verify subsequent unrelated requires work normally and hook is restored
  • Done when: The required change is committed and verification passes: Check Module._load assignment at line 165 and restoreLoadHook at lines 154-157; verify hook persists after failed patch.
  • Evidence: Module._load = nemoclawMSTeamsLoad at line 165; restoreLoadHook only restores if Module._load === nemoclawMSTeamsLoad (line 155), called in finally after first matching load

PRA-9 Required — Tests run against TypeScript source, not compiled JavaScript production artifact

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:19
  • Category: tests
  • Problem: MSTEAMS_HINT_PRELOAD constant points to .ts file but production uses compiled JavaScript from /usr/local/lib/nemoclaw/preloads/. The package-contract test expects compiled output at dist/... but the main test suite does not. TypeScript-only behavior (type-only imports, non-standard syntax) could pass tests but fail at runtime.
  • Impact: Tests provide false confidence; the compiled output could have different behavior (e.g., removed type-only imports, transformed syntax) that breaks in production.
  • Required action: Add test that runs against compiled JavaScript output. Either: (a) add build step in test setup that compiles preloads via tsconfig.runtime-preloads.json and tests .js, or (b) add separate test file that requires compiled path and runs same assertions. Mirror nemoclaw-start-telegram-runtime.test.ts pattern which copies compiled .js to test location.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check MSTEAMS_HINT_PRELOAD constant at line 19 points to .ts file; verify no test runs against compiled .js
  • Missing regression test: Add test file that requires the compiled preload from dist/ and runs identical assertions
  • Done when: The required change is committed and verification passes: Check MSTEAMS_HINT_PRELOAD constant at line 19 points to .ts file; verify no test runs against compiled .js.
  • Evidence: Line 19: const MSTEAMS_HINT_PRELOAD = path.join(import.meta.dirname, '..', 'src', 'lib', 'messaging', 'channels', 'teams', 'runtime', 'msteams-message-hints.ts');

PRA-10 Required — Manifest optional:false but runtime fails open — guarantee mismatch

  • Location: src/lib/messaging/channels/teams/manifest.ts:137
  • Category: security
  • Problem: Manifest declares optional: false (build fails if missing) but preload fails open silently at runtime. This creates a false guarantee: setup-time check passes but runtime patch can silently do nothing. The slack-channel-guard.ts approach throws on unrecognized shapes (fail-closed).
  • Impact: Operators see successful setup (preload installed) but runtime silently degrades mention prompting. No alignment between build-time and runtime guarantees.
  • Required action: Either: (a) change optional: true and add runtime warning diagnostic when patch fails, or (b) keep optional: false but make patchPlugin throw on failure (fail-closed) with clear error message. Option (b) aligns build-time and runtime guarantees.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check manifest.ts line 137: optional: false; check preload patchPlugin catch block returns false silently
  • Missing regression test: Test: verify that when patch fails (e.g., upstream shape change), the build fails or runtime throws rather than silently continuing
  • Done when: The required change is committed and verification passes: Check manifest.ts line 137: optional: false; check preload patchPlugin catch block returns false silently.
  • Evidence: manifest.ts line 137: optional: false; preload patchPlugin catch returns false silently

PRA-11 Required — Security Category 2 FAIL: Input validation insufficient for Module._load trust boundary

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: security
  • Problem: The preload intercepts all module loads and decides whether to patch based on user-controllable request/parent paths. No canonical verification of module identity before patching. This is a trust boundary violation where untrusted input (module request path) controls security-critical patching behavior.
  • Impact: Any module loaded in the gateway process can influence whether the preload patches it by controlling its request path or parent filename. Combined with global hook scope, this is a broad trust boundary violation.
  • Required action: Implement canonical module verification: require.resolve(request) -> read package.json -> verify name === '@openclaw/msteams'. Cache result. Use targeted Module._extensions['.js'] + Module.registerHooks. Add diagnostic emission on patch failure. This fixes PRA-4, PRA-5, PRA-21, and this finding combined.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Review entire preload for any canonical identity verification before patching; none exists
  • Missing regression test: 7 negative tests each verifying preload does NOT patch under attack/adversarial conditions (hoisted fake, symlink traversal, monorepo hoisting, prototype pollution, ESM loader confusion, relative path traversal, malicious parent)
  • Done when: The required change is committed and verification passes: Review entire preload for any canonical identity verification before patching; none exists.
  • Evidence: Entire preload uses isOpenClawMSTeamsPackagePath string matching; no require.resolve + package.json verification

PRA-12 Required — Security Category 8 FAIL: Missing 7 critical negative tests for trust boundary

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:1
  • Category: security
  • Problem: Current tests cover: unrelated path, frozen plugin, non-gateway process, false launcher, ESM relative imports. Missing: (1) hoisted malicious @openclaw/msteams at different scope, (2) symlink traversal into target dir, (3) monorepo hoisting at different depth, (4) prototype pollution via patched module, (5) ESM loader hook confusion, (6) relative path traversal (../../@openclaw/msteams), (7) malicious parent filename injection.
  • Impact: No test coverage for the trust boundary attack vectors that PRA-4 identifies. A malicious or misconfigured dependency could bypass the patch targeting without detection.
  • Required action: Add 7 negative tests each verifying preload does NOT patch or behaves correctly under attack/adversarial conditions. Each test should be a separate it() block with clear attack vector description.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Count negative test cases in test file; verify coverage of 7 attack vectors listed
  • Missing regression test: 7 new it() blocks: hoisted fake package, symlink traversal, monorepo hoisting, prototype pollution, ESM loader confusion, relative path traversal, malicious parent filename
  • Done when: The required change is committed and verification passes: Count negative test cases in test file; verify coverage of 7 attack vectors listed.
  • Evidence: Test file has 13 it() blocks; none cover the 7 trust-boundary attack vectors

PRA-13 Required — Security Category 9 FAIL: Holistic posture degraded by trust boundary violations

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: security
  • Problem: The preload introduces a global Module._load hook that can be influenced by any loaded module's request path. No process gate for the hook installation (only gateway flavor check). No audit trail of patched modules. No max-attempts or timeout guard. The combination of PRA-4 through PRA-11 creates a surface where a compromised or misconfigured dependency could affect the patching behavior.
  • Impact: Cumulative risk: global hook + no canonical verification + fail-open + no compiled tests + missing negative tests = defense-in-depth failure for a security-critical patching mechanism.
  • Required action: Fix all Category 2, 5, 8 issues above. Add process gate (done), canonical verification, fail-closed patching, diagnostics, compiled-output test, align optional:false with fail-closed, automated removal check.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Review preload holistically: global hook, no canonical verification, fail-open, no compiled test, optional:false mismatch
  • Missing regression test: Integration test: full sandbox startup with Teams channel, verify mention hint present in actual message tool output
  • Done when: The required change is committed and verification passes: Review preload holistically: global hook, no canonical verification, fail-open, no compiled test, optional:false mismatch.
  • Evidence: All PRA-4 through PRA-11 findings compound

PRA-14 Resolve/justify — Preload is localized workaround without automated removal enforcement

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:1
  • Category: architecture
  • Problem: Comment states 'Removal criterion: drop this preload once minimum @openclaw/msteams version includes native mention hint' but no CI check enforces this. The version pin in nemoclaw/package.json (2026.5.27) could drift without detection.
  • Impact: Workaround could persist indefinitely even after upstream adds native support, adding unnecessary complexity and attack surface.
  • Recommended action: Document answers inline in preload header. Add automated version-pin test that fails when @openclaw/msteams version in nemoclaw/package.json exceeds known-good version without native hint. Ensure removal criterion actionable (e.g., version check in CI).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check preload header comment for removal criterion; verify no CI job validates version pin against upstream native hint availability
  • Missing regression test: CI test: read @openclaw/msteams version from nemoclaw/package.json, fetch upstream package metadata, fail if version > known-good without native hint
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check preload header comment for removal criterion; verify no CI job validates version pin against upstream native hint availability.
  • Evidence: Preload header lines 10-20 describe removal criterion but no automation exists

PRA-15 Resolve/justify — Massive OpenClaw SDK stub scaffolding duplicated in test — extract to shared helper

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:1
  • Category: architecture
  • Problem: 150+ lines of fixture generation (pluginFixtureSource, writeMSTeamsPackage, writeMSTeamsEntryFlow, writeMSTeamsPackageWithPluginShapedChild, writeUnrelatedMSTeamsLikeModule, runHintsProbe) duplicated in single test file. Creates maintenance burden when upstream changes.
  • Impact: Duplicated scaffolding makes tests harder to maintain and increases risk of fixture drift from reality. Package-contract test duplicates similar logic.
  • Recommended action: Extract fixture generation and probe runner to shared test helper under test/helpers/msteams-fixtures.ts or test/fixtures/. Reduces duplication and ensures consistent test patterns.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check test file for fixture/helper duplication; 150+ lines of scaffolding in single test file
  • Missing regression test: N/A - refactor improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check test file for fixture/helper duplication; 150+ lines of scaffolding in single test file.
  • Evidence: Lines 30-130: pluginFixtureSource, writeMSTeamsPackage, writeMSTeamsEntryFlow, writeMSTeamsPackageWithPluginShapedChild, writeUnrelatedMSTeamsLikeModule, runHintsProbe

PRA-16 Resolve/justify — Fail-open catch and conditional hook restoration are workaround behaviors without source-fix justification

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:75
  • Category: architecture
  • Problem: The comment at line 75 says 'Runtime patching is deliberately best-effort' but doesn't answer: what invalid state is handled, where that state is created, why the source cannot be fixed in this PR, what regression test proves the source cannot regress, and when the workaround can be removed.
  • Impact: Workaround behaviors (fail-open, conditional restoration) are accepted without the required source-of-truth justification, making future removal or fix difficult to evaluate.
  • Recommended action: Document answers inline at lines 75 and 151. If upstream fix is planned, add version gate test. If not, justify why workaround is permanent and add removal automation.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check preload header comment and patchPlugin catch block for source-of-truth justification
  • Missing regression test: N/A - documentation/justification gap
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check preload header comment and patchPlugin catch block for source-of-truth justification.
  • Evidence: Header comment lines 10-20 and patchPlugin catch at line 138 lack the 5 required source-of-truth answers

PRA-17 Resolve/justify — @openclaw/msteams pinned but no npm audit/OSV scan on transitive deps in CI

  • Location: nemoclaw/package.json:17
  • Category: security
  • Problem: @openclaw/msteams@2026.5.27 pinned but no npm audit/OSV scan on transitive dependencies in CI. The package and its dependencies could have known vulnerabilities that go undetected.
  • Impact: Supply-chain vulnerability in transitive dependencies could go undetected until exploited.
  • Recommended action: Add CI step: npm audit --omit=dev (or OSV scanner) on nemoclaw/package.json transitive dependencies. Fail build on high/critical vulnerabilities. Verify all deps from trusted npm registry.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check .github/workflows/ for npm audit or OSV scanning step; none found
  • Missing regression test: CI job that runs npm audit on nemoclaw/package.json and fails on high/critical
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check .github/workflows/ for npm audit or OSV scanning step; none found.
  • Evidence: nemoclaw/package.json line 17 pins openclawVersion: 2026.5.27; no audit workflow found

PRA-18 Resolve/justify — Single-use env var MSTEAMS_FILE leaks process-global state risk

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:80
  • Category: tests
  • Problem: MSTEAMS_FILE env var used for test communication — process-global leak risk. The env var is set in spawnSync options but if tests run in parallel or leak, it could affect other tests or processes.
  • Impact: Parallel test runs could cross-contaminate fixture paths, causing flaky tests or false positives.
  • Recommended action: Replace process.env.MSTEAMS_FILE with module-scoped const MSTEAMS_FILE = fixtureFile or embed fixture path directly in -e script template.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check runHintsProbe() at lines 80-86; MSTEAMS_FILE passed via env object
  • Missing regression test: N/A - test infrastructure improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check runHintsProbe() at lines 80-86; MSTEAMS_FILE passed via env object.
  • Evidence: runHintsProbe() spawnSync env: { ...process.env, MSTEAMS_FILE: fixtureFile }

PRA-19 Resolve/justify — Fragile console.log/JSON.parse stdout capture for result retrieval

  • Location: test/openclaw-msteams-message-hints-patch.test.ts:103
  • Category: tests
  • Problem: runHintsProbe uses console.log/JSON.parse stdout capture for result retrieval. If the preload or loaded module writes to stdout, JSON parsing fails. Should use file-based result passing or structured IPC.
  • Impact: Test flakiness when any loaded code writes to stdout. False negatives/positives from stdout pollution.
  • Recommended action: Replace fragile console.log/JSON.parse stdout capture with file-based result passing (write result to temp file, read back).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Check runHintsProbe() script template at lines 103-110; console.log(JSON.stringify(...)) parsed from stdout
  • Missing regression test: N/A - test infrastructure improvement
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Check runHintsProbe() script template at lines 103-110; console.log(JSON.stringify(...)) parsed from stdout.
  • Evidence: Script template: 'console.log(JSON.stringify(plugin.agentPrompt.messageToolHints({ cfg: {} })));' parsed from stdout

PRA-20 Resolve/justify — No E2E test proving Teams mention renders as real mention chip (issue #5852)

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:14
  • Category: acceptance
  • Problem: The preload injects hint text into messageToolHints but there's no test verifying the actual Teams Bot Framework send path converts @[Display Name](id) into a native mention entity that renders as a mention chip in Teams client. Issue [macOS][Agent&Skills] MS Teams bot @mention renders raw AAD object ID instead of a display-name mention #5852 shows raw AAD object ID rendered instead of mention chip.
  • Impact: Prompt guidance added but no verification that the Bot Framework send path actually produces correct Teams mention entities. The underlying rendering bug may persist.
  • Recommended action: Add E2E scenario test that sends a message with @[Display Name](id) through the Teams channel and verifies the Bot Framework payload contains a mention entity with type 'mention' and the correct user ID. Can be a contract test against the reviewed @openclaw/msteams send path.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Search test/e2e/ for Teams mention tests; none found
  • Missing regression test: E2E test: send message with @[Display Name](id) through Teams channel, verify Bot Framework activity.entities contains mention with correct user AAD ID
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Search test/e2e/ for Teams mention tests; none found.
  • Evidence: Issue [macOS][Agent&Skills] MS Teams bot @mention renders raw AAD object ID instead of a display-name mention #5852 shows raw AAD ID rendered; preload only adds prompt hint, no send-path verification

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.

@sandl99 sandl99 added area: messaging Messaging channels, bridges, manifests, or channel lifecycle bug-fix PR fixes a bug or regression labels Jun 29, 2026
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: channels-stop-start
Optional E2E: messaging-providers

Dispatch hint: channels-stop-start

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: medium

Required E2E

  • channels-stop-start (high): Closest existing live coverage for messaging channel lifecycle and runtime setup: runs real OpenClaw/Hermes sandbox channel stop/start, rebuild, provider reuse, registry, policy-list, and in-sandbox config contracts. The Teams manifest change adds a runtime nodePreload that is applied through the same channel runtime setup path.

Optional E2E

  • messaging-providers (high): Useful adjacent confidence for built-in messaging provider placeholder, policy, runtime, and send contracts in a real sandbox. It does not directly exercise Teams, but it can catch regressions in shared messaging plan/runtime plumbing.

New E2E recommendations

  • teams-openclaw-message-hints-runtime (high): No existing live E2E appears to exercise Microsoft Teams/msteams. The current required job only covers adjacent messaging runtime setup. Add a Teams-focused OpenClaw E2E that enables the Teams channel with fake app credentials, verifies the packaged msteams-message-hints preload is installed into NODE_OPTIONS during boot/connect, and probes the real @openclaw/msteams messageToolHints surface for the native mention hint without requiring a live Teams tenant.
    • Suggested test: Add a free-standing E2E job for Teams message-hints preload/runtime contract

Dispatch hint

  • Workflow: E2E
  • jobs input: channels-stop-start

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Recommendation

Required Vitest E2E scenarios: None
Optional Vitest E2E scenarios: None

Workflow run

Full Vitest E2E advisor summary

Vitest E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required Vitest E2E scenarios

  • None. This PR changes Microsoft Teams messaging manifest/runtime preload behavior, but the trusted Vitest scenario workflow/registry does not currently expose a live-supported Teams/MSTeams typed scenario or free-standing Teams Vitest job. Existing Vitest messaging jobs found in e2e-vitest-scenarios.yaml target Telegram/Discord/Slack/channel lifecycle surfaces and would not prove this Teams-specific preload behavior.

Optional Vitest E2E scenarios

  • None.

Relevant changed files

  • src/lib/messaging/channels/teams/manifest.ts
  • src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Changes requested

Merge posture: Do not merge yet
Primary next action: Fix PRA-2: Prove the production Teams mention delivery contract; then add or justify PRA-T1.
Open items: 1 required · 2 warnings · 0 suggestions · 8 test follow-ups
Since last review: 0 prior items resolved · 2 still apply · 0 new items found

Action checklist

  • PRA-2 Fix: Prove the production Teams mention delivery contract in test/package-contract/msteams-message-hints-preload.test.ts:114
  • PRA-1 Resolve or justify: Source-of-truth review needed: Teams OpenClaw runtime message-hint preload
  • PRA-3 Resolve or justify: Source-of-truth premise for the Teams preload remains only partially proven in src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:11
  • 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: Acceptance clause
  • 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 Required acceptance test/package-contract/msteams-message-hints-preload.test.ts:114 Add production-boundary evidence in this PR. Prefer a focused test that imports or otherwise validates the actual pinned `@openclaw/msteams` channel-plugin-api/send path and asserts that `@[Display Name](AAD_OBJECT_ID)` produces activity text containing `<at>Display Name</at>`, a Teams mention entity for the AAD object ID, and no raw UUID in `activity.text`. If that cannot be executed in repository tests, keep the package-shape fixture but add a precise reviewed-artifact assertion and record the remaining live-delivery gap as an explicit maintainer acceptance decision.
PRA-3 Resolve/justify architecture src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:11 Either prove the upstream parser/send contract with the actual pinned package, or make the remaining live-delivery and artifact-review gap explicit as an accepted limitation. Also either assert the recorded artifact hashes against a reviewed package source in the package-contract test, or reword/remove them so they are not mistaken for automated provenance coverage.

🚨 Required before merge

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

PRA-2 Required — Prove the production Teams mention delivery contract

  • Location: test/package-contract/msteams-message-hints-preload.test.ts:114
  • Category: acceptance
  • Problem: The changed tests now strongly cover the preload's loader mechanics and a reviewed synthetic package-load seam, but they still stop at inserting a prompt hint. The linked issue is about the actual Teams reply: a display-name native mention chip, no visible raw AAD UUID, and a user ping. This test explicitly says it does not claim Bot Framework sender/parser coverage, and the changed code only wraps `agentPrompt.messageToolHints`.
  • Impact: This PR can pass while the user-visible bug remains: the model may receive the hint, but if the pinned `@openclaw/msteams` send/parser path does not convert `@[Display Name](AAD_OBJECT_ID)` into Teams activity text plus a mention entity, Teams can still show the raw UUID and fail to notify the user.
  • Required action: Add production-boundary evidence in this PR. Prefer a focused test that imports or otherwise validates the actual pinned `@openclaw/msteams` channel-plugin-api/send path and asserts that `@[Display Name](AAD_OBJECT_ID)` produces activity text containing `<at>Display Name</at>`, a Teams mention entity for the AAD object ID, and no raw UUID in `activity.text`. If that cannot be executed in repository tests, keep the package-shape fixture but add a precise reviewed-artifact assertion and record the remaining live-delivery gap as an explicit maintainer acceptance decision.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:54-55` and `test/package-contract/msteams-message-hints-preload.test.ts:26-27,114`; then grep the changed tests for `<at>`, `mention entity`, or raw UUID exclusion. The current assertions cover prompt hints and hook restoration, not outgoing Bot Framework activity shape.
  • Missing regression test: Add tests named `production @openclaw/msteams mention send path converts @[Display Name](AAD_OBJECT_ID) into <at>Display Name</at> plus a Teams mention entity` and `production Teams send activity text excludes the raw AAD UUID when mention syntax is used`.
  • Done when: The required change is committed and verification passes: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:54-55` and `test/package-contract/msteams-message-hints-preload.test.ts:26-27,114`; then grep the changed tests for `<at>`, `mention entity`, or raw UUID exclusion. The current assertions cover prompt hints and hook restoration, not outgoing Bot Framework activity shape.
  • Evidence: `msteams-message-hints.ts:54-55` adds only `- MSTeams mentions: use \`@[Display Name](Teams user id or AAD object id)\`` to message tool hints. `msteams-message-hints-preload.test.ts:26-27` states the fixture models only the package/load boundary and does not vendor or claim to test the upstream Bot Framework send/parser code.
Review findings by urgency: 1 required fix, 2 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: Teams OpenClaw runtime message-hint preload

  • 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: The changed tests cover CJS and require(esm) prompt wrapping, gateway scoping, package-load seam, child-module isolation, idempotency, immutable-plugin warning, hook restoration, and OpenClaw pin re-review. Missing are tests against the actual pinned package send/parser contract and automated validation of the recorded artifact hashes.
  • 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: `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` documents the workaround and removal condition; `test/package-contract/msteams-message-hints-preload.test.ts:26-27` explicitly limits coverage to the package/load boundary and excludes Bot Framework sender/parser proof.

PRA-3 Resolve/justify — Source-of-truth premise for the Teams preload remains only partially proven

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:11
  • Category: architecture
  • Problem: This PR adds a localized runtime monkeypatch around the upstream Teams plugin. The file documents the invalid state, source boundary, fail-open behavior, and removal condition, and the tests cover the loader lifecycle. The remaining unverified source-of-truth premise is the comment that the upstream send path already parses `@[Display Name](Teams user id or AAD object id)` into Teams mention entities. The package-contract test also records reviewed artifact integrity and SHA-256 constants, but does not compute or compare those hashes against an actual reviewed artifact in the test.
  • Impact: A localized compatibility patch can hide the real source boundary if the upstream parser contract or reviewed package artifact drifts. Maintainers may believe the issue is fixed by prompt guidance while the actual Teams delivery path remains unverified.
  • Recommended action: Either prove the upstream parser/send contract with the actual pinned package, or make the remaining live-delivery and artifact-review gap explicit as an accepted limitation. Also either assert the recorded artifact hashes against a reviewed package source in the package-contract test, or reword/remove them so they are not mistaken for automated provenance coverage.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` for the workaround/source-boundary comments and `test/package-contract/msteams-message-hints-preload.test.ts:28-35` for the integrity/SHA constants. The test only checks `readPinnedOpenClawVersion()` and the synthetic package shape; it does not validate those constants against an artifact.
  • Missing regression test: Add `reviewed @openclaw/msteams package artifact hashes match the recorded runtime extension and channel-plugin-api SHA-256 values` and `preload patches the actual pinned @openclaw/msteams channel-plugin-api entrypoint before agentPrompt.messageToolHints is read`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` for the workaround/source-boundary comments and `test/package-contract/msteams-message-hints-preload.test.ts:28-35` for the integrity/SHA constants. The test only checks `readPinnedOpenClawVersion()` and the synthetic package shape; it does not validate those constants against an artifact.
  • Evidence: `msteams-message-hints.ts:11-12` states the upstream send path already parses mention syntax, while `msteams-message-hints-preload.test.ts:26-27` disclaims upstream sender/parser coverage and `:28-35` defines artifact hash constants without assertions against a real artifact.

💡 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: 1 possible cut

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

  • PRA-3 shrink (src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:11): Documentation-only `npmIntegrity`, `indexSha256`, and `pluginEntrySha256` constants if they remain unasserted.
    • Replacement: Either assert those constants against the reviewed artifact or reword them as manual-review notes so the test does not imply automated provenance validation.
    • Safety boundary: Do not remove the OpenClaw pin-change test, package-load seam coverage, loader scoping checks, or hook-restoration tests.
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 — production @openclaw/msteams mention send path converts @[Display Name](AAD_OBJECT_ID) into <at>Display Name</at> plus a Teams mention entity. The changed source affects OpenClaw runtime preload installation and a process-global Node loader hook inside the Teams gateway. Mechanical unit/contract coverage is strong, but linked-issue acceptance still depends on the production `@openclaw/msteams` send/parser boundary and Teams/Bot Framework activity shape.
  • PRA-T2 Runtime validation — production Teams send activity text excludes the raw AAD UUID when mention syntax is used. The changed source affects OpenClaw runtime preload installation and a process-global Node loader hook inside the Teams gateway. Mechanical unit/contract coverage is strong, but linked-issue acceptance still depends on the production `@openclaw/msteams` send/parser boundary and Teams/Bot Framework activity shape.
  • PRA-T3 Runtime validation — preload patches the actual pinned @openclaw/msteams channel-plugin-api entrypoint before agentPrompt.messageToolHints is read. The changed source affects OpenClaw runtime preload installation and a process-global Node loader hook inside the Teams gateway. Mechanical unit/contract coverage is strong, but linked-issue acceptance still depends on the production `@openclaw/msteams` send/parser boundary and Teams/Bot Framework activity shape.
  • PRA-T4 Runtime validation — reviewed @openclaw/msteams package artifact hashes match the recorded runtime extension and channel-plugin-api SHA-256 values. The changed source affects OpenClaw runtime preload installation and a process-global Node loader hook inside the Teams gateway. Mechanical unit/contract coverage is strong, but linked-issue acceptance still depends on the production `@openclaw/msteams` send/parser boundary and Teams/Bot Framework activity shape.
  • PRA-T5 Acceptance clause — When the MS Teams bot tries to @-mention a user, the reply shows the raw Entra/AAD object ID as text instead of rendering a proper Teams @mention chip with the person's display name. — add test evidence or identify existing coverage. The preload adds guidance to use `@[Display Name](Teams user id or AAD object id)` in `message`, and tests assert the hint is inserted. No changed test verifies the actual Teams reply renders as a display-name mention chip or that the raw AAD ID is absent from the sent activity.
  • PRA-T6 Acceptance clause — The mention also does not render as a real (highlighted) Teams mention. — add test evidence or identify existing coverage. No changed code or test asserts rendered/highlighted Teams native mention behavior; coverage is limited to prompt hint insertion and loader mechanics.
  • PRA-T7 Acceptance clause — 1. Onboard a sandbox with the Teams channel; set `TEAMS_ALLOWED_USERS` to AAD object IDs. — add test evidence or identify existing coverage. The Teams manifest continues to render `TEAMS_ALLOWED_USERS={{allowedIds.teams.csv}}` and now declares the Teams preload through `runtime.openclaw.nodePreloads`; manifest/compiler tests assert those static plan surfaces. The changed tests do not exercise an onboarded sandbox with Teams configured.
  • PRA-T8 Acceptance clause — 2. In a group chat, ask the bot "can you tag me?". — add test evidence or identify existing coverage. No changed test exercises a Teams group-chat prompt or the model/message-tool path for this request.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: Teams OpenClaw runtime message-hint preload

  • 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: The changed tests cover CJS and require(esm) prompt wrapping, gateway scoping, package-load seam, child-module isolation, idempotency, immutable-plugin warning, hook restoration, and OpenClaw pin re-review. Missing are tests against the actual pinned package send/parser contract and automated validation of the recorded artifact hashes.
  • 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: `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` documents the workaround and removal condition; `test/package-contract/msteams-message-hints-preload.test.ts:26-27` explicitly limits coverage to the package/load boundary and excludes Bot Framework sender/parser proof.

PRA-2 Required — Prove the production Teams mention delivery contract

  • Location: test/package-contract/msteams-message-hints-preload.test.ts:114
  • Category: acceptance
  • Problem: The changed tests now strongly cover the preload's loader mechanics and a reviewed synthetic package-load seam, but they still stop at inserting a prompt hint. The linked issue is about the actual Teams reply: a display-name native mention chip, no visible raw AAD UUID, and a user ping. This test explicitly says it does not claim Bot Framework sender/parser coverage, and the changed code only wraps `agentPrompt.messageToolHints`.
  • Impact: This PR can pass while the user-visible bug remains: the model may receive the hint, but if the pinned `@openclaw/msteams` send/parser path does not convert `@[Display Name](AAD_OBJECT_ID)` into Teams activity text plus a mention entity, Teams can still show the raw UUID and fail to notify the user.
  • Required action: Add production-boundary evidence in this PR. Prefer a focused test that imports or otherwise validates the actual pinned `@openclaw/msteams` channel-plugin-api/send path and asserts that `@[Display Name](AAD_OBJECT_ID)` produces activity text containing `<at>Display Name</at>`, a Teams mention entity for the AAD object ID, and no raw UUID in `activity.text`. If that cannot be executed in repository tests, keep the package-shape fixture but add a precise reviewed-artifact assertion and record the remaining live-delivery gap as an explicit maintainer acceptance decision.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:54-55` and `test/package-contract/msteams-message-hints-preload.test.ts:26-27,114`; then grep the changed tests for `<at>`, `mention entity`, or raw UUID exclusion. The current assertions cover prompt hints and hook restoration, not outgoing Bot Framework activity shape.
  • Missing regression test: Add tests named `production @openclaw/msteams mention send path converts @[Display Name](AAD_OBJECT_ID) into <at>Display Name</at> plus a Teams mention entity` and `production Teams send activity text excludes the raw AAD UUID when mention syntax is used`.
  • Done when: The required change is committed and verification passes: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:54-55` and `test/package-contract/msteams-message-hints-preload.test.ts:26-27,114`; then grep the changed tests for `<at>`, `mention entity`, or raw UUID exclusion. The current assertions cover prompt hints and hook restoration, not outgoing Bot Framework activity shape.
  • Evidence: `msteams-message-hints.ts:54-55` adds only `- MSTeams mentions: use \`@[Display Name](Teams user id or AAD object id)\`` to message tool hints. `msteams-message-hints-preload.test.ts:26-27` states the fixture models only the package/load boundary and does not vendor or claim to test the upstream Bot Framework send/parser code.

PRA-3 Resolve/justify — Source-of-truth premise for the Teams preload remains only partially proven

  • Location: src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:11
  • Category: architecture
  • Problem: This PR adds a localized runtime monkeypatch around the upstream Teams plugin. The file documents the invalid state, source boundary, fail-open behavior, and removal condition, and the tests cover the loader lifecycle. The remaining unverified source-of-truth premise is the comment that the upstream send path already parses `@[Display Name](Teams user id or AAD object id)` into Teams mention entities. The package-contract test also records reviewed artifact integrity and SHA-256 constants, but does not compute or compare those hashes against an actual reviewed artifact in the test.
  • Impact: A localized compatibility patch can hide the real source boundary if the upstream parser contract or reviewed package artifact drifts. Maintainers may believe the issue is fixed by prompt guidance while the actual Teams delivery path remains unverified.
  • Recommended action: Either prove the upstream parser/send contract with the actual pinned package, or make the remaining live-delivery and artifact-review gap explicit as an accepted limitation. Also either assert the recorded artifact hashes against a reviewed package source in the package-contract test, or reword/remove them so they are not mistaken for automated provenance coverage.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` for the workaround/source-boundary comments and `test/package-contract/msteams-message-hints-preload.test.ts:28-35` for the integrity/SHA constants. The test only checks `readPinnedOpenClawVersion()` and the synthetic package shape; it does not validate those constants against an artifact.
  • Missing regression test: Add `reviewed @openclaw/msteams package artifact hashes match the recorded runtime extension and channel-plugin-api SHA-256 values` and `preload patches the actual pinned @openclaw/msteams channel-plugin-api entrypoint before agentPrompt.messageToolHints is read`.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read `src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts:7-22` for the workaround/source-boundary comments and `test/package-contract/msteams-message-hints-preload.test.ts:28-35` for the integrity/SHA constants. The test only checks `readPinnedOpenClawVersion()` and the synthetic package shape; it does not validate those constants against an artifact.
  • Evidence: `msteams-message-hints.ts:11-12` states the upstream send path already parses mention syntax, while `msteams-message-hints-preload.test.ts:26-27` disclaims upstream sender/parser coverage and `:28-35` defines artifact hash constants without assertions against a real artifact.

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.

@sandl99 sandl99 requested a review from cv June 29, 2026 05:56
Signed-off-by: San Dang <sdang@nvidia.com>

@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 (2)
src/lib/messaging/compiler/manifest-compiler.test.ts (1)

310-318: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an applier/build-time check for the new preload path.

This only proves the plan shape. A regression in the layer that copies msteams-message-hints.js or wires the preload into the sandbox would still leave Teams setup broken while this stays green. As per coding guidelines, "Cover behavior changes with manifest/compiler tests plus applier/onboard/channel CLI tests when host effects change," and path instructions, "Testing: cover the changed surface with the narrowest relevant vitest sets ... and applier/build-time tests when runtime preload/build application changes."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/messaging/compiler/manifest-compiler.test.ts` around lines 310 - 318,
The manifest-compiler test only checks the runtime plan shape, so add a
build-time/applier assertion for the new Teams preload path as well. Update the
relevant compiler/applier test coverage around manifest compilation and preload
application (for example the manifest compiler flow that produces nodePreloads
and the build-time copy/wiring path for msteams-message-hints) to verify the
file is actually copied and wired into the sandbox, not just present in the
plan.

Sources: Coding guidelines, Path instructions

test/openclaw-msteams-message-hints-patch.test.ts (1)

105-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the mention contract, not the exact prompt copy.

These checks are brittle against harmless wording edits. Prefer asserting that exactly one hint contains the Teams native mention syntax and that it lands before the targeting hint. As per path instructions, "Prefer observable outcomes through the public boundary over source-text ... assertions."

Possible test shape
-      expect(hints).toEqual([ADAPTIVE_CARD_HINT, MSTEAMS_MENTION_HINT, TARGETING_HINT]);
+      const mentionHints = hints.filter((hint) => hint.includes("@[Display Name]("));
+      const mentionIndex = hints.findIndex((hint) => hint.includes("@[Display Name]("));
+      const targetingIndex = hints.findIndex((hint) => hint.startsWith("- MSTeams targeting:"));
+      expect(mentionHints).toHaveLength(1);
+      expect(mentionIndex).toBeGreaterThanOrEqual(0);
+      expect(targetingIndex).toBeGreaterThan(mentionIndex);

Also applies to: 118-119, 131-131

🤖 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/openclaw-msteams-message-hints-patch.test.ts` around lines 105 - 106,
The tests in the hint patch suite are asserting exact prompt text instead of the
mention contract, which makes them brittle to harmless wording changes. Update
the relevant assertions in the hint-related test cases to verify observable
behavior through the public boundary: ensure exactly one hint uses the Teams
native mention syntax and that it appears before the targeting hint, using the
existing hint identifiers like ADAPTIVE_CARD_HINT, MSTEAMS_MENTION_HINT, and
TARGETING_HINT to keep the checks stable.

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.

Nitpick comments:
In `@src/lib/messaging/compiler/manifest-compiler.test.ts`:
- Around line 310-318: The manifest-compiler test only checks the runtime plan
shape, so add a build-time/applier assertion for the new Teams preload path as
well. Update the relevant compiler/applier test coverage around manifest
compilation and preload application (for example the manifest compiler flow that
produces nodePreloads and the build-time copy/wiring path for
msteams-message-hints) to verify the file is actually copied and wired into the
sandbox, not just present in the plan.

In `@test/openclaw-msteams-message-hints-patch.test.ts`:
- Around line 105-106: The tests in the hint patch suite are asserting exact
prompt text instead of the mention contract, which makes them brittle to
harmless wording changes. Update the relevant assertions in the hint-related
test cases to verify observable behavior through the public boundary: ensure
exactly one hint uses the Teams native mention syntax and that it appears before
the targeting hint, using the existing hint identifiers like ADAPTIVE_CARD_HINT,
MSTEAMS_MENTION_HINT, and TARGETING_HINT to keep the checks stable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b9c355a1-2afe-45e2-997d-372444662669

📥 Commits

Reviewing files that changed from the base of the PR and between e45332b and 601e246.

📒 Files selected for processing (6)
  • docs/manage-sandboxes/messaging-channels.mdx
  • src/lib/messaging/channels/manifests.test.ts
  • src/lib/messaging/channels/teams/manifest.ts
  • src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts
  • src/lib/messaging/compiler/manifest-compiler.test.ts
  • test/openclaw-msteams-message-hints-patch.test.ts
✅ Files skipped from review due to trivial changes (2)
  • docs/manage-sandboxes/messaging-channels.mdx
  • src/lib/messaging/channels/teams/manifest.ts

@sandl99 sandl99 changed the title fix(messaging): install Teams skill during setup fix(messaging): inject Teams mention hints at runtime Jun 29, 2026
Comment thread src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts Outdated
@sandl99

sandl99 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Advisor response for head 16a3c4bad

CI is green on the current head, including CodeQL, static checks, build/typecheck, CLI shards, sandbox image builds, CodeRabbit, and both PR Review Advisor jobs. I reviewed the refreshed Nemotron comment as advisory feedback against the current PR diff.

Scope reminder: this PR adds a localized OpenClaw Teams prompt-hint compatibility preload. It does not change Teams auth, message routing, the native send formatter, dependency versions, or user-facing docs. The runtime effect is limited to appending one static mention-format hint to @openclaw/msteams agentPrompt.messageToolHints when the OpenClaw Teams plugin is loaded.

Fixed in 16a3c4bad

  • PRA-23: fixed. The preload now has an OpenClaw gateway-process gate, matching the established Telegram/safety-net process-shape pattern. Ordinary Node children that inherit NODE_OPTIONS stay inert.
  • PRA-7 / PRA-25: materially addressed for this PR scope. The hook is no longer installed in arbitrary Node children, and Module._load is restored after the Teams plugin export is handled. Keeping the hook until the actual plugin export is found is intentional because the package may load internals before the final plugin object is available.
  • Negative coverage was added for both of the above: non-gateway no-op and hook restoration after patching.

Required items that I am justifying rather than changing in this PR

  • PRA-4, PRA-5, PRA-10: canonical package-name verification would be reasonable defense-in-depth, but I do not think it is a merge blocker for this patch. The advisor overstates one bypass: the specifier check matches @openclaw/msteams and @openclaw/msteams/…, not @openclaw/msteams-evil. The path gate is only used after OpenClaw/Node has already selected code to execute; this preload does not add a new package execution path. The patch also only mutates a plugin-shaped prompt-hint export and does not touch credentials, authorization, channel routing, or message payload handling. Further package identity hardening can be a follow-up without expanding this PR.
  • PRA-6, PRA-9: runtime fail-open is intentional. optional: false means the preload artifact must be present during runtime setup; it should not mean a prompt-hint compatibility patch can take down the Teams channel if the upstream plugin object becomes immutable. Missing the hint degrades model guidance; failing closed would break messaging. A bounded stderr diagnostic is acceptable future cleanup, but fail-closed is the wrong behavior for this class of patch.
  • PRA-8, PRA-14, PRA-T6: compiled-output testing is not required here. The preload is a simple CommonJS-compatible IIFE with no runtime imports, no generated constants, and no branch that depends on TS-only behavior. The runtime-preload TS config typecheck passed, CI built the sandbox image, and the manifest/compiler tests verify the installed production path is /usr/local/lib/nemoclaw/preloads/msteams-message-hints.js.
  • PRA-11, PRA-T1 through PRA-T5: the requested seven adversarial tests are broader than the risk introduced by this PR. Current coverage includes CJS, native require(esm), idempotency, unrelated path no-op, non-gateway no-op, hook restore, ESM relative linking safety, and the Teams native mention formatter contract. More supply-chain style cases are better handled with the package-identity follow-up above.
  • PRA-12: this is a roll-up finding. Given the process gate, hook restoration, limited static prompt-hint mutation, and green CodeQL/static/CI checks, I do not treat it as a separate actionable blocker.

Resolve/justify items

  • PRA-1, PRA-2, PRA-3: source-of-truth rationale is documented in the preload header. Invalid state: OpenClaw Teams exposes native mention support in the send path but not reliably in the always-injected tool hints. Source boundary: upstream @openclaw/msteams. Constraint: NemoClaw cannot patch upstream OpenClaw in this PR. Regression coverage: prompt-hint injection plus native mention formatter contract. Removal condition: drop the preload once the minimum installed @openclaw/msteams version includes an equivalent hint.
  • PRA-13, PRA-20: automated removal enforcement is not necessary for this narrow compatibility patch. The inline removal criterion is enough; OpenClaw version bumps are reviewed in normal dependency-upgrade PRs.
  • PRA-15: outside added lines. This PR does not change nemoclaw/package.json, the OpenClaw version pin, or any dependency lockfile. Adding npm audit/OSV policy for OpenClaw transitive dependencies is repository-wide CI work, not part of this Teams hint patch.
  • PRA-16, PRA-T7: the test env var is scoped to the spawned child process via spawnSync({ env: ... }); it does not mutate parent process.env or leak across Vitest cases.
  • PRA-17, PRA-T8: stdout JSON is acceptable for these child-process isolation tests. The child writes only the JSON payload on success, and failures are reported with stdout/stderr included in the assertion message. Replacing this with worker threads would reduce isolation for a global preload test.
  • PRA-18: stale/out of scope. The docs change was removed from this PR, and the current diff does not touch docs/.
  • PRA-19: merge coordination with chore(openclaw): upgrade to 2026.6.10 and harden runtime integration #5595 is a process concern, not a code defect. CI and manifest/compiler tests protect this PR surface; whichever PR merges second should rebase and keep the preload declaration.

Improvements and suggestions

  • PRA-24: duplicating the hint string in the preload and test is intentional. Sharing a constant would create an import/packaging relationship between runtime preload code and tests, which is not worth it for one sentence.
  • PRA-26: stale. The large SDK scaffold was already removed; the current test fixture is small and local.
  • PRA-27: upstream support would be preferable long term, but NemoClaw needs a local compatibility patch now so Teams users get native mention syntax in the always-visible message-tool hints.
  • PRA-28: full Teams E2E would require external Teams tenant/app state and would be flaky for this behavior. The deterministic boundary is the OpenClaw prompt-hint injection plus the native send formatter contract.

Conclusion: no further code is required for this PR. The remaining advisor items are either addressed, outside added lines, intentionally fail-open for availability, or better suited to follow-up hardening rather than blocking this localized compatibility fix.

@sandl99

sandl99 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator Author

Ready for review @cv

@sandl99 sandl99 closed this Jun 29, 2026
@sandl99 sandl99 reopened this Jun 29, 2026
@cv cv added v0.0.71 and removed v0.0.70 labels Jun 30, 2026
cv added 2 commits June 29, 2026 23:36
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: None
Optional E2E targets: None

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • None. This PR changes Microsoft Teams channel manifest/runtime preload behavior, but the trusted E2E registry has no live-supported Teams typed target and e2e.yaml has no free-standing Teams live job. Existing live messaging targets cover Telegram, Discord, and Slack, not the Teams nodePreload surface changed here, so no dispatchable E2E target would exercise this PR's changed behavior.

Optional E2E targets

  • None.

Relevant changed files

  • src/lib/messaging/channels/teams/manifest.ts
  • src/lib/messaging/channels/teams/runtime/msteams-message-hints.ts

@cv

cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Maintainer disposition for the production-boundary advisor item: this PR intentionally does not claim a real Teams delivery test. The pinned third-party sender/parser is unchanged; the NemoClaw-owned boundary is the channel-plugin-api.js prompt export and preload lifecycle, now covered at its exact CJS/ESM entry shape. A real conversion assertion requires external Teams credentials and delivery, while vendoring a copied parser would be synthetic evidence. The PR body records this limitation and removal/re-review condition. Both E2E-advisor-required adjacent live targets are now dispatched on the exact head.

@cv

cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28425986489
Workflow ref: fix/msteams-openclaw-skill
Requested targets: messaging-providers
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs such as jetson-nvmap-gpu and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
messaging-providers ✅ success

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28425570138
Workflow ref: fix/msteams-openclaw-skill
Requested targets: channels-stop-start
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs such as jetson-nvmap-gpu and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-stop-start ✅ success

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv

cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All requested jobs passed

Run: 28427324151
Workflow ref: fix/msteams-openclaw-skill
Requested targets: (default — all supported)
Requested jobs: messaging-providers,channels-stop-start
Summary: 2 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-stop-start ✅ success
messaging-providers ✅ success

@cv

cv commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Maintainer acceptance for head e120c86d7 (v0.0.71)

I reviewed the implementation, the exact pinned package/load boundary, the regression tests, and the automated advisor findings. This is the trusted maintainer decision requested by GPT findings PRA-2, PRA-1, and PRA-3.

Accepted residual gap

  • Repository tests cannot hermetically prove a Teams UI mention chip or user notification without a provisioned Teams tenant, app, and webhook. This PR adds always-visible prompt guidance only; it does not modify the Bot Framework sender/parser. I accept that residual live-delivery evidence risk for v0.0.71. If raw IDs still render, the source fix belongs upstream and this shim should be reworked or reverted rather than expanded.
  • The published @openclaw/msteams@2026.5.27 artifact and OpenClaw loader seam were manually inspected. The integrity and SHA-256 constants are manual reproducibility notes, not automated remote-provenance claims.

Evidence and finding resolution

  • The hermetic contract binds the reviewed shape to nemoclaw/package.json; a pin bump fails until re-review. It models runtimeExtensions -> OpenClaw createRequire -> ESM channel-plugin-api.js, executes the compiled preload, and asserts the mention contract/order plus hook restoration.
  • optional: false is the setup-time guarantee that the compiled asset exists and is packaged. Runtime shape mismatch is intentionally fail-open because prompt guidance must not take Teams down; it emits one bounded NEMOCLAW_MSTEAMS_HINT_PATCH_SKIPPED warning.
  • The global load hook is restored in finally after the first exact entry attempt whether load or patch succeeds or fails. Tests cover immutable-plugin failure, unrelated/child modules, non-gateway processes, launcher gating, and ESM linking.
  • Package matching controls only a prompt-function mutation after Node has already selected code to execute. It does not grant execution, authentication, routing, or credential access. A malicious same-name or symlinked file under the installed package implies a pre-existing compromised node_modules tree and arbitrary code execution; canonical package-name re-reading would not create a meaningful security boundary here.
  • Exact-head mandatory CI is green and CodeRabbit produced no actionable comments. The advisor-required exact-head channels-stop-start run remains a separate merge gate; this acceptance does not waive it.
  • PR chore(openclaw): upgrade to 2026.6.10 and harden runtime integration #5595 changes the OpenClaw pin and overlapping Teams manifest surface. Whichever lands second must revalidate the package seam; the pin-bound contract intentionally enforces that sequencing.

Override scope

This acceptance is limited to the live Teams delivery/provenance evidence gap and the advisor claims rebutted above. It does not waive failing CI, exact-head E2E, DCO/signature requirements, or any future OpenClaw pin re-review.

@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All requested jobs passed

Run: 28428153446
Workflow ref: fix/msteams-openclaw-skill
Requested targets: (default — all supported)
Requested jobs: channels-stop-start
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
channels-stop-start ✅ success

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maintainer acceptance for exact head e120c86d7 (v0.0.71)

I reviewed the implementation, exact pinned package/load boundary, tests, and automated findings. This formal review records the maintainer decision requested by GPT PRA-2, PRA-1, and PRA-3.

  • I accept the residual live-delivery evidence gap: without a provisioned Teams tenant, app, and webhook, repository tests cannot prove the final UI mention chip or notification. This PR adds prompt guidance only and does not modify the Bot Framework sender/parser. If raw IDs persist, the source fix belongs upstream and this shim should be reworked or reverted.
  • The published @openclaw/msteams@2026.5.27 artifact and OpenClaw loader seam were manually inspected. Recorded integrity and SHA-256 values are reproducibility notes, not automated remote-provenance claims.
  • Hermetic coverage binds the reviewed shape to nemoclaw/package.json, fails on a pin bump, models runtimeExtensions -> OpenClaw createRequire -> ESM channel-plugin-api.js, executes the compiled preload, and asserts hint order plus hook restoration.
  • optional: false requires the packaged asset at setup time. Runtime shape mismatch intentionally preserves Teams and emits one bounded NEMOCLAW_MSTEAMS_HINT_PATCH_SKIPPED warning.
  • The load hook restores in finally after the first exact entry attempt on success or failure. Negative coverage includes immutable plugin failure, unrelated and child modules, non-gateway processes, launcher gating, and ESM linking.
  • Package matching only controls a prompt-function mutation after Node selected code to execute; it adds no execution, authentication, routing, or credential authority. A malicious same-name or symlinked file under the installed package already implies a compromised node_modules tree.
  • Exact-head mandatory CI and CodeRabbit are green. Exact-head advisor-required channels-stop-start run 28428153446 passed for both OpenClaw and Hermes.
  • PR #5595 changes the OpenClaw pin and overlaps the Teams manifest. Whichever lands second must revalidate the seam; the pin-bound contract enforces that sequencing.

This acceptance is limited to the delivery/provenance evidence gap and the stale advisor claims rebutted above. It does not waive CI, E2E, DCO/signature requirements, or future pin re-review. This is a COMMENTED review, not merge approval.

@cv cv merged commit 60f754a into main Jun 30, 2026
131 checks passed
@cv cv deleted the fix/msteams-openclaw-skill branch June 30, 2026 08:54
@jyaunches jyaunches mentioned this pull request Jun 30, 2026
21 tasks
jyaunches added a commit that referenced this pull request Jun 30, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Refreshes the public documentation for NemoClaw v0.0.71 after scanning
commits since v0.0.70. Adds release notes and fills the remaining doc
gaps for Windows bootstrap diagnostics, OpenClaw agent auto-relock
warnings, auto-pair cadence tuning, and plugin-install recovery hints.

## Changes
- `docs/about/release-notes.mdx`: adds the v0.0.71 release-note section,
grouped by gateway recovery, OpenShell auth, policy provenance, day-two
maintenance, messaging/inference, and Windows setup.
- `docs/get-started/windows-preparation.mdx`: documents sanitized WSL
install output and reboot gating in the Windows bootstrap.
- `docs/reference/commands.mdx`: documents the host `agent` wrapper's
shields auto-relock warning and OpenClaw auto-pair watcher tuning
variables.
- `docs/reference/troubleshooting.mdx`: adds plugin-install network
failure recovery guidance and updates Windows WSL troubleshooting for
sanitized install logs and reboot-required handling.

Source summary:
- #6065 -> `docs/about/release-notes.mdx`: Notes explicit model override
preservation and gateway-log guard-chain recovery diagnostics.
- #5874 -> `docs/about/release-notes.mdx`: Summarizes host-mediated
`recover` and `gateway restart`, linking to lifecycle, command,
troubleshooting, and trusted-boundary docs already added by the source
PR.
- #5596 -> `docs/about/release-notes.mdx`: Summarizes OpenShell 0.0.71
gateway auth, loopback binding, and compatibility-container docs already
added by the source PR.
- #5797 and #5798 -> `docs/about/release-notes.mdx`: Summarizes
`policy-list` provenance, Restricted tier suppression, and Balanced tier
weather behavior already reflected in policy docs.
- #5784 -> `docs/about/release-notes.mdx`: Summarizes
`--destroy-user-data` and the safe `--yes` uninstall behavior already
documented in lifecycle and command docs.
- #6034 -> `docs/about/release-notes.mdx`: Summarizes custom Dockerfile
warm-build cache behavior already documented in the command reference.
- #5951 -> `docs/reference/commands.mdx`: Documents the stderr-only host
`agent` wrapper warning after recent shields auto-relock.
- #5387 -> `docs/reference/commands.mdx`: Documents OpenClaw auto-pair
watcher cadence and fast-reentry tuning variables.
- #5835 -> `docs/reference/troubleshooting.mdx`: Adds recovery guidance
for OpenClaw plugin-install network failures.
- #5995 and #5956 -> `docs/about/release-notes.mdx`: Summarizes
Microsoft Teams final-message delivery and runtime mention hints already
covered by messaging docs.
- #5716 -> `docs/about/release-notes.mdx`: Summarizes non-interactive
Ollama loopback safety already covered by local inference docs.
- #5505, #5527, and #5528 -> `docs/about/release-notes.mdx`: Summarizes
compatible local endpoint, model task-fit, and model capability audit
docs.
- #6009 -> `docs/get-started/windows-preparation.mdx`,
`docs/reference/troubleshooting.mdx`: Documents sanitized Windows
bootstrap WSL output and reboot-required gating.
- #6055 -> no additional source doc page change needed beyond the
already-merged quickstart update; release notes did not duplicate
routine quickstart cleanup.

No matching v0.0.71 GitHub announcement discussion was found in the
latest 20 discussions, so this refresh is based on the commit scan and
existing source PR docs.

## 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 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. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: docs-only refresh with no
runtime behavior changes.
- [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 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
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [ ] 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) — ran
`npm run docs`; Fern reported 0 errors and 2 existing warnings.
- [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: Julie Yaunches <jyaunches@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added a new release-notes entry covering gateway recovery,
authentication, network policy/provenance output, uninstall safety,
Windows bootstrap diagnostics, messaging defaults, and inference setup
guidance.
* Clarified Windows preparation steps around reboot behavior and
redacting troubleshooting transcripts.
* Expanded command reference details for OpenClaw wrapper behavior and
new auto-pair tuning options.
* Improved troubleshooting guidance for plugin installation issues, WSL
repair/reboot cases, and install timing problems.

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

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Co-authored-by: Prekshi Vyas <34834085+prekshivyas@users.noreply.github.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

This PR installs a Microsoft Teams-specific OpenClaw runtime preload
that keeps native Teams mention syntax next to OpenClaw's `message` tool
hints. The preload patches the pinned `@openclaw/msteams` prompt export
at its exact package entry while preserving Teams startup if the
upstream export changes or is immutable.

This supersedes NVIDIA#5864 because the issue is not a parser-spacing variant
in NemoClaw. OpenClaw's Teams send path already parses the supported
syntax into Teams mention entities; NemoClaw's failure mode is that the
bot was often not prompted to use that syntax.

## Related Issue

Replaces NVIDIA#5864.
Fixes NVIDIA#5852

## Changes

- Add a Teams OpenClaw `msteams-message-hints` runtime preload installed
for `boot` and `connect` through the messaging runtime-preload
machinery.
- Restrict the CommonJS hook to the reviewed
`@openclaw/msteams/dist/channel-plugin-api.js` boundary; plugin-shaped
child dependencies and unrelated `msteams` paths remain untouched.
- Restore the global load hook in `finally` after the exact entry
attempt, whether patching succeeds, fails, or the module throws.
- Fail open with one bounded static warning when the plugin export
cannot be patched; never include upstream error text or make prompt
guidance take Teams down.
- Recognize the pinned `openclaw.mjs gateway` launcher shape without
activating for arbitrary Node children whose third argument is
`gateway`.
- Cover CommonJS and native `require(esm)` entry loads, the real
`dist/index.js` to `channel-plugin-api.js` flow, child-module isolation,
idempotency, immutable exports, warning behavior, hook restoration,
launcher gating, and unrelated ESM linking.
- Remove the local regex reimplementation that previously overstated
production Teams sender coverage.
- Add a compiled package-contract regression that models the reviewed
2026.5.27 `runtimeExtensions` → OpenClaw `createRequire` → ESM
`channel-plugin-api.js` load seam, binds it to the repository OpenClaw
pin, records the manually reviewed package-load shape, and asserts the
mention contract/order plus hook restoration without vendoring the
upstream parser.

## Source Boundary

The pinned OpenClaw 2026.5.27 package loads its Teams plugin through
`dist/channel-plugin-api.js`, where
`msteamsPlugin.agentPrompt.messageToolHints` is exported. NemoClaw
changes only that prompt function. It does not fork or modify the Bot
Framework sender or mention parser.

The manifest keeps the preload asset `optional: false`: a missing or
mispackaged compiled file is a NemoClaw build/setup failure. After that
asset loads, an upstream export-shape mismatch or immutable plugin is
intentionally fail-open so Teams preserves upstream behavior, emits one
bounded static warning, and starts without the additional prompt hint.

A repository test cannot honestly claim real Teams delivery or Bot
Framework mention conversion without a provisioned Teams app, tenant,
webhook, and live message. Vendoring third-party package code as a
fixture would also create false production proof. The focused tests
therefore lock the reviewed package export/lifecycle boundary, while
live `channels-stop-start` and `messaging-providers` runs validate
adjacent runtime installation and lifecycle. Actual mention conversion
remains the pinned upstream package's contract; revalidate this preload
whenever the OpenClaw pin changes, and remove it once upstream ships
equivalent prompt guidance.

Sequencing note: NVIDIA#5595 upgrades the OpenClaw pin and overlaps the Teams
manifest/compiler surface. If NVIDIA#5595 lands first or this PR is rebased
across it, revalidate this package boundary and keep or remove the shim
based on the new pinned package; do not assume the 2026.5.27 contract
remains unchanged.

## Release Decision

For v0.0.71, this PR is release-deferred. Both required exact-head
advisor verdicts remain blocking (`merge_after_fixes` and
`needs_rework`), and live Teams Bot Framework delivery proof is
unavailable. Maintainers are not overriding either gate; do not merge
this PR for v0.0.71.

The residual evidence gap is that repository tests cannot prove a Teams
UI mention chip or user notification without a provisioned Teams tenant,
app, and webhook. This PR changes only always-visible prompt guidance;
it does not modify or claim automated proof of the Bot Framework
sender/parser.

The pinned 2026.5.27 npm package and OpenClaw loader seam were manually
reviewed. Hermetic CI enforces the repository pin, reviewed package-load
shape, hint contract, and loader restoration, but that evidence does not
satisfy the required delivery-proof gate. If production mentions still
render raw IDs, the source fix belongs in the upstream Teams send path.

## Type of Change

- [x] 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
<!-- 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:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: this restores expected
Teams-native mention prompting automatically and adds no user action,
command, configuration, environment variable, or support boundary.
- [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: exact entry scoping,
fail-open warning, lifecycle restoration, child-module isolation, and
launcher gating were manually audited and regression-tested.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## 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
- [x] Git hooks passed during commit and push
- [x] Targeted tests pass for changed behavior — 47/47 across compiled
package-contract, preload, channel-manifest, and compiler tests
- [ ] 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)
- [ ] Doc pages follow the style guide (doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Exact-head live evidence (head `e120c86d`):

- `channels-stop-start` (OpenClaw + Hermes):
https://github.com/NVIDIA/NemoClaw/actions/runs/28428153446 — passed

Pre-follow-up live evidence (head `8149bce`):

- `channels-stop-start`:
https://github.com/NVIDIA/NemoClaw/actions/runs/28425570138
- `messaging-providers`:
https://github.com/NVIDIA/NemoClaw/actions/runs/28425986489

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


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

* **New Features**
* Improved Microsoft Teams message tool hints to consistently include
native mention guidance.
* Added automatic preloading of the Teams hint patch for both initial
startup and reconnect phases.

* **Bug Fixes**
* Ensures the mention hint is injected only once and positioned before
the first targeting-related hint.
* Applies best-effort patching that won’t break unrelated module
loading.

* **Tests**
* Expanded unit/contract coverage to verify CommonJS/ESM compatibility,
idempotency, correct hint ordering, and safe loader behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: San Dang <sdang@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Refreshes the public documentation for NemoClaw v0.0.71 after scanning
commits since v0.0.70. Adds release notes and fills the remaining doc
gaps for Windows bootstrap diagnostics, OpenClaw agent auto-relock
warnings, auto-pair cadence tuning, and plugin-install recovery hints.

## Changes
- `docs/about/release-notes.mdx`: adds the v0.0.71 release-note section,
grouped by gateway recovery, OpenShell auth, policy provenance, day-two
maintenance, messaging/inference, and Windows setup.
- `docs/get-started/windows-preparation.mdx`: documents sanitized WSL
install output and reboot gating in the Windows bootstrap.
- `docs/reference/commands.mdx`: documents the host `agent` wrapper's
shields auto-relock warning and OpenClaw auto-pair watcher tuning
variables.
- `docs/reference/troubleshooting.mdx`: adds plugin-install network
failure recovery guidance and updates Windows WSL troubleshooting for
sanitized install logs and reboot-required handling.

Source summary:
- NVIDIA#6065 -> `docs/about/release-notes.mdx`: Notes explicit model override
preservation and gateway-log guard-chain recovery diagnostics.
- NVIDIA#5874 -> `docs/about/release-notes.mdx`: Summarizes host-mediated
`recover` and `gateway restart`, linking to lifecycle, command,
troubleshooting, and trusted-boundary docs already added by the source
PR.
- NVIDIA#5596 -> `docs/about/release-notes.mdx`: Summarizes OpenShell 0.0.71
gateway auth, loopback binding, and compatibility-container docs already
added by the source PR.
- NVIDIA#5797 and NVIDIA#5798 -> `docs/about/release-notes.mdx`: Summarizes
`policy-list` provenance, Restricted tier suppression, and Balanced tier
weather behavior already reflected in policy docs.
- NVIDIA#5784 -> `docs/about/release-notes.mdx`: Summarizes
`--destroy-user-data` and the safe `--yes` uninstall behavior already
documented in lifecycle and command docs.
- NVIDIA#6034 -> `docs/about/release-notes.mdx`: Summarizes custom Dockerfile
warm-build cache behavior already documented in the command reference.
- NVIDIA#5951 -> `docs/reference/commands.mdx`: Documents the stderr-only host
`agent` wrapper warning after recent shields auto-relock.
- NVIDIA#5387 -> `docs/reference/commands.mdx`: Documents OpenClaw auto-pair
watcher cadence and fast-reentry tuning variables.
- NVIDIA#5835 -> `docs/reference/troubleshooting.mdx`: Adds recovery guidance
for OpenClaw plugin-install network failures.
- NVIDIA#5995 and NVIDIA#5956 -> `docs/about/release-notes.mdx`: Summarizes
Microsoft Teams final-message delivery and runtime mention hints already
covered by messaging docs.
- NVIDIA#5716 -> `docs/about/release-notes.mdx`: Summarizes non-interactive
Ollama loopback safety already covered by local inference docs.
- NVIDIA#5505, NVIDIA#5527, and NVIDIA#5528 -> `docs/about/release-notes.mdx`: Summarizes
compatible local endpoint, model task-fit, and model capability audit
docs.
- NVIDIA#6009 -> `docs/get-started/windows-preparation.mdx`,
`docs/reference/troubleshooting.mdx`: Documents sanitized Windows
bootstrap WSL output and reboot-required gating.
- NVIDIA#6055 -> no additional source doc page change needed beyond the
already-merged quickstart update; release notes did not duplicate
routine quickstart cleanup.

No matching v0.0.71 GitHub announcement discussion was found in the
latest 20 discussions, so this refresh is based on the commit scan and
existing source PR docs.

## 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 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. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: docs-only refresh with no
runtime behavior changes.
- [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 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
- [x] Git hooks passed during commit and push, or `npx prek run
--from-ref main --to-ref HEAD` passes
- [ ] 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) — ran
`npm run docs`; Fern reported 0 errors and 2 existing warnings.
- [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: Julie Yaunches <jyaunches@nvidia.com>


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

## Summary by CodeRabbit

* **Documentation**
* Added a new release-notes entry covering gateway recovery,
authentication, network policy/provenance output, uninstall safety,
Windows bootstrap diagnostics, messaging defaults, and inference setup
guidance.
* Clarified Windows preparation steps around reboot behavior and
redacting troubleshooting transcripts.
* Expanded command reference details for OpenClaw wrapper behavior and
new auto-pair tuning options.
* Improved troubleshooting guidance for plugin installation issues, WSL
repair/reboot cases, and install timing problems.

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

Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Co-authored-by: Prekshi Vyas <34834085+prekshivyas@users.noreply.github.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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[macOS][Agent&Skills] MS Teams bot @mention renders raw AAD object ID instead of a display-name mention

2 participants