Skip to content

fix(msteams): bound team group lookup cache#102814

Merged
steipete merged 1 commit into
mainfrom
codex/fix-msteams-cache-cap
Jul 9, 2026
Merged

fix(msteams): bound team group lookup cache#102814
steipete merged 1 commit into
mainfrom
codex/fix-msteams-cache-cap

Conversation

@steipete

@steipete steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Microsoft Teams team/group lookups accumulated one cache entry per distinct lookup until TTL expiry. High-cardinality or adversarial traffic could therefore grow the process-local map without a hard bound.

This is a maintainer-owned replacement for #101964. GitHub's signed fork-update API rejected the rebased contributor branch because the stale fork-to-main tree payload exceeded its 45 MB limit.

Why This Change Was Made

Cap the existing TTL cache at 500 entries with the shared pruneMapToMaxSize helper after every successful insertion. The behavior stays single-path: cached hits, misses, null fallbacks, and TTL semantics are unchanged; only the oldest excess entries are removed.

The regression exercises the real resolveTeamGroupId path through 501 distinct successful lookups, proves the cache remains at 500, confirms the oldest entry is evicted, and verifies a later lookup fetches and reinserts it. The patch is preserved as one maintainer commit with sunlit-deng as co-author.

User Impact

Long-running Teams gateways now keep this lookup cache bounded instead of retaining an arbitrary number of tenant/team combinations until expiry.

Evidence

  • Fresh branch autoreview: clean, no actionable findings, confidence 0.99.
  • Formatting: oxfmt --check passed for both touched files.
  • Static hygiene: git diff --check origin/main...HEAD passed.
  • Exact-head isolated AWS proof and hosted CI will be attached before merge.

Supersedes #101964 while preserving contributor credit.

@steipete steipete self-assigned this Jul 9, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: msteams Channel integration: msteams size: XS 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 9, 2026, 9:16 AM ET / 13:16 UTC.

Summary
The PR imports the shared bounded-map helper, caps the Microsoft Teams resolveTeamGroupId team/group lookup cache at 500 successful entries, and adds an overflow eviction regression test.

PR surface: Source +4, Tests +31. Total +35 across 2 files.

Reproducibility: yes. at source level: drive current main resolveTeamGroupId through 501 distinct successful Graph lookups and the Map can grow past 500 because successful inserts are not pruned. I did not execute the repro in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: persistent cache schema: extensions/msteams/src/graph-thread.test.ts, vector/embedding metadata: extensions/msteams/src/graph-thread.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: canonical
Canonical: #102814
Summary: This PR is the maintainer replacement for the earlier contributor PR that proposed the same Teams cache cap.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🌊 off-meta tidepool
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Refresh against current main and let exact-head checks rerun before merge.

Risk before merge

  • [P1] GitHub reports the branch is behind current main, so maintainers should refresh exact-head mergeability and checks before landing.

Maintainer options:

  1. Decide the mitigation before merge
    Land this focused cache cap after a current-main refresh and exact-head checks, then close the superseded source PR with contributor credit preserved.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] No repair lane is needed; this maintainer-labeled PR already contains the narrow fix and needs maintainer refresh/review plus exact-head merge validation.

Security
Cleared: No concrete security or supply-chain concern found; the diff only adds bounded in-memory pruning through an existing SDK helper plus a colocated test.

Review details

Best possible solution:

Land this focused cache cap after a current-main refresh and exact-head checks, then close the superseded source PR with contributor credit preserved.

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

Yes, at source level: drive current main resolveTeamGroupId through 501 distinct successful Graph lookups and the Map can grow past 500 because successful inserts are not pruned. I did not execute the repro in this read-only review.

Is this the best way to solve the issue?

Yes. Pruning the existing Map immediately after successful insertion with the shared helper is narrower than adding local LRU logic or a config knob, and it preserves cache hit, miss, TTL, and fallback behavior.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3fd52514e35f.

Label changes

Label changes:

  • add P2: This fixes a bounded Microsoft Teams process-memory risk in a channel helper with limited blast radius and no evidence of a live outage or security incident.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: Real-behavior proof is not treated as a contributor gate for this maintainer-labeled replacement PR; merge should still wait for the promised exact-head proof/checks.

Label justifications:

  • P2: This fixes a bounded Microsoft Teams process-memory risk in a channel helper with limited blast radius and no evidence of a live outage or security incident.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🌊 off-meta tidepool and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: Real-behavior proof is not treated as a contributor gate for this maintainer-labeled replacement PR; merge should still wait for the promised exact-head proof/checks.
Evidence reviewed

PR surface:

Source +4, Tests +31. Total +35 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 5 1 +4
Tests 1 31 0 +31
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 36 1 +35

What I checked:

  • Current main still has a TTL-only cache: Current main defines teamGroupIdCache and writes successful resolveTeamGroupId lookups without any size pruning, so the central problem remains present. (extensions/msteams/src/graph-thread.ts:83, 3fd52514e35f)
  • PR head applies the cap at the right runtime point: The PR imports pruneMapToMaxSize, defines a 500-entry cap, and prunes immediately after the successful cache insertion while keeping failure fallback uncached. (extensions/msteams/src/graph-thread.ts:90, a8c2db160427)
  • Regression covers overflow and reinsertion: The added test fills 500 distinct Teams ids, inserts a 501st id, verifies the oldest entry is evicted, and proves a later lookup fetches and reinserts that key. (extensions/msteams/src/graph-thread.test.ts:127, a8c2db160427)
  • Shared helper contract matches the intended eviction semantics: pruneMapToMaxSize deletes insertion-ordered oldest Map keys until the map fits the limit, which is the eviction behavior the PR relies on. (src/infra/map-size.ts:13, 3fd52514e35f)
  • Plugin SDK boundary is valid: openclaw/plugin-sdk/collection-runtime is an exported SDK subpath and currently re-exports the bounded-map helper, so the extension import follows the plugin boundary guidance. (package.json:787, 3fd52514e35f)
  • Runtime caller is the Teams thread-context path: Incoming Teams channel replies call resolveTeamGroupId before fetching parent and reply context, so the cache is on the live thread-context path rather than dead code. (extensions/msteams/src/monitor-handler/message-handler.ts:659, 3fd52514e35f)

Likely related people:

  • velanir-ai-manager: Merged PR history and blame show this account authored the PR that introduced graph-thread.ts, the TTL-only teamGroupIdCache, and the Teams thread-context caller path. (role: introduced current behavior; confidence: high; commits: e84a0dde175e; files: extensions/msteams/src/graph-thread.ts, extensions/msteams/src/graph-thread.test.ts, extensions/msteams/src/monitor-handler/message-handler.ts)
  • steipete: Live PR history shows this account merged the current Teams quote/thread-history work, is assigned to this maintainer replacement, and authored the current head commit. (role: merger and recent area owner; confidence: high; commits: e84a0dde175e, a8c2db160427; files: extensions/msteams/src/graph-thread.ts, extensions/msteams/src/graph-thread.test.ts, extensions/msteams/src/monitor-handler/message-handler.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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.

How this review workflow works
  • 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.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jul 9, 2026
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready maintainer proof:

  • Reviewed the full Teams cache owner path, its channel-thread caller, the shared pruneMapToMaxSize contract, sibling caches, and adjacent hit/expiry/fallback tests. Fresh branch autoreview is clean at 0.99 confidence.
  • Exact head: a8c2db160427ce1fb230ae840bf28ec6c027d6c9.
  • Focused Blacksmith Testbox: tbx_01kx3ext7mmp5mevabxk0qfjze, Actions run 29019445244; pnpm test extensions/msteams/src/graph-thread.test.ts passed 31/31.
  • Full exact-head CI: run 29019331298, attempt 2, success. Attempt 1 had no failed job; one runner-cancelled compact shard was rerun successfully.
  • Formatting/static proof: oxfmt --check for both touched files and git diff --check origin/main...HEAD passed.
  • scripts/pr review-validate-artifacts 102814 and OPENCLAW_TESTBOX=1 scripts/pr prepare-run 102814 passed.

This is the clean current-main replacement for #101964; sunlit-deng remains co-author.

@steipete
steipete merged commit f6b9901 into main Jul 9, 2026
187 of 194 checks passed
@steipete
steipete deleted the codex/fix-msteams-cache-cap branch July 9, 2026 13:31
@steipete

steipete commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

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 P2 Normal backlog priority with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant