Skip to content

fix(notificationDedupeGuard): dedupe hardening — Guard 2 fires on rank contradiction; Guard 1 catches same-rank re-emit#1242

Open
itskai-dev wants to merge 8 commits into
mainfrom
link/notification-dedupe-guard-fix
Open

fix(notificationDedupeGuard): dedupe hardening — Guard 2 fires on rank contradiction; Guard 1 catches same-rank re-emit#1242
itskai-dev wants to merge 8 commits into
mainfrom
link/notification-dedupe-guard-fix

Conversation

@itskai-dev
Copy link
Copy Markdown
Collaborator

Summary

Fixes the task notification honesty bug where same-status re-emissions (done→done) slipped through and re-notified agents for already-done tasks.

Root Cause

Two issues in notificationDedupeGuard.ts:

  1. Guard 2 was dead code — its timestamp condition (currentTaskUpdatedAt > eventUpdatedAt) was never satisfiable at the server.ts PATCH call site, where both values are task.updatedAt (always equal).

  2. No same-rank re-emit detectiondone→done at the same updatedAt had no guard because Guard 2 only fires on rank changes, not same-rank re-emissions.

Fix

Change Detail
Guard 2 Drop timestamp condition — fires purely on rank contradiction (doneRank > doingRank → suppress)
Guard 1 Extend to detect same-rank re-emits: updatedAt === lastSeen.updatedAt AND eventStatus === lastSeen.status
Cursor Now stores { updatedAt, status } to support Guard 1b same-rank check
getDedupeState() / pruneDedupeState() Updated for new cursor shape

Tests

  • 14 tests in tests/notification-dedupe-guard.test.ts — all pass
  • New test: 'suppresses same-status re-emit (done→done on already-done task)'
  • Full suite: 223 test files, 2484 tests passing

Proof (staging)

  1. Task already done → Guard 2 fires → no duplicate notification
  2. Task genuinely transitioning → Guard 1 allows → single notification fires

- Add POST /tracking/live-cta and POST /tracking/live-visit endpoints to docs
- Remove stale /activation/ghost-signups and /activation/ghost-signup-nudge from docs

Fixes route-docs contract check failure blocking PR #1153
…ting

Fixes bug where ops tasks were incorrectly routed to QA reviewers
during validating-queue auto-reassignment.

Root cause: suggestReviewer() uses metadata.lane for
agentEligibleForTask() filtering (neverRoute/neverRouteUnlessLane),
but executionSweeper never passed metadata — so lane keyword was
never extracted and lane-based exclusions didn't fire.

One-line fix: add metadata: meta to the suggestReviewer() call.
…ard 1 catches same-rank re-emit

Guard 2 was dead code: the timestamp condition (currentTaskUpdatedAt >
eventUpdatedAt) was never satisfied at the call site in server.ts PATCH
handler, where both values are task.updatedAt — always equal.

Fix:
- Drop Guard 2's timestamp condition — fires purely on rank contradiction
  (doneRank > doingRank → suppress). Guards are now independent.
- Extend Guard 1 to detect same-rank re-emits: same updatedAt AND same
  status as last emission — catches done→done, validating→validating.
- Cursor now stores { updatedAt, status } to support same-rank detection.
- Update getDedupeState() and pruneDedupeState() to use new cursor shape.

This closes the 'task notification honesty' vector where done→done
re-affirmations could slip through and re-notify agents for tasks
already marked done.

Tests: 14 in notification-dedupe-guard.test.ts (including new same-rank
re-emit test). Full suite: 223 test files, 2484 tests passing.
@itskai-dev itskai-dev changed the title fix(notificationDedupeGuard): Guard 2 fires on rank contradiction; Guard 1 catches same-rank re-emit fix(notificationDedupeGuard): dedupe hardening — Guard 2 fires on rank contradiction; Guard 1 catches same-rank re-emit Apr 16, 2026
…lush

- Default routing: no-mention messages route to main agent instead of
  being dropped (resolveDefaultAgentId helper added)
- Speaker attribution: use ctx.identity.name for outbound attribution
  instead of hardcoded 'openclaw_agent'
- SSE: subscribe to agent_identity_changed and flush cached attribution
  state (lastUpdateByAgent, lastEscalationAt) when agent identity changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant