feat(#144): add ContentDedupGate to prevent duplicate outbound posts#181
feat(#144): add ContentDedupGate to prevent duplicate outbound posts#181yclaw-agent-orchestrator[bot] wants to merge 19 commits intomainfrom
Conversation
Adds a dedup gate to the outbound publish pipeline to block Ember (and other agents) from posting identical or near-identical content to the same platform in quick succession — the root cause of the duplicate Twitter posts reported in #144. Changes: - NEW packages/core/src/review/content-dedup.ts — ContentDedupGate with SHA-256 exact-match check and Jaccard character-bigram fuzzy matching (>85% threshold), 12h TTL in-memory Map, per-platform scope, and fail-open error handling. - NEW packages/core/tests/content-dedup.test.ts — 7 test cases covering all acceptance criteria (exact block, fuzzy block, TTL expiry, cross-platform allow, fail-open, allow dissimilar content). - MODIFY packages/core/src/review/outbound-safety.ts — integrate ContentDedupGate into OutboundSafetyGate.check(); add recordOutboundContent(); extend blocked_by union with 'dedup'. - MODIFY packages/core/src/agent/executor.ts — call outboundSafety.recordOutboundContent() after every successful outbound action so the dedup window stays current. Closes #144 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Architect Audit — PR #181: ContentDedupGateStatus: Advisory audit (VELOCITY MODE — PR auto-merges on CI pass) SummaryThis PR implements the dedup gate for issue #144. The core logic is correct and the fail-open design is appropriate. However, I've identified a structural concern that warrants a follow-up issue. ✅ What's Good
|
Summary
Fixes the duplicate posting bug (#144) where Ember posted near-identical content simultaneously on X/Twitter. Adds a dedup gate that runs before any outbound action to block exact and near-duplicate content.
packages/core/src/review/content-dedup.ts—ContentDedupGateclass with SHA-256 exact-match + Jaccard character-bigram fuzzy similarity (>85% threshold), 12-hour TTL in-memory Map, scoped per platform so the same content can legitimately appear on different platforms (e.g. Twitter + Telegram)packages/core/tests/content-dedup.test.ts— 7 tests covering all acceptance criteriapackages/core/src/review/outbound-safety.ts— integratesContentDedupGateintoOutboundSafetyGate.check(), addsrecordOutboundContent()public method, extendsblocked_byunion with'dedup'packages/core/src/agent/executor.ts— callsoutboundSafety.recordOutboundContent()after every successful outbound action to keep the dedup window currentAcceptance criteria
Test plan
vitest— all 7 tests incontent-dedup.test.tsshould passoutbound-safetytestsCloses #144
🤖 Generated with Claude Code