Skip to content

fix(publication): coalesce duplicate exact-result lineages before batch claim #800

Description

@snowzlmbot

Problem

ClawSweeper has a durable exact-review queue, but the publication key currently includes the producing GitHub workflow run id and run attempt. A retry or duplicated artifact for the same already-reviewed queue lease therefore receives a distinct queue key even when it represents the same exact result.

The current safeguards are useful but narrower:

They do not make the publication queue itself single-flight for one exact review tuple. Equal source revisions from different run attempts can remain as separate pending publication items, be prepared independently in later batches, and add queue pressure without adding a new review decision.

This is especially costly while result publication is backlogged. At the live dashboard observation on 2026-07-23, the publication lane had roughly 1.8k pending items, the oldest ready item was about 45 hours old, and the last-hour retry/supersession volume remained material. The review-admission lane was not the binding constraint.

Dashboard: https://clawsweeper.openclaw.ai/

Desired invariant

For a publication lane, one exact reviewed result has at most one effective active or pending publication chain, identified by:

(target repository, item number, lease revision, claim generation)

The producer run id and run attempt remain provenance, but are not the authority boundary for duplicate admission.

This invariant is deliberately lane-scoped:

  • a review lane and a comment-routing lane for the same issue/PR remain independent;
  • a newer exact review revision remains independent from its predecessor and supersedes it through the existing tuple fencing;
  • a batch already leased by the durable batch store remains protected and is never mutated in place;
  • semantically distinct maintainer commands are not collapsed merely because they share an item number.

Proposed behavior

  1. On publication enqueue, derive a canonical publication-lineage identity from the target item and immutable review tuple.
  2. If an active batch owns that lineage, retain the owner and acknowledge an equivalent later delivery as deduplicated.
  3. If a pending or parked lineage already exists, preserve only one authoritative pending item. Prefer the fresher artifact only when replacement is safe; otherwise retain the existing retry/failure history.
  4. Keep legacy run-attempt keys readable during rollout so in-flight leases, batch memberships, and callbacks remain fenced by their original keys.
  5. Reconcile queued legacy duplicates in bounded passes, never deleting an active batch member.
  6. Emit explicit queue metrics for semantic-lineage deduplication and supersession so the dashboard distinguishes reduced duplicate work from completed reviews.

Non-goals

  • Do not change Codex review prompts, review decisions, close/merge policy, or GitHub write authorization.
  • Do not increase concurrency or batch size as a substitute for correctness.
  • Do not cancel review, comment, or apply lanes simply because their item number matches.
  • Do not remove a claimed/leased artifact publisher without its existing tuple and batch fences.

Validation / acceptance criteria

  • deterministic queue tests cover equal-tuple duplicate deliveries with different producer attempts;
  • a pending duplicate is coalesced without increasing observable queue demand;
  • an active batch member remains protected and a later duplicate cannot steal or mutate its ownership;
  • a newer review tuple still supersedes stale pending work, while a different review or comment lane is unaffected;
  • legacy queue keys remain accepted for in-flight callbacks during the rollout window;
  • GitHub Actions validates the current-head implementation and affected regression suite;
  • dashboard telemetry shows semantic-dedupe counts separately from published, retried, and stale-revision-superseded counts.

Related work

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions