Skip to content

fix(msteams): normalize inbound mentions and forwards#102379

Open
galiniliev wants to merge 9 commits into
openclaw:mainfrom
galiniliev:bug-052-msteams-inbound-normalize
Open

fix(msteams): normalize inbound mentions and forwards#102379
galiniliev wants to merge 9 commits into
openclaw:mainfrom
galiniliev:bug-052-msteams-inbound-normalize

Conversation

@galiniliev

@galiniliev galiniliev commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Closes #102376

What Problem This Solves

Fixes an issue where Microsoft Teams users would send mentions, quoted replies, or forwarded messages and the agent would receive incomplete or misleading text. Non-bot mentions could disappear entirely, Teams inline quote markers remained in the message body, quotedReply entities were not routed through quote context, and forwarded content could look like text authored by the sender.

Why This Change Was Made

This adds a Teams-owned inbound normalizer before monitor dispatch. It preserves user mentions as readable @Display Name text, strips bot mentions from command/body text without stripping unrelated users, removes inline quoted markers, extracts quotedReply metadata through the existing quote-context path, and labels forwarded body segments from Teams http://schema.skype.com/Forward HTML blockquotes.

Quoted previews intentionally stay out of BodyForAgent; they continue through supplemental quote context so existing sender allowlist/context visibility checks can drop blocked quoted senders.

User Impact

Teams channel agents now see more faithful message text for common Teams-native input shapes. Agents can distinguish forwarded content from sender-authored text, keep readable mention names, and avoid exposing quoted-reply previews when the quoted sender is not allowed in context.

Evidence

Current PR head after maintainer-review fixes:

head=df0b712fccc8d67dcad5a3462b5259d69c3d465c
base=upstream/main@9c2dc92dd8f
branch=bug-052-msteams-inbound-normalize

Real behavior proof from production telemetry

Sanitized aggregate proof was derived from BUG-052 production telemetry collected on 2026-07-11. The raw telemetry artifact contains internal cluster/database names and account/chat/user dimensions; those identifiers were intentionally omitted here.

Affected runtime path:
  inbound Microsoft Teams bot activity POST
  channel_id=msteams
  activity_type=message

Affected container path:
  in-container @openclaw/msteams message handler
  extensions/msteams/src/monitor-handler/message-handler.ts
  extensions/msteams/src/inbound.ts

7d inbound Teams activity volume:
  type=message channel=msteams msgs=942 distinct_activities=501 median_body_size=1377 p95_body_size=1889
  type=invoke  channel=msteams msgs=116 distinct_activities=64  median_body_size=1767 p95_body_size=1847

14d inbound Teams message trend:
  observed across 3 production islands
  recent days routinely exceeded 200 inbound Teams messages/day
  examples: 2026-07-07=241, 2026-07-08=208, 2026-07-09=223

14d native inbound turn blast radius:
  inbound_turns=737
  distinct_users=42
  distinct_chats=95
  distinct_agents=42

Raw telemetry evidence bundle retained in the BUG-052 local evidence folder, with public PR details redacted:

raw-logs/csc_bot_activities_post_received.ndjson: 400 rows
  Runtime inbound Teams bot-activity receipts. Public summary keeps only activity type, channel, body-size distribution, and row counts; raw activity identifiers and raw message payloads stay out of the PR.

raw-logs/csc_native_msteams_inbound_turn.ndjson: 400 rows
  Native Teams inbound-turn delivery rows backing blast-radius proof. Public summary keeps only aggregate user/chat/agent counts; raw owner, chat, agent, island, and message fields stay out of the PR.

raw-logs/csc_inbound_trend_by_island_day.ndjson: 29 rows
  Aggregated 14-day trend rows. Public summary keeps only total island count and daily message examples, not internal island identifiers.

raw-logs/negative-search-proof.md
  Fresh content-blindness proof: 12,144,198 container-adapter rows over 24h had zero hits for mention, quoted-reply, forward, or normalizer markers.

Telemetry caveat: production logs intentionally do not include message text, entities[], mention tags, quotedReply payloads, or forwarded blockquote HTML. Fresh negative telemetry proof found zero hits across 12,144,198 container-adapter rows in 24h for quotedReply, schema.skype.com, <at>, wasMentioned, monitor-handler, messageHandler, stripMSTeamsMentionTags, or Forward. Production telemetry proves the affected Teams inbound path is live at production scale; exact mention-vs-quote-vs-forward content-shape counts remain covered by sanitized Teams-shaped fixtures.

Current-head verification

$ git diff --check
# passed

$ node scripts/run-vitest.mjs extensions/msteams/src/inbound.test.ts extensions/msteams/src/monitor-handler/message-handler.authz.test.ts
Test Files  2 passed (2)
Tests       62 passed (62)

$ node scripts/run-tsgo.mjs -p tsconfig.extensions.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions.tsbuildinfo
# passed

$ node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo
# passed

Autoreview after the maintainer-review fixes:

$ /tmp/autoreview-openclaw-bug052 --mode local
autoreview clean: no accepted/actionable findings reported
overall: patch is correct (0.92)

Autoreview note: /tmp/autoreview-openclaw-bug052 was a temporary copy of the repo autoreview helper with only the local Codex config isolation adjusted so the reviewer could use the local TOML auth/provider. The repository helper was not changed and no helper change was committed.

Remote proof gap on the current head:

$ crabbox --version
0.12.0

$ node scripts/crabbox-wrapper.mjs --version
provider=blacksmith-testbox requires Crabbox >= 0.22.0 for current Testbox sync, queue, and cleanup behavior
selected binary reported version=0.12.0

A prior Azure Crabbox run proved the original PR head 154ed0faf5473be7f46f62840726c7bab8a903ea, but that is superseded by the rebased head above. Current-head remote proof is blocked until the Crabbox binary is upgraded to >=0.22.0 or an Azure/Blacksmith lane is supplied outside this wrapper.

Real behavior proof summary

  • Behavior addressed: Microsoft Teams inbound mention, quoted-reply, and forwarded-message payloads are normalized before agent text, with supplemental quote context still filtered by existing allowlist/context-visibility rules.
  • Maintainer-review fixes added after initial proof: debounced Teams batches now preserve quotedReply metadata from earlier entries, retain quotedReply.messageId, do not authorize an earlier quote using a later message's channel-thread parent, and do not debounce messages across separate Teams channel thread/root scopes.
  • Evidence after fix: Production telemetry shows the fixed path is real and active: 942 Teams message activities over 7 days, 737 native inbound Teams turns over 14 days, 42 users, 95 chats, 42 agents, 3 production islands, and recent daily message counts above 200/day. Current-head terminal proof shows the patched normalizer/debounce behavior passes focused Teams regression coverage and extension TS lanes.
  • Observed result after fix: Focused Teams tests pass with coverage for mention display-name preservation, bot mention stripping, quoted marker removal, quotedReply supplemental context, blocked quoted sender filtering, forwarded-body labeling, debounced quote preservation, blocked debounced quote filtering with an allowed later thread parent, cross-thread quote isolation, and separate channel root-post debounce scopes.
  • What was not tested: no live Microsoft Teams tenant capture/replay was run in this environment, and current-head remote Crabbox proof is blocked by the installed Crabbox 0.12.0 binary. Production telemetry confirms the affected path is active, while exact content-shape behavior is proven with sanitized Teams-shaped payloads on the current code.

@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: L maintainer Maintainer-authored PR labels Jul 9, 2026
@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 25, 2026, 8:09 PM ET / July 26, 2026, 00:09 UTC.

ClawSweeper review

What this changes

This PR adds Microsoft Teams inbound normalization for mentions, quoted replies, forwarded content, and debounced message batches before agent dispatch.

Merge readiness

Blocked until real behavior proof from a real setup is added - 6 items remain

The repository inspection sandbox could not start, so I cannot responsibly make a code verdict from the supplied PR context alone.

Priority: P2
Reviewed head: 88316f50861e747685caaa3d93e2a94012dad14d
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The available fixture and telemetry evidence is useful but does not establish current-head real Teams behavior, and repository inspection was unavailable for a patch-quality verdict.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The PR body reports fixture tests and aggregate production telemetry, but explicitly says no current-head live Microsoft Teams tenant capture or replay was run; add redacted tenant output, diagnostics, or a recording that shows the changed behavior. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦐 gold shrimp (3/6) Security review found an item that needs attention.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The PR body reports fixture tests and aggregate production telemetry, but explicitly says no current-head live Microsoft Teams tenant capture or replay was run; add redacted tenant output, diagnostics, or a recording that shows the changed behavior. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 2 items Inspection environment blocked: The required read-only repository inspection command failed before it could read AGENTS.md, source, history, or the PR head: bwrap reported loopback: Failed RTM_NEWADDR: Operation not permitted.
Current review context: The provided PR context says the branch is cleanly mergeable but behind main, changes Teams inbound normalizing and quote/debounce paths, and remains labeled maintainer and status: 📣 needs proof.
Findings None None.
Security Needs attention Complete the required security diff pass: The inspection sandbox failed before the current head and changed functions could be read, so this review cannot clear the patch's input-handling and dependency-facing changes.

How this fits together

The Microsoft Teams plugin turns Bot Framework activities into agent turns. Incoming activity text, entities, and HTML attachments are normalized and filtered before dispatch to the agent and supplemental quote context.

flowchart LR
  A[Teams activity] --> B[Teams inbound handler]
  B --> C[Text and quote normalization]
  C --> D[Debounce and thread scoping]
  D --> E[Authorization and quote visibility]
  E --> F[Agent dispatch]
Loading

Decision needed

Question Recommendation
Should this PR remain blocked until a redacted current-head Microsoft Teams tenant transcript or diagnostic output directly demonstrates the new normalization behavior? Require live Teams proof: Keep the PR blocked until a current-head tenant transcript, recording with diagnostics, or redacted runtime output demonstrates mention, quote, and forwarded-content normalization.

Why: The supplied proof confirms test fixtures and aggregate path activity but explicitly lacks a current-head live Teams capture; the correct merge gate depends on maintainer acceptance of that evidence threshold.

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The PR body reports fixture tests and aggregate production telemetry, but explicitly says no current-head live Microsoft Teams tenant capture or replay was run; add redacted tenant output, diagnostics, or a recording that shows the changed behavior. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve security concern: Complete the required security diff pass - The inspection sandbox failed before the current head and changed functions could be read, so this review cannot clear the patch's input-handling and dependency-facing changes.
  • Resolve merge risk (P1) - The mandatory source, caller/callee, scoped-policy, dependency-contract, and current-main comparison could not be completed because the read-only inspection sandbox failed to start.
  • Resolve merge risk (P1) - The submitted evidence remains mock and aggregate-telemetry based: it does not directly demonstrate current-head mention, quote, and forward output in a real Microsoft Teams tenant.
  • Complete next step (P2) - A current-head source and proof review is required before any repair or merge recommendation; the read-only inspection sandbox prevented that review.

Findings

  • [low] Complete the required security diff pass
Agent review details

Security

Needs attention: No concrete security defect is established, but the required supply-chain and security diff inspection could not be completed because repository reads were unavailable.

PR surface

Source +253, Tests +808. Total +1061 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 281 28 +253
Tests 2 812 4 +808
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 1093 32 +1061

Review metrics

None.

Merge-risk options

  • The branch is behind main and multiple required checks are failing or still running; this review cannot determine whether failures are branch-caused without inspecting their logs and merge result.

Maintainer options:

  1. Prove the Teams payloads before merge (recommended)
    Add redacted current-head live evidence that visibly connects Teams mention, quoted-reply, and forward payloads to the agent-facing result.
  2. Accept the remaining proof limitation
    A maintainer may accept the fixture and aggregate telemetry evidence, recognizing that the current head lacks a tenant replay.

Technical review

Best possible solution:

Restore repository read access, then review the PR head against current main; before merge, add redacted current-head Teams tenant evidence that directly shows normalized mention, quote, and forwarded-message output.

Do we have a high-confidence way to reproduce the issue?

No: the supplied context provides fixture-shaped cases and aggregate telemetry, but I could not inspect or run a current-main path because the repository inspection sandbox failed before any source read.

Is this the best way to solve the issue?

Unclear: keeping normalization in the Teams plugin appears directionally appropriate from the supplied discussion, but I could not inspect current source, callers, or the Bot Framework dependency contract to judge the current patch as the best fix.

AGENTS.md: unclear because the file could not be read completely.

Codex review notes: model internal, reasoning high; reviewed against 93a0fdb9b800.

Labels

Label justifications:

  • P2: The PR addresses a user-visible Microsoft Teams message-interpretation bug without evidence of an urgent outage.
  • merge-risk: 🚨 message-delivery: The patch changes agent-facing interpretation of inbound Teams messages and quote context, so an incorrect normalization could misrepresent delivered content.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body reports fixture tests and aggregate production telemetry, but explicitly says no current-head live Microsoft Teams tenant capture or replay was run; add redacted tenant output, diagnostics, or a recording that shows the changed behavior. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

Security concerns:

  • [low] Complete the required security diff pass
    The inspection sandbox failed before the current head and changed functions could be read, so this review cannot clear the patch's input-handling and dependency-facing changes.
    Confidence: 0.98

What I checked:

  • Inspection environment blocked: The required read-only repository inspection command failed before it could read AGENTS.md, source, history, or the PR head: bwrap reported loopback: Failed RTM_NEWADDR: Operation not permitted.
  • Current review context: The provided PR context says the branch is cleanly mergeable but behind main, changes Teams inbound normalizing and quote/debounce paths, and remains labeled maintainer and status: 📣 needs proof. (88316f50861e)

Likely related people:

  • sudie-codes: Merged PR history in the supplied context identifies this contributor as the author of the earlier Microsoft Teams structured quote/reply context implementation. (role: introduced quote-context behavior; confidence: medium; commits: 9f5d286caf83; files: extensions/msteams/src/inbound.ts, extensions/msteams/src/monitor-handler/message-handler.ts)
  • galiniliev: The supplied PR history shows this contributor authored the initial debounce and quote-authorization repairs on this branch. (role: recent area contributor; confidence: medium; commits: d115ddc144f7; files: extensions/msteams/src/inbound.ts, extensions/msteams/src/monitor-handler/message-handler.ts)
  • giodl73-repo: The supplied PR history shows this contributor authored the current-head follow-up commits for nested quote entities, mention order, and DM quote handling. (role: recent area contributor; confidence: medium; commits: 686e254be0d1, ecc0129d0907, 77149accd393; files: extensions/msteams/src/inbound.ts, extensions/msteams/src/monitor-handler/message-handler.ts)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Add redacted current-head Teams tenant proof showing agent-facing output for a mention, quoted reply, and forwarded message.
  • Refresh the branch against main and resolve or explain the branch check failures before maintainer merge review.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (11 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-11T15:06:58.231Z sha 154ed0f :: needs real behavior proof before merge. :: [P2] Carry quote metadata through debounced Teams batches
  • reviewed 2026-07-11T16:00:53.678Z sha 154ed0f :: needs real behavior proof before merge. :: [P2] Carry quote metadata through debounced Teams batches
  • reviewed 2026-07-12T03:04:14.581Z sha 154ed0f :: needs real behavior proof before merge. :: [P2] Carry quote metadata through debounced Teams batches
  • reviewed 2026-07-12T08:18:12.322Z sha eedd5a3 :: needs real behavior proof before merge. :: [P1] Parse the SDK's nested quoted-reply payload
  • reviewed 2026-07-13T22:06:21.807Z sha 97da41c :: needs real behavior proof before merge. :: [P1] Read quoted replies from the SDK's nested payload
  • reviewed 2026-07-13T22:23:38.673Z sha 97da41c :: needs real behavior proof before merge. :: [P1] Read quoted replies from the SDK's nested payload
  • reviewed 2026-07-14T11:04:28.588Z sha df0b712 :: needs real behavior proof before merge. :: [P1] Read quoted replies from the SDK's nested payload
  • reviewed 2026-07-25T20:02:18.013Z sha ddb88f1 :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels Jul 9, 2026
@galiniliev galiniliev self-assigned this Jul 11, 2026
@galiniliev
galiniliev force-pushed the bug-052-msteams-inbound-normalize branch 2 times, most recently from ba32bdd to 154ed0f Compare July 11, 2026 14:18
@galiniliev

Copy link
Copy Markdown
Contributor Author

@clawsweeper recheck

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper assist is taking a look at your question.

I queued a lightweight read-only assist pass. It will post a separate answer comment and will not edit the durable ClawSweeper review comment or trigger close, merge, repair, label, or branch changes.

Request: recheck

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper assist: New exact-head behavior evidence is present, but confirming whether it resolves the prior concerns requires a full correctness review.

Evidence:

  • Azure Crabbox tested SHA 154ed0faf5473be7f46f62840726c7bab8a903ea.
  • Focused Teams tests passed: 2 files, 64 tests.
  • Both extension TypeScript lanes passed.
  • The proof uses sanitized Teams-shaped payloads, not a live Teams tenant capture.

Suggested next action: Comment @clawsweeper review on #102379.


Source: #102379 (comment)
Assist reasoning: high.

@galiniliev

Copy link
Copy Markdown
Contributor Author

@clawsweeper review

@clawsweeper

clawsweeper Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 12, 2026
@galiniliev

Copy link
Copy Markdown
Contributor Author

Codex maintainer review: changes needed before merge.

The PR moves Microsoft Teams inbound mention, quoted-reply, and forward normalization into the Teams plugin, which is the right owner boundary for BUG-052 / #102376. The direct no-debounce behavior is covered by the new focused tests and Azure Crabbox proof, but the batched Teams path still drops the new quote facts.

LOC: +565/-17 (4 files)

Findings:

  • [P2] Preserve quotedReply facts through multi-entry Teams debounce batches - extensions/msteams/src/monitor-handler/message-handler.ts:1076

    handleTeamsMessage now normalizes each activity before enqueue and handleTeamsMessageNow extracts quote metadata from attachments plus activity.entities, but the multi-entry debounce flush constructs a synthetic dispatch from last.context, combinedText, combinedRawText, and attachments: []. If the first buffered Teams activity is an entity-only quotedReply and the second buffered activity is plain text from the same sender/conversation, the agent receives the first normalized body text in the combined batch while extractMSTeamsQuoteInfo(attachments, activity.entities) can only see the last activity's entities. That loses supplemental quote context and the quoted-sender allowlist decision for the message text that was just delivered.

    This is not fixed by the attachment debounce guard: shouldDebounce skips entries with attachments, but the new quotedReply parser also supports activity.entities, and those entries can have no attachments. The existing tests cover direct dispatch and blocked quote filtering, but they do not cover nonzero messages.inbound.debounceMs with a quoted entry followed by a second same-key entry.

    Best fix: prepare quote facts at the same point as the normalized text, carry them on MSTeamsDebounceEntry, and define the batched merge rule explicitly. A conservative merge could keep the last entry that has quote metadata, or suppress quote metadata when multiple quoted entries would be ambiguous, but it should not silently couple combined text to only last.context.activity.entities. Add allowed and blocked quoted-sender regression tests under nonzero debounce.

Best-fix verdict: acceptable boundary, too narrow implementation. Teams-owned normalization is the right layer; the missing piece is carrying the newly parsed metadata through the existing Teams debounce lifecycle.

Alternatives considered: changing the shared debouncer is unnecessary because it already passes every buffered entry to onFlush; extracting quotes only inside handleTeamsMessageNow is the current problem because multi-entry batches no longer have one native activity; disabling debounce for any quotedReply entity would be safe but loses batching for a normal text-only Teams shape and is less complete than preserving prepared facts.

Provenance: likely introduced by this PR's new activity.entities quote support interacting with the older Teams debounce merge from #971. The older merge already retained last.context, but before this PR entity-only quoted replies were not converted into supplemental quote context.

Code read: extensions/AGENTS.md; extensions/msteams/src/inbound.ts; extensions/msteams/src/inbound.test.ts; extensions/msteams/src/monitor-handler/message-handler.ts; extensions/msteams/src/monitor-handler/message-handler.authz.test.ts; src/auto-reply/inbound-debounce.ts; sibling debounce handling in extensions/signal/src/monitor/event-handler.ts, extensions/signal/src/monitor/event-handler.inbound-context.test.ts, and extensions/mattermost/src/mattermost/monitor.ts; current upstream/main for the touched Teams path.

Remaining uncertainty: I did not run a live Teams tenant replay. Existing Azure proof covers sanitized direct dispatch fixtures and type lanes, but not this nonzero-debounce scenario.

@galiniliev
galiniliev force-pushed the bug-052-msteams-inbound-normalize branch from 154ed0f to eedd5a3 Compare July 12, 2026 07:43
@galiniliev

Copy link
Copy Markdown
Contributor Author

@clawsweeper review

@clawsweeper

clawsweeper Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 12, 2026
@galiniliev
galiniliev force-pushed the bug-052-msteams-inbound-normalize branch from eedd5a3 to 97da41c Compare July 13, 2026 21:53
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jul 13, 2026
@galiniliev
galiniliev force-pushed the bug-052-msteams-inbound-normalize branch from 97da41c to 516e68a Compare July 14, 2026 05:06
@galiniliev

Copy link
Copy Markdown
Contributor Author

Maintainer review for current head 516e68a930a122f3abf9a3b8ba38683107d990d8.

This PR fixes Teams inbound text normalization for mention tags, quotedReply entities, forwarded-message markers, and debounced Teams batches. The owner boundary is right: the repair stays in the bundled Microsoft Teams plugin and feeds quote previews through the existing supplemental-context visibility filter.

Findings:

  • Blocking: extensions/msteams/src/monitor-handler/message-handler.ts:768 still lets the current channel-thread parent override a quotedReply entity sender before the allowlist decision. extractMSTeamsQuoteInfo() now returns quoteInfo.senderId from quotedReply entities, but when the same turn also has activity.replyToId and thread-parent Graph lookup succeeds, this block assigns quoteSenderId from parentMsg whenever quoteContext === context; the later quoteSenderId ??= quoteInfo.senderId never restores the entity sender. That means a single non-debounced channel reply can quote a blocked sender, fetch an allowlisted thread/root parent, and pass quoteSenderAllowed, exposing the blocked quotedReply.preview through SupplementalContext. The new debounced test covers the “earlier quote plus later allowed parent” case, but the same-turn path is still open. Please prefer the quotedReply sender facts when present and use the Graph parent sender only as a fallback for legacy HTML Reply attachment metadata that lacks a sender id, then add a focused no-debounce regression: allowlist Alice, use quotedReply.senderId = mallory-aad, replyToId = parent-msg, mocked parent sender Alice, and assert SupplementalContext is {} and the blocked preview is absent.

Best-fix verdict: acceptable layer, but too narrow until current-turn quotedReply authorization keeps the entity sender authoritative over unrelated thread-parent context.

Alternatives considered: moving this to core supplemental filtering would be the wrong layer because core only receives senderAllowed; disabling parent Graph sender fallback entirely would risk regressing existing HTML Reply attachment quotes that have sender names but no AAD sender id. The bounded fix is to distinguish entity-backed quote sender facts from parent-derived fallback facts in the Teams handler.

Code read: extensions/AGENTS.md; extensions/msteams/src/inbound.ts; extensions/msteams/src/monitor-handler/message-handler.ts; extensions/msteams/src/inbound.test.ts; extensions/msteams/src/monitor-handler/message-handler.authz.test.ts; src/channels/inbound-event/context.ts; src/auto-reply/inbound-debounce.ts; extensions/msteams/src/graph-thread.ts.

Remaining uncertainty: I did not run a live Teams tenant replay. Current PR CI is still running; checks-fast-loc-ratchet has reported failure, but the finding above is independent of CI status.

@giodl73-repo
giodl73-repo force-pushed the bug-052-msteams-inbound-normalize branch from ddb88f1 to 88316f5 Compare July 26, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams maintainer Maintainer-authored PR merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MS Teams inbound mentions, quoted replies, and forwards are not normalized for agent text

2 participants