refactor: consolidate duplicated plugin state and doctor migration plumbing onto SDK seams#99850
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 4, 2026, 4:49 AM ET / 08:49 UTC. Summary Reproducibility: not applicable. this is a refactor PR for source-level duplication rather than a runtime bug report. Source review and the linked issue establish the duplicated cache/doctor plumbing being cleaned up. Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the shared SDK seam refactor only after regenerating the API baseline, preserving docs/export contracts, adding real behavior proof for a representative migrated path, and getting maintainer sign-off on the public SDK shape. Do we have a high-confidence way to reproduce the issue? Not applicable: this is a refactor PR for source-level duplication rather than a runtime bug report. Source review and the linked issue establish the duplicated cache/doctor plumbing being cleaned up. Is this the best way to solve the issue? No as-is: the shared-helper direction is likely the right owner-boundary solution, but the missing API baseline update, missing real behavior proof, and public SDK seam decision make this head not merge-ready. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 3d6a2216ea77. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
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
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2d9c1b5a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * open/read/write failure disables the persistent layer for the process so message | ||
| * handling never breaks on state errors, matching the shipped channel-cache contract. | ||
| */ | ||
| export function createPersistentDedupeCache<TRecord>(params: { |
There was a problem hiding this comment.
Regenerate the SDK API baseline
Adding this public openclaw/plugin-sdk/dedupe-runtime export (and the runtime-doctor exports in this commit) changes the Plugin SDK API surface, but docs/.generated/plugin-sdk-api-baseline.sha256 is still unchanged from the parent. The baseline checker in scripts/generate-plugin-sdk-api-baseline.ts compares the rendered public exports to that tracked hash and exits with drift, so pnpm plugin-sdk:api:check will fail until the hash is regenerated with the intentional API changes.
Useful? React with 👍 / 👎.
…nnel presence caches
d2d9c1b to
f404107
Compare
|
Merged via squash.
|
…umbing onto SDK seams (openclaw#99850) * refactor(plugin-sdk): add createPersistentDedupeCache and migrate channel presence caches * refactor(matrix): adopt SDK approval reaction target store * refactor(plugin-sdk): share doctor legacy-state migration fs helpers * refactor(memory-core): dedupe qmd cache entry envelope validation * chore(plugin-sdk): pin surface budgets for shared dedupe and doctor helpers * test(matrix): use future approval expiry fixtures for reaction targets * test(matrix): use future approval expiry fixtures for reaction targets
Closes #99841
What Problem This Solves
Resolves the largest verbatim code-duplication clusters in the bundled plugins, where channel and doctor plumbing was copy-pasted per plugin instead of flowing through plugin SDK family seams:
openclaw/plugin-sdk/approval-reaction-runtimealready provides and imessage/signal/whatsapp already use. The local copy had drifted: its in-memory map was unbounded and never expired entries.fileExistswas copied verbatim into 10 extensiondoctor-contract-api.tsfiles andarchiveLegacySourceinto 9, with per-plugin label prefixes baked into otherwise identical doctor message templates.extensions/memory-core/src/memory/qmd-runtime-cache.tsvalidated the same cache-entry envelope twice in two 50-line normalizers.Every copy was a drift bug waiting to happen;
extensions/AGENTS.mdexplicitly calls this out ("stop copying the logic. Extract one shared helper and migrate both call sites in the same change").Why This Change Was Made
One canonical owner per behavior, per the repo architecture rules:
createPersistentDedupeCachefamily helper inopenclaw/plugin-sdk/dedupe-runtime(memory-first presence checks, best-effort persistence that disables itself on the first state failure so message handling never breaks, re-prime on persistent hits). The four presence-cache files shrink to thin key-shape wrappers; persisted record shapes and namespaces are unchanged, so no state migration is needed.createApprovalReactionTargetStorelike its sibling channels, keeping only the matrix-specific emoji bindings local (checkmark/cross render reliably across Matrix clients). The persisted{version: 1, target}wire format is unchanged and asserted by existing tests. The test-only sync resolver export was dropped; production callers always used the persistence-aware resolver.legacyStateFileExists/archiveLegacyStateSourceare now exported fromopenclaw/plugin-sdk/runtime-doctor(implementation insrc/plugins/doctor-state-migration-fs.ts, next to the doctor contract registry) and all ten doctor contracts consume them. Doctor change/warning strings are preserved via the label parameter (asserted by the existing doctor-contract tests).Reviewed and intentionally left as-is, with reasons: the msteams-local
estimateBase64DecodedBytescopy (documented hot-path load-cost tradeoff vs the broadmedia-runtimebarrel), the discord components-registry store wrapper (linked two-store disable + richer error formatting = different contract), and the core-side OpenAI OAuth TLS preflight twin (src/plugins/provider-openai-chatgpt-oauth-tls.ts), which needs a doctor-contract ownership decision tracked in #99841.User Impact
No user-visible behavior change. Channel presence caches, approval reactions, and doctor migrations behave as before; two internal hardening side effects: the Matrix approval-reaction memory layer is now bounded/TTL-pruned like its siblings, and the MS Teams sent-message memory layer moves from unbounded per-conversation maps to one globally bounded dedupe cache (20k entries). Net -539 lines of production/test code.
Evidence
git diff --numstatvs base: 380 added / 919 deleted (net -539).node scripts/check-duplicates.mjs(production/tests/src-mixed all 0 clones),check-architecture-smells.mjs,check-database-first-legacy-stores.mjs,check-no-extension-src-imports.ts,check-extension-plugin-sdk-boundary.mjs,check-plugin-extension-import-boundary.mjs,check-src-extension-import-boundary.mjs,check-import-cycles.ts- all clean.node scripts/build-all.mjsgreen, including thecheck-plugin-sdk-exportsgate.src/plugin-sdk/dedupe-runtime.test.ts(6 tests: layering, re-prime timestamps, disable-on-error, test reset); existing suites for all migrated files pass unchanged except for three matrix test files updated to the async resolver and one memory-wiki doctor wording assertion ("legacy record" -> canonical "legacy source"): slack sent-thread/inbound-delivery + send/upload/blocks/message-handler + dispatch.streaming (13+50+26), mattermost thread-participation + monitor-gating (5 incl. persisted-shape assertions, +17 shard), msteams sent-message-cache + thread-parent/thread-session handlers (4+7+17 shard), matrix approval-reactions/handler/reaction-events (14+7), all 10 doctor-contract suites, memory-core qmd-runtime-cache (10), plugin-sdk subpath contracts (18) and api-baseline (3).